From 33c5c3b13f47289ccef11aef9b16c26b2a26d7ae Mon Sep 17 00:00:00 2001 From: Bepis <36346617+bbepis@users.noreply.github.com> Date: Mon, 4 Nov 2019 02:01:39 +1100 Subject: [PATCH] Make significant changes to ConfigFile API --- BepInEx.Preloader/Patching/AssemblyPatcher.cs | 6 +- BepInEx.Preloader/Preloader.cs | 12 +- BepInEx/Bootstrap/Chainloader.cs | 10 +- BepInEx/Bootstrap/TypeLoader.cs | 2 +- BepInEx/Configuration/ConfigFile.cs | 309 ++++++++++++------ BepInEx/Configuration/ConfigWrapper.cs | 2 +- BepInEx/Configuration/KeyboardShortcut.cs | 2 +- BepInEx/ConsoleUtil/ConsoleWindow.cs | 4 +- BepInEx/Logging/ConsoleLogListener.cs | 2 +- BepInExTests/Configuration/ConfigFileTests.cs | 34 +- 10 files changed, 251 insertions(+), 132 deletions(-) diff --git a/BepInEx.Preloader/Patching/AssemblyPatcher.cs b/BepInEx.Preloader/Patching/AssemblyPatcher.cs index 63e3617..8935781 100644 --- a/BepInEx.Preloader/Patching/AssemblyPatcher.cs +++ b/BepInEx.Preloader/Patching/AssemblyPatcher.cs @@ -283,17 +283,17 @@ namespace BepInEx.Preloader.Patching #region Config - private static readonly ConfigEntry ConfigDumpAssemblies = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigDumpAssemblies = ConfigFile.CoreConfig.Bind( "Preloader", "DumpAssemblies", false, "If enabled, BepInEx will save patched assemblies into BepInEx/DumpedAssemblies.\nThis can be used by developers to inspect and debug preloader patchers."); - private static readonly ConfigEntry ConfigLoadDumpedAssemblies = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigLoadDumpedAssemblies = ConfigFile.CoreConfig.Bind( "Preloader", "LoadDumpedAssemblies", false, "If enabled, BepInEx will load patched assemblies from BepInEx/DumpedAssemblies instead of memory.\nThis can be used to be able to load patched assemblies into debuggers like dnSpy.\nIf set to true, will override DumpAssemblies."); - private static readonly ConfigEntry ConfigBreakBeforeLoadAssemblies = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigBreakBeforeLoadAssemblies = ConfigFile.CoreConfig.Bind( "Preloader", "BreakBeforeLoadAssemblies", false, "If enabled, BepInEx will call Debugger.Break() once before loading patched assemblies.\nThis can be used with debuggers like dnSpy to install breakpoints into patched assemblies before they are loaded."); diff --git a/BepInEx.Preloader/Preloader.cs b/BepInEx.Preloader/Preloader.cs index bbb8223..6b582ec 100644 --- a/BepInEx.Preloader/Preloader.cs +++ b/BepInEx.Preloader/Preloader.cs @@ -237,32 +237,32 @@ namespace BepInEx.Preloader #region Config - private static readonly ConfigEntry ConfigEntrypointAssembly = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigEntrypointAssembly = ConfigFile.CoreConfig.Bind( "Preloader.Entrypoint", "Assembly", IsPostUnity2017 ? "UnityEngine.CoreModule.dll" : "UnityEngine.dll", "The local filename of the assembly to target."); - private static readonly ConfigEntry ConfigEntrypointType = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigEntrypointType = ConfigFile.CoreConfig.Bind( "Preloader.Entrypoint", "Type", "Application", "The name of the type in the entrypoint assembly to search for the entrypoint method."); - private static readonly ConfigEntry ConfigEntrypointMethod = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigEntrypointMethod = ConfigFile.CoreConfig.Bind( "Preloader.Entrypoint", "Method", ".cctor", "The name of the method in the specified entrypoint assembly and type to hook and load Chainloader from."); - private static readonly ConfigEntry ConfigApplyRuntimePatches = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigApplyRuntimePatches = ConfigFile.CoreConfig.Bind( "Preloader", "ApplyRuntimePatches", true, "Enables or disables runtime patches.\nThis should always be true, unless you cannot start the game due to a Harmony related issue (such as running .NET Standard runtime) or you know what you're doing."); - private static readonly ConfigEntry ConfigShimHarmony = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigShimHarmony = ConfigFile.CoreConfig.Bind( "Preloader", "ShimHarmonySupport", !Utility.CLRSupportsDynamicAssemblies, "If enabled, basic Harmony functionality is patched to use MonoMod's RuntimeDetour instead.\nTry using this if Harmony does not work in a game."); - private static readonly ConfigEntry ConfigPreloaderCOutLogging = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigPreloaderCOutLogging = ConfigFile.CoreConfig.Bind( "Logging", "PreloaderConsoleOutRedirection", true, "Redirects text from Console.Out during preloader patch loading to the BepInEx logging system."); diff --git a/BepInEx/Bootstrap/Chainloader.cs b/BepInEx/Bootstrap/Chainloader.cs index 861d0ba..75a8901 100644 --- a/BepInEx/Bootstrap/Chainloader.cs +++ b/BepInEx/Bootstrap/Chainloader.cs @@ -357,27 +357,27 @@ namespace BepInEx.Bootstrap #region Config - private static readonly ConfigEntry ConfigUnityLogging = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigUnityLogging = ConfigFile.CoreConfig.Bind( "Logging", "UnityLogListening", true, "Enables showing unity log messages in the BepInEx logging system."); - private static readonly ConfigEntry ConfigDiskWriteUnityLog = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigDiskWriteUnityLog = ConfigFile.CoreConfig.Bind( "Logging.Disk", "WriteUnityLog", false, "Include unity log messages in log file output."); - private static readonly ConfigEntry ConfigDiskAppend = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigDiskAppend = ConfigFile.CoreConfig.Bind( "Logging.Disk", "AppendLog", false, "Appends to the log file instead of overwriting, on game startup."); - private static readonly ConfigEntry ConfigDiskLogging = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigDiskLogging = ConfigFile.CoreConfig.Bind( "Logging.Disk", "Enabled", true, "Enables writing log messages to disk."); - private static readonly ConfigEntry ConfigDiskConsoleDisplayedLevel = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigDiskConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind( "Logging.Disk", "DisplayedLogLevel", LogLevel.Info, "Only displays the specified log level and above in the console output."); diff --git a/BepInEx/Bootstrap/TypeLoader.cs b/BepInEx/Bootstrap/TypeLoader.cs index f9f48a8..9a4b865 100644 --- a/BepInEx/Bootstrap/TypeLoader.cs +++ b/BepInEx/Bootstrap/TypeLoader.cs @@ -251,7 +251,7 @@ namespace BepInEx.Bootstrap #region Config - private static readonly ConfigEntry EnableAssemblyCache = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry EnableAssemblyCache = ConfigFile.CoreConfig.Bind( "Caching", "EnableAssemblyCache", true, "Enable/disable assembly metadata cache\nEnabling this will speed up discovery of plugins and patchers by caching the metadata of all types BepInEx discovers."); diff --git a/BepInEx/Configuration/ConfigFile.cs b/BepInEx/Configuration/ConfigFile.cs index 3926c5d..71a99e6 100644 --- a/BepInEx/Configuration/ConfigFile.cs +++ b/BepInEx/Configuration/ConfigFile.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -11,7 +12,7 @@ namespace BepInEx.Configuration /// /// A helper class to handle persistent data. All public methods are thread-safe. /// - public class ConfigFile + public class ConfigFile : IDictionary { private readonly BepInPlugin _ownerMetadata; @@ -22,30 +23,23 @@ namespace BepInEx.Configuration /// protected Dictionary Entries { get; } = new Dictionary(); - private Dictionary HomelessEntries { get; } = new Dictionary(); + private Dictionary OrphanedEntries { get; } = new Dictionary(); /// /// Create a list with all config entries inside of this config file. /// - [Obsolete("Use GetConfigEntries instead")] + [Obsolete("Use Keys instead")] public ReadOnlyCollection ConfigDefinitions { get { - lock (_ioLock) return Entries.Keys.ToList().AsReadOnly(); + lock (_ioLock) + { + return Entries.Keys.ToList().AsReadOnly(); + } } } - /// - /// Create an array with all config entries inside of this config file. Should be only used for metadata purposes. - /// If you want to access and modify an existing setting then use - /// instead with no description. - /// - public ConfigEntryBase[] GetConfigEntries() - { - lock (_ioLock) return Entries.Values.ToArray(); - } - /// /// Full path to the config file. The file might not exist until a setting is added and changed, or is called. /// @@ -87,7 +81,6 @@ namespace BepInEx.Configuration #region Save/Load private readonly object _ioLock = new object(); - private bool _disableSaving; /// /// Reloads the config from disk. Unsaved changes are lost. @@ -96,47 +89,38 @@ namespace BepInEx.Configuration { lock (_ioLock) { - HomelessEntries.Clear(); + OrphanedEntries.Clear(); - try + string currentSection = string.Empty; + + foreach (string rawLine in File.ReadAllLines(ConfigFilePath)) { - _disableSaving = true; + string line = rawLine.Trim(); - string currentSection = string.Empty; + if (line.StartsWith("#")) //comment + continue; - foreach (string rawLine in File.ReadAllLines(ConfigFilePath)) + if (line.StartsWith("[") && line.EndsWith("]")) //section { - string line = rawLine.Trim(); - - if (line.StartsWith("#")) //comment - continue; - - if (line.StartsWith("[") && line.EndsWith("]")) //section - { - currentSection = line.Substring(1, line.Length - 2); - continue; - } - - string[] split = line.Split('='); //actual config line - if (split.Length != 2) - continue; //empty/invalid line - - string currentKey = split[0].Trim(); - string currentValue = split[1].Trim(); - - var definition = new ConfigDefinition(currentSection, currentKey); - - Entries.TryGetValue(definition, out ConfigEntryBase entry); - - if (entry != null) - entry.SetSerializedValue(currentValue); - else - HomelessEntries[definition] = currentValue; + currentSection = line.Substring(1, line.Length - 2); + continue; } - } - finally - { - _disableSaving = false; + + string[] split = line.Split('='); //actual config line + if (split.Length != 2) + continue; //empty/invalid line + + string currentKey = split[0].Trim(); + string currentValue = split[1].Trim(); + + var definition = new ConfigDefinition(currentSection, currentKey); + + Entries.TryGetValue(definition, out ConfigEntryBase entry); + + if (entry != null) + entry.SetSerializedValue(currentValue); + else + OrphanedEntries[definition] = currentValue; } } @@ -150,8 +134,6 @@ namespace BepInEx.Configuration { lock (_ioLock) { - if (_disableSaving) return; - string directoryName = Path.GetDirectoryName(ConfigFilePath); if (directoryName != null) Directory.CreateDirectory(directoryName); @@ -165,7 +147,7 @@ namespace BepInEx.Configuration } var allConfigEntries = Entries.Select(x => new { x.Key, entry = x.Value, value = x.Value.GetSerializedValue() }) - .Concat(HomelessEntries.Select(x => new { x.Key, entry = (ConfigEntryBase)null, value = x.Value })); + .Concat(OrphanedEntries.Select(x => new { x.Key, entry = (ConfigEntryBase)null, value = x.Value })); foreach (var sectionKv in allConfigEntries.GroupBy(x => x.Key.Section).OrderBy(x => x.Key)) { @@ -192,32 +174,40 @@ namespace BepInEx.Configuration #region Wraps /// - /// Access one of the existing settings. If the setting has not been added yet, null is returned. + /// Access one of the existing settings. If the setting has not been added yet, false is returned. Otherwise, true. /// If the setting exists but has a different type than T, an exception is thrown. - /// New settings should be added with . + /// New settings should be added with . /// /// Type of the value contained in this setting. /// Section and Key of the setting. - public ConfigEntry GetSetting(ConfigDefinition configDefinition) + /// The ConfigEntry value to return. + public bool TryGetEntry(ConfigDefinition configDefinition, out ConfigEntry entry) { lock (_ioLock) { - Entries.TryGetValue(configDefinition, out var entry); - return (ConfigEntry)entry; + if (Entries.TryGetValue(configDefinition, out var rawEntry)) + { + entry = (ConfigEntry)rawEntry; + return true; + } + + entry = null; + return false; } } /// /// Access one of the existing settings. If the setting has not been added yet, null is returned. /// If the setting exists but has a different type than T, an exception is thrown. - /// New settings should be added with . + /// New settings should be added with . /// /// Type of the value contained in this setting. /// Section/category/group of the setting. Settings are grouped by this. /// Name of the setting. - public ConfigEntry GetSetting(string section, string key) + /// The ConfigEntry value to return. + public bool TryGetEntry(string section, string key, out ConfigEntry entry) { - return GetSetting(new ConfigDefinition(section, key)); + return TryGetEntry(new ConfigDefinition(section, key), out entry); } /// @@ -228,39 +218,30 @@ namespace BepInEx.Configuration /// Section and Key of the setting. /// Value of the setting if the setting was not created yet. /// Description of the setting shown to the user and other metadata. - public ConfigEntry AddSetting(ConfigDefinition configDefinition, T defaultValue, ConfigDescription configDescription = null) + public ConfigEntry Bind(ConfigDefinition configDefinition, T defaultValue, ConfigDescription configDescription = null) { if (!TomlTypeConverter.CanConvert(typeof(T))) throw new ArgumentException($"Type {typeof(T)} is not supported by the config system. Supported types: {string.Join(", ", TomlTypeConverter.GetSupportedTypes().Select(x => x.Name).ToArray())}"); lock (_ioLock) { - if (Entries.ContainsKey(configDefinition)) - throw new ArgumentException("The setting " + configDefinition + " has already been created. Use GetSetting to get it."); + if (Entries.TryGetValue(configDefinition, out var rawEntry)) + return (ConfigEntry)rawEntry; - try + var entry = new ConfigEntry(this, configDefinition, defaultValue, configDescription); + + Entries[configDefinition] = entry; + + if (OrphanedEntries.TryGetValue(configDefinition, out string homelessValue)) { - _disableSaving = true; - - var entry = new ConfigEntry(this, configDefinition, defaultValue, configDescription); - Entries[configDefinition] = entry; - - if (HomelessEntries.TryGetValue(configDefinition, out string homelessValue)) - { - entry.SetSerializedValue(homelessValue); - HomelessEntries.Remove(configDefinition); - } - - _disableSaving = false; - if (SaveOnConfigSet) - Save(); - - return entry; - } - finally - { - _disableSaving = false; + entry.SetSerializedValue(homelessValue); + OrphanedEntries.Remove(configDefinition); } + + if (SaveOnConfigSet) + Save(); + + return entry; } } @@ -273,8 +254,8 @@ namespace BepInEx.Configuration /// Name of the setting. /// Value of the setting if the setting was not created yet. /// Description of the setting shown to the user and other metadata. - public ConfigEntry AddSetting(string section, string key, T defaultValue, ConfigDescription configDescription = null) - => AddSetting(new ConfigDefinition(section, key), defaultValue, configDescription); + public ConfigEntry Bind(string section, string key, T defaultValue, ConfigDescription configDescription = null) + => Bind(new ConfigDefinition(section, key), defaultValue, configDescription); /// /// Create a new setting. The setting is saved to drive and loaded automatically. @@ -285,27 +266,27 @@ namespace BepInEx.Configuration /// Name of the setting. /// Value of the setting if the setting was not created yet. /// Simple description of the setting shown to the user. - public ConfigEntry AddSetting(string section, string key, T defaultValue, string description) - => AddSetting(new ConfigDefinition(section, key), defaultValue, new ConfigDescription(description)); + public ConfigEntry Bind(string section, string key, T defaultValue, string description) + => Bind(new ConfigDefinition(section, key), defaultValue, new ConfigDescription(description)); /// - /// Access a setting. Use AddSetting and GetSetting instead. + /// Access a setting. Use Bind and GetSetting instead. /// - [Obsolete("Use AddSetting and GetSetting instead")] + [Obsolete("Use Bind instead")] public ConfigWrapper Wrap(string section, string key, string description = null, T defaultValue = default(T)) { lock (_ioLock) { var definition = new ConfigDefinition(section, key, description); - var setting = GetSetting(definition) ?? AddSetting(definition, defaultValue, string.IsNullOrEmpty(description) ? null : new ConfigDescription(description)); + var setting = Bind(definition, defaultValue, string.IsNullOrEmpty(description) ? null : new ConfigDescription(description)); return new ConfigWrapper(setting); } } /// - /// Access a setting. Use AddSetting and GetSetting instead. + /// Access a setting. Use Bind and GetSetting instead. /// - [Obsolete("Use AddSetting and GetSetting instead")] + [Obsolete("Use Bind instead")] public ConfigWrapper Wrap(ConfigDefinition configDefinition, T defaultValue = default(T)) => Wrap(configDefinition.Section, configDefinition.Key, null, defaultValue); @@ -354,5 +335,143 @@ namespace BepInEx.Configuration } #endregion + + /// + public IEnumerator> GetEnumerator() + { + // We can't really do a read lock for this + return Entries.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + void ICollection>.Add(KeyValuePair item) + { + lock (_ioLock) + Entries.Add(item.Key, item.Value); + } + + /// + public bool Contains(KeyValuePair item) + { + lock (_ioLock) + return ((ICollection>)Entries).Contains(item); + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + lock (_ioLock) + ((ICollection>)Entries).CopyTo(array, arrayIndex); + } + + bool ICollection>.Remove(KeyValuePair item) + { + lock (_ioLock) + return Entries.Remove(item.Key); + } + + /// + public int Count + { + get + { + lock (_ioLock) + return Entries.Count; + } + } + + /// + public bool IsReadOnly => false; + + /// + public bool ContainsKey(ConfigDefinition key) + { + lock (_ioLock) + return Entries.ContainsKey(key); + } + + /// + public void Add(ConfigDefinition key, ConfigEntryBase value) + { + throw new InvalidOperationException("Directly adding a config entry is not supported"); + } + + /// + public bool Remove(ConfigDefinition key) + { + lock (_ioLock) + return Entries.Remove(key); + } + + /// + public void Clear() + { + lock (_ioLock) + Entries.Clear(); + } + + bool IDictionary.TryGetValue(ConfigDefinition key, out ConfigEntryBase value) + { + lock (_ioLock) + return Entries.TryGetValue(key, out value); + } + + /// + ConfigEntryBase IDictionary.this[ConfigDefinition key] + { + get + { + lock (_ioLock) + return Entries[key]; + } + set => throw new InvalidOperationException("Directly setting a config entry is not supported"); + } + + /// + public ConfigEntryBase this[ConfigDefinition key] + { + get + { + lock (_ioLock) + return Entries[key]; + } + } + + /// + /// + /// + /// + /// + public ConfigEntryBase this[string section, string key] + => this[new ConfigDefinition(section, key)]; + + /// + /// Returns the ConfigDefinitions that the ConfigFile contains. + /// Creates a new array when the property is accessed. Thread-safe. + /// + public ICollection Keys + { + get + { + lock (_ioLock) + return Entries.Keys.ToArray(); + } + } + + /// + /// Returns the ConfigEntryBase values that the ConfigFile contains. + /// Creates a new array when the property is accessed. Thread-safe. + /// + ICollection IDictionary.Values + { + get + { + lock (_ioLock) + return Entries.Values.ToArray(); + } + } } -} +} \ No newline at end of file diff --git a/BepInEx/Configuration/ConfigWrapper.cs b/BepInEx/Configuration/ConfigWrapper.cs index a216e15..3200820 100644 --- a/BepInEx/Configuration/ConfigWrapper.cs +++ b/BepInEx/Configuration/ConfigWrapper.cs @@ -6,7 +6,7 @@ namespace BepInEx.Configuration /// Provides access to a single setting inside of a . /// /// Type of the setting. - [Obsolete("Use ConfigFile from new AddSetting overloads instead")] + [Obsolete("Use ConfigFile from new Bind overloads instead")] public sealed class ConfigWrapper { /// diff --git a/BepInEx/Configuration/KeyboardShortcut.cs b/BepInEx/Configuration/KeyboardShortcut.cs index 383f74e..a89e384 100644 --- a/BepInEx/Configuration/KeyboardShortcut.cs +++ b/BepInEx/Configuration/KeyboardShortcut.cs @@ -12,7 +12,7 @@ namespace BepInEx.Configuration /// triggered when the user presses the exact combination. For example, F + LeftCtrl will trigger only if user /// presses and holds only LeftCtrl, and then presses F. If any other keys are pressed, the shortcut will not trigger. /// - /// Can be used as a value of a setting in + /// Can be used as a value of a setting in /// to allow user to change this shortcut and have the changes saved. /// /// How to use: Use in this class instead of in the Update loop. diff --git a/BepInEx/ConsoleUtil/ConsoleWindow.cs b/BepInEx/ConsoleUtil/ConsoleWindow.cs index b4e6fb9..23f7ea4 100644 --- a/BepInEx/ConsoleUtil/ConsoleWindow.cs +++ b/BepInEx/ConsoleUtil/ConsoleWindow.cs @@ -13,12 +13,12 @@ namespace UnityInjector.ConsoleUtil { internal class ConsoleWindow { - public static readonly ConfigEntry ConfigConsoleEnabled = ConfigFile.CoreConfig.AddSetting( + public static readonly ConfigEntry ConfigConsoleEnabled = ConfigFile.CoreConfig.Bind( "Logging.Console", "Enabled", false, "Enables showing a console for log output."); - public static readonly ConfigEntry ConfigConsoleShiftJis = ConfigFile.CoreConfig.AddSetting( + public static readonly ConfigEntry ConfigConsoleShiftJis = ConfigFile.CoreConfig.Bind( "Logging.Console", "ShiftJisEncoding", false, "If true, console is set to the Shift-JIS encoding, otherwise UTF-8 encoding."); diff --git a/BepInEx/Logging/ConsoleLogListener.cs b/BepInEx/Logging/ConsoleLogListener.cs index 290d9b9..a23b4b6 100644 --- a/BepInEx/Logging/ConsoleLogListener.cs +++ b/BepInEx/Logging/ConsoleLogListener.cs @@ -23,7 +23,7 @@ namespace BepInEx.Logging public void Dispose() { } - private static readonly ConfigEntry ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.AddSetting( + private static readonly ConfigEntry ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind( "Logging.Console","DisplayedLogLevel", LogLevel.Info, "Only displays the specified log level and above in the console output."); diff --git a/BepInExTests/Configuration/ConfigFileTests.cs b/BepInExTests/Configuration/ConfigFileTests.cs index 855336e..1b68dae 100644 --- a/BepInExTests/Configuration/ConfigFileTests.cs +++ b/BepInExTests/Configuration/ConfigFileTests.cs @@ -46,7 +46,7 @@ namespace BepInEx.Configuration.Tests { var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test")); var lines = File.ReadAllLines(c.ConfigFilePath); Assert.AreEqual(1, lines.Count(x => x.Equals("[Cat]"))); Assert.AreEqual(1, lines.Count(x => x.Equals("## Test"))); @@ -69,7 +69,7 @@ namespace BepInEx.Configuration.Tests public void AutoSaveTest() { var c = MakeConfig(); - c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test")); + c.Bind("Cat", "Key", 0, new ConfigDescription("Test")); var eventFired = new AutoResetEvent(false); c.ConfigReloaded += (sender, args) => eventFired.Set(); @@ -85,9 +85,9 @@ namespace BepInEx.Configuration.Tests var c = MakeConfig(); File.WriteAllText(c.ConfigFilePath, "[Cat]\n# Test\nKey=1\n"); c.Reload(); - var w = c.AddSetting("Cat", "Key", 0, "Test"); + var w = c.Bind("Cat", "Key", 0, "Test"); Assert.AreEqual(w.Value, 1); - var w2 = c.AddSetting("Cat", "Key2", 0, new ConfigDescription("Test")); + var w2 = c.Bind("Cat", "Key2", 0, new ConfigDescription("Test")); Assert.AreEqual(w2.Value, 0); } @@ -95,7 +95,7 @@ namespace BepInEx.Configuration.Tests public void ReadTest2() { var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test")); Assert.AreEqual(w.Value, 0); File.WriteAllText(c.ConfigFilePath, "[Cat]\n# Test\nKey = 1 \n"); @@ -121,7 +121,7 @@ namespace BepInEx.Configuration.Tests public void EventTestWrapper() { var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test")); File.WriteAllText(c.ConfigFilePath, "[Cat]\n# Test\nKey=1\n"); @@ -141,7 +141,7 @@ namespace BepInEx.Configuration.Tests File.WriteAllText(c.ConfigFilePath, "[Cat]\n# Test\nKey=1\nHomeless=0"); c.Reload(); - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test")); c.Save(); @@ -154,7 +154,7 @@ namespace BepInEx.Configuration.Tests var c = MakeConfig(); var eventFired = false; - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test")); w.SettingChanged += (sender, args) => eventFired = true; Assert.IsFalse(eventFired); @@ -169,7 +169,7 @@ namespace BepInEx.Configuration.Tests public void ValueRangeTest() { var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(0, 2))); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(0, 2))); Assert.AreEqual(0, w.Value); w.Value = 2; @@ -185,7 +185,7 @@ namespace BepInEx.Configuration.Tests public void ValueRangeBadTypeTest() { var c = MakeConfig(); - c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(1, 2))); + c.Bind("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(1, 2))); Assert.Fail(); } @@ -193,7 +193,7 @@ namespace BepInEx.Configuration.Tests public void ValueRangeDefaultTest() { var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(1, 2))); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(1, 2))); Assert.AreEqual(w.Value, 1); } @@ -206,7 +206,7 @@ namespace BepInEx.Configuration.Tests File.WriteAllText(c.ConfigFilePath, "[Cat]\nKey = 1\n"); c.Reload(); - var w = c.AddSetting("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(0, 2))); + var w = c.Bind("Cat", "Key", 0, new ConfigDescription("Test", new AcceptableValueRange(0, 2))); Assert.AreEqual(w.Value, 1); @@ -220,7 +220,7 @@ namespace BepInEx.Configuration.Tests public void ValueListTest() { var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", "kek", new ConfigDescription("Test", new AcceptableValueList("lel", "kek", "wew", "why"))); + var w = c.Bind("Cat", "Key", "kek", new ConfigDescription("Test", new AcceptableValueList("lel", "kek", "wew", "why"))); Assert.AreEqual("kek", w.Value); w.Value = "wew"; @@ -240,7 +240,7 @@ namespace BepInEx.Configuration.Tests Assert.AreEqual(shortcut, d); var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", new KeyboardShortcut(KeyCode.A, KeyCode.LeftShift)); + var w = c.Bind("Cat", "Key", new KeyboardShortcut(KeyCode.A, KeyCode.LeftShift)); Assert.AreEqual(new KeyboardShortcut(KeyCode.A, KeyCode.LeftShift), w.Value); w.Value = shortcut; @@ -255,7 +255,7 @@ namespace BepInEx.Configuration.Tests var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", KeyboardShortcut.Empty, new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", KeyboardShortcut.Empty, new ConfigDescription("Test")); Assert.AreEqual("", w.GetSerializedValue()); @@ -280,7 +280,7 @@ namespace BepInEx.Configuration.Tests const string testVal = "new line\n test \t\0"; var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", testVal, new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", testVal, new ConfigDescription("Test")); Assert.AreEqual(testVal, w.Value); Assert.IsFalse(w.GetSerializedValue().Any(x => x == '\n')); @@ -298,7 +298,7 @@ namespace BepInEx.Configuration.Tests public void UnescapedPathString() { var c = MakeConfig(); - var w = c.AddSetting("Cat", "Key", "", new ConfigDescription("Test")); + var w = c.Bind("Cat", "Key", "", new ConfigDescription("Test")); var unescaped = @"D:\test\p ath"; foreach (string testVal in new[] { unescaped, @"D:\\test\\p ath" })