Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of ZioConfigFile v1.0.2
ZioConfigFile.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; using Zio; using Zio.FileSystems; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ZioConfigFile")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+989b526372e295d2a3d8d6eff4aa3222af20bb5c")] [assembly: AssemblyProduct("ZioConfigFile")] [assembly: AssemblyTitle("ZioConfigFile")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ZioConfigFile { public class ZioConfigEntry<T> : ZioConfigEntryBase { private T _typedValue; public T Value { get { return _typedValue; } set { value = ClampValue(value); if (!value.Equals(_typedValue)) { T typedValue = _typedValue; _typedValue = value; OnSettingChanged(this, typedValue); } } } public override object BoxedValue { get { return Value; } set { Value = (T)value; } } public ZioConfigEntry(ConfigDefinition configDefinition, T defaultValue, ConfigDescription configDescription) : base(configDefinition, typeof(T), defaultValue, configDescription) { } public static implicit operator ConfigEntry<T>(ZioConfigEntry<T> zioEntry) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if (zioEntry.configEntryFallback != null) { return (ConfigEntry<T>)(object)zioEntry.configEntryFallback; } if (ZioConfigEntryBase.fallbackConfigFile == null) { ZioConfigEntryBase.fallbackConfigFile = new ConfigFile("", false) { SaveOnConfigSet = false }; } ConfigEntry<T> fallback = new ConfigEntry<T>(ZioConfigEntryBase.fallbackConfigFile, zioEntry.Definition, (T)zioEntry.DefaultValue, zioEntry.Description); fallback.SettingChanged += delegate { if (!zioEntry.duckChanged) { zioEntry.duckFallbackChanged = true; zioEntry.Value = fallback.Value; zioEntry.duckFallbackChanged = false; } }; zioEntry.SettingChanged += delegate { if (!zioEntry.duckFallbackChanged) { zioEntry.duckChanged = true; fallback.Value = zioEntry.Value; zioEntry.duckChanged = false; } }; zioEntry.configEntryFallback = (ConfigEntryBase)(object)fallback; return (ConfigEntry<T>)(object)zioEntry.configEntryFallback; } } public abstract class ZioConfigEntryBase { public bool DontSaveOnChange; protected ConfigEntryBase configEntryFallback; protected bool duckChanged; protected bool duckFallbackChanged; protected static ConfigFile fallbackConfigFile; public ConfigDefinition Definition { get; } public ConfigDescription Description { get; } public Type SettingType { get; } public object DefaultValue { get; } public abstract object BoxedValue { get; set; } public event Action<ZioConfigEntryBase, object, bool> SettingChanged; protected ZioConfigEntryBase(ConfigDefinition configDefinition, Type settingType, object defaultValue, ConfigDescription configDescription) { Definition = configDefinition ?? throw new ArgumentNullException("configDefinition"); SettingType = settingType ?? throw new ArgumentNullException("settingType"); Description = configDescription ?? ConfigDescription.Empty; if (Description.AcceptableValues != null && !SettingType.IsAssignableFrom(Description.AcceptableValues.ValueType)) { throw new AggregateException("configDescription.AcceptableValues is for a different type than the type of this setting"); } DefaultValue = defaultValue; BoxedValue = defaultValue; } public string GetSerializedValue() { return TomlTypeConverter.ConvertToString(BoxedValue, SettingType); } public void SetSerializedValue(string value) { try { BoxedValue = TomlTypeConverter.ConvertToValue(value, SettingType); } catch (Exception ex) { ZioConfigFile.Logger.LogWarning((object)$"Config value of setting \"{Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } } public T ClampValue<T>(T value) { return (Description.AcceptableValues != null) ? ((T)Description.AcceptableValues.Clamp((object)value)) : value; } public void OnSettingChanged(ZioConfigEntryBase config, object oldValue) { this.SettingChanged?.Invoke(config, oldValue, DontSaveOnChange); } public void WriteDescription(StreamWriter writer) { if (!string.IsNullOrEmpty(Description.Description)) { writer.WriteLine("## " + Description.Description.Replace("\n", "\n## ")); } writer.WriteLine("# Setting type: " + SettingType.Name); writer.WriteLine("# Default value: " + TomlTypeConverter.ConvertToString(DefaultValue, SettingType)); if (Description.AcceptableValues != null) { writer.WriteLine(Description.AcceptableValues.ToDescriptionString()); } else if (SettingType.IsEnum) { writer.WriteLine("# Acceptable values: " + string.Join(", ", Enum.GetNames(SettingType))); if (SettingType.GetCustomAttributes(typeof(FlagsAttribute), inherit: true).Any()) { writer.WriteLine("# Multiple values can be set at the same time by separating them with , (e.g. Debug, Warning)"); } } } } public class ZioConfigFile : IDictionary<ConfigDefinition, ZioConfigEntryBase>, ICollection<KeyValuePair<ConfigDefinition, ZioConfigEntryBase>>, IEnumerable<KeyValuePair<ConfigDefinition, ZioConfigEntryBase>>, IEnumerable { protected object _ioLock = new object(); private static readonly FileSystem InternalFileSystem = (FileSystem)new PhysicalFileSystem(); private readonly Stopwatch saveStopwatch = new Stopwatch(); private bool _waitingForSaves; public int waitDuration = 1000; public BepInPlugin OwnerMetadata { get; } public FileSystem FileSystem { get; } public UPath FilePath { get; } public Dictionary<ConfigDefinition, ZioConfigEntryBase> Entries { get; } = new Dictionary<ConfigDefinition, ZioConfigEntryBase>(); protected Dictionary<ConfigDefinition, string> OrphanedEntries { get; } = new Dictionary<ConfigDefinition, string>(); public static ManualLogSource Logger { get; } = new ManualLogSource("ZioConfigFile"); public static FileSystem BepinConfigFileSystem { get; } = (FileSystem)new SubFileSystem((IFileSystem)(object)InternalFileSystem, InternalFileSystem.ConvertPathFromInternal(Paths.ConfigPath), true); public bool SaveOnConfigSet { get; set; } = true; public int Count { get { lock (_ioLock) { return Entries.Count; } } } public bool IsReadOnly => false; ZioConfigEntryBase IDictionary<ConfigDefinition, ZioConfigEntryBase>.this[ConfigDefinition key] { get { lock (_ioLock) { return Entries[key]; } } set { throw new InvalidOperationException("Directly setting a config entry is not supported"); } } public ZioConfigEntryBase this[ConfigDefinition key] { get { lock (_ioLock) { return Entries[key]; } } } public ZioConfigEntryBase this[string section, string key] => this[new ConfigDefinition(section, key)]; public ICollection<ConfigDefinition> Keys { get { lock (_ioLock) { return Entries.Keys; } } } ICollection<ZioConfigEntryBase> IDictionary<ConfigDefinition, ZioConfigEntryBase>.Values { get { lock (_ioLock) { return Entries.Values; } } } public event Action ConfigReloaded; public event Action<ZioConfigEntryBase, object> SettingChanged; public ZioConfigFile(BepInPlugin plugin, bool saveOnInit = true) : this(BepinConfigFileSystem, UPath.op_Implicit(plugin.Name), saveOnInit, plugin) { }//IL_000c: Unknown result type (might be due to invalid IL or missing references) public ZioConfigFile(FileSystem fileSystem, UPath path, bool saveOnInit, BaseUnityPlugin unityPlugin) : this(fileSystem, path, saveOnInit, unityPlugin.Info.Metadata) { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) public ZioConfigFile(FileSystem fileSystem, UPath path, bool saveOnInit, BepInPlugin bepInPlugin = null) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) OwnerMetadata = bepInPlugin; FileSystem = fileSystem; FilePath = path; if (fileSystem.FileExists(path)) { Reload(); } else if (saveOnInit) { Save(); } } public void Reload() { InternalReload(); } protected virtual void InternalReload() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown lock (_ioLock) { if (!FileSystem.FileExists(FilePath)) { return; } OrphanedEntries.Clear(); using Stream stream = FileSystem.OpenFile(FilePath, FileMode.Open, FileAccess.Read, FileShare.None); using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); if (!streamReader.EndOfStream) { string text = ""; string text2 = streamReader.ReadLine(); do { string text3 = text2.Trim(); if (text3.StartsWith("#")) { continue; } if (text3.StartsWith("[") && text3.EndsWith("]")) { text = text3.Substring(1, text3.Length - 2); continue; } string[] array = text3.Split('='); if (array.Length == 2) { ConfigDefinition key = new ConfigDefinition(text, array[0].Trim()); if (Entries.TryGetValue(key, out var value)) { value.SetSerializedValue(array[1].Trim()); } else { OrphanedEntries[key] = array[1].Trim(); } } } while ((text2 = streamReader.ReadLine()) != null); } } OnConfigReloaded(); } public void OnConfigReloaded() { Delegate[] array = this.ConfigReloaded?.GetInvocationList(); if (array == null) { return; } Delegate[] array2 = array; foreach (Delegate @delegate in array2) { try { (@delegate as Action)?.Invoke(); } catch (Exception ex) { Logger.LogError((object)ex); } } } public void OnSettingChanged(ZioConfigEntryBase changedSetting, object valueBefore, bool ignoreSave) { if (!ignoreSave && SaveOnConfigSet) { Save(); } Delegate[] array = this.SettingChanged?.GetInvocationList(); if (array == null) { return; } Delegate[] array2 = array; foreach (Delegate @delegate in array2) { try { (@delegate as Action<ZioConfigEntryBase, object>)?.Invoke(changedSetting, valueBefore); } catch (Exception ex) { Logger.LogError((object)ex); } } } protected virtual void SaveThread() { //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) while (saveStopwatch.ElapsedMilliseconds < waitDuration) { Task.Delay(Mathf.FloorToInt((float)waitDuration * 0.1f)); } using MemoryStream memoryStream = new MemoryStream(); using StreamWriter streamWriter = new StreamWriter(memoryStream, Encoding.UTF8); if (OwnerMetadata != null) { streamWriter.WriteLine($"## Settings file was created by plugin {OwnerMetadata.Name} v{OwnerMetadata.Version}"); streamWriter.WriteLine("## Plugin GUID: " + OwnerMetadata.GUID); streamWriter.WriteLine(); } lock (_ioLock) { foreach (IGrouping<string, (ConfigDefinition, ZioConfigEntryBase, string)> item in from x in Entries.Select((KeyValuePair<ConfigDefinition, ZioConfigEntryBase> x) => (x.Key, x.Value, x.Value.GetSerializedValue())).Concat(((IEnumerable<KeyValuePair<ConfigDefinition, string>>)OrphanedEntries).Select((Func<KeyValuePair<ConfigDefinition, string>, (ConfigDefinition, ZioConfigEntryBase, string)>)((KeyValuePair<ConfigDefinition, string> x) => (x.Key, null, x.Value)))) group x by x.Key.Section into x orderby x.Key select x) { streamWriter.WriteLine("[" + item.Key + "]"); foreach (var item2 in item) { streamWriter.WriteLine(); item2.Item2?.WriteDescription(streamWriter); streamWriter.WriteLine(item2.Item1.Key + " = " + item2.Item3); } streamWriter.WriteLine(); } streamWriter.Flush(); } try { UPath filePath = FilePath; if (((UPath)(ref filePath)).IsNull) { goto IL_0278; } filePath = FilePath; if (((UPath)(ref filePath)).IsEmpty || FilePath == UPath.op_Implicit("/")) { goto IL_0278; } FileSystem.CreateDirectory(UPathExtensions.GetDirectory(FilePath)); goto end_IL_0237; IL_0278: Logger.LogWarning((object)"Tried to create a ZioConfigFile with a null, empty or root path, escaping."); return; end_IL_0237:; } catch (UnauthorizedAccessException ex) { Debug.LogError((object)ex); } using Stream stream = FileSystem.OpenFile(FilePath, FileMode.Create, FileAccess.Write, FileShare.None); stream.Write(memoryStream.GetBuffer(), 0, (int)memoryStream.Length); stream.Close(); _waitingForSaves = false; } public void Save() { saveStopwatch.Restart(); if (!_waitingForSaves) { new Thread(SaveThread).Start(); } _waitingForSaves = true; } public bool TryGetEntry<T>(string section, string key, out ZioConfigEntry<T> entry) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown return TryGetEntry(new ConfigDefinition(section, key), out entry); } public bool TryGetEntry<T>(ConfigDefinition configDefinition, out ZioConfigEntry<T> entry) { lock (_ioLock) { if (Entries.TryGetValue(configDefinition, out var value)) { entry = (ZioConfigEntry<T>)value; return true; } entry = null; return false; } } public virtual ZioConfigEntry<T> Bind<T>(ConfigDefinition configDefinition, T defaultValue, ConfigDescription configDescription = null) { if (!TomlTypeConverter.CanConvert(typeof(T))) { throw new ArgumentException(string.Format("Type {0} is not supported by the config system. Supported types: {1}", typeof(T), string.Join(", ", (from x in TomlTypeConverter.GetSupportedTypes() select x.Name).ToArray()))); } lock (_ioLock) { if (Entries.TryGetValue(configDefinition, out var value)) { return (ZioConfigEntry<T>)value; } ZioConfigEntry<T> zioConfigEntry = new ZioConfigEntry<T>(configDefinition, defaultValue, configDescription); Entries[configDefinition] = zioConfigEntry; zioConfigEntry.SettingChanged += OnSettingChanged; if (OrphanedEntries.TryGetValue(configDefinition, out var value2)) { zioConfigEntry.SetSerializedValue(value2); OrphanedEntries.Remove(configDefinition); } if (SaveOnConfigSet) { Save(); } return zioConfigEntry; } } public ZioConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001b: Expected O, but got Unknown return Bind(new ConfigDefinition(section, key), defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>())); } public ZioConfigEntry<T> Bind<T>(string section, string key, T defaultValue, ConfigDescription configDescription = null) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown return Bind(new ConfigDefinition(section, key), defaultValue, configDescription); } public IEnumerator<KeyValuePair<ConfigDefinition, ZioConfigEntryBase>> GetEnumerator() { return Entries.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void ICollection<KeyValuePair<ConfigDefinition, ZioConfigEntryBase>>.Add(KeyValuePair<ConfigDefinition, ZioConfigEntryBase> item) { lock (_ioLock) { Entries.Add(item.Key, item.Value); } } public bool Contains(KeyValuePair<ConfigDefinition, ZioConfigEntryBase> item) { return Entries.Contains(item); } public void CopyTo(KeyValuePair<ConfigDefinition, ZioConfigEntryBase>[] array, int arrayIndex) { lock (_ioLock) { ((ICollection<KeyValuePair<ConfigDefinition, ZioConfigEntryBase>>)Entries).CopyTo(array, arrayIndex); } } public bool Remove(KeyValuePair<ConfigDefinition, ZioConfigEntryBase> item) { lock (_ioLock) { return Entries.Remove(item.Key); } } public bool ContainsKey(ConfigDefinition key) { lock (_ioLock) { return Entries.ContainsKey(key); } } public void Add(ConfigDefinition key, ZioConfigEntryBase 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(); } } public bool TryGetValue(ConfigDefinition key, out ZioConfigEntryBase value) { lock (_ioLock) { return Entries.TryGetValue(key, out value); } } } [BepInPlugin("bubbet.zioconfigfile", "Zio Config File", "1.0.1")] public class ZioConfigFilePlugin : BaseUnityPlugin { } }