Skip to content

Commit 2940f1e

Browse files
Address possible edge cases w/ dependency warnings
1 parent 0077093 commit 2940f1e

File tree

1 file changed

+67
-8
lines changed

1 file changed

+67
-8
lines changed

Nautilus/Patchers/DependencyWarningPatcher.cs

+67-8
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private static void MainMenuStartPostfix(uGUI_MainMenu __instance)
3636

3737
private static void CreateDependencyWarningUI(uGUI_MainMenu mainMenu)
3838
{
39-
var dependencyErrors = Chainloader.DependencyErrors;
39+
var dependencyErrors = new List<string>(Chainloader.DependencyErrors.Where(ShouldDisplayError));
4040
if (dependencyErrors.Count == 0)
4141
return;
4242

@@ -85,6 +85,7 @@ private static void CreateDependencyWarningUI(uGUI_MainMenu mainMenu)
8585
{
8686
Object.Destroy(child.gameObject);
8787
}
88+
8889
var mainPaneTransform = Object.Instantiate(panePrefab, panesHolder).transform;
8990
var mainPaneContent = mainPaneTransform.Find("Viewport/Content");
9091
#if BELOWZERO
@@ -98,7 +99,7 @@ private static void CreateDependencyWarningUI(uGUI_MainMenu mainMenu)
9899
$"<color=#FF0000>{formattedMissingDependencies}</color>",
99100
"<color=#FFFFFF>Mod load errors:</color>"
100101
};
101-
errorsToDisplay.AddRange(dependencyErrors.Where(ShouldDisplayError));
102+
errorsToDisplay.AddRange(dependencyErrors);
102103
// Add error messages to menu
103104
foreach (var error in errorsToDisplay)
104105
{
@@ -173,7 +174,7 @@ private static string FormatMissingDependencies(IList<string> missingDependencie
173174

174175
private static List<string> GetMissingDependencies()
175176
{
176-
var missingDependencies = new HashSet<string>();
177+
var missingDependencies = new Dictionary<string, Version>();
177178
// Get the list of dependency log warning messages
178179
// The format is as follows: "Could not load [{0}] because it has missing dependencies: {1}"
179180
var dependencyErrors = new List<string>(Chainloader.DependencyErrors);
@@ -188,15 +189,73 @@ private static List<string> GetMissingDependencies()
188189
if (indexOfIncompatible >= 0 && indexOfIncompatible < indexOfColon) continue;
189190
// Otherwise, get the remainder of the string, which should be the dependency's GUID
190191
var dependencyGuidText = error[(indexOfColon + 2)..];
192+
// Split up separate GUIDs if there are multiple
191193
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)
193196
{
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+
}
195214
}
196215
}
197216

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+
}
201260
}
202261
}

0 commit comments

Comments
 (0)