diff --git a/IPA.Loader/Config/IniFile.cs b/IPA.Loader/Config/IniFile.cs
new file mode 100644
index 00000000..7a808728
--- /dev/null
+++ b/IPA.Loader/Config/IniFile.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace IPA.Config
+{
+ ///
+ /// Create a New INI file to store or load data
+ ///
+ [Obsolete("Jesus, this uses old 16-bit system calls!")]
+ internal class IniFile
+ {
+ [DllImport("KERNEL32.DLL", EntryPoint = "GetPrivateProfileStringW",
+ SetLastError = true,
+ CharSet = CharSet.Unicode, ExactSpelling = true,
+ CallingConvention = CallingConvention.StdCall)]
+ private static extern int GetPrivateProfileString(
+ string lpSection,
+ string lpKey,
+ string lpDefault,
+ StringBuilder lpReturnString,
+ int nSize,
+ string lpFileName);
+
+ [DllImport("KERNEL32.DLL", EntryPoint = "WritePrivateProfileStringW",
+ SetLastError = true,
+ CharSet = CharSet.Unicode, ExactSpelling = true,
+ CallingConvention = CallingConvention.StdCall)]
+ private static extern int WritePrivateProfileString(
+ string lpSection,
+ string lpKey,
+ string lpValue,
+ string lpFileName);
+
+ /*private string _path = "";
+ public string Path
+ {
+ get
+ {
+ return _path;
+ }
+ set
+ {
+ if (!File.Exists(value))
+ File.WriteAllText(value, "", Encoding.Unicode);
+ _path = value;
+ }
+ }*/
+
+ private FileInfo _iniFileInfo;
+ public FileInfo IniFileInfo {
+ get => _iniFileInfo;
+ set {
+ _iniFileInfo = value;
+ if (_iniFileInfo.Exists) return;
+ _iniFileInfo.Directory?.Create();
+ _iniFileInfo.Create();
+ }
+ }
+
+ ///
+ /// INIFile Constructor.
+ ///
+ ///
+ public IniFile(string iniPath)
+ {
+ IniFileInfo = new FileInfo(iniPath);
+ //this.Path = INIPath;
+ }
+
+ ///
+ /// Write Data to the INI File
+ ///
+ ///
+ /// Section name
+ ///
+ /// Key Name
+ ///
+ /// Value Name
+ public void IniWriteValue(string section, string key, string value)
+ {
+ WritePrivateProfileString(section, key, value, IniFileInfo.FullName);
+ }
+
+ ///
+ /// Read Data Value From the Ini File
+ ///
+ ///
+ ///
+ ///
+ public string IniReadValue(string section, string key)
+ {
+ const int maxChars = 1023;
+ StringBuilder result = new StringBuilder(maxChars);
+ GetPrivateProfileString(section, key, "", result, maxChars, IniFileInfo.FullName);
+ return result.ToString();
+ }
+ }
+}
diff --git a/IPA.Loader/Config/ModPrefs.cs b/IPA.Loader/Config/ModPrefs.cs
new file mode 100644
index 00000000..a719db6b
--- /dev/null
+++ b/IPA.Loader/Config/ModPrefs.cs
@@ -0,0 +1,266 @@
+using System;
+using System.Globalization;
+using System.IO;
+using IPA.Loader;
+#if NET3
+using Path = Net3_Proxy.Path;
+#endif
+
+namespace IPA.Config
+{
+ ///
+ /// Allows to get and set preferences for your mod.
+ ///
+ [Obsolete("Uses IniFile, which uses 16 bit system calls. Use BS Utils INI system for now.")]
+ public interface IModPrefs
+ {
+ ///
+ /// Gets a string from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ string GetString(string section, string name, string defaultValue = "", bool autoSave = false);
+ ///
+ /// Gets an int from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ int GetInt(string section, string name, int defaultValue = 0, bool autoSave = false);
+ ///
+ /// Gets a float from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ float GetFloat(string section, string name, float defaultValue = 0f, bool autoSave = false);
+ ///
+ /// Gets a bool from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ bool GetBool(string section, string name, bool defaultValue = false, bool autoSave = false);
+ ///
+ /// Checks whether or not a key exists in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ ///
+ bool HasKey(string section, string name);
+ ///
+ /// Sets a float in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ void SetFloat(string section, string name, float value);
+ ///
+ /// Sets an int in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ void SetInt(string section, string name, int value);
+ ///
+ /// Sets a string in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ void SetString(string section, string name, string value);
+ ///
+ /// Sets a bool in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ void SetBool(string section, string name, bool value);
+ }
+
+ ///
+ ///
+ /// Allows to get and set preferences for your mod.
+ ///
+ [Obsolete("Uses IniFile, which uses 16 bit system calls. Use BS Utils INI system for now.")]
+ public class ModPrefs : IModPrefs
+ {
+ private static ModPrefs _staticInstance;
+ private static IModPrefs StaticInstance => _staticInstance ?? (_staticInstance = new ModPrefs());
+
+ private readonly IniFile _instance;
+
+ ///
+ /// Constructs a ModPrefs object for the provide plugin.
+ ///
+ /// the plugin to get the preferences file for
+ public ModPrefs(PluginLoader.PluginMetadata plugin) {
+ _instance = new IniFile(Path.Combine(Environment.CurrentDirectory, "UserData", "ModPrefs",
+ $"{plugin.Name}.ini"));
+ }
+
+ private ModPrefs()
+ {
+ _instance = new IniFile(Path.Combine(Environment.CurrentDirectory, "UserData", "modprefs.ini"));
+ }
+
+ string IModPrefs.GetString(string section, string name, string defaultValue, bool autoSave)
+ {
+ var value = _instance.IniReadValue(section, name);
+ if (value != "")
+ return value;
+ else if (autoSave)
+ (this as IModPrefs).SetString(section, name, defaultValue);
+
+ return defaultValue;
+ }
+ ///
+ /// Gets a string from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ public static string GetString(string section, string name, string defaultValue = "", bool autoSave = false)
+ => StaticInstance.GetString(section, name, defaultValue, autoSave);
+
+ int IModPrefs.GetInt(string section, string name, int defaultValue, bool autoSave)
+ {
+ if (int.TryParse(_instance.IniReadValue(section, name), out var value))
+ return value;
+ else if (autoSave)
+ (this as IModPrefs).SetInt(section, name, defaultValue);
+
+ return defaultValue;
+ }
+ ///
+ /// Gets an int from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ public static int GetInt(string section, string name, int defaultValue = 0, bool autoSave = false)
+ => StaticInstance.GetInt(section, name, defaultValue, autoSave);
+
+ float IModPrefs.GetFloat(string section, string name, float defaultValue, bool autoSave)
+ {
+ if (float.TryParse(_instance.IniReadValue(section, name), out var value))
+ return value;
+ else if (autoSave)
+ (this as IModPrefs).SetFloat(section, name, defaultValue);
+
+ return defaultValue;
+ }
+ ///
+ /// Gets a float from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ public static float GetFloat(string section, string name, float defaultValue = 0f, bool autoSave = false)
+ => StaticInstance.GetFloat(section, name, defaultValue, autoSave);
+
+ bool IModPrefs.GetBool(string section, string name, bool defaultValue, bool autoSave)
+ {
+ string sVal = GetString(section, name, null);
+ if (sVal == "1" || sVal == "0")
+ {
+ return sVal == "1";
+ }
+ else if (autoSave)
+ {
+ (this as IModPrefs).SetBool(section, name, defaultValue);
+ }
+
+ return defaultValue;
+ }
+ ///
+ /// Gets a bool from the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be used when no value is found.
+ /// Whether or not the default value should be written if no value is found.
+ ///
+ public static bool GetBool(string section, string name, bool defaultValue = false, bool autoSave = false)
+ => StaticInstance.GetBool(section, name, defaultValue, autoSave);
+
+ bool IModPrefs.HasKey(string section, string name)
+ {
+ return _instance.IniReadValue(section, name) != null;
+ }
+ ///
+ /// Checks whether or not a key exists in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ ///
+ public static bool HasKey(string section, string name) => StaticInstance.HasKey(section, name);
+
+ void IModPrefs.SetFloat(string section, string name, float value)
+ {
+ _instance.IniWriteValue(section, name, value.ToString(CultureInfo.InvariantCulture));
+ }
+ ///
+ /// Sets a float in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ public static void SetFloat(string section, string name, float value)
+ => StaticInstance.SetFloat(section, name, value);
+
+ void IModPrefs.SetInt(string section, string name, int value)
+ {
+ _instance.IniWriteValue(section, name, value.ToString());
+ }
+ ///
+ /// Sets an int in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ public static void SetInt(string section, string name, int value)
+ => StaticInstance.SetInt(section, name, value);
+
+ void IModPrefs.SetString(string section, string name, string value)
+ {
+ _instance.IniWriteValue(section, name, value);
+ }
+ ///
+ /// Sets a string in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ public static void SetString(string section, string name, string value)
+ => StaticInstance.SetString(section, name, value);
+
+ void IModPrefs.SetBool(string section, string name, bool value)
+ {
+ _instance.IniWriteValue(section, name, value ? "1" : "0");
+ }
+ ///
+ /// Sets a bool in the ini.
+ ///
+ /// Section of the key.
+ /// Name of the key.
+ /// Value that should be written.
+ public static void SetBool(string section, string name, bool value)
+ => StaticInstance.SetBool(section, name, value);
+ }
+}
diff --git a/IPA.Loader/IPA.Loader.csproj b/IPA.Loader/IPA.Loader.csproj
index fe3cb609..b689ce82 100644
--- a/IPA.Loader/IPA.Loader.csproj
+++ b/IPA.Loader/IPA.Loader.csproj
@@ -112,10 +112,12 @@
+
+
diff --git a/IPA.Loader/Loader/PluginInitInjector.cs b/IPA.Loader/Loader/PluginInitInjector.cs
index 247f8817..c3dda102 100644
--- a/IPA.Loader/Loader/PluginInitInjector.cs
+++ b/IPA.Loader/Loader/PluginInitInjector.cs
@@ -64,6 +64,9 @@ namespace IPA.Loader
private static readonly List injectors = new List
{
new TypedInjector(typeof(Logger), (prev, param, meta) => prev ?? new StandardLogger(meta.Name)),
+#pragma warning disable CS0618 // Type or member is obsolete
+ new TypedInjector(typeof(IModPrefs), (prev, param, meta) => prev ?? new ModPrefs(meta)),
+#pragma warning restore CS0618 // Type or member is obsolete
new TypedInjector(typeof(PluginLoader.PluginMetadata), (prev, param, meta) => prev ?? meta),
new TypedInjector(typeof(IConfigProvider), (prev, param, meta) =>
{
diff --git a/Refs/Assembly-CSharp.dll b/Refs/Assembly-CSharp.dll
index 9ce9f2d7..cfa9b242 100644
Binary files a/Refs/Assembly-CSharp.dll and b/Refs/Assembly-CSharp.dll differ
diff --git a/Refs/UnityEngine.CoreModule.Net4.dll b/Refs/UnityEngine.CoreModule.Net4.dll
index 6362cdf1..158ef534 100644
Binary files a/Refs/UnityEngine.CoreModule.Net4.dll and b/Refs/UnityEngine.CoreModule.Net4.dll differ