BepInEx/core/XUnity.Common.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using XUnity.Common.Constants;
using XUnity.Common.Extensions;
using XUnity.Common.Logging;
using XUnity.Common.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("XUnity.AutoTranslator.Plugin.Core")]
[assembly: AssemblyCompany("gravydevsupreme")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Common dependencies shared between XUnity Auto Translator and Resource Redirector.")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyProduct("XUnity.Common")]
[assembly: AssemblyTitle("XUnity.Common")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.0")]
[module: UnverifiableCode]
namespace XUnity.Common.Utilities
{
	public static class ArrayHelper
	{
		public static T[] Null<T>()
		{
			return null;
		}
	}
	public static class CabHelper
	{
		private static string CreateRandomCab()
		{
			return "CAB-" + Guid.NewGuid().ToString("N");
		}

		public static void RandomizeCab(byte[] assetBundleData)
		{
			string @string = Encoding.ASCII.GetString(assetBundleData, 0, Math.Min(1024, assetBundleData.Length - 4));
			int num = @string.IndexOf("CAB-", StringComparison.Ordinal);
			if (num >= 0)
			{
				int num2 = @string.Substring(num).IndexOf('\0');
				if (num2 >= 0 && num2 <= 36)
				{
					string s = CreateRandomCab();
					Buffer.BlockCopy(Encoding.ASCII.GetBytes(s), 36 - num2, assetBundleData, num, num2);
				}
			}
		}

		public static void RandomizeCabWithAnyLength(byte[] assetBundleData)
		{
			FindAndReplaceCab("CAB-", 0, assetBundleData, 2048);
		}

		private static void FindAndReplaceCab(string ansiStringToStartWith, byte byteToEndWith, byte[] data, int maxIterations = -1)
		{
			int num = Math.Min(data.Length, maxIterations);
			if (num == -1)
			{
				num = data.Length;
			}
			int num2 = 0;
			int length = ansiStringToStartWith.Length;
			string text = Guid.NewGuid().ToString("N");
			int num3 = 0;
			for (int i = 0; i < num; i++)
			{
				char c = (char)data[i];
				if (num2 == length)
				{
					while (data[i] != byteToEndWith && i < num)
					{
						if (num3 >= text.Length)
						{
							num3 = 0;
							text = Guid.NewGuid().ToString("N");
						}
						data[i++] = (byte)text[num3++];
					}
					break;
				}
				num2 = ((c == ansiStringToStartWith[num2]) ? (num2 + 1) : 0);
			}
		}
	}
	internal static class CecilFastReflectionHelper
	{
		private static readonly Type[] DynamicMethodDelegateArgs = new Type[2]
		{
			typeof(object),
			typeof(object[])
		};

		public static FastReflectionDelegate CreateFastDelegate(MethodBase method, bool directBoxValueAccess, bool forceNonVirtcall)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0068: 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_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: 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_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: 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_01a7: Expected O, but got Unknown
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + method.DeclaringType.FullName + "." + method.Name + ">", typeof(object), DynamicMethodDelegateArgs);
			ILProcessor iLProcessor = val.GetILProcessor();
			ParameterInfo[] parameters = method.GetParameters();
			bool flag = true;
			if (!method.IsStatic)
			{
				iLProcessor.Emit(OpCodes.Ldarg_0);
				if (method.DeclaringType.IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, method.DeclaringType);
				}
			}
			for (int i = 0; i < parameters.Length; i++)
			{
				Type type = parameters[i].ParameterType;
				bool isByRef = type.IsByRef;
				if (isByRef)
				{
					type = type.GetElementType();
				}
				bool isValueType = type.IsValueType;
				if (isByRef && isValueType && !directBoxValueAccess)
				{
					iLProcessor.Emit(OpCodes.Ldarg_1);
					iLProcessor.Emit(OpCodes.Ldc_I4, i);
				}
				iLProcessor.Emit(OpCodes.Ldarg_1);
				iLProcessor.Emit(OpCodes.Ldc_I4, i);
				if (isByRef && !isValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Ldelema, typeof(object));
					continue;
				}
				iLProcessor.Emit(OpCodes.Ldelem_Ref);
				if (!isValueType)
				{
					continue;
				}
				if (!isByRef || !directBoxValueAccess)
				{
					Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, type);
					if (isByRef)
					{
						Extensions.Emit(iLProcessor, OpCodes.Box, type);
						iLProcessor.Emit(OpCodes.Dup);
						Extensions.Emit(iLProcessor, OpCodes.Unbox, type);
						if (flag)
						{
							flag = false;
							val.Definition.Body.Variables.Add(new VariableDefinition((TypeReference)new PinnedType((TypeReference)new PointerType(((MemberReference)val.Definition).Module.TypeSystem.Void))));
						}
						iLProcessor.Emit(OpCodes.Stloc_0);
						iLProcessor.Emit(OpCodes.Stelem_Ref);
						iLProcessor.Emit(OpCodes.Ldloc_0);
					}
				}
				else
				{
					Extensions.Emit(iLProcessor, OpCodes.Unbox, type);
				}
			}
			if (method.IsConstructor)
			{
				Extensions.Emit(iLProcessor, OpCodes.Newobj, (MethodBase)(method as ConstructorInfo));
			}
			else if (method.IsFinal || !method.IsVirtual || forceNonVirtcall)
			{
				Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)(method as MethodInfo));
			}
			else
			{
				Extensions.Emit(iLProcessor, OpCodes.Callvirt, (MethodBase)(method as MethodInfo));
			}
			Type type2 = (method.IsConstructor ? method.DeclaringType : (method as MethodInfo).ReturnType);
			if ((object)type2 != typeof(void))
			{
				if (type2.IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, type2);
				}
			}
			else
			{
				iLProcessor.Emit(OpCodes.Ldnull);
			}
			iLProcessor.Emit(OpCodes.Ret);
			return (FastReflectionDelegate)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(FastReflectionDelegate));
		}

		public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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)
			//IL_0154: 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)
			if ((object)fieldInfo == null)
			{
				throw new ArgumentNullException("fieldInfo");
			}
			if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType))
			{
				throw new ArgumentException("FieldInfo type does not match return type.");
			}
			if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T))))
			{
				throw new MissingFieldException(typeof(T).Name, fieldInfo.Name);
			}
			DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + typeof(T).FullName + ".Get_" + fieldInfo.Name + ">", typeof(F), new Type[1] { typeof(T) });
			ILProcessor iLProcessor = val.GetILProcessor();
			if (!fieldInfo.IsStatic)
			{
				iLProcessor.Emit(OpCodes.Ldarg_0);
				Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.DeclaringType);
			}
			Extensions.Emit(iLProcessor, fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, fieldInfo);
			if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType)
			{
				Extensions.Emit(iLProcessor, OpCodes.Box, fieldInfo.FieldType);
			}
			iLProcessor.Emit(OpCodes.Ret);
			return (Func<T, F>)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(Func<T, F>));
		}

		public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo)
		{
			//IL_00df: 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)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			if ((object)fieldInfo == null)
			{
				throw new ArgumentNullException("fieldInfo");
			}
			if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType))
			{
				throw new ArgumentException("FieldInfo type does not match argument type.");
			}
			if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T))))
			{
				throw new MissingFieldException(typeof(T).Name, fieldInfo.Name);
			}
			DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + typeof(T).FullName + ".Set_" + fieldInfo.Name + ">", (Type)null, new Type[2]
			{
				typeof(T),
				typeof(F)
			});
			ILProcessor iLProcessor = val.GetILProcessor();
			if (!fieldInfo.IsStatic)
			{
				iLProcessor.Emit(OpCodes.Ldarg_0);
				Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.DeclaringType);
			}
			iLProcessor.Emit(OpCodes.Ldarg_1);
			if ((object)fieldInfo.FieldType != typeof(F))
			{
				if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType)
				{
					if (fieldInfo.FieldType.IsValueType)
					{
						Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, fieldInfo.FieldType);
					}
					else
					{
						Extensions.Emit(iLProcessor, OpCodes.Box, fieldInfo.FieldType);
					}
				}
				else
				{
					Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.FieldType);
				}
			}
			Extensions.Emit(iLProcessor, fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo);
			iLProcessor.Emit(OpCodes.Ret);
			return (Action<T, F>)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(Action<T, F>));
		}
	}
	public static class CustomFastReflectionHelper
	{
		private struct FastReflectionDelegateKey
		{
			public MethodBase Method { get; }

			public bool DirectBoxValueAccess { get; }

			public bool ForceNonVirtCall { get; }

			public FastReflectionDelegateKey(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall)
			{
				Method = method;
				DirectBoxValueAccess = directBoxValueAccess;
				ForceNonVirtCall = forceNonVirtCall;
			}

			public override bool Equals(object obj)
			{
				if (obj is FastReflectionDelegateKey fastReflectionDelegateKey && EqualityComparer<MethodBase>.Default.Equals(Method, fastReflectionDelegateKey.Method) && DirectBoxValueAccess == fastReflectionDelegateKey.DirectBoxValueAccess)
				{
					return ForceNonVirtCall == fastReflectionDelegateKey.ForceNonVirtCall;
				}
				return false;
			}

			public override int GetHashCode()
			{
				return ((1017116076 * -1521134295 + EqualityComparer<MethodBase>.Default.GetHashCode(Method)) * -1521134295 + DirectBoxValueAccess.GetHashCode()) * -1521134295 + ForceNonVirtCall.GetHashCode();
			}
		}

		private static readonly Dictionary<FastReflectionDelegateKey, FastReflectionDelegate> MethodCache = new Dictionary<FastReflectionDelegateKey, FastReflectionDelegate>();

		public static FastReflectionDelegate CreateFastDelegate(this MethodBase method, bool directBoxValueAccess = true, bool forceNonVirtCall = false)
		{
			FastReflectionDelegateKey key = new FastReflectionDelegateKey(method, directBoxValueAccess, forceNonVirtCall);
			if (MethodCache.TryGetValue(key, out var value))
			{
				return value;
			}
			value = (((object)ClrTypes.DynamicMethodDefinition == null) ? GetFastDelegateForSRE(method, directBoxValueAccess, forceNonVirtCall) : GetFastDelegateForCecil(method, directBoxValueAccess, forceNonVirtCall));
			MethodCache.Add(key, value);
			return value;
		}

		public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo)
		{
			if ((object)ClrTypes.DynamicMethodDefinition != null)
			{
				return CreateFastFieldGetterForCecil<T, F>(fieldInfo);
			}
			return CreateFastFieldGetterForSRE<T, F>(fieldInfo);
		}

		public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo)
		{
			if ((object)ClrTypes.DynamicMethodDefinition != null)
			{
				return CreateFastFieldSetterForCecil<T, F>(fieldInfo);
			}
			return CreateFastFieldSetterForSRE<T, F>(fieldInfo);
		}

		private static FastReflectionDelegate GetFastDelegateForCecil(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall)
		{
			try
			{
				return CecilFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall);
			}
			catch (Exception e)
			{
				try
				{
					XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit...");
					return ReflectionEmitFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall);
				}
				catch (Exception e2)
				{
					XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection...");
					return (object target, object[] args) => method.Invoke(target, args);
				}
			}
		}

		private static Func<T, F> CreateFastFieldGetterForCecil<T, F>(FieldInfo fieldInfo)
		{
			try
			{
				return CecilFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo);
			}
			catch (Exception e)
			{
				try
				{
					XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit...");
					return ReflectionEmitFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo);
				}
				catch (Exception e2)
				{
					XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection...");
					return (T target) => (F)fieldInfo.GetValue(target);
				}
			}
		}

		private static Action<T, F> CreateFastFieldSetterForCecil<T, F>(FieldInfo fieldInfo)
		{
			try
			{
				return CecilFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo);
			}
			catch (Exception e)
			{
				try
				{
					XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit...");
					return ReflectionEmitFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo);
				}
				catch (Exception e2)
				{
					XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection...");
					return delegate(T target, F value)
					{
						fieldInfo.SetValue(target, value);
					};
				}
			}
		}

		private static FastReflectionDelegate GetFastDelegateForSRE(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall)
		{
			try
			{
				return ReflectionEmitFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall);
			}
			catch (Exception e)
			{
				XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection...");
				return (object target, object[] args) => method.Invoke(target, args);
			}
		}

		private static Func<T, F> CreateFastFieldGetterForSRE<T, F>(FieldInfo fieldInfo)
		{
			try
			{
				return ReflectionEmitFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo);
			}
			catch (Exception e)
			{
				XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection...");
				return (T target) => (F)fieldInfo.GetValue(target);
			}
		}

		private static Action<T, F> CreateFastFieldSetterForSRE<T, F>(FieldInfo fieldInfo)
		{
			try
			{
				return ReflectionEmitFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo);
			}
			catch (Exception e)
			{
				XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection...");
				return delegate(T target, F value)
				{
					fieldInfo.SetValue(target, value);
				};
			}
		}
	}
	public static class DiacriticHelper
	{
		public static string RemoveAllDiacritics(this string input)
		{
			return new string((from c in input.SafeNormalize(NormalizationForm.FormD)
				where CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark
				select c).ToArray()).SafeNormalize();
		}

		private static string SafeNormalize(this string input, NormalizationForm normalizationForm = NormalizationForm.FormC)
		{
			return ReplaceNonCharacters(input, '?').Normalize(normalizationForm);
		}

		private static string ReplaceNonCharacters(string input, char replacement)
		{
			StringBuilder stringBuilder = new StringBuilder(input.Length);
			for (int i = 0; i < input.Length; i++)
			{
				if (char.IsSurrogatePair(input, i))
				{
					int num = char.ConvertToUtf32(input, i);
					i++;
					if (IsValidCodePoint(num))
					{
						stringBuilder.Append(char.ConvertFromUtf32(num));
					}
					else
					{
						stringBuilder.Append(replacement);
					}
				}
				else
				{
					char c = input[i];
					if (IsValidCodePoint(c))
					{
						stringBuilder.Append(c);
					}
					else
					{
						stringBuilder.Append(replacement);
					}
				}
			}
			return stringBuilder.ToString();
		}

		private static bool IsValidCodePoint(int point)
		{
			if (point >= 64976)
			{
				if (point >= 65008 && (point & 0xFFFF) != 65535 && (point & 0xFFFE) != 65534)
				{
					return point <= 1114111;
				}
				return false;
			}
			return true;
		}
	}
	public static class ExpressionHelper
	{
		public static Delegate CreateTypedFastInvoke(MethodBase method)
		{
			if ((object)method == null)
			{
				throw new ArgumentNullException("method");
			}
			return CreateTypedFastInvokeUnchecked(method);
		}

		public static Delegate CreateTypedFastInvokeUnchecked(MethodBase method)
		{
			if ((object)method == null)
			{
				return null;
			}
			if (method.IsGenericMethod)
			{
				throw new ArgumentException("The provided method must not be generic.", "method");
			}
			if (method is MethodInfo methodInfo)
			{
				Expression[] arguments;
				if (method.IsStatic)
				{
					ParameterExpression[] array = (from p in methodInfo.GetParameters()
						select Expression.Parameter(p.ParameterType, p.Name)).ToArray();
					arguments = array;
					return Expression.Lambda(Expression.Call(null, methodInfo, arguments), array).Compile();
				}
				List<ParameterExpression> list = (from p in methodInfo.GetParameters()
					select Expression.Parameter(p.ParameterType, p.Name)).ToList();
				list.Insert(0, Expression.Parameter(methodInfo.DeclaringType, "instance"));
				ParameterExpression instance = list[0];
				arguments = list.Skip(1).ToArray();
				return Expression.Lambda(Expression.Call(instance, methodInfo, arguments), list.ToArray()).Compile();
			}
			if (method is ConstructorInfo constructorInfo)
			{
				ParameterExpression[] array2 = (from p in constructorInfo.GetParameters()
					select Expression.Parameter(p.ParameterType, p.Name)).ToArray();
				Expression[] arguments = array2;
				return Expression.Lambda(Expression.New(constructorInfo, arguments), array2).Compile();
			}
			throw new ArgumentException("method", "This method only supports MethodInfo and ConstructorInfo.");
		}
	}
	public static class ExtensionDataHelper
	{
		private static readonly object Sync;

		private static readonly WeakDictionary<object, object> WeakDynamicFields;

		public static int WeakReferenceCount
		{
			get
			{
				lock (Sync)
				{
					return WeakDynamicFields.Count;
				}
			}
		}

		static ExtensionDataHelper()
		{
			Sync = new object();
			WeakDynamicFields = new WeakDictionary<object, object>();
			MaintenanceHelper.AddMaintenanceFunction(Cull, 12);
		}

		public static void SetExtensionData<T>(this object obj, T t)
		{
			lock (Sync)
			{
				if (WeakDynamicFields.TryGetValue(obj, out var value))
				{
					if (value is Dictionary<Type, object> dictionary)
					{
						dictionary[typeof(T)] = t;
						return;
					}
					Dictionary<Type, object> dictionary2 = new Dictionary<Type, object>();
					dictionary2.Add(value.GetType(), value);
					dictionary2[typeof(T)] = t;
					WeakDynamicFields[obj] = dictionary2;
				}
				else
				{
					WeakDynamicFields[obj] = t;
				}
			}
		}

		public static T GetOrCreateExtensionData<T>(this object obj) where T : new()
		{
			if (obj == null)
			{
				return default(T);
			}
			lock (Sync)
			{
				if (WeakDynamicFields.TryGetValue(obj, out var value))
				{
					if (value is Dictionary<Type, object> dictionary)
					{
						if (dictionary.TryGetValue(typeof(T), out value))
						{
							return (T)value;
						}
						T val = new T();
						dictionary[typeof(T)] = val;
						return val;
					}
					if (!(value is T result))
					{
						Dictionary<Type, object> dictionary2 = new Dictionary<Type, object>();
						dictionary2.Add(value.GetType(), value);
						T val2 = new T();
						dictionary2[typeof(T)] = val2;
						WeakDynamicFields[obj] = dictionary2;
						return val2;
					}
					return result;
				}
				T val3 = new T();
				WeakDynamicFields[obj] = val3;
				return val3;
			}
		}

		public static T GetExtensionData<T>(this object obj)
		{
			if (obj == null)
			{
				return default(T);
			}
			lock (Sync)
			{
				if (WeakDynamicFields.TryGetValue(obj, out var value))
				{
					if (value is Dictionary<Type, object> dictionary && dictionary.TryGetValue(typeof(T), out value))
					{
						if (!(value is T result))
						{
							return default(T);
						}
						return result;
					}
					if (!(value is T result2))
					{
						return default(T);
					}
					return result2;
				}
			}
			return default(T);
		}

		public static void Cull()
		{
			lock (Sync)
			{
				WeakDynamicFields.RemoveCollectedEntries();
			}
		}

		public static List<KeyValuePair<object, object>> GetAllRegisteredObjects()
		{
			lock (Sync)
			{
				return IterateAllPairs().ToList();
			}
		}

		public static void Remove(object obj)
		{
			lock (Sync)
			{
				WeakDynamicFields.Remove(obj);
			}
		}

		private static IEnumerable<KeyValuePair<object, object>> IterateAllPairs()
		{
			foreach (KeyValuePair<object, object> kvp in WeakDynamicFields)
			{
				if (kvp.Value is Dictionary<Type, object> dictionary)
				{
					foreach (KeyValuePair<Type, object> item in dictionary)
					{
						yield return new KeyValuePair<object, object>(kvp.Key, item.Value);
					}
				}
				else
				{
					yield return kvp;
				}
			}
		}
	}
	public delegate object FastReflectionDelegate(object target, params object[] args);
	public static class HookingHelper
	{
		private static readonly MethodInfo PatchMethod12;

		private static readonly MethodInfo PatchMethod20;

		private static readonly object Harmony;

		private static bool _loggedHarmonyError;

		static HookingHelper()
		{
			PatchMethod12 = ClrTypes.HarmonyInstance?.GetMethod("Patch", new Type[4]
			{
				ClrTypes.MethodBase,
				ClrTypes.HarmonyMethod,
				ClrTypes.HarmonyMethod,
				ClrTypes.HarmonyMethod
			});
			PatchMethod20 = ClrTypes.Harmony?.GetMethod("Patch", new Type[5]
			{
				ClrTypes.MethodBase,
				ClrTypes.HarmonyMethod,
				ClrTypes.HarmonyMethod,
				ClrTypes.HarmonyMethod,
				ClrTypes.HarmonyMethod
			});
			_loggedHarmonyError = false;
			try
			{
				if ((object)ClrTypes.HarmonyInstance != null)
				{
					Harmony = ClrTypes.HarmonyInstance.GetMethod("Create", BindingFlags.Static | BindingFlags.Public).Invoke(null, new object[1] { "xunity.common.hookinghelper" });
				}
				else if ((object)ClrTypes.Harmony != null)
				{
					Harmony = ClrTypes.Harmony.GetConstructor(new Type[1] { typeof(string) }).Invoke(new object[1] { "xunity.common.hookinghelper" });
				}
				else
				{
					XuaLogger.Common.Error("An unexpected exception occurred during harmony initialization, likely caused by unknown Harmony version. Harmony hooks will be unavailable!");
				}
			}
			catch (Exception e)
			{
				XuaLogger.Common.Error(e, "An unexpected exception occurred during harmony initialization. Harmony hooks will be unavailable!");
			}
		}

		public static void PatchAll(IEnumerable<Type> types, bool forceExternHooks)
		{
			foreach (Type type in types)
			{
				PatchType(type, forceExternHooks);
			}
		}

		public static void PatchAll(IEnumerable<Type[]> types, bool forceMonoModHooks)
		{
			foreach (Type[] type in types)
			{
				for (int i = 0; i < type.Length && !PatchType(type[i], forceMonoModHooks); i++)
				{
				}
			}
		}

		public static bool PatchType(Type type, bool forceExternHooks)
		{
			MethodBase methodBase = null;
			IntPtr intPtr = IntPtr.Zero;
			try
			{
				if (Harmony == null && !_loggedHarmonyError)
				{
					_loggedHarmonyError = true;
					XuaLogger.Common.Warn("Harmony is not loaded or could not be initialized. Using fallback hooks instead.");
				}
				BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
				MethodInfo method = type.GetMethod("Prepare", bindingAttr);
				if ((object)method == null || (bool)method.Invoke(null, new object[1] { Harmony }))
				{
					try
					{
						methodBase = (MethodBase)(type.GetMethod("TargetMethod", bindingAttr)?.Invoke(null, new object[1] { Harmony }));
					}
					catch
					{
					}
					try
					{
						intPtr = ((IntPtr?)type.GetMethod("TargetMethodPointer", bindingAttr)?.Invoke(null, null)) ?? IntPtr.Zero;
					}
					catch
					{
					}
					if ((object)methodBase == null && intPtr == IntPtr.Zero)
					{
						if ((object)methodBase != null)
						{
							XuaLogger.Common.Warn("Could not hook '" + methodBase.DeclaringType.FullName + "." + methodBase.Name + "'. Likely due differences between different versions of the engine or text framework.");
						}
						else
						{
							XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework.");
						}
						return false;
					}
					MethodInfo method2 = type.GetMethod("Prefix", bindingAttr);
					MethodInfo method3 = type.GetMethod("Postfix", bindingAttr);
					MethodInfo method4 = type.GetMethod("Finalizer", bindingAttr);
					if ((object)methodBase == null || forceExternHooks || Harmony == null || ((object)method2 == null && (object)method3 == null && (object)method4 == null))
					{
						return PatchWithExternHooks(type, methodBase, intPtr, forced: true);
					}
					if ((object)methodBase != null)
					{
						try
						{
							int? priority = type.GetCustomAttributes(typeof(HookingHelperPriorityAttribute), inherit: false).OfType<HookingHelperPriorityAttribute>().FirstOrDefault()?.priority;
							object obj3 = (((object)method2 != null) ? CreateHarmonyMethod(method2, priority) : null);
							object obj4 = (((object)method3 != null) ? CreateHarmonyMethod(method3, priority) : null);
							object obj5 = (((object)method4 != null) ? CreateHarmonyMethod(method4, priority) : null);
							if ((object)PatchMethod12 != null)
							{
								PatchMethod12.Invoke(Harmony, new object[4] { methodBase, obj3, obj4, null });
							}
							else
							{
								PatchMethod20.Invoke(Harmony, new object[5] { methodBase, obj3, obj4, null, obj5 });
							}
							XuaLogger.Common.Debug("Hooked " + methodBase.DeclaringType.FullName + "." + methodBase.Name + " through Harmony hooks.");
							return true;
						}
						catch (Exception e) when (((Func<bool>)delegate
						{
							// Could not convert BlockContainer to single expression
							System.Runtime.CompilerServices.Unsafe.SkipInit(out int num);
							if (e.FirstInnerExceptionOfType<PlatformNotSupportedException>() == null)
							{
								ArgumentException ex = e.FirstInnerExceptionOfType<ArgumentException>();
								num = ((ex != null && ex.Message?.Contains("no body") == true) ? 1 : 0);
							}
							else
							{
								num = 1;
							}
							return num != 0;
						}).Invoke())
						{
							return PatchWithExternHooks(type, methodBase, intPtr, forced: false);
						}
					}
					XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework.");
				}
			}
			catch (Exception e2)
			{
				if ((object)methodBase != null)
				{
					XuaLogger.Common.Warn(e2, "An error occurred while patching property/method '" + methodBase.DeclaringType.FullName + "." + methodBase.Name + "'. Failing hook: '" + type.Name + "'.");
				}
				else
				{
					XuaLogger.Common.Warn(e2, "An error occurred while patching property/method. Failing hook: '" + type.Name + "'.");
				}
			}
			return false;
		}

		private static bool PatchWithExternHooks(Type type, MethodBase original, IntPtr originalPtr, bool forced)
		{
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			if ((object)ClrTypes.Imports != null)
			{
				if (originalPtr == IntPtr.Zero)
				{
					XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework.");
					return false;
				}
				IntPtr? intPtr = type.GetMethod("ML_Detour", bindingAttr)?.MethodHandle.GetFunctionPointer();
				if (intPtr.HasValue && intPtr.Value != IntPtr.Zero)
				{
					ClrTypes.Imports.GetMethod("Hook", bindingAttr).Invoke(null, new object[2] { originalPtr, intPtr.Value });
					XuaLogger.Common.Debug("Hooked " + type.Name + " through MelonMod Imports.Hook method.");
					return true;
				}
				XuaLogger.Common.Warn("Could not hook '" + type.Name + "' because no detour method was found.");
			}
			else
			{
				if ((object)original == null)
				{
					XuaLogger.Common.Warn("Cannot hook '" + type.Name + "'. Could not locate the original method. Failing hook: '" + type.Name + "'.");
					return false;
				}
				if ((object)ClrTypes.Hook == null || (object)ClrTypes.NativeDetour == null)
				{
					XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. MonoMod hooks is not supported in this runtime as MonoMod is not loaded. Failing hook: '" + type.Name + "'.");
					return false;
				}
				object obj = type.GetMethod("Get_MM_Detour", bindingAttr)?.Invoke(null, null) ?? type.GetMethod("MM_Detour", bindingAttr);
				if (obj != null)
				{
					string text = "(managed)";
					object obj2;
					try
					{
						obj2 = ClrTypes.Hook.GetConstructor(new Type[2]
						{
							typeof(MethodBase),
							typeof(MethodInfo)
						}).Invoke(new object[2] { original, obj });
						obj2.GetType().GetMethod("Apply").Invoke(obj2, null);
					}
					catch (Exception e) when (((Func<bool>)delegate
					{
						// Could not convert BlockContainer to single expression
						System.Runtime.CompilerServices.Unsafe.SkipInit(out int num);
						if (e.FirstInnerExceptionOfType<NullReferenceException>() == null)
						{
							NotSupportedException ex = e.FirstInnerExceptionOfType<NotSupportedException>();
							num = ((ex != null && ex.Message?.Contains("Body-less") == true) ? 1 : 0);
						}
						else
						{
							num = 1;
						}
						return num != 0;
					}).Invoke())
					{
						text = "(native)";
						obj2 = ClrTypes.NativeDetour.GetConstructor(new Type[2]
						{
							typeof(MethodBase),
							typeof(MethodBase)
						}).Invoke(new object[2] { original, obj });
						obj2.GetType().GetMethod("Apply").Invoke(obj2, null);
					}
					type.GetMethod("MM_Init", bindingAttr)?.Invoke(null, new object[1] { obj2 });
					if (forced)
					{
						XuaLogger.Common.Debug("Hooked " + original.DeclaringType.FullName + "." + original.Name + " through forced MonoMod hooks. " + text);
					}
					else
					{
						XuaLogger.Common.Debug("Hooked " + original.DeclaringType.FullName + "." + original.Name + " through MonoMod hooks. " + text);
					}
					return true;
				}
				if (forced)
				{
					XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. Harmony is not supported in this runtime and no alternate MonoMod hook has been implemented. Failing hook: '" + type.Name + "'.");
				}
				else
				{
					XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. Harmony is not supported in this runtime and no alternate MonoMod hook has been implemented. Failing hook: '" + type.Name + "'.");
				}
			}
			return false;
		}

		private static object CreateHarmonyMethod(MethodInfo method, int? priority)
		{
			object obj = ClrTypes.HarmonyMethod.GetConstructor(new Type[1] { typeof(MethodInfo) }).Invoke(new object[1] { method });
			if (priority.HasValue)
			{
				(ClrTypes.HarmonyMethod.GetField("priority", BindingFlags.Instance | BindingFlags.Public) ?? ClrTypes.HarmonyMethod.GetField("prioritiy", BindingFlags.Instance | BindingFlags.Public)).SetValue(obj, priority.Value);
			}
			return obj;
		}
	}
	public class HookingHelperPriorityAttribute : Attribute
	{
		public int priority;

		public HookingHelperPriorityAttribute(int priority)
		{
			this.priority = priority;
		}
	}
	public static class HookPriority
	{
		public const int Last = 0;

		public const int VeryLow = 100;

		public const int Low = 200;

		public const int LowerThanNormal = 300;

		public const int Normal = 400;

		public const int HigherThanNormal = 500;

		public const int High = 600;

		public const int VeryHigh = 700;

		public const int First = 800;
	}
	public static class ListExtensions
	{
		public static void BinarySearchInsert<T>(this List<T> items, T item) where T : IComparable<T>
		{
			int num = items.BinarySearch(item);
			if (num < 0)
			{
				items.Insert(~num, item);
			}
			else
			{
				items.Insert(num, item);
			}
		}
	}
	public static class MaintenanceHelper
	{
		private class ActionRegistration
		{
			public Action Action { get; }

			public int Filter { get; }

			public ActionRegistration(Action action, int filter)
			{
				Action = action;
				Filter = filter;
			}
		}

		private static readonly object Sync = new object();

		private static readonly List<ActionRegistration> RegisteredActions = new List<ActionRegistration>();

		private static bool _initialized;

		public static void AddMaintenanceFunction(Action action, int filter)
		{
			lock (Sync)
			{
				if (!_initialized)
				{
					_initialized = true;
					StartMaintenance();
				}
				ActionRegistration item = new ActionRegistration(action, filter);
				RegisteredActions.Add(item);
			}
		}

		private static void StartMaintenance()
		{
			Thread thread = new Thread(MaintenanceLoop);
			thread.IsBackground = true;
			thread.Start();
		}

		private static void MaintenanceLoop(object state)
		{
			int num = 0;
			while (true)
			{
				lock (Sync)
				{
					foreach (ActionRegistration registeredAction in RegisteredActions)
					{
						if (num % registeredAction.Filter == 0)
						{
							try
							{
								registeredAction.Action();
							}
							catch (Exception e)
							{
								XuaLogger.Common.Error(e, "An unexpected error occurred during maintenance.");
							}
						}
					}
				}
				num++;
				Thread.Sleep(5000);
			}
		}
	}
	public static class Paths
	{
		private static string _gameRoot;

		public static string GameRoot
		{
			get
			{
				return _gameRoot ?? GetAndSetGameRoot();
			}
			set
			{
				_gameRoot = value;
			}
		}

		public static void Initialize()
		{
			GetAndSetGameRoot();
		}

		private static string GetAndSetGameRoot()
		{
			return _gameRoot = new DirectoryInfo(Application.dataPath).Parent.FullName;
		}
	}
	public static class ReflectionCache
	{
		private struct MemberLookupKey
		{
			public Type Type { get; set; }

			public string MemberName { get; set; }

			public MemberLookupKey(Type type, string memberName)
			{
				Type = type;
				MemberName = memberName;
			}

			public override bool Equals(object obj)
			{
				if (obj is MemberLookupKey memberLookupKey)
				{
					if ((object)Type == memberLookupKey.Type)
					{
						return MemberName == memberLookupKey.MemberName;
					}
					return false;
				}
				return false;
			}

			public override int GetHashCode()
			{
				return Type.GetHashCode() + MemberName.GetHashCode();
			}
		}

		private static Dictionary<MemberLookupKey, CachedMethod> Methods = new Dictionary<MemberLookupKey, CachedMethod>();

		private static Dictionary<MemberLookupKey, CachedProperty> Properties = new Dictionary<MemberLookupKey, CachedProperty>();

		private static Dictionary<MemberLookupKey, CachedField> Fields = new Dictionary<MemberLookupKey, CachedField>();

		public static CachedMethod CachedMethod(this Type type, string name)
		{
			return type.CachedMethod(name, (Type[])null);
		}

		public static CachedMethod CachedMethod(this Type type, string name, params Type[] types)
		{
			MemberLookupKey key = new MemberLookupKey(type, name);
			if (!Methods.TryGetValue(key, out var value))
			{
				Type type2 = type;
				MethodInfo methodInfo = null;
				while ((object)methodInfo == null && (object)type2 != null)
				{
					methodInfo = ((types != null && types.Length != 0) ? type2.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, types, null) : type2.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
					type2 = type2.BaseType;
				}
				if ((object)methodInfo != null)
				{
					value = new CachedMethod(methodInfo);
				}
				Methods[key] = value;
			}
			return value;
		}

		public static CachedProperty CachedProperty(this Type type, string name)
		{
			MemberLookupKey key = new MemberLookupKey(type, name);
			if (!Properties.TryGetValue(key, out var value))
			{
				Type type2 = type;
				PropertyInfo propertyInfo = null;
				while ((object)propertyInfo == null && (object)type2 != null)
				{
					propertyInfo = type2.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					type2 = type2.BaseType;
				}
				if ((object)propertyInfo != null)
				{
					value = new CachedProperty(propertyInfo);
				}
				Properties[key] = value;
			}
			return value;
		}

		public static CachedField CachedField(this Type type, string name)
		{
			MemberLookupKey key = new MemberLookupKey(type, name);
			if (!Fields.TryGetValue(key, out var value))
			{
				Type type2 = type;
				FieldInfo fieldInfo = null;
				while ((object)fieldInfo == null && (object)type2 != null)
				{
					fieldInfo = type2.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					type2 = type2.BaseType;
				}
				if ((object)fieldInfo != null)
				{
					value = new CachedField(fieldInfo);
				}
				Fields[key] = value;
			}
			return value;
		}

		public static CachedField CachedFieldByIndex(this Type type, int index, Type fieldType, BindingFlags flags)
		{
			FieldInfo[] array = (from x in type.GetFields(flags)
				where (object)x.FieldType == fieldType
				select x).ToArray();
			if (index < array.Length)
			{
				return new CachedField(array[index]);
			}
			return null;
		}
	}
	public class CachedMethod
	{
		private static readonly object[] Args0 = new object[0];

		private static readonly object[] Args1 = new object[1];

		private static readonly object[] Args2 = new object[2];

		private FastReflectionDelegate _invoke;

		internal CachedMethod(MethodInfo method)
		{
			_invoke = method.CreateFastDelegate();
		}

		public object Invoke(object instance, object[] arguments)
		{
			return _invoke(instance, arguments);
		}

		public object Invoke(object instance)
		{
			return _invoke(instance, Args0);
		}

		public object Invoke(object instance, object arg1)
		{
			try
			{
				Args1[0] = arg1;
				return _invoke(instance, Args1);
			}
			finally
			{
				Args1[0] = null;
			}
		}

		public object Invoke(object instance, object arg1, object arg2)
		{
			try
			{
				Args2[0] = arg1;
				Args2[1] = arg2;
				return _invoke(instance, Args2);
			}
			finally
			{
				Args2[0] = null;
				Args2[1] = null;
			}
		}
	}
	public class CachedProperty
	{
		private static readonly object[] Args0 = new object[0];

		private static readonly object[] Args1 = new object[1];

		private FastReflectionDelegate _set;

		private FastReflectionDelegate _get;

		public Type PropertyType { get; }

		internal CachedProperty(PropertyInfo propertyInfo)
		{
			if (propertyInfo.CanRead)
			{
				_get = propertyInfo.GetGetMethod(nonPublic: true).CreateFastDelegate();
			}
			if (propertyInfo.CanWrite)
			{
				_set = propertyInfo.GetSetMethod(nonPublic: true).CreateFastDelegate();
			}
			PropertyType = propertyInfo.PropertyType;
		}

		public void Set(object instance, object[] arguments)
		{
			if (_set != null)
			{
				_set(instance, arguments);
			}
		}

		public void Set(object instance, object arg1)
		{
			if (_set == null)
			{
				return;
			}
			try
			{
				Args1[0] = arg1;
				_set(instance, Args1);
			}
			finally
			{
				Args1[0] = null;
			}
		}

		public object Get(object instance, object[] arguments)
		{
			if (_get == null)
			{
				return null;
			}
			return _get(instance, arguments);
		}

		public object Get(object instance)
		{
			if (_get == null)
			{
				return null;
			}
			return _get(instance, Args0);
		}
	}
	public class CachedField
	{
		private Func<object, object> _get;

		private Action<object, object> _set;

		public Type FieldType { get; }

		internal CachedField(FieldInfo fieldInfo)
		{
			_get = CustomFastReflectionHelper.CreateFastFieldGetter<object, object>(fieldInfo);
			_set = CustomFastReflectionHelper.CreateFastFieldSetter<object, object>(fieldInfo);
			FieldType = fieldInfo.FieldType;
		}

		public void Set(object instance, object value)
		{
			if (_set != null)
			{
				_set(instance, value);
			}
		}

		public object Get(object instance)
		{
			if (_get == null)
			{
				return null;
			}
			return _get(instance);
		}
	}
	internal static class ReflectionEmitFastReflectionHelper
	{
		private static readonly Type[] DynamicMethodDelegateArgs = new Type[2]
		{
			typeof(object),
			typeof(object[])
		};

		public static FastReflectionDelegate CreateFastDelegate(MethodBase method, bool directBoxValueAccess, bool forceNonVirtcall)
		{
			DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + method.DeclaringType.FullName + "." + method.Name + ">", typeof(object), DynamicMethodDelegateArgs, method.DeclaringType.Module, skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			ParameterInfo[] parameters = method.GetParameters();
			bool flag = true;
			if (!method.IsStatic)
			{
				iLGenerator.Emit(OpCodes.Ldarg_0);
				if (method.DeclaringType.IsValueType)
				{
					iLGenerator.Emit(OpCodes.Unbox_Any, method.DeclaringType);
				}
			}
			for (int i = 0; i < parameters.Length; i++)
			{
				Type type = parameters[i].ParameterType;
				bool isByRef = type.IsByRef;
				if (isByRef)
				{
					type = type.GetElementType();
				}
				bool isValueType = type.IsValueType;
				if (isByRef && isValueType && !directBoxValueAccess)
				{
					iLGenerator.Emit(OpCodes.Ldarg_1);
					iLGenerator.Emit(OpCodes.Ldc_I4, i);
				}
				iLGenerator.Emit(OpCodes.Ldarg_1);
				iLGenerator.Emit(OpCodes.Ldc_I4, i);
				if (isByRef && !isValueType)
				{
					iLGenerator.Emit(OpCodes.Ldelema, typeof(object));
					continue;
				}
				iLGenerator.Emit(OpCodes.Ldelem_Ref);
				if (!isValueType)
				{
					continue;
				}
				if (!isByRef || !directBoxValueAccess)
				{
					iLGenerator.Emit(OpCodes.Unbox_Any, type);
					if (isByRef)
					{
						iLGenerator.Emit(OpCodes.Box, type);
						iLGenerator.Emit(OpCodes.Dup);
						iLGenerator.Emit(OpCodes.Unbox, type);
						if (flag)
						{
							flag = false;
							throw new NotImplementedException("No idea how to implement this...");
						}
						iLGenerator.Emit(OpCodes.Stloc_0);
						iLGenerator.Emit(OpCodes.Stelem_Ref);
						iLGenerator.Emit(OpCodes.Ldloc_0);
					}
				}
				else
				{
					iLGenerator.Emit(OpCodes.Unbox, type);
				}
			}
			if (method.IsConstructor)
			{
				iLGenerator.Emit(OpCodes.Newobj, method as ConstructorInfo);
			}
			else if (method.IsFinal || !method.IsVirtual || forceNonVirtcall)
			{
				iLGenerator.Emit(OpCodes.Call, method as MethodInfo);
			}
			else
			{
				iLGenerator.Emit(OpCodes.Callvirt, method as MethodInfo);
			}
			Type type2 = (method.IsConstructor ? method.DeclaringType : (method as MethodInfo).ReturnType);
			if ((object)type2 != typeof(void))
			{
				if (type2.IsValueType)
				{
					iLGenerator.Emit(OpCodes.Box, type2);
				}
			}
			else
			{
				iLGenerator.Emit(OpCodes.Ldnull);
			}
			iLGenerator.Emit(OpCodes.Ret);
			return (FastReflectionDelegate)dynamicMethod.CreateDelegate(typeof(FastReflectionDelegate));
		}

		public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo)
		{
			if ((object)fieldInfo == null)
			{
				throw new ArgumentNullException("fieldInfo");
			}
			if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType))
			{
				throw new ArgumentException("FieldInfo type does not match return type.");
			}
			if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T))))
			{
				throw new MissingFieldException(typeof(T).Name, fieldInfo.Name);
			}
			DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + typeof(T).FullName + ".Get_" + fieldInfo.Name + ">", typeof(F), new Type[1] { typeof(T) }, fieldInfo.DeclaringType.Module, skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			if (!fieldInfo.IsStatic)
			{
				iLGenerator.Emit(OpCodes.Ldarg_0);
				iLGenerator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType);
			}
			iLGenerator.Emit(fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, fieldInfo);
			if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType)
			{
				iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType);
			}
			iLGenerator.Emit(OpCodes.Ret);
			return (Func<T, F>)dynamicMethod.CreateDelegate(typeof(Func<T, F>));
		}

		public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo)
		{
			if ((object)fieldInfo == null)
			{
				throw new ArgumentNullException("fieldInfo");
			}
			if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType))
			{
				throw new ArgumentException("FieldInfo type does not match argument type.");
			}
			if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T))))
			{
				throw new MissingFieldException(typeof(T).Name, fieldInfo.Name);
			}
			DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + typeof(T).FullName + ".Set_" + fieldInfo.Name + ">", null, new Type[2]
			{
				typeof(T),
				typeof(F)
			}, fieldInfo.DeclaringType.Module, skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			if (!fieldInfo.IsStatic)
			{
				iLGenerator.Emit(OpCodes.Ldarg_0);
				iLGenerator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType);
			}
			iLGenerator.Emit(OpCodes.Ldarg_1);
			if ((object)fieldInfo.FieldType != typeof(F))
			{
				if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType)
				{
					if (fieldInfo.FieldType.IsValueType)
					{
						iLGenerator.Emit(OpCodes.Unbox, fieldInfo.FieldType);
					}
					else
					{
						iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType);
					}
				}
				else
				{
					iLGenerator.Emit(OpCodes.Castclass, fieldInfo.FieldType);
				}
			}
			iLGenerator.Emit(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo);
			iLGenerator.Emit(OpCodes.Ret);
			return (Action<T, F>)dynamicMethod.CreateDelegate(typeof(Action<T, F>));
		}
	}
	public static class TimeHelper
	{
		public static float realtimeSinceStartup => Time.realtimeSinceStartup;
	}
	public class UnityObjectReferenceComparer : IEqualityComparer<object>
	{
		public static readonly UnityObjectReferenceComparer Default = new UnityObjectReferenceComparer();

		public new bool Equals(object x, object y)
		{
			return x == y;
		}

		public int GetHashCode(object obj)
		{
			return obj.GetHashCode();
		}
	}
	public class WeakReference<T> : WeakReference where T : class
	{
		public new T Target => (T)base.Target;

		public static WeakReference<T> Create(T target)
		{
			if (target == null)
			{
				return WeakNullReference<T>.Singleton;
			}
			return new WeakReference<T>(target);
		}

		protected WeakReference(T target)
			: base(target, trackResurrection: false)
		{
		}
	}
	internal class WeakNullReference<T> : WeakReference<T> where T : class
	{
		public static readonly WeakNullReference<T> Singleton = new WeakNullReference<T>();

		public override bool IsAlive => true;

		private WeakNullReference()
			: base((T)null)
		{
		}
	}
	internal sealed class WeakKeyReference<T> : WeakReference<T> where T : class
	{
		public readonly int HashCode;

		public WeakKeyReference(T key, WeakKeyComparer<T> comparer)
			: base(key)
		{
			HashCode = comparer.GetHashCode(key);
		}
	}
	internal sealed class WeakKeyComparer<T> : IEqualityComparer<object> where T : class
	{
		private IEqualityComparer<T> comparer;

		internal WeakKeyComparer(IEqualityComparer<T> comparer)
		{
			if (comparer == null)
			{
				comparer = EqualityComparer<T>.Default;
			}
			this.comparer = comparer;
		}

		public int GetHashCode(object obj)
		{
			if (obj is WeakKeyReference<T> weakKeyReference)
			{
				return weakKeyReference.HashCode;
			}
			return comparer.GetHashCode((T)obj);
		}

		public new bool Equals(object x, object y)
		{
			bool isDead;
			T target = GetTarget(x, out isDead);
			bool isDead2;
			T target2 = GetTarget(y, out isDead2);
			if (isDead)
			{
				if (!isDead2)
				{
					return false;
				}
				return x == y;
			}
			if (isDead2)
			{
				return false;
			}
			return comparer.Equals(target, target2);
		}

		private static T GetTarget(object obj, out bool isDead)
		{
			T result;
			if (obj is WeakKeyReference<T> weakKeyReference)
			{
				result = weakKeyReference.Target;
				isDead = !weakKeyReference.IsAlive;
			}
			else
			{
				result = (T)obj;
				isDead = false;
			}
			return result;
		}
	}
	public sealed class WeakDictionary<TKey, TValue> : BaseDictionary<TKey, TValue> where TKey : class
	{
		private Dictionary<object, TValue> dictionary;

		private WeakKeyComparer<TKey> comparer;

		public override int Count => dictionary.Count;

		public WeakDictionary()
			: this(0, (IEqualityComparer<TKey>)null)
		{
		}

		public WeakDictionary(int capacity)
			: this(capacity, (IEqualityComparer<TKey>)null)
		{
		}

		public WeakDictionary(IEqualityComparer<TKey> comparer)
			: this(0, comparer)
		{
		}

		public WeakDictionary(int capacity, IEqualityComparer<TKey> comparer)
		{
			this.comparer = new WeakKeyComparer<TKey>(comparer);
			dictionary = new Dictionary<object, TValue>(capacity, this.comparer);
		}

		public override void Add(TKey key, TValue value)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			WeakReference<TKey> key2 = new WeakKeyReference<TKey>(key, comparer);
			dictionary.Add(key2, value);
		}

		public override bool ContainsKey(TKey key)
		{
			return dictionary.ContainsKey(key);
		}

		public override bool Remove(TKey key)
		{
			return dictionary.Remove(key);
		}

		public override bool TryGetValue(TKey key, out TValue value)
		{
			if (dictionary.TryGetValue(key, out value))
			{
				return true;
			}
			value = default(TValue);
			return false;
		}

		protected override void SetValue(TKey key, TValue value)
		{
			WeakReference<TKey> key2 = new WeakKeyReference<TKey>(key, comparer);
			dictionary[key2] = value;
		}

		public override void Clear()
		{
			dictionary.Clear();
		}

		public override IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
		{
			foreach (KeyValuePair<object, TValue> item in dictionary)
			{
				WeakReference<TKey> obj = (WeakReference<TKey>)item.Key;
				TValue value = item.Value;
				TKey target = obj.Target;
				if (obj.IsAlive)
				{
					yield return new KeyValuePair<TKey, TValue>(target, value);
				}
			}
		}

		public void RemoveCollectedEntries()
		{
			List<object> list = null;
			foreach (KeyValuePair<object, TValue> item in dictionary)
			{
				WeakReference<TKey> weakReference = (WeakReference<TKey>)item.Key;
				if (!weakReference.IsAlive)
				{
					if (list == null)
					{
						list = new List<object>();
					}
					list.Add(weakReference);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (object item2 in list)
			{
				dictionary.Remove(item2);
			}
		}
	}
	[DebuggerDisplay("Count = {Count}")]
	[DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")]
	public abstract class BaseDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
	{
		private abstract class Collection<T> : ICollection<T>, IEnumerable<T>, IEnumerable
		{
			protected readonly IDictionary<TKey, TValue> dictionary;

			public int Count => dictionary.Count;

			public bool IsReadOnly => true;

			protected Collection(IDictionary<TKey, TValue> dictionary)
			{
				this.dictionary = dictionary;
			}

			public void CopyTo(T[] array, int arrayIndex)
			{
				BaseDictionary<TKey, TValue>.Copy((ICollection<T>)this, array, arrayIndex);
			}

			public virtual bool Contains(T item)
			{
				using (IEnumerator<T> enumerator = GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						T current = enumerator.Current;
						if (EqualityComparer<T>.Default.Equals(current, item))
						{
							return true;
						}
					}
				}
				return false;
			}

			public IEnumerator<T> GetEnumerator()
			{
				foreach (KeyValuePair<TKey, TValue> item in dictionary)
				{
					yield return GetItem(item);
				}
			}

			protected abstract T GetItem(KeyValuePair<TKey, TValue> pair);

			public bool Remove(T item)
			{
				throw new NotSupportedException("Collection is read-only.");
			}

			public void Add(T item)
			{
				throw new NotSupportedException("Collection is read-only.");
			}

			public void Clear()
			{
				throw new NotSupportedException("Collection is read-only.");
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		[DebuggerDisplay("Count = {Count}")]
		[DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryKeyCollectionDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")]
		private class KeyCollection : Collection<TKey>
		{
			public KeyCollection(IDictionary<TKey, TValue> dictionary)
				: base(dictionary)
			{
			}

			protected override TKey GetItem(KeyValuePair<TKey, TValue> pair)
			{
				return pair.Key;
			}

			public override bool Contains(TKey item)
			{
				return dictionary.ContainsKey(item);
			}
		}

		[DebuggerDisplay("Count = {Count}")]
		[DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryValueCollectionDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")]
		private class ValueCollection : Collection<TValue>
		{
			public ValueCollection(IDictionary<TKey, TValue> dictionary)
				: base(dictionary)
			{
			}

			protected override TValue GetItem(KeyValuePair<TKey, TValue> pair)
			{
				return pair.Value;
			}
		}

		private const string PREFIX = "System.Collections.Generic.Mscorlib_";

		private const string SUFFIX = ",mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089";

		private KeyCollection keys;

		private ValueCollection values;

		public abstract int Count { get; }

		public bool IsReadOnly => false;

		public ICollection<TKey> Keys
		{
			get
			{
				if (keys == null)
				{
					keys = new KeyCollection(this);
				}
				return keys;
			}
		}

		public ICollection<TValue> Values
		{
			get
			{
				if (values == null)
				{
					values = new ValueCollection(this);
				}
				return values;
			}
		}

		public TValue this[TKey key]
		{
			get
			{
				if (!TryGetValue(key, out var value))
				{
					throw new KeyNotFoundException();
				}
				return value;
			}
			set
			{
				SetValue(key, value);
			}
		}

		public abstract void Clear();

		public abstract void Add(TKey key, TValue value);

		public abstract bool ContainsKey(TKey key);

		public abstract bool Remove(TKey key);

		public abstract bool TryGetValue(TKey key, out TValue value);

		public abstract IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();

		protected abstract void SetValue(TKey key, TValue value);

		public void Add(KeyValuePair<TKey, TValue> item)
		{
			Add(item.Key, item.Value);
		}

		public bool Contains(KeyValuePair<TKey, TValue> item)
		{
			if (!TryGetValue(item.Key, out var value))
			{
				return false;
			}
			return EqualityComparer<TValue>.Default.Equals(value, item.Value);
		}

		public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
		{
			Copy(this, array, arrayIndex);
		}

		public bool Remove(KeyValuePair<TKey, TValue> item)
		{
			if (!Contains(item))
			{
				return false;
			}
			return Remove(item.Key);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		private static void Copy<T>(ICollection<T> source, T[] array, int arrayIndex)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (arrayIndex < 0 || arrayIndex > array.Length)
			{
				throw new ArgumentOutOfRangeException("arrayIndex");
			}
			if (array.Length - arrayIndex < source.Count)
			{
				throw new ArgumentException("Destination array is not large enough. Check array.Length and arrayIndex.");
			}
			foreach (T item in source)
			{
				array[arrayIndex++] = item;
			}
		}
	}
}
namespace XUnity.Common.MonoMod
{
	public static class DetourExtensions
	{
		public static T GenerateTrampolineEx<T>(this object detour)
		{
			return (T)(from x in detour.GetType().GetMethods()
				where x.Name == "GenerateTrampoline" && x.IsGenericMethod
				select x).FirstOrDefault().MakeGenericMethod(typeof(T)).Invoke(detour, null);
		}
	}
}
namespace XUnity.Common.Logging
{
	internal class ConsoleLogger : XuaLogger
	{
		public ConsoleLogger(string source)
			: base(source)
		{
		}

		protected override void Log(LogLevel level, string message)
		{
			Console.WriteLine(GetDefaultPrefix(level) + " " + message);
		}
	}
	public enum LogLevel
	{
		Debug,
		Info,
		Warn,
		Error
	}
	internal class ModLoaderSpecificLogger : XuaLogger
	{
		public static class BepInExLogLevel
		{
			public const int None = 0;

			public const int Fatal = 1;

			public const int Error = 2;

			public const int Warning = 4;

			public const int Message = 8;

			public const int Info = 16;

			public const int Debug = 32;

			public const int All = 63;
		}

		private static Action<LogLevel, string> _logMethod;

		public ModLoaderSpecificLogger(string source)
			: base(source)
		{
			if (_logMethod != null)
			{
				return;
			}
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public;
			BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public;
			Type type = Type.GetType("BepInEx.Logging.LogLevel, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.LogLevel, BepInEx.Core", throwOnError: false);
			if ((object)type != null)
			{
				if ((object)(Type.GetType("BepInEx.Logging.ManualLogSource, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.ManualLogSource, BepInEx.Core", throwOnError: false)) != null)
				{
					MethodInfo method = (Type.GetType("BepInEx.Logging.Logger, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.Logger, BepInEx.Core", throwOnError: false)).GetMethod("CreateLogSource", bindingAttr, null, new Type[1] { typeof(string) }, null);
					object logInstance2 = method.Invoke(null, new object[1] { base.Source });
					MethodInfo method2 = logInstance2.GetType().GetMethod("Log", bindingAttr2, null, new Type[2]
					{
						type,
						typeof(object)
					}, null);
					FastReflectionDelegate log2 = method2.CreateFastDelegate();
					_logMethod = delegate(LogLevel level, string msg)
					{
						int num2 = Convert(level);
						log2(logInstance2, num2, msg);
					};
				}
				else
				{
					Type type2 = Type.GetType("BepInEx.Logger, BepInEx", throwOnError: false);
					object logInstance = type2.GetProperty("CurrentLogger", bindingAttr).GetValue(null, null);
					MethodInfo method3 = logInstance.GetType().GetMethod("Log", bindingAttr2, null, new Type[2]
					{
						type,
						typeof(object)
					}, null);
					FastReflectionDelegate log = method3.CreateFastDelegate();
					_logMethod = delegate(LogLevel level, string msg)
					{
						int num = Convert(level);
						log(logInstance, num, msg);
					};
				}
			}
			else
			{
				Type type3 = Type.GetType("MelonLoader.MelonLogger, MelonLoader.ModHandler", throwOnError: false);
				if ((object)type3 != null)
				{
					MethodInfo method4 = type3.GetMethod("Log", bindingAttr, null, new Type[2]
					{
						typeof(ConsoleColor),
						typeof(string)
					}, null);
					MethodInfo method5 = type3.GetMethod("Log", bindingAttr, null, new Type[1] { typeof(string) }, null);
					MethodInfo method6 = type3.GetMethod("LogWarning", bindingAttr, null, new Type[1] { typeof(string) }, null);
					MethodInfo method7 = type3.GetMethod("LogError", bindingAttr, null, new Type[1] { typeof(string) }, null);
					FastReflectionDelegate logDebug = method4.CreateFastDelegate();
					FastReflectionDelegate logInfo = method5.CreateFastDelegate();
					FastReflectionDelegate logWarning = method6.CreateFastDelegate();
					FastReflectionDelegate logError = method7.CreateFastDelegate();
					_logMethod = delegate(LogLevel level, string msg)
					{
						switch (level)
						{
						case LogLevel.Debug:
							logDebug(null, ConsoleColor.Gray, msg);
							break;
						case LogLevel.Info:
							logInfo(null, msg);
							break;
						case LogLevel.Warn:
							logWarning(null, msg);
							break;
						case LogLevel.Error:
							logError(null, msg);
							break;
						default:
							throw new ArgumentException("level");
						}
					};
				}
			}
			if (_logMethod != null)
			{
				return;
			}
			throw new Exception("Did not recognize any mod loader!");
		}

		protected override void Log(LogLevel level, string message)
		{
			_logMethod(level, message);
		}

		public static int Convert(LogLevel level)
		{
			return level switch
			{
				LogLevel.Debug => 32, 
				LogLevel.Info => 16, 
				LogLevel.Warn => 4, 
				LogLevel.Error => 2, 
				_ => 0, 
			};
		}
	}
	public abstract class XuaLogger
	{
		private static XuaLogger _default;

		private static XuaLogger _common;

		private static XuaLogger _resourceRedirector;

		public static XuaLogger AutoTranslator
		{
			get
			{
				if (_default == null)
				{
					_default = CreateLogger("XUnity.AutoTranslator");
				}
				return _default;
			}
			set
			{
				_default = value ?? throw new ArgumentNullException("value");
			}
		}

		public static XuaLogger Common
		{
			get
			{
				if (_common == null)
				{
					_common = CreateLogger("XUnity.Common");
				}
				return _common;
			}
			set
			{
				_common = value ?? throw new ArgumentNullException("value");
			}
		}

		public static XuaLogger ResourceRedirector
		{
			get
			{
				if (_resourceRedirector == null)
				{
					_resourceRedirector = CreateLogger("XUnity.ResourceRedirector");
				}
				return _resourceRedirector;
			}
			set
			{
				_resourceRedirector = value ?? throw new ArgumentNullException("value");
			}
		}

		public string Source { get; set; }

		internal static XuaLogger CreateLogger(string source)
		{
			try
			{
				return new ModLoaderSpecificLogger(source);
			}
			catch (Exception)
			{
				return new ConsoleLogger(source);
			}
		}

		public XuaLogger(string source)
		{
			Source = source;
		}

		public void Error(Exception e, string message)
		{
			Log(LogLevel.Error, message + Environment.NewLine + e);
		}

		public void Error(string message)
		{
			Log(LogLevel.Error, message);
		}

		public void Warn(Exception e, string message)
		{
			Log(LogLevel.Warn, message + Environment.NewLine + e);
		}

		public void Warn(string message)
		{
			Log(LogLevel.Warn, message);
		}

		public void Info(Exception e, string message)
		{
			Log(LogLevel.Info, message + Environment.NewLine + e);
		}

		public void Info(string message)
		{
			Log(LogLevel.Info, message);
		}

		public void Debug(Exception e, string message)
		{
			Log(LogLevel.Debug, message + Environment.NewLine + e);
		}

		public void Debug(string message)
		{
			Log(LogLevel.Debug, message);
		}

		protected abstract void Log(LogLevel level, string message);

		protected string GetDefaultPrefix(LogLevel level)
		{
			return level switch
			{
				LogLevel.Debug => "[DEBUG][" + Source + "]: ", 
				LogLevel.Info => "[INFO][" + Source + "]: ", 
				LogLevel.Warn => "[WARN][" + Source + "]: ", 
				LogLevel.Error => "[ERROR][" + Source + "]: ", 
				_ => "[UNKNOW][" + Source + "]: ", 
			};
		}
	}
}
namespace XUnity.Common.Harmony
{
	public static class AccessToolsShim
	{
		private static readonly BindingFlags All;

		private static readonly Func<Type, string, Type[], Type[], MethodInfo> AccessTools_Method;

		private static readonly Func<Type, string, PropertyInfo> AccessTools_Property;

		static AccessToolsShim()
		{
			All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			MethodInfo method = ClrTypes.AccessTools.GetMethod("Method", All, null, new Type[4]
			{
				typeof(Type),
				typeof(string),
				typeof(Type[]),
				typeof(Type[])
			}, null);
			MethodInfo? method2 = ClrTypes.AccessTools.GetMethod("Property", All, null, new Type[2]
			{
				typeof(Type),
				typeof(string)
			}, null);
			AccessTools_Method = (Func<Type, string, Type[], Type[], MethodInfo>)ExpressionHelper.CreateTypedFastInvoke(method);
			AccessTools_Property = (Func<Type, string, PropertyInfo>)ExpressionHelper.CreateTypedFastInvoke(method2);
		}

		public static MethodInfo Method(Type type, string name, params Type[] parameters)
		{
			return AccessTools_Method(type, name, parameters, null);
		}

		public static PropertyInfo Property(Type type, string name)
		{
			return AccessTools_Property(type, name);
		}
	}
}
namespace XUnity.Common.Extensions
{
	public static class ExceptionExtensions
	{
		public static TException FirstInnerExceptionOfType<TException>(this Exception e) where TException : Exception
		{
			for (Exception ex = e; ex != null; ex = ex.InnerException)
			{
				if (ex is TException)
				{
					return (TException)ex;
				}
			}
			return null;
		}
	}
	public static class ObjectExtensions
	{
		public static Type GetUnityType(this object obj)
		{
			return obj.GetType();
		}

		public static bool TryCastTo<TObject>(this object obj, out TObject castedObject)
		{
			if (obj is TObject val)
			{
				castedObject = val;
				return true;
			}
			castedObject = default(TObject);
			return false;
		}
	}
	public static class StreamExtensions
	{
		public static byte[] ReadFully(this Stream stream, int initialLength)
		{
			if (initialLength < 1)
			{
				initialLength = 32768;
			}
			byte[] array = new byte[initialLength];
			int num = 0;
			int num2;
			while ((num2 = stream.Read(array, num, array.Length - num)) > 0)
			{
				num += num2;
				if (num == array.Length)
				{
					int num3 = stream.ReadByte();
					if (num3 == -1)
					{
						return array;
					}
					byte[] array2 = new byte[array.Length * 2];
					Array.Copy(array, array2, array.Length);
					array2[num] = (byte)num3;
					array = array2;
					num++;
				}
			}
			byte[] array3 = new byte[num];
			Array.Copy(array, array3, num);
			return array3;
		}
	}
	public static class StringExtensions
	{
		private static readonly HashSet<char> InvalidFileNameChars = new HashSet<char>(Path.GetInvalidFileNameChars());

		public static string UseCorrectDirectorySeparators(this string path)
		{
			if (Path.DirectorySeparatorChar == '\\')
			{
				return path.Replace('/', Path.DirectorySeparatorChar);
			}
			if (Path.DirectorySeparatorChar == '/')
			{
				return path.Replace('\\', Path.DirectorySeparatorChar);
			}
			return path;
		}

		public static bool IsNullOrWhiteSpace(this string value)
		{
			if (value == null)
			{
				return true;
			}
			for (int i = 0; i < value.Length; i++)
			{
				if (!char.IsWhiteSpace(value[i]))
				{
					return false;
				}
			}
			return true;
		}

		public static string MakeRelativePath(this string fullOrRelativePath, string basePath)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int i = 0;
			bool flag = false;
			string[] array = basePath.Split(':', '\\', '/');
			List<string> list = fullOrRelativePath.Split(':', '\\', '/').ToList();
			if (array.Length == 0 || list.Count <= 0 || array[0] != list[0])
			{
				flag = true;
			}
			bool flag2 = false;
			for (int j = 0; j < list.Count; j++)
			{
				if (list[j] == "..")
				{
					if (flag2)
					{
						int num = j - 1;
						if (num >= 0)
						{
							list.RemoveAt(j);
							list.RemoveAt(num);
							j -= 2;
						}
					}
				}
				else
				{
					flag2 = true;
				}
			}
			if (!flag)
			{
				for (i = 1; i < array.Length && !(array[i] != list[i]); i++)
				{
				}
				for (int k = 0; k < array.Length - i; k++)
				{
					char directorySeparatorChar = Path.DirectorySeparatorChar;
					stringBuilder.Append(".." + directorySeparatorChar);
				}
			}
			for (int l = i; l < list.Count - 1; l++)
			{
				string value = list[l];
				stringBuilder.Append(value).Append(Path.DirectorySeparatorChar);
			}
			string value2 = list[^1];
			stringBuilder.Append(value2);
			return stringBuilder.ToString();
		}

		public static string SanitizeForFileSystem(this string path)
		{
			StringBuilder stringBuilder = new StringBuilder(path.Length);
			foreach (char c in path)
			{
				if (!InvalidFileNameChars.Contains(c))
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		public static string SplitToLines(this string text, int maxStringLength, params char[] splitOnCharacters)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num;
			for (int i = 0; text.Length > i; i += num)
			{
				if (i != 0)
				{
					stringBuilder.Append('\n');
				}
				num = ((i + maxStringLength <= text.Length) ? text.Substring(i, maxStringLength).LastIndexOfAny(splitOnCharacters) : (text.Length - i));
				num = ((num == -1) ? maxStringLength : num);
				stringBuilder.Append(text.Substring(i, num).Trim());
			}
			return stringBuilder.ToString();
		}

		public static bool StartsWithStrict(this string str, string prefix)
		{
			int num = Math.Min(str.Length, prefix.Length);
			if (num < prefix.Length)
			{
				return false;
			}
			for (int i = 0; i < num; i++)
			{
				if (str[i] != prefix[i])
				{
					return false;
				}
			}
			return true;
		}

		public static string GetBetween(this string strSource, string strStart, string strEnd)
		{
			int num = strSource.IndexOf(strStart);
			if (num != -1)
			{
				num += strStart.Length;
				int num2 = strSource.IndexOf(strEnd, num);
				if (num2 > num)
				{
					return strSource.Substring(num, num2 - num);
				}
			}
			return string.Empty;
		}

		public static bool RemindsOf(this string that, string other)
		{
			if (!that.StartsWith(other) && !other.StartsWith(that) && !that.EndsWith(other))
			{
				return other.EndsWith(that);
			}
			return true;
		}
	}
}
namespace XUnity.Common.Constants
{
	public static class ClrTypes
	{
		public static readonly Type AccessTools = FindTypeStrict("Harmony.AccessTools, 0Harmony") ?? FindTypeStrict("HarmonyLib.AccessTools, 0Harmony") ?? FindTypeStrict("Harmony.AccessTools, MelonLoader.ModHandler") ?? FindTypeStrict("HarmonyLib.AccessTools, MelonLoader.ModHandler");

		public static readonly Type HarmonyMethod = FindTypeStrict("Harmony.HarmonyMethod, 0Harmony") ?? FindTypeStrict("HarmonyLib.HarmonyMethod, 0Harmony") ?? FindTypeStrict("Harmony.HarmonyMethod, MelonLoader.ModHandler") ?? FindTypeStrict("HarmonyLib.HarmonyMethod, MelonLoader.ModHandler");

		public static readonly Type HarmonyInstance = FindTypeStrict("Harmony.HarmonyInstance, 0Harmony") ?? FindTypeStrict("Harmony.HarmonyInstance, MelonLoader.ModHandler");

		public static readonly Type Harmony = FindTypeStrict("HarmonyLib.Harmony, 0Harmony") ?? FindTypeStrict("HarmonyLib.Harmony, MelonLoader.ModHandler");

		public static readonly Type Hook = FindTypeStrict("MonoMod.RuntimeDetour.Hook, MonoMod.RuntimeDetour");

		public static readonly Type Detour = FindTypeStrict("MonoMod.RuntimeDetour.Detour, MonoMod.RuntimeDetour");

		public static readonly Type NativeDetour = FindTypeStrict("MonoMod.RuntimeDetour.NativeDetour, MonoMod.RuntimeDetour");

		public static readonly Type DynamicMethodDefinition = FindTypeStrict("MonoMod.Utils.DynamicMethodDefinition, MonoMod.Utils");

		public static readonly Type Imports = FindTypeStrict("MelonLoader.Imports, MelonLoader.ModHandler");

		public static readonly Type MethodBase = FindType("System.Reflection.MethodBase");

		public static readonly Type Task = FindType("System.Threading.Tasks.Task");

		private static Type FindType(string name)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(name, throwOnError: false);
					if ((object)type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static Type FindTypeStrict(string name)
		{
			return Type.GetType(name, throwOnError: false);
		}
	}
	public class TypeContainer
	{
		public Type ClrType { get; }

		public Type UnityType { get; }

		public TypeContainer(Type type)
		{
			UnityType = type;
			ClrType = type;
		}

		public bool IsAssignableFrom(Type unityType)
		{
			if ((object)UnityType != null)
			{
				return UnityType.IsAssignableFrom(unityType);
			}
			return false;
		}
	}
	public static class UnityFeatures
	{
		private static readonly BindingFlags All;

		public static bool SupportsMouseScrollDelta { get; }

		public static bool SupportsClipboard { get; }

		public static bool SupportsCustomYieldInstruction { get; }

		public static bool SupportsSceneManager { get; }

		public static bool SupportsWaitForSecondsRealtime { get; set; }

		static UnityFeatures()
		{
			All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			SupportsMouseScrollDelta = false;
			SupportsClipboard = false;
			SupportsCustomYieldInstruction = false;
			SupportsSceneManager = false;
			SupportsWaitForSecondsRealtime = false;
			try
			{
				SupportsClipboard = (object)UnityTypes.TextEditor?.ClrType.GetProperty("text")?.GetSetMethod() != null;
			}
			catch (Exception)
			{
			}
			try
			{
				SupportsCustomYieldInstruction = UnityTypes.CustomYieldInstruction != null;
			}
			catch (Exception)
			{
			}
			try
			{
				SupportsSceneManager = UnityTypes.Scene != null && UnityTypes.SceneManager != null && (object)UnityTypes.SceneManager.ClrType.GetMethod("add_sceneLoaded", All) != null;
			}
			catch (Exception)
			{
			}
			try
			{
				SupportsMouseScrollDelta = (object)UnityTypes.Input?.ClrType.GetProperty("mouseScrollDelta") != null;
			}
			catch (Exception)
			{
			}
			try
			{
				SupportsWaitForSecondsRealtime = UnityTypes.WaitForSecondsRealtime != null;
			}
			catch (Exception)
			{
			}
		}
	}
	public static class UnityTypes
	{
		public static class TMP_Settings_Properties
		{
			public static CachedProperty Version = TMP_Settings?.ClrType.CachedProperty("version");

			public static CachedProperty FallbackFontAssets = TMP_Settings?.ClrType.CachedProperty("fallbackFontAssets");
		}

		public static class TMP_FontAsset_Properties
		{
			public static CachedProperty Version = TMP_FontAsset?.ClrType.CachedProperty("version");
		}

		public static class AdvScenarioData_Properties
		{
			public static CachedProperty ScenarioLabels = AdvScenarioData?.ClrType.CachedProperty("ScenarioLabels");
		}

		public static class UguiNovelText_Properties
		{
			public static CachedProperty TextGenerator = UguiNovelText?.ClrType.CachedProperty("TextGenerator");
		}

		public static class UguiNovelText_Methods
		{
			public static CachedMethod SetAllDirty = UguiNovelText?.ClrType.CachedMethod("SetAllDirty");
		}

		public static class UguiNovelTextGenerator_Methods
		{
			public static CachedMethod Refresh = UguiNovelTextGenerator?.ClrType.CachedMethod("Refresh");
		}

		public static class AdvUguiMessageWindow_Properties
		{
			public static CachedProperty Text = AdvUguiMessageWindow?.ClrType.CachedProperty("Text");

			public static CachedProperty Engine = AdvUguiMessageWindow?.ClrType.CachedProperty("Engine");
		}

		public static class AdvUiMessageWindow_Fields
		{
			public static CachedField text = AdvUiMessageWindow?.ClrType.CachedField("text");

			public static CachedField nameText = AdvUiMessageWindow?.ClrType.CachedField("nameText");
		}

		public static class AdvUguiMessageWindow_Fields
		{
			public static FieldInfo text = AdvUguiMessageWindow?.ClrType.GetField("text", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

			public static FieldInfo nameText = AdvUguiMessageWindow?.ClrType.GetField("nameText", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

			public static FieldInfo engine = AdvUguiMessageWindow?.ClrType.GetField("engine", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static class AdvEngine_Properties
		{
			public static CachedProperty Page = AdvEngine?.ClrType.CachedProperty("Page");
		}

		public static class AdvPage_Methods
		{
			public static CachedMethod RemakeTextData = AdvPage?.ClrType.CachedMethod("RemakeTextData");

			public static CachedMethod RemakeText = AdvPage?.ClrType.CachedMethod("RemakeText");

			public static CachedMethod ChangeMessageWindowText = AdvPage?.ClrType.CachedMethod("ChangeMessageWindowText", typeof(string), typeof(string), typeof(string), typeof(string));
		}

		public static class UILabel_Properties
		{
			public static CachedProperty MultiLine = UILabel?.ClrType.CachedProperty("multiLine");

			public static CachedProperty OverflowMethod = UILabel?.ClrType.CachedProperty("overflowMethod");

			public static CachedProperty SpacingX = UILabel?.ClrType.CachedProperty("spacingX");

			public static CachedProperty UseFloatSpacing = UILabel?.ClrType.CachedProperty("useFloatSpacing");
		}

		public static class Text_Properties
		{
			public static CachedProperty Font = Text?.ClrType.CachedProperty("font");

			public static CachedProperty FontSize = Text?.ClrType.CachedProperty("fontSize");

			public static CachedProperty HorizontalOverflow = Text?.ClrType.CachedProperty("horizontalOverflow");

			public static CachedProperty VerticalOverflow = Text?.ClrType.CachedProperty("verticalOverflow");

			public static CachedProperty LineSpacing = Text?.ClrType.CachedProperty("lineSpacing");

			public static CachedProperty ResizeTextForBestFit = Text?.ClrType.CachedProperty("resizeTextForBestFit");

			public static CachedProperty ResizeTextMinSize = Text?.ClrType.CachedProperty("resizeTextMinSize");

			public static CachedProperty ResizeTextMaxSize = Text?.ClrType.CachedProperty("resizeTextMaxSize");
		}

		public static class InputField_Properties
		{
			public static CachedProperty Placeholder = InputField?.ClrType.CachedProperty("placeholder");
		}

		public static class TMP_InputField_Properties
		{
			public static CachedProperty Placeholder = TMP_InputField?.ClrType.CachedProperty("placeholder");
		}

		public static class Font_Properties
		{
			public static CachedProperty FontSize = Font?.ClrType.CachedProperty("fontSize");
		}

		public static class AssetBundle_Methods
		{
			public static CachedMethod LoadAll = AssetBundle?.ClrType.CachedMethod("LoadAll", typeof(Type));

			public static CachedMethod LoadAllAssets = AssetBundle?.ClrType.CachedMethod("LoadAllAssets", typeof(Type));

			public static CachedMethod LoadFromFile = AssetBundle?.ClrType.CachedMethod("LoadFromFile", typeof(string));

			public static CachedMethod CreateFromFile = AssetBundle?.ClrType.CachedMethod("CreateFromFile", typeof(string));
		}

		public static class TextExpansion_Methods
		{
			public static CachedMethod SetMessageType = TextExpansion?.ClrType.CachedMethod("SetMessageType");

			public static CachedMethod SkipTypeWriter = TextExpansion?.ClrType.CachedMethod("SkipTypeWriter");
		}

		public static class GameObject_Methods
		{
		}

		public static class TextMesh_Methods
		{
		}

		public static class Text_Methods
		{
		}

		public static class InputField_Methods
		{
		}

		public static class TMP_Text_Methods
		{
		}

		public static class TMP_InputField_Methods
		{
		}

		public static class TextMeshPro_Methods
		{
		}

		public static class TextMeshProUGUI_Methods
		{
		}

		public static class UILabel_Methods
		{
		}

		public static class UIRect_Methods
		{
		}

		public static class SceneManager_Methods
		{
			public static readonly Action<UnityAction<Scene, LoadSceneMode>> add_sceneLoaded = (Action<UnityAction<Scene, LoadSceneMode>>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(SceneManager).GetMethod("add_sceneLoaded", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(UnityAction<Scene, LoadSceneMode>) }, null));
		}

		public static class Texture2D_Methods
		{
			public static readonly Func<Texture2D, byte[], bool> LoadImage = (Func<Texture2D, byte[], bool>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(Texture2D).GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(byte[]) }, null));

			public static readonly Func<Texture2D, byte[]> EncodeToPNG = (Func<Texture2D, byte[]>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(Texture2D).GetMethod("EncodeToPNG", BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null));
		}

		public static class ImageConversion_Methods
		{
			public static readonly Func<Texture2D, byte[], bool, bool> LoadImage = (Func<Texture2D, byte[], bool, bool>)ExpressionHelper.CreateTypedFastInvokeUnchecked(ImageConversion?.ClrType.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			}, null));

			public static readonly Func<Texture2D, byte[]> EncodeToPNG = (Func<Texture2D, byte[]>)ExpressionHelper.CreateTypedFastInvokeUnchecked(ImageConversion?.ClrType.GetMethod("EncodeToPNG", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Texture2D) }, null));
		}

		public static readonly TypeContainer UILabel = FindType("UILabel");

		public static readonly TypeContainer UIWidget = FindType("UIWidget");

		public static readonly TypeContainer UIAtlas = FindType("UIAtlas");

		public static readonly TypeContainer UISprite = FindType("UISprite");

		public static readonly TypeContainer UITexture = FindType("UITexture");

		public static readonly TypeContainer UI2DSprite = FindType("UI2DSprite");

		public static readonly TypeContainer UIFont = FindType("UIFont");

		public static readonly TypeContainer UIPanel = FindType("UIPanel");

		public static readonly TypeContainer UIRect = FindType("UIRect");

		public static readonly TypeContainer UIInput = FindType("UIInput");

		public static readonly TypeContainer TextField = FindType("FairyGUI.TextField");

		public static readonly TypeContainer TMP_InputField = FindType("TMPro.TMP_InputField");

		public static readonly TypeContainer TMP_Text = FindType("TMPro.TMP_Text");

		public static readonly TypeContainer TextMeshProUGUI = FindType("TMPro.TextMeshProUGUI");

		public static readonly TypeContainer TextMeshPro = FindType("TMPro.TextMeshPro");

		public static readonly TypeContainer TMP_FontAsset = FindType("TMPro.TMP_FontAsset");

		public static readonly TypeContainer TMP_Settings = FindType("TMPro.TMP_Settings");

		public static readonly TypeContainer GameObject = FindType("UnityEngine.GameObject");

		public static readonly TypeContainer Transform = FindType("UnityEngine.Transform");

		public static readonly TypeContainer TextMesh = FindType("UnityEngine.TextMesh");

		public static readonly TypeContainer Text = FindType("UnityEngine.UI.Text");

		public static readonly TypeContainer Image = FindType("UnityEngine.UI.Image");

		public static readonly TypeContainer RawImage = FindType("UnityEngine.UI.RawImage");

		public static readonly TypeContainer MaskableGraphic = FindType("UnityEngine.UI.MaskableGraphic");

		public static readonly TypeContainer Graphic = FindType("UnityEngine.UI.Graphic");

		public static readonly TypeContainer GUIContent = FindType("UnityEngine.GUIContent");

		public static readonly TypeContainer WWW = FindType("UnityEngine.WWW");

		public static readonly TypeContainer InputField = FindType("UnityEngine.UI.InputField");

		public static readonly TypeContainer GUI = FindType("UnityEngine.GUI");

		public static readonly TypeContainer GUI_ToolbarButtonSize = FindType("UnityEngine.GUI+ToolbarButtonSize");

		public static readonly TypeContainer GUIStyle = FindType("UnityEngine.GUIStyle");

		public static readonly TypeContainer ImageConversion = FindType("UnityEngine.ImageConversion");

		public static readonly TypeContainer Texture2D = FindType("UnityEngine.Texture2D");

		public static readonly TypeContainer Texture = FindType("UnityEngine.Texture");

		public static readonly TypeContainer SpriteRenderer = FindType("UnityEngine.SpriteRenderer");

		public static readonly TypeContainer Sprite = FindType("UnityEngine.Sprite");

		public static readonly TypeContainer Object = FindType("UnityEngine.Object");

		public static readonly TypeContainer TextEditor = FindType("UnityEngine.TextEditor");

		public static readonly TypeContainer CustomYieldInstruction = FindType("UnityEngine.CustomYieldInstruction");

		public static readonly TypeContainer SceneManager = FindType("UnityEngine.SceneManagement.SceneManager");

		public static readonly TypeContainer Scene = FindType("UnityEngine.SceneManagement.Scene");

		public static readonly TypeContainer UnityEventBase = FindType("UnityEngine.Events.UnityEventBase");

		public static readonly TypeContainer BaseInvokableCall = FindType("UnityEngine.Events.BaseInvokableCall");

		public static readonly TypeContainer Font = FindType("UnityEngine.Font");

		public static readonly TypeContainer WaitForSecondsRealtime = FindType("UnityEngine.WaitForSecondsRealtime");

		public static readonly TypeContainer Input = FindType("UnityEngine.Input");

		public static readonly TypeContainer AssetBundleCreateRequest = FindType("UnityEngine.AssetBundleCreateRequest");

		public static readonly TypeContainer AssetBundle = FindType("UnityEngine.AssetBundle");

		public static readonly TypeContainer AssetBundleRequest = FindType("UnityEngine.AssetBundleRequest");

		public static readonly TypeContainer Resources = FindType("UnityEngine.Resources");

		public static readonly TypeContainer AsyncOperation = FindType("UnityEngine.AsyncOperation");

		public static readonly TypeContainer TextAsset = FindType("UnityEngine.TextAsset");

		public static readonly Type HorizontalWrapMode = FindClrType("UnityEngine.HorizontalWrapMode");

		public static readonly Type TextOverflowModes = FindClrType("TMPro.TextOverflowModes");

		public static readonly Type TextAlignmentOptions = FindClrType("TMPro.TextAlignmentOptions");

		public static readonly Type VerticalWrapMode = FindClrType("UnityEngine.VerticalWrapMode");

		public static readonly TypeContainer TextExpansion = FindType("UnityEngine.UI.TextExpansion");

		public static readonly TypeContainer Typewriter = FindType("Typewriter");

		public static readonly TypeContainer UguiNovelText = FindType("Utage.UguiNovelText");

		public static readonly TypeContainer UguiNovelTextGenerator = FindType("Utage.UguiNovelTextGenerator");

		public static readonly TypeContainer AdvEngine = FindType("Utage.AdvEngine");

		public static readonly TypeContainer AdvPage = FindType("Utage.AdvPage");

		public static readonly TypeContainer TextData = FindType("Utage.TextData");

		public static readonly TypeContainer AdvUguiMessageWindow = FindType("Utage.AdvUguiMessageWindow") ?? FindType("AdvUguiMessageWindow");

		public static readonly TypeContainer AdvUiMessageWindow = FindType("AdvUiMessageWindow");

		public static readonly TypeContainer AdvDataManager = FindType("Utage.AdvDataManager");

		public static readonly TypeContainer AdvScenarioData = FindType("Utage.AdvScenarioData");

		public static readonly TypeContainer AdvScenarioLabelData = FindType("Utage.AdvScenarioLabelData");

		public static readonly TypeContainer DicingTextures = FindType("Utage.DicingTextures");

		public static readonly TypeContainer DicingImage = FindType("Utage.DicingImage");

		public static readonly TypeContainer TextArea2D = FindType("Utage.TextArea2D");

		public static readonly TypeContainer CubismRenderer = FindType("Live2D.Cubism.Rendering.CubismRenderer");

		public static readonly TypeContainer TextWindow = FindType("Assets.System.Text.TextWindow");

		private static Type FindClrType(string name)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(name, throwOnError: false);
					if ((object)type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static TypeContainer FindType(string name)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(name, throwOnError: false);
					if ((object)type != null)
					{
						return new TypeContainer(type);
					}
				}
				catch
				{
				}
			}
			return null;
		}
	}
}

BepInEx/plugins/LCUA_Patcher.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Patchers;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("LCUA_Patcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("LCUA Patcher")]
[assembly: AssemblyFileVersion("2.3.0.0")]
[assembly: AssemblyInformationalVersion("2.3.0+8c5dbbf26a7344d75eda0342b18b9f55e4688821")]
[assembly: AssemblyProduct("LCUA_Patcher")]
[assembly: AssemblyTitle("LCUA_Patcher")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.3.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal class BundleLoader
{
	public static List<string> bundleTextureNames;

	public static List<string> changedTextureNames;

	public static AssetBundle LCUABundle;

	public static bool TryLoadBundle()
	{
		try
		{
			string text = Path.Combine(Paths.BepInExRootPath, "Bundles", "lcua.bundle");
			if (!File.Exists(text))
			{
				return false;
			}
			LCUABundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)LCUABundle != (Object)null)
			{
				bundleTextureNames = (from fullPath in LCUABundle.GetAllAssetNames()
					select Path.GetFileNameWithoutExtension(fullPath)).ToList();
				changedTextureNames = new List<string>();
			}
			return true;
		}
		catch (Exception value)
		{
			Console.WriteLine(value);
			return false;
		}
	}

	public static void ClearChangedTextures()
	{
		changedTextureNames.Clear();
	}

	public static bool TextureFilter(string textureName)
	{
		if (bundleTextureNames.Contains(textureName.ToLower()))
		{
			return !changedTextureNames.Contains(textureName);
		}
		return false;
	}

	public static bool TrySetTexture(ref Texture2D originalTexture)
	{
		try
		{
			string name = ((Object)originalTexture).name;
			if (name == "" || !bundleTextureNames.Contains(name.ToLower()) || changedTextureNames.Contains(name))
			{
				return false;
			}
			Texture2D val = LCUABundle.LoadAsset<Texture2D>(name);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			ImageConversion.LoadImage(originalTexture, ImageConversion.EncodeToPNG(val));
			((Texture)originalTexture).mipMapBias = -1f;
			changedTextureNames.Add(name);
			return true;
		}
		catch (Exception value)
		{
			Console.WriteLine(value);
			return false;
		}
	}
}
internal class Dictionaries
{
	public static readonly Dictionary<string, string> Nodes = new Dictionary<string, string>
	{
		{ "0_Bestiary", "BESTIARY\n\nЩоб отримати доступ до файлу істоти, введіть \"INFO\" після його імені.\n---------------------------------\n\n[currentScannedEnemiesList]" },
		{ "0_StoreHub", "Ласкаво просимо до магазину компанії. \nВикористовуйте слова BUY та INFO на будь-якій позиції. \nЗамовляйте спорядження оптом, вказуючи кількість після назви товару.\n____________________________\n\n[buyableItemsList]\n\nПОКРАЩЕННЯ КОРАБЛЮ:\n* Loud horn   //    Ціна: $100\n* Signal Translator    //    Ціна: $255\n* Teleporter    //    Ціна: $375\n* Inverse Teleporter    //    Ціна: $425\n\nВибір декору кораблів змінюється з кожною квотою. Не забудьте перевірити наступного тижня:\n------------------------------\n[unlockablesSelectionList]" },
		{ "AlreadyOnThisPlanet", "Корабель вже знаходить на орбіті цієї планети." },
		{ "AlreadyUnlocked", "Цю річ вже було розблоковано для вашого кораблю!" },
		{ "CancelPurchase", "Замовлення скасовано." },
		{ "CancelRoute", "Маршрут скасовано." },
		{ "CannotAfford", "Ви не можете дозволити собі ці предмети!\nВаш баланс становить [playerCredits]. Загальна вартість цих предметів становить [totalCost]." },
		{ "CompanyMoonRouteConfirm", "Автопілот прокладає маршрут до будівлі компанії.\n\nПриємного польоту." },
		{ "CompanyMoonroute", "Компанія купує за [companyBuyingPercent] від вартості. \n\nЧи хочете ви направити автопілот до будівлі компанії?\n\n\nПідтвердіть CONFIRM або DENY." },
		{ "ConfirmEject", "Ви хочете катапультувати всіх членів екіпажу, включаючи себе? Ви повинні знаходитися в орбіті навколо місяця.\n\nПідтвердіть CONFIRM або DENY." },
		{ "DenyEject", "Скасовано послідовність катапультування." },
		{ "EjectPlayers", "Катапультуємо екіпаж." },
		{ "FlashedRadarBooster", "Підсвічено підсилювач радара." },
		{ "HelpCommands", ">MOONS\nПереглянути список супутників, до яких автопілот може прокласти маршрут.\n\n>STORE\nПереглянути добірку корисних речей у магазині компанії.\n\n>BESTIARY\nПереглянути список сканованих диких істот планет.\n\n>STORAGE\nОтримати доступ до об'єктів у сховищі.\n\n>OTHER\nПереглянути список інших команд.\n\n[numberOfItemsOnRoute]" },
		{ "ItemsInStorage", "Переміщуючи об'єкт за допомогою B, натисніть X, щоб перемістити його в сховище. Ви можете забрати його зі сховища в цьому меню.\n\nОсь що зберігається на складі:\n\n[storedUnlockablesList]" },
		{ "MoonsCatalogue", "Ласкаво просимо до каталогу екзомісяців.\nЩоб прокласти маршрут автопілота до супутника, використовуйте слово ROUTE.\nЩоб дізнатися інформацію про будь-який супутник, використовуйте слово INFO.\n____________________________\n\n* The Company building   //   Купує за [companyBuyingPercent] від вартості.\n\n* Experimentation [planetTime]\n* Assurance [planetTime]\n* Vow [planetTime]\n\n* Offense [planetTime]\n* March [planetTime]\n* Adamance [planetTime]\n\n* Rend [planetTime]\n* Dine [planetTime]\n* Titan [planetTime]" },
		{ "OtherCommands", "Інші команди:\n\n>VIEW MONITOR\nУвімкути ТА вимкнути камеру мапи на головному моніторі.\n\n>SWITCH [Ім'я гравця]\nПереключити перегляд на гравця на головному моніторі.\n\n>PING [Назва підсилювача радару]\nВключити звук шуму на підсилювачі радару.\n\n>TRANSMIT [message]\nПередати повідомлення за допомогою перекладача сигналів.\n\n>SCAN\nСканує кількість брухту, що залишилися на планеті." },
		{ "ParserError1", "[Немає ніякої дії, що супроводжувала б це слово.]" },
		{ "ParserError2", "[Немає жодного об'єкту, пов'язаного з дією, або ваше слово було введено неправильно чи не існує.]" },
		{ "ParserError3", "[Ця дія несумісна з цим об'єктом.]" },
		{ "SendSignalTranslator", "Передачу відправлено." },
		{ "Start", "Ласкаво просимо до FORTUNE-9 OS\n\tНадано з люб'язності компанії\n\n[currentDayUkrainian].\n\nНапишіть \"Help\" для списку команд." },
		{ "StartFirstTime", "__      _____ _    ___ ___  __  __ ___ \r\n \\ \\    / | __| |  / __/ _ \\|  \\/  | __|\r\n  \\ \\/\\/ /| _|| |_| (_| (_) | |\\/| | _| \r\n   \\_/\\_/ |___|____\\___\\___/|_|  |_|___|\r\n\n\nЛаскаво просимо до FORTUNE-9 OS\n\tНадано з люб'язності компанії\n\nНапишіть \"Help\" для списку команд." },
		{ "SwitchRadarCamPlayer 1", "Перемикання перегляду гравця." },
		{ "SwitchRadarCamPlayer", "Перемикання перегляду гравця." },
		{ "SwitchedCam", "Перемкнуто радар на гравця." },
		{ "ViewInsideShipCam 1", "Перемикання камери радару" },
		{ "WelcomeNode", "BG IG, Системно-дієвий союзник\nАвторське право (C) 2084-2108, Halden Electronics Inc.\nНадано з люб'язності компанії.\n\n\n\nBios для FORTUNE-9 87.7/10MHZ SYSTEM\n\nПоточна дата - Вт 3-7-2532\nПоточний час - 8:03:32.15\n\nБудь ласка, введіть улюблену тварину: " },
		{ "WelcomeNode2", "\nБудь ласка, опишіть свою роль у команді: " },
		{ "BaboonHawkFile", "Бабуїновий яструб (Baboon hawk)\n\nРівень небезпеки Сіґурда: 75%\n\nНаукова назва: Papio-volturius\nБабуїнові яструби - це примати родини Cercopithecidae. Вони горбаті, але в середньому досягають до 2.43 метрів стоячи. Їхні голови кістляві, з птахоподібним дзьобом і довгими рогами, які вони використовують як шампури для поранення та харчування здобиччю. Їх роги складаються з кератину, на відміну від кістки, з якої складається решта їхнього черепа, і не містять ні нервів, ні кровоносних судин. В результаті бабунові яструби часто можуть ламати свої роги від прикладеного ними тиску, але потім повністю відновлювати їх протягом того ж сезону. Бабунові яструби частково заборговані своєю назвою їхнім великим крилам, які ніколи не зможуть підняти їхню велику масу тіла і використовуються замість цього для залякування та захисту від негоди.\n\nНайбільша спостережена зграя бабунових яструбів складалася з 18 особин. Вони не мають чіткої території, і багато їхньої поведінки мотивовано залякуванням та демонстрацією. Вони можуть стати колекціонерами, використовуючи будь-який яскравий чи кольоровий предмет для позначення своєї території. Як самотні розвідники, бабунові яструби, як правило, сором'язливі і не будуть нападати, якщо їх не спровокувати. У великій кількості вони можуть стати великою загрозою; триматись близько до інших і створювати враження небезпеки - це найкращі способи запобігти нападу. Вони віддають перевагу меншим ссавцям, але, будучи в безвихідному становищі, вони відомі використовуванням своєї кількості для нападу на тварин навіть удвічі більших за них, наприклад, на безоких собак. ВОНИ ВКРАЛИ М О Ї ОГІРКИ" },
		{ "BrackenFile", "Бракен (Bracken) — також відомий як Людина-Квітка!\n\nце була людина-квітка, ви не можете сказати інкше! я хотів знайти його тіло .Ви були боягузами\n\nНаукова назва: Rapax-folium\nЄ дискусія щодо роду, до якого належить Бракен. Це двоногий хребетний із шкірою червоного кольору та текстурою буряка. Назва була створена через листя що немовби виростає з його верхнього хребта. Вважається, що це призначено для загрози, однак про конкретику поведінки бракена мало відомо через його хижість і низьку чисельність.\n\nМи трохи знаємо з записів від експертів з дикої природи, які зустрічали його. він самотній мисливець з високим інтелектом. Його поведінка може здатися відстороненою; він проявляє високу агресію навіть коли не спровоковано, але швидко відступає при зоровому контакті. Однак бракени відомі тим, що підвищують свою ворожість коли загнано у кут, або просто коли за ними спостерігають тривалий час. Тому рекомендується тримати їх під прицілом, але не витріщатись. Жодних екземплярів не було зібрано мертвими або живими. Існує теорія, що після смерті їхні тіла проходять швидкий процес розкладання, який є унікальним і відрізняється від інших великих тварин." },
		{ "BunkerSpiderFile", "Бункерні Павуки (Bunker Spiders)\n\nРівень небезпеки Сіґурда: 20%\n\nНаукова назва: Mutinum-ficedula\nБункерні павуки роду Theraphosa є найбільшими арахнідами, знайденими у Тистельній Туманності і другими за розміром, що коли-небудь відкриті. Вважається, що вони еволюціонували для полювання на великих ссавців протягом кількох жалюгідних сотень років, після того як Корабель здійснив свою подорож навколо Тистельної Туманності. (Див. також: Припущення про Збільшення Видового Різноманіття Навколо Згасаючих Туманностей)\n\nБункерні павуки виробляють шовк і кладуть його навколо обраної місцевості для гніздування, потім чекають коли на нього натраплять. Їх можна побачити, чекаючих на стінах, часто над дверима, де здобич може увійти не підозрюючи. Якщо ви зустрінете павука у \"непідготованому\" стані, він може завмерти, як захисна реакція. У цьому випадку краще залишити його в спокої. Якщо бункерний павук реагує агресивно, найкраще не боротися звичайними інструментами. Вони використовують свої пастки з павутини для компенсації свого досить повільного руху, тому слід звертати увагу на своє оточення. Їх павутиння можна легко розірвати будь-яким тупим інструментом.\n\nБункерні павуки можуть становити велику небезпеку для людей, особливо для урбаністичних дослідників, без великої користі для їхніх екосистем. Наказ знищувати їх при першій можливості був неформально узгоджений між багатьма державами, де зустрічаються Бункерні павуки, і на даний момент схвалений Міжнародним Товариством Охорони Дикої Природи з 10/6/2497." },
		{ "CircuitBeeFile", "Електричні Бджілки (Circuit Bees)\n\nРівень небезпеки Сіґурда: 90%\n\nНаукова назва: Crabro-coruscus\nЕлектрична бджола, також відома як червона бджола, є зграйовою летючою комахою роду Apis, нащадком медоносної бджоли. Їхню зовнішність легко розпізнати за їхніми волосяними, червоними тілами та двома комплектами крил. Як їхні предки, їх відомо своєрідною соціальною а також бджолячою поведінкою, великим розміром колоній, будівництвом воскових гнізд, які вони використовують для зберігання меду, та їх важливою роллю в запиленні. На відміну від медоносної бджоли, яка часто обирає високі місця, такі як дерева, для будівництва свого вулика, червоні бджоли створюють свої вулики на землі.\n\nЧервоні бджоли високо обороноздатні. Вони вилітають з гнізда, щоб атакувати будь-яку істоту, яка наближається на кілька метрів, залишаючи тільки королеву та трутнів . Ця смілива поведінка включається за допомогою їх найхарактернішої навички - їх електростатичного заряду. Червоні бджоли виробляють тертя в повітрі. Вони також створюють тертя, теруться двома парами крил одне з іншим і трутся один об одного, перебуваючи в вулику. Феномен, що дозволяє їм створювати такий великий електричний заряд порівняно з медоносною бджолою, ще досліджується, оскільки вони генерують сильне електричне поле, коли панікують чи розлючуються. Ця здатність особливо корисна для них навколо води.\n\n\nКраще тримати відстань. Якщо вулики червоних бджіл вкрадено, рої червоних бджіл розпочнуть наступ, під час якого вони атакуватимуть будь-яку живу істоту. Ця руйнівна поведінка триватиме, поки вони не знайдуть вулик або повністю не виснажать себе, що може зайняти години або дні. Вони відомі тим що можуть залишати поля тіл дрібних гризунів, комах, і навіть деяких більших ссавців, у рідкісних випадках можуть спричиняти пожежі. Переваги та недоліки їхніх впливів на екосистеми сильно обговорюються - непереможний Сіґурд" },
		{ "CoilHeadFile", "ПРУЖИНО-ГОЛОВІ (COIL-HEADS)\n\nРівень небезпеки Сіґурда: 80%\n\nНаукова назва: Vir colligerus\nVir colligerus, або у народі відомі як Пружиноголові, не були докладно вивчені через їхню надзвичайну непередбачуваність та небезпечні властивості. Відомо, що вони можуть загорятися, коли їх розчленовують або навіть деактивують, і вони містять небезпечно високі рівні радіоактивних часток. Через цю, та інші причини існує припущення, що вони були створені як біологічна зброя для війни, хоча це не було доведено.\n\nЗовнішній вигляд Пружиноголових описують як кровавий манекен з головою, котра з'єднаною пружиною. Їхня визначна поведінкова особливість полягає в тому, що вони завмирають коли на них дивляться. Однак це не здається жорстким правилом. Коли вони зіштовхуються з гучним або яскравим світлом, іноді здається, що вони входять у довгий режим перезавантаження.\nПросто гляньте на инх або скористайтеся гранатою! - Сіґурд" },
		{ "EarthLeviathanFile", "Земний Левіафан (Earth Leviathan)\n\nРівень небезпеки Сіґурда: 2%, бо вони не можуть сховатися від каемр корабля!!\n\nНаукова назва: Hemibdella-gigantis\nШанобливо названий Земний Левіафан, з родини Пісциколідів, є одним із найбільших безхребетних, знайдених навколо Тистельної Туманності. Нікому ще не вдалося їх захопити, тому про їхню біологію відомо небагато.\n\nЗдається, вони ведуть себе як хижаки. Припускають, що вони можуть закопатися аж на 40 метрів під землю, судячи з неймовірних тунелів, які вони залишають позаду. Вони можуть виявляти навіть найменші вібрації, саме з цього приводу не рекомендується завмирати якщо вони поруч; це міф. Замість цього, якщо ви чуєте, що вони копаються, тікайте щодуху." },
		{ "EyelessDogFile", "БЕЗОКИЙ ПЕС (EYELESS DOG)\n\nНаукова назва: Leo caecus\nВеликий ссавець класу Saeptivus. Вони соціальні істоти, тому полюють в дуже великих зграях. Їх також називають \"дихаючими левами\" через їхній впізнаваний звук і великі роти. Вони є витривалими мисливцями, і намагаються компенсувати відсутність зору своїм слухом. Існує популярний міф, що вони часто плутають звуки свого власного виду зі своєю здобиччю, влаштовуючи сутички всередині зграї.\n\nЇхня поведінка унікальна, в порівнянні з іншими зграями, оскільки вони схильні розсіюватися щоб пройти великі відстані. Коли сліпий пес знаходить здобич, він гарчить, щоб попередити інших в близькому оточенні, які також подають сигнал, іноді спричиняючи своєрідну ланцюгову реакцію. Безокі пси можуть бути небезпечними в зграях. Проте вони характерно незграбні, роблячи припущення про точне розташування своєї здобичі, які часто є невірними." },
		{ "ForestKeeperFile", "ЛІСНИК (FOREST KEEPER)\n\nРівень небезпеки Сіґурда: 50%\n\nНаукова назва: Satyrid-proceritas\nВважається, що вони мають спільного предка з rapax-folium, цих велетнів часто називають Лісниками через їхнє середовище, в яких вони часто знаходяться. Їхні тіла мають родинки на передній і задній частині, що імітують очі -- ця риса є корисною особливо в період молодості, оскільки вони не дуже рухливі. Їхня шкіра є унікальною, щільний матеріал, який затвердіває протягом їхнього життя; великі шипи та випуклості по всьому тілу формуються в результаті старіння.\n\nГоворять, що Лісники проявляють допитливу поведінку, схожу на поведінку людської дитини віком 5 або 6 років. Вони з'їдять все, що їм виявиться захоплюючим. Лісники, фактично, не потребують класти щось у свій рот, і існує теорія, що їхнім основним джерелом енергії є процес, схожий на фотосинтез. Проте, це робить їх відносно небезпечними для спостереження. Вони можуть бачити на великі відстані, тому важливо не висовуватися і використовувати укриття. Вони не можуть проникати в малі простори, і як правило, не є руйнівними, тому тримайтесь близько до укриттів або навісів." },
		{ "HoardingBugFile", "ЖУК ЗБИРАЧ (HOARDING BUG)\n\nРівень небезпеки Сіґурда: 0%\n\nНаукова назва: Linepithema-crassus\nЖук збирач (з ряду Hymenoptera) - це великі, соціальні комахи. Часто проживають самі, але бувають випадки коли вони можуть розділити гніздо з представниками свого виду. Середній зріст цих комах становить 90 сантиметрів, з кулястими тілами. Тонкість їхньої рідини та крові та матеріал їхніх панцирів сприяє їхній низькій вазі, роблячи їх здатними до польоту з їхніми мембранними крилами. Це також робить їхні тіла трохи прозорими.\n\nЖуки збирачі отримали свою назву через свою територіальну природу. Як тільки вони вибрали місце для свого гнізда, вони будуть намагатися прикрасити його будь-якими речами, які вони можуть знайти, і будуть захищати їх як частину гнізда. Жуки збирачі не настільки небезпечні самі по собі, як у великих вуликах. Однак, якщо залишити їх у спокої, Жуки Збирачі дивовижно нейтральні і не становлять великої небезпеки. мМи любимо цих дурних жуків-обіймашок.!! - це будла нотатка від непідкорного Сіґурда" },
		{ "HygrodereFile", "ГІГРОДЕРА (HYGRODERE)\n\nРівень небезпеки Сіґурда: 0%, якщо ви швидші за равлика!\n\nНаукова назва: Hygrodere\nЕукаріотичний організм, класифікований у парафілетичній групі Prostita. З неймовірною швидкістю розмноження, ці малі організми можуть помножитися на мільйони. Гігродери рідко розділяються на частини, натомість, вони вибирають сформуватись у великі, в'язкі маси, які можуть займати багато простору і ставати небезпечними для обробки, вимагаючи великих інструментів або приманок для переміщення.\n\nГігродер приваблюють тепло та кисень, вони можуть виявляти його, здавалося б, звідусіль. Немає практично ніяких органічних речовин, які вони не можуть перетворити на власну масу. Не знайдено нічого, що може їх отруїти. Постійно змінюючи себе, вони можуть існувати сотні тисяч років. Якщо ви коли-небудь опинитеся в глухому куті, знайдіть високий об'єкт, на якому можна стояти; гігродерам важко лазити. у них чудовий смак! тому що я подружився з одним з них якимось чином,, і ми думаємо що це через мою музику." },
		{ "JesterFile", "ЖАРТІВНИК (JESTER)\n\nРівень небезпеки Сіґурда: 90% Тікайт езвідти, поки він не розізлиться!! Ви не зможете сховатись від нього, просто евакуюйтесь\n\nНаукова назва: БОЖЕВІЛІНУС ШТУКУС\nНЕМАЄ ЖОДНИХ ЧОРТОВИХ НАУКОВИХ ЗАПИСІВ! удачі, ви знаєте стільки ж, скільки і ми. ми просто називаємо його жартівником" },
		{ "LassoManFile", "ЛАСО (LASSO)\n\nРівень небезпеки Сіґурда: 30%, але воно мене трохи лякає\n\nНаукова назва:" },
		{ "LocustFile", "Мандрівна Сарана (Roaming Locusts)\n\nРівень небезпеки Сіґурда: 0%\n\nНаукова назва: Anacridium-vega\n\nВідомі як мандрівна сарана, це вид коників. На відміну від деяких видів, які більш схильні стрибати чи літати, мандрівна сарана практично ніколи не приземляються і тримаються близько один до одного, навіть коли їх небагато. Вони швидко розсіються, якщо хижак порушить їхню групу але їх дуже сильно приваблює світло." },
		{ "ManticoilFile", "Мантикоїли (Manticoils)\n\nРівень небезпеки Сіґурда: 0%\n\nНаукова назва: Quadrupes-manta\nМантикоїл - це птах з родини Corvidae. Їх тіла досить великі порівняно з їхніми ранніми нащадками, а їх розмах крил коливається від 1.39 до 1.62 метрів. Їхнею найвизначнішою ознакою є їхні чотири крила. Задні крила в основному використовуються для стабілізації на низькій швидкості, тоді як передні два крила створюють більшість підйому. Їхні круглі тіла вражають своїм яскраво-жовтим окрасом, з чорними контурами чи смугами вздовж основних (задніх) пір'їн.\n\nМантікоїли в основному харчуються дрібними комахами, але також можуть полювати на дрібних гризунів. Вони високоінтелектуальні та соціальні. Вони не становлять великої загрози і, як правило, мають загально пасивне відношення щодо людей, хоча вони можуть передавати Сказ, Рубенхлорію і вірус Пітта." },
		{ "NutcrackerFile", "Лускунчик\n\nОхоронці дому.\n\nВони спостерігають одним невтомним оком, яке відчуває лише рух; воно пам'ятає останню істоту, яку помітило, незалежно від того, рухається вона чи ні." },
		{ "PufferFile", "Спорова ящірка (Spore lizard)\n\nРівень небезпеки Сіґурда: я, не знаю, можливо 5% я просто ненавиджу цього товстоногого маленького гівн юка\n\nНаукова назва: Lacerta-glomerorum\nУ повсякденній мові їх називають пухляками або споровими ящірками, Lacerta-glomerorum (з родини Alligatoridae) є одними з найбільших і найважчих плазунів. Незважаючи на їхні великі роти, вони є травоїдними і не мають міцного укусу. Вважається, що лампочки на їхніх хвостах виділяють речовину, яка привертає та прискорює ріст грибного виду Lycoperdon perlatum, який вони потім можуть потрясти, щоб виділити спори, як захисний механізм — унікальний приклад мутуалістичних симбіотичних відносин.\n\nСпорові ящірки мають дуже сором'язливий темперамент, намагаючись уникнути будь-якого зіткнення, якщо це можливо. Якщо їхні спроби залякування виявились не ефективними, вони можуть спробувати атакувати, тому не рекомендується заганяти їх у кут чи ганятися за ними. Є історичні записи про те, що спорові ящірки були щонайменше частково одомашнені сотні років тому, проте це намагання зупинилося через ініціативу збирати їхні хвости через їхні лікарські властивості." },
		{ "SnarefleaFile", "БЛОХА-ПАСТКА (SNARE FLEA)\n\nРівень небезпеки Сіґурда: 30%\n\nНаукова назва: Dolus-scolopendra.  \nДуже великий членистоногий класу Chilopoda. Його тіло виробляє шовк, який він в основному використовує, щоб просунутись до місць, де він прихований. Його екзоскелет дещо крихкий, і вони можуть померти від падіння з висоти. Блоха-Пастка не виробляє отрути, та немає сильного укусу. Вона компенсує цю слабкість здатністю стискати себе навколо великої здобичі, щоб задушити.\n\nБлоха-Пастка проживає в темних, теплих місцях. Вона не може вижити при низьких температурах і загалом уникає відкритого повітря та сонця витягуйте цих щурів з їх нори або добрчяе їх побийте! думаю їхні внутрішності можуть стати смачним мілкшейком,," },
		{ "ThumperFile", "Стукачі (Thumpers)\n\nРівень небезпеки Сіґурда: 90%\n\nНаукова назва: Pistris-saevus\nПоловинки, або Стукачі - це дуже агресивний вид хижаків з класу Chondrichthyes. Їхні скелети є хрящовими, надаючи їх тілам еластичність і гумовість. Їхня назва походить з того факту, що їм доводиться з'їдати свої задні ноги, щоб вибратись зі шкаралупи свого вилупленого яйця; почнемо з того, що їхні задні ноги майже нефункціональні. Їхні руки, або ж передні ноги, дуже сильні, тому інколи вони використовують їх для того, щоб топтати здобич. Вони можуть набирати великі швидкості по прямій лінії.\n\nВони безпосередні мисливці, які зазвичай знаходяться на вершині свого харчового ланцюга. Головні їхні слабкості - це їхній інтелект і повна відсутність слуху. Якщо ви натрапите на Стукача, вашим найкращим способом виживання буде вийти з його поля зору, оскільки він повільніший на поворотах і не може легко відстежувати здобич.\n\nЧерез швидку і нестабільну еволюцію цього виду, деякі теоретики вважають, що Стукачі - це один із прикладів збільшеної кількості мутацій, що викликають вищі рівні видової спеціації на планетах навколо Тистельної Туманності." },
		{ "BushWolfFile", "Лис викрадач (Kidnapper fox)\n\nРівень небезпеки Сіґурда: 80% ХОРОША РОБОТА він отримує A+ в шоколі виродків\n\nНаукова назва: Vulpes raptor\nВеличезний ссавець родини Canidae, Лис викрадач має багато унікальних біологічних рис. Дві з яких є його горизонтальна щелепа і унікальна форма черепа яка надає йому велику силу укусу, і його довгий, як у жаби язик який може досягти довжини вдвічі більшу за його вертляве тіло. Вони є самотніми хижаками і мають одного партнера на все життя.\n\nЛиси викрадачі мають дуже довгу й пухнасту шию і хвіст з червонуватою окрасою, який добре зливається з представниками Червоної папороті, де вони практично завжди можуть бути помічені ховаючись і вичікуючи здобич. Лис викрадач та Червона папороть разом утворюють одну з найвідоміших і унікальних симбіозних відносин серед двох інвазивних видів. Разом вони продовжують розповсюджуватись по планетарній системі, приховуючись на великих космічних кораблях. За винятком кількох природніх заповідників, ITDA видали наказ вбивати на місці такі види як Лис викрадач та Червона папороть через їх вплив на екосистеми.\n\nЛис викрадач дістав свою назву через свою агресивну, але водночас сором'язливу територіальну поведінку, віддаючи перевагу вбивати своїх жертв у місцях де їх не видно, часто поряд із Червоною папороттю. Зазвичай вони обирають бути тихими, вичікуючи поки їхня здобич сама їх знайде. Але якщо очікування буде занадто довгим, вони будуть використовувати свої довгі, цупкі язики щоб схопити своїх жертв навіть на великих відстанях. Якщо поблизу вас є Червона папороть вам варто тримати з собою зброю і не відставати від інших членів екіпажу; їх язики достатньо м'які і тендітні, тому вони можуть бути легко вражені, заставляючи їх припинити напад. На сьогоднішній день нараховується всього декілька смертей на рік через Лисів викрадачів, і більшість жертв це діти без нагляду або дорослі які подорожують наодинці.\n\n" },
		{ "ClaySurgeonFile", "Барбер (Barber)\n\nМені наснився Барбер\nОдного дня він перуку мені склав\nБо для стрижки ножиці завеликі мав\n\n" },
		{ "RadMechFile", "СТАРІ ПТАХИ (OLD BIRDS)\n\n Стара птаха це автономна, воєнна зброя наступального типу з людським дизайном. Висотою в 5.8 метрів і 3.4 метрів в ширину, її дві найбільш визначні візуальні особливості це прожектор розташований на голові, який здатний випромінювати до 100,000 люменів, і акустичний пристрій дальнього радіусу дії розташований на грудях, який інколи можуть називати звуковою гарматою. Також є додаткові динаміки на його плечах які викорстовуються для трансляції звуку на великі відстані. Ліва рука Старого птаха це кіготь, а його права рука це насадка, яка здатна запускати ракетні снаряди і підпалювати речі дуже гарячим полум'ям з близької відстані. Старі птахи це одна з перших екстра-орбітальних зброй яку почали використовувати та массово виготовляти.\r\n Суперечки на рахунок того, хто ж розробив Старих птахів існували ще з моменту їх першого появлення\n\nДизайн Старого птаха, аж до загартування металів, здається, мав мету приховати його походження. Його назвали \"ходячий лист викупу.\" \r\n Ноги Старого птаха функціонують як ракети, що дозволяє їм подорожувати на великі відстані і з легкістю знаходити ціль. Але скоріш за все, ця фукнкція існує для того, щоб допомагати їм покидати та повератись на орбіту. Матеріал та паливо, на які покладаються Старі птахи, схожий на ті, що використовували для пасажирських космічних кораблів приблизно з 2130.\r\nКоли Старі птахи приземляються на обрану планету, вони залишаються там назавжди. Хоча вони часто мають достатньо палива на більш ніж одну подорож, у їхніх програмі не було виявлено поведінки, яка б натякала, що вони можуть \"мігрувати\". Проте, існують непідтвердженні свідчення про автономне подорожування Старих птахів до нової планети після сотень років бездіяльності. \r\n Історично Старих птахів називали \"Ал\", ця назва походить з кодового ім'я яке було надано їм англійськими військовими, \"A16-L31\". Проте, в 2384, пісня \"Старі птахи\" випущена як культовий хіт, пост-панк проектом Під Реморою; всього через три роки, в його найвідомішій роботі з тією ж назвою, вуличний артист Ленд Ейрі зафіксував політ та приземлення автоматонів між планетами в порядку схожому на зграю гусей--загалом це вважають одним з найбільш знакових і впливових образів сучасної культури, чим закріпив за собою сучасне прізвисько.\r\n В 2356, Ембріон-5 було класифіковано як Засуджений для цілей подорожі або поселення на човні; Старі птахи були описані свідками як \"вистилаючі горизонт\". Хоча по сьогоднішній день вони здаються непрацюючими, є великий ризик, що багато з них до сих пір у сплячому режимі, тому ця планета скоріш за все залишить свій статус. Маленький місяць скоріш за все був використаний як полігон для випробовування польоту та посадки Старих птахів.\n\n" },
		{ "VainShroudFile", "Червона папороть (Vain Shrouds)\n\nРівень небезпеки Сіґурда:  ЦЕ Н Е ІСТОТА.\n\nНаукова назва: Phlebodium ruber\nЧервона папороть, яку також часто називають просто Папороть, є видом кореневищної папороті родини поліподієвих (Polypodiaceae). В ідеальних умовах листя папороті може досягати 2.4 метри заввишки, хоча в середньому вони становлять 2.1 метри, а ширина - від 30 до 50 сантиметрів. Коріння у них надзвичайно великі, і вони дещо ДЕЩЩЩЩЩЩЩЩЩЩЩЩОколючі. \n\nЗавдяки агресивному розмноженню та значним розмірам, вони займають багато місця, ускладнюючи видимість, і їх важко позбутися. Вони витісняють здорові рослини і мають низьку поживну цінність. Вони також дуже легкозаймисті. Між папороттю та лисицею-викрадачем спостерігається тісний взаємозв'язок, і саме тому папороть становить небезпеку, коли їй дозволяють розмножуватися у великих кількостях. Через цей та інші шкідливі наслідки для багатьох екосистем і сільського господарства, папороть класифікуються як шкідливий бур'ян за класифікацією ITDA з 2147 року.\n\n\n\nПланета їхнього походження невідома, і вперше вони були зафіксовані дослідником рослин Алексом Куртом на CoRoT-7b у 2143 році, перед тим як через кілька тижнів були знайдені на іншому боці тієї ж міжпланетної системи. Поширеним міфом є те, що папороть вперше поширилась по планетах завдяки своїм легким галюциногенним властивостям при вживанні, але їх історія покрита таємницею.\n\nПРОКИНЬТЕСЯ... КОМПАН ІЯ ПРИВ'ЯЗАЛА НАСІННЯ ДО КАПСУЛИ ДОСТАВКИ,ВОНИ ПРОДАЮТЬ НАМ ЗАСІБ ДЛЯ БОРОТЬБИ З БУР'ЯНАМИ, БО ЗНАЮТЬ, ЩО ММИ НЕНАВИДИМО ЦЮ ВИШНЕВО-ЧЕРВОНУ ШТУКУ сорян за капс\n\n" },
		{ "AutopickerInfo", "Відмички розкриють ваш безмежний потенціал ефективності на роботі. Завдяки власному програмному забезпеченню зі штучним інтелектом вони відкриють вам доступ до будь-яких замкнених дверей." },
		{ "BBbulbInfo", "Найдоступніше джерело світла. Він навіть водонепроникний!" },
		{ "BoomboxInfo", "Ці ритмічні мелодії чудово піднімуть моральний дух вашої команди!" },
		{ "ExtensionLadderInfo", "Подовжена драбина може сягати дев'яти метрів! Використовуйте її, щоб піднятися на будь-яку скелю і дотягнутися до зірок! Для економії батарейок драбина автоматично складається через 18 секунд." },
		{ "FlashlightInfo", "Завдяки додатковому часу автономної роботи та ще яскравішій лампочці ваші колеги більше ніколи не залишать вас у темряві!" },
		{ "JetpackInfo", "Цей пристрій доставить вас куди завгодно! Просто використовуйте його відповідально!" },
		{ "MapperInfo", "Найдосконаліший картографічний пристрій, що використовує функцію виявлення світла і дальності, щоб надати вам огляд місцевості над головою." },
		{ "RadarInfo", "Підсилювачі радарів мають багато застосувань! \n\nВикористовуйте команду \"SWITCH\" перед назвою підсилювача радара, щоб переглянути його на головному моніторі. Він повинен бути активований.\n\nВикористовуйте команду \"PING\" перед назвою підсилювача радара, щоб відтворити спеціальний звук з пристрою." },
		{ "ShovelInfo", "Для самозахисту!" },
		{ "SignalTranslatorInfo", "Використовуйте команду \\\"transmit\\\", щоб передати текстове повідомлення всім членам екіпажу. Повідомлення не повинно перевищувати 10 літер." },
		{ "SurvivalKitInfo", "Набір для виживання включає в себе все необхідне в зручній упаковці! :\n\n* Ліхтарик  x4 \n* Рація x4\n* Лопата  x2" },
		{ "TZPChemicalInfo", "Цей безпечний і легальний препарат можна приймати, щоб побачити великі переваги для вашої роботи! Ваша здатність пересуватися на великі відстані та переносити важкі предмети буде неперевершеною! Попередження: Газ TZP може впливати на мозок при тривалому впливі. Дотримуйтесь інструкцій, що додаються до каністри. \nНе забудьте поділитися!" },
		{ "WalkieTalkieInfo", "Корисно для підтримання зв'язку! Чути інших гравців, коли рація у вашому інвентарі. Треба тримати в руці і натиснути на кнопку для передачі голосу." },
		{ "ZapGunInfo", "Найспеціалізованіший засіб самозахисту, здатний посилати до 80 000 вольт! \n\nЩоб якомога довше утримувати його націленим, тягніть пістолет з боку в бік, щоб протистояти вигину і боротися з силою електричного променя. Він може оглушити лише до тих пір, поки ви не припините подачу струму." },
		{ "AssInfo", "220-Assurance\n----------------------\n\nУМОВИ: Схожа на її планету-близнюка, 41-Experimentation, з більш нерівним і висушеним рельєфом. \n\nІСТОРІЯ: 220-Assurance значно молодша ніж її близнюк. Відкрита незадовго до 41-Experimentation.\n\nФАУНА: Невідомо" },
		{ "DineInfo", "7-Dine\n----------------------\n\nУМОВИ: Ця планета є орбітою білої карликової зірки, роблячи її незаселеною. Холодні умови. Постійні хуртовити понижують видимість.\n\nІСТОРІЯ: Декілька відомих мандрівників зникли тут без вісти, надаючи планеті певної репутації. Їхні тіла навряд чи знайдуть, враховуючи погодні умови планети.\n\nФАУНА: Дуже низький шанс існування складного життя." },
		{ "ExpInfo", "41-Experimentation\n----------------------\n\nУМОВИ: Засушливість. Низька заселеність, погіршена промисловими відходами.\n\nІСТОРІЯ: Не була відкритою протягом деякого часу через те, що була близько до орбіти газового гіганту Big Grin. Проте, схоже що її секретно використовували.\n\nФАУНА: Невідомо" },
		{ "MarchInfo", "61-March\n----------------------\n\nУМОВИ: March тримає постійсно моросящу погоду. Його рельєф є більш експансивним.\n\nІСТОРІЯ: Цей місяць є недооціненим через його близнюка, Vow. \n\nФАУНА: Невідомо" },
		{ "OffenseInfo", "21-Offense\n----------------------\n\nУМОВИ: Вважається, що ця планета відкололась від свого брата Assurance. Особливості Offense схожі, нерівний ландшафт і сухі умови, але відрізняється в його екосистемі.\n\nІСТОРІЯ: 21-Offense категоризована як місяць-астероїд, і здається що не існувала сама по собі вже більше декілька сотень років. Промислові споруди тут сильно постраждали; вважається що вони були побудовані задовго до того як 21-Offense відкололась.\n\nФАУНА: Конкурентна і загартована екосистема, яка підтримує агресивні форми життя. Мандрівники до 21-Offense мають знати, що ця плнета не для людей із слабкими нервами." },
		{ "RendInfo", "85-Rend\n----------------------\n\nУМОВИ: Ця планета є орбітою білої карликової зірки, роблячи її незаселеною. Холодні умови. Постійні хуртовити понижують видимість. \n\nІСТОРІЯ: Декілька відомих мандрівників зникли тут без вісти, надаючи планеті певної репутації. Їхні тіла навряд чи знайдуть, враховуючи погодні умови планети. \n\nФАУНА: Дуже низький шанс існування складного життя." },
		{ "TitanInfo", "8-Titan\n----------------------\n\nУМОВИ: Замерзлий, плоский ландшафт.\n\nІСТОРІЯ: Здається, що на цьому місяці видобували ресурси. Дуже просто загубитись поміж гігантського промислового комплексу. Існує багато входів до нього, які розкидані по ландщафту.\n\nФАУНА: Небезпечні істоти, які за чутками проживають у великій системі тунелів." },
		{ "VowInfo", "56-Vow\n----------------------\n\nУМОВИ: Вологі.\n\nІСТОРІЯ: Здається, що Vow був заселений декількома колоніями продовж його континенту, але на даний момент немає ніяких признаків життя, тому вони стали загадкою.\n\nФАУНА: Різноманітна, кишить рослинним життям." },
		{ "buyBoombox", "Ви збираєтесь замовити бумбокс. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyBoombox2", "Замовлено бумбокс х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyExtensLadder", "Ви збираєтесь замовити подовжену драбину. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyExtensLadder2", "Замовлено подовжену драбину х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyFlash", "Ви збираєтесь замовити ліхтарик. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyFlash2", "Замовлено ліхтарик х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyJetpack", "Ви збираєтесь замовити джетпак. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyJetpack2", "Замовлено джетпак х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyLockpickers", "Ви збираєтесь замовити зломщик замків. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyLockpickers2", "Замовлено зломщик замків х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyMapper", "Ви збираєтесь замовити картографічний пристрій. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyMapper2", "Замовлено картографічний пристрій х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyProFlashlight1", "Ви збираєтесь замовити про-ліхтарик. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyProFlashlight2", "Замовлено про-ліхтарик х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyRadarBooster", "Ви збираєтесь замовити підсилювач для радару. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyRadarBooster2", "Замовлено підсилювач для радару х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyShovel", "Ви збираєтесь замовити лопату. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyShovel2", "Замовлено лопату х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buySpraypaint", "Ви збираєтесь замовити балончик з фарбою. Кількість: [variableAmount].\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buySpraypaint2", "Замовлено балончик з фарбою х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyStunGrenade", "Ви збираєтесь замовити шумову гранату. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyStunGrenade2", "Замовлено шумову гранату х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buySurvivalKit", "Ви збираєтесь замовити набір для виживання:\n* Ліхтарики  х4\n* Рації x4\n* Лопата  х1\n\nКількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buySurvivalKit2", "Замовлено набір для виживання х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyTZP", "Ви збираєтесь замовити ТЗП-Інгалятор. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyTZP2", "Замовлено ТЗП-Інгалятор х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyWalkieTalkie", "Ви збираєтесь замовити рацію. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyWalkieTalkie2", "Замовлено рацію х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyZapGun", "Ви збираєтесь замовити шокер. Кількість: [variableAmount]. \nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyZapGun2", "Замовлено шокер х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "buyCruiser", "Ви збираєтесь замовити фургон Компанії.\n[warranty] Кінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyCruiser2", "Замовлено фургон Компанії. Ваш баланс: [playerCredits].\n\nМи настільки впевнені в якості цього продукту, що надаємо на нього довічну гарантію! Якщо ваш фургон буде загублено або пошкоджено, ви можете отримати безкоштовну заміну. Ви не можете придбати товари, поки транспортний засіб перебуває в дорозі." },
		{ "buyWeedkiller", "Ви збираєтесь замовити анігілятор бур'яну. Кількість: [variableAmount].\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "buyWeedkiller2", "Замовлено анігілятор бур'яну х[variableAmount]. Ваш баланс: [playerCredits].\n\nНаші підрядники полюбляють швидку та безкоштовну доставку! Будь-який придбаний предмет прибуде через годину до вашого приблизного місця розташування." },
		{ "FishBowlBuy", "Ви збираєтесь замовити золоту рибку, до якої входить скляна миска.\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "FishBowlBuyConfirm", "Замовлено золоту рибку! Ваш новий баланс становить [playerCredits].\nНатисніть [B], щоб переставити рибку на кораблі, і [V], щоб підтвердити." },
		{ "InverseTeleporterBuy", "Ви збираєтесь замовити зворотній телепорт.\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "InverseTeleporterBuyConfirm", "Замовлено зворотній телепорт! Ваш новий баланс становить [playerCredits].\nНатисніть [B], щоб переставити килимок на кораблі, і [V], щоб підтвердити." },
		{ "PlushiePajamaManBuy", "Ви збираєтесь замовити плюшевого чоловічка у піжамі.\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "PlushiePajamaManBuyConfirm", "Замовлено плюшевого чоловічка у піжамі! Ваш новий баланс становить [playerCredits].\nНатисніть [B], щоб переставити рибок на кораблі, і [V], щоб підтвердити." },
		{ "RomTableBuy1", "Ви збираєтесь замовити романтичний стіл.\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "RomTableBuyConfirm", "Замовлено романтичний стіл! Ваш новий баланс становить [playerCredits].\nНатисніть [B], щоб переставити килимок на кораблі, і [V], щоб підтвердити." },
		{ "SignalTranslatorBuy", "Ви збираєтесь замовити транслятор сигналу.\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "SignalTranslatorBuyConfirm", "Замовлено транслятор сигналу! Ваш новий баланс становить [playerCredits].\nНатисніть [B], щоб переставити рибок на кораблі, і [V], щоб підтвердити.\n\nТранслятор сигналу можна активувати командою \"transmit\", за якою слідує будь-яке повідомлення довжиною до 10 літер." },
		{ "WelcomeMatBuy", "Ви збираєтесь замовити вітальний килимок, який допоможе кожному відчути себе як вдома.\nКінцева сума: [totalCost].\n\nПідтвердіть CONFIRM або DENY." },
		{ "WelcomeMatBuyConfirm", "Замовлено вітальний килимок! Ваш новий баланс становить [playerCredits].\nНатисніть [B], щоб переставити килимок на кораблі, і [V], щоб підтвердити." },
		{ "LogFile1", "Дата: 22 Серпня, 1968\nПривіт. Пишу це, щоб не втратити свій здоровий глузд. Я не зміг знайти шлях, щоб зробити навіть базову річ на цьому старому хиткому комп'ютері, тому Десмонд мені допоміг добавити її, функцію журналу. До цього я просто добавляв свої нотатки до бестіарію, все що я знав. Мій брат сказав, що мені варто вести щоденник, тому я роблю що можу! Я писатиму в професійній манері, тому що ці журнали можуть стати історичним записом, так як вони можливо будуть тут роками, до тих пір поки це все не зітруть. Так сказав Десмонд.\n\n\nЯкщо ти читаєш це в майбутньому, то ти скоріш за все з іншого екіпажу. Швидкість обороту тут просто величезна, можливо тому що ця робота - відстій, і всі повертаються мертвими! Можливо я зможу трішечки допомогти, коли в мене буде достатньо досвіду. Кінець запису.\nОй, наші імена: Сіґурд (я), Річард, Десмонд, Джесс." },
		{ "LogFile2", "Господи, цей костюм здавлює мене так, ніби то я, чорт забирай, мумія! Я дорослий чоловік, дайте йому трішки місця між ногами! Це просто вбиває, я вмираю! Маю надію ти щасливий, тату, Я НАРЕШТІ получив роботу. Та пішов ти! Всі тут смердять. Особливо Річ. Я скину його в річку. Мені начхати з чого вона складається. Мені подобається бути на камерах. Ох\nЯ забув про дату, це 24 Серпня, 1968. Ця клавіатура має віфвошдафійе..а/п;\n\n\nСьогодні ми знайшли декілька сковорідок і великий цвях. Варті майже нічого. Для чого взагалі компанія використовує їх" },
		{ "LogFile3", "ми попали в \"розгортання подій\" за останні декілька днів. це те, що Річ постійно повторює, він пахне як просрочена банка тунця. найгірший літній табір в якому я коли небудь б у в. Сьогоднішня дата 27 Серпня, 1968. \r\nми запевняємось, що хтось завжди має лопату, щоб бити все що рухається, і ми завжди ставимо когось на \"камери\" щоб вони могли відкрити ці великі охоронні двері з буквами та цифрами. запитайте Десмонда чарівника як вони працюють, мені здається він просто пише код на дверях\r. це все\n\r\nми продали деякі речі компанії за 70% вартості. я заспокоїв с в о ї нервки слухаючи чортві ПИСХОТИЧНІ звукви за прилавком. ніхто більше не. ?? \r\nя не можу ігнорувати цього! мій ліхтарик навіть не дойшов туди, проміння просто потемнішало.\n\n\"" },
		{ "LogFile4", "Дата 31 Серпня, 1968. Мене знову поставили на камери, я ненавиджу ходити по цьому місяцю все одно. Ахах їм же гірше, щойно почав падати дощ!!! Я просто сижу. Не можу заснути на цих малесеньких ліжках для муравлів \n\n\nЯ багато думав. Ця робота якась дивна. Якщо ти це читаєш, значить ти скоріш за все попав сюди тим ж шляхом що і я. Платять добре, контракт діє протягом всього сезону. Вони проходять з тобою \"оціночний іспит\" по телефону з дивним голосом. Ти підписав контракт на шаттлі з рештою твого екіпажу. Але протягом всього часу ти ні з ким не говорив. Шаттл був на автопілоті, я думаю що голос по телефону був фальшивим.  Я мав найгірші сни, Я думаю   я просто хочу повернутись назад додому. але я не поповщу додому, плачучи і царапаючи татові двері. це не його син. це не Сіґурд!" },
		{ "LogFile5", "сьогодні зранку мене рано розбудили тому що ми йшли до будови компанії щоб продати наше непотрібне сміття. Тариф був 120% про який Десмонд каже що це рідкість і він не хотів цього пропустити, він дивився за ними як за дурними акціями. \n\nвсе ще відстій тут, Річ досі пахне як шматок алйна .я ледве можу спати. я почув найгрігший звук поза стіною будівлі компанії, він звучав як плачучі червоні лицявсі збиті і зметені бетоном, як товкачка і миска в якій моя мама подрібнює своє насіння і спеції. я все ще чую цей звук. Це просто кошмар. ніхто інший не чув. вони не знають що робити. Джесс думає що я \"сумую за додом,\" ні я сумую від того що маю носити цей дешевий костюм\r\nдата: 4 Вересня, 1968" },
		{ "LogFile6", "ми залиишили Річі позаду. нам залишилось провірити лише одну кімнату і ми могли б закінчити на цьому, я не міг відкрити двері. А потім я оглянувся і Річі уже не було. Це був довбаний зморшкуватий чоловік з квіткою на місті голови, що ходить на двох ногах! воно повернуло свою шию. я почув хруст але його там не було. Я хотів знайти Річі навіть якщо він був мертвим, але вони боягузи! їхні лиця пусті як в ідіотів, там нічого не рухається в їх тупих черепах, все чого вони хотіли це звалити. вони б і мене залишили.ми всі ненавидили Річі але ми не хотіли цього. це цього не варте, просто не варте. у нас є пара ножиць, коробка наповненна штампами і моток шнурів для продажі ні за що. це цього не  а те , для чого це взагалі компанії?\n\n\nдата коли ми останній раз бачили Річі: 7 Вересня, 1968" },
		{ "LogFile7", "дата: 13 Вересня, 1968\n\nз якоїсь причини я був тим хто мав дзвонити компанії щоб повідомити про інцидент. вони були надто налякані щоб зробити це. Це був той самий фальшивий голос який я пам'ятав з інтерв'ю по телефону вдома і тупими тренінговими відео. але воно почуло що я сказав, я думаю, тому що воно сказало вони зв'яжуться з сім'єю і знайдуть заміну і ще щ ось. Воно говорило так швидко.\n\n\nЯ дізнався що можна чути ці крики весь час по рації коли ти  біля стіни будови компанії. вони не вірили мені, що ж, тепер вірять. Вони звучать так ж як коли я почув їх декілька тижнів тому. Вони хочуть звільнитись. Я сказав я не боягуз. Я тільки но отримав цю роботу" },
		{ "LogFile8", "Я говорив по рації, воно звучало як частина криків. він сказав мені що Золота планета дійсно існувала, що це не просто легенда. і він сказав що вона не просто врізалась в метеор. Він сказав що планета була проковтнута \"звірем\", і вони були в його тілі і переварювались. я запитав що то за звір, і він сказав що він не знав!. він сказав що воно з'їло планету і вони все забули. \r\n\r\nя не міг заставити його заткнутись. але я сказав що він був на іншій стороні великої стіни і я міг допомогти йому вибратись звідти. я сказав що він був всередині будівлі. і він почав дуже нервувати/. я не міг розпізнати жодного слова, я думаю він сказав щось про \"випльовувати шкірки\" Тому я просто виключив його. що за дурень\n\r\nДжесс говорить що золота планета це лише історія. Я сказав  Я ЗНАЮ, я не ідіот. Що ж, вона сказала мені варто звільнитись, і вона звільниться якщо я звільнюсь. тому вона залишається" },
		{ "LogFile9", "дата: 19 Вересня, 1968\nминулі вихідні вони відчуваються ніби то Десмонд і Джесс прокинулись. через декілька днів ми маємо зустріти нашого нового четвертого учасника. Ми більше не беремо ніяких ризиків, ми не получаємо стільки ж але це відчувається безпечніше, і я став краще спати. але це все ще дупа. я все ще відчуваю запах Річі і я Богом клянусь він смердів настільки погано\n\nя говорив про те як голос по телефону звучав фальшивим. Потім Десмонду прийшла ця дивна ідея. він чаклун та все таке тому він думає що є шлях щоб використати запис телефонної розмови що я зробив щоб вияснити звідки походить голос. я не знаю чому б він хотів це робити але він здається серйозним. Він використовував термінал часто." },
		{ "LogFile10", "27 Вересня, 1968\r\nдесмонд хоче щоб я напис ав те що ми вияснили і тримати мої \"дурощі на мінімумі\". Тому я додам СТІЛЬКИ своїх дурощів. пішов він. Нового члена команди звати Лукас і він дуже розгублений і наляканий ве сь час, що за дитинка, він хоча б не смердить як монстр.\r було так сонячно, навіть попри те що зараз вересень, і ці костюми цього не витримують\nгаразд десмонд \"відслідкував дзвінок\" і вияснив що десь ще є група людей які вдають що дзвонять нам з будівлі компанії. вони знаходяться через всю сонячну систему !! чому б їм бути так далеко.\r\n\nДесмонд каже він не знає, але я думаю. Що якщо там дійсно є великий монстр в будівлі компанії як голос сказав мені по рації? Вони заманили його, і ми кормим його щоб втримати його прирученим. я просто хотів цю тупу роботу!!!!! " },
		{ "LogFile11", "30 Вересня, 1968\r\n\r\nмені продовжують снитись кошмари про будівлю Компанії де Компанія виривається з тієї величезної бетонної стіни. Але я не знаю чи це на щось схоже, я просто думаю що воно дуже велике і швидке. Ми не можемо вияснити шлях щоб зрозуміти чи голоси по телефону реальні, десмонд каже це занадто далеко. я запитав його чи міг би він ввзяти контроль над автопілотом і він сказав що я божевільний і що це може вбити нас. так я божевільний десмонд\r\n\r\nвін каже що ми мали б дістати наш особистий приватний літак щоб дістатись до цих координат, і хто зна що там дійсно буде. Тож, що якщо там нічого? \r\nя почав цікавитись як я не можу навіть згадати як ми потратипили сюди, ні я просто пам'ятаю маленькі речі типу як політ шаттлу до будівді де ми підписали наші контракти. Але я не пам'ятаю як я потратив на шаттл, я навіть не пам'ятаю як сказав прощання татові. в моїх снах це відчувається так ніби компанія не просто застрягла тут, вона просто ховається. Я не знаю чи повернусь додому" },
		{ "LogFile12", "Десмонд. 3 Жовтня, 1968. Я зашифровую ці журнали щоб зберегти їх прихованими, тому що я боюсь, що система буде стерта якщо їх знайдуть. Це все приманка. Ми мали думати що це просто перехід, але наша справжня робота це стримування неймовірного жаху. Скільки нам ще лишилось поки його наповненість закінчиться і його ненаситний голод? Бог знає, можливо воно пов'язане з цими всіма пустельними місяцями. Тому хто це читає, вибач що обтяжую тебе цим. Хорошого дня або хорошої ночі-- що нам ще залишилось робити? " }
	};

	public static readonly Dictionary<string, string> TextPostProcess = new Dictionary<string, string>
	{
		{ "Routing autopilot to (.+?)\\nYour new balance is \\[playerCredits\\].\\n\\nPlease enjoy your flight.", "Автопілот прокладає маршрут до $1\nВаш новий баланс становить [playerCredits].\n\nПриємного польоту." },
		{ "Routing autopilot to (.+?)\\nYour new balance is \\[playerCredits\\].\\n\\nGood luck.", "Автопілот прокладає маршрут до $1\nВаш новий баланс становить [playerCredits].\n\nУспіхів." },
		{ "Routing autopilot to (.+?) Your new balance is \\[playerCredits\\].", "Автопілот прокладає маршрут до $1\nВаш новий баланс становить [playerCredits]." },
		{ "The cost to route to (.+?) is (.+?). It is (?:\\n)?currently (.+?) on this moon.\\n\\nPlease CONFIRM or DENY.", "Вартість маршруту до $1 становить $2. На цій планеті зараз $3 погода.\n\nПідтвердіть CONFIRM або DENY." },
		{ "\\[No items stored. While moving an object with B, press X to store it.\\]", "[Немає об'єктів в сховищі. Переміщуючи об'єкт за допомогою B, натисніть X, щоб перемістити його в сховище.]" },
		{ "There are ([0-9]+) objects outside the ship, totalling at an approximate value of (\\$[0-9]+).", "За межами корабля знаходиться $1 об'єктів, загальна ціна яких приблизно дорівнює $2." },
		{ "Exception occured on terminal while setting node planet info; current node displayPlanetInfo:(.+?)", "В терміналі виникла помилка під час встановлення інформації про планету вузла; поточний вузол displayPlanetInfo:$1" },
		{ "No data collected on wildlife. Scans are required.", "Дані про диких істот не зібрані. Потрібні сканування." },
		{ "You have a free warranty!", "Ви маєте безкоштовну гарантія!" },
		{ "\\[No items in stock!\\]", "[Немає товарів в наявності!]" },
		{ "\\[ALL DATA HAS BEEN CORRUPTED OR OVERWRITTEN\\]", "[ВСІ ДАНІ БУЛИ ПОШКОДЖЕНІ АБО ПЕРЕЗАПИСАНІ]" },
		{ "([0-9]+) purchased items on route.", "$1 предмет(-ів) в дорозі." },
		{ "\\[No items available\\]", "[Немає доступних товарів]" },
		{ "([0-9]+)% OFF!", "$1% ЗНИЖКИ!" },
		{ "\\(Locked\\)", "(Закрито)" },
		{ "\\(NEW\\)", "(НОВЕ)" },
		{ "Price:", "Ціна:" },
		{ "DustClouds", "Пилові хмари" },
		{ "Rainy", "Дощова" },
		{ "Stormy", "Шторм" },
		{ "Foggy", "Туманно" },
		{ "Flooded", "Затоплено" },
		{ "Eclipsed", "Затемнення" },
		{ "mild weather", "помірна" },
		{ "dustclouds", "пилові хмари" },
		{ "rainy", "дощова" },
		{ "stormy", "шторм" },
		{ "foggy", "туманно" },
		{ "flooded", "затоплено" },
		{ "eclipsed", "затемнення" }
	};

	public static readonly Dictionary<string, string> Chat = new Dictionary<string, string>
	{
		{ "(.*) joined the ship\\.", "$1 приєднався до екіпажу." },
		{ "(.*) started the ship\\.", "$1 запустив корабель." },
		{ "(.*) was left behind\\.", "$1 залишився за бортом." },
		{ "(.*) disconnected\\.", "$1 від'єднався." },
		{ "(.*) was kicked\\.", "$1 був вилучений." }
	};

	public static readonly Dictionary<string, string> Notes = new Dictionary<string, string>
	{
		{ "Most profitable", "Найприбутковіший" },
		{ "Sustained the most injuries.", "Отримав найбільше травм." },
		{ "The laziest employee.", "Найлінивіший працівник." },
		{ "The most paranoid employee.", "Найпараноїдальніший працівник." }
	};

	public static readonly Dictionary<string, string> Loading = new Dictionary<string, string>
	{
		{ "Random seed", "Ключ генерації" },
		{ "LOADING WORLD...", "ЗАВАНТАЖЕННЯ СВІТУ..." }
	};

	public static readonly Dictionary<string, string> ShipTeleporter = new Dictionary<string, string> { { "\\[Cooldown: (.+?) sec\\.\\]", "[Зачекайте $1 сек.]" } };

	public static readonly Dictionary<string, string> PlanetInfo = new Dictionary<string, string>
	{
		{ "A competitive ecosystem supports aggressive lifeforms.", "Конкурентна екосистема підтримує агресивні форми життя." },
		{ "Arid. Thick haze, worsened by industrial artifacts.", "Засушливо. Густий туман, погіршений промисловими відходами." },
		{ "Dangerous entities have been rumored to take residence in the vast network of tunnels.", "Небезпечні істоти які за чутками проживають у великій системи тунелів." },
		{ "Dominated by a few species.", "Домінують декілька видів." },
		{ "Ecosystem supports territorial behaviour.", "Екосистема підтримує територіальну поведінку." },
		{ "Expansive. Constant rain.", "Експансивна. Постійний дощ." },
		{ "Frozen, rocky. Its planet orbits a white dwarf star.", "Заморожена, скеляста. Ця планета є орбітою білої карликової зірки." },
		{ "Humid. Rough terrain. Teeming with plant-life.", "Вологість. Горбиста місцевість. Кишить рослинністю." },
		{ "Jagged and weathered terrain.", "Нерівний та висушений рельєф." },
		{ "No land masses. Continual storms.", "Ніяких земельних масивів. Постійні бурі." },
		{ "Unlikely for complex life to exist", "Навряд чи існує складне життя" },
		{ "Where the Company resides.", "Місцезнаходження компанії." },
		{ "Abandoned", "Закинута" },
		{ "Diverse", "Різноманітна" },
		{ "Eclipsed", "Затемнення" },
		{ "Flooded", "Затоплено" },
		{ "Foggy", "Туманно" },
		{ "None", "Відсутня" },
		{ "Rainy", "Дощить" },
		{ "Safe", "Безпечний" },
		{ "Stormy", "Шторм" },
		{ "Unknown", "Невідомо" },
		{ "CELESTIAL BODY", "Небесне тіло" },
		{ "Orbiting", "На орбіті" },
		{ "POPULATION", "ПОПУЛЯЦІЯ" },
		{ "CONDITIONS", "УМОВИ" },
		{ "FAUNA", "ФАУНА" },
		{ "Weather", "Погода" }
	};
}
internal class R2modmanFixer
{
	public static void TryMoveFiles()
	{
		string path = Path.Combine(Paths.PluginPath, "LCUA-LCUA");
		string sourcePath = Path.Combine(path, "lcua.bundle");
		string[] obj = new string[9]
		{
			Path.Combine(path, "LCUA.txt"),
			Path.Combine(path, "LCUA_Creatures.txt"),
			Path.Combine(path, "LCUA_Interactions.txt"),
			Path.Combine(path, "LCUA_Items.txt"),
			Path.Combine(path, "LCUA_Keybinds.txt"),
			Path.Combine(path, "LCUA_Menu.txt"),
			Path.Combine(path, "LCUA_Mods.txt"),
			Path.Combine(path, "LCUA_Moons.txt"),
			Path.Combine(path, "LCUA_Regex.txt")
		};
		string destinationPath = Path.Combine(Paths.BepInExRootPath, "Bundles");
		string destinationPath2 = Path.Combine(Paths.BepInExRootPath, "Translation", "uk", "Text");
		MoveFile(sourcePath, destinationPath);
		string[] array = obj;
		for (int i = 0; i < array.Length; i++)
		{
			MoveFile(array[i], destinationPath2);
		}
	}

	private static void MoveFile(string sourcePath, string destinationPath)
	{
		try
		{
			if (!Directory.Exists(destinationPath))
			{
				Directory.CreateDirectory(destinationPath);
			}
			destinationPath = Path.Combine(destinationPath, Path.GetFileName(sourcePath));
			if (File.Exists(sourcePath))
			{
				if (File.Exists(destinationPath))
				{
					File.Delete(destinationPath);
				}
				File.Move(sourcePath, destinationPath);
			}
		}
		catch (Exception ex)
		{
			Console.WriteLine("Виникла проблеми при переміщенні файлу " + sourcePath + " до " + destinationPath + ": " + ex.Message);
		}
	}
}
internal class Translator
{
	public static string Translate(string input, Dictionary<string, string> Dictionary)
	{
		foreach (KeyValuePair<string, string> item in Dictionary)
		{
			input = Regex.Replace(input, item.Key, item.Value);
		}
		return input;
	}

	public static string TranslateNode(string nodeName, string nodeText)
	{
		if (!Dictionaries.Nodes.ContainsKey(nodeName))
		{
			return Translate(nodeText, Dictionaries.TextPostProcess);
		}
		if (PatchOnSceneLoadComplete.specialNodes.Keys.Contains(nodeName))
		{
			string[] array = PatchOnSceneLoadComplete.specialNodes[nodeName].Replace("\r\n", "\n").Split(new char[1] { '\n' });
			string[] array2 = Dictionaries.Nodes[nodeName].Replace("\r\n", "\n").Split(new char[1] { '\n' });
			char[] trimChars = new char[2] { '*', ' ' };
			for (int i = 0; i < array.Length && i < array2.Length; i++)
			{
				string text = array[i].Trim(trimChars);
				string text2 = array2[i].Trim(trimChars);
				bool flag = false;
				string[] array3 = nodeText.Replace("\r\n", "\n").Split(new char[1] { '\n' });
				if (i != array.Length - 1 && i != array3.Length - 1)
				{
					flag = array[i + 1] == "" && array3[i + 1] != "";
				}
				if (!(text == "") && !(text2 == ""))
				{
					nodeText = nodeText.Replace(text, text2 + (flag ? "\n" : ""));
				}
			}
			return nodeText;
		}
		return Dictionaries.Nodes[nodeName];
	}

	public static void TranslateLoading()
	{
		if (((UIBehaviour)HUDManager.Instance.loadingText).IsActive())
		{
			((TMP_Text)HUDManager.Instance.loadingText).text = Translate(((TMP_Text)HUDManager.Instance.loadingText).text, Dictionaries.Loading);
		}
	}
}
namespace LCUA_Patcher
{
	[BepInPlugin("LCUA_Patcher", "LCUA_Patcher", "2.3.0")]
	[BepInProcess("Lethal Company.exe")]
	public class Plugin : BaseUnityPlugin
	{
		private void Awake()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)" _    ___ _   _  _   ");
			((BaseUnityPlugin)

BepInEx/plugins/XUnity.AutoTranslator/ExIni.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Win32;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyInformationalVersion("GIT master [cf85ca6f3fc361cf48bf56107e4cec9102b7f5eb] ")]
[assembly: AssemblyTitle("ExIni")]
[assembly: Guid("b8adf1ac-aade-485a-8997-14c4b42e0a8b")]
[assembly: AssemblyDescription("Extended INI File Handler")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("1.0.2.1")]
[assembly: AssemblyCompany("Usagirei")]
[assembly: AssemblyProduct("ExIni")]
[assembly: ComVisible(false)]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCopyright("Copyright © Usagirei 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.0.2.1")]
namespace ExIni;

public class IniComment
{
	public List<string> Comments { get; set; }

	public IniComment()
	{
		Comments = new List<string>();
	}

	public override string ToString()
	{
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < Comments.Count; i++)
		{
			string text = Comments[i];
			string value = ((i < Comments.Count - 1) ? (";" + text + Environment.NewLine) : (";" + text));
			stringBuilder.Append(value);
		}
		return stringBuilder.ToString();
	}

	public void Append(params string[] comments)
	{
		Comments.AddRange(comments);
	}
}
public class IniFile
{
	private readonly IniComment _comments;

	private readonly List<IniSection> _sections;

	public IniSection this[string sec] => CreateSection(sec);

	public IniComment Comments => _comments;

	public List<IniSection> Sections => _sections;

	public IniFile()
	{
		_comments = new IniComment();
		_sections = new List<IniSection>();
	}

	public override string ToString()
	{
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < Sections.Count; i++)
		{
			IniSection iniSection = Sections[i];
			if (iniSection.Comments.Comments.Any())
			{
				stringBuilder.AppendLine(iniSection.Comments.ToString());
			}
			stringBuilder.AppendLine(iniSection.ToString());
			foreach (IniKey key in iniSection.Keys)
			{
				if (key.Comments.Comments.Any())
				{
					stringBuilder.AppendLine(key.Comments.ToString());
				}
				stringBuilder.AppendLine(key.ToString());
			}
			if (i < Sections.Count - 1)
			{
				stringBuilder.AppendLine();
			}
		}
		if (Comments.Comments.Any())
		{
			stringBuilder.AppendLine();
			stringBuilder.AppendLine(Comments.ToString());
		}
		return stringBuilder.ToString();
	}

	public IniSection CreateSection(string section)
	{
		IniSection section2 = GetSection(section);
		if (section2 != null)
		{
			return section2;
		}
		IniSection iniSection = new IniSection(section);
		_sections.Add(iniSection);
		return iniSection;
	}

	public bool DeleteSection(string section)
	{
		if (!HasSection(section))
		{
			return false;
		}
		Sections.Remove(GetSection(section));
		return true;
	}

	public IniSection GetSection(string section)
	{
		if (!HasSection(section))
		{
			return null;
		}
		return _sections.FirstOrDefault((IniSection iniSection) => iniSection.Section == section);
	}

	public bool HasSection(string section)
	{
		return _sections.Any((IniSection iniSection) => iniSection.Section == section);
	}

	public void Merge(IniFile ini)
	{
		Comments.Append(ini.Comments.Comments.ToArray());
		foreach (IniSection section in ini.Sections)
		{
			IniSection iniSection = this[section.Section];
			iniSection.Comments.Append(section.Comments.Comments.ToArray());
			foreach (IniKey key in section.Keys)
			{
				IniKey iniKey = iniSection[key.Key];
				iniKey.Comments.Append(key.Comments.Comments.ToArray());
				iniKey.Value = key.Value;
			}
		}
	}

	public void Save(string filePath)
	{
		string directoryName = Path.GetDirectoryName(filePath);
		if (!string.IsNullOrEmpty(directoryName))
		{
			Directory.CreateDirectory(directoryName);
		}
		File.WriteAllText(filePath, ToString(), Encoding.UTF8);
	}

	public static IniFile FromFile(string iniString)
	{
		return IniParser.Parse(File.ReadAllText(iniString));
	}

	public static IniFile FromString(string iniString)
	{
		return IniParser.Parse(iniString);
	}
}
public class IniKey
{
	private readonly IniComment _comments;

	public IniComment Comments => _comments;

	public string Key { get; set; }

	public string RawValue { get; set; }

	public string Value
	{
		get
		{
			return Resolve(RawValue);
		}
		set
		{
			RawValue = value;
		}
	}

	public IniKey(string key, string value = null)
	{
		Key = key;
		Value = value;
		_comments = new IniComment();
	}

	public override string ToString()
	{
		return $"{Key}={RawValue}";
	}

	private static string GetEnvironment(string env)
	{
		return Environment.ExpandEnvironmentVariables(env);
	}

	private static string GetRegistry(string path)
	{
		string directoryName = Path.GetDirectoryName(path);
		string fileName = Path.GetFileName(path);
		if (string.IsNullOrEmpty(directoryName))
		{
			return null;
		}
		return Registry.GetValue(directoryName, fileName, string.Empty)?.ToString();
	}

	private static string Resolve(string value)
	{
		if (value == null)
		{
			return null;
		}
		Regex regex = new Regex("\\$\\((?<reg>.*)\\)");
		Regex regex2 = new Regex("%.*%");
		while (regex.IsMatch(value) || regex2.IsMatch(value))
		{
			value = regex.Replace(value, (Match match) => GetRegistry(match.Groups["reg"].Value));
			value = GetEnvironment(value);
		}
		return value;
	}
}
internal class IniParser
{
	private static readonly Regex CommentRegex = new Regex("^;(?<com>.*)");

	private static readonly Regex KeyRegex = new Regex("^(?<key>[\\w\\s]+)=(?<val>.*)$");

	private static readonly Regex SectionRegex = new Regex("^\\[(?<sec>[\\w\\s]+)\\]$");

	private static readonly Regex VarRegex = new Regex("^\\@(?<key>[\\w\\s]+)=(?<val>.*)$");

	public static IniFile Parse(string iniString)
	{
		IniFile iniFile = new IniFile();
		string[] array = (from line in iniString.Split(new char[1] { '\n' })
			let trimmed = line.Trim()
			select trimmed.TrimEnd(new char[1] { '\r' })).ToArray();
		List<string> list = new List<string>();
		IniSection iniSection = null;
		bool flag = false;
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i];
			if (string.IsNullOrEmpty(text))
			{
				continue;
			}
			if (IsComment(text))
			{
				string comment = GetComment(text);
				list.Add(comment);
				if (IsVariable(comment))
				{
					string[] variable = GetVariable(comment);
					string variable2 = variable[0];
					string value = variable[1];
					Environment.SetEnvironmentVariable(variable2, value);
				}
				flag = true;
			}
			else if (IsSection(text))
			{
				iniSection = iniFile[GetSection(text)];
				if (flag)
				{
					iniSection.Comments.Append(list.ToArray());
					list.Clear();
					flag = false;
				}
			}
			else if (IsKey(text))
			{
				if (iniSection == null)
				{
					throw new Exception($"{i}: Sectionless Key Value Pair");
				}
				string[] key = GetKey(text);
				string key2 = key[0];
				string value2 = key[1];
				if (flag)
				{
					iniSection[key2].Comments.Append(list.ToArray());
					list.Clear();
					flag = false;
				}
				iniSection[key2].Value = value2;
			}
		}
		if (flag)
		{
			iniFile.Comments.Append(list.ToArray());
		}
		return iniFile;
	}

	private static string GetComment(string line)
	{
		return CommentRegex.Match(line).Groups["com"].Value;
	}

	private static string[] GetKey(string line)
	{
		Match match = KeyRegex.Match(line);
		return new string[2]
		{
			match.Groups["key"].Value,
			match.Groups["val"].Value
		};
	}

	private static string GetSection(string line)
	{
		return SectionRegex.Match(line).Groups["sec"].Value;
	}

	private static string[] GetVariable(string line)
	{
		Match match = VarRegex.Match(line);
		return new string[2]
		{
			match.Groups["key"].Value,
			match.Groups["val"].Value
		};
	}

	private static bool IsComment(string line)
	{
		return CommentRegex.IsMatch(line);
	}

	private static bool IsKey(string line)
	{
		return KeyRegex.IsMatch(line);
	}

	private static bool IsSection(string line)
	{
		return SectionRegex.IsMatch(line);
	}

	private static bool IsVariable(string line)
	{
		return VarRegex.IsMatch(line);
	}
}
public class IniSection
{
	private readonly IniComment _comments;

	private readonly List<IniKey> _keys;

	public IniKey this[string key] => CreateKey(key);

	public IniComment Comments => _comments;

	public List<IniKey> Keys => _keys;

	public string Section { get; set; }

	public IniSection(string section)
	{
		Section = section;
		_comments = new IniComment();
		_keys = new List<IniKey>();
	}

	public override string ToString()
	{
		return $"[{Section}]";
	}

	public IniKey CreateKey(string key)
	{
		IniKey key2 = GetKey(key);
		if (key2 != null)
		{
			return key2;
		}
		IniKey iniKey = new IniKey(key);
		_keys.Add(iniKey);
		return iniKey;
	}

	public IniKey GetKey(string key)
	{
		if (!HasKey(key))
		{
			return null;
		}
		return _keys.FirstOrDefault((IniKey iniKey) => iniKey.Key == key);
	}

	public bool HasKey(string key)
	{
		return _keys.Any((IniKey iniKey) => iniKey.Key == key);
	}

	public bool DeleteKey(string key)
	{
		if (!HasKey(key))
		{
			return false;
		}
		Keys.Remove(GetKey(key));
		return true;
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/BaiduTranslate.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core;
using XUnity.AutoTranslator.Plugin.Core.Constants;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Extensions;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;
using XUnity.Common.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("BaiduTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BaiduTranslate")]
[assembly: AssemblyTitle("BaiduTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BaiduTranslate;

internal class BaiduTranslateEndpoint : HttpEndpoint
{
	private static readonly Dictionary<string, string> SupportedLanguages = new Dictionary<string, string>
	{
		{ "en", "en" },
		{ "ja", "jp" },
		{ "jp", "jp" },
		{ "zh", "zh" },
		{ "zh-Hans", "zh" },
		{ "zh-CN", "zh" },
		{ "zh-Hant", "cht" },
		{ "zh-TW", "cht" },
		{ "ko", "kor" },
		{ "kor", "kor" },
		{ "fra", "fra" },
		{ "fr", "fra" },
		{ "spa", "spa" },
		{ "es", "spa" },
		{ "ara", "ara" },
		{ "ar", "ara" },
		{ "bg", "bul" },
		{ "bul", "bul" },
		{ "et", "est" },
		{ "est", "est" },
		{ "da", "dan" },
		{ "dan", "dan" },
		{ "fi", "fin" },
		{ "fin", "fin" },
		{ "ro", "rom" },
		{ "rom", "rom" },
		{ "sl", "slo" },
		{ "slo", "slo" },
		{ "vi", "vie" },
		{ "vie", "vie" },
		{ "sv", "swe" },
		{ "swe", "swe" },
		{ "th", "th" },
		{ "ru", "ru" },
		{ "pt", "pt" },
		{ "de", "de" },
		{ "it", "it" },
		{ "el", "el" },
		{ "nl", "nl" },
		{ "pl", "pl" },
		{ "cs", "cs" },
		{ "hu", "hu" }
	};

	private static readonly string HttpServicePointTemplateUrl = "https://api.fanyi.baidu.com/api/trans/vip/translate?q={0}&from={1}&to={2}&appid={3}&salt={4}&sign={5}";

	private static readonly MD5 HashMD5 = MD5.Create();

	private string _appId;

	private string _appSecret;

	private float _delay;

	private float _lastRequestTimestamp;

	public override string Id => "BaiduTranslate";

	public override string FriendlyName => "Baidu Translator";

	private string FixLanguage(string lang)
	{
		if (SupportedLanguages.TryGetValue(lang, out var value))
		{
			return value;
		}
		return lang;
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0063: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		_appId = context.GetOrCreateSetting<string>("Baidu", "BaiduAppId", "");
		_appSecret = context.GetOrCreateSetting<string>("Baidu", "BaiduAppSecret", "");
		_delay = context.GetOrCreateSetting<float>("Baidu", "DelaySeconds", 1f);
		if (string.IsNullOrEmpty(_appId))
		{
			throw new EndpointInitializationException("The BaiduTranslate endpoint requires an App Id which has not been provided.");
		}
		if (string.IsNullOrEmpty(_appSecret))
		{
			throw new EndpointInitializationException("The BaiduTranslate endpoint requires an App Secret which has not been provided.");
		}
		context.DisableCertificateChecksFor(new string[1] { "api.fanyi.baidu.com" });
		if (!SupportedLanguages.ContainsKey(context.SourceLanguage))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.ContainsKey(context.DestinationLanguage))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context)
	{
		float realtimeSinceStartup = TimeHelper.realtimeSinceStartup;
		float num = realtimeSinceStartup - _lastRequestTimestamp;
		if (num < _delay)
		{
			float num2 = _delay - num;
			object obj = CoroutineHelper.CreateWaitForSecondsRealtime(num2);
			if (obj != null)
			{
				yield return obj;
			}
			else
			{
				float end = realtimeSinceStartup + num2;
				while (realtimeSinceStartup < end)
				{
					yield return null;
				}
			}
		}
		_lastRequestTimestamp = TimeHelper.realtimeSinceStartup;
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Expected O, but got Unknown
		string text = DateTime.UtcNow.Millisecond.ToString();
		string text2 = CreateMD5(_appId + ((ITranslationContextBase)context).UntranslatedText + text + _appSecret);
		XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpServicePointTemplateUrl, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), _appId, text, text2));
		val.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent);
		val.Headers[HttpRequestHeader.AcceptCharset] = "UTF-8";
		context.Complete(val);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		string data = ((IHttpResponseInspectionContext)context).Response.Data;
		if (data.StartsWith("{\"error"))
		{
			return;
		}
		JSONNode val = JSON.Parse(data);
		StringBuilder stringBuilder = new StringBuilder(data.Length);
		Enumerator enumerator = ((JSONNode)((JSONNode)val.AsObject)["trans_result"].AsArray).GetEnumerator();
		while (((Enumerator)(ref enumerator)).MoveNext())
		{
			string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsObject)["dst"]).ToString();
			text = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
			if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder))
			{
				stringBuilder.Append("\n");
			}
			stringBuilder.Append(text);
		}
		string text2 = stringBuilder.ToString();
		context.Complete(text2);
	}

	private static string CreateMD5(string input)
	{
		byte[] bytes = Encoding.UTF8.GetBytes(input);
		byte[] array = HashMD5.ComputeHash(bytes);
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < array.Length; i++)
		{
			stringBuilder.Append(array[i].ToString("X2"));
		}
		return stringBuilder.ToString().ToLower();
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/BingTranslate.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core;
using XUnity.AutoTranslator.Plugin.Core.Constants;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Shims;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;
using XUnity.Common.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("BingTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BingTranslate")]
[assembly: AssemblyTitle("BingTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BingTranslate;

public class BingTranslateEndpoint : HttpEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"auto-detect", "af", "ar", "bn", "bs", "bg", "yue", "ca", "zh-Hans", "zh-Hant",
		"hr", "cs", "da", "nl", "en", "et", "fj", "fil", "fi", "fr",
		"de", "el", "ht", "he", "hi", "mww", "hu", "is", "id", "it",
		"ja", "sw", "tlh", "tlh-Qaak", "ko", "lv", "lt", "mg", "ms", "mt",
		"nb", "fa", "pl", "pt", "otq", "ro", "ru", "sm", "sr-Cyrl", "sr-Latn",
		"sk", "sl", "es", "sv", "ty", "ta", "te", "th", "to", "tr",
		"uk", "ur", "vi", "cy", "yua"
	};

	private static readonly string HttpsServicePointTemplateUrl = "https://www.bing.com/ttranslatev3?isVertical=1&&IG={0}&IID={1}.{2}";

	private static readonly string HttpsServicePointTemplateUrlWithoutIG = "https://www.bing.com/ttranslatev3?isVertical=1";

	private static readonly string HttpsTranslateUserSite = "https://www.bing.com/translator";

	private static readonly string RequestTemplate = "&fromLang={1}&text={0}&to={2}";

	private static readonly Random RandomNumbers = new Random();

	private static readonly string[] Accepts = new string[1] { "*/*" };

	private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" };

	private static readonly string[] Referers = new string[1] { "https://bing.com/translator" };

	private static readonly string[] Origins = new string[1] { "https://www.bing.com" };

	private static readonly string[] AcceptCharsets = new string[2]
	{
		null,
		Encoding.UTF8.WebName
	};

	private static readonly string[] ContentTypes = new string[1] { "application/x-www-form-urlencoded" };

	private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)];

	private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)];

	private static readonly string Referer = Referers[RandomNumbers.Next(Referers.Length)];

	private static readonly string Origin = Origins[RandomNumbers.Next(Origins.Length)];

	private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)];

	private static readonly string ContentType = ContentTypes[RandomNumbers.Next(ContentTypes.Length)];

	private CookieContainer _cookieContainer;

	private bool _hasSetup;

	private string _ig;

	private string _iid;

	private int _translationCount;

	private int _resetAfter = RandomNumbers.Next(75, 125);

	public override string Id => "BingTranslate";

	public override string FriendlyName => "Bing Translator";

	public BingTranslateEndpoint()
	{
		_cookieContainer = new CookieContainer();
	}

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-CN":
		case "zh":
			return "zh-Hans";
		case "zh-TW":
			return "zh-Hant";
		case "auto":
			return "auto-detect";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0041: 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)
		context.DisableCertificateChecksFor(new string[1] { "www.bing.com" });
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context)
	{
		if (!_hasSetup || _translationCount % _resetAfter == 0)
		{
			_resetAfter = RandomNumbers.Next(75, 125);
			_translationCount = 0;
			_hasSetup = true;
			IEnumerator enumerator = SetupIGAndIID();
			while (enumerator.MoveNext())
			{
				yield return enumerator.Current;
			}
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		_translationCount++;
		string text = null;
		text = ((_ig != null && _iid != null) ? string.Format(HttpsServicePointTemplateUrl, _ig, _iid, _translationCount) : HttpsServicePointTemplateUrlWithoutIG);
		string text2 = string.Format(RequestTemplate, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage));
		XUnityWebRequest val = new XUnityWebRequest("POST", text, text2);
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: true);
		context.Complete(val);
	}

	public override void OnInspectResponse(IHttpResponseInspectionContext context)
	{
		InspectResponse(context.Response);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		string text = ((object)((JSONNode)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsArray)[0]["translations"].AsArray)[0]["text"]).ToString();
		string text2 = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
		context.Complete(text2);
	}

	private XUnityWebRequest CreateWebSiteRequest()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		XUnityWebRequest val = new XUnityWebRequest(HttpsTranslateUserSite);
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: false);
		return val;
	}

	private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest)
	{
		request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent);
		if (AcceptLanguage != null)
		{
			request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage;
		}
		if (Accept != null)
		{
			request.Headers[HttpRequestHeader.Accept] = Accept;
		}
		if (Referer != null && isTranslationRequest)
		{
			request.Headers[HttpRequestHeader.Referer] = Referer;
		}
		if (Origin != null && isTranslationRequest)
		{
			request.Headers["Origin"] = Origin;
		}
		if (AcceptCharset != null)
		{
			request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset;
		}
		if (ContentType != null && isTranslationRequest)
		{
			request.Headers[HttpRequestHeader.ContentType] = ContentType;
		}
	}

	private void InspectResponse(XUnityWebResponse response)
	{
		CookieCollection newCookies = response.NewCookies;
		_cookieContainer.Add(newCookies);
	}

	public IEnumerator SetupIGAndIID()
	{
		_cookieContainer = new CookieContainer();
		XUnityWebResponse response;
		try
		{
			XUnityWebClient val = new XUnityWebClient();
			XUnityWebRequest val2 = CreateWebSiteRequest();
			response = val.Send(val2);
		}
		catch (Exception ex)
		{
			XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up BingTranslate IG. Proceeding without...");
			yield break;
		}
		IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator();
		while (iterator.MoveNext())
		{
			yield return iterator.Current;
		}
		if (((CustomYieldInstructionShim)response).IsTimedOut)
		{
			XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up BingTranslate IG. Proceeding without...");
			yield break;
		}
		if (response.Error != null)
		{
			XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up BingTranslate IG. Proceeding without...");
			yield break;
		}
		if (response.Data == null)
		{
			XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up BingTranslate IG. Proceeding without...");
			yield break;
		}
		InspectResponse(response);
		try
		{
			string data = response.Data;
			_ig = Lookup("\",IG:\"", data);
			_iid = Lookup("data-iid=\"", data);
			if (_ig == null || _iid == null)
			{
				XuaLogger.AutoTranslator.Warn("An error occurred while setting up BingTranslate IG/IID. Proceeding without...");
			}
		}
		catch (Exception ex2)
		{
			XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up BingTranslate IG. Proceeding without...");
		}
	}

	private string Lookup(string lookFor, string html)
	{
		int num = html.IndexOf(lookFor);
		if (num > -1)
		{
			int num2 = num + lookFor.Length;
			int num3 = html.IndexOf("\"", num2);
			if (num2 > -1 && num3 > -1)
			{
				return html.Substring(num2, num3 - num2);
			}
		}
		return null;
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/BingTranslateLegitimate.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("BingTranslateLegitimate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BingTranslateLegitimate")]
[assembly: AssemblyTitle("BingTranslateLegitimate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BingTranslateLegitimate;

public class BingTranslateLegitimateEndpoint : HttpEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"af", "ar", "bn", "bs", "bg", "yue", "ca", "zh-Hans", "zh-Hant", "hr",
		"cs", "da", "nl", "en", "et", "fj", "fil", "fi", "fr", "de",
		"el", "ht", "he", "hi", "mww", "hu", "is", "id", "it", "ja",
		"sw", "tlh", "tlh-Qaak", "ko", "lv", "lt", "mg", "ms", "mt", "nb",
		"fa", "pl", "pt", "otq", "ro", "ru", "sm", "sr-Cyrl", "sr-Latn", "sk",
		"sl", "es", "sv", "ty", "ta", "te", "th", "to", "tr", "uk",
		"ur", "vi", "cy", "yua"
	};

	private static readonly string HttpsServicePointTemplateUrl = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from={0}&to={1}";

	private static readonly Random RandomNumbers = new Random();

	private static readonly string[] Accepts = new string[1] { "application/json" };

	private static readonly string[] ContentTypes = new string[1] { "application/json" };

	private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)];

	private static readonly string ContentType = ContentTypes[RandomNumbers.Next(ContentTypes.Length)];

	private string _key;

	public override string Id => "BingTranslateLegitimate";

	public override string FriendlyName => "Bing Translator (Authenticated)";

	public override int MaxTranslationsPerRequest => 10;

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-CN":
		case "zh":
			return "zh-Hans";
		case "zh-TW":
			return "zh-Hant";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_002d: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		_key = context.GetOrCreateSetting<string>("BingLegitimate", "OcpApimSubscriptionKey", "");
		if (string.IsNullOrEmpty(_key))
		{
			throw new EndpointInitializationException("The BingTranslateLegitimate endpoint requires an API key which has not been provided.");
		}
		context.DisableCertificateChecksFor(new string[1] { "api.cognitive.microsofttranslator.com" });
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Expected O, but got Unknown
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("[");
		for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++)
		{
			string value = JsonHelper.Escape(((ITranslationContextBase)context).UntranslatedTexts[i]);
			stringBuilder.Append("{\"Text\":\"");
			stringBuilder.Append(value);
			stringBuilder.Append("\"}");
			if (((ITranslationContextBase)context).UntranslatedTexts.Length - 1 != i)
			{
				stringBuilder.Append(",");
			}
		}
		stringBuilder.Append("]");
		XUnityWebRequest val = new XUnityWebRequest("POST", string.Format(HttpsServicePointTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage)), stringBuilder.ToString());
		if (Accept != null)
		{
			val.Headers[HttpRequestHeader.Accept] = Accept;
		}
		if (ContentType != null)
		{
			val.Headers[HttpRequestHeader.ContentType] = ContentType;
		}
		val.Headers["Ocp-Apim-Subscription-Key"] = _key;
		context.Complete(val);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		JSONArray asArray = JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsArray;
		List<string> list = new List<string>();
		for (int i = 0; i < ((JSONNode)asArray).Count; i++)
		{
			JSONNode obj = ((JSONNode)((JSONNode)asArray)[i].AsObject)["translations"];
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				JSONNode obj3 = ((JSONNode)obj.AsArray)[0];
				obj2 = ((obj3 != null) ? ((object)((JSONNode)obj3.AsObject)["text"])?.ToString() : null);
			}
			string text = (string)obj2;
			string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
			list.Add(item);
		}
		context.Complete(list.ToArray());
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/CustomTranslate.dll

Decompiled 2 years ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Web;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("CustomTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CustomTranslate")]
[assembly: AssemblyTitle("CustomTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CustomTranslate;

internal class CustomTranslateEndpoint : HttpEndpoint
{
	private static readonly string ServicePointTemplateUrl = "{0}?from={1}&to={2}&text={3}";

	private string _endpoint;

	private string _friendlyName;

	public override string Id => "CustomTranslate";

	public override string FriendlyName => _friendlyName;

	public CustomTranslateEndpoint()
	{
		_friendlyName = "Custom";
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		_endpoint = context.GetOrCreateSetting<string>("Custom", "Url", "");
		if (string.IsNullOrEmpty(_endpoint))
		{
			throw new EndpointInitializationException("The custom endpoint requires a url which has not been provided.");
		}
		Uri uri = new Uri(_endpoint);
		context.DisableCertificateChecksFor(new string[1] { uri.Host });
		_friendlyName = _friendlyName + " (" + uri.Host + ")";
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		XUnityWebRequest val = new XUnityWebRequest(string.Format(ServicePointTemplateUrl, _endpoint, ((ITranslationContextBase)context).SourceLanguage, ((ITranslationContextBase)context).DestinationLanguage, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText)));
		context.Complete(val);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		context.Complete(((IHttpResponseInspectionContext)context).Response.Data);
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/DeepLTranslate.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol;
using XUnity.Common.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("DeepLTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DeepLTranslate")]
[assembly: AssemblyTitle("DeepLTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace DeepLTranslate;

public class DeepLTranslate : ExtProtocolEndpoint
{
	private const float MinimumMinDelaySeconds = 1f;

	private const float MinimumMaxDelaySeconds = 3f;

	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"bg", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr",
		"hu", "it", "ja", "lt", "lv", "nl", "pl", "pt", "ro", "ru",
		"sk", "sl", "sv", "zh", "ko"
	};

	public override string Id => "DeepLTranslate";

	public override string FriendlyName => "DeepL Translator";

	public override int MaxConcurrency => 1;

	public override int MaxTranslationsPerRequest => 25;

	protected override string ConfigurationSectionName => "DeepL";

	private string FixLanguage(string lang)
	{
		if (lang == "zh-Hans" || lang == "zh-CN")
		{
			return "zh";
		}
		return lang;
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		((ExtProtocolEndpoint)this).Initialize(context);
		((ExtProtocolEndpoint)this).MinDelay = context.GetOrCreateSetting<float>("DeepL", "MinDelaySeconds", 2f);
		if (((ExtProtocolEndpoint)this).MinDelay < 1f)
		{
			XuaLogger.AutoTranslator.Warn($"[DeepL] Cannot set MinDelaySeconds below {1f} second(s). Setting MinDelaySeconds={1f}");
			context.SetSetting<float>("DeepL", "MinDelaySeconds", 1f);
		}
		((ExtProtocolEndpoint)this).MaxDelay = context.GetOrCreateSetting<float>("DeepL", "MaxDelaySeconds", 6f);
		if (((ExtProtocolEndpoint)this).MaxDelay < 3f)
		{
			XuaLogger.AutoTranslator.Warn($"[DeepL] Cannot set MaxDelaySeconds below {3f} second(s). Setting MaxDelaySeconds={3f}");
			context.SetSetting<float>("DeepL", "MaxDelaySeconds", 3f);
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
		((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("DeepLTranslate.ExtProtocol.ExtDeepLTranslate, DeepLTranslate.ExtProtocol"), Base64FormattingOptions.None);
	}
}
public class DeepLTranslateLegitimate : ExtProtocolEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"bg", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr",
		"hu", "it", "ja", "lt", "lv", "nl", "pl", "pt", "ro", "ru",
		"sk", "sl", "sv", "zh", "ko"
	};

	public override string Id => "DeepLTranslateLegitimate";

	public override string FriendlyName => "DeepL Translator (Authenticated)";

	public override int MaxConcurrency => 1;

	public override int MaxTranslationsPerRequest => 25;

	protected override string ConfigurationSectionName => "DeepLLegitimate";

	private string FixLanguage(string lang)
	{
		if (lang == "zh-Hans" || lang == "zh-CN")
		{
			return "zh";
		}
		return lang;
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		((ExtProtocolEndpoint)this).Initialize(context);
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
		string orCreateSetting = context.GetOrCreateSetting<string>(((ExtProtocolEndpoint)this).ConfigurationSectionName, "ApiKey", "");
		bool orCreateSetting2 = context.GetOrCreateSetting<bool>(((ExtProtocolEndpoint)this).ConfigurationSectionName, "Free", false);
		if (string.IsNullOrEmpty(orCreateSetting))
		{
			throw new EndpointInitializationException("The endpoint requires an API key which has not been provided.");
		}
		((ExtProtocolEndpoint)this).ConfigForExternalProcess = string.Join("\n", orCreateSetting, orCreateSetting2.ToString());
		((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("DeepLTranslate.ExtProtocol.ExtDeepLTranslateLegitimate, DeepLTranslate.ExtProtocol"), Base64FormattingOptions.None);
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/ezTransXP.dll

Decompiled 2 years ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.Win32;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("ezTransXP")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ezTransXP")]
[assembly: AssemblyTitle("ezTransXP")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ezTransXP;

public class ezTransXPEndpoint : ExtProtocolEndpoint
{
	public override string Id => "ezTransXP";

	public override string FriendlyName => "ezTransXP";

	public override int MaxConcurrency => 1;

	public override int MaxTranslationsPerRequest => 50;

	public override void Initialize(IInitializationContext context)
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		string defaultInstallationPath = GetDefaultInstallationPath();
		string text = context.GetOrCreateSetting<string>("ezTrans", "InstallationPath", defaultInstallationPath);
		if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(defaultInstallationPath))
		{
			context.SetSetting<string>("ezTrans", "InstallationPath", defaultInstallationPath);
			text = defaultInstallationPath;
		}
		context.DisableSpamChecks();
		string text2 = Path.Combine(context.TranslatorDirectory, "FullNET\\ezTransXP.ExtProtocol.exe");
		if (!File.Exists(text2))
		{
			throw new EndpointInitializationException("Could not find any executable at '" + text2 + "'");
		}
		((ExtProtocolEndpoint)this).ExecutablePath = text2;
		((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
		if (context.SourceLanguage != "ja")
		{
			throw new EndpointInitializationException("Current implementation only supports japanese-to-korean.");
		}
		if (context.DestinationLanguage != "ko")
		{
			throw new EndpointInitializationException("Current implementation only supports japanese-to-korean.");
		}
	}

	public static string GetDefaultInstallationPath()
	{
		try
		{
			return (string)Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\ChangShin\\ezTrans", "FilePath", null);
		}
		catch
		{
			return null;
		}
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Common.ExtProtocol.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using XUnity.AutoTranslator.Plugin.ExtProtocol;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: AssemblyCompany("Common.ExtProtocol")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Common.ExtProtocol")]
[assembly: AssemblyTitle("Common.ExtProtocol")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SimpleJSON
{
	public enum JSONNodeType
	{
		Array = 1,
		Object = 2,
		String = 3,
		Number = 4,
		NullValue = 5,
		Boolean = 6,
		None = 7,
		Custom = 255
	}
	public enum JSONTextMode
	{
		Compact,
		Indent
	}
	public abstract class JSONNode
	{
		public struct Enumerator
		{
			private enum Type
			{
				None,
				Array,
				Object
			}

			private Type type;

			private Dictionary<string, JSONNode>.Enumerator m_Object;

			private List<JSONNode>.Enumerator m_Array;

			public bool IsValid => type != Type.None;

			public KeyValuePair<string, JSONNode> Current
			{
				get
				{
					if (type == Type.Array)
					{
						return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
					}
					if (type == Type.Object)
					{
						return m_Object.Current;
					}
					return new KeyValuePair<string, JSONNode>(string.Empty, null);
				}
			}

			public Enumerator(List<JSONNode>.Enumerator aArrayEnum)
			{
				type = Type.Array;
				m_Object = default(Dictionary<string, JSONNode>.Enumerator);
				m_Array = aArrayEnum;
			}

			public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
			{
				type = Type.Object;
				m_Object = aDictEnum;
				m_Array = default(List<JSONNode>.Enumerator);
			}

			public bool MoveNext()
			{
				if (type == Type.Array)
				{
					return m_Array.MoveNext();
				}
				if (type == Type.Object)
				{
					return m_Object.MoveNext();
				}
				return false;
			}
		}

		public struct ValueEnumerator
		{
			private Enumerator m_Enumerator;

			public JSONNode Current => m_Enumerator.Current.Value;

			public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum)
				: this(new Enumerator(aArrayEnum))
			{
			}

			public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
				: this(new Enumerator(aDictEnum))
			{
			}

			public ValueEnumerator(Enumerator aEnumerator)
			{
				m_Enumerator = aEnumerator;
			}

			public bool MoveNext()
			{
				return m_Enumerator.MoveNext();
			}

			public ValueEnumerator GetEnumerator()
			{
				return this;
			}
		}

		public struct KeyEnumerator
		{
			private Enumerator m_Enumerator;

			public JSONNode Current => m_Enumerator.Current.Key;

			public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum)
				: this(new Enumerator(aArrayEnum))
			{
			}

			public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
				: this(new Enumerator(aDictEnum))
			{
			}

			public KeyEnumerator(Enumerator aEnumerator)
			{
				m_Enumerator = aEnumerator;
			}

			public bool MoveNext()
			{
				return m_Enumerator.MoveNext();
			}

			public KeyEnumerator GetEnumerator()
			{
				return this;
			}
		}

		public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable
		{
			private JSONNode m_Node;

			private Enumerator m_Enumerator;

			public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current;

			object IEnumerator.Current => m_Enumerator.Current;

			internal LinqEnumerator(JSONNode aNode)
			{
				m_Node = aNode;
				if (m_Node != null)
				{
					m_Enumerator = m_Node.GetEnumerator();
				}
			}

			public bool MoveNext()
			{
				return m_Enumerator.MoveNext();
			}

			public void Dispose()
			{
				m_Node = null;
				m_Enumerator = default(Enumerator);
			}

			public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator()
			{
				return new LinqEnumerator(m_Node);
			}

			public void Reset()
			{
				if (m_Node != null)
				{
					m_Enumerator = m_Node.GetEnumerator();
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return new LinqEnumerator(m_Node);
			}
		}

		public static bool forceASCII;

		[ThreadStatic]
		private static StringBuilder m_EscapeBuilder;

		public abstract JSONNodeType Tag { get; }

		public virtual JSONNode this[int aIndex]
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		public virtual JSONNode this[string aKey]
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		public virtual string Value
		{
			get
			{
				return "";
			}
			set
			{
			}
		}

		public virtual int Count => 0;

		public virtual bool IsNumber => false;

		public virtual bool IsString => false;

		public virtual bool IsBoolean => false;

		public virtual bool IsNull => false;

		public virtual bool IsArray => false;

		public virtual bool IsObject => false;

		public virtual bool Inline
		{
			get
			{
				return false;
			}
			set
			{
			}
		}

		public virtual IEnumerable<JSONNode> Children
		{
			get
			{
				yield break;
			}
		}

		public IEnumerable<JSONNode> DeepChildren
		{
			get
			{
				foreach (JSONNode child in Children)
				{
					foreach (JSONNode deepChild in child.DeepChildren)
					{
						yield return deepChild;
					}
				}
			}
		}

		public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this);

		public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator());

		public ValueEnumerator Values => new ValueEnumerator(GetEnumerator());

		public virtual double AsDouble
		{
			get
			{
				double result = 0.0;
				if (double.TryParse(Value, out result))
				{
					return result;
				}
				return 0.0;
			}
			set
			{
				Value = value.ToString();
			}
		}

		public virtual int AsInt
		{
			get
			{
				return (int)AsDouble;
			}
			set
			{
				AsDouble = value;
			}
		}

		public virtual float AsFloat
		{
			get
			{
				return (float)AsDouble;
			}
			set
			{
				AsDouble = value;
			}
		}

		public virtual bool AsBool
		{
			get
			{
				bool result = false;
				if (bool.TryParse(Value, out result))
				{
					return result;
				}
				return !string.IsNullOrEmpty(Value);
			}
			set
			{
				Value = (value ? "true" : "false");
			}
		}

		public virtual JSONArray AsArray => this as JSONArray;

		public virtual JSONObject AsObject => this as JSONObject;

		internal static StringBuilder EscapeBuilder
		{
			get
			{
				if (m_EscapeBuilder == null)
				{
					m_EscapeBuilder = new StringBuilder();
				}
				return m_EscapeBuilder;
			}
		}

		public virtual void Add(string aKey, JSONNode aItem)
		{
		}

		public virtual void Add(JSONNode aItem)
		{
			Add("", aItem);
		}

		public virtual JSONNode Remove(string aKey)
		{
			return null;
		}

		public virtual JSONNode Remove(int aIndex)
		{
			return null;
		}

		public virtual JSONNode Remove(JSONNode aNode)
		{
			return aNode;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact);
			return stringBuilder.ToString();
		}

		public virtual string ToString(int aIndent)
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent);
			return stringBuilder.ToString();
		}

		internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);

		public abstract Enumerator GetEnumerator();

		public static implicit operator JSONNode(string s)
		{
			return new JSONString(s);
		}

		public static implicit operator string(JSONNode d)
		{
			if (!(d == null))
			{
				return d.Value;
			}
			return null;
		}

		public static implicit operator JSONNode(double n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator double(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsDouble;
			}
			return 0.0;
		}

		public static implicit operator JSONNode(float n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator float(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsFloat;
			}
			return 0f;
		}

		public static implicit operator JSONNode(int n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator int(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsInt;
			}
			return 0;
		}

		public static implicit operator JSONNode(bool b)
		{
			return new JSONBool(b);
		}

		public static implicit operator bool(JSONNode d)
		{
			if (!(d == null))
			{
				return d.AsBool;
			}
			return false;
		}

		public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue)
		{
			return aKeyValue.Value;
		}

		public static bool operator ==(JSONNode a, object b)
		{
			if ((object)a == b)
			{
				return true;
			}
			bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator;
			bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator;
			if (flag && flag2)
			{
				return true;
			}
			if (!flag)
			{
				return a.Equals(b);
			}
			return false;
		}

		public static bool operator !=(JSONNode a, object b)
		{
			return !(a == b);
		}

		public override bool Equals(object obj)
		{
			return (object)this == obj;
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		internal static string Escape(string aText)
		{
			StringBuilder escapeBuilder = EscapeBuilder;
			escapeBuilder.Length = 0;
			if (escapeBuilder.Capacity < aText.Length + aText.Length / 10)
			{
				escapeBuilder.Capacity = aText.Length + aText.Length / 10;
			}
			foreach (char c in aText)
			{
				switch (c)
				{
				case '\\':
					escapeBuilder.Append("\\\\");
					continue;
				case '"':
					escapeBuilder.Append("\\\"");
					continue;
				case '\n':
					escapeBuilder.Append("\\n");
					continue;
				case '\r':
					escapeBuilder.Append("\\r");
					continue;
				case '\t':
					escapeBuilder.Append("\\t");
					continue;
				case '\b':
					escapeBuilder.Append("\\b");
					continue;
				case '\f':
					escapeBuilder.Append("\\f");
					continue;
				}
				if (c < ' ' || (forceASCII && c > '\u007f'))
				{
					ushort num = c;
					escapeBuilder.Append("\\u").Append(num.ToString("X4"));
				}
				else
				{
					escapeBuilder.Append(c);
				}
			}
			string result = escapeBuilder.ToString();
			escapeBuilder.Length = 0;
			return result;
		}

		private static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted)
		{
			if (quoted)
			{
				ctx.Add(tokenName, token);
				return;
			}
			string text = token.ToLower();
			switch (text)
			{
			case "false":
			case "true":
				ctx.Add(tokenName, text == "true");
				return;
			case "null":
				ctx.Add(tokenName, null);
				return;
			}
			if (double.TryParse(token, out var result))
			{
				ctx.Add(tokenName, result);
			}
			else
			{
				ctx.Add(tokenName, token);
			}
		}

		public static JSONNode Parse(string aJSON)
		{
			Stack<JSONNode> stack = new Stack<JSONNode>();
			JSONNode jSONNode = null;
			int i = 0;
			StringBuilder stringBuilder = new StringBuilder();
			string text = "";
			bool flag = false;
			bool flag2 = false;
			for (; i < aJSON.Length; i++)
			{
				switch (aJSON[i])
				{
				case '{':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					stack.Push(new JSONObject());
					if (jSONNode != null)
					{
						jSONNode.Add(text, stack.Peek());
					}
					text = "";
					stringBuilder.Length = 0;
					jSONNode = stack.Peek();
					break;
				case '[':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					stack.Push(new JSONArray());
					if (jSONNode != null)
					{
						jSONNode.Add(text, stack.Peek());
					}
					text = "";
					stringBuilder.Length = 0;
					jSONNode = stack.Peek();
					break;
				case ']':
				case '}':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					if (stack.Count == 0)
					{
						throw new Exception("JSON Parse: Too many closing brackets");
					}
					stack.Pop();
					if (stringBuilder.Length > 0 || flag2)
					{
						ParseElement(jSONNode, stringBuilder.ToString(), text, flag2);
						flag2 = false;
					}
					text = "";
					stringBuilder.Length = 0;
					if (stack.Count > 0)
					{
						jSONNode = stack.Peek();
					}
					break;
				case ':':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					text = stringBuilder.ToString();
					stringBuilder.Length = 0;
					flag2 = false;
					break;
				case '"':
					flag = !flag;
					flag2 = flag2 || flag;
					break;
				case ',':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					if (stringBuilder.Length > 0 || flag2)
					{
						ParseElement(jSONNode, stringBuilder.ToString(), text, flag2);
						flag2 = false;
					}
					text = "";
					stringBuilder.Length = 0;
					flag2 = false;
					break;
				case '\t':
				case ' ':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
					}
					break;
				case '\\':
					i++;
					if (flag)
					{
						char c = aJSON[i];
						switch (c)
						{
						case 't':
							stringBuilder.Append('\t');
							break;
						case 'r':
							stringBuilder.Append('\r');
							break;
						case 'n':
							stringBuilder.Append('\n');
							break;
						case 'b':
							stringBuilder.Append('\b');
							break;
						case 'f':
							stringBuilder.Append('\f');
							break;
						case 'u':
						{
							string s = aJSON.Substring(i + 1, 4);
							stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier));
							i += 4;
							break;
						}
						default:
							stringBuilder.Append(c);
							break;
						}
					}
					break;
				default:
					stringBuilder.Append(aJSON[i]);
					break;
				case '\n':
				case '\r':
					break;
				}
			}
			if (flag)
			{
				throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
			}
			return jSONNode;
		}
	}
	public class JSONArray : JSONNode
	{
		private List<JSONNode> m_List = new List<JSONNode>();

		private bool inline;

		public override bool Inline
		{
			get
			{
				return inline;
			}
			set
			{
				inline = value;
			}
		}

		public override JSONNodeType Tag => JSONNodeType.Array;

		public override bool IsArray => true;

		public override JSONNode this[int aIndex]
		{
			get
			{
				if (aIndex < 0 || aIndex >= m_List.Count)
				{
					return new JSONLazyCreator(this);
				}
				return m_List[aIndex];
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (aIndex < 0 || aIndex >= m_List.Count)
				{
					m_List.Add(value);
				}
				else
				{
					m_List[aIndex] = value;
				}
			}
		}

		public override JSONNode this[string aKey]
		{
			get
			{
				return new JSONLazyCreator(this);
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				m_List.Add(value);
			}
		}

		public override int Count => m_List.Count;

		public override IEnumerable<JSONNode> Children
		{
			get
			{
				foreach (JSONNode item in m_List)
				{
					yield return item;
				}
			}
		}

		public override Enumerator GetEnumerator()
		{
			return new Enumerator(m_List.GetEnumerator());
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			if (aItem == null)
			{
				aItem = JSONNull.CreateOrGet();
			}
			m_List.Add(aItem);
		}

		public override JSONNode Remove(int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_List.Count)
			{
				return null;
			}
			JSONNode result = m_List[aIndex];
			m_List.RemoveAt(aIndex);
			return result;
		}

		public override JSONNode Remove(JSONNode aNode)
		{
			m_List.Remove(aNode);
			return aNode;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('[');
			int count = m_List.Count;
			if (inline)
			{
				aMode = JSONTextMode.Compact;
			}
			for (int i = 0; i < count; i++)
			{
				if (i > 0)
				{
					aSB.Append(',');
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.AppendLine();
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.Append(' ', aIndent + aIndentInc);
				}
				m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
			}
			if (aMode == JSONTextMode.Indent)
			{
				aSB.AppendLine().Append(' ', aIndent);
			}
			aSB.Append(']');
		}
	}
	public class JSONObject : JSONNode
	{
		private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();

		private bool inline;

		public override bool Inline
		{
			get
			{
				return inline;
			}
			set
			{
				inline = value;
			}
		}

		public override JSONNodeType Tag => JSONNodeType.Object;

		public override bool IsObject => true;

		public override JSONNode this[string aKey]
		{
			get
			{
				if (m_Dict.ContainsKey(aKey))
				{
					return m_Dict[aKey];
				}
				return new JSONLazyCreator(this, aKey);
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (m_Dict.ContainsKey(aKey))
				{
					m_Dict[aKey] = value;
				}
				else
				{
					m_Dict.Add(aKey, value);
				}
			}
		}

		public override JSONNode this[int aIndex]
		{
			get
			{
				if (aIndex < 0 || aIndex >= m_Dict.Count)
				{
					return null;
				}
				return m_Dict.ElementAt(aIndex).Value;
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (aIndex >= 0 && aIndex < m_Dict.Count)
				{
					string key = m_Dict.ElementAt(aIndex).Key;
					m_Dict[key] = value;
				}
			}
		}

		public override int Count => m_Dict.Count;

		public override IEnumerable<JSONNode> Children
		{
			get
			{
				foreach (KeyValuePair<string, JSONNode> item in m_Dict)
				{
					yield return item.Value;
				}
			}
		}

		public override Enumerator GetEnumerator()
		{
			return new Enumerator(m_Dict.GetEnumerator());
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			if (aItem == null)
			{
				aItem = JSONNull.CreateOrGet();
			}
			if (!string.IsNullOrEmpty(aKey))
			{
				if (m_Dict.ContainsKey(aKey))
				{
					m_Dict[aKey] = aItem;
				}
				else
				{
					m_Dict.Add(aKey, aItem);
				}
			}
			else
			{
				m_Dict.Add(Guid.NewGuid().ToString(), aItem);
			}
		}

		public override JSONNode Remove(string aKey)
		{
			if (!m_Dict.ContainsKey(aKey))
			{
				return null;
			}
			JSONNode result = m_Dict[aKey];
			m_Dict.Remove(aKey);
			return result;
		}

		public override JSONNode Remove(int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_Dict.Count)
			{
				return null;
			}
			KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex);
			m_Dict.Remove(keyValuePair.Key);
			return keyValuePair.Value;
		}

		public override JSONNode Remove(JSONNode aNode)
		{
			try
			{
				KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First();
				m_Dict.Remove(keyValuePair.Key);
				return aNode;
			}
			catch
			{
				return null;
			}
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('{');
			bool flag = true;
			if (inline)
			{
				aMode = JSONTextMode.Compact;
			}
			foreach (KeyValuePair<string, JSONNode> item in m_Dict)
			{
				if (!flag)
				{
					aSB.Append(',');
				}
				flag = false;
				if (aMode == JSONTextMode.Indent)
				{
					aSB.AppendLine();
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.Append(' ', aIndent + aIndentInc);
				}
				aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"');
				if (aMode == JSONTextMode.Compact)
				{
					aSB.Append(':');
				}
				else
				{
					aSB.Append(" : ");
				}
				item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
			}
			if (aMode == JSONTextMode.Indent)
			{
				aSB.AppendLine().Append(' ', aIndent);
			}
			aSB.Append('}');
		}
	}
	public class JSONString : JSONNode
	{
		private string m_Data;

		public override JSONNodeType Tag => JSONNodeType.String;

		public override bool IsString => true;

		public override string Value
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONString(string aData)
		{
			m_Data = aData;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"');
		}

		public override bool Equals(object obj)
		{
			if (base.Equals(obj))
			{
				return true;
			}
			if (obj is string text)
			{
				return m_Data == text;
			}
			JSONString jSONString = obj as JSONString;
			if (jSONString != null)
			{
				return m_Data == jSONString.m_Data;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}
	}
	public class JSONNumber : JSONNode
	{
		private double m_Data;

		public override JSONNodeType Tag => JSONNodeType.Number;

		public override bool IsNumber => true;

		public override string Value
		{
			get
			{
				return m_Data.ToString();
			}
			set
			{
				if (double.TryParse(value, out var result))
				{
					m_Data = result;
				}
			}
		}

		public override double AsDouble
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONNumber(double aData)
		{
			m_Data = aData;
		}

		public JSONNumber(string aData)
		{
			Value = aData;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append(m_Data);
		}

		private static bool IsNumeric(object value)
		{
			if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte))
			{
				return value is byte;
			}
			return true;
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (base.Equals(obj))
			{
				return true;
			}
			JSONNumber jSONNumber = obj as JSONNumber;
			if (jSONNumber != null)
			{
				return m_Data == jSONNumber.m_Data;
			}
			if (IsNumeric(obj))
			{
				return Convert.ToDouble(obj) == m_Data;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}
	}
	public class JSONBool : JSONNode
	{
		private bool m_Data;

		public override JSONNodeType Tag => JSONNodeType.Boolean;

		public override bool IsBoolean => true;

		public override string Value
		{
			get
			{
				return m_Data.ToString();
			}
			set
			{
				if (bool.TryParse(value, out var result))
				{
					m_Data = result;
				}
			}
		}

		public override bool AsBool
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONBool(bool aData)
		{
			m_Data = aData;
		}

		public JSONBool(string aData)
		{
			Value = aData;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append(m_Data ? "true" : "false");
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (obj is bool)
			{
				return m_Data == (bool)obj;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}
	}
	public class JSONNull : JSONNode
	{
		private static JSONNull m_StaticInstance = new JSONNull();

		public static bool reuseSameInstance = true;

		public override JSONNodeType Tag => JSONNodeType.NullValue;

		public override bool IsNull => true;

		public override string Value
		{
			get
			{
				return "null";
			}
			set
			{
			}
		}

		public override bool AsBool
		{
			get
			{
				return false;
			}
			set
			{
			}
		}

		public static JSONNull CreateOrGet()
		{
			if (reuseSameInstance)
			{
				return m_StaticInstance;
			}
			return new JSONNull();
		}

		private JSONNull()
		{
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public override bool Equals(object obj)
		{
			if ((object)this == obj)
			{
				return true;
			}
			return obj is JSONNull;
		}

		public override int GetHashCode()
		{
			return 0;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append("null");
		}
	}
	internal class JSONLazyCreator : JSONNode
	{
		private JSONNode m_Node;

		private string m_Key;

		public override JSONNodeType Tag => JSONNodeType.None;

		public override JSONNode this[int aIndex]
		{
			get
			{
				return new JSONLazyCreator(this);
			}
			set
			{
				JSONArray jSONArray = new JSONArray();
				jSONArray.Add(value);
				Set(jSONArray);
			}
		}

		public override JSONNode this[string aKey]
		{
			get
			{
				return new JSONLazyCreator(this, aKey);
			}
			set
			{
				JSONObject jSONObject = new JSONObject();
				jSONObject.Add(aKey, value);
				Set(jSONObject);
			}
		}

		public override int AsInt
		{
			get
			{
				JSONNumber aVal = new JSONNumber(0.0);
				Set(aVal);
				return 0;
			}
			set
			{
				JSONNumber aVal = new JSONNumber(value);
				Set(aVal);
			}
		}

		public override float AsFloat
		{
			get
			{
				JSONNumber aVal = new JSONNumber(0.0);
				Set(aVal);
				return 0f;
			}
			set
			{
				JSONNumber aVal = new JSONNumber(value);
				Set(aVal);
			}
		}

		public override double AsDouble
		{
			get
			{
				JSONNumber aVal = new JSONNumber(0.0);
				Set(aVal);
				return 0.0;
			}
			set
			{
				JSONNumber aVal = new JSONNumber(value);
				Set(aVal);
			}
		}

		public override bool AsBool
		{
			get
			{
				JSONBool aVal = new JSONBool(aData: false);
				Set(aVal);
				return false;
			}
			set
			{
				JSONBool aVal = new JSONBool(value);
				Set(aVal);
			}
		}

		public override JSONArray AsArray
		{
			get
			{
				JSONArray jSONArray = new JSONArray();
				Set(jSONArray);
				return jSONArray;
			}
		}

		public override JSONObject AsObject
		{
			get
			{
				JSONObject jSONObject = new JSONObject();
				Set(jSONObject);
				return jSONObject;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONLazyCreator(JSONNode aNode)
		{
			m_Node = aNode;
			m_Key = null;
		}

		public JSONLazyCreator(JSONNode aNode, string aKey)
		{
			m_Node = aNode;
			m_Key = aKey;
		}

		private void Set(JSONNode aVal)
		{
			if (m_Key == null)
			{
				m_Node.Add(aVal);
			}
			else
			{
				m_Node.Add(m_Key, aVal);
			}
			m_Node = null;
		}

		public override void Add(JSONNode aItem)
		{
			JSONArray jSONArray = new JSONArray();
			jSONArray.Add(aItem);
			Set(jSONArray);
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			JSONObject jSONObject = new JSONObject();
			jSONObject.Add(aKey, aItem);
			Set(jSONObject);
		}

		public static bool operator ==(JSONLazyCreator a, object b)
		{
			if (b == null)
			{
				return true;
			}
			return (object)a == b;
		}

		public static bool operator !=(JSONLazyCreator a, object b)
		{
			return !(a == b);
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return true;
			}
			return (object)this == obj;
		}

		public override int GetHashCode()
		{
			return 0;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append("null");
		}
	}
	public static class JSON
	{
		public static JSONNode Parse(string aJSON)
		{
			return JSONNode.Parse(aJSON);
		}
	}
}
namespace Common.ExtProtocol
{
	public interface IExtTranslateEndpoint
	{
		Task Translate(ITranslationContext context);

		void Initialize(string config);
	}
	public interface ITranslationContext : ITranslationContextBase
	{
		void Complete(string translatedText);

		void Complete(string[] translatedTexts);
	}
	public interface ITranslationContextBase
	{
		string UntranslatedText { get; }

		string[] UntranslatedTexts { get; }

		UntranslatedTextInfo UntranslatedTextInfo { get; }

		UntranslatedTextInfo[] UntranslatedTextInfos { get; }

		string SourceLanguage { get; }

		string DestinationLanguage { get; }

		object UserState { get; set; }

		void Fail(string reason, Exception exception);

		void Fail(string reason);
	}
	public class TranslationContext : ITranslationContext, ITranslationContextBase
	{
		private string[] _untranslatedTexts;

		public string UntranslatedText => UntranslatedTexts[0];

		public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((UntranslatedTextInfo x) => x.UntranslatedText).ToArray());

		public UntranslatedTextInfo UntranslatedTextInfo => UntranslatedTextInfos[0];

		public UntranslatedTextInfo[] UntranslatedTextInfos { get; }

		public string SourceLanguage { get; }

		public string DestinationLanguage { get; }

		internal bool IsDone { get; private set; }

		public string[] TranslatedTexts { get; private set; }

		public string ErrorMessage { get; private set; }

		public Exception Error { get; private set; }

		public object UserState { get; set; }

		public TranslationContext(TransmittableUntranslatedTextInfo[] untranslatedTexts, string sourceLanguage, string destinationLanguage)
		{
			UntranslatedTextInfos = untranslatedTexts.Select((TransmittableUntranslatedTextInfo x) => new UntranslatedTextInfo(x)).ToArray();
			SourceLanguage = sourceLanguage;
			DestinationLanguage = destinationLanguage;
		}

		public void Complete(string translatedText)
		{
			Complete(new string[1] { translatedText });
		}

		public void Complete(string[] translatedTexts)
		{
			if (IsDone)
			{
				return;
			}
			try
			{
				if (translatedTexts.Length == 0)
				{
					FailContext("Received empty translation from translator.", null);
					return;
				}
				for (int i = 0; i < translatedTexts.Length; i++)
				{
					if (string.IsNullOrEmpty(translatedTexts[0]))
					{
						FailContext("Received empty translation from translator.", null);
						return;
					}
				}
				CompleteContext(translatedTexts);
			}
			finally
			{
				IsDone = true;
			}
		}

		public void Fail(string reason, Exception exception)
		{
			if (IsDone)
			{
				return;
			}
			try
			{
				FailContext(reason, exception);
				throw new TranslationContextException();
			}
			finally
			{
				IsDone = true;
			}
		}

		public void Fail(string reason)
		{
			if (IsDone)
			{
				return;
			}
			try
			{
				FailContext(reason, null);
				throw new TranslationContextException();
			}
			finally
			{
				IsDone = true;
			}
		}

		public void FailWithoutThrowing(string reason, Exception exception)
		{
			if (IsDone)
			{
				return;
			}
			try
			{
				FailContext(reason, exception);
			}
			finally
			{
				IsDone = true;
			}
		}

		internal void FailIfNotCompleted()
		{
			if (!IsDone)
			{
				FailWithoutThrowing("The translation request was not completed before returning from translator.", null);
			}
		}

		public void FailContext(string reason, Exception exception)
		{
			ErrorMessage = reason;
			Error = exception;
		}

		public void CompleteContext(string[] translatedTexts)
		{
			TranslatedTexts = translatedTexts;
		}
	}
	[Serializable]
	internal class TranslationContextException : Exception
	{
		public TranslationContextException()
		{
		}

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

		public TranslationContextException(string message, Exception inner)
			: base(message, inner)
		{
		}

		protected TranslationContextException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}
	}
	public class UntranslatedTextInfo
	{
		public string[] ContextBefore { get; }

		public string UntranslatedText { get; }

		public string[] ContextAfter { get; }

		public UntranslatedTextInfo(TransmittableUntranslatedTextInfo untranslatedTextInfo)
		{
			ContextBefore = untranslatedTextInfo.ContextBefore;
			UntranslatedText = untranslatedTextInfo.UntranslatedText;
			ContextAfter = untranslatedTextInfo.ContextAfter;
		}

		public UntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter)
		{
			ContextBefore = contextBefore;
			UntranslatedText = untranslatedText;
			ContextAfter = contextAfter;
		}
	}
}
namespace Common.ExtProtocol.Utilities
{
	public static class JsonHelper
	{
		public static string Unescape(string str)
		{
			if (str == null)
			{
				return null;
			}
			StringBuilder stringBuilder = new StringBuilder(str);
			bool flag = false;
			for (int i = 0; i < stringBuilder.Length; i++)
			{
				char c = stringBuilder[i];
				if (flag)
				{
					bool flag2 = true;
					char c2 = '\0';
					switch (c)
					{
					case 'b':
						c2 = '\b';
						break;
					case 'f':
						c2 = '\f';
						break;
					case 'n':
						c2 = '\n';
						break;
					case 'r':
						c2 = '\r';
						break;
					case 't':
						c2 = '\t';
						break;
					case '"':
						c2 = '"';
						break;
					case '\\':
						c2 = '\\';
						break;
					case 'u':
						c2 = 'u';
						break;
					default:
						flag2 = false;
						break;
					}
					if (flag2)
					{
						if (c2 == 'u')
						{
							char value = (char)int.Parse(new string(new char[4]
							{
								stringBuilder[i + 1],
								stringBuilder[i + 2],
								stringBuilder[i + 3],
								stringBuilder[i + 4]
							}), NumberStyles.HexNumber);
							stringBuilder.Remove(--i, 6);
							stringBuilder.Insert(i, value);
						}
						else
						{
							stringBuilder.Remove(--i, 2);
							stringBuilder.Insert(i, c2);
						}
					}
					flag = false;
				}
				else if (c == '\\')
				{
					flag = true;
				}
			}
			return stringBuilder.ToString();
		}

		public static string Escape(string str)
		{
			if (str == null || str.Length == 0)
			{
				return "";
			}
			int length = str.Length;
			StringBuilder stringBuilder = new StringBuilder(length + 4);
			for (int i = 0; i < length; i++)
			{
				char c = str[i];
				switch (c)
				{
				case '"':
				case '\\':
					stringBuilder.Append('\\');
					stringBuilder.Append(c);
					break;
				case '\b':
					stringBuilder.Append("\\b");
					break;
				case '\t':
					stringBuilder.Append("\\t");
					break;
				case '\n':
					stringBuilder.Append("\\n");
					break;
				case '\f':
					stringBuilder.Append("\\f");
					break;
				case '\r':
					stringBuilder.Append("\\r");
					break;
				case '\u0085':
					stringBuilder.Append("\\u0085");
					break;
				case '\u2028':
					stringBuilder.Append("\\u2028");
					break;
				case '\u2029':
					stringBuilder.Append("\\u2029");
					break;
				default:
					stringBuilder.Append(c);
					break;
				}
			}
			return stringBuilder.ToString();
		}
	}
	public static class StringBuilderExtensions
	{
		public static bool EndsWithWhitespaceOrNewline(this StringBuilder builder)
		{
			if (builder.Length == 0)
			{
				return true;
			}
			char c = builder[builder.Length - 1];
			if (!char.IsWhiteSpace(c))
			{
				return c == '\n';
			}
			return true;
		}
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/DeepLTranslate.ExtProtocol.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Common.ExtProtocol;
using Common.ExtProtocol.Utilities;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using SimpleJSON;

[assembly: AssemblyProduct("DeepLTranslate.ExtProtocol")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCompany("DeepLTranslate.ExtProtocol")]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyTitle("DeepLTranslate.ExtProtocol")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DeepLTranslate.ExtProtocol
{
	[Serializable]
	public class BlockedException : Exception
	{
		public BlockedException()
		{
		}

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

		public BlockedException(string message, Exception inner)
			: base(message, inner)
		{
		}

		protected BlockedException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}
	}
	public static class HttpResponseMessageExtensions
	{
		public static void ThrowIfBlocked(this HttpResponseMessage msg)
		{
			if (msg.StatusCode == HttpStatusCode.TooManyRequests)
			{
				throw new Exception("Too many requests!");
			}
		}
	}
	public class ExtDeepLTranslate : IExtTranslateEndpoint
	{
		private class UntranslatedTextInfo
		{
			public string UntranslatedText { get; set; }

			public List<TranslationPart> TranslationParts { get; set; }
		}

		public class TranslationPart
		{
			public bool IsTranslatable { get; set; }

			public string Value { get; set; }
		}

		private static readonly Regex NewlineSplitter;

		private static readonly DateTime Epoch;

		private static readonly string HttpsServicePointTemplateUrl;

		private static readonly string HttpsTranslateUserSite;

		private static readonly string HttpsTranslateStateSetup;

		private static readonly Random RandomNumbers;

		private static readonly string[] Accepts;

		private static readonly string[] AcceptLanguages;

		private static readonly string[] Referers;

		private static readonly string[] Origins;

		private static readonly string Accept;

		private static readonly string AcceptLanguage;

		private static readonly string Referer;

		private static readonly string Origin;

		private SemaphoreSlim _sem;

		private HttpClient _client;

		private HttpClientHandler _handler;

		private bool _hasSetup;

		private int _translationCount;

		private int _resetAfter = RandomNumbers.Next(75, 125);

		private long _id;

		static ExtDeepLTranslate()
		{
			NewlineSplitter = new Regex("([\\s]*[\\r\\n]+[\\s]*)");
			Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
			HttpsServicePointTemplateUrl = "https://www2.deepl.com/jsonrpc";
			HttpsTranslateUserSite = "https://www.deepl.com/translator";
			HttpsTranslateStateSetup = "https://www.deepl.com/PHP/backend/clientState.php?request_type=jsonrpc&il=EN";
			RandomNumbers = new Random();
			Accepts = new string[1] { "*/*" };
			AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" };
			Referers = new string[1] { "https://www.deepl.com/translator" };
			Origins = new string[1] { "https://www.deepl.com" };
			Accept = Accepts[RandomNumbers.Next(Accepts.Length)];
			AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)];
			Referer = Referers[RandomNumbers.Next(Referers.Length)];
			Origin = Origins[RandomNumbers.Next(Origins.Length)];
			ServicePointManager.SecurityProtocol |= SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
		}

		public ExtDeepLTranslate()
		{
			_sem = new SemaphoreSlim(1, 1);
		}

		public void Initialize(string config)
		{
		}

		public void Reset()
		{
			_hasSetup = false;
		}

		private void CreateClientAndHandler()
		{
			if (_client != null)
			{
				_client.Dispose();
			}
			_handler = new HttpClientHandler();
			_handler.CookieContainer = new CookieContainer();
			_handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
			_client = new HttpClient(_handler, disposeHandler: true);
			_client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36");
		}

		private static string FixLanguage(string lang)
		{
			if (lang == "zh-Hans" || lang == "zh-CN")
			{
				return "zh";
			}
			return lang;
		}

		public async Task EnsureSetupState()
		{
			if (!_hasSetup || _translationCount % _resetAfter == 0)
			{
				_resetAfter = RandomNumbers.Next(75, 125);
				_hasSetup = true;
				_id = 10000 * (long)(10000.0 * RandomNumbers.NextDouble());
				CreateClientAndHandler();
				await SetupState();
			}
		}

		public async Task SetupState()
		{
			_translationCount = 0;
			await RequestWebsite();
			await GetClientState();
		}

		private void AddHeaders(HttpRequestMessage request, HttpContent content, bool isTranslationRequest)
		{
			if (AcceptLanguage != null)
			{
				request.Headers.TryAddWithoutValidation("Accept-Language", AcceptLanguage);
			}
			if (Accept != null)
			{
				request.Headers.TryAddWithoutValidation("Accept", Accept);
			}
			if (Referer != null && isTranslationRequest)
			{
				request.Headers.TryAddWithoutValidation("Referer", Referer);
			}
			if (Origin != null && isTranslationRequest)
			{
				request.Headers.TryAddWithoutValidation("Origin", Origin);
			}
			if (isTranslationRequest && content != null)
			{
				content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
			}
			request.Headers.TryAddWithoutValidation("DNT", "1");
		}

		public async Task Translate(ITranslationContext context)
		{
			_ = 3;
			try
			{
				await _sem.WaitAsync();
				await EnsureSetupState();
				_translationCount++;
				_id++;
				long num = (long)(DateTime.UtcNow - Epoch).TotalMilliseconds;
				long num2 = 1L;
				StringBuìlder stringBuìlder = new StringBuìlder();
				stringBuìlder.Append("{\"jsonrpc\":\"2.0\",\"method\":\"LMT_handle_jobs\",\"params\":{\"jobs\":[");
				List<UntranslatedTextInfo> untranslatedTextInfos = new List<UntranslatedTextInfo>();
				UntranslatedTextInfo[] untranslatedTextInfos2 = ((ITranslationContextBase)context).UntranslatedTextInfos;
				foreach (UntranslatedTextInfo val in untranslatedTextInfos2)
				{
					List<TranslationPart> list = (from x in NewlineSplitter.Split(val.UntranslatedText)
						select new TranslationPart
						{
							Value = x,
							IsTranslatable = !NewlineSplitter.IsMatch(x)
						}).ToList();
					string[] array = (from x in list
						where x.IsTranslatable
						select x.Value).ToArray();
					for (int j = 0; j < array.Length; j++)
					{
						string text = array[j];
						stringBuìlder.Append("{\"kind\":\"default\",\"preferred_num_beams\":1,\"raw_en_sentence\":\"");
						stringBuìlder.Append(JsonHelper.Escape(text));
						HashSet<string> hashSet = new HashSet<string>();
						stringBuìlder.Append("\",\"raw_en_context_before\":[");
						bool flag = false;
						string[] contextBefore = val.ContextBefore;
						foreach (string text2 in contextBefore)
						{
							if (!hashSet.Contains(text2))
							{
								stringBuìlder.Append("\"");
								stringBuìlder.Append(JsonHelper.Escape(text2));
								stringBuìlder.Append("\"");
								stringBuìlder.Append(",");
								flag = true;
							}
						}
						for (int l = 0; l < j; l++)
						{
							if (!hashSet.Contains(array[l]))
							{
								stringBuìlder.Append("\"");
								stringBuìlder.Append(JsonHelper.Escape(array[l]));
								stringBuìlder.Append("\"");
								stringBuìlder.Append(",");
								flag = true;
							}
						}
						if (flag)
						{
							stringBuìlder.Remove(stringBuìlder.Length - 1, 1);
						}
						stringBuìlder.Append("],\"raw_en_context_after\":[");
						bool flag2 = false;
						for (int m = j + 1; m < array.Length; m++)
						{
							if (!hashSet.Contains(array[m]))
							{
								stringBuìlder.Append("\"");
								stringBuìlder.Append(JsonHelper.Escape(array[m]));
								stringBuìlder.Append("\"");
								stringBuìlder.Append(",");
								flag2 = true;
							}
						}
						contextBefore = val.ContextAfter;
						foreach (string text3 in contextBefore)
						{
							if (!hashSet.Contains(text3))
							{
								stringBuìlder.Append("\"");
								stringBuìlder.Append(JsonHelper.Escape(text3));
								stringBuìlder.Append("\"");
								stringBuìlder.Append(",");
								flag2 = true;
							}
						}
						if (flag2)
						{
							stringBuìlder.Remove(stringBuìlder.Length - 1, 1);
						}
						stringBuìlder.Append("]},");
						num2 += text.Count((char c) => c == 'i');
					}
					untranslatedTextInfos.Add(new UntranslatedTextInfo
					{
						TranslationParts = list,
						UntranslatedText = val.UntranslatedText
					});
				}
				stringBuìlder.Remove(stringBuìlder.Length - 1, 1);
				long num3 = num + (num2 - num % num2);
				stringBuìlder.Append("],\"lang\":{\"user_preferred_langs\":[\"");
				stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant());
				stringBuìlder.Append("\",\"");
				stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant());
				stringBuìlder.Append("\"],\"source_lang_user_selected\":\"");
				stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant());
				stringBuìlder.Append("\",\"target_lang\":\"");
				stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant());
				stringBuìlder.Append("\"},\"priority\":-1,\"timestamp\":");
				stringBuìlder.Append(num3.ToString(CultureInfo.InvariantCulture));
				stringBuìlder.Append("},\"id\":");
				stringBuìlder.Append(_id);
				stringBuìlder.Append("}");
				StringContent content = new StringContent(stringBuìlder.ToString());
				using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, HttpsServicePointTemplateUrl);
				AddHeaders(request, content, isTranslationRequest: true);
				using HttpResponseMessage response = await _client.PostAsync(HttpsServicePointTemplateUrl, content);
				response.ThrowIfBlocked();
				response.EnsureSuccessStatusCode();
				ExtractTranslation(await response.Content.ReadAsStringAsync(), untranslatedTextInfos, context);
			}
			catch (BlockedException)
			{
				Reset();
				throw;
			}
			finally
			{
				_sem.Release();
			}
		}

		private void ExtractTranslation(string data, List<UntranslatedTextInfo> untranslatedTextInfos, ITranslationContext context)
		{
			JSONArray asArray = JSON.Parse(data)["result"]["translations"].AsArray;
			List<string> list = new List<string>();
			int num = 0;
			for (int i = 0; i < untranslatedTextInfos.Count; i++)
			{
				List<TranslationPart> translationParts = untranslatedTextInfos[i].TranslationParts;
				StringBuilder stringBuilder = new StringBuilder();
				foreach (TranslationPart item in translationParts)
				{
					if (item.IsTranslatable)
					{
						JSONArray asArray2 = ((JSONNode)asArray)[num++]["beams"].AsArray;
						if (((JSONNode)asArray2).Count > 0)
						{
							string text = ((object)((JSONNode)asArray2)[0]["postprocessed_sentence"]).ToString();
							string value = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
							stringBuilder.Append(value);
						}
					}
					else
					{
						stringBuilder.Append(item.Value);
					}
				}
				string text2 = stringBuilder.ToString();
				if (string.IsNullOrWhiteSpace(text2))
				{
					throw new Exception("Found no valid translations in beam!");
				}
				list.Add(text2);
			}
			context.Complete(list.ToArray());
		}

		public async Task RequestWebsite()
		{
			using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, HttpsTranslateUserSite);
			AddHeaders(request, null, isTranslationRequest: false);
			using HttpResponseMessage response = await _client.SendAsync(request);
			response.ThrowIfBlocked();
			response.EnsureSuccessStatusCode();
			await response.Content.ReadAsStringAsync();
		}

		public async Task GetClientState()
		{
			_id++;
			StringBuìlder stringBuìlder = new StringBuìlder();
			stringBuìlder.Append("{\"jsonrpc\":\"2.0\",\"method\":\"getClientState\",\"params\":{\"v\":\"20180814\"},\"id\":");
			stringBuìlder.Append(_id);
			stringBuìlder.Append("}");
			StringContent content = new StringContent(stringBuìlder.ToString());
			using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, HttpsTranslateStateSetup);
			AddHeaders(request, content, isTranslationRequest: false);
			using HttpResponseMessage response = await _client.SendAsync(request);
			response.ThrowIfBlocked();
			response.EnsureSuccessStatusCode();
			await response.Content.ReadAsStringAsync();
		}

		public void Dispose()
		{
			_client?.Dispose();
		}
	}
	public class ExtDeepLTranslateLegitimate : IExtTranslateEndpoint
	{
		private class UntranslatedTextInfo
		{
			public string UntranslatedText { get; set; }

			public List<TranslationPart> TranslationParts { get; set; }
		}

		public class TranslationPart
		{
			public bool IsTranslatable { get; set; }

			public string Value { get; set; }
		}

		private class TranslationResponse
		{
			public List<Translation> translations { get; set; }
		}

		private class Translation
		{
			public string detected_source_language { get; set; }

			public string text { get; set; }
		}

		private string _httpsServicePointTemplateUrl = "https://api.deepl.com/v2/translate?auth_key={0}";

		private HttpClient _client;

		private HttpClientHandler _handler;

		private string _apiKey;

		static ExtDeepLTranslateLegitimate()
		{
			ServicePointManager.SecurityProtocol |= SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
		}

		public ExtDeepLTranslateLegitimate()
		{
			CreateClientAndHandler();
		}

		public void Initialize(string config)
		{
			string[] array = config.Split(new char[1] { '\n' }, StringSplitOptions.None);
			_apiKey = array[0];
			if (string.Equals(array[1], "true", StringComparison.OrdinalIgnoreCase))
			{
				_httpsServicePointTemplateUrl = "https://api-free.deepl.com/v2/translate?auth_key={0}";
			}
			else
			{
				_httpsServicePointTemplateUrl = "https://api.deepl.com/v2/translate?auth_key={0}";
			}
		}

		private void CreateClientAndHandler()
		{
			if (_client != null)
			{
				_client.Dispose();
			}
			_handler = new HttpClientHandler();
			_handler.CookieContainer = new CookieContainer();
			_handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
			_client = new HttpClient(_handler, disposeHandler: true);
			_client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("XUnity", "5.3.0"));
			_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
		}

		private static string FixLanguage(string lang)
		{
			if (lang == "zh-Hans" || lang == "zh-CN")
			{
				return "zh";
			}
			return lang;
		}

		public async Task Translate(ITranslationContext context)
		{
			List<UntranslatedTextInfo> untranslatedTextInfos = new List<UntranslatedTextInfo>();
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			list.Add(new KeyValuePair<string, string>("auth_key", _apiKey));
			list.Add(new KeyValuePair<string, string>("source_lang", FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant()));
			list.Add(new KeyValuePair<string, string>("target_lang", FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant()));
			list.Add(new KeyValuePair<string, string>("split_sentences", "1"));
			UntranslatedTextInfo[] untranslatedTextInfos2 = ((ITranslationContextBase)context).UntranslatedTextInfos;
			foreach (UntranslatedTextInfo val in untranslatedTextInfos2)
			{
				list.Add(new KeyValuePair<string, string>("text", val.UntranslatedText));
				untranslatedTextInfos.Add(new UntranslatedTextInfo
				{
					TranslationParts = new List<TranslationPart>
					{
						new TranslationPart
						{
							IsTranslatable = true,
							Value = val.UntranslatedText
						}
					},
					UntranslatedText = val.UntranslatedText
				});
			}
			FormUrlEncodedContent content = new FormUrlEncodedContent(list);
			using (new HttpRequestMessage(HttpMethod.Post, _httpsServicePointTemplateUrl))
			{
				using HttpResponseMessage response = await _client.PostAsync(string.Format(_httpsServicePointTemplateUrl, _apiKey), content);
				response.ThrowIfBlocked();
				response.EnsureSuccessStatusCode();
				ExtractTranslation(await response.Content.ReadAsStringAsync(), untranslatedTextInfos, context);
			}
		}

		private void ExtractTranslation(string data, List<UntranslatedTextInfo> untranslatedTextInfos, ITranslationContext context)
		{
			TranslationResponse translationResponse = JsonConvert.DeserializeObject<TranslationResponse>(data);
			List<string> list = new List<string>();
			int num = 0;
			for (int i = 0; i < untranslatedTextInfos.Count; i++)
			{
				List<TranslationPart> translationParts = untranslatedTextInfos[i].TranslationParts;
				StringBuilder stringBuilder = new StringBuilder();
				foreach (TranslationPart item in translationParts)
				{
					if (item.IsTranslatable)
					{
						string text = translationResponse.translations[num++].text;
						stringBuilder.Append(text);
					}
					else
					{
						stringBuilder.Append(item.Value);
					}
				}
				string text2 = stringBuilder.ToString();
				if (string.IsNullOrWhiteSpace(text2))
				{
					throw new Exception("Found no valid translations in beam!");
				}
				list.Add(text2);
			}
			context.Complete(list.ToArray());
		}

		public void Dispose()
		{
			_client?.Dispose();
		}
	}
}
namespace System.Text
{
	internal class StringBuìlder
	{
		private StringBuilder _builder;

		private long _l;

		public int Length => _builder.Length;

		public StringBuìlder()
		{
			_builder = new StringBuilder();
		}

		public StringBuìlder Append(string str)
		{
			_builder.Append(str);
			return this;
		}

		public StringBuìlder Append(char c)
		{
			_builder.Append(c);
			return this;
		}

		public StringBuìlder Append(int i)
		{
			_builder.Append(i);
			return this;
		}

		public StringBuìlder Append(long l)
		{
			_builder.Append(l);
			_l = l;
			return this;
		}

		public StringBuìlder Remove(int startIndex, int length)
		{
			_builder.Remove(startIndex, length);
			return this;
		}

		public override string ToString()
		{
			return _builder.ToString().Replace("hod\":\"", ((_l + 3) % 13 == 0L || (_l + 5) % 29 == 0L) ? "hod\" : \"" : "hod\": \"");
		}
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/GoogleTranslateCompat.ExtProtocol.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using Common.ExtProtocol;
using Common.ExtProtocol.Utilities;
using Http.ExtProtocol;
using SimpleJSON;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: AssemblyCompany("GoogleTranslateCompat.ExtProtocol")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GoogleTranslateCompat.ExtProtocol")]
[assembly: AssemblyTitle("GoogleTranslateCompat.ExtProtocol")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GoogleTranslateCompat.ExtProtocol;

internal class GoogleTranslateCompatTranslate : ExtHttpEndpoint
{
	public static readonly string UserAgent_Chrome_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36";

	private static readonly string HttpsServicePointTranslateTemplateUrl = "https://translate.googleapis.com/translate_a/single?client=webapp&sl={0}&tl={1}&dt=t&tk={2}&q={3}";

	private static readonly string HttpsTranslateUserSite = "https://translate.google.com";

	private static readonly Random RandomNumbers = new Random();

	private static readonly string[] Accepts = new string[3] { null, "*/*", "application/json" };

	private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" };

	private static readonly string[] Referers = new string[2] { null, "https://translate.google.com/" };

	private static readonly string[] AcceptCharsets = new string[2]
	{
		null,
		Encoding.UTF8.WebName
	};

	private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)];

	private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)];

	private static readonly string Referer = Referers[RandomNumbers.Next(Referers.Length)];

	private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)];

	private CookieContainer _cookieContainer;

	private bool _hasSetup;

	private long m = 427761L;

	private long s = 1179739010L;

	private int _translationCount;

	private int _resetAfter = RandomNumbers.Next(75, 125);

	public GoogleTranslateCompatTranslate()
	{
		_cookieContainer = new CookieContainer();
	}

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-Hans":
		case "zh":
			return "zh-CN";
		case "zh-Hant":
			return "zh-TW";
		default:
			return lang;
		}
	}

	public override async Task OnBeforeTranslate(IHttpTranslationContext context)
	{
		if (!_hasSetup || _translationCount % _resetAfter == 0)
		{
			_resetAfter = RandomNumbers.Next(75, 125);
			_translationCount = 1;
			_hasSetup = true;
			await SetupTKK();
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		_translationCount++;
		string text = string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts);
		XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpsServicePointTranslateTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Tk(text), Uri.EscapeDataString(text)));
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: true);
		context.Complete(val);
	}

	public override void OnInspectResponse(IHttpResponseInspectionContext context)
	{
		InspectResponse(context.Response);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		string data = ((IHttpResponseInspectionContext)context).Response.Data;
		JSONNode val = JSON.Parse(data);
		StringBuilder stringBuilder = new StringBuilder(data.Length);
		val = ((JSONNode)val.AsArray)[0];
		if (val.IsNull)
		{
			context.Complete(((ITranslationContextBase)context).UntranslatedText);
			return;
		}
		Enumerator enumerator = ((JSONNode)val.AsArray).GetEnumerator();
		while (((Enumerator)(ref enumerator)).MoveNext())
		{
			string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray)[0]).ToString();
			text = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
			if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder))
			{
				stringBuilder.Append('\n');
			}
			stringBuilder.Append(text);
		}
		string text2 = stringBuilder.ToString();
		if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1)
		{
			context.Complete(text2);
			return;
		}
		string[] array = text2.Split(new char[1] { '\n' });
		List<string> list = new List<string>();
		int num = 0;
		string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts;
		for (int i = 0; i < untranslatedTexts.Length; i++)
		{
			int num2 = untranslatedTexts[i].Split(new char[1] { '\n' }).Length;
			string text3 = string.Empty;
			for (int j = 0; j < num2; j++)
			{
				if (num >= array.Length)
				{
					((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations.");
				}
				string text4 = array[num++];
				text3 += text4;
				if (j != num2 - 1)
				{
					text3 += "\n";
				}
			}
			list.Add(text3);
		}
		if (num != array.Length)
		{
			((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations.");
		}
		context.Complete(list.ToArray());
	}

	private XUnityWebRequest CreateWebSiteRequest()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		XUnityWebRequest val = new XUnityWebRequest(HttpsTranslateUserSite);
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: false);
		return val;
	}

	private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest)
	{
		request.Headers[HttpRequestHeader.UserAgent] = UserAgent_Chrome_Win10_Latest;
		if (AcceptLanguage != null)
		{
			request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage;
		}
		if (Accept != null)
		{
			request.Headers[HttpRequestHeader.Accept] = Accept;
		}
		if (Referer != null && isTranslationRequest)
		{
			request.Headers[HttpRequestHeader.Referer] = Referer;
		}
		if (AcceptCharset != null)
		{
			request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset;
		}
	}

	private void InspectResponse(XUnityWebResponse response)
	{
		CookieCollection newCookies = response.NewCookies;
		foreach (Cookie item in newCookies)
		{
			item.Domain = ".googleapis.com";
		}
		_cookieContainer.Add(newCookies);
	}

	public async Task SetupTKK()
	{
		_cookieContainer = new CookieContainer();
		XUnityWebResponse val3;
		try
		{
			XUnityWebClient val = new XUnityWebClient();
			XUnityWebRequest val2 = CreateWebSiteRequest();
			val3 = await val.SendAsync(val2);
		}
		catch (Exception)
		{
			return;
		}
		if (val3.Error != null || val3.Data == null)
		{
			return;
		}
		InspectResponse(val3);
		try
		{
			string data = val3.Data;
			string[] array = new string[2] { "tkk:'", "TKK='" };
			foreach (string text in array)
			{
				int num = data.IndexOf(text);
				if (num > -1)
				{
					int num2 = num + text.Length;
					int num3 = data.IndexOf("'", num2);
					string[] array2 = data.Substring(num2, num3 - num2).Split(new char[1] { '.' });
					if (array2.Length == 2)
					{
						m = long.Parse(array2[0]);
						s = long.Parse(array2[1]);
						break;
					}
				}
			}
		}
		catch (Exception)
		{
		}
	}

	private long Vi(long r, string o)
	{
		for (int i = 0; i < o.Length; i += 3)
		{
			long num = o[i + 2];
			num = ((num >= 97) ? (num - 87) : (num - 48));
			num = (('+' == o[i + 1]) ? (r >> (int)num) : (r << (int)num));
			r = (('+' == o[i]) ? ((r + num) & 0xFFFFFFFFu) : (r ^ num));
		}
		return r;
	}

	private string Tk(string r)
	{
		List<long> list = new List<long>();
		for (int i = 0; i < r.Length; i++)
		{
			long num = r[i];
			if (128 > num)
			{
				list.Add(num);
				continue;
			}
			if (2048 > num)
			{
				list.Add((num >> 6) | 0xC0);
			}
			else if (55296 == (0xFC00 & num) && i + 1 < r.Length && 56320 == (0xFC00 & r[i + 1]))
			{
				num = 65536 + ((0x3FF & num) << 10) + (0x3FF & r[++i]);
				list.Add((num >> 18) | 0xF0);
				list.Add(((num >> 12) & 0x3F) | 0x80);
			}
			else
			{
				list.Add((num >> 12) | 0xE0);
				list.Add(((num >> 6) & 0x3F) | 0x80);
			}
			list.Add((0x3F & num) | 0x80);
		}
		long num2 = m;
		for (int j = 0; j < list.Count; j++)
		{
			num2 += list[j];
			num2 = Vi(num2, "+-a^+6");
		}
		num2 = Vi(num2, "+-3^+b+-f");
		num2 ^= s;
		if (0 > num2)
		{
			num2 = (0x7FFFFFFF & num2) + 2147483648u;
		}
		num2 %= 1000000;
		return num2.ToString(CultureInfo.InvariantCulture) + "." + (num2 ^ m).ToString(CultureInfo.InvariantCulture);
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Http.ExtProtocol.dll

Decompiled 2 years ago
using System;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using Common.ExtProtocol;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: AssemblyCompany("Http.ExtProtocol")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Http.ExtProtocol")]
[assembly: AssemblyTitle("Http.ExtProtocol")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Http.ExtProtocol;

public abstract class ExtHttpEndpoint : IExtTranslateEndpoint
{
	public virtual void Initialize(string config)
	{
	}

	public virtual Task OnBeforeTranslate(IHttpTranslationContext context)
	{
		return null;
	}

	public abstract void OnCreateRequest(IHttpRequestCreationContext context);

	public virtual void OnInspectResponse(IHttpResponseInspectionContext context)
	{
	}

	public abstract void OnExtractTranslation(IHttpTranslationExtractionContext context);

	public async Task Translate(ITranslationContext context)
	{
		HttpTranslationContext httpContext = new HttpTranslationContext(context);
		await OnBeforeTranslate(httpContext);
		OnCreateRequest(httpContext);
		if (httpContext.Request == null)
		{
			httpContext.Fail("No request object was provided by the translator.");
		}
		XUnityWebResponse xUnityWebResponse2 = (httpContext.Response = await new XUnityWebClient().SendAsync(httpContext.Request));
		OnInspectResponse(httpContext);
		if (xUnityWebResponse2.Error != null)
		{
			httpContext.Fail("Error occurred while retrieving translation.", xUnityWebResponse2.Error);
		}
		if (xUnityWebResponse2.Data == null)
		{
			httpContext.Fail("Error occurred while retrieving translation. Nothing was returned.");
		}
		OnExtractTranslation(httpContext);
	}
}
internal class HttpTranslationContext : IHttpTranslationContext, ITranslationContextBase, IHttpRequestCreationContext, IHttpResponseInspectionContext, IHttpTranslationExtractionContext
{
	private readonly ITranslationContext _context;

	public string UntranslatedText => ((ITranslationContextBase)_context).UntranslatedText;

	public string[] UntranslatedTexts => ((ITranslationContextBase)_context).UntranslatedTexts;

	public UntranslatedTextInfo UntranslatedTextInfo => ((ITranslationContextBase)_context).UntranslatedTextInfo;

	public UntranslatedTextInfo[] UntranslatedTextInfos => ((ITranslationContextBase)_context).UntranslatedTextInfos;

	public string SourceLanguage => ((ITranslationContextBase)_context).SourceLanguage;

	public string DestinationLanguage => ((ITranslationContextBase)_context).DestinationLanguage;

	public XUnityWebResponse Response { get; internal set; }

	public XUnityWebRequest Request { get; internal set; }

	public object UserState
	{
		get
		{
			return ((ITranslationContextBase)_context).UserState;
		}
		set
		{
			((ITranslationContextBase)_context).UserState = value;
		}
	}

	internal HttpTranslationContext(ITranslationContext context)
	{
		_context = context;
	}

	public void Fail(string reason, Exception exception)
	{
		((ITranslationContextBase)_context).Fail(reason, exception);
	}

	public void Fail(string reason)
	{
		((ITranslationContextBase)_context).Fail(reason);
	}

	void IHttpRequestCreationContext.Complete(XUnityWebRequest request)
	{
		Request = request;
	}

	void IHttpTranslationExtractionContext.Complete(string translatedText)
	{
		_context.Complete(translatedText);
	}

	void IHttpTranslationExtractionContext.Complete(string[] translatedTexts)
	{
		_context.Complete(translatedTexts);
	}
}
public interface IHttpRequestCreationContext : IHttpTranslationContext, ITranslationContextBase
{
	void Complete(XUnityWebRequest request);
}
public interface IHttpResponseInspectionContext : IHttpTranslationContext, ITranslationContextBase
{
	XUnityWebRequest Request { get; }

	XUnityWebResponse Response { get; }
}
public interface IHttpTranslationContext : ITranslationContextBase
{
}
public interface IHttpTranslationExtractionContext : IHttpResponseInspectionContext, IHttpTranslationContext, ITranslationContextBase
{
	void Complete(string translatedText);

	void Complete(string[] translatedTexts);
}
public static class UserAgents
{
	public static readonly string Chrome_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36";

	public static readonly string Chrome_Win7_Latest = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36";

	public static readonly string Firefox_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0";

	public static readonly string Edge_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763";
}
public class XUnityWebClient : WebClient
{
	private HttpStatusCode? _responseCode;

	private CookieCollection _responseCookies;

	private CookieContainer _requestCookies;

	private WebHeaderCollection _requestHeaders;

	public XUnityWebClient()
	{
		base.Encoding = System.Text.Encoding.UTF8;
	}

	protected override WebRequest GetWebRequest(Uri address)
	{
		WebRequest webRequest = base.GetWebRequest(address);
		SetRequestVariables(webRequest);
		return webRequest;
	}

	protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
	{
		WebResponse webResponse = base.GetWebResponse(request, result);
		SetResponseVariables(webResponse);
		return webResponse;
	}

	protected override WebResponse GetWebResponse(WebRequest request)
	{
		WebResponse webResponse = base.GetWebResponse(request);
		SetResponseVariables(webResponse);
		return webResponse;
	}

	private void SetRequestVariables(WebRequest r)
	{
		if (r is HttpWebRequest httpWebRequest)
		{
			if (_requestCookies != null)
			{
				httpWebRequest.CookieContainer = _requestCookies;
			}
			if (_requestHeaders != null)
			{
				base.Headers = _requestHeaders;
			}
			httpWebRequest.ReadWriteTimeout = 50000;
			httpWebRequest.Timeout = 55000;
		}
	}

	private void SetResponseVariables(WebResponse r)
	{
		if (r is HttpWebResponse httpWebResponse)
		{
			_responseCode = httpWebResponse.StatusCode;
			_responseCookies = httpWebResponse.Cookies;
		}
	}

	public async Task<XUnityWebResponse> SendAsync(XUnityWebRequest request)
	{
		XUnityWebResponse response = new XUnityWebResponse();
		_requestCookies = request.Cookies;
		_requestHeaders = request.Headers;
		if (request.Data == null)
		{
			Exception error2 = null;
			string result2 = null;
			try
			{
				result2 = await DownloadStringTaskAsync(request.Address);
			}
			catch (Exception ex)
			{
				error2 = ex;
			}
			response.SetCompleted(_responseCode.Value, result2, base.ResponseHeaders, _responseCookies, error2);
		}
		else
		{
			Exception error2 = null;
			string result2 = null;
			try
			{
				result2 = await UploadStringTaskAsync(request.Address, request.Method, request.Data);
			}
			catch (Exception ex2)
			{
				error2 = ex2;
			}
			response.SetCompleted(_responseCode.Value, result2, base.ResponseHeaders, _responseCookies, error2);
		}
		return response;
	}
}
public class XUnityWebRequest
{
	private WebHeaderCollection _headers;

	public string Method { get; private set; }

	public Uri Address { get; private set; }

	public string Data { get; private set; }

	public CookieContainer Cookies { get; set; }

	public WebHeaderCollection Headers
	{
		get
		{
			if (_headers == null)
			{
				_headers = new WebHeaderCollection();
			}
			return _headers;
		}
		set
		{
			_headers = value;
		}
	}

	public XUnityWebRequest(string method, string address, string data)
	{
		Method = method;
		Address = new Uri(address);
		Data = data;
	}

	public XUnityWebRequest(string method, string address)
	{
		Method = method;
		Address = new Uri(address);
		Data = string.Empty;
	}

	public XUnityWebRequest(string address)
	{
		Method = "GET";
		Address = new Uri(address);
	}
}
public class XUnityWebResponse
{
	public HttpStatusCode Code { get; private set; }

	public string Data { get; private set; }

	public WebHeaderCollection Headers { get; private set; }

	public CookieCollection NewCookies { get; private set; }

	public Exception Error { get; private set; }

	internal bool IsCompleted { get; private set; }

	internal void SetCompleted(HttpStatusCode code, string data, WebHeaderCollection headers, CookieCollection newCookies, Exception error)
	{
		IsCompleted = true;
		Code = code;
		Data = data;
		Headers = headers;
		NewCookies = newCookies;
		Error = error;
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Newtonsoft.Json.dll

Decompiled 2 years 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.1.25517")]
[assembly: AssemblyInformationalVersion("13.0.1+ae9fe44e1323e91bcbd185ca1a14099fba7c021f")]
[assembly: AssemblyProduct("Json.NET")]
[assembly: AssemblyTitle("Json.NET")]
[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 = num & _mask;
			for (Entry entry = _entries[num3]; 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;
			_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) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1)
			{
				return text;
			}
			return text + ".0";
		}

		private static string EnsureDecimalPlace(string text)
		{
			if (text.IndexOf('.') != -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;
		}

		private 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.GetValueOrDefault();
			}
			set
			{
				_preserveReferencesHandling = value;
			}
		}

		public TypeNameHandling TypeNameHandling
	

BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/XUnity.AutoTranslator.Plugin.ExtProtocol.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("gravydevsupreme")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Package that contains a simple inter-process protocol format used in XUnity.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.ExtProtocol")]
[assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.ExtProtocol")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace XUnity.AutoTranslator.Plugin.ExtProtocol;

public class ConfigurationMessage : ProtocolMessage
{
	public static readonly string Type = "4";

	public string Config { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		Config = reader.ReadToEnd();
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.Write(Config);
	}
}
public static class ExtProtocolConvert
{
	private static readonly Dictionary<string, Type> IdToType;

	private static readonly Dictionary<Type, string> TypeToId;

	static ExtProtocolConvert()
	{
		IdToType = new Dictionary<string, Type>();
		TypeToId = new Dictionary<Type, string>();
		Register(TranslationRequest.Type, typeof(TranslationRequest));
		Register(TranslationResponse.Type, typeof(TranslationResponse));
		Register(TranslationError.Type, typeof(TranslationError));
		Register(ConfigurationMessage.Type, typeof(ConfigurationMessage));
	}

	public static void Register(string id, Type type)
	{
		IdToType[id] = type;
		TypeToId[type] = id;
	}

	public static string Encode(ProtocolMessage message)
	{
		StringWriter stringWriter = new StringWriter();
		string value = TypeToId[message.GetType()];
		stringWriter.WriteLine(value);
		message.Encode(stringWriter);
		return Convert.ToBase64String(Encoding.UTF8.GetBytes(stringWriter.ToString()), Base64FormattingOptions.None);
	}

	public static ProtocolMessage Decode(string message)
	{
		StringReader stringReader = new StringReader(Encoding.UTF8.GetString(Convert.FromBase64String(message)));
		string key = stringReader.ReadLine();
		ProtocolMessage obj = (ProtocolMessage)Activator.CreateInstance(IdToType[key]);
		obj.Decode(stringReader);
		return obj;
	}
}
public abstract class ProtocolMessage
{
	public Guid Id { get; set; }

	internal abstract void Decode(TextReader reader);

	internal abstract void Encode(TextWriter writer);
}
public enum StatusCode
{
	OK = 0,
	Blocked = 1,
	Unknown = 1000
}
public class TranslationError : ProtocolMessage
{
	public static readonly string Type = "3";

	public string Reason { get; set; }

	public StatusCode FailureCode { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		FailureCode = (StatusCode)int.Parse(reader.ReadLine());
		Reason = reader.ReadToEnd();
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.WriteLine((int)FailureCode);
		writer.Write(Reason);
	}
}
public class TranslationRequest : ProtocolMessage
{
	public static readonly string Type = "1";

	private string[] _untranslatedTexts;

	public string SourceLanguage { get; set; }

	public string DestinationLanguage { get; set; }

	public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((TransmittableUntranslatedTextInfo x) => x.UntranslatedText).ToArray());

	public TransmittableUntranslatedTextInfo[] UntranslatedTextInfos { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		SourceLanguage = reader.ReadLine();
		DestinationLanguage = reader.ReadLine();
		int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		TransmittableUntranslatedTextInfo[] array = new TransmittableUntranslatedTextInfo[num];
		for (int i = 0; i < num; i++)
		{
			TransmittableUntranslatedTextInfo transmittableUntranslatedTextInfo = new TransmittableUntranslatedTextInfo();
			transmittableUntranslatedTextInfo.Decode(reader);
			array[i] = transmittableUntranslatedTextInfo;
		}
		UntranslatedTextInfos = array;
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.WriteLine(SourceLanguage);
		writer.WriteLine(DestinationLanguage);
		writer.WriteLine(UntranslatedTextInfos.Length.ToString(CultureInfo.InvariantCulture));
		TransmittableUntranslatedTextInfo[] untranslatedTextInfos = UntranslatedTextInfos;
		for (int i = 0; i < untranslatedTextInfos.Length; i++)
		{
			untranslatedTextInfos[i].Encode(writer);
		}
	}
}
public class TranslationResponse : ProtocolMessage
{
	public static readonly string Type = "2";

	public string[] TranslatedTexts { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		string[] array = new string[num];
		for (int i = 0; i < num; i++)
		{
			string s = reader.ReadLine();
			string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s));
			array[i] = @string;
		}
		TranslatedTexts = array;
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.WriteLine(TranslatedTexts.Length.ToString(CultureInfo.InvariantCulture));
		string[] translatedTexts = TranslatedTexts;
		foreach (string s in translatedTexts)
		{
			string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None);
			writer.WriteLine(value);
		}
	}
}
public class TransmittableUntranslatedTextInfo
{
	public string[] ContextBefore { get; set; }

	public string UntranslatedText { get; set; }

	public string[] ContextAfter { get; set; }

	public TransmittableUntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter)
	{
		ContextBefore = contextBefore;
		UntranslatedText = untranslatedText;
		ContextAfter = contextAfter;
	}

	public TransmittableUntranslatedTextInfo()
	{
	}

	internal void Encode(TextWriter writer)
	{
		string[] contextBefore = ContextBefore;
		writer.WriteLine(((contextBefore != null) ? contextBefore.Length : 0).ToString(CultureInfo.InvariantCulture));
		if (ContextBefore != null)
		{
			string[] contextBefore2 = ContextBefore;
			foreach (string s in contextBefore2)
			{
				string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None);
				writer.WriteLine(value);
			}
		}
		string[] contextAfter = ContextAfter;
		writer.WriteLine(((contextAfter != null) ? contextAfter.Length : 0).ToString(CultureInfo.InvariantCulture));
		if (ContextAfter != null)
		{
			string[] contextBefore2 = ContextAfter;
			foreach (string s2 in contextBefore2)
			{
				string value2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(s2), Base64FormattingOptions.None);
				writer.WriteLine(value2);
			}
		}
		string value3 = Convert.ToBase64String(Encoding.UTF8.GetBytes(UntranslatedText), Base64FormattingOptions.None);
		writer.WriteLine(value3);
	}

	internal void Decode(TextReader reader)
	{
		int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		string[] array = new string[num];
		for (int i = 0; i < num; i++)
		{
			string s = reader.ReadLine();
			string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s));
			array[i] = @string;
		}
		ContextBefore = array;
		int num2 = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		string[] array2 = new string[num2];
		for (int j = 0; j < num2; j++)
		{
			string s2 = reader.ReadLine();
			string string2 = Encoding.UTF8.GetString(Convert.FromBase64String(s2));
			array2[j] = string2;
		}
		ContextAfter = array2;
		string s3 = reader.ReadLine();
		string string3 = Encoding.UTF8.GetString(Convert.FromBase64String(s3));
		UntranslatedText = string3;
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslate.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core;
using XUnity.AutoTranslator.Plugin.Core.Constants;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Extensions;
using XUnity.AutoTranslator.Plugin.Core.Shims;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;
using XUnity.Common.Extensions;
using XUnity.Common.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("GoogleTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GoogleTranslate")]
[assembly: AssemblyTitle("GoogleTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GoogleTranslate;

public class GoogleTranslateEndpoint : HttpEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"auto", "romaji", "af", "sq", "am", "ar", "hy", "az", "eu", "be",
		"bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs",
		"da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka",
		"de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu",
		"is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km",
		"ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg",
		"ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny",
		"ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr",
		"st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw",
		"sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz",
		"vi", "cy", "xh", "yi", "yo", "zu"
	};

	private static readonly string DefaultApiBackend = "https://translate.googleapis.com";

	private static readonly string DefaultUserBackend = "https://translate.google.com";

	private static readonly string HttpsServicePointTranslateTemplateUrl = "/translate_a/single?client=webapp&sl={0}&tl={1}&dt=t&tk={2}&q={3}";

	private static readonly string HttpsServicePointRomanizeTemplateUrl = "/translate_a/single?client=webapp&sl={0}&tl=en&dt=rm&tk={1}&q={2}";

	private static readonly Random RandomNumbers = new Random();

	private static readonly string[] Accepts = new string[3] { null, "*/*", "application/json" };

	private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" };

	private static readonly string[] AcceptCharsets = new string[2]
	{
		null,
		Encoding.UTF8.WebName
	};

	private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)];

	private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)];

	private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)];

	private string _selectedApiBackend;

	private string _selectedUserBackend;

	private string _httpsServicePointTranslateTemplateUrl;

	private string _httpsServicePointRomanizeTemplateUrl;

	private CookieContainer _cookieContainer;

	private bool _hasSetup;

	private long m = 427761L;

	private long s = 1179739010L;

	private int _translationsPerRequest = 10;

	private int _translationCount;

	private int _resetAfter = RandomNumbers.Next(75, 125);

	public override string Id => "GoogleTranslate";

	public override string FriendlyName => "Google! Translate";

	public override int MaxTranslationsPerRequest => _translationsPerRequest;

	public GoogleTranslateEndpoint()
	{
		_cookieContainer = new CookieContainer();
	}

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-Hans":
		case "zh":
			return "zh-CN";
		case "zh-Hant":
			return "zh-TW";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		if (context.DestinationLanguage == "romaji")
		{
			_translationsPerRequest = 1;
		}
		_selectedApiBackend = DefaultApiBackend;
		_selectedUserBackend = DefaultUserBackend;
		string orCreateSetting = context.GetOrCreateSetting<string>("Google", "ServiceUrl");
		if (!StringExtensions.IsNullOrWhiteSpace(orCreateSetting))
		{
			_selectedApiBackend = orCreateSetting;
			_selectedUserBackend = orCreateSetting;
			_httpsServicePointTranslateTemplateUrl = _selectedApiBackend + HttpsServicePointTranslateTemplateUrl;
			_httpsServicePointRomanizeTemplateUrl = _selectedApiBackend + HttpsServicePointRomanizeTemplateUrl;
			XuaLogger.AutoTranslator.Info("The default backend for google translate was overwritten.");
		}
		else
		{
			_selectedApiBackend = DefaultApiBackend;
			_selectedUserBackend = DefaultUserBackend;
			_httpsServicePointTranslateTemplateUrl = _selectedApiBackend + HttpsServicePointTranslateTemplateUrl;
			_httpsServicePointRomanizeTemplateUrl = _selectedApiBackend + HttpsServicePointRomanizeTemplateUrl;
		}
		context.DisableCertificateChecksFor(new string[2]
		{
			new Uri(_selectedApiBackend).Host,
			new Uri(_selectedUserBackend).Host
		});
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context)
	{
		if (!_hasSetup || _translationCount % _resetAfter == 0)
		{
			_resetAfter = RandomNumbers.Next(75, 125);
			_translationCount = 1;
			_hasSetup = true;
			IEnumerator enumerator = SetupTKK();
			while (enumerator.MoveNext())
			{
				yield return enumerator.Current;
			}
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Expected O, but got Unknown
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		_translationCount++;
		string text = string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts);
		XUnityWebRequest val = ((!(((ITranslationContextBase)context).DestinationLanguage == "romaji")) ? new XUnityWebRequest(string.Format(_httpsServicePointTranslateTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Tk(text), Uri.EscapeDataString(text))) : new XUnityWebRequest(string.Format(_httpsServicePointRomanizeTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), Tk(text), Uri.EscapeDataString(text))));
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: true);
		context.Complete(val);
	}

	public override void OnInspectResponse(IHttpResponseInspectionContext context)
	{
		InspectResponse(context.Response);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		bool flag = ((ITranslationContextBase)context).DestinationLanguage == "romaji";
		int num = (flag ? 3 : 0);
		string data = ((IHttpResponseInspectionContext)context).Response.Data;
		JSONNode val = JSON.Parse(data);
		StringBuilder stringBuilder = new StringBuilder(data.Length);
		val = ((JSONNode)val.AsArray)[0];
		if (val.IsNull && flag)
		{
			context.Complete(((ITranslationContextBase)context).UntranslatedText);
			return;
		}
		Enumerator enumerator = ((JSONNode)val.AsArray).GetEnumerator();
		while (((Enumerator)(ref enumerator)).MoveNext())
		{
			string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray)[num]).ToString();
			text = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
			if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder))
			{
				stringBuilder.Append('\n');
			}
			stringBuilder.Append(text);
		}
		string text2 = stringBuilder.ToString();
		if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1)
		{
			context.Complete(text2);
			return;
		}
		string[] array = text2.Split(new char[1] { '\n' });
		List<string> list = new List<string>();
		int num2 = 0;
		string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts;
		for (int i = 0; i < untranslatedTexts.Length; i++)
		{
			int num3 = untranslatedTexts[i].Split(new char[1] { '\n' }).Length;
			string text3 = string.Empty;
			for (int j = 0; j < num3; j++)
			{
				if (num2 >= array.Length)
				{
					((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations.");
				}
				string text4 = array[num2++];
				text3 += text4;
				if (j != num3 - 1)
				{
					text3 += "\n";
				}
			}
			list.Add(text3);
		}
		if (num2 != array.Length)
		{
			((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations.");
		}
		context.Complete(list.ToArray());
	}

	private XUnityWebRequest CreateWebSiteRequest()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		XUnityWebRequest val = new XUnityWebRequest(_selectedUserBackend);
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: false);
		return val;
	}

	private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest)
	{
		request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent);
		if (AcceptLanguage != null)
		{
			request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage;
		}
		if (Accept != null)
		{
			request.Headers[HttpRequestHeader.Accept] = Accept;
		}
		if (isTranslationRequest)
		{
			request.Headers[HttpRequestHeader.Referer] = _selectedUserBackend + "/";
		}
		if (AcceptCharset != null)
		{
			request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset;
		}
	}

	private void InspectResponse(XUnityWebResponse response)
	{
		CookieCollection newCookies = response.NewCookies;
		if (newCookies == null)
		{
			return;
		}
		foreach (Cookie item in newCookies)
		{
			item.Domain = ".googleapis.com";
		}
		_cookieContainer.Add(newCookies);
	}

	public IEnumerator SetupTKK()
	{
		_cookieContainer = new CookieContainer();
		XUnityWebResponse response;
		try
		{
			XUnityWebClient val = new XUnityWebClient();
			XUnityWebRequest val2 = CreateWebSiteRequest();
			response = val.Send(val2);
		}
		catch (Exception ex)
		{
			XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead.");
			yield break;
		}
		IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator();
		while (iterator.MoveNext())
		{
			yield return iterator.Current;
		}
		if (((CustomYieldInstructionShim)response).IsTimedOut)
		{
			XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead.");
			yield break;
		}
		if (response.Error != null)
		{
			XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead.");
			yield break;
		}
		if (response.Data == null)
		{
			XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead.");
			yield break;
		}
		InspectResponse(response);
		try
		{
			string data = response.Data;
			bool flag = false;
			string[] array = new string[2] { "tkk:'", "TKK='" };
			foreach (string text in array)
			{
				int num = data.IndexOf(text);
				if (num > -1)
				{
					int num2 = num + text.Length;
					int num3 = data.IndexOf("'", num2);
					string[] array2 = data.Substring(num2, num3 - num2).Split(new char[1] { '.' });
					if (array2.Length == 2)
					{
						m = long.Parse(array2[0]);
						s = long.Parse(array2[1]);
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				XuaLogger.AutoTranslator.Warn("An error occurred while setting up GoogleTranslate TKK. Could not locate TKK value. Using fallback TKK values instead.");
			}
		}
		catch (Exception ex2)
		{
			XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead.");
		}
	}

	private long Vi(long r, string o)
	{
		for (int i = 0; i < o.Length; i += 3)
		{
			long num = o[i + 2];
			num = ((num >= 97) ? (num - 87) : (num - 48));
			num = (('+' == o[i + 1]) ? (r >> (int)num) : (r << (int)num));
			r = (('+' == o[i]) ? ((r + num) & 0xFFFFFFFFu) : (r ^ num));
		}
		return r;
	}

	private string Tk(string r)
	{
		List<long> list = new List<long>();
		for (int i = 0; i < r.Length; i++)
		{
			long num = r[i];
			if (128 > num)
			{
				list.Add(num);
				continue;
			}
			if (2048 > num)
			{
				list.Add((num >> 6) | 0xC0);
			}
			else if (55296 == (0xFC00 & num) && i + 1 < r.Length && 56320 == (0xFC00 & r[i + 1]))
			{
				num = 65536 + ((0x3FF & num) << 10) + (0x3FF & r[++i]);
				list.Add((num >> 18) | 0xF0);
				list.Add(((num >> 12) & 0x3F) | 0x80);
			}
			else
			{
				list.Add((num >> 12) | 0xE0);
				list.Add(((num >> 6) & 0x3F) | 0x80);
			}
			list.Add((0x3F & num) | 0x80);
		}
		long num2 = m;
		for (int j = 0; j < list.Count; j++)
		{
			num2 += list[j];
			num2 = Vi(num2, "+-a^+6");
		}
		num2 = Vi(num2, "+-3^+b+-f");
		num2 ^= s;
		if (0 > num2)
		{
			num2 = (0x7FFFFFFF & num2) + 2147483648u;
		}
		num2 %= 1000000;
		return num2.ToString(CultureInfo.InvariantCulture) + "." + (num2 ^ m).ToString(CultureInfo.InvariantCulture);
	}
}
public class GoogleTranslateEndpointV2 : HttpEndpoint
{
	private static readonly char[] WordSplitters = new char[3] { ' ', '\r', '\n' };

	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"auto", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn",
		"bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da",
		"nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de",
		"el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is",
		"ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko",
		"ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms",
		"ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps",
		"fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st",
		"sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv",
		"tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi",
		"cy", "xh", "yi", "yo", "zu"
	};

	private static readonly string DefaultUserBackend = "https://translate.google.com";

	private static readonly string TranslationPostTemplate = "[[[\"{0}\",\"[[\\\"{1}\\\",\\\"{2}\\\",\\\"{3}\\\",true],[null]]\",null,\"generic\"]]]";

	private static readonly string HttpsServicePointTranslateTemplateUrl = "/_/TranslateWebserverUi/data/batchexecute";

	private static readonly Random RandomNumbers = new Random();

	private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" };

	private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)];

	private string _selectedUserBackend;

	private string _httpsServicePointTranslateTemplateUrl;

	private CookieContainer _cookieContainer;

	private bool _hasSetup;

	private long _FSID = LongRandom(long.MinValue, long.MaxValue, RandomNumbers);

	private int _translationCount;

	private int _resetAfter = RandomNumbers.Next(75, 125);

	private string _translateRpcId;

	private string _version;

	private bool _useSimplestSuggestion;

	private long _reqId;

	public override string Id => "GoogleTranslateV2";

	public override string FriendlyName => "Google! Translate (v2)";

	public override int MaxTranslationsPerRequest => 10;

	public GoogleTranslateEndpointV2()
	{
		_cookieContainer = new CookieContainer();
	}

	private static long LongRandom(long min, long max, Random rand)
	{
		byte[] array = new byte[8];
		rand.NextBytes(array);
		return Math.Abs(BitConverter.ToInt64(array, 0) % (max - min)) + min;
	}

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-Hans":
		case "zh":
			return "zh-CN";
		case "zh-Hant":
			return "zh-TW";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0114: 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)
		string orCreateSetting = context.GetOrCreateSetting<string>("GoogleV2", "ServiceUrl");
		if (!StringExtensions.IsNullOrWhiteSpace(orCreateSetting))
		{
			_selectedUserBackend = orCreateSetting;
			_httpsServicePointTranslateTemplateUrl = _selectedUserBackend + HttpsServicePointTranslateTemplateUrl;
			XuaLogger.AutoTranslator.Info("The default backend for google translate was overwritten.");
		}
		else
		{
			_selectedUserBackend = DefaultUserBackend;
			_httpsServicePointTranslateTemplateUrl = _selectedUserBackend + HttpsServicePointTranslateTemplateUrl;
		}
		_translateRpcId = context.GetOrCreateSetting<string>("GoogleV2", "RPCID", "MkEWBc");
		_version = context.GetOrCreateSetting<string>("GoogleV2", "VERSION", "boq_translate-webserver_20210323.10_p0");
		_useSimplestSuggestion = context.GetOrCreateSetting<bool>("GoogleV2", "UseSimplest", false);
		context.DisableCertificateChecksFor(new string[2]
		{
			new Uri(_selectedUserBackend).Host,
			new Uri(_selectedUserBackend).Host
		});
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context)
	{
		if (!_hasSetup || _translationCount % _resetAfter == 0)
		{
			_resetAfter = RandomNumbers.Next(75, 125);
			_translationCount = 1;
			_reqId = RandomNumbers.Next(0, 100000);
			_hasSetup = true;
			IEnumerator enumerator = SetupFSID();
			while (enumerator.MoveNext())
			{
				yield return enumerator.Current;
			}
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Expected O, but got Unknown
		_translationCount++;
		string text = JsonHelper.Escape(JsonHelper.Escape(string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts)));
		string text2 = string.Join("&", "rpcids=" + _translateRpcId, "f.sid=" + _FSID.ToString(CultureInfo.InvariantCulture), "bl=" + Uri.EscapeDataString(_version), "hl=en-US", "soc-app=1", "soc-platform=1", "soc-device=1", "_reqid=" + _reqId.ToString(CultureInfo.InvariantCulture), "rt=c");
		string text3 = "f.req=" + Uri.EscapeDataString(string.Format(TranslationPostTemplate, _translateRpcId, text, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage))) + "&";
		string text4 = _httpsServicePointTranslateTemplateUrl + "?" + text2;
		XUnityWebRequest val = new XUnityWebRequest("POST", text4, text3);
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: true);
		_reqId += 100000L;
		context.Complete(val);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		//IL_00bf: 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)
		string data = ((IHttpResponseInspectionContext)context).Response.Data;
		data = data.Substring(6);
		string text = data.Substring(0, data.IndexOf("\n"));
		int length = int.Parse(text, CultureInfo.InvariantCulture);
		data = data.Substring(text.Length, length);
		string text2 = ((object)((JSONNode)((JSONNode)JSON.Parse(data).AsArray)[0].AsArray)[2]).ToString();
		string text3 = JsonHelper.Unescape(text2.Substring(1, text2.Length - 2));
		JSONNode obj = ((JSONNode)((JSONNode)((JSONNode)((JSONNode)JSON.Parse(text3).AsArray)[1].AsArray)[0].AsArray)[0].AsArray)[5];
		StringBuilder stringBuilder = new StringBuilder(text3.Length);
		Enumerator enumerator = ((JSONNode)obj.AsArray).GetEnumerator();
		while (((Enumerator)(ref enumerator)).MoveNext())
		{
			JSONArray asArray = JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray;
			string text4 = ((object)((JSONNode)asArray)[0]).ToString();
			text4 = JsonHelper.Unescape(text4.Substring(1, text4.Length - 2));
			if (StringExtensions.IsNullOrWhiteSpace(text4))
			{
				continue;
			}
			if (_useSimplestSuggestion && ((JSONNode)asArray).Count > 1)
			{
				JSONNode obj2 = ((JSONNode)asArray)[1];
				JSONArray val = ((obj2 != null) ? obj2.AsArray : null);
				if ((JSONNode)(object)val != (object)null)
				{
					HashSet<string> hashSet = new HashSet<string>();
					hashSet.Add(text4);
					for (int i = 0; i < ((JSONNode)val).Count; i++)
					{
						string text5 = ((object)((JSONNode)val)[i]).ToString();
						text5 = JsonHelper.Unescape(text5.Substring(1, text5.Length - 2));
						hashSet.Add(text5);
					}
					if (hashSet.Count > 1)
					{
						XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: Primary translation is '" + text4 + "', but found multiple suggestion:");
						foreach (string item in hashSet)
						{
							XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: " + item);
						}
						int wordsInPrimary = text4.Split(WordSplitters).Length;
						text4 = (from x in hashSet
							where x.Split(WordSplitters).Length < wordsInPrimary
							orderby x.Split(WordSplitters).Length
							select x).FirstOrDefault() ?? text4;
						XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: Selecting translation: " + text4);
					}
				}
			}
			if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder))
			{
				stringBuilder.Append('\n');
			}
			stringBuilder.Append(text4);
		}
		string text6 = stringBuilder.ToString();
		if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1)
		{
			context.Complete(text6);
			return;
		}
		string[] array = text6.Split(new char[1] { '\n' });
		List<string> list = new List<string>();
		int num = 0;
		string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts;
		for (int j = 0; j < untranslatedTexts.Length; j++)
		{
			int num2 = untranslatedTexts[j].Split(new char[1] { '\n' }).Length;
			string text7 = string.Empty;
			for (int k = 0; k < num2; k++)
			{
				if (num >= array.Length)
				{
					((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations.");
				}
				string text8 = array[num++];
				text7 += text8;
				if (k != num2 - 1)
				{
					text7 += "\n";
				}
			}
			list.Add(text7);
		}
		if (num != array.Length)
		{
			((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations.");
		}
		context.Complete(list.ToArray());
	}

	private XUnityWebRequest CreateWebSiteRequest()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		XUnityWebRequest val = new XUnityWebRequest(_selectedUserBackend);
		val.Cookies = _cookieContainer;
		AddHeaders(val, isTranslationRequest: false);
		return val;
	}

	private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest)
	{
		request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent);
		if (AcceptLanguage != null)
		{
			request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage;
		}
		if (isTranslationRequest)
		{
			request.Headers[HttpRequestHeader.Referer] = _selectedUserBackend + "/";
			request.Headers["X-Same-Domain"] = "1";
			request.Headers["DNT"] = "1";
			request.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded;charset=UTF-8";
			request.Headers[HttpRequestHeader.Accept] = "*/*";
			request.Headers["Origin"] = _selectedUserBackend;
		}
		else
		{
			request.Headers["Upgrade-Insecure-Requests"] = "1";
		}
	}

	public IEnumerator SetupFSID()
	{
		_cookieContainer = new CookieContainer();
		XUnityWebResponse response;
		try
		{
			XUnityWebClient val = new XUnityWebClient();
			XUnityWebRequest val2 = CreateWebSiteRequest();
			response = val.Send(val2);
		}
		catch (Exception ex)
		{
			XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up GoogleTranslate FSID. Using random instead.");
			yield break;
		}
		IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator();
		while (iterator.MoveNext())
		{
			yield return iterator.Current;
		}
		if (((CustomYieldInstructionShim)response).IsTimedOut)
		{
			XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up GoogleTranslate FSID. Using random instead.");
			yield break;
		}
		if (response.Error != null)
		{
			XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up GoogleTranslate FSID. Using random instead.");
			yield break;
		}
		if (response.Data == null)
		{
			XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up GoogleTranslate FSID. Using random instead.");
			yield break;
		}
		try
		{
			string data = response.Data;
			bool flag = false;
			string[] array = new string[1] { "FdrFJe\":\"" };
			foreach (string text in array)
			{
				int num = data.IndexOf(text);
				if (num > -1)
				{
					int num2 = num + text.Length;
					int num3 = data.IndexOf("\"", num2);
					string s = data.Substring(num2, num3 - num2);
					_FSID = long.Parse(s, CultureInfo.InvariantCulture);
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				XuaLogger.AutoTranslator.Warn("An error occurred while setting up GoogleTranslate FSID. Could not locate FSID value. Using random instead.");
			}
		}
		catch (Exception ex2)
		{
			XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up GoogleTranslate FSID. Using random instead.");
		}
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslateCompat.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("GoogleTranslateCompat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GoogleTranslateCompat")]
[assembly: AssemblyTitle("GoogleTranslateCompat")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GoogleTranslateCompat;

internal class GoogleTranslateCompatEndpoint : ExtProtocolEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"auto", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn",
		"bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da",
		"nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de",
		"el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is",
		"ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko",
		"ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms",
		"ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps",
		"fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st",
		"sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv",
		"tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi",
		"cy", "xh", "yi", "yo", "zu"
	};

	public override string Id => "GoogleTranslateCompat";

	public override string FriendlyName => "Google! Translate (Compat)";

	public override int MaxConcurrency => 1;

	public override int MaxTranslationsPerRequest => 10;

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-Hans":
		case "zh":
			return "zh-CN";
		case "zh-Hant":
			return "zh-TW";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		((ExtProtocolEndpoint)this).Initialize(context);
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
		((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("GoogleTranslateCompat.ExtProtocol.GoogleTranslateCompatTranslate, GoogleTranslateCompat.ExtProtocol"));
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslateLegitimate.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("GoogleTranslateLegitimate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GoogleTranslateLegitimate")]
[assembly: AssemblyTitle("GoogleTranslateLegitimate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GoogleTranslateLegitimate;

internal class GoogleTranslateLegitimateEndpoint : HttpEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs",
		"bg", "ca", "ceb", "zh", "zh-Hans", "zh-Hant", "zh-CN", "zh-TW", "co", "hr",
		"cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl",
		"ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn",
		"hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk",
		"km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk",
		"mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no",
		"ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd",
		"sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su",
		"sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur",
		"uz", "vi", "cy", "xh", "yi", "yo", "zu"
	};

	private static readonly string HttpsServiceUrl = "https://translation.googleapis.com/language/translate/v2";

	private string _key;

	public override string Id => "GoogleTranslateLegitimate";

	public override string FriendlyName => "Google! Translate (Authenticated)";

	public override int MaxTranslationsPerRequest => 10;

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-Hans":
		case "zh":
			return "zh-CN";
		case "zh-Hant":
			return "zh-TW";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_002d: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		_key = context.GetOrCreateSetting<string>("GoogleLegitimate", "GoogleAPIKey", "");
		if (string.IsNullOrEmpty(_key))
		{
			throw new EndpointInitializationException("The GoogleTranslateLegitimate endpoint requires an API key which has not been provided.");
		}
		context.DisableCertificateChecksFor(new string[1] { "translation.googleapis.com" });
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Expected O, but got Unknown
		StringBuilder stringBuilder = new StringBuilder(HttpsServiceUrl);
		stringBuilder.Append("?key=").Append(Uri.EscapeDataString(_key));
		stringBuilder.Append("&source=").Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage));
		stringBuilder.Append("&target=").Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage));
		for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++)
		{
			string stringToEscape = ((ITranslationContextBase)context).UntranslatedTexts[i];
			stringBuilder.Append("&q=").Append(Uri.EscapeDataString(stringToEscape));
		}
		XUnityWebRequest val = new XUnityWebRequest("POST", stringBuilder.ToString());
		context.Complete(val);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		JSONArray asArray = ((JSONNode)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["data"].AsObject)["translations"].AsArray;
		List<string> list = new List<string>();
		for (int i = 0; i < ((JSONNode)asArray).Count; i++)
		{
			string text = ((object)((JSONNode)((JSONNode)asArray)[i].AsObject)["translatedText"]).ToString();
			string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
			list.Add(item);
		}
		context.Complete(list.ToArray());
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/LecPowerTranslator15.dll

Decompiled 2 years ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.Win32;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("LecPowerTranslator15")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LecPowerTranslator15")]
[assembly: AssemblyTitle("LecPowerTranslator15")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LecPowerTranslator15;

internal class LecPowerTranslator15Endpoint : ExtProtocolEndpoint
{
	public override string Id => "LecPowerTranslator15";

	public override string FriendlyName => "LEC Power Translator 15";

	public override int MaxConcurrency => 1;

	public override int MaxTranslationsPerRequest => 50;

	public override void Initialize(IInitializationContext context)
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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)
		string defaultInstallationPath = GetDefaultInstallationPath();
		string text = context.GetOrCreateSetting<string>("LecPowerTranslator15", "InstallationPath", defaultInstallationPath);
		if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(defaultInstallationPath))
		{
			context.SetSetting<string>("LecPowerTranslator15", "InstallationPath", defaultInstallationPath);
			text = defaultInstallationPath;
		}
		if (string.IsNullOrEmpty(text))
		{
			throw new EndpointInitializationException("The LecPowerTranslator15 requires the path to the installation folder.");
		}
		context.DisableSpamChecks();
		string text2 = Path.Combine(context.TranslatorDirectory, Path.Combine("FullNET", "Lec.ExtProtocol.exe"));
		if (!File.Exists(text2))
		{
			throw new EndpointInitializationException("Could not find any executable at '" + text2 + "'");
		}
		((ExtProtocolEndpoint)this).ExecutablePath = text2;
		((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
		if (context.SourceLanguage != "ja")
		{
			throw new EndpointInitializationException("Current implementation only supports japanese-to-english.");
		}
		if (context.DestinationLanguage != "en")
		{
			throw new EndpointInitializationException("Current implementation only supports japanese-to-english.");
		}
	}

	public static string GetDefaultInstallationPath()
	{
		try
		{
			string text = GetInstallationPathFromRegistry();
			if (!string.IsNullOrEmpty(text))
			{
				text = new DirectoryInfo(text).Parent.FullName;
			}
			return text ?? string.Empty;
		}
		catch
		{
			return string.Empty;
		}
	}

	public static string GetInstallationPathFromRegistry()
	{
		try
		{
			if (IntPtr.Size == 8)
			{
				return (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LogoMedia\\LEC Power Translator 15\\Configuration", "ApplicationPath", null);
			}
			return (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\LogoMedia\\LEC Power Translator 15\\Configuration", "ApplicationPath", null);
		}
		catch
		{
			return null;
		}
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/LingoCloudTranslate.dll

Decompiled 2 years ago
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("LingoCloudTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LingoCloudTranslate")]
[assembly: AssemblyTitle("LingoCloudTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LingoCloudTranslate;

internal class LingoCloudTranslateEndpoint : HttpEndpoint
{
	private static readonly Dictionary<string, string> SupportedLanguages = new Dictionary<string, string>
	{
		{ "en", "en" },
		{ "ja", "ja" },
		{ "jp", "ja" },
		{ "zh", "zh" },
		{ "zh-Hans", "zh" },
		{ "zh-CN", "zh" },
		{ "zh-Hant", "zh" },
		{ "zh-TW", "zh" }
	};

	private static readonly string HttpServicePointTemplateUrl = "https://api.interpreter.caiyunai.com/v1/translator";

	public string _token;

	public override string Id => "LingoCloudTranslate";

	public override string FriendlyName => "CaiYun Translator";

	private string FixLanguage(string lang)
	{
		if (SupportedLanguages.TryGetValue(lang, out var value))
		{
			return value;
		}
		return lang;
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_002d: 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_009b: Unknown result type (might be due to invalid IL or missing references)
		_token = context.GetOrCreateSetting<string>("LingoCloud", "LingoCloudToken", "");
		if (string.IsNullOrEmpty(_token))
		{
			throw new EndpointInitializationException("The LingoCloudTranslate endpoint requires an App Id which has not been provided.");
		}
		context.DisableCertificateChecksFor(new string[1] { "api.interpreter.caiyunai.com" });
		if (!SupportedLanguages.ContainsKey(context.SourceLanguage))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.ContainsKey(context.DestinationLanguage))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Expected O, but got Unknown
		JSONObject val = new JSONObject();
		string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts;
		foreach (string text in untranslatedTexts)
		{
			((JSONNode)val)["source"].Add(JSONNode.op_Implicit(text));
		}
		((JSONNode)val)["trans_type"] = JSONNode.op_Implicit("auto2" + FixLanguage(((ITranslationContextBase)context).DestinationLanguage));
		((JSONNode)val)["request_id"] = JSONNode.op_Implicit("demo");
		((JSONNode)val)["detect"] = JSONNode.op_Implicit("true");
		string text2 = ((object)val).ToString();
		XUnityWebRequest val2 = new XUnityWebRequest("POST", HttpServicePointTemplateUrl, text2);
		val2.Headers[HttpRequestHeader.ContentType] = "application/json";
		val2.Headers["X-Authorization"] = "token " + _token;
		context.Complete(val2);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		string text = ((object)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["target"]).ToString();
		string text2 = JsonHelper.Unescape(text.Substring(2, text.Length - 4));
		context.Complete(text2);
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/PapagoTranslate.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core;
using XUnity.AutoTranslator.Plugin.Core.Constants;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Shims;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;
using XUnity.Common.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("PapagoTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PapagoTranslate")]
[assembly: AssemblyTitle("PapagoTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PapagoTranslate;

public class PapagoTranslateEndpoint : HttpEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"en", "ko", "zh-CN", "zh-TW", "es", "fr", "ru", "vi", "th", "id",
		"de", "ja", "hi", "pt"
	};

	private static readonly HashSet<string> SMTLanguages = new HashSet<string> { "hi", "pt" };

	private static readonly string UrlBase = "https://papago.naver.com";

	private static readonly string UrlN2MT = "/apis/n2mt/translate";

	private static readonly string UrlNSMT = "/apis/nsmt/translate";

	private static readonly string FormUrlEncodedTemplate = "deviceId={0}&locale=en&dict=false&honorific=false&instant=true&source={1}&target={2}&text={3}";

	private static readonly Random RandomNumbers = new Random();

	private static readonly Guid UUID = Guid.NewGuid();

	private static readonly Regex PatternSource = new Regex("/vendors~main[^\"]+", RegexOptions.Singleline);

	private static readonly Regex PatternVersion = new Regex("v\\d\\.\\d\\.\\d_[^\"]+", RegexOptions.Singleline);

	private string _version;

	private bool _isSMT;

	private int _translationCount;

	private int _resetAfter;

	public override string Id => "PapagoTranslate";

	public override string FriendlyName => "Papago Translator";

	public override int MaxTranslationsPerRequest => 10;

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-Hans":
		case "zh":
			return "zh-CN";
		case "zh-Hant":
			return "zh-TW";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		context.DisableCertificateChecksFor(new string[1] { "papago.naver.com" });
		string text = FixLanguage(context.SourceLanguage);
		string text2 = FixLanguage(context.DestinationLanguage);
		_isSMT = SMTLanguages.Contains(text) || SMTLanguages.Contains(text2);
		if (!SupportedLanguages.Contains(text2))
		{
			throw new EndpointInitializationException("The language '" + context.DestinationLanguage + "' is not supported by Papago Translate.");
		}
		if (_isSMT && text != "en" && text2 != "en")
		{
			throw new EndpointInitializationException("Translation from '" + context.SourceLanguage + "' to '" + context.DestinationLanguage + "' is not supported by Papago Translate.");
		}
	}

	public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context)
	{
		if (_resetAfter == 0 || _translationCount % _resetAfter == 0)
		{
			_translationCount = 1;
			_resetAfter = RandomNumbers.Next(150, 200);
			IEnumerator enumerator = SetupVersion();
			while (enumerator.MoveNext())
			{
				yield return enumerator.Current;
			}
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		string text = Uri.EscapeDataString(string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts));
		XUnityWebRequest val = new XUnityWebRequest("POST", UrlBase + (_isSMT ? UrlNSMT : UrlN2MT), string.Format(FormUrlEncodedTemplate, UUID, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), text));
		DateTime utcNow = DateTime.UtcNow;
		DateTime minValue = DateTime.MinValue;
		double num = Math.Truncate(utcNow.Subtract(minValue.AddYears(1969)).TotalMilliseconds);
		byte[] bytes = Encoding.UTF8.GetBytes(_version);
		byte[] bytes2 = Encoding.UTF8.GetBytes($"{UUID}\n{val.Address}\n{num}");
		string arg = Convert.ToBase64String(new HMACMD5(bytes).ComputeHash(bytes2));
		val.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent);
		val.Headers["Authorization"] = $"PPG {UUID}:{arg}";
		val.Headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8";
		val.Headers["Timestamp"] = num.ToString();
		context.Complete(val);
		_translationCount++;
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		string text = ((object)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["translatedText"]).ToString();
		string text2 = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
		if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1)
		{
			context.Complete(text2);
			return;
		}
		string[] array = text2.Split(new char[1] { '\n' });
		string[] array2 = new string[((ITranslationContextBase)context).UntranslatedTexts.Length];
		int num = 0;
		for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++)
		{
			string[] array3 = ((ITranslationContextBase)context).UntranslatedTexts[i].Split(new char[1] { '\n' });
			StringBuilder stringBuilder = new StringBuilder();
			for (int j = 0; j < array3.Length; j++)
			{
				string value = array[num++];
				if (array3.Length - 1 == j)
				{
					stringBuilder.Append(value);
				}
				else
				{
					stringBuilder.AppendLine(value);
				}
			}
			array2[i] = stringBuilder.ToString();
		}
		if (num != array.Length)
		{
			((ITranslationContextBase)context).Fail("Received invalid number of translations in batch.");
		}
		context.Complete(array2);
	}

	private IEnumerator SetupVersion()
	{
		XUnityWebClient client = new XUnityWebClient();
		XUnityWebResponse response2 = client.Send(new XUnityWebRequest(UrlBase));
		IEnumerator iterator2 = ((CustomYieldInstructionShim)response2).GetSupportedEnumerator();
		while (iterator2.MoveNext())
		{
			yield return iterator2.Current;
		}
		Match match = PatternSource.Match(response2.Data);
		if (!match.Success)
		{
			XuaLogger.AutoTranslator.Warn("Could not parse papago page");
			yield break;
		}
		string value = match.Value;
		response2 = client.Send(new XUnityWebRequest(UrlBase + value));
		iterator2 = ((CustomYieldInstructionShim)response2).GetSupportedEnumerator();
		while (iterator2.MoveNext())
		{
			yield return iterator2.Current;
		}
		Match match2 = PatternVersion.Match(response2.Data);
		if (!match2.Success)
		{
			XuaLogger.AutoTranslator.Warn("Could not parse papago version");
			yield break;
		}
		XuaLogger.AutoTranslator.Debug("Current papago version is " + match2.Value);
		_version = match2.Value;
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/WatsonTranslate.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Www;
using XUnity.AutoTranslator.Plugin.Core.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("WatsonTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WatsonTranslate")]
[assembly: AssemblyTitle("WatsonTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace WatsonTranslate;

internal class WatsonTranslateEndpoint : WwwEndpoint
{
	private static readonly HashSet<string> SupportedLanguagePairs = new HashSet<string>
	{
		"ar-en", "ca-es", "zh-en", "zh-TW-en", "cs-en", "da-en", "nl-en", "en-ar", "en-cs", "en-da",
		"en-de", "en-es", "en-fi", "en-fr", "en-hi", "en-it", "en-ja", "en-ko", "en-nb", "en-nl",
		"en-pl", "en-pt", "en-ru", "en-sv", "en-tr", "en-zh", "en-zh-TW", "fi-en", "fr-de", "fr-en",
		"fr-es", "de-en", "de-fr", "de-it", "hi-en", "hu-en", "it-de", "it-en", "ja-en", "ko-en",
		"nb-en", "pl-en", "pt-en", "ru-en", "es-ca", "es-en", "es-fr", "sv-en", "tr-en"
	};

	private string _fullUrl;

	private string _url;

	private string _key;

	public override string Id => "WatsonTranslate";

	public override string FriendlyName => "Watson Language Translator";

	public override int MaxTranslationsPerRequest => 10;

	private string FixLanguage(string lang)
	{
		switch (lang)
		{
		case "zh-CN":
		case "zh-Hans":
			return "zh";
		case "zh-Hant":
			return "zh-TW";
		default:
			return lang;
		}
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0048: 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)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		_url = context.GetOrCreateSetting<string>("Watson", "Url", "");
		_key = context.GetOrCreateSetting<string>("Watson", "Key", "");
		if (string.IsNullOrEmpty(_url))
		{
			throw new EndpointInitializationException("The WatsonTranslate endpoint requires a url which has not been provided.");
		}
		if (string.IsNullOrEmpty(_key))
		{
			throw new EndpointInitializationException("The WatsonTranslate endpoint requires a key which has not been provided.");
		}
		_fullUrl = _url.TrimEnd(new char[1] { '/' }) + "/v3/translate?version=2018-05-01";
		string text = FixLanguage(context.SourceLanguage) + "-" + FixLanguage(context.DestinationLanguage);
		if (!SupportedLanguagePairs.Contains(text))
		{
			throw new EndpointInitializationException("The language model '" + text + "' is not supported.");
		}
	}

	public override void OnCreateRequest(IWwwRequestCreationContext context)
	{
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Expected O, but got Unknown
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("{\"text\":[");
		for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++)
		{
			string value = JsonHelper.Escape(((ITranslationContextBase)context).UntranslatedTexts[i]);
			stringBuilder.Append("\"").Append(value).Append("\"");
			if (((ITranslationContextBase)context).UntranslatedTexts.Length - 1 != i)
			{
				stringBuilder.Append(",");
			}
		}
		stringBuilder.Append("],\"model_id\":\"").Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage)).Append("-")
			.Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage))
			.Append("\"}");
		WwwRequestInfo val = new WwwRequestInfo(_fullUrl, stringBuilder.ToString());
		val.Headers["Accept"] = "application/json";
		val.Headers["Content-Type"] = "application/json";
		val.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("apikey:" + _key));
		context.Complete(val);
	}

	public override void OnExtractTranslation(IWwwTranslationExtractionContext context)
	{
		JSONArray asArray = ((JSONNode)JSON.Parse(context.ResponseData).AsObject)["translations"].AsArray;
		List<string> list = new List<string>();
		for (int i = 0; i < ((JSONNode)asArray).Count; i++)
		{
			string text = ((object)((JSONNode)((JSONNode)asArray)[i].AsObject)["translation"]).ToString();
			string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2));
			list.Add(item);
		}
		context.Complete(list.ToArray());
	}
}

BepInEx/plugins/XUnity.AutoTranslator/Translators/YandexTranslate.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using SimpleJSON;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("YandexTranslate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("YandexTranslate")]
[assembly: AssemblyTitle("YandexTranslate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace YandexTranslate;

internal class YandexTranslateEndpoint : HttpEndpoint
{
	private static readonly HashSet<string> SupportedLanguages = new HashSet<string>
	{
		"az", "sq", "am", "en", "ar", "hy", "af", "eu", "ba", "be",
		"bn", "my", "bg", "bs", "cy", "hu", "vi", "ht", "gl", "nl",
		"mrj", "el", "ka", "gu", "da", "he", "yi", "id", "ga", "it",
		"is", "es", "kk", "kn", "ca", "ky", "zh", "ko", "xh", "km",
		"lo", "la", "lv", "lt", "lb", "mg", "ms", "ml", "mt", "mk",
		"mi", "mr", "mhr", "mn", "de", "ne", "no", "pa", "pap", "fa",
		"pl", "pt", "ro", "ru", "ceb", "sr", "si", "sk", "sl", "sw",
		"su", "tg", "th", "tl", "ta", "tt", "te", "tr", "udm", "uz",
		"uk", "ur", "fi", "fr", "hi", "hr", "cs", "sv", "gd", "et",
		"eo", "jv", "ja"
	};

	private static readonly string HttpsServicePointTemplateUrl = "https://translate.yandex.net/api/v1.5/tr.json/translate?key={3}&text={2}&lang={0}-{1}&format=plain";

	private string _key;

	public override string Id => "YandexTranslate";

	public override string FriendlyName => "Yandex Translate";

	private string FixLanguage(string lang)
	{
		if (lang == "zh-CN" || lang == "zh-Hans")
		{
			return "zh";
		}
		return lang;
	}

	public override void Initialize(IInitializationContext context)
	{
		//IL_0041: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		_key = context.GetOrCreateSetting<string>("Yandex", "YandexAPIKey", "");
		context.DisableCertificateChecksFor(new string[1] { "translate.yandex.net" });
		if (string.IsNullOrEmpty(_key))
		{
			throw new EndpointInitializationException("The YandexTranslate endpoint requires an API key which has not been provided.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage)))
		{
			throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported.");
		}
		if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage)))
		{
			throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported.");
		}
	}

	public override void OnCreateRequest(IHttpRequestCreationContext context)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpsServicePointTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), _key));
		val.Headers[HttpRequestHeader.Accept] = "*/*";
		val.Headers[HttpRequestHeader.AcceptCharset] = "UTF-8";
		context.Complete(val);
	}

	public override void OnExtractTranslation(IHttpTranslationExtractionContext context)
	{
		JSONNode obj = JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data);
		string text = ((object)((JSONNode)obj.AsObject)["code"]).ToString();
		if (text != "200")
		{
			((ITranslationContextBase)context).Fail("Received bad response code: " + text);
		}
		string text2 = ((object)((JSONNode)obj.AsObject)["text"]).ToString();
		string text3 = JsonHelper.Unescape(text2.Substring(2, text2.Length - 4));
		if (string.IsNullOrEmpty(text3))
		{
			((ITranslationContextBase)context).Fail("Received no translation.");
		}
		context.Complete(text3);
	}
}

BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.BepInEx.dll

Decompiled 2 years ago
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using ExIni;
using XUnity.AutoTranslator.Plugin.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("XUnity.AutoTranslator.Plugin.BepInEx")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("5.3.0.0")]
[assembly: AssemblyInformationalVersion("5.3.0+27fbfc0c2dfc32b3bb59b97a5639344e09ecfdc5")]
[assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.BepInEx")]
[assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.BepInEx")]
[assembly: AssemblyVersion("5.3.0.0")]
namespace XUnity.AutoTranslator.Plugin.BepInEx;

[BepInPlugin("gravydevsupreme.xunity.autotranslator", "XUnity Auto Translator", "5.3.0")]
public class AutoTranslatorPlugin : BaseUnityPlugin, IPluginEnvironment
{
	private IniFile _file;

	private string _configPath;

	public IniFile Preferences => _file ?? (_file = ReloadConfig());

	public string ConfigPath { get; }

	public string TranslationPath { get; }

	public bool AllowDefaultInitializeHarmonyDetourBridge => false;

	public AutoTranslatorPlugin()
	{
		ConfigPath = Paths.ConfigPath;
		TranslationPath = Paths.BepInExRootPath;
		_configPath = Path.Combine(ConfigPath, "AutoTranslatorConfig.ini");
	}

	public IniFile ReloadConfig()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (!File.Exists(_configPath))
		{
			return (IniFile)(((object)_file) ?? ((object)new IniFile()));
		}
		IniFile val = IniFile.FromFile(_configPath);
		if (_file == null)
		{
			return _file = val;
		}
		_file.Merge(val);
		return _file;
	}

	public void SaveConfig()
	{
		_file.Save(_configPath);
	}

	private void Awake()
	{
		PluginLoader.LoadWithConfig((IPluginEnvironment)(object)this);
	}
}

BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.Core.dll

Decompiled 2 years ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Cache;
using System.Net.Security;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using DynamicLinq;
using ExIni;
using Harmony;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Encryption;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using UnityEngine;
using UnityEngine.SceneManagement;
using XUnity.AutoTranslator.Plugin.Core.AssetRedirection;
using XUnity.AutoTranslator.Plugin.Core.Configuration;
using XUnity.AutoTranslator.Plugin.Core.Debugging;
using XUnity.AutoTranslator.Plugin.Core.Endpoints;
using XUnity.AutoTranslator.Plugin.Core.Extensions;
using XUnity.AutoTranslator.Plugin.Core.Fonts;
using XUnity.AutoTranslator.Plugin.Core.Hooks;
using XUnity.AutoTranslator.Plugin.Core.Hooks.NGUI;
using XUnity.AutoTranslator.Plugin.Core.Hooks.TextMeshPro;
using XUnity.AutoTranslator.Plugin.Core.Hooks.UGUI;
using XUnity.AutoTranslator.Plugin.Core.Managed.Textures;
using XUnity.AutoTranslator.Plugin.Core.Parsing;
using XUnity.AutoTranslator.Plugin.Core.Properties;
using XUnity.AutoTranslator.Plugin.Core.Shims;
using XUnity.AutoTranslator.Plugin.Core.Text;
using XUnity.AutoTranslator.Plugin.Core.Textures;
using XUnity.AutoTranslator.Plugin.Core.UI;
using XUnity.AutoTranslator.Plugin.Core.UIResize;
using XUnity.AutoTranslator.Plugin.Core.Utilities;
using XUnity.AutoTranslator.Plugin.Core.Web;
using XUnity.AutoTranslator.Plugin.Core.Web.Internal;
using XUnity.AutoTranslator.Plugin.ExtProtocol;
using XUnity.AutoTranslator.Plugin.Utilities;
using XUnity.Common.Constants;
using XUnity.Common.Extensions;
using XUnity.Common.Harmony;
using XUnity.Common.Logging;
using XUnity.Common.MonoMod;
using XUnity.Common.Utilities;
using XUnity.ResourceRedirector;

[assembly: AssemblyFileVersion("5.3.0.0")]
[assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.Core")]
[assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.Core")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: InternalsVisibleTo("XUnity.AutoTranslator.Plugin.Core.Tests")]
[assembly: AssemblyInformationalVersion("5.3.0+27fbfc0c2dfc32b3bb59b97a5639344e09ecfdc5")]
[assembly: AssemblyDescription("Main development dependency for XUnity Auto Translator.")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCompany("gravydevsupreme")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("5.3.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]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DynamicLinq
{
	internal static class DynamicQueryable
	{
		public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values)
		{
			return (IQueryable<T>)((IQueryable)source).Where(predicate, values);
		}

		public static IQueryable Where(this IQueryable source, string predicate, params object[] values)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (predicate == null)
			{
				throw new ArgumentNullException("predicate");
			}
			LambdaExpression expression = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);
			return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Where", new Type[1] { source.ElementType }, source.Expression, Expression.Quote(expression)));
		}

		public static IQueryable Select(this IQueryable source, string selector, params object[] values)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (selector == null)
			{
				throw new ArgumentNullException("selector");
			}
			LambdaExpression lambdaExpression = DynamicExpression.ParseLambda(source.ElementType, null, selector, values);
			return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Select", new Type[2]
			{
				source.ElementType,
				lambdaExpression.Body.Type
			}, source.Expression, Expression.Quote(lambdaExpression)));
		}

		public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values)
		{
			return (IQueryable<T>)((IQueryable)source).OrderBy(ordering, values);
		}

		public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (ordering == null)
			{
				throw new ArgumentNullException("ordering");
			}
			ParameterExpression[] parameters = new ParameterExpression[1] { Expression.Parameter(source.ElementType, "") };
			ExpressionParser expressionParser = new ExpressionParser(parameters, ordering, values);
			IEnumerable<DynamicOrdering> enumerable = expressionParser.ParseOrdering();
			Expression expression = source.Expression;
			string text = "OrderBy";
			string text2 = "OrderByDescending";
			foreach (DynamicOrdering item in enumerable)
			{
				expression = Expression.Call(typeof(Queryable), item.Ascending ? text : text2, new Type[2]
				{
					source.ElementType,
					item.Selector.Type
				}, expression, Expression.Quote(Expression.Lambda(item.Selector, parameters)));
				text = "ThenBy";
				text2 = "ThenByDescending";
			}
			return source.Provider.CreateQuery(expression);
		}

		public static IQueryable Take(this IQueryable source, int count)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Take", new Type[1] { source.ElementType }, source.Expression, Expression.Constant(count)));
		}

		public static IQueryable Skip(this IQueryable source, int count)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Skip", new Type[1] { source.ElementType }, source.Expression, Expression.Constant(count)));
		}

		public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			if (keySelector == null)
			{
				throw new ArgumentNullException("keySelector");
			}
			if (elementSelector == null)
			{
				throw new ArgumentNullException("elementSelector");
			}
			LambdaExpression lambdaExpression = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values);
			LambdaExpression lambdaExpression2 = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, values);
			return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "GroupBy", new Type[3]
			{
				source.ElementType,
				lambdaExpression.Body.Type,
				lambdaExpression2.Body.Type
			}, source.Expression, Expression.Quote(lambdaExpression), Expression.Quote(lambdaExpression2)));
		}

		public static bool Any(this IQueryable source)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			return (bool)source.Provider.Execute(Expression.Call(typeof(Queryable), "Any", new Type[1] { source.ElementType }, source.Expression));
		}

		public static int Count(this IQueryable source)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			return (int)source.Provider.Execute(Expression.Call(typeof(Queryable), "Count", new Type[1] { source.ElementType }, source.Expression));
		}
	}
	internal abstract class DynamicClass
	{
		public override string ToString()
		{
			PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("{");
			for (int i = 0; i < properties.Length; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(properties[i].Name);
				stringBuilder.Append("=");
				stringBuilder.Append(properties[i].GetValue(this, null));
			}
			stringBuilder.Append("}");
			return stringBuilder.ToString();
		}
	}
	internal class DynamicProperty
	{
		private string name;

		private Type type;

		public string Name => name;

		public Type Type => type;

		public DynamicProperty(string name, Type type)
		{
			if (name == null)
			{
				throw new ArgumentNullException("name");
			}
			if ((object)type == null)
			{
				throw new ArgumentNullException("type");
			}
			this.name = name;
			this.type = type;
		}
	}
	internal static class DynamicExpression
	{
		public static Expression Parse(Type resultType, string expression, params object[] values)
		{
			ExpressionParser expressionParser = new ExpressionParser(null, expression, values);
			return expressionParser.Parse(resultType);
		}

		public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, params object[] values)
		{
			return ParseLambda(new ParameterExpression[1] { Expression.Parameter(itType, "") }, resultType, expression, values);
		}

		public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values)
		{
			ExpressionParser expressionParser = new ExpressionParser(parameters, expression, values);
			return Expression.Lambda(expressionParser.Parse(resultType), parameters);
		}

		public static Expression<Func<T, S>> ParseLambda<T, S>(string expression, params object[] values)
		{
			return (Expression<Func<T, S>>)ParseLambda(typeof(T), typeof(S), expression, values);
		}

		public static Type CreateClass(params DynamicProperty[] properties)
		{
			throw new NotImplementedException();
		}

		public static Type CreateClass(IEnumerable<DynamicProperty> properties)
		{
			throw new NotImplementedException();
		}
	}
	internal class DynamicOrdering
	{
		public Expression Selector;

		public bool Ascending;
	}
	internal class Signature : IEquatable<Signature>
	{
		public DynamicProperty[] properties;

		public int hashCode;

		public Signature(IEnumerable<DynamicProperty> properties)
		{
			this.properties = properties.ToArray();
			hashCode = 0;
			foreach (DynamicProperty property in properties)
			{
				hashCode ^= property.Name.GetHashCode() ^ property.Type.GetHashCode();
			}
		}

		public override int GetHashCode()
		{
			return hashCode;
		}

		public override bool Equals(object obj)
		{
			return obj is Signature && Equals((Signature)obj);
		}

		public bool Equals(Signature other)
		{
			if (properties.Length != other.properties.Length)
			{
				return false;
			}
			for (int i = 0; i < properties.Length; i++)
			{
				if (properties[i].Name != other.properties[i].Name || (object)properties[i].Type != other.properties[i].Type)
				{
					return false;
				}
			}
			return true;
		}
	}
	internal sealed class ParseException : Exception
	{
		private int position;

		public int Position => position;

		public ParseException(string message, int position)
			: base(message)
		{
			this.position = position;
		}

		public override string ToString()
		{
			return $"{Message} (at index {position})";
		}
	}
	internal class ExpressionParser
	{
		private struct Token
		{
			public TokenId id;

			public string text;

			public int pos;
		}

		private enum TokenId
		{
			Unknown,
			End,
			Identifier,
			StringLiteral,
			IntegerLiteral,
			RealLiteral,
			Exclamation,
			Percent,
			Amphersand,
			OpenParen,
			CloseParen,
			Asterisk,
			Plus,
			Comma,
			Minus,
			Dot,
			Slash,
			Colon,
			LessThan,
			Equal,
			GreaterThan,
			Question,
			OpenBracket,
			CloseBracket,
			Bar,
			ExclamationEqual,
			DoubleAmphersand,
			LessThanEqual,
			LessGreater,
			DoubleEqual,
			GreaterThanEqual,
			DoubleBar
		}

		private interface ILogicalSignatures
		{
			void F(bool x, bool y);

			void F(bool? x, bool? y);
		}

		private interface IArithmeticSignatures
		{
			void F(int x, int y);

			void F(uint x, uint y);

			void F(long x, long y);

			void F(ulong x, ulong y);

			void F(float x, float y);

			void F(double x, double y);

			void F(decimal x, decimal y);

			void F(int? x, int? y);

			void F(uint? x, uint? y);

			void F(long? x, long? y);

			void F(ulong? x, ulong? y);

			void F(float? x, float? y);

			void F(double? x, double? y);

			void F(decimal? x, decimal? y);
		}

		private interface IRelationalSignatures : IArithmeticSignatures
		{
			void F(string x, string y);

			void F(char x, char y);

			void F(DateTime x, DateTime y);

			void F(TimeSpan x, TimeSpan y);

			void F(char? x, char? y);

			void F(DateTime? x, DateTime? y);

			void F(TimeSpan? x, TimeSpan? y);
		}

		private interface IEqualitySignatures : IRelationalSignatures, IArithmeticSignatures
		{
			void F(bool x, bool y);

			void F(bool? x, bool? y);
		}

		private interface IAddSignatures : IArithmeticSignatures
		{
			void F(DateTime x, TimeSpan y);

			void F(TimeSpan x, TimeSpan y);

			void F(DateTime? x, TimeSpan? y);

			void F(TimeSpan? x, TimeSpan? y);
		}

		private interface ISubtractSignatures : IAddSignatures, IArithmeticSignatures
		{
			void F(DateTime x, DateTime y);

			void F(DateTime? x, DateTime? y);
		}

		private interface INegationSignatures
		{
			void F(int x);

			void F(long x);

			void F(float x);

			void F(double x);

			void F(decimal x);

			void F(int? x);

			void F(long? x);

			void F(float? x);

			void F(double? x);

			void F(decimal? x);
		}

		private interface INotSignatures
		{
			void F(bool x);

			void F(bool? x);
		}

		private interface IEnumerableSignatures
		{
			void Where(bool predicate);

			void Any();

			void Any(bool predicate);

			void All(bool predicate);

			void Count();

			void Count(bool predicate);

			void Min(object selector);

			void Max(object selector);

			void Sum(int selector);

			void Sum(int? selector);

			void Sum(long selector);

			void Sum(long? selector);

			void Sum(float selector);

			void Sum(float? selector);

			void Sum(double selector);

			void Sum(double? selector);

			void Sum(decimal selector);

			void Sum(decimal? selector);

			void Average(int selector);

			void Average(int? selector);

			void Average(long selector);

			void Average(long? selector);

			void Average(float selector);

			void Average(float? selector);

			void Average(double selector);

			void Average(double? selector);

			void Average(decimal selector);

			void Average(decimal? selector);
		}

		private class MethodData
		{
			public MethodBase MethodBase;

			public ParameterInfo[] Parameters;

			public Expression[] Args;
		}

		private static readonly Type[] predefinedTypes = new Type[20]
		{
			typeof(object),
			typeof(bool),
			typeof(char),
			typeof(string),
			typeof(sbyte),
			typeof(byte),
			typeof(short),
			typeof(ushort),
			typeof(int),
			typeof(uint),
			typeof(long),
			typeof(ulong),
			typeof(float),
			typeof(double),
			typeof(decimal),
			typeof(DateTime),
			typeof(TimeSpan),
			typeof(Guid),
			typeof(Math),
			typeof(Convert)
		};

		private static readonly Expression trueLiteral = Expression.Constant(true);

		private static readonly Expression falseLiteral = Expression.Constant(false);

		private static readonly Expression nullLiteral = Expression.Constant(null);

		private static readonly string keywordIt = "it";

		private static readonly string keywordIif = "iif";

		private static readonly string keywordNew = "new";

		private static Dictionary<string, object> keywords;

		private Dictionary<string, object> symbols;

		private IDictionary<string, object> externals;

		private Dictionary<Expression, string> literals;

		private ParameterExpression it;

		private string text;

		private int textPos;

		private int textLen;

		private char ch;

		private Token token;

		public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values)
		{
			if (expression == null)
			{
				throw new ArgumentNullException("expression");
			}
			if (keywords == null)
			{
				keywords = CreateKeywords();
			}
			symbols = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
			literals = new Dictionary<Expression, string>();
			if (parameters != null)
			{
				ProcessParameters(parameters);
			}
			if (values != null)
			{
				ProcessValues(values);
			}
			text = expression;
			textLen = text.Length;
			SetTextPos(0);
			NextToken();
		}

		private void ProcessParameters(ParameterExpression[] parameters)
		{
			foreach (ParameterExpression parameterExpression in parameters)
			{
				if (!string.IsNullOrEmpty(parameterExpression.Name))
				{
					AddSymbol(parameterExpression.Name, parameterExpression);
				}
			}
			if (parameters.Length == 1 && string.IsNullOrEmpty(parameters[0].Name))
			{
				it = parameters[0];
			}
		}

		private void ProcessValues(object[] values)
		{
			for (int i = 0; i < values.Length; i++)
			{
				object obj = values[i];
				if (i == values.Length - 1 && obj is IDictionary<string, object>)
				{
					externals = (IDictionary<string, object>)obj;
				}
				else
				{
					AddSymbol("@" + i.ToString(CultureInfo.InvariantCulture), obj);
				}
			}
		}

		private void AddSymbol(string name, object value)
		{
			if (symbols.ContainsKey(name))
			{
				throw ParseError("The identifier '{0}' was defined more than once", name);
			}
			symbols.Add(name, value);
		}

		public Expression Parse(Type resultType)
		{
			int pos = token.pos;
			Expression expression = ParseExpression();
			if ((object)resultType != null && (expression = PromoteExpression(expression, resultType, exact: true)) == null)
			{
				throw ParseError(pos, "Expression of type '{0}' expected", GetTypeName(resultType));
			}
			ValidateToken(TokenId.End, "Syntax error");
			return expression;
		}

		public IEnumerable<DynamicOrdering> ParseOrdering()
		{
			List<DynamicOrdering> list = new List<DynamicOrdering>();
			while (true)
			{
				Expression selector = ParseExpression();
				bool ascending = true;
				if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending"))
				{
					NextToken();
				}
				else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending"))
				{
					NextToken();
					ascending = false;
				}
				list.Add(new DynamicOrdering
				{
					Selector = selector,
					Ascending = ascending
				});
				if (token.id != TokenId.Comma)
				{
					break;
				}
				NextToken();
			}
			ValidateToken(TokenId.End, "Syntax error");
			return list;
		}

		private Expression ParseExpression()
		{
			int pos = token.pos;
			Expression expression = ParseLogicalOr();
			if (token.id == TokenId.Question)
			{
				NextToken();
				Expression expr = ParseExpression();
				ValidateToken(TokenId.Colon, "':' expected");
				NextToken();
				Expression expr2 = ParseExpression();
				expression = GenerateConditional(expression, expr, expr2, pos);
			}
			return expression;
		}

		private Expression ParseLogicalOr()
		{
			Expression left = ParseLogicalAnd();
			while (this.token.id == TokenId.DoubleBar || TokenIdentifierIs("or"))
			{
				Token token = this.token;
				NextToken();
				Expression right = ParseLogicalAnd();
				CheckAndPromoteOperands(typeof(ILogicalSignatures), token.text, ref left, ref right, token.pos);
				left = Expression.OrElse(left, right);
			}
			return left;
		}

		private Expression ParseLogicalAnd()
		{
			Expression left = ParseComparison();
			while (this.token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and"))
			{
				Token token = this.token;
				NextToken();
				Expression right = ParseComparison();
				CheckAndPromoteOperands(typeof(ILogicalSignatures), token.text, ref left, ref right, token.pos);
				left = Expression.AndAlso(left, right);
			}
			return left;
		}

		private Expression ParseComparison()
		{
			Expression left = ParseAdditive();
			while (this.token.id == TokenId.Equal || this.token.id == TokenId.DoubleEqual || this.token.id == TokenId.ExclamationEqual || this.token.id == TokenId.LessGreater || this.token.id == TokenId.GreaterThan || this.token.id == TokenId.GreaterThanEqual || this.token.id == TokenId.LessThan || this.token.id == TokenId.LessThanEqual)
			{
				Token token = this.token;
				NextToken();
				Expression right = ParseAdditive();
				bool flag = token.id == TokenId.Equal || token.id == TokenId.DoubleEqual || token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater;
				if (flag && !left.Type.IsValueType && !right.Type.IsValueType)
				{
					if ((object)left.Type != right.Type)
					{
						if (left.Type.IsAssignableFrom(right.Type))
						{
							right = Expression.Convert(right, left.Type);
						}
						else
						{
							if (!right.Type.IsAssignableFrom(left.Type))
							{
								throw IncompatibleOperandsError(token.text, left, right, token.pos);
							}
							left = Expression.Convert(left, right.Type);
						}
					}
				}
				else if (IsEnumType(left.Type) || IsEnumType(right.Type))
				{
					if ((object)left.Type != right.Type)
					{
						Expression expression;
						if ((expression = PromoteExpression(right, left.Type, exact: true)) != null)
						{
							right = expression;
						}
						else
						{
							if ((expression = PromoteExpression(left, right.Type, exact: true)) == null)
							{
								throw IncompatibleOperandsError(token.text, left, right, token.pos);
							}
							left = expression;
						}
					}
				}
				else
				{
					CheckAndPromoteOperands(flag ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), token.text, ref left, ref right, token.pos);
				}
				switch (token.id)
				{
				case TokenId.Equal:
				case TokenId.DoubleEqual:
					left = GenerateEqual(left, right);
					break;
				case TokenId.ExclamationEqual:
				case TokenId.LessGreater:
					left = GenerateNotEqual(left, right);
					break;
				case TokenId.GreaterThan:
					left = GenerateGreaterThan(left, right);
					break;
				case TokenId.GreaterThanEqual:
					left = GenerateGreaterThanEqual(left, right);
					break;
				case TokenId.LessThan:
					left = GenerateLessThan(left, right);
					break;
				case TokenId.LessThanEqual:
					left = GenerateLessThanEqual(left, right);
					break;
				}
			}
			return left;
		}

		private Expression ParseAdditive()
		{
			Expression left = ParseMultiplicative();
			while (this.token.id == TokenId.Plus || this.token.id == TokenId.Minus || this.token.id == TokenId.Amphersand)
			{
				Token token = this.token;
				NextToken();
				Expression right = ParseMultiplicative();
				TokenId id = token.id;
				TokenId tokenId = id;
				if (tokenId != TokenId.Amphersand)
				{
					if (tokenId != TokenId.Plus)
					{
						if (tokenId == TokenId.Minus)
						{
							CheckAndPromoteOperands(typeof(ISubtractSignatures), token.text, ref left, ref right, token.pos);
							left = GenerateSubtract(left, right);
						}
						continue;
					}
					if ((object)left.Type != typeof(string) && (object)right.Type != typeof(string))
					{
						CheckAndPromoteOperands(typeof(IAddSignatures), token.text, ref left, ref right, token.pos);
						left = GenerateAdd(left, right);
						continue;
					}
				}
				left = GenerateStringConcat(left, right);
			}
			return left;
		}

		private Expression ParseMultiplicative()
		{
			Expression left = ParseUnary();
			while (this.token.id == TokenId.Asterisk || this.token.id == TokenId.Slash || this.token.id == TokenId.Percent || TokenIdentifierIs("mod"))
			{
				Token token = this.token;
				NextToken();
				Expression right = ParseUnary();
				CheckAndPromoteOperands(typeof(IArithmeticSignatures), token.text, ref left, ref right, token.pos);
				switch (token.id)
				{
				case TokenId.Asterisk:
					left = Expression.Multiply(left, right);
					break;
				case TokenId.Slash:
					left = Expression.Divide(left, right);
					break;
				case TokenId.Identifier:
				case TokenId.Percent:
					left = Expression.Modulo(left, right);
					break;
				}
			}
			return left;
		}

		private Expression ParseUnary()
		{
			if (this.token.id == TokenId.Minus || this.token.id == TokenId.Exclamation || TokenIdentifierIs("not"))
			{
				Token token = this.token;
				NextToken();
				if (token.id == TokenId.Minus && (this.token.id == TokenId.IntegerLiteral || this.token.id == TokenId.RealLiteral))
				{
					this.token.text = "-" + this.token.text;
					this.token.pos = token.pos;
					return ParsePrimary();
				}
				Expression expr = ParseUnary();
				if (token.id == TokenId.Minus)
				{
					CheckAndPromoteOperand(typeof(INegationSignatures), token.text, ref expr, token.pos);
					expr = Expression.Negate(expr);
				}
				else
				{
					CheckAndPromoteOperand(typeof(INotSignatures), token.text, ref expr, token.pos);
					expr = Expression.Not(expr);
				}
				return expr;
			}
			return ParsePrimary();
		}

		private Expression ParsePrimary()
		{
			Expression expression = ParsePrimaryStart();
			while (true)
			{
				if (token.id == TokenId.Dot)
				{
					NextToken();
					expression = ParseMemberAccess(null, expression);
					continue;
				}
				if (token.id == TokenId.OpenBracket)
				{
					expression = ParseElementAccess(expression);
					continue;
				}
				break;
			}
			return expression;
		}

		private Expression ParsePrimaryStart()
		{
			return token.id switch
			{
				TokenId.Identifier => ParseIdentifier(), 
				TokenId.StringLiteral => ParseStringLiteral(), 
				TokenId.IntegerLiteral => ParseIntegerLiteral(), 
				TokenId.RealLiteral => ParseRealLiteral(), 
				TokenId.OpenParen => ParseParenExpression(), 
				_ => throw ParseError("Expression expected"), 
			};
		}

		private Expression ParseStringLiteral()
		{
			ValidateToken(TokenId.StringLiteral);
			char c = token.text[0];
			string text = token.text.Substring(1, token.text.Length - 2);
			int startIndex = 0;
			while (true)
			{
				int num = text.IndexOf(c, startIndex);
				if (num < 0)
				{
					break;
				}
				text = text.Remove(num, 1);
				startIndex = num + 1;
			}
			if (c == '\'')
			{
				if (text.Length != 1)
				{
					throw ParseError("Character literal must contain exactly one character");
				}
				NextToken();
				return CreateLiteral(text[0], text);
			}
			NextToken();
			return CreateLiteral(text, text);
		}

		private Expression ParseIntegerLiteral()
		{
			ValidateToken(TokenId.IntegerLiteral);
			string text = token.text;
			if (text[0] != '-')
			{
				if (!ulong.TryParse(text, out var result))
				{
					throw ParseError("Invalid integer literal '{0}'", text);
				}
				NextToken();
				if (result <= int.MaxValue)
				{
					return CreateLiteral((int)result, text);
				}
				if (result <= uint.MaxValue)
				{
					return CreateLiteral((uint)result, text);
				}
				if (result <= long.MaxValue)
				{
					return CreateLiteral((long)result, text);
				}
				return CreateLiteral(result, text);
			}
			if (!long.TryParse(text, out var result2))
			{
				throw ParseError("Invalid integer literal '{0}'", text);
			}
			NextToken();
			if (result2 >= int.MinValue && result2 <= int.MaxValue)
			{
				return CreateLiteral((int)result2, text);
			}
			return CreateLiteral(result2, text);
		}

		private Expression ParseRealLiteral()
		{
			ValidateToken(TokenId.RealLiteral);
			string text = token.text;
			object obj = null;
			char c = text[text.Length - 1];
			double result2;
			if (c == 'F' || c == 'f')
			{
				if (float.TryParse(text.Substring(0, text.Length - 1), out var result))
				{
					obj = result;
				}
			}
			else if (double.TryParse(text, out result2))
			{
				obj = result2;
			}
			if (obj == null)
			{
				throw ParseError("Invalid real literal '{0}'", text);
			}
			NextToken();
			return CreateLiteral(obj, text);
		}

		private Expression CreateLiteral(object value, string text)
		{
			ConstantExpression constantExpression = Expression.Constant(value);
			literals.Add(constantExpression, text);
			return constantExpression;
		}

		private Expression ParseParenExpression()
		{
			ValidateToken(TokenId.OpenParen, "'(' expected");
			NextToken();
			Expression result = ParseExpression();
			ValidateToken(TokenId.CloseParen, "')' or operator expected");
			NextToken();
			return result;
		}

		private Expression ParseIdentifier()
		{
			ValidateToken(TokenId.Identifier);
			if (keywords.TryGetValue(token.text, out var value))
			{
				if (value is Type)
				{
					return ParseTypeAccess((Type)value);
				}
				if (value == keywordIt)
				{
					return ParseIt();
				}
				if (value == keywordIif)
				{
					return ParseIif();
				}
				if (value == keywordNew)
				{
					return ParseNew();
				}
				NextToken();
				return (Expression)value;
			}
			if (symbols.TryGetValue(token.text, out value) || (externals != null && externals.TryGetValue(token.text, out value)))
			{
				Expression expression = value as Expression;
				if (expression == null)
				{
					expression = Expression.Constant(value);
				}
				else if (expression is LambdaExpression lambda)
				{
					return ParseLambdaInvocation(lambda);
				}
				NextToken();
				return expression;
			}
			if (it != null)
			{
				return ParseMemberAccess(null, it);
			}
			throw ParseError("Unknown identifier '{0}'", token.text);
		}

		private Expression ParseIt()
		{
			if (it == null)
			{
				throw ParseError("No 'it' is in scope");
			}
			NextToken();
			return it;
		}

		private Expression ParseIif()
		{
			int pos = token.pos;
			NextToken();
			Expression[] array = ParseArgumentList();
			if (array.Length != 3)
			{
				throw ParseError(pos, "The 'iif' function requires three arguments");
			}
			return GenerateConditional(array[0], array[1], array[2], pos);
		}

		private Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos)
		{
			if ((object)test.Type != typeof(bool))
			{
				throw ParseError(errorPos, "The first expression must be of type 'Boolean'");
			}
			if ((object)expr1.Type != expr2.Type)
			{
				Expression expression = ((expr2 != nullLiteral) ? PromoteExpression(expr1, expr2.Type, exact: true) : null);
				Expression expression2 = ((expr1 != nullLiteral) ? PromoteExpression(expr2, expr1.Type, exact: true) : null);
				if (expression != null && expression2 == null)
				{
					expr1 = expression;
				}
				else
				{
					if (expression2 == null || expression != null)
					{
						string text = ((expr1 != nullLiteral) ? expr1.Type.Name : "null");
						string text2 = ((expr2 != nullLiteral) ? expr2.Type.Name : "null");
						if (expression != null && expression2 != null)
						{
							throw ParseError(errorPos, "Both of the types '{0}' and '{1}' convert to the other", text, text2);
						}
						throw ParseError(errorPos, "Neither of the types '{0}' and '{1}' converts to the other", text, text2);
					}
					expr2 = expression2;
				}
			}
			return Expression.Condition(test, expr1, expr2);
		}

		private Expression ParseNew()
		{
			NextToken();
			ValidateToken(TokenId.OpenParen, "'(' expected");
			NextToken();
			List<DynamicProperty> list = new List<DynamicProperty>();
			List<Expression> list2 = new List<Expression>();
			while (true)
			{
				int pos = token.pos;
				Expression expression = ParseExpression();
				string name;
				if (TokenIdentifierIs("as"))
				{
					NextToken();
					name = GetIdentifier();
					NextToken();
				}
				else
				{
					if (!(expression is MemberExpression memberExpression))
					{
						throw ParseError(pos, "Expression is missing an 'as' clause");
					}
					name = memberExpression.Member.Name;
				}
				list2.Add(expression);
				list.Add(new DynamicProperty(name, expression.Type));
				if (token.id != TokenId.Comma)
				{
					break;
				}
				NextToken();
			}
			ValidateToken(TokenId.CloseParen, "')' or ',' expected");
			NextToken();
			Type type = DynamicExpression.CreateClass(list);
			MemberBinding[] array = new MemberBinding[list.Count];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = Expression.Bind(type.GetProperty(list[i].Name), list2[i]);
			}
			return Expression.MemberInit(Expression.New(type), array);
		}

		private Expression ParseLambdaInvocation(LambdaExpression lambda)
		{
			int pos = token.pos;
			NextToken();
			Expression[] array = ParseArgumentList();
			if (FindMethod(lambda.Type, "Invoke", staticAccess: false, array, out var _) != 1)
			{
				throw ParseError(pos, "Argument list incompatible with lambda expression");
			}
			return Expression.Invoke(lambda, array);
		}

		private Expression ParseTypeAccess(Type type)
		{
			int pos = token.pos;
			NextToken();
			if (token.id == TokenId.Question)
			{
				if (!type.IsValueType || IsNullableType(type))
				{
					throw ParseError(pos, "Type '{0}' has no nullable form", GetTypeName(type));
				}
				type = typeof(Nullable<>).MakeGenericType(type);
				NextToken();
			}
			if (token.id == TokenId.OpenParen)
			{
				Expression[] array = ParseArgumentList();
				MethodBase method;
				switch (FindBestMethod(type.GetConstructors(), array, out method))
				{
				case 0:
					if (array.Length == 1)
					{
						return GenerateConversion(array[0], type, pos);
					}
					throw ParseError(pos, "No matching constructor in type '{0}'", GetTypeName(type));
				case 1:
					return Expression.New((ConstructorInfo)method, array);
				default:
					throw ParseError(pos, "Ambiguous invocation of '{0}' constructor", GetTypeName(type));
				}
			}
			ValidateToken(TokenId.Dot, "'.' or '(' expected");
			NextToken();
			return ParseMemberAccess(type, null);
		}

		private Expression GenerateConversion(Expression expr, Type type, int errorPos)
		{
			Type type2 = expr.Type;
			if ((object)type2 == type)
			{
				return expr;
			}
			if (type2.IsValueType && type.IsValueType)
			{
				if ((IsNullableType(type2) || IsNullableType(type)) && (object)GetNonNullableType(type2) == GetNonNullableType(type))
				{
					return Expression.Convert(expr, type);
				}
				if (((IsNumericType(type2) || IsEnumType(type2)) && IsNumericType(type)) || IsEnumType(type))
				{
					return Expression.ConvertChecked(expr, type);
				}
			}
			if (type2.IsAssignableFrom(type) || type.IsAssignableFrom(type2) || type2.IsInterface || type.IsInterface)
			{
				return Expression.Convert(expr, type);
			}
			throw ParseError(errorPos, "A value of type '{0}' cannot be converted to type '{1}'", GetTypeName(type2), GetTypeName(type));
		}

		private Expression ParseMemberAccess(Type type, Expression instance)
		{
			if (instance != null)
			{
				type = instance.Type;
			}
			int pos = token.pos;
			string identifier = GetIdentifier();
			NextToken();
			if (token.id == TokenId.OpenParen)
			{
				if (instance != null && (object)type != typeof(string))
				{
					Type type2 = FindGenericType(typeof(IEnumerable<>), type);
					if ((object)type2 != null)
					{
						Type elementType = type2.GetGenericArguments()[0];
						return ParseAggregate(instance, elementType, identifier, pos);
					}
				}
				Expression[] array = ParseArgumentList();
				MethodBase method;
				switch (FindMethod(type, identifier, instance == null, array, out method))
				{
				case 0:
					throw ParseError(pos, "No applicable method '{0}' exists in type '{1}'", identifier, GetTypeName(type));
				case 1:
				{
					MethodInfo methodInfo = (MethodInfo)method;
					if (!IsPredefinedType(methodInfo.DeclaringType))
					{
						throw ParseError(pos, "Methods on type '{0}' are not accessible", GetTypeName(methodInfo.DeclaringType));
					}
					if ((object)methodInfo.ReturnType == typeof(void))
					{
						throw ParseError(pos, "Method '{0}' in type '{1}' does not return a value", identifier, GetTypeName(methodInfo.DeclaringType));
					}
					return Expression.Call(instance, methodInfo, array);
				}
				default:
					throw ParseError(pos, "Ambiguous invocation of method '{0}' in type '{1}'", identifier, GetTypeName(type));
				}
			}
			MemberInfo memberInfo = FindPropertyOrField(type, identifier, instance == null);
			if ((object)memberInfo == null)
			{
				throw ParseError(pos, "No property or field '{0}' exists in type '{1}'", identifier, GetTypeName(type));
			}
			return (memberInfo is PropertyInfo) ? Expression.Property(instance, (PropertyInfo)memberInfo) : Expression.Field(instance, (FieldInfo)memberInfo);
		}

		private static Type FindGenericType(Type generic, Type type)
		{
			while ((object)type != null && (object)type != typeof(object))
			{
				if (type.IsGenericType && (object)type.GetGenericTypeDefinition() == generic)
				{
					return type;
				}
				if (generic.IsInterface)
				{
					Type[] interfaces = type.GetInterfaces();
					foreach (Type type2 in interfaces)
					{
						Type type3 = FindGenericType(generic, type2);
						if ((object)type3 != null)
						{
							return type3;
						}
					}
				}
				type = type.BaseType;
			}
			return null;
		}

		private Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
		{
			ParameterExpression parameterExpression = it;
			ParameterExpression parameterExpression2 = (it = Expression.Parameter(elementType, ""));
			Expression[] array = ParseArgumentList();
			it = parameterExpression;
			if (FindMethod(typeof(IEnumerableSignatures), methodName, staticAccess: false, array, out var method) != 1)
			{
				throw ParseError(errorPos, "No applicable aggregate method '{0}' exists", methodName);
			}
			return Expression.Call(typeArguments: (!(method.Name == "Min") && !(method.Name == "Max")) ? new Type[1] { elementType } : new Type[2]
			{
				elementType,
				array[0].Type
			}, arguments: (array.Length != 0) ? new Expression[2]
			{
				instance,
				Expression.Lambda(array[0], parameterExpression2)
			} : new Expression[1] { instance }, type: typeof(Enumerable), methodName: method.Name);
		}

		private Expression[] ParseArgumentList()
		{
			ValidateToken(TokenId.OpenParen, "'(' expected");
			NextToken();
			Expression[] result = ((token.id != TokenId.CloseParen) ? ParseArguments() : new Expression[0]);
			ValidateToken(TokenId.CloseParen, "')' or ',' expected");
			NextToken();
			return result;
		}

		private Expression[] ParseArguments()
		{
			List<Expression> list = new List<Expression>();
			while (true)
			{
				list.Add(ParseExpression());
				if (token.id != TokenId.Comma)
				{
					break;
				}
				NextToken();
			}
			return list.ToArray();
		}

		private Expression ParseElementAccess(Expression expr)
		{
			int pos = token.pos;
			ValidateToken(TokenId.OpenBracket, "'(' expected");
			NextToken();
			Expression[] array = ParseArguments();
			ValidateToken(TokenId.CloseBracket, "']' or ',' expected");
			NextToken();
			if (expr.Type.IsArray)
			{
				if (expr.Type.GetArrayRank() != 1 || array.Length != 1)
				{
					throw ParseError(pos, "Indexing of multi-dimensional arrays is not supported");
				}
				Expression expression = PromoteExpression(array[0], typeof(int), exact: true);
				if (expression == null)
				{
					throw ParseError(pos, "Array index must be an integer expression");
				}
				return Expression.ArrayIndex(expr, expression);
			}
			MethodBase method;
			return FindIndexer(expr.Type, array, out method) switch
			{
				0 => throw ParseError(pos, "No applicable indexer exists in type '{0}'", GetTypeName(expr.Type)), 
				1 => Expression.Call(expr, (MethodInfo)method, array), 
				_ => throw ParseError(pos, "Ambiguous invocation of indexer in type '{0}'", GetTypeName(expr.Type)), 
			};
		}

		private static bool IsPredefinedType(Type type)
		{
			Type[] array = predefinedTypes;
			foreach (Type type2 in array)
			{
				if ((object)type2 == type)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsNullableType(Type type)
		{
			return type.IsGenericType && (object)type.GetGenericTypeDefinition() == typeof(Nullable<>);
		}

		private static Type GetNonNullableType(Type type)
		{
			return IsNullableType(type) ? type.GetGenericArguments()[0] : type;
		}

		private static string GetTypeName(Type type)
		{
			Type nonNullableType = GetNonNullableType(type);
			string text = nonNullableType.Name;
			if ((object)type != nonNullableType)
			{
				text += "?";
			}
			return text;
		}

		private static bool IsNumericType(Type type)
		{
			return GetNumericTypeKind(type) != 0;
		}

		private static bool IsSignedIntegralType(Type type)
		{
			return GetNumericTypeKind(type) == 2;
		}

		private static bool IsUnsignedIntegralType(Type type)
		{
			return GetNumericTypeKind(type) == 3;
		}

		private static int GetNumericTypeKind(Type type)
		{
			type = GetNonNullableType(type);
			if (type.IsEnum)
			{
				return 0;
			}
			switch (Type.GetTypeCode(type))
			{
			case TypeCode.Char:
			case TypeCode.Single:
			case TypeCode.Double:
			case TypeCode.Decimal:
				return 1;
			case TypeCode.SByte:
			case TypeCode.Int16:
			case TypeCode.Int32:
			case TypeCode.Int64:
				return 2;
			case TypeCode.Byte:
			case TypeCode.UInt16:
			case TypeCode.UInt32:
			case TypeCode.UInt64:
				return 3;
			default:
				return 0;
			}
		}

		private static bool IsEnumType(Type type)
		{
			return GetNonNullableType(type).IsEnum;
		}

		private void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos)
		{
			Expression[] array = new Expression[1] { expr };
			if (FindMethod(signatures, "F", staticAccess: false, array, out var _) != 1)
			{
				throw ParseError(errorPos, "Operator '{0}' incompatible with operand type '{1}'", opName, GetTypeName(array[0].Type));
			}
			expr = array[0];
		}

		private void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos)
		{
			Expression[] array = new Expression[2] { left, right };
			if (FindMethod(signatures, "F", staticAccess: false, array, out var _) != 1)
			{
				throw IncompatibleOperandsError(opName, left, right, errorPos);
			}
			left = array[0];
			right = array[1];
		}

		private Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos)
		{
			return ParseError(pos, "Operator '{0}' incompatible with operand types '{1}' and '{2}'", opName, GetTypeName(left.Type), GetTypeName(right.Type));
		}

		private MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)
		{
			BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | (staticAccess ? BindingFlags.Static : BindingFlags.Instance);
			foreach (Type item in SelfAndBaseTypes(type))
			{
				MemberInfo[] array = item.FindMembers(MemberTypes.Field | MemberTypes.Property, bindingAttr, Type.FilterNameIgnoreCase, memberName);
				if (array.Length != 0)
				{
					return array[0];
				}
			}
			return null;
		}

		private int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method)
		{
			BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | (staticAccess ? BindingFlags.Static : BindingFlags.Instance);
			foreach (Type item in SelfAndBaseTypes(type))
			{
				MemberInfo[] source = item.FindMembers(MemberTypes.Method, bindingAttr, Type.FilterNameIgnoreCase, methodName);
				int num = FindBestMethod(source.Cast<MethodBase>(), args, out method);
				if (num != 0)
				{
					return num;
				}
			}
			method = null;
			return 0;
		}

		private int FindIndexer(Type type, Expression[] args, out MethodBase method)
		{
			foreach (Type item in SelfAndBaseTypes(type))
			{
				MemberInfo[] defaultMembers = item.GetDefaultMembers();
				if (defaultMembers.Length != 0)
				{
					IEnumerable<MethodBase> methods = from m in defaultMembers.OfType<PropertyInfo>().Select((Func<PropertyInfo, MethodBase>)((PropertyInfo p) => p.GetGetMethod()))
						where (object)m != null
						select m;
					int num = FindBestMethod(methods, args, out method);
					if (num != 0)
					{
						return num;
					}
				}
			}
			method = null;
			return 0;
		}

		private static IEnumerable<Type> SelfAndBaseTypes(Type type)
		{
			if (type.IsInterface)
			{
				List<Type> list = new List<Type>();
				AddInterface(list, type);
				return list;
			}
			return SelfAndBaseClasses(type);
		}

		private static IEnumerable<Type> SelfAndBaseClasses(Type type)
		{
			while ((object)type != null)
			{
				yield return type;
				type = type.BaseType;
			}
		}

		private static void AddInterface(List<Type> types, Type type)
		{
			if (!types.Contains(type))
			{
				types.Add(type);
				Type[] interfaces = type.GetInterfaces();
				foreach (Type type2 in interfaces)
				{
					AddInterface(types, type2);
				}
			}
		}

		private int FindBestMethod(IEnumerable<MethodBase> methods, Expression[] args, out MethodBase method)
		{
			MethodData[] applicable = (from m in methods
				select new MethodData
				{
					MethodBase = m,
					Parameters = m.GetParameters()
				} into m
				where IsApplicable(m, args)
				select m).ToArray();
			if (applicable.Length > 1)
			{
				applicable = applicable.Where((MethodData m) => applicable.All((MethodData n) => m == n || IsBetterThan(args, m, n))).ToArray();
			}
			if (applicable.Length == 1)
			{
				MethodData methodData = applicable[0];
				for (int i = 0; i < args.Length; i++)
				{
					args[i] = methodData.Args[i];
				}
				method = methodData.MethodBase;
			}
			else
			{
				method = null;
			}
			return applicable.Length;
		}

		private bool IsApplicable(MethodData method, Expression[] args)
		{
			if (method.Parameters.Length != args.Length)
			{
				return false;
			}
			Expression[] array = new Expression[args.Length];
			for (int i = 0; i < args.Length; i++)
			{
				ParameterInfo parameterInfo = method.Parameters[i];
				if (parameterInfo.IsOut)
				{
					return false;
				}
				Expression expression = PromoteExpression(args[i], parameterInfo.ParameterType, exact: false);
				if (expression == null)
				{
					return false;
				}
				array[i] = expression;
			}
			method.Args = array;
			return true;
		}

		private Expression PromoteExpression(Expression expr, Type type, bool exact)
		{
			if ((object)expr.Type == type)
			{
				return expr;
			}
			if (expr is ConstantExpression)
			{
				ConstantExpression constantExpression = (ConstantExpression)expr;
				string value;
				if (constantExpression == nullLiteral)
				{
					if (!type.IsValueType || IsNullableType(type))
					{
						return Expression.Constant(null, type);
					}
				}
				else if (literals.TryGetValue(constantExpression, out value))
				{
					Type nonNullableType = GetNonNullableType(type);
					object obj = null;
					switch (Type.GetTypeCode(constantExpression.Type))
					{
					case TypeCode.Int32:
					case TypeCode.UInt32:
					case TypeCode.Int64:
					case TypeCode.UInt64:
						obj = ParseNumber(value, nonNullableType);
						break;
					case TypeCode.Double:
						if ((object)nonNullableType == typeof(decimal))
						{
							obj = ParseNumber(value, nonNullableType);
						}
						break;
					case TypeCode.String:
						obj = ParseEnum(value, nonNullableType);
						break;
					}
					if (obj != null)
					{
						return Expression.Constant(obj, type);
					}
				}
			}
			if (IsCompatibleWith(expr.Type, type))
			{
				if (type.IsValueType || exact)
				{
					return Expression.Convert(expr, type);
				}
				return expr;
			}
			return null;
		}

		private static object ParseNumber(string text, Type type)
		{
			switch (Type.GetTypeCode(GetNonNullableType(type)))
			{
			case TypeCode.SByte:
			{
				if (sbyte.TryParse(text, out var result6))
				{
					return result6;
				}
				break;
			}
			case TypeCode.Byte:
			{
				if (byte.TryParse(text, out var result10))
				{
					return result10;
				}
				break;
			}
			case TypeCode.Int16:
			{
				if (short.TryParse(text, out var result2))
				{
					return result2;
				}
				break;
			}
			case TypeCode.UInt16:
			{
				if (ushort.TryParse(text, out var result8))
				{
					return result8;
				}
				break;
			}
			case TypeCode.Int32:
			{
				if (int.TryParse(text, out var result4))
				{
					return result4;
				}
				break;
			}
			case TypeCode.UInt32:
			{
				if (uint.TryParse(text, out var result11))
				{
					return result11;
				}
				break;
			}
			case TypeCode.Int64:
			{
				if (long.TryParse(text, out var result9))
				{
					return result9;
				}
				break;
			}
			case TypeCode.UInt64:
			{
				if (ulong.TryParse(text, out var result7))
				{
					return result7;
				}
				break;
			}
			case TypeCode.Single:
			{
				if (float.TryParse(text, out var result5))
				{
					return result5;
				}
				break;
			}
			case TypeCode.Double:
			{
				if (double.TryParse(text, out var result3))
				{
					return result3;
				}
				break;
			}
			case TypeCode.Decimal:
			{
				if (decimal.TryParse(text, out var result))
				{
					return result;
				}
				break;
			}
			}
			return null;
		}

		private static object ParseEnum(string name, Type type)
		{
			if (type.IsEnum)
			{
				MemberInfo[] array = type.FindMembers(MemberTypes.Field, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public, Type.FilterNameIgnoreCase, name);
				if (array.Length != 0)
				{
					return ((FieldInfo)array[0]).GetValue(null);
				}
			}
			return null;
		}

		private static bool IsCompatibleWith(Type source, Type target)
		{
			if ((object)source == target)
			{
				return true;
			}
			if (!target.IsValueType)
			{
				return target.IsAssignableFrom(source);
			}
			Type nonNullableType = GetNonNullableType(source);
			Type nonNullableType2 = GetNonNullableType(target);
			if ((object)nonNullableType != source && (object)nonNullableType2 == target)
			{
				return false;
			}
			TypeCode typeCode = (nonNullableType.IsEnum ? TypeCode.Object : Type.GetTypeCode(nonNullableType));
			TypeCode typeCode2 = (nonNullableType2.IsEnum ? TypeCode.Object : Type.GetTypeCode(nonNullableType2));
			switch (typeCode)
			{
			case TypeCode.SByte:
				switch (typeCode2)
				{
				case TypeCode.SByte:
				case TypeCode.Int16:
				case TypeCode.Int32:
				case TypeCode.Int64:
				case TypeCode.Single:
				case TypeCode.Double:
				case TypeCode.Decimal:
					return true;
				}
				break;
			case TypeCode.Byte:
			{
				TypeCode typeCode3 = typeCode2;
				TypeCode typeCode4 = typeCode3;
				if ((uint)(typeCode4 - 6) > 9u)
				{
					break;
				}
				return true;
			}
			case TypeCode.Int16:
				switch (typeCode2)
				{
				case TypeCode.Int16:
				case TypeCode.Int32:
				case TypeCode.Int64:
				case TypeCode.Single:
				case TypeCode.Double:
				case TypeCode.Decimal:
					return true;
				}
				break;
			case TypeCode.UInt16:
			{
				TypeCode typeCode9 = typeCode2;
				TypeCode typeCode10 = typeCode9;
				if ((uint)(typeCode10 - 8) > 7u)
				{
					break;
				}
				return true;
			}
			case TypeCode.Int32:
				switch (typeCode2)
				{
				case TypeCode.Int32:
				case TypeCode.Int64:
				case TypeCode.Single:
				case TypeCode.Double:
				case TypeCode.Decimal:
					return true;
				}
				break;
			case TypeCode.UInt32:
			{
				TypeCode typeCode13 = typeCode2;
				TypeCode typeCode14 = typeCode13;
				if ((uint)(typeCode14 - 10) > 5u)
				{
					break;
				}
				return true;
			}
			case TypeCode.Int64:
			{
				TypeCode typeCode11 = typeCode2;
				TypeCode typeCode12 = typeCode11;
				if (typeCode12 != TypeCode.Int64 && (uint)(typeCode12 - 13) > 2u)
				{
					break;
				}
				return true;
			}
			case TypeCode.UInt64:
			{
				TypeCode typeCode7 = typeCode2;
				TypeCode typeCode8 = typeCode7;
				if ((uint)(typeCode8 - 12) > 3u)
				{
					break;
				}
				return true;
			}
			case TypeCode.Single:
			{
				TypeCode typeCode5 = typeCode2;
				TypeCode typeCode6 = typeCode5;
				if ((uint)(typeCode6 - 13) > 1u)
				{
					break;
				}
				return true;
			}
			default:
				if ((object)nonNullableType == nonNullableType2)
				{
					return true;
				}
				break;
			}
			return false;
		}

		private static bool IsBetterThan(Expression[] args, MethodData m1, MethodData m2)
		{
			bool result = false;
			for (int i = 0; i < args.Length; i++)
			{
				int num = CompareConversions(args[i].Type, m1.Parameters[i].ParameterType, m2.Parameters[i].ParameterType);
				if (num < 0)
				{
					return false;
				}
				if (num > 0)
				{
					result = true;
				}
			}
			return result;
		}

		private static int CompareConversions(Type s, Type t1, Type t2)
		{
			if ((object)t1 == t2)
			{
				return 0;
			}
			if ((object)s == t1)
			{
				return 1;
			}
			if ((object)s == t2)
			{
				return -1;
			}
			bool flag = IsCompatibleWith(t1, t2);
			bool flag2 = IsCompatibleWith(t2, t1);
			if (flag && !flag2)
			{
				return 1;
			}
			if (flag2 && !flag)
			{
				return -1;
			}
			if (IsSignedIntegralType(t1) && IsUnsignedIntegralType(t2))
			{
				return 1;
			}
			if (IsSignedIntegralType(t2) && IsUnsignedIntegralType(t1))
			{
				return -1;
			}
			return 0;
		}

		private Expression GenerateEqual(Expression left, Expression right)
		{
			return Expression.Equal(left, right);
		}

		private Expression GenerateNotEqual(Expression left, Expression right)
		{
			return Expression.NotEqual(left, right);
		}

		private Expression GenerateGreaterThan(Expression left, Expression right)
		{
			if ((object)left.Type == typeof(string))
			{
				return Expression.GreaterThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
			}
			return Expression.GreaterThan(left, right);
		}

		private Expression GenerateGreaterThanEqual(Expression left, Expression right)
		{
			if ((object)left.Type == typeof(string))
			{
				return Expression.GreaterThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
			}
			return Expression.GreaterThanOrEqual(left, right);
		}

		private Expression GenerateLessThan(Expression left, Expression right)
		{
			if ((object)left.Type == typeof(string))
			{
				return Expression.LessThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
			}
			return Expression.LessThan(left, right);
		}

		private Expression GenerateLessThanEqual(Expression left, Expression right)
		{
			if ((object)left.Type == typeof(string))
			{
				return Expression.LessThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0));
			}
			return Expression.LessThanOrEqual(left, right);
		}

		private Expression GenerateAdd(Expression left, Expression right)
		{
			if ((object)left.Type == typeof(string) && (object)right.Type == typeof(string))
			{
				return GenerateStaticMethodCall("Concat", left, right);
			}
			return Expression.Add(left, right);
		}

		private Expression GenerateSubtract(Expression left, Expression right)
		{
			return Expression.Subtract(left, right);
		}

		private Expression GenerateStringConcat(Expression left, Expression right)
		{
			return Expression.Call(null, typeof(string).GetMethod("Concat", new Type[2]
			{
				typeof(object),
				typeof(object)
			}), new Expression[2] { left, right });
		}

		private MethodInfo GetStaticMethod(string methodName, Expression left, Expression right)
		{
			return left.Type.GetMethod(methodName, new Type[2] { left.Type, right.Type });
		}

		private Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right)
		{
			return Expression.Call(null, GetStaticMethod(methodName, left, right), new Expression[2] { left, right });
		}

		private void SetTextPos(int pos)
		{
			textPos = pos;
			ch = ((textPos < textLen) ? text[textPos] : '\0');
		}

		private void NextChar()
		{
			if (textPos < textLen)
			{
				textPos++;
			}
			ch = ((textPos < textLen) ? text[textPos] : '\0');
		}

		private void NextToken()
		{
			while (char.IsWhiteSpace(ch))
			{
				NextChar();
			}
			int num = textPos;
			TokenId id;
			switch (ch)
			{
			case '!':
				NextChar();
				if (ch == '=')
				{
					NextChar();
					id = TokenId.ExclamationEqual;
				}
				else
				{
					id = TokenId.Exclamation;
				}
				break;
			case '%':
				NextChar();
				id = TokenId.Percent;
				break;
			case '&':
				NextChar();
				if (ch == '&')
				{
					NextChar();
					id = TokenId.DoubleAmphersand;
				}
				else
				{
					id = TokenId.Amphersand;
				}
				break;
			case '(':
				NextChar();
				id = TokenId.OpenParen;
				break;
			case ')':
				NextChar();
				id = TokenId.CloseParen;
				break;
			case '*':
				NextChar();
				id = TokenId.Asterisk;
				break;
			case '+':
				NextChar();
				id = TokenId.Plus;
				break;
			case ',':
				NextChar();
				id = TokenId.Comma;
				break;
			case '-':
				NextChar();
				id = TokenId.Minus;
				break;
			case '.':
				NextChar();
				id = TokenId.Dot;
				break;
			case '/':
				NextChar();
				id = TokenId.Slash;
				break;
			case ':':
				NextChar();
				id = TokenId.Colon;
				break;
			case '<':
				NextChar();
				if (ch == '=')
				{
					NextChar();
					id = TokenId.LessThanEqual;
				}
				else if (ch == '>')
				{
					NextChar();
					id = TokenId.LessGreater;
				}
				else
				{
					id = TokenId.LessThan;
				}
				break;
			case '=':
				NextChar();
				if (ch == '=')
				{
					NextChar();
					id = TokenId.DoubleEqual;
				}
				else
				{
					id = TokenId.Equal;
				}
				break;
			case '>':
				NextChar();
				if (ch == '=')
				{
					NextChar();
					id = TokenId.GreaterThanEqual;
				}
				else
				{
					id = TokenId.GreaterThan;
				}
				break;
			case '?':
				NextChar();
				id = TokenId.Question;
				break;
			case '[':
				NextChar();
				id = TokenId.OpenBracket;
				break;
			case ']':
				NextChar();
				id = TokenId.CloseBracket;
				break;
			case '|':
				NextChar();
				if (ch == '|')
				{
					NextChar();
					id = TokenId.DoubleBar;
				}
				else
				{
					id = TokenId.Bar;
				}
				break;
			case '"':
			case '\'':
			{
				char c = ch;
				do
				{
					NextChar();
					while (textPos < textLen && ch != c)
					{
						NextChar();
					}
					if (textPos == textLen)
					{
						throw ParseError(textPos, "Unterminated string literal");
					}
					NextChar();
				}
				while (ch == c);
				id = TokenId.StringLiteral;
				break;
			}
			default:
				if (char.IsLetter(ch) || ch == '@' || ch == '_')
				{
					do
					{
						NextChar();
					}
					while (char.IsLetterOrDigit(ch) || ch == '_');
					id = TokenId.Identifier;
				}
				else if (char.IsDigit(ch))
				{
					id = TokenId.IntegerLiteral;
					do
					{
						NextChar();
					}
					while (char.IsDigit(ch));
					if (ch == '.')
					{
						id = TokenId.RealLiteral;
						NextChar();
						ValidateDigit();
						do
						{
							NextChar();
						}
						while (char.IsDigit(ch));
					}
					if (ch == 'E' || ch == 'e')
					{
						id = TokenId.RealLiteral;
						NextChar();
						if (ch == '+' || ch == '-')
						{
							NextChar();
						}
						ValidateDigit();
						do
						{
							NextChar();
						}
						while (char.IsDigit(ch));
					}
					if (ch == 'F' || ch == 'f')
					{
						NextChar();
					}
				}
				else
				{
					if (textPos != textLen)
					{
						throw ParseError(textPos, "Syntax error '{0}'", ch);
					}
					id = TokenId.End;
				}
				break;
			}
			token.id = id;
			token.text = text.Substring(num, textPos - num);
			token.pos = num;
		}

		private bool TokenIdentifierIs(string id)
		{
			return token.id == TokenId.Identifier && string.Equals(id, token.text, StringComparison.OrdinalIgnoreCase);
		}

		private string GetIdentifier()
		{
			ValidateToken(TokenId.Identifier, "Identifier expected");
			string text = token.text;
			if (text.Length > 1 && text[0] == '@')
			{
				text = text.Substring(1);
			}
			return text;
		}

		private void ValidateDigit()
		{
			if (!char.IsDigit(ch))
			{
				throw ParseError(textPos, "Digit expected");
			}
		}

		private void ValidateToken(TokenId t, string errorMessage)
		{
			if (token.id != t)
			{
				throw ParseError(errorMessage);
			}
		}

		private void ValidateToken(TokenId t)
		{
			if (token.id != t)
			{
				throw ParseError("Syntax error");
			}
		}

		private Exception ParseError(string format, params object[] args)
		{
			return ParseError(token.pos, format, args);
		}

		private Exception ParseError(int pos, string format, params object[] args)
		{
			return new ParseException(string.Format(CultureInfo.CurrentCulture, format, args), pos);
		}

		private static Dictionary<string, object> CreateKeywords()
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
			dictionary.Add("true", trueLiteral);
			dictionary.Add("false", falseLiteral);
			dictionary.Add("null", nullLiteral);
			dictionary.Add(keywordIt, keywordIt);
			dictionary.Add(keywordIif, keywordIif);
			dictionary.Add(keywordNew, keywordNew);
			Type[] array = predefinedTypes;
			foreach (Type type in array)
			{
				dictionary.Add(type.Name, type);
			}
			return dictionary;
		}
	}
	internal static class Res
	{
		public const string DuplicateIdentifier = "The identifier '{0}' was defined more than once";

		public const string ExpressionTypeMismatch = "Expression of type '{0}' expected";

		public const string ExpressionExpected = "Expression expected";

		public const string InvalidCharacterLiteral = "Character literal must contain exactly one character";

		public const string InvalidIntegerLiteral = "Invalid integer literal '{0}'";

		public const string InvalidRealLiteral = "Invalid real literal '{0}'";

		public const string UnknownIdentifier = "Unknown identifier '{0}'";

		public const string NoItInScope = "No 'it' is in scope";

		public const string IifRequiresThreeArgs = "The 'iif' function requires three arguments";

		public const string FirstExprMustBeBool = "The first expression must be of type 'Boolean'";

		public const string BothTypesConvertToOther = "Both of the types '{0}' and '{1}' convert to the other";

		public const string NeitherTypeConvertsToOther = "Neither of the types '{0}' and '{1}' converts to the other";

		public const string MissingAsClause = "Expression is missing an 'as' clause";

		public const string ArgsIncompatibleWithLambda = "Argument list incompatible with lambda expression";

		public const string TypeHasNoNullableForm = "Type '{0}' has no nullable form";

		public const string NoMatchingConstructor = "No matching constructor in type '{0}'";

		public const string AmbiguousConstructorInvocation = "Ambiguous invocation of '{0}' constructor";

		public const string CannotConvertValue = "A value of type '{0}' cannot be converted to type '{1}'";

		public const string NoApplicableMethod = "No applicable method '{0}' exists in type '{1}'";

		public const string MethodsAreInaccessible = "Methods on type '{0}' are not accessible";

		public const string MethodIsVoid = "Method '{0}' in type '{1}' does not return a value";

		public const string AmbiguousMethodInvocation = "Ambiguous invocation of method '{0}' in type '{1}'";

		public const string UnknownPropertyOrField = "No property or field '{0}' exists in type '{1}'";

		public const string NoApplicableAggregate = "No applicable aggregate method '{0}' exists";

		public const string CannotIndexMultiDimArray = "Indexing of multi-dimensional arrays is not supported";

		public const string InvalidIndex = "Array index must be an integer expression";

		public const string NoApplicableIndexer = "No applicable indexer exists in type '{0}'";

		public const string AmbiguousIndexerInvocation = "Ambiguous invocation of indexer in type '{0}'";

		public const string IncompatibleOperand = "Operator '{0}' incompatible with operand type '{1}'";

		public const string IncompatibleOperands = "Operator '{0}' incompatible with operand types '{1}' and '{2}'";

		public const string UnterminatedStringLiteral = "Unterminated string literal";

		public const string InvalidCharacter = "Syntax error '{0}'";

		public const string DigitExpected = "Digit expected";

		public const string SyntaxError = "Syntax error";

		public const string TokenExpected = "{0} expected";

		public const string ParseExceptionFormat = "{0} (at index {1})";

		public const string ColonExpected = "':' expected";

		public const string OpenParenExpected = "'(' expected";

		public const string CloseParenOrOperatorExpected = "')' or operator expected";

		public const string CloseParenOrCommaExpected = "')' or ',' expected";

		public const string DotOrOpenParenExpected = "'.' or '(' expected";

		public const string OpenBracketExpected = "'[' expected";

		public const string CloseBracketOrCommaExpected = "']' or ',' expected";

		public const string IdentifierExpected = "Identifier expected";
	}
}
namespace SimpleJSON
{
	public enum JSONNodeType
	{
		Array = 1,
		Object = 2,
		String = 3,
		Number = 4,
		NullValue = 5,
		Boolean = 6,
		None = 7,
		Custom = 255
	}
	public enum JSONTextMode
	{
		Compact,
		Indent
	}
	public abstract class JSONNode
	{
		public struct Enumerator
		{
			private enum Type
			{
				None,
				Array,
				Object
			}

			private Type type;

			private Dictionary<string, JSONNode>.Enumerator m_Object;

			private List<JSONNode>.Enumerator m_Array;

			public bool IsValid => type != Type.None;

			public KeyValuePair<string, JSONNode> Current
			{
				get
				{
					if (type == Type.Array)
					{
						return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
					}
					if (type == Type.Object)
					{
						return m_Object.Current;
					}
					return new KeyValuePair<string, JSONNode>(string.Empty, null);
				}
			}

			public Enumerator(List<JSONNode>.Enumerator aArrayEnum)
			{
				type = Type.Array;
				m_Object = default(Dictionary<string, JSONNode>.Enumerator);
				m_Array = aArrayEnum;
			}

			public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
			{
				type = Type.Object;
				m_Object = aDictEnum;
				m_Array = default(List<JSONNode>.Enumerator);
			}

			public bool MoveNext()
			{
				if (type == Type.Array)
				{
					return m_Array.MoveNext();
				}
				if (type == Type.Object)
				{
					return m_Object.MoveNext();
				}
				return false;
			}
		}

		public struct ValueEnumerator
		{
			private Enumerator m_Enumerator;

			public JSONNode Current => m_Enumerator.Current.Value;

			public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum)
				: this(new Enumerator(aArrayEnum))
			{
			}

			public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
				: this(new Enumerator(aDictEnum))
			{
			}

			public ValueEnumerator(Enumerator aEnumerator)
			{
				m_Enumerator = aEnumerator;
			}

			public bool MoveNext()
			{
				return m_Enumerator.MoveNext();
			}

			public ValueEnumerator GetEnumerator()
			{
				return this;
			}
		}

		public struct KeyEnumerator
		{
			private Enumerator m_Enumerator;

			public JSONNode Current => m_Enumerator.Current.Key;

			public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum)
				: this(new Enumerator(aArrayEnum))
			{
			}

			public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
				: this(new Enumerator(aDictEnum))
			{
			}

			public KeyEnumerator(Enumerator aEnumerator)
			{
				m_Enumerator = aEnumerator;
			}

			public bool MoveNext()
			{
				return m_Enumerator.MoveNext();
			}

			public KeyEnumerator GetEnumerator()
			{
				return this;
			}
		}

		public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable
		{
			private JSONNode m_Node;

			private Enumerator m_Enumerator;

			public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current;

			object IEnumerator.Current => m_Enumerator.Current;

			internal LinqEnumerator(JSONNode aNode)
			{
				m_Node = aNode;
				if (m_Node != null)
				{
					m_Enumerator = m_Node.GetEnumerator();
				}
			}

			public bool MoveNext()
			{
				return m_Enumerator.MoveNext();
			}

			public void Dispose()
			{
				m_Node = null;
				m_Enumerator = default(Enumerator);
			}

			public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator()
			{
				return new LinqEnumerator(m_Node);
			}

			public void Reset()
			{
				if (m_Node != null)
				{
					m_Enumerator = m_Node.GetEnumerator();
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return new LinqEnumerator(m_Node);
			}
		}

		public static bool forceASCII;

		[ThreadStatic]
		private static StringBuilder m_EscapeBuilder;

		public abstract JSONNodeType Tag { get; }

		public virtual JSONNode this[int aIndex]
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		public virtual JSONNode this[string aKey]
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		public virtual string Value
		{
			get
			{
				return "";
			}
			set
			{
			}
		}

		public virtual int Count => 0;

		public virtual bool IsNumber => false;

		public virtual bool IsString => false;

		public virtual bool IsBoolean => false;

		public virtual bool IsNull => false;

		public virtual bool IsArray => false;

		public virtual bool IsObject => false;

		public virtual bool Inline
		{
			get
			{
				return false;
			}
			set
			{
			}
		}

		public virtual IEnumerable<JSONNode> Children
		{
			get
			{
				yield break;
			}
		}

		public IEnumerable<JSONNode> DeepChildren
		{
			get
			{
				foreach (JSONNode C in Children)
				{
					foreach (JSONNode deepChild in C.DeepChildren)
					{
						yield return deepChild;
					}
				}
			}
		}

		public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this);

		public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator());

		public ValueEnumerator Values => new ValueEnumerator(GetEnumerator());

		public virtual double AsDouble
		{
			get
			{
				double result = 0.0;
				if (double.TryParse(Value, out result))
				{
					return result;
				}
				return 0.0;
			}
			set
			{
				Value = value.ToString();
			}
		}

		public virtual int AsInt
		{
			get
			{
				return (int)AsDouble;
			}
			set
			{
				AsDouble = value;
			}
		}

		public virtual float AsFloat
		{
			get
			{
				return (float)AsDouble;
			}
			set
			{
				AsDouble = value;
			}
		}

		public virtual bool AsBool
		{
			get
			{
				bool result = false;
				if (bool.TryParse(Value, out result))
				{
					return result;
				}
				return !string.IsNullOrEmpty(Value);
			}
			set
			{
				Value = (value ? "true" : "false");
			}
		}

		public virtual JSONArray AsArray => this as JSONArray;

		public virtual JSONObject AsObject => this as JSONObject;

		internal static StringBuilder EscapeBuilder
		{
			get
			{
				if (m_EscapeBuilder == null)
				{
					m_EscapeBuilder = new StringBuilder();
				}
				return m_EscapeBuilder;
			}
		}

		public virtual void Add(string aKey, JSONNode aItem)
		{
		}

		public virtual void Add(JSONNode aItem)
		{
			Add("", aItem);
		}

		public virtual JSONNode Remove(string aKey)
		{
			return null;
		}

		public virtual JSONNode Remove(int aIndex)
		{
			return null;
		}

		public virtual JSONNode Remove(JSONNode aNode)
		{
			return aNode;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact);
			return stringBuilder.ToString();
		}

		public virtual string ToString(int aIndent)
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent);
			return stringBuilder.ToString();
		}

		internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);

		public abstract Enumerator GetEnumerator();

		public static implicit operator JSONNode(string s)
		{
			return new JSONString(s);
		}

		public static implicit operator string(JSONNode d)
		{
			return (d == null) ? null : d.Value;
		}

		public static implicit operator JSONNode(double n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator double(JSONNode d)
		{
			return (d == null) ? 0.0 : d.AsDouble;
		}

		public static implicit operator JSONNode(float n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator float(JSONNode d)
		{
			return (d == null) ? 0f : d.AsFloat;
		}

		public static implicit operator JSONNode(int n)
		{
			return new JSONNumber(n);
		}

		public static implicit operator int(JSONNode d)
		{
			return (!(d == null)) ? d.AsInt : 0;
		}

		public static implicit operator JSONNode(bool b)
		{
			return new JSONBool(b);
		}

		public static implicit operator bool(JSONNode d)
		{
			return !(d == null) && d.AsBool;
		}

		public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue)
		{
			return aKeyValue.Value;
		}

		public static bool operator ==(JSONNode a, object b)
		{
			if ((object)a == b)
			{
				return true;
			}
			bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator;
			bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator;
			if (flag && flag2)
			{
				return true;
			}
			return !flag && a.Equals(b);
		}

		public static bool operator !=(JSONNode a, object b)
		{
			return !(a == b);
		}

		public override bool Equals(object obj)
		{
			return (object)this == obj;
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		internal static string Escape(string aText)
		{
			StringBuilder escapeBuilder = EscapeBuilder;
			escapeBuilder.Length = 0;
			if (escapeBuilder.Capacity < aText.Length + aText.Length / 10)
			{
				escapeBuilder.Capacity = aText.Length + aText.Length / 10;
			}
			foreach (char c in aText)
			{
				switch (c)
				{
				case '\\':
					escapeBuilder.Append("\\\\");
					continue;
				case '"':
					escapeBuilder.Append("\\\"");
					continue;
				case '\n':
					escapeBuilder.Append("\\n");
					continue;
				case '\r':
					escapeBuilder.Append("\\r");
					continue;
				case '\t':
					escapeBuilder.Append("\\t");
					continue;
				case '\b':
					escapeBuilder.Append("\\b");
					continue;
				case '\f':
					escapeBuilder.Append("\\f");
					continue;
				}
				if (c < ' ' || (forceASCII && c > '\u007f'))
				{
					ushort num = c;
					escapeBuilder.Append("\\u").Append(num.ToString("X4"));
				}
				else
				{
					escapeBuilder.Append(c);
				}
			}
			string result = escapeBuilder.ToString();
			escapeBuilder.Length = 0;
			return result;
		}

		private static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted)
		{
			if (quoted)
			{
				ctx.Add(tokenName, token);
				return;
			}
			string text = token.ToLower();
			double result;
			if (text == "false" || text == "true")
			{
				ctx.Add(tokenName, text == "true");
			}
			else if (text == "null")
			{
				ctx.Add(tokenName, null);
			}
			else if (double.TryParse(token, out result))
			{
				ctx.Add(tokenName, result);
			}
			else
			{
				ctx.Add(tokenName, token);
			}
		}

		public static JSONNode Parse(string aJSON)
		{
			Stack<JSONNode> stack = new Stack<JSONNode>();
			JSONNode jSONNode = null;
			int i = 0;
			StringBuilder stringBuilder = new StringBuilder();
			string text = "";
			bool flag = false;
			bool flag2 = false;
			for (; i < aJSON.Length; i++)
			{
				switch (aJSON[i])
				{
				case '{':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					stack.Push(new JSONObject());
					if (jSONNode != null)
					{
						jSONNode.Add(text, stack.Peek());
					}
					text = "";
					stringBuilder.Length = 0;
					jSONNode = stack.Peek();
					break;
				case '[':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					stack.Push(new JSONArray());
					if (jSONNode != null)
					{
						jSONNode.Add(text, stack.Peek());
					}
					text = "";
					stringBuilder.Length = 0;
					jSONNode = stack.Peek();
					break;
				case ']':
				case '}':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					if (stack.Count == 0)
					{
						throw new Exception("JSON Parse: Too many closing brackets");
					}
					stack.Pop();
					if (stringBuilder.Length > 0 || flag2)
					{
						ParseElement(jSONNode, stringBuilder.ToString(), text, flag2);
						flag2 = false;
					}
					text = "";
					stringBuilder.Length = 0;
					if (stack.Count > 0)
					{
						jSONNode = stack.Peek();
					}
					break;
				case ':':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					text = stringBuilder.ToString();
					stringBuilder.Length = 0;
					flag2 = false;
					break;
				case '"':
					flag = !flag;
					flag2 = flag2 || flag;
					break;
				case ',':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
						break;
					}
					if (stringBuilder.Length > 0 || flag2)
					{
						ParseElement(jSONNode, stringBuilder.ToString(), text, flag2);
						flag2 = false;
					}
					text = "";
					stringBuilder.Length = 0;
					flag2 = false;
					break;
				case '\t':
				case ' ':
					if (flag)
					{
						stringBuilder.Append(aJSON[i]);
					}
					break;
				case '\\':
					i++;
					if (flag)
					{
						char c = aJSON[i];
						switch (c)
						{
						case 't':
							stringBuilder.Append('\t');
							break;
						case 'r':
							stringBuilder.Append('\r');
							break;
						case 'n':
							stringBuilder.Append('\n');
							break;
						case 'b':
							stringBuilder.Append('\b');
							break;
						case 'f':
							stringBuilder.Append('\f');
							break;
						case 'u':
						{
							string s = aJSON.Substring(i + 1, 4);
							stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier));
							i += 4;
							break;
						}
						default:
							stringBuilder.Append(c);
							break;
						}
					}
					break;
				default:
					stringBuilder.Append(aJSON[i]);
					break;
				case '\n':
				case '\r':
					break;
				}
			}
			if (flag)
			{
				throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
			}
			return jSONNode;
		}
	}
	public class JSONArray : JSONNode
	{
		private List<JSONNode> m_List = new List<JSONNode>();

		private bool inline = false;

		public override bool Inline
		{
			get
			{
				return inline;
			}
			set
			{
				inline = value;
			}
		}

		public override JSONNodeType Tag => JSONNodeType.Array;

		public override bool IsArray => true;

		public override JSONNode this[int aIndex]
		{
			get
			{
				if (aIndex < 0 || aIndex >= m_List.Count)
				{
					return new JSONLazyCreator(this);
				}
				return m_List[aIndex];
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (aIndex < 0 || aIndex >= m_List.Count)
				{
					m_List.Add(value);
				}
				else
				{
					m_List[aIndex] = value;
				}
			}
		}

		public override JSONNode this[string aKey]
		{
			get
			{
				return new JSONLazyCreator(this);
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				m_List.Add(value);
			}
		}

		public override int Count => m_List.Count;

		public override IEnumerable<JSONNode> Children
		{
			get
			{
				foreach (JSONNode item in m_List)
				{
					yield return item;
				}
			}
		}

		public override Enumerator GetEnumerator()
		{
			return new Enumerator(m_List.GetEnumerator());
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			if (aItem == null)
			{
				aItem = JSONNull.CreateOrGet();
			}
			m_List.Add(aItem);
		}

		public override JSONNode Remove(int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_List.Count)
			{
				return null;
			}
			JSONNode result = m_List[aIndex];
			m_List.RemoveAt(aIndex);
			return result;
		}

		public override JSONNode Remove(JSONNode aNode)
		{
			m_List.Remove(aNode);
			return aNode;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('[');
			int count = m_List.Count;
			if (inline)
			{
				aMode = JSONTextMode.Compact;
			}
			for (int i = 0; i < count; i++)
			{
				if (i > 0)
				{
					aSB.Append(',');
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.AppendLine();
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.Append(' ', aIndent + aIndentInc);
				}
				m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
			}
			if (aMode == JSONTextMode.Indent)
			{
				aSB.AppendLine().Append(' ', aIndent);
			}
			aSB.Append(']');
		}
	}
	public class JSONObject : JSONNode
	{
		private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();

		private bool inline = false;

		public override bool Inline
		{
			get
			{
				return inline;
			}
			set
			{
				inline = value;
			}
		}

		public override JSONNodeType Tag => JSONNodeType.Object;

		public override bool IsObject => true;

		public override JSONNode this[string aKey]
		{
			get
			{
				if (m_Dict.ContainsKey(aKey))
				{
					return m_Dict[aKey];
				}
				return new JSONLazyCreator(this, aKey);
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (m_Dict.ContainsKey(aKey))
				{
					m_Dict[aKey] = value;
				}
				else
				{
					m_Dict.Add(aKey, value);
				}
			}
		}

		public override JSONNode this[int aIndex]
		{
			get
			{
				if (aIndex < 0 || aIndex >= m_Dict.Count)
				{
					return null;
				}
				return m_Dict.ElementAt(aIndex).Value;
			}
			set
			{
				if (value == null)
				{
					value = JSONNull.CreateOrGet();
				}
				if (aIndex >= 0 && aIndex < m_Dict.Count)
				{
					string key = m_Dict.ElementAt(aIndex).Key;
					m_Dict[key] = value;
				}
			}
		}

		public override int Count => m_Dict.Count;

		public override IEnumerable<JSONNode> Children
		{
			get
			{
				foreach (KeyValuePair<string, JSONNode> item in m_Dict)
				{
					yield return item.Value;
				}
			}
		}

		public override Enumerator GetEnumerator()
		{
			return new Enumerator(m_Dict.GetEnumerator());
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			if (aItem == null)
			{
				aItem = JSONNull.CreateOrGet();
			}
			if (!string.IsNullOrEmpty(aKey))
			{
				if (m_Dict.ContainsKey(aKey))
				{
					m_Dict[aKey] = aItem;
				}
				else
				{
					m_Dict.Add(aKey, aItem);
				}
			}
			else
			{
				m_Dict.Add(Guid.NewGuid().ToString(), aItem);
			}
		}

		public override JSONNode Remove(string aKey)
		{
			if (!m_Dict.ContainsKey(aKey))
			{
				return null;
			}
			JSONNode result = m_Dict[aKey];
			m_Dict.Remove(aKey);
			return result;
		}

		public override JSONNode Remove(int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_Dict.Count)
			{
				return null;
			}
			KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex);
			m_Dict.Remove(keyValuePair.Key);
			return keyValuePair.Value;
		}

		public override JSONNode Remove(JSONNode aNode)
		{
			try
			{
				KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First();
				m_Dict.Remove(keyValuePair.Key);
				return aNode;
			}
			catch
			{
				return null;
			}
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('{');
			bool flag = true;
			if (inline)
			{
				aMode = JSONTextMode.Compact;
			}
			foreach (KeyValuePair<string, JSONNode> item in m_Dict)
			{
				if (!flag)
				{
					aSB.Append(',');
				}
				flag = false;
				if (aMode == JSONTextMode.Indent)
				{
					aSB.AppendLine();
				}
				if (aMode == JSONTextMode.Indent)
				{
					aSB.Append(' ', aIndent + aIndentInc);
				}
				aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"');
				if (aMode == JSONTextMode.Compact)
				{
					aSB.Append(':');
				}
				else
				{
					aSB.Append(" : ");
				}
				item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
			}
			if (aMode == JSONTextMode.Indent)
			{
				aSB.AppendLine().Append(' ', aIndent);
			}
			aSB.Append('}');
		}
	}
	public class JSONString : JSONNode
	{
		private string m_Data;

		public override JSONNodeType Tag => JSONNodeType.String;

		public override bool IsString => true;

		public override string Value
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONString(string aData)
		{
			m_Data = aData;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"');
		}

		public override bool Equals(object obj)
		{
			if (base.Equals(obj))
			{
				return true;
			}
			if (obj is string text)
			{
				return m_Data == text;
			}
			JSONString jSONString = obj as JSONString;
			if (jSONString != null)
			{
				return m_Data == jSONString.m_Data;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}
	}
	public class JSONNumber : JSONNode
	{
		private double m_Data;

		public override JSONNodeType Tag => JSONNodeType.Number;

		public override bool IsNumber => true;

		public override string Value
		{
			get
			{
				return m_Data.ToString();
			}
			set
			{
				if (double.TryParse(value, out var result))
				{
					m_Data = result;
				}
			}
		}

		public override double AsDouble
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONNumber(double aData)
		{
			m_Data = aData;
		}

		public JSONNumber(string aData)
		{
			Value = aData;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append(m_Data);
		}

		private static bool IsNumeric(object value)
		{
			return value is int || value is uint || value is float || value is double || value is decimal || value is long || value is ulong || value is short || value is ushort || value is sbyte || value is byte;
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (base.Equals(obj))
			{
				return true;
			}
			JSONNumber jSONNumber = obj as JSONNumber;
			if (jSONNumber != null)
			{
				return m_Data == jSONNumber.m_Data;
			}
			if (IsNumeric(obj))
			{
				return Convert.ToDouble(obj) == m_Data;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}
	}
	public class JSONBool : JSONNode
	{
		private bool m_Data;

		public override JSONNodeType Tag => JSONNodeType.Boolean;

		public override bool IsBoolean => true;

		public override string Value
		{
			get
			{
				return m_Data.ToString();
			}
			set
			{
				if (bool.TryParse(value, out var result))
				{
					m_Data = result;
				}
			}
		}

		public override bool AsBool
		{
			get
			{
				return m_Data;
			}
			set
			{
				m_Data = value;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONBool(bool aData)
		{
			m_Data = aData;
		}

		public JSONBool(string aData)
		{
			Value = aData;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append(m_Data ? "true" : "false");
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (obj is bool)
			{
				return m_Data == (bool)obj;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return m_Data.GetHashCode();
		}
	}
	public class JSONNull : JSONNode
	{
		private static JSONNull m_StaticInstance = new JSONNull();

		public static bool reuseSameInstance = true;

		public override JSONNodeType Tag => JSONNodeType.NullValue;

		public override bool IsNull => true;

		public override string Value
		{
			get
			{
				return "null";
			}
			set
			{
			}
		}

		public override bool AsBool
		{
			get
			{
				return false;
			}
			set
			{
			}
		}

		public static JSONNull CreateOrGet()
		{
			if (reuseSameInstance)
			{
				return m_StaticInstance;
			}
			return new JSONNull();
		}

		private JSONNull()
		{
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public override bool Equals(object obj)
		{
			if ((object)this == obj)
			{
				return true;
			}
			return obj is JSONNull;
		}

		public override int GetHashCode()
		{
			return 0;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append("null");
		}
	}
	internal class JSONLazyCreator : JSONNode
	{
		private JSONNode m_Node = null;

		private string m_Key = null;

		public override JSONNodeType Tag => JSONNodeType.None;

		public override JSONNode this[int aIndex]
		{
			get
			{
				return new JSONLazyCreator(this);
			}
			set
			{
				JSONArray jSONArray = new JSONArray();
				jSONArray.Add(value);
				Set(jSONArray);
			}
		}

		public override JSONNode this[string aKey]
		{
			get
			{
				return new JSONLazyCreator(this, aKey);
			}
			set
			{
				JSONObject jSONObject = new JSONObject();
				jSONObject.Add(aKey, value);
				Set(jSONObject);
			}
		}

		public override int AsInt
		{
			get
			{
				JSONNumber aVal = new JSONNumber(0.0);
				Set(aVal);
				return 0;
			}
			set
			{
				JSONNumber aVal = new JSONNumber(value);
				Set(aVal);
			}
		}

		public override float AsFloat
		{
			get
			{
				JSONNumber aVal = new JSONNumber(0.0);
				Set(aVal);
				return 0f;
			}
			set
			{
				JSONNumber aVal = new JSONNumber(value);
				Set(aVal);
			}
		}

		public override double AsDouble
		{
			get
			{
				JSONNumber aVal = new JSONNumber(0.0);
				Set(aVal);
				return 0.0;
			}
			set
			{
				JSONNumber aVal = new JSONNumber(value);
				Set(aVal);
			}
		}

		public override bool AsBool
		{
			get
			{
				JSONBool aVal = new JSONBool(aData: false);
				Set(aVal);
				return false;
			}
			set
			{
				JSONBool aVal = new JSONBool(value);
				Set(aVal);
			}
		}

		public override JSONArray AsArray
		{
			get
			{
				JSONArray jSONArray = new JSONArray();
				Set(jSONArray);
				return jSONArray;
			}
		}

		public override JSONObject AsObject
		{
			get
			{
				JSONObject jSONObject = new JSONObject();
				Set(jSONObject);
				return jSONObject;
			}
		}

		public override Enumerator GetEnumerator()
		{
			return default(Enumerator);
		}

		public JSONLazyCreator(JSONNode aNode)
		{
			m_Node = aNode;
			m_Key = null;
		}

		public JSONLazyCreator(JSONNode aNode, string aKey)
		{
			m_Node = aNode;
			m_Key = aKey;
		}

		private void Set(JSONNode aVal)
		{
			if (m_Key == null)
			{
				m_Node.Add(aVal);
			}
			else
			{
				m_Node.Add(m_Key, aVal);
			}
			m_Node = null;
		}

		public override void Add(JSONNode aItem)
		{
			JSONArray jSONArray = new JSONArray();
			jSONArray.Add(aItem);
			Set(jSONArray);
		}

		public override void Add(string aKey, JSONNode aItem)
		{
			JSONObject jSONObject = new JSONObject();
			jSONObject.Add(aKey, aItem);
			Set(jSONObject);
		}

		public static bool operator ==(JSONLazyCreator a, object b)
		{
			if (b == null)
			{
				return true;
			}
			return (object)a == b;
		}

		public static bool operator !=(JSONLazyCreator a, object b)
		{
			return !(a == b);
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return true;
			}
			return (object)this == obj;
		}

		public override int GetHashCode()
		{
			return 0;
		}

		internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
		{
			aSB.Append("null");
		}
	}
	public static class JSON
	{
		public static JSONNode Parse(string aJSON)
		{
			return JSONNode.Parse(aJSON);
		}
	}
}
namespace XUnity.AutoTranslator.Plugin
{
	internal class SceneLoadInformation
	{
		public SceneInformation ActiveScene { get; set; }

		public List<SceneInformation> LoadedScenes { get; set; }

		public SceneLoadInformation()
		{
			LoadedScenes = new List<SceneInformation>();
			if (UnityFeatures.SupportsSceneManager)
			{
				LoadBySceneManager();
			}
			else
			{
				LoadByApplication();
			}
		}

		public void LoadBySceneManager()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			ActiveScene = new SceneInformation(((Scene)(ref activeScene)).buildIndex, ((Scene)(ref activeScene)).name);
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				LoadedScenes.Add(new SceneInformation(((Scene)(ref sceneAt)).buildIndex, ((Scene)(ref sceneAt)).name));
			}
		}

		public void LoadByApplication()
		{
			ActiveScene = new SceneInformation(Application.loadedLevel, Application.loadedLevelName);
			LoadedScenes.Add(new SceneInformation(Application.loadedLevel, Application.loadedLevelName));
		}
	}
	internal class SceneInformation
	{
		public int Id { get; set; }

		public string Name { get; set; }

		public SceneInformation(int id, string name)
		{
			Id = id;
			Name = name;
		}
	}
}
namespace XUnity.AutoTranslator.Plugin.Utilities
{
	internal static class TranslationScopeHelper
	{
		public static int GetScope(object ui)
		{
			if (Settings.EnableTranslationScoping)
			{
				try
				{
					Component val = (Component)((ui is Component) ? ui : null);
					if (val != null && Object.op_Implicit((Object)(object)val))
					{
						return GetScopeFromComponent(val);
					}
					GUIContent val2 = (GUIContent)((ui is GUIContent) ? ui : null);
					if (val2 != null)
					{
						return -1;
					}
					return GetActiveSceneId();
				}
				catch (MissingMemberException ex)
				{
					XuaLogger.AutoTranslator.Error((Exception)ex, "A 'missing member' error occurred while retriving translation scope. Disabling translation scopes.");
					Settings.EnableTranslationScoping = false;
				}
			}
			return -1;
		}

		private static int GetScopeFromComponent(Component component)
		{
			//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)
			Scene scene = component.gameObject.scene;
			return ((Scene)(ref scene)).buildIndex;
		}

		public static int GetActiveSceneId()
		{
			if (UnityFeatures.SupportsSceneManager)
			{
				return GetActiveSceneIdBySceneManager();
			}
			return GetActiveSceneIdByApplication();
		}

		private static int GetActiveSceneIdBySceneManager()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			return ((Scene)(ref activeScene)).buildIndex;
		}

		public static void RegisterSceneLoadCallback(Action<int> sceneLoaded)
		{
			SceneManagerLoader.EnableSceneLoadScanInternal(sceneLoaded);
		}

		private static int GetActiveSceneIdByApplication()
		{
			return Application.loadedLevel;
		}
	}
	internal static class SceneManagerLoader
	{
		public static void EnableSceneLoadScanInternal(Action<int> sceneLoaded)
		{
			SceneManager.sceneLoaded += delegate(Scene arg1, LoadSceneMode arg2)
			{
				sceneLoaded(((Scene)(ref arg1)).buildIndex);
			};
		}
	}
	internal static class TranslationScopes
	{
		public const int None = -1;
	}
}
namespace XUnity.AutoTranslator.Plugin.Core
{
	public class AutoTranslationPlugin : MonoBehaviour, IMonoBehaviour, IMonoBehaviour_Update, IInternalTranslator, ITranslator, ITranslationRegistry
	{
		internal static AutoTranslationPlugin Current;

		private bool _hasResizedCurrentComponentDuringDiscovery;

		internal XuaWindow MainWindow;

		internal TranslationAggregatorWindow TranslationAggregatorWindow;

		internal TranslationAggregatorOptionsWindow TranslationAggregatorOptionsWindow;

		internal TranslationManager TranslationManager;

		internal TextTranslationCache TextCache;

		internal Dictionary<string, TextTranslationCache> PluginTextCaches = new Dictionary<string, TextTranslationCache>(StringComparer.OrdinalIgnoreCase);

		internal TextureTranslationCache TextureCache;

		internal UIResizeCache ResizeCache;

		internal SpamChecker SpamChecker;

		private Dictionary<string, UntranslatedText> CachedKeys = new Dictionary<string, UntranslatedText>(StringComparer.Ordinal);

		private List<Action<ComponentTranslationContext>> _shouldIgnore = new List<Action<ComponentTranslationContext>>();

		private List<string> _textsToCopyToClipboardOrdered = new List<string>();

		private HashSet<string> _textsToCopyToClipboard = new HashSet<string>();

		private float _clipboardUpdated = 0f;

		private HashSet<string> _immediatelyTranslating = new HashSet<string>();

		private bool _isInTranslatedMode = true;

		private bool _textHooksEnabled = true;

		private float _batchOperationSecondCounter = 0f;

		private bool _hasValidOverrideFont = false;

		private bool _hasOverridenFont = false;

		private bool _initialized = false;

		private bool _started = false;

		private bool _temporarilyDisabled = false;

		private string _requireSpriteRendererCheckCausedBy = null;

		private int _lastSpriteUpdateFrame = -1;

		private bool _isCalledFromSceneManager = false;

		private bool _translationReloadRequest = false;

		private bool _hasUiBeenSetup = false;

		private static bool _inputSupported = true;

		public void Initialize()
		{
			Current = this;
			Paths.Initialize();
			HarmonyLoader.Load();
			Settings.Configure();
			DebugConsole.Enable();
			InitializeHarmonyDetourBridge();
			InitializeTextTranslationCaches();
			HooksSetup.InstallTextHooks();
			HooksSetup.InstallImageHooks();
			HooksSetup.InstallSpriteRendererHooks();
			HooksSetup.InstallTextGetterCompatHooks();
			HooksSetup.InstallComponentBasedPluginTranslationHooks();
			TextureCache = new TextureTranslationCache();
			TextureCache.TextureTranslationFileChanged += TextureCache_TextureTranslationFileChanged;
			ResizeCache = new UIResizeCache();
			TranslationManager = new TranslationManager();
			TranslationManager.JobCompleted += OnJobCompleted;
			TranslationManager.JobFailed += OnJobFailed;
			TranslationManager.InitializeEndpoints();
			SpamChecker = new SpamChecker(TranslationManager);
			UnityTextParsers.Initialize();
			InitializeResourceRedirector();
			ValidateConfiguration();
			EnableSceneLoadScan();
			LoadFallbackFont();
			LoadTranslations(reload: false);
			XuaLogger.AutoTranslator.Info("Loaded XUnity.AutoTranslator into Unity [" + Application.unityVersion + "] game.");
		}

		private static void LoadFallbackFont()
		{
			try
			{
				if (!string.IsNullOrEmpty(Settings.FallbackFontTextMeshPro))
				{
					Object orCreateFallbackFontTextMeshPro = FontCache.GetOrCreateFallbackFontTextMeshPro();
					if (TMP_Settings_Properties.FallbackFontAssets == null)
					{
						XuaLogger.AutoTranslator.Info("Cannot use fallback font because it is not supported in this version.");
						return;
					}
					if (orCreateFallbackFontTextMeshPro == (Object)null)
					{
						XuaLogger.AutoTranslator.Warn("Could not load fallback font for TextMesh Pro: " + Settings.FallbackFontTextMeshPro);
						return;
					}
					IList list = (IList)TMP_Settings_Properties.FallbackFontAssets.Get((object)null);
					list.Add(orCreateFallbackFontTextMeshPro);
					XuaLogger.AutoTranslator.Info("Loaded fallback font for TextMesh Pro: " + Settings.FallbackFontTextMeshPro);
				}
			}
			catch (Exception ex)
			{
				XuaLogger.AutoTranslator.Error(ex, "An error occurred while trying to load fallback font for TextMesh Pro.");
			}
		}

		private static void InitializeHarmonyDetourBridge()
		{
			try
			{
				if (Settings.InitializeHarmonyDetourBridge)
				{
					InitializeHarmonyDetourBridgeSafe();
				}
			}
			catch (Exception ex)
			{
				XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing harmony detour bridge.");
			}
		}

		private static void InitializeHarmonyDetourBridgeSafe()
		{
			HarmonyDetourBridge.Init(true, (Type)0);
		}

		private void InitializeTextTranslationCaches()
		{
			try
			{
				TextCache = new TextTranslationCache();
				TextCache.TextTranslationFileChanged += TextCache_TextTranslationFileChanged;
				string path = Path.Combine(Settings.TranslationsPath, "plugins");
				DirectoryInfo directoryInfo = new DirectoryInfo(path);
				if (directoryInfo.Exists)
				{
					DirectoryInfo[] directories = directoryInfo.GetDirectories();
					foreach (DirectoryInfo directoryInfo2 in directories)
					{
						TextTranslationCache value = new TextTranslationCache(directoryInfo2);
						PluginTextCaches.Add(directoryInfo2.Name, value);
					}
				}
			}
			catch (Exception ex)
			{
				XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing text translation caches.");
			}
		}

		private void TextCache_TextTranslationFile

BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.ExtProtocol.dll

Decompiled 2 years ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("gravydevsupreme")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Package that contains a simple inter-process protocol format used in XUnity.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+27fbfc0c2dfc32b3bb59b97a5639344e09ecfdc5")]
[assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.ExtProtocol")]
[assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.ExtProtocol")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace XUnity.AutoTranslator.Plugin.ExtProtocol;

public class ConfigurationMessage : ProtocolMessage
{
	public static readonly string Type = "4";

	public string Config { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		Config = reader.ReadToEnd();
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.Write(Config);
	}
}
public static class ExtProtocolConvert
{
	private static readonly Dictionary<string, Type> IdToType;

	private static readonly Dictionary<Type, string> TypeToId;

	static ExtProtocolConvert()
	{
		IdToType = new Dictionary<string, Type>();
		TypeToId = new Dictionary<Type, string>();
		Register(TranslationRequest.Type, typeof(TranslationRequest));
		Register(TranslationResponse.Type, typeof(TranslationResponse));
		Register(TranslationError.Type, typeof(TranslationError));
		Register(ConfigurationMessage.Type, typeof(ConfigurationMessage));
	}

	public static void Register(string id, Type type)
	{
		IdToType[id] = type;
		TypeToId[type] = id;
	}

	public static string Encode(ProtocolMessage message)
	{
		StringWriter stringWriter = new StringWriter();
		string value = TypeToId[message.GetType()];
		stringWriter.WriteLine(value);
		message.Encode(stringWriter);
		return Convert.ToBase64String(Encoding.UTF8.GetBytes(stringWriter.ToString()), Base64FormattingOptions.None);
	}

	public static ProtocolMessage Decode(string message)
	{
		string @string = Encoding.UTF8.GetString(Convert.FromBase64String(message));
		StringReader stringReader = new StringReader(@string);
		string key = stringReader.ReadLine();
		Type type = IdToType[key];
		ProtocolMessage protocolMessage = (ProtocolMessage)Activator.CreateInstance(type);
		protocolMessage.Decode(stringReader);
		return protocolMessage;
	}
}
public abstract class ProtocolMessage
{
	public Guid Id { get; set; }

	internal abstract void Decode(TextReader reader);

	internal abstract void Encode(TextWriter writer);
}
public enum StatusCode
{
	OK = 0,
	Blocked = 1,
	Unknown = 1000
}
public class TranslationError : ProtocolMessage
{
	public static readonly string Type = "3";

	public string Reason { get; set; }

	public StatusCode FailureCode { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		FailureCode = (StatusCode)int.Parse(reader.ReadLine());
		Reason = reader.ReadToEnd();
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.WriteLine((int)FailureCode);
		writer.Write(Reason);
	}
}
public class TranslationRequest : ProtocolMessage
{
	public static readonly string Type = "1";

	private string[] _untranslatedTexts;

	public string SourceLanguage { get; set; }

	public string DestinationLanguage { get; set; }

	public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((TransmittableUntranslatedTextInfo x) => x.UntranslatedText).ToArray());

	public TransmittableUntranslatedTextInfo[] UntranslatedTextInfos { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		SourceLanguage = reader.ReadLine();
		DestinationLanguage = reader.ReadLine();
		int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		TransmittableUntranslatedTextInfo[] array = new TransmittableUntranslatedTextInfo[num];
		for (int i = 0; i < num; i++)
		{
			TransmittableUntranslatedTextInfo transmittableUntranslatedTextInfo = new TransmittableUntranslatedTextInfo();
			transmittableUntranslatedTextInfo.Decode(reader);
			array[i] = transmittableUntranslatedTextInfo;
		}
		UntranslatedTextInfos = array;
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.WriteLine(SourceLanguage);
		writer.WriteLine(DestinationLanguage);
		writer.WriteLine(UntranslatedTextInfos.Length.ToString(CultureInfo.InvariantCulture));
		TransmittableUntranslatedTextInfo[] untranslatedTextInfos = UntranslatedTextInfos;
		foreach (TransmittableUntranslatedTextInfo transmittableUntranslatedTextInfo in untranslatedTextInfos)
		{
			transmittableUntranslatedTextInfo.Encode(writer);
		}
	}
}
public class TranslationResponse : ProtocolMessage
{
	public static readonly string Type = "2";

	public string[] TranslatedTexts { get; set; }

	internal override void Decode(TextReader reader)
	{
		base.Id = new Guid(reader.ReadLine());
		int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		string[] array = new string[num];
		for (int i = 0; i < num; i++)
		{
			string s = reader.ReadLine();
			string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s));
			array[i] = @string;
		}
		TranslatedTexts = array;
	}

	internal override void Encode(TextWriter writer)
	{
		writer.WriteLine(base.Id.ToString());
		writer.WriteLine(TranslatedTexts.Length.ToString(CultureInfo.InvariantCulture));
		string[] translatedTexts = TranslatedTexts;
		foreach (string s in translatedTexts)
		{
			string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None);
			writer.WriteLine(value);
		}
	}
}
public class TransmittableUntranslatedTextInfo
{
	public string[] ContextBefore { get; set; }

	public string UntranslatedText { get; set; }

	public string[] ContextAfter { get; set; }

	public TransmittableUntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter)
	{
		ContextBefore = contextBefore;
		UntranslatedText = untranslatedText;
		ContextAfter = contextAfter;
	}

	public TransmittableUntranslatedTextInfo()
	{
	}

	internal void Encode(TextWriter writer)
	{
		string[] contextBefore = ContextBefore;
		writer.WriteLine(((contextBefore != null) ? contextBefore.Length : 0).ToString(CultureInfo.InvariantCulture));
		if (ContextBefore != null)
		{
			string[] contextBefore2 = ContextBefore;
			foreach (string s in contextBefore2)
			{
				string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None);
				writer.WriteLine(value);
			}
		}
		string[] contextAfter = ContextAfter;
		writer.WriteLine(((contextAfter != null) ? contextAfter.Length : 0).ToString(CultureInfo.InvariantCulture));
		if (ContextAfter != null)
		{
			string[] contextAfter2 = ContextAfter;
			foreach (string s2 in contextAfter2)
			{
				string value2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(s2), Base64FormattingOptions.None);
				writer.WriteLine(value2);
			}
		}
		string value3 = Convert.ToBase64String(Encoding.UTF8.GetBytes(UntranslatedText), Base64FormattingOptions.None);
		writer.WriteLine(value3);
	}

	internal void Decode(TextReader reader)
	{
		int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		string[] array = new string[num];
		for (int i = 0; i < num; i++)
		{
			string s = reader.ReadLine();
			string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s));
			array[i] = @string;
		}
		ContextBefore = array;
		int num2 = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
		string[] array2 = new string[num2];
		for (int j = 0; j < num2; j++)
		{
			string s2 = reader.ReadLine();
			string string2 = Encoding.UTF8.GetString(Convert.FromBase64String(s2));
			array2[j] = string2;
		}
		ContextAfter = array2;
		string s3 = reader.ReadLine();
		string string3 = Encoding.UTF8.GetString(Convert.FromBase64String(s3));
		UntranslatedText = string3;
	}
}

BepInEx/plugins/XUnity.ResourceRedirector/XUnity.ResourceRedirector.BepInEx.dll

Decompiled 2 years ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("XUnity.ResourceRedirector.BepInEx")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyInformationalVersion("2.1.0")]
[assembly: AssemblyProduct("XUnity.ResourceRedirector.BepInEx")]
[assembly: AssemblyTitle("XUnity.ResourceRedirector.BepInEx")]
[assembly: AssemblyVersion("2.1.0.0")]
namespace XUnity.ResourceRedirector.BepInEx;

[BepInPlugin("gravydevsupreme.xunity.resourceredirector", "XUnity Resource Redirector", "2.1.0")]
public class ResourceRedirectorPlugin : BaseUnityPlugin
{
	public static ConfigEntry<bool> LogAllLoadedResources { get; set; }

	public static ConfigEntry<bool> LogCallbackOrder { get; set; }

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		LogAllLoadedResources = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Diagnostics", "Log all loaded resources"), false, (ConfigDescription)null);
		ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value;
		LogAllLoadedResources.SettingChanged += delegate
		{
			ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value;
		};
		LogCallbackOrder = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Diagnostics", "Log callback order"), false, (ConfigDescription)null);
		ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value;
		LogCallbackOrder.SettingChanged += delegate
		{
			ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value;
		};
		((BaseUnityPlugin)this).Config.ConfigReloaded += Config_ConfigReloaded;
	}

	private static void Config_ConfigReloaded(object sender, EventArgs e)
	{
		ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value;
		ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value;
	}
}

BepInEx/plugins/XUnity.ResourceRedirector/XUnity.ResourceRedirector.dll

Decompiled 2 years ago
using System;
using System.CodeDom.Compiler;
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.Resources;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis;
using UnityEngine;
using XUnity.Common.Constants;
using XUnity.Common.Extensions;
using XUnity.Common.Harmony;
using XUnity.Common.Logging;
using XUnity.Common.MonoMod;
using XUnity.Common.Utilities;
using XUnity.ResourceRedirector.Constants;
using XUnity.ResourceRedirector.Hooks;
using XUnity.ResourceRedirector.Properties;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("gravydevsupreme")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Main development dependency for XUnity Resource Redirector.")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyInformationalVersion("2.1.0")]
[assembly: AssemblyProduct("XUnity.ResourceRedirector")]
[assembly: AssemblyTitle("XUnity.ResourceRedirector")]
[assembly: AssemblyVersion("2.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[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 XUnity.ResourceRedirector
{
	internal class AssetBundleExtensionData
	{
		private string _normalizedPath;

		private string _path;

		public string NormalizedPath
		{
			get
			{
				if (Path != null && _normalizedPath == null)
				{
					_normalizedPath = StringExtensions.MakeRelativePath(Path.ToLowerInvariant(), EnvironmentEx.LoweredCurrentDirectory);
				}
				return _normalizedPath;
			}
		}

		public string Path
		{
			get
			{
				return _path;
			}
			set
			{
				if (_path != value)
				{
					_path = value;
					_normalizedPath = null;
				}
			}
		}
	}
	public static class AssetBundleHelper
	{
		internal static string PathForLoadedInMemoryBundle;

		public static AssetBundle CreateEmptyAssetBundle()
		{
			byte[] empty = Resources.empty;
			CabHelper.RandomizeCab(empty);
			return AssetBundle.LoadFromMemory(empty);
		}

		public static AssetBundleCreateRequest CreateEmptyAssetBundleRequest()
		{
			byte[] empty = Resources.empty;
			CabHelper.RandomizeCab(empty);
			return AssetBundle.LoadFromMemoryAsync(empty);
		}

		public static AssetBundle LoadFromMemory(string path, byte[] binary, uint crc)
		{
			try
			{
				PathForLoadedInMemoryBundle = path;
				return AssetBundle.LoadFromMemory(binary, crc);
			}
			finally
			{
				PathForLoadedInMemoryBundle = null;
			}
		}

		public static AssetBundleCreateRequest LoadFromMemoryAsync(string path, byte[] binary, uint crc)
		{
			try
			{
				PathForLoadedInMemoryBundle = path;
				return AssetBundle.LoadFromMemoryAsync(binary, crc);
			}
			finally
			{
				PathForLoadedInMemoryBundle = null;
			}
		}

		public static AssetBundle LoadFromFileWithRandomizedCabIfRequired(string path, uint crc, ulong offset)
		{
			return LoadFromFileWithRandomizedCabIfRequired(path, crc, offset, confirmFileExists: true);
		}

		internal static AssetBundle LoadFromFileWithRandomizedCabIfRequired(string path, uint crc, ulong offset, bool confirmFileExists)
		{
			AssetBundle val = AssetBundle.LoadFromFile(path, crc, offset);
			if ((Object)(object)val == (Object)null && (!confirmFileExists || File.Exists(path)))
			{
				byte[] array;
				using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
				{
					long num = fileStream.Length - (long)offset;
					fileStream.Seek((long)offset, SeekOrigin.Begin);
					array = StreamExtensions.ReadFully((Stream)fileStream, (int)num);
				}
				CabHelper.RandomizeCabWithAnyLength(array);
				XuaLogger.ResourceRedirector.Warn("Randomized CAB for '" + path + "' in order to load it because another asset bundle already uses its CAB-string. You can ignore the previous error message, but this is likely caused by two mods incorrectly using the same CAB-string.");
				return AssetBundle.LoadFromMemory(array);
			}
			return val;
		}
	}
	public class AssetBundleLoadedContext
	{
		private string _normalizedPath;

		public AssetBundleLoadingParameters Parameters { get; }

		public AssetBundle Bundle { get; set; }

		internal bool SkipRemainingPostfixes { get; private set; }

		internal AssetBundleLoadedContext(AssetBundleLoadingParameters parameters, AssetBundle bundle)
		{
			Parameters = parameters;
			Bundle = bundle;
		}

		public string GetNormalizedPath()
		{
			if (_normalizedPath == null && Parameters.Path != null)
			{
				_normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory);
			}
			return _normalizedPath;
		}

		public void Complete(bool skipRemainingPostfixes = true)
		{
			SkipRemainingPostfixes = skipRemainingPostfixes;
		}

		public void DisableRecursion()
		{
			ResourceRedirection.RecursionEnabled = false;
		}
	}
	public class AssetBundleLoadingContext : IAssetBundleLoadingContext
	{
		private string _normalizedPath;

		public AssetBundleLoadingParameters Parameters { get; }

		public AssetBundle Bundle { get; set; }

		internal bool SkipRemainingPrefixes { get; private set; }

		internal bool SkipOriginalCall { get; private set; }

		internal bool SkipAllPostfixes { get; private set; }

		internal AssetBundleLoadingContext(AssetBundleLoadingParameters parameters)
		{
			Parameters = parameters;
		}

		public string GetNormalizedPath()
		{
			if (_normalizedPath == null && Parameters.Path != null)
			{
				_normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory);
			}
			return _normalizedPath;
		}

		public void Complete()
		{
			Complete(skipRemainingPrefixes: true, true, true);
		}

		public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true)
		{
			Complete(skipRemainingPrefixes, skipOriginalCall, true);
		}

		public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true)
		{
			SkipRemainingPrefixes = skipRemainingPrefixes;
			if (skipOriginalCall.HasValue)
			{
				SkipOriginalCall = skipOriginalCall.Value;
			}
			if (skipAllPostfixes.HasValue)
			{
				SkipAllPostfixes = skipAllPostfixes.Value;
			}
		}

		public void DisableRecursion()
		{
			ResourceRedirection.RecursionEnabled = false;
		}
	}
	public class AssetBundleLoadingParameters
	{
		public string Path { get; set; }

		public uint Crc { get; set; }

		public ulong Offset { get; set; }

		public Stream Stream { get; set; }

		public uint ManagedReadBufferSize { get; }

		public byte[] Binary { get; set; }

		public AssetBundleLoadType LoadType { get; }

		internal AssetBundleLoadingParameters(byte[] data, string path, uint crc, ulong offset, Stream stream, uint managedReadBufferSize, AssetBundleLoadType loadType)
		{
			Binary = data;
			Path = path;
			Crc = crc;
			Offset = offset;
			Stream = stream;
			ManagedReadBufferSize = managedReadBufferSize;
			LoadType = loadType;
		}
	}
	public enum AssetBundleLoadType
	{
		LoadFromFile = 1,
		LoadFromMemory,
		LoadFromStream
	}
	public class AssetLoadedContext : IAssetOrResourceLoadedContext
	{
		private AssetBundleExtensionData _ext;

		private bool _lookedForExt;

		private BackingFieldOrArray _backingField;

		public AssetLoadedParameters Parameters { get; }

		public AssetBundle Bundle { get; }

		public Object[] Assets
		{
			get
			{
				return _backingField.Array;
			}
			set
			{
				_backingField.Array = value;
			}
		}

		public Object Asset
		{
			get
			{
				return _backingField.Field;
			}
			set
			{
				_backingField.Field = value;
			}
		}

		internal bool SkipRemainingPostfixes { get; private set; }

		internal AssetLoadedContext(AssetLoadedParameters parameters, AssetBundle bundle, Object[] assets)
		{
			Parameters = parameters;
			Bundle = bundle;
			_backingField = new BackingFieldOrArray(assets);
		}

		internal AssetLoadedContext(AssetLoadedParameters parameters, AssetBundle bundle, Object asset)
		{
			Parameters = parameters;
			Bundle = bundle;
			_backingField = new BackingFieldOrArray(asset);
		}

		public bool HasReferenceBeenRedirectedBefore(Object asset)
		{
			return ExtensionDataHelper.GetExtensionData<ResourceExtensionData>((object)asset)?.HasBeenRedirected ?? false;
		}

		public string GetUniqueFileSystemAssetPath(Object asset)
		{
			ResourceExtensionData orCreateExtensionData = ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)asset);
			if (orCreateExtensionData.FullFileSystemAssetPath == null)
			{
				string text = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle)?.NormalizedPath;
				string path = (string.IsNullOrEmpty(text) ? "unnamed_assetbundle" : text.ToLowerInvariant());
				string name = asset.name;
				if (!string.IsNullOrEmpty(name))
				{
					path = Path.Combine(path, name.ToLowerInvariant());
				}
				else
				{
					string text2 = null;
					if (Assets.Length > 1)
					{
						int num = Array.IndexOf(Assets, asset);
						text2 = ((num != -1) ? ("_" + num.ToString(CultureInfo.InvariantCulture)) : "_with_unknown_index");
					}
					path = Path.Combine(path, (Parameters.LoadType == AssetLoadType.LoadMainAsset) ? "main_asset" : ("unnamed_asset" + text2));
				}
				path = StringExtensions.UseCorrectDirectorySeparators(path);
				orCreateExtensionData.FullFileSystemAssetPath = path;
			}
			return orCreateExtensionData.FullFileSystemAssetPath;
		}

		public string GetAssetBundlePath()
		{
			if (!_lookedForExt)
			{
				_lookedForExt = true;
				_ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle);
			}
			return _ext?.Path;
		}

		public string GetNormalizedAssetBundlePath()
		{
			if (!_lookedForExt)
			{
				_lookedForExt = true;
				_ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle);
			}
			return _ext?.NormalizedPath;
		}

		public void Complete(bool skipRemainingPostfixes = true)
		{
			SkipRemainingPostfixes = skipRemainingPostfixes;
		}

		public void DisableRecursion()
		{
			ResourceRedirection.RecursionEnabled = false;
		}
	}
	public class AssetLoadedParameters
	{
		public string Name { get; }

		public Type Type { get; }

		public AssetLoadType LoadType { get; }

		internal AssetLoadedParameters(string name, Type type, AssetLoadType loadType)
		{
			Name = name;
			Type = type;
			LoadType = loadType;
		}
	}
	public class AssetLoadingContext : IAssetLoadingContext
	{
		private AssetBundleExtensionData _ext;

		private bool _lookedForExt;

		private BackingFieldOrArray _backingField;

		public AssetLoadingParameters Parameters { get; }

		public AssetBundle Bundle { get; }

		public Object[] Assets
		{
			get
			{
				return _backingField.Array;
			}
			set
			{
				_backingField.Array = value;
			}
		}

		public Object Asset
		{
			get
			{
				return _backingField.Field;
			}
			set
			{
				_backingField.Field = value;
			}
		}

		internal bool SkipRemainingPrefixes { get; private set; }

		internal bool SkipOriginalCall { get; private set; }

		internal bool SkipAllPostfixes { get; private set; }

		internal AssetLoadingContext(AssetLoadingParameters parameters, AssetBundle bundle)
		{
			Parameters = parameters;
			Bundle = bundle;
		}

		public string GetAssetBundlePath()
		{
			if (!_lookedForExt)
			{
				_lookedForExt = true;
				_ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle);
			}
			return _ext?.Path;
		}

		public string GetNormalizedAssetBundlePath()
		{
			if (!_lookedForExt)
			{
				_lookedForExt = true;
				_ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle);
			}
			return _ext?.NormalizedPath;
		}

		public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true)
		{
			SkipRemainingPrefixes = skipRemainingPrefixes;
			if (skipOriginalCall.HasValue)
			{
				SkipOriginalCall = skipOriginalCall.Value;
			}
			if (skipAllPostfixes.HasValue)
			{
				SkipAllPostfixes = skipAllPostfixes.Value;
			}
		}

		public void DisableRecursion()
		{
			ResourceRedirection.RecursionEnabled = false;
		}
	}
	public class AssetLoadingParameters
	{
		public string Name { get; set; }

		public Type Type { get; set; }

		public AssetLoadType LoadType { get; }

		internal AssetLoadingParameters(string name, Type type, AssetLoadType loadType)
		{
			Name = name;
			Type = type;
			LoadType = loadType;
		}

		internal AssetLoadedParameters ToAssetLoadedParameters()
		{
			return new AssetLoadedParameters(Name, Type, LoadType);
		}
	}
	public enum AssetLoadType
	{
		LoadMainAsset = 1,
		LoadByType,
		LoadNamed,
		LoadNamedWithSubAssets
	}
	internal class AsyncAssetBundleLoadInfo
	{
		public AssetBundleLoadingParameters Parameters { get; }

		public AssetBundle Bundle { get; }

		public bool SkipAllPostfixes { get; }

		public AsyncAssetBundleLoadingResolve ResolveType { get; }

		public AsyncAssetBundleLoadInfo(AssetBundleLoadingParameters parameters, AssetBundle bundle, bool skipAllPostfixes, AsyncAssetBundleLoadingResolve resolveType)
		{
			Parameters = parameters;
			Bundle = bundle;
			SkipAllPostfixes = skipAllPostfixes;
			ResolveType = resolveType;
		}
	}
	public class AsyncAssetBundleLoadingContext : IAssetBundleLoadingContext
	{
		private string _normalizedPath;

		private AssetBundle _bundle;

		private AssetBundleCreateRequest _request;

		public AssetBundleLoadingParameters Parameters { get; }

		public AssetBundleCreateRequest Request
		{
			get
			{
				return _request;
			}
			set
			{
				_request = value;
				ResolveType = AsyncAssetBundleLoadingResolve.ThroughRequest;
			}
		}

		public AssetBundle Bundle
		{
			get
			{
				return _bundle;
			}
			set
			{
				if (!ResourceRedirection.SyncOverAsyncEnabled)
				{
					throw new InvalidOperationException("Trying to set the Bundle property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'.");
				}
				_bundle = value;
				ResolveType = AsyncAssetBundleLoadingResolve.ThroughBundle;
			}
		}

		public AsyncAssetBundleLoadingResolve ResolveType { get; set; }

		internal bool SkipRemainingPrefixes { get; private set; }

		internal bool SkipOriginalCall { get; set; }

		internal bool SkipAllPostfixes { get; private set; }

		internal AsyncAssetBundleLoadingContext(AssetBundleLoadingParameters parameters)
		{
			Parameters = parameters;
		}

		public string GetNormalizedPath()
		{
			if (_normalizedPath == null && Parameters.Path != null)
			{
				_normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory);
			}
			return _normalizedPath;
		}

		public void Complete()
		{
			Complete(skipRemainingPrefixes: true, true, true);
		}

		public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true)
		{
			Complete(skipRemainingPrefixes, skipOriginalCall, true);
		}

		public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true)
		{
			SkipRemainingPrefixes = skipRemainingPrefixes;
			if (skipOriginalCall.HasValue)
			{
				SkipOriginalCall = skipOriginalCall.Value;
			}
			if (skipAllPostfixes.HasValue)
			{
				SkipAllPostfixes = skipAllPostfixes.Value;
			}
		}

		public void DisableRecursion()
		{
			ResourceRedirection.RecursionEnabled = false;
		}
	}
	public enum AsyncAssetBundleLoadingResolve
	{
		ThroughRequest,
		ThroughBundle
	}
	internal class AsyncAssetLoadInfo
	{
		public AssetLoadingParameters Parameters { get; }

		public AssetBundle Bundle { get; }

		public bool SkipAllPostfixes { get; }

		public AsyncAssetLoadingResolve ResolveType { get; }

		public Object[] Assets { get; }

		public AsyncAssetLoadInfo(AssetLoadingParameters parameters, AssetBundle bundle, bool skipAllPostfixes, AsyncAssetLoadingResolve resolveType, Object[] assets)
		{
			Parameters = parameters;
			Bundle = bundle;
			SkipAllPostfixes = skipAllPostfixes;
			ResolveType = resolveType;
			Assets = assets;
		}
	}
	public class AsyncAssetLoadingContext : IAssetLoadingContext
	{
		private AssetBundleExtensionData _ext;

		private bool _lookedForExt;

		private Object[] _assets;

		private AssetBundleRequest _request;

		private BackingFieldOrArray _backingField;

		public AssetLoadingParameters Parameters { get; }

		public AssetBundle Bundle { get; }

		public AssetBundleRequest Request
		{
			get
			{
				return _request;
			}
			set
			{
				_request = value;
				ResolveType = AsyncAssetLoadingResolve.ThroughRequest;
			}
		}

		public Object[] Assets
		{
			get
			{
				return _backingField.Array;
			}
			set
			{
				if (!ResourceRedirection.SyncOverAsyncEnabled)
				{
					throw new InvalidOperationException("Trying to set the Assets/Asset property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'.");
				}
				_backingField.Array = value;
				ResolveType = AsyncAssetLoadingResolve.ThroughAssets;
			}
		}

		public Object Asset
		{
			get
			{
				return _backingField.Field;
			}
			set
			{
				if (!ResourceRedirection.SyncOverAsyncEnabled)
				{
					throw new InvalidOperationException("Trying to set the Assets/Asset property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'.");
				}
				_backingField.Field = value;
				ResolveType = AsyncAssetLoadingResolve.ThroughAssets;
			}
		}

		public AsyncAssetLoadingResolve ResolveType { get; set; }

		internal bool SkipRemainingPrefixes { get; private set; }

		internal bool SkipOriginalCall { get; set; }

		internal bool SkipAllPostfixes { get; private set; }

		internal AsyncAssetLoadingContext(AssetLoadingParameters parameters, AssetBundle bundle)
		{
			Parameters = parameters;
			Bundle = bundle;
		}

		public string GetAssetBundlePath()
		{
			if (!_lookedForExt)
			{
				_lookedForExt = true;
				_ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle);
			}
			return _ext?.Path;
		}

		public string GetNormalizedAssetBundlePath()
		{
			if (!_lookedForExt)
			{
				_lookedForExt = true;
				_ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle);
			}
			return _ext?.NormalizedPath;
		}

		public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true)
		{
			SkipRemainingPrefixes = skipRemainingPrefixes;
			if (skipOriginalCall.HasValue)
			{
				SkipOriginalCall = skipOriginalCall.Value;
			}
			if (skipAllPostfixes.HasValue)
			{
				SkipAllPostfixes = skipAllPostfixes.Value;
			}
		}

		public void DisableRecursion()
		{
			ResourceRedirection.RecursionEnabled = false;
		}
	}
	public enum AsyncAssetLoadingResolve
	{
		ThroughRequest,
		ThroughAssets
	}
	internal struct BackingFieldOrArray
	{
		private Object _field;

		private Object[] _array;

		private BackingSource _source;

		public Object Field
		{
			get
			{
				if (_source == BackingSource.None)
				{
					return null;
				}
				if (_source == BackingSource.SingleField)
				{
					return _field;
				}
				if (_array == null || _array.Length == 0)
				{
					return null;
				}
				return _array[0];
			}
			set
			{
				_field = value;
				_array = null;
				_source = BackingSource.SingleField;
			}
		}

		public Object[] Array
		{
			get
			{
				if (_source == BackingSource.Array)
				{
					return _array;
				}
				if (_field == (Object)null)
				{
					Array = (Object[])(object)new Object[0];
				}
				else
				{
					Array = (Object[])(object)new Object[1] { _field };
				}
				return _array;
			}
			set
			{
				_field = null;
				_array = value;
				_source = BackingSource.Array;
			}
		}

		public BackingFieldOrArray(Object field)
		{
			_field = field;
			_array = null;
			_source = BackingSource.SingleField;
		}

		public BackingFieldOrArray(Object[] array)
		{
			_field = null;
			_array = array;
			_source = BackingSource.Array;
		}

		public IEnumerable<Object> IterateObjects()
		{
			if (_array != null)
			{
				Object[] array = _array;
				for (int i = 0; i < array.Length; i++)
				{
					yield return array[i];
				}
			}
			else if (_field != (Object)null)
			{
				yield return _field;
			}
		}
	}
	internal enum BackingSource : byte
	{
		None,
		SingleField,
		Array
	}
	public static class CallbackPriority
	{
		public const int Default = 0;
	}
	public enum HookBehaviour
	{
		OneCallbackPerLoadCall = 1,
		OneCallbackPerResourceLoaded
	}
	public interface IAssetBundleLoadingContext
	{
		AssetBundleLoadingParameters Parameters { get; }

		AssetBundle Bundle { get; set; }

		string GetNormalizedPath();

		void Complete();

		void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true);

		void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true);

		void DisableRecursion();
	}
	public interface IAssetLoadingContext
	{
		AssetLoadingParameters Parameters { get; }

		AssetBundle Bundle { get; }

		Object[] Assets { get; set; }

		Object Asset { get; set; }

		string GetAssetBundlePath();

		string GetNormalizedAssetBundlePath();

		void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true);

		void DisableRecursion();
	}
	public interface IAssetOrResourceLoadedContext
	{
		Object[] Assets { get; set; }

		Object Asset { get; set; }

		bool HasReferenceBeenRedirectedBefore(Object asset);

		string GetUniqueFileSystemAssetPath(Object asset);

		void Complete(bool skipRemainingPostfixes = true);

		void DisableRecursion();
	}
	internal class PrioritizedCallback
	{
		public static PrioritizedCallback<TCallback> Create<TCallback>(TCallback item, int priority) where TCallback : Delegate
		{
			return new PrioritizedCallback<TCallback>(item, priority);
		}
	}
	internal class PrioritizedCallback<TCallback> : PrioritizedCallback, IComparable<PrioritizedCallback<TCallback>>, IEquatable<PrioritizedCallback<TCallback>> where TCallback : Delegate
	{
		public TCallback Callback { get; }

		public int Priority { get; }

		public Type TargetType { get; set; }

		public bool IsBeingCalled { get; set; }

		public PrioritizedCallback(TCallback callback, int priority)
		{
			Callback = callback;
			Priority = priority;
			TargetType = callback.Target?.GetType();
		}

		public int CompareTo(PrioritizedCallback<TCallback> other)
		{
			return other.Priority.CompareTo(Priority);
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as PrioritizedCallback<TCallback>);
		}

		public bool Equals(PrioritizedCallback<TCallback> other)
		{
			return EqualityComparer<TCallback>.Default.Equals(Callback, other.Callback);
		}

		public override int GetHashCode()
		{
			return -1406788065 * -1521134295 + EqualityComparer<TCallback>.Default.GetHashCode(Callback);
		}

		public override string ToString()
		{
			return "[" + Priority + "] " + (TargetType?.Name ?? Callback.Method.DeclaringType?.Name) + "." + Callback.Method?.Name;
		}
	}
	internal class ResourceExtensionData
	{
		public bool HasBeenRedirected { get; set; }

		public string FullFileSystemAssetPath { get; set; }
	}
	public class ResourceLoadedContext : IAssetOrResourceLoadedContext
	{
		private BackingFieldOrArray _backingField;

		public ResourceLoadedParameters Parameters { get; }

		public Object[] Assets
		{
			get
			{
				return _backingField.Array;
			}
			set
			{
				_backingField.Array = value;
			}
		}

		public Object Asset
		{
			get
			{
				return _backingField.Field;
			}
			set
			{
				_backingField.Field = value;
			}
		}

		internal bool SkipRemainingPostfixes { get; set; }

		internal ResourceLoadedContext(ResourceLoadedParameters parameters, Object[] assets)
		{
			Parameters = parameters;
			_backingField = new BackingFieldOrArray(assets);
		}

		internal ResourceLoadedContext(ResourceLoadedParameters parameters, Object asset)
		{
			Parameters = parameters;
			_backingField = new BackingFieldOrArray(asset);
		}

		public bool HasReferenceBeenRedirectedBefore(Object asset)
		{
			return ExtensionDataHelper.GetExtensionData<ResourceExtensionData>((object)asset)?.HasBeenRedirected ?? false;
		}

		public string GetUniqueFileSystemAssetPath(Object asset)
		{
			ResourceExtensionData orCreateExtensionData = ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)asset);
			if (orCreateExtensionData.FullFileSystemAssetPath == null)
			{
				string text = string.Empty;
				if (!string.IsNullOrEmpty(Parameters.Path))
				{
					text = Parameters.Path.ToLowerInvariant();
				}
				if (Parameters.LoadType == ResourceLoadType.LoadByType)
				{
					string name = asset.name;
					if (!string.IsNullOrEmpty(name))
					{
						text = Path.Combine(text, name.ToLowerInvariant());
					}
					else
					{
						string text2 = null;
						if (Assets.Length > 1)
						{
							int num = Array.IndexOf(Assets, asset);
							text2 = ((num != -1) ? ("_" + num.ToString(CultureInfo.InvariantCulture)) : "_with_unknown_index");
						}
						text = Path.Combine(text, "unnamed_asset" + text2);
					}
				}
				text = StringExtensions.UseCorrectDirectorySeparators(text);
				orCreateExtensionData.FullFileSystemAssetPath = text;
			}
			return orCreateExtensionData.FullFileSystemAssetPath;
		}

		public void Complete(bool skipRemainingPostfixes = true)
		{
			SkipRemainingPostfixes = skipRemainingPostfixes;
		}

		public void DisableRecursion()
		{
			ResourceRedirection.RecursionEnabled = false;
		}
	}
	public class ResourceLoadedParameters
	{
		public string Path { get; set; }

		public Type Type { get; set; }

		public ResourceLoadType LoadType { get; }

		internal ResourceLoadedParameters(string path, Type type, ResourceLoadType loadType)
		{
			Path = path;
			Type = type;
			LoadType = loadType;
		}
	}
	public enum ResourceLoadType
	{
		LoadByType = 1,
		LoadNamed,
		LoadNamedBuiltIn
	}
	public static class ResourceRedirection
	{
		private static readonly List<PrioritizedCallback<Action<AssetLoadedContext>>> PostfixRedirectionsForAssetsPerCall = new List<PrioritizedCallback<Action<AssetLoadedContext>>>();

		private static readonly List<PrioritizedCallback<Action<AssetLoadedContext>>> PostfixRedirectionsForAssetsPerResource = new List<PrioritizedCallback<Action<AssetLoadedContext>>>();

		private static readonly List<PrioritizedCallback<Action<ResourceLoadedContext>>> PostfixRedirectionsForResourcesPerCall = new List<PrioritizedCallback<Action<ResourceLoadedContext>>>();

		private static readonly List<PrioritizedCallback<Action<ResourceLoadedContext>>> PostfixRedirectionsForResourcesPerResource = new List<PrioritizedCallback<Action<ResourceLoadedContext>>>();

		private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAssetsPerCall = new List<PrioritizedCallback<Delegate>>();

		private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAsyncAssetsPerCall = new List<PrioritizedCallback<Delegate>>();

		private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAssetBundles = new List<PrioritizedCallback<Delegate>>();

		private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAsyncAssetBundles = new List<PrioritizedCallback<Delegate>>();

		private static readonly List<PrioritizedCallback<Action<AssetBundleLoadedContext>>> PostfixRedirectionsForAssetBundles = new List<PrioritizedCallback<Action<AssetBundleLoadedContext>>>();

		private static Action<AssetBundleLoadingContext> _emulateAssetBundles;

		private static Action<AsyncAssetBundleLoadingContext> _emulateAssetBundlesAsync;

		private static Action<AssetBundleLoadingContext> _redirectionMissingAssetBundlesToEmpty;

		private static Action<AsyncAssetBundleLoadingContext> _redirectionMissingAssetBundlesToEmptyAsync;

		private static bool _enabledRandomizeCabIfConflict = false;

		private static Action<AssetBundleLoadingContext> _enableCabRandomizationPrefix;

		private static Action<AsyncAssetBundleLoadingContext> _enableCabRandomizationPrefixAsync;

		private static Action<AssetBundleLoadedContext> _enableCabRandomizationPostfix;

		private static bool _initialized = false;

		private static bool _initializedSyncOverAsyncEnabled = false;

		private static bool _logAllLoadedResources = false;

		private static bool _isFiringAssetBundle;

		private static bool _isFiringResource;

		private static bool _isFiringAsset;

		private static bool _isRecursionDisabledPermanently;

		internal static bool RecursionEnabled = true;

		internal static bool SyncOverAsyncEnabled = false;

		public static bool LogAllLoadedResources
		{
			get
			{
				return _logAllLoadedResources;
			}
			set
			{
				if (value)
				{
					Initialize();
				}
				_logAllLoadedResources = value;
			}
		}

		public static bool LogCallbackOrder { get; set; }

		public static void Initialize()
		{
			if (!_initialized)
			{
				_initialized = true;
				HookingHelper.PatchAll((IEnumerable<Type>)ResourceAndAssetHooks.GeneralHooks, false);
			}
		}

		public static void EnableSyncOverAsyncAssetLoads()
		{
			Initialize();
			if (!_initializedSyncOverAsyncEnabled)
			{
				_initializedSyncOverAsyncEnabled = true;
				SyncOverAsyncEnabled = true;
				HookingHelper.PatchAll((IEnumerable<Type>)ResourceAndAssetHooks.SyncOverAsyncHooks, false);
			}
		}

		public static void DisableRecursionPermanently()
		{
			_isRecursionDisabledPermanently = true;
		}

		public static void EnableEmulateAssetBundles(int priority, string emulationDirectory)
		{
			if (_emulateAssetBundles == null && _emulateAssetBundlesAsync == null)
			{
				_emulateAssetBundles = delegate(AssetBundleLoadingContext ctx)
				{
					HandleAssetBundleEmulation<AssetBundleLoadingContext>(ctx, SetBundle);
				};
				_emulateAssetBundlesAsync = delegate(AsyncAssetBundleLoadingContext ctx)
				{
					HandleAssetBundleEmulation<AsyncAssetBundleLoadingContext>(ctx, SetRequest);
				};
				RegisterAssetBundleLoadingHook(priority, _emulateAssetBundles);
				RegisterAsyncAssetBundleLoadingHook(priority, _emulateAssetBundlesAsync);
			}
			void HandleAssetBundleEmulation<T>(T context, Action<T, string> changeBundle) where T : IAssetBundleLoadingContext
			{
				if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile)
				{
					string normalizedPath = context.GetNormalizedPath();
					string text = Path.Combine(emulationDirectory, normalizedPath);
					if (File.Exists(text))
					{
						changeBundle(context, text);
						ref T reference = ref context;
						T val = default(T);
						if (val == null)
						{
							val = reference;
							reference = ref val;
						}
						reference.Complete(skipRemainingPrefixes: true, true);
						XuaLogger.ResourceRedirector.Debug("Redirected asset bundle: '" + context.Parameters.Path + "' => '" + text + "'");
					}
				}
			}
			static void SetBundle(AssetBundleLoadingContext context, string path)
			{
				context.Bundle = AssetBundle.LoadFromFile(path, context.Parameters.Crc, context.Parameters.Offset);
			}
			static void SetRequest(AsyncAssetBundleLoadingContext context, string path)
			{
				context.Request = AssetBundle.LoadFromFileAsync(path, context.Parameters.Crc, context.Parameters.Offset);
			}
		}

		public static void DisableEmulateAssetBundles()
		{
			if (_emulateAssetBundles != null && _emulateAssetBundlesAsync != null)
			{
				UnregisterAssetBundleLoadingHook(_emulateAssetBundles);
				UnregisterAsyncAssetBundleLoadingHook(_emulateAssetBundlesAsync);
				_emulateAssetBundles = null;
				_emulateAssetBundlesAsync = null;
			}
		}

		public static void EnableRedirectMissingAssetBundlesToEmptyAssetBundle(int priority)
		{
			if (_redirectionMissingAssetBundlesToEmpty == null && _redirectionMissingAssetBundlesToEmptyAsync == null)
			{
				_redirectionMissingAssetBundlesToEmpty = delegate(AssetBundleLoadingContext ctx)
				{
					HandleMissingBundle<AssetBundleLoadingContext>(ctx, SetBundle);
				};
				_redirectionMissingAssetBundlesToEmptyAsync = delegate(AsyncAssetBundleLoadingContext ctx)
				{
					HandleMissingBundle<AsyncAssetBundleLoadingContext>(ctx, SetRequest);
				};
				RegisterAssetBundleLoadingHook(priority, _redirectionMissingAssetBundlesToEmpty);
				RegisterAsyncAssetBundleLoadingHook(priority, _redirectionMissingAssetBundlesToEmptyAsync);
			}
			static void HandleMissingBundle<TContext>(TContext context, Action<TContext, byte[]> changeBundle) where TContext : IAssetBundleLoadingContext
			{
				if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile && !File.Exists(context.Parameters.Path))
				{
					byte[] empty = Resources.empty;
					CabHelper.RandomizeCab(empty);
					changeBundle(context, empty);
					ref TContext reference = ref context;
					TContext val = default(TContext);
					if (val == null)
					{
						val = reference;
						reference = ref val;
					}
					reference.Complete(skipRemainingPrefixes: true, true);
					XuaLogger.ResourceRedirector.Warn("Tried to load non-existing asset bundle: " + context.Parameters.Path);
				}
			}
			static void SetBundle(AssetBundleLoadingContext context, byte[] assetBundleData)
			{
				AssetBundle bundle = AssetBundle.LoadFromMemory(assetBundleData);
				context.Bundle = bundle;
			}
			static void SetRequest(AsyncAssetBundleLoadingContext context, byte[] assetBundleData)
			{
				AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(assetBundleData);
				context.Request = request;
			}
		}

		public static void EnableRandomizeCabIfConflict(int priority, bool forceRandomizeWhenInMemory)
		{
			if (_enabledRandomizeCabIfConflict)
			{
				return;
			}
			_enabledRandomizeCabIfConflict = true;
			if (forceRandomizeWhenInMemory)
			{
				_enableCabRandomizationPrefix = delegate(AssetBundleLoadingContext ctx)
				{
					HandleCabRandomizePrefix(ctx);
				};
				_enableCabRandomizationPrefixAsync = delegate(AsyncAssetBundleLoadingContext ctx)
				{
					HandleCabRandomizePrefix(ctx);
				};
				RegisterAssetBundleLoadingHook(priority, _enableCabRandomizationPrefix);
				RegisterAsyncAssetBundleLoadingHook(priority, _enableCabRandomizationPrefixAsync);
			}
			_enableCabRandomizationPostfix = delegate(AssetBundleLoadedContext ctx)
			{
				HandleCabRandomizePostfix(ctx);
			};
			RegisterAssetBundleLoadedHook(priority, _enableCabRandomizationPostfix);
			void HandleCabRandomizePostfix(AssetBundleLoadedContext context)
			{
				if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile)
				{
					if ((Object)(object)context.Bundle == (Object)null && File.Exists(context.Parameters.Path))
					{
						XuaLogger.ResourceRedirector.Warn("The asset bundle '" + context.Parameters.Path + "' could not be loaded likely due to conflicting CAB-string. Retrying in-memory with randomized CAB-string.");
						byte[] array;
						using (FileStream fileStream = new FileStream(context.Parameters.Path, FileMode.Open, FileAccess.Read))
						{
							long length = fileStream.Length;
							long offset = (long)context.Parameters.Offset;
							long num = length - offset;
							fileStream.Seek(offset, SeekOrigin.Begin);
							array = StreamExtensions.ReadFully((Stream)fileStream, (int)num);
						}
						if (!forceRandomizeWhenInMemory)
						{
							CabHelper.RandomizeCabWithAnyLength(array);
						}
						AssetBundle val = AssetBundle.LoadFromMemory(array, 0u);
						if ((Object)(object)val != (Object)null)
						{
							context.Bundle = val;
							context.Complete();
						}
					}
				}
				else if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromMemory)
				{
					if ((Object)(object)context.Bundle == (Object)null && !forceRandomizeWhenInMemory)
					{
						string text = AssetBundleHelper.PathForLoadedInMemoryBundle ?? "Unnamed";
						XuaLogger.ResourceRedirector.Warn("Could not load an in-memory asset bundle (" + text + ") likely due to conflicting CAB-string. Retrying with randomized CAB-string.");
						CabHelper.RandomizeCabWithAnyLength(context.Parameters.Binary);
						AssetBundle val2 = AssetBundle.LoadFromMemory(context.Parameters.Binary, 0u);
						if ((Object)(object)val2 != (Object)null)
						{
							context.Bundle = val2;
							context.Complete();
						}
					}
				}
				else if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromStream && (Object)(object)context.Bundle == (Object)null)
				{
					string text2 = AssetBundleHelper.PathForLoadedInMemoryBundle ?? "Unnamed";
					XuaLogger.ResourceRedirector.Warn("Could not load a stream asset bundle (" + text2 + ") likely due to conflicting CAB-string. Retrying with randomized CAB-string.");
					byte[] array2 = StreamExtensions.ReadFully(context.Parameters.Stream, 0);
					if (!forceRandomizeWhenInMemory)
					{
						CabHelper.RandomizeCabWithAnyLength(array2);
					}
					AssetBundle val3 = AssetBundle.LoadFromMemory(array2, 0u);
					if ((Object)(object)val3 != (Object)null)
					{
						context.Bundle = val3;
						context.Complete();
					}
				}
			}
			static void HandleCabRandomizePrefix(IAssetBundleLoadingContext context)
			{
				if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromMemory)
				{
					CabHelper.RandomizeCabWithAnyLength(context.Parameters.Binary);
				}
			}
		}

		public static void DisableRandomizeCabIfConflict()
		{
			if (_enabledRandomizeCabIfConflict)
			{
				_enabledRandomizeCabIfConflict = false;
				if (_enableCabRandomizationPrefix != null)
				{
					UnregisterAssetBundleLoadingHook(_enableCabRandomizationPrefix);
					_enableCabRandomizationPrefix = null;
				}
				if (_enableCabRandomizationPrefixAsync != null)
				{
					UnregisterAsyncAssetBundleLoadingHook(_enableCabRandomizationPrefixAsync);
					_enableCabRandomizationPrefixAsync = null;
				}
				if (_enableCabRandomizationPostfix != null)
				{
					UnregisterAssetBundleLoadedHook(_enableCabRandomizationPostfix);
					_enableCabRandomizationPostfix = null;
				}
			}
		}

		public static void DisableRedirectMissingAssetBundlesToEmptyAssetBundle()
		{
			if (_redirectionMissingAssetBundlesToEmpty != null && _redirectionMissingAssetBundlesToEmptyAsync != null)
			{
				UnregisterAssetBundleLoadingHook(_redirectionMissingAssetBundlesToEmpty);
				UnregisterAsyncAssetBundleLoadingHook(_redirectionMissingAssetBundlesToEmptyAsync);
				_redirectionMissingAssetBundlesToEmpty = null;
				_redirectionMissingAssetBundlesToEmptyAsync = null;
			}
		}

		internal static bool TryGetAssetBundleLoadInfo(AssetBundleRequest request, out AsyncAssetLoadInfo result)
		{
			result = ExtensionDataHelper.GetExtensionData<AsyncAssetLoadInfo>((object)request);
			return result != null;
		}

		internal static bool TryGetAssetBundle(AssetBundleCreateRequest request, out AsyncAssetBundleLoadInfo result)
		{
			result = ExtensionDataHelper.GetExtensionData<AsyncAssetBundleLoadInfo>((object)request);
			return result != null;
		}

		internal static bool ShouldBlockAsyncOperationMethods(AssetBundleRequest operation)
		{
			if (TryGetAssetBundleLoadInfo(operation, out var result))
			{
				return result.ResolveType == AsyncAssetLoadingResolve.ThroughAssets;
			}
			return false;
		}

		internal static bool ShouldBlockAsyncOperationMethods(AssetBundleCreateRequest operation)
		{
			if (TryGetAssetBundle(operation, out var result))
			{
				return result.ResolveType == AsyncAssetBundleLoadingResolve.ThroughBundle;
			}
			return false;
		}

		internal static bool ShouldBlockAsyncOperationMethods(AsyncOperation operation)
		{
			if (SyncOverAsyncEnabled)
			{
				AssetBundleRequest operation2 = default(AssetBundleRequest);
				if (!ObjectExtensions.TryCastTo<AssetBundleRequest>((object)operation, ref operation2) || !ShouldBlockAsyncOperationMethods(operation2))
				{
					AssetBundleCreateRequest operation3 = default(AssetBundleCreateRequest);
					if (ObjectExtensions.TryCastTo<AssetBundleCreateRequest>((object)operation, ref operation3))
					{
						return ShouldBlockAsyncOperationMethods(operation3);
					}
					return false;
				}
				return true;
			}
			return false;
		}

		internal static AssetBundleLoadingContext Hook_AssetBundleLoading_Prefix(AssetBundleLoadingParameters parameters, out AssetBundle bundle)
		{
			AssetBundleLoadingContext assetBundleLoadingContext = new AssetBundleLoadingContext(parameters);
			if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled))
			{
				bundle = null;
				return assetBundleLoadingContext;
			}
			try
			{
				_isFiringAssetBundle = true;
				if (_logAllLoadedResources)
				{
					XuaLogger.ResourceRedirector.Debug("Loading Asset Bundle: (" + assetBundleLoadingContext.GetNormalizedPath() + ").");
				}
				List<PrioritizedCallback<Delegate>> prefixRedirectionsForAssetBundles = PrefixRedirectionsForAssetBundles;
				int count = prefixRedirectionsForAssetBundles.Count;
				for (int i = 0; i < count; i++)
				{
					PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAssetBundles[i];
					if (prioritizedCallback.IsBeingCalled)
					{
						continue;
					}
					try
					{
						prioritizedCallback.IsBeingCalled = true;
						if (prioritizedCallback.Callback is Action<AssetBundleLoadingContext> action)
						{
							action(assetBundleLoadingContext);
						}
						else if (prioritizedCallback.Callback is Action<IAssetBundleLoadingContext> action2)
						{
							action2(assetBundleLoadingContext);
						}
						if (assetBundleLoadingContext.SkipRemainingPrefixes)
						{
							break;
						}
					}
					catch (Exception ex)
					{
						XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoading event.");
					}
					finally
					{
						RecursionEnabled = true;
						prioritizedCallback.IsBeingCalled = false;
					}
				}
			}
			catch (Exception ex2)
			{
				XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetBundleLoading event.");
			}
			finally
			{
				_isFiringAssetBundle = false;
			}
			bundle = assetBundleLoadingContext.Bundle;
			return assetBundleLoadingContext;
		}

		internal static AssetBundleLoadedContext Hook_AssetBundleLoaded_Postfix(AssetBundleLoadingParameters parameters, ref AssetBundle bundle)
		{
			AssetBundleLoadedContext assetBundleLoadedContext = new AssetBundleLoadedContext(parameters, bundle);
			if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled))
			{
				bundle = null;
				return assetBundleLoadedContext;
			}
			try
			{
				_isFiringAssetBundle = true;
				List<PrioritizedCallback<Action<AssetBundleLoadedContext>>> postfixRedirectionsForAssetBundles = PostfixRedirectionsForAssetBundles;
				int count = postfixRedirectionsForAssetBundles.Count;
				for (int i = 0; i < count; i++)
				{
					PrioritizedCallback<Action<AssetBundleLoadedContext>> prioritizedCallback = postfixRedirectionsForAssetBundles[i];
					if (prioritizedCallback.IsBeingCalled)
					{
						continue;
					}
					try
					{
						prioritizedCallback.IsBeingCalled = true;
						prioritizedCallback.Callback(assetBundleLoadedContext);
						if (assetBundleLoadedContext.SkipRemainingPostfixes)
						{
							break;
						}
					}
					catch (Exception ex)
					{
						XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoaded event.");
					}
					finally
					{
						RecursionEnabled = true;
						prioritizedCallback.IsBeingCalled = false;
					}
				}
			}
			catch (Exception ex2)
			{
				XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetBundleLoaded event.");
			}
			finally
			{
				_isFiringAssetBundle = false;
			}
			bundle = assetBundleLoadedContext.Bundle;
			return assetBundleLoadedContext;
		}

		internal static AsyncAssetBundleLoadingContext Hook_AssetBundleLoading_Prefix(AssetBundleLoadingParameters parameters, out AssetBundleCreateRequest request)
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			AsyncAssetBundleLoadingContext asyncAssetBundleLoadingContext = new AsyncAssetBundleLoadingContext(parameters);
			if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled))
			{
				request = null;
				return asyncAssetBundleLoadingContext;
			}
			try
			{
				_isFiringAssetBundle = true;
				if (_logAllLoadedResources)
				{
					XuaLogger.ResourceRedirector.Debug("Loading Asset Bundle (async): (" + asyncAssetBundleLoadingContext.GetNormalizedPath() + ").");
				}
				List<PrioritizedCallback<Delegate>> prefixRedirectionsForAsyncAssetBundles = PrefixRedirectionsForAsyncAssetBundles;
				int count = prefixRedirectionsForAsyncAssetBundles.Count;
				for (int i = 0; i < count; i++)
				{
					PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAsyncAssetBundles[i];
					if (prioritizedCallback.IsBeingCalled)
					{
						continue;
					}
					try
					{
						prioritizedCallback.IsBeingCalled = true;
						if (prioritizedCallback.Callback is Action<AsyncAssetBundleLoadingContext> action)
						{
							action(asyncAssetBundleLoadingContext);
						}
						else if (prioritizedCallback.Callback is Action<IAssetBundleLoadingContext> action2)
						{
							action2(asyncAssetBundleLoadingContext);
						}
						if (asyncAssetBundleLoadingContext.SkipRemainingPrefixes)
						{
							break;
						}
					}
					catch (Exception ex)
					{
						XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoading event.");
					}
					finally
					{
						RecursionEnabled = true;
						prioritizedCallback.IsBeingCalled = false;
					}
				}
			}
			catch (Exception ex2)
			{
				XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AsyncAssetBundleLoading event.");
			}
			finally
			{
				_isFiringAssetBundle = false;
			}
			if (asyncAssetBundleLoadingContext.ResolveType == AsyncAssetBundleLoadingResolve.ThroughRequest)
			{
				request = asyncAssetBundleLoadingContext.Request;
			}
			else
			{
				if (asyncAssetBundleLoadingContext.ResolveType != AsyncAssetBundleLoadingResolve.ThroughBundle)
				{
					throw new InvalidOperationException("Found invalid ResolveType on context: " + asyncAssetBundleLoadingContext.ResolveType);
				}
				request = new AssetBundleCreateRequest();
				if (!asyncAssetBundleLoadingContext.SkipOriginalCall)
				{
					XuaLogger.ResourceRedirector.Warn("Resolving sync over async asset load, but 'SkipOriginalCall' was not set to true. Forcing it to true.");
					asyncAssetBundleLoadingContext.SkipOriginalCall = true;
				}
			}
			return asyncAssetBundleLoadingContext;
		}

		internal static void Hook_AssetBundleLoading_Postfix(AsyncAssetBundleLoadingContext context, AssetBundleCreateRequest request)
		{
			if (request != null)
			{
				ExtensionDataHelper.SetExtensionData<AsyncAssetBundleLoadInfo>((object)request, new AsyncAssetBundleLoadInfo(context.Parameters, context.Bundle, context.SkipAllPostfixes, context.ResolveType));
			}
		}

		internal static void Hook_AssetLoading_Postfix(AsyncAssetLoadingContext context, AssetBundleRequest request)
		{
			if (request != null)
			{
				ExtensionDataHelper.SetExtensionData<AsyncAssetLoadInfo>((object)request, new AsyncAssetLoadInfo(context.Parameters, context.Bundle, context.SkipAllPostfixes, context.ResolveType, context.Assets));
			}
		}

		internal static AssetLoadingContext Hook_AssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle parentBundle, ref Object asset)
		{
			Object[] assets = null;
			AssetLoadingContext result = Hook_AssetLoading_Prefix(parameters, parentBundle, ref assets);
			if (assets == null || assets.Length == 0)
			{
				asset = null;
				return result;
			}
			if (assets.Length > 1)
			{
				XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in AssetLoadeding event. Returned more than one asset to call requiring only a single asset.");
				asset = assets[0];
				return result;
			}
			if (assets.Length == 1)
			{
				asset = assets[0];
			}
			return result;
		}

		internal static AssetLoadingContext Hook_AssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle bundle, ref Object[] assets)
		{
			AssetLoadingContext assetLoadingContext = new AssetLoadingContext(parameters, bundle);
			try
			{
				if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled))
				{
					return assetLoadingContext;
				}
				_isFiringAsset = true;
				List<PrioritizedCallback<Delegate>> prefixRedirectionsForAssetsPerCall = PrefixRedirectionsForAssetsPerCall;
				int count = prefixRedirectionsForAssetsPerCall.Count;
				for (int i = 0; i < count; i++)
				{
					PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAssetsPerCall[i];
					if (prioritizedCallback.IsBeingCalled)
					{
						continue;
					}
					try
					{
						prioritizedCallback.IsBeingCalled = true;
						if (prioritizedCallback.Callback is Action<AssetLoadingContext> action)
						{
							action(assetLoadingContext);
						}
						else if (prioritizedCallback.Callback is Action<IAssetLoadingContext> action2)
						{
							action2(assetLoadingContext);
						}
						if (assetLoadingContext.SkipRemainingPrefixes)
						{
							break;
						}
					}
					catch (Exception ex)
					{
						XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetLoading event.");
					}
					finally
					{
						RecursionEnabled = true;
						prioritizedCallback.IsBeingCalled = false;
					}
				}
				assets = assetLoadingContext.Assets;
			}
			catch (Exception ex2)
			{
				XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetLoading event.");
			}
			finally
			{
				_isFiringAsset = false;
			}
			return assetLoadingContext;
		}

		internal static AsyncAssetLoadingContext Hook_AsyncAssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle bundle, ref AssetBundleRequest request)
		{
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			AsyncAssetLoadingContext asyncAssetLoadingContext = new AsyncAssetLoadingContext(parameters, bundle);
			try
			{
				if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled))
				{
					return asyncAssetLoadingContext;
				}
				_isFiringAsset = true;
				List<PrioritizedCallback<Delegate>> prefixRedirectionsForAsyncAssetsPerCall = PrefixRedirectionsForAsyncAssetsPerCall;
				int count = prefixRedirectionsForAsyncAssetsPerCall.Count;
				for (int i = 0; i < count; i++)
				{
					PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAsyncAssetsPerCall[i];
					if (prioritizedCallback.IsBeingCalled)
					{
						continue;
					}
					try
					{
						prioritizedCallback.IsBeingCalled = true;
						if (prioritizedCallback.Callback is Action<AsyncAssetLoadingContext> action)
						{
							action(asyncAssetLoadingContext);
						}
						else if (prioritizedCallback.Callback is Action<IAssetLoadingContext> action2)
						{
							action2(asyncAssetLoadingContext);
						}
						if (asyncAssetLoadingContext.SkipRemainingPrefixes)
						{
							break;
						}
					}
					catch (Exception ex)
					{
						XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AsyncAssetLoading event.");
					}
					finally
					{
						RecursionEnabled = true;
						prioritizedCallback.IsBeingCalled = false;
					}
				}
				if (asyncAssetLoadingContext.ResolveType == AsyncAssetLoadingResolve.ThroughRequest)
				{
					request = asyncAssetLoadingContext.Request;
				}
				else
				{
					if (asyncAssetLoadingContext.ResolveType != AsyncAssetLoadingResolve.ThroughAssets)
					{
						throw new InvalidOperationException("Found invalid ResolveType on context: " + asyncAssetLoadingContext.ResolveType);
					}
					request = new AssetBundleRequest();
					if (!asyncAssetLoadingContext.SkipOriginalCall)
					{
						XuaLogger.ResourceRedirector.Warn("Resolving sync over async asset load, but 'SkipOriginalCall' was not set to true. Forcing it to true.");
						asyncAssetLoadingContext.SkipOriginalCall = true;
					}
				}
			}
			catch (Exception ex2)
			{
				XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AsyncAssetLoading event.");
			}
			finally
			{
				_isFiringAsset = false;
			}
			return asyncAssetLoadingContext;
		}

		internal static void Hook_AssetLoaded_Postfix(AssetLoadingParameters parameters, AssetBundle parentBundle, ref Object asset)
		{
			Object[] assets = (Object[])(object)((!(asset == (Object)null)) ? new Object[1] { asset } : new Object[0]);
			Hook_AssetLoaded_Postfix(parameters, parentBundle, ref assets);
			if (assets == null || assets.Length == 0)
			{
				asset = null;
			}
			else if (assets.Length > 1)
			{
				XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in AssetLoaded event. Returned more than one asset to call requiring only a single asset.");
				asset = assets[0];
			}
			else if (assets.Length == 1)
			{
				asset = assets[0];
			}
		}

		internal static void Hook_AssetLoaded_Postfix(AssetLoadingParameters parameters, AssetBundle bundle, ref Object[] assets)
		{
			FireAssetLoadedEvent(parameters.ToAssetLoadedParameters(), bundle, ref assets);
		}

		internal static void Hook_ResourceLoaded_Postfix(ResourceLoadedParameters parameters, ref Object asset)
		{
			Object[] assets = (Object[])(object)((!(asset == (Object)null)) ? new Object[1] { asset } : new Object[0]);
			Hook_ResourceLoaded_Postfix(parameters, ref assets);
			if (assets == null || assets.Length == 0)
			{
				asset = null;
			}
			else if (assets.Length > 1)
			{
				XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in ResourceLoaded event. Returned more than one asset to call requiring only a single asset.");
				asset = assets[0];
			}
			else if (assets.Length == 1)
			{
				asset = assets[0];
			}
		}

		internal static void Hook_ResourceLoaded_Postfix(ResourceLoadedParameters parameters, ref Object[] assets)
		{
			FireResourceLoadedEvent(parameters, ref assets);
		}

		internal static void FireAssetLoadedEvent(AssetLoadedParameters parameters, AssetBundle assetBundle, ref Object[] assets)
		{
			Object[] array = assets?.ToArray();
			try
			{
				AssetLoadedContext assetLoadedContext = new AssetLoadedContext(parameters, assetBundle, assets);
				if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled))
				{
					return;
				}
				_isFiringAsset = true;
				if (_logAllLoadedResources && assets != null)
				{
					for (int i = 0; i < assets.Length; i++)
					{
						Object val = assets[i];
						if (val != (Object)null)
						{
							string uniqueFileSystemAssetPath = assetLoadedContext.GetUniqueFileSystemAssetPath(val);
							XuaLogger.ResourceRedirector.Debug("Loaded Asset: '" + ObjectExtensions.GetUnityType((object)val).FullName + "', Load Type: '" + parameters.LoadType.ToString() + "', Unique Path: (" + uniqueFileSystemAssetPath + ").");
						}
					}
				}
				List<PrioritizedCallback<Action<AssetLoadedContext>>> postfixRedirectionsForAssetsPerCall = PostfixRedirectionsForAssetsPerCall;
				int count = postfixRedirectionsForAssetsPerCall.Count;
				for (int j = 0; j < count; j++)
				{
					PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback = postfixRedirectionsForAssetsPerCall[j];
					if (prioritizedCallback.IsBeingCalled)
					{
						continue;
					}
					try
					{
						prioritizedCallback.IsBeingCalled = true;
						prioritizedCallback.Callback(assetLoadedContext);
						if (assetLoadedContext.SkipRemainingPostfixes)
						{
							break;
						}
					}
					catch (Exception ex)
					{
						XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetLoaded event.");
					}
					finally
					{
						RecursionEnabled = true;
						prioritizedCallback.IsBeingCalled = false;
					}
				}
				assets = assetLoadedContext.Assets;
				if (assetLoadedContext.SkipRemainingPostfixes || assets == null)
				{
					return;
				}
				int num = assets.Length;
				for (int k = 0; k < num; k++)
				{
					Object val2 = assets[k];
					if (val2 != (Object)null)
					{
						AssetLoadedContext assetLoadedContext2 = new AssetLoadedContext(parameters, assetBundle, val2);
						List<PrioritizedCallback<Action<AssetLoadedContext>>> postfixRedirectionsForAssetsPerResource = PostfixRedirectionsForAssetsPerResource;
						int count2 = postfixRedirectionsForAssetsPerResource.Count;
						for (int l = 0; l < count2; l++)
						{
							PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback2 = postfixRedirectionsForAssetsPerResource[l];
							if (prioritizedCallback2.IsBeingCalled)
							{
								continue;
							}
							try
							{
								prioritizedCallback2.IsBeingCalled = true;
								prioritizedCallback2.Callback(assetLoadedContext2);
								if (assetLoadedContext2.Asset != (Object)null)
								{
									assets[k] = assetLoadedContext2.Asset;
								}
								else
								{
									XuaLogger.ResourceRedirector.Warn($"Illegal behaviour by redirection handler in AssetLoaded event. You must not remove an asset reference when hooking with behaviour {HookBehaviour.OneCallbackPerResourceLoaded}.");
								}
								if (assetLoadedContext2.SkipRemainingPostfixes)
								{
									break;
								}
							}
							catch (Exception ex2)
							{
								XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetLoaded event.");
							}
							finally
							{
								RecursionEnabled = true;
								prioritizedCallback2.IsBeingCalled = false;
							}
						}
					}
					else
					{
						XuaLogger.ResourceRedirector.Error("Found unexpected null asset during AssetLoaded event.");
					}
				}
			}
			catch (Exception ex3)
			{
				XuaLogger.ResourceRedirector.Error(ex3, "An error occurred while invoking AssetLoaded event.");
			}
			finally
			{
				_isFiringAsset = false;
				if (array != null)
				{
					Object[] array2 = array;
					for (int m = 0; m < array2.Length; m++)
					{
						ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)array2[m]).HasBeenRedirected = true;
					}
				}
			}
		}

		internal static void FireResourceLoadedEvent(ResourceLoadedParameters parameters, ref Object[] assets)
		{
			Object[] array = assets?.ToArray();
			try
			{
				ResourceLoadedContext resourceLoadedContext = new ResourceLoadedContext(parameters, assets);
				if (_isFiringResource && (_isRecursionDisabledPermanently || !RecursionEnabled))
				{
					return;
				}
				_isFiringResource = true;
				if (_logAllLoadedResources && assets != null)
				{
					for (int i = 0; i < assets.Length; i++)
					{
						Object val = assets[i];
						if (val != (Object)null)
						{
							string uniqueFileSystemAssetPath = resourceLoadedContext.GetUniqueFileSystemAssetPath(val);
							XuaLogger.ResourceRedirector.Debug("Loaded Asset: '" + ObjectExtensions.GetUnityType((object)val).FullName + "', Load Type: '" + parameters.LoadType.ToString() + "', Unique Path: (" + uniqueFileSystemAssetPath + ").");
						}
					}
				}
				List<PrioritizedCallback<Action<ResourceLoadedContext>>> postfixRedirectionsForResourcesPerCall = PostfixRedirectionsForResourcesPerCall;
				int count = postfixRedirectionsForResourcesPerCall.Count;
				for (int j = 0; j < count; j++)
				{
					PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback = postfixRedirectionsForResourcesPerCall[j];
					if (prioritizedCallback.IsBeingCalled)
					{
						continue;
					}
					try
					{
						prioritizedCallback.IsBeingCalled = true;
						prioritizedCallback.Callback(resourceLoadedContext);
						if (resourceLoadedContext.SkipRemainingPostfixes)
						{
							break;
						}
					}
					catch (Exception ex)
					{
						XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking ResourceLoaded event.");
					}
					finally
					{
						RecursionEnabled = true;
						prioritizedCallback.IsBeingCalled = false;
					}
				}
				assets = resourceLoadedContext.Assets;
				if (resourceLoadedContext.SkipRemainingPostfixes || assets == null)
				{
					return;
				}
				int num = assets.Length;
				for (int k = 0; k < num; k++)
				{
					Object val2 = assets[k];
					if (val2 != (Object)null)
					{
						ResourceLoadedContext resourceLoadedContext2 = new ResourceLoadedContext(parameters, val2);
						List<PrioritizedCallback<Action<ResourceLoadedContext>>> postfixRedirectionsForResourcesPerResource = PostfixRedirectionsForResourcesPerResource;
						int count2 = postfixRedirectionsForResourcesPerResource.Count;
						for (int l = 0; l < count2; l++)
						{
							PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback2 = postfixRedirectionsForResourcesPerResource[l];
							if (prioritizedCallback2.IsBeingCalled)
							{
								continue;
							}
							try
							{
								prioritizedCallback2.IsBeingCalled = true;
								prioritizedCallback2.Callback(resourceLoadedContext2);
								if (resourceLoadedContext2.Asset != (Object)null)
								{
									assets[k] = resourceLoadedContext2.Asset;
								}
								else
								{
									XuaLogger.ResourceRedirector.Warn($"Illegal behaviour by redirection handler in ResourceLoaded event. You must not remove an asset reference when hooking with behaviour {HookBehaviour.OneCallbackPerResourceLoaded}.");
								}
								if (resourceLoadedContext2.SkipRemainingPostfixes)
								{
									break;
								}
							}
							catch (Exception ex2)
							{
								XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking ResourceLoaded event.");
							}
							finally
							{
								RecursionEnabled = true;
								prioritizedCallback2.IsBeingCalled = false;
							}
						}
					}
					else
					{
						XuaLogger.ResourceRedirector.Error("Found unexpected null asset during ResourceLoaded event.");
					}
				}
			}
			catch (Exception ex3)
			{
				XuaLogger.ResourceRedirector.Error(ex3, "An error occurred while invoking ResourceLoaded event.");
			}
			finally
			{
				_isFiringResource = false;
				if (array != null)
				{
					Object[] array2 = array;
					for (int m = 0; m < array2.Length; m++)
					{
						ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)array2[m]).HasBeenRedirected = true;
					}
				}
			}
		}

		private static void LogEventRegistration(string eventType, IEnumerable callbacks)
		{
			XuaLogger.ResourceRedirector.Debug("Registered new callback for " + eventType + ".");
			LogNewCallbackOrder(eventType, callbacks);
		}

		private static void LogEventUnregistration(string eventType, IEnumerable callbacks)
		{
			XuaLogger.ResourceRedirector.Debug("Unregistered callback for " + eventType + ".");
			LogNewCallbackOrder(eventType, callbacks);
		}

		private static void LogNewCallbackOrder(string eventType, IEnumerable callbacks)
		{
			if (!LogCallbackOrder)
			{
				return;
			}
			XuaLogger.ResourceRedirector.Debug("New callback order for " + eventType + ":");
			foreach (object callback in callbacks)
			{
				XuaLogger.ResourceRedirector.Debug(callback.ToString());
			}
		}

		public static void RegisterAssetBundleLoadedHook(int priority, Action<AssetBundleLoadedContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Action<AssetBundleLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority);
			if (PostfixRedirectionsForAssetBundles.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetBundleLoadedContext>>>(PostfixRedirectionsForAssetBundles, prioritizedCallback);
			LogEventRegistration("AssetBundleLoaded", PostfixRedirectionsForAssetBundles);
		}

		public static void RegisterAssetBundleLoadedHook(Action<AssetBundleLoadedContext> action)
		{
			RegisterAssetBundleLoadedHook(0, action);
		}

		public static void UnregisterAssetBundleLoadedHook(Action<AssetBundleLoadedContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PostfixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Action<AssetBundleLoadedContext>> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AssetBundleLoaded", PostfixRedirectionsForAssetBundles);
		}

		public static void RegisterAssetLoadingHook(int priority, Action<AssetLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority);
			if (PrefixRedirectionsForAssetsPerCall.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetsPerCall, prioritizedCallback);
			LogEventRegistration("AssetLoading", PrefixRedirectionsForAssetsPerCall);
		}

		public static void RegisterAssetLoadingHook(Action<AssetLoadingContext> action)
		{
			RegisterAssetLoadingHook(0, action);
		}

		public static void UnregisterAssetLoadingHook(Action<AssetLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrefixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AssetLoading", PrefixRedirectionsForAssetsPerCall);
		}

		public static void RegisterAsyncAssetLoadingHook(int priority, Action<AsyncAssetLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority);
			if (PrefixRedirectionsForAsyncAssetsPerCall.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetsPerCall, prioritizedCallback);
			LogEventRegistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall);
		}

		public static void RegisterAsyncAssetLoadingHook(Action<AsyncAssetLoadingContext> action)
		{
			RegisterAsyncAssetLoadingHook(0, action);
		}

		public static void UnregisterAsyncAssetLoadingHook(Action<AsyncAssetLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrefixRedirectionsForAsyncAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall);
		}

		public static void RegisterAsyncAndSyncAssetLoadingHook(int priority, Action<IAssetLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority);
			if (PrefixRedirectionsForAsyncAssetsPerCall.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetsPerCall, prioritizedCallback);
			LogEventRegistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall);
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetsPerCall, prioritizedCallback);
			LogEventRegistration("AssetLoading", PrefixRedirectionsForAssetsPerCall);
		}

		public static void RegisterAsyncAndSyncAssetLoadingHook(Action<IAssetLoadingContext> action)
		{
			RegisterAsyncAndSyncAssetLoadingHook(0, action);
		}

		public static void UnregisterAsyncAndSyncAssetLoadingHook(Action<IAssetLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrefixRedirectionsForAsyncAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall);
			PrefixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AssetLoading", PrefixRedirectionsForAssetsPerCall);
		}

		public static void RegisterAssetLoadedHook(HookBehaviour behaviour, int priority, Action<AssetLoadedContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority);
			if (PostfixRedirectionsForAssetsPerCall.Contains(prioritizedCallback) || PostfixRedirectionsForAssetsPerResource.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			switch (behaviour)
			{
			case HookBehaviour.OneCallbackPerLoadCall:
				ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetLoadedContext>>>(PostfixRedirectionsForAssetsPerCall, prioritizedCallback);
				LogEventRegistration("AssetLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForAssetsPerCall);
				break;
			case HookBehaviour.OneCallbackPerResourceLoaded:
				ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetLoadedContext>>>(PostfixRedirectionsForAssetsPerResource, prioritizedCallback);
				LogEventRegistration("AssetLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForAssetsPerResource);
				break;
			}
		}

		public static void RegisterAssetLoadedHook(HookBehaviour behaviour, Action<AssetLoadedContext> action)
		{
			RegisterAssetLoadedHook(behaviour, 0, action);
		}

		public static void UnregisterAssetLoadedHook(Action<AssetLoadedContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (PostfixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Action<AssetLoadedContext>> x) => x.Callback == action) > 0)
			{
				LogEventRegistration("AssetLoaded (" + HookBehaviour.OneCallbackPerLoadCall.ToString() + ")", PostfixRedirectionsForAssetsPerCall);
			}
			if (PostfixRedirectionsForAssetsPerResource.RemoveAll((PrioritizedCallback<Action<AssetLoadedContext>> x) => x.Callback == action) > 0)
			{
				LogEventRegistration("AssetLoaded (" + HookBehaviour.OneCallbackPerResourceLoaded.ToString() + ")", PostfixRedirectionsForAssetsPerResource);
			}
		}

		public static void RegisterAssetBundleLoadingHook(int priority, Action<AssetBundleLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority);
			if (PrefixRedirectionsForAssetBundles.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetBundles, prioritizedCallback);
			LogEventRegistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles);
		}

		public static void RegisterAssetBundleLoadingHook(Action<AssetBundleLoadingContext> action)
		{
			RegisterAssetBundleLoadingHook(0, action);
		}

		public static void UnregisterAssetBundleLoadingHook(Action<AssetBundleLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrefixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles);
		}

		public static void RegisterAsyncAssetBundleLoadingHook(int priority, Action<AsyncAssetBundleLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority);
			if (PrefixRedirectionsForAsyncAssetBundles.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetBundles, prioritizedCallback);
			LogEventRegistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles);
		}

		public static void RegisterAsyncAssetBundleLoadingHook(Action<AsyncAssetBundleLoadingContext> action)
		{
			RegisterAsyncAssetBundleLoadingHook(0, action);
		}

		public static void UnregisterAsyncAssetBundleLoadingHook(Action<AsyncAssetBundleLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrefixRedirectionsForAsyncAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles);
		}

		public static void RegisterAsyncAndSyncAssetBundleLoadingHook(int priority, Action<IAssetBundleLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority);
			if (PrefixRedirectionsForAssetBundles.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetBundles, prioritizedCallback);
			LogEventRegistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles);
			ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetBundles, prioritizedCallback);
			LogEventRegistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles);
		}

		public static void RegisterAsyncAndSyncAssetBundleLoadingHook(Action<IAssetBundleLoadingContext> action)
		{
			RegisterAsyncAndSyncAssetBundleLoadingHook(0, action);
		}

		public static void UnregisterAsyncAndSyncAssetBundleLoadingHook(Action<IAssetBundleLoadingContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrefixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles);
			PrefixRedirectionsForAsyncAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action));
			LogEventUnregistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles);
		}

		public static void RegisterResourceLoadedHook(HookBehaviour behaviour, int priority, Action<ResourceLoadedContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority);
			if (PostfixRedirectionsForResourcesPerCall.Contains(prioritizedCallback) || PostfixRedirectionsForResourcesPerResource.Contains(prioritizedCallback))
			{
				throw new ArgumentException("This callback has already been registered.", "action");
			}
			Initialize();
			switch (behaviour)
			{
			case HookBehaviour.OneCallbackPerLoadCall:
				ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<ResourceLoadedContext>>>(PostfixRedirectionsForResourcesPerCall, prioritizedCallback);
				LogEventRegistration("ResourceLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForResourcesPerCall);
				break;
			case HookBehaviour.OneCallbackPerResourceLoaded:
				ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<ResourceLoadedContext>>>(PostfixRedirectionsForResourcesPerResource, prioritizedCallback);
				LogEventRegistration("ResourceLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForResourcesPerResource);
				break;
			}
		}

		public static void RegisterResourceLoadedHook(HookBehaviour behaviour, Action<ResourceLoadedContext> action)
		{
			RegisterResourceLoadedHook(behaviour, 0, action);
		}

		public static void UnregisterResourceLoadedHook(Action<ResourceLoadedContext> action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (PostfixRedirectionsForResourcesPerCall.RemoveAll((PrioritizedCallback<Action<ResourceLoadedContext>> x) => x.Callback == action) > 0)
			{
				LogEventRegistration("ResourceLoaded (" + HookBehaviour.OneCallbackPerLoadCall.ToString() + ")", PostfixRedirectionsForResourcesPerCall);
			}
			if (PostfixRedirectionsForResourcesPerResource.RemoveAll((PrioritizedCallback<Action<ResourceLoadedContext>> x) => x.Callback == action) > 0)
			{
				LogEventRegistration("ResourceLoaded (" + HookBehaviour.OneCallbackPerResourceLoaded.ToString() + ")", PostfixRedirectionsForResourcesPerResource);
			}
		}
	}
}
namespace XUnity.ResourceRedirector.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					resourceMan = new ResourceManager("XUnity.ResourceRedirector.Properties.Resources", typeof(Resources).Assembly);
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] empty => (byte[])ResourceManager.GetObject("empty", resourceCulture);

		internal Resources()
		{
		}
	}
}
namespace XUnity.ResourceRedirector.Hooks
{
	internal static class ResourceAndAssetHooks
	{
		public static readonly Type[] GeneralHooks = new Type[21]
		{
			typeof(AssetBundle_LoadFromFileAsync_Hook),
			typeof(AssetBundle_LoadFromFile_Hook),
			typeof(AssetBundle_LoadFromMemoryAsync_Hook),
			typeof(AssetBundle_LoadFromMemory_Hook),
			typeof(AssetBundle_LoadFromStreamAsync_Hook),
			typeof(AssetBundle_LoadFromStream_Hook),
			typeof(AssetBundle_mainAsset_Hook),
			typeof(AssetBundle_returnMainAsset_Hook),
			typeof(AssetBundle_Load_Hook),
			typeof(AssetBundle_LoadAsync_Hook),
			typeof(AssetBundle_LoadAll_Hook),
			typeof(AssetBundle_LoadAsset_Internal_Hook),
			typeof(AssetBundle_LoadAssetAsync_Internal_Hook),
			typeof(AssetBundle_LoadAssetWithSubAssets_Internal_Hook),
			typeof(AssetBundle_LoadAssetWithSubAssetsAsync_Internal_Hook),
			typeof(AssetBundleRequest_asset_Hook),
			typeof(AssetBundleRequest_allAssets_Hook),
			typeof(Resources_Load_Hook),
			typeof(Resources_LoadAll_Hook),
			typeof(Resources_GetBuiltinResource_Old_Hook),
			typeof(Resources_GetBuiltinResource_New_Hook)
		};

		public static readonly Type[] SyncOverAsyncHooks = new Type[10]
		{
			typeof(AssetBundleCreateRequest_assetBundle_Hook),
			typeof(AssetBundleCreateRequest_DisableCompatibilityChecks_Hook),
			typeof(AssetBundleCreateRequest_SetEnableCompatibilityChecks_Hook),
			typeof(AsyncOperation_isDone_Hook),
			typeof(AsyncOperation_progress_Hook),
			typeof(AsyncOperation_priority_Hook),
			typeof(AsyncOperation_set_priority_Hook),
			typeof(AsyncOperation_allowSceneActivation_Hook),
			typeof(AsyncOperation_set_allowSceneActivation_Hook),
			typeof(AsyncOperation_Finalize_Hook)
		};
	}
	internal static class AssetBundleCreateRequest_assetBundle_Hook
	{
		private delegate AssetBundle OriginalMethod(AssetBundleCreateRequest __instance);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			return UnityTypes.AssetBundleCreateRequest != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest;
			return AccessToolsShim.Property((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "assetBundle")?.GetGetMethod();
		}

		private static bool Prefix(AssetBundleCreateRequest __instance, ref AssetBundle __result, ref AsyncAssetBundleLoadInfo __state)
		{
			if (ResourceRedirection.TryGetAssetBundle(__instance, out __state))
			{
				if (__state.ResolveType == AsyncAssetBundleLoadingResolve.ThroughBundle)
				{
					__result = __state.Bundle;
					return false;
				}
				return true;
			}
			return true;
		}

		private static void Postfix(ref AssetBundle __result, ref AsyncAssetBundleLoadInfo __state)
		{
			if (__state == null)
			{
				return;
			}
			if (!__state.SkipAllPostfixes)
			{
				ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result);
			}
			if ((Object)(object)__result != (Object)null && __state != null)
			{
				string path = __state.Parameters.Path;
				if (path != null)
				{
					ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = path;
				}
			}
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static AssetBundle MM_Detour(AssetBundleCreateRequest __instance)
		{
			AssetBundle __result = null;
			AsyncAssetBundleLoadInfo __state = null;
			if (Prefix(__instance, ref __result, ref __state))
			{
				__result = _original(__instance);
			}
			Postfix(ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundleCreateRequest_DisableCompatibilityChecks_Hook
	{
		private delegate void OriginalMethod(AssetBundleCreateRequest __instance);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest;
			return (object)AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }) == null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest;
			return AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "DisableCompatibilityChecks", new Type[0]);
		}

		private static bool Prefix(AssetBundleCreateRequest __instance)
		{
			return !ResourceRedirection.ShouldBlockAsyncOperationMethods(__instance);
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static void MM_Detour(AssetBundleCreateRequest __instance)
		{
			if (Prefix(__instance))
			{
				_original(__instance);
			}
		}
	}
	internal static class AssetBundleCreateRequest_SetEnableCompatibilityChecks_Hook
	{
		private delegate void OriginalMethod(AssetBundleCreateRequest __instance, bool set);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest;
			return (object)AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }) != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest;
			return AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) });
		}

		private static bool Prefix(AssetBundleCreateRequest __instance, bool set)
		{
			return !ResourceRedirection.ShouldBlockAsyncOperationMethods(__instance);
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static void MM_Detour(AssetBundleCreateRequest __instance, bool set)
		{
			if (Prefix(__instance, set))
			{
				_original(__instance, set);
			}
		}
	}
	internal static class AssetBundle_LoadFromFileAsync_Hook
	{
		private delegate AssetBundleCreateRequest OriginalMethod(string path, uint crc, ulong offset);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			return UnityTypes.AssetBundle != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromFileAsync_Internal", new Type[3]
			{
				typeof(string),
				typeof(uint),
				typeof(ulong)
			});
			if ((object)methodInfo == null)
			{
				TypeContainer assetBundle2 = UnityTypes.AssetBundle;
				methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromFileAsync", new Type[3]
				{
					typeof(string),
					typeof(uint),
					typeof(ulong)
				});
			}
			return methodInfo;
		}

		private static bool Prefix(ref string path, ref uint crc, ref ulong offset, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state)
		{
			AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, path, crc, offset, null, 0u, AssetBundleLoadType.LoadFromFile);
			__state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result);
			AssetBundleLoadingParameters parameters2 = __state.Parameters;
			path = parameters2.Path;
			crc = parameters2.Crc;
			offset = parameters2.Offset;
			return !__state.SkipOriginalCall;
		}

		private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state)
		{
			ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result);
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static AssetBundleCreateRequest MM_Detour(string path, uint crc, ulong offset)
		{
			AssetBundleCreateRequest __result = null;
			AsyncAssetBundleLoadingContext __state = null;
			if (Prefix(ref path, ref crc, ref offset, ref __result, ref __state))
			{
				__result = _original(path, crc, offset);
			}
			Postfix(ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundle_LoadFromFile_Hook
	{
		private delegate AssetBundle OriginalMethod(string path, uint crc, ulong offset);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			return UnityTypes.AssetBundle != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromFile_Internal", new Type[3]
			{
				typeof(string),
				typeof(uint),
				typeof(ulong)
			});
			if ((object)methodInfo == null)
			{
				TypeContainer assetBundle2 = UnityTypes.AssetBundle;
				methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromFile", new Type[3]
				{
					typeof(string),
					typeof(uint),
					typeof(ulong)
				});
			}
			return methodInfo;
		}

		private static bool Prefix(ref string path, ref uint crc, ref ulong offset, ref AssetBundle __result, ref AssetBundleLoadingContext __state)
		{
			AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, path, crc, offset, null, 0u, AssetBundleLoadType.LoadFromFile);
			__state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result);
			AssetBundleLoadingParameters parameters2 = __state.Parameters;
			path = parameters2.Path;
			crc = parameters2.Crc;
			offset = parameters2.Offset;
			return !__state.SkipOriginalCall;
		}

		private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state)
		{
			if (!__state.SkipAllPostfixes)
			{
				ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result);
			}
			if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null)
			{
				ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path;
			}
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static AssetBundle MM_Detour(string path, uint crc, ulong offset)
		{
			AssetBundle __result = null;
			AssetBundleLoadingContext __state = null;
			if (Prefix(ref path, ref crc, ref offset, ref __result, ref __state))
			{
				__result = _original(path, crc, offset);
			}
			Postfix(ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundle_LoadFromMemoryAsync_Hook
	{
		private delegate AssetBundleCreateRequest OriginalMethod(byte[] binary, uint crc);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			return UnityTypes.AssetBundle != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromMemoryAsync_Internal", new Type[2]
			{
				typeof(byte[]),
				typeof(uint)
			});
			if ((object)methodInfo == null)
			{
				TypeContainer assetBundle2 = UnityTypes.AssetBundle;
				methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromMemoryAsync", new Type[2]
				{
					typeof(byte[]),
					typeof(uint)
				});
			}
			return methodInfo;
		}

		private static bool Prefix(ref byte[] binary, ref uint crc, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state)
		{
			AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(binary, null, crc, 0uL, null, 0u, AssetBundleLoadType.LoadFromMemory);
			__state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result);
			AssetBundleLoadingParameters parameters2 = __state.Parameters;
			binary = parameters2.Binary;
			crc = parameters2.Crc;
			return !__state.SkipOriginalCall;
		}

		private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state)
		{
			ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result);
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static AssetBundleCreateRequest MM_Detour(byte[] binary, uint crc)
		{
			AssetBundleCreateRequest __result = null;
			AsyncAssetBundleLoadingContext __state = null;
			if (Prefix(ref binary, ref crc, ref __result, ref __state))
			{
				__result = _original(binary, crc);
			}
			Postfix(ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundle_LoadFromMemory_Hook
	{
		private delegate AssetBundle OriginalMethod(byte[] binary, uint crc);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			return UnityTypes.AssetBundle != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromMemory_Internal", new Type[2]
			{
				typeof(byte[]),
				typeof(uint)
			});
			if ((object)methodInfo == null)
			{
				TypeContainer assetBundle2 = UnityTypes.AssetBundle;
				methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromMemory", new Type[2]
				{
					typeof(byte[]),
					typeof(uint)
				});
			}
			return methodInfo;
		}

		private static bool Prefix(ref byte[] binary, ref uint crc, ref AssetBundle __result, ref AssetBundleLoadingContext __state)
		{
			AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(binary, null, crc, 0uL, null, 0u, AssetBundleLoadType.LoadFromMemory);
			__state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result);
			AssetBundleLoadingParameters parameters2 = __state.Parameters;
			binary = parameters2.Binary;
			crc = parameters2.Crc;
			return !__state.SkipOriginalCall;
		}

		private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state)
		{
			if (!__state.SkipAllPostfixes)
			{
				ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result);
			}
			if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null)
			{
				ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path;
			}
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static AssetBundle MM_Detour(byte[] binary, uint crc)
		{
			AssetBundle __result = null;
			AssetBundleLoadingContext __state = null;
			if (Prefix(ref binary, ref crc, ref __result, ref __state))
			{
				__result = _original(binary, crc);
			}
			Postfix(ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundle_LoadFromStreamAsync_Hook
	{
		private delegate AssetBundleCreateRequest OriginalMethod(Stream stream, uint crc, uint managedReadBufferSize);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			return UnityTypes.AssetBundle != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromStreamAsyncInternal", new Type[3]
			{
				typeof(Stream),
				typeof(uint),
				typeof(uint)
			});
			if ((object)methodInfo == null)
			{
				TypeContainer assetBundle2 = UnityTypes.AssetBundle;
				methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromStreamAsync", new Type[3]
				{
					typeof(Stream),
					typeof(uint),
					typeof(uint)
				});
			}
			return methodInfo;
		}

		private static bool Prefix(ref Stream stream, ref uint crc, ref uint managedReadBufferSize, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state)
		{
			AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, null, crc, 0uL, stream, managedReadBufferSize, AssetBundleLoadType.LoadFromMemory);
			__state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result);
			AssetBundleLoadingParameters parameters2 = __state.Parameters;
			stream = parameters2.Stream;
			crc = parameters2.Crc;
			managedReadBufferSize = parameters2.ManagedReadBufferSize;
			return !__state.SkipOriginalCall;
		}

		private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state)
		{
			ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result);
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static AssetBundleCreateRequest MM_Detour(Stream stream, uint crc, uint managedReadBufferSize)
		{
			AssetBundleCreateRequest __result = null;
			AsyncAssetBundleLoadingContext __state = null;
			if (Prefix(ref stream, ref crc, ref managedReadBufferSize, ref __result, ref __state))
			{
				__result = _original(stream, crc, managedReadBufferSize);
			}
			Postfix(ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundle_LoadFromStream_Hook
	{
		private delegate AssetBundle OriginalMethod(Stream stream, uint crc, uint managedReadBufferSize);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			return UnityTypes.AssetBundle != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromStreamInternal", new Type[3]
			{
				typeof(Stream),
				typeof(uint),
				typeof(uint)
			});
			if ((object)methodInfo == null)
			{
				TypeContainer assetBundle2 = UnityTypes.AssetBundle;
				methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromStream", new Type[3]
				{
					typeof(Stream),
					typeof(uint),
					typeof(uint)
				});
			}
			return methodInfo;
		}

		private static bool Prefix(ref Stream stream, ref uint crc, ref uint managedReadBufferSize, ref AssetBundle __result, ref AssetBundleLoadingContext __state)
		{
			AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, null, crc, 0uL, stream, managedReadBufferSize, AssetBundleLoadType.LoadFromMemory);
			__state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result);
			AssetBundleLoadingParameters parameters2 = __state.Parameters;
			stream = parameters2.Stream;
			crc = parameters2.Crc;
			managedReadBufferSize = parameters2.ManagedReadBufferSize;
			return !__state.SkipOriginalCall;
		}

		private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state)
		{
			if (!__state.SkipAllPostfixes)
			{
				ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result);
			}
			if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null)
			{
				ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path;
			}
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static AssetBundle MM_Detour(Stream stream, uint crc, uint managedReadBufferSize)
		{
			AssetBundle __result = null;
			AssetBundleLoadingContext __state = null;
			if (Prefix(ref stream, ref crc, ref managedReadBufferSize, ref __result, ref __state))
			{
				__result = _original(stream, crc, managedReadBufferSize);
			}
			Postfix(ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundle_mainAsset_Hook
	{
		private delegate Object OriginalMethod(AssetBundle __instance);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			return (object)AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "returnMainAsset", new Type[1] { typeof(AssetBundle) }) == null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			return AccessToolsShim.Property((assetBundle != null) ? assetBundle.ClrType : null, "mainAsset")?.GetGetMethod();
		}

		private static bool Prefix(AssetBundle __instance, ref Object __result, ref AssetLoadingContext __state)
		{
			AssetLoadingParameters parameters = new AssetLoadingParameters(null, null, AssetLoadType.LoadMainAsset);
			__state = ResourceRedirection.Hook_AssetLoading_Prefix(parameters, __instance, ref __result);
			return !__state.SkipOriginalCall;
		}

		private static void Postfix(AssetBundle __instance, ref Object __result, ref AssetLoadingContext __state)
		{
			if (!__state.SkipAllPostfixes)
			{
				ResourceRedirection.Hook_AssetLoaded_Postfix(__state.Parameters, __instance, ref __result);
			}
		}

		private static void MM_Init(object detour)
		{
			_original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour);
		}

		private static Object MM_Detour(AssetBundle __instance)
		{
			Object __result = null;
			AssetLoadingContext __state = null;
			if (Prefix(__instance, ref __result, ref __state))
			{
				__result = _original(__instance);
			}
			Postfix(__instance, ref __result, ref __state);
			return __result;
		}
	}
	internal static class AssetBundle_returnMainAsset_Hook
	{
		private delegate Object OriginalMethod(AssetBundle __instance);

		private static OriginalMethod _original;

		private static bool Prepare(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			return (object)AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "returnMainAsset", new Type[1] { typeof(AssetBundle) }) != null;
		}

		private static MethodBase TargetMethod(object instance)
		{
			TypeContainer assetBundle = UnityTypes.AssetBundle;
			return AccessToolsShim.Method((assetBundle != null) ? assetBu