diff --git a/Doorstop b/Doorstop index 055301d4..92da7bf4 160000 --- a/Doorstop +++ b/Doorstop @@ -1 +1 @@ -Subproject commit 055301d4402532f60957f0e7745359aa78962a46 +Subproject commit 92da7bf4fbea717040bf4b1bb2d4e07af12bf861 diff --git a/IPA.Injector/Backups/BackupUnit.cs b/IPA.Injector/Backups/BackupUnit.cs index 99b2158e..4a0a78d8 100644 --- a/IPA.Injector/Backups/BackupUnit.cs +++ b/IPA.Injector/Backups/BackupUnit.cs @@ -1,5 +1,4 @@ -using IPA.Utilities; -using System; +using System; using System.Collections.Generic; using System.IO; @@ -68,7 +67,7 @@ namespace IPA.Injector.Backups /// public void Add(FileInfo file) { - var relativePath = LoneFunctions.GetRelativePath(file.FullName, Environment.CurrentDirectory); + var relativePath = Utilities.LoneFunctions.GetRelativePath(file.FullName, Environment.CurrentDirectory); var backupPath = new FileInfo(Path.Combine(_backupPath.FullName, relativePath)); // Copy over diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index 0e296c07..81a2435a 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using IPA.Config; using UnityEngine; using static IPA.Logging.Logger; using MethodAttributes = Mono.Cecil.MethodAttributes; @@ -34,6 +35,8 @@ namespace IPA.Injector SetupLibraryLoading(); + SelfConfig.Set(); + loader.Debug("Prepping bootstrapper"); InstallBootstrapPatch(); @@ -184,7 +187,7 @@ namespace IPA.Injector pluginAsyncLoadTask.Wait(); log.Debug("Plugins loaded"); log.Debug(string.Join(", ", PluginLoader.PluginsMetadata)); - //PluginComponent.Create(); + PluginComponent.Create(); } } } diff --git a/IPA.Loader/Config/Config.cs b/IPA.Loader/Config/Config.cs new file mode 100644 index 00000000..f7307c41 --- /dev/null +++ b/IPA.Loader/Config/Config.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using IPA.Config.ConfigProviders; +using IPA.Utilities; + +namespace IPA.Config +{ + /// + /// A class to handle updating ConfigProviders automatically + /// + public static class Config + { + static Config() + { + JsonConfigProvider.RegisterConfig(); + } + + /// + /// + /// Defines the type of the + /// + [AttributeUsage(AttributeTargets.Class)] + public class TypeAttribute : Attribute + { + /// + /// The extension associated with this type, without the '.' + /// + // ReSharper disable once UnusedAutoPropertyAccessor.Global + public string Extension { get; private set; } + + /// + /// + /// Constructs the attribute with a specified extension. + /// + /// the extension associated with this type, without the '.' + public TypeAttribute(string ext) + { + Extension = ext; + } + } + + /// + /// + /// Specifies that a particular parameter is preferred to be a specific type of . If it is not available, also specifies backups. If none are available, the default is used. + /// + [AttributeUsage(AttributeTargets.Parameter)] + public class PreferAttribute : Attribute + { + /// + /// The order of preference for the config type. + /// + // ReSharper disable once UnusedAutoPropertyAccessor.Global + public string[] PreferenceOrder { get; private set; } + + /// + /// + /// Constructs the attribute with a specific preference list. Each entry is the extension without a '.' + /// + /// The preferences in order of preference. + public PreferAttribute(params string[] preference) + { + PreferenceOrder = preference; + } + } + + private static readonly Dictionary registeredProviders = new Dictionary(); + + /// + /// Registers a to use for configs. + /// + /// the type to register + public static void Register() where T : IConfigProvider => Register(typeof(T)); + + /// + /// Registers a to use for configs. + /// + /// the type to register + public static void Register(Type type) + { + if (!(type.GetCustomAttribute(typeof(TypeAttribute)) is TypeAttribute ext)) + throw new InvalidOperationException("Type does not have TypeAttribute"); + + if (!typeof(IConfigProvider).IsAssignableFrom(type)) + throw new InvalidOperationException("Type not IConfigProvider"); + + if (registeredProviders.ContainsKey(ext.Extension)) + throw new InvalidOperationException($"Extension provider for {ext.Extension} already exists"); + + registeredProviders.Add(ext.Extension, type); + } + + private static SortedList, IConfigProvider> configProviders = new SortedList, IConfigProvider>(); + + /// + /// Gets an using the specified list pf preferred config types. + /// + /// the name of the file to associate it with + /// the preferred config types to try to get + /// an of the requested type, or of type JSON. + public static IConfigProvider GetProviderFor(string filename, params string[] extensions) + { + var chosenExt = extensions.FirstOrDefault(s => registeredProviders.ContainsKey(s)) ?? "json"; + var type = registeredProviders[chosenExt]; + var provider = Activator.CreateInstance(type) as IConfigProvider; + if (provider != null) + { + provider.Filename = filename; + configProviders.Add(provider.LastModified, provider); + } + + return provider; + } + + /// + /// Gets an using the specified list pf preferred config types. + /// + /// the name of the file to associate it with + /// the parameter info to try and get info for + /// an of the requested type, or of type JSON. + public static IConfigProvider GetProviderFor(string filename, ParameterInfo info) + { + var prefs = new string[0]; + if (info.GetCustomAttribute(typeof(PreferAttribute)) is PreferAttribute prefer) + prefs = prefer.PreferenceOrder; + + return GetProviderFor(filename, prefs); + } + + private static SortedDictionary linkedProviders = + new SortedDictionary(); + + /// + /// Creates a linked for the config provider. This will be automatically updated whenever the file on-disk changes. + /// + /// the type of the parsed value + /// the to create a link to + /// an action to perform on value change + /// a to an ever-changing value, mirroring whatever the file contains. + public static Ref MakeLink(this IConfigProvider config, Action> onChange = null) + { + Ref @ref = config.Parse(); + void ChangeDelegate() + { + @ref.Value = config.Parse(); + onChange?.Invoke(config, @ref); + } + + if (linkedProviders.ContainsKey(config)) + linkedProviders[config] = (Action) Delegate.Combine(linkedProviders[config], (Action) ChangeDelegate); + else + linkedProviders.Add(config, ChangeDelegate); + + ChangeDelegate(); + + return @ref; + } + + /// + /// Removes all linked such that they are no longer updated. + /// + /// the to unlink + public static void RemoveLinks(this IConfigProvider config) + { + if (linkedProviders.ContainsKey(config)) + linkedProviders.Remove(config); + } + + internal static void Update() + { + foreach (var provider in configProviders) + { + + if (provider.Value.LastModified > provider.Key.Value) + { + try + { + provider.Value.Load(); // auto reload if it changes + provider.Key.Value = provider.Value.LastModified; + } + catch (Exception e) + { + Logging.Logger.config.Error("Error when trying to load config"); + Logging.Logger.config.Error(e); + } + } + if (provider.Value.HasChanged) + { + try + { + provider.Value.Save(); + provider.Key.Value = DateTime.Now; + } + catch (Exception e) + { + Logging.Logger.config.Error("Error when trying to save config"); + Logging.Logger.config.Error(e); + } + } + + if (provider.Value.InMemoryChanged) + { + provider.Value.InMemoryChanged = false; + try + { + if (linkedProviders.ContainsKey(provider.Value)) + linkedProviders[provider.Value](); + } + catch (Exception e) + { + Logging.Logger.config.Error("Error running link change events"); + Logging.Logger.config.Error(e); + } + } + } + } + + internal static void Save() + { + foreach (var provider in configProviders) + if (provider.Value.HasChanged) + try + { + provider.Value.Save(); + } + catch (Exception e) + { + Logging.Logger.config.Error("Error when trying to save config"); + Logging.Logger.config.Error(e); + } + } + + } +} diff --git a/IPA.Loader/Config/ConfigProviders/JsonConfigProvider.cs b/IPA.Loader/Config/ConfigProviders/JsonConfigProvider.cs index 4c2eba10..c0b018b0 100644 --- a/IPA.Loader/Config/ConfigProviders/JsonConfigProvider.cs +++ b/IPA.Loader/Config/ConfigProviders/JsonConfigProvider.cs @@ -8,14 +8,21 @@ using Newtonsoft.Json.Linq; namespace IPA.Config.ConfigProviders { + [Config.Type("json")] internal class JsonConfigProvider : IConfigProvider { + public static void RegisterConfig() + { + Config.Register(); + } + private JObject jsonObj; // TODO: create a wrapper that allows empty object creation public dynamic Dynamic => jsonObj; - + public bool HasChanged { get; private set; } + public bool InMemoryChanged { get; set; } public DateTime LastModified => File.GetLastWriteTime(Filename + ".json"); @@ -38,7 +45,7 @@ namespace IPA.Config.ConfigProviders var fileInfo = new FileInfo(Filename + ".json"); if (fileInfo.Exists) { - var json = fileInfo.OpenText().ReadToEnd(); + string json = File.ReadAllText(fileInfo.FullName); try { jsonObj = JObject.Parse(json); @@ -57,6 +64,7 @@ namespace IPA.Config.ConfigProviders } SetupListeners(); + InMemoryChanged = true; } private void SetupListeners() @@ -69,30 +77,32 @@ namespace IPA.Config.ConfigProviders private void JsonObj_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { HasChanged = true; + InMemoryChanged = true; } private void JsonObj_ListChanged(object sender, ListChangedEventArgs e) { HasChanged = true; + InMemoryChanged = true; } private void JsonObj_PropertyChanged(object sender, PropertyChangedEventArgs e) { HasChanged = true; + InMemoryChanged = true; } public T Parse() { + if (jsonObj == null) + return default(T); return jsonObj.ToObject(); } public void Save() { Logger.config.Debug($"Saving file {Filename}.json"); - - var fileInfo = new FileInfo(Filename + ".json"); - - File.WriteAllText(fileInfo.FullName, JsonConvert.SerializeObject(jsonObj, Formatting.Indented)); + File.WriteAllText(Filename + ".json", JsonConvert.SerializeObject(jsonObj, Formatting.Indented)); HasChanged = false; } @@ -102,6 +112,7 @@ namespace IPA.Config.ConfigProviders jsonObj = JObject.FromObject(obj); SetupListeners(); HasChanged = true; + InMemoryChanged = true; } } } diff --git a/IPA.Loader/Config/IConfigProvider.cs b/IPA.Loader/Config/IConfigProvider.cs index d26816d3..88f23efe 100644 --- a/IPA.Loader/Config/IConfigProvider.cs +++ b/IPA.Loader/Config/IConfigProvider.cs @@ -32,7 +32,11 @@ namespace IPA.Config /// bool HasChanged { get; } /// - /// Will be set with the filename (no extension) to save to. When saving, the implimentation should add the appropriate extension. Should error if set multiple times. + /// Returns if the data in memory has been changed - notably including loads. + /// + bool InMemoryChanged { get; set; } + /// + /// Will be set with the filename (no extension) to save to. When saving, the implementation should add the appropriate extension. Should error if set multiple times. /// string Filename { set; } /// diff --git a/IPA.Loader/Config/SelfConfig.cs b/IPA.Loader/Config/SelfConfig.cs new file mode 100644 index 00000000..d83097df --- /dev/null +++ b/IPA.Loader/Config/SelfConfig.cs @@ -0,0 +1,48 @@ +using System.IO; +using IPA.Logging; +using IPA.Utilities; + +namespace IPA.Config +{ + internal class SelfConfig + { + private static IConfigProvider _loaderConfig; + + public static IConfigProvider LoaderConfig + { + get => _loaderConfig; + set + { + _loaderConfig?.RemoveLinks(); + value.Load(); + SelfConfigRef = value.MakeLink((c, v) => + { + var val = v.Value; + if (val.Regenerate) + c.Store(val = new SelfConfig { Regenerate = false }); + + StandardLogger.Configure(val); + }); + _loaderConfig = value; + } + } + + public static Ref SelfConfigRef; + public static void Set() + { + LoaderConfig = Config.GetProviderFor(Path.Combine("UserData", IPA_Name), "toml", "json"); + } + + internal const string IPA_Name = "Beat Saber IPA - Builtin manifest support"; + internal const string IPA_Version = "3.12.0"; + + public bool Regenerate = true; + + public class DebugObject + { + public bool ShowCallSource = false; + public bool ShowDebug = false; + } + public DebugObject Debug = new DebugObject(); + } +} diff --git a/IPA.Loader/IPA.Loader.csproj b/IPA.Loader/IPA.Loader.csproj index dbc49238..995a137e 100644 --- a/IPA.Loader/IPA.Loader.csproj +++ b/IPA.Loader/IPA.Loader.csproj @@ -56,8 +56,10 @@ + + diff --git a/IPA.Loader/Loader/Composite/CompositeBSPlugin.cs b/IPA.Loader/Loader/Composite/CompositeBSPlugin.cs index 5080628f..2efa8158 100644 --- a/IPA.Loader/Loader/Composite/CompositeBSPlugin.cs +++ b/IPA.Loader/Loader/Composite/CompositeBSPlugin.cs @@ -54,11 +54,11 @@ namespace IPA.Loader.Composite Invoke(plugin => plugin.OnFixedUpdate()); } - public string Name => throw new NotImplementedException(); + public string Name => throw new InvalidOperationException(); - public string Version => throw new NotImplementedException(); + public string Version => throw new InvalidOperationException(); - public ModsaberModInfo ModInfo => throw new NotImplementedException(); + public ModsaberModInfo ModInfo => throw new InvalidOperationException(); public void OnLateUpdate() { Invoke(plugin => { diff --git a/IPA.Loader/Loader/Composite/CompositeIPAPlugin.cs b/IPA.Loader/Loader/Composite/CompositeIPAPlugin.cs index b254aa52..9825f6bc 100644 --- a/IPA.Loader/Loader/Composite/CompositeIPAPlugin.cs +++ b/IPA.Loader/Loader/Composite/CompositeIPAPlugin.cs @@ -43,9 +43,9 @@ namespace IPA.Loader.Composite Invoke(plugin => plugin.OnFixedUpdate()); } - public string Name => throw new NotImplementedException(); + public string Name => throw new InvalidOperationException(); - public string Version => throw new NotImplementedException(); + public string Version => throw new InvalidOperationException(); public void OnLateUpdate() { Invoke(plugin => { diff --git a/IPA.Loader/Loader/PluginComponent.cs b/IPA.Loader/Loader/PluginComponent.cs index d0e1b36a..2ff13378 100644 --- a/IPA.Loader/Loader/PluginComponent.cs +++ b/IPA.Loader/Loader/PluginComponent.cs @@ -1,5 +1,4 @@ using IPA.Loader.Composite; -using System; using System.Diagnostics.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; @@ -24,9 +23,9 @@ namespace IPA.Loader DontDestroyOnLoad(gameObject); bsPlugins = new CompositeBSPlugin(PluginManager.BSPlugins); -#pragma warning disable CS0618 // Type or member is obsolete +#pragma warning disable 618 ipaPlugins = new CompositeIPAPlugin(PluginManager.Plugins); -#pragma warning restore CS0618 // Type or member is obsolete +#pragma warning restore 618 gameObject.AddComponent(); @@ -37,23 +36,15 @@ namespace IPA.Loader SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; - foreach (var provider in PluginManager.configProviders) - if (provider.Key.HasChanged) - try - { - provider.Key.Save(); - } - catch (Exception e) - { - Logging.Logger.log.Error("Error when trying to save config"); - Logging.Logger.log.Error(e); - } + Config.Config.Save(); } void Update() { bsPlugins.OnUpdate(); ipaPlugins.OnUpdate(); + + Config.Config.Update(); } void LateUpdate() @@ -61,32 +52,7 @@ namespace IPA.Loader bsPlugins.OnLateUpdate(); ipaPlugins.OnLateUpdate(); - foreach (var provider in PluginManager.configProviders) - { - if (provider.Key.HasChanged) - try - { - provider.Key.Save(); - } - catch (Exception e) - { - Logging.Logger.log.Error("Error when trying to save config"); - Logging.Logger.log.Error(e); - } - else if (provider.Key.LastModified > provider.Value.Value) - { - try - { - provider.Key.Load(); // auto reload if it changes - provider.Value.Value = provider.Key.LastModified; - } - catch (Exception e) - { - Logging.Logger.log.Error("Error when trying to load config"); - Logging.Logger.log.Error(e); - } - } - } + //Config.Config.Update(); } void FixedUpdate() @@ -112,17 +78,7 @@ namespace IPA.Loader bsPlugins.OnApplicationQuit(); ipaPlugins.OnApplicationQuit(); - foreach (var provider in PluginManager.configProviders) - if (provider.Key.HasChanged) - try - { - provider.Key.Save(); - } - catch (Exception e) - { - Logging.Logger.log.Error("Error when trying to save config"); - Logging.Logger.log.Error(e); - } + Config.Config.Save(); quitting = true; } diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index d59d011e..c79f2496 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using IPA.Config; using IPA.Logging; using IPA.Utilities; using Newtonsoft.Json; @@ -16,17 +17,10 @@ namespace IPA.Loader /// public class PluginLoader { - /// - /// The directory to load plugins from. - /// - public static string PluginsDirectory => Path.Combine(BeatSaber.InstallPath, "Plugins"); - internal static Task LoadTask() => Task.Run(() => { LoadMetadata(); - Logger.log.Debug(string.Join(", ", PluginsMetadata)); Resolve(); - Logger.log.Debug(string.Join(", ", PluginsMetadata)); ComputeLoadOrder(); }); @@ -81,7 +75,7 @@ namespace IPA.Loader } /// - public override string ToString() => $"{Name}({Id}@{Version})({PluginType?.AssemblyQualifiedName}) from '{File.Name}'"; + public override string ToString() => $"{Name}({Id}@{Version})({PluginType?.AssemblyQualifiedName}) from '{LoneFunctions.GetRelativePath(File.FullName, BeatSaber.InstallPath)}'"; } /// @@ -101,7 +95,7 @@ namespace IPA.Loader internal static void LoadMetadata() { - string[] plugins = Directory.GetFiles(PluginsDirectory, "*.dll"); + string[] plugins = Directory.GetFiles(BeatSaber.PluginsPath, "*.dll"); try { @@ -273,7 +267,6 @@ namespace IPA.Loader return 0; }); - Logger.log.Debug(string.Join(", ", PluginsMetadata)); var metadata = new List(); var pluginsToLoad = new Dictionary(); @@ -303,5 +296,75 @@ namespace IPA.Loader { } + + internal static PluginInfo LoadPlugin(PluginMetadata meta) + { + var info = new PluginInfo(); + + try + { + Logger.loader.Debug(meta.Assembly.GetName().ToString()); + meta.Assembly = Assembly.Load(meta.Assembly.GetName()); + + var type = meta.PluginType; + var instance = (IBeatSaberPlugin)Activator.CreateInstance(type); + + info.Metadata = meta; + info.Filename = meta.File.FullName; + info.Plugin = instance; + + { + var init = type.GetMethod("Init", BindingFlags.Instance | BindingFlags.Public); + if (init != null) + { + var initArgs = new List(); + var initParams = init.GetParameters(); + + Logger modLogger = null; + IModPrefs modPrefs = null; + IConfigProvider cfgProvider = null; + + foreach (var param in initParams) + { + var ptype = param.ParameterType; + if (ptype.IsAssignableFrom(typeof(Logger))) + { + if (modLogger == null) modLogger = new StandardLogger(meta.Name); + initArgs.Add(modLogger); + } + else if (ptype.IsAssignableFrom(typeof(IModPrefs))) + { + if (modPrefs == null) modPrefs = new ModPrefs(instance); + initArgs.Add(modPrefs); + } + else if (ptype.IsAssignableFrom(typeof(IConfigProvider))) + { + if (cfgProvider == null) + { + cfgProvider = Config.Config.GetProviderFor(Path.Combine("UserData", $"{meta.Name}"), param); + } + initArgs.Add(cfgProvider); + } + else + initArgs.Add(ptype.GetDefault()); + } + + init.Invoke(instance, initArgs.ToArray()); + } + } + } + catch (AmbiguousMatchException) + { + Logger.loader.Error($"Only one Init allowed per plugin (ambiguous match in {meta.Name})"); + return null; + } + catch (Exception e) + { + Logger.loader.Error($"Could not init plugin {meta.Name}: {e}"); + return null; + } + + return info; + } } } \ No newline at end of file diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs index d0ee686b..6d235e09 100644 --- a/IPA.Loader/Loader/PluginManager.cs +++ b/IPA.Loader/Loader/PluginManager.cs @@ -94,8 +94,6 @@ namespace IPA.Loader internal static IConfigProvider SelfConfigProvider { get; set; } - internal static readonly List>> configProviders = new List>>(); - private static void LoadPlugins() { string pluginDirectory = Path.Combine(Environment.CurrentDirectory, "Plugins"); @@ -180,7 +178,7 @@ namespace IPA.Loader Author = "DaNike", Features = new string[0], Description = "", - Version = new SemVer.Version(SelfPlugin.IPA_Version), + Version = new SemVer.Version(SelfConfig.IPA_Version), GameVersion = BeatSaber.GameVersion, Id = "beatsaber-ipa-reloaded" }; @@ -188,11 +186,6 @@ namespace IPA.Loader _bsPlugins.Add(selfPlugin); - configProviders.Add(new KeyValuePair>( - SelfConfigProvider = new JsonConfigProvider {Filename = Path.Combine("UserData", SelfPlugin.IPA_Name)}, - new Ref(SelfConfigProvider.LastModified))); - SelfConfigProvider.Load(); - //Load copied plugins string[] copiedPlugins = Directory.GetFiles(cacheDir, "*.dll"); foreach (string s in copiedPlugins) @@ -294,7 +287,7 @@ namespace IPA.Loader if (cfgProvider == null) { cfgProvider = new JsonConfigProvider { Filename = Path.Combine("UserData", $"{bsPlugin.Name}") }; - configProviders.Add(new KeyValuePair>(cfgProvider, new Ref(cfgProvider.LastModified))); + //configProviders.Add(new KeyValuePair>(cfgProvider, new Ref(cfgProvider.LastModified))); cfgProvider.Load(); } initArgs.Add(cfgProvider); diff --git a/IPA.Loader/Logging/Logger.cs b/IPA.Loader/Logging/Logger.cs index 5bd74266..fcbc7de7 100644 --- a/IPA.Loader/Logging/Logger.cs +++ b/IPA.Loader/Logging/Logger.cs @@ -107,6 +107,11 @@ namespace IPA.Logging /// Shows all messages. /// All = DebugOnly | InfoUp, + + /// + /// Used for when the level is undefined. + /// + Undefined = Byte.MaxValue } /// diff --git a/IPA.Loader/Logging/StandardLogger.cs b/IPA.Loader/Logging/StandardLogger.cs index aa64f4d2..0b297782 100644 --- a/IPA.Loader/Logging/StandardLogger.cs +++ b/IPA.Loader/Logging/StandardLogger.cs @@ -44,25 +44,25 @@ namespace IPA.Logging }; private readonly string logName; - private static readonly bool showSourceClass; + private static bool showSourceClass; + /// /// All levels defined by this filter will be sent to loggers. All others will be ignored. /// - public static LogLevel PrintFilter { get; set; } + public static LogLevel PrintFilter { get; set; } = LogLevel.All; private readonly List printers = new List(defaultPrinters); private readonly Dictionary children = new Dictionary(); - static StandardLogger() + internal static void Configure(SelfConfig cfg) { - showSourceClass = ModPrefs.GetBool("IPA", "DebugShowCallSource", false, true); - PrintFilter = ModPrefs.GetBool("IPA", "PrintDebug", false, true) ? LogLevel.All : LogLevel.InfoUp; + showSourceClass = cfg.Debug.ShowCallSource; + PrintFilter = cfg.Debug.ShowDebug ? LogLevel.All : LogLevel.InfoUp; } private StandardLogger(string mainName, string subName, params LogPrinter[] inherited) { logName = $"{mainName}/{subName}"; - printers = new List(inherited) { new PluginSubLogPrinter(mainName, subName) @@ -78,7 +78,6 @@ namespace IPA.Logging internal StandardLogger(string name) { logName = name; - printers.Add(new PluginLogFilePrinter(name)); if (logThread == null || !logThread.IsAlive) @@ -219,13 +218,9 @@ namespace IPA.Logging public static Logger GetChildLogger(this Logger logger, string name) { if (logger is StandardLogger standardLogger) - { return standardLogger.GetChild(name); - } - else - { - throw new InvalidOperationException(); - } + + throw new InvalidOperationException(); } } } diff --git a/IPA.Loader/Updating/SelfPlugin.cs b/IPA.Loader/Updating/SelfPlugin.cs index b86d6b61..852af2f7 100644 --- a/IPA.Loader/Updating/SelfPlugin.cs +++ b/IPA.Loader/Updating/SelfPlugin.cs @@ -1,21 +1,21 @@ -using UnityEngine.SceneManagement; +using System; +using IPA.Config; +using UnityEngine.SceneManagement; namespace IPA.Updating { + [Obsolete("Only used for old updating system, replaced with a PluginMeta for teh embedded manifest")] internal class SelfPlugin : IBeatSaberPlugin { - internal const string IPA_Name = "Beat Saber IPA - Builtin manifest support"; - internal const string IPA_Version = "3.12.0"; - public static SelfPlugin Instance { get; set; } = new SelfPlugin(); - public string Name => IPA_Name; + public string Name => SelfConfig.IPA_Name; - public string Version => IPA_Version; + public string Version => SelfConfig.IPA_Version; public ModsaberModInfo ModInfo => new ModsaberModInfo { - CurrentVersion = IPA_Version, + CurrentVersion = SelfConfig.IPA_Version, InternalName = "beatsaber-ipa-reloaded" }; diff --git a/IPA.Loader/Utilities/BeatSaber.cs b/IPA.Loader/Utilities/BeatSaber.cs index 3585b5be..a26d9b85 100644 --- a/IPA.Loader/Utilities/BeatSaber.cs +++ b/IPA.Loader/Utilities/BeatSaber.cs @@ -48,6 +48,10 @@ namespace IPA.Utilities /// The path to the `Libs\Native` folder. Use only if necessary. /// public static string NativeLibraryPath => Path.Combine(LibraryPath, "Native"); + /// + /// The directory to load plugins from. + /// + public static string PluginsPath => Path.Combine(InstallPath, "Plugins"); private static bool FindSteamVRAsset() {