Decompiled source of ConfigurableCompany v3.7.0

Amrv.ConfigurableCompany.dll

Decompiled a week 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.Data;
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.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.7.0.0")]
[assembly: AssemblyInformationalVersion("3.7.0+539fa0b903db614796175bc4cc1f7ce1c2770753")]
[assembly: AssemblyProduct("Amrv.ConfigurableCompany")]
[assembly: AssemblyTitle("Amrv.ConfigurableCompany")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TheAnsuz/Lethal-Company-Configurable-Company-API")]
[assembly: AssemblyVersion("3.7.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.7.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.7.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:#}";
		}
	}
	public class Reference<T> : IDisposable where T : class
	{
		private readonly object _lock = new object();

		private T _value;

		public virtual bool IsAlive { get; private set; } = true;


		public virtual T Item
		{
			get
			{
				if (IsAlive)
				{
					return _value;
				}
				throw new NullReferenceException("Tried to get reference item after breaking it's bond");
			}
			set
			{
				lock (_lock)
				{
					if (IsAlive && value == null)
					{
						Break();
					}
					else
					{
						Bind(value);
					}
				}
			}
		}

		public Reference()
		{
			IsAlive = false;
		}

		public Reference(T item)
		{
			Item = item;
		}

		[Obsolete("Reference content may leak")]
		public static implicit operator T(Reference<T> reference)
		{
			return reference.Item;
		}

		public virtual void Break()
		{
			lock (_lock)
			{
				IsAlive = false;
				_value = null;
			}
		}

		public virtual void Bind(T item)
		{
			if (item == null)
			{
				Break();
				return;
			}
			lock (_lock)
			{
				IsAlive = true;
				_value = item;
			}
		}

		public virtual void Dispose()
		{
			Break();
		}

		~Reference()
		{
			_value = null;
		}
	}
}
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;
			}
			return list.ToArray();
		}

		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.7.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.7.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.SetConfigMetadata();
			IOController.SaveCategories();
			IOController.SaveSections();
			IOController.SaveConfigs();
		}

		internal static void Warn(object data)
		{
			((BaseUnityPlugin)_plugin).Logger.LogWarning(data);
		}

		internal static void Error(object data)
		{
			((BaseUnityPlugin)_plugin).Logger.LogError(data);
		}

		internal static void Info(object data)
		{
			((BaseUnityPlugin)_plugin).Logger.LogInfo(data);
		}

		internal static void Debug(object data)
		{
			((BaseUnityPlugin)_plugin).Logger.LogDebug(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)
		{
		}
	}
	internal static class CCache
	{
		private static string _userSeed;

		public static string UsedSeed
		{
			get
			{
				return _userSeed;
			}
			set
			{
				ConfigurableCompanyPlugin.Debug("Set cache UserSeed to " + value);
				_userSeed = value;
			}
		}
	}
	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(MenuManager manager)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			MenuLoader.Create();
			IOController.LoadCategories();
			IOController.LoadSections();
			IOController.LoadConfigs();
			IOController.GetConfigCache();
			MenuController.AfterCreation(AfterCreation);
			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, manager);
						break;
					}
				}
			}
		}

		private static IEnumerator AfterCreation(MenuManager manager)
		{
			MenuController.SetLocked(GameNetworkManager.Instance?.currentSaveFileName == "LCChallengeFile");
			MenuController.UpdateSeedFromCache();
			yield return null;
			MenuLoader.Destroy();
			yield return null;
		}

		public static void DestroyMenu()
		{
			IOController.SaveCategories();
			IOController.SaveSections();
			IOController.SaveConfigs();
			MenuController.Destroy();
			MenuLoader.Destroy();
			MenuPopup.Destroy();
		}
	}
	public static class RandomSeedParser
	{
		private static readonly Random selector;

		public static readonly Dictionary<char, int> CHAR_MAPPING;

		public static readonly char[] CHAR_ARRAY;

		static RandomSeedParser()
		{
			selector = new Random();
			CHAR_ARRAY = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
			CHAR_MAPPING = new Dictionary<char, int>(CHAR_ARRAY.Length);
			for (int i = 0; i < CHAR_ARRAY.Length; i++)
			{
				CHAR_MAPPING[CHAR_ARRAY[i]] = i;
			}
		}

		public static bool IsValidString(string str)
		{
			if (str.Length > 10)
			{
				return false;
			}
			for (int i = 0; i < str.Length; i++)
			{
				if (!IsValidChar(str[i]))
				{
					return false;
				}
			}
			return true;
		}

		public static bool IsValidChar(char ch)
		{
			if (ch <= '/' || ch >= ':')
			{
				if (ch > '@')
				{
					return ch < '[';
				}
				return false;
			}
			return true;
		}

		public static string GenerateRandom()
		{
			return GenerateRandom(selector);
		}

		public static string GenerateRandom(Random random)
		{
			char[] array = new char[10];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = CHAR_ARRAY[random.Next(CHAR_ARRAY.Length)];
			}
			return new string(array);
		}

		public static long FromSeed(string str)
		{
			str = FormalizeString(str);
			long num = 0L;
			for (int i = 0; i < str.Length; i++)
			{
				num *= 36;
				num += CHAR_MAPPING.GetValueOrDefault(str[i], 0);
			}
			return num;
		}

		public static string FormalizeString(string str)
		{
			str = str.Trim();
			StringBuilder stringBuilder = new StringBuilder(Math.Min(10, str.Length));
			for (int i = 0; i < stringBuilder.Capacity; i++)
			{
				if (CHAR_MAPPING.TryGetValue(str[i], out var _))
				{
					stringBuilder.Append(char.ToUpper(str[i]));
				}
			}
			return stringBuilder.ToString();
		}
	}
	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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			ConfigurableCompanyPlugin.Debug("MenuManager::Start [Postfix]");
			if (!__instance.isInitScene)
			{
				MenuLoader.Create();
				LifecycleEventRouter.CreateMenu(__instance);
				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()
		{
			ConfigurableCompanyPlugin.Debug("MenuManager::ClickHostButton [Postfix]");
			MenuController.SetVisible(visible: true);
		}

		[HarmonyPatch("ConfirmHostButton")]
		[HarmonyPostfix]
		private static void ConfirmHostButton_Postfix()
		{
			ConfigurableCompanyPlugin.Debug("MenuManager::ConfirmHostButton [Postfix]");
			MenuController.DestroyIfCreating();
			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.UpdateSeedFromCache();
				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_00b6: Unknown result type (might be due to invalid IL or missing references)
			ConfigBundle configBundle = new ConfigBundle();
			configBundle.AddMetadata("VERSION", "2n");
			CConfig[] array = new CConfig[CConfig.Storage.Count];
			int num = 0;
			foreach (CConfig value2 in CConfig.Storage.Values)
			{
				if (value2.Synchronized)
				{
					WriteConfigBundle(value2, configBundle);
					array[num++] = value2;
				}
			}
			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);
			Array.Resize(ref array, num + 1);
			CEvents.IOSEvents.Synchronize.InvokeFull(new CEventSynchronize(sent: true, array));
		}

		public static void SendConfig(params CConfig[] configs)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			ConfigBundle configBundle = new ConfigBundle();
			configBundle.AddMetadata("VERSION", "2n");
			int num = 0;
			CConfig[] array = configs;
			foreach (CConfig cConfig in array)
			{
				if (cConfig.Synchronized)
				{
					WriteConfigBundle(cConfig, configBundle);
					num++;
				}
			}
			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);
			Array.Resize(ref configs, num + 1);
			CEvents.IOSEvents.Synchronize.InvokeFull(new CEventSynchronize(sent: true, configs));
		}

		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");
			MenuController.DestroyIfCreating();
			LifecycleEventRouter.DestroyMenu();
			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;
			}
			CConfig[] array = new CConfig[configBundle.Entries().Count];
			int num = 0;
			foreach (KeyValuePair<string, ConfigBundle.ConfigEntry> item in configBundle.Entries())
			{
				if (CConfig.Storage.TryGetValue(item.Key, out var value2) && value2.Synchronized)
				{
					ReadConfigBundle(value2, item.Value);
					array[num++] = value2;
				}
			}
			Array.Resize(ref array, num + 1);
			CEvents.IOSEvents.Synchronize.InvokeFull(new CEventSynchronize(sent: false, array));
		}

		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 const string FIELD_CUSTOM_SEED = "Seed";

		public static void SaveCategories()
		{
			IOCategories.Save();
		}

		public static void LoadCategories()
		{
			IOCategories.Load();
		}

		public static void SaveSections()
		{
			IOSections.Save();
		}

		public static void LoadSections()
		{
			IOSections.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 bool GetSectionOpenState(CSection section)
		{
			return IOSections.GetOpenState(section);
		}

		public static void SetSectionOpenState(CSection section, bool open)
		{
			IOSections.SetOpenState(section, 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);
			ApplyMetadata(cfg);
			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 SetConfigMetadata()
		{
			IOConfigurations.GetOrCreate(IOConfigurations.FileName, out var cfg);
			ApplyMetadata(cfg);
		}

		public static void SetConfigCache()
		{
			IOConfigurations.GetOrCreate(IOConfigurations.FileName, out var cfg);
			ApplyMetadata(cfg);
			foreach (CConfig value in CConfig.Storage.Values)
			{
				WriteConfigEntryCache(value, cfg);
			}
		}

		public static void GetConfigCache()
		{
			if (IOConfigurations.TryGetFile(IOConfigurations.FileName, out var cfg))
			{
				if (cfg.TryGetMetadata("Seed", out var value) && value != null)
				{
					CCache.UsedSeed = value;
				}
				else
				{
					CCache.UsedSeed = "";
				}
				{
					foreach (CConfig value2 in CConfig.Storage.Values)
					{
						if (cfg.TryGetEntry(value2.ID, out var entry))
						{
							ReadConfigEntryCache(value2, entry);
						}
						else
						{
							value2.Reset(Amrv.ConfigurableCompany.API.ChangeReason.READ_FROM_FILE);
						}
					}
					return;
				}
			}
			foreach (CConfig value3 in CConfig.Storage.Values)
			{
				value3.Reset(Amrv.ConfigurableCompany.API.ChangeReason.READ_FROM_FILE);
			}
		}

		private static void ApplyMetadata(CCFGFile cfg)
		{
			cfg.AddMetadata("VERSION", "2");
			if (CCache.UsedSeed != null)
			{
				cfg.AddMetadata("Seed", CCache.UsedSeed);
			}
		}

		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() });
			}
		}
	}
	internal static class IOSections
	{
		private static readonly CCATFile File = new CCATFile(Path.Combine(ConfigurableCompanyPlugin.DataFolder, "sections.ccat"));

		public static void Load()
		{
			File.Read();
		}

		public static void Save()
		{
			File.Write();
		}

		public static bool GetOpenState(CSection section)
		{
			if (File.TryGetState(section.ID, out var state))
			{
				return state;
			}
			return false;
		}

		public static void SetOpenState(CSection section, bool open)
		{
			File.SetState(section.ID, open);
		}
	}
}
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 GameObject GetChild(this GameObject gameObject, int index)
		{
			Transform child = gameObject.transform.GetChild(index);
			return ((child != null) ? ((Component)child).gameObject : null) ?? null;
		}

		public static GameObject GetChild(this GameObject gameObject, params int[] indexes)
		{
			Transform val = gameObject.transform;
			for (int i = 0; i < indexes.Length; i++)
			{
				val = ((val != null) ? val.GetChild(indexes[i]) : null) ?? null;
			}
			return ((val != null) ? ((Component)val).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
{
	public static class GlobalCanvas
	{
		private static GameObject _canvasObject;

		private static Canvas _canvas;

		private static CanvasScaler _canvasScaler;

		private static EventSystem _eventSystem;

		private static GraphicRaycaster _raycaster;

		private static object _creationLock = new object();

		private static bool _created = false;

		public static Canvas Instance
		{
			get
			{
				lock (_creationLock)
				{
					if (!_created || (Object)(object)_canvas == (Object)null)
					{
						Destroy();
						Create();
					}
					return _canvas;
				}
			}
		}

		public static void Create()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			lock (_creationLock)
			{
				if (!_created)
				{
					_canvasObject = new GameObject("ConfigurableCompanyCanvas", new Type[4]
					{
						typeof(Canvas),
						typeof(CanvasScaler),
						typeof(LifecycleListener),
						typeof(GraphicRaycaster)
					});
					Object.DontDestroyOnLoad((Object)(object)_canvasObject);
					_canvas = _canvasObject.GetComponent<Canvas>();
					_canvasScaler = _canvasObject.GetComponent<CanvasScaler>();
					_raycaster = _canvasObject.GetComponent<GraphicRaycaster>();
					_canvasObject.GetComponent<LifecycleListener>().DestroyEvent += Destroy;
					_canvas.renderMode = (RenderMode)0;
					_canvas.pixelPerfect = true;
					_canvas.sortingOrder = 0;
					_canvasScaler.uiScaleMode = (ScaleMode)0;
					_canvasScaler.scaleFactor = 1.55f;
					_canvasScaler.referencePixelsPerUnit = 1f;
					_raycaster.blockingObjects = (BlockingObjects)1;
					_created = true;
				}
			}
		}

		public static void Destroy()
		{
			lock (_creationLock)
			{
				if (_created)
				{
					Object.Destroy((Object)(object)_canvasObject);
					_canvas = null;
					_canvasObject = null;
					_canvasScaler = null;
					_created = false;
				}
			}
		}
	}
	internal class MenuBind
	{
		private static MenuBind _instance;

		private readonly Reference<MenuBind> CurrentBind = new Reference<MenuBind>();

		public readonly Reference<MenuToggle> Toggler = new Reference<MenuToggle>();

		public readonly Reference<MenuPages> Pages = new Reference<MenuPages>();

		public readonly Reference<MenuButtons> Buttons = new Reference<MenuButtons>();

		public readonly Reference<MenuTooltip> Tooltip = new Reference<MenuTooltip>();

		public readonly Reference<MenuCategories> Categories = new Reference<MenuCategories>();

		public readonly Reference<MenuSections> Sections = new Reference<MenuSections>();

		public readonly Reference<MenuConfigs> Configs = new Reference<MenuConfigs>();

		public readonly Reference<MenuPresets> Presets = new Reference<MenuPresets>();

		protected GameObject Container { get; private set; }

		public GameObject Overlay { get; private set; }

		public GameObject ShowMenu { get; private set; }

		public GameObject Menu { get; private set; }

		protected GameObject FileName { get; private set; }

		protected TextMeshProUGUI FileText { get; private set; }

		protected TextMeshProUGUI BetaText { get; private set; }

		public string Filename
		{
			get
			{
				return ((TMP_Text)FileText).text;
			}
			set
			{
				FileName.SetActive(!string.IsNullOrEmpty(value));
				((TMP_Text)FileText).SetText(value, true);
			}
		}

		public static IEnumerator Create(Transform parent)
		{
			if (_instance == null || (Object)(object)_instance.Container == (Object)null)
			{
				_instance = new MenuBind(parent);
				yield return null;
				yield return _instance.UpdateMenu();
			}
			else
			{
				ConfigurableCompanyPlugin.Warn("Can't create MenuBind while there is an existing one");
			}
			_instance.Toggler.Item.Open = false;
			_instance.Toggler.Item.Visible = false;
			_instance.Filename = GameNetworkManager.Instance.currentSaveFileName;
			MenuLoader.GetInstance().Fill = 1f;
		}

		public static MenuBind GetInstance()
		{
			return _instance;
		}

		private MenuBind(Transform parent)
		{
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Expected O, but got Unknown
			MenuLoader instance = MenuLoader.GetInstance();
			ConfigurableCompanyPlugin.Debug("[MenuBind] Preparing menu");
			instance.Text = "Creating menu<br>Preparing menu...";
			instance.Fill = 0.1f;
			MenuEventRouter.OnAction_PrepareMenu();
			ConfigurableCompanyPlugin.Debug("[MenuBind] Instantiating container");
			instance.Text = "Creating menu<br>Instantiating container...";
			instance.Fill = 0.05f;
			Container = Object.Instantiate<GameObject>(MenuPrefabs.Menu);
			Container.SetActive(false);
			((Object)Container).name = "Configuration menu";
			Container.transform.SetParent(parent, false);
			Container.AddComponent<LifecycleListener>().DestroyEvent += Event_OnDestroy;
			instance.Fill = 0.1f;
			Overlay = ((Component)Container.transform.Find("Overlay")).gameObject;
			ShowMenu = ((Component)Container.transform.Find("Show menu")).gameObject;
			Menu = ((Component)Container.transform.Find("Menu")).gameObject;
			instance.Fill = 0.12f;
			FileName = Menu.FindChild("Info/File name");
			FileText = FileName.FindChild("Area/Text").GetComponent<TextMeshProUGUI>();
			instance.Fill = 0.135f;
			Menu.FindChild("Beta").AddComponent<RegionButton>().OnMouseClick += OnIssuesButtonClick;
			((UnityEvent)Menu.FindChild("Help").GetComponent<Button>().onClick).AddListener(new UnityAction(OnHelpButtonClick));
			BetaText = Menu.FindChild("Beta").GetComponent<TextMeshProUGUI>();
			CurrentBind.Item = this;
			instance.Text = "Creating menu<br>Creating Toggler...";
			instance.Fill = 0.15f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Toggler'");
			Toggler.Item = new MenuToggle(CurrentBind, Container);
			instance.Text = "Creating menu<br>Creating Pages...";
			instance.Fill = 0.2f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Pages'");
			Pages.Item = new MenuPages(CurrentBind);
			instance.Text = "Creating menu<br>Creating Buttons...";
			instance.Fill = 0.24f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Buttons'");
			Buttons.Item = new MenuButtons(CurrentBind);
			instance.Text = "Creating menu<br>Creating Tooltip...";
			instance.Fill = 0.29f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Tooltip'");
			Tooltip.Item = new MenuTooltip(CurrentBind);
			instance.Text = "Creating menu<br>Creating Categories...";
			instance.Fill = 0.33f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Categories'");
			Categories.Item = new MenuCategories(CurrentBind);
			instance.Text = "Creating menu<br>Creating Sections...";
			instance.Fill = 0.38f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Sections'");
			Sections.Item = new MenuSections(CurrentBind);
			instance.Text = "Creating menu<br>Creating Configs...";
			instance.Fill = 0.42f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Configs'");
			Configs.Item = new MenuConfigs(CurrentBind);
			instance.Text = "Creating menu<br>Creating Presets...";
			instance.Fill = 0.49f;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Creating 'Presets'");
			Presets.Item = new MenuPresets(CurrentBind);
		}

		private IEnumerator UpdateMenu()
		{
			MenuLoader loader = MenuLoader.GetInstance();
			loader.Text = "Populating menu<br>Updating Pages...";
			loader.Fill = 0.5f;
			yield return null;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Updating 'Pages'");
			yield return Pages.Item.UpdateContent();
			loader.Fill = 0.54f;
			yield return null;
			yield return Pages.Item.UpdateSelf();
			loader.Fill = 0.59f;
			yield return null;
			loader.Text = "Populating menu<br>Updating Categories...";
			ConfigurableCompanyPlugin.Debug("[MenuBind] Updating 'Categories'");
			yield return Categories.Item.UpdateContent();
			loader.Fill = 0.62f;
			yield return null;
			yield return Categories.Item.UpdateSelf();
			loader.Fill = 0.66f;
			yield return null;
			loader.Text = "Populating menu<br>Updating Sections...";
			ConfigurableCompanyPlugin.Debug("[MenuBind] Updating 'Sections'");
			yield return Sections.Item.UpdateContent();
			loader.Fill = 0.7f;
			yield return null;
			yield return Sections.Item.UpdateSelf();
			loader.Fill = 0.74f;
			yield return null;
			loader.Text = "Populating menu<br>Updating Configs (0%)...";
			ConfigurableCompanyPlugin.Debug("[MenuBind] Updating 'Configs' 1/2");
			yield return Configs.Item.UpdateContent();
			loader.Fill = 0.85f;
			yield return null;
			loader.Text = "Populating menu<br>Updating Config holder...";
			ConfigurableCompanyPlugin.Debug("[MenuBind] Updating 'Configs' 2/2");
			yield return Configs.Item.UpdateSelf();
			loader.Fill = 0.89f;
			yield return null;
			loader.Text = "Populating menu<br>Updating Presets...";
			ConfigurableCompanyPlugin.Debug("[MenuBind] Updating 'Presets'");
			yield return Presets.Item.UpdateContent();
			loader.Fill = 0.92f;
			yield return null;
			yield return Presets.Item.UpdateSelf();
			loader.Fill = 0.96f;
			yield return null;
			ConfigurableCompanyPlugin.Debug("[MenuBind] Menu created");
			MenuEventRouter.OnAction_CreateMenu();
			loader.Fill = 0.99f;
			yield return null;
		}

		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()
		{
			MenuEventRouter.OnAction_DestroyMenu();
		}

		internal void Destroy()
		{
			ConfigurableCompanyPlugin.Debug("[Destroy] MenuBind deletion in progress");
			Toggler.Item.Destroy();
			Toggler.Break();
			Pages.Item.Destroy();
			Pages.Break();
			Buttons.Item.Destroy();
			Buttons.Break();
			Tooltip.Item.Destroy();
			Tooltip.Break();
			Categories.Item.Destroy();
			Categories.Break();
			Sections.Item.Destroy();
			Sections.Break();
			Configs.Item.Destroy();
			Configs.Break();
			Presets.Item.Destroy();
			Presets.Break();
			FileText = null;
			BetaText = null;
			Object.Destroy((Object)(object)Overlay);
			Overlay = null;
			Object.Destroy((Object)(object)ShowMenu);
			ShowMenu = null;
			Object.Destroy((Object)(object)Menu);
			Menu = null;
			Object.Destroy((Object)(object)FileName);
			FileName = null;
			Object.Destroy((Object)(object)Container);
			Container = null;
			CurrentBind.Break();
			_instance = null;
		}

		~MenuBind()
		{
			ConfigurableCompanyPlugin.Debug("[Destroy] MenuBind deleted");
		}
	}
	internal static class MenuController
	{
		public delegate IEnumerator AfterCreationProcess(MenuManager manager);

		private static MenuBind Instance;

		private static GameObject _creator;

		private static CoroutinePool _pool;

		private static AfterCreationProcess _afterCreation;

		public static void AfterCreation(AfterCreationProcess action)
		{
			_afterCreation = (AfterCreationProcess)Delegate.Combine(_afterCreation, action);
		}

		public static void Create(GameObject parent, MenuManager manager)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			_creator = new GameObject("Configurable company menu creator", new Type[1] { typeof(CoroutinePool) });
			_pool = _creator.GetComponent<CoroutinePool>();
			((MonoBehaviour)_pool).StartCoroutine(CreateAsync(parent, manager, _pool));
		}

		public static void DestroyIfCreating()
		{
			if ((Object)(object)_pool != (Object)null)
			{
				((MonoBehaviour)_pool).StopAllCoroutines();
				_pool = null;
			}
			Object.Destroy((Object)(object)_creator);
			_creator = null;
		}

		private static IEnumerator CreateAsync(GameObject parent, MenuManager manager, CoroutinePool creatorPool)
		{
			MenuLoader.GetInstance().Visible = true;
			MenuLoader.GetInstance().Fill = 0f;
			MenuLoader.GetInstance().Text = "Creating menu";
			yield return MenuBind.Create(parent.transform);
			Instance = MenuBind.GetInstance();
			MenuLoader.GetInstance().Visible = true;
			MenuLoader.GetInstance().Fill = 1f;
			MenuLoader.GetInstance().Text = "Activating";
			yield return null;
			SetVisible(manager.HostSettingsScreen.activeSelf);
			Instance.Toggler.Item.Open = false;
			MenuLoader.GetInstance().Visible = false;
			if (_afterCreation != null)
			{
				yield return _afterCreation(manager);
			}
			yield return null;
			Object.Destroy((Object)(object)((Component)creatorPool).gameObject, 5f);
		}

		public static bool IsLocked()
		{
			return Instance?.Toggler.Item.Locked ?? false;
		}

		public static void SetLocked(bool locked)
		{
			if (Instance != null)
			{
				Instance.Toggler.Item.Locked = locked;
			}
		}

		public static void SetVisible(bool visible)
		{
			if (Instance != null)
			{
				Instance.Toggler.Item.Visible = visible;
			}
		}

		public static void SetCurrentFileName(string filename)
		{
			if (Instance != null)
			{
				Instance.Filename = filename;
			}
		}

		public static void SetRandomizerDetails(InfoProvider info)
		{
			if (Instance != null)
			{
				Instance.Buttons.Item.SetRandomizerDetails(info);
			}
		}

		public static void SetCurrentPage(CPage page)
		{
			if (Instance != null)
			{
				Instance.Pages.Item.CurrentPage = page;
			}
		}

		public static void AddPage(CPage page)
		{
			if (Instance != null)
			{
				Instance.Pages.Item.AddPage(page);
			}
		}

		public static void AddCategory(CCategory category)
		{
			if (Instance != null)
			{
				Instance.Categories.Item.AddCategory(category);
			}
		}

		public static void AddSection(CSection section)
		{
			if (Instance != null)
			{
				Instance.Sections.Item.AddSection(section);
			}
		}

		public static void AddConfig(CConfig config)
		{
			if (Instance != null)
			{
				Instance.Configs.Item.AddConfig(config);
			}
		}

		public static void RefreshConfig(CConfig config)
		{
			if (Instance != null)
			{
				Instance.Configs.Item.Refresh(config);
			}
		}

		public static void SaveConfigs()
		{
			if (Instance != null)
			{
				Instance.Configs.Item.SaveToConfig();
			}
		}

		public static void LoadConfigs()
		{
			if (Instance != null)
			{
				Instance.Configs.Item.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.Item.ReceiveReset(config);
				}
				else
				{
					Instance.Configs.Item.Refresh(config);
				}
			}
		}

		public static void TriggerToggleConfig(CConfig config, bool enabled)
		{
			if (Instance != null)
			{
				Instance.Configs.Item.ReceiveToggle(config, enabled);
			}
		}

		public static void Destroy()
		{
			if (Instance != null)
			{
				Instance.Destroy();
				Instance = null;
			}
		}

		public static void RefreshPresets()
		{
			if (Instance != null)
			{
				Instance.Presets.Item.UpdateContentFull();
			}
		}

		public static void UpdateSeedFromCache()
		{
			ConfigurableCompanyPlugin.Debug("Trying to update seed info with cached seed");
			if (Instance != null)
			{
				if (CCache.UsedSeed == null)
				{
					ConfigurableCompanyPlugin.Debug("Invalid cached seed for update: " + CCache.UsedSeed);
					return;
				}
				InfoProvider infoProvider = InfoProvider.Create(CCache.UsedSeed, SpecialSeed.GetSpecialSeed(CCache.UsedSeed));
				SetRandomizerDetails(infoProvider);
				ConfigurableCompanyPlugin.Debug("Updated seed from " + (infoProvider.IsSpecialSeed ? "Special seed" : (infoProvider.IsChallenge ? "Challenge seed" : "Normal seed")) + ": " + infoProvider.SeedString);
			}
		}
	}
	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(string seed)
		{
			ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Randomize (" + seed + ")");
			if (seed == null || seed == "")
			{
				foreach (CConfig value in CConfig.Storage.Values)
				{
					value.Reset(Amrv.ConfigurableCompany.API.ChangeReason.USER_RANDOMIZED);
				}
				CEvents.MenuEvents.Randomize.InvokeFull(new CEventRandomize(RNGProvider.Static, InfoProvider.Default));
				CCache.UsedSeed = "";
				MenuController.SetRandomizerDetails(InfoProvider.Default);
				return;
			}
			InfoProvider infoProvider = InfoProvider.Create(seed, SpecialSeed.GetSpecialSeed(seed));
			RNGProvider rNGProvider = (infoProvider.IsSpecialSeed ? new RNGProvider(infoProvider.SpecialSeed.Seed) : new RNGProvider(RandomSeedParser.FromSeed(seed)));
			CCache.UsedSeed = infoProvider.SeedString;
			MenuController.SetRandomizerDetails(infoProvider);
			CEvents.MenuEvents.Randomize.InvokeFull(new CEventRandomize(rNGProvider, infoProvider));
			List<CConfig> list = new List<CConfig>();
			foreach (CConfig value2 in CConfig.Storage.Values)
			{
				try
				{
					value2.Randomize(rNGProvider, infoProvider, Amrv.ConfigurableCompany.API.ChangeReason.USER_RANDOMIZED);
				}
				catch (Exception data)
				{
					list.Add(value2);
					ConfigurableCompanyPlugin.Error(data);
				}
			}
			if (list.Count > 0)
			{
				MenuPopup.Show("ERROR", $"Unable to randomize all configs ({list.Count} errors)", MenuPopup.NO_ACTION, null);
			}
		}

		public static void OnClick_ShowPage(CPage page)
		{
			ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | ShowPage (" + page.Name + ")");
			MenuController.SetCurrentPage(page);
			CEvents.MenuEvents.ChangePage.InvokeFull(new CEventChangePage(page));
		}

		public static void OnAction_PrepareMenu()
		{
			ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Prepare");
			CEvents.MenuEvents.Prepare.InvokeFull();
		}

		public static void OnAction_CreateMenu()
		{
			ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Create");
			CEvents.MenuEvents.Create.InvokeFull();
		}

		public static void OnAction_DestroyMenu()
		{
			ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnAction | Destroy");
			CEvents.MenuEvents.Destroy.InvokeFull();
		}

		public static void OnClick_ToggleMenu(bool open)
		{
			ConfigurableCompanyPlugin.Debug("MenuEventRouter > OnClick | Toggle (" + (open ? "Open" : "Close") + ")");
			CEvents.MenuEvents.Toggle.InvokeFull(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 |