diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index 81a2435a..c6ff86c8 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -51,6 +51,13 @@ namespace IPA.Injector } } + private static void SetupLibraryLoading() + { + if (_loadingDone) return; + _loadingDone = true; + AppDomain.CurrentDomain.AssemblyResolve += LibLoader.AssemblyLibLoader; + } + private static void InstallBootstrapPatch() { var cAsmName = Assembly.GetExecutingAssembly().GetName(); @@ -62,93 +69,103 @@ namespace IPA.Injector loader.Warn("No backup found! Was BSIPA installed using the installer?"); loader.Debug("Ensuring patch on UnityEngine.CoreModule exists"); - #region Insert patch into UnityEngine.CoreModule.dll - var unityPath = Path.Combine(Environment.CurrentDirectory, "Beat Saber_Data", "Managed", "UnityEngine.CoreModule.dll"); - var unityAsmDef = AssemblyDefinition.ReadAssembly(unityPath, new ReaderParameters - { - ReadWrite = false, - InMemory = true, - ReadingMode = ReadingMode.Immediate - }); - var unityModDef = unityAsmDef.MainModule; - - bool modified = false; - foreach (var asmref in unityModDef.AssemblyReferences) + #region Insert patch into UnityEngine.CoreModule.dll { - if (asmref.Name == cAsmName.Name) + var unityPath = Path.Combine(Environment.CurrentDirectory, "Beat Saber_Data", "Managed", + "UnityEngine.CoreModule.dll"); + + var unityAsmDef = AssemblyDefinition.ReadAssembly(unityPath, new ReaderParameters { - if (asmref.Version != cAsmName.Version) + ReadWrite = false, + InMemory = true, + ReadingMode = ReadingMode.Immediate + }); + var unityModDef = unityAsmDef.MainModule; + + bool modified = false; + foreach (var asmref in unityModDef.AssemblyReferences) + { + if (asmref.Name == cAsmName.Name) { - asmref.Version = cAsmName.Version; - modified = true; + if (asmref.Version != cAsmName.Version) + { + asmref.Version = cAsmName.Version; + modified = true; + } } } - } - var application = unityModDef.GetType("UnityEngine", "Application"); + var application = unityModDef.GetType("UnityEngine", "Application"); - MethodDefinition cctor = null; - foreach (var m in application.Methods) - if (m.IsRuntimeSpecialName && m.Name == ".cctor") - cctor = m; + MethodDefinition cctor = null; + foreach (var m in application.Methods) + if (m.IsRuntimeSpecialName && m.Name == ".cctor") + cctor = m; - var cbs = unityModDef.ImportReference(((Action)CreateBootstrapper).Method); + var cbs = unityModDef.ImportReference(((Action) CreateBootstrapper).Method); - if (cctor == null) - { - cctor = new MethodDefinition(".cctor", MethodAttributes.RTSpecialName | MethodAttributes.Static | MethodAttributes.SpecialName, unityModDef.TypeSystem.Void); - application.Methods.Add(cctor); - modified = true; - - var ilp = cctor.Body.GetILProcessor(); - ilp.Emit(OpCodes.Call, cbs); - ilp.Emit(OpCodes.Ret); - } - else - { - var ilp = cctor.Body.GetILProcessor(); - for (var i = 0; i < Math.Min(2, cctor.Body.Instructions.Count); i++) + if (cctor == null) + { + cctor = new MethodDefinition(".cctor", + MethodAttributes.RTSpecialName | MethodAttributes.Static | MethodAttributes.SpecialName, + unityModDef.TypeSystem.Void); + application.Methods.Add(cctor); + modified = true; + + var ilp = cctor.Body.GetILProcessor(); + ilp.Emit(OpCodes.Call, cbs); + ilp.Emit(OpCodes.Ret); + } + else { - var ins = cctor.Body.Instructions[i]; - switch (i) + var ilp = cctor.Body.GetILProcessor(); + for (var i = 0; i < Math.Min(2, cctor.Body.Instructions.Count); i++) { - case 0 when ins.OpCode != OpCodes.Call: - ilp.Replace(ins, ilp.Create(OpCodes.Call, cbs)); - modified = true; - break; - case 0: + var ins = cctor.Body.Instructions[i]; + switch (i) { - var methodRef = ins.Operand as MethodReference; - if (methodRef?.FullName != cbs.FullName) - { + case 0 when ins.OpCode != OpCodes.Call: ilp.Replace(ins, ilp.Create(OpCodes.Call, cbs)); modified = true; + break; + case 0: + { + var methodRef = ins.Operand as MethodReference; + if (methodRef?.FullName != cbs.FullName) + { + ilp.Replace(ins, ilp.Create(OpCodes.Call, cbs)); + modified = true; + } + + break; } - - break; + case 1 when ins.OpCode != OpCodes.Ret: + ilp.Replace(ins, ilp.Create(OpCodes.Ret)); + modified = true; + break; } - case 1 when ins.OpCode != OpCodes.Ret: - ilp.Replace(ins, ilp.Create(OpCodes.Ret)); - modified = true; - break; } } - } - if (modified) - { - bkp?.Add(unityPath); - unityAsmDef.Write(unityPath); + if (modified) + { + bkp?.Add(unityPath); + unityAsmDef.Write(unityPath); + } } #endregion loader.Debug("Ensuring Assembly-CSharp is virtualized"); + #region Virtualize Assembly-CSharp.dll - var ascPath = Path.Combine(Environment.CurrentDirectory, "Beat Saber_Data", "Managed", "Assembly-CSharp.dll"); - - var ascModule = VirtualizedModule.Load(ascPath); - ascModule.Virtualize(cAsmName, () => bkp?.Add(ascPath)); + { + var ascPath = Path.Combine(Environment.CurrentDirectory, "Beat Saber_Data", "Managed", + "Assembly-CSharp.dll"); + + var ascModule = VirtualizedModule.Load(ascPath); + ascModule.Virtualize(cAsmName, () => bkp?.Add(ascPath)); + } #endregion } @@ -173,14 +190,6 @@ namespace IPA.Injector } private static bool _loadingDone; - - private static void SetupLibraryLoading() - { - if (_loadingDone) return; - _loadingDone = true; - AppDomain.CurrentDomain.AssemblyResolve += LibLoader.AssemblyLibLoader; - } - private static void Bootstrapper_Destroyed() { // wait for plugins to finish loading diff --git a/IPA.Loader/Config/Config.cs b/IPA.Loader/Config/Config.cs index f7307c41..a2232fd7 100644 --- a/IPA.Loader/Config/Config.cs +++ b/IPA.Loader/Config/Config.cs @@ -128,8 +128,8 @@ namespace IPA.Config return GetProviderFor(filename, prefs); } - private static SortedDictionary linkedProviders = - new SortedDictionary(); + private static Dictionary linkedProviders = + new Dictionary(); /// /// Creates a linked for the config provider. This will be automatically updated whenever the file on-disk changes. diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index 7a25585b..4e646cc7 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -284,13 +284,6 @@ namespace IPA.Loader PluginsMetadata = metadata; } - internal static List LoadPlugins() - { - var list = PluginsMetadata.Select(LoadPlugin).Where(p => p != null).ToList(); - - return list; - } - internal static PluginInfo LoadPlugin(PluginMetadata meta) { if (meta.PluginType == null) @@ -313,7 +306,7 @@ namespace IPA.Loader info.Metadata = meta; info.Plugin = instance; - { + { var init = type.GetMethod("Init", BindingFlags.Instance | BindingFlags.Public); if (init != null) { @@ -342,6 +335,7 @@ namespace IPA.Loader if (cfgProvider == null) { cfgProvider = Config.Config.GetProviderFor(Path.Combine("UserData", $"{meta.Name}"), param); + cfgProvider.Load(); } initArgs.Add(cfgProvider); } @@ -366,5 +360,12 @@ namespace IPA.Loader return info; } + + internal static List LoadPlugins() + { + var list = PluginsMetadata.Select(LoadPlugin).Where(p => p != null).ToList(); + + return list; + } } } \ No newline at end of file diff --git a/IPA.Loader/Utilities/Ref.cs b/IPA.Loader/Utilities/Ref.cs index f710ad6a..9f68a2a5 100644 --- a/IPA.Loader/Utilities/Ref.cs +++ b/IPA.Loader/Utilities/Ref.cs @@ -8,7 +8,7 @@ namespace IPA.Utilities /// A class to store a reference for passing to methods which cannot take ref parameters. /// /// the type of the value - public class Ref + public class Ref : IComparable, IComparable> { private T _value; /// @@ -76,6 +76,20 @@ namespace IPA.Utilities { if (Error != null) throw Error; } + + /// + public int CompareTo(T other) + { + if (Value is IComparable compare) + return compare.CompareTo(other); + return Equals(Value, other) ? 0 : -1; + } + + /// + public int CompareTo(Ref other) + { + return CompareTo(other.Value); + } } internal static class ExceptionUtilities