From 1e3dc22ea4a81d997fe1ac4a68f9d039f690a913 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Fri, 17 May 2019 00:10:17 -0500 Subject: [PATCH] Added begginings of disablable mod support --- IPA.Injector/Injector.cs | 3 +- IPA.Loader/Config/SelfConfig.cs | 2 +- IPA.Loader/IPA.Loader.csproj | 2 + IPA.Loader/Loader/DisabledConfig.cs | 42 ++++++++++++++ IPA.Loader/Loader/PluginLoader.cs | 18 ++++++ IPA.Loader/Loader/PluginManager.cs | 55 ++++++++++++++----- .../BeatSaber/IDisablablePlugin.cs | 29 ++++++++++ 7 files changed, 136 insertions(+), 15 deletions(-) create mode 100644 IPA.Loader/Loader/DisabledConfig.cs create mode 100644 IPA.Loader/PluginInterfaces/BeatSaber/IDisablablePlugin.cs diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index 7c167cac..3f5bd820 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -50,7 +50,8 @@ namespace IPA.Injector log.Debug("Initializing logger"); - SelfConfig.Set(); + SelfConfig.Load(); + DisabledConfig.Load(); loader.Debug("Prepping bootstrapper"); diff --git a/IPA.Loader/Config/SelfConfig.cs b/IPA.Loader/Config/SelfConfig.cs index 07a4711d..c63770a3 100644 --- a/IPA.Loader/Config/SelfConfig.cs +++ b/IPA.Loader/Config/SelfConfig.cs @@ -31,7 +31,7 @@ namespace IPA.Config public static Ref SelfConfigRef; - public static void Set() + public static void Load() { LoaderConfig = Config.GetProviderFor(IPAName, "json"); } diff --git a/IPA.Loader/IPA.Loader.csproj b/IPA.Loader/IPA.Loader.csproj index 7f3fd570..ea82d36e 100644 --- a/IPA.Loader/IPA.Loader.csproj +++ b/IPA.Loader/IPA.Loader.csproj @@ -64,6 +64,7 @@ + @@ -80,6 +81,7 @@ + diff --git a/IPA.Loader/Loader/DisabledConfig.cs b/IPA.Loader/Loader/DisabledConfig.cs new file mode 100644 index 00000000..255be034 --- /dev/null +++ b/IPA.Loader/Loader/DisabledConfig.cs @@ -0,0 +1,42 @@ +using IPA.Config; +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 + { + private static IConfigProvider _provider; + + public static IConfigProvider Provider + { + get => _provider; + set + { + _provider?.RemoveLinks(); + value.Load(); + Ref = value.MakeLink((c, v) => + { + if (v.Value.Reset) + c.Store(v.Value = new DisabledConfig { Reset = false }); + }); + _provider = value; + } + } + + public static Ref Ref; + + public static void Load() + { + Provider = Config.Config.GetProviderFor("Disabled Mods", "json"); + } + + public bool Reset = true; + + public HashSet DisabledModIds = new HashSet(); + } +} diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index 6f439a8c..34ca9950 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -23,6 +23,7 @@ namespace IPA.Loader { LoadMetadata(); Resolve(); + FilterDisabled(); ComputeLoadOrder(); }); @@ -287,6 +288,7 @@ namespace IPA.Loader } // keep track of these for the updater; it should still be able to update mods not loaded + // TODO: add ignore reason internal static HashSet ignoredPlugins = new HashSet(); internal static void Resolve() @@ -353,6 +355,22 @@ namespace IPA.Loader PluginsMetadata = resolved; } + 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; + foreach (var meta in PluginsMetadata) + { + if (disabled.Contains(meta.Id ?? meta.Name)) + ignoredPlugins.Add(meta); + else + enabled.Add(meta); + } + + PluginsMetadata = enabled; + } + internal static void ComputeLoadOrder() { #if DEBUG diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs index fdaee05f..84fb14c1 100644 --- a/IPA.Loader/Loader/PluginManager.cs +++ b/IPA.Loader/Loader/PluginManager.cs @@ -26,18 +26,7 @@ namespace IPA.Loader /// /// An of new Beat Saber plugins /// - internal static IEnumerable BSPlugins - { - get - { - if(_bsPlugins == null) - { - LoadPlugins(); - } - return (_bsPlugins ?? throw new InvalidOperationException()).Select(p => p.Plugin); - } - } - + internal static IEnumerable BSPlugins => (_bsPlugins ?? throw new InvalidOperationException()).Select(p => p.Plugin); private static List _bsPlugins; internal static IEnumerable BSMetas => _bsPlugins; @@ -56,11 +45,51 @@ namespace IPA.Loader /// /// the ModSaber name of the plugin to get (must be an exact match) /// the plugin info for the requested plugin or null - public static PluginInfo GetPluginFromModSaberName(string name) + [Obsolete("Old name. Use GetPluginFromId instead.")] + public static PluginInfo GetPluginFromModSaberName(string name) => GetPluginFromId(name); + + /// + /// Gets info about the plugin with the specified ID. + /// + /// the ModSaber name of the plugin to get (must be an exact match) + /// the plugin info for the requested plugin or null + public static PluginInfo GetPluginFromId(string name) { return BSMetas.FirstOrDefault(p => p.Metadata.Id == name); } + /// + /// Disables a plugin for the next time the game starts. + /// + /// the plugin to disable + public static void DisablePlugin(PluginInfo plugin) => + DisablePlugin(plugin.Metadata.Id ?? plugin.Metadata.Name); + + /// + /// Disables a plugin for the next time the game starts. + /// + /// the ID, or name if the ID is null, of the plugin to disable + public static void DisablePlugin(string pluginId) + { + DisabledConfig.Ref.Value.DisabledModIds.Add(pluginId); + } + + /// + /// Enables a plugin that had been previously disabled. + /// + /// the plugin to enable + public static void EnablePlugin(PluginMetadata plugin) => + EnablePlugin(plugin.Id ?? plugin.Name); + + /// + /// Enables a plugin that had been previously disabled. + /// + /// the ID, or name if the ID is null, of the plugin to enable + public static void EnablePlugin(string pluginId) + { + DisabledConfig.Ref.Value.DisabledModIds.Remove(pluginId); + } + /// /// Gets a list of all BSIPA plugins. /// diff --git a/IPA.Loader/PluginInterfaces/BeatSaber/IDisablablePlugin.cs b/IPA.Loader/PluginInterfaces/BeatSaber/IDisablablePlugin.cs new file mode 100644 index 00000000..40fa9734 --- /dev/null +++ b/IPA.Loader/PluginInterfaces/BeatSaber/IDisablablePlugin.cs @@ -0,0 +1,29 @@ +namespace IPA +{ + /// + /// Provides methods to allow runtime enabling and disabling of a plugin. + /// + public interface IDisablablePlugin + { + /// + /// Called when a plugin is enabled. This is where you shhould set up Harmony patches and the like. + /// + /// + /// This will be called after Init, and will be called when the plugin loads normally too. + /// When a plugin is disabled at startup, neither this nor Init will be called until it is enabled. + /// + /// Init will only ever be called once. + /// + void OnEnable(); + + /// + /// Called when a plugin is disabled at runtime. This should disable things like Harmony patches and unsubscribe + /// from events. After this is called there should be no lingering effects of the mod. + /// + /// + /// This will get called at shutdown, after , as well as when the + /// plugin is disabled at runtime. + /// + void OnDisable(); + } +}