Decompiled source of LethalUtilities Public Testing v2.0.1

LethalUtilities.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalUtilities.Configuration;
using LethalUtilitiesV2;
using Microsoft.CodeAnalysis;
using MonoMod.Utils;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LethalUtilities")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fc87b84960862e64d1b0d4748adc0adfa6ed415a")]
[assembly: AssemblyProduct("LethalUtilities")]
[assembly: AssemblyTitle("LethalUtilities")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Kyxino/LethalUtilities")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 LethalUtilitiesV2
{
	public enum RunConfig
	{
		Enabled,
		UseLoadSettings,
		ConfigDisabled
	}
	public class Utils
	{
		[CompilerGenerated]
		private sealed class <HarmonyEnumerator>d__3 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator Enumerator;

			public Action EnumeratorPrefix;

			public Action EnumeratorPostfix;

			public Action<object> YieldPrefix;

			public Func<object, object> YieldAction;

			public Action<object> YieldPostfix;

			private object <CurrentItem>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <HarmonyEnumerator>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<CurrentItem>5__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (EnumeratorPrefix != null)
					{
						EnumeratorPrefix();
					}
					break;
				case 1:
					<>1__state = -1;
					if (YieldPostfix != null)
					{
						YieldPostfix(<CurrentItem>5__1);
					}
					<CurrentItem>5__1 = null;
					break;
				}
				if (Enumerator.MoveNext())
				{
					<CurrentItem>5__1 = Enumerator.Current;
					if (YieldPrefix != null)
					{
						YieldPrefix(<CurrentItem>5__1);
					}
					<>2__current = ((YieldAction != null) ? YieldAction(<CurrentItem>5__1) : null);
					<>1__state = 1;
					return true;
				}
				if (EnumeratorPostfix != null)
				{
					EnumeratorPostfix();
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static T InvokeMethod<T>(object OBJECT, string METHOD, object[] PARAMETERS = null)
		{
			return (T)OBJECT.GetType().GetMethod(METHOD, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Invoke(OBJECT, PARAMETERS);
		}

		private static T GetField<T>(object OBJECT, string FIELD)
		{
			return (T)OBJECT.GetType().GetField(FIELD, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(OBJECT);
		}

		private static T SetField<T>(object OBJECT, string FIELD, T VALUE)
		{
			OBJECT.GetType().GetField(FIELD, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(OBJECT, VALUE);
			return VALUE;
		}

		[IteratorStateMachine(typeof(<HarmonyEnumerator>d__3))]
		public static IEnumerator HarmonyEnumerator(IEnumerator Enumerator, Action EnumeratorPrefix = null, Action EnumeratorPostfix = null, Action<object> YieldPrefix = null, Func<object, object> YieldAction = null, Action<object> YieldPostfix = null)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <HarmonyEnumerator>d__3(0)
			{
				Enumerator = Enumerator,
				EnumeratorPrefix = EnumeratorPrefix,
				EnumeratorPostfix = EnumeratorPostfix,
				YieldPrefix = YieldPrefix,
				YieldAction = YieldAction,
				YieldPostfix = YieldPostfix
			};
		}
	}
	public static class ObjectExtensions
	{
		public static string Val(this object Value)
		{
			return string.Format("{0} ({1})", Value, (Value != null) ? ((object)Value.GetType()) : ((object)"N/A"));
		}
	}
	[BepInPlugin("Kyxino-LUv2", "Ky-LethalUtilities", "2.0.1")]
	public class UtilsMod : BaseUnityPlugin
	{
		[JsonConverter(typeof(IL_SubField))]
		internal class IL_SubFieldConverter : JsonConverter<IL_SubField>
		{
			public override bool CanRead => true;

			public override bool CanWrite => false;

			public override void WriteJson(JsonWriter writer, IL_SubField value, JsonSerializer serializer)
			{
			}

			public override IL_SubField ReadJson(JsonReader reader, Type objectType, IL_SubField existingValue, bool hasExistingValue, JsonSerializer serializer)
			{
				return IL_SubField.Parse(serializer.Deserialize<List<string>>(reader));
			}
		}

		public class IL_SubField
		{
			public static Dictionary<int, IL_SubField> HashChecks = new Dictionary<int, IL_SubField>();

			public IL_Field Field;

			public List<string> SubFieldList;

			public object SubFieldValue;

			public Type SubFieldType;

			public bool IsLocal;

			public int LocalHash;

			public IL_SubField(IL_Field Field, List<string> SubFieldList, bool IsLocal = false)
			{
				this.Field = Field;
				this.SubFieldList = SubFieldList;
				SubFieldType = (SubFieldValue = GetSubFieldValue(Field.OriginalValue))?.GetType();
				this.IsLocal = IsLocal;
				HashChecks.TryAdd(GetHashCode(), this);
			}

			public object GetSubFieldValue(object Field)
			{
				if (IsLocal)
				{
					return Field;
				}
				Logger("GetSubFieldValue", (LogLevel)16, (object)"START");
				Logger("GetSubFieldValue", (LogLevel)16, Field);
				foreach (string subField in SubFieldList)
				{
					try
					{
						Logger("GetSubFieldValue", (LogLevel)16, (object)$"Field: {Field} ({Field?.GetType()}) | SubField: {subField}");
						MethodInfo methodInfo = Field?.GetType()?.GetMethod("get_" + subField);
						Field = ((!(methodInfo != null)) ? Field?.GetType()?.GetField(subField)?.GetValue(Field) : methodInfo.Invoke(Field, Array.Empty<object>()));
						Logger("GetSubFieldValue", (LogLevel)8, (object)$"Field: {Field}");
					}
					catch (Exception ex)
					{
						Logger("GetSubFieldValue", (LogLevel)2, (object)("SubField Error | " + GeneralExtensions.Join<string>((IEnumerable<string>)SubFieldList, (Func<string, string>)null, ", ") + ": " + ex.Message));
						return null;
					}
				}
				Logger("GetSubFieldValue", (LogLevel)16, (object)"END");
				return Field;
			}

			public void SetSubFieldValue(object Field, object Value)
			{
				if (IsLocal)
				{
					return;
				}
				Logger("SetSubFieldValue", (LogLevel)16, (object)"START");
				Logger("SetSubFieldValue", (LogLevel)16, Field);
				for (int i = 0; i < SubFieldList.Count; i++)
				{
					string text = SubFieldList[i];
					try
					{
						Logger("SetSubFieldValue", (LogLevel)16, Field);
						if (i == SubFieldList.Count - 1)
						{
							MethodInfo methodInfo = Field?.GetType()?.GetMethod("set_" + text);
							if (methodInfo != null)
							{
								methodInfo.Invoke(Field = Value, Array.Empty<object>());
							}
							else
							{
								Field?.GetType()?.GetField(text)?.SetValue(Field, Field = Value);
							}
						}
						else
						{
							Field = Field?.GetType()?.GetMethod("get_" + text)?.Invoke(Field, Array.Empty<object>()) ?? Field?.GetType().GetField(text).GetValue(Field);
						}
						Logger("SetSubFieldValue", (LogLevel)8, Field);
					}
					catch (Exception ex)
					{
						Logger("SetSubFieldValue", (LogLevel)2, (object)string.Format("SubField Set Error {0}/{1} | {2}: {3}", i + 1, SubFieldList.Count, GeneralExtensions.Join<string>((IEnumerable<string>)SubFieldList, (Func<string, string>)null, ", "), ex.Message));
						return;
					}
				}
				Logger("SetSubFieldValue", (LogLevel)16, (object)"END");
			}

			public static IL_SubField Parse(List<string> SearchList, object FieldValue = null, bool CanSet = false, bool LiveValue = false)
			{
				List<string> list = SearchList.Where((string x) => x.Contains("::")).ToList();
				List<string> SubFieldList = SearchList.Where((string x) => !x.Contains("::")).ToList();
				bool flag = list.Count == 0;
				if (flag)
				{
					list = SubFieldList;
					SubFieldList = new List<string>();
				}
				int num = list.FindIndex((string x) => x.StartsWith("="));
				if (num == -1)
				{
					return null;
				}
				List<string> range = list.GetRange(0, num);
				string text = list[num];
				string fieldTarget = text.Substring(1, text.Length - 1);
				List<string> range2 = list.GetRange(num + 1, list.Count - num - 1);
				List<string> RawFieldList = range.Union(new <>z__ReadOnlySingleElementList<string>(list[num])).Union(range2).ToList();
				IL_Field iL_Field = (flag ? null : IL_Field.CachedIL_Fields.FirstOrDefault((IL_Field x) => x.RawFieldList != null && (RawFieldList?.SequenceEqual(x.RawFieldList) ?? false)));
				if (iL_Field == null)
				{
					iL_Field = new IL_Field(range, fieldTarget, range2, FieldValue, CanSet, LiveValue, flag);
					if (!flag)
					{
						IL_Field.CachedIL_Fields.Add(iL_Field);
					}
				}
				IL_SubField iL_SubField = (flag ? null : iL_Field.SubFields.FirstOrDefault((IL_SubField x) => SubFieldList.SequenceEqual(x.SubFieldList)));
				if (iL_SubField == null)
				{
					iL_Field.SubFields.Add(iL_SubField = new IL_SubField(iL_Field, SubFieldList, flag));
				}
				return iL_SubField;
			}

			public override int GetHashCode()
			{
				return HashCode.Combine(Field, SubFieldList);
			}
		}

		public class IL_Field : IEquatable<IL_Field>
		{
			public static List<IL_Field> CachedIL_Fields = new List<IL_Field>();

			public List<string> PreFieldLook;

			public object OriginalValue;

			public object FieldValue;

			public Type FieldType;

			public IL_Fragment FieldTarget;

			public List<string> PostFieldLook;

			public List<string> RawFieldList;

			public bool CanSet;

			public bool LiveValue;

			public bool IsLocal;

			public List<IL_SubField> SubFields;

			public IL_Field(List<string> PreFieldLook, string FieldTarget, List<string> PostFieldLook, object FieldValue = null, bool CanSet = false, bool LiveValue = false, bool IsLocal = false)
			{
				this.PreFieldLook = PreFieldLook;
				OriginalValue = FieldValue;
				this.FieldValue = FieldValue;
				FieldType = FieldValue?.GetType();
				this.FieldTarget = new IL_Fragment(FieldTarget);
				this.PostFieldLook = PostFieldLook;
				RawFieldList = PreFieldLook.Union(new <>z__ReadOnlySingleElementList<string>("=" + FieldTarget)).Union(PostFieldLook).ToList();
				this.CanSet = CanSet;
				this.LiveValue = LiveValue;
				SubFields = new List<IL_SubField>(1)
				{
					new IL_SubField(this, new List<string>())
				};
				this.IsLocal = IsLocal;
			}

			public override bool Equals(object obj)
			{
				return obj is IL_Field iL_Field && PreFieldLook.Equals(iL_Field.PreFieldLook) && FieldTarget.Equals(iL_Field.FieldTarget) && PostFieldLook.Equals(iL_Field.PostFieldLook);
			}

			public bool Equals(IL_Field IL_Obj)
			{
				return PreFieldLook.Equals(IL_Obj.PreFieldLook) && FieldTarget.Equals(IL_Obj.FieldTarget);
			}

			public override int GetHashCode()
			{
				return HashCode.Combine(PreFieldLook, FieldTarget, PostFieldLook);
			}
		}

		public class IL_Fragment
		{
			public static Dictionary<string, IL_Fragment> Cached_Fragments = new Dictionary<string, IL_Fragment>();

			public List<string> Raw;

			public List<string> Unorganized;

			public string SpecificTarget;

			public IL_Fragment(string Target)
			{
				Raw = Target.Split(' ').ToList();
				Unorganized = Raw.Where((string x) => !x.Contains("::")).ToList();
				SpecificTarget = Raw.FirstOrDefault((string x) => x.Contains("::"));
			}

			public bool Match(IL_Fragment OpNameSplit)
			{
				return OpNameSplit.SpecificTarget == SpecificTarget || (SpecificTarget != null && OpNameSplit.SpecificTarget != null && SpecificTarget.Contains(OpNameSplit.SpecificTarget) && OpNameSplit.Unorganized.All((string Partial) => Unorganized.FirstOrDefault((string x) => x.Contains(Partial)) != null));
			}

			public override string ToString()
			{
				return GeneralExtensions.Join<string>((IEnumerable<string>)Raw, (Func<string, string>)null, " ");
			}
		}

		public class CachedMethods
		{
			public static string Path = Directory.GetParent(Assembly.GetExecutingAssembly().Location)?.ToString() + "\\methods.LU.cache";

			public List<string> Methods = new List<string>();

			public Dictionary<string, string> Mods = new Dictionary<string, string>();

			public List<string> LUHashes = new List<string>();

			public string GameUUID;

			public string LU_UUID;
		}

		public static BepInPlugin Metadata = MetadataHelper.GetMetadata(typeof(UtilsMod));

		private readonly Harmony HarmonyX = new Harmony("Kyxino-LUv2");

		public static ManualLogSource MLS = Logger.CreateLogSource("LethalUtilitiesV2");

		public List<JsonVarLUFile> LUFiles;

		public static Dictionary<string, ManualLogSource> Loggers = new Dictionary<string, ManualLogSource>();

		public static Dictionary<IL_SubField, List<JsonVarLU>> VariablesLU = new Dictionary<IL_SubField, List<JsonVarLU>>();

		public static MethodInfo ManageField = AccessTools.Method(typeof(UtilsMod), "ManagingField", (Type[])null, (Type[])null);

		public static MethodInfo TypeMethod = AccessTools.Method(typeof(Type), "GetTypeFromHandle", (Type[])null, (Type[])null);

		public static int MethodsChanged = 0;

		public static string TranspileMethodName;

		private void Awake()
		{
			ConfigUtilities.AddAllTypes();
			JsonConvert.DefaultSettings = () => new JsonSerializerSettings
			{
				Converters = new List<JsonConverter>(1) { (JsonConverter)(object)new IL_SubFieldConverter() }
			};
			LUFiles = new List<JsonVarLUFile>();
			string[] files = Directory.GetFiles(Paths.BepInExRootPath, "*.LU.json", SearchOption.AllDirectories);
			foreach (string path in files)
			{
				string text = File.ReadAllText(path);
				JsonVarLUFile jsonVarLUFile = JsonConvert.DeserializeObject<JsonVarLUFile>(text);
				jsonVarLUFile.Hash = Extensions.ToHexadecimalString(MD5.Create().ComputeHash(Encoding.Default.GetBytes(text)));
				LUFiles.Add(jsonVarLUFile);
				string folderName = null;
				string fileName = null;
				string categoryName = null;
				NetworkedConfigSync syncType = NetworkedConfigSync.Unspecified;
				bool? includesRaw = null;
				for (int j = 0; j < jsonVarLUFile.Variables.Count; j++)
				{
					JsonVarLU jsonVarLU = jsonVarLUFile.Variables[j];
					if (jsonVarLUFile.Settings.RolloverFolder)
					{
						JsonVarLU jsonVarLU2 = jsonVarLU;
						folderName = jsonVarLU2.FolderName ?? (jsonVarLU2.FolderName = folderName);
					}
					if (jsonVarLUFile.Settings.RolloverFile)
					{
						JsonVarLU jsonVarLU2 = jsonVarLU;
						fileName = jsonVarLU2.FileName ?? (jsonVarLU2.FileName = fileName);
					}
					if (jsonVarLUFile.Settings.RolloverCategory)
					{
						JsonVarLU jsonVarLU2 = jsonVarLU;
						categoryName = jsonVarLU2.CategoryName ?? (jsonVarLU2.CategoryName = categoryName);
					}
					if (jsonVarLUFile.Settings.RolloverSyncType)
					{
						if (jsonVarLU.SyncType == NetworkedConfigSync.Unspecified)
						{
							jsonVarLU.SyncType = syncType;
						}
						else
						{
							syncType = jsonVarLU.SyncType;
						}
					}
					if (jsonVarLUFile.Settings.RolloverRaw)
					{
						if (!jsonVarLU.IncludesRaw.HasValue)
						{
							jsonVarLU.IncludesRaw = includesRaw;
						}
						else
						{
							includesRaw = jsonVarLU.IncludesRaw;
						}
					}
				}
			}
			LUFiles.Sort((JsonVarLUFile L, JsonVarLUFile N) => L.Settings.Priority.CompareTo(N.Settings.Priority));
			foreach (JsonVarLU item in LUFiles.SelectMany((JsonVarLUFile LUFile) => LUFile.Variables))
			{
				if (item.SearchForValue == null)
				{
					continue;
				}
				item.WaitFor.Add(item.SearchForValue.Field);
				if (!VariablesLU.TryGetValue(item.SearchForValue, out var value))
				{
					VariablesLU.TryAdd(item.SearchForValue, value = new List<JsonVarLU>());
				}
				if (!value.Contains(item))
				{
					value.Add(item);
				}
				if (item.SearchForKey == null)
				{
					continue;
				}
				item.WaitFor.Add(item.SearchForKey.Field);
				if (!VariablesLU.TryGetValue(item.SearchForKey, out var value2))
				{
					VariablesLU.TryAdd(item.SearchForKey, value2 = new List<JsonVarLU>());
				}
				if (!value2.Contains(item))
				{
					value2.Add(item);
				}
				if (item.ValidKeys != null)
				{
					if (!VariablesLU.TryGetValue(item.ValidKeys, out var value3))
					{
						VariablesLU.TryAdd(item.ValidKeys, value3 = new List<JsonVarLU>());
					}
					if (!value3.Contains(item))
					{
						value3.Add(item);
					}
				}
			}
			ApplyChanges();
			MLS.LogInfo((object)"All enabled patches have been executed.");
		}

		public static void Logger(string Name, LogLevel LogLevel, object Data)
		{
		}

		public static void Logger(string Name, object Data, LogLevel LogLevel = 16)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Logger(Name, LogLevel, Data);
		}

		public static object HandleVar(JsonVarLU Var, object ModifyValue)
		{
			ConfigEntry<object> entry = Var.Entry;
			ConfigUtilities.TypeConverterBase converter = entry.EntrySettings.GetConverter();
			if (converter.TypeEnum == ConfigUtilities.TypeConverterEnum.Variable)
			{
				Logger("LoggerVarTest", (LogLevel)2, (object)("Variable? " + Var.FolderName + "." + Var.FileName + "." + Var.CategoryName + "." + Var.VariableName));
				if (converter.KeyType == typeof(LU_EQ))
				{
					return (Var.Entry.Value is LU_EQ lU_EQ) ? lU_EQ.CalcFormula(ModifyValue.ToString()) : null;
				}
				if (converter.KeyType == typeof(string))
				{
					return Var.Entry.Value?.ToString();
				}
				if (converter.KeyType == typeof(bool))
				{
					return Var.Entry.Value;
				}
				return null;
			}
			if (converter.TypeEnum == ConfigUtilities.TypeConverterEnum.Dictionary)
			{
				Logger("LoggerVarTest", (LogLevel)2, (object)("Dictionary? " + Var.FolderName + "." + Var.FileName + "." + Var.CategoryName + "." + Var.VariableName));
				if (converter.ValueType == typeof(LU_EQ))
				{
					object obj = converter.ConvertToHash(entry.Value);
					Dictionary<int, LU_EQ> dictionary = (Dictionary<int, LU_EQ>)obj;
					IL_SubField searchForKey = Var.SearchForKey;
					Logger("HandleVar", (LogLevel)1, (object)$"VALUES: {searchForKey?.Field?.OriginalValue} | {searchForKey?.Field?.FieldValue}");
					object obj2 = searchForKey?.GetSubFieldValue(searchForKey?.Field?.OriginalValue);
					int? num = obj2?.GetHashCode();
					if (!num.HasValue)
					{
						return null;
					}
					List<object> usedKeys = entry.EntrySettings.UsedKeys;
					if (true && !usedKeys.Contains(obj2))
					{
						usedKeys.Add(obj2);
						entry.ConfigFile.Save();
					}
					LU_EQ value;
					LU_EQ lU_EQ2 = (dictionary.TryGetValue(num.Value, out value) ? value : LU_EQ.Default);
					Logger("HandleVar", (LogLevel)1, (object)$"HASH ({num}:{lU_EQ2.Formula}) | x = {ModifyValue}");
					return lU_EQ2.CalcFormula(ModifyValue.ToString());
				}
			}
			return null;
		}

		public static object ManagingField(object Field, int LoggedSubField_Hash, Type FieldType, bool IsSetting)
		{
			if (!IL_SubField.HashChecks.TryGetValue(LoggedSubField_Hash, out var value))
			{
				return Field;
			}
			IL_Field iL_Field = value?.Field;
			IL_Fragment iL_Fragment = iL_Field?.FieldTarget;
			Logger("ManagingField", (LogLevel)8, (object)"STARTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT");
			Logger("ManagingField", (LogLevel)16, (object)(IsSetting ? "Setting?" : "Getting?"));
			Logger("ManagingField", (LogLevel)1, (object)string.Format("{0} FIELD | Name: {1} | Value: {2} | Type: {3} | IsSetting: {4}", IsSetting ? "SETTING" : "GETTING", iL_Fragment?.ToString() ?? "N/A", Field, FieldType, IsSetting));
			if (!iL_Field.LiveValue)
			{
				iL_Field.LiveValue = true;
				iL_Field.OriginalValue = Field;
			}
			iL_Field.FieldValue = Field;
			object obj = (iL_Field.IsLocal ? Field : iL_Field.OriginalValue);
			value.SubFieldType = (value.SubFieldValue = value.GetSubFieldValue(obj)).GetType();
			if (!VariablesLU.TryGetValue(value, out var value2))
			{
				return Field;
			}
			Logger("ManagingField", (LogLevel)1, (object)string.Format("{0} {1}", iL_Fragment, IsSetting ? "SET" : "GET"));
			bool flag = false;
			object obj2 = obj;
			Logger("ManagingField", (LogLevel)1, (object)$"Pre-Value: {obj2.Val()}:({value.SubFieldType}) | {Field} ({Field.GetType()})");
			foreach (JsonVarLU item in value2)
			{
				Logger("ManagingField", (LogLevel)1, (object)string.Format("InList: {0}.{1} | {2} | {3}:{4}", item.CategoryName, item.VariableName, item.WaitFor.Count, item.SearchForKey?.Field?.FieldTarget?.ToString() ?? "N/A", item.SearchForValue?.Field?.FieldTarget?.ToString() ?? "N/A"));
				if (item.WaitFor.Contains(iL_Field))
				{
					item.WaitFor.Remove(iL_Field);
				}
				if (item.ValidKeys != null)
				{
					List<object> usedKeys = item.UsedKeys;
					if (usedKeys != null)
					{
						object subFieldValue = item.ValidKeys.GetSubFieldValue(item.ValidKeys.Field?.FieldValue);
						if (subFieldValue != null && !usedKeys.Contains(subFieldValue))
						{
							usedKeys.Add(subFieldValue);
							item.Entry?.ConfigFile?.Save();
						}
					}
				}
				if (item.WaitFor.Count <= 0)
				{
					item.SaveToFile();
					if (item.SearchForValue.Field.FieldTarget == iL_Field.FieldTarget && item.IsVarEnabled())
					{
						obj2 = HandleVar(item, obj2);
						flag = true;
						Logger("ManagingField", (LogLevel)1, (object)("Cur-Value: " + obj2.Val()));
					}
				}
			}
			if (!flag)
			{
				return Field;
			}
			Logger("ManagingField", (LogLevel)1, (object)$"Value ({iL_Fragment}): {obj2.Val()} | {iL_Field.FieldValue.Val()} : {value.SubFieldValue.Val()}");
			Logger("ManagingField", (LogLevel)1, (object)("Post1?: " + obj2.Val()));
			obj2 = obj2.ToString();
			if (value.SubFieldType == typeof(int))
			{
				obj2 = (int.TryParse((string)obj2, out var result) ? ((object)result) : null);
			}
			else if (value.SubFieldType == typeof(float))
			{
				obj2 = (float.TryParse((string)obj2, out var result2) ? ((object)result2) : null);
			}
			else if (value.SubFieldType == typeof(double))
			{
				obj2 = (double.TryParse((string)obj2, out var result3) ? ((object)result3) : null);
			}
			Logger("ManagingField", (LogLevel)1, (object)("Post2?: " + obj2.Val()));
			Logger("ManagingField", (LogLevel)1, (object)("Post-Value: " + obj2.Val() + " | " + iL_Field.FieldValue.Val() + " : " + value.SubFieldValue.Val()));
			Logger("ManagingField", (LogLevel)8, (object)"ENDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD");
			if (IsSetting)
			{
				value.SetSubFieldValue(obj, obj2);
			}
			object obj3 = ((value.SubFieldList.Count == 0) ? obj2 : Field);
			Logger("ManagingField", (LogLevel)8, (object)("RESULT " + obj3.Val()));
			return obj3;
		}

		public static KeyValuePair<IL_SubField, List<JsonVarLU>> GetVariable(List<CodeInstruction> InstructionList, int i, string SpecificMethod)
		{
			IL_Fragment OpNameSplit = new IL_Fragment(((object)InstructionList[i]).ToString());
			foreach (KeyValuePair<IL_SubField, List<JsonVarLU>> item in VariablesLU.Where((KeyValuePair<IL_SubField, List<JsonVarLU>> x) => OpNameSplit.Match(x.Key.Field.FieldTarget) && x.Value.FirstOrDefault((JsonVarLU y) => y.SearchAt == null || y.SearchAt.FirstOrDefault((string z) => SpecificMethod.Contains(z)) != null) != null))
			{
				bool flag = true;
				IL_Field field = item.Key.Field;
				List<string> preFieldLook = field.PreFieldLook;
				List<string> postFieldLook = field.PostFieldLook;
				for (int j = 0; j < preFieldLook.Count && flag; j++)
				{
					string pattern = preFieldLook[j];
					int num = i + (j - preFieldLook.Count);
					if (!(flag = 0 <= num && num < InstructionList.Count))
					{
						break;
					}
					CodeInstruction val = InstructionList[num];
					flag = Regex.IsMatch(((object)val).ToString(), pattern) || Regex.IsMatch(val.opcode.ToString(), pattern);
				}
				if (!flag)
				{
					continue;
				}
				for (int k = 0; k < postFieldLook.Count && flag; k++)
				{
					string pattern2 = postFieldLook[k];
					int num2 = i + k + 1;
					if (!(flag = 0 <= num2 && num2 < InstructionList.Count))
					{
						break;
					}
					CodeInstruction val2 = InstructionList[num2];
					flag = Regex.IsMatch(((object)val2).ToString(), pattern2) || Regex.IsMatch(val2.opcode.ToString(), pattern2);
				}
				if (!flag)
				{
					continue;
				}
				return item;
			}
			return default(KeyValuePair<IL_SubField, List<JsonVarLU>>);
		}

		private static IEnumerable<CodeInstruction> DecorateInstructions(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			bool flag = false;
			List<CodeInstruction> list2 = instructions.ToList();
			for (int i = 0; i < list2.Count; i++)
			{
				CodeInstruction val = list2[i];
				bool flag2 = val.opcode == OpCodes.Stfld || val.opcode == OpCodes.Stsfld;
				bool flag3 = val.opcode == OpCodes.Call;
				bool flag4 = val.opcode == OpCodes.Ldc_R4;
				if (!flag2 && !flag3 && !flag4 && val.opcode != OpCodes.Ldfld && val.opcode != OpCodes.Ldsfld)
				{
					list.Add(val);
					continue;
				}
				KeyValuePair<IL_SubField, List<JsonVarLU>> variable = GetVariable(list2, i, TranspileMethodName);
				if (variable.Value == null)
				{
					list.Add(val);
					continue;
				}
				Type type = (flag4 ? val.operand.GetType() : (flag3 ? ((MethodInfo)val.operand).ReturnType : ((FieldInfo)val.operand).FieldType));
				flag = true;
				if (!flag2)
				{
					list.Add(val);
				}
				IL_Field field = variable.Key.Field;
				field.CanSet |= flag2;
				field.FieldType = type;
				list.Add(new CodeInstruction(OpCodes.Box, (object)type));
				list.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)variable.Key.GetHashCode()));
				list.Add(new CodeInstruction(OpCodes.Ldtoken, (object)type));
				list.Add(new CodeInstruction(OpCodes.Call, (object)TypeMethod));
				list.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)(flag2 ? 1 : 0)));
				list.Add(new CodeInstruction(OpCodes.Call, (object)ManageField));
				list.Add(new CodeInstruction(OpCodes.Unbox_Any, (object)type));
				if (flag2)
				{
					list.Add(val);
				}
			}
			if (flag)
			{
				MethodsChanged++;
			}
			IEnumerable<CodeInstruction> result;
			if (!flag)
			{
				result = instructions;
			}
			else
			{
				IEnumerable<CodeInstruction> enumerable = list;
				result = enumerable;
			}
			return result;
		}

		public void ApplyChanges()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			string text = Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId.ToString();
			HarmonyMethod val = new HarmonyMethod(((object)this).GetType(), "DecorateInstructions", (Type[])null);
			Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
			pluginInfos.Remove("com.sinai.unityexplorer");
			pluginInfos.Remove(HarmonyX.Id);
			Stopwatch stopwatch = Stopwatch.StartNew();
			CachedMethods Cached = JsonConvert.DeserializeObject<CachedMethods>(File.Exists(CachedMethods.Path) ? File.ReadAllText(CachedMethods.Path) : "{}");
			bool flag = true;
			foreach (JsonVarLUFile lUFile in LUFiles)
			{
				flag &= Cached.LUHashes.Contains(lUFile.Hash);
				if (!flag)
				{
					break;
				}
			}
			if (flag)
			{
				flag &= text == Cached.LU_UUID;
			}
			CachedMethods cachedMethods = new CachedMethods();
			cachedMethods.LU_UUID = text;
			cachedMethods.LUHashes = LUFiles.Select((JsonVarLUFile x) => x.Hash).ToList();
			IEnumerable<MethodInfo> first = Array.Empty<MethodInfo>();
			foreach (PluginInfo item in pluginInfos.Select((KeyValuePair<string, PluginInfo> x) => x.Value))
			{
				if (!((Object)(object)item.Instance == (Object)null))
				{
					Assembly assembly = Assembly.GetAssembly(((object)item.Instance).GetType());
					IEnumerable<MethodInfo> enumerable = ((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(assembly)).SelectMany((Func<Type, IEnumerable<MethodInfo>>)AccessTools.GetDeclaredMethods).Where(FilterUnpatchable);
					cachedMethods.Mods.TryAdd(item.Metadata.GUID, assembly.ManifestModule.ModuleVersionId.ToString());
					if (flag && Cached.Mods.TryGetValue(item.Metadata.GUID, out var value) && value == assembly.ManifestModule.ModuleVersionId.ToString())
					{
						enumerable = enumerable.Where(FilterCached);
					}
					first = first.Union(enumerable);
				}
			}
			Assembly assembly2 = Assembly.GetAssembly(typeof(Item));
			IEnumerable<MethodInfo> enumerable2 = ((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(assembly2)).SelectMany((Func<Type, IEnumerable<MethodInfo>>)AccessTools.GetDeclaredMethods).Where(FilterUnpatchable);
			first = ((!((cachedMethods.GameUUID = assembly2.ManifestModule.ModuleVersionId.ToString()) == Cached.GameUUID && flag)) ? first.Union(enumerable2) : first.Union(enumerable2.Where(FilterCached)));
			MLS.LogWarning((object)$"Attempting to patch up to {first.Count()} methods.");
			foreach (MethodInfo item2 in first)
			{
				int methodsChanged = MethodsChanged;
				try
				{
					TranspileMethodName = $"{item2.DeclaringType}::{item2.Name}";
					HarmonyX.Patch((MethodBase)item2, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
					if (MethodsChanged - methodsChanged == 1)
					{
						cachedMethods.Methods.Add($"{item2.ReturnType} {TranspileMethodName}");
					}
				}
				catch (Exception ex)
				{
					MLS.LogFatal((object)string.Format("Failed to patch {0} ({1}) with error: {2}\n{3}", item2, (MethodsChanged - methodsChanged == 1) ? "CHANGED" : "UNCHANGED", ex.Message, ex.GetBaseException()));
				}
			}
			File.WriteAllText(CachedMethods.Path, JsonConvert.SerializeObject((object)cachedMethods));
			MLS.LogMessage((object)$"Done adjusting {MethodsChanged}/{first.Count()} methods. Time: {stopwatch.Elapsed}");
			bool FilterCached(MethodInfo x)
			{
				return Cached.Methods.Contains($"{x.ReturnType} {x.DeclaringType}::{x.Name}");
			}
			static bool FilterUnpatchable(MethodInfo x)
			{
				return !x.ContainsGenericParameters && !x.IsGenericMethod && MethodBaseExtensions.HasMethodBody((MethodBase)x);
			}
		}
	}
	public class JsonVarLU
	{
		[JsonProperty("SearchAt")]
		public List<string> SearchAt;

		[JsonProperty("SearchForValue")]
		public UtilsMod.IL_SubField SearchForValue;

		[JsonProperty("SearchForKey")]
		public UtilsMod.IL_SubField SearchForKey;

		[JsonProperty("ValidKeys")]
		public UtilsMod.IL_SubField ValidKeys;

		[JsonProperty("FolderName")]
		public string FolderName;

		[JsonProperty("FileName")]
		public string FileName;

		[JsonProperty("CategoryName")]
		public string CategoryName;

		[JsonProperty("VariableName")]
		public string VariableName;

		[JsonProperty("Description")]
		public string Description;

		[JsonProperty("SectionOrder")]
		public int SectionOrder;

		[JsonProperty("SyncType")]
		public NetworkedConfigSync SyncType;

		[JsonProperty("IsVarList")]
		public bool IsVarList;

		[JsonProperty("IncludesRaw")]
		public bool? IncludesRaw;

		[JsonProperty("IncludeAccessedKeys")]
		public bool IncludeAccessedKeys;

		public ConfigEntry<object> Entry;

		public List<object> UsedKeys = new List<object>();

		public List<UtilsMod.IL_Field> WaitFor = new List<UtilsMod.IL_Field>();

		public ConfigFile VarConfigFile;

		public bool Saved = false;

		public static Dictionary<string, ConfigFile> Files = new Dictionary<string, ConfigFile>();

		public bool IsVarEnabled()
		{
			switch (VarConfigFile.ConfigEnabledVar.Value)
			{
			case LoadSettings.ApplyConfig:
				return true;
			case LoadSettings.Disabled:
				return false;
			default:
			{
				List<string> value = VarConfigFile.LoadSettingsVar.Value;
				return value.Contains(CategoryName) || value.Contains(VariableName);
			}
			}
		}

		public void SaveToFile()
		{
			if (!Saved)
			{
				Saved = true;
				UtilsMod.IL_Field iL_Field = SearchForValue?.Field;
				UtilsMod.IL_Field iL_Field2 = SearchForKey?.Field;
				Type type = SearchForKey?.SubFieldType;
				object defaultValue = SearchForValue?.GetSubFieldValue(SearchForValue.Field.OriginalValue);
				Type type2 = SearchForValue.SubFieldType;
				if (type2 == typeof(int) || type2 == typeof(float) || type2 == typeof(double))
				{
					type2 = typeof(LU_EQ);
					defaultValue = new LU_EQ();
				}
				ConfigEntrySettings configEntrySettings = new ConfigEntrySettings(null, CategoryName, VariableName)
				{
					KeyType = type,
					ValueType = type2,
					Description = Description,
					SectionOrder = SectionOrder,
					UsedKeys = UsedKeys,
					Rule = (IsVarList ? LU_Direction.DictionaryKey : LU_Direction.None),
					IncludeAccessedKeys = IncludeAccessedKeys,
					SyncType = SyncType
				};
				ConfigUtilities.TypeConverterBase converter = configEntrySettings.GetConverter();
				if (IsVarList && converter.GetDefaultValue != null)
				{
					defaultValue = converter.GetDefaultValue(type, type2);
				}
				string folderName = FolderName;
				string fileName = FileName;
				string text = Paths.BepInExRootPath + "\\LethalUtilities" + ((folderName != null) ? ("\\" + folderName) : "") + "\\" + fileName + ".cfg";
				if (!Files.TryGetValue(text, out VarConfigFile))
				{
					Files.TryAdd(text, VarConfigFile = new ConfigFile(text, saveOnInit: true, UtilsMod.Metadata));
					VarConfigFile.ConfigEnabledVar = VarConfigFile.Bind(new ConfigEntrySettings(null, "ACTIVE SETTINGS", "ConfigEnabled")
					{
						ValueType = typeof(LoadSettings),
						SectionOrder = -999,
						Rule = LU_Direction.None,
						SyncType = NetworkedConfigSync.SyncWithHost
					}, LoadSettings.OnlyLoadSettings);
					VarConfigFile.LoadSettingsVar = VarConfigFile.Bind(new ConfigEntrySettings(null, "ACTIVE SETTINGS", "LoadSettings")
					{
						ValueType = typeof(string),
						SectionOrder = -999,
						Rule = LU_Direction.DictionaryValue,
						SyncType = NetworkedConfigSync.SyncWithHost
					}, new List<string>());
				}
				Entry = VarConfigFile.Bind(configEntrySettings, defaultValue, (!IncludesRaw.GetValueOrDefault()) ? null : SearchForValue?.GetSubFieldValue(SearchForValue.Field.OriginalValue)?.ToString());
			}
		}
	}
	public class JsonVarLUSettings
	{
		[JsonProperty("Priority")]
		public int Priority;

		[JsonProperty("RolloverFolder")]
		public bool RolloverFolder;

		[JsonProperty("RolloverFile")]
		public bool RolloverFile;

		[JsonProperty("RolloverCategory")]
		public bool RolloverCategory;

		[JsonProperty("RolloverSyncType")]
		public bool RolloverSyncType;

		[JsonProperty("RolloverRaw")]
		public bool RolloverRaw;
	}
	public class JsonVarLUFile
	{
		[JsonProperty("Settings")]
		public JsonVarLUSettings Settings;

		[JsonProperty("Variables")]
		public List<JsonVarLU> Variables;

		public string Hash;
	}
	public class LU_EQ
	{
		public static LU_EQ Default = new LU_EQ();

		public string Formula;

		private static readonly List<List<string>> IDK_TableThing = new List<List<string>>(2)
		{
			new List<string>(1) { "^" },
			new List<string>(2) { "*", "/" }
		};

		public LU_EQ(string StringFormula = "1x")
		{
			Formula = StringFormula;
			base..ctor();
		}

		public string CalcFormula(string Value)
		{
			List<string> list = Convert(Formula);
			int num = 0;
			while (true)
			{
				num++;
				string s = ((num > 1) ? list.ElementAtOrDefault(num - 2) : null);
				string s2 = ((num > 0) ? list.ElementAtOrDefault(num - 1) : null);
				string text = list.ElementAtOrDefault(num);
				UtilsMod.Logger("LU_EQ", (LogLevel)4, (object)string.Join(" ", list));
				if (text == null)
				{
					break;
				}
				float.TryParse(s, out var result);
				float.TryParse(s2, out var result2);
				switch (text)
				{
				case "+":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = (result + result2).ToString();
					break;
				case "-":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = (result - result2).ToString();
					break;
				case "*":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = (result * result2).ToString();
					break;
				case "/":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = (result / result2).ToString();
					break;
				case "^":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = MathF.Pow(result, result2).ToString();
					break;
				case "%":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = (result % result2).ToString();
					break;
				case ">":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = ((result > result2) ? "1" : "0");
					break;
				case "<":
					list.RemoveAt(num--);
					list.RemoveAt(num--);
					list[num] = ((result < result2) ? "1" : "0");
					break;
				case "x":
					list[num] = Value;
					break;
				}
			}
			return list.FirstOrDefault();
		}

		private static void IDK(List<object> Parent)
		{
			foreach (List<object> item3 in Parent.Where((object ObjectTesting) => ObjectTesting is List<object>).Cast<List<object>>())
			{
				IDK(item3);
				foreach (List<string> item4 in IDK_TableThing)
				{
					int num = 0;
					while (true)
					{
						object item = item3[num];
						num++;
						if (num >= item3.Count)
						{
							break;
						}
						object obj = item3[num];
						if (item4.Contains(obj.ToString()))
						{
							item3.RemoveAt(num);
							object item2 = item3[num];
							item3.RemoveAt(num);
							item3[--num] = new List<object> { item, obj, item2 };
						}
					}
				}
			}
		}

		private static void IDK2(List<string> Stack, List<object> Parent)
		{
			bool flag = false;
			for (int i = 0; i < Parent.Count; i += 2)
			{
				object obj = Parent[i];
				if (!flag)
				{
					if (obj is List<object>)
					{
						List<string> list = new List<string>();
						IDK2(list, obj as List<object>);
						foreach (string item in list)
						{
							Stack.Add(item);
						}
					}
					else
					{
						Stack.Add(obj.ToString());
					}
					flag = true;
				}
				object obj2 = Parent.ElementAtOrDefault(i + 1);
				object obj3 = Parent.ElementAtOrDefault(i + 2);
				if (obj2 == null)
				{
					continue;
				}
				if (obj3 is List<object>)
				{
					List<string> list2 = new List<string>();
					IDK2(list2, obj3 as List<object>);
					foreach (string item2 in list2)
					{
						Stack.Add(item2);
					}
				}
				else
				{
					Stack.Add(obj3.ToString());
				}
				Stack.Add(obj2.ToString());
			}
		}

		public static List<string> Convert(string Value)
		{
			UtilsMod.Logger("LU_EQ", (LogLevel)2, (object)("LU_EQ-Convert: " + Value));
			Value = Regex.Replace(Value, "\\s", "");
			Value = Regex.Replace(Value, "([\\)])([\\(])", "$1*$2");
			Value = Regex.Replace(Value, "([^\\+\\-\\*\\/\\^][\\(\\)])(\\d*x)", "$1*$2");
			Value = Regex.Replace(Value, "(\\d*x)([\\(\\)][^\\+\\-\\*\\/\\^])", "$1*$2");
			Value = Regex.Replace(Value, "(\\d+)(x)", "$1*$2");
			Value = Regex.Replace(Value, "(x)(\\d+)", "$1*$2");
			UtilsMod.Logger("LU_EQ", (LogLevel)2, (object)("LU_EQ-Convert: " + Value));
			List<string> list = new List<string>();
			List<object> list2 = new List<object>();
			Match match = Regex.Match(Value, "(\\-?[\\dx\\.]+)", RegexOptions.Multiline);
			Match match2 = Regex.Match(Value, "([\\+\\-\\*\\/\\^\\%])(\\-?[\\dx\\.]+)", RegexOptions.Multiline);
			Match match3 = match;
			for (int i = 0; i < Value.Length; i++)
			{
				char c = Value[i];
				switch (c)
				{
				case '(':
				{
					List<object> list3 = new List<object> { list2 };
					list2.Add(list3);
					list2 = list3;
					continue;
				}
				case ')':
				{
					List<object> list4 = list2;
					list2 = (List<object>)list4[0];
					list4.RemoveAt(0);
					if (list4.Count == 1)
					{
						List<object> list5 = list2;
						list5[list5.Count - 1] = list4[0];
					}
					continue;
				}
				}
				string text = match3.Groups.ElementAtOrDefault<Group>(1)?.Value;
				string text2 = match3.Groups.ElementAtOrDefault<Group>(2)?.Value;
				int index = match3.Index;
				int num = index + match3.Length - 1;
				if (text != null && i == index)
				{
					i = num;
					list2.Add(text);
					if (text2 != null)
					{
						list2.Add(text2);
					}
					match2 = ((match3 == match) ? match2 : match2.NextMatch());
					match3 = match2;
				}
				else
				{
					list2.Add(c);
				}
			}
			IDK(new List<object>(1) { list2 });
			IDK2(list, list2);
			return list;
		}
	}
}
namespace LethalUtilities.Preloader
{
	internal class Plugin
	{
	}
}
namespace LethalUtilities.Configuration
{
	public enum LU_Direction
	{
		None,
		DictionaryKey,
		DictionaryValue
	}
	public enum NetworkedConfigSync
	{
		Unspecified,
		HostOnly,
		ClientOnly,
		SyncWithHost
	}
	public enum LoadSettings
	{
		ApplyConfig,
		OnlyLoadSettings,
		Disabled
	}
	public class ConfigUtilities
	{
		public enum TypeConverterEnum
		{
			Unknown,
			Variable,
			List,
			Dictionary
		}

		public class TypeConverterBase
		{
			public Type KeyType;

			public Type ValueType;

			public Func<object, Type, Type, string> ConvertToString;

			public Func<string, Type, Type, object> ConvertToObject;

			public Func<object, object> ConvertToHash;

			public Func<Type, Type, object> GetDefaultValue;

			public TypeConverterEnum TypeEnum = TypeConverterEnum.Unknown;
		}

		public class DictTypeConverter<KeyT, ValueT> : TypeConverterBase
		{
			public Func<object, Type, Type, string> ConvertToString_Default = delegate(object input, Type keyType, Type valueType)
			{
				Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
				foreach (KeyValuePair<KeyT, ValueT> item in input as Dictionary<KeyT, ValueT>)
				{
					dictionary2.TryAdd(TomlTypeConverter.ConvertToString((object)item.Key, keyType), TomlTypeConverter.ConvertToString((object)item.Value, valueType));
				}
				return JsonConvert.SerializeObject((object)dictionary2);
			};

			public Func<string, Type, Type, object> ConvertToObject_Default = delegate(string input, Type keyType, Type valueType)
			{
				Dictionary<KeyT, ValueT> dictionary = new Dictionary<KeyT, ValueT>();
				foreach (KeyValuePair<string, string> item2 in JsonConvert.DeserializeObject<Dictionary<string, string>>(input))
				{
					dictionary.TryAdd((KeyT)TomlTypeConverter.ConvertToValue(item2.Key, keyType), (ValueT)TomlTypeConverter.ConvertToValue(item2.Value, valueType));
				}
				return dictionary;
			};

			public Func<object, object> ConvertToHash_Default = (object input) => ((Dictionary<KeyT, ValueT>)input).ToDictionary((KeyValuePair<KeyT, ValueT> x) => x.Key.GetHashCode(), (KeyValuePair<KeyT, ValueT> x) => x.Value);

			public ValueT GetValueFromKey(Dictionary<KeyT, ValueT> Dict, KeyT Key)
			{
				return Dict.GetValueOrDefault(Key);
			}

			public ValueT GetValueFromKey(object Dict, KeyT Key)
			{
				return GetValueFromKey((Dictionary<KeyT, ValueT>)Dict, Key);
			}

			public DictTypeConverter(Func<object, Type, Type, string> ConvertToString = null, Func<string, Type, Type, object> ConvertToObject = null, Func<Type, Type, object> GetDefaultValue = null)
			{
				KeyType = typeof(KeyT);
				ValueType = typeof(ValueT);
				base.ConvertToString = ConvertToString ?? ConvertToString_Default;
				base.ConvertToObject = ConvertToObject ?? ConvertToObject_Default;
				base.GetDefaultValue = GetDefaultValue;
				ConvertToHash = ConvertToHash_Default;
				TypeEnum = TypeConverterEnum.Dictionary;
			}
		}

		public class ListTypeConverter<ValueT> : TypeConverterBase
		{
			public Func<object, Type, Type, string> ConvertToString_Default = (object input, Type keyType, Type valueType) => JsonConvert.SerializeObject((object)(input as List<ValueT>).Select((ValueT E) => TomlTypeConverter.ConvertToString((object)E, valueType)));

			public Func<string, Type, Type, object> ConvertToObject_Default = (string input, Type keyType, Type valueType) => from E in JsonConvert.DeserializeObject<List<string>>(input)
				select (ValueT)TomlTypeConverter.ConvertToValue(E, valueType);

			public ListTypeConverter(Func<object, Type, Type, string> ConvertToString = null, Func<string, Type, Type, object> ConvertToObject = null, Func<Type, Type, object> GetDefaultValue = null)
			{
				ValueType = typeof(ValueT);
				base.ConvertToString = ConvertToString ?? ConvertToString_Default;
				base.ConvertToObject = ConvertToObject ?? ConvertToObject_Default;
				base.GetDefaultValue = GetDefaultValue;
				TypeEnum = TypeConverterEnum.List;
			}
		}

		public class TypeConverter<T> : TypeConverterBase
		{
			public Func<object, Type, Type, string> ConvertToString_Default = (object input, Type keyType, Type valueType) => TomlTypeConverter.ConvertToString(input, keyType);

			public Func<string, Type, Type, object> ConvertToObject_Default = (string input, Type keyType, Type valueType) => (T)TomlTypeConverter.ConvertToValue(input, keyType);

			public TypeConverter(Func<object, Type, Type, string> ConvertToString = null, Func<string, Type, Type, object> ConvertToObject = null, Func<Type, Type, object> GetDefaultValue = null)
			{
				KeyType = typeof(T);
				base.ConvertToString = ConvertToString ?? ConvertToString_Default;
				base.ConvertToObject = ConvertToObject ?? ConvertToObject_Default;
				base.GetDefaultValue = GetDefaultValue;
				TypeEnum = TypeConverterEnum.Variable;
			}
		}

		public static bool AddedTypes = false;

		public static List<TypeConverterBase> CustomDictTypeConverters = new List<TypeConverterBase>(9)
		{
			new DictTypeConverter<Enum, LU_EQ>(delegate(object input, Type keyType, Type valueType)
			{
				Dictionary<string, string> dictionary10 = new Dictionary<string, string>();
				foreach (KeyValuePair<Enum, LU_EQ> item in input as Dictionary<Enum, LU_EQ>)
				{
					dictionary10.TryAdd(item.Key.ToString(), item.Value.Formula);
				}
				return JsonConvert.SerializeObject((object)dictionary10);
			}, delegate(string input, Type keyType, Type valueType)
			{
				Dictionary<Enum, LU_EQ> dictionary9 = new Dictionary<Enum, LU_EQ>();
				foreach (KeyValuePair<string, string> item2 in JsonConvert.DeserializeObject<Dictionary<string, string>>(input))
				{
					if (Enum.TryParse(keyType, item2.Key, ignoreCase: true, out object result12))
					{
						dictionary9.TryAdd((Enum)result12, new LU_EQ(item2.Value));
					}
				}
				return dictionary9;
			}, delegate(Type keyType, Type valueType)
			{
				Dictionary<Enum, LU_EQ> dictionary8 = new Dictionary<Enum, LU_EQ>();
				foreach (Enum value2 in Enum.GetValues(keyType))
				{
					dictionary8.Add(value2, new LU_EQ());
				}
				return dictionary8;
			}),
			new DictTypeConverter<string, LU_EQ>(delegate(object input, Type keyType, Type valueType)
			{
				Dictionary<string, string> dictionary7 = new Dictionary<string, string>();
				foreach (KeyValuePair<string, LU_EQ> item3 in input as Dictionary<string, LU_EQ>)
				{
					dictionary7.TryAdd(item3.Key, item3.Value?.Formula);
				}
				return JsonConvert.SerializeObject((object)dictionary7);
			}, delegate(string input, Type keyType, Type valueType)
			{
				Dictionary<string, LU_EQ> dictionary6 = new Dictionary<string, LU_EQ>();
				foreach (KeyValuePair<string, string> item4 in JsonConvert.DeserializeObject<Dictionary<string, string>>(input))
				{
					dictionary6.TryAdd(item4.Key, new LU_EQ(item4.Value));
				}
				return dictionary6;
			}, (Type keyType, Type valueType) => new Dictionary<string, LU_EQ>()),
			new DictTypeConverter<string, List<string>>(),
			new DictTypeConverter<string, string>(null, null, (Type keyType, Type valueType) => new Dictionary<string, LU_EQ>()),
			new ListTypeConverter<string>((object input, Type keyType, Type valueType) => JsonConvert.SerializeObject((object)(input as List<string>)), (string input, Type keyType, Type valueType) => JsonConvert.DeserializeObject<List<string>>(input), (Type keyType, Type valueType) => new List<string>()),
			new TypeConverter<Enum>((object input, Type keyType, Type valueType) => input.ToString(), (string input, Type keyType, Type valueType) => Enum.TryParse(valueType, input, out object result11) ? result11 : null),
			new TypeConverter<string>(),
			new TypeConverter<bool>((object input, Type keyType, Type valueType) => input.ToString(), (string input, Type keyType, Type valueType) => bool.TryParse(input, out var result10) ? ((object)result10) : null, (Type keyType, Type valueType) => null),
			new TypeConverter<LU_EQ>((object input, Type keyType, Type valueType) => ((LU_EQ)input).Formula, (string input, Type keyType, Type valueType) => new LU_EQ(input), (Type keyType, Type valueType) => new LU_EQ())
		};

		public static readonly Dictionary<Type, TypeConverter> CustomTypeConverters = new Dictionary<Type, TypeConverter>
		{
			[typeof(Dictionary<string, List<string>>)] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(input),
				ConvertToString = (object input, Type type) => JsonConvert.SerializeObject(input)
			},
			[typeof(Dictionary<string, string>)] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => JsonConvert.DeserializeObject<Dictionary<string, string>>(input),
				ConvertToString = (object input, Type type) => JsonConvert.SerializeObject(input)
			},
			[typeof(List<string>)] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => JsonConvert.DeserializeObject<List<string>>(input),
				ConvertToString = (object input, Type type) => JsonConvert.SerializeObject(input)
			},
			[typeof(LU_EQ)] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => new LU_EQ(input),
				ConvertToString = (object input, Type type) => ((LU_EQ)input).Formula
			},
			[typeof(AnimationCurve)] = new TypeConverter
			{
				ConvertToObject = delegate(string input, Type type)
				{
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					//IL_001b: Expected O, but got Unknown
					//IL_0047: Unknown result type (might be due to invalid IL or missing references)
					//IL_004d: Expected O, but got Unknown
					//IL_031d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0323: Expected O, but got Unknown
					//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
					//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
					//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
					//IL_0300: Unknown result type (might be due to invalid IL or missing references)
					if (type != typeof(AnimationCurve))
					{
						return (object)new AnimationCurve();
					}
					string[] array4 = Regex.Replace(input, "[\\s%()%[\\]]+", "").Split(',');
					if (string.IsNullOrEmpty(array4[0]))
					{
						return (object)new AnimationCurve();
					}
					Keyframe[] array5 = (Keyframe[])(object)new Keyframe[array4.Length];
					Keyframe val11 = default(Keyframe);
					for (int l = 0; l < array5.Length; l++)
					{
						string[] array6 = array4[l].Split(';');
						string[] array7 = ((array6 != null && array6.Length >= 1) ? ((array6 != null) ? array6[0]?.Split(':') : null) : null);
						string[] array8 = ((array6 != null && array6.Length >= 2) ? ((array6 != null) ? array6[1]?.Split('|') : null) : null);
						string[] array9 = ((array6 != null && array6.Length >= 3) ? ((array6 != null) ? array6[2]?.Split(':') : null) : null);
						string[] array10 = ((array9 != null && array9.Length >= 2) ? ((array9 != null) ? array9[1] : null) : ((array9 != null) ? array9[0] : null))?.Split('|');
						float result3 = (float.TryParse(((array7 != null) ? array7[0] : null) ?? "0", NumberStyles.Float, new CultureInfo("en-US"), out result3) ? result3 : 0f);
						float result4 = (float.TryParse((array7 != null && array7.Length >= 2) ? ((array7 != null) ? array7[1] : null) : "0", NumberStyles.Float, new CultureInfo("en-US"), out result4) ? result4 : 0f);
						float result5 = (float.TryParse(((array8 != null) ? array8[0] : null) ?? "0", NumberStyles.Float, new CultureInfo("en-US"), out result5) ? result5 : 0f);
						float result6 = (float.TryParse((array8 != null && array8.Length >= 2) ? ((array8 != null) ? array8[1] : null) : (((array8 != null) ? array8[0] : null) ?? "0"), NumberStyles.Float, new CultureInfo("en-US"), out result6) ? result6 : 0f);
						float result7 = (float.TryParse(((array10 != null) ? array10[0] : null) ?? "0", NumberStyles.Float, new CultureInfo("en-US"), out result7) ? result7 : 0f);
						float result8 = (float.TryParse((array10 != null && array10.Length >= 2) ? ((array10 != null) ? array10[1] : null) : (((array10 != null) ? array10[0] : null) ?? "0"), NumberStyles.Float, new CultureInfo("en-US"), out result8) ? result8 : 0f);
						int result9 = (int.TryParse(((array9 != null) ? array9[0] : null) ?? "0", NumberStyles.Float, new CultureInfo("en-US"), out result9) ? result9 : 0);
						((Keyframe)(ref val11))..ctor(result3, result4, result5, result6, result7, result8);
						((Keyframe)(ref val11)).weightedMode = (WeightedMode)result9;
						Keyframe val12 = val11;
						array5[l] = val12;
					}
					return (object)new AnimationCurve(array5);
				},
				ConvertToString = delegate(object input, Type type)
				{
					//IL_0021: Unknown result type (might be due to invalid IL or missing references)
					//IL_0089: Unknown result type (might be due to invalid IL or missing references)
					//IL_008e: Unknown result type (might be due to invalid IL or missing references)
					//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d0: Expected I4, but got Unknown
					if (type != typeof(AnimationCurve))
					{
						return "";
					}
					Keyframe[] keys = ((AnimationCurve)input).keys;
					if (keys.Length == 0)
					{
						return "";
					}
					if (keys.Length == 1)
					{
						return ((Keyframe)(ref keys[0])).value.ToString(new CultureInfo("en-US"));
					}
					StringBuilder stringBuilder = new StringBuilder();
					Keyframe[] array3 = keys;
					for (int k = 0; k < array3.Length; k++)
					{
						Keyframe val10 = array3[k];
						float time = ((Keyframe)(ref val10)).time;
						float value = ((Keyframe)(ref val10)).value;
						float inTangent = ((Keyframe)(ref val10)).inTangent;
						float outTangent = ((Keyframe)(ref val10)).outTangent;
						float inWeight = ((Keyframe)(ref val10)).inWeight;
						float outWeight = ((Keyframe)(ref val10)).outWeight;
						int num2 = (int)((Keyframe)(ref val10)).weightedMode;
						stringBuilder.Append(time.ToString(new CultureInfo("en-US")) + ":" + value.ToString(new CultureInfo("en-US")));
						if (inTangent != 0f || outTangent != 0f)
						{
							stringBuilder.Append((inTangent == outTangent) ? $";({inTangent})" : $";({inTangent}|{outTangent})");
							if (inWeight != 0f || outWeight != 0f)
							{
								stringBuilder.Append((num2 != 0) ? (";" + num2.ToString(new CultureInfo("en-US")) + ":") : ";");
								stringBuilder.Append((inWeight == outWeight) ? ("[" + inWeight.ToString(new CultureInfo("en-US")) + "]") : ("[" + inWeight.ToString(new CultureInfo("en-US")) + "|" + outWeight.ToString(new CultureInfo("en-US")) + "]"));
							}
							else if (num2 != 0)
							{
								stringBuilder.Append(";" + num2.ToString(new CultureInfo("en-US")));
							}
						}
						stringBuilder.Append(", ");
					}
					return stringBuilder.ToString(0, Math.Max(0, stringBuilder.Length - 2));
				}
			},
			[typeof(string[])] = SimpleConverter(new string[0]),
			[typeof(Battery)] = SimpleConverter<Battery>(new Battery(false, 1f)),
			[typeof(IntWithRarity[])] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => ((IEnumerable<KeyValuePair<int, int>>)JsonConvert.DeserializeObject<Dictionary<int, int>>(input)).Select((Func<KeyValuePair<int, int>, IntWithRarity>)((KeyValuePair<int, int> x) => new IntWithRarity
				{
					id = x.Key,
					rarity = x.Value
				})).ToArray(),
				ConvertToString = (object input, Type type) => JsonConvert.SerializeObject((object)((IntWithRarity[])input).Select((IntWithRarity x) => new KeyValuePair<int, int>(x.id, x.rarity)).ToDictionary((KeyValuePair<int, int> x) => x.Key, (KeyValuePair<int, int> x) => x.Value))
			},
			[typeof(CompatibleNoun[])] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => ((IEnumerable<KeyValuePair<string, string>>)JsonConvert.DeserializeObject<Dictionary<string, string>>(input)).Select((Func<KeyValuePair<string, string>, CompatibleNoun>)((KeyValuePair<string, string> PAIR) => new CompatibleNoun
				{
					noun = ((IEnumerable<TerminalKeyword>)Resources.FindObjectsOfTypeAll<TerminalKeyword>()).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword X) => MakeFileNameSafe(((Object)X).name) == PAIR.Key)),
					result = ((IEnumerable<TerminalNode>)Resources.FindObjectsOfTypeAll<TerminalNode>()).FirstOrDefault((Func<TerminalNode, bool>)((TerminalNode X) => MakeFileNameSafe(((Object)X).name) == PAIR.Value))
				})).ToArray(),
				ConvertToString = delegate(object input, Type type)
				{
					Dictionary<string, string> NewOptions = new Dictionary<string, string>();
					IEnumerable<CompatibleNoun> enumerable = ((CompatibleNoun[])input).Where((CompatibleNoun x) => (Object)(object)x.noun != (Object)null && !NewOptions.ContainsKey(((Object)x.noun).name));
					foreach (CompatibleNoun item5 in enumerable)
					{
						Dictionary<string, string> dictionary5 = NewOptions;
						string name = ((Object)item5.noun).name;
						TerminalNode result2 = item5.result;
						dictionary5.Add(name, ((result2 != null) ? ((Object)result2).name : null) ?? "");
					}
					return JsonConvert.SerializeObject((object)NewOptions);
				}
			},
			[typeof(TerminalKeyword)] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => ((IEnumerable<TerminalKeyword>)Resources.FindObjectsOfTypeAll<TerminalKeyword>()).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword X) => MakeFileNameSafe(((Object)X).name) == input)),
				ConvertToString = (object input, Type type) => ((Object)(TerminalKeyword)input).name
			},
			[typeof(TerminalNode)] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => ((IEnumerable<TerminalNode>)Resources.FindObjectsOfTypeAll<TerminalNode>()).FirstOrDefault((Func<TerminalNode, bool>)((TerminalNode X) => MakeFileNameSafe(((Object)X).name) == input)),
				ConvertToString = (object input, Type type) => ((Object)(TerminalNode)input).name
			},
			[typeof(SpawnableEnemyWithRarity[])] = new TypeConverter
			{
				ConvertToObject = delegate(string input, Type type)
				{
					//IL_005d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0062: Unknown result type (might be due to invalid IL or missing references)
					//IL_0069: Unknown result type (might be due to invalid IL or missing references)
					//IL_007f: Expected O, but got Unknown
					List<SpawnableEnemyWithRarity> list5 = new List<SpawnableEnemyWithRarity>();
					foreach (KeyValuePair<string, int> PAIR5 in JsonConvert.DeserializeObject<Dictionary<string, int>>(input))
					{
						EnemyType val9 = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType X) => MakeFileNameSafe(X.enemyName) == PAIR5.Key));
						if (!((Object)(object)val9 == (Object)null) && !((Object)(object)val9 == (Object)null))
						{
							list5.Add(new SpawnableEnemyWithRarity
							{
								enemyType = val9,
								rarity = PAIR5.Value
							});
						}
					}
					return list5.ToArray();
				},
				ConvertToString = delegate(object input, Type type)
				{
					Dictionary<string, int> dictionary4 = new Dictionary<string, int>();
					SpawnableEnemyWithRarity[] array2 = (SpawnableEnemyWithRarity[])input;
					foreach (SpawnableEnemyWithRarity val8 in array2)
					{
						string text4 = val8.enemyType?.enemyName;
						if (text4 != null && text4 != null)
						{
							if (dictionary4.ContainsKey(text4))
							{
								dictionary4[text4] += val8.rarity;
							}
							else
							{
								dictionary4.Add(text4, val8.rarity);
							}
						}
					}
					return JsonConvert.SerializeObject((object)dictionary4);
				}
			},
			[typeof(SpawnableItemWithRarity[])] = new TypeConverter
			{
				ConvertToObject = delegate(string input, Type type)
				{
					//IL_005d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0062: Unknown result type (might be due to invalid IL or missing references)
					//IL_0069: Unknown result type (might be due to invalid IL or missing references)
					//IL_007f: Expected O, but got Unknown
					List<SpawnableItemWithRarity> list4 = new List<SpawnableItemWithRarity>();
					foreach (KeyValuePair<string, int> PAIR4 in JsonConvert.DeserializeObject<Dictionary<string, int>>(input))
					{
						Item val7 = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item X) => MakeFileNameSafe(X.itemName) == PAIR4.Key));
						if (!((Object)(object)val7 == (Object)null) && !((Object)(object)val7 == (Object)null))
						{
							list4.Add(new SpawnableItemWithRarity
							{
								spawnableItem = val7,
								rarity = PAIR4.Value
							});
						}
					}
					return list4.ToArray();
				},
				ConvertToString = delegate(object input, Type type)
				{
					Dictionary<string, int> dictionary3 = new Dictionary<string, int>();
					SpawnableItemWithRarity[] array = (SpawnableItemWithRarity[])input;
					foreach (SpawnableItemWithRarity val6 in array)
					{
						string text3 = val6.spawnableItem?.itemName;
						if (text3 != null && text3 != null)
						{
							if (dictionary3.ContainsKey(text3))
							{
								dictionary3[text3] += val6.rarity;
							}
							else
							{
								dictionary3.Add(text3, val6.rarity);
							}
						}
					}
					return JsonConvert.SerializeObject((object)dictionary3);
				}
			},
			[typeof(List<SpawnableEnemyWithRarity>)] = new TypeConverter
			{
				ConvertToObject = delegate(string input, Type type)
				{
					//IL_005d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0062: Unknown result type (might be due to invalid IL or missing references)
					//IL_0069: Unknown result type (might be due to invalid IL or missing references)
					//IL_007f: Expected O, but got Unknown
					List<SpawnableEnemyWithRarity> list3 = new List<SpawnableEnemyWithRarity>();
					foreach (KeyValuePair<string, int> PAIR3 in JsonConvert.DeserializeObject<Dictionary<string, int>>(input))
					{
						EnemyType val5 = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType X) => MakeFileNameSafe(X.enemyName) == PAIR3.Key));
						if (!((Object)(object)val5 == (Object)null) && !((Object)(object)val5 == (Object)null))
						{
							list3.Add(new SpawnableEnemyWithRarity
							{
								enemyType = val5,
								rarity = PAIR3.Value
							});
						}
					}
					return list3;
				},
				ConvertToString = delegate(object input, Type type)
				{
					Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
					foreach (SpawnableEnemyWithRarity item6 in (List<SpawnableEnemyWithRarity>)input)
					{
						string text2 = item6.enemyType?.enemyName;
						if (text2 != null && text2 != null)
						{
							if (dictionary2.ContainsKey(text2))
							{
								dictionary2[text2] += item6.rarity;
							}
							else
							{
								dictionary2.Add(text2, item6.rarity);
							}
						}
					}
					return JsonConvert.SerializeObject((object)dictionary2);
				}
			},
			[typeof(List<SpawnableItemWithRarity>)] = new TypeConverter
			{
				ConvertToObject = delegate(string input, Type type)
				{
					//IL_005d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0062: Unknown result type (might be due to invalid IL or missing references)
					//IL_0069: Unknown result type (might be due to invalid IL or missing references)
					//IL_007f: Expected O, but got Unknown
					List<SpawnableItemWithRarity> list2 = new List<SpawnableItemWithRarity>();
					foreach (KeyValuePair<string, int> PAIR2 in JsonConvert.DeserializeObject<Dictionary<string, int>>(input))
					{
						Item val4 = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item X) => MakeFileNameSafe(X.itemName) == PAIR2.Key));
						if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4 == (Object)null))
						{
							list2.Add(new SpawnableItemWithRarity
							{
								spawnableItem = val4,
								rarity = PAIR2.Value
							});
						}
					}
					return list2;
				},
				ConvertToString = delegate(object input, Type type)
				{
					Dictionary<string, int> dictionary = new Dictionary<string, int>();
					foreach (SpawnableItemWithRarity item7 in (List<SpawnableItemWithRarity>)input)
					{
						string text = item7.spawnableItem?.itemName;
						if (text != null && text != null)
						{
							if (dictionary.ContainsKey(text))
							{
								dictionary[text] += item7.rarity;
							}
							else
							{
								dictionary.Add(text, item7.rarity);
							}
						}
					}
					return JsonConvert.SerializeObject((object)dictionary);
				}
			},
			[typeof(EnemyType)] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType X) => MakeFileNameSafe(X.enemyName) == input)),
				ConvertToString = (object input, Type type) => ((EnemyType)input).enemyName
			},
			[typeof(List<ItemGroup>)] = new TypeConverter
			{
				ConvertToObject = delegate(string input, Type type)
				{
					List<ItemGroup> list = new List<ItemGroup>();
					foreach (string item8 in JsonConvert.DeserializeObject<List<string>>(input))
					{
						ItemGroup val3 = ScriptableObject.CreateInstance<ItemGroup>();
						((Object)val3).name = item8;
						list.Add(val3);
					}
					return list;
				},
				ConvertToString = (object input, Type type) => JsonConvert.SerializeObject((object)((List<ItemGroup>)input).Select((ItemGroup x) => ((Object)x).name).ToList())
			},
			[typeof(RandomWeatherWithVariables[])] = new TypeConverter
			{
				ConvertToObject = (string input, Type type) => JsonConvert.DeserializeObject<Dictionary<string, List<int>>>(input).Select(delegate(KeyValuePair<string, List<int>> PAIR)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					//IL_001a: Unknown result type (might be due to invalid IL or missing references)
					//IL_006a: Expected O, but got I4
					? val = new RandomWeatherWithVariables();
					? val2 = val;
					int num;
					if (!Enum.TryParse<LevelWeatherType>(PAIR.Key, out LevelWeatherType result))
					{
						num = -1;
						val = num;
						num = (int)val;
					}
					else
					{
						val = result;
						num = (int)val;
					}
					((RandomWeatherWithVariables)val2).weatherType = (LevelWeatherType)val;
					((RandomWeatherWithVariables)num).weatherVariable = ((PAIR.Value.Count > 0) ? PAIR.Value[0] : 0);
					((RandomWeatherWithVariables)num).weatherVariable2 = ((PAIR.Value.Count > 1) ? PAIR.Value[1] : 0);
					return (RandomWeatherWithVariables)(object)num;
				}).ToArray(),
				ConvertToString = (object input, Type type) => JsonConvert.SerializeObject((object)((RandomWeatherWithVariables[])input).Select((RandomWeatherWithVariables x) => new KeyValuePair<string, List<int>>(((object)(LevelWeatherType)(ref x.weatherType)).ToString(), new List<int>(2) { x.weatherVariable, x.weatherVariable2 })).ToDictionary((KeyValuePair<string, List<int>> x) => x.Key, (KeyValuePair<string, List<int>> x) => x.Value))
			}
		};

		public static bool AddAllTypes()
		{
			if (AddedTypes)
			{
				return false;
			}
			AddedTypes = true;
			foreach (KeyValuePair<Type, TypeConverter> customTypeConverter in CustomTypeConverters)
			{
				TomlTypeConverter.AddConverter(customTypeConverter.Key, customTypeConverter.Value);
			}
			return true;
		}

		public static string MakeFileNameSafe(string FileName)
		{
			return Regex.Replace(FileName, "[\\/:*?\"<>|]", "");
		}

		public static TypeConverter SimpleConverter<T>(T Default)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			return new TypeConverter
			{
				ConvertToObject = (string input, Type type) => (type != typeof(T)) ? Default : JsonConvert.DeserializeObject<T>(input),
				ConvertToString = (object input, Type type) => JsonConvert.SerializeObject((type != typeof(T)) ? ((object)Default) : input)
			};
		}
	}
	public sealed class SettingChangedEventArgs : EventArgs
	{
		public ConfigEntryBase ChangedSetting { get; }

		public SettingChangedEventArgs(ConfigEntryBase changedSetting)
		{
			ChangedSetting = changedSetting;
			base..ctor();
		}
	}
	public class ConfigEntrySettings
	{
		private static readonly char[] _invalidConfigChars = new char[8] { '=', '\n', '\t', '\\', '"', '\'', '[', ']' };

		public ConfigEntryBase Config;

		public int SectionOrder;

		private readonly string _StringValue;

		public string Description;

		public NetworkedConfigSync SyncType;

		public Type KeyType;

		public Type ValueType;

		public List<object> UsedKeys;

		public List<string> AcceptableKeys;

		public AcceptableValueBase AcceptableValues;

		public bool IncludeAccessedKeys;

		public LU_Direction Rule;

		public string Section { get; }

		public string Key { get; }

		public string StringValue => Config?.GetSerializedValue() ?? _StringValue;

		public ConfigEntrySettings(ConfigEntryBase Config, string Section, string Key, string StringValue = null, int SectionOrder = -1)
		{
			this.Config = Config;
			this.Section = (CheckInvalidConfigChars(Section, "Section") ? Section : null);
			this.SectionOrder = SectionOrder;
			this.Key = (CheckInvalidConfigChars(Key, "Key") ? Key : null);
			_StringValue = StringValue;
			UsedKeys = new List<object>();
			AcceptableKeys = new List<string>();
			IncludeAccessedKeys = false;
			Rule = LU_Direction.None;
			base..ctor();
		}

		public ConfigUtilities.TypeConverterBase GetConverter()
		{
			foreach (ConfigUtilities.TypeConverterBase customDictTypeConverter in ConfigUtilities.CustomDictTypeConverters)
			{
				if (customDictTypeConverter.TypeEnum == ConfigUtilities.TypeConverterEnum.Variable && Rule == LU_Direction.None)
				{
					Type keyType = customDictTypeConverter.KeyType;
					if ((object)keyType != null && keyType.IsAssignableFrom(ValueType))
					{
						return customDictTypeConverter;
					}
				}
				else if (customDictTypeConverter.TypeEnum == ConfigUtilities.TypeConverterEnum.Dictionary && Rule == LU_Direction.DictionaryKey)
				{
					Type keyType2 = customDictTypeConverter.KeyType;
					if ((object)keyType2 != null && keyType2.IsAssignableFrom(KeyType))
					{
						Type valueType = customDictTypeConverter.ValueType;
						if ((object)valueType != null && valueType.IsAssignableFrom(ValueType))
						{
							return customDictTypeConverter;
						}
					}
				}
				else if (customDictTypeConverter.TypeEnum == ConfigUtilities.TypeConverterEnum.List && Rule == LU_Direction.DictionaryValue)
				{
					Type valueType2 = customDictTypeConverter.ValueType;
					if ((object)valueType2 != null && valueType2.IsAssignableFrom(ValueType))
					{
						return customDictTypeConverter;
					}
				}
			}
			return null;
		}

		private static bool CheckInvalidConfigChars(string val, string name)
		{
			if (val == null)
			{
				throw new ArgumentNullException(name);
			}
			if (val != val.Trim())
			{
				throw new ArgumentException("Cannot use whitespace characters at start or end of section and key names", name);
			}
			if (val.Any((char c) => _invalidConfigChars.Contains(c)))
			{
				throw new ArgumentException("Cannot use any of the following characters in section and key names: = \\n \\t \\ \" ' [ ]", name);
			}
			return true;
		}
	}
	public abstract class AcceptableValueBase
	{
		public Type ValueType { get; }

		protected AcceptableValueBase(Type ValueType)
		{
			this.ValueType = ValueType;
			base..ctor();
		}

		public abstract object Clamp(object value);

		public abstract bool IsValid(object value);

		public abstract string ToDescriptionString();
	}
	public class AcceptableValueList<T> : AcceptableValueBase where T : IEquatable<T>
	{
		public virtual T[] AcceptableValues { get; }

		public AcceptableValueList(params T[] AcceptableValues)
		{
			if (AcceptableValues == null)
			{
				throw new ArgumentNullException("AcceptableValues");
			}
			if (AcceptableValues.Length == 0)
			{
				throw new ArgumentException("At least one acceptable value is needed", "AcceptableValues");
			}
			this.AcceptableValues = AcceptableValues;
			base..ctor(typeof(T));
		}

		public override object Clamp(object value)
		{
			return IsValid(value) ? value : ((object)AcceptableValues[0]);
		}

		public override bool IsValid(object value)
		{
			int result;
			if (value is T)
			{
				T v = (T)value;
				result = (AcceptableValues.Any((T x) => x.Equals(v)) ? 1 : 0);
			}
			else
			{
				result = 0;
			}
			return (byte)result != 0;
		}

		public override string ToDescriptionString()
		{
			return "# Acceptable values: " + string.Join(", ", AcceptableValues.Select((T x) => x.ToString()));
		}
	}
	public class AcceptableValueRange<T> : AcceptableValueBase where T : IComparable
	{
		public virtual T MinValue { get; }

		public virtual T MaxValue { get; }

		public AcceptableValueRange(T MinValue, T MaxValue)
		{
			T val = MinValue;
			if (val == null)
			{
				throw new ArgumentNullException("MinValue");
			}
			this.MinValue = val;
			if (MaxValue == null)
			{
				throw new ArgumentNullException("MaxValue");
			}
			if (MinValue.CompareTo(MaxValue) >= 0)
			{
				throw new ArgumentNullException("MinValue has to be lower than MaxValue");
			}
			this.MaxValue = MaxValue;
			base..ctor(typeof(T));
		}

		public override object Clamp(object value)
		{
			return (MinValue.CompareTo(value) > 0) ? ((object)MinValue) : ((MaxValue.CompareTo(value) < 0) ? ((object)MaxValue) : value);
		}

		public override bool IsValid(object value)
		{
			return MinValue.CompareTo(value) <= 0 && MaxValue.CompareTo(value) >= 0;
		}

		public override string ToDescriptionString()
		{
			return $"# Acceptable value range: From {MinValue} to {MaxValue}";
		}
	}
	public abstract class ConfigEntryBase
	{
		public object DefaultValue;

		public object HashValue;

		public string RawValue;

		public ConfigFile ConfigFile { get; }

		public ConfigEntrySettings EntrySettings { get; set; }

		public abstract object BoxedValue { get; set; }

		internal ConfigEntryBase(ConfigFile configFile, ConfigEntrySettings entrySettings, object defaultValue, string rawValue = null)
		{
			entrySettings.Config = this;
			ConfigFile = configFile ?? throw new ArgumentNullException("configFile");
			EntrySettings = entrySettings ?? throw new ArgumentNullException("entrySettings");
			DefaultValue = defaultValue;
			RawValue = rawValue;
			BoxedValue = defaultValue;
		}

		public string GetSerializedValue()
		{
			return (EntrySettings.GetConverter() ?? throw new InvalidOperationException("Cannot convert from type " + ((EntrySettings.KeyType != null && EntrySettings.ValueType != null) ? $"Dictionary<{EntrySettings.KeyType}, {EntrySettings.ValueType}>" : ((EntrySettings.ValueType != null) ? $"List<{EntrySettings.ValueType}>" : $"{EntrySettings.KeyType}")))).ConvertToString(BoxedValue, EntrySettings.KeyType, EntrySettings.ValueType);
		}

		public void SetSerializedValue(string value)
		{
			try
			{
				ConfigUtilities.TypeConverterBase typeConverterBase = EntrySettings.GetConverter() ?? throw new InvalidOperationException("Cannot convert to type " + ((EntrySettings.KeyType != null && EntrySettings.ValueType != null) ? $"Dictionary<{EntrySettings.KeyType}, {EntrySettings.ValueType}>" : ((EntrySettings.ValueType != null) ? $"List<{EntrySettings.ValueType}>" : $"{EntrySettings.KeyType}")));
				BoxedValue = typeConverterBase.ConvertToObject(value, EntrySettings.KeyType, EntrySettings.ValueType);
			}
			catch (Exception ex)
			{
				UtilsMod.MLS.Log((LogLevel)4, (object)("Config value of setting \"" + EntrySettings.Section + "." + EntrySettings.Key + "\" could not be parsed and will be ignored. Reason: " + ex.Message + "; Value: " + value));
			}
		}

		protected T ClampValue<T>(T value)
		{
			return (EntrySettings.AcceptableValues != null) ? ((T)EntrySettings.AcceptableValues.Clamp(value)) : value;
		}

		protected void OnSettingChanged(object sender)
		{
			ConfigFile.OnSettingChanged(sender, this);
		}

		public string FixTypeName(Type Fix)
		{
			return (Fix == null) ? "null" : ((typeof(List<>).Name == Fix.Name) ? ("List<" + FixTypeName(Fix.GenericTypeArguments.ElementAtOrDefault(0)) + ">") : ((typeof(Dictionary<, >).Name == Fix.Name) ? ("Dictionary<" + FixTypeName(Fix.GenericTypeArguments.ElementAtOrDefault(0)) + ", " + FixTypeName(Fix.GenericTypeArguments.ElementAtOrDefault(1)) + ">") : Fix.Name));
		}

		public void WriteDescription(StreamWriter writer)
		{
			if (!string.IsNullOrEmpty(EntrySettings.Description))
			{
				writer.WriteLine("## " + EntrySettings.Description.Replace("\n", "\n## "));
			}
			writer.WriteLine("# Setting type: " + ((EntrySettings.Rule == LU_Direction.DictionaryKey) ? ("Dictionary<" + FixTypeName(EntrySettings.KeyType) + ", " + FixTypeName(EntrySettings.ValueType) + ">") : ((EntrySettings.Rule == LU_Direction.DictionaryValue) ? ("List<" + FixTypeName(EntrySettings.ValueType) + ">") : FixTypeName(EntrySettings.ValueType))));
			writer.WriteLine("# Sync type: " + EntrySettings.SyncType);
			if (RawValue != null)
			{
				writer.WriteLine("# Raw value: " + RawValue);
			}
			bool flag = EntrySettings.IncludeAccessedKeys;
			if (EntrySettings.AcceptableKeys != null && EntrySettings.AcceptableKeys.Count > 0)
			{
				writer.WriteLine("# Acceptable keys: " + string.Join(", ", EntrySettings.AcceptableKeys));
			}
			else if (EntrySettings.KeyType != null && EntrySettings.KeyType.IsEnum)
			{
				writer.WriteLine("# Acceptable keys: " + string.Join(", ", Enum.GetNames(EntrySettings.KeyType)));
			}
			else if (EntrySettings.UsedKeys != null && EntrySettings.UsedKeys.Count > 0)
			{
				flag = true;
			}
			if (flag)
			{
				writer.WriteLine("# Accessed keys: " + string.Join(", ", EntrySettings.UsedKeys));
			}
			if (EntrySettings.AcceptableValues != null)
			{
				writer.WriteLine(EntrySettings.AcceptableValues.ToDescriptionString());
			}
			else if (EntrySettings.ValueType == null || !EntrySettings.ValueType.IsEnum)
			{
				return;
			}
			writer.WriteLine("# Acceptable values: " + string.Join(", ", Enum.GetNames(EntrySettings.ValueType)));
			if (EntrySettings.ValueType.GetCustomAttributes(typeof(FlagsAttribute), inherit: true).Any())
			{
				writer.WriteLine("# Multiple values can be set at the same time by separating them with , (e.g. Debug, Warning)");
			}
		}
	}
	public sealed class ConfigEntry<T> : ConfigEntryBase
	{
		private T _typedValue;

		public T Value
		{
			get
			{
				return _typedValue;
			}
			set
			{
				if (!object.Equals(_typedValue, value = ClampValue(value)))
				{
					_typedValue = value;
					OnSettingChanged(this);
				}
			}
		}

		public override object BoxedValue
		{
			get
			{
				return Value;
			}
			set
			{
				Value = (T)value;
			}
		}

		public event EventHandler SettingChanged;

		internal ConfigEntry(ConfigFile configFile, ConfigEntrySettings entrySettings, object defaultValue, string RawValue = "")
			: base(configFile, entrySettings, defaultValue, RawValue)
		{
			configFile.SettingChanged += delegate(object sender, SettingChangedEventArgs args)
			{
				if (args.ChangedSetting == this)
				{
					this.SettingChanged?.Invoke(sender, args);
				}
			};
		}
	}
	public class ConfigFile
	{
		public ConfigEntry<LoadSettings> ConfigEnabledVar;

		public ConfigEntry<List<string>> LoadSettingsVar;

		private readonly BepInPlugin _ownerMetadata;

		private readonly object _ioLock = new object();

		protected Dictionary<string, ConfigEntryBase> Entries { get; } = new Dictionary<string, ConfigEntryBase>();


		private Dictionary<string, ConfigEntrySettings> OrphanedEntries { get; } = new Dictionary<string, ConfigEntrySettings>();


		public string ConfigFilePath { get; }

		public bool SaveOnConfigSet { get; set; } = true;


		public event EventHandler ConfigReloaded;

		public event EventHandler<SettingChangedEventArgs> SettingChanged;

		public ConfigFile(string configPath, bool saveOnInit, BepInPlugin ownerMetadata = null)
		{
			_ownerMetadata = ownerMetadata;
			if (configPath == null)
			{
				throw new ArgumentNullException("configPath");
			}
			configPath = Path.GetFullPath(configPath);
			ConfigFilePath = configPath;
			if (File.Exists(ConfigFilePath))
			{
				Reload();
			}
			else if (saveOnInit)
			{
				Save();
			}
		}

		public void Reload()
		{
			lock (_ioLock)
			{
				OrphanedEntries.Clear();
				string text = string.Empty;
				string[] array = File.ReadAllLines(ConfigFilePath);
				foreach (string text2 in array)
				{
					string text3 = text2.Trim();
					if (text3.StartsWith("#"))
					{
						continue;
					}
					if (text3.StartsWith("[") && text3.EndsWith("]"))
					{
						string text4 = text3;
						text = text4.Substring(1, text4.Length - 1 - 1);
						continue;
					}
					string[] array2 = text3.Split(new char[1] { '=' }, 2);
					if (array2.Length == 2)
					{
						string text5 = array2[0].Trim();
						string text6 = array2[1].Trim();
						string key = text + "." + text5;
						Entries.TryGetValue(key, out var value);
						if (value != null)
						{
							value.SetSerializedValue(text6);
						}
						else
						{
							OrphanedEntries[key] = new ConfigEntrySettings(null, text, text5, text6);
						}
					}
				}
			}
			OnConfigReloaded();
		}

		public void Save()
		{
			lock (_ioLock)
			{
				string directoryName = Path.GetDirectoryName(ConfigFilePath);
				if (directoryName != null)
				{
					Directory.CreateDirectory(directoryName);
				}
				using StreamWriter streamWriter = new StreamWriter(ConfigFilePath, append: false, Utility.UTF8NoBom);
				if (_ownerMetadata != null)
				{
					streamWriter.WriteLine($"## Settings file was created by plugin {_ownerMetadata.Name} v{_ownerMetadata.Version}");
					streamWriter.WriteLine("## Plugin GUID: " + _ownerMetadata.GUID);
					streamWriter.WriteLine();
				}
				foreach (IGrouping<(int, string), ConfigEntrySettings> item in from x in Entries.Select((KeyValuePair<string, ConfigEntryBase> x) => x.Value.EntrySettings).Concat(OrphanedEntries.Select((KeyValuePair<string, ConfigEntrySettings> x) => x.Value))
					group x by (x.SectionOrder, x.Section) into x
					orderby x.Key.SectionOrder == -1, x.Key.SectionOrder, x.Key.Section
					select x)
				{
					streamWriter.WriteLine("[" + item.Key.Item2 + "]");
					foreach (ConfigEntrySettings item2 in item)
					{
						streamWriter.WriteLine();
						item2.Config?.WriteDescription(streamWriter);
						streamWriter.WriteLine(item2.Key + " = " + item2.StringValue);
					}
					streamWriter.WriteLine();
				}
			}
		}

		public ConfigEntry<T> Bind<T>(ConfigEntrySettings entrySettings, T defaultValue, string RawValue = null)
		{
			lock (_ioLock)
			{
				string key = entrySettings.Section + "." + entrySettings.Key;
				if (Entries.TryGetValue(key, out var value))
				{
					return value as ConfigEntry<T>;
				}
				ConfigEntry<T> configEntry = new ConfigEntry<T>(this, entrySettings, defaultValue, RawValue);
				Entries[key] = configEntry;
				if (OrphanedEntries.TryGetValue(key, out var value2))
				{
					configEntry.SetSerializedValue(value2.StringValue);
					OrphanedEntries.Remove(key);
				}
				if (SaveOnConfigSet)
				{
					Save();
				}
				return configEntry;
			}
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string configDescription = null, int order = -1, string RawValue = "", LU_Direction Rule = LU_Direction.None, NetworkedConfigSync SyncType = NetworkedConfigSync.Unspecified)
		{
			return Bind(new ConfigEntrySettings(null, section ?? throw new ArgumentNullException("section"), key ?? throw new ArgumentNullException("key"))
			{
				ValueType = typeof(T),
				Description = configDescription,
				SectionOrder = order,
				Rule = Rule,
				SyncType = SyncType
			}, defaultValue, RawValue);
		}

		internal void OnSettingChanged(object sender, ConfigEntryBase changedEntryBase)
		{
			if (changedEntryBase == null)
			{
				throw new ArgumentNullException("changedEntryBase");
			}
			if (SaveOnConfigSet)
			{
				Save();
			}
			if (this.SettingChanged == null)
			{
				return;
			}
			SettingChangedEventArgs e = new SettingChangedEventArgs(changedEntryBase);
			foreach (EventHandler<SettingChangedEventArgs> item in this.SettingChanged.GetInvocationList().Cast<EventHandler<SettingChangedEventArgs>>())
			{
				try
				{
					item(sender, e);
				}
				catch (Exception ex)
				{
					UtilsMod.MLS.Log((LogLevel)2, (object)ex);
				}
			}
		}

		private void OnConfigReloaded()
		{
			if (this.ConfigReloaded == null)
			{
				return;
			}
			foreach (EventHandler item in this.ConfigReloaded.GetInvocationList().Cast<EventHandler>())
			{
				try
				{
					item(this, EventArgs.Empty);
				}
				catch (Exception ex)
				{
					UtilsMod.MLS.Log((LogLevel)2, (object)ex);
				}
			}
		}

		public bool Remove(string section, string key)
		{
			lock (_ioLock)
			{
				return Entries.Remove(section + "." + key);
			}
		}
	}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			return !_moveNextCalled && (_moveNextCalled = true);
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		return (!EqualityComparer<T>.Default.Equals(_item, (T)value)) ? (-1) : 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return (!EqualityComparer<T>.Default.Equals(_item, item)) ? (-1) : 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}