Decompiled source of Razis Fimbulwinter v1.0.0

BepInEx/plugins/Newtonsoft.Json.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq.JsonPath;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AllowPartiallyTrustedCallers]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")]
[assembly: CLSCompliant(true)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: AssemblyCompany("Newtonsoft")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © James Newton-King 2008")]
[assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")]
[assembly: AssemblyFileVersion("13.0.3.27908")]
[assembly: AssemblyInformationalVersion("13.0.3+0a2e291c0d9c0c7675d445703e51750363a549ef")]
[assembly: AssemblyProduct("Json.NET")]
[assembly: AssemblyTitle("Json.NET .NET 4.5")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("13.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)]
	internal sealed class NotNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
	internal sealed class NotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public NotNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class MaybeNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class AllowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal class DoesNotReturnIfAttribute : Attribute
	{
		public bool ParameterValue { get; }

		public DoesNotReturnIfAttribute(bool parameterValue)
		{
			ParameterValue = parameterValue;
		}
	}
}
namespace Newtonsoft.Json
{
	public enum ConstructorHandling
	{
		Default,
		AllowNonPublicDefaultConstructor
	}
	public enum DateFormatHandling
	{
		IsoDateFormat,
		MicrosoftDateFormat
	}
	public enum DateParseHandling
	{
		None,
		DateTime,
		DateTimeOffset
	}
	public enum DateTimeZoneHandling
	{
		Local,
		Utc,
		Unspecified,
		RoundtripKind
	}
	public class DefaultJsonNameTable : JsonNameTable
	{
		private class Entry
		{
			internal readonly string Value;

			internal readonly int HashCode;

			internal Entry Next;

			internal Entry(string value, int hashCode, Entry next)
			{
				Value = value;
				HashCode = hashCode;
				Next = next;
			}
		}

		private static readonly int HashCodeRandomizer;

		private int _count;

		private Entry[] _entries;

		private int _mask = 31;

		static DefaultJsonNameTable()
		{
			HashCodeRandomizer = Environment.TickCount;
		}

		public DefaultJsonNameTable()
		{
			_entries = new Entry[_mask + 1];
		}

		public override string? Get(char[] key, int start, int length)
		{
			if (length == 0)
			{
				return string.Empty;
			}
			int num = length + HashCodeRandomizer;
			num += (num << 7) ^ key[start];
			int num2 = start + length;
			for (int i = start + 1; i < num2; i++)
			{
				num += (num << 7) ^ key[i];
			}
			num -= num >> 17;
			num -= num >> 11;
			num -= num >> 5;
			int num3 = Volatile.Read(ref _mask);
			int num4 = num & num3;
			for (Entry entry = _entries[num4]; entry != null; entry = entry.Next)
			{
				if (entry.HashCode == num && TextEquals(entry.Value, key, start, length))
				{
					return entry.Value;
				}
			}
			return null;
		}

		public string Add(string key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			int length = key.Length;
			if (length == 0)
			{
				return string.Empty;
			}
			int num = length + HashCodeRandomizer;
			for (int i = 0; i < key.Length; i++)
			{
				num += (num << 7) ^ key[i];
			}
			num -= num >> 17;
			num -= num >> 11;
			num -= num >> 5;
			for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next)
			{
				if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal))
				{
					return entry.Value;
				}
			}
			return AddEntry(key, num);
		}

		private string AddEntry(string str, int hashCode)
		{
			int num = hashCode & _mask;
			Entry entry = new Entry(str, hashCode, _entries[num]);
			_entries[num] = entry;
			if (_count++ == _mask)
			{
				Grow();
			}
			return entry.Value;
		}

		private void Grow()
		{
			Entry[] entries = _entries;
			int num = _mask * 2 + 1;
			Entry[] array = new Entry[num + 1];
			for (int i = 0; i < entries.Length; i++)
			{
				Entry entry = entries[i];
				while (entry != null)
				{
					int num2 = entry.HashCode & num;
					Entry next = entry.Next;
					entry.Next = array[num2];
					array[num2] = entry;
					entry = next;
				}
			}
			_entries = array;
			Volatile.Write(ref _mask, num);
		}

		private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length)
		{
			if (str1.Length != str2Length)
			{
				return false;
			}
			for (int i = 0; i < str1.Length; i++)
			{
				if (str1[i] != str2[str2Start + i])
				{
					return false;
				}
			}
			return true;
		}
	}
	[Flags]
	public enum DefaultValueHandling
	{
		Include = 0,
		Ignore = 1,
		Populate = 2,
		IgnoreAndPopulate = 3
	}
	public enum FloatFormatHandling
	{
		String,
		Symbol,
		DefaultValue
	}
	public enum FloatParseHandling
	{
		Double,
		Decimal
	}
	public enum Formatting
	{
		None,
		Indented
	}
	public interface IArrayPool<T>
	{
		T[] Rent(int minimumLength);

		void Return(T[]? array);
	}
	public interface IJsonLineInfo
	{
		int LineNumber { get; }

		int LinePosition { get; }

		bool HasLineInfo();
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonArrayAttribute : JsonContainerAttribute
	{
		private bool _allowNullItems;

		public bool AllowNullItems
		{
			get
			{
				return _allowNullItems;
			}
			set
			{
				_allowNullItems = value;
			}
		}

		public JsonArrayAttribute()
		{
		}

		public JsonArrayAttribute(bool allowNullItems)
		{
			_allowNullItems = allowNullItems;
		}

		public JsonArrayAttribute(string id)
			: base(id)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)]
	public sealed class JsonConstructorAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public abstract class JsonContainerAttribute : Attribute
	{
		internal bool? _isReference;

		internal bool? _itemIsReference;

		internal ReferenceLoopHandling? _itemReferenceLoopHandling;

		internal TypeNameHandling? _itemTypeNameHandling;

		private Type? _namingStrategyType;

		private object[]? _namingStrategyParameters;

		public string? Id { get; set; }

		public string? Title { get; set; }

		public string? Description { get; set; }

		public Type? ItemConverterType { get; set; }

		public object[]? ItemConverterParameters { get; set; }

		public Type? NamingStrategyType
		{
			get
			{
				return _namingStrategyType;
			}
			set
			{
				_namingStrategyType = value;
				NamingStrategyInstance = null;
			}
		}

		public object[]? NamingStrategyParameters
		{
			get
			{
				return _namingStrategyParameters;
			}
			set
			{
				_namingStrategyParameters = value;
				NamingStrategyInstance = null;
			}
		}

		internal NamingStrategy? NamingStrategyInstance { get; set; }

		public bool IsReference
		{
			get
			{
				return _isReference.GetValueOrDefault();
			}
			set
			{
				_isReference = value;
			}
		}

		public bool ItemIsReference
		{
			get
			{
				return _itemIsReference.GetValueOrDefault();
			}
			set
			{
				_itemIsReference = value;
			}
		}

		public ReferenceLoopHandling ItemReferenceLoopHandling
		{
			get
			{
				return _itemReferenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_itemReferenceLoopHandling = value;
			}
		}

		public TypeNameHandling ItemTypeNameHandling
		{
			get
			{
				return _itemTypeNameHandling.GetValueOrDefault();
			}
			set
			{
				_itemTypeNameHandling = value;
			}
		}

		protected JsonContainerAttribute()
		{
		}

		protected JsonContainerAttribute(string id)
		{
			Id = id;
		}
	}
	public static class JsonConvert
	{
		public static readonly string True = "true";

		public static readonly string False = "false";

		public static readonly string Null = "null";

		public static readonly string Undefined = "undefined";

		public static readonly string PositiveInfinity = "Infinity";

		public static readonly string NegativeInfinity = "-Infinity";

		public static readonly string NaN = "NaN";

		public static Func<JsonSerializerSettings>? DefaultSettings { get; set; }

		public static string ToString(DateTime value)
		{
			return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind);
		}

		public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling)
		{
			DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling);
			using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
			stringWriter.Write('"');
			DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture);
			stringWriter.Write('"');
			return stringWriter.ToString();
		}

		public static string ToString(DateTimeOffset value)
		{
			return ToString(value, DateFormatHandling.IsoDateFormat);
		}

		public static string ToString(DateTimeOffset value, DateFormatHandling format)
		{
			using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
			stringWriter.Write('"');
			DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture);
			stringWriter.Write('"');
			return stringWriter.ToString();
		}

		public static string ToString(bool value)
		{
			if (!value)
			{
				return False;
			}
			return True;
		}

		public static string ToString(char value)
		{
			return ToString(char.ToString(value));
		}

		public static string ToString(Enum value)
		{
			return value.ToString("D");
		}

		public static string ToString(int value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(short value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(ushort value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(uint value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(long value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		private static string ToStringInternal(BigInteger value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(ulong value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(float value)
		{
			return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
		}

		internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
		}

		private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value)))
			{
				return text;
			}
			if (floatFormatHandling == FloatFormatHandling.DefaultValue)
			{
				if (nullable)
				{
					return Null;
				}
				return "0.0";
			}
			return quoteChar + text + quoteChar;
		}

		public static string ToString(double value)
		{
			return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
		}

		internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
		}

		private static string EnsureDecimalPlace(double value, string text)
		{
			if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1)
			{
				return text;
			}
			return text + ".0";
		}

		private static string EnsureDecimalPlace(string text)
		{
			if (StringUtils.IndexOf(text, '.') != -1)
			{
				return text;
			}
			return text + ".0";
		}

		public static string ToString(byte value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(sbyte value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(decimal value)
		{
			return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
		}

		public static string ToString(Guid value)
		{
			return ToString(value, '"');
		}

		internal static string ToString(Guid value, char quoteChar)
		{
			string text = value.ToString("D", CultureInfo.InvariantCulture);
			string text2 = quoteChar.ToString(CultureInfo.InvariantCulture);
			return text2 + text + text2;
		}

		public static string ToString(TimeSpan value)
		{
			return ToString(value, '"');
		}

		internal static string ToString(TimeSpan value, char quoteChar)
		{
			return ToString(value.ToString(), quoteChar);
		}

		public static string ToString(Uri? value)
		{
			if (value == null)
			{
				return Null;
			}
			return ToString(value, '"');
		}

		internal static string ToString(Uri value, char quoteChar)
		{
			return ToString(value.OriginalString, quoteChar);
		}

		public static string ToString(string? value)
		{
			return ToString(value, '"');
		}

		public static string ToString(string? value, char delimiter)
		{
			return ToString(value, delimiter, StringEscapeHandling.Default);
		}

		public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling)
		{
			if (delimiter != '"' && delimiter != '\'')
			{
				throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter");
			}
			return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling);
		}

		public static string ToString(object? value)
		{
			if (value == null)
			{
				return Null;
			}
			return ConvertUtils.GetTypeCode(value.GetType()) switch
			{
				PrimitiveTypeCode.String => ToString((string)value), 
				PrimitiveTypeCode.Char => ToString((char)value), 
				PrimitiveTypeCode.Boolean => ToString((bool)value), 
				PrimitiveTypeCode.SByte => ToString((sbyte)value), 
				PrimitiveTypeCode.Int16 => ToString((short)value), 
				PrimitiveTypeCode.UInt16 => ToString((ushort)value), 
				PrimitiveTypeCode.Int32 => ToString((int)value), 
				PrimitiveTypeCode.Byte => ToString((byte)value), 
				PrimitiveTypeCode.UInt32 => ToString((uint)value), 
				PrimitiveTypeCode.Int64 => ToString((long)value), 
				PrimitiveTypeCode.UInt64 => ToString((ulong)value), 
				PrimitiveTypeCode.Single => ToString((float)value), 
				PrimitiveTypeCode.Double => ToString((double)value), 
				PrimitiveTypeCode.DateTime => ToString((DateTime)value), 
				PrimitiveTypeCode.Decimal => ToString((decimal)value), 
				PrimitiveTypeCode.DBNull => Null, 
				PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), 
				PrimitiveTypeCode.Guid => ToString((Guid)value), 
				PrimitiveTypeCode.Uri => ToString((Uri)value), 
				PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), 
				PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), 
				_ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), 
			};
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value)
		{
			return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Formatting formatting)
		{
			return SerializeObject(value, formatting, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return SerializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return SerializeObject(value, null, formatting, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, JsonSerializerSettings? settings)
		{
			return SerializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			return SerializeObjectInternal(value, type, jsonSerializer);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings)
		{
			return SerializeObject(value, null, formatting, settings);
		}

		[DebuggerStepThrough]
		public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			jsonSerializer.Formatting = formatting;
			return SerializeObjectInternal(value, type, jsonSerializer);
		}

		private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer)
		{
			StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture);
			using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
			{
				jsonTextWriter.Formatting = jsonSerializer.Formatting;
				jsonSerializer.Serialize(jsonTextWriter, value, type);
			}
			return stringWriter.ToString();
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value)
		{
			return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value, JsonSerializerSettings settings)
		{
			return DeserializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value, Type type)
		{
			return DeserializeObject(value, type, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static T? DeserializeObject<T>(string value)
		{
			return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
		{
			return DeserializeObject<T>(value);
		}

		[DebuggerStepThrough]
		public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
		{
			return DeserializeObject<T>(value, settings);
		}

		[DebuggerStepThrough]
		public static T? DeserializeObject<T>(string value, params JsonConverter[] converters)
		{
			return (T)DeserializeObject(value, typeof(T), converters);
		}

		[DebuggerStepThrough]
		public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings)
		{
			return (T)DeserializeObject(value, typeof(T), settings);
		}

		[DebuggerStepThrough]
		public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return DeserializeObject(value, type, settings);
		}

		public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings)
		{
			ValidationUtils.ArgumentNotNull(value, "value");
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			if (!jsonSerializer.IsCheckAdditionalContentSet())
			{
				jsonSerializer.CheckAdditionalContent = true;
			}
			using JsonTextReader reader = new JsonTextReader(new StringReader(value));
			return jsonSerializer.Deserialize(reader, type);
		}

		[DebuggerStepThrough]
		public static void PopulateObject(string value, object target)
		{
			PopulateObject(value, target, null);
		}

		public static void PopulateObject(string value, object target, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			using JsonReader jsonReader = new JsonTextReader(new StringReader(value));
			jsonSerializer.Populate(jsonReader, target);
			if (settings == null || !settings.CheckAdditionalContent)
			{
				return;
			}
			while (jsonReader.Read())
			{
				if (jsonReader.TokenType != JsonToken.Comment)
				{
					throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object.");
				}
			}
		}

		public static string SerializeXmlNode(XmlNode? node)
		{
			return SerializeXmlNode(node, Formatting.None);
		}

		public static string SerializeXmlNode(XmlNode? node, Formatting formatting)
		{
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
			return SerializeObject(node, formatting, xmlNodeConverter);
		}

		public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject)
		{
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter
			{
				OmitRootObject = omitRootObject
			};
			return SerializeObject(node, formatting, xmlNodeConverter);
		}

		public static XmlDocument? DeserializeXmlNode(string value)
		{
			return DeserializeXmlNode(value, null);
		}

		public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName)
		{
			return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false);
		}

		public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute)
		{
			return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false);
		}

		public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
		{
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
			xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName;
			xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute;
			xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters;
			return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter);
		}

		public static string SerializeXNode(XObject? node)
		{
			return SerializeXNode(node, Formatting.None);
		}

		public static string SerializeXNode(XObject? node, Formatting formatting)
		{
			return SerializeXNode(node, formatting, omitRootObject: false);
		}

		public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject)
		{
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter
			{
				OmitRootObject = omitRootObject
			};
			return SerializeObject(node, formatting, xmlNodeConverter);
		}

		public static XDocument? DeserializeXNode(string value)
		{
			return DeserializeXNode(value, null);
		}

		public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName)
		{
			return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false);
		}

		public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute)
		{
			return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false);
		}

		public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
			xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName;
			xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute;
			xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters;
			return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter);
		}
	}
	public abstract class JsonConverter
	{
		public virtual bool CanRead => true;

		public virtual bool CanWrite => true;

		public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer);

		public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer);

		public abstract bool CanConvert(Type objectType);
	}
	public abstract class JsonConverter<T> : JsonConverter
	{
		public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
		{
			if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T))))
			{
				throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
			}
			WriteJson(writer, (T)value, serializer);
		}

		public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer);

		public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
		{
			bool flag = existingValue == null;
			if (!flag && !(existingValue is T))
			{
				throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
			}
			return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer);
		}

		public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer);

		public sealed override bool CanConvert(Type objectType)
		{
			return typeof(T).IsAssignableFrom(objectType);
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)]
	public sealed class JsonConverterAttribute : Attribute
	{
		private readonly Type _converterType;

		public Type ConverterType => _converterType;

		public object[]? ConverterParameters { get; }

		public JsonConverterAttribute(Type converterType)
		{
			if (converterType == null)
			{
				throw new ArgumentNullException("converterType");
			}
			_converterType = converterType;
		}

		public JsonConverterAttribute(Type converterType, params object[] converterParameters)
			: this(converterType)
		{
			ConverterParameters = converterParameters;
		}
	}
	public class JsonConverterCollection : Collection<JsonConverter>
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonDictionaryAttribute : JsonContainerAttribute
	{
		public JsonDictionaryAttribute()
		{
		}

		public JsonDictionaryAttribute(string id)
			: base(id)
		{
		}
	}
	[Serializable]
	public class JsonException : Exception
	{
		public JsonException()
		{
		}

		public JsonException(string message)
			: base(message)
		{
		}

		public JsonException(string message, Exception? innerException)
			: base(message, innerException)
		{
		}

		public JsonException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			return new JsonException(message);
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public class JsonExtensionDataAttribute : Attribute
	{
		public bool WriteData { get; set; }

		public bool ReadData { get; set; }

		public JsonExtensionDataAttribute()
		{
			WriteData = true;
			ReadData = true;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public sealed class JsonIgnoreAttribute : Attribute
	{
	}
	public abstract class JsonNameTable
	{
		public abstract string? Get(char[] key, int start, int length);
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonObjectAttribute : JsonContainerAttribute
	{
		private MemberSerialization _memberSerialization;

		internal MissingMemberHandling? _missingMemberHandling;

		internal Required? _itemRequired;

		internal NullValueHandling? _itemNullValueHandling;

		public MemberSerialization MemberSerialization
		{
			get
			{
				return _memberSerialization;
			}
			set
			{
				_memberSerialization = value;
			}
		}

		public MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling.GetValueOrDefault();
			}
			set
			{
				_missingMemberHandling = value;
			}
		}

		public NullValueHandling ItemNullValueHandling
		{
			get
			{
				return _itemNullValueHandling.GetValueOrDefault();
			}
			set
			{
				_itemNullValueHandling = value;
			}
		}

		public Required ItemRequired
		{
			get
			{
				return _itemRequired.GetValueOrDefault();
			}
			set
			{
				_itemRequired = value;
			}
		}

		public JsonObjectAttribute()
		{
		}

		public JsonObjectAttribute(MemberSerialization memberSerialization)
		{
			MemberSerialization = memberSerialization;
		}

		public JsonObjectAttribute(string id)
			: base(id)
		{
		}
	}
	internal enum JsonContainerType
	{
		None,
		Object,
		Array,
		Constructor
	}
	internal struct JsonPosition
	{
		private static readonly char[] SpecialCharacters = new char[18]
		{
			'.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t',
			'\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029'
		};

		internal JsonContainerType Type;

		internal int Position;

		internal string? PropertyName;

		internal bool HasIndex;

		public JsonPosition(JsonContainerType type)
		{
			Type = type;
			HasIndex = TypeHasIndex(type);
			Position = -1;
			PropertyName = null;
		}

		internal int CalculateLength()
		{
			switch (Type)
			{
			case JsonContainerType.Object:
				return PropertyName.Length + 5;
			case JsonContainerType.Array:
			case JsonContainerType.Constructor:
				return MathUtils.IntLength((ulong)Position) + 2;
			default:
				throw new ArgumentOutOfRangeException("Type");
			}
		}

		internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer)
		{
			switch (Type)
			{
			case JsonContainerType.Object:
			{
				string propertyName = PropertyName;
				if (propertyName.IndexOfAny(SpecialCharacters) != -1)
				{
					sb.Append("['");
					if (writer == null)
					{
						writer = new StringWriter(sb);
					}
					JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer);
					sb.Append("']");
				}
				else
				{
					if (sb.Length > 0)
					{
						sb.Append('.');
					}
					sb.Append(propertyName);
				}
				break;
			}
			case JsonContainerType.Array:
			case JsonContainerType.Constructor:
				sb.Append('[');
				sb.Append(Position);
				sb.Append(']');
				break;
			}
		}

		internal static bool TypeHasIndex(JsonContainerType type)
		{
			if (type != JsonContainerType.Array)
			{
				return type == JsonContainerType.Constructor;
			}
			return true;
		}

		internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition)
		{
			int num = 0;
			if (positions != null)
			{
				for (int i = 0; i < positions.Count; i++)
				{
					num += positions[i].CalculateLength();
				}
			}
			if (currentPosition.HasValue)
			{
				num += currentPosition.GetValueOrDefault().CalculateLength();
			}
			StringBuilder stringBuilder = new StringBuilder(num);
			StringWriter writer = null;
			char[] buffer = null;
			if (positions != null)
			{
				foreach (JsonPosition position in positions)
				{
					position.WriteTo(stringBuilder, ref writer, ref buffer);
				}
			}
			currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer);
			return stringBuilder.ToString();
		}

		internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message)
		{
			if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal))
			{
				message = message.Trim();
				if (!StringUtils.EndsWith(message, '.'))
				{
					message += ".";
				}
				message += " ";
			}
			message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path);
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition);
			}
			message += ".";
			return message;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
	public sealed class JsonPropertyAttribute : Attribute
	{
		internal NullValueHandling? _nullValueHandling;

		internal DefaultValueHandling? _defaultValueHandling;

		internal ReferenceLoopHandling? _referenceLoopHandling;

		internal ObjectCreationHandling? _objectCreationHandling;

		internal TypeNameHandling? _typeNameHandling;

		internal bool? _isReference;

		internal int? _order;

		internal Required? _required;

		internal bool? _itemIsReference;

		internal ReferenceLoopHandling? _itemReferenceLoopHandling;

		internal TypeNameHandling? _itemTypeNameHandling;

		public Type? ItemConverterType { get; set; }

		public object[]? ItemConverterParameters { get; set; }

		public Type? NamingStrategyType { get; set; }

		public object[]? NamingStrategyParameters { get; set; }

		public NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling.GetValueOrDefault();
			}
			set
			{
				_nullValueHandling = value;
			}
		}

		public DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling.GetValueOrDefault();
			}
			set
			{
				_defaultValueHandling = value;
			}
		}

		public ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_referenceLoopHandling = value;
			}
		}

		public ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling.GetValueOrDefault();
			}
			set
			{
				_objectCreationHandling = value;
			}
		}

		public TypeNameHandling TypeNameHandling
		{
			get
			{
				return _typeNameHandling.GetValueOrDefault();
			}
			set
			{
				_typeNameHandling = value;
			}
		}

		public bool IsReference
		{
			get
			{
				return _isReference.GetValueOrDefault();
			}
			set
			{
				_isReference = value;
			}
		}

		public int Order
		{
			get
			{
				return _order.GetValueOrDefault();
			}
			set
			{
				_order = value;
			}
		}

		public Required Required
		{
			get
			{
				return _required.GetValueOrDefault();
			}
			set
			{
				_required = value;
			}
		}

		public string? PropertyName { get; set; }

		public ReferenceLoopHandling ItemReferenceLoopHandling
		{
			get
			{
				return _itemReferenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_itemReferenceLoopHandling = value;
			}
		}

		public TypeNameHandling ItemTypeNameHandling
		{
			get
			{
				return _itemTypeNameHandling.GetValueOrDefault();
			}
			set
			{
				_itemTypeNameHandling = value;
			}
		}

		public bool ItemIsReference
		{
			get
			{
				return _itemIsReference.GetValueOrDefault();
			}
			set
			{
				_itemIsReference = value;
			}
		}

		public JsonPropertyAttribute()
		{
		}

		public JsonPropertyAttribute(string propertyName)
		{
			PropertyName = propertyName;
		}
	}
	public abstract class JsonReader : IDisposable
	{
		protected internal enum State
		{
			Start,
			Complete,
			Property,
			ObjectStart,
			Object,
			ArrayStart,
			Array,
			Closed,
			PostValue,
			ConstructorStart,
			Constructor,
			Error,
			Finished
		}

		private JsonToken _tokenType;

		private object? _value;

		internal char _quoteChar;

		internal State _currentState;

		private JsonPosition _currentPosition;

		private CultureInfo? _culture;

		private DateTimeZoneHandling _dateTimeZoneHandling;

		private int? _maxDepth;

		private bool _hasExceededMaxDepth;

		internal DateParseHandling _dateParseHandling;

		internal FloatParseHandling _floatParseHandling;

		private string? _dateFormatString;

		private List<JsonPosition>? _stack;

		protected State CurrentState => _currentState;

		public bool CloseInput { get; set; }

		public bool SupportMultipleContent { get; set; }

		public virtual char QuoteChar
		{
			get
			{
				return _quoteChar;
			}
			protected internal set
			{
				_quoteChar = value;
			}
		}

		public DateTimeZoneHandling DateTimeZoneHandling
		{
			get
			{
				return _dateTimeZoneHandling;
			}
			set
			{
				if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_dateTimeZoneHandling = value;
			}
		}

		public DateParseHandling DateParseHandling
		{
			get
			{
				return _dateParseHandling;
			}
			set
			{
				if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_dateParseHandling = value;
			}
		}

		public FloatParseHandling FloatParseHandling
		{
			get
			{
				return _floatParseHandling;
			}
			set
			{
				if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_floatParseHandling = value;
			}
		}

		public string? DateFormatString
		{
			get
			{
				return _dateFormatString;
			}
			set
			{
				_dateFormatString = value;
			}
		}

		public int? MaxDepth
		{
			get
			{
				return _maxDepth;
			}
			set
			{
				if (value <= 0)
				{
					throw new ArgumentException("Value must be positive.", "value");
				}
				_maxDepth = value;
			}
		}

		public virtual JsonToken TokenType => _tokenType;

		public virtual object? Value => _value;

		public virtual Type? ValueType => _value?.GetType();

		public virtual int Depth
		{
			get
			{
				int num = _stack?.Count ?? 0;
				if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
				{
					return num;
				}
				return num + 1;
			}
		}

		public virtual string Path
		{
			get
			{
				if (_currentPosition.Type == JsonContainerType.None)
				{
					return string.Empty;
				}
				JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null);
				return JsonPosition.BuildPath(_stack, currentPosition);
			}
		}

		public CultureInfo Culture
		{
			get
			{
				return _culture ?? CultureInfo.InvariantCulture;
			}
			set
			{
				_culture = value;
			}
		}

		public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync();
		}

		public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			if (TokenType == JsonToken.PropertyName)
			{
				await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			}
			if (JsonTokenUtils.IsStartToken(TokenType))
			{
				int depth = Depth;
				while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth)
				{
				}
			}
		}

		internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken)
		{
			if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
			{
				throw CreateUnexpectedEndException();
			}
		}

		public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean());
		}

		public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes());
		}

		internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken)
		{
			List<byte> buffer = new List<byte>();
			do
			{
				if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
				{
					SetToken(JsonToken.None);
				}
			}
			while (!ReadArrayElementIntoByteArrayReportDone(buffer));
			byte[] array = buffer.ToArray();
			SetToken(JsonToken.Bytes, array, updateIndex: false);
			return array;
		}

		public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime());
		}

		public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset());
		}

		public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal());
		}

		public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return Task.FromResult(ReadAsDouble());
		}

		public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32());
		}

		public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString());
		}

		internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken)
		{
			bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			if (flag)
			{
				flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			}
			return flag;
		}

		internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken)
		{
			JsonToken tokenType = TokenType;
			if (tokenType == JsonToken.None || tokenType == JsonToken.Comment)
			{
				return MoveToContentFromNonContentAsync(cancellationToken);
			}
			return AsyncUtils.True;
		}

		private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken)
		{
			JsonToken tokenType;
			do
			{
				if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
				{
					return false;
				}
				tokenType = TokenType;
			}
			while (tokenType == JsonToken.None || tokenType == JsonToken.Comment);
			return true;
		}

		internal JsonPosition GetPosition(int depth)
		{
			if (_stack != null && depth < _stack.Count)
			{
				return _stack[depth];
			}
			return _currentPosition;
		}

		protected JsonReader()
		{
			_currentState = State.Start;
			_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
			_dateParseHandling = DateParseHandling.DateTime;
			_floatParseHandling = FloatParseHandling.Double;
			_maxDepth = 64;
			CloseInput = true;
		}

		private void Push(JsonContainerType value)
		{
			UpdateScopeWithFinishedValue();
			if (_currentPosition.Type == JsonContainerType.None)
			{
				_currentPosition = new JsonPosition(value);
				return;
			}
			if (_stack == null)
			{
				_stack = new List<JsonPosition>();
			}
			_stack.Add(_currentPosition);
			_currentPosition = new JsonPosition(value);
			if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth)
			{
				return;
			}
			_hasExceededMaxDepth = true;
			throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
		}

		private JsonContainerType Pop()
		{
			JsonPosition currentPosition;
			if (_stack != null && _stack.Count > 0)
			{
				currentPosition = _currentPosition;
				_currentPosition = _stack[_stack.Count - 1];
				_stack.RemoveAt(_stack.Count - 1);
			}
			else
			{
				currentPosition = _currentPosition;
				_currentPosition = default(JsonPosition);
			}
			if (_maxDepth.HasValue && Depth <= _maxDepth)
			{
				_hasExceededMaxDepth = false;
			}
			return currentPosition.Type;
		}

		private JsonContainerType Peek()
		{
			return _currentPosition.Type;
		}

		public abstract bool Read();

		public virtual int? ReadAsInt32()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is int)
				{
					return (int)value;
				}
				int num;
				if (value is BigInteger bigInteger)
				{
					num = (int)bigInteger;
				}
				else
				{
					try
					{
						num = Convert.ToInt32(value, CultureInfo.InvariantCulture);
					}
					catch (Exception ex)
					{
						throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
					}
				}
				SetToken(JsonToken.Integer, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
			{
				string s = (string)Value;
				return ReadInt32String(s);
			}
			default:
				throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal int? ReadInt32String(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (int.TryParse(s, NumberStyles.Integer, Culture, out var result))
			{
				SetToken(JsonToken.Integer, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual string? ReadAsString()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.String:
				return (string)Value;
			default:
				if (JsonTokenUtils.IsPrimitiveToken(contentToken))
				{
					object value = Value;
					if (value != null)
					{
						string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture));
						SetToken(JsonToken.String, text, updateIndex: false);
						return text;
					}
				}
				throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		public virtual byte[]? ReadAsBytes()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.StartObject:
			{
				ReadIntoWrappedTypeObject();
				byte[] array2 = ReadAsBytes();
				ReaderReadAndAssert();
				if (TokenType != JsonToken.EndObject)
				{
					throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
				}
				SetToken(JsonToken.Bytes, array2, updateIndex: false);
				return array2;
			}
			case JsonToken.String:
			{
				string text = (string)Value;
				Guid g;
				byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray()));
				SetToken(JsonToken.Bytes, array3, updateIndex: false);
				return array3;
			}
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Bytes:
				if (Value is Guid guid)
				{
					byte[] array = guid.ToByteArray();
					SetToken(JsonToken.Bytes, array, updateIndex: false);
					return array;
				}
				return (byte[])Value;
			case JsonToken.StartArray:
				return ReadArrayIntoByteArray();
			default:
				throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal byte[] ReadArrayIntoByteArray()
		{
			List<byte> list = new List<byte>();
			do
			{
				if (!Read())
				{
					SetToken(JsonToken.None);
				}
			}
			while (!ReadArrayElementIntoByteArrayReportDone(list));
			byte[] array = list.ToArray();
			SetToken(JsonToken.Bytes, array, updateIndex: false);
			return array;
		}

		private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer)
		{
			switch (TokenType)
			{
			case JsonToken.None:
				throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
			case JsonToken.Integer:
				buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
				return false;
			case JsonToken.EndArray:
				return true;
			case JsonToken.Comment:
				return false;
			default:
				throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
			}
		}

		public virtual double? ReadAsDouble()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is double)
				{
					return (double)value;
				}
				double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger));
				SetToken(JsonToken.Float, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
				return ReadDoubleString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal double? ReadDoubleString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result))
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual bool? ReadAsBoolean()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L));
				SetToken(JsonToken.Boolean, flag, updateIndex: false);
				return flag;
			}
			case JsonToken.String:
				return ReadBooleanString((string)Value);
			case JsonToken.Boolean:
				return (bool)Value;
			default:
				throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal bool? ReadBooleanString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (bool.TryParse(s, out var result))
			{
				SetToken(JsonToken.Boolean, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual decimal? ReadAsDecimal()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is decimal)
				{
					return (decimal)value;
				}
				decimal num;
				if (value is BigInteger bigInteger)
				{
					num = (decimal)bigInteger;
				}
				else
				{
					try
					{
						num = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
					}
					catch (Exception ex)
					{
						throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
					}
				}
				SetToken(JsonToken.Float, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
				return ReadDecimalString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal decimal? ReadDecimalString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result))
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success)
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual DateTime? ReadAsDateTime()
		{
			switch (GetContentToken())
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Date:
				if (Value is DateTimeOffset dateTimeOffset)
				{
					SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false);
				}
				return (DateTime)Value;
			case JsonToken.String:
				return ReadDateTimeString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
			}
		}

		internal DateTime? ReadDateTimeString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt))
			{
				dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
			{
				dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual DateTimeOffset? ReadAsDateTimeOffset()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Date:
				if (Value is DateTime dateTime)
				{
					SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false);
				}
				return (DateTimeOffset)Value;
			case JsonToken.String:
			{
				string s = (string)Value;
				return ReadDateTimeOffsetString(s);
			}
			default:
				throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal DateTimeOffset? ReadDateTimeOffsetString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt))
			{
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
			{
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		internal void ReaderReadAndAssert()
		{
			if (!Read())
			{
				throw CreateUnexpectedEndException();
			}
		}

		internal JsonReaderException CreateUnexpectedEndException()
		{
			return JsonReaderException.Create(this, "Unexpected end when reading JSON.");
		}

		internal void ReadIntoWrappedTypeObject()
		{
			ReaderReadAndAssert();
			if (Value != null && Value.ToString() == "$type")
			{
				ReaderReadAndAssert();
				if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal))
				{
					ReaderReadAndAssert();
					if (Value.ToString() == "$value")
					{
						return;
					}
				}
			}
			throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject));
		}

		public void Skip()
		{
			if (TokenType == JsonToken.PropertyName)
			{
				Read();
			}
			if (JsonTokenUtils.IsStartToken(TokenType))
			{
				int depth = Depth;
				while (Read() && depth < Depth)
				{
				}
			}
		}

		protected void SetToken(JsonToken newToken)
		{
			SetToken(newToken, null, updateIndex: true);
		}

		protected void SetToken(JsonToken newToken, object? value)
		{
			SetToken(newToken, value, updateIndex: true);
		}

		protected void SetToken(JsonToken newToken, object? value, bool updateIndex)
		{
			_tokenType = newToken;
			_value = value;
			switch (newToken)
			{
			case JsonToken.StartObject:
				_currentState = State.ObjectStart;
				Push(JsonContainerType.Object);
				break;
			case JsonToken.StartArray:
				_currentState = State.ArrayStart;
				Push(JsonContainerType.Array);
				break;
			case JsonToken.StartConstructor:
				_currentState = State.ConstructorStart;
				Push(JsonContainerType.Constructor);
				break;
			case JsonToken.EndObject:
				ValidateEnd(JsonToken.EndObject);
				break;
			case JsonToken.EndArray:
				ValidateEnd(JsonToken.EndArray);
				break;
			case JsonToken.EndConstructor:
				ValidateEnd(JsonToken.EndConstructor);
				break;
			case JsonToken.PropertyName:
				_currentState = State.Property;
				_currentPosition.PropertyName = (string)value;
				break;
			case JsonToken.Raw:
			case JsonToken.Integer:
			case JsonToken.Float:
			case JsonToken.String:
			case JsonToken.Boolean:
			case JsonToken.Null:
			case JsonToken.Undefined:
			case JsonToken.Date:
			case JsonToken.Bytes:
				SetPostValueState(updateIndex);
				break;
			case JsonToken.Comment:
				break;
			}
		}

		internal void SetPostValueState(bool updateIndex)
		{
			if (Peek() != 0 || SupportMultipleContent)
			{
				_currentState = State.PostValue;
			}
			else
			{
				SetFinished();
			}
			if (updateIndex)
			{
				UpdateScopeWithFinishedValue();
			}
		}

		private void UpdateScopeWithFinishedValue()
		{
			if (_currentPosition.HasIndex)
			{
				_currentPosition.Position++;
			}
		}

		private void ValidateEnd(JsonToken endToken)
		{
			JsonContainerType jsonContainerType = Pop();
			if (GetTypeForCloseToken(endToken) != jsonContainerType)
			{
				throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType));
			}
			if (Peek() != 0 || SupportMultipleContent)
			{
				_currentState = State.PostValue;
			}
			else
			{
				SetFinished();
			}
		}

		protected void SetStateBasedOnCurrent()
		{
			JsonContainerType jsonContainerType = Peek();
			switch (jsonContainerType)
			{
			case JsonContainerType.Object:
				_currentState = State.Object;
				break;
			case JsonContainerType.Array:
				_currentState = State.Array;
				break;
			case JsonContainerType.Constructor:
				_currentState = State.Constructor;
				break;
			case JsonContainerType.None:
				SetFinished();
				break;
			default:
				throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType));
			}
		}

		private void SetFinished()
		{
			_currentState = ((!SupportMultipleContent) ? State.Finished : State.Start);
		}

		private JsonContainerType GetTypeForCloseToken(JsonToken token)
		{
			return token switch
			{
				JsonToken.EndObject => JsonContainerType.Object, 
				JsonToken.EndArray => JsonContainerType.Array, 
				JsonToken.EndConstructor => JsonContainerType.Constructor, 
				_ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), 
			};
		}

		void IDisposable.Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (_currentState != State.Closed && disposing)
			{
				Close();
			}
		}

		public virtual void Close()
		{
			_currentState = State.Closed;
			_tokenType = JsonToken.None;
			_value = null;
		}

		internal void ReadAndAssert()
		{
			if (!Read())
			{
				throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
			}
		}

		internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter)
		{
			if (!ReadForType(contract, hasConverter))
			{
				throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
			}
		}

		internal bool ReadForType(JsonContract? contract, bool hasConverter)
		{
			if (hasConverter)
			{
				return Read();
			}
			switch (contract?.InternalReadType ?? ReadType.Read)
			{
			case ReadType.Read:
				return ReadAndMoveToContent();
			case ReadType.ReadAsInt32:
				ReadAsInt32();
				break;
			case ReadType.ReadAsInt64:
			{
				bool result = ReadAndMoveToContent();
				if (TokenType == JsonToken.Undefined)
				{
					throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long)));
				}
				return result;
			}
			case ReadType.ReadAsDecimal:
				ReadAsDecimal();
				break;
			case ReadType.ReadAsDouble:
				ReadAsDouble();
				break;
			case ReadType.ReadAsBytes:
				ReadAsBytes();
				break;
			case ReadType.ReadAsBoolean:
				ReadAsBoolean();
				break;
			case ReadType.ReadAsString:
				ReadAsString();
				break;
			case ReadType.ReadAsDateTime:
				ReadAsDateTime();
				break;
			case ReadType.ReadAsDateTimeOffset:
				ReadAsDateTimeOffset();
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
			return TokenType != JsonToken.None;
		}

		internal bool ReadAndMoveToContent()
		{
			if (Read())
			{
				return MoveToContent();
			}
			return false;
		}

		internal bool MoveToContent()
		{
			JsonToken tokenType = TokenType;
			while (tokenType == JsonToken.None || tokenType == JsonToken.Comment)
			{
				if (!Read())
				{
					return false;
				}
				tokenType = TokenType;
			}
			return true;
		}

		private JsonToken GetContentToken()
		{
			JsonToken tokenType;
			do
			{
				if (!Read())
				{
					SetToken(JsonToken.None);
					return JsonToken.None;
				}
				tokenType = TokenType;
			}
			while (tokenType == JsonToken.Comment);
			return tokenType;
		}
	}
	[Serializable]
	public class JsonReaderException : JsonException
	{
		public int LineNumber { get; }

		public int LinePosition { get; }

		public string? Path { get; }

		public JsonReaderException()
		{
		}

		public JsonReaderException(string message)
			: base(message)
		{
		}

		public JsonReaderException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public JsonReaderException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
			: base(message, innerException)
		{
			Path = path;
			LineNumber = lineNumber;
			LinePosition = linePosition;
		}

		internal static JsonReaderException Create(JsonReader reader, string message)
		{
			return Create(reader, message, null);
		}

		internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex)
		{
			return Create(reader as IJsonLineInfo, reader.Path, message, ex);
		}

		internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			int lineNumber;
			int linePosition;
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				lineNumber = lineInfo.LineNumber;
				linePosition = lineInfo.LinePosition;
			}
			else
			{
				lineNumber = 0;
				linePosition = 0;
			}
			return new JsonReaderException(message, path, lineNumber, linePosition, ex);
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public sealed class JsonRequiredAttribute : Attribute
	{
	}
	[Serializable]
	public class JsonSerializationException : JsonException
	{
		public int LineNumber { get; }

		public int LinePosition { get; }

		public string? Path { get; }

		public JsonSerializationException()
		{
		}

		public JsonSerializationException(string message)
			: base(message)
		{
		}

		public JsonSerializationException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public JsonSerializationException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
			: base(message, innerException)
		{
			Path = path;
			LineNumber = lineNumber;
			LinePosition = linePosition;
		}

		internal static JsonSerializationException Create(JsonReader reader, string message)
		{
			return Create(reader, message, null);
		}

		internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex)
		{
			return Create(reader as IJsonLineInfo, reader.Path, message, ex);
		}

		internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			int lineNumber;
			int linePosition;
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				lineNumber = lineInfo.LineNumber;
				linePosition = lineInfo.LinePosition;
			}
			else
			{
				lineNumber = 0;
				linePosition = 0;
			}
			return new JsonSerializationException(message, path, lineNumber, linePosition, ex);
		}
	}
	public class JsonSerializer
	{
		internal TypeNameHandling _typeNameHandling;

		internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling;

		internal PreserveReferencesHandling _preserveReferencesHandling;

		internal ReferenceLoopHandling _referenceLoopHandling;

		internal MissingMemberHandling _missingMemberHandling;

		internal ObjectCreationHandling _objectCreationHandling;

		internal NullValueHandling _nullValueHandling;

		internal DefaultValueHandling _defaultValueHandling;

		internal ConstructorHandling _constructorHandling;

		internal MetadataPropertyHandling _metadataPropertyHandling;

		internal JsonConverterCollection? _converters;

		internal IContractResolver _contractResolver;

		internal ITraceWriter? _traceWriter;

		internal IEqualityComparer? _equalityComparer;

		internal ISerializationBinder _serializationBinder;

		internal StreamingContext _context;

		private IReferenceResolver? _referenceResolver;

		private Formatting? _formatting;

		private DateFormatHandling? _dateFormatHandling;

		private DateTimeZoneHandling? _dateTimeZoneHandling;

		private DateParseHandling? _dateParseHandling;

		private FloatFormatHandling? _floatFormatHandling;

		private FloatParseHandling? _floatParseHandling;

		private StringEscapeHandling? _stringEscapeHandling;

		private CultureInfo _culture;

		private int? _maxDepth;

		private bool _maxDepthSet;

		private bool? _checkAdditionalContent;

		private string? _dateFormatString;

		private bool _dateFormatStringSet;

		public virtual IReferenceResolver? ReferenceResolver
		{
			get
			{
				return GetReferenceResolver();
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Reference resolver cannot be null.");
				}
				_referenceResolver = value;
			}
		}

		[Obsolete("Binder is obsolete. Use SerializationBinder instead.")]
		public virtual SerializationBinder Binder
		{
			get
			{
				if (_serializationBinder is SerializationBinder result)
				{
					return result;
				}
				if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter)
				{
					return serializationBinderAdapter.SerializationBinder;
				}
				throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set.");
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Serialization binder cannot be null.");
				}
				_serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value);
			}
		}

		public virtual ISerializationBinder SerializationBinder
		{
			get
			{
				return _serializationBinder;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Serialization binder cannot be null.");
				}
				_serializationBinder = value;
			}
		}

		public virtual ITraceWriter? TraceWriter
		{
			get
			{
				return _traceWriter;
			}
			set
			{
				_traceWriter = value;
			}
		}

		public virtual IEqualityComparer? EqualityComparer
		{
			get
			{
				return _equalityComparer;
			}
			set
			{
				_equalityComparer = value;
			}
		}

		public virtual TypeNameHandling TypeNameHandling
		{
			get
			{
				return _typeNameHandling;
			}
			set
			{
				if (value < TypeNameHandling.None || value > TypeNameHandling.Auto)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameHandling = value;
			}
		}

		[Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")]
		public virtual FormatterAssemblyStyle TypeNameAssemblyFormat
		{
			get
			{
				return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling;
			}
			set
			{
				if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value;
			}
		}

		public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling
		{
			get
			{
				return _typeNameAssemblyFormatHandling;
			}
			set
			{
				if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameAssemblyFormatHandling = value;
			}
		}

		public virtual PreserveReferencesHandling PreserveReferencesHandling
		{
			get
			{
				return _preserveReferencesHandling;
			}
			set
			{
				if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_preserveReferencesHandling = value;
			}
		}

		public virtual ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling;
			}
			set
			{
				if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_referenceLoopHandling = value;
			}
		}

		public virtual MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling;
			}
			set
			{
				if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_missingMemberHandling = value;
			}
		}

		public virtual NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling;
			}
			set
			{
				if (value < NullValueHandling.Include || value > NullValueHandling.Ignore)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_nullValueHandling = value;
			}
		}

		public virtual DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling;
			}
			set
			{
				if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_defaultValueHandling = value;
			}
		}

		public virtual ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling;
			}
			set
			{
				if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_objectCreationHandling = value;
			}
		}

		public virtual ConstructorHandling ConstructorHandling
		{
			get
			{
				return _constructorHandling;
			}
			set
			{
				if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_constructorHandling = value;
			}
		}

		public virtual MetadataPropertyHandling MetadataPropertyHandling
		{
			get
			{
				return _metadataPropertyHandling;
			}
			set
			{
				if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_metadataPropertyHandling = value;
			}
		}

		public virtual JsonConverterCollection Converters
		{
			get
			{
				if (_converters == null)
				{
					_converters = new JsonConverterCollection();
				}
				return _converters;
			}
		}

		public virtual IContractResolver ContractResolver
		{
			get
			{
				return _contractResolver;
			}
			set
			{
				_contractResolver = value ?? DefaultContractResolver.Instance;
			}
		}

		public virtual StreamingContext Context
		{
			get
			{
				return _context;
			}
			set
			{
				_context = value;
			}
		}

		public virtual Formatting Formatting
		{
			get
			{
				return _formatting.GetValueOrDefault();
			}
			set
			{
				_formatting = value;
			}
		}

		public virtual DateFormatHandling DateFormatHandling
		{
			get
			{
				return _dateFormatHandling.GetValueOrDefault();
			}
			set
			{
				_dateFormatHandling = value;
			}
		}

		public virtual DateTimeZoneHandling DateTimeZoneHandling
		{
			get
			{
				return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind;
			}
			set
			{
				_dateTimeZoneHandling = value;
			}
		}

		public virtual DateParseHandling DateParseHandling
		{
			get
			{
				return _dateParseHandling ?? DateParseHandling.DateTime;
			}
			set
			{
				_dateParseHandling = value;
			}
		}

		public virtual FloatParseHandling FloatParseHandling
		{
			get
			{
				return _floatParseHandling.GetValueOrDefault();
			}
			set
			{
				_floatParseHandling = value;
			}
		}

		public virtual FloatFormatHandling FloatFormatHandling
		{
			get
			{
				return _floatFormatHandling.GetValueOrDefault();
			}
			set
			{
				_floatFormatHandling = value;
			}
		}

		public virtual StringEscapeHandling StringEscapeHandling
		{
			get
			{
				return _stringEscapeHandling.GetValueOrDefault();
			}
			set
			{
				_stringEscapeHandling = value;
			}
		}

		public virtual string DateFormatString
		{
			get
			{
				return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
			}
			set
			{
				_dateFormatString = value;
				_dateFormatStringSet = true;
			}
		}

		public virtual CultureInfo Culture
		{
			get
			{
				return _culture ?? JsonSerializerSettings.DefaultCulture;
			}
			set
			{
				_culture = value;
			}
		}

		public virtual int? MaxDepth
		{
			get
			{
				return _maxDepth;
			}
			set
			{
				if (value <= 0)
				{
					throw new ArgumentException("Value must be positive.", "value");
				}
				_maxDepth = value;
				_maxDepthSet = true;
			}
		}

		public virtual bool CheckAdditionalContent
		{
			get
			{
				return _checkAdditionalContent.GetValueOrDefault();
			}
			set
			{
				_checkAdditionalContent = value;
			}
		}

		public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error;

		internal bool IsCheckAdditionalContentSet()
		{
			return _checkAdditionalContent.HasValue;
		}

		public JsonSerializer()
		{
			_referenceLoopHandling = ReferenceLoopHandling.Error;
			_missingMemberHandling = MissingMemberHandling.Ignore;
			_nullValueHandling = NullValueHandling.Include;
			_defaultValueHandling = DefaultValueHandling.Include;
			_objectCreationHandling = ObjectCreationHandling.Auto;
			_preserveReferencesHandling = PreserveReferencesHandling.None;
			_constructorHandling = ConstructorHandling.Default;
			_typeNameHandling = TypeNameHandling.None;
			_metadataPropertyHandling = MetadataPropertyHandling.Default;
			_context = JsonSerializerSettings.DefaultContext;
			_serializationBinder = DefaultSerializationBinder.Instance;
			_culture = JsonSerializerSettings.DefaultCulture;
			_contractResolver = DefaultContractResolver.Instance;
		}

		public static JsonSerializer Create()
		{
			return new JsonSerializer();
		}

		public static JsonSerializer Create(JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = Create();
			if (settings != null)
			{
				ApplySerializerSettings(jsonSerializer, settings);
			}
			return jsonSerializer;
		}

		public static JsonSerializer CreateDefault()
		{
			return Create(JsonConvert.DefaultSettings?.Invoke());
		}

		public static JsonSerializer CreateDefault(JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = CreateDefault();
			if (settings != null)
			{
				ApplySerializerSettings(jsonSerializer, settings);
			}
			return jsonSerializer;
		}

		private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings)
		{
			if (!CollectionUtils.IsNullOrEmpty(settings.Converters))
			{
				for (int i = 0; i < settings.Converters.Count; i++)
				{
					serializer.Converters.Insert(i, settings.Converters[i]);
				}
			}
			if (settings._typeNameHandling.HasValue)
			{
				serializer.TypeNameHandling = settings.TypeNameHandling;
			}
			if (settings._metadataPropertyHandling.HasValue)
			{
				serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling;
			}
			if (settings._typeNameAssemblyFormatHandling.HasValue)
			{
				serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling;
			}
			if (settings._preserveReferencesHandling.HasValue)
			{
				serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling;
			}
			if (settings._referenceLoopHandling.HasValue)
			{
				serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling;
			}
			if (settings._missingMemberHandling.HasValue)
			{
				serializer.MissingMemberHandling = settings.MissingMemberHandling;
			}
			if (settings._objectCreationHandling.HasValue)
			{
				serializer.ObjectCreationHandling = settings.ObjectCreationHandling;
			}
			if (settings._nullValueHandling.HasValue)
			{
				serializer.NullValueHandling = settings.NullValueHandling;
			}
			if (settings._defaultValueHandling.HasValue)
			{
				serializer.DefaultValueHandling = settings.DefaultValueHandling;
			}
			if (settings._constructorHandling.HasValue)
			{
				serializer.ConstructorHandling = settings.ConstructorHandling;
			}
			if (settings._context.HasValue)
			{
				serializer.Context = settings.Context;
			}
			if (settings._checkAdditionalContent.HasValue)
			{
				serializer._checkAdditionalContent = settings._checkAdditionalContent;
			}
			if (settings.Error != null)
			{
				serializer.Error += settings.Error;
			}
			if (settings.ContractResolver != null)
			{
				serializer.ContractResolver = settings.ContractResolver;
			}
			if (settings.ReferenceResolverProvider != null)
			{
				serializer.ReferenceResolver = settings.ReferenceResolverProvider();
			}
			if (settings.TraceWriter != null)
			{
				serializer.TraceWriter = settings.TraceWriter;
			}
			if (settings.EqualityComparer != null)
			{
				serializer.EqualityComparer = settings.EqualityComparer;
			}
			if (settings.SerializationBinder != null)
			{
				serializer.SerializationBinder = settings.SerializationBinder;
			}
			if (settings._formatting.HasValue)
			{
				serializer._formatting = settings._formatting;
			}
			if (settings._dateFormatHandling.HasValue)
			{
				serializer._dateFormatHandling = settings._dateFormatHandling;
			}
			if (settings._dateTimeZoneHandling.HasValue)
			{
				serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
			}
			if (settings._dateParseHandling.HasValue)
			{
				serializer._dateParseHandling = settings._dateParseHandling;
			}
			if (settings._dateFormatStringSet)
			{
				serializer._dateFormatString = settings._dateFormatString;
				serializer._dateFormatStringSet = settings._dateFormatStringSet;
			}
			if (settings._floatFormatHandling.HasValue)
			{
				serializer._floatFormatHandling = settings._floatFormatHandling;
			}
			if (settings._floatParseHandling.HasValue)
			{
				serializer._floatParseHandling = settings._floatParseHandling;
			}
			if (settings._stringEscapeHandling.HasValue)
			{
				serializer._stringEscapeHandling = settings._stringEscapeHandling;
			}
			if (settings._culture != null)
			{
				serializer._culture = settings._culture;
			}
			if (settings._maxDepthSet)
			{
				serializer._maxDepth = settings._maxDepth;
				serializer._maxDepthSet = settings._maxDepthSet;
			}
		}

		[DebuggerStepThrough]
		public void Populate(TextReader reader, object target)
		{
			Populate(new JsonTextReader(reader), target);
		}

		[DebuggerStepThrough]
		public void Populate(JsonReader reader, object target)
		{
			PopulateInternal(reader, target);
		}

		internal virtual void PopulateInternal(JsonReader reader, object target)
		{
			ValidationUtils.ArgumentNotNull(reader, "reader");
			ValidationUtils.ArgumentNotNull(target, "target");
			SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
			TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
			new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target);
			if (traceJsonReader != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
			}
			ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
		}

		[DebuggerStepThrough]
		public object? Deserialize(JsonReader reader)
		{
			return Deserialize(reader, null);
		}

		[DebuggerStepThrough]
		public object? Deserialize(TextReader reader, Type objectType)
		{
			return Deserialize(new JsonTextReader(reader), objectType);
		}

		[DebuggerStepThrough]
		public T? Deserialize<T>(JsonReader reader)
		{
			return (T)Deserialize(reader, typeof(T));
		}

		[DebuggerStepThrough]
		public object? Deserialize(JsonReader reader, Type? objectType)
		{
			return DeserializeInternal(reader, objectType);
		}

		internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType)
		{
			ValidationUtils.ArgumentNotNull(reader, "reader");
			SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
			TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
			object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
			if (traceJsonReader != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
			}
			ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
			return result;
		}

		internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString)
		{
			if (_culture != null && !_culture.Equals(reader.Culture))
			{
				previousCulture = reader.Culture;
				reader.Culture = _culture;
			}
			else
			{
				previousCulture = null;
			}
			if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling)
			{
				previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
				reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault();
			}
			else
			{
				previousDateTimeZoneHandling = null;
			}
			if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling)
			{
				previousDateParseHandling = reader.DateParseHandling;
				reader.DateParseHandling = _dateParseHandling.GetValueOrDefault();
			}
			else
			{
				previousDateParseHandling = null;
			}
			if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling)
			{
				previousFloatParseHandling = reader.FloatParseHandling;
				reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault();
			}
			else
			{
				previousFloatParseHandling = null;
			}
			if (_maxDepthSet && reader.MaxDepth != _maxDepth)
			{
				previousMaxDepth = reader.MaxDepth;
				reader.MaxDepth = _maxDepth;
			}
			else
			{
				previousMaxDepth = null;
			}
			if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString)
			{
				previousDateFormatString = reader.DateFormatString;
				reader.DateFormatString = _dateFormatString;
			}
			else
			{
				previousDateFormatString = null;
			}
			if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver)
			{
				jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable();
			}
		}

		private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString)
		{
			if (previousCulture != null)
			{
				reader.Culture = previousCulture;
			}
			if (previousDateTimeZoneHandling.HasValue)
			{
				reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault();
			}
			if (previousDateParseHandling.HasValue)
			{
				reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault();
			}
			if (previousFloatParseHandling.HasValue)
			{
				reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault();
			}
			if (_maxDepthSet)
			{
				reader.MaxDepth = previousMaxDepth;
			}
			if (_dateFormatStringSet)
			{
				reader.DateFormatString = previousDateFormatString;
			}
			if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable())
			{
				jsonTextReader.PropertyNameTable = null;
			}
		}

		public void Serialize(TextWriter textWriter, object? value)
		{
			Serialize(new JsonTextWriter(textWriter), value);
		}

		public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType)
		{
			SerializeInternal(jsonWriter, value, objectType);
		}

		public void Serialize(TextWriter textWriter, object? value, Type objectType)
		{
			Serialize(new JsonTextWriter(textWriter), value, objectType);
		}

		public void Serialize(JsonWriter jsonWriter, object? value)
		{
			SerializeInternal(jsonWriter, value, null);
		}

		private TraceJsonReader CreateTraceJsonReader(JsonReader reader)
		{
			TraceJsonReader traceJsonReader = new TraceJsonReader(reader);
			if (reader.TokenType != 0)
			{
				traceJsonReader.WriteCurrentToken();
			}
			return traceJsonReader;
		}

		internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType)
		{
			ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
			Formatting? formatting = null;
			if (_formatting.HasValue && jsonWriter.Formatting != _formatting)
			{
				formatting = jsonWriter.Formatting;
				jsonWriter.Formatting = _formatting.GetValueOrDefault();
			}
			DateFormatHandling? dateFormatHandling = null;
			if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling)
			{
				dateFormatHandling = jsonWriter.DateFormatHandling;
				jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault();
			}
			DateTimeZoneHandling? dateTimeZoneHandling = null;
			if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling)
			{
				dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling;
				jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault();
			}
			FloatFormatHandling? floatFormatHandling = null;
			if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling)
			{
				floatFormatHandling = jsonWriter.FloatFormatHandling;
				jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault();
			}
			StringEscapeHandling? stringEscapeHandling = null;
			if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling)
			{
				stringEscapeHandling = jsonWriter.StringEscapeHandling;
				jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault();
			}
			CultureInfo cultureInfo = null;
			if (_culture != null && !_culture.Equals(jsonWriter.Culture))
			{
				cultureInfo = jsonWriter.Culture;
				jsonWriter.Culture = _culture;
			}
			string dateFormatString = null;
			if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString)
			{
				dateFormatString = jsonWriter.DateFormatString;
				jsonWriter.DateFormatString = _dateFormatString;
			}
			TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null);
			new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType);
			if (traceJsonWriter != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null);
			}
			if (formatting.HasValue)
			{
				jsonWriter.Formatting = formatting.GetValueOrDefault();
			}
			if (dateFormatHandling.HasValue)
			{
				jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault();
			}
			if (dateTimeZoneHandling.HasValue)
			{
				jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault();
			}
			if (floatFormatHandling.HasValue)
			{
				jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault();
			}
			if (stringEscapeHandling.HasValue)
			{
				jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault();
			}
			if (_dateFormatStringSet)
			{
				jsonWriter.DateFormatString = dateFormatString;
			}
			if (cultureInfo != null)
			{
				jsonWriter.Culture = cultureInfo;
			}
		}

		internal IReferenceResolver GetReferenceResolver()
		{
			if (_referenceResolver == null)
			{
				_referenceResolver = new DefaultReferenceResolver();
			}
			return _referenceResolver;
		}

		internal JsonConverter? GetMatchingConverter(Type type)
		{
			return GetMatchingConverter(_converters, type);
		}

		internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType)
		{
			if (converters != null)
			{
				for (int i = 0; i < converters.Count; i++)
				{
					JsonConverter jsonConverter = converters[i];
					if (jsonConverter.CanConvert(objectType))
					{
						return jsonConverter;
					}
				}
			}
			return null;
		}

		internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e)
		{
			this.Error?.Invoke(this, e);
		}
	}
	public class JsonSerializerSettings
	{
		internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error;

		internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore;

		internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include;

		internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include;

		internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto;

		internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None;

		internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default;

		internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None;

		internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default;

		internal static readonly StreamingContext DefaultContext;

		internal const Formatting DefaultFormatting = Formatting.None;

		internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat;

		internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;

		internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime;

		internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double;

		internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String;

		internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default;

		internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple;

		internal static readonly CultureInfo DefaultCulture;

		internal const bool DefaultCheckAdditionalContent = false;

		internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";

		internal const int DefaultMaxDepth = 64;

		internal Formatting? _formatting;

		internal DateFormatHandling? _dateFormatHandling;

		internal DateTimeZoneHandling? _dateTimeZoneHandling;

		internal DateParseHandling? _dateParseHandling;

		internal FloatFormatHandling? _floatFormatHandling;

		internal FloatParseHandling? _floatParseHandling;

		internal StringEscapeHandling? _stringEscapeHandling;

		internal CultureInfo? _culture;

		internal bool? _checkAdditionalContent;

		internal int? _maxDepth;

		internal bool _maxDepthSet;

		internal string? _dateFormatString;

		internal bool _dateFormatStringSet;

		internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling;

		internal DefaultValueHandling? _defaultValueHandling;

		internal PreserveReferencesHandling? _preserveReferencesHandling;

		internal NullValueHandling? _nullValueHandling;

		internal ObjectCreationHandling? _objectCreationHandling;

		internal MissingMemberHandling? _missingMemberHandling;

		internal ReferenceLoopHandling? _referenceLoopHandling;

		internal StreamingContext? _context;

		internal ConstructorHandling? _constructorHandling;

		internal TypeNameHandling? _typeNameHandling;

		internal MetadataPropertyHandling? _metadataPropertyHandling;

		public ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_referenceLoopHandling = value;
			}
		}

		public MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling.GetValueOrDefault();
			}
			set
			{
				_missingMemberHandling = value;
			}
		}

		public ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling.GetValueOrDefault();
			}
			set
			{
				_objectCreationHandling = value;
			}
		}

		public NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling.GetValueOrDefault();
			}
			set
			{
				_nullValueHandling = value;
			}
		}

		public DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling.GetValueOrDefault();
			}
			set
			{
				_defaultValueHandling = value;
			}
		}

		public IList<JsonConverter> Converters { get; set; }

		public PreserveReferencesHandling PreserveReferencesHandling
		{
			get
			{
				return _preserveReferencesHandling.GetValueOrDef

BepInEx/plugins/ConfigurationManager.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ConfigurationManager.Utilities;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyProduct("BepInEx.ConfigurationManager")]
[assembly: AssemblyTitle("BepInEx.ConfigurationManager")]
[assembly: AssemblyDescription("Universal in-game configuration manager for BepInEx plugins")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("https://github.com/BepInEx/BepInEx.ConfigurationManager")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("18.3.1.0")]
namespace ConfigurationManager
{
	internal static class SettingSearcher
	{
		private static readonly ICollection<string> _updateMethodNames = new string[4] { "Update", "FixedUpdate", "LateUpdate", "OnGUI" };

		public static HashSet<string> recognizedFiles = new HashSet<string>();

		public static List<string> OtherConfigFiles { get; private set; } = new List<string>();


		public static BaseUnityPlugin[] FindPlugins()
		{
			return (from x in Chainloader.PluginInfos.Values
				select x.Instance into plugin
				where (Object)(object)plugin != (Object)null
				select plugin).Union(Object.FindObjectsOfType(typeof(BaseUnityPlugin)).Cast<BaseUnityPlugin>()).ToArray();
		}

		public static void CollectSettings(out IEnumerable<SettingEntryBase> results, out List<string> modsWithoutSettings, bool showDebug)
		{
			modsWithoutSettings = new List<string>();
			OtherConfigFiles = new List<string>();
			try
			{
				results = GetBepInExCoreConfig();
			}
			catch (Exception ex)
			{
				results = Enumerable.Empty<SettingEntryBase>();
				ConfigurationManager.Logger.LogError((object)ex);
			}
			recognizedFiles.Clear();
			OtherConfigFiles.Clear();
			BaseUnityPlugin[] array = FindPlugins();
			foreach (BaseUnityPlugin val in array)
			{
				Type type = ((object)val).GetType();
				BepInPlugin metadata = val.Info.Metadata;
				string item = ((metadata != null) ? metadata.Name : null) ?? ((object)val).GetType().FullName;
				if (type.GetCustomAttributes(typeof(BrowsableAttribute), inherit: false).Cast<BrowsableAttribute>().Any((BrowsableAttribute x) => !x.Browsable))
				{
					modsWithoutSettings.Add(item);
					continue;
				}
				List<SettingEntryBase> list = new List<SettingEntryBase>();
				list.AddRange(GetPluginConfig(val).Cast<SettingEntryBase>());
				list.RemoveAll((SettingEntryBase x) => x.Browsable == false);
				if (list.Count == 0)
				{
					modsWithoutSettings.Add(item);
				}
				recognizedFiles.Add(val.Config.ConfigFilePath);
				if (showDebug && type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any((MethodInfo x) => _updateMethodNames.Contains(x.Name)))
				{
					PropertySettingEntry propertySettingEntry = new PropertySettingEntry(val, type.GetProperty("enabled"), val);
					propertySettingEntry.DispName = "!Allow plugin to run on every frame";
					propertySettingEntry.Description = "Disabling this will disable some or all of the plugin's functionality.\nHooks and event-based functionality will not be disabled.\nThis setting will be lost after game restart.";
					propertySettingEntry.IsAdvanced = true;
					list.Add(propertySettingEntry);
				}
				if (list.Count > 0)
				{
					results = results.Concat(list);
				}
			}
			List<string> first = (from file in Directory.GetFiles(Paths.ConfigPath, "*.*", SearchOption.AllDirectories)
				where file.EndsWith(".cfg") || file.EndsWith(".json") || file.EndsWith(".yaml") || file.EndsWith(".yml")
				select file).ToList();
			OtherConfigFiles = first.Except(recognizedFiles).ToList();
		}

		private static IEnumerable<SettingEntryBase> GetBepInExCoreConfig()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			PropertyInfo property = typeof(ConfigFile).GetProperty("CoreConfig", BindingFlags.Static | BindingFlags.NonPublic);
			if ((object)property == null)
			{
				throw new ArgumentNullException("coreConfigProp");
			}
			ConfigFile source = (ConfigFile)property.GetValue(null, null);
			BepInPlugin bepinMeta = new BepInPlugin("BepInEx", "BepInEx", typeof(Chainloader).Assembly.GetName().Version.ToString());
			return ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)source).Select((Func<KeyValuePair<ConfigDefinition, ConfigEntryBase>, SettingEntryBase>)((KeyValuePair<ConfigDefinition, ConfigEntryBase> kvp) => new ConfigSettingEntry(kvp.Value, null)
			{
				IsAdvanced = true,
				PluginInfo = bepinMeta
			}));
		}

		private static IEnumerable<ConfigSettingEntry> GetPluginConfig(BaseUnityPlugin plugin)
		{
			return ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)plugin.Config).Select((KeyValuePair<ConfigDefinition, ConfigEntryBase> kvp) => new ConfigSettingEntry(kvp.Value, plugin));
		}
	}
	internal sealed class ConfigSettingEntry : SettingEntryBase
	{
		public ConfigEntryBase Entry { get; }

		public override Type SettingType => Entry.SettingType;

		public ConfigSettingEntry(ConfigEntryBase entry, BaseUnityPlugin owner)
		{
			Entry = entry;
			DispName = entry.Definition.Key;
			base.Category = entry.Definition.Section;
			ConfigDescription description = entry.Description;
			base.Description = ((description != null) ? description.Description : null);
			TypeConverter converter = TomlTypeConverter.GetConverter(entry.SettingType);
			if (converter != null)
			{
				base.ObjToStr = (object o) => converter.ConvertToString(o, entry.SettingType);
				base.StrToObj = (string s) => converter.ConvertToObject(s, entry.SettingType);
			}
			ConfigDescription description2 = entry.Description;
			AcceptableValueBase val = ((description2 != null) ? description2.AcceptableValues : null);
			if (val != null)
			{
				GetAcceptableValues(val);
			}
			base.DefaultValue = entry.DefaultValue;
			ConfigDescription description3 = entry.Description;
			SetFromAttributes((description3 != null) ? description3.Tags : null, owner);
		}

		private void GetAcceptableValues(AcceptableValueBase values)
		{
			Type type = ((object)values).GetType();
			PropertyInfo property = type.GetProperty("AcceptableValues", BindingFlags.Instance | BindingFlags.Public);
			if ((object)property != null)
			{
				base.AcceptableValues = ((IEnumerable)property.GetValue(values, null)).Cast<object>().ToArray();
				return;
			}
			PropertyInfo property2 = type.GetProperty("MinValue", BindingFlags.Instance | BindingFlags.Public);
			PropertyInfo property3 = type.GetProperty("MaxValue", BindingFlags.Instance | BindingFlags.Public);
			if ((object)property2 != null && (object)property3 != null)
			{
				base.AcceptableValueRange = new KeyValuePair<object, object>(property2.GetValue(values, null), property3.GetValue(values, null));
				base.ShowRangeAsPercent = ((base.AcceptableValueRange.Key.Equals(0) || base.AcceptableValueRange.Key.Equals(1)) && base.AcceptableValueRange.Value.Equals(100)) || (base.AcceptableValueRange.Key.Equals(0f) && base.AcceptableValueRange.Value.Equals(1f));
			}
		}

		public override object Get()
		{
			return Entry.BoxedValue;
		}

		protected override void SetValue(object newVal)
		{
			Entry.BoxedValue = newVal;
		}
	}
	[BepInPlugin("com.bepis.bepinex.configurationmanager", "Configuration Manager", "18.3.1")]
	public class ConfigurationManager : BaseUnityPlugin
	{
		private enum Tab
		{
			Plugins,
			OtherFiles
		}

		internal sealed class PluginSettingsData
		{
			public sealed class PluginSettingsGroupData
			{
				public string Name;

				public List<SettingEntryBase> Settings;

				public float CalculatedHeight;
			}

			public BepInPlugin Info;

			public List<PluginSettingsGroupData> Categories;

			public int Height;

			public string Website;

			private bool _collapsed;

			public bool Collapsed
			{
				get
				{
					return _collapsed;
				}
				set
				{
					_collapsed = value;
					Height = 0;
				}
			}
		}

		public const string GUID = "com.bepis.bepinex.configurationmanager";

		public const string Version = "18.3.1";

		internal static ManualLogSource Logger;

		private static SettingFieldDrawer _fieldDrawer;

		private static readonly Color _advancedSettingColor = new Color(1f, 0.95f, 0.67f, 1f);

		private const int WindowId = -68;

		private const string SearchBoxName = "searchBox";

		private bool _focusSearchBox;

		private string _searchString = string.Empty;

		private string _selectedPluginName = null;

		private const string FileEditorName = "fileEditor";

		private string _fileEditorString = string.Empty;

		private bool _focusFileEditor;

		private Tab _selectedTab = Tab.Plugins;

		private string _selectedOtherFile;

		private static HashSet<string> _pinnedPlugins = new HashSet<string>();

		public bool OverrideHotkey;

		private bool _displayingWindow;

		private bool _obsoleteCursor;

		private string _modsWithoutSettings;

		private List<SettingEntryBase> _allSettings;

		private List<PluginSettingsData> _filteredSetings = new List<PluginSettingsData>();

		private bool _windowWasMoved;

		private bool _tipsPluginHeaderWasClicked;

		private bool _tipsWindowWasMoved;

		private Rect _screenRect;

		private Vector2 _pluginWindowScrollPos;

		private Vector2 _settingWindowScrollPos;

		private int _tipsHeight;

		private PropertyInfo _curLockState;

		private PropertyInfo _curVisible;

		private int _previousCursorLockState;

		private bool _previousCursorVisible;

		private GameObject _overlayCanvasObj;

		private Canvas _overlayCanvas;

		private CanvasScaler _overlayCanvasScaler;

		private GraphicRaycaster _overlayRaycaster;

		private Image _overlayBlocker;

		private readonly Dictionary<string, string> _otherFileContents = new Dictionary<string, string>();

		private readonly ConfigEntry<bool> _showAdvanced;

		private readonly ConfigEntry<bool> _showKeybinds;

		private readonly ConfigEntry<bool> _showSettings;

		private readonly ConfigEntry<bool> _showDefault;

		private readonly ConfigEntry<KeyboardShortcut> _keybind;

		private readonly ConfigEntry<bool> _hideSingleSection;

		private readonly ConfigEntry<string> _pinnedPluginsConfig;

		private bool _showDebug;

		public static ConfigEntry<Vector2> _windowSize;

		public static ConfigEntry<int> _textSize;

		public static ConfigEntry<Color> _fontColor;

		public static ConfigEntry<Color> _widgetBackgroundColor;

		public static ConfigEntry<Color> _settingDescriptionColor;

		public static ConfigEntry<Color> _closeButtonColor;

		public static ConfigEntry<Color> _cancelButtonColor;

		public static ConfigEntry<Color> _lightGreenSettingTextColor;

		public static ConfigEntry<Color> _saveButtonColor;

		public static ConfigEntry<Color> _leftPanelColor;

		public static ConfigEntry<Color> _panelBackgroundColor;

		public static ConfigEntry<Color> _categorySectionColor;

		public static ConfigEntry<Color> _categoryHeaderColor;

		public static ConfigEntry<Color> _lightGreySlidersColor;

		public static ConfigEntry<Color> _mediumGreySlidersColor;

		public static ConfigEntry<Color> _classTypeColor;

		public static ConfigEntry<Color> _highlightColor;

		public static ConfigEntry<Color> _defaultValueColor;

		public static ConfigEntry<Color> _rangeValueColor;

		internal Rect SettingWindowRect { get; private set; }

		internal int LeftColumnWidth { get; private set; }

		internal int RightColumnWidth { get; private set; }

		public bool DisplayingWindow
		{
			get
			{
				return _displayingWindow;
			}
			set
			{
				if (_displayingWindow == value)
				{
					return;
				}
				_displayingWindow = value;
				SettingFieldDrawer.ClearCache();
				if (_displayingWindow)
				{
					CalculateWindowRect();
					BuildSettingList();
					_focusSearchBox = true;
					ShowOverlayCanvas();
					if ((object)_curLockState != null)
					{
						_previousCursorLockState = (_obsoleteCursor ? Convert.ToInt32((bool)_curLockState.GetValue(null, null)) : ((int)_curLockState.GetValue(null, null)));
						_previousCursorVisible = (bool)_curVisible.GetValue(null, null);
					}
				}
				else
				{
					HideOverlayCanvas();
					if (!_previousCursorVisible || _previousCursorLockState != 0)
					{
						SetUnlockCursor(_previousCursorLockState, _previousCursorVisible);
					}
				}
				this.DisplayingWindowChanged?.Invoke(this, new ValueChangedEventArgs<bool>(value));
			}
		}

		public string SearchString
		{
			get
			{
				return _searchString;
			}
			private set
			{
				if (value == null)
				{
					value = string.Empty;
				}
				if (!(_searchString == value))
				{
					_searchString = value;
					BuildFilteredSettingList();
				}
			}
		}

		public event EventHandler<ValueChangedEventArgs<bool>> DisplayingWindowChanged;

		public ConfigurationManager()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Expected O, but got Unknown
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Expected O, but got Unknown
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			_fieldDrawer = new SettingFieldDrawer(this);
			_windowSize = ((BaseUnityPlugin)this).Config.Bind<Vector2>("General", "Window Size", new Vector2(0.55f, 0.95f), "Window size. The x is the width and the y is the height. This is a percent of screen to take up. 0.5 in the x is 50% of the screen width.");
			_textSize = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Font Size", 14, "Font Size");
			_fontColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Font Color", new Color(1f, 1f, 1f, 1f), "Font color");
			_widgetBackgroundColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Widget Color", GUIHelper.DarkGreenSaveButton, "Widget color");
			_settingDescriptionColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Description Color", GUIHelper.SettingDescription, "Description Color");
			_closeButtonColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Close Button Color", GUIHelper.RedCloseButton, "Color for the close button (#BF3030).");
			_cancelButtonColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Cancel Button Color", GUIHelper.DarkRedCancelButton, "Color for the cancel button (#541B1B).");
			_lightGreenSettingTextColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Light Green Setting Text Color", GUIHelper.LightGreenSettingText, "Light green color for setting text (#A7EDA7).");
			_saveButtonColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Save Button Color", GUIHelper.DarkGreenSaveButton, "Dark green color for save button (#1C401B).");
			_leftPanelColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Left Panel Color", GUIHelper.DarkGreyLeftPanel, "Dark grey background for the left panel (#262626).");
			_panelBackgroundColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Panel Background Color", GUIHelper.BlackPanelBackground, "Black background for the entire panel (#0D0D0D).");
			_categorySectionColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Category Section Color", GUIHelper.MediumBlackCategorySection, "Medium black background for category sections (#1F1F1F).");
			_categoryHeaderColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Category Header Color", GUIHelper.MediumBlackCategoryHeader, "Medium black background for category header (#121212).");
			_lightGreySlidersColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Light Grey Sliders Color", GUIHelper.LightGreySliders, "Light grey for sliders (#4C4C4C).");
			_mediumGreySlidersColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Medium Grey Sliders Color", GUIHelper.MediumGreySliders, "Medium grey for sliders (#404040).");
			_classTypeColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Class/Type Name Color", GUIHelper.GreenClassTypeName, "Green for class/type name (#148B32).");
			_defaultValueColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Default Value Label Color", GUIHelper.DefaultValueColor, "Default Value label color (#FFF4AC).");
			_rangeValueColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Range Value Label Color", GUIHelper.RangeValueColor, "Range Value label color.");
			_highlightColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Highlight Color", GUIHelper.YellowTanHighlight, "Yellow/tan highlight (#989076).");
			_showAdvanced = ((BaseUnityPlugin)this).Config.Bind<bool>("Filtering", "Show advanced", false, (ConfigDescription)null);
			_showKeybinds = ((BaseUnityPlugin)this).Config.Bind<bool>("Filtering", "Show keybinds", true, (ConfigDescription)null);
			_showSettings = ((BaseUnityPlugin)this).Config.Bind<bool>("Filtering", "Show settings", true, (ConfigDescription)null);
			_showDefault = ((BaseUnityPlugin)this).Config.Bind<bool>("Filtering", "Show default", true, (ConfigDescription)null);
			_keybind = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Show config manager", new KeyboardShortcut((KeyCode)282, (KeyCode[])(object)new KeyCode[0]), new ConfigDescription("The shortcut used to toggle the config manager window on and off.\nThe key can be overridden by a game-specific plugin if necessary, in that case this setting is ignored.", (AcceptableValueBase)null, new object[0]));
			_hideSingleSection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Hide single sections", false, new ConfigDescription("Show section title for plugins with only one section", (AcceptableValueBase)null, new object[0]));
			_pinnedPluginsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Pins", "Pinned plugins", "", new ConfigDescription("Comma-separated list of plugin GUIDs to pin to the top of the list. Use the GUID of the plugin to pin it, or use the configuration manager UI to pin it.", (AcceptableValueBase)null, new object[0]));
		}

		public static void RegisterCustomSettingDrawer(Type settingType, Action<SettingEntryBase> onGuiDrawer)
		{
			if ((object)settingType == null)
			{
				throw new ArgumentNullException("settingType");
			}
			if (onGuiDrawer == null)
			{
				throw new ArgumentNullException("onGuiDrawer");
			}
			if (SettingFieldDrawer.SettingDrawHandlers.ContainsKey(settingType))
			{
				Logger.LogWarning((object)("Tried to add a setting drawer for type " + settingType.FullName + " while one already exists."));
			}
			else
			{
				SettingFieldDrawer.SettingDrawHandlers[settingType] = onGuiDrawer;
			}
		}

		public void BuildSettingList()
		{
			SettingSearcher.CollectSettings(out var results, out var modsWithoutSettings, _showDebug);
			_modsWithoutSettings = string.Join(", ", (from x in modsWithoutSettings
				select x.TrimStart(new char[1] { '!' }) into x
				orderby x
				select x).ToArray());
			_allSettings = results.ToList();
			BuildFilteredSettingList();
		}

		private void BuildFilteredSettingList()
		{
			for (int i = 0; i < _filteredSetings.Count; i++)
			{
				PluginSettingsData data = _filteredSetings[i];
				PluginSettingsDataPool.Release(data);
			}
			_filteredSetings.Clear();
			IEnumerable<SettingEntryBase> source = _allSettings;
			string[] searchStrings = SearchString.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (searchStrings.Length != 0)
			{
				source = source.Where((SettingEntryBase x) => ContainsSearchString(x, searchStrings));
			}
			else
			{
				if (!_showAdvanced.Value)
				{
					source = source.Where((SettingEntryBase x) => !x.IsAdvanced.GetValueOrDefault());
				}
				if (!_showKeybinds.Value)
				{
					source = source.Where((SettingEntryBase x) => !IsKeyboardShortcut(x));
				}
				if (!_showSettings.Value)
				{
					source = source.Where((SettingEntryBase x) => x.IsAdvanced.GetValueOrDefault() || IsKeyboardShortcut(x));
				}
				if (!_showDefault.Value)
				{
					source = source.Where((SettingEntryBase x) => x.DefaultValue != null && x.Get() != null && !x.Get().Equals(x.DefaultValue));
				}
			}
			_filteredSetings = (from x in (from x in source
					group x by x.PluginInfo).Select(delegate(IGrouping<BepInPlugin, SettingEntryBase> pluginSettings)
				{
					IEnumerable<PluginSettingsData.PluginSettingsGroupData> source2 = from eb in pluginSettings
						group eb by eb.Category into x
						orderby string.Equals(x.Key, "Keyboard shortcuts", StringComparison.Ordinal), x.Key
						select new PluginSettingsData.PluginSettingsGroupData
						{
							Name = x.Key,
							Settings = (from set in x
								orderby set.Order descending, set.DispName
								select set).ToList()
						};
					string website = Utils.GetWebsite(pluginSettings.First().PluginInstance);
					return PluginSettingsDataPool.Get(pluginSettings.Key, source2.ToList(), website);
				})
				orderby x.Info.Name
				select x).ToList();
			_filteredSetings = (from p in _filteredSetings
				orderby IsPinned(p.Info.GUID) descending, p.Info.Name
				select p).ToList();
		}

		private static bool IsKeyboardShortcut(SettingEntryBase x)
		{
			return (object)x.SettingType == typeof(KeyboardShortcut) || (object)x.SettingType == typeof(KeyCode);
		}

		private static bool ContainsSearchString(SettingEntryBase setting, string[] searchStrings)
		{
			string combinedSearchTarget = setting.PluginInfo.Name + Environment.NewLine + setting.PluginInfo.GUID + Environment.NewLine + setting.DispName + Environment.NewLine + setting.Category + Environment.NewLine + setting.Description + Environment.NewLine + setting.DefaultValue?.ToString() + Environment.NewLine + setting.Get();
			return searchStrings.All((string s) => combinedSearchTarget.IndexOf(s, StringComparison.InvariantCultureIgnoreCase) >= 0);
		}

		private void CalculateWindowRect()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			float x = _windowSize.Value.x;
			float y = _windowSize.Value.y;
			float num = Mathf.Clamp((float)Screen.width * x, 400f, (float)Screen.width * x);
			float num2 = Mathf.Clamp((float)Screen.height * y, 300f, (float)Screen.height * y);
			int num3 = Mathf.RoundToInt(((float)Screen.width - num) / 2f);
			int num4 = Mathf.RoundToInt(((float)Screen.height - num2) / 2f);
			SettingWindowRect = new Rect((float)num3, (float)num4, num, num2);
			_screenRect = new Rect(0f, 0f, (float)Screen.width, (float)Screen.height);
			Rect settingWindowRect = SettingWindowRect;
			LeftColumnWidth = Mathf.RoundToInt(((Rect)(ref settingWindowRect)).width / 3.5f);
			settingWindowRect = SettingWindowRect;
			RightColumnWidth = (int)((Rect)(ref settingWindowRect)).width - LeftColumnWidth;
			_windowWasMoved = false;
		}

		private void OnGUI()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			if (!DisplayingWindow)
			{
				return;
			}
			if ((int)Event.current.type == 5)
			{
				KeyCode keyCode = Event.current.keyCode;
				KeyboardShortcut value = _keybind.Value;
				if (keyCode == ((KeyboardShortcut)(ref value)).MainKey)
				{
					DisplayingWindow = false;
					return;
				}
			}
			Rect settingWindowRect;
			if ((int)Event.current.type == 0)
			{
				Vector2 mousePosition = Event.current.mousePosition;
				settingWindowRect = SettingWindowRect;
				if (!((Rect)(ref settingWindowRect)).Contains(mousePosition))
				{
					DisplayingWindow = false;
				}
			}
			if (_textSize.Value > 9 && _textSize.Value < 100)
			{
				ImguiUtils.fontSize = Mathf.Clamp(_textSize.Value, 10, 30);
			}
			ImguiUtils.CreateBackgrounds();
			ImguiUtils.CreateStyles();
			SetUnlockCursor(0, cursorVisible: true);
			Vector2 val = Vector2.op_Implicit(UnityInput.Current.mousePosition);
			val.y = (float)Screen.height - val.y;
			if (!_windowWasMoved)
			{
				if (GUI.Button(_screenRect, string.Empty, GUI.skin.box))
				{
					settingWindowRect = SettingWindowRect;
					if (!((Rect)(ref settingWindowRect)).Contains(val))
					{
						DisplayingWindow = false;
					}
				}
				ImguiUtils.DrawWindowBackground(SettingWindowRect);
			}
			Rect val2 = GUIHelper.CreateWindowWithColor(-68, SettingWindowRect, new WindowFunction(SettingsWindow), "Configuration Manager 18.3.1", _panelBackgroundColor.Value);
			GUI.FocusWindow(-68);
			if (val2 != SettingWindowRect)
			{
				_windowWasMoved = true;
				SettingWindowRect = val2;
				_tipsWindowWasMoved = true;
			}
			if (SettingFieldDrawer.SettingKeyboardShortcut)
			{
				return;
			}
			if (_windowWasMoved)
			{
				settingWindowRect = SettingWindowRect;
				if (!((Rect)(ref settingWindowRect)).Contains(val))
				{
					return;
				}
			}
			Input.ResetInputAxes();
		}

		private static void DrawTooltip(Rect area)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			string tooltip = GUI.tooltip;
			if (!string.IsNullOrEmpty(tooltip))
			{
				GUIStyle val = GUI.skin.box.CreateCopy();
				val.wordWrap = true;
				val.alignment = (TextAnchor)4;
				GUIContent val2 = new GUIContent(tooltip);
				float num = val.CalcHeight(val2, 400f) + 10f;
				Vector2 mousePosition = Event.current.mousePosition;
				float num2 = ((mousePosition.x + 400f > ((Rect)(ref area)).width) ? (((Rect)(ref area)).width - 400f) : mousePosition.x);
				float num3 = ((mousePosition.y + 25f + num > ((Rect)(ref area)).height) ? (mousePosition.y - num) : (mousePosition.y + 25f));
				Rect val3 = default(Rect);
				((Rect)(ref val3))..ctor(num2, num3, 400f, num);
				ImguiUtils.DrawControlBackground(val3, Color.black);
				val.Draw(val3, val2, -1);
			}
		}

		private void SettingsWindow(int id)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Invalid comparison between Unknown and I4
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0585: Unknown result type (might be due to invalid IL or missing references)
			//IL_0528: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Expected O, but got Unknown
			Rect val = SettingWindowRect;
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref val)).width, 20f));
			DrawWindowHeader();
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.MaxWidth((float)(LeftColumnWidth + RightColumnWidth))
			});
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.MaxWidth((float)LeftColumnWidth),
				GUILayout.ExpandWidth(true)
			});
			GUILayout.BeginHorizontal(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			if (GUIHelper.CreateButtonWithColor("Plugins", default(Color), ImguiUtils.buttonStyle, GUILayout.ExpandWidth(true)))
			{
				_selectedTab = Tab.Plugins;
				_selectedPluginName = null;
				_selectedOtherFile = null;
			}
			if (GUIHelper.CreateButtonWithColor("Other Config Files", default(Color), ImguiUtils.buttonStyle, GUILayout.ExpandWidth(true)))
			{
				_selectedTab = Tab.OtherFiles;
				_selectedPluginName = null;
				_selectedOtherFile = null;
			}
			GUILayout.EndHorizontal();
			_pluginWindowScrollPos = GUILayout.BeginScrollView(_pluginWindowScrollPos, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			if (_selectedTab == Tab.Plugins)
			{
				int i = _tipsHeight;
				PluginSettingsData pluginSettingsData;
				for (int j = 0; j < _filteredSetings.Count; i += pluginSettingsData.Height, j++)
				{
					pluginSettingsData = _filteredSetings[j];
					if (pluginSettingsData.Height != 0)
					{
						if ((float)(i + pluginSettingsData.Height) >= _pluginWindowScrollPos.y)
						{
							float num = i;
							float y = _pluginWindowScrollPos.y;
							val = SettingWindowRect;
							if (num <= y + ((Rect)(ref val)).height)
							{
								goto IL_01c1;
							}
						}
						try
						{
							GUILayout.Space((float)pluginSettingsData.Height);
						}
						catch (ArgumentException)
						{
						}
						continue;
					}
					goto IL_01c1;
					IL_01c1:
					try
					{
						DrawSinglePlugin(pluginSettingsData);
					}
					catch (ArgumentException)
					{
					}
					if (pluginSettingsData.Height == 0 && (int)Event.current.type == 7)
					{
						val = GUILayoutUtility.GetLastRect();
						pluginSettingsData.Height = (int)((Rect)(ref val)).height;
					}
				}
			}
			else if (_selectedTab == Tab.OtherFiles)
			{
				foreach (string otherConfigFile in SettingSearcher.OtherConfigFiles)
				{
					DrawOtherFile(otherConfigFile);
				}
			}
			if (_showDebug)
			{
				GUILayout.Space(10f);
				GUIHelper.BeginColor(_fontColor.Value);
				GUILayout.Label("Plugins with no options available: " + _modsWithoutSettings, (GUILayoutOption[])(object)new GUILayoutOption[0]);
				GUIHelper.EndColor();
			}
			else
			{
				GUILayout.Space(70f);
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			GUILayout.Box(GUIContent.none, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(1f),
				GUILayout.ExpandHeight(true)
			});
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.MaxWidth((float)RightColumnWidth),
				GUILayout.ExpandWidth(false)
			});
			_settingWindowScrollPos = GUILayout.BeginScrollView(_settingWindowScrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
			if (_selectedTab == Tab.Plugins)
			{
				if (string.IsNullOrEmpty(_selectedPluginName))
				{
					GUIHelper.BeginColor(_fontColor.Value);
					GUILayout.Label("Select a plugin from the left column to view settings.", (GUILayoutOption[])(object)new GUILayoutOption[0]);
					GUIHelper.EndColor();
				}
				else
				{
					PluginSettingsData pluginSettingsData2 = _filteredSetings.FirstOrDefault((PluginSettingsData p) => p.Info.Name == _selectedPluginName);
					if (pluginSettingsData2 != null)
					{
						GUIHelper.CreateLabelWithColor("Editing: " + pluginSettingsData2.Info.Name, _fontColor.Value, ImguiUtils.labelStyle, GUILayout.ExpandWidth(false));
						GUILayout.BeginHorizontal(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
						GUIStyle val2 = new GUIStyle(GUI.skin.button);
						if (GUILayout.Button("Reset All Settings For " + pluginSettingsData2.Info.Name, val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
						{
							foreach (PluginSettingsData.PluginSettingsGroupData category in pluginSettingsData2.Categories)
							{
								foreach (SettingEntryBase setting in category.Settings)
								{
									setting.Set(setting.DefaultValue);
								}
							}
							BuildFilteredSettingList();
						}
						GUILayout.EndHorizontal();
						DrawPluginSettings(pluginSettingsData2);
					}
					else
					{
						GUIHelper.BeginColor(_fontColor.Value);
						GUILayout.Label("Plugin not found.", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)RightColumnWidth) });
						GUIHelper.EndColor();
					}
				}
			}
			else if (_selectedTab == Tab.OtherFiles)
			{
				if (string.IsNullOrEmpty(_selectedOtherFile))
				{
					GUIHelper.BeginColor(_fontColor.Value);
					GUILayout.Label("Select a file from the left column to edit.", (GUILayoutOption[])(object)new GUILayoutOption[0]);
					GUIHelper.EndColor();
				}
				else
				{
					DrawOtherFileEditor(_selectedOtherFile);
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			if (!SettingFieldDrawer.DrawCurrentDropdown())
			{
				DrawTooltip(SettingWindowRect);
			}
		}

		private void DrawTips()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			string text = ((!_tipsPluginHeaderWasClicked) ? "Tip: Click plugin names to expand. Click setting and group names to see their descriptions." : ((!_tipsWindowWasMoved) ? "Tip: You can drag this window to move it. It will stay open while you interact with the game." : null));
			if (text != null)
			{
				GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
				GUIHelper.BeginColor(_fontColor.Value);
				GUILayout.Label(text, (GUILayoutOption[])(object)new GUILayoutOption[0]);
				GUIHelper.EndColor();
				GUILayout.EndHorizontal();
			}
		}

		private void DrawOtherFileEditor(string filePath)
		{
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GUIHelper.BeginColor(_fontColor.Value);
				GUILayout.Label("Editing: " + Path.GetFileName(filePath), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				GUIHelper.EndColor();
				if (!_otherFileContents.TryGetValue(filePath, out var value))
				{
					value = File.ReadAllText(filePath);
					_otherFileContents[filePath] = value;
				}
				GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
				if (GUIHelper.CreateButtonWithColor("Save", _saveButtonColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
				{
					File.WriteAllText(filePath, _otherFileContents[filePath]);
					Logger.LogInfo((object)("File saved: " + filePath));
				}
				if (GUIHelper.CreateButtonWithColor("Open File Location", _saveButtonColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
				{
					Utils.OpenFileLocation(filePath);
				}
				GUILayout.FlexibleSpace();
				if (GUIHelper.CreateButtonWithColor("Delete File", _closeButtonColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
				{
					File.Delete(filePath);
					_otherFileContents.Remove(filePath);
					Logger.LogInfo((object)("File deleted: " + filePath));
					_selectedOtherFile = null;
				}
				GUILayout.EndHorizontal();
				GUI.SetNextControlName("fileEditor");
				string text = GUILayout.TextArea(value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
				if (text != _otherFileContents[filePath])
				{
					_otherFileContents[filePath] = text;
				}
				if (GUI.GetNameOfFocusedControl() == "fileEditor")
				{
					GUI.FocusWindow(-68);
					GUI.FocusControl("fileEditor");
				}
			}
			catch (Exception ex)
			{
				GUIHelper.CreateLabelWithColor("Failed to load or edit file: " + ex.Message, _fontColor.Value, ImguiUtils.labelStyle, GUILayout.ExpandWidth(false));
			}
		}

		private void DrawWindowHeader()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			GUI.enabled = SearchString == string.Empty;
			bool value = _showSettings.Value;
			GUIStyle toggleStyle = ImguiUtils.toggleStyle;
			bool flag = GUIHelper.CreateToggleWithColor(value, "Normal settings", default(Color), toggleStyle);
			if (_showSettings.Value != flag)
			{
				_showSettings.Value = flag;
				BuildFilteredSettingList();
			}
			bool value2 = _showDefault.Value;
			toggleStyle = ImguiUtils.toggleStyle;
			flag = GUIHelper.CreateToggleWithColor(value2, "Show Default", default(Color), toggleStyle);
			if (_showDefault.Value != flag)
			{
				_showDefault.Value = flag;
				BuildFilteredSettingList();
			}
			bool value3 = _showKeybinds.Value;
			toggleStyle = ImguiUtils.toggleStyle;
			flag = GUIHelper.CreateToggleWithColor(value3, "Keyboard shortcuts", default(Color), toggleStyle);
			if (_showKeybinds.Value != flag)
			{
				_showKeybinds.Value = flag;
				BuildFilteredSettingList();
			}
			flag = GUIHelper.CreateToggleWithColor(_showAdvanced.Value, "Advanced settings", _advancedSettingColor, null);
			if (_showAdvanced.Value != flag)
			{
				_showAdvanced.Value = flag;
				BuildFilteredSettingList();
			}
			GUI.enabled = true;
			GUILayout.Space(8f);
			bool showDebug = _showDebug;
			toggleStyle = ImguiUtils.toggleStyle;
			flag = GUIHelper.CreateToggleWithColor(showDebug, "Debug info", default(Color), toggleStyle);
			if (_showDebug != flag)
			{
				_showDebug = flag;
				BuildSettingList();
			}
			toggleStyle = ImguiUtils.buttonStyle;
			if (GUIHelper.CreateButtonWithColor("Open BepInEx Log", default(Color), toggleStyle))
			{
				try
				{
					Utils.OpenBepInExLog();
				}
				catch (SystemException ex)
				{
					Logger.Log((LogLevel)10, (object)ex.Message);
				}
			}
			toggleStyle = ImguiUtils.buttonStyle;
			if (GUIHelper.CreateButtonWithColor("Open Player Log", default(Color), toggleStyle))
			{
				try
				{
					Utils.OpenLog();
				}
				catch (SystemException ex2)
				{
					Logger.Log((LogLevel)10, (object)ex2.Message);
				}
			}
			GUILayout.Space(8f);
			if (GUIHelper.CreateButtonWithColor("Close", _closeButtonColor.Value, ImguiUtils.buttonStyle))
			{
				DisplayingWindow = false;
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			GUIHelper.CreateLabelWithColor("Search: ", _fontColor.Value, ImguiUtils.labelStyle, GUILayout.ExpandWidth(false));
			GUI.SetNextControlName("searchBox");
			SearchString = GUILayout.TextField(SearchString, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (_focusSearchBox)
			{
				GUI.FocusWindow(-68);
				GUI.FocusControl("searchBox");
				_focusSearchBox = false;
			}
			if (GUIHelper.CreateButtonWithColor("Clear", _widgetBackgroundColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
			{
				SearchString = string.Empty;
			}
			GUILayout.EndHorizontal();
		}

		private void DrawSinglePlugin(PluginSettingsData plugin)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			GUIStyle val = GUI.skin.box.CreateCopy();
			Texture2D texture2D = TexturePool.GetTexture2D(1, 1, (TextureFormat)4, mipChain: false);
			texture2D.SetPixel(0, 0, _highlightColor.Value);
			texture2D.Apply();
			val.hover.background = texture2D;
			val.fontSize = ImguiUtils.fontSize;
			GUILayout.BeginVertical(val, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			GUIContent content = new GUIContent($"{plugin.Info.Name.TrimStart(new char[1] { '!' })} {plugin.Info.Version}", (Texture)null, "GUID: " + plugin.Info.GUID);
			bool flag = !string.IsNullOrEmpty(SearchString);
			bool flag2 = plugin.Website != null;
			if (flag2)
			{
				GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
				GUILayout.Space(29f);
			}
			if (SettingFieldDrawer.DrawPluginHeader(content) && !flag)
			{
				_tipsPluginHeaderWasClicked = true;
				_selectedPluginName = plugin.Info.Name;
			}
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
			GUILayout.FlexibleSpace();
			if (IsPinned(plugin.Info.GUID))
			{
				if (GUIHelper.CreateButtonWithColor("Unpin", _closeButtonColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
				{
					UnpinPlugin(plugin.Info.GUID);
					BuildFilteredSettingList();
				}
			}
			else if (GUIHelper.CreateButtonWithColor("Pin", _saveButtonColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
			{
				PinPlugin(plugin.Info.GUID);
				BuildFilteredSettingList();
			}
			GUILayout.EndHorizontal();
			if (flag2)
			{
				if (GUIHelper.CreateButtonWithColor(new GUIContent("URL", (Texture)null, plugin.Website), GUI.skin.label, Color.gray, GUILayout.ExpandWidth(false)))
				{
					Utils.OpenWebsite(plugin.Website);
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndVertical();
		}

		private void DrawPluginSettings(PluginSettingsData selectedPlugin)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Invalid comparison between Unknown and I4
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Invalid comparison between Unknown and I4
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			float y = _settingWindowScrollPos.y;
			Rect val = SettingWindowRect;
			float height = ((Rect)(ref val)).height;
			float num = 0f;
			foreach (PluginSettingsData.PluginSettingsGroupData category in selectedPlugin.Categories)
			{
				float num2 = category.CalculatedHeight;
				if (num2 != 0f && (!(num + num2 >= y) || !(num <= y + height)))
				{
					GUILayout.Space(num2);
					num += num2;
					continue;
				}
				float num3 = 0f;
				if ((int)Event.current.type == 7)
				{
					val = GUILayoutUtility.GetLastRect();
					num3 = ((Rect)(ref val)).yMax;
				}
				GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				if (!string.IsNullOrEmpty(category.Name))
				{
					SettingFieldDrawer.DrawCategoryHeader(category.Name);
				}
				foreach (SettingEntryBase setting in category.Settings)
				{
					DrawSingleSetting(setting);
					GUILayout.Space(2f);
				}
				GUILayout.EndVertical();
				if ((int)Event.current.type == 7)
				{
					val = GUILayoutUtility.GetLastRect();
					float yMax = ((Rect)(ref val)).yMax;
					num2 = (category.CalculatedHeight = yMax - num3);
				}
				num += num2;
			}
		}

		private void DrawOtherFile(string file)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.GetExtension(file).ToUpperInvariant().TrimStart(new char[1] { '.' });
			GUIContent content = (_showDebug ? new GUIContent(Path.GetFileName(file) + " (" + text + ")", (Texture)null, "File Type: " + text) : new GUIContent(Path.GetFileName(file) + " (" + text + ")"));
			bool flag = !string.IsNullOrEmpty(SearchString);
			GUIStyle val = GUI.skin.box.CreateCopy();
			Texture2D texture2D = TexturePool.GetTexture2D(1, 1, (TextureFormat)4, mipChain: false);
			texture2D.SetPixel(0, 0, _highlightColor.Value);
			texture2D.Apply();
			val.hover.background = texture2D;
			GUILayout.BeginVertical(val, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			if (SettingFieldDrawer.DrawPluginHeader(content) && !flag)
			{
				_tipsPluginHeaderWasClicked = true;
				_selectedOtherFile = file;
			}
			GUILayout.EndVertical();
		}

		private void DrawSingleSetting(SettingEntryBase setting)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = GUI.skin.box.CreateCopy();
			bool flag = setting.DefaultValue != null && setting.Get() != null && setting.Get().Equals(setting.DefaultValue);
			val.normal.background = ImguiUtils.MakeTexture(1, 1, (Color)(flag ? _categorySectionColor.Value : new Color(_categorySectionColor.Value.r / 2f, _categorySectionColor.Value.g / 2f, _categorySectionColor.Value.b / 2f, _categorySectionColor.Value.a)));
			GUILayout.BeginHorizontal(val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
			try
			{
				DrawSettingName(setting);
				if (!flag)
				{
					DrawDefaultButton(setting);
				}
			}
			catch (Exception arg)
			{
				Logger.Log((LogLevel)2, (object)$"Failed to draw setting {setting.DispName} - {arg}");
				GUIHelper.CreateLabelWithColor("Failed to draw this field, check log for details.", _fontColor.Value, ImguiUtils.labelStyle);
			}
			GUILayout.EndHorizontal();
		}

		private void DrawSettingName(SettingEntryBase setting)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			if (!setting.HideSettingName)
			{
				GUIStyle val = GUI.skin.label.CreateCopy();
				val.wordWrap = true;
				val.fontStyle = (FontStyle)1;
				val.normal.textColor = _lightGreenSettingTextColor.Value;
				GUIStyle val2 = GUI.skin.label.CreateCopy();
				val2.wordWrap = true;
				val2.fontStyle = (FontStyle)2;
				val2.normal.textColor = _settingDescriptionColor.Value;
				GUIStyle val3 = GUI.skin.label.CreateCopy();
				val3.wordWrap = true;
				val3.fontStyle = (FontStyle)2;
				val3.normal.textColor = _classTypeColor.Value;
				GUIStyle val4 = GUI.skin.label.CreateCopy();
				val4.wordWrap = true;
				val4.fontStyle = (FontStyle)2;
				val4.normal.textColor = _rangeValueColor.Value;
				GUIStyle val5 = GUI.skin.label.CreateCopy();
				val5.wordWrap = true;
				val5.fontStyle = (FontStyle)3;
				val5.normal.textColor = _defaultValueColor.Value;
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.ExpandWidth(false),
					GUILayout.MaxWidth((float)RightColumnWidth)
				});
				GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				GUILayout.Label(setting.DispName.TrimStart(new char[1] { '!' }), val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				GUILayout.Label(" (" + setting.SettingType.Name + ")", val3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				if (setting.AcceptableValueRange.Key != null)
				{
					object key = setting.AcceptableValueRange.Key;
					object value = setting.AcceptableValueRange.Value;
					GUILayout.Label($" [{key} - {value}]", val4, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				}
				if (setting.DefaultValue != null)
				{
					GUILayout.Label($" Default: {setting.DefaultValue}", val5, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				}
				GUILayout.EndHorizontal();
				if (!string.IsNullOrEmpty(setting.Description))
				{
					GUILayout.Label(setting.Description, val2, (GUILayoutOption[])(object)new GUILayoutOption[0]);
				}
				_fieldDrawer.DrawSettingValue(setting);
				GUILayout.EndVertical();
			}
			else
			{
				_fieldDrawer.DrawSettingValue(setting);
			}
		}

		private static void DrawDefaultButton(SettingEntryBase setting)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (setting.HideDefaultButton)
			{
				return;
			}
			GUIHelper.BeginColor(_widgetBackgroundColor.Value);
			object defaultValue = setting.DefaultValue;
			if (defaultValue != null || setting.SettingType.IsClass)
			{
				GUILayout.Space(5f);
				if (GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
				{
					setting.Set(defaultValue);
				}
			}
			GUIHelper.EndColor();
		}

		public static void PinPlugin(string pluginName)
		{
			if (!_pinnedPlugins.Contains(pluginName))
			{
				_pinnedPlugins.Add(pluginName);
			}
			UpdatePluginConfig();
		}

		public static void UnpinPlugin(string pluginName)
		{
			_pinnedPlugins.Remove(pluginName);
			UpdatePluginConfig();
		}

		public static bool IsPinned(string pluginName)
		{
			return _pinnedPlugins.Contains(pluginName);
		}

		public static void UpdatePluginConfig()
		{
			string value = string.Join(",", _pinnedPlugins.ToArray());
			SettingFieldDrawer._instance._pinnedPluginsConfig.Value = value;
			((BaseUnityPlugin)SettingFieldDrawer._instance).Config.Save();
		}

		private void LoadPinnedPluginsFromConfig()
		{
			string value = _pinnedPluginsConfig.Value;
			if (!string.IsNullOrEmpty(value))
			{
				_pinnedPlugins = new HashSet<string>(value.Split(new char[1] { ',' }));
			}
		}

		private void CreateOverlayCanvas()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_overlayCanvasObj != (Object)null))
			{
				_overlayCanvasObj = new GameObject("ConfigurationManagerOverlayCanvas");
				Object.DontDestroyOnLoad((Object)(object)_overlayCanvasObj);
				_overlayCanvas = _overlayCanvasObj.AddComponent<Canvas>();
				_overlayCanvasScaler = _overlayCanvasObj.AddComponent<CanvasScaler>();
				_overlayRaycaster = _overlayCanvasObj.AddComponent<GraphicRaycaster>();
				_overlayCanvas.renderMode = (RenderMode)0;
				_overlayCanvas.sortingOrder = 9999;
				GameObject val = new GameObject("ConfigurationManagerBlockerImage");
				val.transform.SetParent(_overlayCanvasObj.transform, false);
				_overlayBlocker = val.AddComponent<Image>();
				((Graphic)_overlayBlocker).color = new Color(0f, 0f, 0f, 0.5f);
				((Graphic)_overlayBlocker).raycastTarget = true;
				RectTransform rectTransform = ((Graphic)_overlayBlocker).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
			}
		}

		private void ShowOverlayCanvas()
		{
			if ((Object)(object)_overlayCanvasObj == (Object)null)
			{
				CreateOverlayCanvas();
			}
			_overlayCanvasObj.SetActive(true);
		}

		private void HideOverlayCanvas()
		{
			if ((Object)(object)_overlayCanvasObj != (Object)null)
			{
				_overlayCanvasObj.SetActive(false);
			}
		}

		private void Start()
		{
			LoadPinnedPluginsFromConfig();
			Type typeFromHandle = typeof(Cursor);
			_curLockState = typeFromHandle.GetProperty("lockState", BindingFlags.Static | BindingFlags.Public);
			_curVisible = typeFromHandle.GetProperty("visible", BindingFlags.Static | BindingFlags.Public);
			if ((object)_curLockState == null && (object)_curVisible == null)
			{
				_obsoleteCursor = true;
				_curLockState = typeof(Screen).GetProperty("lockCursor", BindingFlags.Static | BindingFlags.Public);
				_curVisible = typeof(Screen).GetProperty("showCursor", BindingFlags.Static | BindingFlags.Public);
			}
			try
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			catch (IOException ex)
			{
				Logger.Log((LogLevel)12, (object)("WARNING: Failed to write to config directory, expect issues!\nError message:" + ex.Message));
			}
			catch (UnauthorizedAccessException ex2)
			{
				Logger.Log((LogLevel)12, (object)("WARNING: Permission denied to write to config directory, expect issues!\nError message:" + ex2.Message));
			}
		}

		private void Update()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Invalid comparison between Unknown and I4
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Invalid comparison between Unknown and I4
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Invalid comparison between Unknown and I4
			if (DisplayingWindow)
			{
				SetUnlockCursor(0, cursorVisible: true);
				if (GUI.GetNameOfFocusedControl() == "fileEditor" && ((int)Event.current.type == 4 || (int)Event.current.type == 5) && Event.current.isKey)
				{
					Input.ResetInputAxes();
					if (Input.GetKeyDown((KeyCode)27))
					{
						GUI.FocusControl((string)null);
						Event.current.Use();
					}
					if ((int)Event.current.keyCode == 9 && (int)Event.current.type == 5)
					{
						GUIUtility.keyboardControl = 0;
						GUIUtility.hotControl = 0;
						Event.current.Use();
						GUIUtility.ExitGUI();
					}
					if ((int)Event.current.keyCode == 13 && (int)Event.current.type == 5)
					{
						GUIUtility.keyboardControl = 0;
						GUIUtility.hotControl = 0;
						Event.current.Use();
						GUIUtility.ExitGUI();
					}
					return;
				}
			}
			if (!OverrideHotkey && !DisplayingWindow)
			{
				KeyboardShortcut value = _keybind.Value;
				if (((KeyboardShortcut)(ref value)).IsUp())
				{
					ImguiUtils.CreateBackgrounds();
					DisplayingWindow = true;
				}
			}
		}

		private void LateUpdate()
		{
			if (DisplayingWindow)
			{
				SetUnlockCursor(0, cursorVisible: true);
			}
		}

		private void OnDestroy()
		{
			TexturePool.ClearAll();
			PluginSettingsDataPool.ClearAll();
			GC.Collect();
		}

		private void SetUnlockCursor(int lockState, bool cursorVisible)
		{
			if ((object)_curLockState != null)
			{
				if (_obsoleteCursor)
				{
					_curLockState.SetValue(null, Convert.ToBoolean(lockState), null);
				}
				else
				{
					_curLockState.SetValue(null, lockState, null);
				}
				_curVisible.SetValue(null, cursorVisible, null);
			}
		}
	}
	internal class PropertySettingEntry : SettingEntryBase
	{
		private Type _settingType;

		public object Instance { get; internal set; }

		public PropertyInfo Property { get; internal set; }

		public override string DispName
		{
			get
			{
				return string.IsNullOrEmpty(base.DispName) ? Property.Name : base.DispName;
			}
			protected internal set
			{
				base.DispName = value;
			}
		}

		public override Type SettingType => _settingType ?? (_settingType = Property.PropertyType);

		public PropertySettingEntry(object instance, PropertyInfo settingProp, BaseUnityPlugin pluginInstance)
		{
			SetFromAttributes(settingProp.GetCustomAttributes(inherit: false), pluginInstance);
			if (!base.Browsable.HasValue)
			{
				base.Browsable = settingProp.CanRead && settingProp.CanWrite;
			}
			base.ReadOnly = settingProp.CanWrite;
			Property = settingProp;
			Instance = instance;
		}

		public override object Get()
		{
			return Property.GetValue(Instance, null);
		}

		protected override void SetValue(object newVal)
		{
			Property.SetValue(Instance, newVal, null);
		}
	}
	public abstract class SettingEntryBase
	{
		public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

		private static readonly PropertyInfo[] _myProperties = typeof(SettingEntryBase).GetProperties(BindingFlags.Instance | BindingFlags.Public);

		public object[] AcceptableValues { get; protected set; }

		public KeyValuePair<object, object> AcceptableValueRange { get; protected set; }

		public bool? ShowRangeAsPercent { get; protected set; }

		public Action<ConfigEntryBase> CustomDrawer { get; private set; }

		public CustomHotkeyDrawerFunc CustomHotkeyDrawer { get; private set; }

		public bool? Browsable { get; protected set; }

		public string Category { get; protected set; }

		public object DefaultValue { get; protected set; }

		public bool HideDefaultButton { get; protected set; }

		public bool HideSettingName { get; protected set; }

		public string Description { get; protected internal set; }

		public virtual string DispName { get; protected internal set; }

		public BepInPlugin PluginInfo { get; protected internal set; }

		public bool? ReadOnly { get; protected set; }

		public abstract Type SettingType { get; }

		public BaseUnityPlugin PluginInstance { get; private set; }

		public bool? IsAdvanced { get; internal set; }

		public int Order { get; protected set; }

		public Func<object, string> ObjToStr { get; internal set; }

		public Func<string, object> StrToObj { get; internal set; }

		public abstract object Get();

		public void Set(object newVal)
		{
			if (!ReadOnly.GetValueOrDefault())
			{
				SetValue(newVal);
			}
		}

		protected abstract void SetValue(object newVal);

		internal void SetFromAttributes(object[] attribs, BaseUnityPlugin pluginInstance)
		{
			PluginInstance = pluginInstance;
			PluginInfo = ((pluginInstance != null) ? pluginInstance.Info.Metadata : null);
			if (attribs == null || attribs.Length == 0)
			{
				return;
			}
			foreach (object obj in attribs)
			{
				object obj2 = obj;
				object obj3 = obj2;
				if (obj3 == null)
				{
					continue;
				}
				if (!(obj3 is DisplayNameAttribute displayNameAttribute))
				{
					if (!(obj3 is CategoryAttribute categoryAttribute))
					{
						if (!(obj3 is DescriptionAttribute descriptionAttribute))
						{
							if (!(obj3 is DefaultValueAttribute defaultValueAttribute))
							{
								if (!(obj3 is ReadOnlyAttribute readOnlyAttribute))
								{
									if (!(obj3 is BrowsableAttribute browsableAttribute))
									{
										Action<SettingEntryBase> action = obj3 as Action<SettingEntryBase>;
										if (action == null)
										{
											if (obj3 is string text)
											{
												switch (text)
												{
												case "ReadOnly":
													ReadOnly = true;
													break;
												case "Browsable":
													Browsable = true;
													break;
												case "Unbrowsable":
												case "Hidden":
													Browsable = false;
													break;
												case "Advanced":
													IsAdvanced = true;
													break;
												}
												continue;
											}
											Type type = obj.GetType();
											if (!(type.Name == "ConfigurationManagerAttributes"))
											{
												break;
											}
											FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
											foreach (var item in from my in _myProperties
												join other in fields on my.Name equals other.Name
												select new { my, other })
											{
												try
												{
													object obj4 = item.other.GetValue(obj);
													if (obj4 != null)
													{
														if ((object)item.my.PropertyType != item.other.FieldType && typeof(Delegate).IsAssignableFrom(item.my.PropertyType))
														{
															obj4 = Delegate.CreateDelegate(item.my.PropertyType, ((Delegate)obj4).Target, ((Delegate)obj4).Method);
														}
														item.my.SetValue(this, obj4, null);
													}
												}
												catch (Exception ex)
												{
													ConfigurationManager.Logger.LogWarning((object)("Failed to copy value " + item.my.Name + " from provided tag object " + type.FullName + " - " + ex.Message));
												}
											}
										}
										else
										{
											CustomDrawer = delegate
											{
												action(this);
											};
										}
									}
									else
									{
										Browsable = browsableAttribute.Browsable;
									}
								}
								else
								{
									ReadOnly = readOnlyAttribute.IsReadOnly;
								}
							}
							else
							{
								DefaultValue = defaultValueAttribute.Value;
							}
						}
						else
						{
							Description = descriptionAttribute.Description;
						}
					}
					else
					{
						Category = categoryAttribute.Category;
					}
				}
				else
				{
					DispName = displayNameAttribute.DisplayName;
				}
			}
		}
	}
	internal class SettingFieldDrawer
	{
		private sealed class FloatConfigCacheEntry
		{
			public float Value = 0f;

			public string FieldText = string.Empty;

			public Color FieldColor = Color.clear;
		}

		private sealed class ColorCacheEntry
		{
			public Color Last;

			public Texture2D Tex;
		}

		private static IEnumerable<KeyCode> _keysToCheck;

		private static readonly Dictionary<SettingEntryBase, ComboBox> _comboBoxCache;

		private static readonly Dictionary<SettingEntryBase, ColorCacheEntry> _colorCache;

		private static readonly Dictionary<SettingEntryBase, FloatConfigCacheEntry> _floatConfigCache;

		internal static ConfigurationManager _instance;

		private static SettingEntryBase _currentKeyboardShortcutToSet;

		private static GUIStyle _categoryHeaderSkin;

		private static GUIStyle _pluginHeaderSkin;

		private readonly Dictionary<Type, bool> _canCovertCache = new Dictionary<Type, bool>();

		private static Texture2D _hueSatTex;

		private static bool _isDraggingHSRect;

		private static Vector2 _hsDragPos;

		public static Dictionary<Type, Action<SettingEntryBase>> SettingDrawHandlers { get; }

		public static bool SettingKeyboardShortcut => _currentKeyboardShortcutToSet != null;

		static SettingFieldDrawer()
		{
			_comboBoxCache = new Dictionary<SettingEntryBase, ComboBox>();
			_colorCache = new Dictionary<SettingEntryBase, ColorCacheEntry>();
			_floatConfigCache = new Dictionary<SettingEntryBase, FloatConfigCacheEntry>();
			_isDraggingHSRect = false;
			SettingDrawHandlers = new Dictionary<Type, Action<SettingEntryBase>>
			{
				{
					typeof(bool),
					DrawBoolField
				},
				{
					typeof(float),
					DrawFloatField
				},
				{
					typeof(KeyboardShortcut),
					DrawKeyboardShortcut
				},
				{
					typeof(KeyCode),
					DrawKeyCode
				},
				{
					typeof(Color),
					DrawColor
				},
				{
					typeof(Vector2),
					DrawVector2
				},
				{
					typeof(Vector3),
					DrawVector3
				},
				{
					typeof(Vector4),
					DrawVector4
				},
				{
					typeof(Quaternion),
					DrawQuaternion
				}
			};
		}

		public SettingFieldDrawer(ConfigurationManager instance)
		{
			_instance = instance;
		}

		public void DrawSettingValue(SettingEntryBase setting)
		{
			if (setting.CustomDrawer != null)
			{
				setting.CustomDrawer((setting is ConfigSettingEntry configSettingEntry) ? configSettingEntry.Entry : null);
			}
			else if (setting.CustomHotkeyDrawer != null)
			{
				bool isCurrentlyAcceptingInput = _currentKeyboardShortcutToSet == setting;
				bool flag = isCurrentlyAcceptingInput;
				setting.CustomHotkeyDrawer((setting is ConfigSettingEntry configSettingEntry2) ? configSettingEntry2.Entry : null, ref isCurrentlyAcceptingInput);
				if (isCurrentlyAcceptingInput != flag)
				{
					_currentKeyboardShortcutToSet = (isCurrentlyAcceptingInput ? setting : null);
				}
			}
			else if (setting.ShowRangeAsPercent.HasValue && setting.AcceptableValueRange.Key != null)
			{
				DrawRangeField(setting, _instance.RightColumnWidth);
			}
			else if (setting.AcceptableValues != null)
			{
				DrawListField(setting);
			}
			else if (!DrawFieldBasedOnValueType(setting))
			{
				if (setting.SettingType.IsEnum)
				{
					DrawEnumField(setting);
				}
				else
				{
					DrawUnknownField(setting, _instance.RightColumnWidth);
				}
			}
		}

		public static void ClearCache()
		{
			_comboBoxCache.Clear();
			foreach (KeyValuePair<SettingEntryBase, ColorCacheEntry> item in _colorCache)
			{
				ColorCacheEntry value = item.Value;
				if ((Object)(object)value.Tex != (Object)null)
				{
					TexturePool.ReleaseTexture2D(value.Tex);
				}
			}
			_colorCache.Clear();
		}

		public static void DrawCenteredLabel(string text, params GUILayoutOption[] options)
		{
			GUILayout.BeginHorizontal(options);
			GUILayout.FlexibleSpace();
			GUILayout.Label(text, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
		}

		public static void DrawCategoryHeader(string text)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (_categoryHeaderSkin == null || (_categoryHeaderSkin != null && ConfigurationManager._categoryHeaderColor.Value != _categoryHeaderSkin.normal.background.GetPixel(0, 0)))
			{
				_categoryHeaderSkin = GUI.skin.box.CreateCopy();
				_categoryHeaderSkin.alignment = (TextAnchor)1;
				_categoryHeaderSkin.wordWrap = true;
				_categoryHeaderSkin.stretchWidth = true;
				_categoryHeaderSkin.fontSize = 16;
				_categoryHeaderSkin.fontStyle = (FontStyle)1;
				Texture2D texture2D = TexturePool.GetTexture2D(1, 1, (TextureFormat)4, mipChain: false);
				texture2D.SetPixel(0, 0, ConfigurationManager._categoryHeaderColor.Value);
				texture2D.Apply();
				_categoryHeaderSkin.normal.background = texture2D;
			}
			GUIStyle categoryHeaderSkin = _categoryHeaderSkin;
			GUIHelper.CreateLabelWithColor(text, default(Color), categoryHeaderSkin);
		}

		public static bool DrawPluginHeader(GUIContent content)
		{
			//IL_005c: 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)
			if (_pluginHeaderSkin == null)
			{
				_pluginHeaderSkin = GUI.skin.label.CreateCopy();
				_pluginHeaderSkin.alignment = (TextAnchor)1;
				_pluginHeaderSkin.wordWrap = true;
				_pluginHeaderSkin.stretchWidth = true;
				_pluginHeaderSkin.fontSize = 15;
			}
			return GUIHelper.CreateButtonWithColor(content, _pluginHeaderSkin, default(Color), GUILayout.ExpandWidth(true));
		}

		public static bool DrawCurrentDropdown()
		{
			if (ComboBox.CurrentDropdownDrawer != null)
			{
				ComboBox.CurrentDropdownDrawer();
				ComboBox.CurrentDropdownDrawer = null;
				return true;
			}
			return false;
		}

		private static void DrawListField(SettingEntryBase setting)
		{
			//IL_0084: 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)
			object[] acceptableValues = setting.AcceptableValues;
			if (acceptableValues.Length == 0)
			{
				throw new ArgumentException("AcceptableValueListAttribute returned an empty list of acceptable values. You need to supply at least 1 option.");
			}
			if (!setting.SettingType.IsInstanceOfType(acceptableValues.FirstOrDefault((object x) => x != null)))
			{
				throw new ArgumentException("AcceptableValueListAttribute returned a list with items of type other than the settng type itself.");
			}
			if ((object)setting.SettingType == typeof(KeyCode))
			{
				DrawKeyCode(setting);
				return;
			}
			Rect settingWindowRect = _instance.SettingWindowRect;
			DrawComboboxField(setting, acceptableValues, ((Rect)(ref settingWindowRect)).yMax, _instance.RightColumnWidth);
		}

		private static bool DrawFieldBasedOnValueType(SettingEntryBase setting)
		{
			if (SettingDrawHandlers.TryGetValue(setting.SettingType, out var value))
			{
				value(setting);
				return true;
			}
			return false;
		}

		private static void DrawBoolField(SettingEntryBase setting)
		{
			bool flag = (bool)setting.Get();
			bool flag2 = GUILayout.Toggle(flag, flag ? " Enabled" : " Disabled", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(false),
				GUILayout.MaxWidth((float)_instance.RightColumnWidth)
			});
			if (flag2 != flag)
			{
				setting.Set(flag2);
			}
		}

		public static void DrawFloatField(SettingEntryBase configEntry)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)configEntry.Get();
			if (!_floatConfigCache.TryGetValue(configEntry, out var value))
			{
				value = new FloatConfigCacheEntry
				{
					Value = num,
					FieldColor = GUI.color
				};
				_floatConfigCache[configEntry] = value;
			}
			if (GUIHelper.HasChanged() || GUIHelper.IsEnterPressed() || (double)value.Value != (double)num)
			{
				value.Value = num;
				value.FieldText = num.ToString(NumberFormatInfo.InvariantInfo);
				value.FieldColor = GUI.color;
			}
			string text = GUIHelper.CreateTextFieldWithColor(value.FieldText, value.FieldColor, GUILayout.ExpandWidth(true));
			if (text == value.FieldText)
			{
				return;
			}
			value.FieldText = text;
			if (ShouldParse(text) && float.TryParse(text, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var result))
			{
				configEntry.Set(result);
				value.Value = (float)configEntry.Get();
				value.FieldText = value.Value.ToString(NumberFormatInfo.InvariantInfo);
				if (value.FieldText == text)
				{
					value.FieldColor = GUI.color;
					return;
				}
				value.FieldColor = Color.yellow;
				value.FieldText = text;
			}
			else
			{
				value.FieldColor = Color.red;
			}
		}

		private static bool ShouldParse(string text)
		{
			if (text == null || text.Length <= 0)
			{
				return false;
			}
			switch (text[text.Length - 1])
			{
			case '+':
			case ',':
			case '-':
			case '.':
			case 'E':
			case 'e':
				return false;
			default:
				return true;
			}
		}

		private static void DrawEnumField(SettingEntryBase setting)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (setting.SettingType.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any())
			{
				DrawFlagsField(setting, Enum.GetValues(setting.SettingType), _instance.RightColumnWidth);
				return;
			}
			Array values = Enum.GetValues(setting.SettingType);
			Rect settingWindowRect = _instance.SettingWindowRect;
			DrawComboboxField(setting, values, ((Rect)(ref settingWindowRect)).yMax, _instance.RightColumnWidth);
		}

		private static void DrawFlagsField(SettingEntryBase setting, IList enumValues, int maxWidth)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			long num = Convert.ToInt64(setting.Get());
			var array = (from Enum x in enumValues
				select new
				{
					name = x.ToString(),
					val = Convert.ToInt64(x)
				}).ToArray();
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)maxWidth) });
			int i = 0;
			while (i < array.Length)
			{
				GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
				int num2 = 0;
				for (; i < array.Length; i++)
				{
					var anon = array[i];
					if (anon.val != 0)
					{
						int num3 = (int)GUI.skin.toggle.CalcSize(new GUIContent(anon.name)).x;
						num2 += num3;
						if (num2 > maxWidth)
						{
							break;
						}
						GUI.changed = false;
						bool flag = GUILayout.Toggle((num & anon.val) == anon.val, anon.name, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
						if (GUI.changed)
						{
							long value = (flag ? (num | anon.val) : (num & ~anon.val));
							setting.Set(Enum.ToObject(setting.SettingType, value));
						}
					}
				}
				GUILayout.EndHorizontal();
			}
			GUI.changed = false;
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
		}

		private static void DrawComboboxField(SettingEntryBase setting, IList list, float windowYmax, int rightColumnWidth)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			GUIContent val = ObjectToGuiContent($"{setting.Get()}");
			Rect rect = GUILayoutUtility.GetRect(val, GUI.skin.button, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(false),
				GUILayout.MaxWidth((float)_instance.RightColumnWidth / 4f)
			});
			if (!_comboBoxCache.TryGetValue(setting, out var value))
			{
				value = new ComboBox(rect, val, list.Cast<object>().Select(ObjectToGuiContent).ToArray(), GUI.skin.button, windowYmax);
				_comboBoxCache[setting] = value;
			}
			else
			{
				value.Rect = rect;
				value.ButtonContent = val;
			}
			value.Show(delegate(int id)
			{
				if (id >= 0 && id < list.Count)
				{
					setting.Set(list[id]);
				}
			});
		}

		private static GUIContent ObjectToGuiContent(object x)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			if (x is Enum)
			{
				Type type = x.GetType();
				DescriptionAttribute descriptionAttribute = type.GetMember(x.ToString()).FirstOrDefault()?.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false).Cast<DescriptionAttribute>().FirstOrDefault();
				if (descriptionAttribute != null)
				{
					return new GUIContent(descriptionAttribute.Description);
				}
				return new GUIContent(x.ToString().ToProperCase());
			}
			return new GUIContent(x.ToString());
		}

		private static void DrawRangeField(SettingEntryBase setting, int rightColumnWidth)
		{
			object obj = setting.Get();
			float num = (float)Convert.ToDouble(obj, CultureInfo.InvariantCulture);
			float num2 = (float)Convert.ToDouble(setting.AcceptableValueRange.Key, CultureInfo.InvariantCulture);
			float num3 = (float)Convert.ToDouble(setting.AcceptableValueRange.Value, CultureInfo.InvariantCulture);
			float num4 = GUILayout.HorizontalSlider(num, num2, num3, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(false),
				GUILayout.MaxWidth((float)rightColumnWidth)
			});
			if (Math.Abs(num4 - num) > Mathf.Abs(num3 - num2) / 1000f)
			{
				object newVal = Convert.ChangeType(num4, setting.SettingType, CultureInfo.InvariantCulture);
				setting.Set(newVal);
			}
			if (setting.ShowRangeAsPercent.GetValueOrDefault())
			{
				DrawCenteredLabel(Mathf.Round(100f * Mathf.Abs(num4 - num2) / Mathf.Abs(num3 - num2)) + "%", GUILayout.Width(50f));
				return;
			}
			string text = obj.ToString().AppendZeroIfFloat(setting.SettingType);
			string text2 = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			if (!(text2 != text))
			{
				return;
			}
			try
			{
				float num5 = (float)Convert.ToDouble(text2, CultureInfo.InvariantCulture);
				float num6 = Mathf.Clamp(num5, num2, num3);
				setting.Set(Convert.ChangeType(num6, setting.SettingType, CultureInfo.InvariantCulture));
			}
			catch (FormatException)
			{
			}
		}

		private void DrawUnknownField(SettingEntryBase setting, int rightColumnWidth)
		{
			if (setting.ObjToStr != null && setting.StrToObj != null)
			{
				string text = setting.ObjToStr(setting.Get()).AppendZeroIfFloat(setting.SettingType);
				string text2 = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)rightColumnWidth) });
				if (text2 != text)
				{
					setting.Set(setting.StrToObj(text2));
				}
			}
			else
			{
				object obj = setting.Get();
				string text3 = ((obj == null) ? "NULL" : obj.ToString().AppendZeroIfFloat(setting.SettingType));
				if (CanCovert(text3, setting.SettingType))
				{
					string text4 = GUILayout.TextField(text3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)rightColumnWidth) });
					if (text4 != text3)
					{
						setting.Set(Convert.ChangeType(text4, setting.SettingType, CultureInfo.InvariantCulture));
					}
				}
				else
				{
					GUILayout.TextArea(text3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)rightColumnWidth) });
				}
			}
			GUILayout.FlexibleSpace();
		}

		private bool CanCovert(string value, Type type)
		{
			if (_canCovertCache.ContainsKey(type))
			{
				return _canCovertCache[type];
			}
			try
			{
				object obj = Convert.ChangeType(value, type);
				_canCovertCache[type] = true;
				return true;
			}
			catch
			{
				_canCovertCache[type] = false;
				return false;
			}
		}

		private static void DrawKeyCode(SettingEntryBase setting)
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (_currentKeyboardShortcutToSet == setting)
			{
				GUILayout.Label("Press any key", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				GUIUtility.keyboardControl = -1;
				IInputSystem current = UnityInput.Current;
				if (_keysToCheck == null)
				{
					_keysToCheck = current.SupportedKeyCodes.Except((IEnumerable<KeyCode>)(object)new KeyCode[2]
					{
						(KeyCode)323,
						default(KeyCode)
					}).ToArray();
				}
				foreach (KeyCode item in _keysToCheck)
				{
					if (current.GetKeyUp(item))
					{
						setting.Set(item);
						_currentKeyboardShortcutToSet = null;
						break;
					}
				}
				if (GUIHelper.CreateButtonWithColor("Cancel", ConfigurationManager._cancelButtonColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
				{
					_currentKeyboardShortcutToSet = null;
				}
			}
			else
			{
				object[] acceptableValues = setting.AcceptableValues;
				Array list = ((acceptableValues != null && acceptableValues.Length > 1) ? setting.AcceptableValues : Enum.GetValues(setting.SettingType));
				Rect settingWindowRect = _instance.SettingWindowRect;
				DrawComboboxField(setting, list, ((Rect)(ref settingWindowRect)).yMax, _instance.RightColumnWidth);
				if (GUIHelper.CreateButtonWithColor(new GUIContent("Set...", (Texture)null, "Set the key by pressing any key on your keyboard."), ImguiUtils.buttonStyle, default(Color), GUILayout.ExpandWidth(false)))
				{
					_currentKeyboardShortcutToSet = setting;
				}
			}
		}

		private static void DrawKeyboardShortcut(SettingEntryBase setting)
		{
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			if (_currentKeyboardShortcutToSet == setting)
			{
				GUILayout.Label("Press any key combination", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				GUIUtility.keyboardControl = -1;
				IInputSystem current = UnityInput.Current;
				if (_keysToCheck == null)
				{
					_keysToCheck = current.SupportedKeyCodes.Except((IEnumerable<KeyCode>)(object)new KeyCode[2]
					{
						(KeyCode)323,
						default(KeyCode)
					}).ToArray();
				}
				foreach (KeyCode item in _keysToCheck)
				{
					if (current.GetKeyUp(item))
					{
						setting.Set((object)new KeyboardShortcut(item, _keysToCheck.Where((Func<KeyCode, bool>)current.GetKey).ToArray()));
						_currentKeyboardShortcutToSet = null;
						break;
					}
				}
				if (GUIHelper.CreateButtonWithColor("Cancel", ConfigurationManager._cancelButtonColor.Value, ImguiUtils.buttonStyle, GUILayout.ExpandWidth(false)))
				{
					_currentKeyboardShortcutToSet = null;
				}
			}
			else
			{
				if (GUILayout.Button("   " + setting.Get().ToString() + "   ", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
				{
					_currentKeyboardShortcutToSet = setting;
				}
				if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
				{
					setting.Set(KeyboardShortcut.Empty);
					_currentKeyboardShortcutToSet = null;
				}
			}
		}

		private static void DrawVector2(SettingEntryBase obj)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = (Vector2)obj.Get();
			Vector2 val2 = val;
			val.x = DrawSingleVectorSlider(val.x, "X");
			val.y = DrawSingleVectorSlider(val.y, "Y");
			if (val != val2)
			{
				obj.Set(val);
			}
		}

		private static void DrawVector3(SettingEntryBase obj)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (Vector3)obj.Get();
			Vector3 val2 = val;
			val.x = DrawSingleVectorSlider(val.x, "X");
			val.y = DrawSingleVectorSlider(val.y, "Y");
			val.z = DrawSingleVectorSlider(val.z, "Z");
			if (val != val2)
			{
				obj.Set(val);
			}
		}

		private static void DrawVector4(SettingEntryBase obj)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Vector4 val = (Vector4)obj.Get();
			Vector4 val2 = val;
			val.x = DrawSingleVectorSlider(val.x, "X");
			val.y = DrawSingleVectorSlider(val.y, "Y");
			val.z = DrawSingleVectorSlider(val.z, "Z");
			val.w = DrawSingleVectorSlider(val.w, "W");
			if (val != val2)
			{
				obj.Set(val);
			}
		}

		private static void DrawQuaternion(SettingEntryBase obj)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = (Quaternion)obj.Get();
			Quaternion val2 = val;
			val.x = DrawSingleVectorSlider(val.x, "X");
			val.y = DrawSingleVectorSlider(val.y, "Y");
			val.z = DrawSingleVectorSlider(val.z, "Z");
			val.w = DrawSingleVectorSlider(val.w, "W");
			if (val != val2)
			{
				obj.Set(val);
			}
		}

		private static float DrawSingleVectorSlider(float setting, string label)
		{
			GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
			float.TryParse(GUILayout.TextField(setting.ToString("F", CultureInfo.InvariantCulture), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }), NumberStyles.Any, CultureInfo.InvariantCulture, out var result);
			return result;
		}

		private static void DrawColor(SettingEntryBase obj)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			Color value = (Color)obj.Get();
			GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
			DrawHexField(ref value);
			GUILayout.Space(3f);
			GUIHelper.BeginColor(value);
			GUILayout.Label(string.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (!_colorCache.TryGetValue(obj, out var value2))
			{
				value2 = new ColorCacheEntry
				{
					Tex = new Texture2D(40, 10, (TextureFormat)5, false),
					Last = value
				};
				value2.Tex.FillTexture(value);
				_colorCache[obj] = value2;
			}
			if ((int)Event.current.type == 7)
			{
				GUI.DrawTexture(GUILayoutUtility.GetLastRect(), (Texture)(object)value2.Tex);
			}
			GUIHelper.EndColor();
			GUILayout.Space(3f);
			GUILayout.EndHorizontal();
			GUILayout.Space(4f);
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
			DrawColorField("Red", ref value, ref value.r);
			GUILayout.Space(3f);
			DrawColorField("Green", ref value, ref value.g);
			GUILayout.Space(3f);
			DrawColorField("Blue", ref value, ref value.b);
			GUILayout.Space(3f);
			DrawColorField("Alpha", ref value, ref value.a);
			if (value != value2.Last)
			{
				obj.Set(value);
				value2.Tex.FillTexture(value);
				value2.Last = value;
			}
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
		}

		private static void EnsureHueSatTexture()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if ((Object)(object)_hueSatTex == (Object)null)
			{
				_hueSatTex = new Texture2D(128, 128, (TextureFormat)4, false);
				((Texture)_hueSatTex).wrapMode = (TextureWrapMode)1;
			}
		}

		private static void RecolorHueSatTexture(float V)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_hueSatTex == (Object)null)
			{
				return;
			}
			int width = ((Texture)_hueSatTex).width;
			int height = ((Texture)_hueSatTex).height;
			Color32[] array = (Color32[])(object)new Color32[width * height];
			for (int i = 0; i < height; i++)
			{
				float num = 1f - (float)i / (float)(height - 1);
				for (int j = 0; j <

BepInEx/plugins/ConnectorLib.JSON.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

[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.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Warp World, Inc.")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("© 2024 Warp World, Inc.")]
[assembly: AssemblyFileVersion("5.0.8924.25521")]
[assembly: AssemblyInformationalVersion("5.0.8924.25521+1ef6cca7b48ffec6f735086f83465220347f78d1")]
[assembly: AssemblyProduct("ConnectorLib.JSON")]
[assembly: AssemblyTitle("ConnectorLib.JSON")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("5.0.8924.25521")]
[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]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 ConnectorLib.JSON
{
	internal class AnnotatedEnumConverter<T> : JsonConverter<T> where T : struct, Enum
	{
		[AttributeUsage(AttributeTargets.Field)]
		public class JsonValueAttribute : Attribute
		{
			public readonly string Value;

			public JsonValueAttribute(string value)
			{
				Value = value;
				base..ctor();
			}
		}

		private static readonly Dictionary<T, JsonValueAttribute?> _attributes;

		static AnnotatedEnumConverter()
		{
			T[] source = (T[])Enum.GetValues(typeof(T));
			_attributes = source.Select((T m) => new KeyValuePair<T, JsonValueAttribute>(m, GetAttributeOfType<JsonValueAttribute>(m))).ToDictionary();
		}

		private static T? GetAttributeOfType<T>(Enum enumVal) where T : Attribute
		{
			Enum enumVal2 = enumVal;
			Type type = enumVal2.GetType();
			MemberInfo memberInfo = type.GetTypeInfo().DeclaredMembers.First((MemberInfo m) => string.Equals(m.Name, enumVal2.ToString(), StringComparison.Ordinal));
			object[] array = memberInfo.GetCustomAttributes(typeof(T), inherit: false).ToArray();
			return (array.Length != 0) ? ((T)array[0]) : null;
		}

		public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
		{
			JsonValueAttribute jsonValueAttribute = _attributes[value];
			if (jsonValueAttribute != null)
			{
				serializer.Serialize(writer, (object)jsonValueAttribute.Value);
			}
			else
			{
				serializer.Serialize(writer, (object)Enum.GetName(typeof(T), value));
			}
		}

		public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			string value = serializer.Deserialize<string>(reader);
			if (value == null)
			{
				return default(T);
			}
			KeyValuePair<T, JsonValueAttribute>? keyValuePair = _attributes.Cast<KeyValuePair<T, JsonValueAttribute>?>().FirstOrDefault((KeyValuePair<T, JsonValueAttribute>? a) => (a?.Value?.Value?.Equals(value, StringComparison.OrdinalIgnoreCase)).GetValueOrDefault());
			if (keyValuePair.HasValue)
			{
				return keyValuePair.Value.Key;
			}
			if (Enum.TryParse<T>(value, ignoreCase: true, out var result))
			{
				return result;
			}
			return default(T);
		}
	}
	public class CamelCaseStringEnumConverter : JsonConverter<Enum>
	{
		public override void WriteJson(JsonWriter writer, Enum? value, JsonSerializer serializer)
		{
			if (value == null)
			{
				serializer.Serialize(writer, (object)null);
			}
			else
			{
				serializer.Serialize(writer, (object)value.ToCamelCase());
			}
		}

		public override Enum ReadJson(JsonReader reader, Type objectType, Enum? existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			return ReadJToken(JToken.ReadFrom(reader), objectType);
		}

		public static Enum ReadJToken(JToken reader, Type objectType)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			JTokenType type = reader.Type;
			JTokenType val = type;
			if ((int)val != 6)
			{
				if ((int)val == 8)
				{
					string text = Extensions.Value<string>((IEnumerable<JToken>)reader);
					if (text == null)
					{
						throw new SerializationException("The value was null.");
					}
					try
					{
						object obj = Enum.Parse(objectType, text, ignoreCase: true);
						return (Enum)obj;
					}
					catch (Exception)
					{
						throw new SerializationException("The value was not recognized.");
					}
				}
				throw new SerializationException("The value was not a string or number.");
			}
			int? num = Extensions.Value<int>((IEnumerable<JToken>)reader);
			if (!num.HasValue)
			{
				throw new SerializationException("The value was null.");
			}
			return (Enum)Enum.ToObject(objectType, num.Value);
		}
	}
	[Serializable]
	public class EffectRequest : SimpleJSONRequest
	{
		[Serializable]
		public class Target
		{
			public string? service;

			public string? id;

			public string? name;

			public string? avatar;
		}

		public string? code;

		public string? message;

		public JToken? parameters;

		public uint? quantity;

		public JArray? targets;

		public long? duration;

		public string? viewer;

		public JArray? viewers;

		public int? cost;

		public EffectRequest()
		{
			type = RequestType.Start;
		}
	}
	[Serializable]
	public class EffectResponse : SimpleJSONResponse
	{
		private class MetadataConverter : JsonConverter<Dictionary<string, EffectResponseMetadata>?>
		{
			public override void WriteJson(JsonWriter writer, Dictionary<string, EffectResponseMetadata>? value, JsonSerializer serializer)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				if (value == null)
				{
					serializer.Serialize(writer, (object)null);
					return;
				}
				JObject val = new JObject();
				foreach (KeyValuePair<string, EffectResponseMetadata> item in value)
				{
					JObject val2 = JObject.FromObject((object)item.Value);
					val2.Remove("key");
					val[item.Key] = (JToken)(object)val2;
				}
				serializer.Serialize(writer, (object)val);
			}

			public override Dictionary<string, EffectResponseMetadata>? ReadJson(JsonReader reader, Type objectType, Dictionary<string, EffectResponseMetadata>? existingValue, bool hasExistingValue, JsonSerializer serializer)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Expected O, but got Unknown
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				JObject val = (JObject)serializer.Deserialize(reader);
				if (val == null)
				{
					return null;
				}
				Dictionary<string, EffectResponseMetadata> dictionary = new Dictionary<string, EffectResponseMetadata>();
				foreach (JProperty item in val.Properties())
				{
					JObject val2 = (JObject)item.Value;
					val2["key"] = JToken.op_Implicit(item.Name);
					dictionary.Add(item.Name, ((JToken)val2).ToObject<EffectResponseMetadata>());
				}
				return dictionary;
			}
		}

		public EffectStatus status;

		public string? message;

		public long timeRemaining;

		[JsonConverter(typeof(MetadataConverter))]
		public Dictionary<string, EffectResponseMetadata>? metadata;

		public EffectResponse()
		{
		}

		public EffectResponse(uint id, EffectStatus status, string? message = null)
			: this(id, status, 0L, message)
		{
		}

		[JsonConstructor]
		public EffectResponse(uint id, EffectStatus status, long timeRemaining, string? message = null)
		{
			base.id = id;
			this.status = status;
			this.timeRemaining = timeRemaining;
			this.message = message;
			type = ResponseType.EffectRequest;
		}
	}
	public class EffectResponseMetadata
	{
		public string key;

		public JToken? value;

		public EffectStatus status;

		public long? timeRemaining;

		public string? message;

		[JsonConstructor]
		public EffectResponseMetadata(string key, EffectStatus status, object? value = null, long timeRemaining = 0L, string? message = null)
		{
			this.key = key;
			this.value = value.IfNotNull((Func<object, JToken?>)JToken.FromObject);
			this.status = status;
			this.timeRemaining = timeRemaining;
			this.message = message;
			base..ctor();
		}

		public static EffectResponseMetadata Success(string key, object? value, string? message = null)
		{
			return new EffectResponseMetadata(key, EffectStatus.Success, value, 0L, message);
		}

		public static EffectResponseMetadata Failure(string key)
		{
			return new EffectResponseMetadata(key, EffectStatus.Failure, null, 0L);
		}

		public static EffectResponseMetadata Failure(string key, string? message)
		{
			return new EffectResponseMetadata(key, EffectStatus.Failure, null, 0L, message);
		}

		public static EffectResponseMetadata Failure(string key, object? value, string? message = null)
		{
			return new EffectResponseMetadata(key, EffectStatus.Failure, null, 0L, message);
		}

		public static EffectResponseMetadata Retry(string key, long delay = 0L, string? message = null)
		{
			return new EffectResponseMetadata(key, EffectStatus.Retry, null, delay, message);
		}
	}
	[JsonConverter(typeof(CamelCaseStringEnumConverter))]
	public enum EffectStatus
	{
		Success = 0,
		Failure = 1,
		Unavailable = 2,
		Retry = 3,
		Queue = 4,
		Running = 5,
		Paused = 6,
		Resumed = 7,
		Finished = 8,
		Visible = 128,
		NotVisible = 129,
		Selectable = 130,
		NotSelectable = 131,
		NotReady = 255
	}
	[Serializable]
	public class EffectUpdate : SimpleJSONResponse
	{
		[JsonConverter(typeof(CamelCaseStringEnumConverter))]
		public enum IdentifierType
		{
			Effect,
			Group,
			Category
		}

		[Obsolete]
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string? code;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string[]? ids;

		public IdentifierType idType;

		public EffectStatus status;

		public string? message;

		public EffectUpdate()
		{
		}

		public EffectUpdate(string code, EffectStatus status, string? message = null)
		{
			ids = new string[1] { code };
			idType = IdentifierType.Effect;
			this.status = status;
			this.message = message;
			type = ResponseType.EffectStatus;
		}
	}
	[Serializable]
	public class EmptyRequest : SimpleJSONRequest
	{
	}
	[Serializable]
	public class EmptyResponse : SimpleJSONResponse
	{
	}
	internal static class EnumEx
	{
		public static string ToCamelCase(this Enum value)
		{
			return value.ToString("G").ToCamelCase();
		}
	}
	[JsonConverter(typeof(CamelCaseStringEnumConverter))]
	public enum GameState
	{
		Unknown = 0,
		Ready = 1,
		Error = -1,
		Unmodded = -2,
		NotFocused = -3,
		Loading = -4,
		Paused = -5,
		WrongMode = -6,
		SafeArea = -7,
		Cutscene = -8,
		BadPlayerState = -9,
		Menu = -10,
		Map = -11
	}
	[Serializable]
	public class GameUpdate : SimpleJSONResponse
	{
		public GameState state;

		public string? message;

		public GameUpdate(GameState state, string? message = null)
		{
			this.state = state;
			this.message = message;
			type = ResponseType.GameUpdate;
		}
	}
	[Serializable]
	public class GenericEvent : SimpleJSONResponse
	{
		[JsonProperty(PropertyName = "internal")]
		public bool @internal;

		public string eventType;

		public Dictionary<string, string> data;

		public GenericEvent()
		{
			type = ResponseType.GenericEvent;
		}
	}
	internal class HexColorConverter : JsonConverter<ParameterColorValue>
	{
		private static readonly Dictionary<char, byte> CHAR_LOOKUP = new Dictionary<char, byte>
		{
			{ '0', 0 },
			{ '1', 1 },
			{ '2', 2 },
			{ '3', 3 },
			{ '4', 4 },
			{ '5', 5 },
			{ '6', 6 },
			{ '7', 7 },
			{ '8', 8 },
			{ '9', 9 },
			{ 'A', 10 },
			{ 'B', 11 },
			{ 'C', 12 },
			{ 'D', 13 },
			{ 'E', 14 },
			{ 'F', 15 }
		};

		public override void WriteJson(JsonWriter writer, ParameterColorValue value, JsonSerializer serializer)
		{
			serializer.Serialize(writer, (object)string.Format("#{0}{1:X2}{2:X2}{3:X2}", (value.A != byte.MaxValue) ? value.A.ToString("X2") : string.Empty, value.R, value.G, value.B));
		}

		public override ParameterColorValue ReadJson(JsonReader reader, Type objectType, ParameterColorValue existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			string value = serializer.Deserialize<string>(reader);
			if (TryParse(value, out var color))
			{
				return color;
			}
			throw new SerializationException("Unrecognized color code.");
		}

		public static bool TryParse(string value, out ParameterColorValue color)
		{
			if (value == null)
			{
				color = default(ParameterColorValue);
				return false;
			}
			value = value.TrimStart(new char[1] { '#' });
			switch (value.Length)
			{
			case 6:
			{
				string[] array2 = Chop(value, 2);
				byte result2;
				byte red3 = (byte)(byte.TryParse(array2[0], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0);
				byte green3 = (byte)(byte.TryParse(array2[1], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0);
				byte blue3 = (byte)(byte.TryParse(array2[2], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result2) ? result2 : 0);
				color = ParameterColorValue.FromArgb(red3, green3, blue3);
				return true;
			}
			case 8:
			{
				string[] array = Chop(value, 2);
				byte result;
				byte alpha2 = (byte)(byte.TryParse(array[0], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0);
				byte red2 = (byte)(byte.TryParse(array[1], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0);
				byte green2 = (byte)(byte.TryParse(array[2], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0);
				byte blue2 = (byte)(byte.TryParse(array[3], NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out result) ? result : 0);
				color = ParameterColorValue.FromArgb(alpha2, red2, green2, blue2);
				return true;
			}
			case 3:
			{
				byte value3;
				byte red4 = (byte)(CHAR_LOOKUP.TryGetValue(value[0], out value3) ? checked((byte)(value3 * 16)) : 0);
				byte green4 = (byte)(CHAR_LOOKUP.TryGetValue(value[1], out value3) ? checked((byte)(value3 * 16)) : 0);
				byte blue4 = (byte)(CHAR_LOOKUP.TryGetValue(value[2], out value3) ? checked((byte)(value3 * 16)) : 0);
				color = ParameterColorValue.FromArgb(red4, green4, blue4);
				return true;
			}
			case 4:
			{
				byte value2;
				byte alpha = (byte)(CHAR_LOOKUP.TryGetValue(value[0], out value2) ? checked((byte)(value2 * 16)) : 0);
				byte red = (byte)(CHAR_LOOKUP.TryGetValue(value[1], out value2) ? checked((byte)(value2 * 16)) : 0);
				byte green = (byte)(CHAR_LOOKUP.TryGetValue(value[2], out value2) ? checked((byte)(value2 * 16)) : 0);
				byte blue = (byte)(CHAR_LOOKUP.TryGetValue(value[3], out value2) ? checked((byte)(value2 * 16)) : 0);
				color = ParameterColorValue.FromArgb(alpha, red, green, blue);
				return true;
			}
			default:
				color = default(ParameterColorValue);
				return false;
			}
		}

		private unsafe static string[] Chop(string value, int chopLength)
		{
			int length = value.Length;
			char* ptr = stackalloc char[chopLength];
			string[] array = new string[length];
			for (int i = 0; i < length; i = checked(i + chopLength))
			{
				int j;
				for (j = 0; j < chopLength; j = checked(j + 1))
				{
					int num = checked(i + j);
					if (num >= length)
					{
						break;
					}
					*(char*)((byte*)ptr + checked(unchecked((nint)j) * (nint)2)) = value[num];
				}
				array[i / chopLength] = new string(ptr, 0, j);
			}
			return array;
		}
	}
	internal static class IEnumerableEx
	{
		public static Dictionary<K, V> ToDictionary<K, V>(this IEnumerable<KeyValuePair<K, V>> values) where K : notnull
		{
			Dictionary<K, V> dictionary = new Dictionary<K, V>();
			foreach (KeyValuePair<K, V> value in values)
			{
				dictionary.Add(value.Key, value.Value);
			}
			return dictionary;
		}
	}
	[Serializable]
	public class LoginRequest : SimpleJSONRequest
	{
		public string? login;

		public string? password;
	}
	[Serializable]
	public class MessageRequest : SimpleJSONRequest
	{
		public string? message;
	}
	[Serializable]
	public class MessageResponse : SimpleJSONResponse
	{
		public string? message;
	}
	internal static class ObjectEx
	{
		public static T2? IfNotNull<T1, T2>(this T1? value, Func<T1, T2?> selector) where T2 : class
		{
			return (value != null) ? selector(value) : null;
		}
	}
	public class ParameterColor : ParameterBase, IParameterValue
	{
		[JsonProperty(PropertyName = "value")]
		[JsonConverter(typeof(HexColorConverter))]
		public ParameterColorValue Value;

		[JsonIgnore]
		string IParameterValue.ID => ID;

		[JsonIgnore]
		string IParameterValue.Name => Name;

		[JsonIgnore]
		ParameterType IParameterValue.Type => Type;

		[JsonIgnore]
		object? IParameterValue.Value => Value;

		[JsonConstructor]
		public ParameterColor(string name, string id, ParameterColorValue value)
			: base(name, id, ParameterType.HexColor)
		{
			Value = value;
		}

		[JsonConstructor]
		public ParameterColor(string name, string id, string value)
			: base(name, id, ParameterType.HexColor)
		{
			if (!HexColorConverter.TryParse(value, out Value))
			{
				throw new ArgumentException("Unknown color code.", "value");
			}
		}
	}
	[Serializable]
	[DebuggerDisplay("{NameAndARGBValue}")]
	[TypeForwardedFrom("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
	public readonly struct ParameterColorValue : IEquatable<ParameterColorValue>
	{
		public static readonly ParameterColorValue Empty = default(ParameterColorValue);

		private const short StateARGBValueValid = 2;

		private const short StateValueMask = 2;

		private const short StateNameValid = 8;

		private const long NotDefinedValue = 0L;

		internal const int ARGBAlphaShift = 24;

		internal const int ARGBRedShift = 16;

		internal const int ARGBGreenShift = 8;

		internal const int ARGBBlueShift = 0;

		internal const uint ARGBAlphaMask = 4278190080u;

		internal const uint ARGBRedMask = 16711680u;

		internal const uint ARGBGreenMask = 65280u;

		internal const uint ARGBBlueMask = 255u;

		private readonly long value;

		private readonly short state;

		public byte R => (byte)(Value >> 16);

		public byte G => (byte)(Value >> 8);

		public byte B => (byte)Value;

		public byte A => (byte)(Value >> 24);

		public bool IsEmpty => state == 0;

		private long Value
		{
			get
			{
				if (((uint)state & 2u) != 0)
				{
					return value;
				}
				return 0L;
			}
		}

		private ParameterColorValue(long value, short state)
		{
			this.value = value;
			this.state = state;
		}

		private static ParameterColorValue FromArgb(uint argb)
		{
			return new ParameterColorValue(argb, 2);
		}

		public static ParameterColorValue FromArgb(int argb)
		{
			return FromArgb((uint)argb);
		}

		public static ParameterColorValue FromArgb(byte alpha, byte red, byte green, byte blue)
		{
			return FromArgb((uint)((alpha << 24) | (red << 16) | (green << 8) | blue));
		}

		public static ParameterColorValue FromArgb(int alpha, ParameterColorValue baseColor)
		{
			return FromArgb(checked(((uint)alpha << 24) | ((uint)baseColor.Value & 0xFFFFFFu)));
		}

		public static ParameterColorValue FromArgb(byte red, byte green, byte blue)
		{
			return FromArgb(byte.MaxValue, red, green, blue);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void GetRgbValues(out byte r, out byte g, out byte b)
		{
			checked
			{
				uint num = (uint)Value;
				r = (byte)((num & 0xFF0000) >> 16);
				g = (byte)((num & 0xFF00) >> 8);
				b = (byte)(num & 0xFFu);
			}
		}

		public float GetBrightness()
		{
			GetRgbValues(out var r, out var g, out var b);
			int num = Math.Min(Math.Min(r, g), b);
			int num2 = Math.Max(Math.Max(r, g), b);
			return (float)checked(num2 + num) / 510f;
		}

		public float GetHue()
		{
			GetRgbValues(out var r, out var g, out var b);
			if (r == g && g == b)
			{
				return 0f;
			}
			int num = Math.Min(Math.Min(r, g), b);
			int num2 = Math.Max(Math.Max(r, g), b);
			checked
			{
				float num3 = num2 - num;
				float num4 = ((r == num2) ? ((float)(g - b) / num3) : ((g != num2) ? ((float)(r - g) / num3 + 4f) : ((float)(b - r) / num3 + 2f)));
				num4 *= 60f;
				if (num4 < 0f)
				{
					num4 += 360f;
				}
				return num4;
			}
		}

		public float GetSaturation()
		{
			GetRgbValues(out var r, out var g, out var b);
			if (r == g && g == b)
			{
				return 0f;
			}
			int num = Math.Min(Math.Min(r, g), b);
			int num2 = Math.Max(Math.Max(r, g), b);
			checked
			{
				int num3 = num2 + num;
				if (num3 > 255)
				{
					num3 = 510 - num2 - num;
				}
				return (float)(num2 - num) / (float)num3;
			}
		}

		public int ToArgb()
		{
			return (int)Value;
		}

		public override string ToString()
		{
			if (((uint)state & 2u) != 0)
			{
				return "ParameterColorValue [A=" + A + ", R=" + R + ", G=" + G + ", B=" + B + "]";
			}
			return "ParameterColorValue [Empty]";
		}

		public static bool operator ==(ParameterColorValue left, ParameterColorValue right)
		{
			return left.value == right.value && left.state == right.state;
		}

		public static bool operator !=(ParameterColorValue left, ParameterColorValue right)
		{
			return !(left == right);
		}

		public override bool Equals(object? obj)
		{
			return obj is ParameterColorValue other && Equals(other);
		}

		public bool Equals(ParameterColorValue other)
		{
			return this == other;
		}

		public override int GetHashCode()
		{
			long num = value;
			int num2 = num.GetHashCode() * 397;
			short num3 = state;
			return num2 ^ num3.GetHashCode();
		}
	}
	public class ParameterValue<T> : ParameterBase, IParameterValue
	{
		[JsonProperty(PropertyName = "value")]
		public T? Value;

		[JsonIgnore]
		string IParameterValue.ID => ID;

		[JsonIgnore]
		string IParameterValue.Name => Name;

		[JsonIgnore]
		ParameterType IParameterValue.Type => Type;

		[JsonIgnore]
		object? IParameterValue.Value => Value;

		[JsonConstructor]
		public ParameterValue(string name, string id, T? value)
			: base(name, id, ParameterType.Options)
		{
			Value = value;
		}

		public override string ToString()
		{
			return Name;
		}
	}
	[Serializable]
	public class PlayerInfo : SimpleJSONRequest
	{
		public JObject? player;

		public PlayerInfo()
		{
			type = RequestType.Start;
		}
	}
	[Serializable]
	[JsonConverter(typeof(Converter))]
	public class RequestParameters : IReadOnlyList<string>, IEnumerable<string>, IEnumerable, IReadOnlyCollection<string>, IReadOnlyDictionary<string, IParameterValue>, IEnumerable<KeyValuePair<string, IParameterValue>>, IReadOnlyCollection<KeyValuePair<string, IParameterValue>>
	{
		private class Converter : JsonConverter<RequestParameters>
		{
			public override void WriteJson(JsonWriter writer, RequestParameters? value, JsonSerializer serializer)
			{
				serializer.Serialize(writer, (object)value?._parameters);
			}

			public override RequestParameters? ReadJson(JsonReader reader, Type objectType, RequestParameters? existingValue, bool hasExistingValue, JsonSerializer serializer)
			{
				JObject val = JObject.Load(reader);
				List<IParameterValue> list = new List<IParameterValue>();
				foreach (KeyValuePair<string, JToken> item in val)
				{
					string key = item.Key;
					string name = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"name"]);
					switch (Extensions.Value<ParameterBase.ParameterType>((IEnumerable<JToken>)item.Value[(object)"type"]))
					{
					case ParameterBase.ParameterType.Options:
					{
						string value2 = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"value"]);
						list.Add(new ParameterValue<string>(name, key, value2));
						break;
					}
					case ParameterBase.ParameterType.HexColor:
					{
						string value = Extensions.Value<string>((IEnumerable<JToken>)item.Value[(object)"value"]);
						if (HexColorConverter.TryParse(value, out var color))
						{
							list.Add(new ParameterColor(name, key, color));
						}
						break;
					}
					default:
						throw new SerializationException();
					}
				}
				return new RequestParameters(list);
			}
		}

		private readonly Dictionary<string, IParameterValue> _parameters;

		private readonly List<string> _parameter_list;

		int IReadOnlyCollection<string>.Count => _parameters.Count;

		int IReadOnlyCollection<KeyValuePair<string, IParameterValue>>.Count => _parameters.Count;

		public string this[int index] => _parameter_list[index];

		public IParameterValue this[string key] => _parameters[key];

		public IEnumerable<string> Keys => _parameters.Keys;

		public IEnumerable<IParameterValue> Values => _parameters.Values;

		public int Count => _parameters.Count;

		private RequestParameters()
		{
			_parameters = new Dictionary<string, IParameterValue>();
			_parameter_list = new List<string>();
		}

		public RequestParameters(IEnumerable<IParameterValue> list)
		{
			list = list.ToArray();
			_parameters = list.ToDictionary((IParameterValue d) => d.ID);
			_parameter_list = list.Select((IParameterValue v) => v.Value.ToString()).ToList();
		}

		public RequestParameters(IEnumerable<KeyValuePair<string, IParameterValue>> parameters)
		{
			_parameters = parameters.ToDictionary();
			_parameter_list = _parameters.Values.Select((IParameterValue p) => p.Value.ToString()).ToList();
		}

		IEnumerator<KeyValuePair<string, IParameterValue>> IEnumerable<KeyValuePair<string, IParameterValue>>.GetEnumerator()
		{
			return _parameters.GetEnumerator();
		}

		IEnumerator<string> IEnumerable<string>.GetEnumerator()
		{
			return _parameters.Values.Select((IParameterValue v) => v.Value?.ToString()).GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<string>)this).GetEnumerator();
		}

		public bool ContainsKey(string key)
		{
			return _parameters.ContainsKey(key);
		}

		public bool TryGetValue(string key, out IParameterValue value)
		{
			return _parameters.TryGetValue(key, out value);
		}

		public IEnumerable<string> Where(Func<string, bool> predicate)
		{
			return Enumerable.Where(this, predicate);
		}

		public IEnumerable<TResult> Select<TResult>(Func<string, TResult> selector)
		{
			return Enumerable.Select(this, selector);
		}

		public IEnumerable<TResult> SelectMany<TResult>(Func<string, IEnumerable<TResult>> selector)
		{
			return Enumerable.SelectMany(this, selector);
		}

		public IEnumerable<TResult> SelectMany<TResult>(Func<string, int, IEnumerable<TResult>> selector)
		{
			return Enumerable.SelectMany(this, selector);
		}

		public string First()
		{
			return this.First<string>();
		}

		public string First(Func<string, bool> predicate)
		{
			return Enumerable.First(this, predicate);
		}

		public string? FirstOrDefault()
		{
			return this.FirstOrDefault<string>();
		}

		public string FirstOrDefault(string defaultValue)
		{
			return this.FirstOrDefault<string>() ?? defaultValue;
		}

		public string? FirstOrDefault(Func<string, bool> predicate)
		{
			return Enumerable.FirstOrDefault(this, predicate);
		}

		public string FirstOrDefault(Func<string, bool> predicate, string defaultValue)
		{
			return Enumerable.FirstOrDefault(this, predicate) ?? defaultValue;
		}

		public bool Any()
		{
			return this.Any<string>();
		}

		public bool Any(Func<string, bool> predicate)
		{
			return Enumerable.Any(this, predicate);
		}
	}
	public interface IParameterValue
	{
		string ID { get; }

		string Name { get; }

		ParameterBase.ParameterType Type { get; }

		object? Value { get; }
	}
	public abstract class ParameterBase
	{
		[JsonConverter(typeof(AnnotatedEnumConverter<ParameterType>))]
		public enum ParameterType
		{
			[AnnotatedEnumConverter<ParameterType>.JsonValue("options")]
			Options,
			[AnnotatedEnumConverter<ParameterType>.JsonValue("hex-color")]
			HexColor
		}

		[JsonIgnore]
		public readonly string ID;

		[JsonProperty(PropertyName = "title")]
		public readonly string Name;

		[JsonProperty(PropertyName = "type")]
		public readonly ParameterType Type;

		protected ParameterBase(string name, string id, ParameterType type)
		{
			ID = id;
			Name = name;
			Type = type;
		}
	}
	[JsonConverter(typeof(CamelCaseStringEnumConverter))]
	public enum RequestType : byte
	{
		Test = 0,
		Start = 1,
		Stop = 2,
		GenericEvent = 16,
		RpcResponse = 208,
		PlayerInfo = 224,
		Login = 240,
		GameUpdate = 253,
		KeepAlive = byte.MaxValue
	}
	[JsonConverter(typeof(CamelCaseStringEnumConverter))]
	public enum ResponseType : byte
	{
		EffectRequest = 0,
		EffectStatus = 1,
		GenericEvent = 16,
		LoadEvent = 24,
		SaveEvent = 25,
		RpcRequest = 208,
		Login = 240,
		LoginSuccess = 241,
		GameUpdate = 253,
		Disconnect = 254,
		KeepAlive = byte.MaxValue
	}
	[Serializable]
	public class RpcRequest : SimpleJSONResponse
	{
		public string? method;

		public object?[]? args;
	}
	[Serializable]
	public class RpcResponse : SimpleJSONRequest
	{
		public object? value;

		public RpcResponse()
		{
			type = RequestType.RpcResponse;
		}
	}
	public abstract class SimpleJSONMessage
	{
		public static readonly JsonSerializerSettings JSON_SERIALIZER_SETTINGS = new JsonSerializerSettings
		{
			NullValueHandling = (NullValueHandling)1,
			MissingMemberHandling = (MissingMemberHandling)0,
			Formatting = (Formatting)0
		};

		public static readonly JsonSerializer JSON_SERIALIZER = new JsonSerializer
		{
			NullValueHandling = JSON_SERIALIZER_SETTINGS.NullValueHandling,
			MissingMemberHandling = JSON_SERIALIZER_SETTINGS.MissingMemberHandling,
			Formatting = JSON_SERIALIZER_SETTINGS.Formatting
		};

		private static int _next_id = 0;

		public static uint NextID
		{
			get
			{
				uint result;
				while ((result = (uint)Interlocked.Increment(ref _next_id)) == 0)
				{
				}
				return result;
			}
		}

		public abstract uint ID { get; }

		public abstract bool IsKeepAlive { get; }
	}
	[Serializable]
	public class SimpleJSONRequest : SimpleJSONMessage
	{
		public uint id = SimpleJSONMessage.NextID;

		public RequestType type;

		[JsonIgnore]
		public override uint ID => id;

		[JsonIgnore]
		public override bool IsKeepAlive => type == RequestType.KeepAlive;

		public static SimpleJSONRequest Parse(string json)
		{
			return Parse(JObject.Parse(json));
		}

		public static SimpleJSONRequest Parse(JObject j)
		{
			switch ((RequestType)(object)CamelCaseStringEnumConverter.ReadJToken(j.GetValue("type"), typeof(RequestType)))
			{
			case RequestType.Test:
			case RequestType.Start:
				return ((JToken)j).ToObject<EffectRequest>(SimpleJSONMessage.JSON_SERIALIZER);
			case RequestType.Stop:
				return ((JToken)j).ToObject<EffectRequest>(SimpleJSONMessage.JSON_SERIALIZER);
			case RequestType.RpcResponse:
				return ((JToken)j).ToObject<RpcResponse>(SimpleJSONMessage.JSON_SERIALIZER);
			case RequestType.PlayerInfo:
				return ((JToken)j).ToObject<PlayerInfo>(SimpleJSONMessage.JSON_SERIALIZER);
			case RequestType.Login:
				return ((JToken)j).ToObject<MessageRequest>(SimpleJSONMessage.JSON_SERIALIZER);
			case RequestType.GameUpdate:
				return ((JToken)j).ToObject<EmptyRequest>(SimpleJSONMessage.JSON_SERIALIZER);
			case RequestType.KeepAlive:
				return ((JToken)j).ToObject<EmptyRequest>(SimpleJSONMessage.JSON_SERIALIZER);
			default:
				throw new SerializationException("Message type was missing or unknown.");
			}
		}
	}
	[Serializable]
	public class SimpleJSONResponse : SimpleJSONMessage
	{
		public uint id;

		public ResponseType type;

		[JsonIgnore]
		public override uint ID => id;

		[JsonIgnore]
		public override bool IsKeepAlive => type == ResponseType.KeepAlive;

		[JsonIgnore]
		public static SimpleJSONResponse KeepAlive { get; } = new EmptyResponse
		{
			type = ResponseType.KeepAlive
		};


		public static SimpleJSONResponse Parse(string json)
		{
			return Parse(JObject.Parse(json));
		}

		public static SimpleJSONResponse Parse(JObject j)
		{
			return (ResponseType)(object)CamelCaseStringEnumConverter.ReadJToken(j.GetValue("type"), typeof(ResponseType)) switch
			{
				ResponseType.EffectRequest => ((JToken)j).ToObject<EffectResponse>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.EffectStatus => ((JToken)j).ToObject<EffectUpdate>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.RpcRequest => ((JToken)j).ToObject<RpcRequest>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.GenericEvent => ((JToken)j).ToObject<GenericEvent>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.Login => ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.LoginSuccess => ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.GameUpdate => ((JToken)j).ToObject<GameUpdate>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.Disconnect => ((JToken)j).ToObject<MessageResponse>(SimpleJSONMessage.JSON_SERIALIZER), 
				ResponseType.KeepAlive => ((JToken)j).ToObject<EmptyResponse>(SimpleJSONMessage.JSON_SERIALIZER), 
				_ => throw new SerializationException("Message type was missing or unknown."), 
			};
		}
	}
	internal static class StringEx
	{
		public static string ToCamelCase(this string input)
		{
			bool flag = false;
			string text = "";
			checked
			{
				for (int i = 0; i < input.Length; i++)
				{
					if (char.IsUpper(input[i]))
					{
						if (flag)
						{
							text += input.Substring(i);
							break;
						}
						text += char.ToLower(input[i]);
					}
					else
					{
						flag = true;
						text = ((i <= 1 || !char.IsUpper(input[i - 1]) || !char.IsUpper(input[i - 2])) ? (text + input[i]) : (text.Substring(0, text.Length - 1) + char.ToUpper(input[i - 1]) + input[i]));
					}
				}
				return text;
			}
		}
	}
}

BepInEx/plugins/RaziCirclet.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using AzuExtendedPlayerInventory;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExtraSlotsAPI;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RaziCirclet")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("RazisDev")]
[assembly: AssemblyProduct("RaziCirclet")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[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;
		}
	}
}
internal class CustomPrefabs
{
	[HarmonyPatch(typeof(ZNetView), "Awake")]
	public static class ZNetView_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ZSyncTransform), "Awake")]
	public static class ZSyncTransform_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ZSyncTransform), "OnEnable")]
	public static class ZSyncTransform_OnEnable_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ItemDrop), "Awake")]
	public static class ItemDrop_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(ItemDrop), "Start")]
	public static class ItemDrop_Start_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(Piece), "Awake")]
	public static class Piece_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(WearNTear), "Awake")]
	public static class WearNTear_Awake_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(WearNTear), "Start")]
	public static class WearNTear_Start_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	[HarmonyPatch(typeof(GuidePoint), "Start")]
	public static class GuidePoint_Start_AddPrefab
	{
		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			return !prefabInit;
		}
	}

	private const string c_rootObjectName = "_azumattRoot";

	private const string c_rootPrefabsName = "Prefabs";

	private static GameObject rootObject;

	private static GameObject rootPrefabs;

	public static bool prefabInit;

	private static void InitRootObject()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Expected O, but got Unknown
		if ((Object)(object)rootObject == (Object)null)
		{
			rootObject = (GameObject)(((object)GameObject.Find("_azumattRoot")) ?? ((object)new GameObject("_azumattRoot")));
		}
		Object.DontDestroyOnLoad((Object)(object)rootObject);
		if ((Object)(object)rootPrefabs == (Object)null)
		{
			Transform obj = rootObject.transform.Find("Prefabs");
			rootPrefabs = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)rootPrefabs == (Object)null)
			{
				rootPrefabs = new GameObject("Prefabs");
				rootPrefabs.transform.SetParent(rootObject.transform, false);
				rootPrefabs.SetActive(false);
			}
		}
	}

	internal static GameObject InitPrefabClone(GameObject prefabToClone, string prefabName)
	{
		InitRootObject();
		if ((Object)(object)rootPrefabs.transform.Find(prefabName) != (Object)null)
		{
			return ((Component)rootPrefabs.transform.Find(prefabName)).gameObject;
		}
		prefabInit = true;
		GameObject val = Object.Instantiate<GameObject>(prefabToClone, rootPrefabs.transform, false);
		prefabInit = false;
		((Object)val).name = prefabName;
		return val;
	}

	internal static Component AddComponent(GameObject gameObject, Type type)
	{
		prefabInit = true;
		Component result = gameObject.AddComponent(type);
		prefabInit = false;
		return result;
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			string key2 = key;
			string placeholder2 = placeholder;
			Func<T, string> convertConfigValue2 = convertConfigValue;
			ConfigEntry<T> config2 = config;
			if (convertConfigValue2 == null)
			{
				convertConfigValue2 = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key2))
			{
				PlaceholderProcessors[key2] = new Dictionary<string, Func<string>>();
			}
			config2.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key2][placeholder2] = () => convertConfigValue2(config2.Value);
				UpdatePlaceholderText(Localization.instance, key2);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1];
				if (dictionary.ContainsKey(text))
				{
					Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
				}
				else
				{
					dictionary[text] = item;
				}
			}
			byte[] array = LoadTranslationFromAssembly("English");
			if (array == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.ContainsKey(language))
				{
					text2 = File.ReadAllText(dictionary[language]);
				}
				else
				{
					byte[] array2 = LoadTranslationFromAssembly(language);
					if (array2 != null)
					{
						text2 = Encoding.UTF8.GetString(array2);
					}
				}
			}
			if (text2 == null && dictionary.ContainsKey("English"))
			{
				text2 = File.ReadAllText(dictionary["English"]);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string> { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			string resourceFileName2 = resourceFileName;
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName2, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace RaziCirclet
{
	[Serializable]
	public class HumanoidHelmetCirclet
	{
		public ItemData circlet;

		public HumanoidHelmetCirclet()
		{
			circlet = null;
		}
	}
	public static class HumanoidExtension
	{
		[HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")]
		public static class Humanoid_SetupVisEquipment_CustomItemType
		{
			private static void Postfix(Humanoid __instance, VisEquipment visEq)
			{
				if (!RaziCircletPlugin.enablePutOnTop.Value.IsOff())
				{
					ItemData circlet = __instance.GetCirclet();
					if (RaziCircletPlugin.equipCircletUnderHelmet.Value.IsOn())
					{
						visEq.SetCircletItem((circlet != null) ? ((Object)circlet.m_dropPrefab).name : "");
						return;
					}
					string helmetItem = ((circlet != null) ? ((Object)circlet.m_dropPrefab).name : ((__instance.m_helmetItem != null) ? ((Object)__instance.m_helmetItem.m_dropPrefab).name : ""));
					visEq.SetHelmetItem(helmetItem);
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "GetEquipmentWeight")]
		public static class Humanoid_GetEquipmentWeight_CustomItemType
		{
			private static void Postfix(Humanoid __instance, ref float __result)
			{
				if (!RaziCircletPlugin.enablePutOnTop.Value.IsOff())
				{
					ItemData circlet = __instance.GetCirclet();
					if (circlet != null)
					{
						__result += circlet.m_shared.m_weight;
					}
				}
			}
		}

		private static readonly ConditionalWeakTable<Humanoid, HumanoidHelmetCirclet> data = new ConditionalWeakTable<Humanoid, HumanoidHelmetCirclet>();

		public static HumanoidHelmetCirclet GetCircletData(this Humanoid humanoid)
		{
			return data.GetOrCreateValue(humanoid);
		}

		public static ItemData GetCirclet(this Humanoid humanoid)
		{
			return humanoid.GetCircletData().circlet;
		}

		public static ItemData SetCirclet(this Humanoid humanoid, ItemData item)
		{
			return humanoid.GetCircletData().circlet = item;
		}
	}
	[Serializable]
	public class VisEquipmentCirclet
	{
		public string m_circletItem = "";

		public GameObject m_circletItemInstance;

		public int m_currentCircletItemHash = 0;

		public bool m_showCirclet = true;

		public static readonly int s_circletItem = StringExtensionMethods.GetStableHashCode("CircletItem");
	}
	public static class VisEquipmentExtension
	{
		[HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")]
		public static class VisEquipment_UpdateEquipmentVisuals_CustomItemType
		{
			private static void Prefix(VisEquipment __instance)
			{
				int hash = 0;
				ZDO zDO = __instance.m_nview.GetZDO();
				if (zDO != null)
				{
					hash = zDO.GetInt(VisEquipmentCirclet.s_circletItem, 0);
				}
				else
				{
					VisEquipmentCirclet circletData = __instance.GetCircletData();
					if (!string.IsNullOrEmpty(circletData.m_circletItem))
					{
						hash = StringExtensionMethods.GetStableHashCode(circletData.m_circletItem);
					}
				}
				if (__instance.SetCircletEquipped(hash))
				{
					__instance.UpdateLodgroup();
				}
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "UpdateLodgroup")]
		public static class VisEquipment_UpdateLodgroup_CustomItemType
		{
			private static void Prefix(VisEquipment __instance)
			{
				if (RaziCircletPlugin.enablePutOnTop.Value.IsOff() || (Object)(object)__instance.m_lodGroup == (Object)null)
				{
					return;
				}
				VisEquipmentCirclet circletData = __instance.GetCircletData();
				if (Object.op_Implicit((Object)(object)circletData.m_circletItemInstance))
				{
					bool flag = __instance.m_currentHelmetItemHash == 0 || RaziCircletPlugin.alwaysShowCirclet.Value.IsOn();
					if (circletData.m_showCirclet != flag)
					{
						((Component)circletData.m_circletItemInstance.transform.Find("bronzehelmet")).gameObject.SetActive(flag);
						circletData.m_showCirclet = flag;
					}
				}
			}
		}

		private static readonly ConditionalWeakTable<VisEquipment, VisEquipmentCirclet> data = new ConditionalWeakTable<VisEquipment, VisEquipmentCirclet>();

		public static VisEquipmentCirclet GetCircletData(this VisEquipment visEquipment)
		{
			return data.GetOrCreateValue(visEquipment);
		}

		public static void SetCircletItem(this VisEquipment visEquipment, string name)
		{
			VisEquipmentCirclet circletData = visEquipment.GetCircletData();
			if (circletData.m_circletItem != name)
			{
				circletData.m_circletItem = name;
				if (visEquipment.m_nview.GetZDO() != null && visEquipment.m_nview.IsOwner())
				{
					visEquipment.m_nview.GetZDO().Set(VisEquipmentCirclet.s_circletItem, (!string.IsNullOrEmpty(name)) ? StringExtensionMethods.GetStableHashCode(name) : 0, false);
				}
			}
		}

		public static bool SetCircletEquipped(this VisEquipment visEquipment, int hash)
		{
			VisEquipmentCirclet circletData = visEquipment.GetCircletData();
			if (circletData.m_currentCircletItemHash == hash)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)circletData.m_circletItemInstance))
			{
				Object.Destroy((Object)(object)circletData.m_circletItemInstance);
				circletData.m_circletItemInstance = null;
			}
			circletData.m_currentCircletItemHash = hash;
			if (hash != 0)
			{
				circletData.m_circletItemInstance = visEquipment.AttachItem(hash, 0, visEquipment.m_helmet, true, false);
			}
			circletData.m_showCirclet = true;
			return true;
		}
	}
	internal static class CustomItemType
	{
		[HarmonyPatch(typeof(Humanoid), "EquipItem")]
		public static class Humanoid_EquipItem_CircletOnTop
		{
			private static void Postfix(Humanoid __instance, ItemData item, ref bool __result, bool triggerEquipEffects)
			{
				if (RaziCircletPlugin.enablePutOnTop.Value.IsOff())
				{
					return;
				}
				if (CircletItem.IsCircletItem(__instance.m_helmetItem))
				{
					RaziCircletPlugin.RaziCircletLogger.LogInfo((object)"Unequipping circlet on circlet equipment");
					__instance.UnequipItem(__instance.GetCirclet(), triggerEquipEffects);
				}
				else if (CircletItem.IsCircletItem(item))
				{
					bool flag = __instance.GetCirclet() != null;
					__instance.UnequipItem(__instance.GetCirclet(), triggerEquipEffects);
					if (flag)
					{
						__instance.m_visEquipment.UpdateEquipmentVisuals();
					}
					__instance.SetCirclet(item);
					if (__instance.IsItemEquiped(item))
					{
						item.m_equipped = true;
						__result = true;
					}
					__instance.SetupEquipment();
					if (triggerEquipEffects)
					{
						__instance.TriggerEquipEffect(item);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
		public static class Humanoid_UnequipItem_CircletOnTop
		{
			private static void Postfix(Humanoid __instance, ItemData item, bool triggerEquipEffects)
			{
				if (!RaziCircletPlugin.enablePutOnTop.Value.IsOff() && CircletItem.IsCircletItem(item) && __instance.GetCirclet() == item)
				{
					__instance.SetCirclet(null);
					__instance.SetupEquipment();
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UnequipAllItems")]
		public class Humanoid_UnequipAllItems_CircletOnTop
		{
			public static void Postfix(Humanoid __instance)
			{
				if (!RaziCircletPlugin.enablePutOnTop.Value.IsOff())
				{
					__instance.UnequipItem(__instance.GetCirclet(), false);
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "IsItemEquiped")]
		public static class Humanoid_IsItemEquiped_CircletOnTop
		{
			private static void Postfix(Humanoid __instance, ItemData item, ref bool __result)
			{
				if (!RaziCircletPlugin.enablePutOnTop.Value.IsOff() && CircletItem.IsCircletItem(item))
				{
					__result = __result || __instance.GetCirclet() == item;
				}
			}
		}

		[HarmonyPatch(typeof(ItemData), "IsEquipable")]
		public static class ItemDropItemData_IsEquipable_CircletOnTop
		{
			private static void Postfix(ItemData __instance, ref bool __result)
			{
				if (!RaziCircletPlugin.enablePutOnTop.Value.IsOff())
				{
					__result = __result || CircletItem.IsCircletType(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "Changed")]
		public static class Inventory_Changed_CustomItemType
		{
			private static void Prefix(Inventory __instance)
			{
				Player localPlayer = Player.m_localPlayer;
				if (__instance == ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null) && ((Humanoid)(object)Player.m_localPlayer).GetCirclet() != null && !__instance.ContainsItem(((Humanoid)(object)Player.m_localPlayer).GetCirclet()))
				{
					((Humanoid)(object)Player.m_localPlayer).SetCirclet(null);
					((Humanoid)Player.m_localPlayer).SetupEquipment();
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class AddSlotsPatchZNetSceneAwakePatch
		{
			private static void Postfix(ZNetScene __instance)
			{
				if (RaziCircletPlugin.itemSlotAzuEPI.Value.IsOn() && AzuExtendedPlayerInventory.API.IsLoaded())
				{
					AzuExtendedPlayerInventory.API.AddSlot(RaziCircletPlugin.itemSlotAzuEPIName.Value, (Player player) => ((Humanoid)(object)player).GetCirclet(), CircletItem.IsCircletItem);
				}
				if (ExtraSlotsAPI.API.IsReady())
				{
					ExtraSlotsAPI.API.AddSlotBefore("CircletExtended", () => RaziCircletPlugin.itemSlotExtraSlotsName.Value, CircletItem.IsCircletItem, CircletItem.IsCircletSlotAvailable, "HipLantern");
				}
			}
		}
	}
	public static class CircletItem
	{
		[HarmonyPatch(typeof(Inventory), "Load")]
		public class Inventory_Load_CircletStats
		{
			public static void Postfix(Inventory __instance)
			{
				PatchInventory(__instance);
			}
		}

		[HarmonyPatch(typeof(Inventory), "Changed")]
		public static class Inventory_Changed_PatchCirclets
		{
			private static void Prefix(Inventory __instance)
			{
				PatchInventory(__instance);
			}
		}

		public const string itemNameHelmetDverger = "HelmetDverger";

		public const string itemDropNameHelmetDverger = "$item_helmet_dverger";

		public static int itemHashHelmetDverger = StringExtensionMethods.GetStableHashCode("HelmetDverger");

		public static GameObject circletPrefab;

		internal static ItemType GetItemType()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return (ItemType)itemHashHelmetDverger;
		}

		internal static bool IsCircletType(ItemData item)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return item != null && item.m_shared.m_itemType == GetItemType();
		}

		internal static bool IsCircletItem(ItemDrop item)
		{
			return (Object)(object)item != (Object)null && (IsCircletItemName(item.GetPrefabName(((Object)item).name)) || IsCircletItemData(item.m_itemData));
		}

		internal static bool IsCircletItemData(ItemData item)
		{
			return item != null && (((Object)(object)item.m_dropPrefab != (Object)null && IsCircletItemName(((Object)item.m_dropPrefab).name)) || IsCircletItemDropName(item.m_shared.m_name));
		}

		internal static bool IsCircletItem(ItemData item)
		{
			return IsCircletItemData(item) && IsCircletType(item);
		}

		internal static bool IsCircletItemDropName(string name)
		{
			return name == "$item_helmet_dverger";
		}

		internal static bool IsCircletItemName(string name)
		{
			return name == "HelmetDverger";
		}

		public static bool IsCircletSlotKnown()
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || Player.m_localPlayer.m_isLoading)
			{
				return true;
			}
			return Player.m_localPlayer.IsKnownMaterial("$item_helmet_dverger");
		}

		public static bool IsCircletSlotAvailable()
		{
			return RaziCircletPlugin.itemSlotExtraSlots.Value.IsOn() && (RaziCircletPlugin.itemSlotExtraSlotsDiscovery.Value.IsOff() || IsCircletSlotKnown());
		}

		internal static void PatchCircletItemData(ItemData item, bool inventoryItemUpdate = true)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (item != null && RaziCircletPlugin.enablePutOnTop.Value.IsOn())
			{
				item.m_shared.m_itemType = GetItemType();
				item.m_shared.m_attachOverride = (ItemType)6;
			}
		}

		internal static void PatchInventory(Inventory inventory)
		{
			if (inventory == null)
			{
				return;
			}
			List<ItemData> list = new List<ItemData>();
			inventory.GetAllItems("$item_helmet_dverger", list);
			foreach (ItemData item in list)
			{
				PatchCircletItemData(item);
			}
		}
	}
	[BepInPlugin("RazisDev.RaziCirclet", "RaziCirclet", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RaziCircletPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order = null;

			[UsedImplicitly]
			public bool? Browsable = null;

			[UsedImplicitly]
			public string? Category = null;

			[UsedImplicitly]
			public Action<ConfigEntryBase>? CustomDrawer = null;
		}

		private class AcceptableShortcuts : AcceptableValueBase
		{
			public AcceptableShortcuts()
				: base(typeof(KeyboardShortcut))
			{
			}

			public override object Clamp(object value)
			{
				return value;
			}

			public override bool IsValid(object value)
			{
				return true;
			}

			public override string ToDescriptionString()
			{
				return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes);
			}
		}

		internal const string ModName = "RaziCirclet";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "RazisDev";

		private const string ModGUID = "RazisDev.RaziCirclet";

		private static string ConfigFileName = "RazisDev.RaziCirclet.cfg";

		private static string ConfigFileFullPath;

		internal static string ConnectionError;

		private readonly Harmony _harmony = new Harmony("RazisDev.RaziCirclet");

		public static readonly ManualLogSource RaziCircletLogger;

		private static readonly ConfigSync ConfigSync;

		private FileSystemWatcher _watcher;

		private readonly object _reloadLock = new object();

		private DateTime _lastConfigReloadTime;

		private const long RELOAD_DELAY = 10000000L;

		private static ConfigEntry<Toggle> _serverConfigLocked;

		public static ConfigEntry<Toggle> equipCircletUnderHelmet;

		public static ConfigEntry<Toggle> itemSlotAzuEPI;

		public static ConfigEntry<string> itemSlotAzuEPIName;

		public static ConfigEntry<Toggle> itemSlotExtraSlots;

		public static ConfigEntry<string> itemSlotExtraSlotsName;

		public static ConfigEntry<Toggle> itemSlotExtraSlotsDiscovery;

		public static ConfigEntry<Toggle> enablePutOnTop;

		public static ConfigEntry<Toggle> alwaysShowCirclet;

		public void Awake()
		{
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			_serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked);
			itemSlotAzuEPI = config("2 - Custom slot", "AzuEPI - Create slot", Toggle.On, "Create custom equipment slot with AzuExtendedPlayerInventory. Game restart is required to apply changes.");
			itemSlotAzuEPIName = config("2 - Custom slot", "AzuEPI - Slot Name", "Circlet", "Name of the custom equipment slot in AzuEPI.");
			itemSlotExtraSlots = config("2 - Custom slot", "ExtraSlots - Create slot", Toggle.On, "Create custom equipment slot with ExtraSlots.");
			itemSlotExtraSlotsName = config("2 - Custom slot", "ExtraSlots - Slot Name", "Circlet", "Name of the custom equipment slot in ExtraSlots.");
			itemSlotExtraSlotsDiscovery = config("2 - Custom slot", "ExtraSlots - Available after discovery", Toggle.On, "If enabled - slot will be active only if you know circlet item.");
			enablePutOnTop = config("3 - Features", "Enable put on top", Toggle.On, "Enables equipping Circlet on top of other helmet. Equip Circlet without using a helmet slot.");
			alwaysShowCirclet = config("3 - Features", "Always Show Circlet", Toggle.On, "If enabled - Circlet will be always visible, even if you have helmet equipped. Might not look good with all helmets.");
			itemSlotExtraSlots.SettingChanged += delegate
			{
				ExtraSlotsAPI.API.UpdateSlots();
			};
			equipCircletUnderHelmet = config("4 - Visual state", "Equip under helmet", Toggle.On, "If enabled - Circlet will be invisible if put on top of the helmet.\nIf disabled - Circlet will replace helmet");
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
			Game.isModded = true;
			((BaseUnityPlugin)this).Config.Save();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		private void OnDestroy()
		{
			SaveWithRespectToConfigSet();
			_watcher?.Dispose();
		}

		private void SetupWatcher()
		{
			_watcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			_watcher.Changed += ReadConfigValues;
			_watcher.Created += ReadConfigValues;
			_watcher.Renamed += ReadConfigValues;
			_watcher.IncludeSubdirectories = true;
			_watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			_watcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			DateTime now = DateTime.Now;
			long num = now.Ticks - _lastConfigReloadTime.Ticks;
			if (num < 10000000)
			{
				return;
			}
			lock (_reloadLock)
			{
				if (!File.Exists(ConfigFileFullPath))
				{
					RaziCircletLogger.LogWarning((object)"Config file does not exist. Skipping reload.");
					return;
				}
				try
				{
					RaziCircletLogger.LogDebug((object)"Reloading configuration...");
					SaveWithRespectToConfigSet(reload: true);
					RaziCircletLogger.LogInfo((object)"Configuration reload complete.");
				}
				catch (Exception ex)
				{
					RaziCircletLogger.LogError((object)("Error reloading configuration: " + ex.Message));
				}
			}
			_lastConfigReloadTime = now;
		}

		private void SaveWithRespectToConfigSet(bool reload = false)
		{
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			if (reload)
			{
				((BaseUnityPlugin)this).Config.Reload();
			}
			((BaseUnityPlugin)this).Config.Save();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
			SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2);
			syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		static RaziCircletPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ConnectionError = "";
			RaziCircletLogger = Logger.CreateLogSource("RaziCirclet");
			ConfigSync = new ConfigSync("RazisDev.RaziCirclet")
			{
				DisplayName = "RaziCirclet",
				CurrentVersion = "1.0.0",
				MinimumRequiredVersion = "1.0.0"
			};
			_serverConfigLocked = null;
		}
	}
	public static class KeyboardExtensions
	{
		public static bool IsKeyDown(this KeyboardShortcut shortcut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
		}

		public static bool IsKeyHeld(this KeyboardShortcut shortcut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
		}
	}
	public static class ToggleExtentions
	{
		public static bool IsOn(this RaziCircletPlugin.Toggle value)
		{
			return value == RaziCircletPlugin.Toggle.On;
		}

		public static bool IsOff(this RaziCircletPlugin.Toggle value)
		{
			return value == RaziCircletPlugin.Toggle.Off;
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	public static class RegisterAndCheckVersion
	{
		private static void Prefix(ZNetPeer peer, ref ZNet __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			RaziCircletPlugin.RaziCircletLogger.LogDebug((object)"Registering version RPC handler");
			peer.m_rpc.Register<ZPackage>("RaziCirclet_VersionCheck", (Action<ZRpc, ZPackage>)RpcHandlers.RPC_RaziCirclet_Version);
			RaziCircletPlugin.RaziCircletLogger.LogInfo((object)"Invoking version check");
			ZPackage val = new ZPackage();
			val.Write("1.0.0");
			peer.m_rpc.Invoke("RaziCirclet_VersionCheck", new object[1] { val });
		}
	}
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	public static class VerifyClient
	{
		private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance)
		{
			if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc))
			{
				return true;
			}
			RaziCircletPlugin.RaziCircletLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting"));
			rpc.Invoke("Error", new object[1] { 3 });
			return false;
		}

		private static void Postfix(ZNet __instance)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "RaziCircletRequestAdminSync", new object[1] { (object)new ZPackage() });
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
	public class ShowConnectionError
	{
		private static void Postfix(FejdStartup __instance)
		{
			if (__instance.m_connectionFailedPanel.activeSelf)
			{
				__instance.m_connectionFailedError.fontSizeMax = 25f;
				__instance.m_connectionFailedError.fontSizeMin = 15f;
				TMP_Text connectionFailedError = __instance.m_connectionFailedError;
				connectionFailedError.text = connectionFailedError.text + "\n" + RaziCircletPlugin.ConnectionError;
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Disconnect")]
	public static class RemoveDisconnectedPeerFromVerified
	{
		private static void Prefix(ZNetPeer peer, ref ZNet __instance)
		{
			if (__instance.IsServer())
			{
				RaziCircletPlugin.RaziCircletLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list"));
				RpcHandlers.ValidatedPeers.Remove(peer.m_rpc);
			}
		}
	}
	public static class RpcHandlers
	{
		public static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>();

		public static void RPC_RaziCirclet_Version(ZRpc rpc, ZPackage pkg)
		{
			string text = pkg.ReadString();
			RaziCircletPlugin.RaziCircletLogger.LogInfo((object)("Version check, local: 1.0.0,  remote: " + text));
			if (text != "1.0.0")
			{
				RaziCircletPlugin.ConnectionError = "RaziCirclet Installed: 1.0.0\n Needed: " + text;
				if (ZNet.instance.IsServer())
				{
					RaziCircletPlugin.RaziCircletLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting..."));
					rpc.Invoke("Error", new object[1] { 3 });
				}
			}
			else if (!ZNet.instance.IsServer())
			{
				RaziCircletPlugin.RaziCircletLogger.LogInfo((object)"Received same version from server!");
			}
			else
			{
				RaziCircletPlugin.RaziCircletLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list"));
				ValidatedPeers.Add(rpc);
			}
		}
	}
}
namespace ServerSync
{
	[PublicAPI]
	internal abstract class OwnConfigEntryBase
	{
		public object? LocalBaseValue;

		public bool SynchronizedConfig = true;

		public abstract ConfigEntryBase BaseConfig { get; }
	}
	[PublicAPI]
	internal class SyncedConfigEntry<T> : OwnConfigEntryBase
	{
		public readonly ConfigEntry<T> SourceConfig;

		public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig;

		public T Value
		{
			get
			{
				return SourceConfig.Value;
			}
			set
			{
				SourceConfig.Value = value;
			}
		}

		public SyncedConfigEntry(ConfigEntry<T> sourceConfig)
		{
			SourceConfig = sourceConfig;
		}

		public void AssignLocalValue(T value)
		{
			if (LocalBaseValue == null)
			{
				Value = value;
			}
			else
			{
				LocalBaseValue = value;
			}
		}
	}
	internal abstract class CustomSyncedValueBase
	{
		public object? LocalBaseValue;

		public readonly string Identifier;

		public readonly Type Type;

		private object? boxedValue;

		protected bool localIsOwner;

		public readonly int Priority;

		public object? BoxedValue
		{
			get
			{
				return boxedValue;
			}
			set
			{
				boxedValue = value;
				this.ValueChanged?.Invoke();
			}
		}

		public event Action? ValueChanged;

		protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority)
		{
			Priority = priority;
			Identifier = identifier;
			Type = type;
			configSync.AddCustomValue(this);
			localIsOwner = configSync.IsSourceOfTruth;
			configSync.SourceOfTruthChanged += delegate(bool truth)
			{
				localIsOwner = truth;
			};
		}
	}
	[PublicAPI]
	internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase
	{
		public T Value
		{
			get
			{
				return (T)base.BoxedValue;
			}
			set
			{
				base.BoxedValue = value;
			}
		}

		public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0)
			: base(configSync, identifier, typeof(T), priority)
		{
			Value = value;
		}

		public void AssignLocalValue(T value)
		{
			if (localIsOwner)
			{
				Value = value;
			}
			else
			{
				LocalBaseValue = value;
			}
		}
	}
	internal class ConfigurationManagerAttributes
	{
		[UsedImplicitly]
		public bool? ReadOnly = false;
	}
	[PublicAPI]
	internal class ConfigSync
	{
		[HarmonyPatch(typeof(ZRpc), "HandlePackage")]
		private static class SnatchCurrentlyHandlingRPC
		{
			public static ZRpc? currentRpc;

			[HarmonyPrefix]
			private static void Prefix(ZRpc __instance)
			{
				currentRpc = __instance;
			}
		}

		[HarmonyPatch(typeof(ZNet), "Awake")]
		internal static class RegisterRPCPatch
		{
			[HarmonyPostfix]
			private static void Postfix(ZNet __instance)
			{
				isServer = __instance.IsServer();
				foreach (ConfigSync configSync2 in configSyncs)
				{
					ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync);
					if (isServer)
					{
						configSync2.InitialSyncDone = true;
						Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections"));
					}
				}
				if (isServer)
				{
					((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges());
				}
				static void SendAdmin(List<ZNetPeer> peers, bool isAdmin)
				{
					ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1]
					{
						new PackageEntry
						{
							section = "Internal",
							key = "lockexempt",
							type = typeof(bool),
							value = isAdmin
						}
					});
					ConfigSync configSync = configSyncs.First();
					if (configSync != null)
					{
						((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package));
					}
				}
				static IEnumerator WatchAdminListChanges()
				{
					MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null);
					SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
					List<string> CurrentList = new List<string>(adminList.GetList());
					while (true)
					{
						yield return (object)new WaitForSeconds(30f);
						if (!adminList.GetList().SequenceEqual(CurrentList))
						{
							CurrentList = new List<string>(adminList.GetList());
							List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p)
							{
								string hostName = p.m_rpc.GetSocket().GetHostName();
								return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName }));
							}).ToList();
							List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList();
							SendAdmin(nonAdminPeer, isAdmin: false);
							SendAdmin(adminPeer, isAdmin: true);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		private static class RegisterClientRPCPatch
		{
			[HarmonyPostfix]
			private static void Postfix(ZNet __instance, ZNetPeer peer)
			{
				if (__instance.IsServer())
				{
					return;
				}
				foreach (ConfigSync configSync in configSyncs)
				{
					peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync);
				}
			}
		}

		private class ParsedConfigs
		{
			public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>();

			public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>();
		}

		[HarmonyPatch(typeof(ZNet), "Shutdown")]
		private class ResetConfigsOnShutdown
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				ProcessingServerUpdate = true;
				foreach (ConfigSync configSync in configSyncs)
				{
					configSync.resetConfigsFromServer();
					configSync.IsSourceOfTruth = true;
					configSync.InitialSyncDone = false;
				}
				ProcessingServerUpdate = false;
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		private class SendConfigsAfterLogin
		{
			private class BufferingSocket : ISocket
			{
				public volatile bool finished = false;

				public volatile int versionMatchQueued = -1;

				public readonly List<ZPackage> Package = new List<ZPackage>();

				public readonly ISocket Original;

				public BufferingSocket(ISocket original)
				{
					Original = original;
				}

				public bool IsConnected()
				{
					return Original.IsConnected();
				}

				public ZPackage Recv()
				{
					return Original.Recv();
				}

				public int GetSendQueueSize()
				{
					return Original.GetSendQueueSize();
				}

				public int GetCurrentSendRate()
				{
					return Original.GetCurrentSendRate();
				}

				public bool IsHost()
				{
					return Original.IsHost();
				}

				public void Dispose()
				{
					Original.Dispose();
				}

				public bool GotNewData()
				{
					return Original.GotNewData();
				}

				public void Close()
				{
					Original.Close();
				}

				public string GetEndPointString()
				{
					return Original.GetEndPointString();
				}

				public void GetAndResetStats(out int totalSent, out int totalRecv)
				{
					Original.GetAndResetStats(ref totalSent, ref totalRecv);
				}

				public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec)
				{
					Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec);
				}

				public ISocket Accept()
				{
					return Original.Accept();
				}

				public int GetHostPort()
				{
					return Original.GetHostPort();
				}

				public bool Flush()
				{
					return Original.Flush();
				}

				public string GetHostName()
				{
					return Original.GetHostName();
				}

				public void VersionMatch()
				{
					if (finished)
					{
						Original.VersionMatch();
					}
					else
					{
						versionMatchQueued = Package.Count;
					}
				}

				public void Send(ZPackage pkg)
				{
					//IL_0057: Unknown result type (might be due to invalid IL or missing references)
					//IL_005d: Expected O, but got Unknown
					int pos = pkg.GetPos();
					pkg.SetPos(0);
					int num = pkg.ReadInt();
					if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished)
					{
						ZPackage val = new ZPackage(pkg.GetArray());
						val.SetPos(pos);
						Package.Add(val);
					}
					else
					{
						pkg.SetPos(pos);
						Original.Send(pkg);
					}
				}
			}

			[HarmonyPriority(800)]
			[HarmonyPrefix]
			private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Invalid comparison between Unknown and I4
				if (__instance.IsServer())
				{
					BufferingSocket value = new BufferingSocket(rpc.GetSocket());
					AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, value);
					object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc });
					ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null);
					if (val != null && (int)ZNet.m_onlineBackend > 0)
					{
						AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, value);
					}
					if (__state == null)
					{
						__state = new Dictionary<Assembly, BufferingSocket>();
					}
					__state[Assembly.GetExecutingAssembly()] = value;
				}
			}

			[HarmonyPostfix]
			private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc)
			{
				ZRpc rpc2 = rpc;
				ZNet __instance2 = __instance;
				Dictionary<Assembly, BufferingSocket> __state2 = __state;
				ZNetPeer peer;
				if (__instance2.IsServer())
				{
					object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 });
					peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null);
					if (peer == null)
					{
						SendBufferedData();
					}
					else
					{
						((MonoBehaviour)__instance2).StartCoroutine(sendAsync());
					}
				}
				void SendBufferedData()
				{
					if (rpc2.GetSocket() is BufferingSocket bufferingSocket)
					{
						AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original);
						object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 });
						ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null);
						if (val != null)
						{
							AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original);
						}
					}
					BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()];
					bufferingSocket2.finished = true;
					for (int i = 0; i < bufferingSocket2.Package.Count; i++)
					{
						if (i == bufferingSocket2.versionMatchQueued)
						{
							bufferingSocket2.Original.VersionMatch();
						}
						bufferingSocket2.Original.Send(bufferingSocket2.Package[i]);
					}
					if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued)
					{
						bufferingSocket2.Original.VersionMatch();
					}
				}
				IEnumerator sendAsync()
				{
					foreach (ConfigSync configSync in configSyncs)
					{
						List<PackageEntry> entries = new List<PackageEntry>();
						if (configSync.CurrentVersion != null)
						{
							entries.Add(new PackageEntry
							{
								section = "Internal",
								key = "serverversion",
								type = typeof(string),
								value = configSync.CurrentVersion
							});
						}
						MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null);
						SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
						entries.Add(new PackageEntry
						{
							section = "Internal",
							key = "lockexempt",
							type = typeof(bool),
							value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2]
							{
								adminList,
								rpc2.GetSocket().GetHostName()
							}))
						});
						ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false);
						yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package));
					}
					SendBufferedData();
				}
			}
		}

		private class PackageEntry
		{
			public string section = null;

			public string key = null;

			public Type type = null;

			public object? value;
		}

		[HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")]
		private static class PreventSavingServerInfo
		{
			[HarmonyPrefix]
			private static bool Prefix(ConfigEntryBase __instance, ref string __result)
			{
				OwnConfigEntryBase ownConfigEntryBase = configData(__instance);
				if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase))
				{
					return true;
				}
				__result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType);
				return false;
			}
		}

		[HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")]
		private static class PreventConfigRereadChangingValues
		{
			[HarmonyPrefix]
			private static bool Prefix(ConfigEntryBase __instance, string value)
			{
				OwnConfigEntryBase ownConfigEntryBase = configData(__instance);
				if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null)
				{
					return true;
				}
				try
				{
					ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType);
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}");
				}
				return false;
			}
		}

		private class InvalidDeserializationTypeException : Exception
		{
			public string expected = null;

			public string received = null;

			public string field = "";
		}

		public static bool ProcessingServerUpdate;

		public readonly string Name;

		public string? DisplayName;

		public string? CurrentVersion;

		public string? MinimumRequiredVersion;

		public bool ModRequired = false;

		private bool? forceConfigLocking;

		private bool isSourceOfTruth = true;

		private static readonly HashSet<ConfigSync> configSyncs;

		private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>();

		private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>();

		private static bool isServer;

		private static bool lockExempt;

		private OwnConfigEntryBase? lockedConfig = null;

		private const byte PARTIAL_CONFIGS = 1;

		private const byte FRAGMENTED_CONFIG = 2;

		private const byte COMPRESSED_CONFIG = 4;

		private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>();

		private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>();

		private static long packageCounter;

		public bool IsLocked
		{
			get
			{
				bool? flag = forceConfigLocking;
				bool num;
				if (!flag.HasValue)
				{
					if (lockedConfig == null)
					{
						goto IL_0052;
					}
					num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0;
				}
				else
				{
					num = flag.GetValueOrDefault();
				}
				if (!num)
				{
					goto IL_0052;
				}
				int result = ((!lockExempt) ? 1 : 0);
				goto IL_0053;
				IL_0053:
				return (byte)result != 0;
				IL_0052:
				result = 0;
				goto IL_0053;
			}
			set
			{
				forceConfigLocking = value;
			}
		}

		public bool IsAdmin => lockExempt || isSourceOfTruth;

		public bool IsSourceOfTruth
		{
			get
			{
				return isSourceOfTruth;
			}
			private set
			{
				if (value != isSourceOfTruth)
				{
					isSourceOfTruth = value;
					this.SourceOfTruthChanged?.Invoke(value);
				}
			}
		}

		public bool InitialSyncDone { get; private set; } = false;


		public event Action<bool>? SourceOfTruthChanged;

		private event Action? lockedConfigChanged;

		static ConfigSync()
		{
			ProcessingServerUpdate = false;
			configSyncs = new HashSet<ConfigSync>();
			lockExempt = false;
			packageCounter = 0L;
			RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle);
		}

		public ConfigSync(string name)
		{
			Name = name;
			configSyncs.Add(this);
			new VersionCheck(this);
		}

		public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
		{
			ConfigEntry<T> configEntry2 = configEntry;
			OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2);
			SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>;
			if (syncedEntry == null)
			{
				syncedEntry = new SyncedConfigEntry<T>(configEntry2);
				AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1]
				{
					new ConfigurationManagerAttributes()
				}.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray());
				configEntry2.SettingChanged += delegate
				{
					if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig)
					{
						Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2);
					}
				};
				allConfigs.Add(syncedEntry);
			}
			return syncedEntry;
		}

		public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible
		{
			if (lockedConfig != null)
			{
				throw new Exception("Cannot initialize locking ConfigEntry twice");
			}
			lockedConfig = AddConfigEntry<T>(lockingConfig);
			lockingConfig.SettingChanged += delegate
			{
				this.lockedConfigChanged?.Invoke();
			};
			return (SyncedConfigEntry<T>)lockedConfig;
		}

		internal void AddCustomValue(CustomSyncedValueBase customValue)
		{
			CustomSyncedValueBase customValue2 = customValue;
			if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier))
			{
				throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)");
			}
			allCustomValues.Add(customValue2);
			allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority));
			customValue2.ValueChanged += delegate
			{
				if (!ProcessingServerUpdate)
				{
					Broadcast(ZRoutedRpc.Everybody, customValue2);
				}
			};
		}

		private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package)
		{
			lockedConfigChanged += serverLockedSettingChanged;
			IsSourceOfTruth = false;
			if (HandleConfigSyncRPC(0L, package, clientUpdate: false))
			{
				InitialSyncDone = true;
			}
		}

		private void RPC_FromOtherClientConfigSync(long sender, ZPackage package)
		{
			HandleConfigSyncRPC(sender, package, clientUpdate: true);
		}

		private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Expected O, but got Unknown
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Expected O, but got Unknown
			try
			{
				if (isServer && IsLocked)
				{
					ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc;
					object obj;
					if (currentRpc == null)
					{
						obj = null;
					}
					else
					{
						ISocket socket = currentRpc.GetSocket();
						obj = ((socket != null) ? socket.GetHostName() : null);
					}
					string text = (string)obj;
					if (text != null)
					{
						MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null);
						SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
						if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text }))))
						{
							return false;
						}
					}
				}
				cacheExpirations.RemoveAll(delegate(KeyValuePair<long, string> kv)
				{
					if (kv.Key < DateTimeOffset.Now.Ticks)
					{
						configValueCache.Remove(kv.Value);
						return true;
					}
					return false;
				});
				byte b = package.ReadByte();
				if ((b & 2u) != 0)
				{
					long num = package.ReadLong();
					string text2 = sender.ToString() + num;
					if (!configValueCache.TryGetValue(text2, out SortedDictionary<int, byte[]> value))
					{
						value = new SortedDictionary<int, byte[]>();
						configValueCache[text2] = value;
						cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2));
					}
					int key = package.ReadInt();
					int num2 = package.ReadInt();
					value.Add(key, package.ReadByteArray());
					if (value.Count < num2)
					{
						return false;
					}
					configValueCache.Remove(text2);
					package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray());
					b = package.ReadByte();
				}
				ProcessingServerUpdate = true;
				if ((b & 4u) != 0)
				{
					byte[] buffer = package.ReadByteArray();
					MemoryStream stream = new MemoryStream(buffer);
					MemoryStream memoryStream = new MemoryStream();
					using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress))
					{
						deflateStream.CopyTo(memoryStream);
					}
					package = new ZPackage(memoryStream.ToArray());
					b = package.ReadByte();
				}
				if ((b & 1) == 0)
				{
					resetConfigsFromServer();
				}
				ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package);
				ConfigFile val2 = null;
				bool saveOnConfigSet = false;
				foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues)
				{
					if (!isServer && configValue.Key.LocalBaseValue == null)
					{
						configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue;
					}
					if (val2 == null)
					{
						val2 = configValue.Key.BaseConfig.ConfigFile;
						saveOnConfigSet = val2.SaveOnConfigSet;
						val2.SaveOnConfigSet = false;
					}
					configValue.Key.BaseConfig.BoxedValue = configValue.Value;
				}
				if (val2 != null)
				{
					val2.SaveOnConfigSet = saveOnConfigSet;
				}
				foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues)
				{
					if (!isServer)
					{
						CustomSyncedValueBase key2 = customValue.Key;
						if (key2.LocalBaseValue == null)
						{
							key2.LocalBaseValue = customValue.Key.BoxedValue;
						}
					}
					customValue.Key.BoxedValue = customValue.Value;
				}
				Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name));
				if (!isServer)
				{
					serverLockedSettingChanged();
				}
				return true;
			}
			finally
			{
				ProcessingServerUpdate = false;
			}
		}

		private ParsedConfigs ReadConfigsFromPackage(ZPackage package)
		{
			ParsedConfigs parsedConfigs = new ParsedConfigs();
			Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c);
			Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c);
			int num = package.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string text = package.ReadString();
				string text2 = package.ReadString();
				string text3 = package.ReadString();
				Type type = Type.GetType(text3);
				if (text3 == "" || type != null)
				{
					object obj;
					try
					{
						obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type));
					}
					catch (InvalidDeserializationTypeException ex)
					{
						Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected));
						continue;
					}
					OwnConfigEntryBase value2;
					if (text == "Internal")
					{
						CustomSyncedValueBase value;
						if (text2 == "serverversion")
						{
							if (obj?.ToString() != CurrentVersion)
							{
								Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown")));
							}
						}
						else if (text2 == "lockexempt")
						{
							if (obj is bool flag)
							{
								lockExempt = flag;
							}
						}
						else if (dictionary2.TryGetValue(text2, out value))
						{
							if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3)
							{
								parsedConfigs.customValues[value] = obj;
								continue;
							}
							Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName));
						}
					}
					else if (dictionary.TryGetValue(text + "_" + text2, out value2))
					{
						Type type2 = configType(value2.BaseConfig);
						if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3)
						{
							parsedConfigs.configValues[value2] = obj;
							continue;
						}
						Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName));
					}
					else
					{
						Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match."));
					}
					continue;
				}
				Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs"));
				return new ParsedConfigs();
			}
			return parsedConfigs;
		}

		private static bool isWritableConfig(OwnConfigEntryBase config)
		{
			OwnConfigEntryBase config2 = config;
			ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config2));
			if (configSync == null)
			{
				return true;
			}
			return configSync.IsSourceOfTruth || !config2.SynchronizedConfig || config2.LocalBaseValue == null || (!configSync.IsLocked && (config2 != configSync.lockedConfig || lockExempt));
		}

		private void serverLockedSettingChanged()
		{
			foreach (OwnConfigEntryBase allConfig in allConfigs)
			{
				configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig);
			}
		}

		private void resetConfigsFromServer()
		{
			ConfigFile val = null;
			bool saveOnConfigSet = false;
			foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null))
			{
				if (val == null)
				{
					val = item.BaseConfig.ConfigFile;
					saveOnConfigSet = val.SaveOnConfigSet;
					val.SaveOnConfigSet = false;
				}
				item.BaseConfig.BoxedValue = item.LocalBaseValue;
				item.LocalBaseValue = null;
			}
			if (val != null)
			{
				val.SaveOnConfigSet = saveOnConfigSet;
			}
			foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null))
			{
				item2.BoxedValue = item2.LocalBaseValue;
				item2.LocalBaseValue = null;
			}
			lockedConfigChanged -= serverLockedSettingChanged;
			serverLockedSettingChanged();
		}

		private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package)
		{
			ZNetPeer peer2 = peer;
			ZRoutedRpc rpc = ZRoutedRpc.instance;
			if (rpc == null)
			{
				yield break;
			}
			byte[] data = package.GetArray();
			if (data != null && data.LongLength > 250000)
			{
				int fragments = (int)(1 + (data.LongLength - 1) / 250000);
				long packageIdentifier = ++packageCounter;
				int fragment = 0;
				while (fragment < fragments)
				{
					foreach (bool item in waitForQueue())
					{
						yield return item;
					}
					if (peer2.m_socket.IsConnected())
					{
						ZPackage fragmentedPackage = new ZPackage();
						fragmentedPackage.Write((byte)2);
						fragmentedPackage.Write(packageIdentifier);
						fragmentedPackage.Write(fragment);
						fragmentedPackage.Write(fragments);
						fragmentedPackage.Write(data.Skip(250000 * fragment).Take(250000).ToArray());
						SendPackage(fragmentedPackage);
						if (fragment != fragments - 1)
						{
							yield return true;
						}
						int num = fragment + 1;
						fragment = num;
						continue;
					}
					break;
				}
				yield break;
			}
			foreach (bool item2 in waitForQueue())
			{
				yield return item2;
			}
			SendPackage(package);
			void SendPackage(ZPackage pkg)
			{
				string text = Name + " ConfigSync";
				if (isServer)
				{
					peer2.m_rpc.Invoke(text, new object[1] { pkg });
				}
				else
				{
					rpc.InvokeRoutedRPC(peer2.m_server ? 0 : peer2.m_uid, text, new object[1] { pkg });
				}
			}
			IEnumerable<bool> waitForQueue()
			{
				float timeout = Time.time + 30f;
				while (peer2.m_socket.GetSendQueueSize() > 20000)
				{
					if (Time.time > timeout)
					{
						Debug.Log((object)$"Disconnecting {peer2.m_uid} after 30 seconds config sending timeout");
						peer2.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 });
						ZNet.instance.Disconnect(peer2);
						break;
					}
					yield return false;
				}
			}
		}

		private IEnumerator sendZPackage(long target, ZPackage package)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return Enumerable.Empty<object>().GetEnumerator();
			}
			List<ZNetPeer> list = (List<ZNetPeer>)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance);
			if (target != ZRoutedRpc.Everybody)
			{
				list = list.Where((ZNetPeer p) => p.m_uid == target).ToList();
			}
			return sendZPackage(list, package);
		}

		private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package)
		{
			ZPackage package2 = package;
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				yield break;
			}
			byte[] rawData = package2.GetArray();
			if (rawData != null && rawData.LongLength > 10000)
			{
				ZPackage compressedPackage = new ZPackage();
				compressedPackage.Write((byte)4);
				MemoryStream output = new MemoryStream();
				using (DeflateStream deflateStream = new DeflateStream(output, CompressionLevel.Optimal))
				{
					deflateStream.Write(rawData, 0, rawData.Length);
				}
				compressedPackage.Write(output.ToArray());
				package2 = compressedPackage;
			}
			List<IEnumerator<bool>> writers = (from peer in peers
				where peer.IsReady()
				select peer into p
				select distributeConfigToPeers(p, package2)).ToList();
			writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext());
			while (writers.Count > 0)
			{
				yield return null;
				writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext());
			}
		}

		private void Broadcast(long target, params ConfigEntryBase[] configs)
		{
			if (!IsLocked || isServer)
			{
				ZPackage package = ConfigsToPackage(configs);
				ZNet instance = ZNet.instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package));
				}
			}
		}

		private void Broadcast(long target, params CustomSyncedValueBase[] customValues)
		{
			if (!IsLocked || isServer)
			{
				ZPackage package = ConfigsToPackage(null, customValues);
				ZNet instance = ZNet.instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package));
				}
			}
		}

		private static OwnConfigEntryBase? configData(ConfigEntryBase config)
		{
			return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault();
		}

		public static SyncedConfigEntry<T>? ConfigData<T>(ConfigEntry<T> config)
		{
			return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault();
		}

		private static T configAttribute<T>(ConfigEntryBase config)
		{
			return config.Description.Tags.OfType<T>().First();
		}

		private static Type configType(ConfigEntryBase config)
		{
			return configType(config.SettingType);
		}

		private static Type configType(Type type)
		{
			return type.IsEnum ? Enum.GetUnderlyingType(type) : type;
		}

		private static ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase>? configs = null, IEnumerable<CustomSyncedValueBase>? customValues = null, IEnumerable<PackageEntry>? packageEntries = null, bool partial = true)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>();
			List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>();
			ZPackage val = new ZPackage();
			val.Write((byte)(partial ? 1 : 0));
			val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0));
			foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>())
			{
				AddEntryToPackage(val, item);
			}
			foreach (CustomSyncedValueBase item2 in list2)
			{
				AddEntryToPackage(val, new PackageEntry
				{
					section = "Internal",
					key = item2.Identifier,
					type = item2.Type,
					value = item2.BoxedValue
				});
			}
			foreach (ConfigEntryBase item3 in list)
			{
				AddEntryToPackage(val, new PackageEntry
				{
					section = item3.Definition.Section,
					key = item3.Definition.Key,
					type = configType(item3),
					value = item3.BoxedValue
				});
			}
			return val;
		}

		private static void AddEntryToPackage(ZPackage package, PackageEntry entry)
		{
			package.Write(entry.section);
			package.Write(entry.key);
			package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type));
			AddValueToZPackage(package, entry.value);
		}

		private static string GetZPackageTypeString(Type type)
		{
			return type.AssemblyQualifiedName;
		}

		private static void AddValueToZPackage(ZPackage package, object? value)
		{
			Type type = value?.GetType();
			if (value is Enum)
			{
				value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture);
			}
			else
			{
				if (value is ICollection collection)
				{
					package.Write(collection.Count);
					{
						foreach (object item in collection)
						{
							AddValueToZPackage(package, item);
						}
						return;
					}
				}
				if ((object)type != null && type.IsValueType && !type.IsPrimitive)
				{
					FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					package.Write(fields.Length);
					FieldInfo[] array = fields;
					foreach (FieldInfo fieldInfo in array)
					{
						package.Write(GetZPackageTypeString(fieldInfo.FieldType));
						AddValueToZPackage(package, fieldInfo.GetValue(value));
					}
					return;
				}
			}
			ZRpc.Serialize(new object[1] { value }, ref package);
		}

		private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type)
		{
			if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				int num = package.ReadInt();
				if (num != fields.Length)
				{
					throw new InvalidDeserializationTypeException
					{
						received = $"(field count: {num})",
						expected = $"(field count: {fields.Length})"
					};
				}
				object uninitializedObject = FormatterServices.GetUninitializedObject(type);
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					string text = package.ReadString();
					if (text != GetZPackageTypeString(fieldInfo.FieldType))
					{
						throw new InvalidDeserializationTypeException
						{
							received = text,
							expected = GetZPackageTypeString(fieldInfo.FieldType),
							field = fieldInfo.Name
						};
					}
					fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType));
				}
				return uninitializedObject;
			}
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
			{
				int num2 = package.ReadInt();
				IDictionary dictionary = (IDictionary)Activator.CreateInstance(type);
				Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments);
				FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic);
				for (int j = 0; j < num2; j++)
				{
					object obj = ReadValueWithTypeFromZPackage(package, type2);
					dictionary.Add(field.GetValue(obj), field2.GetValue(obj));
				}
				return dictionary;
			}
			if (type != typeof(List<string>) && type.IsGenericType)
			{
				Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]);
				if ((object)type3 != null && type3.IsAssignableFrom(type))
				{
					int num3 = package.ReadInt();
					object obj2 = Activator.CreateInstance(type);
					MethodInfo method = type3.GetMethod("Add");
					for (int k = 0; k < num3; k++)
					{
						method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) });
					}
					return obj2;
				}
			}
			ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
			AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type);
			List<object> source = new List<object>();
			ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source);
			return source.First();
		}
	}
	[PublicAPI]
	[HarmonyPatch]
	internal class VersionCheck
	{
		private static readonly HashSet<VersionCheck> versionChecks;

		private static readonly Dictionary<string, string> notProcessedNames;

		public string Name;

		private string? displayName;

		private string? currentVersion;

		private string? minimumRequiredVersion;

		public bool ModRequired = true;

		private string? ReceivedCurrentVersion;

		private string? ReceivedMinimumRequiredVersion;

		private readonly List<ZRpc> ValidatedClients = new List<ZRpc>();

		private ConfigSync? ConfigSync;

		public string DisplayName
		{
			get
			{
				return displayName ?? Name;
			}
			set
			{
				displayName = value;
			}
		}

		public string CurrentVersion
		{
			get
			{
				return currentVersion ?? "0.0.0";
			}
			set
			{
				currentVersion = value;
			}
		}

		public string MinimumRequiredVersion
		{
			get
			{
				return minimumRequiredVersion ?? (ModRequired ? CurrentVersion : "0.0.0");
			}
			set
			{
				minimumRequiredVersion = value;
			}
		}

		private static void PatchServerSync()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null));
			if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0)
			{
				return;
			}
			Harmony val = new Harmony("org.bepinex.helpers.ServerSync");
			foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) })
				where t.IsClass
				select t)
			{
				val.PatchAll(item);
			}
		}

		static VersionCheck()
		{
			versionChecks = new HashSet<VersionCheck>();
			notProcessedNames = new Dictionary<string, string>();
			typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1]
			{
				new Action(PatchServerSync)
			});
		}

		public VersionCheck(string name)
		{
			Name = name;
			ModRequired = true;
			versionChecks.Add(this);
		}

		public VersionCheck(ConfigSync configSync)
		{
			ConfigSync = configSync;
			Name = ConfigSync.Name;
			versionChecks.Add(this);
		}

		public void Initialize()
		{
			ReceivedCurrentVersion = null;
			ReceivedMinimumRequiredVersion = null;
			if (ConfigSync != null)
			{
				Name = ConfigSync.Name;
				DisplayName = ConfigSync.DisplayName;
				CurrentVersion = ConfigSync.CurrentVersion;
				MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion;
				ModRequired = ConfigSync.ModRequired;
			}
		}

		private bool IsVersionOk()
		{
			if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null)
			{
				return !ModRequired;
			}
			bool flag = new System.Version(CurrentVersion) >= new System.Version(ReceivedMinimumRequiredVersion);
			bool flag2 = new System.Version(ReceivedCurrentVersion) >= new System.Version(MinimumRequiredVersion);
			return flag && flag2;
		}

		private string ErrorClient()
		{
			if (ReceivedMinimumRequiredVersion == null)
			{
				return DisplayName + " is not installed on the server.";
			}
			return (new System.Version(CurrentVersion) >= new System.Version(ReceivedMinimumRequiredVersion)) ? (DisplayName + " may not be higher than version " + ReceivedCurrentVersion + ". You have version " + CurrentVersion + ".") : (DisplayName + " needs to be at least version " + ReceivedMinimumRequiredVersion + ". You have version " + CurrentVersion + ".");
		}

		private string ErrorServer(ZRpc rpc)
		{
			return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion;
		}

		private string Error(ZRpc? rpc = null)
		{
			return (rpc == null) ? ErrorClient() : ErrorServer(rpc);
		}

		private static VersionCheck[] GetFailedClient()
		{
			return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray();
		}

		private static VersionCheck[] GetFailedServer(ZRpc rpc)
		{
			ZRpc rpc2 = rpc;
			return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc2)).ToArray();
		}

		private static void Logout()
		{
			Game.instance.Logout(true, true);
			AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3);
		}

		private static void DisconnectClient(ZRpc rpc)
		{
			rpc.Invoke("Error", new object[1] { 3 });
		}

		private static void CheckVersion(ZRpc rpc, ZPackage pkg)
		{
			CheckVersion(rpc, pkg, null);
		}

		private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action<ZRpc, ZPackage>? original)
		{
			string text = pkg.ReadString();
			string text2 = pkg.ReadString();
			string text3 = pkg.ReadString();
			bool flag = false;
			foreach (VersionCheck versionCheck in versionChecks)
			{
				if (!(text != versionCheck.Name))
				{
					Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + "."));
					versionCheck.ReceivedMinimumRequiredVersion = text2;
					versionCheck.ReceivedCurrentVersion = text3;
					if (ZNet.instance.IsServer() && versionCheck.IsVersionOk())
					{
						versionCheck.ValidatedClients.Add(rpc);
					}
					flag = true;
				}
			}
			if (flag)
			{
				return;
			}
			pkg.SetPos(0);
			if (original != null)
			{
				original(rpc, pkg);
				if (pkg.GetPos() == 0)
				{
					notProcessedNames.Add(text, text3);
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		[HarmonyPrefix]
		private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance)
		{
			VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient());
			if (array.Length == 0)
			{
				return true;
			}
			VersionCheck[] array2 = array;
			foreach (VersionCheck versionCheck in array2)
			{
				Debug.LogWarning((object)versionCheck.Error(rpc));
			}
			if (__instance.IsServer())
			{
				DisconnectClient(rpc);
			}
			else
			{
				Logout();
			}
			return false;
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		[HarmonyPrefix]
		private static void RegisterAndCheckVersion(ZNetPeer peer, ZNet __instance)
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			notProcessedNames.Clear();
			IDictionary dictionary = (IDictionary)typeof(ZRpc).GetField("m_functions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(peer.m_rpc);
			if (dictionary.Contains(StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")))
			{
				object obj = dictionary[StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")];
				Action<ZRpc, ZPackage> action = (Action<ZRpc, ZPackage>)obj.GetType().GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
				peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg)
				{
					CheckVersion(rpc, pkg, action);
				});
			}
			else
			{
				peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)CheckVersion);
			}
			foreach (VersionCheck versionCheck in versionChecks)
			{
				versionCheck.Initialize();
				if (versionCheck.ModRequired || __instance.IsServer())
				{
					Debug.Log((object)("Sending " + versionCheck.DisplayName + " version " + versionCheck.CurrentVersion + " and minimum version " + versionCheck.MinimumRequiredVersion + " to the " + (__instance.IsServer() ? "client" : "server") + "."));
					ZPackage val = new ZPackage();
					val.Write(versionCheck.Name);
					val.Write(versionCheck.MinimumRequiredVersion);
					val.Write(versionCheck.CurrentVersion);
					peer.m_rpc.Invoke("ServerSync VersionCheck", new object[1] { val });
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Disconnect")]
		[HarmonyPrefix]
		private static void RemoveDisconnected(ZNetPeer peer, ZNet __instance)
		{
			if (!__instance.IsServer())
			{
				return;
			}
			foreach (VersionCheck versionCheck in versionChecks)
			{
				versionCheck.ValidatedClients.Remove(peer.m_rpc);
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
		[HarmonyPostfix]
		private static void ShowConnectionError(FejdStartup __instance)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.m_connectionFailedPanel.activeSelf || (int)ZNet.GetConnectionStatus() != 3)
			{
				return;
			}
			bool flag = false;
			VersionCheck[] failedClient = GetFailedClient();
			if (failedClient.Length != 0)
			{
				string text = string.Join("\n", failedClient.Select((VersionCheck check) => check.Error()));
				TMP_Text connectionFailedError = __instance.m_connectionFailedError;
				connectionFailedError.text = connectionFailedError.text + "\n" + text;
				flag = true;
			}
			foreach (KeyValuePair<string, string> item in notProcessedNames.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> kv) => kv.Key))
			{
				if (!__instance.m_connectionFailedError.text.Contains(item.Key))
				{
					TMP_Text connectionFailedError2 = __instance.m_connectionFailedError;
					connectionFailedError2.text = connectionFailedError2.text + "\nServer expects you to have " + item.Key + " (Version: " + item.Value + ") installed.";
					flag = true;
				}
			}
			if (flag)
			{
				RectTransform component = ((Component)__instance.m_connectionFailedPanel.transform.Find("Image")).GetComponent<RectTransform>();
				Vector2 sizeDelta = component.sizeDelta;
				sizeDelta.x = 675f;
				component.sizeDelta = sizeDelta;
				__instance.m_connectionFailedError.ForceMeshUpdate(false, false);
				float num = __instance.m_connectionFailedError.renderedHeight + 105f;
				RectTransform component2 = ((Component)((Component)component).transform.Find("ButtonOk")).GetComponent<RectTransform>();
				component2.anchoredPosition = new Vector2(component2.anchoredPosition.x, component2.anchoredPosition.y - (num - component.sizeDelta.y) / 2f);
				sizeDelta = component.sizeDelta;
				sizeDelta.y = num;
				component.sizeDelta = sizeDelta;
			}
		}
	}
}
namespace AzuExtendedPlayerInventory
{
	[PublicAPI]
	internal class API
	{
		public delegate void SlotAddedHandler(string slotName);

		public delegate void SlotRemovedHandler(string slotName);

		public static event Action<Hud>? OnHudAwake;

		public static event Action<Hud>? OnHudAwakeComplete;

		public static event Action<Hud>? OnHudUpdate;

		public static event Action<Hud>? OnHudUpdateComplete;

		public static event SlotAddedHandler? SlotAdded;

		public static event SlotRemovedHandler? SlotRemoved;

		public static bool IsLoaded()
		{
			return false;
		}

		public static bool AddSlot(string slotName, Func<Player, ItemData?> getItem, Func<ItemData, bool> isValid, int index = -1)
		{
			return false;
		}

		public static bool RemoveSlot(string slotName)
		{
			return false;
		}

		public static SlotInfo GetSlots()
		{
			return new SlotInfo();
		}

		public static SlotInfo GetQuickSlots()
		{
			return new SlotInfo();
		}

		public static List<ItemData> GetQuickSlotsItems()
		{
			return new List<ItemData>();
		}

		public static int GetAddedRows(int width)
		{
			return 0;
		}
	}
	[PublicAPI]
	internal class SlotInfo
	{
		public string[] SlotNames { get; set; } = new string[0];


		public Vector2[] SlotPositions { get; set; } = (Vector2[])(object)new Vector2[0];


		public Func<Player, ItemData?>?[] GetItemFuncs { get; set; } = new Func<Player, ItemData>[0];


		public Func<ItemData, bool>?[] IsValidFuncs { get; set; } = new Func<ItemData, bool>[0];

	}
}
namespace ExtraSlotsAPI
{
	internal static class API
	{
		private static bool _isNotReady;

		private static readonly List<ItemData> _emptyItemList = new List<ItemData>();

		private static readonly List<ExtraSlot> _emptySlotList = new List<ExtraSlot>();

		internal static Type _typeAPI;

		internal static Type _typeSlot;

		public static bool IsReady()
		{
			if (_isNotReady)
			{
				return false;
			}
			if (_typeAPI != null && _typeSlot != null)
			{
				return true;
			}
			_isNotReady = !Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlots");
			if (_isNotReady)
			{
				return false;
			}
			if (_typeAPI == null || _typeSlot == null)
			{
				Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["shudnal.ExtraSlots"].Instance).GetType());
				if (assembly == null)
				{
					_isNotReady = true;
					return false;
				}
				_typeAPI = assembly.GetType("ExtraSlots.API");
				_typeSlot = assembly.GetType("ExtraSlots.Slots+Slot");
			}
			if (_typeAPI != null)
			{
				return _typeSlot != null;
			}
			return false;
		}

		public static List<ExtraSlot> GetExtraSlots()
		{
			if (!IsReady())
			{
				return _emptySlotList;
			}
			return ((IEnumerable<object>)AccessTools.Method(_typeAPI, "GetExtraSlots", (Type[])null, (Type[])null).Invoke(_typeAPI, null)).Select((object slot) => slot.ToExtraSlot()).ToList();
		}

		public static List<ExtraSlot> GetEquipmentSlots()
		{
			if (!IsReady())
			{
				return _emptySlotList;
			}
			return ((IEnumerable<object>)AccessTools.Method(_typeAPI, "GetEquipmentSlots", (Type[])null, (Type[])null).Invoke(_typeAPI, null)).Select((object slot) => slot.ToExtraSlot()).ToList();
		}

		public static List<ExtraSlot> GetQuickSlots()
		{
			if (!IsReady())
			{
				return _emptySlotList;
			}
			return ((IEnumerable<object>)AccessTools.Method(_typeAPI, "GetQuickSlots", (Type[])null, (Type[])null).Invoke(_typeAPI, null)).Select((object slot) => slot.ToExtraSlot()).ToList();
		}

		public static List<ExtraSlot> GetFoodSlots()
		{
			if (!IsReady())
			{
				return _emptySlotList;
			}
			return ((IEnumerable<object>)AccessTools.Method(_typeAPI, "GetFoodSlots", (Type[])null, (Type[])null).Invoke(_typeAPI, null)).Select((object slot) => slot.ToExtraSlot()).ToList();
		}

		public static List<ExtraSlot> GetAmmoSlots()
		{
			if (!IsReady())
			{
				return _emptySlotList;
			}
			return ((IEnumerable<object>)AccessTools.Method(_typeAPI, "GetAmmoSlots", (Type[])null, (Type[])null).Invoke(_typeAPI, null)).Select((object slot) => slot.ToExtraSlot()).ToList();
		}

		public static List<ExtraSlot> GetMiscSlots()
		{
			if (!IsReady())
			{
				return _emptySlotList;
			}
			return ((IEnumerable<object>)AccessTools.Method(_typeAPI, "GetMiscSlots", (Type[])null, (Type[])null).Invoke(_typeAPI, null)).Select((object slot) => slot.ToExtraSlot()).ToList();
		}

		public static ExtraSlot FindSlot(string slotID)
		{
			if (!IsReady())
			{
				return null;
			}
			return AccessTools.Method(_typeAPI, "FindSlot", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { slotID }).ToExtraSlot();
		}

		public static List<ItemData> GetAllExtraSlotsItems()
		{
			if (!IsReady())
			{
				return _emptyItemList;
			}
			return (List<ItemData>)AccessTools.Method(_typeAPI, "GetAllExtraSlotsItems", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static List<ItemData> GetEquipmentSlotsItems()
		{
			if (!IsReady())
			{
				return _emptyItemList;
			}
			return (List<ItemData>)AccessTools.Method(_typeAPI, "GetEquipmentSlotsItems", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static List<ItemData> GetQuickSlotsItems()
		{
			if (!IsReady())
			{
				return _emptyItemList;
			}
			return (List<ItemData>)AccessTools.Method(_typeAPI, "GetQuickSlotsItems", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static List<ItemData> GetFoodSlotsItems()
		{
			if (!IsReady())
			{
				return _emptyItemList;
			}
			return (List<ItemData>)AccessTools.Method(_typeAPI, "GetFoodSlotsItems", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static List<ItemData> GetAmmoSlotsItems()
		{
			if (!IsReady())
			{
				return _emptyItemList;
			}
			return (List<ItemData>)AccessTools.Method(_typeAPI, "GetAmmoSlotsItems", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static List<ItemData> GetMiscSlotsItems()
		{
			if (!IsReady())
			{
				return _emptyItemList;
			}
			return (List<ItemData>)AccessTools.Method(_typeAPI, "GetMiscSlotsItems", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static int GetExtraRows()
		{
			if (!IsReady())
			{
				return -1;
			}
			return (int)AccessTools.Method(_typeAPI, "GetExtraRows", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static int GetInventoryHeightFull()
		{
			if (!IsReady())
			{
				return -1;
			}
			return (int)AccessTools.Method(_typeAPI, "GetInventoryHeightFull", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static int GetInventoryHeightPlayer()
		{
			if (!IsReady())
			{
				return -1;
			}
			return (int)AccessTools.Method(_typeAPI, "GetInventoryHeightPlayer", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
		}

		public static bool IsGridPositionASlot(Vector2i gridPos)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "IsGridPositionASlot", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { gridPos });
		}

		public static bool IsItemInSlot(ItemData item)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "IsItemInSlot", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { item });
		}

		public static bool IsItemInEquipmentSlot(ItemData item)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "IsItemInEquipmentSlot", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { item });
		}

		public static bool IsAnyGlobalKeyActive(string requiredKeys)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "requiredKeys", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { requiredKeys });
		}

		public static bool IsItemTypeKnown(ItemType itemType)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "IsItemTypeKnown", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { itemType });
		}

		public static bool IsAnyMaterialDiscovered(string itemNames)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "IsAnyMaterialDiscovered", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { itemNames });
		}

		public static bool AddSlot(string slotID, Func<string> getName, Func<ItemData, bool> itemIsValid, Func<bool> isActive)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "AddSlot", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[5] { slotID, -1, getName, itemIsValid, isActive });
		}

		public static bool AddSlotWithIndex(string slotID, int slotIndex, Func<string> getName, Func<ItemData, bool> itemIsValid, Func<bool> isActive)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "AddSlotWithIndex", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[5] { slotID, slotIndex, getName, itemIsValid, isActive });
		}

		public static bool AddSlotBefore(string slotID, Func<string> getName, Func<ItemData, bool> itemIsValid, Func<bool> isActive, params string[] slotIDs)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "AddSlotBefore", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[5] { slotID, getName, itemIsValid, isActive, slotIDs });
		}

		public static bool AddSlotAfter(string slotID, Func<string> getName, Func<ItemData, bool> itemIsValid, Func<bool> isActive, params string[] slotIDs)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "AddSlotAfter", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[5] { slotID, getName, itemIsValid, isActive, slotIDs });
		}

		public static bool RemoveSlot(string slotID)
		{
			if (!IsReady())
			{
				return false;
			}
			return (bool)AccessTools.Method(_typeAPI, "RemoveSlot", (Type[])null, (Type[])null).Invoke(_typeAPI, new object[1] { slotID });
		}

		public static void UpdateSlots()
		{
			if (IsReady())
			{
				AccessTools.Method(_typeAPI, "UpdateSlots", (Type[])null, (Type[])null).Invoke(_typeAPI, null);
			}
		}
	}
	internal static class Extensions
	{
		internal static ExtraSlot ToExtraSlot(this object slot)
		{
			return new ExtraSlot
			{
				_id = () => (string)AccessTools.Property(API._typeSlot, "ID").GetValue(slot),
				_name = () => (string)AccessTools.Property(API._typeSlot, "Name").GetValue(slot),
				_gridPosition = () => (Vector2i)AccessTools.Property(API._typeSlot, "GridPosition").GetValue(slot),
				_item = () => (ItemData)AccessTools.Property(API._typeSlot, "Item").GetValue(slot),
				_itemFits = (ItemData item) => (bool)AccessTools.Method(API._typeSlot, "ItemFits", (Type[])null, (Type[])null).Invoke(slot, new object[1] { item }),
				_isActive = () => (bool)AccessTools.Property(API._typeSlot, "IsActive").GetValue(slot),
				_isFree = () => (bool)AccessTools.Property(API._typeSlot, "IsFree").GetValue(slot),
				_isHotkeySlot = () => (bool)AccessTools.Property(API._typeSlot, "IsHotkeySlot").GetValue(slot),
				_isEquipmentSlot = () => (bool)AccessTools.Property(API._typeSlot, "IsEquipmentSlot").GetValue(slot),
				_isQuickSlot = () => (bool)AccessTools.Property(API._typeSlot, "IsQ

BepInEx/plugins/TintedGreenGoggles.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemManager;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: AssemblyFileVersion("1.0.2")]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyProduct("TintedGreenGoggles")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("TintedGreenGoggles")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<70b3c5c4-bfa0-4502-b935-9458bfedfcbc>Embedded]
	internal sealed class <70b3c5c4-bfa0-4502-b935-9458bfedfcbc>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[<70b3c5c4-bfa0-4502-b935-9458bfedfcbc>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	internal sealed class <d7a12342-7464-415d-8c3a-7280e87ee333>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <d7a12342-7464-415d-8c3a-7280e87ee333>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <d7a12342-7464-415d-8c3a-7280e87ee333>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[<70b3c5c4-bfa0-4502-b935-9458bfedfcbc>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	internal sealed class <3db7695e-db40-448a-a700-552ed53b94e2>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <3db7695e-db40-448a-a700-552ed53b94e2>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace TintedGreenGoggles
{
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	[BepInPlugin("Azumatt.TintedGreenGoggles", "TintedGreenGoggles", "1.0.2")]
	public class TintedGreenGogglesPlugin : BaseUnityPlugin
	{
		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)]
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)]
		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order;

			[UsedImplicitly]
			public bool? Browsable;

			[UsedImplicitly]
			[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
			public string Category;

			[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 2, 1 })]
			[UsedImplicitly]
			public Action<ConfigEntryBase> CustomDrawer;
		}

		internal const string ModName = "TintedGreenGoggles";

		internal const string ModVersion = "1.0.2";

		internal const string Author = "Azumatt";

		private const string ModGUID = "Azumatt.TintedGreenGoggles";

		private static string ConfigFileName = "Azumatt.TintedGreenGoggles.cfg";

		private static string ConfigFileFullPath;

		internal static string ConnectionError;

		private readonly Harmony _harmony = new Harmony("Azumatt.TintedGreenGoggles");

		public static readonly ManualLogSource TintedGreenGogglesLogger;

		private static readonly ConfigSync ConfigSync;

		private static ConfigEntry<Toggle> _serverConfigLocked;

		private static ConfigEntry<Toggle> _recipeIsActiveConfig;

		public void Awake()
		{
			Localizer.Load();
			_serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked);
			Item item = new Item("tintedgreengoggles", "TintedGreenGoggles");
			item.Crafting.Add(CraftingTable.Disabled, 1);
			item.RequiredItems.Add("Iron", 10);
			item.RequiredItems.Add("Guck", 1);
			item.RequiredItems.Add("Crystal", 1);
			item.RequiredUpgradeItems.Add("Iron", 10);
			item.RequiredUpgradeItems.Add("Guck", 1);
			item.RequiredUpgradeItems.Add("Crystal", 1);
			item.Trade.Price = 100u;
			item.Trade.Stack = 1u;
			item.Trade.Trader = Trader.Hildir;
			Item item2 = new Item("tintedgreengoggles", "TintedGreenGoggles_light");
			item2.Crafting.Add(CraftingTable.Disabled, 1);
			item2.RequiredItems.Add("Iron", 10);
			item2.RequiredItems.Add("Guck", 1);
			item2.RequiredItems.Add("Crystal", 2);
			item2.RequiredUpgradeItems.Add("Iron", 10);
			item2.RequiredUpgradeItems.Add("Guck", 1);
			item2.RequiredUpgradeItems.Add("Crystal", 2);
			item2.Trade.Price = 150u;
			item2.Trade.Stack = 1u;
			item2.Trade.Trader = Trader.Hildir;
			Item item3 = new Item("tintedgreengoggles", "TintedBlueGoggles");
			item3.Crafting.Add(CraftingTable.Disabled, 1);
			item3.RequiredItems.Add("Iron", 10);
			item3.RequiredItems.Add("Guck", 1);
			item3.RequiredItems.Add("Crystal", 1);
			item3.RequiredUpgradeItems.Add("Iron", 10);
			item3.RequiredUpgradeItems.Add("Guck", 1);
			item3.RequiredUpgradeItems.Add("Crystal", 1);
			item3.Trade.Price = 100u;
			item3.Trade.Stack = 1u;
			item3.Trade.Trader = Trader.Hildir;
			Item item4 = new Item("tintedgreengoggles", "TintedBlueGoggles_light");
			item4.Crafting.Add(CraftingTable.Disabled, 1);
			item4.RequiredItems.Add("Iron", 10);
			item4.RequiredItems.Add("Guck", 1);
			item4.RequiredItems.Add("Crystal", 2);
			item4.RequiredUpgradeItems.Add("Iron", 10);
			item4.RequiredUpgradeItems.Add("Guck", 1);
			item4.RequiredUpgradeItems.Add("Crystal", 2);
			item4.Trade.Price = 150u;
			item4.Trade.Stack = 1u;
			item4.Trade.Trader = Trader.Hildir;
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				TintedGreenGogglesLogger.LogDebug((object)"ReadConfigValues called");
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				TintedGreenGogglesLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
				TintedGreenGogglesLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		private ConfigEntry<T> config<[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
			ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		private ConfigEntry<T> config<[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		static TintedGreenGogglesPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ConnectionError = "";
			TintedGreenGogglesLogger = Logger.CreateLogSource("TintedGreenGoggles");
			ConfigSync = new ConfigSync("Azumatt.TintedGreenGoggles")
			{
				DisplayName = "TintedGreenGoggles",
				CurrentVersion = "1.0.2",
				MinimumRequiredVersion = "1.0.2"
			};
			_serverConfigLocked = null;
			_recipeIsActiveConfig = null;
		}
	}
}
namespace LocalizationManager
{
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	[PublicAPI]
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private static BaseUnityPlugin _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out var value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out var value2))
			{
				text = value2.Aggregate(text, [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null)
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
				UpdatePlaceholderText(Localization.instance, key);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1];
				if (dictionary.ContainsKey(text))
				{
					Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
				}
				else
				{
					dictionary[text] = item;
				}
			}
			byte[] array = LoadTranslationFromAssembly("English");
			if (array == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.ContainsKey(language))
				{
					text2 = File.ReadAllText(dictionary[language]);
				}
				else
				{
					byte[] array2 = LoadTranslationFromAssembly(language);
					if (array2 != null)
					{
						text2 = Encoding.UTF8.GetString(array2);
					}
				}
			}
			if (text2 == null && dictionary.ContainsKey("English"))
			{
				text2 = File.ReadAllText(dictionary["English"]);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string> { ".json", ".yml" };
			new Harmony("org.bepinex.helpers.LocalizationManager").Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		[return: <d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private static byte[] LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(2)]
		public static byte[] ReadEmbeddedFileBytes([<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(1)] string resourceFileName, Assembly containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace ItemManager
{
	[PublicAPI]
	public enum CraftingTable
	{
		Disabled,
		Inventory,
		[InternalName("piece_workbench")]
		Workbench,
		[InternalName("piece_cauldron")]
		Cauldron,
		[InternalName("forge")]
		Forge,
		[InternalName("piece_artisanstation")]
		ArtisanTable,
		[InternalName("piece_stonecutter")]
		StoneCutter,
		[InternalName("piece_magetable")]
		MageTable,
		[InternalName("blackforge")]
		BlackForge,
		[InternalName("piece_preptable")]
		FoodPreparationTable,
		[InternalName("piece_MeadCauldron")]
		MeadKetill,
		Custom
	}
	[PublicAPI]
	public enum ConversionPiece
	{
		Disabled,
		[InternalName("smelter")]
		Smelter,
		[InternalName("charcoal_kiln")]
		CharcoalKiln,
		[InternalName("blastfurnace")]
		BlastFurnace,
		[InternalName("windmill")]
		Windmill,
		[InternalName("piece_spinningwheel")]
		SpinningWheel,
		[InternalName("eitrrefinery")]
		EitrRefinery,
		Custom
	}
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	public class InternalName : Attribute
	{
		public readonly string internalName;

		public InternalName(string internalName)
		{
			this.internalName = internalName;
		}
	}
	[PublicAPI]
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	public class RequiredResourceList
	{
		public readonly List<Requirement> Requirements = new List<Requirement>();

		public bool Free;

		public void Add(string itemName, int amount, int quality = 0)
		{
			Requirements.Add(new Requirement
			{
				itemName = itemName,
				amount = amount,
				quality = quality
			});
		}

		public void Add(string itemName, ConfigEntry<int> amountConfig, int quality = 0)
		{
			Requirements.Add(new Requirement
			{
				itemName = itemName,
				amountConfig = amountConfig,
				quality = quality
			});
		}
	}
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	[PublicAPI]
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	public class CraftingStationList
	{
		public readonly List<CraftingStationConfig> Stations = new List<CraftingStationConfig>();

		public void Add(CraftingTable table, int level)
		{
			Stations.Add(new CraftingStationConfig
			{
				Table = table,
				level = level
			});
		}

		public void Add(string customTable, int level)
		{
			Stations.Add(new CraftingStationConfig
			{
				Table = CraftingTable.Custom,
				level = level,
				custom = customTable
			});
		}
	}
	[PublicAPI]
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	public class ItemRecipe
	{
		public readonly RequiredResourceList RequiredItems = new RequiredResourceList();

		public readonly RequiredResourceList RequiredUpgradeItems = new RequiredResourceList();

		public readonly CraftingStationList Crafting = new CraftingStationList();

		public int CraftAmount = 1;

		public bool RequireOnlyOneIngredient;

		public float QualityResultAmountMultiplier = 1f;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		public ConfigEntryBase RecipeIsActive;
	}
	[PublicAPI]
	public class Trade
	{
		public Trader Trader;

		public uint Price;

		public uint Stack = 1u;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		public string RequiredGlobalKey;
	}
	[Flags]
	[PublicAPI]
	public enum Trader
	{
		None = 0,
		Haldor = 1,
		Hildir = 2
	}
	public struct Requirement
	{
		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(1)]
		public string itemName;

		public int amount;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		public ConfigEntry<int> amountConfig;

		[Description("Set to a non-zero value to apply the requirement only for a specific quality")]
		public int quality;
	}
	public struct CraftingStationConfig
	{
		public CraftingTable Table;

		public int level;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		public string custom;
	}
	[Flags]
	public enum Configurability
	{
		Disabled = 0,
		Recipe = 1,
		Stats = 2,
		Drop = 4,
		Trader = 8,
		Full = 0xF
	}
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	[PublicAPI]
	public class DropTargets
	{
		public readonly List<DropTarget> Drops = new List<DropTarget>();

		public void Add(string creatureName, float chance, int min = 1, int? max = null, bool levelMultiplier = true)
		{
			Drops.Add(new DropTarget
			{
				creature = creatureName,
				chance = chance,
				min = min,
				max = max.GetValueOrDefault(min),
				levelMultiplier = levelMultiplier
			});
		}
	}
	public struct DropTarget
	{
		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(1)]
		public string creature;

		public int min;

		public int max;

		public float chance;

		public bool levelMultiplier;
	}
	public enum Toggle
	{
		On = 1,
		Off = 0
	}
	[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(1)]
	[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
	[PublicAPI]
	public class Item
	{
		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
		private class ItemConfig
		{
			[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 2, 1 })]
			public ConfigEntry<string> craft;

			[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 2, 1 })]
			public ConfigEntry<string> upgrade;

			public ConfigEntry<CraftingTable> table;

			public ConfigEntry<int> tableLevel;

			public ConfigEntry<string> customTable;

			[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
			public ConfigEntry<int> maximumTableLevel;

			public ConfigEntry<Toggle> requireOneIngredient;

			public ConfigEntry<float> qualityResultAmountMultiplier;
		}

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
		private class TraderConfig
		{
			public ConfigEntry<Trader> trader;

			public ConfigEntry<uint> price;

			public ConfigEntry<uint> stack;

			public ConfigEntry<string> requiredGlobalKey;
		}

		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)]
		private class RequirementQuality
		{
			public int quality;
		}

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(2)]
		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order;

			[UsedImplicitly]
			public bool? Browsable;

			[UsedImplicitly]
			public string Category;

			[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 2, 1 })]
			[UsedImplicitly]
			public Action<ConfigEntryBase> CustomDrawer;

			public Func<bool> browsability;
		}

		[PublicAPI]
		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)]
		public enum DamageModifier
		{
			Normal,
			Resistant,
			Weak,
			Immune,
			Ignore,
			VeryResistant,
			VeryWeak,
			None
		}

		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)]
		private delegate void setDmgFunc(ref DamageTypes dmg, float value);

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
		private class SerializedRequirements
		{
			public readonly List<Requirement> Reqs;

			public SerializedRequirements(List<Requirement> reqs)
			{
				Reqs = reqs;
			}

			public SerializedRequirements(string reqs)
				: this(reqs.Split(new char[1] { ',' }).Select([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (string r) =>
				{
					string[] array = r.Split(new char[1] { ':' });
					Requirement result = default(Requirement);
					result.itemName = array[0];
					result.amount = ((array.Length <= 1 || !int.TryParse(array[1], out var result2)) ? 1 : result2);
					result.quality = ((array.Length > 2 && int.TryParse(array[2], out var result3)) ? result3 : 0);
					return result;
				}).ToList())
			{
			}

			public override string ToString()
			{
				return string.Join(",", Reqs.Select([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Requirement r) => $"{r.itemName}:{r.amount}" + ((r.quality > 0) ? $":{r.quality}" : "")));
			}

			[return: <d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
			public static ItemDrop fetchByName(ObjectDB objectDB, string name)
			{
				GameObject itemPrefab = objectDB.GetItemPrefab(name);
				ItemDrop obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)obj == (Object)null)
				{
					Debug.LogWarning((object)("The required item '" + name + "' does not exist."));
				}
				return obj;
			}

			public static Requirement[] toPieceReqs(ObjectDB objectDB, SerializedRequirements craft, SerializedRequirements upgrade)
			{
				//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0178: Unknown result type (might be due to invalid IL or missing references)
				//IL_017d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0185: Unknown result type (might be due to invalid IL or missing references)
				//IL_018c: Unknown result type (might be due to invalid IL or missing references)
				//IL_018f: Expected O, but got Unknown
				//IL_0194: Expected O, but got Unknown
				//IL_011c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0125: Expected O, but got Unknown
				Dictionary<string, Requirement> dictionary = craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func<Requirement, string>)([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Requirement r) => r.itemName), (Func<Requirement, Requirement>)([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Requirement r) =>
				{
					//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_002f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_003e: Expected O, but got Unknown
					ItemDrop val6 = ResItem(r);
					return (val6 != null) ? new Requirement
					{
						m_amount = (r.amountConfig?.Value ?? r.amount),
						m_resItem = val6,
						m_amountPerLevel = 0
					} : ((Requirement)null);
				}));
				List<Requirement> list = dictionary.Values.Where([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Requirement v) => v != null).ToList();
				foreach (Requirement item in upgrade.Reqs.Where((Requirement r) => r.itemName != ""))
				{
					if (item.quality > 0)
					{
						ItemDrop val = ResItem(item);
						if (val != null)
						{
							Requirement val2 = new Requirement
							{
								m_resItem = val,
								m_amountPerLevel = (item.amountConfig?.Value ?? item.amount),
								m_amount = 0
							};
							list.Add(val2);
							requirementQuality.Add(val2, new RequirementQuality
							{
								quality = item.quality
							});
						}
						continue;
					}
					if (!dictionary.TryGetValue(item.itemName, out var value) || value == null)
					{
						ItemDrop val3 = ResItem(item);
						if (val3 != null)
						{
							string itemName = item.itemName;
							Requirement val4 = new Requirement
							{
								m_resItem = val3,
								m_amount = 0
							};
							Requirement val5 = val4;
							dictionary[itemName] = val4;
							value = val5;
							list.Add(value);
						}
					}
					if (value != null)
					{
						value.m_amountPerLevel = item.amountConfig?.Value ?? item.amount;
					}
				}
				return list.ToArray();
				[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(2)]
				ItemDrop ResItem(Requirement r)
				{
					return fetchByName(objectDB, r.itemName);
				}
			}
		}

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)]
		private class SerializedDrop
		{
			public readonly List<DropTarget> Drops;

			public SerializedDrop(List<DropTarget> drops)
			{
				Drops = drops;
			}

			public SerializedDrop(string drops)
			{
				Drops = ((drops == "") ? ((IEnumerable<string>)Array.Empty<string>()) : ((IEnumerable<string>)drops.Split(new char[1] { ',' }))).Select([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (string r) =>
				{
					string[] array = r.Split(new char[1] { ':' });
					if (array.Length <= 2 || !int.TryParse(array[2], out var result))
					{
						result = 1;
					}
					if (array.Length <= 3 || !int.TryParse(array[3], out var result2))
					{
						result2 = result;
					}
					bool levelMultiplier = array.Length <= 4 || array[4] != "0";
					DropTarget result3 = default(DropTarget);
					result3.creature = array[0];
					result3.chance = ((array.Length > 1 && float.TryParse(array[1], out var result4)) ? result4 : 1f);
					result3.min = result;
					result3.max = result2;
					result3.levelMultiplier = levelMultiplier;
					return result3;
				}).ToList();
			}

			public override string ToString()
			{
				return string.Join(",", Drops.Select([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (DropTarget r) => $"{r.creature}:{r.chance.ToString(CultureInfo.InvariantCulture)}:{r.min}:" + ((r.min == r.max) ? "" : $"{r.max}") + (r.levelMultiplier ? "" : ":0")));
			}

			[return: <d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
			private static Character fetchByName(ZNetScene netScene, string name)
			{
				GameObject prefab = netScene.GetPrefab(name);
				Character obj = ((prefab != null) ? prefab.GetComponent<Character>() : null);
				if ((Object)(object)obj == (Object)null)
				{
					Debug.LogWarning((object)("The drop target character '" + name + "' does not exist."));
				}
				return obj;
			}

			public Dictionary<Character, Drop> toCharacterDrops(ZNetScene netScene, GameObject item)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Expected O, but got Unknown
				Dictionary<Character, Drop> dictionary = new Dictionary<Character, Drop>();
				foreach (DropTarget drop in Drops)
				{
					Character val = fetchByName(netScene, drop.creature);
					if (val != null)
					{
						dictionary[val] = new Drop
						{
							m_prefab = item,
							m_amountMin = drop.min,
							m_amountMax = drop.max,
							m_chance = drop.chance,
							m_levelMultiplier = drop.levelMultiplier
						};
					}
				}
				return dictionary;
			}
		}

		private static readonly List<Item> registeredItems = new List<Item>();

		private static readonly Dictionary<ItemDrop, Item> itemDropMap = new Dictionary<ItemDrop, Item>();

		private static Dictionary<Item, Dictionary<string, List<Recipe>>> activeRecipes = new Dictionary<Item, Dictionary<string, List<Recipe>>>();

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 1, 1, 2 })]
		private static Dictionary<Recipe, ConfigEntryBase> hiddenCraftRecipes = new Dictionary<Recipe, ConfigEntryBase>();

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 1, 1, 2 })]
		private static Dictionary<Recipe, ConfigEntryBase> hiddenUpgradeRecipes = new Dictionary<Recipe, ConfigEntryBase>();

		private static Dictionary<Item, Dictionary<string, ItemConfig>> itemCraftConfigs = new Dictionary<Item, Dictionary<string, ItemConfig>>();

		private static Dictionary<Item, ConfigEntry<string>> itemDropConfigs = new Dictionary<Item, ConfigEntry<string>>();

		private Dictionary<CharacterDrop, Drop> characterDrops = new Dictionary<CharacterDrop, Drop>();

		private readonly Dictionary<ConfigEntryBase, Action> statsConfigs = new Dictionary<ConfigEntryBase, Action>();

		private static readonly ConditionalWeakTable<Requirement, RequirementQuality> requirementQuality = new ConditionalWeakTable<Requirement, RequirementQuality>();

		public static Configurability DefaultConfigurability = Configurability.Full;

		public Configurability? Configurable;

		private Configurability configurationVisible = Configurability.Full;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private TraderConfig traderConfig;

		public readonly GameObject Prefab;

		[Description("Specifies the maximum required crafting station level to upgrade and repair the item.\nDefault is calculated from crafting station level and maximum quality.")]
		public int MaximumRequiredStationLevel = int.MaxValue;

		[Description("Assigns the item as a drop item to a creature.\nUses a creature name, a drop chance and a minimum and maximum amount.")]
		public readonly DropTargets DropsFrom = new DropTargets();

		[Description("Configures whether the item can be bought at the trader.\nDon't forget to set cost to something above 0 or the item will be sold for free.")]
		public readonly Trade Trade = new Trade();

		internal List<Conversion> Conversions = new List<Conversion>();

		internal List<ItemConversion> conversions = new List<ItemConversion>();

		public Dictionary<string, ItemRecipe> Recipes = new Dictionary<string, ItemRecipe>();

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private static object configManager;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private static Localization _english;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private static BaseUnityPlugin _plugin;

		private static bool hasConfigSync = true;

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private static object _configSync;

		private Configurability configurability => Configurable ?? DefaultConfigurability;

		[Description("Specifies the resources needed to craft the item.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the item should need.")]
		public RequiredResourceList RequiredItems => this[""].RequiredItems;

		[Description("Specifies the resources needed to upgrade the item.\nUse .Add to add resources with their internal ID and an amount. This amount will be multipled by the item quality level.\nUse one .Add for each resource type the upgrade should need.")]
		public RequiredResourceList RequiredUpgradeItems => this[""].RequiredUpgradeItems;

		[Description("Specifies the crafting station needed to craft the item.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.\nUse one .Add for each crafting station.")]
		public CraftingStationList Crafting => this[""].Crafting;

		[Description("Specifies a config entry which toggles whether a recipe is active.")]
		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		public ConfigEntryBase RecipeIsActive
		{
			[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(2)]
			get
			{
				return this[""].RecipeIsActive;
			}
			[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(2)]
			set
			{
				this[""].RecipeIsActive = value;
			}
		}

		[Description("Specifies the number of items that should be given to the player with a single craft of the item.\nDefaults to 1.")]
		public int CraftAmount
		{
			get
			{
				return this[""].CraftAmount;
			}
			set
			{
				this[""].CraftAmount = value;
			}
		}

		public bool RequireOnlyOneIngredient
		{
			get
			{
				return this[""].RequireOnlyOneIngredient;
			}
			set
			{
				this[""].RequireOnlyOneIngredient = value;
			}
		}

		public float QualityResultAmountMultiplier
		{
			get
			{
				return this[""].QualityResultAmountMultiplier;
			}
			set
			{
				this[""].QualityResultAmountMultiplier = value;
			}
		}

		public ItemRecipe this[string name]
		{
			get
			{
				if (Recipes.TryGetValue(name, out var value))
				{
					return value;
				}
				return Recipes[name] = new ItemRecipe();
			}
		}

		private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English"));

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		[<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(2)]
		private static object configSync
		{
			[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(2)]
			get
			{
				if (_configSync == null && hasConfigSync)
				{
					Type type = Assembly.GetExecutingAssembly().GetType("ServerSync.ConfigSync");
					if ((object)type != null)
					{
						_configSync = Activator.CreateInstance(type, plugin.Info.Metadata.GUID + " ItemManager");
						type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString());
						type.GetProperty("IsLocked").SetValue(_configSync, true);
					}
					else
					{
						hasConfigSync = false;
					}
				}
				return _configSync;
			}
		}

		public Item(string assetBundleFileName, string prefabName, string folderName = "assets")
			: this(PrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName)
		{
		}

		public Item(AssetBundle bundle, string prefabName)
			: this(PrefabManager.RegisterPrefab(bundle, prefabName, addToObjectDb: true), skipRegistering: true)
		{
		}

		public Item(GameObject prefab, bool skipRegistering = false)
		{
			if (!skipRegistering)
			{
				PrefabManager.RegisterPrefab(prefab, addToObjectDb: true);
			}
			Prefab = prefab;
			registeredItems.Add(this);
			itemDropMap[Prefab.GetComponent<ItemDrop>()] = this;
			Prefab.GetComponent<ItemDrop>().m_itemData.m_dropPrefab = Prefab;
		}

		public void ToggleConfigurationVisibility(Configurability visible)
		{
			configurationVisible = visible;
			if (itemDropConfigs.TryGetValue(this, out var value))
			{
				Toggle((ConfigEntryBase)(object)value, Configurability.Drop);
			}
			if (itemCraftConfigs.TryGetValue(this, out var value2))
			{
				foreach (ItemConfig value4 in value2.Values)
				{
					ToggleObj(value4, Configurability.Recipe);
				}
			}
			foreach (Conversion conversion in Conversions)
			{
				if (conversion.config != null)
				{
					ToggleObj(conversion.config, Configurability.Recipe);
				}
			}
			foreach (KeyValuePair<ConfigEntryBase, Action> statsConfig in statsConfigs)
			{
				Toggle(statsConfig.Key, Configurability.Stats);
				if ((visible & Configurability.Stats) != 0)
				{
					statsConfig.Value();
				}
			}
			reloadConfigDisplay();
			void Toggle(ConfigEntryBase cfg, Configurability check)
			{
				object[] tags = cfg.Description.Tags;
				for (int j = 0; j < tags.Length; j++)
				{
					if (tags[j] is ConfigurationManagerAttributes configurationManagerAttributes)
					{
						configurationManagerAttributes.Browsable = (visible & check) != 0 && (configurationManagerAttributes.browsability == null || configurationManagerAttributes.browsability());
					}
				}
			}
			void ToggleObj(object obj, Configurability check)
			{
				FieldInfo[] fields = obj.GetType().GetFields();
				for (int i = 0; i < fields.Length; i++)
				{
					object? value3 = fields[i].GetValue(obj);
					ConfigEntryBase val = (ConfigEntryBase)((value3 is ConfigEntryBase) ? value3 : null);
					if (val != null)
					{
						Toggle(val, check);
					}
				}
			}
		}

		internal static void reloadConfigDisplay()
		{
			object obj = configManager?.GetType().GetProperty("DisplayingWindow").GetValue(configManager);
			if (obj is bool && (bool)obj)
			{
				configManager.GetType().GetMethod("BuildSettingList").Invoke(configManager, Array.Empty<object>());
			}
		}

		private void UpdateItemTableConfig(string recipeKey, CraftingTable table, string customTableValue)
		{
			if (activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(recipeKey, out var value))
			{
				value.First().m_enabled = table != CraftingTable.Disabled;
				if ((uint)table <= 1u)
				{
					value.First().m_craftingStation = null;
				}
				else if (table == CraftingTable.Custom)
				{
					Recipe obj = value.First();
					GameObject prefab = ZNetScene.instance.GetPrefab(customTableValue);
					obj.m_craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
				}
				else
				{
					value.First().m_craftingStation = ZNetScene.instance.GetPrefab(getInternalName(table)).GetComponent<CraftingStation>();
				}
			}
		}

		private void UpdateCraftConfig(string recipeKey, SerializedRequirements craftRequirements, SerializedRequirements upgradeRequirements)
		{
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !activeRecipes.ContainsKey(this) || !activeRecipes[this].TryGetValue(recipeKey, out var value))
			{
				return;
			}
			foreach (Recipe item in value)
			{
				item.m_resources = SerializedRequirements.toPieceReqs(ObjectDB.instance, craftRequirements, upgradeRequirements);
			}
		}

		internal static void Patch_FejdStartup()
		{
			//IL_0f2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f33: Unknown result type (might be due to invalid IL or missing references)
			//IL_21f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_2203: Expected O, but got Unknown
			//IL_0ff7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ffa: Unknown result type (might be due to invalid IL or missing references)
			//IL_1050: Expected I4, but got Unknown
			//IL_0c1d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c27: Expected O, but got Unknown
			//IL_1184: Unknown result type (might be due to invalid IL or missing references)
			//IL_1187: Unknown result type (might be due to invalid IL or missing references)
			//IL_1189: Invalid comparison between Unknown and I4
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Expected O, but got Unknown
			//IL_118b: Unknown result type (might be due to invalid IL or missing references)
			//IL_118f: Invalid comparison between Unknown and I4
			//IL_0d40: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d4a: Expected O, but got Unknown
			//IL_0deb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0df5: Expected O, but got Unknown
			//IL_1191: Unknown result type (might be due to invalid IL or missing references)
			//IL_1195: Invalid comparison between Unknown and I4
			//IL_0e9f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea9: Expected O, but got Unknown
			//IL_1390: Unknown result type (might be due to invalid IL or missing references)
			//IL_1393: Unknown result type (might be due to invalid IL or missing references)
			//IL_1395: Invalid comparison between Unknown and I4
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Expected O, but got Unknown
			//IL_1397: Unknown result type (might be due to invalid IL or missing references)
			//IL_139b: Unknown result type (might be due to invalid IL or missing references)
			//IL_139d: Invalid comparison between Unknown and I4
			//IL_139f: Unknown result type (might be due to invalid IL or missing references)
			//IL_13a3: Invalid comparison between Unknown and I4
			//IL_059d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a7: Expected O, but got Unknown
			//IL_1478: Unknown result type (might be due to invalid IL or missing references)
			//IL_147d: Unknown result type (might be due to invalid IL or missing references)
			//IL_147f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1482: Invalid comparison between Unknown and I4
			//IL_1484: Unknown result type (might be due to invalid IL or missing references)
			//IL_1488: Invalid comparison between Unknown and I4
			//IL_06b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bf: Expected O, but got Unknown
			//IL_14f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_14fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_14fc: Invalid comparison between Unknown and I4
			//IL_14fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_1502: Unknown result type (might be due to invalid IL or missing references)
			//IL_1504: Invalid comparison between Unknown and I4
			//IL_0794: Unknown result type (might be due to invalid IL or missing references)
			//IL_079e: Expected O, but got Unknown
			//IL_1506: Unknown result type (might be due to invalid IL or missing references)
			//IL_150a: Invalid comparison between Unknown and I4
			//IL_1647: Unknown result type (might be due to invalid IL or missing references)
			//IL_164a: Invalid comparison between Unknown and I4
			//IL_089e: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a8: Expected O, but got Unknown
			//IL_1847: Unknown result type (might be due to invalid IL or missing references)
			//IL_184e: Invalid comparison between Unknown and I4
			//IL_1917: Unknown result type (might be due to invalid IL or missing references)
			//IL_191c: Unknown result type (might be due to invalid IL or missing references)
			//IL_191e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1922: Unknown result type (might be due to invalid IL or missing references)
			//IL_1924: Invalid comparison between Unknown and I4
			//IL_1993: Unknown result type (might be due to invalid IL or missing references)
			//IL_1996: Unknown result type (might be due to invalid IL or missing references)
			//IL_1998: Invalid comparison between Unknown and I4
			//IL_15bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_15c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_199a: Unknown result type (might be due to invalid IL or missing references)
			//IL_199e: Invalid comparison between Unknown and I4
			//IL_19a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_19a4: Invalid comparison between Unknown and I4
			//IL_1e11: Unknown result type (might be due to invalid IL or missing references)
			//IL_1e14: Invalid comparison between Unknown and I4
			Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager");
			if (DefaultConfigurability != 0)
			{
				bool saveOnConfigSet = plugin.Config.SaveOnConfigSet;
				plugin.Config.SaveOnConfigSet = false;
				foreach (Item item4 in registeredItems.Where([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Item i) => i.configurability != Configurability.Disabled))
				{
					Item item3 = item4;
					string name2 = item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
					string englishName = new Regex("[=\\n\\t\\\\\"\\'\\[\\]]*").Replace(english.Localize(name2), "").Trim();
					string localizedName = Localization.instance.Localize(name2).Trim();
					int order = 0;
					if ((item3.configurability & Configurability.Recipe) != 0)
					{
						itemCraftConfigs[item3] = new Dictionary<string, ItemConfig>();
						foreach (string item5 in item3.Recipes.Keys.DefaultIfEmpty(""))
						{
							string configKey = item5;
							string text = ((configKey == "") ? "" : (" (" + configKey + ")"));
							if (configKey == "")
							{
								Configurability? configurable = item3.Configurable;
								if (configurable.HasValue && item3.Crafting.Stations.Count == 0)
								{
									item3.Crafting.Add(CraftingTable.Disabled, 1);
								}
							}
							if (!item3.Recipes.ContainsKey(configKey) || item3.Recipes[configKey].Crafting.Stations.Count <= 0)
							{
								continue;
							}
							ItemConfig itemConfig2 = (itemCraftConfigs[item3][configKey] = new ItemConfig());
							ItemConfig cfg = itemConfig2;
							List<ConfigurationManagerAttributes> hideWhenNoneAttributes = new List<ConfigurationManagerAttributes>();
							cfg.table = config(englishName, "Crafting Station" + text, item3.Recipes[configKey].Crafting.Stations.First().Table, new ConfigDescription("Crafting station where " + englishName + " is available.", (AcceptableValueBase)null, new object[1]
							{
								new ConfigurationManagerAttributes
								{
									Order = (order -= 1),
									Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0),
									Category = localizedName
								}
							}));
							ConfigurationManagerAttributes customTableAttributes = new ConfigurationManagerAttributes
							{
								Order = (order -= 1),
								browsability = CustomTableBrowsability,
								Browsable = (CustomTableBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0),
								Category = localizedName
							};
							cfg.customTable = config(englishName, "Custom Crafting Station" + text, item3.Recipes[configKey].Crafting.Stations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes }));
							cfg.table.SettingChanged += TableConfigChanged;
							cfg.customTable.SettingChanged += TableConfigChanged;
							ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
							{
								Order = (order -= 1),
								browsability = TableLevelBrowsability,
								Browsable = (TableLevelBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0),
								Category = localizedName
							};
							hideWhenNoneAttributes.Add(configurationManagerAttributes);
							cfg.tableLevel = config(englishName, "Crafting Station Level" + text, item3.Recipes[configKey].Crafting.Stations.First().level, new ConfigDescription("Required crafting station level to craft " + englishName + ".", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
							cfg.tableLevel.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
							{
								if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out var value6))
								{
									value6.First().m_minStationLevel = cfg.tableLevel.Value;
								}
							};
							if (item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality > 1)
							{
								cfg.maximumTableLevel = config(englishName, "Maximum Crafting Station Level" + text, (item3.MaximumRequiredStationLevel == int.MaxValue) ? (item3.Recipes[configKey].Crafting.Stations.First().level + item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality - 1) : item3.MaximumRequiredStationLevel, new ConfigDescription("Maximum crafting station level to upgrade and repair " + englishName + ".", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
							}
							cfg.requireOneIngredient = config(englishName, "Require only one resource" + text, item3.Recipes[configKey].RequireOnlyOneIngredient ? Toggle.On : Toggle.Off, new ConfigDescription("Whether only one of the ingredients is needed to craft " + englishName, (AcceptableValueBase)null, new object[1]
							{
								new ConfigurationManagerAttributes
								{
									Order = (order -= 1),
									browsability = TableLevelBrowsability,
									Browsable = (TableLevelBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0),
									Category = localizedName
								}
							}));
							ConfigurationManagerAttributes qualityResultAttributes = new ConfigurationManagerAttributes
							{
								Order = (order -= 1),
								browsability = QualityResultBrowsability,
								Browsable = (QualityResultBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0),
								Category = localizedName
							};
							cfg.requireOneIngredient.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
							{
								if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out var value5))
								{
									foreach (Recipe item6 in value5)
									{
										item6.m_requireOnlyOneIngredient = cfg.requireOneIngredient.Value == Toggle.On;
									}
								}
								qualityResultAttributes.Browsable = QualityResultBrowsability();
								reloadConfigDisplay();
							};
							cfg.qualityResultAmountMultiplier = config(englishName, "Quality Multiplier" + text, item3.Recipes[configKey].QualityResultAmountMultiplier, new ConfigDescription("Multiplies the crafted amount based on the quality of the resources when crafting " + englishName + ". Only works, if Require Only One Resource is true.", (AcceptableValueBase)null, new object[1] { qualityResultAttributes }));
							cfg.qualityResultAmountMultiplier.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
							{
								if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out var value4))
								{
									foreach (Recipe item7 in value4)
									{
										item7.m_qualityResultAmountMultiplier = cfg.qualityResultAmountMultiplier.Value;
									}
								}
							};
							if ((!item3.Recipes[configKey].RequiredItems.Free || item3.Recipes[configKey].RequiredItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredItems.Requirements.All((Requirement r) => r.amountConfig == null))
							{
								cfg.craft = itemConfig("Crafting Costs" + text, new SerializedRequirements(item3.Recipes[configKey].RequiredItems.Requirements).ToString(), "Item costs to craft " + englishName, isUpgrade: false);
							}
							if (item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality > 1 && (!item3.Recipes[configKey].RequiredUpgradeItems.Free || item3.Recipes[configKey].RequiredUpgradeItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredUpgradeItems.Requirements.All((Requirement r) => r.amountConfig == null))
							{
								cfg.upgrade = itemConfig("Upgrading Costs" + text, new SerializedRequirements(item3.Recipes[configKey].RequiredUpgradeItems.Requirements).ToString(), "Item costs per level to upgrade " + englishName, isUpgrade: true);
							}
							if (cfg.craft != null)
							{
								cfg.craft.SettingChanged += ConfigChanged;
							}
							if (cfg.upgrade != null)
							{
								cfg.upgrade.SettingChanged += ConfigChanged;
							}
							void ConfigChanged(object o, EventArgs e)
							{
								item3.UpdateCraftConfig(configKey, new SerializedRequirements(cfg.craft?.Value ?? ""), new SerializedRequirements(cfg.upgrade?.Value ?? ""));
							}
							bool CustomTableBrowsability()
							{
								return cfg.table.Value == CraftingTable.Custom;
							}
							bool ItemBrowsability()
							{
								return cfg.table.Value != CraftingTable.Disabled;
							}
							bool QualityResultBrowsability()
							{
								return cfg.requireOneIngredient.Value == Toggle.On;
							}
							void TableConfigChanged(object o, EventArgs e)
							{
								item3.UpdateItemTableConfig(configKey, cfg.table.Value, cfg.customTable.Value);
								customTableAttributes.Browsable = cfg.table.Value == CraftingTable.Custom;
								foreach (ConfigurationManagerAttributes item8 in hideWhenNoneAttributes)
								{
									item8.Browsable = cfg.table.Value != CraftingTable.Disabled;
								}
								reloadConfigDisplay();
							}
							bool TableLevelBrowsability()
							{
								return cfg.table.Value != CraftingTable.Disabled;
							}
							ConfigEntry<string> itemConfig(string name, string value, string desc, bool isUpgrade)
							{
								//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
								//IL_00b1: Expected O, but got Unknown
								ConfigurationManagerAttributes configurationManagerAttributes3 = new ConfigurationManagerAttributes
								{
									CustomDrawer = drawRequirementsConfigTable(item3, isUpgrade),
									Order = (order -= 1),
									browsability = ItemBrowsability,
									Browsable = (ItemBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0),
									Category = localizedName
								};
								hideWhenNoneAttributes.Add(configurationManagerAttributes3);
								return config(englishName, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes3 }));
							}
						}
						if ((item3.configurability & Configurability.Drop) != 0)
						{
							ConfigEntry<string> val3 = (itemDropConfigs[item3] = config(englishName, "Drops from", new SerializedDrop(item3.DropsFrom.Drops).ToString(), new ConfigDescription(englishName + " drops from this creature.", (AcceptableValueBase)null, new object[1]
							{
								new ConfigurationManagerAttributes
								{
									CustomDrawer = drawDropsConfigTable,
									Category = localizedName,
									Browsable = ((item3.configurationVisible & Configurability.Drop) != 0)
								}
							})));
							val3.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
							{
								item3.UpdateCharacterDrop();
							};
						}
						for (int j = 0; j < item3.Conversions.Count; j++)
						{
							string text2 = ((item3.Conversions.Count > 1) ? $"{j + 1}. " : "");
							Conversion conversion = item3.Conversions[j];
							conversion.config = new Conversion.ConversionConfig();
							int index = j;
							conversion.config.input = config(englishName, text2 + "Conversion Input Item", conversion.Input, new ConfigDescription("Input item to create " + englishName, (AcceptableValueBase)null, new object[1]
							{
								new ConfigurationManagerAttributes
								{
									Category = localizedName,
									Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0)
								}
							}));
							conversion.config.input.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
							{
								if (index < item3.conversions.Count)
								{
									ObjectDB instance = ObjectDB.instance;
									if (instance != null)
									{
										ItemDrop from = SerializedRequirements.fetchByName(instance, conversion.config.input.Value);
										item3.conversions[index].m_from = from;
										UpdatePiece();
									}
								}
							};
							conversion.config.piece = config(englishName, text2 + "Conversion Piece", conversion.Piece, new ConfigDescription("Conversion piece used to create " + englishName, (AcceptableValueBase)null, new object[1]
							{
								new ConfigurationManagerAttributes
								{
									Category = localizedName,
									Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0)
								}
							}));
							conversion.config.piece.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
							{
								UpdatePiece();
							};
							conversion.config.customPiece = config(englishName, text2 + "Conversion Custom Piece", conversion.customPiece ?? "", new ConfigDescription("Custom conversion piece to create " + englishName, (AcceptableValueBase)null, new object[1]
							{
								new ConfigurationManagerAttributes
								{
									Category = localizedName,
									Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0)
								}
							}));
							conversion.config.customPiece.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
							{
								UpdatePiece();
							};
							void UpdatePiece()
							{
								if (index < item3.conversions.Count && Object.op_Implicit((Object)(object)ZNetScene.instance))
								{
									string text3 = ((conversion.config.piece.Value == ConversionPiece.Disabled) ? null : ((conversion.config.piece.Value == ConversionPiece.Custom) ? conversion.config.customPiece.Value : getInternalName(conversion.config.piece.Value)));
									string activePiece = conversion.config.activePiece;
									if (conversion.config.activePiece != null)
									{
										int num = ZNetScene.instance.GetPrefab(conversion.config.activePiece).GetComponent<Smelter>().m_conversion.IndexOf(item3.conversions[index]);
										if (num >= 0)
										{
											Smelter[] array3 = Resources.FindObjectsOfTypeAll<Smelter>();
											foreach (Smelter val4 in array3)
											{
												if (Utils.GetPrefabName(((Component)val4).gameObject) == activePiece)
												{
													val4.m_conversion.RemoveAt(num);
												}
											}
										}
										conversion.config.activePiece = null;
									}
									if (item3.conversions[index].m_from != null && conversion.config.piece.Value != 0)
									{
										GameObject prefab = ZNetScene.instance.GetPrefab(text3);
										if (((prefab != null) ? prefab.GetComponent<Smelter>() : null) != null)
										{
											conversion.config.activePiece = text3;
											Smelter[] array3 = Resources.FindObjectsOfTypeAll<Smelter>();
											foreach (Smelter val5 in array3)
											{
												if (Utils.GetPrefabName(((Component)val5).gameObject) == text3)
												{
													val5.m_conversion.Add(item3.conversions[index]);
												}
											}
										}
									}
								}
							}
						}
					}
					if ((item3.configurability & Configurability.Stats) != 0)
					{
						item3.statsConfigs.Clear();
						SharedData shared2 = item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
						ItemType itemType = shared2.m_itemType;
						statcfg<float>("Weight", "Weight of " + englishName + ".", (SharedData shared) => shared.m_weight, delegate(SharedData shared, float value)
						{
							shared.m_weight = value;
						});
						statcfg<int>("Trader Value", "Trader value of " + englishName + ".", (SharedData shared) => shared.m_value, delegate(SharedData shared, int value)
						{
							shared.m_value = value;
						});
						bool flag;
						switch (itemType - 3)
						{
						case 0:
						case 1:
						case 2:
						case 3:
						case 4:
						case 8:
						case 9:
						case 11:
						case 14:
						case 16:
						case 19:
							flag = true;
							break;
						default:
							flag = false;
							break;
						}
						if (flag)
						{
							statcfg<float>("Durability", "Durability of " + englishName + ".", (SharedData shared) => shared.m_maxDurability, delegate(SharedData shared, float value)
							{
								shared.m_maxDurability = value;
							});
							statcfg<float>("Durability per Level", "Durability gain per level of " + englishName + ".", (SharedData shared) => shared.m_durabilityPerLevel, delegate(SharedData shared, float value)
							{
								shared.m_durabilityPerLevel = value;
							});
							statcfg<float>("Movement Speed Modifier", "Movement speed modifier of " + englishName + ".", (SharedData shared) => shared.m_movementModifier, delegate(SharedData shared, float value)
							{
								shared.m_movementModifier = value;
							});
						}
						if ((itemType - 3 <= 2 || (int)itemType == 14 || (int)itemType == 22) ? true : false)
						{
							statcfg<float>("Block Armor", "Block armor of " + englishName + ".", (SharedData shared) => shared.m_blockPower, delegate(SharedData shared, float value)
							{
								shared.m_blockPower = value;
							});
							statcfg<float>("Block Armor per Level", "Block armor per level for " + englishName + ".", (SharedData shared) => shared.m_blockPowerPerLevel, delegate(SharedData shared, float value)
							{
								shared.m_blockPowerPerLevel = value;
							});
							statcfg<float>("Block Force", "Block force of " + englishName + ".", (SharedData shared) => shared.m_deflectionForce, delegate(SharedData shared, float value)
							{
								shared.m_deflectionForce = value;
							});
							statcfg<float>("Block Force per Level", "Block force per level for " + englishName + ".", (SharedData shared) => shared.m_deflectionForcePerLevel, delegate(SharedData shared, float value)
							{
								shared.m_deflectionForcePerLevel = value;
							});
							statcfg<float>("Parry Bonus", "Parry bonus of " + englishName + ".", (SharedData shared) => shared.m_timedBlockBonus, delegate(SharedData shared, float value)
							{
								shared.m_timedBlockBonus = value;
							});
						}
						else if ((itemType - 6 <= 1 || itemType - 11 <= 1 || (int)itemType == 17) ? true : false)
						{
							statcfg<float>("Armor", "Armor of " + englishName + ".", (SharedData shared) => shared.m_armor, delegate(SharedData shared, float value)
							{
								shared.m_armor = value;
							});
							statcfg<float>("Armor per Level", "Armor per level for " + englishName + ".", (SharedData shared) => shared.m_armorPerLevel, delegate(SharedData shared, float value)
							{
								shared.m_armorPerLevel = value;
							});
						}
						SkillType skillType = shared2.m_skillType;
						if (((int)skillType == 7 || (int)skillType == 12) ? true : false)
						{
							statcfg<int>("Tool tier", "Tool tier of " + englishName + ".", (SharedData shared) => shared.m_toolTier, delegate(SharedData shared, int value)
							{
								shared.m_toolTier = value;
							});
						}
						if ((itemType - 5 <= 2 || itemType - 11 <= 1 || (int)itemType == 17) ? true : false)
						{
							Dictionary<DamageType, DamageModifier> modifiers = shared2.m_damageModifiers.ToDictionary((DamageModPair d) => d.m_type, (DamageModPair d) => (DamageModifier)d.m_modifier);
							DamageType[] first = (DamageType[])Enum.GetValues(typeof(DamageType));
							DamageType[] array = new DamageType[5];
							RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
							foreach (DamageType item9 in first.Except((IEnumerable<DamageType>)(object)array))
							{
								DamageType damageType = item9;
								statcfg<DamageModifier>(((object)(DamageType)(ref damageType)).ToString() + " Resistance", ((object)(DamageType)(ref damageType)).ToString() + " resistance of " + englishName + ".", (SharedData _) => (!modifiers.TryGetValue(damageType, out var value3)) ? DamageModifier.None : value3, delegate(SharedData shared, DamageModifier value)
								{
									//IL_0002: Unknown result type (might be due to invalid IL or missing references)
									//IL_000b: Unknown result type (might be due to invalid IL or missing references)
									//IL_0010: Unknown result type (might be due to invalid IL or missing references)
									//IL_0018: Unknown result type (might be due to invalid IL or missing references)
									//IL_001d: Unknown result type (might be due to invalid IL or missing references)
									//IL_001e: Unknown result type (might be due to invalid IL or missing references)
									//IL_002a: Unknown result type (might be due to invalid IL or missing references)
									//IL_002f: Unknown result type (might be due to invalid IL or missing references)
									//IL_0035: Unknown result type (might be due to invalid IL or missing references)
									//IL_0077: Unknown result type (might be due to invalid IL or missing references)
									//IL_0054: Unknown result type (might be due to invalid IL or missing references)
									DamageModPair val6 = default(DamageModPair);
									val6.m_type = damageType;
									val6.m_modifier = (DamageModifier)value;
									DamageModPair val7 = val6;
									for (int n = 0; n < shared.m_damageModifiers.Count; n++)
									{
										if (shared.m_damageModifiers[n].m_type == damageType)
										{
											if (value == DamageModifier.None)
											{
												shared.m_damageModifiers.RemoveAt(n);
											}
											else
											{
												shared.m_damageModifiers[n] = val7;
											}
											return;
										}
									}
									if (value != DamageModifier.None)
									{
										shared.m_damageModifiers.Add(val7);
									}
								});
							}
						}
						if ((int)itemType == 2 && shared2.m_food > 0f)
						{
							statcfg<float>("Health", "Health value of " + englishName + ".", (SharedData shared) => shared.m_food, delegate(SharedData shared, float value)
							{
								shared.m_food = value;
							});
							statcfg<float>("Stamina", "Stamina value of " + englishName + ".", (SharedData shared) => shared.m_foodStamina, delegate(SharedData shared, float value)
							{
								shared.m_foodStamina = value;
							});
							statcfg<float>("Eitr", "Eitr value of " + englishName + ".", (SharedData shared) => shared.m_foodEitr, delegate(SharedData shared, float value)
							{
								shared.m_foodEitr = value;
							});
							statcfg<float>("Duration", "Duration of " + englishName + ".", (SharedData shared) => shared.m_foodBurnTime, delegate(SharedData shared, float value)
							{
								shared.m_foodBurnTime = value;
							});
							statcfg<float>("Health Regen", "Health regen value of " + englishName + ".", (SharedData shared) => shared.m_foodRegen, delegate(SharedData shared, float value)
							{
								shared.m_foodRegen = value;
							});
						}
						if ((int)shared2.m_skillType == 10)
						{
							statcfg<float>("Health Cost", "Health cost of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackHealth, delegate(SharedData shared, float value)
							{
								shared.m_attack.m_attackHealth = value;
							});
							statcfg<float>("Health Cost Percentage", "Health cost percentage of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackHealthPercentage, delegate(SharedData shared, float value)
							{
								shared.m_attack.m_attackHealthPercentage = value;
							});
						}
						skillType = shared2.m_skillType;
						if (skillType - 9 <= 1)
						{
							statcfg<float>("Eitr Cost", "Eitr cost of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackEitr, delegate(SharedData shared, float value)
							{
								shared.m_attack.m_attackEitr = value;
							});
						}
						if ((itemType - 3 <= 1 || (int)itemType == 14 || (int)itemType == 22) ? true : false)
						{
							statcfg<float>("Knockback", "Knockback of " + englishName + ".", (SharedData shared) => shared.m_attackForce, delegate(SharedData shared, float value)
							{
								shared.m_attackForce = value;
							});
							statcfg<float>("Backstab Bonus", "Backstab bonus of " + englishName + ".", (SharedData shared) => shared.m_backstabBonus, delegate(SharedData shared, float value)
							{
								shared.m_backstabBonus = value;
							});
							statcfg<float>("Attack Stamina", "Attack stamina of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackStamina, delegate(SharedData shared, float value)
							{
								shared.m_attack.m_attackStamina = value;
							});
							SetDmg("True", (DamageTypes dmg) => dmg.m_damage, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_damage = val;
							});
							SetDmg("Slash", (DamageTypes dmg) => dmg.m_slash, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_slash = val;
							});
							SetDmg("Pierce", (DamageTypes dmg) => dmg.m_pierce, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_pierce = val;
							});
							SetDmg("Blunt", (DamageTypes dmg) => dmg.m_blunt, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_blunt = val;
							});
							SetDmg("Chop", (DamageTypes dmg) => dmg.m_chop, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_chop = val;
							});
							SetDmg("Pickaxe", (DamageTypes dmg) => dmg.m_pickaxe, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_pickaxe = val;
							});
							SetDmg("Fire", (DamageTypes dmg) => dmg.m_fire, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_fire = val;
							});
							SetDmg("Poison", (DamageTypes dmg) => dmg.m_poison, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_poison = val;
							});
							SetDmg("Frost", (DamageTypes dmg) => dmg.m_frost, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_frost = val;
							});
							SetDmg("Lightning", (DamageTypes dmg) => dmg.m_lightning, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_lightning = val;
							});
							SetDmg("Spirit", (DamageTypes dmg) => dmg.m_spirit, delegate(ref DamageTypes dmg, float val)
							{
								dmg.m_spirit = val;
							});
							if ((int)itemType == 4)
							{
								statcfg<int>("Projectiles", "Number of projectiles that " + englishName + " shoots at once.", (SharedData shared) => shared.m_attack.m_projectileBursts, delegate(SharedData shared, int value)
								{
									shared.m_attack.m_projectileBursts = value;
								});
								statcfg<float>("Burst Interval", "Time between the projectiles " + englishName + " shoots at once.", (SharedData shared) => shared.m_attack.m_burstInterval, delegate(SharedData shared, float value)
								{
									shared.m_attack.m_burstInterval = value;
								});
								statcfg<float>("Minimum Accuracy", "Minimum accuracy for " + englishName + ".", (SharedData shared) => shared.m_attack.m_projectileAccuracyMin, delegate(SharedData shared, float value)
								{
									shared.m_attack.m_projectileAccuracyMin = value;
								});
								statcfg<float>("Accuracy", "Accuracy for " + englishName + ".", (SharedData shared) => shared.m_attack.m_projectileAccuracy, delegate(SharedData shared, float value)
								{
									shared.m_attack.m_projectileAccuracy = value;
								});
								statcfg<float>("Minimum Velocity", "Minimum velocity for " + englishName + ".", (SharedData shared) => shared.m_attack.m_projectileVelMin, delegate(SharedData shared, float value)
								{
									shared.m_attack.m_projectileVelMin = value;
								});
								statcfg<float>("Velocity", "Velocity for " + englishName + ".", (SharedData shared) => shared.m_attack.m_projectileVel, delegate(SharedData shared, float value)
								{
									shared.m_attack.m_projectileVel = value;
								});
								statcfg<float>("Maximum Draw Time", "Time until " + englishName + " is fully drawn at skill level 0.", (SharedData shared) => shared.m_attack.m_drawDurationMin, delegate(SharedData shared, float value)
								{
									shared.m_attack.m_drawDurationMin = value;
								});
								statcfg<float>("Stamina Drain", "Stamina drain per second while drawing " + englishName + ".", (SharedData shared) => shared.m_attack.m_drawStaminaDrain, delegate(SharedData shared, float value)
								{
									shared.m_attack.m_drawStaminaDrain = value;
								});
							}
						}
					}
					List<ConfigurationManagerAttributes> traderAttributes;
					if ((item3.configurability & Configurability.Trader) != 0)
					{
						traderAttributes = new List<ConfigurationManagerAttributes>();
						item3.traderConfig = new TraderConfig
						{
							trader = config(englishName, "Trader Selling", item3.Trade.Trader, new ConfigDescription("Which traders sell " + englishName + ".", (AcceptableValueBase)null, new object[1]
							{
								new ConfigurationManagerAttributes
								{
									Order = (order -= 1),
									Browsable = ((item3.configurationVisible & Configurability.Trader) != 0),
									Category = localizedName
								}
							}))
						};
						item3.traderConfig.trader.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
						{
							item3.ReloadTraderConfiguration();
							foreach (ConfigurationManagerAttributes item10 in traderAttributes)
							{
								item10.Browsable = TraderBrowsability();
							}
							reloadConfigDisplay();
						};
						item3.traderConfig.price = traderConfig<uint>("Trader Price", item3.Trade.Price, "Price of " + englishName + " at the trader.");
						item3.traderConfig.stack = traderConfig<uint>("Trader Stack", item3.Trade.Stack, "Stack size of " + englishName + " in the trader. Also known as the number of items sold by a trader in one transaction.");
						item3.traderConfig.requiredGlobalKey = traderConfig<string>("Trader Required Global Key", item3.Trade.RequiredGlobalKey ?? "", "Required global key to unlock " + englishName + " at the trader.");
						if (item3.traderConfig.trader.Value != 0)
						{
							PrefabManager.AddItemToTrader(item3.Prefab, item3.traderConfig.trader.Value, item3.traderConfig.price.Value, item3.traderConfig.stack.Value, item3.traderConfig.requiredGlobalKey.Value);
						}
					}
					else if (item3.Trade.Trader != 0)
					{
						PrefabManager.AddItemToTrader(item3.Prefab, item3.Trade.Trader, item3.Trade.Price, item3.Trade.Stack, item3.Trade.RequiredGlobalKey);
					}
					void SetDmg(string dmgType, Func<DamageTypes, float> readDmg, setDmgFunc setDmg)
					{
						statcfg<float>(dmgType + " Damage", dmgType + " damage dealt by " + englishName + ".", (SharedData shared) => readDmg(shared.m_damages), delegate(SharedData shared, float val)
						{
							setDmg(ref shared.m_damages, val);
						});
						statcfg<float>(dmgType + " Damage Per Level", dmgType + " damage dealt increase per level for " + englishName + ".", (SharedData shared) => readDmg(shared.m_damagesPerLevel), delegate(SharedData shared, float val)
						{
							setDmg(ref shared.m_damagesPerLevel, val);
						});
					}
					bool TraderBrowsability()
					{
						return item3.traderConfig.trader.Value != Trader.None;
					}
					void statcfg<T>(string configName, string description, [<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 1, 1, 0 })] Func<SharedData, T> readDefault, [<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 1, 1, 0 })] Action<SharedData, T> setValue)
					{
						//IL_0078: Unknown result type (might be due to invalid IL or missing references)
						//IL_0082: Expected O, but got Unknown
						SharedData shared3 = item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
						ConfigEntry<T> cfg2 = config(englishName, configName, readDefault(shared3), new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
						{
							new ConfigurationManagerAttributes
							{
								Category = localizedName,
								Browsable = ((item3.configurationVisible & Configurability.Stats) != 0)
							}
						}));
						if ((item3.configurationVisible & Configurability.Stats) != 0)
						{
							setValue(shared3, cfg2.Value);
						}
						item3.statsConfigs.Add((ConfigEntryBase)(object)cfg2, ApplyConfig);
						cfg2.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
						{
							if ((item3.configurationVisible & Configurability.Stats) != 0)
							{
								ApplyConfig();
							}
						};
						void ApplyConfig()
						{
							item3.ApplyToAllInstances(delegate(ItemData item)
							{
								setValue(item.m_shared, cfg2.Value);
							});
						}
					}
					[return: <d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 1, 0 })]
					ConfigEntry<T> traderConfig<T>(string name, [<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(0)] T value, string desc)
					{
						//IL_0099: Unknown result type (might be due to invalid IL or missing references)
						//IL_00a3: Expected O, but got Unknown
						ConfigurationManagerAttributes configurationManagerAttributes2 = new ConfigurationManagerAttributes
						{
							Order = (order -= 1),
							browsability = TraderBrowsability,
							Browsable = (TraderBrowsability() && (item3.configurationVisible & Configurability.Trader) != 0),
							Category = localizedName
						};
						traderAttributes.Add(configurationManagerAttributes2);
						ConfigEntry<T> obj = config(englishName, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes2 }));
						obj.SettingChanged += [<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (object _, EventArgs _) =>
						{
							item3.ReloadTraderConfiguration();
						};
						return obj;
					}
				}
				if (saveOnConfigSet)
				{
					plugin.Config.SaveOnConfigSet = true;
					plugin.Config.Save();
				}
			}
			configManager = ((type == null) ? null : Chainloader.ManagerObject.GetComponent(type));
			foreach (Item registeredItem in registeredItems)
			{
				Item item2 = registeredItem;
				foreach (KeyValuePair<string, ItemRecipe> recipe in item2.Recipes)
				{
					KeyValuePair<string, ItemRecipe> kv = recipe;
					RequiredResourceList[] array2 = new RequiredResourceList[2]
					{
						kv.Value.RequiredItems,
						kv.Value.RequiredUpgradeItems
					};
					foreach (RequiredResourceList requiredResourceList in array2)
					{
						for (int l = 0; l < requiredResourceList.Requirements.Count; l++)
						{
							ConfigEntry<int> amountCfg;
							int resourceIndex;
							if ((item2.configurability & Configurability.Recipe) != 0)
							{
								amountCfg = requiredResourceList.Requirements[l].amountConfig;
								if (amountCfg != null)
								{
									resourceIndex = l;
									amountCfg.SettingChanged += ConfigChanged;
								}
							}
							void ConfigChanged(object o, EventArgs e)
							{
								if (Object.op_Implicit((Object)(object)ObjectDB.instance) && activeRecipes.ContainsKey(item2) && activeRecipes[item2].TryGetValue(kv.Key, out var value2))
								{
									foreach (Recipe item11 in value2)
									{
										item11.m_resources[resourceIndex].m_amount = amountCfg.Value;
									}
								}
							}
						}
					}
				}
				item2.InitializeNewRegisteredItem();
			}
		}

		private void InitializeNewRegisteredItem()
		{
			foreach (KeyValuePair<string, ItemRecipe> recipe in Recipes)
			{
				KeyValuePair<string, ItemRecipe> kv = recipe;
				ConfigEntryBase enabledCfg = kv.Value.RecipeIsActive;
				if (enabledCfg != null)
				{
					((object)enabledCfg).GetType().GetEvent("SettingChanged").AddEventHandler(enabledCfg, new EventHandler(ConfigChanged));
				}
				void ConfigChanged(object o, EventArgs e)
				{
					if (Object.op_Implicit((Object)(object)ObjectDB.instance) && activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(kv.Key, out var value))
					{
						foreach (Recipe item in value)
						{
							item.m_enabled = (int)enabledCfg.BoxedValue != 0;
						}
					}
				}
			}
		}

		public void ReloadCraftingConfiguration()
		{
			if (Object.op_Implicit((Object)(object)ObjectDB.instance) && ObjectDB.instance.GetItemPrefab(StringExtensionMethods.GetStableHashCode(((Object)Prefab).name)) == null)
			{
				registerRecipesInObjectDB(ObjectDB.instance);
				ObjectDB.instance.m_items.Add(Prefab);
				ObjectDB.instance.m_itemByHash.Add(StringExtensionMethods.GetStableHashCode(((Object)Prefab).name), Prefab);
				ZNetScene.instance.m_prefabs.Add(Prefab);
				ZNetScene.instance.m_namedPrefabs.Add(StringExtensionMethods.GetStableHashCode(((Object)Prefab).name), Prefab);
			}
			foreach (string item in Recipes.Keys.DefaultIfEmpty(""))
			{
				if (Recipes.TryGetValue(item, out var value) && value.Crafting.Stations.Count > 0)
				{
					UpdateItemTableConfig(item, value.Crafting.Stations.First().Table, value.Crafting.Stations.First().custom ?? "");
					UpdateCraftConfig(item, new SerializedRequirements(value.RequiredItems.Requirements), new SerializedRequirements(value.RequiredUpgradeItems.Requirements));
				}
			}
		}

		private void ReloadTraderConfiguration()
		{
			if (traderConfig.trader.Value == Trader.None)
			{
				PrefabManager.RemoveItemFromTrader(Prefab);
			}
			else
			{
				PrefabManager.AddItemToTrader(Prefab, traderConfig.trader.Value, traderConfig.price.Value, traderConfig.stack.Value, traderConfig.requiredGlobalKey.Value);
			}
		}

		public static void ApplyToAllInstances(GameObject prefab, Action<ItemData> callback)
		{
			callback(prefab.GetComponent<ItemDrop>().m_itemData);
			string name = prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
			Inventory[] source = (from c in Player.s_players.Select([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Player p) => ((Humanoid)p).GetInventory()).Concat(from c in Object.FindObjectsOfType<Container>()
					select c.GetInventory())
				where c != null
				select c).ToArray();
			foreach (ItemData item in (from i in (from p in ObjectDB.instance.m_items
					select p.GetComponent<ItemDrop>() into c
					where Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((Component)c).GetComponent<ZNetView>())
					select c).Concat(ItemDrop.s_instances)
				select i.m_itemData).Concat(source.SelectMany([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (Inventory i) => i.GetAllItems())))
			{
				if (item.m_shared.m_name == name)
				{
					callback(item);
				}
			}
		}

		public void ApplyToAllInstances(Action<ItemData> callback)
		{
			ApplyToAllInstances(Prefab, callback);
		}

		[<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)]
		[return: <d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(1)]
		private static string getInternalName<T>(T value) where T : struct
		{
			return ((InternalName)typeof(T).GetMember(value.ToString())[0].GetCustomAttributes(typeof(InternalName)).First()).internalName;
		}

		private void registerRecipesInObjectDB(ObjectDB objectDB)
		{
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Expected O, but got Unknown
			activeRecipes[this] = new Dictionary<string, List<Recipe>>();
			itemCraftConfigs.TryGetValue(this, out var value);
			foreach (KeyValuePair<string, ItemRecipe> recipe in Recipes)
			{
				List<Recipe> list = new List<Recipe>();
				foreach (CraftingStationConfig station in recipe.Value.Crafting.Stations)
				{
					ItemConfig itemConfig = value?[recipe.Key];
					Recipe val = ScriptableObject.CreateInstance<Recipe>();
					string name = ((Object)Prefab).name;
					CraftingTable table = station.Table;
					((Object)val).name = name + "_Recipe_" + table;
					val.m_amount = recipe.Value.CraftAmount;
					ConfigEntryBase recipeIsActive = recipe.Value.RecipeIsActive;
					val.m_enabled = (int)(((recipeIsActive != null) ? recipeIsActive.BoxedValue : null) ?? ((object)1)) != 0 && (itemConfig == null || itemConfig.table.Value != CraftingTable.Disabled);
					val.m_item = Prefab.GetComponent<ItemDrop>();
					val.m_resources = SerializedRequirements.toPieceReqs(objectDB, (itemConfig?.craft == null) ? new SerializedRequirements(recipe.Value.RequiredItems.Requirements) : new SerializedRequirements(itemConfig.craft.Value), (itemConfig?.upgrade == null) ? new SerializedRequirements(recipe.Value.RequiredUpgradeItems.Requirements) : new SerializedRequirements(itemConfig.upgrade.Value));
					table = ((itemConfig == null || list.Count > 0) ? station.Table : itemConfig.table.Value);
					if ((uint)table <= 1u)
					{
						val.m_craftingStation = null;
					}
					else if (((itemConfig == null || list.Count > 0) ? station.Table : itemConfig.table.Value) == CraftingTable.Custom)
					{
						GameObject prefab = ZNetScene.instance.GetPrefab((itemConfig == null || list.Count > 0) ? station.custom : itemConfig.customTable.Value);
						if (prefab != null)
						{
							val.m_craftingStation = prefab.GetComponent<CraftingStation>();
						}
						else
						{
							Debug.LogWarning((object)("Custom crafting station '" + ((itemConfig == null || list.Count > 0) ? station.custom : itemConfig.customTable.Value) + "' does not exist"));
						}
					}
					else
					{
						val.m_craftingStation = ZNetScene.instance.GetPrefab(getInternalName((itemConfig == null || list.Count > 0) ? station.Table : itemConfig.table.Value)).GetComponent<CraftingStation>();
					}
					val.m_minStationLevel = ((itemConfig == null || list.Count > 0) ? station.level : itemConfig.tableLevel.Value);
					val.m_requireOnlyOneIngredient = ((itemConfig == null) ? recipe.Value.RequireOnlyOneIngredient : (itemConfig.requireOneIngredient.Value == Toggle.On));
					val.m_qualityResultAmountMultiplier = itemConfig?.qualityResultAmountMultiplier.Value ?? recipe.Value.QualityResultAmountMultiplier;
					list.Add(val);
					RequiredResourceList requiredItems;
					if (station.Table != 0)
					{
						requiredItems = recipe.Value.RequiredItems;
						if (requiredItems != null && !requiredItems.Free)
						{
							List<Requirement> requirements = requiredItems.Requirements;
							if (requirements != null && requirements.Count == 0)
							{
								hiddenCraftRecipes.Add(val, recipe.Value.RecipeIsActive);
							}
						}
					}
					requiredItems = recipe.Value.RequiredUpgradeItems;
					if (requiredItems != null && !requiredItems.Free)
					{
						List<Requirement> requirements = requiredItems.Requirements;
						if (requirements != null && requirements.Count == 0)
						{
							hiddenUpgradeRecipes.Add(val, recipe.Value.RecipeIsActive);
						}
					}
				}
				activeRecipes[this].Add(recipe.Key, list);
				objectDB.m_recipes.AddRange(list);
			}
			conversions = new List<ItemConversion>();
			for (int i = 0; i < Conversions.Count; i++)
			{
				Conversion conversion = Conversions[i];
				conversions.Add(new ItemConversion
				{
					m_from = SerializedRequirements.fetchByName(ObjectDB.instance, conversion.config?.input.Value ?? conversion.Input),
					m_to = Prefab.GetComponent<ItemDrop>()
				});
				ConversionPiece conversionPiece = conversion.config?.piece.Value ?? conversion.Piece;
				string text = null;
				if (conversionPiece != 0 && conversions[i].m_from != null)
				{
					text = ((conversionPiece != ConversionPiece.Custom) ? getInternalName(conversionPiece) : (conversion.config?.customPiece.Value ?? conversion.customPiece));
					GameObject prefab2 = ZNetScene.instance.GetPrefab(text);
					Smelter val2 = ((prefab2 != null) ? prefab2.GetComponent<Smelter>() : null);
					if (val2 != null)
					{
						val2.m_conversion.Add(conversions[i]);
					}
					else
					{
						text = null;
					}
				}
				if (conversion.config != null)
				{
					conversion.config.activePiece = text;
				}
			}
		}

		[HarmonyPriority(0)]
		internal static void Patch_ObjectDBInit(ObjectDB __instance)
		{
			if ((Object)(object)__instance.GetItemPrefab("Wood") == (Object)null)
			{
				return;
			}
			hiddenCraftRecipes.Clear();
			hiddenUpgradeRecipes.Clear();
			foreach (Item registeredItem in registeredItems)
			{
				registeredItem.registerRecipesInObjectDB(__instance);
			}
		}

		internal static void Patch_TraderGetAvailableItems(Trader __instance, ref List<TradeItem> __result)
		{
			string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
			Trader trader2 = ((prefabName == "Haldor") ? Trader.Haldor : ((prefabName == "Hildir") ? Trader.Hildir : Trader.None));
			Trader trader = trader2;
			__result.AddRange(from tuple in PrefabManager.CustomTradeItems.Values
				where (tuple.Item1 & trader) != 0
				select tuple.Item2 into tradeItem
				where string.IsNullOrEmpty(tradeItem.m_requiredGlobalKey) || ZoneSystem.instance.GetGlobalKey(tradeItem.m_requiredGlobalKey)
				select tradeItem);
		}

		internal static void Patch_OnAddSmelterInput(ItemData item, bool __result)
		{
			if (__result)
			{
				((Humanoid)Player.m_localPlayer).UnequipItem(item, true);
			}
		}

		internal static void Patch_MaximumRequiredStationLevel(Recipe __instance, ref int __result, int quality)
		{
			if (!itemDropMap.TryGetValue(__instance.m_item, out var value))
			{
				return;
			}
			IEnumerable<ItemConfig> source;
			if (!itemCraftConfigs.TryGetValue(value, out var value2))
			{
				source = Enumerable.Empty<ItemConfig>();
			}
			else
			{
				CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
				if (currentCraftingStation != null)
				{
					string stationName = Utils.GetPrefabName(((Component)currentCraftingStation).gameObject);
					source = from c in value2.Where([<3db7695e-db40-448a-a700-552ed53b94e2>NullableContext(0)] (KeyValuePair<string, ItemConfig> c) =>
						{
							switch (c.Value.table.Value)
							{
							case CraftingTable.Disabled:
							case CraftingTable.Inventory:
								return false;
							case CraftingTable.Custom:
								return c.Value.customTable.Value == stationName;
							default:
								return getInternalName(c.Value.table.Value) == stationName;
							}
						})
						select c.Value;
				}
				else
				{
					source = value2.Values;
				}
			}
			__result = Mathf.Min(Mathf.Max(1, __instance.m_minStationLevel) + (quality - 1), (from cfg in source
				where cfg.maximumTableLevel != null
				select cfg.maximumTableLevel.Value).DefaultIfEmpty(value.MaximumRequiredStationLevel).Max());
		}

		internal static void Patch_GetAvailableRecipesPrefix([<d7a12342-7464-415d-8c3a-7280e87ee333>Nullable(new byte[] { 2, 1, 1, 1 })] ref Dictionary<Assembly, List<Recipe>> __state)
		{
			if (__state == null)
			{
				__state = new Dictionary<Assembly, List<Recipe>>();
			}
			Dictionary<Recipe, ConfigEntryBase> source;
			if (InventoryGui.instance.InCraftTab())
			{
				source = hiddenCraftRecipes;
			}
			else
			{
				if (!InventoryGui.instance.InUpradeTab())
				{
					return;
				}
				source = hiddenUpgradeRecipes;
			}
			List<Recipe> list = (from kv in source
				select kv.Key into r
				where r.m_enabled
				select r).ToList();
			__state[Assembly.GetExecutingAssembly()] = list;
			foreach (Recipe item in list)
			{
				item.m_enabled = false;
			}
		}

		internal static void Patch_GetAvailableRecipesFinalizer(Dictionary<Assembly, List<Recipe>> __state)
		{
			if (!__state.TryGetValue(Assembly.GetExecutingAssembly(), out var value))
			{
				return;
			}
			foreach (Recipe item in value)
			{
				item.m_enabled = true;
			}
		}

		internal static IEnumerable<CodeInstruction> Transpile_SetupRequirementList(IEnumerable<CodeInstruction> instructionsEnumerable, ILGenerator ilg)
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Expected O, but got Unknown
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Expected O, but got Unknown
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			List<CodeInstruction> list = instructionsEnumerable.ToList();
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(InventoryGui), "SetupRequirement", (Type[])null, (Type[])null);
			CodeInstruction val = null;
			CodeInstruction val2 = null;
			LocalBuilder localBuilder = ilg.DeclareLocal(typeof(int));
			Dictionary<Label, int> dictionary = new Dictionary<Label, int>();
			bool flag = false;
			int num = 0;
			int value = 0;
			Label? label = default(Label?);
			for (int i = 0; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.Calls(list[i], methodInfo))
				{
					val = list[i + 2];
					val2 = list[i + 5];
					flag = true;
				}
				if (flag)
				{
					if (CodeInstructionExtensions.Branches(list[i], ref label) && dictionary.TryGetValue(label.Value, out value))
					{
						num = i;
						break;
					}
					continue;
				}
				foreach (Label label4 in list[i].labels)
				{
					dictionary[label4] = i;
				}
			}
			if (list[value - 3].opcode == OpCodes.Dup)
			{
				return list;
			}
			Label label2 = ilg.DefineLabel();
			Label label3 = ilg.DefineLabel();
			list[num + 1].labels.Add(label2);
			list.InsertRange(num + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[11]
			{
				new CodeInstruction(OpCodes.Ldloc, (object)localBuilder),
				new CodeInstruction(OpCodes.Brfalse, (object)label2),
				val.Clone(),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(InventoryGui), "m_recipeRequirementList")),
				new CodeInstruction(OpCodes.Ldlen, (object)null),
				new CodeInstruction(OpCodes.Bgt, (object)label2),
				new CodeInstruction(OpCodes.Ldc_I4_0, (object)null),
				val2.Clone(),
				new CodeInstruction(OpCodes.Ldc_I4_0, (object)null),
				new CodeInstruction(OpCodes.Br, (object)label3)
			});
			list.InsertRange(value - 2, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Dup, (object)null)
				{
					labels = new List<Label> { label3 }
				},
				new CodeInstruction(OpCodes.Stloc, (object)localBuilder)
			});
			return list;
		}

		internal static bool Patch_RequirementGetAmount(Requirement __instance, int qualityLevel, ref int __result)
		{
			if (requirementQuality.TryGetValue(__instance, out var value))
			{
				__result = ((value.quality == qualityLevel) ? __instance.m_amountPerLevel : 0);
				return false;
			}
			return true;
		}

		internal static void Patch_ZNetSceneAwake(ZNetScene __instance)
		{
			foreach (Item registeredItem in registeredItems)
			{
				registeredItem.AssignDropToCreature();
			}
		}

		public void AssignDropToCreature()
		{
			foreach (KeyValuePair<CharacterDrop, Drop> characterDrop in characterDrops)
			{
				if (Object.op_Implicit((Object)(object)characterDrop.Key))
				{
					characterDrop.Key.m_drops.Remove(characterDrop.Value);
				}
			}
			characterDrops.Clear();
			SerializedDrop serializedDrop = new SerializedDrop(DropsFrom.Drops);
			if (itemDropConfigs.TryGetValue(this, out var value))
			{
				serializedDrop = new SerializedDrop(value.Value);
			}
			foreach (KeyValuePair<Character, Drop> item in serializedDrop.toCharacterDrops(ZNetScene.s_instance, Prefab))
			{
				CharacterDrop val = ((Component)item.Key).GetComponent<CharacterDrop>();
				if (val == nu