diff --git a/BepInEx.Patcher/Program.cs b/BepInEx.Patcher/Program.cs index db20afc..021e531 100644 --- a/BepInEx.Patcher/Program.cs +++ b/BepInEx.Patcher/Program.cs @@ -59,20 +59,27 @@ namespace BepInEx.Patcher static void InjectAssembly(AssemblyDefinition unity, AssemblyDefinition injected) { //Entry point - var originalInjectMethod = injected.MainModule.Types.First(x => x.Name == "Chainloader").Methods.First(x => x.Name == "Initialize"); + var originalInjectMethod = injected.MainModule.Types.First(x => x.Name == "Chainloader") + .Methods.First(x => x.Name == "Initialize"); var injectMethod = unity.MainModule.Import(originalInjectMethod); - var sceneManager = unity.MainModule.Types.First(x => x.Name == "SceneManager"); + var sceneManager = unity.MainModule.Types.First(x => x.Name == "Application"); - ILProcessor IL; + var voidType = unity.MainModule.Import(typeof(void)); + var cctor = new MethodDefinition(".cctor", + Mono.Cecil.MethodAttributes.Static + | Mono.Cecil.MethodAttributes.Private + | Mono.Cecil.MethodAttributes.HideBySig + | Mono.Cecil.MethodAttributes.SpecialName + | Mono.Cecil.MethodAttributes.RTSpecialName, + voidType); - foreach (var loadScene in sceneManager.Methods.Where(x => x.Name == "LoadScene")) - { - IL = loadScene.Body.GetILProcessor(); + var ilp = cctor.Body.GetILProcessor(); + ilp.Append(ilp.Create(OpCodes.Call, injectMethod)); + ilp.Append(ilp.Create(OpCodes.Ret)); - IL.InsertBefore(loadScene.Body.Instructions[0], IL.Create(OpCodes.Call, injectMethod)); - } + sceneManager.Methods.Add(cctor); } } } diff --git a/BepInEx/Config.cs b/BepInEx/Config.cs index 444e42c..0b620a0 100644 --- a/BepInEx/Config.cs +++ b/BepInEx/Config.cs @@ -1,7 +1,8 @@ using BepInEx.Common; +using System; using System.Collections.Generic; using System.IO; -using System.Linq; +using System.Text.RegularExpressions; namespace BepInEx { @@ -14,6 +15,17 @@ namespace BepInEx private static string configPath => Path.Combine(Utility.PluginsDirectory, "config.ini"); + private static Regex sanitizeKeyRegex = new Regex("[^a-zA-Z0-9]+"); + + private static void RaiseConfigReloaded() + { + var handler = ConfigReloaded; + if (handler != null) + handler.Invoke(); + } + + public static event Action ConfigReloaded; + /// /// If enabled, writes the config to disk every time a value is set. /// @@ -30,6 +42,31 @@ namespace BepInEx SaveConfig(); } } + + /// + /// Returns the value of the key if found, otherwise returns the default value. + /// + /// The key to search for. + /// The default value to return if the key is not found. + /// The value of the key. + public static string GetEntry(string key, string defaultValue = "", string section = "") + { + key = Sanitize(key); + if (section.IsNullOrWhiteSpace()) + section = "Global"; + else + section = Sanitize(section); + + Dictionary subdict; + + if (!cache.TryGetValue(section, out subdict)) + return defaultValue; + + if (subdict.TryGetValue(key, out string value)) + return value; + else + return defaultValue; + } /// /// Reloads the config from disk. Unwritten changes are lost. @@ -44,10 +81,10 @@ namespace BepInEx { string line = rawLine.Trim(); - int commentIndex = line.IndexOf("//"); + bool commentIndex = line.StartsWith("//"); - if (commentIndex != -1) //trim comment - line = line.Remove(commentIndex); + if (commentIndex) //trim comment + continue; if (line.StartsWith("[") && line.EndsWith("]")) //section { @@ -64,6 +101,8 @@ namespace BepInEx cache[currentSection][split[0]] = split[1]; } + + RaiseConfigReloaded(); } /// @@ -83,29 +122,6 @@ namespace BepInEx } } - /// - /// Returns the value of the key if found, otherwise returns the default value. - /// - /// The key to search for. - /// The default value to return if the key is not found. - /// The value of the key. - public static string GetEntry(string key, string defaultValue = "", string section = "") - { - if (section.IsNullOrWhiteSpace()) - section = "Global"; - - Dictionary subdict; - - if (!cache.TryGetValue(section, out subdict)) - return defaultValue; - - - if (subdict.TryGetValue(key, out string value)) - return value; - else - return defaultValue; - } - /// /// Sets the value of the key in the config. /// @@ -113,8 +129,11 @@ namespace BepInEx /// The value to set. public static void SetEntry(string key, string value, string section = "") { + key = Sanitize(key); if (section.IsNullOrWhiteSpace()) section = "Global"; + else + section = Sanitize(section); Dictionary subdict; @@ -129,8 +148,53 @@ namespace BepInEx if (SaveOnConfigSet) SaveConfig(); } + + /// + /// Returns wether a value is currently set. + /// + /// The key to check against + /// The section to check in + /// True if the key is present + public static bool HasEntry(string key, string section = "") + { + key = Sanitize(key); + if (section.IsNullOrWhiteSpace()) + section = "Global"; + else + section = Sanitize(section); + + return cache.ContainsKey(section) && cache[section].ContainsKey(key); + } + + + /// + /// Removes a value from the config. + /// + /// The key to remove + /// The section to remove from + /// True if the key was removed + public static bool UnsetEntry(string key, string section = "") + { + key = Sanitize(key); + if (section.IsNullOrWhiteSpace()) + section = "Global"; + else + section = Sanitize(section); + + if (!HasEntry(key, section)) + return false; + + cache[section].Remove(key); + return true; + } + + public static string Sanitize(string key) + { + return sanitizeKeyRegex.Replace(key, "_"); + } #region Extensions + public static string GetEntry(this BaseUnityPlugin plugin, string key, string defaultValue = "") { return GetEntry(key, defaultValue, plugin.ID); @@ -140,6 +204,11 @@ namespace BepInEx { SetEntry(key, value, plugin.ID); } - #endregion + + public static bool HasEntry(this BaseUnityPlugin plugin, string key) + { + return HasEntry(key, plugin.ID); + } + #endregion Extensions } }