Decompiled source of ConfigurableCompany v3.4.0
Amrv.ConfigurableCompany.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using Amrv.ConfigurableCompany.API; using Amrv.ConfigurableCompany.API.Accesors; using Amrv.ConfigurableCompany.API.ConfigTypes; using Amrv.ConfigurableCompany.API.Display; using Amrv.ConfigurableCompany.API.Event; using Amrv.ConfigurableCompany.Core; using Amrv.ConfigurableCompany.Core.Config; using Amrv.ConfigurableCompany.Core.Dependency; using Amrv.ConfigurableCompany.Core.Display; using Amrv.ConfigurableCompany.Core.Display.ConfigTypes; using Amrv.ConfigurableCompany.Core.Display.Items; using Amrv.ConfigurableCompany.Core.Display.Menu; using Amrv.ConfigurableCompany.Core.Display.Scripts; using Amrv.ConfigurableCompany.Core.Display.items; using Amrv.ConfigurableCompany.Core.Display.menu; using Amrv.ConfigurableCompany.Core.Extensions; using Amrv.ConfigurableCompany.Core.IO; using Amrv.ConfigurableCompany.Core.Net; using Amrv.ConfigurableCompany.Core.Patch; using Amrv.ConfigurableCompany.Plugin; using Amrv.ConfigurableCompany.Utils; using Amrv.ConfigurableCompany.Utils.IO; using Amrv.ConfigurableCompany.Utils.Unity; using Amrv.ConfigurableCompany.content.display; using Amrv.ConfigurableCompany.content.model; using Amrv.ConfigurableCompany.content.model.data; using Amrv.ConfigurableCompany.content.model.events; using Amrv.ConfigurableCompany.content.model.types; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AMRV")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("An api to allow developers to create configurable parameters for lethal company. These configurations can be modified in-game using a built in menu, persist during sesions and are save-dependant on each game file.")] [assembly: AssemblyFileVersion("3.4.0.0")] [assembly: AssemblyInformationalVersion("3.4.0+d5bb5641471f20117ae4ccf02972d5c45eab6885")] [assembly: AssemblyProduct("Amrv.ConfigurableCompany")] [assembly: AssemblyTitle("Amrv.ConfigurableCompany")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TheAnsuz/Lethal-Company-Configurable-Company-API")] [assembly: AssemblyVersion("3.4.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] internal sealed class IsUnmanagedAttribute : Attribute { } [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 Amrv.ConfigurableCompany { [Obsolete("Use CTypes")] public class ConfigurationTypes { public static readonly ConfigurationType String = new StringConfigurationType(); public static readonly ConfigurationType SmallString = new SmallStringConfigurationType(); public static readonly ConfigurationType Boolean = new BooleanConfigurationType(); public static readonly ConfigurationType Percent = new PercentConfigurationType(); public static readonly ConfigurationType Float = new FloatConfigurationType(); public static readonly ConfigurationType Integer = new IntegerConfigurationType(); public static ConfigurationType RangeInteger(int min, int max) { return new IntegerConfigurationType(min, max); } public static ConfigurationType RangeFloat(float min, float max) { return new FloatConfigurationType(min, max); } public static ConfigurationType Slider(float min, float max) { return new SliderConfigurationType(min, max); } public static ConfigurationType StringOfLength(int maxLength) { return new StringConfigurationType(maxLength); } public static ConfigurationType Options(Type enumeration) { return new EnumConfigurationType(enumeration); } public static ConfigurationType Options(params string[] options) { return new ListConfigurationType(options); } private ConfigurationTypes() { } } [Obsolete("Use CEvents")] public class Events { [Obsolete("Use CEvents.ConfigEvents.ChangeConfig")] public static EventType<ConfigurationChanged> ConfigurationChanged = new EventType<ConfigurationChanged>(); [Obsolete("Use CEvents.ConfigEvents.CreateConfig")] public static EventType<ConfigurationCreated> ConfigurationCreated = new EventType<ConfigurationCreated>(); [Obsolete("Use CEvents.LifecycleEvents.PluginStart")] public static EventType<EventArgs> PluginInitialized = new EventType<EventArgs>(); [Obsolete("Use CEvents.LifecycleEvents.PluginStart")] public static EventType<EventArgs> PluginSetup = new EventType<EventArgs>(); [Obsolete("Use CEvents.LifecycleEvents.PluginStart")] public static EventType<EventArgs> PluginEnabled = new EventType<EventArgs>(); [Obsolete("Use CEvents.MenuEvents.Create")] public static EventType<EventArgs> BeforeMenuDisplay = new EventType<EventArgs>(); [Obsolete("Use CEvents.MenuEvents.Prepare")] public static EventType<EventArgs> AfterMenuDisplay = new EventType<EventArgs>(); private Events() { } internal static void Start() { CEvents.ConfigEvents.ChangeConfig.AddListener(delegate(CEventChangeConfig e) { ChangeResult result = ((!e.Success) ? ChangeResult.FAILED : (e.Converted ? ChangeResult.SUCCESS_CONVERTED : ChangeResult.SUCCESS)); if (Configuration.TryGet(e.Config.ID, out var value2)) { ConfigurationChanged.Invoke(new ConfigurationChanged(value2, e.OldValue, e.NewValue, e.Reason.OldReason(), result)); } }); CEvents.ConfigEvents.CreateConfig.AddListener(delegate(CEventCreateConfig e) { if (Configuration.TryGet(e.Config.ID, out var value)) { ConfigurationCreated.Invoke(new ConfigurationCreated(value)); } }); CEvents.LifecycleEvents.PluginStart.AddListener(delegate { PluginSetup.Invoke(EventArgs.Empty); PluginInitialized.Invoke(EventArgs.Empty); PluginEnabled.Invoke(EventArgs.Empty); }); CEvents.MenuEvents.Create.AddListener(delegate { AfterMenuDisplay.Invoke(EventArgs.Empty); }); CEvents.MenuEvents.Prepare.AddListener(delegate { BeforeMenuDisplay.Invoke(EventArgs.Empty); }); } } [Obsolete("Use ConfigAPI")] public sealed class LethalConfiguration { private static readonly Dictionary<Assembly, ConfigurationPage> _defaultModPages = new Dictionary<Assembly, ConfigurationPage>(); private static readonly Dictionary<Assembly, ConfigurationCategory> _defaultModCategories = new Dictionary<Assembly, ConfigurationCategory>(); public const string PLUGIN_GUID = "dev.amrv.lethalCompany.config"; public const string PLUGIN_VERSION = "3.4.0"; public static ConfigurationCategory DefaultCategory => ConfigurationCategory.Default; public static ConfigurationPage DefaultPage => ConfigurationPage.Default; public static Dictionary<string, Configuration>.KeyCollection ConfigIDs => Configuration.Ids; public static Dictionary<string, Configuration>.ValueCollection Configs => Configuration.Configs; public static Dictionary<string, ConfigurationCategory>.KeyCollection CategoryIDs => ConfigurationCategory.Ids; public static Dictionary<string, ConfigurationCategory>.ValueCollection Categories => ConfigurationCategory.Categories; private LethalConfiguration() { } public static ConfigurationBuilder CreateConfig() { return new ConfigurationBuilder(); } public static ConfigurationBuilder CreateConfig(string id) { return new ConfigurationBuilder(id); } public static ConfigurationCategoryBuilder CreateCategory() { return new ConfigurationCategoryBuilder(); } public static ConfigurationCategoryBuilder CreateCategory(string id) { return new ConfigurationCategoryBuilder(id); } public static ConfigurationPageBuilder CreatePage() { return new ConfigurationPageBuilder(); } public static ConfigurationPage PageForMyMod(string name = null) { Assembly callingAssembly = Assembly.GetCallingAssembly(); if (!_defaultModPages.TryGetValue(callingAssembly, out var value)) { value = new ConfigurationPageBuilder { Name = (name ?? Assembly.GetCallingAssembly().GetName().Name) }.Build(); _defaultModPages.Add(callingAssembly, value); } return value; } public static ConfigurationCategory CategoryForMyMod(string name = "General") { Assembly callingAssembly = Assembly.GetCallingAssembly(); if (!_defaultModCategories.TryGetValue(callingAssembly, out var value)) { value = new ConfigurationCategoryBuilder().SetID(callingAssembly.GetName().Name.Replace(" ", "_").Replace(".", "-").ToLower()).SetName(name ?? Assembly.GetCallingAssembly().GetName().Name); _defaultModCategories.Add(callingAssembly, value); } return value; } public static bool TryGetConfig(string id, out Configuration config) { return Configuration.TryGet(id, out config); } public static bool TryGetCategory(string id, out ConfigurationCategory category) { return ConfigurationCategory.TryGet(id, out category); } } public static class PluginInfo { public const string PLUGIN_GUID = "Amrv.ConfigurableCompany"; public const string PLUGIN_NAME = "Amrv.ConfigurableCompany"; public const string PLUGIN_VERSION = "3.4.0"; } } namespace Amrv.ConfigurableCompany.Utils { public class IDGen { [CompilerGenerated] private int <Bytes>P; private readonly List<int> Hash; public IDGen(int Bytes) { <Bytes>P = Bytes; Hash = new List<int>(); base..ctor(); } public static string DeterministicString(object any) { throw new NotImplementedException(); } public static int DeterministicIntHash(string str) { int num = 0; byte[] bytes = Encoding.UTF8.GetBytes(str); byte[] array = new byte[4]; for (int i = 0; i < bytes.Length; i++) { array[i % array.Length] ^= (byte)(((bytes[i] << 7) ^ (bytes[i] >> 3)) | (bytes[i] << 5)); } for (int j = 0; j < array.Length; j++) { num = (num << 8) | array[j]; } return num; } public void AddDeterminant(string any) { Hash.Add(DeterministicIntHash(any)); } private byte[] GenerateID() { byte[] array = new byte[<Bytes>P]; byte[] array2 = new byte[<Bytes>P]; foreach (int item in Hash) { new Random(item).NextBytes(array2); for (int i = 0; i < array2.Length; i++) { array[i] |= array2[i]; } } return array; } public byte[] GetIDBytes() { return GenerateID(); } public string GetIDHex() { return BitConverter.ToString(GenerateID()); } public string GetIDBaseX(int @base) { throw new NotImplementedException(); } public string GetIDBaseX(params char[] notation) { throw new NotImplementedException(); } public string GetIDBase64() { return Convert.ToBase64String(GenerateID()); } } public static class NumberUtils { private static readonly HashSet<Type> DecimalTypes = new HashSet<Type> { typeof(double), typeof(float), typeof(decimal) }; private static readonly HashSet<Type> WholeNumberTypes = new HashSet<Type> { typeof(int), typeof(long), typeof(short), typeof(sbyte), typeof(byte), typeof(ulong), typeof(ushort), typeof(uint) }; private static readonly HashSet<Type> NumericTypes = new HashSet<Type> { typeof(int), typeof(double), typeof(decimal), typeof(long), typeof(short), typeof(sbyte), typeof(byte), typeof(ulong), typeof(ushort), typeof(uint), typeof(float) }; private const double THOUSAND = 1000.0; private const double MILLION = 1000000.0; private const double BILLION = 1000000000.0; private const double TRILLION = 1000000000000.0; private const double QUADRILLION = 1000000000000000.0; private const double QUINTILLION = 1E+18; private const double TOO_MUCH = 1E+21; public static bool IsWhole(object any) { return WholeNumberTypes.Contains(any.GetType()); } public static bool IsWhole(Type type) { return WholeNumberTypes.Contains(type); } public static bool IsWhole<T>() { return WholeNumberTypes.Contains(typeof(T)); } public static bool IsDecimal(object any) { return DecimalTypes.Contains(any.GetType()); } public static bool IsDecimal(Type type) { return DecimalTypes.Contains(type); } public static bool IsDecimal<T>() { return DecimalTypes.Contains(typeof(T)); } public static bool IsNumber(object any) { return NumericTypes.Contains(any.GetType()); } public static bool IsNumber(Type type) { return NumericTypes.Contains(type); } public static bool IsNumber<T>() { return NumericTypes.Contains(Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T)); } public static string NumberWithSuffix(double num) { if (num == double.MinValue || num == double.NegativeInfinity) { return "-Infinite"; } if (num == double.MaxValue || num == double.PositiveInfinity) { return "Infinite"; } if (num == 0.0) { return "0"; } string text = ((num < 0.0) ? "-" : ""); num = Math.Abs(num); if (num > 1E+21) { return text + "Infinite"; } if (num > 1E+18) { return $"{text}{num / 1E+18:#.00}E"; } if (num > 1000000000000000.0) { return $"{text}{num / 1000000000000000.0:#.00}Q"; } if (num > 1000000000000.0) { return $"{text}{num / 1000000000000.0:#.00}T"; } if (num > 1000000000.0) { return $"{text}{num / 1000000000.0:#.00}B"; } if (num > 1000000.0) { return $"{text}{num / 1000000.0:#.00}M"; } if (num > 1000.0) { return $"{text}{num / 1000.0:#.00}K"; } return $"{text}{num:#}"; } public static string NumberWithSuffix(long num) { if (num == long.MinValue) { return "-Infinite"; } if (num == long.MaxValue) { return "Infinite"; } if (num == 0L) { return "0"; } string text = ((num < 0) ? "-" : ""); num = Math.Abs(num); if ((double)num > 1E+21) { return text + "Infinite"; } if ((double)num > 1E+18) { return $"{text}{(double)num / 1E+18:#}E"; } if ((double)num > 1000000000000000.0) { return $"{text}{(double)num / 1000000000000000.0:#}Q"; } if ((double)num > 1000000000000.0) { return $"{text}{(double)num / 1000000000000.0:#}T"; } if ((double)num > 1000000000.0) { return $"{text}{(double)num / 1000000000.0:#}B"; } if ((double)num > 1000000.0) { return $"{text}{(double)num / 1000000.0:#}M"; } if ((double)num > 1000.0) { return $"{text}{(double)num / 1000.0:#}K"; } return $"{text}{num:#}"; } } } namespace Amrv.ConfigurableCompany.Utils.Unity { public class FastBundle : IDisposable { private readonly AssetBundle Bundle; private string path; public string Path { get { return path; } set { path = value.ToLower(); } } public FastBundle(AssetBundle bundle) { Bundle = bundle; path = ""; base..ctor(); } public void In(string segment) { path += segment.ToLower(); } public void OutAll() { path = string.Empty; } public void Out() { Out("/"); } public void Out(string segment) { int num = path.LastIndexOf(segment); if (num != -1) { path = path.Substring(0, num); } } [Obsolete("use GetAllAssetNames")] public string[] AllAssetNames() { return Bundle.AllAssetNames(); } public string[] GetAllAssetNames() { return Bundle.GetAllAssetNames(); } public string[] GetAllScenePaths() { return Bundle.GetAllScenePaths(); } public override bool Equals(object other) { return ((object)Bundle).Equals(other); } public bool Contains(string name) { return Bundle.Contains(name); } public override int GetHashCode() { return ((object)Bundle).GetHashCode(); } public IntPtr GetCachedPtr() { return ((Object)Bundle).GetCachedPtr(); } public int GetInstanceID() { return ((Object)Bundle).GetInstanceID(); } public override string ToString() { return ((object)Bundle).ToString(); } public void EnsureRunningOnMainThread() { ((Object)Bundle).EnsureRunningOnMainThread(); } public T[] LoadAllAssets<T>() where T : Object { return Bundle.LoadAllAssets<T>(); } public AssetBundleRequest LoadAllAssetsAsync<T>() where T : Object { return Bundle.LoadAllAssetsAsync<T>(); } public T LoadAsset<T>(string name) where T : Object { return Bundle.LoadAsset<T>(path + name); } public AssetBundleRequest LoadAssetAsync<T>(string name) where T : Object { return Bundle.LoadAssetAsync<T>(path + name.ToLower()); } public Object LoadAsset_Internal(string name, Type type) { return Bundle.LoadAsset_Internal(path + name.ToLower(), type); } public bool TryLoadAsset<T>(in string name, out T asset) where T : Object { asset = LoadAsset<T>(name); return (Object)(object)asset != (Object)null; } public T[] LoadAssetWithSubAssets<T>(string name) where T : Object { return Bundle.LoadAssetWithSubAssets<T>(path + name.ToLower()); } public AssetBundleRequest LoadAssetWithSubAssetsAsync<T>(string name) where T : Object { return Bundle.LoadAssetWithSubAssetsAsync<T>(path + name.ToLower()); } public bool LoadAssetWithSubAssets<T>(in string name, out T[] assets) where T : Object { assets = LoadAssetWithSubAssets<T>(name); if (assets != null) { return assets.Length != 0; } return false; } public void Unload(bool unloadAllLoadedObjects) { Bundle.Unload(unloadAllLoadedObjects); } public void UnloadAsync(bool unloadAllLoadedObjects) { Bundle.UnloadAsync(unloadAllLoadedObjects); } public void MarkDirty() { ((Object)Bundle).MarkDirty(); } public void Dispose() { Bundle.Unload(false); } } internal class UnityAsset { public static FastBundle GetBundle(string folder, string name) { return new FastBundle(AssetBundle.LoadFromFile(folder + name)); } public static T LoadAsset<T>(string folder, string name, string assetPath) where T : Object { AssetBundle val = AssetBundle.LoadFromFile(folder + name); if ((Object)(object)val == (Object)null) { return default(T); } T result = val.LoadAsset<T>(assetPath.ToLower()); val.UnloadAsync(false); return result; } public static T FindAsset<T>(string name) where T : Object { T[] array = Resources.FindObjectsOfTypeAll<T>(); if (array == null || array.Length == 0) { return default(T); } T[] array2 = array; foreach (T val in array2) { if (((Object)val).name.Contains(name)) { return val; } } return array[0]; } private UnityAsset() { } } public class UnityObject { private readonly GameObject _gameObject; public static UnityObject Create(string name, GameObject parent = null) { UnityObject unityObject = new UnityObject(name); if ((Object)(object)parent != (Object)null) { unityObject.SetParent(parent); } return unityObject; } private UnityObject(string name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown _gameObject = new GameObject(name); } public UnityObject AddComponent<T>(bool dontAddIfExists = true) where T : Component { T component; return AddComponent<T>(out component, dontAddIfExists); } public UnityObject AddComponent<T>(out T component, bool dontAddIfExists = true) where T : Component { if (dontAddIfExists && _gameObject.TryGetComponent<T>(ref component)) { return this; } component = _gameObject.AddComponent<T>(); return this; } public UnityObject SetParent(GameObject parent, bool moveToParent = true) { _gameObject.transform.SetParent(parent.transform, !moveToParent); _gameObject.layer = parent.layer; return this; } public UnityObject SetParent(Transform parent, bool moveToParent = true) { _gameObject.transform.SetParent(parent, !moveToParent); return this; } public GameObject GetObject() { return _gameObject; } public static implicit operator GameObject(UnityObject obj) { return obj.GetObject(); } } } namespace Amrv.ConfigurableCompany.Utils.IO { public abstract class Bundle : IEnumerable { public abstract IEnumerable<string> Keys { get; } public abstract IEnumerable<string> Values { get; } public abstract int Count { get; } public string this[string key] { get { return Get(key, null); } set { Set(key, value); } } public abstract void Clear(); public abstract void Set(string key, string value); public abstract void Add(string key, string value); public abstract void Remove(string key); public abstract string Get(string key, string defaultValue); public abstract string Pack(); public abstract void Unpack(string data); public abstract bool Contains(string key); public abstract bool TryGet(string key, out string value); public abstract IEnumerator<KeyValuePair<string, string>> GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public class CCATFile { public const int SIZE_KEY_ESTIMATE = 60; public const int SIZE_VALUE_ESTIMATE = 6; public const char TOKEN_VALUE_SEPARATOR = ':'; public const char TOKEN_DATA_SKIP = '\\'; public const char TOKEN_NEXT_ENTRY = '\n'; public const string STRING_VALUE_SEPARATOR = ":"; public const string STRING_DATA_SKIP = "\\"; public const string STRING_NEXT_ENTRY = "\n"; private readonly Dictionary<string, bool> _states = new Dictionary<string, bool>(); public readonly string File; public CCATFile(string filepath) { File = filepath; base..ctor(); } private static string MakeDataSafe(in string data) { StringBuilder stringBuilder = new StringBuilder(data); stringBuilder.Replace("\\", "\\\\"); stringBuilder.Replace(":", "\\:"); stringBuilder.Replace("\n", "\\\n"); return stringBuilder.ToString(); } private static string RevertDataSafe(in string data) { StringBuilder stringBuilder = new StringBuilder(data); stringBuilder.Replace("\\:", ":"); stringBuilder.Replace("\\\n", "\n"); stringBuilder.Replace("\\\\", "\\"); return stringBuilder.ToString(); } public bool TryGetState(string name, out bool state) { return _states.TryGetValue(name, out state); } public void SetState(string name, bool state) { _states[name] = state; } public void RemoveState(string name) { _states.Remove(name); } public IReadOnlyDictionary<string, bool> States() { return _states; } public void Read() { if (!System.IO.File.Exists(File)) { return; } string text = System.IO.File.ReadAllText(File); _states.Clear(); int startIndex = 0; bool flag = false; for (int i = 0; i < text.Length; i++) { if (flag) { flag = false; continue; } switch (text[i]) { case '\\': flag = true; break; case '\n': ReadSingleEntry(text, startIndex, i); startIndex = i + 1; break; } } } private void ReadSingleEntry(string content, int startIndex, int endIndex) { bool flag = false; for (int i = startIndex; i < endIndex; i++) { if (flag) { flag = false; } else if (content[i] == '\\') { flag = true; } else if (content[i] == ':') { int num = startIndex; string data = content.Substring(num, i - num); num = i + 1; string text = content.Substring(num, endIndex - num); SetState(RevertDataSafe(in data), text.Equals("true")); break; } } } public void Write() { StringBuilder stringBuilder = new StringBuilder(60 + 6 * _states.Count); foreach (KeyValuePair<string, bool> state in _states) { string data = state.Key; stringBuilder.Append(MakeDataSafe(in data)).Append(':').Append(state.Value.ToString().ToLower()) .Append('\n'); } System.IO.File.WriteAllText(File, stringBuilder.ToString()); } } public class CCFGFile { public class CCFGEntry { public readonly Dictionary<string, string> Metadata = new Dictionary<string, string>(); public string Value; public string this[string meta] { get { return Metadata[meta]; } set { Metadata[meta] = value; } } } public const int META_CAPACITY_ESTIMATE = 15; public const int ENTRY_CAPACITY_ESTIMATE = 90; public const char TOKEN_ENTRY_START = '['; public const char TOKEN_ENTRY_END = ']'; public const char TOKEN_META_SEPARATOR = '|'; public const char TOKEN_VALUE_SEPARATOR = ':'; public const char TOKEN_DATA_SKIP = '\\'; public const string STRING_ENTRY_START = "["; public const string STRING_ENTRY_END = "]"; public const string STRING_META_SEPARATOR = "|"; public const string STRING_VALUE_SEPARATOR = ":"; public const string STRING_DATA_SKIP = "\\"; private readonly Dictionary<string, string> _meta = new Dictionary<string, string>(); private readonly Dictionary<string, CCFGEntry> _entries = new Dictionary<string, CCFGEntry>(); public readonly string File; public CCFGFile(string file) { File = file; base..ctor(); } private static string MakeDataSafe(in string data) { StringBuilder stringBuilder = new StringBuilder(data); stringBuilder.Replace("\\", "\\\\"); stringBuilder.Replace("[", "\\["); stringBuilder.Replace("]", "\\]"); stringBuilder.Replace("|", "\\|"); stringBuilder.Replace(":", "\\:"); return stringBuilder.ToString(); } private static string RevertDataSafe(in string data) { StringBuilder stringBuilder = new StringBuilder(data); stringBuilder.Replace("\\[", "["); stringBuilder.Replace("\\]", "]"); stringBuilder.Replace("\\|", "|"); stringBuilder.Replace("\\:", ":"); stringBuilder.Replace("\\\\", "\\"); return stringBuilder.ToString(); } public void AddMetadata(string name, string value) { _meta[name] = value; } public void RemoveMetadata(string name) { _meta.Remove(name); } public bool TryGetMetadata(string name, out string value) { return _meta.TryGetValue(name, out value); } public IReadOnlyDictionary<string, string> Metadata() { return _meta; } public void ClearMetadata() { _meta.Clear(); } public CCFGEntry AddEntry(string name, string value, Dictionary<string, string> meta = null) { if (TryGetEntry(name, out var entry)) { entry.Value = value; entry.Metadata.Clear(); if (meta != null) { foreach (KeyValuePair<string, string> metum in meta) { entry[metum.Key] = metum.Value; } } } else { entry = new CCFGEntry { Value = value }; _entries[name] = entry; if (meta != null) { foreach (KeyValuePair<string, string> metum2 in meta) { entry[metum2.Key] = metum2.Value; } } } return entry; } public void RemoveEntry(string name) { _entries.Remove(name); } public bool TryGetEntry(string name, out CCFGEntry entry) { return _entries.TryGetValue(name, out entry); } public IReadOnlyDictionary<string, CCFGEntry> Entries() { return _entries; } public void Read() { if (System.IO.File.Exists(File)) { string content = System.IO.File.ReadAllText(File); _meta.Clear(); _entries.Clear(); ReadEntries(content); } } public void Write() { int num = 15 * _meta.Count; int num2 = 90 * _entries.Count; StringBuilder stringBuilder = new StringBuilder(num + num2); stringBuilder.Append('['); foreach (KeyValuePair<string, string> metum in _meta) { stringBuilder.Append('|'); string data = metum.Key; StringBuilder stringBuilder2 = stringBuilder.Append(MakeDataSafe(in data)).Append(':'); string data2 = metum.Value; stringBuilder2.Append(MakeDataSafe(in data2)); } stringBuilder.Append(']'); stringBuilder.Append(Environment.NewLine); foreach (KeyValuePair<string, CCFGEntry> entry in _entries) { StringBuilder stringBuilder3 = stringBuilder.Append('['); string data = entry.Key; stringBuilder3.Append(MakeDataSafe(in data)).Append(':').Append(MakeDataSafe(in entry.Value.Value)); foreach (KeyValuePair<string, string> metadatum in entry.Value.Metadata) { stringBuilder.Append('|'); data = metadatum.Key; StringBuilder stringBuilder4 = stringBuilder.Append(MakeDataSafe(in data)).Append(':'); string data2 = metadatum.Value; stringBuilder4.Append(MakeDataSafe(in data2)); } stringBuilder.Append(']'); stringBuilder.Append(Environment.NewLine); } if (!Directory.Exists(Path.GetDirectoryName(File))) { Directory.CreateDirectory(Path.GetDirectoryName(File)); } System.IO.File.WriteAllText(File, stringBuilder.ToString()); } private void ReadEntries(string content) { bool flag = false; for (int i = 0; i < content.Length; i++) { if (flag) { flag = false; } else if (content[i] == '\\') { flag = true; } else if (content[i] == '[') { ReadSingleEntry(content, in i, out i); } } } private void ReadSingleEntry(string content, in int index, out int endIndex) { int num = index + 1; int num2 = -1; int num3 = -1; bool flag = false; bool flag2 = false; bool flag3 = false; string text = null; endIndex = index; for (int i = index; i < content.Length; i++) { if (flag3) { flag3 = false; continue; } switch (content[i]) { case '\\': flag3 = true; break; case '|': if (flag2) { int num4 = num; string data3 = content.Substring(num4, num2 - num4); num4 = num3; string data4 = content.Substring(num4, i - num4); if (flag) { CCFGEntry entry2; if (text == null) { AddMetadata(RevertDataSafe(in data3), RevertDataSafe(in data4)); } else if (TryGetEntry(text, out entry2)) { entry2.Metadata.Add(RevertDataSafe(in data3), RevertDataSafe(in data4)); } } else { text = RevertDataSafe(in data3); AddEntry(text, RevertDataSafe(in data4)); } } num = i + 1; flag = true; flag2 = false; break; case ':': flag2 = true; num2 = i; num3 = i + 1; break; case ']': { endIndex = i; if (!flag2) { return; } int num4 = num; string data = content.Substring(num4, num2 - num4); num4 = num3; string data2 = content.Substring(num4, i - num4); if (flag) { CCFGEntry entry; if (text == null) { AddMetadata(RevertDataSafe(in data), RevertDataSafe(in data2)); } else if (TryGetEntry(text, out entry)) { entry.Metadata.Add(RevertDataSafe(in data), RevertDataSafe(in data2)); } } else { text = RevertDataSafe(in data); AddEntry(text, RevertDataSafe(in data2)); } return; } } } } } public class ConfigBundle { public class ConfigEntry { public readonly Dictionary<string, string> Metadata = new Dictionary<string, string>(); public string Value; public string this[string meta] { get { return Metadata[meta]; } set { Metadata[meta] = value; } } } public const int META_CAPACITY_ESTIMATE = 15; public const int ENTRY_CAPACITY_ESTIMATE = 90; public const char TOKEN_ENTRY_START = '['; public const char TOKEN_ENTRY_END = ']'; public const char TOKEN_META_SEPARATOR = '|'; public const char TOKEN_VALUE_SEPARATOR = ':'; public const char TOKEN_DATA_SKIP = '\\'; public const string STRING_ENTRY_START = "["; public const string STRING_ENTRY_END = "]"; public const string STRING_META_SEPARATOR = "|"; public const string STRING_VALUE_SEPARATOR = ":"; public const string STRING_DATA_SKIP = "\\"; private readonly Dictionary<string, string> _meta = new Dictionary<string, string>(); private readonly Dictionary<string, ConfigEntry> _entries = new Dictionary<string, ConfigEntry>(); private static string MakeDataSafe(in string data) { StringBuilder stringBuilder = new StringBuilder(data); stringBuilder.Replace("\\", "\\\\"); stringBuilder.Replace("[", "\\["); stringBuilder.Replace("]", "\\]"); stringBuilder.Replace("|", "\\|"); stringBuilder.Replace(":", "\\:"); return stringBuilder.ToString(); } private static string RevertDataSafe(in string data) { StringBuilder stringBuilder = new StringBuilder(data); stringBuilder.Replace("\\[", "["); stringBuilder.Replace("\\]", "]"); stringBuilder.Replace("\\|", "|"); stringBuilder.Replace("\\:", ":"); stringBuilder.Replace("\\\\", "\\"); return stringBuilder.ToString(); } public void AddMetadata(string name, string value) { _meta[name] = value; } public void RemoveMetadata(string name) { _meta.Remove(name); } public bool TryGetMetadata(string name, out string value) { return _meta.TryGetValue(name, out value); } public IReadOnlyDictionary<string, string> Metadata() { return _meta; } public void ClearMetadata() { _meta.Clear(); } public ConfigEntry AddEntry(string name, string value, Dictionary<string, string> meta = null) { if (TryGetEntry(name, out var entry)) { entry.Value = value; entry.Metadata.Clear(); if (meta != null) { foreach (KeyValuePair<string, string> metum in meta) { entry[metum.Key] = metum.Value; } } } else { entry = new ConfigEntry { Value = value }; _entries[name] = entry; if (meta != null) { foreach (KeyValuePair<string, string> metum2 in meta) { entry[metum2.Key] = metum2.Value; } } } return entry; } public void RemoveEntry(string name) { _entries.Remove(name); } public bool TryGetEntry(string name, out ConfigEntry entry) { return _entries.TryGetValue(name, out entry); } public IReadOnlyDictionary<string, ConfigEntry> Entries() { return _entries; } public void Read(in string data) { _meta.Clear(); _entries.Clear(); ReadEntries(data); } public void Write(out string data) { int num = 15 * _meta.Count; int num2 = 90 * _entries.Count; StringBuilder stringBuilder = new StringBuilder(num + num2); stringBuilder.Append('['); foreach (KeyValuePair<string, string> metum in _meta) { stringBuilder.Append('|'); string data2 = metum.Key; StringBuilder stringBuilder2 = stringBuilder.Append(MakeDataSafe(in data2)).Append(':'); string data3 = metum.Value; stringBuilder2.Append(MakeDataSafe(in data3)); } stringBuilder.Append(']'); stringBuilder.Append(Environment.NewLine); foreach (KeyValuePair<string, ConfigEntry> entry in _entries) { StringBuilder stringBuilder3 = stringBuilder.Append('['); string data2 = entry.Key; stringBuilder3.Append(MakeDataSafe(in data2)).Append(':').Append(MakeDataSafe(in entry.Value.Value)); foreach (KeyValuePair<string, string> metadatum in entry.Value.Metadata) { stringBuilder.Append('|'); data2 = metadatum.Key; StringBuilder stringBuilder4 = stringBuilder.Append(MakeDataSafe(in data2)).Append(':'); string data3 = metadatum.Value; stringBuilder4.Append(MakeDataSafe(in data3)); } stringBuilder.Append(']'); } data = stringBuilder.ToString(); } private void ReadEntries(string content) { bool flag = false; for (int i = 0; i < content.Length; i++) { if (flag) { flag = false; } else if (content[i] == '\\') { flag = true; } else if (content[i] == '[') { ReadSingleEntry(content, in i, out i); } } } private void ReadSingleEntry(string content, in int index, out int endIndex) { int num = index + 1; int num2 = -1; int num3 = -1; bool flag = false; bool flag2 = false; bool flag3 = false; string text = null; endIndex = index; for (int i = index; i < content.Length; i++) { if (flag3) { flag3 = false; continue; } switch (content[i]) { case '\\': flag3 = true; break; case '|': if (flag2) { int num4 = num; string data3 = content.Substring(num4, num2 - num4); num4 = num3; string data4 = content.Substring(num4, i - num4); if (flag) { ConfigEntry entry2; if (text == null) { AddMetadata(RevertDataSafe(in data3), RevertDataSafe(in data4)); } else if (TryGetEntry(text, out entry2)) { entry2.Metadata.Add(RevertDataSafe(in data3), RevertDataSafe(in data4)); } } else { text = RevertDataSafe(in data3); AddEntry(text, RevertDataSafe(in data4)); } } num = i + 1; flag = true; flag2 = false; break; case ':': flag2 = true; num2 = i; num3 = i + 1; break; case ']': { endIndex = i; if (!flag2) { return; } int num4 = num; string data = content.Substring(num4, num2 - num4); num4 = num3; string data2 = content.Substring(num4, i - num4); if (flag) { ConfigEntry entry; if (text == null) { AddMetadata(RevertDataSafe(in data), RevertDataSafe(in data2)); } else if (TryGetEntry(text, out entry)) { entry.Metadata.Add(RevertDataSafe(in data), RevertDataSafe(in data2)); } } else { text = RevertDataSafe(in data); AddEntry(text, RevertDataSafe(in data2)); } return; } } } } } [Obsolete("")] public class DefaultBundle : Bundle { public const string TOKEN_FILE_START = "{"; public const string TOKEN_FILE_END = "}"; public const string TOKEN_ENTRY_START = "["; public const string TOKEN_ENTRY_END = "]"; public const string TOKEN_ENTRY_SEPARATOR = ":"; public const string TOKEN_ENTRY_VALUE_SEPARATOR = "="; private readonly Dictionary<string, string> _data = new Dictionary<string, string>(); public string TOKEN_SKIP => "\\"; public override IEnumerable<string> Keys => _data.Keys; public override IEnumerable<string> Values => _data.Values; public override int Count => _data.Count; public override void Set(string key, string value) { _data[key] = value; } public override void Add(string key, string value) { _data.Add(key, value); } public override void Clear() { _data.Clear(); } public override bool Contains(string key) { return _data.ContainsKey(key); } public override string Get(string key, string defaultValue) { return _data.GetValueOrDefault(key, defaultValue); } public override IEnumerator<KeyValuePair<string, string>> GetEnumerator() { return _data.GetEnumerator(); } public override void Remove(string key) { _data.Remove(key); } public override bool TryGet(string key, out string value) { return _data.TryGetValue(key, out value); } public override string Pack() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); foreach (KeyValuePair<string, string> datum in _data) { stringBuilder.Append("[").Append(datum.Key.Replace("=", TOKEN_SKIP + "=")).Append("=") .Append(datum.Value.Replace("]", TOKEN_SKIP + "]")) .Append("]") .Append(":"); } if (_data.Count > 0) { stringBuilder.Remove(stringBuilder.Length - ":".Length, ":".Length); } stringBuilder.AppendLine("}"); return stringBuilder.ToString(); } public override void Unpack(string data) { Step0_findBoundary(data, out var minIndex, out var maxIndex); if (minIndex == -1 || maxIndex == -1) { return; } if (maxIndex < minIndex) { throw new IOException($"Begining {minIndex} and EOD {maxIndex} file are not valid"); } string[] array = Step1_getAllEntries(data, minIndex, maxIndex); foreach (string text in array) { int num = FindNextToken(text, 0, "="); if (num != -1) { string key = text.Substring(0, num).Replace(TOKEN_SKIP + "=", "="); string text2 = text; int num2 = num + 1; Set(key, text2.Substring(num2, text2.Length - num2).Replace(TOKEN_SKIP + "]", "]")); } } } private string[] Step1_getAllEntries(string data, int minIndex, int maxIndex) { int index = minIndex; List<string> list = new List<string>(); int foundBeginIndex; int foundFinalIndex; while (Step11_getNextEntry(data, out foundBeginIndex, out foundFinalIndex, index, maxIndex)) { list.Add(data.Substring(foundBeginIndex + 1, foundFinalIndex - 1 - foundBeginIndex)); index = foundFinalIndex; } int num = 0; string[] array = new string[list.Count]; foreach (string item in list) { array[num] = item; num++; } return array; } private bool Step11_getNextEntry(string data, out int foundBeginIndex, out int foundFinalIndex, int index, int maxIndex) { foundBeginIndex = FindNextToken(data, index, "[", maxIndex); if (foundBeginIndex == -1) { foundFinalIndex = -1; return false; } foundFinalIndex = FindNextToken(data, foundBeginIndex, "]", maxIndex); return foundFinalIndex != -1; } private void Step0_findBoundary(string data, out int minIndex, out int maxIndex) { minIndex = data.IndexOf("{"); maxIndex = data.LastIndexOf("}"); } private int FindNextToken(string data, int startIndex, string token, int endIndex = -1) { int num = 0; if (endIndex < 0) { endIndex = data.Length; } for (int i = startIndex; i < endIndex; i++) { num = ((data[i] == token[num]) ? (num + 1) : 0); if (num == token.Length) { if (!IsTokenBefore(data, i - token.Length + 1, TOKEN_SKIP)) { return i - token.Length + 1; } num = 0; } } return -1; } private bool IsTokenBefore(string data, int index, string token) { int num = token.Length; int num2 = index; while (num2 > 0) { if (data[num2 - 1] == token[num - 1]) { num--; if (num == 0) { return true; } num2--; continue; } return false; } return false; } } public static class PathUtils { public static string FormPath(params string[] paths) { if (paths == null) { return null; } string text = string.Empty; for (int i = 0; i < paths.Length; i++) { text = Path.Combine(text, paths[i]); } return text; } public static string TryCreateFile(string path, string filename) { return TryCreateFile(Path.Combine(path, filename)); } public static string TryCreateFile(string path) { Directory.CreateDirectory(Path.GetDirectoryName(path)); File.Create(path); return path; } public static bool TryCreateFolder(string path) { try { Directory.CreateDirectory(Path.GetDirectoryName(path)); return true; } catch (Exception) { return false; } } } } namespace Amrv.ConfigurableCompany.Plugin { [BepInPlugin("dev.amrv.lethalCompany.config", "Configurable Company", "3.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal sealed class ConfigurableCompanyPlugin : BaseUnityPlugin { public const string PLUGIN_GUID = "dev.amrv.lethalCompany.config"; public const string PLUGIN_NAME = "Configurable Company"; public const string PLUGIN_VERSION = "3.4.0"; private static ConfigurableCompanyPlugin _plugin; private readonly Harmony Patcher = new Harmony("dev.amrv.lethalCompany.config"); public static string PluginFolder { get; private set; } public static string DataFolder { get; private set; } public ConfigurableCompanyPlugin() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown if ((Object)(object)_plugin != (Object)null) { throw new Exception("You can't create multiples instances of ConfigurableCompanyPlugin"); } _plugin = this; PluginFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) + Path.DirectorySeparatorChar; DataFolder = Path.Combine(Application.persistentDataPath, "Configurable Company", Directory.GetParent(Paths.BepInExRootPath).Name); Directory.CreateDirectory(DataFolder); Info("Initializating Configurable Company"); MenuPrefabs.Ping(); CTypes.Ping(); Events.Start(); NetEventRouter.RegisterListeners(); Patcher = new Harmony("dev.amrv.lethalCompany.config"); Patcher.PatchAll(typeof(ConfigurableCompanyPlugin).Assembly); DependencyManager.CheckDependencies(Patcher); Application.quitting += OnQuit; Info("Completed Configurable Company Initialization"); LifecycleEventRouter.PluginStart(); } private static void OnQuit() { IOController.SaveCategories(); IOController.SaveConfigs(); } internal static void Error(object data) { ((BaseUnityPlugin)_plugin).Logger.LogError(data); } internal static void Info(object data) { ((BaseUnityPlugin)_plugin).Logger.LogInfo(data); } [Obsolete("Only use for debugging purposes")] internal static void Debug(object data) { } } } namespace Amrv.ConfigurableCompany.Core { public class BuildingException : Exception { public BuildingException() { } public BuildingException(string message) : base(message) { } public BuildingException(string message, Exception innerException) : base(message, innerException) { } protected BuildingException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public class IDStorage<T> : IReadOnlyDictionary<string, T>, IEnumerable<KeyValuePair<string, T>>, IEnumerable, IReadOnlyCollection<KeyValuePair<string, T>>, IEnumerable<string> { private readonly Dictionary<string, T> _storage; public T this[string key] => _storage[key]; public IEnumerable<string> Keys => _storage.Keys; public IEnumerable<T> Values => _storage.Values; public int Count => _storage.Count; internal IDStorage(Dictionary<string, T> dictionary = null) { _storage = dictionary ?? new Dictionary<string, T>(); } public bool ContainsKey(string key) { return _storage.ContainsKey(key); } public IEnumerator<KeyValuePair<string, T>> GetEnumerator() { return _storage.GetEnumerator(); } public bool TryGetValue(string key, out T value) { return _storage.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { return _storage.GetEnumerator(); } IEnumerator<string> IEnumerable<string>.GetEnumerator() { return _storage.Keys.GetEnumerator(); } } public abstract class InstanceBuilder<T> : IDisposable { private T instance; public virtual bool TryBuild(out T item) { try { item = Build(); return true; } catch (Exception) { item = default(T); return false; } } public virtual T GetOrCreate() { if (TryGetExisting(out var item)) { return item; } return Build(); } public T Build() { try { T val = instance; return (val != null) ? val : (instance = BuildInstance()); } catch (Exception arg) { ConfigurableCompanyPlugin.Error($"Error creating entry{Environment.NewLine}{arg}"); return default(T); } } protected abstract T BuildInstance(); protected abstract bool TryGetExisting(out T item); public virtual void Dispose() { Build(); } public static implicit operator T(InstanceBuilder<T> builder) { return builder.Build(); } } internal static class LifecycleEventRouter { public static void PluginStart() { CEvents.LifecycleEvents.PluginStart.Invoke(); } public static void CreateMenu() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) ConfigurableCompanyPlugin.Debug("Creating menu"); IOController.LoadCategories(); IOController.LoadConfigs(); IOController.GetConfigCache(); Canvas[] array = Object.FindObjectsOfType<Canvas>(); foreach (Canvas val in array) { if ((Object)(object)((Component)val).gameObject.transform.parent == (Object)null) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).name == "MainMenu") { MenuController.Create(((Component)val).gameObject); break; } } } MenuController.SetLocked(GameNetworkManager.Instance?.currentSaveFileName == "LCChallengeFile"); } public static void DestroyMenu() { IOController.SaveCategories(); IOController.SaveConfigs(); MenuController.Destroy(); } } public sealed class ReadonlyDictionary<K, V> : IReadOnlyDictionary<K, V>, IEnumerable<KeyValuePair<K, V>>, IEnumerable, IReadOnlyCollection<KeyValuePair<K, V>> { [CompilerGenerated] private Dictionary<K, V> <wrapper>P; public V this[K key] => <wrapper>P.GetValueOrDefault(key, default(V)); public IEnumerable<K> Keys => <wrapper>P.Keys; public IEnumerable<V> Values => <wrapper>P.Values; public int Count => <wrapper>P.Count; public ReadonlyDictionary(Dictionary<K, V> wrapper) { <wrapper>P = wrapper; base..ctor(); } public bool ContainsKey(K key) { return <wrapper>P.ContainsKey(key); } public IEnumerator<KeyValuePair<K, V>> GetEnumerator() { return <wrapper>P.GetEnumerator(); } public bool TryGetValue(K key, out V value) { return <wrapper>P.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { return <wrapper>P.GetEnumerator(); } } } namespace Amrv.ConfigurableCompany.Core.Patch { [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { [HarmonyPatch("SaveGame")] [HarmonyPostfix] private static void SaveGameValues_Postfix() { if (NetSynchronizer.IsServer) { IOController.SetConfigCache(); IOController.SaveConfigs(); } } } [HarmonyPatch(typeof(MenuManager))] internal class MenuManagerPatch { [CompilerGenerated] private static class <>O { public static UnityAction <0>__ClickBackButton_Event; } [HarmonyPatch("Start")] [HarmonyPostfix] private static void Start_Postfix(MenuManager __instance) { //IL_0041: 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_004c: Expected O, but got Unknown ConfigurableCompanyPlugin.Debug("MenuManager::Start [Postfix]"); if (!__instance.isInitScene) { LifecycleEventRouter.CreateMenu(); ButtonClickedEvent onClick = __instance.HostSettingsScreen.FindChild("HostSettingsContainer/Back").GetComponent<Button>().onClick; object obj = <>O.<0>__ClickBackButton_Event; if (obj == null) { UnityAction val = ClickBackButton_Event; <>O.<0>__ClickBackButton_Event = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } } private static void ClickBackButton_Event() { MenuController.SetVisible(visible: false); } [HarmonyPatch("ClickHostButton")] [HarmonyPostfix] private static void ClickHostButton_Postfix() { MenuController.SetVisible(visible: true); } [HarmonyPatch("ConfirmHostButton")] [HarmonyPostfix] private static void ConfirmHostButton_Postfix() { LifecycleEventRouter.DestroyMenu(); } } [HarmonyPatch(typeof(NetworkManager))] internal class NetworkManagerPatch { [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void UpdateSingleton(NetworkManager value) { ConfigurableCompanyPlugin.Debug($"Detected NetworkManager singleton modification ({(Object)(object)value == (Object)null}) {value}"); if ((Object)(object)value == (Object)null) { NetSynchronizer.Destroy(); } else { NetSynchronizer.Create(value); } } } [HarmonyPatch(typeof(SaveFileUISlot))] internal class SaveFileUISlotPatch { public static bool Patch_SetFileToThis_Postfix = true; [HarmonyPatch("SetFileToThis")] [HarmonyPostfix] private static void SetFileToThis_Postfix(SaveFileUISlot __instance) { if (Patch_SetFileToThis_Postfix) { ConfigurableCompanyPlugin.Debug($"SaveFileUISlot::SetFileToThis [Postfix] | fileNum: {__instance.fileNum} |"); MenuController.SetLocked(__instance.fileNum == -1); IOController.LoadConfigs(); IOController.GetConfigCache(); MenuController.SetCurrentFileName(GameNetworkManager.Instance.currentSaveFileName); } } } } namespace Amrv.ConfigurableCompany.Core.Net { internal static class NetController { public const string VERSION = "2n"; public const string CONFIGS_SYNC = "configurable-company_client_configs-sync"; public static void SendAllConfigs(ulong client) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) ConfigBundle configBundle = new ConfigBundle(); configBundle.AddMetadata("VERSION", "2n"); foreach (CConfig value2 in CConfig.Storage.Values) { if (value2.Synchronized) { WriteConfigBundle(value2, configBundle); } } configBundle.Write(out var data); ConfigurableCompanyPlugin.Debug($"Send configuration bundle with size {FastBufferWriter.GetWriteSize(data, false)}"); FastBufferWriter value = default(FastBufferWriter); ((FastBufferWriter)(ref value))..ctor(FastBufferWriter.GetWriteSize(data, false), (Allocator)2, -1); ((FastBufferWriter)(ref value)).WriteValueSafe(data, false); NetSynchronizer.Messaging.Send("configurable-company_client_configs-sync", value, (NetworkDelivery)4, client); } public static void SendConfig(params CConfig[] configs) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) ConfigBundle configBundle = new ConfigBundle(); configBundle.AddMetadata("VERSION", "2n"); foreach (CConfig cConfig in configs) { if (cConfig.Synchronized) { WriteConfigBundle(cConfig, configBundle); } } configBundle.Write(out var data); ConfigurableCompanyPlugin.Debug($"Send configuration bundle with size {FastBufferWriter.GetWriteSize(data, false)}"); FastBufferWriter value = default(FastBufferWriter); ((FastBufferWriter)(ref value))..ctor(FastBufferWriter.GetWriteSize(data, false), (Allocator)2, -1); ((FastBufferWriter)(ref value)).WriteValueSafe(data, false); NetSynchronizer.Messaging.Send("configurable-company_client_configs-sync", value); } private static void WriteConfigBundle(CConfig config, ConfigBundle bundle) { if (config.SerializeValue(out var data)) { bundle.AddEntry(config.ID, data, new Dictionary<string, string> { ["enabled"] = config.Enabled.ToString() }); } } } internal static class NetEventRouter { public static void RegisterListeners() { NetSynchronizer.ServerCallbacks.Start += Server_Start; NetSynchronizer.ServerCallbacks.Stop += Server_Stop; NetSynchronizer.ServerCallbacks.ClientConnect += Server_ClientConnect; NetSynchronizer.ServerCallbacks.ClientDisconnect += Server_ClientDisconnect; NetSynchronizer.ClientCallbacks.Connect += Client_Connect; NetSynchronizer.ClientCallbacks.Disconnect += Client_Disconnect; } public static void Server_Start() { ConfigurableCompanyPlugin.Debug("NetEventRouter > Server :: Start"); NetReceiveRouter.RegisterServerMessages(); } public static void Server_ClientConnect(ulong client) { ConfigurableCompanyPlugin.Debug($"NetEventRouter > Server :: ClientConnect | id: {client} |"); if (NetSynchronizer.IsServer) { NetController.SendAllConfigs(client); } } public static void Server_ClientDisconnect(ulong obj) { ConfigurableCompanyPlugin.Debug($"NetEventRouter > Server :: ClientDisconnect | id: {obj} |"); } public static void Server_Stop(bool obj) { ConfigurableCompanyPlugin.Debug($"NetEventRouter > Server :: Stop | ???: {obj} |"); } public static void Client_Disconnect(bool obj) { ConfigurableCompanyPlugin.Debug($"NetEventRouter > Client :: Disconnect | ???: {obj} |"); } public static void Client_Connect() { ConfigurableCompanyPlugin.Debug("NetEventRouter > Client :: Connect"); NetReceiveRouter.RegisterClientMessages(); } } internal class NetReceiveRouter { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__Client_ReceiveConfigs; } public const string CONFIGS_SYNC = "configurable-company_client_configs-sync"; public static void RegisterClientMessages() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown ConfigurableCompanyPlugin.Debug("NetReceiveRouter::RegisterClientMessages"); object obj = <>O.<0>__Client_ReceiveConfigs; if (obj == null) { HandleNamedMessageDelegate val = Client_ReceiveConfigs; <>O.<0>__Client_ReceiveConfigs = val; obj = (object)val; } NetSynchronizer.Messaging.Register("configurable-company_client_configs-sync", (HandleNamedMessageDelegate)obj); } public static void RegisterServerMessages() { ConfigurableCompanyPlugin.Debug("NetReceiveRouter::RegisterServerMessages"); } internal static void Client_ReceiveConfigs(ulong senderClientId, FastBufferReader messagePayload) { ConfigurableCompanyPlugin.Debug($"NetReceiveRouter::Client_ReceiveConfigs {((FastBufferReader)(ref messagePayload)).Length}"); if (NetSynchronizer.IsServer) { return; } ConfigBundle configBundle = new ConfigBundle(); string data = default(string); ((FastBufferReader)(ref messagePayload)).ReadValueSafe(ref data, false); configBundle.Read(in data); if (!configBundle.TryGetMetadata("VERSION", out var value) || !value.Equals("2n")) { ConfigurableCompanyPlugin.Error("Can't sync configurations, version mismatch " + value + " | 2n"); return; } foreach (KeyValuePair<string, ConfigBundle.ConfigEntry> item in configBundle.Entries()) { if (CConfig.Storage.TryGetValue(item.Key, out var value2) && value2.Synchronized) { ReadConfigBundle(value2, item.Value); } } } private static void ReadConfigBundle(CConfig config, ConfigBundle.ConfigEntry entry) { config.DeserializeValue(in entry.Value, Amrv.ConfigurableCompany.API.ChangeReason.SYNCHRONIZATION); if (entry.Metadata.TryGetValue("enabled", out var value)) { config.Enabled = value.ToLower().Equals("true"); } } } public static class NetSynchronizer { public static class StateCallbacks { public static event Action<NetworkManager> Start; public static event Action Stop; internal static void TriggerStart(NetworkManager instance) { StateCallbacks.Start?.Invoke(instance); } internal static void TriggerStop() { StateCallbacks.Stop?.Invoke(); } } public static class ServerCallbacks { public static event Action<ulong> ClientConnect; public static event Action<ulong> ClientDisconnect; public static event Action Start; public static event Action<bool> Stop; internal static void TriggerClientConnect(ulong client) { ServerCallbacks.ClientConnect?.Invoke(client); } internal static void TriggerClientDisconnect(ulong client) { ServerCallbacks.ClientDisconnect?.Invoke(client); } internal static void TriggerStart() { ServerCallbacks.Start?.Invoke(); } internal static void TriggerStop(bool forced) { ServerCallbacks.Stop?.Invoke(forced); } } public static class ClientCallbacks { public static event Action Connect; public static event Action<bool> Disconnect; internal static void TriggerConnect() { ClientCallbacks.Connect?.Invoke(); } internal static void TriggerDisconnect(bool forced) { ClientCallbacks.Disconnect?.Invoke(forced); } } public static class Messaging { public static void Send(string identifier, FastBufferWriter? writer = null, params ulong[] clients) { Send(identifier, writer, (NetworkDelivery)3, clients); } public static void Send(string identifier, FastBufferWriter? writer = null, NetworkDelivery delivery = 3, params ulong[] clients) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { FastBufferWriter valueOrDefault = writer.GetValueOrDefault(); if (clients == null || clients.Length == 0) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll(identifier, valueOrDefault, delivery); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(identifier, (IReadOnlyList<ulong>)clients, valueOrDefault, delivery); } } } public static bool Register(string identifier, HandleNamedMessageDelegate handler) { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler(identifier, handler); return true; } public static bool Unregister(string identifier) { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; if (customMessagingManager != null) { customMessagingManager.UnregisterNamedMessageHandler(identifier); } return true; } public static FastBufferWriter GetWriter(int size = 0) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return new FastBufferWriter(size, (Allocator)2, -1); } public static int GetSize(string text, bool oneByteChars = false) { return FastBufferWriter.GetWriteSize(text, oneByteChars); } public static int GetSize<T>(T item) where T : unmanaged { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) return FastBufferWriter.GetWriteSize<T>(ref item, default(ForStructs)); } public static int GetSize<T>(params T[] items) where T : unmanaged { return FastBufferWriter.GetWriteSize<T>(items, -1, 0); } } public static bool IsServer { get { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null) { return false; } return singleton.IsServer; } } public static bool IsClient { get { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null) { return false; } return singleton.IsClient; } } public static bool IsHost { get { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null) { return false; } return singleton.IsHost; } } internal static void Create(NetworkManager instance) { NetworkManager.Singleton.OnClientStarted += ClientCallbacks.TriggerConnect; NetworkManager.Singleton.OnClientStopped += ClientCallbacks.TriggerDisconnect; NetworkManager.Singleton.OnClientConnectedCallback += ServerCallbacks.TriggerClientConnect; NetworkManager.Singleton.OnClientDisconnectCallback += ServerCallbacks.TriggerClientDisconnect; NetworkManager.Singleton.OnServerStarted += ServerCallbacks.TriggerStart; NetworkManager.Singleton.OnServerStopped += ServerCallbacks.TriggerStop; StateCallbacks.TriggerStart(instance); } internal static void Destroy() { StateCallbacks.TriggerStop(); } } } namespace Amrv.ConfigurableCompany.Core.IO { public sealed class ConfigFile { public const string METADATA_VERSION = "VERSION"; public const string FLAG_ENABLED = "enabled"; private readonly CCFGFile _ccfg; public string File => _ccfg.File; public string Version => _ccfg.Metadata().GetValueOrDefault("VERSION", null); public ConfigFile(string path, string file, int version, char type) { _ccfg = new CCFGFile(Path.Combine(path, file)); _ccfg.AddMetadata("VERSION", $"{version}{type}"); } public bool IsValidVersion(int version, char type) { if (_ccfg.TryGetMetadata("VERSION", out var value)) { string text = value; if (int.TryParse(text.Substring(0, text.Length - 1), out var result)) { return version >= result; } return false; } return false; } public bool WriteConfigValue(CConfig config) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (config.SerializeValue(out var data)) { if (config.Toggleable) { dictionary["enabled"] = $"{config.Enabled}"; } _ccfg.AddEntry(config.ID, data, dictionary); return true; } return false; } public bool ReadConfigValue(CConfig config) { if (_ccfg.TryGetEntry(config.ID, out var entry)) { config.DeserializeValue(in entry.Value, Amrv.ConfigurableCompany.API.ChangeReason.READ_FROM_FILE); if (config.Toggleable && entry.Metadata.TryGetValue("enabled", out var value)) { config.Enabled = value.ToLower().Equals("true"); } return true; } return false; } public void Load() { _ccfg.Read(); } public void Save() { _ccfg.Write(); } } internal static class IOCategories { private static readonly CCATFile File = new CCATFile(Path.Combine(ConfigurableCompanyPlugin.DataFolder, "categories.ccat")); public static void Load() { File.Read(); } public static void Save() { File.Write(); } public static bool GetOpenState(CCategory category) { if (File.TryGetState(category.ID, out var state)) { return state; } return false; } public static void SetOpenState(CCategory category, bool open) { File.SetState(category.ID, open); } } internal static class IOConfigurations { private const string FALLBACK_FILE = "LCUnknownFile"; private static readonly Dictionary<string, CCFGFile> _files = new Dictionary<string, CCFGFile>(); public static string FileName => GameNetworkManager.Instance?.currentSaveFileName ?? "LCUnknownFile"; public static string FullPath => Path.Combine(ConfigurableCompanyPlugin.DataFolder, GameNetworkManager.Instance?.currentSaveFileName ?? "LCUnknownFile"); public static string GetFullPath(string file) { return Path.Combine(ConfigurableCompanyPlugin.DataFolder, file + ".ccfg"); } public static void Load(string file) { if (!_files.TryGetValue(file, out var value)) { value = new CCFGFile(GetFullPath(file)); _files.Add(file, value); } value.Read(); } public static void Save(string file) { if (_files.TryGetValue(file, out var value)) { value.Write(); } } public static void GetOrCreate(string file, out CCFGFile cfg) { if (!_files.TryGetValue(file, out cfg)) { cfg = new CCFGFile(GetFullPath(file)); _files.Add(file, cfg); } } public static bool TryGetFile(string file, out CCFGFile cfg) { return _files.TryGetValue(file, out cfg); } internal static void Delete(string file) { if (_files.TryGetValue(file, out var _)) { File.Delete(file); _files.Remove(file); } } } public static class IOController { public const string VERSION = "2"; public static void SaveCategories() { IOCategories.Save(); } public static void LoadCategories() { IOCategories.Load(); } public static bool GetCategoryOpenState(CCategory category) { return IOCategories.GetOpenState(category); } public static void SetCategoryOpenState(CCategory category, bool open) { IOCategories.SetOpenState(category, open); } public static void SaveConfigs() { IOConfigurations.Save(IOConfigurations.FileName); } public static void LoadConfigs() { IOConfigurations.Load(IOConfigurations.FileName); } public static void RemoveConfigs() { IOConfigurations.Delete(IOConfigurations.FileName); } public static void SetConfigCache(CConfig config) { IOConfigurations.GetOrCreate(IOConfigurations.FileName, out var cfg); cfg.AddMetadata("VERSION", "2"); WriteConfigEntryCache(config, cfg); } public static bool GetConfigCache(CConfig config) { if (IOConfigurations.TryGetFile(IOConfigurations.FileName, out var cfg) && cfg.TryGetEntry(config.ID, out var entry)) { ReadConfigEntryCache(config, entry); } return false; } public static void SetConfigCache() { IOConfigurations.GetOrCreate(IOConfigurations.FileName, out var cfg); cfg.AddMetadata("VERSION", "2"); foreach (CConfig value in CConfig.Storage.Values) { WriteConfigEntryCache(value, cfg); } } public static void GetConfigCache() { if (IOConfigurations.TryGetFile(IOConfigurations.FileName, out var cfg)) { foreach (CConfig value in CConfig.Storage.Values) { if (cfg.TryGetEntry(value.ID, out var entry)) { ReadConfigEntryCache(value, entry); } else { value.Reset(Amrv.ConfigurableCompany.API.ChangeReason.READ_FROM_FILE); } } return; } foreach (CConfig value2 in CConfig.Storage.Values) { value2.Reset(Amrv.ConfigurableCompany.API.ChangeReason.READ_FROM_FILE); } } private static void ReadConfigEntryCache(CConfig config, CCFGFile.CCFGEntry entry) { config.DeserializeValue(in entry.Value, Amrv.ConfigurableCompany.API.ChangeReason.READ_FROM_FILE); if (entry.Metadata.TryGetValue("enabled", out var value)) { config.Enabled = value.ToLower().Equals("true"); } } private static void WriteConfigEntryCache(CConfig config, CCFGFile file) { if (config.SerializeValue(out var data)) { file.AddEntry(config.ID, data, new Dictionary<string, string> { ["enabled"] = config.Enabled.ToString() }); } } } } namespace Amrv.ConfigurableCompany.Core.Extensions { public static class DictionaryExtensions { public static ReadonlyDictionary<K, V> AsReadOnly<K, V>(this Dictionary<K, V> dictionary) { return new ReadonlyDictionary<K, V>(dictionary); } } public static class GameObjectExtensions { public static GameObject FindChild(this GameObject gameObject, string child) { Transform obj = gameObject.transform.Find(child); return ((obj != null) ? ((Component)obj).gameObject : null) ?? null; } public static void AddComponent<T>(this GameObject gameObject, out T addedComponent) where T : Component { addedComponent = gameObject.AddComponent<T>(); } } public static class RandomExtensions { public static ulong NextULong(this Random rng) { byte[] array = new byte[8]; rng.NextBytes(array); return BitConverter.ToUInt64(array, 0); } public static ulong NextULong(this Random rng, ulong max, bool inclusiveUpperBound = false) { return rng.NextULong(0uL, max, inclusiveUpperBound); } public static ulong NextULong(this Random rng, ulong min, ulong max, bool inclusiveUpperBound = false) { ulong num = max - min; if (inclusiveUpperBound) { if (num == ulong.MaxValue) { return rng.NextULong(); } num++; } if (num == 0) { throw new ArgumentOutOfRangeException("Max must be greater than min when inclusiveUpperBound is false, and greater than or equal to when true", "max"); } ulong num2 = ulong.MaxValue - ulong.MaxValue % num; ulong num3; do { num3 = rng.NextULong(); } while (num3 > num2); return num3 % num + min; } public static long NextLong(this Random rng) { byte[] array = new byte[8]; rng.NextBytes(array); return BitConverter.ToInt64(array, 0); } public static long NextLong(this Random rng, long max, bool inclusiveUpperBound = false) { return rng.NextLong(long.MinValue, max, inclusiveUpperBound); } public static long NextLong(this Random rng, long min, long max, bool inclusiveUpperBound = false) { ulong num = (ulong)(max - min); if (inclusiveUpperBound) { if (num == ulong.MaxValue) { return rng.NextLong(); } num++; } if (num == 0) { throw new ArgumentOutOfRangeException("Max must be greater than min when inclusiveUpperBound is false, and greater than or equal to when true", "max"); } ulong num2 = ulong.MaxValue - ulong.MaxValue % num; ulong num3; do { num3 = rng.NextULong(); } while (num3 > num2); return (long)(num3 % num) + min; } public static double NextDouble(this Random random, double minValue, double maxValue) { return random.NextDouble() * (maxValue - minValue) + minValue; } public static bool NextBool(this Random random) { return random.Next() % 2 == 0; } public static long Gaussian(this Random random, long expected, double deviation) { double d = 1.0 - random.NextDouble(); double num = 1.0 - random.NextDouble(); return (long)(Math.Sqrt(-2.0 * Math.Log(d)) * Math.Cos(Math.PI * 2.0 * num) * deviation + (double)expected); } public static double Gaussian(this Random random, double expected, double deviation) { double d = 1.0 - random.NextDouble(); double num = 1.0 - random.NextDouble(); return Math.Sqrt(-2.0 * Math.Log(d)) * Math.Cos(Math.PI * 2.0 * num) * deviation + expected; } } } namespace Amrv.ConfigurableCompany.Core.Display { internal class MenuBind { protected readonly GameObject Container; public readonly GameObject Overlay; public readonly GameObject ShowMenu; public readonly GameObject Menu; protected readonly GameObject FileName; protected readonly TextMeshProUGUI FileText; protected readonly TextMeshProUGUI BetaText; public readonly MenuToggle Toggler; public readonly MenuPages Pages; public readonly MenuButtons Buttons; public readonly MenuTooltip Tooltip; public readonly MenuCategories Categories; public readonly MenuSections Sections; public readonly MenuConfigs Configs; public readonly MenuPresets Presets; private static MenuBind _instance; public string Filename { get { return ((TMP_Text)FileText).text; } set { FileName.SetActive(!string.IsNullOrEmpty(value)); ((TMP_Text)FileText).SetText(value, true); } } public static MenuBind Create(Transform parent) { if (_instance != null) { throw new BuildingException("Can't create MenuBind while there is an existing one"); } _instance = new MenuBind(parent); _instance.Toggler.Open = false; _instance.Toggler.Visible = false; _instance.Filename = GameNetworkManager.Instance.currentSaveFileName; return _instance; } private MenuBind(Transform parent) { //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown MenuEventRouter.OnAction_PrepareMenu(); Container = Object.Instantiate<GameObject>(MenuPrefabs.Menu); ((Object)Container).name = "Configuration menu"; Container.transform.SetParent(parent, false); Container.AddComponent<LifecycleListener>().DestroyEvent += Event_OnDestroy; Overlay = ((Component)Container.transform.Find("Overlay")).gameObject; ShowMenu = ((Component)Container.transform.Find("Show menu")).gameObject; Menu = ((Component)Container.transform.Find("Menu")).gameObject; FileName = Menu.FindChild("Info/File name"); FileText = FileName.FindChild("Area/Text").GetComponent<TextMeshProUGUI>(); Menu.FindChild("Beta").AddComponent<RegionButton>().OnMouseClick += OnIssuesButtonClick; ((UnityEvent)Menu.FindChild("Help").GetComponent<Button>().onClick).AddListener(new UnityAction(OnHelpButtonClick)); BetaText = Menu.FindChild("Beta").GetComponent<TextMeshProUGUI>(); Toggler = new MenuToggle(this, Container); Pages = new MenuPages(this); Buttons = new MenuButtons(this); Tooltip = new MenuTooltip(this); Categories = new MenuCategories(this); Sections = new MenuSections(this); Configs = new MenuConfigs(this); Presets = new MenuPresets(this); Pages.UpdateContent(); Pages.UpdateSelf(); Categories.UpdateContent(); Categories.UpdateSelf(); Sections.UpdateContent(); Sections.UpdateSelf(); Configs.UpdateContent(); Configs.UpdateSelf(); Presets.UpdateContent(); Presets.UpdateSelf(); MenuEventRouter.OnAction_CreateMenu(); } private void OnHelpButtonClick() { Application.OpenURL("https://github.com/TheAnsuz/Lethal-Company-Configurable-Company-API/wiki/user_usage"); } private void OnIssuesButtonClick(object sender, PointerEventData e) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (TMP_TextUtilities.FindIntersectingLink((TMP_Text)(object)BetaText, e.pointerPressRaycast.worldPosition, (Camera)null) != -1) { Application.OpenURL("https://github.com/TheAnsuz/Lethal-Company-Configurable-Company-API/issues/new/choose"); } } private void Event_OnDestroy() { Pages.Destroy(); Tooltip.Destroy(); _instance = null; MenuEventRouter.OnAction_DestroyMenu(); } internal void Destroy() { Object.Destroy((Object)(object)Container); } } internal static class MenuController { private static MenuBind Instance; public static void Create(GameObject parent) { Instance = MenuBind.Create(parent.transform); SetVisible(visible: false); Instance.Toggler.Open = false; } public static void SetLocked(bool locked) { if (Instance != null) { Instance.Toggler.Locked = locked; } } public static void SetVisible(bool visible) { if (Instance != null) { Instance.Toggler.Visible = visible; } } public static void SetCurrentFileName(string filename) { if (Instance != null) { Instance.Filename = filename; } } public static void SetCurrentPage(CPage page) { if (Instance != null) { Instance.Pages.CurrentPage = page; } } public static void AddPage(CPage page) { if (Instance != null) { Instance.Pages.AddPage(page); } } public static void AddCategory(CCategory category) { if (Instance != null) { Instance.Categories.AddCategory(category); } } public static void AddSection(CSection section) { if (Instance != null) { Instance.Sections.AddSection(section); } } public static void AddConfig(CConfig config) { if (Instance != null) { Instance.Configs.AddConfig(config); } } public static void RefreshConfig(CConfig config) { if (Instance != null) { Instance.Configs.Refresh(config); } } public static void SaveConfigs() { if (Instance != null) { Instance.Configs.SaveToConfig(); } } public static void LoadConfigs() { if (Instance != null) { Instance.Configs.LoadFromConfig(); } } public static void UpdateConfig(CConfig config, Amrv.ConfigurableCompany.API.ChangeReason reason) { if (Instance != null) { if (reason == Amrv.ConfigurableCompany.API.ChangeReason.USER_RESET || reason == Amrv.ConfigurableCompany.API.ChangeReason.SCRIPT_RESET) { Instance.Configs.ReceiveReset(config); } else { Instance.Configs.Refresh(config); } } } public static void TriggerToggleConfig(CConfig config, bool enabled) { if (Instance != null) { Instance.Configs.ReceiveToggle(config, enabled); } } public static void Destroy() { if (Instance != null) { Instance.Destroy(); Instance = null; } } public static void RefreshPresets() { if (Instance != null) { Instance.Presets.UpdateContent(); } } } internal static class MenuEventRouter { public static void OnClick_Save() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Save"); MenuController.SaveConfigs(); IOController.SetConfigCache(); IOController.SaveConfigs(); CEvents.MenuEvents.Save.Invoke(); } public static void OnClick_Reset() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Reset"); foreach (CConfig value in CConfig.Storage.Values) { value.Reset(Amrv.ConfigurableCompany.API.ChangeReason.USER_RESET); } IOController.SetConfigCache(); IOController.SaveConfigs(); CEvents.MenuEvents.Reset.Invoke(); } public static void OnClick_Restore() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Restore"); MenuController.LoadConfigs(); CEvents.MenuEvents.Restore.Invoke(); } public static void OnClick_Copy() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Copy"); Clipboard.CopyToClipboard(); CEvents.MenuEvents.Copy.Invoke(); } public static void OnClick_Paste() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Paste"); Clipboard.PasteFromClipboard(); CEvents.MenuEvents.Paste.Invoke(); } public static void OnClick_Randomize(int seed, Random random) { ConfigurableCompanyPlugin.Debug($"MenuEventRouter > OnClick | Randomize ({seed})"); foreach (CConfig value in CConfig.Storage.Values) { value.Randomize(random, Amrv.ConfigurableCompany.API.ChangeReason.USER_RANDOMIZED); } CEvents.MenuEvents.Randomize.Invoke(new CEventRandomize(seed, random)); } public static void OnClick_ShowPage(CPage page) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | ShowPage (" + page.Name + ")"); MenuController.SetCurrentPage(page); CEvents.MenuEvents.ChangePage.Invoke(new CEventChangePage(page)); } public static void OnAction_PrepareMenu() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Prepare"); CEvents.MenuEvents.Prepare.Invoke(); } public static void OnAction_CreateMenu() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Create"); CEvents.MenuEvents.Create.Invoke(); } public static void OnAction_DestroyMenu() { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Destroy"); MenuController.Destroy(); CEvents.MenuEvents.Destroy.Invoke(); } public static void OnClick_ToggleMenu(bool open) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Toggle (" + (open ? "Open" : "Close") + ")"); CEvents.MenuEvents.Toggle.Invoke(new CEventMenuToggle(open)); } public static void OnClick_PresetCreate(string name) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Preset create | name: " + name); Presets.Create(name); } public static void OnClick_PresetLoad(string name) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Preset load | name: " + name); Presets.Stablish(name); } public static void OnClick_PresetSave(string name) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Preset save | name: " + name); Presets.Update(name); } public static void OnClick_PresetDelete(string name) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Preset remove | name: " + name); Presets.Delete(name); } public static void OnAction_VisibleMenu(bool visible) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Visible (" + (visible ? "Visible" : "Hidden") + ")"); CEvents.MenuEvents.Visible.Invoke(new CEventMenuVisible(visible)); } public static void OnAction_ToggleCategory(CCategory category, bool active) { ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Toggle Category (" + category.ID + ", " + (active ? "Visible" : "Hidden") + ")"); IOController.SetCategoryOpenState(category, active); } } } namespace Amrv.ConfigurableCompany.Core.Display.Scripts { public class CustomCharacterValidator : TMP_InputValidator { public delegate bool CharValidator(ref string text, ref int pos, ref char ch); private const char NO_CHAR = '\0'; public CharValidator Validator; public static TMP_InputValidator Create(CharValidator validator) { CustomCharacterValidator customCharacterValidator = ScriptableObject.CreateInstance<CustomCharacterValidator>(); customCharacterValidator.Validator = validator; return (TMP_InputValidator)(object)customCharacterValidator; } public override char Validate(ref string text, ref int pos, char ch) { CharValidator validator = Validator; if (validator != null && !validator(ref text, ref pos, ref ch)) { return '\0'; } return ch; } } public class LifecycleListener : MonoBehaviour { public event Action DestroyEvent; protected void OnDestroy() { this.DestroyEvent?.Invoke(); } } internal class NoDrawGraphic : Graphic { public override void SetMaterialDirty() { } public override void SetVerticesDirty() { } protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); } } public class RegionButton : Button { public static readonly Navigation DEFAULT_NAVIGATION; public event EventHandler<PointerEventData> OnMouseEnter; public event EventHandler<PointerEventData> OnMouseExit; public event EventHandler<PointerEventData> OnMouseClick; protected override void Start() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ((UIBehaviour)this).Start(); ((Selectable)this).navigation = DEFAULT_NAVIGATION; } public override void OnPointerClick(PointerEventData eventData) { ((Button)this).OnPointerClick(eventData); this.OnMouseClick?.Invoke(this, eventData); } public override void OnPointerEnter(PointerEventData eventData) { ((Selectable)this).OnPointerEnter(eventData); this.OnMouseEnter?.Invoke(this, eventData); } public override void OnPointerExit(PointerEventData eventData) { ((Selectable)this).OnPointerExit(eventData); this.OnMouseExit?.Invoke(this, eventData); } static RegionButton() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) Navigation dEFAULT_NAVIGATION = default(Navigation); ((Navigation)(ref dEFAULT_NAVIGATION)).mode = (Mode)0; DEFAULT_NAVIGATION = dEFAULT_NAVIGATION; } } public class UIRegion : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { public event Action<PointerEventData> OnEnter; public event Action<PointerEventData> OnExit; public void OnPointerEnter(PointerEventData eventData) { this.OnEnter?.Invoke(eventData); } public void OnPointerExit(PointerEventData eventData) { this.OnExit?.Invoke(eventData); } } } namespace Amrv.ConfigurableCompany.Core.Display.menu { public class MenuPresets : IMenuPart { private readonly MenuBind Bind; private readonly GameObject Container; private readonly TMP_InputField InputField; private readonly GameObject Content; private string CurrentPresetFile; private readonly Dictionary<string, MenuPreset> Items = new Dictionary<string, MenuPreset>(); internal MenuPresets(MenuBind menuBind) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown Bind = menuBind; Container = menuBind.Menu.FindChild("Presets"); InputField = Container.FindChild("Input").GetComponent<TMP_InputField>(); Content = Container.FindChild("List/Viewport/Content"); ((UnityEvent)Container.FindChild("Buttons/Create").GetComponent<Button>().onClick).AddListener(new UnityAction(OnClickCreate)); ((UnityEvent)Container.FindChild("Buttons/Load").GetComponent<Button>().onClick).AddListener(new UnityAction(OnClickLoad)); ((UnityEvent)Container.FindChild("Buttons/Save").GetComponent<Button>().onClick).AddListener(new UnityAction(OnClickSave)); ((UnityEvent)Container.FindChild("Buttons/Delete").GetComponent<Button>().onClick).AddListener(new UnityAction(OnClickDelete)); ((UnityEvent<string>)(object)InputField.onEndEdit).AddListener((UnityAction<string>)UpdateCurrentFile); } private void UpdateCurrentFile(string text) { CurrentPresetFile = text + ".ccfg"; } private void OnClickCreate() { MenuEventRouter.OnClick_PresetCreate(CurrentPresetFile); } private void OnClickLoad() { MenuEventRouter.OnClick_PresetLoad(CurrentPresetFile); } private void OnClickSave() { MenuEventRouter.OnClick_PresetSave(CurrentPresetFile); } private void OnClickDelete() { MenuEventRouter.OnClick_PresetDelete(CurrentPresetFile); } public void Destroy() { } public void UpdateContent() { Dictionary<string, MenuPreset> dictionary = new Dictionary<string, MenuPreset>(Items); foreach (string item in Presets.List) { if (dictionary.TryGetValue(item, out var _)) { dictionary.Remove(item); } else { AddItem(item); } } foreach (KeyValuePair<string, MenuPreset> item2 in dictionary) { DeleteItem(item2.Key); } if (Items.Count > 0) { Dictionary<string, MenuPreset>.Enumerator enumerator3 = Items.GetEnumerator(); for (int i = 0; i < Items.Count; i++) { enumerator3.MoveNext(); } MenuPreset value2 = enumerator3.Current.Value; CurrentPresetFile = value2.File; InputField.text = value2.Text; } else { CurrentPresetFile = null; InputField.text = null; } } private void OnPrefabClick(MenuPreset preset) { CurrentPresetFile = preset.File; InputField.text = preset.Text; } public void DeleteItem(string item) { if (Items.TryGetValue(item, out var value)) { value.Delete(); Items.Remove(item); } } public void AddItem(string item) { MenuPreset menuPreset = new MenuPreset(item, Content); Items.Add(item, menuPreset); menuPreset.OnClick += OnPrefabClick; } public void UpdateSelf() { InputField.text = Path.GetFileNameWithoutExtension(CurrentPresetFile); } } } namespace Amrv.ConfigurableCompany.Core.Display.Menu { internal interface IMenuPart { void Destroy(); void UpdateContent(); void UpdateSelf(); } internal class MenuButtons : IMenuPart { private readonly MenuBind Bind; protected readonly GameObject ButtonSave; protected readonly GameObject ButtonReset; protected readonly GameObject ButtonRestore; protected readonly GameObject ButtonCopy; protected readonly GameObject ButtonPaste; protected readonly GameObject ButtonRandomize; protected readonly TMP_InputField ButtonRandomize_Input; internal MenuButtons(MenuBind bind) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Expected O, but got Unknown Bind = bind; ButtonSave = Bind.Menu.FindChild("Buttons/Save"); ((UnityEvent)ButtonSave.GetComponent<Button>().onClick).AddListener(new UnityAction(OnSave)); ButtonReset = Bind.Menu.FindChild("Buttons/Reset"); ((UnityEvent)ButtonReset.GetComponent<Button>().onClick).AddListener(new UnityAction(OnReset)); ButtonRestore = Bind.Menu.FindChild("Buttons/Restore"); ((UnityEvent)ButtonRestore.GetComponent<Button>().onClick).AddListener(new UnityAction(OnRestore)); ButtonCopy = Bind.Menu.FindChild("Buttons/Copy"); ((UnityEvent)ButtonCopy.GetComponent<Button>().onClick).AddListener(new UnityAction(OnCopy)); ButtonPaste = Bind.Menu.FindChild("Buttons/Paste"); ((UnityEvent)ButtonPaste.GetComponent<Button>().onClick).AddListener(new UnityAction(OnPaste)); ButtonRandomize = Bind.Menu.FindChild("Buttons/Randomize"); ButtonRandomize_Input = ButtonRandomize.GetComponentInChildren<TMP_InputField>(); ((UnityEvent)ButtonRandomize.GetComponent<Button>().onClick).AddListener(new UnityAction(OnRandomize)); } private void OnRandomize() { Random random; if (int.TryParse(ButtonRandomize_Input.text, out var result) && result != 0) { random = new Random(Math.Abs(result)); } else { result = new Random().Next(); random = new Random(Math.Abs(result)); } ButtonRandomize_Input.text = result.ToString(); MenuEventRouter.OnClick_Randomize(result, random); } private void OnSave() { MenuEventRouter.OnClick_Save(); } private void OnReset() { MenuEventRouter.OnClick_Reset(); } private void OnRestore() { MenuEventRouter.OnClick_Restore(); } private void OnCopy() { MenuEventRouter.OnClick_Copy(); } private void OnPaste() { MenuEventRouter.OnClick_Paste(); } [Obsolete("Does nothing on this class")] public void Destroy() { } [Obsolete("Does nothing on this class")] public void UpdateContent() { } [Obsolete("Does nothing on this class")] public void UpdateSelf() { } } internal class MenuCategories : IMenuPart { private readonly MenuBind Bind; private readonly GameObject Panel; private readonly GameObject Content; protected readonly Dictionary<CCategory, MenuCategory> Categories = new Dictionary<CCategory, MenuCategory>(); internal MenuCategories(MenuBind bind) { Bind = bind; Panel = Bind.Menu.FindChild("Panel"); Content = Panel.FindChild("Scroll View/Viewport/Content"); } public void AddCategory(CCategory category) { MenuCategory menuCategory = MenuCategory.CreateCategory(Content.transform, category); Categories.Add(category, menuCategory); menuCategory.SetVisible(category.Page.Equals(Bind.Pages.CurrentPage)); } public MenuCategory GetCategory(CCategory category) { return Categories[category]; } internal void DisplayPage(CPage page) { foreach (KeyValuePair<CCategory, MenuCategory> category in Categories) { category.Value.SetVisible(category.Key.Page.Equals(page)); } } public void Destroy() { } public void UpdateContent() { foreach (CCategory value in CCategory.Storage.Values) { AddCategory(value); } } public void UpdateSelf() { } } internal class MenuConfigs : IMenuPart { private readonly MenuBind Bind; private readonly Dictionary<CConfig, MenuConfig> _configs = new Dictionary<CConfig, MenuConfig>(); internal MenuConfigs(MenuBind bind) { Bind = bind; } public void AddConfig(CConfig config) { MenuConfig menuConfig = null; if (config.Section != null) { menuConfig = MenuConfig.CreateConfig(Bind.Sections.GetSection(config.Section).Content.transform, config, Bind, first: false); } else if (config.Category != null) { menuConfig = MenuConfig.CreateConfig(Bind.Categories.GetCategory(config.Category).Content.transform, config, Bind, first: true); } if (menuConfig != null) { _configs[config] = menuConfig; } } public MenuConfig GetConfig(CConfig config) { return _configs[config]; } public void Refresh(CConfig config) { if (_configs.TryGetValue(config, out var value)) { value.Load(); } } public void LoadFromConfig() { foreach (MenuConfig value in _configs.Values) { value.Load(); } } public void SaveToConfig() { foreach (MenuConfig value in _configs.Values) { value.Save(); } } public void Destroy() { foreach (CConfig key in _configs.Keys) { key.Reset(); } } public void UpdateContent() { foreach (CConfig value in CConfig.Storage.Values) { AddConfig(value); } } public void UpdateSelf() { } internal void ReceiveToggle(CConfig config, bool enabled) { _configs[config].ReceiveToggle(enabled); } internal void ReceiveReset(CConfig config) { _configs[config].ReceiveReset(); } } internal class MenuPages : IMenuPart { protected readonly MenuBind Bind; protected readonly GameObject PageContainer; protected readonly GameObject PageName; protected readonly TextMeshProUGUI PageName_Text; protected readonly Dictionary<CPage, MenuPage> Pages = new Dictionary<CPage, MenuPage>(); private CPage _currentPage; public CPage CurrentPage { get { return _currentPage; } set { if (_currentPage != value) { PageName.SetActive(!string.IsNullOrEmpty(value?.Name ?? null)); ((TMP_Text)PageName_Text).SetText(value?.Name ?? null, true); Bind.Categories.DisplayPage(value); _currentPage = value; } } } internal MenuPages(MenuBind bind) { Bind = bind; PageContainer = Bind.Menu.FindChild("Pages/Scroll View/Viewport/Content"); PageName = Bind.Menu.FindChild("Info/Page name"); PageName_Text = PageName.FindChild("Area/Text").GetComponent<TextMeshProUGUI>(); } public void AddPage(CPage page) { Pages[page] = MenuPage.CreatePage(PageContainer.transform, page); } public MenuPage GetPage(CPage page) { return Pages[page]; } public void Destroy() { foreach (MenuPage value in Pages.Values) { value.Destroy(); } Pages.Clear(); } public void UpdateContent() { foreach (CPage value in CPage.Storage.Values) { AddPage(value); if (CurrentPage == null) { CPage cPage2 = (CurrentPage = value); } } } public void UpdateSelf() { } } internal static class MenuPrefabs { public static readonly GameObject Menu; public static readonly GameObject Page; public static readonly GameObject Tag; public static readonly GameObject Category; public static readonly GameObject Section; public static readonly GameObject Preset; public static readonly GameObject Config_Input; public static readonly GameObject Config_LargeInput; public static readonly GameObject Config_Bool; public static readonly GameObject Config_Slider; public static readonly GameObject Config_Enum; public static readonly GameObject Config_DoubleSlider; public static readonly GameObject Config_DoubleInput; static MenuPrefabs() { using FastBundle fastBundle = UnityAsset.GetBundle(ConfigurableCompanyPlugin.PluginFolder, "configuration_menu"); fastBundle.Path = "Assets/ConfigurationMenu/"; Menu = fastBundle.LoadAsset<GameObject>("Configuration Menu.prefab"); Page = fastBundle.LoadAsset<GameObject>("Configuration Page.prefab"); Tag = fastBundle.LoadAsset<GameObject>("Configuration Tag.prefab"); Category = fastBundle.LoadAsset<GameObject>("Configuration Category.prefab"); Section = fastBundle.LoadAsset<GameObject>("Configuration Section.prefab"); Preset = fastBundle.LoadAsset<GameObject>("Configuration Preset.prefab"); Config_Input = fastBundle.LoadAsset<GameObject>("ConfigType Input.prefab"); Config_LargeInput = fastBundle.LoadAsset<GameObject>("ConfigType LargeInput.prefab"); Config_Bool = fastBundle.LoadAsset<GameObject>("ConfigType Bool.prefab"); Config_Slider = fastBundle.LoadAsset<GameObject>("ConfigType Slider.prefab"); Config_Enum = fastBundle.LoadAsset<GameObject>("ConfigType Enum.prefab"); Config_DoubleSlider = fastBundle.LoadAsset<GameObject>("ConfigType DoubleSlider.prefab"); Config_DoubleInput = fastBundle.LoadAsset<GameObject>("ConfigType DoubleInput.prefab"); } internal static void Ping() { } } internal class MenuSections : IMenuPart { protected readonly MenuBind Bind; protected readonly Dictionary<CSection, MenuSection> _sections = new Dictionary<CSection, MenuSection>(); internal MenuSections(MenuBind bind) { Bind = bind; } public void AddSec