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/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