@@ -36,7 +36,7 @@ private static void MainMenuStartPostfix(uGUI_MainMenu __instance)
36
36
37
37
private static void CreateDependencyWarningUI ( uGUI_MainMenu mainMenu )
38
38
{
39
- var dependencyErrors = Chainloader . DependencyErrors ;
39
+ var dependencyErrors = new List < string > ( Chainloader . DependencyErrors . Where ( ShouldDisplayError ) ) ;
40
40
if ( dependencyErrors . Count == 0 )
41
41
return ;
42
42
@@ -85,6 +85,7 @@ private static void CreateDependencyWarningUI(uGUI_MainMenu mainMenu)
85
85
{
86
86
Object . Destroy ( child . gameObject ) ;
87
87
}
88
+
88
89
var mainPaneTransform = Object . Instantiate ( panePrefab , panesHolder ) . transform ;
89
90
var mainPaneContent = mainPaneTransform . Find ( "Viewport/Content" ) ;
90
91
#if BELOWZERO
@@ -98,7 +99,7 @@ private static void CreateDependencyWarningUI(uGUI_MainMenu mainMenu)
98
99
$ "<color=#FF0000>{ formattedMissingDependencies } </color>",
99
100
"<color=#FFFFFF>Mod load errors:</color>"
100
101
} ;
101
- errorsToDisplay . AddRange ( dependencyErrors . Where ( ShouldDisplayError ) ) ;
102
+ errorsToDisplay . AddRange ( dependencyErrors ) ;
102
103
// Add error messages to menu
103
104
foreach ( var error in errorsToDisplay )
104
105
{
@@ -173,7 +174,7 @@ private static string FormatMissingDependencies(IList<string> missingDependencie
173
174
174
175
private static List < string > GetMissingDependencies ( )
175
176
{
176
- var missingDependencies = new HashSet < string > ( ) ;
177
+ var missingDependencies = new Dictionary < string , Version > ( ) ;
177
178
// Get the list of dependency log warning messages
178
179
// The format is as follows: "Could not load [{0}] because it has missing dependencies: {1}"
179
180
var dependencyErrors = new List < string > ( Chainloader . DependencyErrors ) ;
@@ -188,15 +189,73 @@ private static List<string> GetMissingDependencies()
188
189
if ( indexOfIncompatible >= 0 && indexOfIncompatible < indexOfColon ) continue ;
189
190
// Otherwise, get the remainder of the string, which should be the dependency's GUID
190
191
var dependencyGuidText = error [ ( indexOfColon + 2 ) ..] ;
192
+ // Split up separate GUIDs if there are multiple
191
193
var dependencyGuids = dependencyGuidText . Split ( new [ ] { ", " } , StringSplitOptions . RemoveEmptyEntries ) ;
192
- foreach ( var guid in dependencyGuids )
194
+ // Format individual GUIDs and add them to the list
195
+ foreach ( var formattedGuid in dependencyGuids )
193
196
{
194
- missingDependencies . Add ( guid ) ;
197
+ // Separate the name and version of each formatted GUID string
198
+ var dependencyData = SeparateDependencyNameAndVersion ( formattedGuid ) ;
199
+ // Update the dictionary of dependencies, avoiding duplicates and displaying the highest version
200
+ if ( missingDependencies . TryGetValue ( dependencyData . Item1 , out var previousHighestVersion ) )
201
+ {
202
+ // Make sure only the highest version requirement is present
203
+ // E.g., if we have Nautilus (1.0 or newer) and Nautilus (2.0 or newer), only display the latter
204
+ if ( previousHighestVersion == null ||
205
+ dependencyData . Item2 != null && dependencyData . Item2 > previousHighestVersion )
206
+ {
207
+ missingDependencies [ dependencyData . Item1 ] = dependencyData . Item2 ;
208
+ }
209
+ }
210
+ else
211
+ {
212
+ missingDependencies . Add ( dependencyData . Item1 , dependencyData . Item2 ) ;
213
+ }
195
214
}
196
215
}
197
216
198
- var list = missingDependencies . ToList ( ) ;
199
- list . Sort ( ) ;
200
- return list ;
217
+ // Finally, make a list of formatted strings:
218
+ var formattedDependencyStrings = new List < string > ( ) ;
219
+ foreach ( var dependency in missingDependencies )
220
+ {
221
+ var formattedString = dependency . Key ;
222
+ // Only add the version number if the requirement exists and isn't 0.0.0
223
+ if ( dependency . Value != default )
224
+ {
225
+ formattedString += $ " ({ dependency . Value } or newer)";
226
+ }
227
+
228
+ formattedDependencyStrings . Add ( formattedString ) ;
229
+ }
230
+
231
+ formattedDependencyStrings . Sort ( ) ;
232
+ return formattedDependencyStrings ;
233
+ }
234
+
235
+ // Attempts to find a version from the given dependency name and returns the GUID name by itself
236
+ // Example string of a formatted dependency name with version:
237
+ // "com.snmodding.nautilus (v1.0.0.34 or newer)"
238
+ private static ( string , Version ) SeparateDependencyNameAndVersion ( string formattedDependency )
239
+ {
240
+ try
241
+ {
242
+ // Parentheses cannot exist in GUIDs, so this is ONLY present if the GUID is accompanied by a version
243
+ if ( ! formattedDependency . Contains ( "(" ) )
244
+ {
245
+ return ( formattedDependency , default ) ;
246
+ }
247
+
248
+ // Surpass the "(v"
249
+ var versionBeginIndex = formattedDependency . IndexOf ( '(' ) + 2 ;
250
+ var length = formattedDependency . LastIndexOf ( " or newer)" , StringComparison . Ordinal ) + 1 -
251
+ versionBeginIndex ;
252
+ var rawGuidName = formattedDependency . Substring ( 0 , versionBeginIndex - 3 ) ;
253
+ return ( rawGuidName , Version . Parse ( formattedDependency . Substring ( versionBeginIndex , length ) ) ) ;
254
+ }
255
+ catch ( Exception e )
256
+ {
257
+ InternalLogger . Warn ( $ "Exception getting version from string '{ formattedDependency } '" + e ) ;
258
+ return ( formattedDependency , default ) ;
259
+ }
201
260
}
202
261
}
0 commit comments