diff --git a/BSIPA-ModList/UI/WarningUI.cs b/BSIPA-ModList/UI/WarningUI.cs index 5d85a070..4a770953 100644 --- a/BSIPA-ModList/UI/WarningUI.cs +++ b/BSIPA-ModList/UI/WarningUI.cs @@ -15,18 +15,20 @@ namespace BSIPA_ModList.UI { public string ModName; public string[] MissingDependencies; + public string[] IgnoredDependencies; public string[] DisabledDependencies; - public WarningEntry(string modName, string[] missingDependencies, string[] disabledDependencies) + public WarningEntry(string modName, string[] missingDependencies, string[] ignoredDependencies, string[] disabledDependencies) { ModName = modName; MissingDependencies = missingDependencies; + IgnoredDependencies = ignoredDependencies; DisabledDependencies = disabledDependencies; } } internal class WarningUI : MonoBehaviour - { + { // TODO: rework this to just use disable/ignore reason internal static WarningUI Instance; internal static bool firstShow = true; @@ -83,11 +85,16 @@ namespace BSIPA_ModList.UI } _warningsQueue.Clear(); - Dictionary loadedPlugins = PluginManager.AllPlugins.Select(x => x.Metadata).Concat(PluginManager.DisabledPlugins).Concat(PluginLoader.ignoredPlugins).ToDictionary(x => x.Id, y => y.Version); - foreach (var meta in PluginManager.AllPlugins.Select(x => x.Metadata).Concat(PluginManager.DisabledPlugins).Concat(PluginLoader.ignoredPlugins)) + var enabledPlugins = PluginManager.AllPlugins.Select(p => p.Metadata).Where(x => x.Id != null).ToDictionary(x => x.Id, y => y.Version); + var ignoredPlugins = PluginLoader.ignoredPlugins.Where(x => x.Id != null).ToDictionary(x => x.Id, y => y.Version); + var disabledPlugins = PluginManager.DisabledPlugins.Where(x => x.Id != null).ToDictionary(x => x.Id, y => y.Version); + + // iterate only disabled and ignored, as thats where missing deps can end up + foreach (var meta in PluginManager.DisabledPlugins.Concat(PluginLoader.ignoredPlugins)) { List disabledDependencies = new List(); + List ignoredDependencies = new List(); List missingDependencies = new List(); foreach (var dep in meta.Manifest.Dependencies) { @@ -95,22 +102,30 @@ namespace BSIPA_ModList.UI Logger.log.Debug($"Looking for dependency {dep.Key} with version range {dep.Value.Intersect(new SemVer.Range("*.*.*"))}"); #endif - if (loadedPlugins.ContainsKey(dep.Key) && dep.Value.IsSatisfied(loadedPlugins[dep.Key])) + if (disabledPlugins.TryGetValue(dep.Key, out var version) && dep.Value.IsSatisfied(version)) { Logger.log.Debug($"Dependency {dep.Key} was found, but disabled."); - disabledDependencies.Add($"{dep.Key}@{dep.Value.ToString()}"); + disabledDependencies.Add($"{dep.Key} {dep.Value.ToString()}"); + } + else if (ignoredPlugins.TryGetValue(dep.Key, out version) && dep.Value.IsSatisfied(version)) + { + Logger.log.Debug($"Dependency {dep.Key} was found, but was ignored, likely due to a missing dependency."); + ignoredDependencies.Add($"{dep.Key} {dep.Value.ToString()}"); + } + else if (enabledPlugins.TryGetValue(dep.Key, out version) && dep.Value.IsSatisfied(version)) + { + // do nothing, this was probably user disabled } else { - Logger.log.Debug($"{meta.Name} is missing dependency {dep.Key}@{dep.Value}"); - missingDependencies.Add($"{dep.Key}@{dep.Value.ToString()}"); + Logger.log.Debug($"{meta.Name} is missing dependency {dep.Key} {dep.Value}"); + missingDependencies.Add($"{dep.Key} {dep.Value.ToString()}"); } - } - if(disabledDependencies.Count > 0 || missingDependencies.Count > 0) - { - _warningsQueue.Enqueue(new WarningEntry(meta.Name, missingDependencies.ToArray(), disabledDependencies.ToArray())); } + + if(disabledDependencies.Count > 0 || ignoredDependencies.Count > 0 || missingDependencies.Count > 0) + _warningsQueue.Enqueue(new WarningEntry(meta.Name, missingDependencies.ToArray(), ignoredDependencies.ToArray(), disabledDependencies.ToArray())); } if (_warningsQueue.Count > 0) @@ -129,6 +144,7 @@ namespace BSIPA_ModList.UI WarningEntry warning = _warningsQueue.Dequeue(); _warningDialog.Init("Unmet Dependencies", $"Mod {warning.ModName} has unmet dependencies!" + (warning.MissingDependencies.Length > 0 ? $"\nMissing:\n{string.Join("\n", warning.MissingDependencies)}" : "") + + (warning.IgnoredDependencies.Length > 0 ? $"\nIgnored:\n{string.Join("\n", warning.IgnoredDependencies)}" : "") + (warning.DisabledDependencies.Length > 0 ? $"\nDisabled:\n{string.Join("\n", warning.DisabledDependencies)}" : "") , "Okay", WarningDialogDidFinish); _mainFlow.InvokePrivateMethod("PresentViewController", _warningDialog, null, true); diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index 62586fc7..9aa89eed 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -23,8 +23,10 @@ namespace IPA.Loader { LoadMetadata(); Resolve(); - FilterDisabled(); ComputeLoadOrder(); + FilterDisabled(); + + ResolveDependencies(); }); /// @@ -368,7 +370,7 @@ namespace IPA.Loader } private static void FilterDisabled() - { // TODO: move disabled to a seperate list from ignored + { var enabled = new List(PluginsMetadata.Count); var disabled = DisabledConfig.Ref.Value.DisabledModIds; @@ -438,17 +440,20 @@ namespace IPA.Loader } } - var deTreed = new List(); - DeTree(deTreed, pluginTree); + PluginsMetadata = new List(); + DeTree(PluginsMetadata, pluginTree); #if DEBUG - Logger.loader.Debug(string.Join(", ", deTreed.Select(p => p.ToString()))); + Logger.loader.Debug(string.Join(", ", PluginsMetadata.Select(p => p.ToString()))); #endif + } + internal static void ResolveDependencies() + { var metadata = new List(); var pluginsToLoad = new Dictionary(); var disabledLookup = DisabledPlugins.Where(m => m.Id != null).ToDictionary(m => m.Id, m => m.Version); - foreach (var meta in deTreed) + foreach (var meta in PluginsMetadata) { bool load = true; bool disable = false; @@ -633,7 +638,7 @@ namespace IPA.Loader } if (instance is IDisablablePlugin disable) - try + try // TODO: move this out to after all plugins have been inited { disable.OnEnable(); } diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs index 2fae7a29..56752e65 100644 --- a/IPA.Loader/Loader/PluginManager.cs +++ b/IPA.Loader/Loader/PluginManager.cs @@ -156,7 +156,7 @@ namespace IPA.Loader return false; } - if (IsEnabled(plugin)) return false; + if (!IsDisabled(plugin)) return false; Logger.loader.Info($"Enabling {plugin.Name}"); @@ -229,7 +229,7 @@ namespace IPA.Loader /// /// the plugin to check /// if the plugin is enabled, otherwise. - public static bool IsEnabled(PluginMetadata meta) => !IsDisabled(meta); + public static bool IsEnabled(PluginMetadata meta) => BSMetas.Any(p => p.Metadata == meta); private static readonly List runtimeDisabled = new List(); /// diff --git a/Refs/UnityEngine.CoreModule.dll b/Refs/UnityEngine.CoreModule.dll index 09b46aec..bf2ff633 100644 Binary files a/Refs/UnityEngine.CoreModule.dll and b/Refs/UnityEngine.CoreModule.dll differ