From d0d682cdaad5a13dd3bb0dc81ea9c6b23c86c8d0 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Sun, 5 Apr 2020 01:04:56 -0500 Subject: [PATCH] DisabledConfig now correctly enables and disables mods when reloaded --- IPA.Loader/Loader/DisabledConfig.cs | 139 ++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 40 deletions(-) diff --git a/IPA.Loader/Loader/DisabledConfig.cs b/IPA.Loader/Loader/DisabledConfig.cs index e1059c5f..b06bc8a6 100644 --- a/IPA.Loader/Loader/DisabledConfig.cs +++ b/IPA.Loader/Loader/DisabledConfig.cs @@ -1,44 +1,103 @@ -using IPA.Config; -using IPA.Config.Stores; -using IPA.Config.Stores.Attributes; -using IPA.Config.Stores.Converters; -using IPA.Utilities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace IPA.Loader -{ - internal class DisabledConfig - { - public static Config.Config Disabled { get; set; } - - public static DisabledConfig Instance; - - public static void Load() - { - Disabled = Config.Config.GetConfigFor("Disabled Mods", "json"); - Instance = Disabled.Generated(); - } - - public virtual bool Reset { get; set; } = true; - - [NonNullable] - [UseConverter(typeof(CollectionConverter>))] - public virtual HashSet DisabledModIds { get; set; } = new HashSet(); - - protected internal virtual void Changed() { } - protected internal virtual IDisposable ChangeTransaction() => null; - - protected virtual void OnReload() - { +using IPA.Config; +using IPA.Config.Stores; +using IPA.Config.Stores.Attributes; +using IPA.Config.Stores.Converters; +using IPA.Logging; +using IPA.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +#if NET4 +using Task = System.Threading.Tasks.Task; +using TaskEx = System.Threading.Tasks.Task; +#endif +#if NET3 +using Net3_Proxy; +#endif + +namespace IPA.Loader +{ + internal class DisabledConfig + { + public static Config.Config Disabled { get; set; } + + public static DisabledConfig Instance; + + public static void Load() + { + Disabled = Config.Config.GetConfigFor("Disabled Mods", "json"); + Instance = Disabled.Generated(); + } + + public virtual bool Reset { get; set; } = true; + + [NonNullable] + [UseConverter(typeof(CollectionConverter>))] + public virtual HashSet DisabledModIds { get; set; } = new HashSet(); + + protected internal virtual void Changed() { } + protected internal virtual IDisposable ChangeTransaction() => null; + + private Task disableUpdateTask = null; + private int updateState = 0; + + protected virtual void OnReload() + { if (DisabledModIds == null || Reset) { DisabledModIds = new HashSet(); Reset = false; - } - } - } -} + } + + var referToState = unchecked(++updateState); + var copy = DisabledModIds.ToArray(); + if (disableUpdateTask == null || disableUpdateTask.IsCompleted) + { + disableUpdateTask = UpdateDisabledMods(copy); + } + else + { + disableUpdateTask = disableUpdateTask.ContinueWith(t => + { + // skip if another got here before the last finished + if (referToState != updateState) return TaskEx.WhenAll(); + else return UpdateDisabledMods(copy); + }); + } + } + + private Task UpdateDisabledMods(string[] updateWithDisabled) + { + do + { + using var transaction = PluginManager.PluginStateTransaction(); + var disabled = transaction.DisabledPlugins.ToArray(); + foreach (var plugin in disabled) + transaction.Enable(plugin, autoDeps: true); + + var all = transaction.EnabledPlugins.ToArray(); + foreach (var plugin in all.Where(m => updateWithDisabled.Contains(m.Id))) + transaction.Disable(plugin, autoDependents: true); + + try + { + return transaction.Commit().ContinueWith(t => + { + if (t.IsFaulted) + { + Logger.loader.Error("Error changing disabled plugins"); + Logger.loader.Error(t.Exception); + } + }); + } + catch (InvalidOperationException) + { + continue; + } + } + while (true); + } + } +}