Decompiled source of ConfigurableCompany v3.4.0

Amrv.ConfigurableCompany.dll

Decompiled 2 months ago
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