Decompiled source of SuperQoLity v1.0.20

BepInEx/plugins/es.damntry.SuperQoLity/Damntry.Globals.BepInEx.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Damntry.Utils.Events;
using Damntry.Utils.ExtensionMethods;
using Damntry.Utils.Logging;
using Damntry.Utils.Reflection;
using Damntry.UtilsBepInEx.Configuration;
using Damntry.UtilsBepInEx.Configuration.ConfigurationManager;
using Damntry.UtilsBepInEx.Configuration.ConfigurationManager.Patch;
using Damntry.UtilsBepInEx.Configuration.ConfigurationManager.SettingAttributes;
using Damntry.UtilsBepInEx.HarmonyPatching.Attributes;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.Attributes;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.BaseClasses;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.Interfaces;
using Damntry.UtilsBepInEx.HarmonyPatching.Exceptions;
using Damntry.UtilsUnity.Components.InputManagement;
using Damntry.UtilsUnity.Components.InputManagement.Model;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.Utils;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Damntry BepInEx Globals")]
[assembly: AssemblyDescription("Utils usable in any type of BepInEx project")]
[assembly: AssemblyCompany("Damntry")]
[assembly: AssemblyProduct("Damntry BepInEx Globals")]
[assembly: AssemblyCopyright("Copyright © Damntry 2026")]
[assembly: AssemblyFileVersion("0.6.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("0.6.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class ParamCollectionAttribute : 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 Damntry.UtilsBepInEx.ModHelpers
{
	public abstract class ExternalModHelper
	{
		protected enum ModLoadStatus
		{
			NotLoaded,
			DifferentVersion,
			LoadedOk
		}

		protected ModLoadStatus ModStatus { get; private set; }

		protected PluginInfo ModPluginInfo { get; private set; }

		public bool IsModLoadedAndEnabled => ModStatus != ModLoadStatus.NotLoaded;

		public ModInfoData ModInfo { get; private set; }

		private ExternalModHelper()
		{
		}

		public ExternalModHelper(string GUID, string modName, Version supportedVersion)
		{
			checkArgsForErrors(GUID, modName, supportedVersion);
			Init(GUID, modName, supportedVersion);
		}

		public ExternalModHelper(string GUID, string modName, string supportedVersion)
		{
			checkArgsForErrors(GUID, modName, supportedVersion, out var parsedSupportedVersion);
			Init(GUID, modName, parsedSupportedVersion);
		}

		private void checkArgsForErrors(string GUID, string modName, string supportedVersion, out Version parsedSupportedVersion)
		{
			if (supportedVersion == null)
			{
				throw new ArgumentNullException("supportedVersion");
			}
			if (!Version.TryParse(supportedVersion, out parsedSupportedVersion))
			{
				throw new ArgumentException("The arg supportedVersion doesnt have a valid Version format.");
			}
			checkArgsForErrors(GUID, modName, parsedSupportedVersion);
		}

		private void checkArgsForErrors(string GUID, string modName, Version supportedVersion)
		{
			if (GUID == null)
			{
				throw new ArgumentNullException("GUID");
			}
			if (modName == null)
			{
				throw new ArgumentNullException("modName");
			}
			if (supportedVersion == null)
			{
				throw new ArgumentNullException("supportedVersion");
			}
		}

		private void Init(string GUID, string modName, Version supportedVersion)
		{
			ModInfo = new ModInfoData(GUID, modName, supportedVersion);
			ModStatus = IsModLoaded();
		}

		protected virtual ModLoadStatus IsModLoaded()
		{
			PluginInfo value;
			bool num = Chainloader.PluginInfos.TryGetValue(ModInfo.GUID, out value);
			ModPluginInfo = value;
			if (num)
			{
				ModInfo.LoadedVersion = ModPluginInfo.Metadata.Version;
				if (ModInfo.LoadedVersion != ModInfo.SupportedVersion)
				{
					return ModLoadStatus.DifferentVersion;
				}
				return ModLoadStatus.LoadedOk;
			}
			return ModLoadStatus.NotLoaded;
		}

		protected bool GetConfigValue<T>(string configKey, out T value)
		{
			return ConfigMethods.GetExternalConfigValue<T>(ModInfo.GUID, configKey, out value);
		}
	}
	public class ModInfoData
	{
		public string GUID { get; internal set; }

		public string Name { get; internal set; }

		public Version SupportedVersion { get; internal set; }

		public Version LoadedVersion { get; internal set; }

		internal ModInfoData(string GUID, string modName, Version SupportedVersion)
		{
			this.GUID = GUID;
			Name = modName;
			this.SupportedVersion = SupportedVersion;
		}

		public ModInfoData(ModInfoData modInfo)
		{
			GUID = modInfo.GUID;
			Name = modInfo.Name;
			SupportedVersion = modInfo.SupportedVersion;
			LoadedVersion = modInfo.LoadedVersion;
		}
	}
}
namespace Damntry.UtilsBepInEx.Logging
{
	public sealed class BepInExTimeLogger : TimeLogger
	{
		private static ManualLogSource bepinexLogger;

		protected override void InitializeLogger(params object[] args)
		{
			if (args == null)
			{
				throw new ArgumentNullException("args");
			}
			if (args.Length == 0 || !(args[0] is string))
			{
				throw new ArgumentException("The argument is empty or its first index is not a string");
			}
			bepinexLogger = Logger.CreateLogSource((string)args[0]);
		}

		protected override void LogMessage(string message, LogTier logLevel)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			bepinexLogger.Log(convertLogLevel(logLevel), (object)message);
		}

		private LogLevel convertLogLevel(LogTier logLevel)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if ((int)logLevel == -1)
			{
				return (LogLevel)63;
			}
			return (LogLevel)logLevel;
		}
	}
}
namespace Damntry.UtilsBepInEx.IL
{
	public static class ILExtensionMethods
	{
		public static int LocalIndex(this CodeInstruction code)
		{
			if (code.opcode == OpCodes.Ldloc_0 || code.opcode == OpCodes.Stloc_0)
			{
				return 0;
			}
			if (code.opcode == OpCodes.Ldloc_1 || code.opcode == OpCodes.Stloc_1)
			{
				return 1;
			}
			if (code.opcode == OpCodes.Ldloc_2 || code.opcode == OpCodes.Stloc_2)
			{
				return 2;
			}
			if (code.opcode == OpCodes.Ldloc_3 || code.opcode == OpCodes.Stloc_3)
			{
				return 3;
			}
			if (code.opcode == OpCodes.Ldloc_S || code.opcode == OpCodes.Ldloc)
			{
				return GetLocalOperandIndex(code.operand);
			}
			if (code.opcode == OpCodes.Stloc_S || code.opcode == OpCodes.Stloc)
			{
				return GetLocalOperandIndex(code.operand);
			}
			if (code.opcode == OpCodes.Ldloca_S || code.opcode == OpCodes.Ldloca)
			{
				return GetLocalOperandIndex(code.operand);
			}
			throw new ArgumentException("Instruction is not a load or store", "code");
		}

		private static int GetLocalOperandIndex(object operand)
		{
			if (operand.GetType() == typeof(LocalBuilder))
			{
				return ((LocalBuilder)operand).LocalIndex;
			}
			return Convert.ToInt32(operand);
		}

		public static int ArgumentIndex(this CodeInstruction code)
		{
			if (code.opcode == OpCodes.Ldarg_0)
			{
				return 0;
			}
			if (code.opcode == OpCodes.Ldarg_1)
			{
				return 1;
			}
			if (code.opcode == OpCodes.Ldarg_2)
			{
				return 2;
			}
			if (code.opcode == OpCodes.Ldarg_3)
			{
				return 3;
			}
			if (code.opcode == OpCodes.Ldarg_S || code.opcode == OpCodes.Ldarg)
			{
				return Convert.ToInt32(code.operand);
			}
			if (code.opcode == OpCodes.Starg_S || code.opcode == OpCodes.Starg)
			{
				return Convert.ToInt32(code.operand);
			}
			if (code.opcode == OpCodes.Ldarga_S || code.opcode == OpCodes.Ldarga)
			{
				return Convert.ToInt32(code.operand);
			}
			throw new ArgumentException("Instruction is not a load or store", "code");
		}

		public static string GetFormattedIL(this IEnumerable<CodeInstruction> instrList)
		{
			return instrList.Aggregate("", (string combinedText, CodeInstruction instr) => combinedText + "\n" + GetFormattedILSingleLine(instr));
		}

		private static string GetFormattedILSingleLine(CodeInstruction instruction)
		{
			string text = FormatArgument(instruction.operand);
			string text2 = ((text.Length > 0) ? " " : "");
			string text3 = instruction.opcode.ToString();
			if (instruction.opcode.FlowControl == FlowControl.Branch || instruction.opcode.FlowControl == FlowControl.Cond_Branch)
			{
				text3 += " =>";
			}
			text3 = text3.PadRight(10);
			return $"{CodePos(instruction)}{text3}{text2}{text}";
		}

		private static string CodePos(CodeInstruction instruction)
		{
			return "";
		}

		private static string FormatArgument(object argument, string extra = null)
		{
			if (argument == null)
			{
				return "";
			}
			Type type = argument.GetType();
			if (argument is MethodBase methodBase)
			{
				return GeneralExtensions.FullDescription(methodBase) + ((extra != null) ? (" " + extra) : "");
			}
			if (argument is FieldInfo fieldInfo)
			{
				return GeneralExtensions.FullDescription(fieldInfo.FieldType) + " " + GeneralExtensions.FullDescription(fieldInfo.DeclaringType) + "::" + fieldInfo.Name;
			}
			if (type == typeof(Label))
			{
				return $"Label{((Label)argument).GetHashCode()}";
			}
			if (type == typeof(Label[]))
			{
				return "Labels" + string.Join(",", ((Label[])argument).Select((Label l) => l.GetHashCode().ToString()).ToArray());
			}
			if (type == typeof(LocalBuilder))
			{
				return $"{((LocalBuilder)argument).LocalIndex} ({((LocalBuilder)argument).LocalType})";
			}
			if (type == typeof(string))
			{
				return GeneralExtensions.ToLiteral(argument.ToString(), "\"");
			}
			return argument.ToString().Trim();
		}
	}
	public static class CodeInstructionNew
	{
		public static CodeInstruction LoadLocal(int index, bool useAddress = false)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			if (useAddress)
			{
				if (index >= 256)
				{
					return new CodeInstruction(OpCodes.Ldloca, (object)index);
				}
				return new CodeInstruction(OpCodes.Ldloca_S, (object)Convert.ToByte(index));
			}
			if (index != 0)
			{
				if (index != 1)
				{
					if (index != 2)
					{
						if (index != 3)
						{
							if (index >= 256)
							{
								return new CodeInstruction(OpCodes.Ldloc, (object)index);
							}
							return new CodeInstruction(OpCodes.Ldloc_S, (object)Convert.ToByte(index));
						}
						return new CodeInstruction(OpCodes.Ldloc_3, (object)null);
					}
					return new CodeInstruction(OpCodes.Ldloc_2, (object)null);
				}
				return new CodeInstruction(OpCodes.Ldloc_1, (object)null);
			}
			return new CodeInstruction(OpCodes.Ldloc_0, (object)null);
		}

		public static CodeInstruction StoreLocal(int index)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			if (index != 0)
			{
				if (index != 1)
				{
					if (index != 2)
					{
						if (index != 3)
						{
							if (index >= 256)
							{
								return new CodeInstruction(OpCodes.Stloc, (object)index);
							}
							return new CodeInstruction(OpCodes.Stloc_S, (object)Convert.ToByte(index));
						}
						return new CodeInstruction(OpCodes.Stloc_3, (object)null);
					}
					return new CodeInstruction(OpCodes.Stloc_2, (object)null);
				}
				return new CodeInstruction(OpCodes.Stloc_1, (object)null);
			}
			return new CodeInstruction(OpCodes.Stloc_0, (object)null);
		}

		public static CodeInstruction LoadArgument(int index, bool useAddress = false)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			if (useAddress)
			{
				if (index >= 256)
				{
					return new CodeInstruction(OpCodes.Ldarga, (object)index);
				}
				return new CodeInstruction(OpCodes.Ldarga_S, (object)Convert.ToByte(index));
			}
			if (index != 0)
			{
				if (index != 1)
				{
					if (index != 2)
					{
						if (index != 3)
						{
							if (index >= 256)
							{
								return new CodeInstruction(OpCodes.Ldarg, (object)index);
							}
							return new CodeInstruction(OpCodes.Ldarg_S, (object)Convert.ToByte(index));
						}
						return new CodeInstruction(OpCodes.Ldarg_3, (object)null);
					}
					return new CodeInstruction(OpCodes.Ldarg_2, (object)null);
				}
				return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
			}
			return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
		}

		public static CodeInstruction StoreArgument(int index)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (index >= 256)
			{
				return new CodeInstruction(OpCodes.Starg, (object)index);
			}
			return new CodeInstruction(OpCodes.Starg_S, (object)Convert.ToByte(index));
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching
{
	public class HarmonyInstancePatcher
	{
		private enum PatchRecursiveAction
		{
			StopAll,
			SkipAndContinueNested,
			PatchAndContinueNested
		}

		private readonly Type harmonyInstanceType;

		private readonly Lazy<Harmony> harmonyPatch;

		public HarmonyInstancePatcher(Type harmonyInstanceType)
		{
			this.harmonyInstanceType = harmonyInstanceType;
			harmonyPatch = new Lazy<Harmony>((Func<Harmony>)(() => new Harmony(GetHarmonyInstanceId())));
		}

		internal string GetHarmonyInstanceId()
		{
			return harmonyInstanceType.FullName;
		}

		public List<MethodInfo> PatchInstance()
		{
			return StartRecursivePatching(harmonyPatch.Value);
		}

		public void UnpatchInstance()
		{
			harmonyPatch.Value.UnpatchSelf();
		}

		public int GetPatchedCount()
		{
			return harmonyPatch.Value.GetPatchedMethods().Count();
		}

		private List<MethodInfo> StartRecursivePatching(Harmony harmonyPatch)
		{
			List<MethodInfo> list = new List<MethodInfo>();
			if (PatchClass(harmonyInstanceType, harmonyPatch, list))
			{
				PatchNestedClassesRecursive(new List<Type>(), harmonyInstanceType, harmonyPatch, list);
			}
			return list;
		}

		private void PatchNestedClassesRecursive(List<Type> classList, Type classType, Harmony harmony, List<MethodInfo> listPatchedMethods)
		{
			Type[] nestedTypes = classType.GetNestedTypes(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (Type type in nestedTypes)
			{
				if (type.IsClass && PatchClass(type, harmony, listPatchedMethods))
				{
					PatchNestedClassesRecursive(classList, type, harmony, listPatchedMethods);
				}
			}
		}

		private bool PatchClass(Type classType, Harmony harmonyPatch, List<MethodInfo> listPatchedMethods)
		{
			switch (CheckAttributesForAllowedAction(classType))
			{
			case PatchRecursiveAction.StopAll:
				return false;
			case PatchRecursiveAction.PatchAndContinueNested:
			{
				PatchClassProcessor val = harmonyPatch.CreateClassProcessor(classType, true);
				listPatchedMethods.AddRange(val.Patch());
				break;
			}
			}
			return true;
		}

		private PatchRecursiveAction CheckAttributesForAllowedAction(Type classType)
		{
			if (ReflectionExtension.HasCustomAttribute<AutoPatchIgnoreClassAndNested>((MemberInfo)classType))
			{
				return PatchRecursiveAction.StopAll;
			}
			if (ReflectionExtension.HasCustomAttribute<AutoPatchIgnoreClass>((MemberInfo)classType))
			{
				return PatchRecursiveAction.SkipAndContinueNested;
			}
			return PatchRecursiveAction.PatchAndContinueNested;
		}

		public List<MethodInfo> PatchClassByType(Type classType)
		{
			ThrowIfNotOwnInstanceNestedClass(classType);
			return harmonyPatch.Value.CreateClassProcessor(classType).Patch();
		}

		public void UnpatchMethod(Type originalClassType, string originalMethodName)
		{
			if (originalMethodName == null)
			{
				throw new ArgumentNullException("originalMethodName");
			}
			MethodInfo methodInfo = AccessTools.Method(originalClassType, originalMethodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new InvalidOperationException("The method \"" + originalMethodName + "\" couldnt be found in the type " + originalClassType.FullName + ".");
			}
			harmonyPatch.Value.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)0, harmonyPatch.Value.Id);
		}

		private void ThrowIfNotOwnInstanceNestedClass(Type classType)
		{
			if (classType == null)
			{
				throw new ArgumentNullException("classType");
			}
			if (classType == harmonyInstanceType)
			{
				throw new InvalidOperationException("Use the method PatchInstance/UnpatchInstance() instead.");
			}
			if (GetTopClassOfNested(classType) != harmonyInstanceType)
			{
				throw new InvalidOperationException("Class must be a nested class of " + harmonyInstanceType.FullName + ". If you want to do this action on another Instance, use that instance methods instead.");
			}
		}

		private Type GetTopClassOfNested(Type classType)
		{
			while (classType.IsNested)
			{
				classType = classType.DeclaringType;
			}
			return classType;
		}
	}
	public class HarmonyMonoMethods
	{
		public static MethodDefinition GetMethodDefinition(MethodInfo methodInfo)
		{
			MethodDefinition val = MethodBaseToMethodDefinition(methodInfo);
			if (val == null)
			{
				AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(AssemblyUtils.GetAssemblyDllFilePath(methodInfo.DeclaringType));
				try
				{
					val = Extensions.FindMethod(val2.MainModule.GetType(methodInfo.DeclaringType.FullName), Extensions.GetID((MethodBase)methodInfo, (string)null, (string)null, true, false, false), false);
				}
				catch (Exception ex)
				{
					TimeLogger.Logger.LogDebug(TimeLogger.FormatException(ex, "Error while trying to convert MethodInfo to MethodDefinition. You can safely ignore this error if you are not the dev."), (LogCategories)4194304);
				}
			}
			return val;
		}

		public static MethodDefinition MethodBaseToMethodDefinition(MethodBase method)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			return (MethodDefinition)((MemberReference)(TypeDefinition)ModuleDefinition.ReadModule((Stream)new MemoryStream(File.ReadAllBytes(method.DeclaringType.Module.FullyQualifiedName))).LookupToken(method.DeclaringType.MetadataToken)).Module.LookupToken(method.MetadataToken);
		}

		public static IEnumerable<(MethodInfo methodInfo, HarmonyMethod harmonyMethod)> GetAllPatchMethodTargets(Type assemblyType, bool skipNonExecutablePatches)
		{
			HarmonyMethod harmonyMethod;
			return (from type in Assembly.GetAssembly(assemblyType).GetTypes()
				where !skipNonExecutablePatches || IsPatchExecutable(type)
				select type).SelectMany((Type type) => from mInfo in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where IsHarmonyAttribute(mInfo)
				select (GetTargetMethodFromHarmonyPatchMethod(type, mInfo, out harmonyMethod), harmonyMethod));
		}

		private static bool IsPatchExecutable(Type methodClassType)
		{
			MethodInfo methodInfo = (from m in methodClassType.GetMethods(AccessTools.all)
				where m.ReturnType == typeof(bool)
				select m).FirstOrDefault((MethodInfo m) => m.Name == "Prepare" || m.GetCustomAttributes(inherit: true).Any((object attr) => attr.GetType().FullName == typeof(HarmonyPrepare).FullName));
			if (methodInfo != null)
			{
				object[] array = AccessTools.ActualParameters((MethodBase)methodInfo, Array.Empty<object>());
				return ReflectionHelper.CallMethod<bool>((object)null, methodInfo, array);
			}
			return true;
		}

		public static bool IsHarmonyAttribute(MethodInfo methodInfo)
		{
			IEnumerable<Attribute> enumerable = null;
			try
			{
				enumerable = methodInfo.GetCustomAttributes();
			}
			catch (TypeNotFoundInAssemblyException)
			{
				return false;
			}
			return enumerable.Any((Attribute attr) => attr is HarmonyAttribute);
		}

		public static MethodInfo GetTargetMethodFromHarmonyPatchMethod(Type methodClassType, MethodInfo patchMethodInfo, out HarmonyMethod harmonyMethod)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable<HarmonyMethod> source = from attr in patchMethodInfo.GetCustomAttributes(inherit: true)
				where attr is HarmonyAttribute
				select ((HarmonyAttribute)attr).info;
			harmonyMethod = HarmonyMethod.Merge(source.ToList());
			if (harmonyMethod.method == null && harmonyMethod.declaringType == null)
			{
				HarmonyMethod val = HarmonyMethod.Merge(HarmonyMethodExtensions.GetFromType(methodClassType));
				harmonyMethod = HarmonyMethodExtensions.Merge(val, harmonyMethod);
			}
			HarmonyMethod val2 = harmonyMethod;
			MethodType valueOrDefault = val2.methodType.GetValueOrDefault();
			if (!val2.methodType.HasValue)
			{
				valueOrDefault = (MethodType)0;
				val2.methodType = valueOrDefault;
			}
			MethodInfo methodInfo = AccessTools.Method("HarmonyLib.PatchTools:GetOriginalMethod", new Type[1] { typeof(HarmonyMethod) }, (Type[])null);
			if (methodInfo != null)
			{
				return (MethodInfo)methodInfo.Invoke(null, new object[1] { harmonyMethod });
			}
			TimeLogger.Logger.LogWarning("Reflection access to \"HarmonyLib.PatchTools:GetOriginalMethod\" returned null. Using backup method.", (LogCategories)4194304);
			return AccessTools.Method(harmonyMethod.declaringType, harmonyMethod.methodName, harmonyMethod.argumentTypes, (Type[])null);
		}
	}
	public class MethodSignatureChecker
	{
		internal class MethodSignature
		{
			public string Arguments { get; set; }

			public string ReturnType { get; set; }

			public int IL_BodyHashcode { get; set; }

			public void Set_IL_BodyHashcode(Collection<Instruction> instructions)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				if (instructions == null)
				{
					throw new ArgumentNullException("instructions");
				}
				int num = 17;
				Enumerator<Instruction> enumerator = instructions.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						Instruction current = enumerator.Current;
						num = num * 71 + ((object)current).ToString().GetHashCode();
					}
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
				IL_BodyHashcode = num;
			}

			internal bool Equals(MethodSignature other, out string errorDetail)
			{
				errorDetail = null;
				if (other == null)
				{
					errorDetail = "\tWrong method call or no longer exists.";
				}
				else if (Arguments != other.Arguments)
				{
					errorDetail = "\tArguments are different";
				}
				else if (ReturnType != other.ReturnType)
				{
					errorDetail = "\tReturn types are different";
				}
				else if (IL_BodyHashcode != other.IL_BodyHashcode)
				{
					errorDetail = "\tIL method body hashcode is different";
				}
				if (errorDetail != null)
				{
					errorDetail = errorDetail.PadRight(38);
				}
				return errorDetail == null;
			}
		}

		private readonly struct MethodInfoData
		{
			private readonly struct FullMethodName
			{
				private readonly string method;

				private readonly string declaringType;

				private readonly string[] parameters;

				public FullMethodName(string declaredTypeName, string methodName, string[] typeParameterNames = null)
				{
					method = methodName;
					declaringType = ReflectionHelper.ConvertFullTypeToNormal(declaredTypeName);
					parameters = ReflectionHelper.ConvertFullTypesToNormal(typeParameterNames);
				}

				public FullMethodName(string declaredTypeName, string methodName, Type[] typeParameter = null)
				{
					method = methodName;
					declaringType = ReflectionHelper.ConvertFullTypeToNormal(declaredTypeName);
					string[] array = null;
					if (typeParameter != null && typeParameter.Length != 0)
					{
						array = (from t in typeParameter
							where t != null
							select t.Name).ToArray();
					}
					parameters = array;
				}

				public string GetText()
				{
					string text = "";
					if (parameters != null && parameters.Length != 0)
					{
						text = string.Join(", ", parameters);
					}
					return declaringType + "." + method + "(" + text + ")";
				}
			}

			private readonly bool isMethodInfo;

			private readonly MethodInfo methodInfo;

			private readonly Type declaringType;

			private readonly string methodName;

			private readonly Type[] parameters;

			private readonly Type[] generics;

			private readonly string fullTypeName;

			private readonly string[] fullTypeParameters;

			private readonly FullMethodName fullMethodName;

			public MethodInfoData(MethodInfo methodInfo, string declaredTypeName, string methodName, string[] typeParameterNames = null)
			{
				declaringType = null;
				this.methodName = null;
				parameters = null;
				generics = null;
				fullTypeName = null;
				fullTypeParameters = null;
				if (string.IsNullOrEmpty(declaredTypeName))
				{
					throw new ArgumentNullException("declaredTypeName cannot be empty.");
				}
				if (string.IsNullOrEmpty(methodName))
				{
					throw new ArgumentNullException("methodName cannot be empty.");
				}
				this.methodInfo = methodInfo;
				fullMethodName = new FullMethodName(declaredTypeName, methodName, typeParameterNames);
				isMethodInfo = true;
			}

			public MethodInfoData(MethodInfo methodInfo, Type declaringType, string methodName, Type[] parameters = null, Type[] generics = null)
			{
				this.declaringType = null;
				this.methodName = null;
				this.parameters = null;
				this.generics = null;
				fullTypeName = null;
				fullTypeParameters = null;
				if (declaringType == null)
				{
					throw new ArgumentNullException("declaringType cannot be null.");
				}
				if (string.IsNullOrEmpty(methodName))
				{
					throw new ArgumentException("methodName cannot be null or empty.");
				}
				this.methodInfo = methodInfo;
				fullMethodName = new FullMethodName(declaringType.Name, methodName, parameters);
				isMethodInfo = true;
			}

			public MethodInfoData(Type declaringType, string methodName, Type[] parameters = null, Type[] generics = null)
			{
				isMethodInfo = false;
				methodInfo = null;
				fullTypeName = null;
				fullTypeParameters = null;
				if (declaringType == null)
				{
					throw new ArgumentNullException("declaringType cannot be null.");
				}
				if (string.IsNullOrEmpty(methodName))
				{
					throw new ArgumentException("methodName cannot be null or empty.");
				}
				this.declaringType = declaringType;
				this.methodName = methodName;
				this.parameters = parameters;
				this.generics = generics;
				fullMethodName = new FullMethodName(declaringType.Name, methodName, parameters);
			}

			public MethodInfoData(Type declaringType, string methodName, string[] fullTypeParameters = null, Type[] generics = null)
			{
				isMethodInfo = false;
				methodInfo = null;
				parameters = null;
				fullTypeName = null;
				if (declaringType == null)
				{
					throw new ArgumentNullException("declaringType cannot be null.");
				}
				if (string.IsNullOrEmpty(methodName))
				{
					throw new ArgumentException("methodName cannot be null or empty.");
				}
				this.declaringType = declaringType;
				this.methodName = methodName;
				this.fullTypeParameters = fullTypeParameters;
				this.generics = generics;
				fullMethodName = new FullMethodName(declaringType.Name, methodName, fullTypeParameters);
			}

			public MethodInfoData(string fullTypeName, string methodName, string[] fullTypeParameters = null, Type[] generics = null)
			{
				isMethodInfo = false;
				methodInfo = null;
				declaringType = null;
				parameters = null;
				if (string.IsNullOrEmpty(fullTypeName))
				{
					throw new ArgumentNullException("fullTypeName cannot be null or empty.");
				}
				if (string.IsNullOrEmpty(methodName))
				{
					throw new ArgumentException("methodName cannot be null or empty.");
				}
				this.fullTypeName = fullTypeName;
				this.methodName = methodName;
				this.fullTypeParameters = fullTypeParameters;
				this.generics = generics;
				fullMethodName = new FullMethodName(fullTypeName, methodName, fullTypeParameters);
			}

			public MethodInfo GetMethodInfo()
			{
				if (isMethodInfo)
				{
					return methodInfo;
				}
				Type obj = ((declaringType != null) ? declaringType : AssemblyUtils.GetTypeFromLoadedAssemblies(fullTypeName, true));
				Type[] array = ((parameters != null) ? parameters : AssemblyUtils.GetTypesFromLoadedAssemblies(true, fullTypeParameters));
				return AccessTools.Method(obj, methodName, array, generics);
			}

			public string GetFullMethodName()
			{
				return fullMethodName.GetText();
			}
		}

		private List<MethodInfoData> listMethodInfoData;

		private Dictionary<string, MethodSignature> previousMethodSignatures;

		private readonly string pathFileMethodSignatures;

		private readonly Type pluginType;

		public CheckResult LastCheckResult { get; private set; }

		public MethodSignatureChecker(Type pluginType)
		{
			this.pluginType = pluginType;
			LastCheckResult = new CheckResult();
			string combinedPathFromAssemblyFolder = AssemblyUtils.GetCombinedPathFromAssemblyFolder(pluginType, "MethodSignatureChecker");
			if (!Directory.Exists(combinedPathFromAssemblyFolder))
			{
				Directory.CreateDirectory(combinedPathFromAssemblyFolder);
			}
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			pathFileMethodSignatures = combinedPathFromAssemblyFolder + directorySeparatorChar + "methodsignatures.json";
			listMethodInfoData = new List<MethodInfoData>();
		}

		public static MethodSignatureChecker StartSignatureCheck(Type pluginType)
		{
			MethodSignatureChecker methodSignatureChecker = new MethodSignatureChecker(pluginType);
			methodSignatureChecker.PopulateMethodSignaturesFromHarmonyPatches();
			methodSignatureChecker.StartSignatureCheck();
			return methodSignatureChecker;
		}

		public void PopulateMethodSignaturesFromHarmonyPatches()
		{
			foreach (var (methodInfo, val) in HarmonyMonoMethods.GetAllPatchMethodTargets(pluginType, skipNonExecutablePatches: true))
			{
				AddMethod(methodInfo, val.declaringType, val.methodName, val.argumentTypes);
			}
		}

		public void AddMethod(MethodInfo methodInfo, string declaredTypeName, string methodName, string[] typeParameterNames = null)
		{
			listMethodInfoData.Add(new MethodInfoData(methodInfo, declaredTypeName, methodName, typeParameterNames));
		}

		public void AddMethod(MethodInfo methodInfo, Type declaringType, string methodName, Type[] parameters = null)
		{
			listMethodInfoData.Add(new MethodInfoData(methodInfo, declaringType, methodName, parameters));
		}

		public void AddMethod(string fullTypeName, string methodName, string[] fullTypeParameters = null, Type[] generics = null)
		{
			listMethodInfoData.Add(new MethodInfoData(fullTypeName, methodName, fullTypeParameters, generics));
		}

		public void AddMethod(Type declaringType, string methodName, string[] fullTypeParameters = null, Type[] generics = null)
		{
			listMethodInfoData.Add(new MethodInfoData(declaringType, methodName, fullTypeParameters, generics));
		}

		public void AddMethod(Type declaringType, string methodName)
		{
			listMethodInfoData.Add(new MethodInfoData(declaringType, methodName, (Type[])null, (Type[])null));
		}

		public void AddMethod(Type declaringType, string methodName, Type[] parameters = null, Type[] generics = null)
		{
			listMethodInfoData.Add(new MethodInfoData(declaringType, methodName, parameters, generics));
		}

		private MethodSignature CreateMethodSignature(MethodInfo methodInfo, MethodDefinition methodDef)
		{
			MethodSignature methodSignature = new MethodSignature();
			object[] parameters = methodInfo.GetParameters();
			methodSignature.Arguments = string.Join("", parameters);
			methodSignature.ReturnType = methodInfo.ReturnType.FullName;
			methodSignature.Set_IL_BodyHashcode(methodDef.Body.Instructions);
			return methodSignature;
		}

		public CheckResult StartSignatureCheck()
		{
			CheckResult checkResult = new CheckResult(CheckResult.SignatureCheckResult.Started, "");
			Dictionary<string, MethodSignature> dictionary = new Dictionary<string, MethodSignature>();
			foreach (MethodInfoData listMethodInfoDatum in listMethodInfoData)
			{
				if (GetMethodSignature(listMethodInfoDatum, out var methodSigEntry) && !dictionary.ContainsKey(methodSigEntry.Key))
				{
					dictionary.Add(methodSigEntry.Key, methodSigEntry.Value);
				}
			}
			if (dictionary == null || !dictionary.Any())
			{
				return checkResult.SetValues(CheckResult.SignatureCheckResult.NoSignaturesAdded, "No method signature has been added. Signature comparison will be skipped.");
			}
			if (TryLoadSignaturesFromFile(checkResult))
			{
				CompareOldSignaturesAgainstNew(checkResult, dictionary);
			}
			if (checkResult.ResultType != CheckResult.SignatureCheckResult.SignaturesDifferent)
			{
				SaveSignaturesToFile(dictionary);
			}
			if (checkResult.ResultType == CheckResult.SignatureCheckResult.Started)
			{
				throw new InvalidOperationException("Something went wrong. Method check finished with result \"Started\".");
			}
			return LastCheckResult = checkResult;
		}

		private bool GetMethodSignature(MethodInfoData methodInfoData, out KeyValuePair<string, MethodSignature> methodSigEntry)
		{
			string text = "";
			MethodSignature value = null;
			MethodInfo methodInfo = methodInfoData.GetMethodInfo();
			if (methodInfo != null)
			{
				MethodDefinition methodDefinition = HarmonyMonoMethods.GetMethodDefinition(methodInfo);
				if (methodDefinition == null)
				{
					methodSigEntry = default(KeyValuePair<string, MethodSignature>);
					return false;
				}
				value = CreateMethodSignature(methodInfo, methodDefinition);
			}
			text = methodInfoData.GetFullMethodName();
			methodSigEntry = new KeyValuePair<string, MethodSignature>(text, value);
			return true;
		}

		private bool TryLoadSignaturesFromFile(CheckResult checkResult)
		{
			if (!File.Exists(pathFileMethodSignatures))
			{
				checkResult.SetValues(CheckResult.SignatureCheckResult.NoPreviousSignatures, "No method signature file. Skipped check.");
				return false;
			}
			try
			{
				string text = File.ReadAllText(pathFileMethodSignatures, Encoding.Unicode);
				previousMethodSignatures = JsonConvert.DeserializeObject<Dictionary<string, MethodSignature>>(text);
			}
			catch (Exception ex)
			{
				checkResult.SetValues(CheckResult.SignatureCheckResult.FileError, TimeLogger.FormatException(ex, "Error while reading and deserializing from file \"" + pathFileMethodSignatures + "\". It might be corrupted. Trying to delete file and skipping loading signatures."));
				try
				{
					File.Delete(pathFileMethodSignatures);
				}
				catch
				{
				}
				return false;
			}
			return true;
		}

		private void SaveSignaturesToFile(Dictionary<string, MethodSignature> currentMethodSignatures)
		{
			string contents = JsonConvert.SerializeObject((object)currentMethodSignatures, (Formatting)1);
			File.WriteAllText(pathFileMethodSignatures, contents, Encoding.Unicode);
		}

		private void CompareOldSignaturesAgainstNew(CheckResult checkResult, Dictionary<string, MethodSignature> currentMethodSignatures)
		{
			Dictionary<string, MethodSignature> dictionary = previousMethodSignatures;
			if (dictionary == null || !dictionary.Any() || currentMethodSignatures == null || !currentMethodSignatures.Any())
			{
				return;
			}
			foreach (KeyValuePair<string, MethodSignature> currentMethodSignature in currentMethodSignatures)
			{
				if (previousMethodSignatures.TryGetValue(currentMethodSignature.Key, out var value))
				{
					MethodSignature value2 = currentMethodSignature.Value;
					if (value != null && !value.Equals(value2, out var errorDetail))
					{
						checkResult.ResultType = CheckResult.SignatureCheckResult.SignaturesDifferent;
						checkResult.AddErrorMessage(errorDetail + " | " + currentMethodSignature.Key);
					}
				}
			}
			if (checkResult.ResultType != CheckResult.SignatureCheckResult.SignaturesDifferent)
			{
				checkResult.SetValues(CheckResult.SignatureCheckResult.SignaturesOk, "Method signature check ok.");
			}
		}
	}
	public class CheckResult
	{
		public enum SignatureCheckResult
		{
			Unchecked,
			Started,
			FileError,
			NoSignaturesAdded,
			NoPreviousSignatures,
			SignaturesDifferent,
			SignaturesOk
		}

		public static CheckResult UnknownError = new CheckResult(SignatureCheckResult.Unchecked, "Unknown Error due to exception");

		public SignatureCheckResult ResultType { get; internal set; }

		public string ResultMessage { get; private set; } = "";


		public string DetailMessage { get; private set; } = "";


		internal CheckResult()
		{
			ResultType = SignatureCheckResult.Unchecked;
		}

		internal CheckResult(SignatureCheckResult result, string resultMessage)
		{
			ResultMessage = resultMessage;
			ResultType = result;
		}

		internal CheckResult SetValues(SignatureCheckResult result, string resultMessage)
		{
			ResultMessage = resultMessage;
			ResultType = result;
			return this;
		}

		internal void AddErrorMessage(string resultMessage)
		{
			if (string.IsNullOrEmpty(ResultMessage))
			{
				ResultMessage = "Method signatures have changed since last successful check";
			}
			DetailMessage = DetailMessage + "\n" + resultMessage;
		}

		public void LogResultMessage(LogTier logLevel, bool onlyWhenNotOk, bool showInGame)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (ShouldLogMessage(onlyWhenNotOk))
			{
				string text = ResultMessage;
				if (ResultType == SignatureCheckResult.SignaturesDifferent)
				{
					text = text + ":" + DetailMessage;
				}
				TimeLogger.Logger.Log(logLevel, text, (LogCategories)4194304);
				TimeLogger.Logger.SendMessageNotificationError(ResultMessage, false);
			}
		}

		private bool ShouldLogMessage(bool onlyWhenNotOk)
		{
			if (string.IsNullOrEmpty(ResultMessage))
			{
				if (ResultType == SignatureCheckResult.Unchecked)
				{
					return false;
				}
				ResultMessage = "Result message was empty for a result in which this is not allowed.";
				return true;
			}
			if (onlyWhenNotOk && (ResultType == SignatureCheckResult.SignaturesOk || ResultType == SignatureCheckResult.NoPreviousSignatures))
			{
				return false;
			}
			return true;
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.Helpers
{
	public class ArgumentHelper<T>
	{
		public T Value { get; set; }

		public CodeInstruction LoadFieldArgHelper_IL { get; private set; }

		public CodeInstruction GetterValue_IL { get; private set; }

		public CodeInstruction SetterValue_IL { get; private set; }

		public ArgumentHelper(Type declaringClassType, string instanceName, T argumentValue)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			Value = argumentValue;
			FieldInfo fieldInfo = AccessTools.Field(declaringClassType, instanceName);
			if (fieldInfo == null)
			{
				throw new InvalidOperationException($"No field was found in the type {declaringClassType} with name {instanceName}.");
			}
			LoadFieldArgHelper_IL = new CodeInstruction(OpCodes.Ldsfld, (object)fieldInfo);
			if (!fieldInfo.IsStatic)
			{
				LoadFieldArgHelper_IL.opcode = OpCodes.Ldfld;
			}
			PropertyInfo propertyInfo = AccessTools.Property(typeof(ArgumentHelper<T>), "Value");
			GetterValue_IL = new CodeInstruction(OpCodes.Callvirt, (object)propertyInfo.GetGetMethod());
			SetterValue_IL = new CodeInstruction(OpCodes.Callvirt, (object)propertyInfo.GetSetMethod());
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.Exceptions
{
	public class TranspilerDefaultMsgException : Exception
	{
		private const string defaultErrorText = "Transpiler couldnt perform its changes due to unexpected source code changes.";

		public TranspilerDefaultMsgException()
			: base(composeErrorText())
		{
		}

		public TranspilerDefaultMsgException(string errorDetail)
			: base(composeErrorText(errorDetail))
		{
		}

		public TranspilerDefaultMsgException(string errorDetail, Exception inner)
			: base(composeErrorText(errorDetail), inner)
		{
		}

		private static string composeErrorText(string errorDetail = "")
		{
			return "Transpiler couldnt perform its changes due to unexpected source code changes.\n" + errorDetail;
		}
	}
	public class TypeNotFoundInAssemblyException : Exception
	{
		public TypeNotFoundInAssemblyException()
		{
		}

		public TypeNotFoundInAssemblyException(string errorDetail)
			: base(errorDetail)
		{
		}

		public TypeNotFoundInAssemblyException(string errorDetail, Exception inner)
			: base(errorDetail, inner)
		{
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching
{
	public static class Container<T> where T : AutoPatchedInstanceBase
	{
		public static T Instance => AutoPatchContainer.GetInstance<T>();
	}
	internal static class AutoPatchContainer
	{
		private static Dictionary<Type, AutoPatchedInstanceBase> registeredInstances = new Dictionary<Type, AutoPatchedInstanceBase>();

		internal static T GetInstance<T>() where T : AutoPatchedInstanceBase
		{
			ThrowIfTypeInvalidOrNotRegistered<T>();
			return (T)registeredInstances[typeof(T)];
		}

		internal static AutoPatchedInstanceBase GetAbstractInstance(Type patchType)
		{
			ThrowIfTypeInvalidOrNotRegistered(patchType);
			return registeredInstances[patchType];
		}

		internal static IReadOnlyDictionary<Type, AutoPatchedInstanceBase> GetRegisteredAutoPatches()
		{
			return registeredInstances;
		}

		internal static void RegisterPatchClass(Type autoPatchType)
		{
			ThrowIfTypeInvalidOrAlreadyRegistered(autoPatchType);
			object obj = Activator.CreateInstance(autoPatchType);
			registeredInstances.Add(autoPatchType, (AutoPatchedInstanceBase)obj);
		}

		internal static void UnregisterPatchClass(Type autoPatchClass)
		{
			ThrowIfTypeInvalidOrNotRegistered(autoPatchClass);
			registeredInstances.Remove(autoPatchClass);
		}

		private static void ThrowIfTypeInvalidOrAlreadyRegistered<T>()
		{
			ThrowIfTypeInvalidOrAlreadyRegistered(typeof(T));
		}

		private static void ThrowIfTypeInvalidOrAlreadyRegistered(Type patchClassType)
		{
			if (patchClassType.IsAbstract || !patchClassType.IsSubclassOf(typeof(AutoPatchedInstanceBase)))
			{
				throw new InvalidOperationException("The type " + patchClassType.FullName + " must be a non abstract subclass of AutoPatchedInstanceBase.");
			}
			if (registeredInstances.ContainsKey(patchClassType))
			{
				throw new InvalidOperationException("The type " + patchClassType.FullName + " has already been registered.");
			}
		}

		private static void ThrowIfTypeInvalidOrNotRegistered<T>()
		{
			ThrowIfTypeInvalidOrNotRegistered(typeof(T));
		}

		private static void ThrowIfTypeInvalidOrNotRegistered(Type patchClassType)
		{
			if (patchClassType.IsAbstract || !patchClassType.IsSubclassOf(typeof(AutoPatchedInstanceBase)))
			{
				throw new InvalidOperationException("The type " + patchClassType.FullName + " must be a non abstract subclass of AutoPatchedInstanceBase.");
			}
			if (!registeredInstances.ContainsKey(patchClassType))
			{
				throw new InvalidOperationException("The type " + patchClassType.FullName + " is not registered.");
			}
		}
	}
	public static class AutoPatcher
	{
		public enum AutoPatchResult
		{
			none,
			error,
			disabled,
			success
		}

		public static bool RegisterAllAutoPatchContainers()
		{
			List<Type> list = GetAutoPatchClasses(Assembly.GetCallingAssembly()).ToList();
			if (list.Count == 0)
			{
				return false;
			}
			foreach (Type item in list)
			{
				AutoPatchContainer.RegisterPatchClass(item);
			}
			return true;
		}

		public static bool StartAutoPatcher()
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (KeyValuePair<Type, AutoPatchedInstanceBase> registeredAutoPatch in AutoPatchContainer.GetRegisteredAutoPatches())
			{
				AutoPatchResult autoPatchResult = Patch(registeredAutoPatch.Key, registeredAutoPatch.Value);
				if (autoPatchResult == AutoPatchResult.disabled)
				{
					num2++;
					continue;
				}
				num3++;
				if (autoPatchResult == AutoPatchResult.error)
				{
					num++;
				}
			}
			if (num == 0)
			{
				TimeLogger.Logger.LogInfo($"All {num3} auto-patches applied successfully.", (LogCategories)8);
				return true;
			}
			TimeLogger.Logger.LogFatal($"Oh oh, {num} out of {num3} auto-patches failed. " + "Check above for errors.", (LogCategories)8);
			return false;
		}

		private static AutoPatchResult Patch(Type autoPatchType, AutoPatchedInstanceBase autoPatchInstance)
		{
			AutoPatchResult autoPatchResult = AutoPatchResult.none;
			try
			{
				if (autoPatchInstance == null)
				{
					throw new InvalidOperationException("Auto patch received a null instance from the registered type " + autoPatchType.FullName + ".");
				}
				if (autoPatchInstance.IsAutoPatchEnabled)
				{
					autoPatchInstance.PatchInstance();
					autoPatchResult = AutoPatchResult.success;
				}
				else
				{
					autoPatchResult = AutoPatchResult.disabled;
				}
			}
			catch (Exception ex)
			{
				autoPatchResult = AutoPatchResult.error;
				TimeLogger.Logger.LogExceptionWithMessage("Error auto patching class " + autoPatchType.FullName + ".", ex, (LogCategories)8);
				if (autoPatchInstance != null)
				{
					TimeLogger.Logger.LogError(autoPatchInstance.ErrorMessageOnAutoPatchFail, (LogCategories)2097152);
					if (autoPatchInstance.IsRollbackOnAutoPatchFail && autoPatchInstance.GetPatchedCount() > 0)
					{
						autoPatchInstance.UnpatchInstance();
					}
				}
			}
			finally
			{
				try
				{
					autoPatchInstance?.RaiseEventOnAutoPatchFinish(autoPatchResult);
				}
				catch (Exception ex2)
				{
					TimeLogger.Logger.LogExceptionWithMessage("Error calling RaiseEventOnAutoPatchFinish:", ex2, (LogCategories)2097152);
				}
			}
			return autoPatchResult;
		}

		public static bool IsPatchActiveFromResult(AutoPatchResult autoPatchResult)
		{
			switch (autoPatchResult)
			{
			case AutoPatchResult.success:
				return true;
			case AutoPatchResult.error:
			case AutoPatchResult.disabled:
				return false;
			default:
				throw new NotImplementedException($"The switch case {autoPatchResult} is not implemented or should not have happened.");
			}
		}

		private static IEnumerable<Type> GetAutoPatchClasses(Assembly assembly)
		{
			return from type in assembly.GetTypes()
				where type.IsClass && !type.IsAbstract && type.IsSubclassOf(typeof(AutoPatchedInstanceBase))
				select type;
		}

		public static string[] GetHarmonyInstanceIdsForAttribute(Type[] autoPatchTypes)
		{
			return autoPatchTypes.Select((Type autoPatchType) => AutoPatchContainer.GetAbstractInstance(autoPatchType).harmonyPatchInstance.Value.GetHarmonyInstanceId()).ToArray();
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.Interfaces
{
	public interface IAutoPatchSupport : ISelfPatch
	{
		bool IsAutoPatchEnabled { get; }

		bool IsRollbackOnAutoPatchFail { get; }

		string ErrorMessageOnAutoPatchFail { get; }

		void RaiseEventOnAutoPatchFinish(AutoPatcher.AutoPatchResult patchResult);
	}
	public interface IConfigPatchDependence
	{
		void SetSettingPatchDependence<T>(ConfigEntry<T> configEntry);
	}
	public interface ISelfPatch
	{
		bool IsPatchActive { get; }

		event Action<bool> OnPatchFinished;

		List<MethodInfo> PatchInstance();

		void UnpatchInstance();
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.BaseClasses
{
	public abstract class AutoPatchedInstanceBase : IAutoPatchSupport, ISelfPatch, IConfigPatchDependence
	{
		internal readonly Lazy<HarmonyInstancePatcher> harmonyPatchInstance;

		public abstract bool IsAutoPatchEnabled { get; }

		public abstract bool IsRollbackOnAutoPatchFail { get; }

		public abstract bool IsPatchActive { get; protected set; }

		public abstract string ErrorMessageOnAutoPatchFail { get; protected set; }

		public abstract event Action<bool> OnPatchFinished;

		internal AutoPatchedInstanceBase()
		{
			harmonyPatchInstance = new Lazy<HarmonyInstancePatcher>(() => new HarmonyInstancePatcher(GetType()));
		}

		public List<MethodInfo> PatchInstance()
		{
			return harmonyPatchInstance.Value.PatchInstance();
		}

		public void UnpatchInstance()
		{
			harmonyPatchInstance.Value.UnpatchInstance();
		}

		public int GetPatchedCount()
		{
			return harmonyPatchInstance.Value.GetPatchedCount();
		}

		public abstract void RaiseEventOnAutoPatchFinish(AutoPatcher.AutoPatchResult autoPatchResult);

		public void SetSettingPatchDependence<U>(ConfigEntry<U> configEntry)
		{
			OnPatchFinished += delegate(bool IsPatchActive)
			{
				configEntry.SetConfigAttribute<U, bool>(ConfigurationManagerAttributes.ConfigAttributes.Browsable, IsPatchActive);
			};
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.BaseClasses.Inheritable
{
	public abstract class FullyAutoPatchedInstance : AutoPatchedInstanceBase
	{
		public override bool IsRollbackOnAutoPatchFail => true;

		public override bool IsPatchActive { get; protected set; }

		public override event Action<bool> OnPatchFinished;

		public void AutoPatchResultEvent(AutoPatcher.AutoPatchResult autoPatchResult)
		{
			IsPatchActive = AutoPatcher.IsPatchActiveFromResult(autoPatchResult);
		}

		public virtual void OnPatchFinishedVirtual(bool IsActive)
		{
		}

		public override void RaiseEventOnAutoPatchFinish(AutoPatcher.AutoPatchResult autoPatchResult)
		{
			AutoPatchResultEvent(autoPatchResult);
			if (OnPatchFinished != null)
			{
				OnPatchFinished(IsPatchActive);
			}
			OnPatchFinishedVirtual(IsPatchActive);
		}
	}
	public abstract class HybridPatchedInstance : AutoPatchedInstanceBase
	{
		public override void RaiseEventOnAutoPatchFinish(AutoPatcher.AutoPatchResult autoPatchResult)
		{
		}

		public List<MethodInfo> PatchClassByType(Type classType)
		{
			return harmonyPatchInstance.Value.PatchClassByType(classType);
		}

		public void UnpatchMethod(Type classType, string methodName)
		{
			harmonyPatchInstance.Value.UnpatchMethod(classType, methodName);
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.Attributes
{
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
	public class AutoPatchIgnoreClass : AutoPatchAttribute
	{
	}
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
	public class AutoPatchIgnoreClassAndNested : AutoPatchAttribute
	{
	}
	public abstract class AutoPatchAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
	public class HarmonyBeforeInstance : HarmonyPatch
	{
		private HarmonyBeforeInstance()
		{
		}

		public HarmonyBeforeInstance(params Type[] beforeInstances)
		{
			((HarmonyAttribute)this).info.before = AutoPatcher.GetHarmonyInstanceIdsForAttribute(beforeInstances);
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
	public class HarmonyAfterInstance : HarmonyPatch
	{
		private HarmonyAfterInstance()
		{
		}

		public HarmonyAfterInstance(params Type[] afterInstances)
		{
			((HarmonyAttribute)this).info.after = AutoPatcher.GetHarmonyInstanceIdsForAttribute(afterInstances);
		}
	}
}
namespace Damntry.UtilsBepInEx.HarmonyPatching.Attributes
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Delegate, AllowMultiple = true)]
	public class HarmonyPatchStringTypes : HarmonyAttribute
	{
		public HarmonyPatchStringTypes(string fullTypeName, string methodName)
		{
			SetMethodInfo(fullTypeName, methodName, (Type[])null);
		}

		public HarmonyPatchStringTypes(string fullTypeName, string methodName, Type[] argumentTypes)
		{
			SetMethodInfo(fullTypeName, methodName, argumentTypes);
		}

		private void SetMethodInfo(string fullTypeName, string methodName, string[] argumentFullTypeNames)
		{
			Type[] typesFromLoadedAssemblies = AssemblyUtils.GetTypesFromLoadedAssemblies(true, argumentFullTypeNames);
			SetMethodInfo(fullTypeName, methodName, typesFromLoadedAssemblies);
		}

		private void SetMethodInfo(string fullTypeName, string methodName, Type[] argumentTypes)
		{
			Type typeFromLoadedAssemblies = AssemblyUtils.GetTypeFromLoadedAssemblies(fullTypeName, true);
			base.info.declaringType = typeFromLoadedAssemblies;
			base.info.methodName = methodName;
			base.info.argumentTypes = argumentTypes;
		}
	}
}
namespace Damntry.UtilsBepInEx.Debug
{
	public interface ITimeScaleMethods
	{
		void ReadVanillaValues();

		void SetAdjustedSpeed(float timeScaleDiff);
	}
	public static class TimeScaleDebug
	{
		private class TimeScaleDebugBehaviour : MonoBehaviour
		{
			private bool vanillaValuesRead;

			public void Update()
			{
				float timeScale = Time.timeScale;
				if (!vanillaValuesRead && timeScale == Settings.DefaultTimeScale)
				{
					TimeScaleMethods.ReadVanillaValues();
					vanillaValuesRead = true;
				}
				if (((IEnumerable<KeyCode>)Settings.KeyModifiers).All((Func<KeyCode, bool>)Input.GetKey))
				{
					bool flag = false;
					bool isIncrease = false;
					if (Input.GetAxis("Mouse ScrollWheel") > 0f)
					{
						isIncrease = true;
						flag = true;
					}
					else if (Input.GetAxis("Mouse ScrollWheel") < 0f)
					{
						flag = true;
					}
					if (flag)
					{
						Time.timeScale = CalculateNewTimeScale(timeScale, isIncrease);
						float adjustedSpeed = Settings.DefaultTimeScale / Time.timeScale;
						TimeScaleMethods.SetAdjustedSpeed(adjustedSpeed);
						TimeLogger.Logger.Log((LogTier)8, "Time Scale : " + Math.Round(Time.timeScale, 3), (LogCategories)int.MinValue, Settings.PreprocessMsgFunc, Settings.ShowInGameNotification(), Settings.SkipNotificationQueue, Array.Empty<(Action<string>, bool)>());
					}
				}
			}
		}

		private class TimeScaleSettings
		{
			public int TotalScrollNotches { get; init; }

			public float DefaultTimeScale { get; init; }

			public float MinTimeScale { get; init; }

			public float MaxTimeScale { get; init; }

			public int DefaultStartStep { get; init; }

			public float[] FixedThresholds { get; init; }

			public PreprocessMessageFunc PreprocessMsgFunc { get; init; }

			public Func<bool> ShowInGameNotification { get; init; }

			public bool SkipNotificationQueue { get; init; }

			public KeyCode[] KeyModifiers { get; init; }
		}

		public static readonly KeyCode[] DefaultKeyModifiers = (KeyCode[])(object)new KeyCode[2]
		{
			(KeyCode)308,
			(KeyCode)306
		};

		private static TimeScaleSettings Settings;

		private static ITimeScaleMethods TimeScaleMethods;

		private static TimeScaleDebugBehaviour behaviourRef;

		private static AnimationCurve timeScaleCurve;

		private static int currentNotch;

		public static void Initialize<T>(GameObject parent, KeyCode[] keyModifiers = null, float defaultTimeScale = 1f, float minTimeScale = 0.002f, float maxTimeScale = 50f, int totalScrollNotches = 100, float notchRatio = 0.3f, float[] thresholds = null, PreprocessMessageFunc preprocessMsgFunc = null, Func<bool> showInGameNotification = null, bool skipNotificationQueue = true) where T : ITimeScaleMethods, new()
		{
			if (Object.op_Implicit((Object)(object)behaviourRef))
			{
				TimeLogger.Logger.LogWarning("There is still an active MonoBehaviour " + $"added previously ({behaviourRef}).", (LogCategories)int.MinValue);
				return;
			}
			if (!Object.op_Implicit((Object)(object)parent))
			{
				TimeLogger.Logger.LogWarning("parent parameter is null. TimeScaleDebugfunctionality wont work.", (LogCategories)int.MinValue);
				return;
			}
			TimeScaleMethods = new T();
			TimeScaleSettings timeScaleSettings = new TimeScaleSettings();
			timeScaleSettings.TotalScrollNotches = totalScrollNotches;
			timeScaleSettings.DefaultTimeScale = defaultTimeScale;
			timeScaleSettings.MinTimeScale = minTimeScale;
			timeScaleSettings.MaxTimeScale = maxTimeScale;
			timeScaleSettings.DefaultStartStep = (int)((float)totalScrollNotches * Mathf.Clamp01(notchRatio));
			timeScaleSettings.FixedThresholds = thresholds ?? new float[1] { defaultTimeScale };
			timeScaleSettings.KeyModifiers = keyModifiers ?? DefaultKeyModifiers;
			timeScaleSettings.PreprocessMsgFunc = preprocessMsgFunc;
			timeScaleSettings.ShowInGameNotification = showInGameNotification;
			timeScaleSettings.SkipNotificationQueue = skipNotificationQueue;
			Settings = timeScaleSettings;
			behaviourRef = parent.AddComponent<TimeScaleDebugBehaviour>();
			CreateTimeScaleCurve();
			currentNotch = Settings.DefaultStartStep;
		}

		private static void CreateTimeScaleCurve()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			timeScaleCurve = new AnimationCurve();
			timeScaleCurve.AddKey(new Keyframe(0f, Settings.MinTimeScale, 0f, 0f));
			timeScaleCurve.AddKey(new Keyframe((float)Settings.DefaultStartStep, Settings.DefaultTimeScale, 0f, 0f));
			timeScaleCurve.AddKey(new Keyframe((float)Settings.TotalScrollNotches, Settings.MaxTimeScale, 0f, 0f));
		}

		private static float CalculateNewTimeScale(float currentTimeScale, bool isIncrease)
		{
			currentNotch += (isIncrease ? 1 : (-1));
			currentNotch = NumberExtensionMethods.ClampReturn(currentNotch, 0, Settings.TotalScrollNotches);
			float num = timeScaleCurve.Evaluate((float)currentNotch);
			float[] fixedThresholds = Settings.FixedThresholds;
			foreach (float num2 in fixedThresholds)
			{
				if ((isIncrease && num2 > currentTimeScale && num2 < num) || (!isIncrease && num2 > num && num2 < currentTimeScale))
				{
					num = num2;
					break;
				}
			}
			return num;
		}
	}
}
namespace Damntry.UtilsBepInEx.Configuration
{
	public static class BepinexConfigExtensions
	{
		public static T GetMaxValue<T>(this AcceptableValueBase acceptableVal) where T : IComparable, IEquatable<T>
		{
			if (acceptableVal is AcceptableValueRange<T>)
			{
				return ((AcceptableValueRange<T>)(object)acceptableVal).GetMaxNumericValue<T>();
			}
			if (acceptableVal is AcceptableValueList<T>)
			{
				return ((AcceptableValueList<T>)(object)acceptableVal).GetMaxNumericValue<T>();
			}
			return default(T);
		}

		public static T GetMaxNumericValue<T>(this AcceptableValueRange<T> acceptableVal) where T : IComparable
		{
			return acceptableVal.MaxValue;
		}

		public static T GetMaxNumericValue<T>(this AcceptableValueList<T> acceptableVal) where T : IEquatable<T>, IComparable
		{
			if (!NumberExtensionMethods.IsNumeric(typeof(T)))
			{
				throw new InvalidOperationException("Only numeric types are allowed, but received a " + typeof(T).FullName);
			}
			return acceptableVal.AcceptableValues.OrderBy((T x) => x).Last();
		}
	}
	public class ConfigMethods
	{
		public static bool GetExternalConfigValue<T>(string ModGUID, string configKey, out T value)
		{
			value = default(T);
			if (Chainloader.PluginInfos.TryGetValue(ModGUID, out var value2))
			{
				ConfigEntryBase val = (from c in (IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)value2.Instance.Config
					where c.Key.Key == configKey
					select c.Value).FirstOrDefault();
				if (val != null)
				{
					value = (T)val.BoxedValue;
					return true;
				}
			}
			return false;
		}
	}
}
namespace Damntry.UtilsBepInEx.Configuration.ConfigurationManager
{
	public enum MultiplayerModInstallSide
	{
		Unspecified,
		Any,
		HostSideOnly,
		HostAndOptionalClient,
		HostAndSoftClient,
		HostAndHardClient
	}
	public class ConfigManagerController
	{
		internal const string ConfigMngFullTypeName = "ConfigurationManager.ConfigurationManager";

		private const string InstallSideInitialDescription = "[Multiplayer requirements] This setting requires that the mod ";

		private const string UnusedSettingText = "# Old unused setting, can be deleted safely:  ";

		private ConfigFile configFile;

		private string currentSectionName;

		private int currentSectionOrder;

		private int currentConfigOrder;

		public ConfigManagerController(ConfigFile configFile)
		{
			this.configFile = configFile ?? throw new ArgumentNullException("configFile");
			currentSectionOrder = 0;
			currentConfigOrder = int.MaxValue;
			if (AssemblyUtils.GetTypeFromLoadedAssemblies("ConfigurationManager.ConfigurationManager", true) != null)
			{
				ConfigurationManagerPatch.PatchSelf();
			}
			ConfigEntryBasePatch.PatchSelf();
		}

		private void SetSection(string sectionName, bool skipSectionOrder = false)
		{
			if (!(sectionName == currentSectionName))
			{
				if (!skipSectionOrder)
				{
					currentSectionOrder++;
				}
				currentConfigOrder = int.MaxValue;
				currentSectionName = sectionName;
			}
		}

		public static bool RefreshGUI()
		{
			if (ConfigurationManagerPatch.ConfigMngInstance != null)
			{
				string text = "BuildSettingList";
				try
				{
					ReflectionHelper.CallMethod(ConfigurationManagerPatch.ConfigMngInstance, text, (object[])null);
					return true;
				}
				catch (Exception ex)
				{
					TimeLogger.Logger.LogExceptionWithMessage("Error when trying to call the method to refresh ConfigurationManager GUI.", ex, (LogCategories)64);
				}
			}
			return false;
		}

		public ConfigEntry<bool> AddSectionNote(string sectionText, string description = null, IConfigPatchDependence patchInstanceDependency = null, bool hidden = false, bool isAdvanced = false)
		{
			string text = "\u200b";
			ConfigEntryBasePatch.AddNote(text);
			return AddConfig(sectionText, text, defaultValue: true, description, patchInstanceDependency, MultiplayerModInstallSide.Unspecified, hidden, disabled: true, null, showRangeAsPercent: false, hideDefaultButton: true, isAdvanced, skipSectionIncrease: true);
		}

		public ConfigEntry<string> AddQuasiNote(string sectionName, string key, string textboxMessage, string description = null, IConfigPatchDependence patchInstanceDependency = null, bool hidden = false, bool isAdvanced = false)
		{
			return AddQuasiNote(sectionName, key, textboxMessage, description, patchInstanceDependency, hidden, isAdvanced, skipSectionIncrease: false);
		}

		public ConfigEntry<string> AddGUIHiddenNote(string sectionName, string key, string description = null, IConfigPatchDependence patchInstanceDependency = null, bool isAdvanced = false)
		{
			return AddQuasiNote(sectionName, key, null, description, patchInstanceDependency, hidden: true, isAdvanced, skipSectionIncrease: true);
		}

		private ConfigEntry<string> AddQuasiNote(string sectionName, string key, string textboxMessage, string description = null, IConfigPatchDependence patchInstanceDependency = null, bool hidden = false, bool isAdvanced = false, bool skipSectionIncrease = false)
		{
			if (textboxMessage == null)
			{
				textboxMessage = "";
			}
			ConfigEntryBasePatch.AddNote(key);
			return AddConfig(sectionName, key, textboxMessage, description, patchInstanceDependency, MultiplayerModInstallSide.Unspecified, hidden, disabled: true, null, showRangeAsPercent: false, hideDefaultButton: true, isAdvanced, skipSectionIncrease);
		}

		public ConfigEntry<T> AddConfig<T>(string sectionName, string key, T defaultValue, string description = null, IConfigPatchDependence patchInstanceDependency = null, MultiplayerModInstallSide modInstallSide = MultiplayerModInstallSide.Unspecified, bool hidden = false, bool disabled = false, bool hideDefaultButton = false, bool isAdvanced = false)
		{
			return AddConfig(sectionName, key, defaultValue, description, patchInstanceDependency, modInstallSide, hidden, disabled, null, showRangeAsPercent: false, hideDefaultButton, isAdvanced);
		}

		public ConfigEntry<T> AddConfigWithAcceptableValues<T>(string sectionName, string key, T defaultValue, string description = null, IConfigPatchDependence patchInstanceDependency = null, MultiplayerModInstallSide modInstallSide = MultiplayerModInstallSide.Unspecified, bool hidden = false, bool disabled = false, AcceptableValueList<T> acceptableValueList = null, bool hideDefaultButton = false, bool isAdvanced = false) where T : IEquatable<T>
		{
			return AddConfig(sectionName, key, defaultValue, description, patchInstanceDependency, modInstallSide, hidden, disabled, (AcceptableValueBase)(object)acceptableValueList, showRangeAsPercent: false, hideDefaultButton, isAdvanced);
		}

		public ConfigEntry<T> AddConfigWithAcceptableValues<T>(string sectionName, string key, T defaultValue, string description = null, IConfigPatchDependence patchInstanceDependency = null, MultiplayerModInstallSide modInstallSide = MultiplayerModInstallSide.Unspecified, bool hidden = false, bool disabled = false, AcceptableValueRange<T> acceptableValueRange = null, bool showRangeAsPercent = false, bool hideDefaultButton = false, bool isAdvanced = false) where T : IComparable
		{
			return AddConfig(sectionName, key, defaultValue, description, patchInstanceDependency, modInstallSide, hidden, disabled, (AcceptableValueBase)(object)acceptableValueRange, showRangeAsPercent, hideDefaultButton, isAdvanced);
		}

		private ConfigEntry<T> AddConfig<T>(string sectionName, string key, T defaultValue, string description = null, IConfigPatchDependence patchInstanceDependency = null, MultiplayerModInstallSide modInstallSide = MultiplayerModInstallSide.Unspecified, bool hidden = false, bool disabled = false, AcceptableValueBase acceptableVal = null, bool showRangeAsPercent = false, bool hideDefaultButton = false, bool isAdvanced = false, bool skipSectionIncrease = false)
		{
			SetSection(sectionName, skipSectionIncrease);
			return AddConfig(key, defaultValue, description, patchInstanceDependency, modInstallSide, hidden, disabled, acceptableVal, showRangeAsPercent, hideDefaultButton, isAdvanced);
		}

		private ConfigEntry<T> AddConfig<T>(string key, T defaultValue, string description = null, IConfigPatchDependence patchInstanceDependency = null, MultiplayerModInstallSide modInstallSide = MultiplayerModInstallSide.Unspecified, bool hidden = false, bool disabled = false, AcceptableValueBase acceptableVal = null, bool showRangeAsPercent = false, bool hideDefaultButton = false, bool isAdvanced = false)
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			if (description == null)
			{
				description = "";
			}
			if (patchInstanceDependency != null)
			{
				hidden = true;
			}
			if (modInstallSide != 0)
			{
				string descriptionFromInstallSide = GetDescriptionFromInstallSide(modInstallSide);
				if (!Utility.IsNullOrWhiteSpace(description))
				{
					description += "\n\n";
				}
				description += descriptionFromInstallSide;
			}
			ConfigDescription val = new ConfigDescription(description, acceptableVal, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					IsAdvanced = isAdvanced,
					Order = currentConfigOrder--,
					Browsable = !hidden,
					DefaultValue = defaultValue,
					ShowRangeAsPercent = showRangeAsPercent,
					ReadOnly = disabled,
					HideDefaultButton = hideDefaultButton,
					Category = currentSectionOrder.ToString("D2") + ". " + currentSectionName
				}
			});
			ConfigEntry<T> val2 = configFile.Bind<T>(currentSectionName, key, defaultValue, val);
			patchInstanceDependency?.SetSettingPatchDependence<T>(val2);
			return val2;
		}

		public void RenameOrphanedSettings()
		{
			try
			{
				string backingFieldName = GetBackingFieldName("OrphanedEntries");
				FieldInfo fieldInfo = AccessTools.Field(((object)configFile).GetType(), backingFieldName);
				if (fieldInfo == null)
				{
					TimeLogger.Logger.LogWarning("The field '" + backingFieldName + "' could not be " + $"found in type {((object)configFile).GetType()}", (LogCategories)64);
					return;
				}
				IDictionary<ConfigDefinition, string> dictionary = (IDictionary<ConfigDefinition, string>)fieldInfo.GetValue(configFile);
				if (dictionary == null)
				{
					return;
				}
				string text = "";
				bool flag = false;
				foreach (KeyValuePair<ConfigDefinition, string> item in dictionary)
				{
					if (!item.Key.Key.StartsWith("# Old unused setting, can be deleted safely:  "))
					{
						if (!string.IsNullOrEmpty(text))
						{
							text += " || ";
						}
						text = text + "\"" + item.Key.Key + "\"";
						RenameSettingKeyname(item.Key);
						flag = true;
					}
				}
				if (flag)
				{
					configFile.Save();
					TimeLogger.Logger.LogDebug("Some config keys were found to be obsolete: " + text + ". They got renamed to make clear that they are of no use anymore.", (LogCategories)64);
				}
			}
			catch (Exception ex)
			{
				TimeLogger.Logger.LogExceptionWithMessage("Error while trying to rename orphaned Bepinex config settings.", ex, (LogCategories)64);
			}
		}

		private void RenameSettingKeyname(ConfigDefinition key)
		{
			AccessTools.Field(((object)key).GetType(), GetBackingFieldName("Key")).SetValue(key, "# Old unused setting, can be deleted safely:  " + key.Key);
		}

		public string GetBackingFieldName(string varName)
		{
			return "<" + varName + ">k__BackingField";
		}

		public bool Remove(string section, string key)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return configFile.Remove(new ConfigDefinition(section, key));
		}

		public bool Remove(ConfigDefinition key)
		{
			return configFile.Remove(key);
		}

		public void ClearAllConfigs()
		{
			configFile.Clear();
		}

		public int Count()
		{
			return configFile.Count;
		}

		private string GetDescriptionFromInstallSide(MultiplayerModInstallSide modInstallSide)
		{
			return "[Multiplayer requirements] This setting requires that the mod " + modInstallSide switch
			{
				MultiplayerModInstallSide.Any => "is installed for the player/s that wants its functionality, hosting or not.", 
				MultiplayerModInstallSide.HostSideOnly => "is installed in the host. It is not needed in the client.", 
				MultiplayerModInstallSide.HostAndOptionalClient => "is installed in the host. Clients can also install it.", 
				MultiplayerModInstallSide.HostAndSoftClient => "is installed in the host, and should be installed in the clients.", 
				MultiplayerModInstallSide.HostAndHardClient => "is installed in both the host and the clients.", 
				_ => "", 
			};
		}

		public bool SetConfigAttribute<T1, T2>(string section, string key, ConfigurationManagerAttributes.ConfigAttributes configAttribute, T2 attrValue)
		{
			return GetConfigEntry<T2>(section, key).SetConfigAttribute<T2, T2>(configAttribute, attrValue);
		}

		public R GetConfigAttribute<T, R>(string section, string key, ConfigurationManagerAttributes.ConfigAttributes configAttribute)
		{
			return GetConfigEntry<T>(section, key).GetConfigAttribute<T, R>(configAttribute);
		}

		private ConfigEntry<T> GetConfigEntry<T>(string section, string key)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			ConfigEntry<T> val = default(ConfigEntry<T>);
			if (!configFile.TryGetEntry<T>(new ConfigDefinition(section, key), ref val) || ((ConfigEntryBase)val).Description == null || ((ConfigEntryBase)val).Description.Tags == null)
			{
				throw new InvalidOperationException("The config entry with section \"" + section + "\" and key \"" + key + "\" could not be found.");
			}
			return val;
		}
	}
	public static class ConfigManagerExtension
	{
		public static bool SetConfigAttribute<T1, T2>(this ConfigEntry<T1> configEntry, ConfigurationManagerAttributes.ConfigAttributes configAttribute, T2 attrValue)
		{
			ConfigurationManagerAttributes configManagerAttribInstance;
			FieldInfo configAttributeFieldInfo = GetConfigAttributeFieldInfo<T1>(configEntry, configAttribute, out configManagerAttribInstance);
			if (configAttributeFieldInfo == null)
			{
				return false;
			}
			configAttributeFieldInfo.SetValue(configManagerAttribInstance, attrValue);
			return true;
		}

		public static R GetConfigAttribute<T, R>(this ConfigEntry<T> configEntry, ConfigurationManagerAttributes.ConfigAttributes configAttribute)
		{
			ConfigurationManagerAttributes configManagerAttribInstance;
			FieldInfo configAttributeFieldInfo = GetConfigAttributeFieldInfo<T>(configEntry, configAttribute, out configManagerAttribInstance);
			if (configAttributeFieldInfo == null)
			{
				throw new InvalidOperationException("The attribute \"" + configAttribute.ToString() + "\" could not be found.");
			}
			object value = configAttributeFieldInfo.GetValue(configManagerAttribInstance);
			if (value != null && !(value is R))
			{
				throw new InvalidOperationException("The attribute value is of type \"" + value.GetType().FullName + "\" and is not compatible with the type \"" + typeof(R).FullName + "\" passed by parameter.");
			}
			return (R)value;
		}

		private static FieldInfo GetConfigAttributeFieldInfo<T>(ConfigEntry<T> configEntry, ConfigurationManagerAttributes.ConfigAttributes configAttribute, out ConfigurationManagerAttributes configManagerAttribInstance)
		{
			configManagerAttribInstance = null;
			object[] tags = ((ConfigEntryBase)configEntry).Description.Tags;
			foreach (object obj in tags)
			{
				if (obj is ConfigurationManagerAttributes)
				{
					configManagerAttribInstance = (ConfigurationManagerAttributes)obj;
					break;
				}
			}
			if (configManagerAttribInstance == null)
			{
				return null;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(ConfigurationManagerAttributes), configAttribute.ToString());
			if (fieldInfo == null)
			{
				return null;
			}
			return fieldInfo;
		}
	}
}
namespace Damntry.UtilsBepInEx.Configuration.ConfigurationManager.SettingAttributes
{
	public sealed class ConfigurationManagerAttributes
	{
		public enum ConfigAttributes
		{
			ShowRangeAsPercent,
			CustomDrawer,
			CustomHotkeyDrawer,
			Browsable,
			Category,
			DefaultValue,
			HideDefaultButton,
			HideSettingName,
			Description,
			DispName,
			Order,
			ReadOnly,
			IsAdvanced
		}

		public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

		public bool? ShowRangeAsPercent;

		public Action<ConfigEntryBase> CustomDrawer;

		public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;
	}
}
namespace Damntry.UtilsBepInEx.Configuration.ConfigurationManager.Patch
{
	internal class ConfigEntryBasePatch
	{
		private static readonly HashSet<string> keyNotes;

		internal static Lazy<Harmony> Harmony { get; }

		static ConfigEntryBasePatch()
		{
			Harmony = new Lazy<Harmony>((Func<Harmony>)(() => new Harmony(typeof(ConfigEntryBasePatch).FullName)));
			keyNotes = new HashSet<string>();
		}

		internal static void PatchSelf()
		{
			try
			{
				Harmony.Value.PatchAll(typeof(ConfigEntryBasePatch));
			}
			catch (Exception ex)
			{
				TimeLogger.Logger.LogExceptionWithMessage("Error while trying to apply patch in type ConfigEntryBasePatch", ex, (LogCategories)64);
			}
		}

		public static void AddNote(string configKey)
		{
			keyNotes.Add(configKey);
		}

		[HarmonyPatch(typeof(ConfigEntryBase), "WriteDescription")]
		[HarmonyPrefix]
		public static bool WriteDescriptionPatch(ConfigEntryBase __instance, StreamWriter writer)
		{
			if (keyNotes.Contains(__instance.Definition.Key))
			{
				if (!string.IsNullOrEmpty(__instance.Description.Description))
				{
					writer.WriteLine("## " + __instance.Description.Description.Replace("\n", "\n## "));
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class ConfigurationManagerPatch
	{
		private static Lazy<Harmony> Harmony { get; } = new Lazy<Harmony>((Func<Harmony>)(() => new Harmony(typeof(ConfigurationManagerPatch).FullName)));


		internal static object ConfigMngInstance { get; private set; }

		internal static void PatchSelf()
		{
			try
			{
				Harmony.Value.PatchAll(typeof(ConfigurationManagerPatch));
			}
			catch (Exception ex)
			{
				TimeLogger.Logger.LogExceptionWithMessage("Error while trying to apply patch in type ConfigurationManagerPatch", ex, (LogCategories)64);
			}
		}

		[HarmonyPatchStringTypes("ConfigurationManager.ConfigurationManager", "Update")]
		[HarmonyPostfix]
		internal static void GetConfigManagerInstancePatch(object __instance)
		{
			if (__instance != null)
			{
				ConfigMngInstance = __instance;
				Harmony.Value.UnpatchSelf();
			}
		}
	}
}
namespace Damntry.UtilsBepInEx.Components
{
	public class InputBepInEx : InputDetection
	{
		private static InputBepInEx _instance;

		private readonly Dictionary<string, ConfigEntry<KeyboardShortcut>> configKeyPresses;

		public static InputBepInEx Instance => _instance ?? (_instance = new InputBepInEx());

		public InputBepInEx()
			: base(typeof(InputBepInEx), (OnValidationError)0, false, (List<KeyBind>)null)
		{
			configKeyPresses = new Dictionary<string, ConfigEntry<KeyboardShortcut>>();
		}

		protected InputBepInEx(Type callingKeypressClass, OnValidationError onError, bool restrictAllModifiers, [ParamCollection] List<KeyBind> restrictedKeyBinds)
			: base(callingKeypressClass, onError, restrictAllModifiers, restrictedKeyBinds)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			configKeyPresses = new Dictionary<string, ConfigEntry<KeyboardShortcut>>();
		}

		protected override void HotkeyValidationError(string hotkeyName, string message, KeyBind keyBind)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (IsConfigManagedKeyPress(hotkeyName, out var configEntry))
			{
				EventMethods.ExecuteBypassingEvent((Action)delegate
				{
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_001c: Unknown result type (might be due to invalid IL or missing references)
					configEntry.Value = new KeyboardShortcut(keyBind.KeyCode, keyBind.Modifiers);
				}, (EventData[])(object)new EventData[1]
				{
					new EventData(((object)configEntry).GetType(), (object)configEntry, "SettingChanged")
				});
				ConfigManagerController.RefreshGUI();
			}
			((InputDetection)this).HotkeyValidationError(hotkeyName, message, keyBind);
		}

		public void AddHotkeyFromConfig(ConfigEntry<KeyboardShortcut> hotkeyConfig, InputState inputState, HotkeyContext hotkeyContext, Action action)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			string hotkeyName = GetHotkeyNameFromConfig(hotkeyConfig, inputState);
			string hotkeyName2 = hotkeyName;
			KeyboardShortcut value = hotkeyConfig.Value;
			KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
			value = hotkeyConfig.Value;
			AddHotkeyBepInExInternal(hotkeyName2, mainKey, ((KeyboardShortcut)(ref value)).Modifiers.ToArray(), inputState, hotkeyContext, 65, action, null, hotkeyConfig);
			hotkeyConfig.SettingChanged += delegate
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				ChangeConfigHotkey(hotkeyConfig, hotkeyName, inputState, hotkeyContext, 65, action);
			};
		}

		public void AddHotkeyFromConfig(ConfigEntry<KeyboardShortcut> hotkeyConfig, InputState inputState, HotkeyContext hotkeyContext, int cooldownMillis, Action action)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			string hotkeyName = GetHotkeyNameFromConfig(hotkeyConfig, inputState);
			string hotkeyName2 = hotkeyName;
			KeyboardShortcut value = hotkeyConfig.Value;
			KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
			value = hotkeyConfig.Value;
			AddHotkeyBepInExInternal(hotkeyName2, mainKey, ((KeyboardShortcut)(ref value)).Modifiers.ToArray(), inputState, hotkeyContext, cooldownMillis, action, null, hotkeyConfig);
			hotkeyConfig.SettingChanged += delegate
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				ChangeConfigHotkey(hotkeyConfig, hotkeyName, inputState, hotkeyContext, cooldownMillis, action);
			};
		}

		private string GetHotkeyNameFromConfig(ConfigEntry<KeyboardShortcut> hotkeyConfig, InputState inputState)
		{
			return ((ConfigEntryBase)hotkeyConfig).Definition.Key + "-" + ((object)(InputState)(ref inputState)).ToString();
		}

		private void ChangeConfigHotkey(ConfigEntry<KeyboardShortcut> hotkeyConfig, string hotkeyName, InputState inputState, HotkeyContext hotkeyContext, int cooldownMillis, Action action)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			InputData value;
			bool num = ((InputDetection)this).KeyPressActions.TryGetValue(hotkeyName, out value);
			KeyboardShortcut value2 = hotkeyConfig.Value;
			KeyCode[] modifiers = ((KeyboardShortcut)(ref value2)).Modifiers.ToArray();
			if (num)
			{
				ChangeHotkeyBepInExInternal(hotkeyName, ((KeyboardShortcut)(ref value2)).MainKey, modifiers, fromConfig: true);
			}
			else
			{
				AddHotkeyBepInExInternal(hotkeyName, ((KeyboardShortcut)(ref value2)).MainKey, modifiers, inputState, hotkeyContext, cooldownMillis, action, null, hotkeyConfig);
			}
		}

		public override bool TryAddHotkey(string hotkeyName, KeyCode keyCode, KeyCode[] modifiers, InputState inputState, HotkeyContext hotkeyContext, Action action)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return AddHotkeyBepInExInternal(hotkeyName, keyCode, modifiers, inputState, hotkeyContext, 65, action, null);
		}

		public override bool TryAddHotkey(string hotkeyName, KeyCode keyCode, KeyCode[] modifiers, InputState inputState, HotkeyContext hotkeyContext, int cooldownMillis, Action action)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return AddHotkeyBepInExInternal(hotkeyName, keyCode, modifiers, inputState, hotkeyContext, cooldownMillis, action, null);
		}

		public bool TryAddHotkey(string hotkeyName, KeyCode keyCode, KeyCode[] modifiers, InputState inputState, HotkeyContext hotkeyContext, Action action, string groupName)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return AddHotkeyBepInExInternal(hotkeyName, keyCode, modifiers, inputState, hotkeyContext, 65, action, groupName);
		}

		public bool TryAddHotkey(string hotkeyName, KeyCode keyCode, KeyCode[] modifiers, InputState inputState, HotkeyContext hotkeyContext, int cooldownMillis, Action action, string groupName)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return AddHotkeyBepInExInternal(hotkeyName, keyCode, modifiers, inputState, hotkeyContext, cooldownMillis, action, groupName);
		}

		protected bool AddHotkeyBepInExInternal(string hotkeyName, KeyCode keyCode, KeyCode[] modifiers, InputState inputState, HotkeyContext hotkeyContext, int cooldownMillis, Action action, string groupName, ConfigEntry<KeyboardShortcut> hotkeyConfig = null)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			HotkeyAddResult val = ((InputDetection)this).AddHotkeyInternal(hotkeyName, keyCode, modifiers, inputState, hotkeyContext, cooldownMillis, action, groupName);
			if (hotkeyConfig != null && (int)val != 2)
			{
				if (hotkeyConfig == null)
				{
					throw new InvalidOperationException("Tried to add config hotkey ");
				}
				configKeyPresses.Add(hotkeyName, hotkeyConfig);
			}
			return (int)val == 0;
		}

		public override bool ChangeHotkey(string hotkeyName, KeyCode keyCode, KeyCode[] modifiers)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return ChangeHotkeyBepInExInternal(hotkeyName, keyCode, modifiers, fromConfig: false);
		}

		protected bool ChangeHotkeyBepInExInternal(string hotkeyName, KeyCode keyCode, KeyCode[] modifiers, bool fromConfig)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (IsConfigManagedKeyPress(hotkeyName, out var _) && !fromConfig)
			{
				LogConfigManagedWarningMessage(hotkeyName);
				return false;
			}
			return ((InputDetection)this).ChangeHotkeyInternal(hotkeyName, keyCode, modifiers);
		}

		public override bool RemoveHotkey(string hotkeyName)
		{
			return RemoveHotkeyBepInExInternal(hotkeyName, null, fromConfig: false);
		}

		public override bool RemoveHotkeyGroup(string groupName)
		{
			return RemoveHotkeyBepInExInternal(null, groupName, fromConfig: false);
		}

		protected bool RemoveHotkeyBepInExInternal(string hotkeyName, string groupName, bool fromConfig)
		{
			if (!string.IsNullOrEmpty(hotkeyName))
			{
				return RemoveHotkeyFromName(hotkeyName, fromConfig);
			}
			if (!string.IsNullOrEmpty(groupName))
			{
				if (((InputDetection)this).NamedGroupsCache.TryGetValue(groupName, out var value))
				{
					bool flag = true;
					string[] array = value.ToArray();
					foreach (string hotkeyName2 in array)
					{
						flag &= RemoveHotkeyFromName(hotkeyName2, fromConfig);
					}
					return flag;
				}
				return false;
			}
			throw new ArgumentException("Both hotkeyName and groupName cant be empty.");
		}

		private bool RemoveHotkeyFromName(string hotkeyName, bool fromConfig)
		{
			ConfigEntry<KeyboardShortcut> configEntry;
			bool flag = IsConfigManagedKeyPress(hotkeyName, out configEntry);
			if (flag && !fromConfig)
			{
				LogConfigManagedWarningMessage(hotkeyName);
				return false;
			}
			bool flag2 = ((InputDetection)this).RemoveHotkeysInternal(hotkeyName, (string)null);
			if (flag && flag2)
			{
				configKeyPresses.Remove(hotkeyName);
			}
			return flag2;
		}

		public bool IsConfigManagedKeyPress(string hotkeyName, out ConfigEntry<KeyboardShortcut> configEntry)
		{
			return configKeyPresses.TryGetValue(hotkeyName, out configEntry);
		}

		private void LogConfigManagedWarningMessage(string hotkeyName)
		{
			TimeLogger.Logger.LogWarning("The hotkey '" + hotkeyName + "' is being automatically managed from the BepInEx settings and cant be manually handled.", (LogCategories)33554432);
		}
	}
}

BepInEx/plugins/es.damntry.SuperQoLity/Damntry.Globals.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Damntry.Utils.Collections.Queues.Interfaces;
using Damntry.Utils.ExtensionMethods;
using Damntry.Utils.Logging;
using Damntry.Utils.Reflection;
using Damntry.Utils.Tasks;
using Damntry.Utils.Tasks.AsyncDelay;
using Damntry.Utils.Tasks.TaskTimeout;
using Damntry.Utils.Timers.StopwatchImpl;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Damntry Globals")]
[assembly: AssemblyDescription("Utils usable in any type of project")]
[assembly: AssemblyCompany("Damntry")]
[assembly: AssemblyProduct("Damntry Globals")]
[assembly: AssemblyCopyright("Copyright © Damntry 2026")]
[assembly: AssemblyFileVersion("0.4.9.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("0.4.9.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 HighResolutionTimer
{
	public class HighResolutionTimer
	{
		public static readonly double TickLength = 1000f / (float)Stopwatch.Frequency;

		public static readonly double Frequency = Stopwatch.Frequency;

		public static bool IsHighResolution = Stopwatch.IsHighResolution;

		private volatile float _interval;

		private volatile bool _isRunning;

		private Thread _thread;

		public float Interval
		{
			get
			{
				return _interval;
			}
			set
			{
				if (value < 0f || float.IsNaN(value))
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_interval = value;
			}
		}

		public bool IsRunning => _isRunning;

		public bool UseHighPriorityThread { get; set; }

		public event EventHandler<HighResolutionTimerElapsedEventArgs> Elapsed;

		public HighResolutionTimer()
			: this(1f)
		{
		}

		public HighResolutionTimer(float interval)
		{
			Interval = interval;
		}

		public void Start()
		{
			if (!_isRunning)
			{
				_isRunning = true;
				_thread = new Thread(ExecuteTimer)
				{
					IsBackground = true
				};
				if (UseHighPriorityThread)
				{
					_thread.Priority = ThreadPriority.Highest;
				}
				_thread.Start();
			}
		}

		public void Stop(bool joinThread = true)
		{
			_isRunning = false;
			if (joinThread && Thread.CurrentThread != _thread)
			{
				_thread.Join();
			}
		}

		private void ExecuteTimer()
		{
			float num = 0f;
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			while (_isRunning)
			{
				num += _interval;
				double num2;
				while (true)
				{
					num2 = ElapsedHiRes(stopwatch);
					double num3 = (double)num - num2;
					if (num3 <= 0.0)
					{
						break;
					}
					if (num3 < 1.0)
					{
						Thread.SpinWait(10);
					}
					else if (num3 < 5.0)
					{
						Thread.SpinWait(100);
					}
					else if (num3 < 15.0)
					{
						Thread.Sleep(1);
					}
					else
					{
						Thread.Sleep(10);
					}
					if (!_isRunning)
					{
						return;
					}
				}
				double delay = num2 - (double)num;
				this.Elapsed?.Invoke(this, new HighResolutionTimerElapsedEventArgs(delay));
				if (!_isRunning)
				{
					return;
				}
				if (stopwatch.Elapsed.TotalHours >= 1.0)
				{
					stopwatch.Restart();
					num = 0f;
				}
			}
			stopwatch.Stop();
		}

		private static double ElapsedHiRes(Stopwatch stopwatch)
		{
			return (double)stopwatch.ElapsedTicks * TickLength;
		}
	}
	public class HighResolutionTimerElapsedEventArgs : EventArgs
	{
		public double Delay { get; }

		internal HighResolutionTimerElapsedEventArgs(double delay)
		{
			Delay = delay;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	public class IsExternalInit
	{
	}
}
namespace Damntry.Utils
{
	public static class EmbeddedReferenceResolve
	{
		public static Assembly LoadEmbeddedResource(byte[] resourceBytes)
		{
			if (resourceBytes == null || resourceBytes.Length == 0)
			{
				throw new ArgumentException("Argument resourceBytes cant be null or empty");
			}
			Assembly assembly = Assembly.Load(resourceBytes);
			if (assembly == null)
			{
				throw new InvalidOperationException("A dll resource could not be loaded.");
			}
			return assembly;
		}

		public static void LoadAssemblyFromResources(params string[] resourceNames)
		{
			if (resourceNames == null || resourceNames.Length == 0)
			{
				throw new ArgumentException("Argument resourceNames cant be null or empty");
			}
			foreach (string text in resourceNames)
			{
				if (ResolveFromResourceName(Assembly.GetCallingAssembly(), text) == null)
				{
					throw new InvalidOperationException("The dll resource '" + text + "' could not be loaded. Make sure it is added to the resources of the assembly you are calling from.");
				}
			}
		}

		private static Assembly ResolveFromResourceName(Assembly assembly, string resourceName)
		{
			using Stream stream = assembly.GetManifestResourceStream(resourceName);
			byte[] array = new byte[(int)stream.Length];
			stream.Read(array, 0, (int)stream.Length);
			return Assembly.Load(array);
		}
	}
}
namespace Damntry.Utils.Timers
{
	public class PeriodicTimeLimitedCounter<T> where T : IStopwatch, new()
	{
		private IStopwatch swLimitHit;

		private bool constantPeriodTimer;

		private int hitCounter;

		private int hitCounterMax;

		private double maxPeriodTimeMillis;

		private bool triggerOncePerPeriod;

		public PeriodicTimeLimitedCounter(bool constantPeriodTimer, int hitCounterMax, double maxPeriodTimeMillis, bool ignoreFirstHit, bool triggerOncePerPeriod = true)
		{
			this.constantPeriodTimer = constantPeriodTimer;
			this.hitCounterMax = hitCounterMax;
			this.maxPeriodTimeMillis = maxPeriodTimeMillis;
			hitCounter = (ignoreFirstHit ? (-1) : 0);
			this.triggerOncePerPeriod = triggerOncePerPeriod;
			swLimitHit = new T();
		}

		public bool TryIncreaseCounter()
		{
			bool flag = false;
			bool flag2 = false;
			hitCounter++;
			if (swLimitHit.ElapsedMillisecondsPrecise <= maxPeriodTimeMillis)
			{
				if (!constantPeriodTimer)
				{
					flag = true;
				}
				flag2 = (triggerOncePerPeriod ? (hitCounter == hitCounterMax) : (hitCounter >= hitCounterMax));
			}
			else
			{
				flag = true;
			}
			if (flag)
			{
				swLimitHit.Restart();
				hitCounter = 0;
			}
			if (!swLimitHit.IsRunning)
			{
				swLimitHit.Start();
			}
			return !flag2;
		}

		public void StartTime()
		{
			swLimitHit.Restart();
		}

		public void ResetAll()
		{
			hitCounter = 0;
			swLimitHit.Reset();
		}
	}
}
namespace Damntry.Utils.Timers.StopwatchImpl
{
	public interface IStopwatch
	{
		bool IsRunning { get; }

		long ElapsedMilliseconds { get; }

		long ElapsedSeconds { get; }

		double ElapsedMillisecondsPrecise { get; }

		double ElapsedSecondsPrecise { get; }

		void Start();

		void Stop();

		void Reset();

		void Restart();
	}
	public class StopwatchDiag : Stopwatch, IStopwatch
	{
		public long ElapsedSeconds => base.ElapsedMilliseconds * 1000;

		public double ElapsedMillisecondsPrecise => base.Elapsed.TotalMilliseconds;

		public double ElapsedSecondsPrecise => base.Elapsed.TotalSeconds;

		public new static StopwatchDiag StartNew()
		{
			StopwatchDiag stopwatchDiag = new StopwatchDiag();
			stopwatchDiag.Start();
			return stopwatchDiag;
		}

		bool IStopwatch.get_IsRunning()
		{
			return base.IsRunning;
		}

		long IStopwatch.get_ElapsedMilliseconds()
		{
			return base.ElapsedMilliseconds;
		}

		void IStopwatch.Start()
		{
			Start();
		}

		void IStopwatch.Stop()
		{
			Stop();
		}

		void IStopwatch.Reset()
		{
			Reset();
		}

		void IStopwatch.Restart()
		{
			Restart();
		}
	}
}
namespace Damntry.Utils.Tasks
{
	public class CancellableSingleTask<T> where T : AsyncDelayBase<T>
	{
		private SemaphoreSlim semaphoreLock;

		private Task task;

		private string taskLogName;

		private CancellationTokenSource cancelTokenSource;

		private bool isSemaphoreAcquiredManually;

		private bool logEvents;

		private int maxExternalSemaphoreAcquireTimeMillis;

		public bool IsTaskRunning
		{
			get
			{
				if (task != null)
				{
					return task.Status < TaskStatus.RanToCompletion;
				}
				return false;
			}
		}

		public bool IsCancellationRequested
		{
			get
			{
				if (cancelTokenSource != null)
				{
					return cancelTokenSource.IsCancellationRequested;
				}
				return false;
			}
		}

		public CancellationToken CancellationToken
		{
			get
			{
				if (cancelTokenSource != null)
				{
					return cancelTokenSource.Token;
				}
				throw new InvalidOperationException("There is no cancellation token as no task has been started.");
			}
		}

		public CancellableSingleTask(bool logEvents = true)
		{
			this.logEvents = logEvents;
			semaphoreLock = new SemaphoreSlim(1, 1);
			isSemaphoreAcquiredManually = false;
		}

		public async Task StartTaskAsync(Func<Task> asyncWorkerFunction, string taskLogName, bool throwExceptionIfRunning)
		{
			await StartTaskAsync(asyncWorkerFunction, taskLogName, awaitTask: false, throwExceptionIfRunning, newThread: false);
		}

		public async Task StartThreadedTaskAsync(Func<Task> asyncWorkerFunction, string taskLogName, bool throwExceptionIfRunning)
		{
			await StartTaskAsync(asyncWorkerFunction, taskLogName, awaitTask: false, throwExceptionIfRunning, newThread: true);
		}

		public async Task StartThreadedTaskAsync(Action workerFunction, string taskLogName, bool throwExceptionIfRunning)
		{
			await StartTaskAsync(delegate
			{
				workerFunction();
				return Task.CompletedTask;
			}, taskLogName, awaitTask: false, throwExceptionIfRunning, newThread: true);
		}

		public async Task StartAwaitableTaskAsync(Func<Task> asyncWorkerFunction, string taskLogName, bool throwExceptionIfRunning)
		{
			await StartTaskAsync(asyncWorkerFunction, taskLogName, awaitTask: true, throwExceptionIfRunning, newThread: false);
		}

		public async Task StartAwaitableThreadedTaskAsync(Func<Task> asyncWorkerFunction, string taskLogName, bool throwExceptionIfRunning)
		{
			await StartTaskAsync(asyncWorkerFunction, taskLogName, awaitTask: true, throwExceptionIfRunning, newThread: true);
		}

		private async Task StartTaskAsync(Func<Task> asyncWorkerFunction, string taskLogName, bool awaitTask, bool throwIfAlreadyRunning, bool newThread)
		{
			await GetSemaphoreLock();
			try
			{
				if (task != null && !task.IsCompleted)
				{
					if (throwIfAlreadyRunning)
					{
						throw new InvalidOperationException(GetTextAlreadyRunningTask(taskLogName));
					}
					if (logEvents)
					{
						TimeLogger.Logger.LogDebugFunc(() => GetTextAlreadyRunningTask(taskLogName), LogCategories.Task);
					}
					return;
				}
				this.taskLogName = taskLogName;
				cancelTokenSource = new CancellationTokenSource();
				if (logEvents)
				{
					TimeLogger.Logger.LogDebugFunc(() => "Task \"" + taskLogName + "\" is now going to run " + (newThread ? "in a new thread" : "asynchronously") + ".", LogCategories.Task);
				}
				if (newThread)
				{
					task = Task.Run(() => asyncWorkerFunction());
				}
				else
				{
					task = asyncWorkerFunction();
				}
			}
			finally
			{
				semaphoreLock.Release();
			}
			if (awaitTask)
			{
				await task;
			}
			else
			{
				task.FireAndForgetCancels(LogCategories.Task);
			}
		}

		private string GetTextAlreadyRunningTask(string taskLogName)
		{
			StringBuilder stringBuilder = new StringBuilder(25);
			if (this.taskLogName != taskLogName)
			{
				stringBuilder.Append("Cant start task \"");
				stringBuilder.Append(taskLogName);
				stringBuilder.Append("\": ");
			}
			stringBuilder.Append("Task \"");
			stringBuilder.Append(this.taskLogName);
			stringBuilder.Append("\" is already running.");
			return stringBuilder.ToString();
		}

		public async Task StopTaskAndWaitAsync()
		{
			await StopTaskAndWaitAsync(null, null, -1);
		}

		public async Task StopTaskAndWaitAsync(int maxStopTimeMillis)
		{
			await StopTaskAndWaitAsync(null, null, maxStopTimeMillis);
		}

		public async Task StopTaskAndWaitAsync(Action onTaskStopped, int maxStopTimeMillis)
		{
			await StopTaskAndWaitAsync(onTaskStopped, null, maxStopTimeMillis);
		}

		public async Task StopTaskAndWaitAsync(Func<Task> onTaskStoppedAsync, int maxStopTimeMillis)
		{
			await StopTaskAndWaitAsync(null, onTaskStoppedAsync, maxStopTimeMillis);
		}

		private async Task StopTaskAndWaitAsync(Action onTaskStopped, Func<Task> onTaskStoppedAsync, int maxStopTimeMillis)
		{
			await GetSemaphoreLock();
			try
			{
				Task obj = new Task(async delegate
				{
					if (task == null)
					{
						if (logEvents)
						{
							TimeLogger.Logger.LogDebugFunc(() => "Cant stop task \"" + taskLogName + "\". It was never started, or already stopped.", LogCategories.Task);
						}
					}
					else
					{
						if (cancelTokenSource != null && !task.IsTaskEnded())
						{
							if (logEvents)
							{
								TimeLogger.Logger.LogDebugFunc(() => "Canceling task \"" + taskLogName + "\"", LogCategories.Task);
							}
							cancelTokenSource.Cancel();
						}
						else if (logEvents)
						{
							TimeLogger.Logger.LogDebugFunc(() => "Cant stop task \"" + taskLogName + "\". It is already finished.", LogCategories.Task);
						}
						try
						{
							await task;
						}
						catch (Exception ex)
						{
							if (!(ex is TaskCanceledException) && !(ex is OperationCanceledException))
							{
								throw;
							}
							if (logEvents)
							{
								TimeLogger.Logger.LogDebugFunc(() => "Task \"" + taskLogName + "\" successfully canceled.", LogCategories.Task);
							}
						}
						task.Dispose();
						task = null;
						if (onTaskStopped != null)
						{
							onTaskStopped();
						}
						if (onTaskStoppedAsync != null)
						{
							await onTaskStoppedAsync();
						}
					}
				});
				obj.Start();
				await TaskTimeoutMethods<T>.AwaitTaskWithTimeoutAsync(obj, taskLogName, maxStopTimeMillis, throwTimeoutException: true);
			}
			finally
			{
				semaphoreLock.Release();
			}
		}

		private async Task GetSemaphoreLock()
		{
			int millisecondsTimeout = -1;
			if (isSemaphoreAcquiredManually)
			{
				millisecondsTimeout = maxExternalSemaphoreAcquireTimeMillis;
			}
			if (!(await semaphoreLock.WaitAsync(millisecondsTimeout)))
			{
				throw new ExternalSemaphoreHeldException("The operation could not complete because the semaphore was held externally for too long.");
			}
		}

		public async Task WaitSemaphoreAsync(int maxSemaphoreAcquireTimeMillis)
		{
			await WaitSemaphoreTimeoutAsync(-1, maxSemaphoreAcquireTimeMillis);
		}

		public async Task<bool> WaitSemaphoreTimeoutAsync(int millisecondTimeout, int maxSemaphoreAcquireTimeMillis)
		{
			if (isSemaphoreAcquiredManually)
			{
				throw new InvalidOperationException("Semaphore lock has already been manually acquired. You must release it first by calling ReleaseSemaphore().");
			}
			maxExternalSemaphoreAcquireTimeMillis = maxSemaphoreAcquireTimeMillis;
			isSemaphoreAcquiredManually = await semaphoreLock.WaitAsync(millisecondTimeout);
			return isSemaphoreAcquiredManually;
		}

		public void ReleaseSemaphore()
		{
			if (isSemaphoreAcquiredManually)
			{
				isSemaphoreAcquiredManually = false;
				semaphoreLock.Release();
				return;
			}
			throw new InvalidOperationException("No lock for the semaphore was acquired manually. Call WaitSemaphoreAsync() first.");
		}
	}
	public class ExternalSemaphoreHeldException : Exception
	{
		public ExternalSemaphoreHeldException()
		{
		}

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

		public ExternalSemaphoreHeldException(string message, Exception inner)
			: base(message, inner)
		{
		}
	}
	public class DelayedSingleTask<T> where T : AsyncDelayBase<T>
	{
		private Task delayedTask;

		private CancellationTokenSource taskCancel;

		private Action actionTask;

		public DelayedSingleTask(Action actionTask)
		{
			if (actionTask == null)
			{
				throw new ArgumentNullException("actionTask");
			}
			this.actionTask = actionTask;
			taskCancel = new CancellationTokenSource();
		}

		public async void Start(int delayMillis)
		{
			if (delayedTask != null && !delayedTask.IsCompleted && !delayedTask.IsCanceled)
			{
				taskCancel.Cancel();
				try
				{
					await delayedTask;
				}
				catch (Exception ex)
				{
					if (!(ex is TaskCanceledException) && !(ex is OperationCanceledException) && !(ex is ThreadAbortException))
					{
						TimeLogger.Logger.LogExceptionWithMessage("Exception while starting and executing delayed task.", ex, LogCategories.Task);
					}
				}
				taskCancel = new CancellationTokenSource();
			}
			delayedTask = StartDelayedCancellableTask(delayMillis);
			delayedTask.FireAndForgetCancels(LogCategories.Task, dismissCancelLog: true);
		}

		private async Task StartDelayedCancellableTask(int delayMillis)
		{
			await AsyncDelayBase<T>.Instance.Delay(delayMillis, taskCancel.Token);
			if (!taskCancel.IsCancellationRequested)
			{
				actionTask();
			}
		}
	}
}
namespace Damntry.Utils.Tasks.TaskTimeout
{
	public class TaskTimeout<T> where T : AsyncDelayBase<T>
	{
		public static async Task StartAwaitableTaskWithTimeoutAsync(Func<CancellationToken, Task> asyncWorkerFunction, string taskLogName, int maxCompletionTimeMillis)
		{
			await StartTaskStaticAndWaitWithTimeoutAsync(asyncWorkerFunction, taskLogName, newThread: false, maxCompletionTimeMillis);
		}

		public static async Task StartAwaitableThreadedTaskWithTimeoutAsync(Func<CancellationToken, Task> asyncWorkerFunction, string taskLogName, int maxCompletionTimeMillis)
		{
			await StartTaskStaticAndWaitWithTimeoutAsync(asyncWorkerFunction, taskLogName, newThread: true, maxCompletionTimeMillis);
		}

		private static async Task StartTaskStaticAndWaitWithTimeoutAsync(Func<CancellationToken, Task> asyncWorkerFunction, string taskLogName, bool newThread, int maxCompletionTimeMillis)
		{
			TimeLogger.Logger.LogDebugFunc(() => "Task \"" + taskLogName + "\" is now going to run " + (newThread ? "in a new thread" : "asynchronously") + ".", LogCategories.Task);
			CancellationTokenSource cancelWorker = new CancellationTokenSource();
			Task workTask = ((!newThread) ? asyncWorkerFunction(cancelWorker.Token) : Task.Run(() => asyncWorkerFunction(cancelWorker.Token)));
			if (!(await TaskTimeoutMethods<T>.AwaitTaskWithTimeoutAsync(workTask, taskLogName, maxCompletionTimeMillis, throwTimeoutException: false)))
			{
				cancelWorker.Cancel();
				await workTask;
				throw new TimeoutException("Task \"" + taskLogName + "\" is finished but it took longer than " + maxCompletionTimeMillis + "ms.");
			}
		}
	}
	internal class TaskTimeoutMethods<T> where T : AsyncDelayBase<T>
	{
		internal static async Task<bool> AwaitTaskWithTimeoutAsync(Task task, string taskLogName, int maxStopTimeMillis, bool throwTimeoutException)
		{
			CancellationTokenSource cancelDelay = new CancellationTokenSource();
			try
			{
				await AwaitTaskWithTimeoutAsync(task, taskLogName, maxStopTimeMillis, cancelDelay.Token);
				if (!task.IsCompleted)
				{
					if (throwTimeoutException)
					{
						throw new TimeoutException($"Task \"{taskLogName}\" took longer than the specified {maxStopTimeMillis} ms to stop.");
					}
					return false;
				}
				return true;
			}
			finally
			{
				cancelDelay.Cancel();
			}
		}

		private static async Task AwaitTaskWithTimeoutAsync(Task task, string taskLogName, int maxStopTimeMillis, CancellationToken cancelToken)
		{
			try
			{
				await Task.WhenAny(new Task[2]
				{
					task,
					AsyncDelayBase<T>.Instance.Delay(maxStopTimeMillis, cancelToken)
				});
			}
			catch (Exception ex)
			{
				if (ex is TaskCanceledException || ex is OperationCanceledException)
				{
					TimeLogger.Logger.LogDebugFunc(() => "Task \"" + taskLogName + "\" successfully canceled.", LogCategories.Task);
					return;
				}
				throw;
			}
		}
	}
}
namespace Damntry.Utils.Tasks.AsyncDelay
{
	public class AsyncDelay : AsyncDelayBase<AsyncDelay>
	{
		public override Task Delay(int millisecondsDelay)
		{
			return Task.Delay(millisecondsDelay);
		}

		public override Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
		{
			return Task.Delay(millisecondsDelay, cancellationToken);
		}
	}
	public abstract class AsyncDelayBase<T> where T : AsyncDelayBase<T>
	{
		private static AsyncDelayBase<T> instance = Activator.CreateInstance<T>();

		public static AsyncDelayBase<T> Instance => instance;

		public abstract Task Delay(int millisecondsDelay);

		public abstract Task Delay(int millisecondsDelay, CancellationToken cancellationToken);
	}
}
namespace Damntry.Utils.Reflection
{
	public static class AssemblyUtils
	{
		private static Assembly[] assemblyCache;

		public static MethodInfo GetMethodFromLoadedAssembly(string fullTypeName, string methodName, bool refreshCache = true)
		{
			return GetTypeFromLoadedAssemblies(fullTypeName, refreshCache).GetMethod(methodName, ReflectionHelper.AllBindings);
		}

		public static Type GetTypeFromLoadedAssemblies(string fullTypeName, bool refreshCache = true)
		{
			if (refreshCache || assemblyCache == null)
			{
				assemblyCache = AppDomain.CurrentDomain.GetAssemblies();
			}
			return (from a in assemblyCache
				select a.GetType(fullTypeName, throwOnError: false) into t
				where t != null
				select t).FirstOrDefault();
		}

		public static Type[] GetTypesFromLoadedAssemblies(bool refreshCache, params string[] argumentFullTypeNames)
		{
			if (argumentFullTypeNames == null)
			{
				return null;
			}
			bool flag = true;
			List<Type> list = new List<Type>(argumentFullTypeNames.Length);
			foreach (string text in argumentFullTypeNames)
			{
				Type typeFromLoadedAssemblies = GetTypeFromLoadedAssemblies(text, flag && refreshCache);
				if (typeFromLoadedAssemblies == null)
				{
					throw new ArgumentException("The type with value \"" + text + "\" couldnt be found in the assembly.");
				}
				list.Add(typeFromLoadedAssemblies);
				flag = false;
			}
			return list?.ToArray();
		}

		public static string GetAssemblyDllFilePath(Type assemblyType)
		{
			return Assembly.GetAssembly(assemblyType).Location;
		}

		public static string GetAssemblyDllFolderPath(Type assemblyType)
		{
			return Path.GetDirectoryName(GetAssemblyDllFilePath(assemblyType));
		}

		public static string GetCombinedPathFromAssemblyFolder(Type assemblyType, string addedPath)
		{
			string text = GetAssemblyDllFolderPath(assemblyType);
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			if (!addedPath.StartsWith(directorySeparatorChar.ToString()))
			{
				string text2 = text;
				directorySeparatorChar = Path.DirectorySeparatorChar;
				text = text2 + directorySeparatorChar;
			}
			return text + addedPath;
		}
	}
	public class MemberInfoHelper : MemberInfo
	{
		private readonly MemberInfo member;

		private FieldInfo Field => (FieldInfo)member;

		private PropertyInfo Property => (PropertyInfo)member;

		public bool IsStatic => member.MemberType switch
		{
			MemberTypes.Field => Field.IsStatic, 
			MemberTypes.Property => Property.IsStatic(), 
			_ => throw new NotImplementedException(), 
		};

		public Type MemberInfoType => member.MemberType switch
		{
			MemberTypes.Field => Field.FieldType, 
			MemberTypes.Property => Property.PropertyType, 
			_ => throw new NotImplementedException(), 
		};

		public override MemberTypes MemberType => member.MemberType;

		public override string Name => member.Name;

		public override Type DeclaringType => member.DeclaringType;

		public override Type ReflectedType => member.ReflectedType;

		public MemberInfoHelper(MemberInfo memberInfo)
		{
			if (memberInfo == null)
			{
				throw new ArgumentNullException("member");
			}
			if (!(memberInfo is FieldInfo) && !(memberInfo is PropertyInfo))
			{
				throw new NotSupportedException("Only FieldInfo and PropertyInfo members are supported.");
			}
			member = memberInfo;
		}

		public void SetValue(object obj, object value)
		{
			if (member.MemberType == MemberTypes.Field)
			{
				Field.SetValue(obj, value);
			}
			else if (member.MemberType == MemberTypes.Property)
			{
				Property.SetValue(obj, value);
			}
		}

		public object GetValue(object obj)
		{
			if (member.MemberType == MemberTypes.Field)
			{
				return Field.GetValue(obj);
			}
			if (member.MemberType == MemberTypes.Property)
			{
				return Property.GetValue(obj);
			}
			throw new NotImplementedException();
		}

		public object GetValueStaticAgnostic(object obj)
		{
			obj = (IsStatic ? null : obj);
			if (member.MemberType == MemberTypes.Field)
			{
				return Field.GetValue(obj);
			}
			if (member.MemberType == MemberTypes.Property)
			{
				return Property.GetValue(obj);
			}
			throw new NotImplementedException();
		}

		public override object[] GetCustomAttributes(bool inherit)
		{
			return member.GetCustomAttributes(inherit);
		}

		public override object[] GetCustomAttributes(Type attributeType, bool inherit)
		{
			return member.GetCustomAttributes(attributeType, inherit);
		}

		public override bool IsDefined(Type attributeType, bool inherit)
		{
			return member.IsDefined(attributeType, inherit);
		}
	}
	public static class ReflectionHelper
	{
		public enum MemberType
		{
			Property,
			Field,
			Both
		}

		public static BindingFlags AllBindings { get; } = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty;


		public static void CallMethod(object classInstance, string methodName, object[] args = null)
		{
			CallMethod<object>(classInstance, methodName, args);
		}

		public static R CallStaticMethod<R>(Type classType, string methodName, object[] args = null)
		{
			return CallMethod<R>(null, classType, methodName, args);
		}

		public static R CallMethod<R>(object classInstance, string methodName, object[] args = null)
		{
			return CallMethod<R>(classInstance, classInstance.GetType(), methodName, args);
		}

		private static R CallMethod<R>(object classInstance, Type classType, string methodName, object[] args = null)
		{
			MethodInfo method = classType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			return CallMethod<R>(classInstance, method, args);
		}

		public static R CallMethod<R>(object classInstance, MethodInfo methodInfo, object[] args = null)
		{
			try
			{
				return (R)methodInfo.Invoke(classInstance, args);
			}
			catch (TargetParameterCountException e)
			{
				TimeLogger.Logger.LogExceptionWithMessage("Parameter count error while calling method " + methodInfo.Name, e, LogCategories.Reflect);
				throw;
			}
		}

		public static string ListMemberValues(object target, MemberType memberType, bool showPrivate = true)
		{
			BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
			if (showPrivate)
			{
				bindingFlags |= BindingFlags.NonPublic;
			}
			StringBuilder sbMembers = new StringBuilder();
			MemberInfo[] array = Array.Empty<MemberInfo>();
			if (memberType == MemberType.Both || memberType == MemberType.Property)
			{
				MemberInfo[] properties = target.GetType().GetProperties(bindingFlags);
				array = properties;
			}
			if (memberType == MemberType.Both || memberType == MemberType.Field)
			{
				if (array.Length != 0)
				{
					array = array.Concat(target.GetType().GetFields(bindingFlags)).ToArray();
				}
				else
				{
					MemberInfo[] properties = target.GetType().GetFields(bindingFlags);
					array = properties;
				}
			}
			Array.ForEach(array, delegate(MemberInfo minfo)
			{
				sbMembers.Append(minfo.Name);
				sbMembers.Append(" = ");
				if (minfo is PropertyInfo)
				{
					sbMembers.Append(((PropertyInfo)minfo).GetValue(target, null));
				}
				else if (minfo is FieldInfo)
				{
					sbMembers.Append(((FieldInfo)minfo).GetValue(target));
				}
				sbMembers.AppendLine();
			});
			return sbMembers.ToString();
		}

		public static string ConvertFullTypeToNormal(string type)
		{
			if (string.IsNullOrEmpty(type) || !type.Contains("."))
			{
				return type;
			}
			return type.Substring(type.LastIndexOf(".") + 1);
		}

		public static string[] ConvertFullTypesToNormal(params string[] types)
		{
			string[] result = null;
			if (types == null || !types.Any())
			{
				result = types.Select((string s) => ConvertFullTypeToNormal(s)).ToArray();
			}
			return result;
		}

		public static object GetDefaultValue(this Type type)
		{
			return FormatterServices.GetUninitializedObject(type);
		}
	}
}
namespace Damntry.Utils.Numerics
{
	public class RollingIntegerRange
	{
		[CompilerGenerated]
		private int <minValueInclusive>P;

		[CompilerGenerated]
		private int <maxValueInclusive>P;

		[CompilerGenerated]
		private int <step>P;

		private int currentValue;

		public RollingIntegerRange(int minValueInclusive, int maxValueInclusive, int step = 1)
		{
			<minValueInclusive>P = minValueInclusive;
			<maxValueInclusive>P = maxValueInclusive;
			<step>P = step;
			base..ctor();
		}

		public int GetNextValue()
		{
			currentValue += <step>P;
			if (currentValue > <maxValueInclusive>P)
			{
				currentValue = <minValueInclusive>P;
			}
			else if (currentValue < <minValueInclusive>P)
			{
				currentValue = <maxValueInclusive>P;
			}
			return currentValue;
		}
	}
}
namespace Damntry.Utils.Maths
{
	public static class MathMethods
	{
		public static ulong GreatestCommonDivisor(ulong n1, ulong n2)
		{
			while (n1 != 0L && n2 != 0L)
			{
				if (n1 > n2)
				{
					n1 %= n2;
				}
				else
				{
					n2 %= n1;
				}
			}
			return n1 | n2;
		}

		public static int CountDigits(uint num)
		{
			if ((long)num != 0L)
			{
				return (((long)num > 0L) ? 1 : 2) + (int)Math.Log10(Math.Abs((double)num));
			}
			return 1;
		}

		public static int CountDigits(int num)
		{
			return CountDigits((uint)num);
		}
	}
}
namespace Damntry.Utils.Logging
{
	public class LOG
	{
		public static void TEMPDEBUG(string message, bool onlyIfTrue = true)
		{
		}

		public static void TEMPDEBUG_FUNC(Func<string> textLambda, bool onlyIfTrue = true)
		{
		}

		public static void Debug(string message, LogCategories logCategory, bool onlyIfTrue = true)
		{
		}

		public static void Debug_func(Func<string> textLambda, LogCategories logCategory, bool onlyIfTrue = true)
		{
		}

		public static void TEMPWARNING(string message, bool onlyIfTrue = true)
		{
		}

		public static void TEMPWARNING_FUNC(Func<string> textLambda, bool onlyIfTrue = true)
		{
		}

		public static void TEMPFATAL(string message, bool onlyIfTrue = true)
		{
		}

		public static void TEMP(LogTier logLevel, string message, bool onlyIfTrue = true)
		{
		}

		private static void Log(LogTier logLevel, string message, bool onlyIfTrue = true, LogCategories logCategory = LogCategories.TempTest)
		{
		}

		private static void LogFunc(LogTier logLevel, Func<string> textLambda, bool onlyIfTrue = true, LogCategories logCategory = LogCategories.TempTest)
		{
		}
	}
	public sealed class DefaultTimeLogger : TimeLogger
	{
		protected override void InitializeLogger(params object[] args)
		{
		}

		protected override void LogMessage(string message, LogTier logLevel)
		{
			ConsoleColor consoleColor = ConsoleColor.Gray;
			switch (logLevel)
			{
			case LogTier.All:
				consoleColor = ConsoleColor.White;
				break;
			case LogTier.Debug:
				consoleColor = ConsoleColor.DarkGray;
				break;
			case LogTier.Info:
				consoleColor = ConsoleColor.Gray;
				break;
			case LogTier.Warning:
				consoleColor = ConsoleColor.Yellow;
				break;
			case LogTier.Error:
				consoleColor = ConsoleColor.DarkRed;
				break;
			case LogTier.Fatal:
				consoleColor = ConsoleColor.Red;
				break;
			case LogTier.Message:
				consoleColor = ConsoleColor.Gray;
				break;
			case LogTier.None:
				return;
			default:
				throw new InvalidOperationException("Invalid log level.");
			}
			Console.ForegroundColor = consoleColor;
			Console.WriteLine(message);
			Console.ResetColor();
		}
	}
	public static class Performance
	{
		private enum StopResetAction
		{
			Stop,
			Reset,
			Record,
			Log
		}

		public static class PerformanceFileLoggingMethods
		{
			public static async Task BeginOrResumePerfFileLoggingWithTextFunc(Func<string> getFirstPerfLogLineFunc)
			{
				if (TimeLogger.DebugEnabled)
				{
					string firstPerfLogText = null;
					if (getFirstPerfLogLineFunc != null)
					{
						firstPerfLogText = getFirstPerfLogLineFunc();
					}
					await PerfLogger.DLog.BeginPerfFileLoggingWithText(firstPerfLogText);
				}
			}

			public static async Task BeginOrResumePerfFileLoggingWithText(string firstPerfLogLine)
			{
				if (TimeLogger.DebugEnabled)
				{
					await PerfLogger.DLog.BeginPerfFileLoggingWithText(firstPerfLogLine);
				}
			}

			public static async Task BeginOrResumePerfFileLogging()
			{
				if (TimeLogger.DebugEnabled)
				{
					await PerfLogger.DLog.BeginPerfFileLoggingWithText(null);
				}
			}

			public static async Task StopPerfFileLogging()
			{
				if (PerfLogger.IsInstanced)
				{
					await PerfLogger.DLog.StopPerfFileLogging();
				}
			}
		}

		public static class PerformanceTableLoggingMethods
		{
			public static async Task StartLogPerformanceTableNewThread(int logTableIntervalMillis)
			{
				await logTableTask.StartThreadedTaskAsync(() => LogPerformanceTableInterval(logTableIntervalMillis), "Logger performance table", throwExceptionIfRunning: true);
			}

			public static async Task StopThreadLogPerformanceTable()
			{
				await logTableTask.StopTaskAndWaitAsync(5000);
			}

			public static void LogPerformanceTable()
			{
				Performance.LogPerformanceTable();
			}
		}

		private class StopwatchMeasure : Stopwatch
		{
			private string name;

			private bool showTotals;

			private double lastRunMilli;

			private int runCount;

			private double min;

			private double max;

			private TrimmedMean trimmedMean;

			public double TotalMilli { get; private set; }

			public StopwatchMeasure(string measureName, bool showTotals)
			{
				this.showTotals = showTotals;
				name = measureName;
				trimmedMean = new TrimmedMean();
				initializeMeasure();
			}

			private void initializeMeasure()
			{
				TotalMilli = 0.0;
				runCount = 0;
				min = 2147483647.0;
				max = 0.0;
				trimmedMean.Initialize();
			}

			[Obsolete("Use Start(resetRunValues) instead.", true)]
			public new void Start()
			{
			}

			public void Start(bool resetRunValues)
			{
				if (resetRunValues)
				{
					initializeMeasure();
				}
				base.Start();
			}

			public void RecordRun()
			{
				lastRunMilli = base.Elapsed.TotalMilliseconds;
				if (showTotals)
				{
					TotalMilli += lastRunMilli;
					runCount++;
					if (lastRunMilli < min)
					{
						min = lastRunMilli;
					}
					if (lastRunMilli > max)
					{
						max = lastRunMilli;
					}
					trimmedMean.addNewValue(lastRunMilli);
				}
				Reset();
			}

			public string GetLogString()
			{
				string text = $"{name} has taken {lastRunMilli:F3} ms";
				if (showTotals)
				{
					text += $", with a total of {TotalMilli:F3}ms spent in {runCount} run/s. Avg run: {GetAverageRun(formatTiming: false)}ms, Min: {min:F3}ms, Max: {max:F3}ms";
				}
				return text + ".";
			}

			public (string name, string total, string runs, string avg, string meanTrim, string min, string max) GetFormattedRunValues(int measureNameMaxLength)
			{
				return (name.PadRight(measureNameMaxLength), FormatTiming(TotalMilli), ((base.IsRunning ? "*" : "") + runCount).PadLeft(RunCountPadding), GetAverageRun(formatTiming: true), GetMeanTrimmedRun(), FormatTiming(min), FormatTiming(max));
			}

			private string GetAverageRun(bool formatTiming)
			{
				double number = Math.Round(TotalMilli / (double)runCount, MeasureDecimals);
				if (!formatTiming)
				{
					return number.ToString();
				}
				return FormatTiming(number);
			}

			private string GetMeanTrimmedRun()
			{
				string result = "";
				(double, TrimmedMean.CalculationResult) tuple = trimmedMean.GetTrimmedMean();
				if (tuple.Item2 == TrimmedMean.CalculationResult.NotEnoughData)
				{
					result = "*Collecting*".PadSides(MeasureTimingsPadding);
				}
				else if (tuple.Item2 == TrimmedMean.CalculationResult.Partial)
				{
					result = FormatTiming(tuple.Item1, "~");
				}
				else if (tuple.Item2 == TrimmedMean.CalculationResult.Full)
				{
					result = FormatTiming(tuple.Item1);
				}
				return result;
			}

			private string FormatTiming(double number, string leftSymbol = null)
			{
				string text = string.Format($"{{0:F{MeasureDecimals}}}ms", number);
				return (((leftSymbol != null) ? leftSymbol : "") + text).PadLeft(MeasureTimingsPadding);
			}
		}

		private class TrimmedMean
		{
			public enum CalculationResult
			{
				NotEnoughData,
				Partial,
				Full
			}

			private List<double> historyValues;

			private int rollingIndex;

			private readonly int maxNumValues;

			private readonly int minNumValues;

			private readonly int trimPercentage;

			public TrimmedMean(int minValuesHistoric = 5, int maxValuesHistoric = 30, int trimPercentage = 5)
			{
				if (minValuesHistoric > maxValuesHistoric)
				{
					throw new ArgumentException("minValuesHistoric must be less or equal than maxValuesHistoric.");
				}
				minNumValues = minValuesHistoric.ClampReturn(5, int.MaxValue);
				maxNumValues = maxValuesHistoric.ClampReturn(5, int.MaxValue);
				this.trimPercentage = trimPercentage.ClampReturn(0, 99);
				Initialize();
			}

			public void Initialize()
			{
				if (historyValues == null)
				{
					historyValues = new List<double>(maxNumValues);
				}
				else
				{
					historyValues.Clear();
				}
				rollingIndex = 0;
			}

			public void addNewValue(double value)
			{
				if (historyValues.Count > maxNumValues)
				{
					throw new InvalidOperationException("The trimmed mean cant contain more values that the specified limit.");
				}
				if (historyValues.Count == maxNumValues)
				{
					historyValues[rollingIndex] = value;
				}
				else
				{
					historyValues.Add(value);
				}
				rollingIndex++;
				if (rollingIndex >= maxNumValues)
				{
					rollingIndex = 0;
				}
			}

			public (double trimmedMean, CalculationResult calcResult) GetTrimmedMean()
			{
				CalculationResult item = CalculationResult.NotEnoughData;
				if (historyValues.Count < minNumValues)
				{
					return (0.0, item);
				}
				item = ((historyValues.Count < maxNumValues) ? CalculationResult.Partial : CalculationResult.Full);
				List<double> list = new List<double>(historyValues);
				list.Sort();
				int num = (int)Math.Round((double)maxNumValues * ((double)trimPercentage / 100.0), 0);
				double num2 = 0.0;
				for (int i = num; i < list.Count - num; i++)
				{
					num2 += list[i];
				}
				return (num2 / (double)(list.Count - num * 2), item);
			}
		}

		private class PerfLogger
		{
			private static readonly Lazy<PerfLogger> instance = new Lazy<PerfLogger>(() => new PerfLogger());

			private static readonly Lazy<string> pathLogFile = new Lazy<string>(() => GetLogPathFile());

			private static readonly string folderPerformanceLogs = "PerformanceLogs";

			private static readonly int logIntervalTime = 5000;

			private static Queue<string> logQueue;

			private static object queueLock;

			private static CancellableSingleTask<AsyncDelay> threadedTask;

			private StringBuilder sbLogText;

			public static PerfLogger DLog => instance.Value;

			public static bool IsInstanced => instance != null;

			private PerfLogger()
			{
				logQueue = new Queue<string>();
				queueLock = new object();
				threadedTask = new CancellableSingleTask<AsyncDelay>();
				sbLogText = new StringBuilder();
			}

			public async Task BeginPerfFileLoggingWithText(string firstPerfLogText)
			{
				if (firstPerfLogText != null && firstPerfLogText != "")
				{
					QueueAtFront(firstPerfLogText);
				}
				await threadedTask.StartThreadedTaskAsync((Func<Task>)LogConsumer, "Write performance log", throwExceptionIfRunning: true);
			}

			public async Task StopPerfFileLogging()
			{
				await threadedTask.StopTaskAndWaitAsync(5000);
				WriteBacklogToDisk(checkCancellation: false);
			}

			private void QueueAtFront(string firstPerfLogText)
			{
				lock (queueLock)
				{
					string[] array = logQueue.ToArray();
					logQueue.Clear();
					logQueue.Enqueue(firstPerfLogText);
					string[] array2 = array;
					foreach (string item in array2)
					{
						logQueue.Enqueue(item);
					}
				}
			}

			public void LogPerformance(string message)
			{
				lock (queueLock)
				{
					logQueue.Enqueue(message);
				}
			}

			private async Task LogConsumer()
			{
				if (TimeLogger.DebugEnabled)
				{
					TimeLogger.Logger.LogDebugFunc(() => "Beginning performance logging on file \"" + pathLogFile.Value + "\"", LogCategories.Loading);
					while (!threadedTask.IsCancellationRequested)
					{
						WriteBacklogToDisk(checkCancellation: true);
						await Task.Delay(logIntervalTime, threadedTask.CancellationToken);
					}
					TimeLogger.Logger.LogDebug("Performance logging stopped.", LogCategories.Loading);
				}
			}

			private void WriteBacklogToDisk(bool checkCancellation)
			{
				lock (queueLock)
				{
					if (logQueue.Count > 0)
					{
						do
						{
							sbLogText.AppendLine(logQueue.Dequeue());
						}
						while (logQueue.Count > 0);
					}
				}
				if ((!checkCancellation || !threadedTask.IsCancellationRequested) && sbLogText.Length > 0)
				{
					LogToDisk(sbLogText.ToString());
					sbLogText.Clear();
				}
			}

			private void LogToDisk(string text)
			{
				string directoryName = Path.GetDirectoryName(pathLogFile.Value);
				if (!Directory.Exists(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				using StreamWriter streamWriter = new StreamWriter(pathLogFile.Value, append: true);
				streamWriter.Write(text);
			}

			private static string GetLogPathFile()
			{
				return Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), folderPerformanceLogs), "PerformanceLog_" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + ".log");
			}
		}

		private static Dictionary<string, StopwatchMeasure> mapMeasures = new Dictionary<string, StopwatchMeasure>();

		private static int measureNameMaxLength;

		private static readonly int MeasureDecimals = 3;

		private static readonly int MeasureTimingsPadding = MeasureDecimals + 9;

		private static readonly int MeasureTotalTimingPadding = MeasureTimingsPadding + 2;

		private static readonly int RunCountPadding = 8;

		private static Stopwatch swPerfTotalRunTime;

		private static readonly Lazy<string> StaticHeaderText = new Lazy<string>(() => GetStaticHeaderText());

		private static readonly Lazy<string> StaticHorizontalSeparatorText = new Lazy<string>(() => GetStaticHorizontalSeparatorText());

		private static Action<string> logPerfAction = delegate(string text)
		{
			PerfLogger.DLog.LogPerformance(text);
		};

		private static CancellableSingleTask<AsyncDelay> logTableTask = new CancellableSingleTask<AsyncDelay>();

		public static void Start(string measureName, bool logTotals = true)
		{
			GetCreateMeasure(measureName, logTotals).Start(resetRunValues: false);
		}

		public static void StartOver(string measureName, bool logTotals = true)
		{
			GetCreateMeasure(measureName, logTotals).Start(resetRunValues: true);
		}

		public static void Reset(string measureName, bool doNotWarn = false)
		{
			StopOrReset(measureName, StopResetAction.Reset, doNotWarn);
		}

		public static void Stop(string measureName, bool doNotWarn = false)
		{
			StopOrReset(measureName, StopResetAction.Stop, doNotWarn);
		}

		public static void StopAndLog(string measureName, bool doNotWarn = false)
		{
			StopOrReset(measureName, StopResetAction.Log, doNotWarn);
		}

		public static void StopAndRecord(string measureName, bool doNotWarn = false)
		{
			StopOrReset(measureName, StopResetAction.Record, doNotWarn);
		}

		private static void StopOrReset(string measureName, StopResetAction stopResetAction, bool doNotWarn)
		{
			StopwatchMeasure swMeasure = GetMeasure(measureName, doNotWarn);
			if (swMeasure == null)
			{
				return;
			}
			if (stopResetAction == StopResetAction.Reset)
			{
				swMeasure.Reset();
				return;
			}
			swMeasure.Stop();
			if (stopResetAction != StopResetAction.Record && stopResetAction != StopResetAction.Log)
			{
				return;
			}
			swMeasure.RecordRun();
			if (stopResetAction == StopResetAction.Log)
			{
				LogPerformance(() => swMeasure.GetLogString());
			}
		}

		private static StopwatchMeasure GetCreateMeasure(string measureName, bool logTotals)
		{
			mapMeasures.TryGetValue(measureName, out var value);
			if (value == null)
			{
				value = new StopwatchMeasure(measureName, logTotals);
				mapMeasures.Add(measureName, value);
				measureNameMaxLength = Math.Max(measureNameMaxLength, measureName.Length);
				if (swPerfTotalRunTime == null)
				{
					swPerfTotalRunTime = Stopwatch.StartNew();
				}
			}
			return value;
		}

		private static StopwatchMeasure GetMeasure(string measureName, bool doNotWarn)
		{
			if (!mapMeasures.TryGetValue(measureName, out var value) && !doNotWarn)
			{
				TimeLogger.Logger.LogWarning("The specified stopwatch \"" + measureName + "\" doesnt exist.", LogCategories.PerfTest);
			}
			return value;
		}

		private static async Task LogPerformanceTableInterval(int logTableIntervalMillis)
		{
			while (!logTableTask.IsCancellationRequested)
			{
				await Task.Delay(logTableIntervalMillis, logTableTask.CancellationToken);
				LogPerformanceTable();
			}
		}

		private static void LogPerformanceTable()
		{
			LogPerformance(() => GetAllMeasuresTotalsSorted());
		}

		private static void LogPerformance(Func<string> logTextFunc)
		{
			TimeLogger.Logger.LogDebugFunc(logTextFunc, LogCategories.PerfTest, (logPerfAction, true));
		}

		private static string GetAllMeasuresTotalsSorted()
		{
			List<StopwatchMeasure> list = (from x in mapMeasures.Values.ToList()
				orderby x.TotalMilli descending
				select x).ToList();
			string value = "".PadRight(5, '\t');
			string logStringSummaryHorizontalSeparator = GetLogStringSummaryHorizontalSeparator();
			string logStringSummaryHeader = GetLogStringSummaryHeader();
			StringBuilder stringBuilder = new StringBuilder(100 + 125 * list.Count);
			stringBuilder.Append("Performance table, sorted by total time. ");
			if (swPerfTotalRunTime != null)
			{
				stringBuilder.AppendLine("The total run time since the Start of the first measure is " + swPerfTotalRunTime.Elapsed.ToString("hh':'mm':'ss'.'fff"));
				stringBuilder.Append(value);
				stringBuilder.AppendLine(logStringSummaryHorizontalSeparator);
				stringBuilder.Append(value);
				stringBuilder.AppendLine(logStringSummaryHeader);
				stringBuilder.Append(value);
				stringBuilder.Append(logStringSummaryHorizontalSeparator);
				foreach (StopwatchMeasure item in list)
				{
					stringBuilder.AppendLine();
					stringBuilder.Append(value);
					stringBuilder.Append(GetLogStringSummaryRunValues(item));
				}
				stringBuilder.AppendLine();
				stringBuilder.Append(value);
				stringBuilder.AppendLine(logStringSummaryHorizontalSeparator);
				return stringBuilder.ToString();
			}
			stringBuilder.AppendLine("No measures have been created yet.");
			return stringBuilder.ToString();
		}

		private static string GetLogStringSummaryHeader()
		{
			return "| " + "Measure name".PadSides(measureNameMaxLength) + " " + StaticHeaderText.Value;
		}

		private static string GetLogStringSummaryHorizontalSeparator()
		{
			return "|-" + "".PadSides(measureNameMaxLength, '-') + "-" + StaticHorizontalSeparatorText.Value;
		}

		private static string GetLogStringSummaryRunValues(StopwatchMeasure measure)
		{
			(string, string, string, string, string, string, string) formattedRunValues = measure.GetFormattedRunValues(measureNameMaxLength);
			return "| " + formattedRunValues.Item1 + " | " + formattedRunValues.Item2 + " | " + formattedRunValues.Item3 + " | " + formattedRunValues.Item4 + " | " + formattedRunValues.Item5 + " | " + formattedRunValues.Item6 + " | " + formattedRunValues.Item7 + " |";
		}

		private static string GetStaticHeaderText()
		{
			return "| " + "Total".PadSides(MeasureTotalTimingPadding) + " | " + "Runs".PadSides(RunCountPadding) + " | " + "Average".PadSides(MeasureTimingsPadding) + " | " + "Mean Trimmed".PadSides(MeasureTimingsPadding) + " | " + "Min".PadSides(MeasureTimingsPadding) + " | " + "Max".PadSides(MeasureTimingsPadding) + " |";
		}

		private static string GetStaticHorizontalSeparatorText()
		{
			return "|-" + "".PadSides(MeasureTotalTimingPadding, '-') + "-|-" + "".PadSides(RunCountPadding, '-') + "-|-" + "".PadSides(MeasureTimingsPadding, '-') + "-|-" + "".PadSides(MeasureTimingsPadding, '-') + "-|-" + "".PadSides(MeasureTimingsPadding, '-') + "-|-" + "".PadSides(MeasureTimingsPadding, '-') + "-|";
		}
	}
	public static class StringExtensions
	{
		public static string PadSides(this string str, int totalWidth, char paddingChar = ' ', bool padLeftOnUneven = true)
		{
			int num = totalWidth - str.Length;
			if (num % 2 == 1)
			{
				str = (padLeftOnUneven ? str.PadLeft(str.Length + 1, paddingChar) : str.PadRight(str.Length + 1, paddingChar));
				num--;
			}
			if (num < 1)
			{
				return str;
			}
			int totalWidth2 = num / 2 + str.Length;
			return str.PadLeft(totalWidth2, paddingChar).PadRight(totalWidth, paddingChar);
		}
	}
	public enum PreprocessType
	{
		FileLogging,
		GameNotification
	}
	[Flags]
	public enum LogTier
	{
		None = 0,
		Fatal = 1,
		Error = 2,
		Warning = 4,
		Message = 8,
		Info = 0x10,
		Debug = 0x20,
		All = -1
	}
	[Flags]
	public enum LogCategories
	{
		Null = 0,
		TempTest = 1,
		Vanilla = 2,
		PerfTest = 4,
		Loading = 8,
		Task = 0x10,
		Reflect = 0x20,
		Config = 0x40,
		PerfCheck = 0x80,
		Events = 0x100,
		Network = 0x200,
		Cache = 0x400,
		UI = 0x800,
		Notifs = 0x100000,
		AutoPatch = 0x200000,
		MethodChk = 0x400000,
		OtherMod = 0x800000,
		JobSched = 0x1000000,
		KeyMouse = 0x2000000,
		Highlight = 0x4000000,
		AI = 0x8000000,
		Visuals = 0x10000000,
		Audio = 0x20000000,
		Other = int.MinValue,
		All = -1
	}
	public abstract class TimeLogger
	{
		public delegate void NotificationAction(string notificationText, LogTier logTier, bool skipQueue);

		public delegate string PreprocessMessageFunc(string message, LogTier logLevel, LogCategories category, bool showInGameNotification, PreprocessType preprocType);

		private static TimeLogger instance;

		private Dictionary<LogCategories, string> logCategoryStringCache;

		private static string notificationMsgPrefix;

		private static NotificationAction notificationAction;

		private static PreprocessMessageFunc globalPreprocessMessageFunc;

		private int maxCategoryLength = Enum.GetNames(typeof(LogCategories)).Aggregate("", (string max, string cur) => (max.Length <= cur.Length) ? cur : max).Length;

		private LogCategories AllowedCategories;

		public static TimeLogger Logger
		{
			get
			{
				if (instance == null)
				{
					InitializeTimeLogger<DefaultTimeLogger>(debugEnabled: false, Array.Empty<object>());
					instance.LogWarning("TimeLogger has been automatically initialized with a DefaultTimeLogger. If you want to use a different custom logger, call a InitializeTimeLogger...() method earlier.", LogCategories.Loading);
				}
				return instance;
			}
		}

		public static bool DebugEnabled { get; set; }

		protected TimeLogger()
		{
			logCategoryStringCache = new Dictionary<LogCategories, string>();
		}

		protected abstract void LogMessage(string logMessage, LogTier logLevel);

		protected abstract void InitializeLogger(params object[] argsT);

		public static void InitializeTimeLogger<T>(bool debugEnabled = false, params object[] argsT) where T : TimeLogger
		{
			InitializeTimeLogger<T>(null, debugEnabled, argsT);
		}

		public static void InitializeTimeLogger<T>(PreprocessMessageFunc preprocessMessageFunc, bool debugEnabled = false, params object[] argsT) where T : TimeLogger
		{
			DebugEnabled = debugEnabled;
			globalPreprocessMessageFunc = preprocessMessageFunc;
			instance = Activator.CreateInstance<T>();
			instance.InitializeLogger(argsT);
		}

		public static void InitializeTimeLoggerWithGameNotifications<T>(NotificationAction notificationAction, string notificationMsgPrefix, bool debugEnabled = false, params object[] argsT) where T : TimeLogger
		{
			InitializeTimeLoggerWithGameNotifications<T>(null, notificationAction, notificationMsgPrefix, debugEnabled, argsT);
		}

		public static void InitializeTimeLoggerWithGameNotifications<T>(PreprocessMessageFunc preprocessMessageFunc, NotificationAction notificationAction, string notificationMsgPrefix, bool debugEnabled = false, params object[] argsT) where T : TimeLogger
		{
			if (notificationAction == null)
			{
				throw new ArgumentNullException("notificationAction", "The argument notificationAction cannot be null. Call InitializeTimeLogger(...) instead.");
			}
			InitializeTimeLogger<T>(preprocessMessageFunc, debugEnabled, argsT);
			AddGameNotificationSupport(notificationAction, notificationMsgPrefix);
		}

		public static void AddGameNotificationSupport(NotificationAction notificationAction, string notificationMsgPrefix)
		{
			if (notificationAction == null)
			{
				throw new ArgumentNullException("notificationAction");
			}
			TimeLogger.notificationAction = notificationAction;
			TimeLogger.notificationMsgPrefix = ((notificationMsgPrefix != null) ? notificationMsgPrefix : "");
		}

		public static void RemoveGameNotificationSupport()
		{
			notificationAction = null;
			notificationMsgPrefix = null;
		}

		public void LogInfo(string text, LogCategories category)
		{
			LogInternal(LogTier.Info, text, category, showInGameNotification: false, null);
		}

		public void LogInfoShowInGame(string text, LogCategories category)
		{
			LogInternal(LogTier.Info, text, category, showInGameNotification: true, null);
		}

		public void LogMessage(string text, LogCategories category)
		{
			LogInternal(LogTier.Message, text, category, showInGameNotification: false, null);
		}

		public void LogMessageShowInGame(string text, LogCategories category)
		{
			LogInternal(LogTier.Message, text, category, showInGameNotification: true, null);
		}

		public void LogDebug(string text, LogCategories category)
		{
			LogInternal(LogTier.Debug, text, category, showInGameNotification: false, null);
		}

		public void LogDebugShowInGame(string text, LogCategories category)
		{
			LogInternal(LogTier.Debug, text, category, showInGameNotification: true, null);
		}

		public void LogDebug(string text, LogCategories category, bool showInGameNotification)
		{
			LogInternal(LogTier.Debug, text, category, showInGameNotification, null);
		}

		public void LogDebugFunc(Func<string> textLambda, LogCategories category)
		{
			LogInternalFunc(LogTier.Debug, textLambda, category, false);
		}

		public void LogDebugFunc(Func<string> textLambda, LogCategories category, params (Action<string> action, bool useFullLog)[] actionsArgs)
		{
			LogInternalFunc(LogTier.Debug, textLambda, category, showInGameNotification: false, actionsArgs);
		}

		public void LogDebugFuncShowInGame(Func<string> textLambda, LogCategories category)
		{
			LogInternalFunc(LogTier.Debug, textLambda, category, true);
		}

		public void LogDebugFunc(Func<string> textLambda, LogCategories category, bool showInGameNotification)
		{
			LogInternalFunc(LogTier.Debug, textLambda, category, showInGameNotification);
		}

		public void LogDebugFunc(Func<string> textLambda, LogCategories category, bool showInGameNotification, params (Action<string> action, bool useFullLog)[] actionsArgs)
		{
			LogInternalFunc(LogTier.Debug, textLambda, category, showInGameNotification, actionsArgs);
		}

		public void LogWarning(string text, LogCategories category)
		{
			LogInternal(LogTier.Warning, text, category, showInGameNotification: false, null);
		}

		public void LogWarningShowInGame(string text, LogCategories category)
		{
			LogInternal(LogTier.Warning, text, category, showInGameNotification: true, null);
		}

		public void LogException(Exception e, LogCategories category)
		{
			LogExceptionInternal(null, e, category, showInGame: false);
		}

		public void LogExceptionWithMessage(string text, Exception e, LogCategories category)
		{
			LogExceptionInternal(text, e, category, showInGame: false);
		}

		public void LogExceptionShowInGame(Exception e, LogCategories category)
		{
			LogExceptionInternal(null, e, category, showInGame: true);
		}

		public void LogExceptionShowInGameWithMessage(string text, Exception e, LogCategories category)
		{
			LogExceptionInternal(text, e, category, showInGame: true);
		}

		private void LogExceptionInternal(string text, Exception e, LogCategories category, bool showInGame)
		{
			PreprocessMessageFunc preprocessMsgFunc = (string msg, LogTier _, LogCategories _, bool _, PreprocessType prepType) => prepType switch
			{
				PreprocessType.FileLogging => FormatException(e, msg), 
				PreprocessType.GameNotification => msg ?? e.Message, 
				_ => null, 
			};
			LogInternal(LogTier.Fatal, text, category, preprocessMsgFunc, showInGame, false);
		}

		public void LogFatal(string text, LogCategories category)
		{
			LogInternal(LogTier.Fatal, text, category, showInGameNotification: false, null);
		}

		public void LogFatalShowInGame(string text, LogCategories category)
		{
			LogInternal(LogTier.Fatal, text, category, showInGameNotification: true, null);
		}

		public void LogError(string text, LogCategories category)
		{
			LogInternal(LogTier.Error, text, category, showInGameNotification: false, null);
		}

		public void LogErrorShowInGame(string text, LogCategories category)
		{
			LogInternal(LogTier.Error, text, category, showInGameNotification: true, null);
		}

		public void LogFunc(LogTier logLevel, Func<string> textLambda, LogCategories category, bool showInGameNotification, params (Action<string> action, bool useFullLog)[] actionsArgs)
		{
			LogInternalFunc(logLevel, textLambda, category, showInGameNotification, actionsArgs);
		}

		private void LogInternalFunc(LogTier logLevel, Func<string> textLambda, LogCategories category, bool showInGameNotification, params (Action<string> action, bool useFullLog)[] actionsArgs)
		{
			if (logLevel != LogTier.Debug || DebugEnabled)
			{
				LogInternal(logLevel, textLambda(), category, showInGameNotification, actionsArgs);
			}
		}

		public void Log(LogTier logLevel, string text, LogCategories category)
		{
			LogInternal(logLevel, text, category, showInGameNotification: false, null);
		}

		public void Log(LogTier logLevel, string text, LogCategories category, bool showInGameNotification)
		{
			LogInternal(logLevel, text, category, showInGameNotification, null);
		}

		public void Log(LogTier logLevel, string text, LogCategories category, PreprocessMessageFunc preprocessMsgFunc, bool showInGameNotification, bool skipQueue = false, params (Action<string> action, bool useFullLog)[] actionsArgs)
		{
			if (preprocessMsgFunc == null)
			{
				preprocessMsgFunc = globalPreprocessMessageFunc;
			}
			LogInternal(logLevel, text, category, preprocessMsgFunc, showInGameNotification, skipQueue, actionsArgs);
		}

		private void LogInternal(LogTier logLevel, string originalText, LogCategories category, bool showInGameNotification, params (Action<string> action, bool useFullLog)[] actionsArgs)
		{
			LogInternal(logLevel, originalText, category, globalPreprocessMessageFunc, showInGameNotification, skipQueue: false, actionsArgs);
		}

		private void LogInternal(LogTier logLevel, string originalText, LogCategories category, PreprocessMessageFunc preprocessMsgFunc, bool showInGameNotification, bool skipQueue = false, params (Action<string> action, bool useFullLog)[] actionsArgs)
		{
			if ((logLevel == LogTier.Debug && !DebugEnabled) || (AllowedCategories != 0 && !AllowedCategories.HasFlag(category)))
			{
				return;
			}
			string text = PreprocessMessage(originalText, logLevel, category, showInGameNotification, preprocessMsgFunc, PreprocessType.FileLogging);
			string text2 = FormatLogMessageWithTime(text, category);
			LogMessage(text2, logLevel);
			if (showInGameNotification)
			{
				string message = PreprocessMessage(originalText, logLevel, category, showInGameNotification: true, preprocessMsgFunc, PreprocessType.GameNotification);
				SendMessageNotification(logLevel, message, skipQueue);
			}
			if (actionsArgs != null)
			{
				for (int i = 0; i < actionsArgs.Length; i++)
				{
					(Action<string>, bool) tuple = actionsArgs[i];
					tuple.Item1(tuple.Item2 ? text2 : text);
				}
			}
		}

		private string PreprocessMessage(string text, LogTier logLevel, LogCategories category, bool showInGameNotification, PreprocessMessageFunc preprocessMsgFunc, PreprocessType prepType)
		{
			if (preprocessMsgFunc != null)
			{
				return preprocessMsgFunc(text, logLevel, category, showInGameNotification, prepType) ?? text;
			}
			return text;
		}

		public string GetCategoryStringFromCache(LogCategories category)
		{
			if (!logCategoryStringCache.TryGetValue(category, out var value))
			{
				value = category.ToString();
				logCategoryStringCache.Add(category, value);
			}
			return value;
		}

		private string FormatLogMessageWithTime(string text, LogCategories category)
		{
			StringBuilder stringBuilder = new StringBuilder(100);
			string text2 = ((category == LogCategories.Null) ? "" : GetCategoryStringFromCache(category));
			stringBuilder.Append("[");
			stringBuilder.Append(text2.PadRight(maxCategoryLength, ' '));
			stringBuilder.Append("] ");
			stringBuilder.Append(DateTime.Now.ToString("HH:mm:ss.fff"));
			stringBuilder.Append(" - ");
			stringBuilder.Append(text);
			return stringBuilder.ToString();
		}

		public static string FormatException(Exception e, string text = null)
		{
			string text2 = ((text != null) ? (text + "\n" + e.Message) : e.Message);
			text2 += $"(In {e.TargetSite})\n{e.StackTrace}";
			if (e.InnerException != null)
			{
				text2 = text2 + "\n * InnerException: " + e.InnerException.Message + " " + $"(In {e.InnerException.TargetSite})\n{e.InnerException.StackTrace}";
			}
			return text2;
		}

		public void SendMessageNotificationError(string message, bool skipQueue)
		{
			SendMessageNotification(LogTier.Error, message, skipQueue);
		}

		public void SendMessageNotification(LogTier logLevel, string message, bool skipQueue)
		{
			if (logLevel != LogTier.Debug || DebugEnabled)
			{
				notificationAction?.Invoke(message, logLevel, skipQueue);
			}
		}
	}
}
namespace Damntry.Utils.ExtensionMethods
{
	public static class EnumExtension
	{
		private static class EnumLambdaCompiled<TEnum>
		{
			public static Func<TEnum, long> EnumToLongFunc = GenerateEnumToLongFunc();

			public static Func<long, TEnum> LongToEnumFunc = GenerateLongToEnumFunc();

			private static Func<TEnum, long> GenerateEnumToLongFunc()
			{
				ParameterExpression parameterExpression = Expression.Parameter(typeof(TEnum));
				return Expression.Lambda<Func<TEnum, long>>(Expression.Convert(parameterExpression, typeof(long)), new ParameterExpression[1] { parameterExpression }).Compile();
			}

			private static Func<long, TEnum> GenerateLongToEnumFunc()
			{
				ParameterExpression parameterExpression = Expression.Parameter(typeof(long));
				return Expression.Lambda<Func<long, TEnum>>(Expression.Convert(parameterExpression, typeof(TEnum)), new ParameterExpression[1] { parameterExpression }).Compile();
			}
		}

		public static string GetDescription(this Enum enumValue)
		{
			FieldInfo field = enumValue.GetType().GetField(enumValue.ToString());
			if (field == null)
			{
				return enumValue.ToString();
			}
			field.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false);
			if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute descriptionAttribute)
			{
				return descriptionAttribute.Description;
			}
			return enumValue.ToString();
		}

		public static long ToLong<TEnum>(this TEnum enumValue) where TEnum : struct, Enum
		{
			return EnumLambdaCompiled<TEnum>.EnumToLongFunc(enumValue);
		}

		public static long EnumToLong<T>(T enumValue)
		{
			if (typeof(T).IsEnum)
			{
				return EnumLambdaCompiled<T>.EnumToLongFunc(enumValue);
			}
			throw new Exception("The type is not an enum.");
		}

		public static TEnum LongToEnum<TEnum>(long value) where TEnum : Enum
		{
			return EnumLambdaCompiled<TEnum>.LongToEnumFunc(value);
		}

		public static T LongToEnumUnconstrained<T>(long value)
		{
			if (typeof(T).IsEnum)
			{
				return EnumLambdaCompiled<T>.LongToEnumFunc(value);
			}
			throw new Exception("The type is not an enum.");
		}
	}
	public static class NumberExtensionMethods
	{
		public const double EpsilonTolerance = 1E-09;

		private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
		{
			typeof(int),
			typeof(double),
			typeof(decimal),
			typeof(long),
			typeof(short),
			typeof(sbyte),
			typeof(byte),
			typeof(ulong),
			typeof(ushort),
			typeof(uint),
			typeof(float)
		};

		public static bool IsNumeric(this Type myType)
		{
			return NumericTypes.Contains(Nullable.GetUnderlyingType(myType) ?? myType);
		}

		public static bool IsInteger(this float num)
		{
			return (double)Math.Abs(num - (float)(int)num) < 1E-09;
		}

		public static bool IsInteger(this double num)
		{
			return Math.Abs(num - (double)(long)num) < 1E-09;
		}

		public static bool IsInteger(this float num, float epsilonTolerance)
		{
			return Math.Abs(num - (float)(int)num) < epsilonTolerance;
		}

		public static bool IsInteger(this double num, float epsilonTolerance)
		{
			return Math.Abs(num - (double)(long)num) < (double)epsilonTolerance;
		}

		public static bool Clamp(this ref float value, float min, float max)
		{
			return ClampIComparable(ref value, min, max);
		}

		public static bool Clamp(this ref double value, double min, double max)
		{
			return ClampIComparable(ref value, min, max);
		}

		public static bool Clamp(this ref int value, int min, int max)
		{
			return ClampIComparable(ref value, min, max);
		}

		public static bool Clamp(this ref byte value, byte min, byte max)
		{
			return ClampIComparable(ref value, min, max);
		}

		public static float ClampReturn(this float value, float min, float max)
		{
			return ClampIComparable(value, min, max);
		}

		public static double ClampReturn(this double value, double min, double max)
		{
			return ClampIComparable(value, min, max);
		}

		public static int ClampReturn(this int value, int min, int max)
		{
			return ClampIComparable(value, min, max);
		}

		public static byte ClampReturn(this byte value, byte min, byte max)
		{
			return ClampIComparable(value, min, max);
		}

		private static T ClampIComparable<T>(T value, T min, T max) where T : IComparable<T>
		{
			if (min.CompareTo(min) > 0)
			{
				throw new ArgumentException("Clamp: The max value is lower than the min value.");
			}
			if (value.CompareTo(min) < 0)
			{
				return min;
			}
			if (value.CompareTo(max) > 0)
			{
				return max;
			}
			return value;
		}

		private static bool ClampIComparable<T>(ref T value, T min, T max) where T : IComparable<T>
		{
			if (min.CompareTo(min) > 0)
			{
				throw new ArgumentException("Clamp: The max value is lower than the min value.");
			}
			if (value.CompareTo(min) < 0)
			{
				value = min;
				return false;
			}
			if (value.CompareTo(max) > 0)
			{
				value = max;
				return false;
			}
			return true;
		}
	}
	public static class ReflectionExtension
	{
		public static bool IsSubclassOfRawGeneric(this Type toCheck, Type baseType)
		{
			while (toCheck != typeof(object))
			{
				Type type = (toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck);
				if (baseType == type)
				{
					return true;
				}
				toCheck = toCheck.BaseType;
			}
			return false;
		}

		public static bool HasCustomAttribute<T>(this MemberInfo memberInfo) where T : Attribute
		{
			return (T)Attribute.GetCustomAttribute(memberInfo, typeof(T)) != null;
		}

		public static bool IsStatic(this PropertyInfo source, bool nonPublic = true)
		{
			return source.GetAccessors(nonPublic).Any((MethodInfo x) => x.IsStatic);
		}
	}
	public static class TaskExtensionMethods
	{
		public static bool IsTaskEnded(this Task task)
		{
			if (!task.IsCompleted)
			{
				return task.IsFaulted;
			}
			return true;
		}

		public static async void FireAndForgetCancels(this Task task, LogCategories category, bool dismissCancelLog = false)
		{
			try
			{
				if (!task.IsCompleted || task.IsFaulted)
				{
					await task.ConfigureAwait(continueOnCapturedContext: false);
				}
			}
			catch (Exception ex)
			{
				if (ex is TaskCanceledException || ex is OperationCanceledException || ex is ThreadAbortException)
				{
					if (!dismissCancelLog)
					{
						TimeLogger.Logger.LogDebug("\"Fire and Forget\" task successfully canceled.", category);
					}
				}
				else
				{
					TimeLogger.Logger.LogExceptionWithMessage("Error while awaiting \"Fire and Forget\" type of task:", ex, category);
				}
			}
		}

		public static async void FireAndForget(this Task task, LogCategories category)
		{
			try
			{
				if (!task.IsCompleted || task.IsFaulted)
				{
					await task.ConfigureAwait(continueOnCapturedContext: false);
				}
			}
			catch (Exception e)
			{
				TimeLogger.Logger.LogExceptionWithMessage("Error while awaiting \"Fire and Forget\" type of task:", e, category);
			}
		}
	}
}
namespace Damntry.Utils.Events
{
	public static class EventMethods
	{
		public record struct EventData(Type ClassType, object Instance, string FieldName);

		public static void ExecuteBypassingEvent(Action eventTriggerAction, params EventData[] eventsData)
		{
			if (eventTriggerAction == null)
			{
				throw new ArgumentNullException("eventTriggerAction");
			}
			if (eventsData == null)
			{
				throw new ArgumentNullException("eventsData");
			}
			List<(FieldInfo, object, object)> list = new List<(FieldInfo, object, object)>();
			for (int i = 0; i < eventsData.Length; i++)
			{
				EventData eventData = eventsData[i];
				FieldInfo field = eventData.ClassType.GetField(eventData.FieldName, ReflectionHelper.AllBindings);
				if (field == null)
				{
					throw new MemberAccessException("Field '" + eventData.FieldName + "' " + $"of type '{eventData.ClassType} couldnt be found.'");
				}
				object obj = (field.IsStatic ? null : eventData.Instance);
				object value = field.GetValue(obj);
				list.Add((field, obj, value));
			}
			if (list.Count == 0)
			{
				eventTriggerAction();
				return;
			}
			foreach (var item in list)
			{
				item.Item1.SetValue(item.Item2, null);
			}
			try
			{
				eventTriggerAction();
			}
			finally
			{
				foreach (var item2 in list)
				{
					item2.Item1.SetValue(item2.Item2, item2.Item3);
				}
			}
		}

		public static bool TryTriggerEvents(Action ev)
		{
			bool result = true;
			if (ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				for (int i = 0; i < invocationList.Length; i++)
				{
					Action action = (Action)invocationList[i];
					try
					{
						action();
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + action.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		public static bool TryTriggerEvents<T>(Action<T> ev, T arg1)
		{
			bool result = true;
			if (ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				for (int i = 0; i < invocationList.Length; i++)
				{
					Action<T> action = (Action<T>)invocationList[i];
					try
					{
						action(arg1);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + action.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		public static bool TryTriggerEvents<T1, T2>(Action<T1, T2> ev, T1 arg1, T2 arg2)
		{
			bool result = true;
			if (ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				for (int i = 0; i < invocationList.Length; i++)
				{
					Action<T1, T2> action = (Action<T1, T2>)invocationList[i];
					try
					{
						action(arg1, arg2);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + action.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		public static bool TryTriggerEvents<T1, T2, T3>(Action<T1, T2, T3> ev, T1 arg1, T2 arg2, T3 arg3)
		{
			bool result = true;
			if (ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				for (int i = 0; i < invocationList.Length; i++)
				{
					Action<T1, T2, T3> action = (Action<T1, T2, T3>)invocationList[i];
					try
					{
						action(arg1, arg2, arg3);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + action.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		public static bool TryTriggerEvents<T1, T2, T3, T4>(Action<T1, T2, T3, T4> ev, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
		{
			bool result = true;
			if (ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				for (int i = 0; i < invocationList.Length; i++)
				{
					Action<T1, T2, T3, T4> action = (Action<T1, T2, T3, T4>)invocationList[i];
					try
					{
						action(arg1, arg2, arg3, arg4);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + action.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		public static bool TryTriggerEvents<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> ev, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
		{
			bool result = true;
			if (ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				for (int i = 0; i < invocationList.Length; i++)
				{
					Action<T1, T2, T3, T4, T5> action = (Action<T1, T2, T3, T4, T5>)invocationList[i];
					try
					{
						action(arg1, arg2, arg3, arg4, arg5);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + action.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		public static bool TryTriggerEvents<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> ev, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
		{
			bool result = true;
			if (ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				for (int i = 0; i < invocationList.Length; i++)
				{
					Action<T1, T2, T3, T4, T5, T6> action = (Action<T1, T2, T3, T4, T5, T6>)invocationList[i];
					try
					{
						action(arg1, arg2, arg3, arg4, arg5, arg6);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + action.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		[Obsolete("Barely faster than TryTriggerEventsDelegate. Use TryTriggerEvents instead.")]
		private static bool TryTriggerEventsLambda<T>(Action<T> ev, T arg1)
		{
			return TryTriggerEventsLambda(ev, delegate(Delegate del)
			{
				((Action<T>)del)(arg1);
			});
		}

		private static bool TryTriggerEventsLambda(Delegate ev, Action<Delegate> action)
		{
			bool result = true;
			if ((object)ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				foreach (Delegate @delegate in invocationList)
				{
					try
					{
						action(@delegate);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + @delegate.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}

		[Obsolete("Too slow.")]
		private static bool TryTriggerEventsDelegate(Delegate ev, params object[] args)
		{
			bool result = true;
			if ((object)ev != null)
			{
				Delegate[] invocationList = ev.GetInvocationList();
				foreach (Delegate @delegate in invocationList)
				{
					try
					{
						@delegate?.Method.Invoke(@delegate.Target, args);
					}
					catch (Exception e)
					{
						result = false;
						TimeLogger.Logger.LogExceptionWithMessage("Exception while invoking method \"" + @delegate.Method.Name + "\" " + $"from event {ev.GetType()}", e, LogCategories.Events);
					}
				}
			}
			return result;
		}
	}
}
namespace Damntry.Utils.Collections
{
	public class TreeNode<T>
	{
		private readonly T _value;

		private readonly List<TreeNode<T>> _children = new List<TreeNode<T>>();

		public TreeNode<T> this[int i] => _children[i];

		public TreeNode<T> Parent { get; private set; }

		public T Value => _value;

		public ReadOnlyCollection<TreeNode<T>> Children => _children.AsReadOnly();

		public TreeNode(T value)
		{
			_value = value;
		}

		private TreeNode(T value, TreeNode<T> parent)
		{
			_value = value;
			Parent = parent;
		}

		public TreeNode<T> AddChild(T value)
		{
			TreeNode<T> treeNode = new TreeNode<T>(value, this);
			_children.Add(treeNode);
			return treeNode;
		}

		public TreeNode<T>[] AddChildren(params T[] values)
		{
			return values.Select(AddChild).ToArray();
		}

		public bool RemoveChild(TreeNode<T> node)
		{
			return _children.Remove(node);
		}

		public void TransverseAndDo(Action<T> action)
		{
			action(Value);
			foreach (TreeNode<T> child in _children)
			{
				child.TransverseAndDo(action);
			}
		}

		public IEnumerable<T> Flatten()
		{
			return new T[1] { Value }.Concat(_children.SelectMany((TreeNode<T> x) => x.Flatten()));
		}
	}
}
namespace Damntry.Utils.Collections.Queues
{
	public class CommonConcurrentQueue<T> : ConcurrentQueue<T>, ICommonQueue<T>
	{
		public bool TryEnqueue(T item)
		{
			Enqueue(item);
			return true;
		}

		public new bool TryDequeue(out T item)
		{
			return base.TryDequeue(out item);
		}
	}
	public class CommonQueue<T> : Queue<T>, ICommonQueue<T>
	{
		public bool TryEnqueue(T item)
		{
			Enqueue(item);
			return true;
		}

		public new bool TryDequeue(out T item)
		{
			item = Dequeue();
			return true;
		}
	}
	public class ConcurrentFixedCapacityQueue<T> : ConcurrentQueue<T>, ICommonQueue<T>
	{
		private readonly int maxCapacity;

		private readonly bool keepOld;

		private readonly object queueLock;

		public ConcurrentFixedCapacityQueue(int maxCapacity, bool keepOld)
		{
			if (maxCapacity <= 0)
			{
				throw new ArgumentOutOfRangeException("Only values over zero are allowed.");
			}
			this.maxCapacity = maxCapacity;
			this.keepOld = keepOld;
			queueLock = new object();
		}

		[Obsolete("Use \"Enqueue(T item, out T dequeuedItem)\" instead.")]
		public new T Enqueue(T item)
		{
			throw new NotImplementedException("Use \"Enqueue(T item, out T dequeuedItem)\" instead.");
		}

		public bool TryEnqueue(T item)
		{
			T dequeuedItem;
			return TryEnqueue(item, out dequeuedItem);
		}

		public bool TryEnqueue(T item, out T dequeuedItem)
		{
			dequeuedItem = default(T);
			lock (queueLock)
			{
				if (base.Count > maxCapacity)
				{
					throw new InvalidOperationException("This LimitedQueue contains more items than allowed. Avoid casting this FixedCapacityQueue instance into a Queue to call the base Enqueue(T) method.");
				}
				if (!keepOld && base.Count == maxCapacity)
				{
					base.TryDequeue(out dequeuedItem);
				}
				if (base.Count >= maxCapacity)
				{
					return false;
				}
				base.Enqueue(item);
			}
			return true;
		}

		public new bool TryDequeue(out T item)
		{
			lock (queueLock)
			{
				return base.TryDequeue(out item);
			}
		}
	}
	public class FixedCapacityQueue<T> : Queue<T>, ICommonQueue<T>
	{
		private readonly int maxCapacity;

		private readonly bool keepOld;

		public FixedCapacityQueue(int maxCapacity, bool keepOld)
			: base(maxCapacity)
		{
			if (maxCapacity <= 0)
			{
				throw new ArgumentOutOfRangeException("Only values over zero are allowed.");
			}
			this.maxCapacity = maxCapacity;
			this.keepOld = keepOld;
		}

		[Obsolete("Use \"Enqueue(T item, out T dequeuedItem)\" instead.")]
		public new T Enqueue(T item)
		{
			throw new NotImplementedException("Use \"Enqueue(T item, out T dequeuedItem)\" instead.");
		}

		public bool TryEnqueue(T item)
		{
			T dequeuedItem;
			return TryEnqueue(item, out dequeuedItem);
		}

		public bool TryEnqueue(T item, out T dequeuedItem)
		{
			dequeuedItem = default(T);
			if (base.Count > maxCapacity)
			{
				throw new InvalidOperationException("This LimitedQueue contains more items than allowed. Avoid casting this FixedCapacityQueue instance into a Queue to call the base Enqueue(T) method.");
			}
			if (!keepOld && base.Count == maxCapacity)
			{
				dequeuedItem = Dequeue();
			}
			if (base.Count >= maxCapacity)
			{
				return false;
			}
			base.Enqueue(item);
			return true;
		}

		public new bool TryDequeue(out T item)
		{
			item = Dequeue();
			return true;
		}
	}
	public class FixedCapacityUniqueQueue<T> : FixedCapacityQueue<T>
	{
		public FixedCapacityUniqueQueue(int maxCapacity, bool keepOld)
			: base(maxCapacity, keepOld)
		{
		}

		[Obsolete("Use \"Enqueue(T item, out T dequeuedItem)\" instead.")]
		public new T Enqueue(T item)
		{
			throw new NotImplementedException("Use \"Enqueue(T item, out T dequeuedItem)\" instead.");
		}

		public new bool TryEnqueue(T item, out T dequeuedItem)
		{
			dequeuedItem = default(T);
			if (base.Count > 0 && Contains(item))
			{
				return false;
			}
			return base.TryEnqueue(item, out dequeuedItem);
		}
	}
}
namespace Damntry.Utils.Collections.Queues.Interfaces
{
	public interface ICommonQueue<T>
	{
		int Count { get; }

		bool TryEnqueue(T item);

		bool TryDequeue(out T item);
	}
}

BepInEx/plugins/es.damntry.SuperQoLity/Damntry.Globals.Mirror.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Configuration;
using Damntry.Utils.ExtensionMethods;
using Damntry.Utils.Logging;
using Damntry.Utils.Maths;
using Damntry.Utils.Reflection;
using Damntry.UtilsBepInEx.IL;
using Damntry.UtilsMirror.Attributes;
using Damntry.UtilsMirror.Components;
using Damntry.UtilsMirror.Helpers;
using Damntry.UtilsMirror.SyncVar;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Damntry Mirror Globals")]
[assembly: AssemblyDescription("Utils usable in any type of Mirror Unity project")]
[assembly: AssemblyCompany("Damntry")]
[assembly: AssemblyProduct("Damntry Mirror Globals")]
[assembly: AssemblyCopyright("Copyright © Damntry 2026")]
[assembly: AssemblyFileVersion("0.2.5.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("0.2.5.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 Damntry.UtilsMirror
{
	public static class MirrorUtils
	{
		public static bool IsSyncVarDirty(NetworkReader reader, long byteOffset, bool keepUnmodified)
		{
			int position = reader.Position;
			ulong num = NetworkReaderExtensions.ReadULong(reader);
			if (keepUnmodified)
			{
				reader.Position = position;
			}
			return (num & (ulong)byteOffset) != 0;
		}
	}
}
namespace Damntry.UtilsMirror.SyncVar
{
	public enum EnableStatus
	{
		AllDisabled,
		LocallyOnly,
		RemotelyOnly,
		AllEnabled
	}
	public class BoolSyncVarSetting : SyncVarSetting<bool>
	{
		public override bool Value
		{
			get
			{
				if (base.ConfigEntry.Value)
				{
					if (base.IsSynced && !NetworkServer.active)
					{
						return base.Value;
					}
					return true;
				}
				return false;
			}
			set
			{
				SetValue(value, checkWritable: true);
			}
		}

		public EnableStatus Status
		{
			get
			{
				if (base.ConfigEntry.Value)
				{
					if (!Value)
					{
						return EnableStatus.LocallyOnly;
					}
					return EnableStatus.AllEnabled;
				}
				if (!Value)
				{
					return EnableStatus.AllDisabled;
				}
				return EnableStatus.RemotelyOnly;
			}
		}

		public bool IsEnabledLocally => base.ConfigEntry.Value;

		public BoolSyncVarSetting(bool defaultValue, ConfigEntry<bool> configEntry)
			: base(defaultValue, configEntry)
		{
		}
	}
	public interface ISyncVar
	{
		void SetToDefaultValue(Type declaringType, string syncVarName);

		bool Writable();

		void InitializeSyncObject(NetworkBehaviour netBehaviour);
	}
	[Serializable]
	public class SyncVar<T> : SyncObject, ISyncVar, IEquatable<T>
	{
		[SerializeField]
		protected T _Value;

		public Action OnFinishSyncing;

		private NetworkBehaviour networkBehaviourContainer;

		public Action<T, T> OnValueChangedCallback;

		private bool hookGuard;

		public virtual T Value
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				return _Value;
			}
			set
			{
				SetValue(value, checkWritable: true);
			}
		}

		public bool IsSynced
		{
			get
			{
				if (NetworkClient.active && Object.op_Implicit((Object)(object)networkBehaviourContainer))
				{
					return networkBehaviourContainer.netId != 0;
				}
				return false;
			}
		}

		public T DefaultValue { get; private set; }

		protected void SetValue(T value, bool checkWritable)
		{
			if ((!checkWritable || Writable()) && !Equals(value))
			{
				T value2 = _Value;
				_Value = value;
				if (base.OnDirty != null)
				{
					base.OnDirty();
				}
				if (OnValueChangedCallback != null && !hookGuard && Object.op_Implicit((Object)(object)networkBehaviourContainer) && !networkBehaviourContainer.authority)
				{
					hookGuard = true;
					InvokeCallback(value2, value);
					hookGuard = false;
				}
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		protected virtual void InvokeCallback(T oldValue, T newValue)
		{
			OnValueChangedCallback?.Invoke(oldValue, newValue);
		}

		public override void ClearChanges()
		{
		}

		public override void Reset()
		{
		}

		public virtual void SetToDefaultValue(Type declaringType, string syncVarName)
		{
			NetworkSpawnManager.DebugLog(() => "Setting SyncVar '" + declaringType.Name + "." + syncVarName + "' " + $"from {_Value} to its DefaultValue {DefaultValue}");
			_Value = DefaultValue;
		}

		public SyncVar(T defaultValue)
		{
			InitValues(defaultValue, defaultValue, null);
		}

		public SyncVar(T value, T defaultValue)
		{
			InitValues(value, defaultValue, null);
		}

		public SyncVar(T value, T defaultValue, Action<T, T> onValueChangedCallback)
		{
			OnValueChangedCallback = (Action<T, T>)Delegate.Combine(OnValueChangedCallback, onValueChangedCallback);
			InitValues(value, defaultValue, null);
		}

		public SyncVar(NetworkBehaviour netBehaviour, T value, T defaultValue)
		{
			if ((Object)(object)netBehaviour == (Object)null)
			{
				throw new ArgumentNullException("netBehaviour");
			}
			InitValues(value, defaultValue, netBehaviour);
		}

		public SyncVar(NetworkBehaviour netBehaviour, T value, T defaultValue, Action<T, T> onValueChangedCallback)
		{
			if ((Object)(object)netBehaviour == (Object)null)
			{
				throw new ArgumentNullException("netBehaviour");
			}
			OnValueChangedCallback = (Action<T, T>)Delegate.Combine(OnValueChangedCallback, onValueChangedCallback);
			InitValues(value, defaultValue, netBehaviour);
		}

		private void InitValues(T value, T defaultValue, NetworkBehaviour netBehaviour)
		{
			_Value = value;
			DefaultValue = defaultValue;
			if (typeof(T).IsEnum)
			{
				RegisterCustomEnum(value);
			}
			if ((Object)(object)netBehaviour != (Object)null)
			{
				InitSyncObjectReflection(netBehaviour, markAsSynced: true);
			}
		}

		private void RegisterCustomEnum<TEnum>(TEnum value)
		{
			if (Writer<TEnum>.write == null)
			{
				Writer<TEnum>.write = delegate(NetworkWriter writer, TEnum value)
				{
					NetworkWriterExtensions.WriteLong(writer, EnumExtension.EnumToLong<TEnum>(value));
				};
			}
			if (Reader<TEnum>.read == null)
			{
				Reader<TEnum>.read = (NetworkReader reader) => EnumExtension.LongToEnumUnconstrained<TEnum>(NetworkReaderExtensions.ReadLong(reader));
			}
		}

		public bool Writable()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Invalid comparison between Unknown and I4
			//IL_004c: 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)
			//IL_00a1: Invalid comparison between Unknown and I4
			if ((Object)(object)networkBehaviourContainer == (Object)null)
			{
				bool isNetworkOffline = !NetworkSpawnManager.IsNetworkOnline();
				NetworkSpawnManager.DebugLog(() => $"Writable returned {isNetworkOffline} for a non networked SyncVar!");
				return isNetworkOffline;
			}
			if (NetworkServer.active && NetworkClient.active)
			{
				if ((int)networkBehaviourContainer.syncDirection != 0)
				{
					return networkBehaviourContainer.netIdentity.isOwned;
				}
				return true;
			}
			if (NetworkServer.active)
			{
				return (int)networkBehaviourContainer.syncDirection == 0;
			}
			if (NetworkClient.active)
			{
				if (networkBehaviourContainer.netIdentity.netId != 0)
				{
					if ((int)networkBehaviourContainer.syncDirection == 1)
					{
						return networkBehaviourContainer.netIdentity.isOwned;
					}
					return false;
				}
				return true;
			}
			return true;
		}

		public virtual void InitializeSyncObject(NetworkBehaviour netBehaviour)
		{
			InitSyncObjectReflection(netBehaviour, markAsSynced: true);
		}

		protected void InitSyncObjectReflection(NetworkBehaviour netBehaviour, bool markAsSynced)
		{
			networkBehaviourContainer = netBehaviour;
			NetworkSpawnManager.DebugLog(() => "Initializing SyncVar of Value type " + typeof(T).Name + " in " + ((Object)netBehaviour).name);
			ReflectionHelper.CallMethod((object)netBehaviour, "InitSyncObject", new object[1] { this });
			NetworkSpawnManager.DebugLog(() => "Finished initializing SyncVar of Value type " + typeof(T).Name + " in " + ((Object)netBehaviour).name);
			if (markAsSynced)
			{
				OnFinishSyncing?.Invoke();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static implicit operator T(SyncVar<T> field)
		{
			return field.Value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static implicit operator SyncVar<T>(T value)
		{
			return new SyncVar<T>(value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override void OnSerializeAll(NetworkWriter writer)
		{
			writer.Write<T>(Value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override void OnSerializeDelta(NetworkWriter writer)
		{
			writer.Write<T>(Value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override void OnDeserializeAll(NetworkReader reader)
		{
			SetValue(reader.Read<T>(), checkWritable: false);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override void OnDeserializeDelta(NetworkReader reader)
		{
			SetValue(reader.Read<T>(), checkWritable: false);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool Equals(T other)
		{
			return EqualityComparer<T>.Default.Equals(_Value, other);
		}

		public override string ToString()
		{
			return Value.ToString();
		}
	}
	public class SyncVarSetting<T> : SyncVar<T>, ISyncVar
	{
		public ConfigEntry<T> ConfigEntry { get; private set; }

		public SyncVarSetting(T defaultValue, ConfigEntry<T> configEntry)
			: base(defaultValue, defaultValue)
		{
			Init(configEntry);
		}

		public SyncVarSetting(T defaultValue, Action<T, T> onValueChangedCallback, ConfigEntry<T> configEntry)
			: base(defaultValue, defaultValue, onValueChangedCallback)
		{
			Init(configEntry);
		}

		private void Init(ConfigEntry<T> configEntry)
		{
			if (configEntry == null)
			{
				throw new ArgumentNullException("configEntry", "SyncVarSetting ConfigEntry cannot be null. Make sure that Bepinex config binding has been completed successfully before this call. If not using a ConfigEntry is intended, use SyncVar instead.");
			}
			NetworkSpawnManager.DebugLog(() => "SyncVarSetting constructor. " + $"Setting SyncVar to its configEntry value ({configEntry.Value}).");
			ConfigEntry = configEntry;
			_Value = configEntry.Value;
			RegisterSyncvarSetting();
		}

		public void RegisterSyncvarSetting()
		{
			UnregisterSyncvarSetting();
			ConfigEntry.SettingChanged += SetValueFromConfig;
		}

		public void UnregisterSyncvarSetting()
		{
			ConfigEntry.SettingChanged -= SetValueFromConfig;
		}

		public override void InitializeSyncObject(NetworkBehaviour netBehaviour)
		{
			InitSyncObjectReflection(netBehaviour, markAsSynced: false);
			NetworkSpawnManager.DebugLog(() => "SyncVarSetting fully initialized. " + $"Setting SyncVar from {_Value} to its configEntry value ({ConfigEntry.Value}).");
			SetValueFromConfig();
			OnFinishSyncing?.Invoke();
		}

		private void SetValueFromConfig(object sender, EventArgs e)
		{
			SetValueFromConfig();
		}

		public void SetValueFromConfig()
		{
			if (NetworkServer.active)
			{
				Value = ConfigEntry.Value;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static implicit operator T(SyncVarSetting<T> field)
		{
			return field.Value;
		}
	}
}
namespace Damntry.UtilsMirror.Helpers
{
	public static class NetworkPrefabHelper
	{
		private static readonly string NetworkRootObjName = "NetworkedObjects";

		public static GameObject GetNetworkReadyPrefab<T>(string prefabName, out NetworkBehaviour networkBehaviour) where T : NetworkBehaviour
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			GameObject val = new GameObject(prefabName);
			val.SetActive(false);
			val.transform.parent = GetRootNetworkTransform();
			val.AddComponent<NetworkIdentity>();
			networkBehaviour = (NetworkBehaviour)(object)val.AddComponent<T>();
			return val;
		}

		private static Transform GetRootNetworkTransform()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			GameObject val = GameObject.Find(NetworkRootObjName);
			if (val == null)
			{
				val = new GameObject(NetworkRootObjName);
			}
			return val.transform;
		}

		public static bool AssetIdExistsAsPrefab(uint assetId)
		{
			return NetworkClient.prefabs.ContainsKey(assetId);
		}

		public static bool AssetIdAlreadyRegistered(uint assetId)
		{
			string text = "spawnHandlers";
			Type typeFromHandle = typeof(NetworkClient);
			FieldInfo fieldInfo = AccessTools.Field(typeFromHandle, text);
			if (fieldInfo == null)
			{
				return true;
			}
			object value = fieldInfo.GetValue(null);
			if (value == null)
			{
				TimeLogger.Logger.LogError($"The field {typeFromHandle}.{text} value is null.", (LogCategories)512);
				return true;
			}
			if (!(value is Dictionary<uint, SpawnHandlerDelegate>))
			{
				TimeLogger.Logger.LogError($"The field {typeFromHandle}.{text} does not have " + "the expected Dictionary type.", (LogCategories)512);
				return true;
			}
			return ((Dictionary<uint, SpawnHandlerDelegate>)value).ContainsKey(assetId);
		}

		public static bool IsPrefabGameObjectRegistered(GameObject prefabObj, uint expectedAssetId)
		{
			if (NetworkClient.prefabs != null && NetworkClient.prefabs.TryGetValue(expectedAssetId, out var value))
			{
				return prefabObj == value;
			}
			return false;
		}

		public static bool IsPrefabHandlerRegistered(SpawnHandlerDelegate spawnHandlerDelegate, uint expectedAssetId)
		{
			if (FindSpawnhandlerByAssetId(expectedAssetId, out var IsFieldNotFound, out var spawnDelegate))
			{
				return spawnHandlerDelegate == spawnDelegate;
			}
			return IsFieldNotFound;
		}

		public static bool FindSpawnhandlerByAssetId(uint assetId, out bool IsFieldNotFound, out SpawnHandlerDelegate spawnDelegate)
		{
			spawnDelegate = null;
			IsFieldNotFound = false;
			try
			{
				string text = "spawnHandlers";
				FieldInfo field = typeof(NetworkClient).GetField("spawnHandlers", AccessTools.all);
				if (field != null)
				{
					return ((Dictionary<uint, SpawnHandlerDelegate>)field.GetValue(null)).TryGetValue(assetId, out spawnDelegate);
				}
				TimeLogger.Logger.LogError("The field " + text + " could not be found in type " + typeof(NetworkClient).Name + ".", (LogCategories)512);
			}
			catch (Exception ex)
			{
				TimeLogger.Logger.LogException(ex, (LogCategories)512);
			}
			IsFieldNotFound = true;
			return false;
		}
	}
	public interface INetworkPrefabSpawner
	{
		Type NetworkBehaviourType { get; }

		uint DefinedAssetId { get; }

		bool IsSelfManagedSpawning { get; }

		void AddToPrefabs();

		void Spawn();
	}
	public class NetworkPrefabSpawner<T> : INetworkPrefabSpawner where T : NetworkBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnSpawnDelegate <>9__19_1;

			internal void <AddToPrefabs>b__19_1(GameObject spawned)
			{
			}
		}

		private GameObject prefabObj;

		private NetworkBehaviour networkBehaviourInstance;

		public uint DefinedAssetId { get; init; }

		public bool PrefabRegisterOk { get; private set; }

		public bool IsSelfManagedSpawning { get; init; }

		public Type NetworkBehaviourType { get; private set; }

		public NetworkPrefabSpawner(uint assetId, bool isSelfManagedSpawning)
		{
			NetworkBehaviourType = typeof(T);
			DefinedAssetId = assetId;
			IsSelfManagedSpawning = isSelfManagedSpawning;
		}

		public void AddToPrefabs()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			string typeName = NetworkBehaviourType.Name;
			prefabObj = NetworkPrefabHelper.GetNetworkReadyPrefab<T>(typeName, out networkBehaviourInstance);
			if ((Object)(object)prefabObj == (Object)null)
			{
				TimeLogger.Logger.LogError("A prefab object couldnt be created from type " + typeName, (LogCategories)512);
				return;
			}
			uint definedAssetId = DefinedAssetId;
			if (NetworkPrefabHelper.AssetIdExistsAsPrefab(definedAssetId))
			{
				TimeLogger.Logger.LogError($"The specified assetId \"{definedAssetId}\" for the NetworkBehaviour " + "class " + typeName + " was already found in the NetworkClient.", (LogCategories)512);
				return;
			}
			if (NetworkPrefabHelper.AssetIdAlreadyRegistered(definedAssetId))
			{
				TimeLogger.Logger.LogError($"The specified assetId \"{definedAssetId}\" for the NetworkBehaviour " + "class " + typeName + " has already been registered. Its possible there is a duplicated assetId in this project, or one coming from another mod, or added by the game at runtime.", (LogCategories)512);
				return;
			}
			SpawnHandlerDelegate val = (SpawnHandlerDelegate)((SpawnMessage msg) => prefabObj);
			object obj = <>c.<>9__19_1;
			if (obj == null)
			{
				UnSpawnDelegate val2 = delegate
				{
				};
				<>c.<>9__19_1 = val2;
				obj = (object)val2;
			}
			UnSpawnDelegate val3 = (UnSpawnDelegate)obj;
			NetworkClient.RegisterPrefab(prefabObj, DefinedAssetId, val, val3);
			PrefabRegisterOk = NetworkPrefabHelper.IsPrefabHandlerRegistered(val, DefinedAssetId);
			if (!PrefabRegisterOk)
			{
				NetworkSpawnManager.DebugLog(() => "Prefab NOT registered for NetworkBehaviour " + typeName + ".");
				return;
			}
			NetworkSpawnManager.DebugLog(() => "Prefab was registered correctly for NetworkBehaviour " + typeName + ".");
			TriggerStartNetworkSession(NetworkSpawnManager.GetCurrentNetworkMode());
		}

		private void TriggerStartNetworkSession(NetworkMode networkMode)
		{
			if (typeof(ISyncVarBehaviour).IsAssignableFrom(typeof(T)))
			{
				((ISyncVarBehaviour)networkBehaviourInstance).StartNetworkSession(networkMode);
			}
		}

		public void Spawn()
		{
			if (IsSelfManagedSpawning && PrefabRegisterOk)
			{
				if ((Object)(object)prefabObj == (Object)null)
				{
					TimeLogger.Logger.LogFatal("The prefab object to spawn for type " + NetworkBehaviourType.Name + ". is null. Make sure to call AddToPrefabs() before spawning happens.", (LogCategories)512);
				}
				else
				{
					NetworkServer.Spawn(prefabObj, (NetworkConnection)null);
				}
			}
		}
	}
	public enum NetworkMode
	{
		NotInitialized,
		Offline,
		ServerOnly,
		ClientOnly,
		Host
	}
	[HarmonyPatch]
	public static class NetworkSpawnManager
	{
		private static readonly Harmony harmony;

		private static readonly Dictionary<Type, INetworkPrefabSpawner> networkBehaviourRegistry;

		private static uint _assetIdSignature;

		public static bool NetworkDebugLog;

		public static event Action OnBeforeObjectSpawn;

		static NetworkSpawnManager()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			NetworkDebugLog = true;
			harmony = new Harmony(typeof(NetworkSpawnManager).FullName);
			networkBehaviourRegistry = new Dictionary<Type, INetworkPrefabSpawner>();
		}

		public static bool IsNetworkActive()
		{
			if (!NetworkServer.active)
			{
				return NetworkClient.active;
			}
			return true;
		}

		public static bool IsNetworkOnline()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if ((Object)(object)NetworkManager.singleton != (Object)null)
			{
				return (int)NetworkManager.singleton.mode > 0;
			}
			return false;
		}

		public static bool IsNetworkOnlineHosting()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if (!((Object)(object)NetworkManager.singleton != (Object)null) || (int)NetworkManager.singleton.mode != 3)
			{
				return (int)NetworkManager.singleton.mode == 1;
			}
			return true;
		}

		public static bool IsNetworkClientOnly()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if ((Object)(object)NetworkManager.singleton != (Object)null)
			{
				return (int)NetworkManager.singleton.mode == 2;
			}
			return false;
		}

		public static NetworkMode GetCurrentNetworkMode()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected I4, but got Unknown
			if ((Object)(object)NetworkManager.singleton == (Object)null)
			{
				return NetworkMode.NotInitialized;
			}
			NetworkManagerMode mode = NetworkManager.singleton.mode;
			return (int)mode switch
			{
				0 => NetworkMode.Offline, 
				1 => NetworkMode.ServerOnly, 
				2 => NetworkMode.ClientOnly, 
				3 => NetworkMode.Host, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static void Initialize(int assetIdSignature)
		{
			if (assetIdSignature < 1 || assetIdSignature > 4293)
			{
				TimeLogger.Logger.LogFatal($"The value of assetIdSignature is {assetIdSignature} " + "but it must be between 1 and 4293, both inclusive. All related network functionality will not work.", (LogCategories)512);
				return;
			}
			_assetIdSignature = (uint)assetIdSignature;
			harmony.PatchAll(typeof(NetworkSpawnManager));
			if (!harmony.GetPatchedMethods().Any())
			{
				TimeLogger.Logger.LogFatal("NetworkSpawnManager patch failed. Modded network features wont work.", (LogCategories)512);
			}
		}

		[HarmonyPatch(typeof(NetworkServer), "SpawnObjects")]
		[HarmonyPatch(typeof(NetworkClient), "PrepareToSpawnSceneObjects")]
		[HarmonyPostfix]
		public static void OnStartNetworkSessionPostfix(MethodBase __originalMethod)
		{
			DebugLog(() => "OnStartNetworkSessionPostfix - Coming from method " + $"{__originalMethod.Name} - Network mode: {NetworkManager.singleton.mode}");
			if (IsNetworkActive())
			{
				DebugLog("Mirror network system is active. Adding network spawns");
				NetworkSpawnManager.OnBeforeObjectSpawn?.Invoke();
				AddNetworkSpawns();
			}
			else
			{
				DebugLog("Mirror network system is NOT active. Skipping this session initialization");
			}
		}

		public static void RegisterNetwork<T>(uint assetId, bool isSelfManagedSpawning = true) where T : NetworkBehaviour
		{
			if (assetId == 0)
			{
				throw new ArgumentException("The assetId parameter cant be 0.");
			}
			if (MathMethods.CountDigits(assetId) > 6)
			{
				throw new ArgumentException("The assetId parameter must have less than 7 digits [1 to 999999].");
			}
			Type typeFromHandle = typeof(T);
			if (networkBehaviourRegistry.ContainsKey(typeFromHandle))
			{
				throw new InvalidOperationException("The NetworkBehaviour of type " + typeFromHandle.Name + " was already registered.");
			}
			NetworkPrefabSpawner<T> value = new NetworkPrefabSpawner<T>(GetAssetIdFromSignature(assetId), isSelfManagedSpawning);
			networkBehaviourRegistry.Add(typeFromHandle, value);
		}

		private static void AddNetworkSpawns()
		{
			foreach (KeyValuePair<Type, INetworkPrefabSpawner> item in networkBehaviourRegistry)
			{
				item.Value.AddToPrefabs();
			}
			if (NetworkServer.active)
			{
				BeginHostSpawning();
			}
		}

		private static void BeginHostSpawning()
		{
			DebugLog(() => $"Spawning objects - NetworkServer active? {NetworkServer.active}");
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (KeyValuePair<Type, INetworkPrefabSpawner> item in networkBehaviourRegistry)
			{
				item.Value.Spawn();
			}
		}

		private static uint GetAssetIdFromSignature(uint assetId)
		{
			return _assetIdSignature * 1000000 + assetId;
		}

		public static void DebugLog(Func<string> textLambda)
		{
		}

		public static void DebugLog(string text)
		{
		}
	}
}
namespace Damntry.UtilsMirror.Components
{
	public interface ISyncVarBehaviour
	{
		void StartNetworkSession(NetworkMode networkMode);
	}
	public abstract class SyncVarNetworkBehaviour<T> : NetworkBehaviour, ISyncVarBehaviour where T : SyncVarNetworkBehaviour<T>
	{
		private static readonly BindingFlags SearchFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private readonly Type derivedType = typeof(T);

		private readonly List<ISyncVar> validSyncVarList = new List<ISyncVar>();

		private static readonly Dictionary<MethodBase, MethodInfo> methodRedirects = new Dictionary<MethodBase, MethodInfo>();

		private readonly Harmony harmony = new Harmony(typeof(SyncVarNetworkBehaviour<T>).FullName);

		private static readonly bool IS_DEBUG_NETWORK_TESTS__ENABLED = false;

		protected virtual void OnStartNetworkSession(NetworkMode networkMode)
		{
		}

		protected virtual void OnSyncVarValuesDefaulted()
		{
		}

		protected virtual void OnSyncVarsNetworkReady()
		{
		}

		protected static ushort GetMirrorMethodHashCode(string methodName)
		{
			return (ushort)((uint)Extensions.GetStableHashCode(methodName) & 0xFFFFu);
		}

		public void StartNetworkSession(NetworkMode networkMode)
		{
			NetworkSpawnManager.DebugLog(() => "OnStartNetworkSession call begins for type " + derivedType.Name + ".");
			OnStartNetworkSession(networkMode);
			validSyncVarList.Clear();
			foreach (MemberInfoHelper item in GetDerivedSyncVarsOfType(typeof(SyncVar<>)))
			{
				if (CheckSyncVarValidity(item, out var syncVarInstance))
				{
					validSyncVarList.Add(syncVarInstance);
					syncVarInstance.SetToDefaultValue(((MemberInfo)(object)item).DeclaringType, ((MemberInfo)(object)item).Name);
				}
			}
			OnSyncVarValuesDefaulted();
		}

		protected virtual void Awake()
		{
			foreach (ISyncVar validSyncVar in validSyncVarList)
			{
				InitializeSyncVar(validSyncVar, (T)this);
			}
			validSyncVarList.Clear();
			NetworkSpawnManager.DebugLog(() => "OnSyncVarsNetworkReady call begins for type " + derivedType.Name + ".");
			OnSyncVarsNetworkReady();
		}

		private List<MemberInfoHelper> GetDerivedSyncVarsOfType(Type searchType)
		{
			IEnumerable<MemberInfo> enumerable = derivedType.GetFields(SearchFlags).Cast<MemberInfo>().Concat(derivedType.GetProperties(SearchFlags))
				.Cast<MemberInfo>();
			if (enumerable == null || enumerable.Count() == 0)
			{
				return new List<MemberInfoHelper>();
			}
			return (from mif in enumerable.Where((MemberInfo mi) => ReflectionExtension.HasCustomAttribute<SyncVarNetworkAttribute>(mi)).Select((Func<MemberInfo, MemberInfoHelper>)((MemberInfo mi) => new MemberInfoHelper(mi)))
				where ReflectionExtension.IsSubclassOfRawGeneric(mif.MemberInfoType, searchType)
				select mif).ToList();
		}

		private bool CheckSyncVarValidity(MemberInfoHelper syncVarInfoHelper, out ISyncVar syncVarInstance)
		{
			syncVarInstance = null;
			Type memberInfoType = syncVarInfoHelper.MemberInfoType;
			if (!memberInfoType.IsSubclassOf(typeof(SyncObject)))
			{
				TimeLogger.Logger.LogError("The var " + derivedType.Name + "." + ((MemberInfo)(object)syncVarInfoHelper).Name + " does not inherit from SyncObject and will be skipped. Make sure that the SyncVarNetworkAttribute annotation was intended.", (LogCategories)512);
				return false;
			}
			if (!typeof(ISyncVar).IsAssignableFrom(memberInfoType))
			{
				TimeLogger.Logger.LogError("The var " + derivedType.Name + "." + ((MemberInfo)(object)syncVarInfoHelper).Name + " does not inherit from ISyncVar and will be skipped. Make sure that the SyncVarNetworkAttribute annotation was intended.", (LogCategories)512);
				return false;
			}
			syncVarInstance = (ISyncVar)syncVarInfoHelper.GetValueStaticAgnostic((object)(T)this);
			if (syncVarInstance == null)
			{
				TimeLogger.Logger.LogError("The var " + derivedType.Name + "." + ((MemberInfo)(object)syncVarInfoHelper).Name + " has not been instantiated and will be skipped. Make sure to call its constructor.", (LogCategories)512);
				return false;
			}
			return true;
		}

		private void InitializeSyncVar(ISyncVar syncVarInstance, T netBehaviourInstance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			if (!IsSyncVarNetworkInitialized((SyncObject)syncVarInstance))
			{
				syncVarInstance.InitializeSyncObject((NetworkBehaviour)(object)netBehaviourInstance);
			}
		}

		private bool IsSyncVarNetworkInitialized(SyncObject syncVarInstance)
		{
			return base.syncObjects.Contains(syncVarInstance);
		}

		private Delegate GetOnChangeDelegate(string onChangeMethodName, T netBehaviourInstance, Type syncVarType)
		{
			Type type = syncVarType.GetGenericArguments()[0];
			MethodInfo method = derivedType.GetMethod(onChangeMethodName, SearchFlags, null, new Type[2] { type, type }, null);
			if (method == null)
			{
				TimeLogger.Logger.LogWarning("Method \"" + onChangeMethodName + "\" could not be found in type " + derivedType.Name + ", or does not have the required signature:  " + onChangeMethodName + "(" + syncVarType.Name + " oldValue, " + syncVarType.Name + " newValue).", (LogCategories)512);
				return null;
			}
			Delegate @delegate = Delegate.CreateDelegate(typeof(Action<, >).MakeGenericType(type, type), netBehaviourInstance, method);
			if ((object)@delegate == null)
			{
				TimeLogger.Logger.LogWarning("A delegate for method \"" + derivedType.Name + "." + onChangeMethodName + "\" could not be created.", (LogCategories)512);
				return null;
			}
			return @delegate;
		}

		public void CmdCall<T1>(string callingMethodName, bool requiresAuthority, T1 arg1)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			SendCmd(val, callingMethodName, requiresAuthority);
		}

		public void CmdCall<T1, T2>(string callingMethodName, bool requiresAuthority, T1 arg1, T2 arg2)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			SendCmd(val, callingMethodName, requiresAuthority);
		}

		public void CmdCall<T1, T2, T3>(string callingMethodName, bool requiresAuthority, T1 arg1, T2 arg2, T3 arg3)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			SendCmd(val, callingMethodName, requiresAuthority);
		}

		public void CmdCall<T1, T2, T3, T4>(string callingMethodName, bool requiresAuthority, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			((NetworkWriter)val).Write<T4>(arg4);
			SendCmd(val, callingMethodName, requiresAuthority);
		}

		public void CmdCall<T1, T2, T3, T4, T5>(string callingMethodName, bool requiresAuthority, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			((NetworkWriter)val).Write<T4>(arg4);
			((NetworkWriter)val).Write<T5>(arg5);
			SendCmd(val, callingMethodName, requiresAuthority);
		}

		public void CmdCall<T1, T2, T3, T4, T5, T6>(string callingMethodName, bool requiresAuthority, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			((NetworkWriter)val).Write<T4>(arg4);
			((NetworkWriter)val).Write<T5>(arg5);
			((NetworkWriter)val).Write<T6>(arg6);
			SendCmd(val, callingMethodName, requiresAuthority);
		}

		public void RpcCall<T1>(string callingMethodName, bool includeOwner, T1 arg1)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			SendRpc(val, callingMethodName, includeOwner);
		}

		public void RpcCall<T1, T2>(string callingMethodName, bool includeOwner, T1 arg1, T2 arg2)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			SendRpc(val, callingMethodName, includeOwner);
		}

		public void RpcCall<T1, T2, T3>(string callingMethodName, bool includeOwner, T1 arg1, T2 arg2, T3 arg3)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			SendRpc(val, callingMethodName, includeOwner);
		}

		public void RpcCall<T1, T2, T3, T4>(string callingMethodName, bool includeOwner, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			((NetworkWriter)val).Write<T4>(arg4);
			SendRpc(val, callingMethodName, includeOwner);
		}

		public void RpcCall<T1, T2, T3, T4, T5>(string callingMethodName, bool includeOwner, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			((NetworkWriter)val).Write<T4>(arg4);
			((NetworkWriter)val).Write<T5>(arg5);
			SendRpc(val, callingMethodName, includeOwner);
		}

		public void RpcCall<T1, T2, T3, T4, T5, T6>(string callingMethodName, bool includeOwner, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
		{
			NetworkWriterPooled val = NetworkWriterPool.Get();
			((NetworkWriter)val).Write<T1>(arg1);
			((NetworkWriter)val).Write<T2>(arg2);
			((NetworkWriter)val).Write<T3>(arg3);
			((NetworkWriter)val).Write<T4>(arg4);
			((NetworkWriter)val).Write<T5>(arg5);
			((NetworkWriter)val).Write<T6>(arg6);
			SendRpc(val, callingMethodName, includeOwner);
		}

		private void SendCmd(NetworkWriterPooled writer, string methodName, bool requiresAuthority)
		{
			((NetworkBehaviour)this).SendCommandInternal(methodName, (int)GetMirrorMethodHashCode(methodName), (NetworkWriter)(object)writer, 0, requiresAuthority);
			NetworkWriterPool.Return(writer);
		}

		private void SendRpc(NetworkWriterPooled writer, string methodName, bool includeOwner)
		{
			((NetworkBehaviour)this).SendRPCInternal(methodName, (int)GetMirrorMethodHashCode(methodName), (NetworkWriter)(object)writer, 0, includeOwner);
			NetworkWriterPool.Return(writer);
		}

		private void InitializeRedirectsRPC_CMD()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			List<(MethodInfo, MethodInfo)> rPC_MethodTargets = GetRPC_MethodTargets();
			LOG.TEMPWARNING($"{rPC_MethodTargets.Count} RPC methods", true);
			foreach (var item in rPC_MethodTargets)
			{
				if (!methodRedirects.ContainsKey(item.Item1))
				{
					methodRedirects.Add(item.Item1, item.Item2);
					MethodInfo method = new Func<IEnumerable<CodeInstruction>, ILGenerator, MethodBase, IEnumerable>(TranspileRPC_Call).Method;
					harmony.Patch((MethodBase)item.Item1, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			LOG.TEMPWARNING("Method patching finished.", true);
		}

		public override void OnStopClient()
		{
			harmony.UnpatchSelf();
			methodRedirects.Clear();
		}

		private List<(MethodInfo origMethod, MethodInfo targetMethod)> GetRPC_MethodTargets()
		{
			return (from mi in derivedType.GetMethods(SearchFlags)
				where ReflectionExtension.HasCustomAttribute<RPC_CallOnClientAttribute>((MemberInfo)mi)
				select (mi, GetMethodInfoFromRPCAttribute(mi)) into tup
				where tup.Item2 != null
				select tup).ToList();
		}

		private MethodInfo GetMethodInfoFromRPCAttribute(MethodInfo methodInfo)
		{
			RPC_CallOnClientAttribute customAttribute = methodInfo.GetCustomAttribute<RPC_CallOnClientAttribute>();
			if (Type.GetType(customAttribute.declaringType.AssemblyQualifiedName) == null)
			{
				TimeLogger.Logger.LogError("The type FullName could not be found.", (LogCategories)512);
			}
			MethodInfo methodInfo2 = AccessTools.Method(customAttribute.declaringType, customAttribute.targetMethodName, customAttribute.parameters, customAttribute.generics);
			if (methodInfo2 != null && !CompareMethodSignatures(methodInfo, methodInfo2))
			{
				methodInfo2 = null;
			}
			return methodInfo2;
		}

		public static bool CompareMethodSignatures(MethodInfo mi1, MethodInfo mi2, bool compareDeclaringType = false)
		{
			List<string> list = new List<string>();
			if (mi1.IsGenericMethod || mi2.IsGenericMethod)
			{
				list.Add("generic methods not supported");
			}
			if (mi1.ReturnType != mi2.ReturnType)
			{
				list.Add("return type");
			}
			if (mi1.GetParameters().Length != mi2.GetParameters().Length)
			{
				list.Add("number of parameters");
			}
			else
			{
				for (int i = 0; i < mi1.GetParameters().Length; i++)
				{
					if (mi1.GetParameters()[i].ParameterType != mi2.GetParameters()[i].ParameterType)
					{
						list.Add($"param {i + 1} type");
					}
				}
			}
			if (mi1.IsStatic != mi2.IsStatic)
			{
				list.Add("static modifier");
			}
			if (list.Count > 0)
			{
				TimeLogger.Logger.LogError("The methods " + mi1.DeclaringType.Name + "." + mi1.Name + " and " + mi2.DeclaringType.Name + "." + mi2.Name + " need to have the same method signature. Fix the following differences: " + string.Join(", ", list), (LogCategories)32);
			}
			return list.Count == 0;
		}

		[HarmonyDebug]
		private static IEnumerable TranspileRPC_Call(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase originalMethod)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			methodRedirects.TryGetValue(originalMethod, out var value);
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
			LOG.TEMPWARNING("Before emitting delegate " + ILExtensionMethods.GetFormattedIL(val.InstructionEnumeration()), true);
			if (NetworkServer.active)
			{
				LOG.TEMPWARNING("Host. RPC network send logic.", true);
				val.Advance(1);
				InsertRPC_GenerationCall(val, generator, value.GetParameters(), value.IsStatic);
			}
			else if (NetworkClient.active)
			{
				LOG.TEMPWARNING("Client. Executing next.", true);
				EmitCallTargetMethod(val, value);
			}
			else
			{
				TimeLogger.Logger.LogError("RPC method " + originalMethod.Name + " was called when no Mirror network component was active.", (LogCategories)512);
			}
			LOG.TEMPWARNING("After emitting delegate " + ILExtensionMethods.GetFormattedIL(val.InstructionEnumeration()), true);
			return val.InstructionEnumeration();
		}

		private static void InsertRPC_GenerationCall(CodeMatcher codeMatcher, ILGenerator generator, ParameterInfo[] parameters, bool isStatic)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			int num = parameters.Length;
			if (num > 0)
			{
				codeMatcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Ldc_I4, (object)num)
				}).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Newarr, (object)typeof(object))
				});
				int num2 = ((!isStatic) ? 1 : 0);
				for (int i = 0; i < num; i++)
				{
					codeMatcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
					{
						new CodeInstruction(OpCodes.Dup, (object)null)
					}).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
					{
						new CodeInstruction(OpCodes.Ldc_I4, (object)i)
					}).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstructionNew.LoadArgument(i + num2, false) });
					Type parameterType = parameters[i].ParameterType;
					if (parameterType.IsValueType)
					{
						codeMatcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
						{
							new CodeInstruction(OpCodes.Box, (object)parameterType)
						});
					}
					codeMatcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
					{
						new CodeInstruction(OpCodes.Stelem_Ref, (object)null)
					});
				}
			}
			codeMatcher.Insert((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate<Action<object[]>>((Action<object[]>)MakeRPC_Call) });
		}

		private static void MakeRPC_Call(object[] args)
		{
			LOG.TEMPWARNING(string.Format("MakeRPC_Call - {0} ({1}) params: {2}", args.Length, args[0], string.Join(", ", args)), true);
			NetworkWriterPooled val = NetworkWriterPool.Get();
			for (int i = 0; i < args.Length; i++)
			{
				_ = args[i];
			}
			NetworkWriterPool.Return(val);
			LOG.TEMPWARNING("MakeRPC_Call finished", true);
		}

		private static void EmitCallTargetMethod(CodeMatcher codeMatcher, MethodInfo targetMethod)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			codeMatcher.End().Advance(-1);
			LoadMethodArgIntoStack(codeMatcher, targetMethod);
			codeMatcher.Insert((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)targetMethod)
			});
		}

		private static void LoadMethodArgIntoStack(CodeMatcher codeMatcher, MethodInfo targetMethod)
		{
			int num = targetMethod.GetParameters().Count() + ((!targetMethod.IsStatic) ? 1 : 0);
			for (int i = 0; i < num; i++)
			{
				codeMatcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstructionNew.LoadArgument(i, false) });
			}
		}

		[RPC_CallOnClient(typeof(SyncVarNetworkAttribute), "UpdateSupermarketNameOnClient", null)]
		private void UpdateSupermarketName(string marketName)
		{
		}

		private static void UpdateSupermarketNameOnClient()
		{
		}
	}
}
namespace Damntry.UtilsMirror.Attributes
{
	[AttributeUsage(AttributeTargets.Method)]
	public class RPC_CallOnClientAttribute : Attribute
	{
		public Type declaringType;

		public string targetMethodName;

		public Type[] parameters;

		public Type[] generics;

		public RPC_CallOnClientAttribute(Type declaringType, string targetMethodName, Type[] parameters = null)
		{
			SetTargetMethod(declaringType, targetMethodName, parameters);
		}

		public RPC_CallOnClientAttribute(Type declaringType, string targetMethodName, Type[] parameters, Type[] generics)
		{
			SetTargetMethod(declaringType, targetMethodName, parameters, generics);
		}

		private void SetTargetMethod(Type declaringType, string targetMethodName, Type[] parameters = null, Type[] generics = null)
		{
			if (declaringType == null)
			{
				TimeLogger.Logger.LogError("Parameter declaringType is null.", (LogCategories)512);
				return;
			}
			if (string.IsNullOrEmpty(targetMethodName))
			{
				TimeLogger.Logger.LogError("Parameter targetMethodName is null or empty.", (LogCategories)512);
				return;
			}
			this.declaringType = declaringType;
			this.targetMethodName = targetMethodName;
			this.parameters = parameters;
			this.generics = generics;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
	public class SyncVarNetworkAttribute : Attribute
	{
	}
}

BepInEx/plugins/es.damntry.SuperQoLity/Damntry.Globals.Unity.dll

Decompiled 3 weeks 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.Text;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using Damntry.Utils.ExtensionMethods;
using Damntry.Utils.Logging;
using Damntry.Utils.Reflection;
using Damntry.Utils.Tasks.AsyncDelay;
using Damntry.Utils.Timers.StopwatchImpl;
using Damntry.UtilsUnity;
using Damntry.UtilsUnity.Components.InputManagement.Model;
using Damntry.UtilsUnity.Rendering;
using Damntry.UtilsUnity.UI.Extensions;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Damntry Globals unity")]
[assembly: AssemblyDescription("Utils for projects using Unity")]
[assembly: AssemblyCompany("Damntry")]
[assembly: AssemblyProduct("Damntry Globals unity")]
[assembly: AssemblyCopyright("Copyright © Damntry 2025")]
[assembly: AssemblyFileVersion("0.1.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("0.1.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class ParamCollectionAttribute : 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;
		}
	}
}
public class LeanAudioStream
{
	public int position;

	public AudioClip audioClip;

	public float[] audioArr;

	public LeanAudioStream(float[] audioArr)
	{
		this.audioArr = audioArr;
	}

	public void OnAudioRead(float[] data)
	{
		for (int i = 0; i < data.Length; i++)
		{
			data[i] = audioArr[position];
			position++;
		}
	}

	public void OnAudioSetPosition(int newPosition)
	{
		position = newPosition;
	}
}
public class LeanAudio
{
	[CompilerGenerated]
	private static class <>O
	{
		public static PCMSetPositionCallback <0>__OnAudioSetPosition;
	}

	public static float MIN_FREQEUNCY_PERIOD = 0.000115f;

	public static int PROCESSING_ITERATIONS_MAX = 50000;

	public static float[] generatedWaveDistances;

	public static int generatedWaveDistancesCount = 0;

	private static float[] longList;

	public static LeanAudioOptions options()
	{
		if (generatedWaveDistances == null)
		{
			generatedWaveDistances = new float[PROCESSING_ITERATIONS_MAX];
			longList = new float[PROCESSING_ITERATIONS_MAX];
		}
		return new LeanAudioOptions();
	}

	public static LeanAudioStream createAudioStream(AnimationCurve volume, AnimationCurve frequency, LeanAudioOptions options = null)
	{
		if (options == null)
		{
			options = new LeanAudioOptions();
		}
		options.useSetData = false;
		createAudioFromWave(createAudioWave(volume, frequency, options), options);
		return options.stream;
	}

	public static AudioClip createAudio(AnimationCurve volume, AnimationCurve frequency, LeanAudioOptions options = null)
	{
		if (options == null)
		{
			options = new LeanAudioOptions();
		}
		return createAudioFromWave(createAudioWave(volume, frequency, options), options);
	}

	private static int createAudioWave(AnimationCurve volume, AnimationCurve frequency, LeanAudioOptions options)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		Keyframe val = volume[volume.length - 1];
		float time = ((Keyframe)(ref val)).time;
		int num = 0;
		float num2 = 0f;
		for (int i = 0; i < PROCESSING_ITERATIONS_MAX; i++)
		{
			float num3 = frequency.Evaluate(num2);
			if (num3 < MIN_FREQEUNCY_PERIOD)
			{
				num3 = MIN_FREQEUNCY_PERIOD;
			}
			float num4 = volume.Evaluate(num2 + 0.5f * num3);
			if (options.vibrato != null)
			{
				for (int j = 0; j < options.vibrato.Length; j++)
				{
					float num5 = Mathf.Abs(Mathf.Sin(1.5708f + num2 * (1f / ((Vector3)(ref options.vibrato[j]))[0]) * (float)Math.PI));
					float num6 = 1f - ((Vector3)(ref options.vibrato[j]))[1];
					num5 = ((Vector3)(ref options.vibrato[j]))[1] + num6 * num5;
					num4 *= num5;
				}
			}
			if (num2 + 0.5f * num3 >= time)
			{
				break;
			}
			if (num >= PROCESSING_ITERATIONS_MAX - 1)
			{
				Debug.LogError((object)("LeanAudio has reached it's processing cap. To avoid this error increase the number of iterations ex: LeanAudio.PROCESSING_ITERATIONS_MAX = " + PROCESSING_ITERATIONS_MAX * 2));
				break;
			}
			int num7 = num / 2;
			num2 += num3;
			generatedWaveDistances[num7] = num2;
			longList[num] = num2;
			longList[num + 1] = ((i % 2 == 0) ? (0f - num4) : num4);
			num += 2;
		}
		num += -2;
		generatedWaveDistancesCount = num / 2;
		return num;
	}

	private static AudioClip createAudioFromWave(int waveLength, LeanAudioOptions options)
	{
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Expected O, but got Unknown
		//IL_029a: Expected O, but got Unknown
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Expected O, but got Unknown
		float num = longList[waveLength - 2];
		float[] array = new float[(int)((float)options.frequencyRate * num)];
		int num2 = 0;
		float num3 = longList[num2];
		float num4 = 0f;
		_ = longList[num2];
		float num5 = longList[num2 + 1];
		for (int i = 0; i < array.Length; i++)
		{
			float num6 = (float)i / (float)options.frequencyRate;
			if (num6 > longList[num2])
			{
				num4 = longList[num2];
				num2 += 2;
				num3 = longList[num2] - longList[num2 - 2];
				num5 = longList[num2 + 1];
			}
			float num7 = (num6 - num4) / num3;
			float num8 = Mathf.Sin(num7 * (float)Math.PI);
			if (options.waveStyle == LeanAudioOptions.LeanAudioWaveStyle.Square)
			{
				if (num8 > 0f)
				{
					num8 = 1f;
				}
				if (num8 < 0f)
				{
					num8 = -1f;
				}
			}
			else if (options.waveStyle == LeanAudioOptions.LeanAudioWaveStyle.Sawtooth)
			{
				float num9 = ((num8 > 0f) ? 1f : (-1f));
				num8 = ((!(num7 < 0.5f)) ? ((1f - num7) * 2f * num9) : (num7 * 2f * num9));
			}
			else if (options.waveStyle == LeanAudioOptions.LeanAudioWaveStyle.Noise)
			{
				float num10 = 1f - options.waveNoiseInfluence + Mathf.PerlinNoise(0f, num6 * options.waveNoiseScale) * options.waveNoiseInfluence;
				num8 *= num10;
			}
			num8 *= num5;
			if (options.modulation != null)
			{
				for (int j = 0; j < options.modulation.Length; j++)
				{
					float num11 = Mathf.Abs(Mathf.Sin(1.5708f + num6 * (1f / ((Vector3)(ref options.modulation[j]))[0]) * (float)Math.PI));
					float num12 = 1f - ((Vector3)(ref options.modulation[j]))[1];
					num11 = ((Vector3)(ref options.modulation[j]))[1] + num12 * num11;
					num8 *= num11;
				}
			}
			array[i] = num8;
		}
		int num13 = array.Length;
		AudioClip val = null;
		if (options.useSetData)
		{
			int frequencyRate = options.frequencyRate;
			object obj = <>O.<0>__OnAudioSetPosition;
			if (obj == null)
			{
				PCMSetPositionCallback val2 = OnAudioSetPosition;
				<>O.<0>__OnAudioSetPosition = val2;
				obj = (object)val2;
			}
			val = AudioClip.Create("Generated Audio", num13, 1, frequencyRate, false, (PCMReaderCallback)null, (PCMSetPositionCallback)obj);
			val.SetData(array, 0);
		}
		else
		{
			options.stream = new LeanAudioStream(array);
			val = AudioClip.Create("Generated Audio", num13, 1, options.frequencyRate, false, new PCMReaderCallback(options.stream.OnAudioRead), new PCMSetPositionCallback(options.stream.OnAudioSetPosition));
			options.stream.audioClip = val;
		}
		return val;
	}

	private static void OnAudioSetPosition(int newPosition)
	{
	}

	public static AudioClip generateAudioFromCurve(AnimationCurve curve, int frequencyRate = 44100)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		Keyframe val = curve[curve.length - 1];
		float time = ((Keyframe)(ref val)).time;
		float[] array = new float[(int)((float)frequencyRate * time)];
		for (int i = 0; i < array.Length; i++)
		{
			float num = (float)i / (float)frequencyRate;
			array[i] = curve.Evaluate(num);
		}
		int num2 = array.Length;
		AudioClip obj = AudioClip.Create("Generated Audio", num2, 1, frequencyRate, false);
		obj.SetData(array, 0);
		return obj;
	}

	public static AudioSource play(AudioClip audio, float volume)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		AudioSource obj = playClipAt(audio, Vector3.zero);
		obj.volume = volume;
		return obj;
	}

	public static AudioSource play(AudioClip audio)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return playClipAt(audio, Vector3.zero);
	}

	public static AudioSource play(AudioClip audio, Vector3 pos)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return playClipAt(audio, pos);
	}

	public static AudioSource play(AudioClip audio, Vector3 pos, float volume)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		AudioSource obj = playClipAt(audio, pos);
		obj.minDistance = 1f;
		obj.volume = volume;
		return obj;
	}

	public static AudioSource playClipAt(AudioClip clip, Vector3 pos)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject();
		val.transform.position = pos;
		AudioSource obj = val.AddComponent<AudioSource>();
		obj.clip = clip;
		obj.Play();
		Object.Destroy((Object)(object)val, clip.length);
		return obj;
	}

	public static void printOutAudioClip(AudioClip audioClip, ref AnimationCurve curve, float scaleX = 1f)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		float[] array = new float[audioClip.samples * audioClip.channels];
		audioClip.GetData(array, 0);
		int i = 0;
		Keyframe[] array2 = (Keyframe[])(object)new Keyframe[array.Length];
		for (; i < array.Length; i++)
		{
			array2[i] = new Keyframe((float)i * scaleX, array[i]);
		}
		curve = new AnimationCurve(array2);
	}
}
public class LeanAudioOptions
{
	public enum LeanAudioWaveStyle
	{
		Sine,
		Square,
		Sawtooth,
		Noise
	}

	public LeanAudioWaveStyle waveStyle;

	public Vector3[] vibrato;

	public Vector3[] modulation;

	public int frequencyRate = 44100;

	public float waveNoiseScale = 1000f;

	public float waveNoiseInfluence = 1f;

	public bool useSetData = true;

	public LeanAudioStream stream;

	public LeanAudioOptions setFrequency(int frequencyRate)
	{
		this.frequencyRate = frequencyRate;
		return this;
	}

	public LeanAudioOptions setVibrato(Vector3[] vibrato)
	{
		this.vibrato = vibrato;
		return this;
	}

	public LeanAudioOptions setWaveSine()
	{
		waveStyle = LeanAudioWaveStyle.Sine;
		return this;
	}

	public LeanAudioOptions setWaveSquare()
	{
		waveStyle = LeanAudioWaveStyle.Square;
		return this;
	}

	public LeanAudioOptions setWaveSawtooth()
	{
		waveStyle = LeanAudioWaveStyle.Sawtooth;
		return this;
	}

	public LeanAudioOptions setWaveNoise()
	{
		waveStyle = LeanAudioWaveStyle.Noise;
		return this;
	}

	public LeanAudioOptions setWaveStyle(LeanAudioWaveStyle style)
	{
		waveStyle = style;
		return this;
	}

	public LeanAudioOptions setWaveNoiseScale(float waveScale)
	{
		waveNoiseScale = waveScale;
		return this;
	}

	public LeanAudioOptions setWaveNoiseInfluence(float influence)
	{
		waveNoiseInfluence = influence;
		return this;
	}
}
public class LeanTester : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <timeoutCheck>d__2 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public LeanTester <>4__this;

		private float <pauseEndTime>5__2;

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

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

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

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

		private bool MoveNext()
		{
			int num = <>1__state;
			LeanTester leanTester = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<pauseEndTime>5__2 = Time.realtimeSinceStartup + leanTester.timeout;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if (Time.realtimeSinceStartup < <pauseEndTime>5__2)
			{
				<>2__current = 0;
				<>1__state = 1;
				return true;
			}
			if (!LeanTest.testsFinished)
			{
				Debug.Log((object)LeanTest.formatB("Tests timed out!"));
				LeanTest.overview();
			}
			return false;
		}

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

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

	public float timeout = 15f;

	public void Start()
	{
		((MonoBehaviour)this).StartCoroutine(timeoutCheck());
	}

	[IteratorStateMachine(typeof(<timeoutCheck>d__2))]
	private IEnumerator timeoutCheck()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <timeoutCheck>d__2(0)
		{
			<>4__this = this
		};
	}
}
public class LeanTest
{
	public static int expected = 0;

	private static int tests = 0;

	private static int passes = 0;

	public static float timeout = 15f;

	public static bool timeoutStarted = false;

	public static bool testsFinished = false;

	public static void debug(string name, bool didPass, string failExplaination = null)
	{
		expect(didPass, name, failExplaination);
	}

	public static void expect(bool didPass, string definition, string failExplaination = null)
	{
		//IL_010b: 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_011b: Unknown result type (might be due to invalid IL or missing references)
		float num = printOutLength(definition);
		int totalWidth = 40 - (int)(num * 1.05f);
		string text = "".PadRight(totalWidth, "_"[0]);
		string text2 = formatB(definition) + " " + text + " [ " + (didPass ? formatC("pass", "green") : formatC("fail", "red")) + " ]";
		if (!didPass && failExplaination != null)
		{
			text2 = text2 + " - " + failExplaination;
		}
		Debug.Log((object)text2);
		if (didPass)
		{
			passes++;
		}
		tests++;
		if (tests == expected && !testsFinished)
		{
			overview();
		}
		else if (tests > expected)
		{
			Debug.Log((object)(formatB("Too many tests for a final report!") + " set LeanTest.expected = " + tests));
		}
		if (!timeoutStarted)
		{
			timeoutStarted = true;
			GameObject val = new GameObject
			{
				name = "~LeanTest"
			};
			(val.AddComponent(typeof(LeanTester)) as LeanTester).timeout = timeout;
			((Object)val).hideFlags = (HideFlags)61;
		}
	}

	public static string padRight(int len)
	{
		string text = "";
		for (int i = 0; i < len; i++)
		{
			text += "_";
		}
		return text;
	}

	public static float printOutLength(string str)
	{
		float num = 0f;
		for (int i = 0; i < str.Length; i++)
		{
			num = ((str[i] != "I"[0]) ? ((str[i] != "J"[0]) ? (num + 1f) : (num + 0.85f)) : (num + 0.5f));
		}
		return num;
	}

	public static string formatBC(string str, string color)
	{
		return formatC(formatB(str), color);
	}

	public static string formatB(string str)
	{
		return "<b>" + str + "</b>";
	}

	public static string formatC(string str, string color)
	{
		return "<color=" + color + ">" + str + "</color>";
	}

	public static void overview()
	{
		testsFinished = true;
		int num = expected - passes;
		string text = ((num > 0) ? formatBC(num.ToString() ?? "", "red") : (num.ToString() ?? ""));
		Debug.Log((object)(formatB("Final Report:") + " _____________________ PASSED: " + formatBC(passes.ToString() ?? "", "green") + " FAILED: " + text + " "));
	}
}
public enum TweenAction
{
	MOVE_X,
	MOVE_Y,
	MOVE_Z,
	MOVE_LOCAL_X,
	MOVE_LOCAL_Y,
	MOVE_LOCAL_Z,
	MOVE_CURVED,
	MOVE_CURVED_LOCAL,
	MOVE_SPLINE,
	MOVE_SPLINE_LOCAL,
	SCALE_X,
	SCALE_Y,
	SCALE_Z,
	ROTATE_X,
	ROTATE_Y,
	ROTATE_Z,
	ROTATE_AROUND,
	ROTATE_AROUND_LOCAL,
	CANVAS_ROTATEAROUND,
	CANVAS_ROTATEAROUND_LOCAL,
	CANVAS_PLAYSPRITE,
	ALPHA,
	TEXT_ALPHA,
	CANVAS_ALPHA,
	CANVASGROUP_ALPHA,
	ALPHA_VERTEX,
	COLOR,
	CALLBACK_COLOR,
	TEXT_COLOR,
	CANVAS_COLOR,
	CANVAS_MOVE_X,
	CANVAS_MOVE_Y,
	CANVAS_MOVE_Z,
	CALLBACK,
	MOVE,
	MOVE_LOCAL,
	MOVE_TO_TRANSFORM,
	ROTATE,
	ROTATE_LOCAL,
	SCALE,
	VALUE3,
	GUI_MOVE,
	GUI_MOVE_MARGIN,
	GUI_SCALE,
	GUI_ALPHA,
	GUI_ROTATE,
	DELAYED_SOUND,
	CANVAS_MOVE,
	CANVAS_SCALE,
	CANVAS_SIZEDELTA
}
public enum LeanTweenType
{
	notUsed,
	linear,
	easeOutQuad,
	easeInQuad,
	easeInOutQuad,
	easeInCubic,
	easeOutCubic,
	easeInOutCubic,
	easeInQuart,
	easeOutQuart,
	easeInOutQuart,
	easeInQuint,
	easeOutQuint,
	easeInOutQuint,
	easeInSine,
	easeOutSine,
	easeInOutSine,
	easeInExpo,
	easeOutExpo,
	easeInOutExpo,
	easeInCirc,
	easeOutCirc,
	easeInOutCirc,
	easeInBounce,
	easeOutBounce,
	easeInOutBounce,
	easeInBack,
	easeOutBack,
	easeInOutBack,
	easeInElastic,
	easeOutElastic,
	easeInOutElastic,
	easeSpring,
	easeShake,
	punch,
	once,
	clamp,
	pingPong,
	animationCurve
}
public class LeanTween : MonoBehaviour
{
	public static bool throwErrors = true;

	public static float tau = (float)Math.PI * 2f;

	public static float PI_DIV2 = (float)Math.PI / 2f;

	private static LTSeq[] sequences;

	private static LTDescr[] tweens;

	private static int[] tweensFinished;

	private static LTDescr tween;

	private static int tweenMaxSearch = -1;

	private static int maxTweens = 400;

	private static int maxSequences = 400;

	private static int frameRendered = -1;

	private static GameObject _tweenEmpty;

	public static float dtEstimated = -1f;

	public static float dtManual;

	public static float dtActual;

	private static uint global_counter = 0u;

	private static int i;

	private static int j;

	private static int finishedCnt;

	public static AnimationCurve punch = new AnimationCurve((Keyframe[])(object)new Keyframe[9]
	{
		new Keyframe(0f, 0f),
		new Keyframe(0.112586f, 0.9976035f),
		new Keyframe(0.3120486f, -0.1720615f),
		new Keyframe(0.4316337f, 0.07030682f),
		new Keyframe(0.5524869f, -0.03141804f),
		new Keyframe(0.6549395f, 0.003909959f),
		new Keyframe(0.770987f, -0.009817753f),
		new Keyframe(0.8838775f, 0.001939224f),
		new Keyframe(1f, 0f)
	});

	public static AnimationCurve shake = new AnimationCurve((Keyframe[])(object)new Keyframe[4]
	{
		new Keyframe(0f, 0f),
		new Keyframe(0.25f, 1f),
		new Keyframe(0.75f, -1f),
		new Keyframe(1f, 0f)
	});

	private static int maxTweenReached;

	public static int startSearch = 0;

	public static LTDescr d;

	private static Action<LTEvent>[] eventListeners;

	private static GameObject[] goListeners;

	private static int eventsMaxSearch = 0;

	public static int EVENTS_MAX = 10;

	public static int LISTENERS_MAX = 10;

	private static int INIT_LISTENERS_MAX = LISTENERS_MAX;

	public static int maxSearch => tweenMaxSearch;

	public static int maxSimulataneousTweens => maxTweens;

	public static int tweensRunning
	{
		get
		{
			int num = 0;
			for (int i = 0; i <= tweenMaxSearch; i++)
			{
				if (tweens[i].toggle)
				{
					num++;
				}
			}
			return num;
		}
	}

	public static GameObject tweenEmpty
	{
		get
		{
			init(maxTweens);
			return _tweenEmpty;
		}
	}

	public static void init()
	{
		init(maxTweens);
	}

	public static void init(int maxSimultaneousTweens)
	{
		init(maxSimultaneousTweens, maxSequences);
	}

	public static void init(int maxSimultaneousTweens, int maxSimultaneousSequences)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		if (tweens == null)
		{
			maxTweens = maxSimultaneousTweens;
			tweens = new LTDescr[maxTweens];
			tweensFinished = new int[maxTweens];
			_tweenEmpty = new GameObject();
			((Object)_tweenEmpty).name = "~LeanTween";
			_tweenEmpty.AddComponent(typeof(LeanTween));
			_tweenEmpty.isStatic = true;
			((Object)_tweenEmpty).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)_tweenEmpty);
			for (int i = 0; i < maxTweens; i++)
			{
				tweens[i] = new LTDescr();
			}
			SceneManager.sceneLoaded += onLevelWasLoaded54;
			sequences = new LTSeq[maxSimultaneousSequences];
			for (int j = 0; j < maxSimultaneousSequences; j++)
			{
				sequences[j] = new LTSeq();
			}
		}
	}

	public static void reset()
	{
		if (tweens != null)
		{
			for (int i = 0; i <= tweenMaxSearch; i++)
			{
				if (tweens[i] != null)
				{
					tweens[i].toggle = false;
				}
			}
		}
		tweens = null;
		Object.Destroy((Object)(object)_tweenEmpty);
	}

	public void LateUpdate()
	{
		update();
	}

	private static void onLevelWasLoaded54(Scene scene, LoadSceneMode mode)
	{
		internalOnLevelWasLoaded(((Scene)(ref scene)).buildIndex);
	}

	private static void internalOnLevelWasLoaded(int lvl)
	{
		LTGUI.reset();
	}

	public static void update()
	{
		if (frameRendered == Time.frameCount)
		{
			return;
		}
		init();
		dtEstimated = ((dtEstimated < 0f) ? 0f : (dtEstimated = Time.unscaledDeltaTime));
		dtActual = Time.deltaTime;
		maxTweenReached = 0;
		finishedCnt = 0;
		for (int i = 0; i <= tweenMaxSearch && i < maxTweens; i++)
		{
			tween = tweens[i];
			if (tween.toggle)
			{
				maxTweenReached = i;
				if (tween.updateInternal())
				{
					tweensFinished[finishedCnt] = i;
					finishedCnt++;
				}
			}
		}
		tweenMaxSearch = maxTweenReached;
		frameRendered = Time.frameCount;
		for (int j = 0; j < finishedCnt; j++)
		{
			LeanTween.j = tweensFinished[j];
			tween = tweens[LeanTween.j];
			removeTween(LeanTween.j);
			if (tween.hasExtraOnCompletes && (Object)(object)tween.trans != (Object)null)
			{
				tween.callOnCompletes();
			}
		}
	}

	public static void removeTween(int i, int uniqueId)
	{
		if (tweens[i].uniqueId == uniqueId)
		{
			removeTween(i);
		}
	}

	public static void removeTween(int i)
	{
		if (!tweens[i].toggle)
		{
			return;
		}
		tweens[i].toggle = false;
		if (tweens[i].destroyOnComplete)
		{
			if (tweens[i].ltRect != null)
			{
				LTGUI.destroy(tweens[i].ltRect.id);
			}
			else if ((Object)(object)tweens[i].trans != (Object)null && (Object)(object)((Component)tweens[i].trans).gameObject != (Object)(object)_tweenEmpty)
			{
				Object.Destroy((Object)(object)((Component)tweens[i].trans).gameObject);
			}
		}
		startSearch = i;
		if (i + 1 >= tweenMaxSearch)
		{
			startSearch = 0;
		}
	}

	public static Vector3[] add(Vector3[] a, Vector3 b)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		Vector3[] array = (Vector3[])(object)new Vector3[a.Length];
		for (i = 0; i < a.Length; i++)
		{
			array[i] = a[i] + b;
		}
		return array;
	}

	public static float closestRot(float from, float to)
	{
		float num = 0f - (360f - to);
		float num2 = 360f + to;
		float num3 = Mathf.Abs(to - from);
		float num4 = Mathf.Abs(num - from);
		float num5 = Mathf.Abs(num2 - from);
		if (num3 < num4 && num3 < num5)
		{
			return to;
		}
		if (num4 < num5)
		{
			return num;
		}
		return num2;
	}

	public static void cancelAll()
	{
		cancelAll(callComplete: false);
	}

	public static void cancelAll(bool callComplete)
	{
		init();
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			if ((Object)(object)tweens[i].trans != (Object)null)
			{
				if (callComplete && tweens[i].optional.onComplete != null)
				{
					tweens[i].optional.onComplete();
				}
				removeTween(i);
			}
		}
	}

	public static void cancel(GameObject gameObject)
	{
		cancel(gameObject, callOnComplete: false);
	}

	public static void cancel(GameObject gameObject, bool callOnComplete)
	{
		init();
		Transform transform = gameObject.transform;
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			if (tweens[i].toggle && (Object)(object)tweens[i].trans == (Object)(object)transform)
			{
				if (callOnComplete && tweens[i].optional.onComplete != null)
				{
					tweens[i].optional.onComplete();
				}
				removeTween(i);
			}
		}
	}

	public static void cancel(RectTransform rect)
	{
		cancel(((Component)rect).gameObject, callOnComplete: false);
	}

	public static void cancel(GameObject gameObject, int uniqueId, bool callOnComplete = false)
	{
		if (uniqueId < 0)
		{
			return;
		}
		init();
		int num = uniqueId & 0xFFFF;
		int num2 = uniqueId >> 16;
		if ((Object)(object)tweens[num].trans == (Object)null || ((Object)(object)((Component)tweens[num].trans).gameObject == (Object)(object)gameObject && tweens[num].counter == num2))
		{
			if (callOnComplete && tweens[num].optional.onComplete != null)
			{
				tweens[num].optional.onComplete();
			}
			removeTween(num);
		}
	}

	public static void cancel(LTRect ltRect, int uniqueId)
	{
		if (uniqueId >= 0)
		{
			init();
			int num = uniqueId & 0xFFFF;
			int num2 = uniqueId >> 16;
			if (tweens[num].ltRect == ltRect && tweens[num].counter == num2)
			{
				removeTween(num);
			}
		}
	}

	public static void cancel(int uniqueId)
	{
		cancel(uniqueId, callOnComplete: false);
	}

	public static void cancel(int uniqueId, bool callOnComplete)
	{
		if (uniqueId < 0)
		{
			return;
		}
		init();
		int num = uniqueId & 0xFFFF;
		int num2 = uniqueId >> 16;
		if (num > tweens.Length - 1)
		{
			int num3 = num - tweens.Length;
			LTSeq lTSeq = sequences[num3];
			for (int i = 0; i < maxSequences; i++)
			{
				if (lTSeq.current.tween != null)
				{
					removeTween(lTSeq.current.tween.uniqueId & 0xFFFF);
				}
				if (lTSeq.previous != null)
				{
					lTSeq.current = lTSeq.previous;
					continue;
				}
				break;
			}
		}
		else if (tweens[num].counter == num2)
		{
			if (callOnComplete && tweens[num].optional.onComplete != null)
			{
				tweens[num].optional.onComplete();
			}
			removeTween(num);
		}
	}

	public static LTDescr descr(int uniqueId)
	{
		int num = uniqueId & 0xFFFF;
		int num2 = uniqueId >> 16;
		if (tweens[num] != null && tweens[num].uniqueId == uniqueId && tweens[num].counter == num2)
		{
			return tweens[num];
		}
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			if (tweens[i].uniqueId == uniqueId && tweens[i].counter == num2)
			{
				return tweens[i];
			}
		}
		return null;
	}

	public static LTDescr description(int uniqueId)
	{
		return descr(uniqueId);
	}

	public static LTDescr[] descriptions(GameObject gameObject = null)
	{
		if ((Object)(object)gameObject == (Object)null)
		{
			return null;
		}
		List<LTDescr> list = new List<LTDescr>();
		Transform transform = gameObject.transform;
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			if (tweens[i].toggle && (Object)(object)tweens[i].trans == (Object)(object)transform)
			{
				list.Add(tweens[i]);
			}
		}
		return list.ToArray();
	}

	[Obsolete("Use 'pause( id )' instead")]
	public static void pause(GameObject gameObject, int uniqueId)
	{
		pause(uniqueId);
	}

	public static void pause(int uniqueId)
	{
		int num = uniqueId & 0xFFFF;
		int num2 = uniqueId >> 16;
		if (tweens[num].counter == num2)
		{
			tweens[num].pause();
		}
	}

	public static void pause(GameObject gameObject)
	{
		Transform transform = gameObject.transform;
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			if ((Object)(object)tweens[i].trans == (Object)(object)transform)
			{
				tweens[i].pause();
			}
		}
	}

	public static void pauseAll()
	{
		init();
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			tweens[i].pause();
		}
	}

	public static void resumeAll()
	{
		init();
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			tweens[i].resume();
		}
	}

	[Obsolete("Use 'resume( id )' instead")]
	public static void resume(GameObject gameObject, int uniqueId)
	{
		resume(uniqueId);
	}

	public static void resume(int uniqueId)
	{
		int num = uniqueId & 0xFFFF;
		int num2 = uniqueId >> 16;
		if (tweens[num].counter == num2)
		{
			tweens[num].resume();
		}
	}

	public static void resume(GameObject gameObject)
	{
		Transform transform = gameObject.transform;
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			if ((Object)(object)tweens[i].trans == (Object)(object)transform)
			{
				tweens[i].resume();
			}
		}
	}

	public static bool isTweening(GameObject gameObject = null)
	{
		if ((Object)(object)gameObject == (Object)null)
		{
			for (int i = 0; i <= tweenMaxSearch; i++)
			{
				if (tweens[i].toggle)
				{
					return true;
				}
			}
			return false;
		}
		Transform transform = gameObject.transform;
		for (int j = 0; j <= tweenMaxSearch; j++)
		{
			if (tweens[j].toggle && (Object)(object)tweens[j].trans == (Object)(object)transform)
			{
				return true;
			}
		}
		return false;
	}

	public static bool isTweening(RectTransform rect)
	{
		return isTweening(((Component)rect).gameObject);
	}

	public static bool isTweening(int uniqueId)
	{
		int num = uniqueId & 0xFFFF;
		int num2 = uniqueId >> 16;
		if (num < 0 || num >= maxTweens)
		{
			return false;
		}
		if (tweens[num].counter == num2 && tweens[num].toggle)
		{
			return true;
		}
		return false;
	}

	public static bool isTweening(LTRect ltRect)
	{
		for (int i = 0; i <= tweenMaxSearch; i++)
		{
			if (tweens[i].toggle && tweens[i].ltRect == ltRect)
			{
				return true;
			}
		}
		return false;
	}

	public static void drawBezierPath(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float arrowSize = 0f, Transform arrowTransform = null)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: 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)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: 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_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: 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_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: 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)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: 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)
		Vector3 val = a;
		Vector3 val2 = -a + 3f * (b - c) + d;
		Vector3 val3 = 3f * (a + c) - 6f * b;
		Vector3 val4 = 3f * (b - a);
		if (arrowSize > 0f)
		{
			Vector3 position = arrowTransform.position;
			Quaternion rotation = arrowTransform.rotation;
			float num = 0f;
			for (float num2 = 1f; num2 <= 120f; num2 += 1f)
			{
				float num3 = num2 / 120f;
				Vector3 val5 = ((val2 * num3 + val3) * num3 + val4) * num3 + a;
				Gizmos.DrawLine(val, val5);
				float num4 = num;
				Vector3 val6 = val5 - val;
				num = num4 + ((Vector3)(ref val6)).magnitude;
				if (num > 1f)
				{
					num -= 1f;
					arrowTransform.position = val5;
					arrowTransform.LookAt(val, Vector3.forward);
					Vector3 val7 = arrowTransform.TransformDirection(Vector3.right);
					Vector3 val8 = val - val5;
					val8 = ((Vector3)(ref val8)).normalized;
					Gizmos.DrawLine(val5, val5 + (val7 + val8) * arrowSize);
					val7 = arrowTransform.TransformDirection(-Vector3.right);
					Gizmos.DrawLine(val5, val5 + (val7 + val8) * arrowSize);
				}
				val = val5;
			}
			arrowTransform.position = position;
			arrowTransform.rotation = rotation;
		}
		else
		{
			for (float num5 = 1f; num5 <= 30f; num5 += 1f)
			{
				float num3 = num5 / 30f;
				Vector3 val5 = ((val2 * num3 + val3) * num3 + val4) * num3 + a;
				Gizmos.DrawLine(val, val5);
				val = val5;
			}
		}
	}

	public static object logError(string error)
	{
		if (throwErrors)
		{
			Debug.LogError((object)error);
		}
		else
		{
			Debug.Log((object)error);
		}
		return null;
	}

	public static LTDescr options(LTDescr seed)
	{
		Debug.LogError((object)"error this function is no longer used");
		return null;
	}

	public static LTDescr options()
	{
		init();
		bool flag = false;
		j = 0;
		i = startSearch;
		while (j <= maxTweens)
		{
			if (j >= maxTweens)
			{
				return logError("LeanTween - You have run out of available spaces for tweening. To avoid this error increase the number of spaces to available for tweening when you initialize the LeanTween class ex: LeanTween.init( " + maxTweens * 2 + " );") as LTDescr;
			}
			if (i >= maxTweens)
			{
				i = 0;
			}
			if (!tweens[i].toggle)
			{
				if (i + 1 > tweenMaxSearch)
				{
					tweenMaxSearch = i + 1;
				}
				startSearch = i + 1;
				flag = true;
				break;
			}
			j++;
			i++;
		}
		if (!flag)
		{
			logError("no available tween found!");
		}
		tweens[i].reset();
		global_counter++;
		if (global_counter > 32768)
		{
			global_counter = 0u;
		}
		tweens[i].setId((uint)i, global_counter);
		return tweens[i];
	}

	private static LTDescr pushNewTween(GameObject gameObject, Vector3 to, float time, LTDescr tween)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		init(maxTweens);
		if ((Object)(object)gameObject == (Object)null || tween == null)
		{
			return null;
		}
		tween.trans = gameObject.transform;
		tween.to = to;
		tween.time = time;
		return tween;
	}

	public static LTDescr play(RectTransform rectTransform, Sprite[] sprites)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		float time = 0.25f * (float)sprites.Length;
		return pushNewTween(((Component)rectTransform).gameObject, new Vector3((float)sprites.Length - 1f, 0f, 0f), time, options().setCanvasPlaySprite().setSprites(sprites).setRepeat(-1));
	}

	public static LTDescr alpha(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		LTDescr lTDescr = pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setAlpha());
		SpriteRenderer component = gameObject.GetComponent<SpriteRenderer>();
		lTDescr.spriteRen = component;
		return lTDescr;
	}

	public static LTSeq sequence(bool initSequence = true)
	{
		init(maxTweens);
		for (int i = 0; i < sequences.Length; i++)
		{
			if ((sequences[i].tween != null && sequences[i].tween.toggle) || sequences[i].toggle)
			{
				continue;
			}
			LTSeq lTSeq = sequences[i];
			if (initSequence)
			{
				lTSeq.init((uint)(i + tweens.Length), global_counter);
				global_counter++;
				if (global_counter > 32768)
				{
					global_counter = 0u;
				}
			}
			else
			{
				lTSeq.reset();
			}
			return lTSeq;
		}
		return null;
	}

	public static LTDescr alpha(LTRect ltRect, float to, float time)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		ltRect.alphaEnabled = true;
		return pushNewTween(tweenEmpty, new Vector3(to, 0f, 0f), time, options().setGUIAlpha().setRect(ltRect));
	}

	public static LTDescr textAlpha(RectTransform rectTransform, float to, float time)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTransform).gameObject, new Vector3(to, 0f, 0f), time, options().setTextAlpha());
	}

	public static LTDescr alphaText(RectTransform rectTransform, float to, float time)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTransform).gameObject, new Vector3(to, 0f, 0f), time, options().setTextAlpha());
	}

	public static LTDescr alphaCanvas(CanvasGroup canvasGroup, float to, float time)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)canvasGroup).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasGroupAlpha());
	}

	public static LTDescr alphaVertex(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setAlphaVertex());
	}

	public static LTDescr color(GameObject gameObject, Color to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: 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_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		LTDescr lTDescr = pushNewTween(gameObject, new Vector3(1f, to.a, 0f), time, options().setColor().setPoint(new Vector3(to.r, to.g, to.b)));
		SpriteRenderer component = gameObject.GetComponent<SpriteRenderer>();
		lTDescr.spriteRen = component;
		return lTDescr;
	}

	public static LTDescr textColor(RectTransform rectTransform, Color to, float time)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTransform).gameObject, new Vector3(1f, to.a, 0f), time, options().setTextColor().setPoint(new Vector3(to.r, to.g, to.b)));
	}

	public static LTDescr colorText(RectTransform rectTransform, Color to, float time)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTransform).gameObject, new Vector3(1f, to.a, 0f), time, options().setTextColor().setPoint(new Vector3(to.r, to.g, to.b)));
	}

	public static LTDescr delayedCall(float delayTime, Action callback)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(tweenEmpty, Vector3.zero, delayTime, options().setCallback().setOnComplete(callback));
	}

	public static LTDescr delayedCall(float delayTime, Action<object> callback)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(tweenEmpty, Vector3.zero, delayTime, options().setCallback().setOnComplete(callback));
	}

	public static LTDescr delayedCall(GameObject gameObject, float delayTime, Action callback)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, Vector3.zero, delayTime, options().setCallback().setOnComplete(callback));
	}

	public static LTDescr delayedCall(GameObject gameObject, float delayTime, Action<object> callback)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, Vector3.zero, delayTime, options().setCallback().setOnComplete(callback));
	}

	public static LTDescr destroyAfter(LTRect rect, float delayTime)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(tweenEmpty, Vector3.zero, delayTime, options().setCallback().setRect(rect).setDestroyOnComplete(doesDestroy: true));
	}

	public static LTDescr move(GameObject gameObject, Vector3 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, to, time, options().setMove());
	}

	public static LTDescr move(GameObject gameObject, Vector2 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to.x, to.y, gameObject.transform.position.z), time, options().setMove());
	}

	public static LTDescr move(GameObject gameObject, Vector3[] to, float time)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveCurved();
		if (d.optional.path == null)
		{
			d.optional.path = new LTBezierPath(to);
		}
		else
		{
			d.optional.path.setPoints(to);
		}
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr move(GameObject gameObject, LTBezierPath to, float time)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveCurved();
		d.optional.path = to;
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr move(GameObject gameObject, LTSpline to, float time)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveSpline();
		d.optional.spline = to;
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr moveSpline(GameObject gameObject, Vector3[] to, float time)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveSpline();
		d.optional.spline = new LTSpline(to);
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr moveSpline(GameObject gameObject, LTSpline to, float time)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveSpline();
		d.optional.spline = to;
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr moveSplineLocal(GameObject gameObject, Vector3[] to, float time)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveSplineLocal();
		d.optional.spline = new LTSpline(to);
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr move(LTRect ltRect, Vector2 to, float time)
	{
		//IL_0005: 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)
		return pushNewTween(tweenEmpty, Vector2.op_Implicit(to), time, options().setGUIMove().setRect(ltRect));
	}

	public static LTDescr moveMargin(LTRect ltRect, Vector2 to, float time)
	{
		//IL_0005: 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)
		return pushNewTween(tweenEmpty, Vector2.op_Implicit(to), time, options().setGUIMoveMargin().setRect(ltRect));
	}

	public static LTDescr moveX(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setMoveX());
	}

	public static LTDescr moveY(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setMoveY());
	}

	public static LTDescr moveZ(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setMoveZ());
	}

	public static LTDescr moveLocal(GameObject gameObject, Vector3 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, to, time, options().setMoveLocal());
	}

	public static LTDescr moveLocal(GameObject gameObject, Vector3[] to, float time)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveCurvedLocal();
		if (d.optional.path == null)
		{
			d.optional.path = new LTBezierPath(to);
		}
		else
		{
			d.optional.path.setPoints(to);
		}
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr moveLocalX(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setMoveLocalX());
	}

	public static LTDescr moveLocalY(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setMoveLocalY());
	}

	public static LTDescr moveLocalZ(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setMoveLocalZ());
	}

	public static LTDescr moveLocal(GameObject gameObject, LTBezierPath to, float time)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveCurvedLocal();
		d.optional.path = to;
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr moveLocal(GameObject gameObject, LTSpline to, float time)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		d = options().setMoveSplineLocal();
		d.optional.spline = to;
		return pushNewTween(gameObject, new Vector3(1f, 0f, 0f), time, d);
	}

	public static LTDescr move(GameObject gameObject, Transform to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, Vector3.zero, time, options().setTo(to).setMoveToTransform());
	}

	public static LTDescr rotate(GameObject gameObject, Vector3 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, to, time, options().setRotate());
	}

	public static LTDescr rotate(LTRect ltRect, float to, float time)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(tweenEmpty, new Vector3(to, 0f, 0f), time, options().setGUIRotate().setRect(ltRect));
	}

	public static LTDescr rotateLocal(GameObject gameObject, Vector3 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, to, time, options().setRotateLocal());
	}

	public static LTDescr rotateX(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setRotateX());
	}

	public static LTDescr rotateY(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setRotateY());
	}

	public static LTDescr rotateZ(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setRotateZ());
	}

	public static LTDescr rotateAround(GameObject gameObject, Vector3 axis, float add, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(add, 0f, 0f), time, options().setAxis(axis).setRotateAround());
	}

	public static LTDescr rotateAroundLocal(GameObject gameObject, Vector3 axis, float add, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(add, 0f, 0f), time, options().setRotateAroundLocal().setAxis(axis));
	}

	public static LTDescr scale(GameObject gameObject, Vector3 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, to, time, options().setScale());
	}

	public static LTDescr scale(LTRect ltRect, Vector2 to, float time)
	{
		//IL_0005: 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)
		return pushNewTween(tweenEmpty, Vector2.op_Implicit(to), time, options().setGUIScale().setRect(ltRect));
	}

	public static LTDescr scaleX(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setScaleX());
	}

	public static LTDescr scaleY(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setScaleY());
	}

	public static LTDescr scaleZ(GameObject gameObject, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setScaleZ());
	}

	public static LTDescr value(GameObject gameObject, float from, float to, float time)
	{
		//IL_000c: 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)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setCallback().setFrom(new Vector3(from, 0f, 0f)));
	}

	public static LTDescr value(float from, float to, float time)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(tweenEmpty, new Vector3(to, 0f, 0f), time, options().setCallback().setFrom(new Vector3(from, 0f, 0f)));
	}

	public static LTDescr value(GameObject gameObject, Vector2 from, Vector2 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to.x, to.y, 0f), time, options().setValue3().setTo(new Vector3(to.x, to.y, 0f)).setFrom(new Vector3(from.x, from.y, 0f)));
	}

	public static LTDescr value(GameObject gameObject, Vector3 from, Vector3 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, to, time, options().setValue3().setFrom(from));
	}

	public static LTDescr value(GameObject gameObject, Color from, Color to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: 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_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		LTDescr lTDescr = pushNewTween(gameObject, new Vector3(1f, to.a, 0f), time, options().setCallbackColor().setPoint(new Vector3(to.r, to.g, to.b)).setFromColor(from)
			.setHasInitialized(has: false));
		SpriteRenderer component = gameObject.GetComponent<SpriteRenderer>();
		lTDescr.spriteRen = component;
		return lTDescr;
	}

	public static LTDescr value(GameObject gameObject, Action<float> callOnUpdate, float from, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setCallback().setTo(new Vector3(to, 0f, 0f)).setFrom(new Vector3(from, 0f, 0f))
			.setOnUpdate(callOnUpdate));
	}

	public static LTDescr value(GameObject gameObject, Action<float, float> callOnUpdateRatio, float from, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setCallback().setTo(new Vector3(to, 0f, 0f)).setFrom(new Vector3(from, 0f, 0f))
			.setOnUpdateRatio(callOnUpdateRatio));
	}

	public static LTDescr value(GameObject gameObject, Action<Color> callOnUpdate, Color from, Color to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: 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)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(1f, to.a, 0f), time, options().setCallbackColor().setPoint(new Vector3(to.r, to.g, to.b)).setAxis(new Vector3(from.r, from.g, from.b))
			.setFrom(new Vector3(0f, from.a, 0f))
			.setHasInitialized(has: false)
			.setOnUpdateColor(callOnUpdate));
	}

	public static LTDescr value(GameObject gameObject, Action<Color, object> callOnUpdate, Color from, Color to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: 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)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(1f, to.a, 0f), time, options().setCallbackColor().setPoint(new Vector3(to.r, to.g, to.b)).setAxis(new Vector3(from.r, from.g, from.b))
			.setFrom(new Vector3(0f, from.a, 0f))
			.setHasInitialized(has: false)
			.setOnUpdateColor(callOnUpdate));
	}

	public static LTDescr value(GameObject gameObject, Action<Vector2> callOnUpdate, Vector2 from, Vector2 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to.x, to.y, 0f), time, options().setValue3().setTo(new Vector3(to.x, to.y, 0f)).setFrom(new Vector3(from.x, from.y, 0f))
			.setOnUpdateVector2(callOnUpdate));
	}

	public static LTDescr value(GameObject gameObject, Action<Vector3> callOnUpdate, Vector3 from, Vector3 to, float time)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, to, time, options().setValue3().setTo(to).setFrom(from)
			.setOnUpdateVector3(callOnUpdate));
	}

	public static LTDescr value(GameObject gameObject, Action<float, object> callOnUpdate, float from, float to, float time)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, new Vector3(to, 0f, 0f), time, options().setCallback().setTo(new Vector3(to, 0f, 0f)).setFrom(new Vector3(from, 0f, 0f))
			.setOnUpdate(callOnUpdate, gameObject));
	}

	public static LTDescr delayedSound(AudioClip audio, Vector3 pos, float volume)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(tweenEmpty, pos, 0f, options().setDelayedSound().setTo(pos).setFrom(new Vector3(volume, 0f, 0f))
			.setAudio(audio));
	}

	public static LTDescr delayedSound(GameObject gameObject, AudioClip audio, Vector3 pos, float volume)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(gameObject, pos, 0f, options().setDelayedSound().setTo(pos).setFrom(new Vector3(volume, 0f, 0f))
			.setAudio(audio));
	}

	public static LTDescr move(RectTransform rectTrans, Vector3 to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, to, time, options().setCanvasMove().setRect(rectTrans));
	}

	public static LTDescr moveX(RectTransform rectTrans, float to, float time)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasMoveX().setRect(rectTrans));
	}

	public static LTDescr moveY(RectTransform rectTrans, float to, float time)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasMoveY().setRect(rectTrans));
	}

	public static LTDescr moveZ(RectTransform rectTrans, float to, float time)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasMoveZ().setRect(rectTrans));
	}

	public static LTDescr rotate(RectTransform rectTrans, float to, float time)
	{
		//IL_0011: 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)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasRotateAround().setRect(rectTrans).setAxis(Vector3.forward));
	}

	public static LTDescr rotate(RectTransform rectTrans, Vector3 to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, to, time, options().setCanvasRotateAround().setRect(rectTrans).setAxis(Vector3.forward));
	}

	public static LTDescr rotateAround(RectTransform rectTrans, Vector3 axis, float to, float time)
	{
		//IL_0011: 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)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasRotateAround().setRect(rectTrans).setAxis(axis));
	}

	public static LTDescr rotateAroundLocal(RectTransform rectTrans, Vector3 axis, float to, float time)
	{
		//IL_0011: 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)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasRotateAroundLocal().setRect(rectTrans).setAxis(axis));
	}

	public static LTDescr scale(RectTransform rectTrans, Vector3 to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, to, time, options().setCanvasScale().setRect(rectTrans));
	}

	public static LTDescr size(RectTransform rectTrans, Vector2 to, float time)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, Vector2.op_Implicit(to), time, options().setCanvasSizeDelta().setRect(rectTrans));
	}

	public static LTDescr alpha(RectTransform rectTrans, float to, float time)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(to, 0f, 0f), time, options().setCanvasAlpha().setRect(rectTrans));
	}

	public static LTDescr color(RectTransform rectTrans, Color to, float time)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		return pushNewTween(((Component)rectTrans).gameObject, new Vector3(1f, to.a, 0f), time, options().setCanvasColor().setRect(rectTrans).setPoint(new Vector3(to.r, to.g, to.b)));
	}

	public static float tweenOnCurve(LTDescr tweenDescr, float ratioPassed)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return tweenDescr.from.x + tweenDescr.diff.x * tweenDescr.optional.animationCurve.Evaluate(ratioPassed);
	}

	public static Vector3 tweenOnCurveVector(LTDescr tweenDescr, float ratioPassed)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: 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)
		return new Vector3(tweenDescr.from.x + tweenDescr.diff.x * tweenDescr.optional.animationCurve.Evaluate(ratioPassed), tweenDescr.from.y + tweenDescr.diff.y * tweenDescr.optional.animationCurve.Evaluate(ratioPassed), tweenDescr.from.z + tweenDescr.diff.z * tweenDescr.optional.animationCurve.Evaluate(ratioPassed));
	}

	public static float easeOutQuadOpt(float start, float diff, float ratioPassed)
	{
		return (0f - diff) * ratioPassed * (ratioPassed - 2f) + start;
	}

	public static float easeInQuadOpt(float start, float diff, float ratioPassed)
	{
		return diff * ratioPassed * ratioPassed + start;
	}

	public static float easeInOutQuadOpt(float start, float diff, float ratioPassed)
	{
		ratioPassed /= 0.5f;
		if (ratioPassed < 1f)
		{
			return diff / 2f * ratioPassed * ratioPassed + start;
		}
		ratioPassed -= 1f;
		return (0f - diff) / 2f * (ratioPassed * (ratioPassed - 2f) - 1f) + start;
	}

	public static Vector3 easeInOutQuadOpt(Vector3 start, Vector3 diff, float ratioPassed)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		ratioPassed /= 0.5f;
		if (ratioPassed < 1f)
		{
			return diff / 2f * ratioPassed * ratioPassed + start;
		}
		ratioPassed -= 1f;
		return -diff / 2f * (ratioPassed * (ratioPassed - 2f) - 1f) + start;
	}

	public static float linear(float start, float end, float val)
	{
		return Mathf.Lerp(start, end, val);
	}

	public static float clerp(float start, float end, float val)
	{
		float num = 0f;
		float num2 = 360f;
		float num3 = Mathf.Abs((num2 - num) / 2f);
		float num4 = 0f;
		float num5 = 0f;
		if (end - start < 0f - num3)
		{
			num5 = (num2 - start + end) * val;
			return start + num5;
		}
		if (end - start > num3)
		{
			num5 = (0f - (num2 - end + start)) * val;
			return start + num5;
		}
		return start + (end - start) * val;
	}

	public static float spring(float start, float end, float val)
	{
		val = Mathf.Clamp01(val);
		val = (Mathf.Sin(val * (float)Math.PI * (0.2f + 2.5f * val * val * val)) * Mathf.Pow(1f - val, 2.2f) + val) * (1f + 1.2f * (1f - val));
		return start + (end - start) * val;
	}

	public static float easeInQuad(float start, float end, float val)
	{
		end -= start;
		return end * val * val + start;
	}

	public static float easeOutQuad(float start, float end, float val)
	{
		end -= start;
		return (0f - end) * val * (val - 2f) + start;
	}

	public static float easeInOutQuad(float start, float end, float val)
	{
		val /= 0.5f;
		end -= start;
		if (val < 1f)
		{
			return end / 2f * val * val + start;
		}
		val -= 1f;
		return (0f - end) / 2f * (val * (val - 2f) - 1f) + start;
	}

	public static float easeInOutQuadOpt2(float start, float diffBy2, float val, float val2)
	{
		val /= 0.5f;
		if (val < 1f)
		{
			return diffBy2 * val2 + start;
		}
		val -= 1f;
		return (0f - diffBy2) * (val2 - 2f - 1f) + start;
	}

	public static float easeInCubic(float start, float end, float val)
	{
		end -= start;
		return end * val * val * val + start;
	}

	public static float easeOutCubic(float start, float end, float val)
	{
		val -= 1f;
		end -= start;
		return end * (val * val * val + 1f) + start;
	}

	public static float easeInOutCubic(float start, float end, float val)
	{
		val /= 0.5f;
		end -= start;
		if (val < 1f)
		{
			return end / 2f * val * val * val + start;
		}
		val -= 2f;
		return end / 2f * (val * val * val + 2f) + start;
	}

	public static float easeInQuart(float start, float end, float val)
	{
		end -= start;
		return end * val * val * val * val + start;
	}

	public static float easeOutQuart(float start, float end, float val)
	{
		val -= 1f;
		end -= start;
		return (0f - end) * (val * val * val * val - 1f) + start;
	}

	public static float easeInOutQuart(float start, float end, float val)
	{
		val /= 0.5f;
		end -= start;
		if (val < 1f)
		{
			return end / 2f * val * val * val * val + start;
		}
		val -= 2f;
		return (0f - end) / 2f * (val * val * val * val - 2f) + start;
	}

	public static float easeInQuint(float start, float end, float val)
	{
		end -= start;
		return end * val * val * val * val * val + start;
	}

	public static float easeOutQuint(float start, float end, float val)
	{
		val -= 1f;
		end -= start;
		return end * (val * val * val * val * val + 1f) + start;
	}

	public static float easeInOutQuint(float start, float end, float val)
	{
		val /= 0.5f;
		end -= start;
		if (val < 1f)
		{
			return end / 2f * val * val * val * val * val + start;
		}
		val -= 2f;
		return end / 2f * (val * val * val * val * val + 2f) + start;
	}

	public static float easeInSine(float start, float end, float val)
	{
		end -= start;
		return (0f - end) * Mathf.Cos(val / 1f * ((float)Math.PI / 2f)) + end + start;
	}

	public static float easeOutSine(float start, float end, float val)
	{
		end -= start;
		return end * Mathf.Sin(val / 1f * ((float)Math.PI / 2f)) + start;
	}

	public static float easeInOutSine(float start, float end, float val)
	{
		end -= start;
		return (0f - end) / 2f * (Mathf.Cos((float)Math.PI * val / 1f) - 1f) + start;
	}

	public static float easeInExpo(float start, float end, float val)
	{
		end -= start;
		return end * Mathf.Pow(2f, 10f * (val / 1f - 1f)) + start;
	}

	public static float easeOutExpo(float start, float end, float val)
	{
		end -= start;
		return end * (0f - Mathf.Pow(2f, -10f * val / 1f) + 1f) + start;
	}

	public static float easeInOutExpo(float start, float end, float val)
	{
		val /= 0.5f;
		end -= start;
		if (val < 1f)
		{
			return end / 2f * Mathf.Pow(2f, 10f * (val - 1f)) + start;
		}
		val -= 1f;
		return end / 2f * (0f - Mathf.Pow(2f, -10f * val) + 2f) + start;
	}

	public static float easeInCirc(float start, float end, float val)
	{
		end -= start;
		return (0f - end) * (Mathf.Sqrt(1f - val * val) - 1f) + start;
	}

	public static float easeOutCirc(float start, float end, float val)
	{
		val -= 1f;
		end -= start;
		return end * Mathf.Sqrt(1f - val * val) + start;
	}

	public static float easeInOutCirc(float start, float end, float val)
	{
		val /= 0.5f;
		end -= start;
		if (val < 1f)
		{
			return (0f - end) / 2f * (Mathf.Sqrt(1f - val * val) - 1f) + start;
		}
		val -= 2f;
		return end / 2f * (Mathf.Sqrt(1f - val * val) + 1f) + start;
	}

	public static float easeInBounce(float start, float end, float val)
	{
		end -= start;
		float num = 1f;
		return end - easeOutBounce(0f, end, num - val) + start;
	}

	public static float easeOutBounce(float start, float end, float val)
	{
		val /= 1f;
		end -= start;
		if (val < 0.36363637f)
		{
			return end * (7.5625f * val * val) + start;
		}
		if (val < 0.72727275f)
		{
			val -= 0.54545456f;
			return end * (7.5625f * val * val + 0.75f) + start;
		}
		if ((double)val < 0.9090909090909091)
		{
			val -= 0.8181818f;
			return end * (7.5625f * val * val + 0.9375f) + start;
		}
		val -= 21f / 22f;
		return end * (7.5625f * val * val + 63f / 64f) + start;
	}

	public static float easeInOutBounce(float start, float end, float val)
	{
		end -= start;
		float num = 1f;
		if (val < num / 2f)
		{
			return easeInBounce(0f, end, val * 2f) * 0.5f + start;
		}
		return easeOutBounce(0f, end, val * 2f - num) * 0.5f + end * 0.5f + start;
	}

	public static float easeInBack(float start, float end, float val, float overshoot = 1f)
	{
		end -= start;
		val /= 1f;
		float num = 1.70158f * overshoot;
		return end * val * val * ((num + 1f) * val - num) + start;
	}

	public static float easeOutBack(float start, float end, float val, float overshoot = 1f)
	{
		float num = 1.70158f * overshoot;
		end -= start;
		val = val / 1f - 1f;
		return end * (val * val * ((num + 1f) * val + num) + 1f) + start;
	}

	public static float easeInOutBack(float start, float end, float val, float overshoot = 1f)
	{
		float num = 1.70158f * overshoot;
		end -= start;
		val /= 0.5f;
		if (val < 1f)
		{
			num *= 1.525f * overshoot;
			return end / 2f * (val * val * ((num + 1f) * val - num)) + start;
		}
		val -= 2f;
		num *= 1.525f * overshoot;
		return end / 2f * (val * val * ((num + 1f) * val + num) + 2f) + start;
	}

	public static float easeInElastic(float start, float end, float val, float overshoot = 1f, float period = 0.3f)
	{
		end -= start;
		float num = 0f;
		float num2 = 0f;
		if (val == 0f)
		{
			return start;
		}
		if (val == 1f)
		{
			return start + end;
		}
		if (num2 == 0f || num2 < Mathf.Abs(end))
		{
			num2 = end;
			num = period / 4f;
		}
		else
		{
			num = period / ((float)Math.PI * 2f) * Mathf.Asin(end / num2);
		}
		if (overshoot > 1f && val > 0.6f)
		{
			overshoot = 1f + (1f - val) / 0.4f * (overshoot - 1f);
		}
		val -= 1f;
		return start - num2 * Mathf.Pow(2f, 10f * val) * Mathf.Sin((val - num) * ((float)Math.PI * 2f) / period) * overshoot;
	}

	public static float easeOutElastic(float start, float end, float val, float overshoot = 1f, float period = 0.3f)
	{
		end -= start;
		float num = 0f;
		float num2 = 0f;
		if (val == 0f)
		{
			return start;
		}
		if (val == 1f)
		{
			return start + end;
		}
		if (num2 == 0f || num2 < Mathf.Abs(end))
		{
			num2 = end;
			num = period / 4f;
		}
		else
		{
			num = period / ((float)Math.PI * 2f) * Mathf.Asin(end / num2);
		}
		if (overshoot > 1f && val < 0.4f)
		{
			overshoot = 1f + val / 0.4f * (overshoot - 1f);
		}
		return start + end + num2 * Mathf.Pow(2f, -10f * val) * Mathf.Sin((val - num) * ((float)Math.PI * 2f) / period) * overshoot;
	}

	public static float easeInOutElastic(float start, float end, float val, float overshoot = 1f, float period = 0.3f)
	{
		end -= start;
		float num = 0f;
		float num2 = 0f;
		if (val == 0f)
		{
			return start;
		}
		val /= 0.5f;
		if (val == 2f)
		{
			return start + end;
		}
		if (num2 == 0f || num2 < Mathf.Abs(end))
		{
			num2 = end;
			num = period / 4f;
		}
		else
		{
			num = period / ((float)Math.PI * 2f) * Mathf.Asin(end / num2);
		}
		if (overshoot > 1f)
		{
			if (val < 0.2f)
			{
				overshoot = 1f + val / 0.2f * (overshoot - 1f);
			}
			else if (val > 0.8f)
			{
				overshoot = 1f + (1f - val) / 0.2f * (overshoot - 1f);
			}
		}
		if (val < 1f)
		{
			val -= 1f;
			return start - 0.5f * (num2 * Mathf.Pow(2f, 10f * val) * Mathf.Sin((val - num) * ((float)Math.PI * 2f) / period)) * overshoot;
		}
		val -= 1f;
		return end + start + num2 * Mathf.Pow(2f, -10f * val) * Mathf.Sin((val - num) * ((float)Math.PI * 2f) / period) * 0.5f * overshoot;
	}

	public static void addListener(int eventId, Action<LTEvent> callback)
	{
		addListener(tweenEmpty, eventId, callback);
	}

	public static void addListener(GameObject caller, int eventId, Action<LTEvent> callback)
	{
		if (eventListeners == null)
		{
			INIT_LISTENERS_MAX = LISTENERS_MAX;
			eventListeners = new Action<LTEvent>[EVENTS_MAX * LISTENERS_MAX];
			goListeners = (GameObject[])(object)new GameObject[EVENTS_MAX * LISTENERS_MAX];
		}
		for (i = 0; i < INIT_LISTENERS_MAX; i++)
		{
			int num = eventId * INIT_LISTENERS_MAX + i;
			if ((Object)(object)goListeners[num] == (Object)null || eventListeners[num] == null)
			{
				eventListeners[num] = callback;
				goListeners[num] = caller;
				if (i >= eventsMaxSearch)
				{
					eventsMaxSearch = i + 1;
				}
				return;
			}
			if ((Object)(object)goListeners[num] == (Object)(object)caller && object.Equals(eventListeners[num], callback))
			{
				return;
			}
		}
		Debug.LogError((object)("You ran out of areas to add listeners, consider increasing LISTENERS_MAX, ex: LeanTween.LISTENERS_MAX = " + LISTENERS_MAX * 2));
	}

	public static bool removeListener(int eventId, Action<LTEvent> callback)
	{
		return removeListener(tweenEmpty, eventId, callback);
	}

	public static bool removeListener(int eventId)
	{
		int num = eventId * INIT_LISTENERS_MAX + i;
		eventListeners[num] = null;
		goListeners[num] = null;
		return true;
	}

	public static bool removeListener(GameObject caller, int eventId, Action<LTEvent> callback)
	{
		for (i = 0; i < eventsMaxSearch; i++)
		{
			int num = eventId * INIT_LISTENERS_MAX + i;
			if ((Object)(object)goListeners[num] == (Object)(object)caller && object.Equals(eventListeners[num], callback))
			{
				eventListeners[num] = null;
				goListeners[num] = null;
				return true;
			}
		}
		return false;
	}

	public static void dispatchEvent(int eventId)
	{
		dispatchEvent(eventId, null);
	}

	public static void dispatchEvent(int eventId, object data)
	{
		for (int i = 0; i < eventsMaxSearch; i++)
		{
			int num = eventId * INIT_LISTENERS_MAX + i;
			if (eventListeners[num] != null)
			{
				if (Object.op_Implicit((Object)(object)goListeners[num]))
				{
					eventListeners[num](new LTEvent(eventId, data));
				}
				else
				{
					eventListeners[num] = null;
				}
			}
		}
	}
}
public class LTUtility
{
	public static Vector3[] reverse(Vector3[] arr)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		int num = arr.Length;
		int num2 = 0;
		int num3 = num - 1;
		while (num2 < num3)
		{
			Vector3 val = arr[num2];
			arr[num2] = arr[num3];
			arr[num3] = val;
			num2++;
			num3--;
		}
		return arr;
	}
}
public class LTBezier
{
	public float length;

	private Vector3 a;

	private Vector3 aa;

	private Vector3 bb;

	private Vector3 cc;

	private float len;

	private float[] arcLengths;

	public LTBezier(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float precision)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: 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)
		this.a = a;
		aa = -a + 3f * (b - c) + d;
		bb = 3f * (a + c) - 6f * b;
		cc = 3f * (b - a);
		len = 1f / precision;
		arcLengths = new float[(int)len + 1];
		arcLengths[0] = 0f;
		Vector3 val = a;
		float num = 0f;
		for (int i = 1; (float)i <= len; i++)
		{
			Vector3 val2 = bezierPoint((float)i * precision);
			float num2 = num;
			Vector3 val3 = val - val2;
			num = num2 + ((Vector3)(ref val3)).magnitude;
			arcLengths[i] = num;
			val = val2;
		}
		length = num;
	}

	private float map(float u)
	{
		float num = u * arcLengths[(int)len];
		int num2 = 0;
		int num3 = (int)len;
		int num4 = 0;
		while (num2 < num3)
		{
			num4 = num2 + ((int)((float)(num3 - num2) / 2f) | 0);
			if (arcLengths[num4] < num)
			{
				num2 = num4 + 1;
			}
			else
			{
				num3 = num4;
			}
		}
		if (arcLengths[num4] > num)
		{
			num4--;
		}
		if (num4 < 0)
		{
			num4 = 0;
		}
		return ((float)num4 + (num - arcLengths[num4]) / (arcLengths[num4 + 1] - arcLengths[num4])) / len;
	}

	private Vector3 bezierPoint(float t)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		return ((aa * t + bb) * t + cc) * t + a;
	}

	public Vector3 point(float t)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		return bezierPoint(map(t));
	}
}
public class LTBezierPath
{
	public Vector3[] pts;

	public float length;

	public bool orientToPath;

	public bool orientToPath2d;

	private LTBezier[] beziers;

	private float[] lengthRatio;

	private int currentBezier;

	private int previousBezier;

	public float distance => length;

	public LTBezierPath()
	{
	}

	public LTBezierPath(Vector3[] pts_)
	{
		setPoints(pts_);
	}

	public void setPoints(Vector3[] pts_)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: 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)
		if (pts_.Length < 4)
		{
			LeanTween.logError("LeanTween - When passing values for a vector path, you must pass four or more values!");
		}
		if (pts_.Length % 4 != 0)
		{
			LeanTween.logError("LeanTween - When passing values for a vector path, they must be in sets of four: controlPoint1, controlPoint2, endPoint2, controlPoint2, controlPoint2...");
		}
		pts = pts_;
		int num = 0;
		beziers = new LTBezier[pts.Length / 4];
		lengthRatio = new float[beziers.Length];
		length = 0f;
		for (int i = 0; i < pts.Length; i += 4)
		{
			beziers[num] = new LTBezier(pts[i], pts[i + 2], pts[i + 1], pts[i + 3], 0.05f);
			length += beziers[num].length;
			num++;
		}
		for (int i = 0; i < beziers.Length; i++)
		{
			lengthRatio[i] = beziers[i].length / length;
		}
	}

	public Vector3 point(float ratio)
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		float num = 0f;
		for (int i = 0; i < lengthRatio.Length; i++)
		{
			num += lengthRatio[i];
			if (num >= ratio)
			{
				return beziers[i].point((ratio - (num - lengthRatio[i])) / lengthRatio[i]);
			}
		}
		return beziers[lengthRatio.Length - 1].point(1f);
	}

	public void place2d(Transform transform, float ratio)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		transform.position = point(ratio);
		ratio += 0.001f;
		if (ratio <= 1f)
		{
			Vector3 val = point(ratio) - transform.position;
			float num = Mathf.Atan2(val.y, val.x) * 57.29578f;
			transform.eulerAngles = new Vector3(0f, 0f, num);
		}
	}

	public void placeLocal2d(Transform transform, float ratio)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		transform.localPosition = point(ratio);
		ratio += 0.001f;
		if (ratio <= 1f)
		{
			Vector3 val = point(ratio) - transform.localPosition;
			float num = Mathf.Atan2(val.y, val.x) * 57.29578f;
			transform.localEulerAngles = new Vector3(0f, 0f, num);
		}
	}

	public void place(Transform transform, float ratio)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		place(transform, ratio, Vector3.up);
	}

	public void place(Transform transform, float ratio, Vector3 worldUp)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		transform.position = point(ratio);
		ratio += 0.001f;
		if (ratio <= 1f)
		{
			transform.LookAt(point(ratio), worldUp);
		}
	}

	public void placeLocal(Transform transform, float ratio)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		placeLocal(transform, ratio, Vector3.up);
	}

	public void placeLocal(Transform transform, float ratio, Vector3 worldUp)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		ratio = getRationInOneRange(ratio);
		transform.localPosition = point(ratio);
		ratio = getRationInOneRange(ratio + 0.001f);
		if (ratio <= 1f)
		{
			transform.LookAt(transform.parent.TransformPoint(point(ratio)), worldUp);
		}
	}

	public float getRationInOneRange(float ratio)
	{
		if (ratio >= 0f && ratio <= 1f)
		{
			return ratio;
		}
		if (ratio < 0f)
		{
			return Mathf.Ceil(ratio) - ratio;
		}
		return ratio - Mathf.Floor(ratio);
	}

	public void gizmoDraw(float t = -1f)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = point(0f);
		for (int i = 1; i <= 120; i++)
		{
			float ratio = (float)i / 120f;
			Vector3 val2 = point(ratio);
			Gizmos.color = ((previousBezier == currentBezier) ? Color.magenta : Color.grey);
			Gizmos.DrawLine(val2, val);
			val = val2;
			previousBezier = currentBezier;
		}
	}
}
[Serializable]
public class LTSpline
{
	public static int DISTANCE_COUNT = 3;

	public static int SUBLINE_COUNT = 20;

	public float distance;

	public bool constantSpeed = true;

	public Vector3[] pts;

	[NonSerialized]
	public Vector3[] ptsAdj;

	public int ptsAdjLength;

	public bool orientToPath;

	public bool orientToPath2d;

	private int numSections;

	private int currPt;

	public LTSpline(Vector3[] pts)
	{
		init(pts, constantSpeed: true);
	}

	public LTSpline(Vector3[] pts, bool constantSpeed)
	{
		this.constantSpeed = constantSpeed;
		init(pts, constantSpeed);
	}

	private void init(Vector3[] pts, bool constantSpeed)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		if (pts.Length < 4)
		{
			LeanTween.logError("LeanTween - When passing values for a spline path, you must pass four or more values!");
			return;
		}
		this.pts = (Vector

BepInEx/plugins/es.damntry.SuperQoLity/Microsoft.Bcl.HashCode.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Numerics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using FxResources.Microsoft.Bcl.HashCode;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: CLSCompliant(true)]
[assembly: AssemblyDefaultAlias("Microsoft.Bcl.HashCode")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Microsoft.Bcl.HashCode")]
[assembly: AssemblyFileVersion("6.0.24.56208")]
[assembly: AssemblyInformationalVersion("6.0.0+d0c2a5a83211e271826172a6b0510c25a52dbd53")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Bcl.HashCode")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/maintenance-packages")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("6.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal class Interop
{
	internal unsafe static void GetRandomBytes(byte* buffer, int length)
	{
		if (!System.LocalAppContextSwitches.UseNonRandomizedHashSeed)
		{
			using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create())
			{
				byte[] array = new byte[length];
				randomNumberGenerator.GetBytes(array);
				Marshal.Copy(array, 0, (IntPtr)buffer, length);
			}
		}
	}
}
namespace FxResources.Microsoft.Bcl.HashCode
{
	internal static class SR
	{
	}
}
namespace System
{
	public struct HashCode
	{
		private static readonly uint s_seed = GenerateGlobalSeed();

		private const uint Prime1 = 2654435761u;

		private const uint Prime2 = 2246822519u;

		private const uint Prime3 = 3266489917u;

		private const uint Prime4 = 668265263u;

		private const uint Prime5 = 374761393u;

		private uint _v1;

		private uint _v2;

		private uint _v3;

		private uint _v4;

		private uint _queue1;

		private uint _queue2;

		private uint _queue3;

		private uint _length;

		private unsafe static uint GenerateGlobalSeed()
		{
			uint result = default(uint);
			global::Interop.GetRandomBytes((byte*)(&result), 4);
			return result;
		}

		public static int Combine<T1>(T1 value1)
		{
			uint queuedValue = (uint)(value1?.GetHashCode() ?? 0);
			uint num = MixEmptyState();
			num += 4;
			num = QueueRound(num, queuedValue);
			return (int)MixFinal(num);
		}

		public static int Combine<T1, T2>(T1 value1, T2 value2)
		{
			uint queuedValue = (uint)(value1?.GetHashCode() ?? 0);
			uint queuedValue2 = (uint)(value2?.GetHashCode() ?? 0);
			uint num = MixEmptyState();
			num += 8;
			num = QueueRound(num, queuedValue);
			num = QueueRound(num, queuedValue2);
			return (int)MixFinal(num);
		}

		public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3)
		{
			uint queuedValue = (uint)(value1?.GetHashCode() ?? 0);
			uint queuedValue2 = (uint)(value2?.GetHashCode() ?? 0);
			uint queuedValue3 = (uint)(value3?.GetHashCode() ?? 0);
			uint num = MixEmptyState();
			num += 12;
			num = QueueRound(num, queuedValue);
			num = QueueRound(num, queuedValue2);
			num = QueueRound(num, queuedValue3);
			return (int)MixFinal(num);
		}

		public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4)
		{
			uint input = (uint)(value1?.GetHashCode() ?? 0);
			uint input2 = (uint)(value2?.GetHashCode() ?? 0);
			uint input3 = (uint)(value3?.GetHashCode() ?? 0);
			uint input4 = (uint)(value4?.GetHashCode() ?? 0);
			Initialize(out var v, out var v2, out var v3, out var v4);
			v = Round(v, input);
			v2 = Round(v2, input2);
			v3 = Round(v3, input3);
			v4 = Round(v4, input4);
			uint num = MixState(v, v2, v3, v4);
			num += 16;
			return (int)MixFinal(num);
		}

		public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5)
		{
			uint input = (uint)(value1?.GetHashCode() ?? 0);
			uint input2 = (uint)(value2?.GetHashCode() ?? 0);
			uint input3 = (uint)(value3?.GetHashCode() ?? 0);
			uint input4 = (uint)(value4?.GetHashCode() ?? 0);
			uint queuedValue = (uint)(value5?.GetHashCode() ?? 0);
			Initialize(out var v, out var v2, out var v3, out var v4);
			v = Round(v, input);
			v2 = Round(v2, input2);
			v3 = Round(v3, input3);
			v4 = Round(v4, input4);
			uint num = MixState(v, v2, v3, v4);
			num += 20;
			num = QueueRound(num, queuedValue);
			return (int)MixFinal(num);
		}

		public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6)
		{
			uint input = (uint)(value1?.GetHashCode() ?? 0);
			uint input2 = (uint)(value2?.GetHashCode() ?? 0);
			uint input3 = (uint)(value3?.GetHashCode() ?? 0);
			uint input4 = (uint)(value4?.GetHashCode() ?? 0);
			uint queuedValue = (uint)(value5?.GetHashCode() ?? 0);
			uint queuedValue2 = (uint)(value6?.GetHashCode() ?? 0);
			Initialize(out var v, out var v2, out var v3, out var v4);
			v = Round(v, input);
			v2 = Round(v2, input2);
			v3 = Round(v3, input3);
			v4 = Round(v4, input4);
			uint num = MixState(v, v2, v3, v4);
			num += 24;
			num = QueueRound(num, queuedValue);
			num = QueueRound(num, queuedValue2);
			return (int)MixFinal(num);
		}

		public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7)
		{
			uint input = (uint)(value1?.GetHashCode() ?? 0);
			uint input2 = (uint)(value2?.GetHashCode() ?? 0);
			uint input3 = (uint)(value3?.GetHashCode() ?? 0);
			uint input4 = (uint)(value4?.GetHashCode() ?? 0);
			uint queuedValue = (uint)(value5?.GetHashCode() ?? 0);
			uint queuedValue2 = (uint)(value6?.GetHashCode() ?? 0);
			uint queuedValue3 = (uint)(value7?.GetHashCode() ?? 0);
			Initialize(out var v, out var v2, out var v3, out var v4);
			v = Round(v, input);
			v2 = Round(v2, input2);
			v3 = Round(v3, input3);
			v4 = Round(v4, input4);
			uint num = MixState(v, v2, v3, v4);
			num += 28;
			num = QueueRound(num, queuedValue);
			num = QueueRound(num, queuedValue2);
			num = QueueRound(num, queuedValue3);
			return (int)MixFinal(num);
		}

		public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8)
		{
			uint input = (uint)(value1?.GetHashCode() ?? 0);
			uint input2 = (uint)(value2?.GetHashCode() ?? 0);
			uint input3 = (uint)(value3?.GetHashCode() ?? 0);
			uint input4 = (uint)(value4?.GetHashCode() ?? 0);
			uint input5 = (uint)(value5?.GetHashCode() ?? 0);
			uint input6 = (uint)(value6?.GetHashCode() ?? 0);
			uint input7 = (uint)(value7?.GetHashCode() ?? 0);
			uint input8 = (uint)(value8?.GetHashCode() ?? 0);
			Initialize(out var v, out var v2, out var v3, out var v4);
			v = Round(v, input);
			v2 = Round(v2, input2);
			v3 = Round(v3, input3);
			v4 = Round(v4, input4);
			v = Round(v, input5);
			v2 = Round(v2, input6);
			v3 = Round(v3, input7);
			v4 = Round(v4, input8);
			uint num = MixState(v, v2, v3, v4);
			num += 32;
			return (int)MixFinal(num);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4)
		{
			v1 = (uint)((int)s_seed + -1640531535 + -2048144777);
			v2 = s_seed + 2246822519u;
			v3 = s_seed;
			v4 = s_seed - 2654435761u;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint Round(uint hash, uint input)
		{
			return BitOperations.RotateLeft(hash + (uint)((int)input * -2048144777), 13) * 2654435761u;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint QueueRound(uint hash, uint queuedValue)
		{
			return BitOperations.RotateLeft(hash + (uint)((int)queuedValue * -1028477379), 17) * 668265263;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint MixState(uint v1, uint v2, uint v3, uint v4)
		{
			return BitOperations.RotateLeft(v1, 1) + BitOperations.RotateLeft(v2, 7) + BitOperations.RotateLeft(v3, 12) + BitOperations.RotateLeft(v4, 18);
		}

		private static uint MixEmptyState()
		{
			return s_seed + 374761393;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint MixFinal(uint hash)
		{
			hash ^= hash >> 15;
			hash *= 2246822519u;
			hash ^= hash >> 13;
			hash *= 3266489917u;
			hash ^= hash >> 16;
			return hash;
		}

		public void Add<T>(T value)
		{
			Add(value?.GetHashCode() ?? 0);
		}

		public void Add<T>(T value, IEqualityComparer<T>? comparer)
		{
			Add(comparer?.GetHashCode(value) ?? value?.GetHashCode() ?? 0);
		}

		private void Add(int value)
		{
			uint num = _length++;
			switch (num % 4)
			{
			case 0u:
				_queue1 = (uint)value;
				return;
			case 1u:
				_queue2 = (uint)value;
				return;
			case 2u:
				_queue3 = (uint)value;
				return;
			}
			if (num == 3)
			{
				Initialize(out _v1, out _v2, out _v3, out _v4);
			}
			_v1 = Round(_v1, _queue1);
			_v2 = Round(_v2, _queue2);
			_v3 = Round(_v3, _queue3);
			_v4 = Round(_v4, (uint)value);
		}

		public int ToHashCode()
		{
			uint length = _length;
			uint num = length % 4;
			uint num2 = ((length < 4) ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4));
			num2 += length * 4;
			if (num != 0)
			{
				num2 = QueueRound(num2, _queue1);
				if (num > 1)
				{
					num2 = QueueRound(num2, _queue2);
					if (num > 2)
					{
						num2 = QueueRound(num2, _queue3);
					}
				}
			}
			return (int)MixFinal(num2);
		}

		[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", true)]
		[EditorBrowsable(EditorBrowsableState.Never)]
		public override int GetHashCode()
		{
			throw new NotSupportedException(System.SR.HashCode_HashCodeNotSupported);
		}

		[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", true)]
		[EditorBrowsable(EditorBrowsableState.Never)]
		public override bool Equals(object? obj)
		{
			throw new NotSupportedException(System.SR.HashCode_EqualityNotSupported);
		}
	}
	internal static class LocalAppContextSwitches
	{
		private static int s_useNonRandomizedHashSeed;

		public static bool UseNonRandomizedHashSeed
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				return GetCachedSwitchValue("Switch.System.Data.UseNonRandomizedHashSeed", ref s_useNonRandomizedHashSeed);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static bool GetCachedSwitchValue(string switchName, ref int cachedSwitchValue)
		{
			if (cachedSwitchValue < 0)
			{
				return false;
			}
			if (cachedSwitchValue > 0)
			{
				return true;
			}
			return GetCachedSwitchValueInternal(switchName, ref cachedSwitchValue);
		}

		private static bool GetCachedSwitchValueInternal(string switchName, ref int cachedSwitchValue)
		{
			if (!AppContext.TryGetSwitch(switchName, out var isEnabled))
			{
				isEnabled = GetSwitchDefaultValue(switchName);
			}
			AppContext.TryGetSwitch("TestSwitch.LocalAppContext.DisableCaching", out var isEnabled2);
			if (!isEnabled2)
			{
				cachedSwitchValue = (isEnabled ? 1 : (-1));
			}
			return isEnabled;
		}

		private static bool GetSwitchDefaultValue(string switchName)
		{
			if (switchName == "Switch.System.Runtime.Serialization.SerializationGuard")
			{
				return true;
			}
			return false;
		}
	}
	internal static class SR
	{
		private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled;

		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string HashCode_EqualityNotSupported => GetResourceString("HashCode_EqualityNotSupported");

		internal static string HashCode_HashCodeNotSupported => GetResourceString("HashCode_HashCodeNotSupported");

		private static bool UsingResourceKeys()
		{
			return s_usingResourceKeys;
		}

		internal static string GetResourceString(string resourceKey)
		{
			if (UsingResourceKeys())
			{
				return resourceKey;
			}
			string result = null;
			try
			{
				result = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			return result;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string resourceString = GetResourceString(resourceKey);
			if (!(resourceKey == resourceString) && resourceString != null)
			{
				return resourceString;
			}
			return defaultString;
		}

		internal static string Format(string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}

		internal static string Format(string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(provider, resourceFormat, p1);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(provider, resourceFormat, p1, p2);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(provider, resourceFormat, p1, p2, p3);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(provider, resourceFormat, args);
			}
			return resourceFormat;
		}
	}
}
namespace System.Numerics
{
	internal static class BitOperations
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static uint RotateLeft(uint value, int offset)
		{
			return (value << offset) | (value >> 32 - offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ulong RotateLeft(ulong value, int offset)
		{
			return (value << offset) | (value >> 64 - offset);
		}
	}
}

BepInEx/plugins/es.damntry.SuperQoLity/SuperQoLity-Release.dll

Decompiled 3 weeks ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using Cysharp.Threading.Tasks;
using Damntry.Utils.Collections.Queues;
using Damntry.Utils.Collections.Queues.Interfaces;
using Damntry.Utils.Events;
using Damntry.Utils.ExtensionMethods;
using Damntry.Utils.Logging;
using Damntry.Utils.Reflection;
using Damntry.Utils.Tasks;
using Damntry.Utils.Tasks.AsyncDelay;
using Damntry.Utils.Timers;
using Damntry.Utils.Timers.StopwatchImpl;
using Damntry.UtilsBepInEx.Components;
using Damntry.UtilsBepInEx.Configuration;
using Damntry.UtilsBepInEx.Configuration.ConfigurationManager;
using Damntry.UtilsBepInEx.Configuration.ConfigurationManager.SettingAttributes;
using Damntry.UtilsBepInEx.Debug;
using Damntry.UtilsBepInEx.HarmonyPatching;
using Damntry.UtilsBepInEx.HarmonyPatching.Attributes;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.Attributes;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.BaseClasses;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.BaseClasses.Inheritable;
using Damntry.UtilsBepInEx.HarmonyPatching.AutoPatching.Interfaces;
using Damntry.UtilsBepInEx.HarmonyPatching.Exceptions;
using Damntry.UtilsBepInEx.IL;
using Damntry.UtilsBepInEx.Logging;
using Damntry.UtilsBepInEx.ModHelpers;
using Damntry.UtilsMirror.Attributes;
using Damntry.UtilsMirror.Components;
using Damntry.UtilsMirror.Helpers;
using Damntry.UtilsMirror.SyncVar;
using Damntry.UtilsUnity.Components.InputManagement;
using Damntry.UtilsUnity.Components.InputManagement.Model;
using Damntry.UtilsUnity.ExtensionMethods;
using Damntry.UtilsUnity.Rendering;
using Damntry.UtilsUnity.Resources;
using Damntry.UtilsUnity.Tasks.AsyncDelay;
using Damntry.UtilsUnity.Timers;
using Damntry.UtilsUnity.UI;
using Damntry.UtilsUnity.UI.Extensions;
using Damntry.UtilsUnity.Vectors;
using HarmonyLib;
using HighlightPlus;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using Mirror;
using Mirror.RemoteCalls;
using Rewired;
using Rito.RadialMenu_v3;
using StarterAssets;
using Steamworks;
using SuperQoLity.SuperMarket.ModUtils;
using SuperQoLity.SuperMarket.ModUtils.ExternalMods;
using SuperQoLity.SuperMarket.ModUtils.Messaging;
using SuperQoLity.SuperMarket.ModUtils.UI;
using SuperQoLity.SuperMarket.PatchClassHelpers.Components;
using SuperQoLity.SuperMarket.PatchClassHelpers.ContainerEntities;
using SuperQoLity.SuperMarket.PatchClassHelpers.ContainerEntities.Search;
using SuperQoLity.SuperMarket.PatchClassHelpers.ContainerEntities.ShelfSlotInfo;
using SuperQoLity.SuperMarket.PatchClassHelpers.Equipment.Model;
using SuperQoLity.SuperMarket.PatchClassHelpers.Equipment.RadialWheel;
using SuperQoLity.SuperMarket.PatchClassHelpers.Equipment.RadialWheel.Model;
using SuperQoLity.SuperMarket.PatchClassHelpers.Highlighting;
using SuperQoLity.SuperMarket.PatchClassHelpers.Highlighting.Caching;
using SuperQoLity.SuperMarket.PatchClassHelpers.Highlighting.Definitions;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.Customers;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.Employees.RestockMatch;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.Employees.RestockMatch.Component;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.Employees.RestockMatch.Helpers;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.Employees.RestockMatch.Models;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.Employees.TargetMarking;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.JobScheduler;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.JobScheduler.AutoMode;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.JobScheduler.AutoMode.DataDefinition;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.JobScheduler.Helpers;
using SuperQoLity.SuperMarket.PatchClassHelpers.NPCs.Movement;
using SuperQoLity.SuperMarket.PatchClassHelpers.Networking.SyncVarBehaviours;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons.Definitions;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons.Definitions.Interfaces;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons.FireEffects;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons.FireEffects.Helpers;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons.FireEffects.Helpers.Model;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons.FireEffects.Model;
using SuperQoLity.SuperMarket.PatchClassHelpers.Weapons.Helpers;
using SuperQoLity.SuperMarket.Patches.BroomShotgun;
using SuperQoLity.SuperMarket.Patches.Building;
using SuperQoLity.SuperMarket.Patches.EquipmentWheel;
using SuperQoLity.SuperMarket.Patches.Highlighting;
using SuperQoLity.SuperMarket.Patches.Misc;
using SuperQoLity.SuperMarket.Patches.NPC;
using SuperQoLity.SuperMarket.Patches.NPC.Customer;
using SuperQoLity.SuperMarket.Patches.NPC.EmployeeModule;
using SuperQoLity.SuperMarket.Patches.TransferItemsModule;
using SuperQoLity.SuperMarket.Standalone;
using SuperQoLity.SuperMarket.Standalone.Components;
using SuperQoLity.SuperMarket.Standalone.MainMenuLogo;
using SuperQoLity.SuperMarket.Standalone.MainMenuLogo.Fsm;
using TMPro;
using TeoGames.Mesh_Combiner.Scripts.Combine;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Animations.Rigging;
using UnityEngine.Events;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Networking;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityHotReloadNS;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("None")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Bepinex plugin for Supermarket Together adding extra QoL features")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2.0+c4b32d218afa47503040f7dcdb612726fce98e4b")]
[assembly: AssemblyProduct("es.damntry.SuperQoLity")]
[assembly: AssemblyTitle("SuperQoLity")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal delegate TResult <>f__AnonymousDelegate0<T1, TResult>(T1 arg = default(T1));
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SuperQoLity
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("es.damntry.SuperQoLity", "SuperQoLity", "1.0.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static PreprocessMessageFunc <0>__RemoveSpecialNotifNewLinesForLog;
		}

		private static int AssetIdModSignature { get; } = 3071;


		public static bool IsSolutionInDebugMode { get; private set; } = false;


		public void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__RemoveSpecialNotifNewLinesForLog;
			if (obj == null)
			{
				PreprocessMessageFunc val = GameNotifications.RemoveSpecialNotifNewLinesForLog;
				<>O.<0>__RemoveSpecialNotifNewLinesForLog = val;
				obj = (object)val;
			}
			TimeLogger.InitializeTimeLogger<BepInExTimeLogger>((PreprocessMessageFunc)obj, false, new object[1] { "SuperQoLity" });
			SolutionDebugModeHandler();
			ModConfig.Instance.InitializeConfig((BaseUnityPlugin)(object)this);
			ConfigDebugModeHandler();
			AutoPatcher.RegisterAllAutoPatchContainers();
			ModConfig.Instance.StartConfigBinding();
			GameNotifications.Instance.InitializeGameNotifications();
			TaskExtensionMethods.FireAndForget(((InputDetection)InputManagerSMT.Instance).InitializeAsync((Func<MonoBehaviour>)(() => (MonoBehaviour)(object)FirstPersonController.Instance), (Func<bool>)(() => !AuxUtils.IsChatOpen())), (LogCategories)8);
			NetworkSpawnManager.Initialize(AssetIdModSignature);
			TimeLogger.Logger.LogDebug("SuperQoLity (es.damntry.SuperQoLity) initialization finished.", (LogCategories)8);
			bool flag = AutoPatcher.StartAutoPatcher();
			CopyBuildableOnCursor.AddHotkeys();
			MainMenuLogos.StartProcess();
			StartingMessage.InitStartingMessages(flag);
			TimeLogger.Logger.LogMessage("Mod SuperQoLity (es.damntry.SuperQoLity) loaded " + (flag ? "" : "(not quite) ") + "successfully.", (LogCategories)8);
		}

		private void SetupHotReloading()
		{
			InputManagerSMT.Instance.TryAddHotkey("HotReload", (KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }, (InputState)0, HotkeyActiveContext.AlwaysActiveHighPrio, async delegate
			{
				TimeLogger.Logger.LogMessageShowInGame("Beginning SuperQoLity Hot Reloading", (LogCategories)int.MinValue);
				await Task.Delay(100);
				UnityHotReload.LoadNewAssemblyVersion(((object)this).GetType().Assembly, "C:\\Users\\Damntry\\Visual Studio Projects\\Visual Studio 2019 Projects\\repos\\!Supermarket Together\\SupermarketTogether_SuperQoLity\\SMT_QoLity\\bin\\Debug\\net481\\SuperQoLity.dll");
				TimeLogger.Logger.LogMessageShowInGame("Hot Reloading finished", (LogCategories)int.MinValue);
			});
		}

		private void SolutionDebugModeHandler()
		{
		}

		public static void ConfigDebugModeHandler()
		{
			bool flag = ModConfig.Instance.IsDebugEnabledConfig();
			if (flag != TimeLogger.DebugEnabled)
			{
				TimeLogger.DebugEnabled = flag;
				TimeLogger.Logger.LogWarning("SuperQoLity Debug Dev mode " + (flag ? "enabled" : "disabled") + ".", (LogCategories)8);
			}
		}

		public static void HookChangeDebugSetting()
		{
			ModConfig.Instance.EnabledDevMode.SettingChanged += delegate
			{
				ConfigDebugModeHandler();
			};
		}

		private CheckResult StartMethodSignatureCheck()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			try
			{
				MethodSignatureChecker val = new MethodSignatureChecker(((object)this).GetType());
				val.PopulateMethodSignaturesFromHarmonyPatches();
				val.AddMethod(typeof(NPC_Manager), "EmployeeNPCControl", new Type[1] { typeof(int) }, (Type[])null);
				val.AddMethod(typeof(NPC_Manager), "GetFreeStorageContainer", new Type[1] { typeof(int) }, (Type[])null);
				val.AddMethod(typeof(NPC_Manager), "MainRestockUpdate");
				val.AddMethod(typeof(NPC_Manager), "CheckIfShelfWithSameProduct");
				val.AddMethod(typeof(NPC_Manager), "GetRandomGroundBox");
				val.AddMethod(typeof(NPC_Manager), "GetRandomGroundBoxAllowedInStorage");
				val.AddMethod(typeof(NPC_Manager), "DropBoxOnGround");
				val.AddMethod(typeof(NPC_Manager), "UnequipBox");
				val.AddMethod(typeof(NPC_Manager), "AttemptToGetRestPosition");
				val.AddMethod(typeof(NPC_Manager), "CashierGetAvailableCheckout");
				val.AddMethod(typeof(NPC_Manager), "UpdateEmployeeCheckouts");
				val.AddMethod(typeof(NPC_Manager), "CheckIfCustomerInQueue");
				val.AddMethod(typeof(NPC_Manager), "GetThiefTarget");
				val.AddMethod(typeof(NPC_Manager), "IsFirstSecurityEmployee");
				val.AddMethod(typeof(NPC_Manager), "GetClosestDropProduct");
				val.AddMethod(typeof(NPC_Manager), "RetrieveCorrectPatrolPoint");
				val.AddMethod(typeof(NPC_Manager), "UpdateEmployeeStats");
				return val.StartSignatureCheck();
			}
			catch (Exception ex)
			{
				TimeLogger.Logger.LogException(ex, (LogCategories)4194304);
				return CheckResult.UnknownError;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "es.damntry.SuperQoLity";

		public const string PLUGIN_NAME = "SuperQoLity";

		public const string PLUGIN_VERSION = "1.0.2.0";

		public const string BETTERSMT_SUPPORTED_VERSION = "2.5.0";
	}
}
namespace SuperQoLity.SuperMarket
{
	public enum GameOnlineMode
	{
		None,
		Host,
		Client
	}
	public enum GameWorldEvent
	{
		QuitOrMenu,
		LoadingWorld,
		CanvasAwake,
		FPControllerStarted,
		WorldLoaded
	}
	public enum CharacterSourceType
	{
		LocalPlayer,
		RemotePlayer,
		Employee
	}
	public static class WorldState
	{
		public static class BuildingEvents
		{
			public static Action<Transform, ParentContainerType> OnShelfBuiltOrLoaded;

			public static Action<Data_Container> OnProductShelfLoadedBuiltOrUpdated;

			public static Action<Data_Container> OnStorageLoadedBuiltOrUpdated;
		}

		public static class ContainerEvents
		{
			public static Action<Transform> OnBoxSpawned;

			public static Action<Transform, int> OnBoxEquippedOrUpdatedLocalPlayer;

			public static Action<Transform, Transform, int, CharacterSourceType> OnBoxEquippedRemotePlayerOrEmployee;

			public static Action<Transform, CharacterSourceType> OnBoxDroppedByPlayer;

			public static Action<Data_Container> OnBoxIntoStorage;

			public static Action<Data_Container> OnProdShelfAssigned;

			public static Action<Data_Container> OnProdShelfUnassigned;
		}

		public static class PlayerEvents
		{
			public static Action<PlayerNetwork, Transform, Transform, int, int, bool> OnChangeEquipment;
		}

		public static class NPC_Events
		{
			public static Action<NPC_Info, int> OnEmployeeSpawned;
		}

		public static Action<bool, bool> OnGamePauseChanged;

		public static GameWorldEvent CurrentGameWorldState { get; private set; }

		public static GameOnlineMode CurrentOnlineMode { get; set; }

		public static bool IsWorldLoaded => CurrentGameWorldState == GameWorldEvent.WorldLoaded;

		public static bool IsHost => CurrentOnlineMode == GameOnlineMode.Host;

		public static bool IsClient => CurrentOnlineMode == GameOnlineMode.Client;

		public static event Action<GameWorldEvent> OnGameWorldChange;

		public static event Action OnQuitOrMainMenu;

		public static event Action OnLoadingWorld;

		public static event Action OnCanvasAwake;

		public static event Action OnFPControllerStarted;

		public static event Action OnWorldLoaded;

		public static bool IsGameWorldAtOrAfter(GameWorldEvent worldState)
		{
			return CurrentGameWorldState >= worldState;
		}

		public static void SetGameWorldState(GameWorldEvent state)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (state > CurrentGameWorldState || state == GameWorldEvent.QuitOrMenu)
			{
				TimeLogger.Logger.LogDebugFunc((Func<string>)(() => "World state change from " + $"{CurrentGameWorldState} to {state}"), (LogCategories)8);
				CurrentGameWorldState = state;
			}
			else
			{
				LogTier val = (LogTier)((CurrentOnlineMode == GameOnlineMode.Client) ? 32 : 2);
				TimeLogger.Logger.LogFunc(val, (Func<string>)(() => "World state wanted to change from " + $"{CurrentGameWorldState} to {state}, but it is not allowed."), (LogCategories)8, false, (ValueTuple<Action<string>, bool>[])null);
			}
			EventMethods.TryTriggerEvents<GameWorldEvent>(WorldState.OnGameWorldChange, state);
			EventMethods.TryTriggerEvents(GetSubscribersForWorldState(state));
		}

		public static void SubscribeToWorldStateEvent(GameWorldEvent state, Action actionOnEvent)
		{
			switch (state)
			{
			case GameWorldEvent.QuitOrMenu:
				OnQuitOrMainMenu += actionOnEvent;
				break;
			case GameWorldEvent.LoadingWorld:
				OnLoadingWorld += actionOnEvent;
				break;
			case GameWorldEvent.CanvasAwake:
				OnCanvasAwake += actionOnEvent;
				break;
			case GameWorldEvent.FPControllerStarted:
				OnFPControllerStarted += actionOnEvent;
				break;
			case GameWorldEvent.WorldLoaded:
				OnWorldLoaded += actionOnEvent;
				break;
			}
		}

		public static void UnsubscribeFromWorldStateEvent(GameWorldEvent state, Action actionOnEvent)
		{
			switch (state)
			{
			case GameWorldEvent.QuitOrMenu:
				OnQuitOrMainMenu -= actionOnEvent;
				break;
			case GameWorldEvent.LoadingWorld:
				OnLoadingWorld -= actionOnEvent;
				break;
			case GameWorldEvent.CanvasAwake:
				OnCanvasAwake -= actionOnEvent;
				break;
			case GameWorldEvent.FPControllerStarted:
				OnFPControllerStarted -= actionOnEvent;
				break;
			case GameWorldEvent.WorldLoaded:
				OnWorldLoaded -= actionOnEvent;
				break;
			}
		}

		public static Action GetSubscribersForWorldState(GameWorldEvent state)
		{
			return state switch
			{
				GameWorldEvent.QuitOrMenu => WorldState.OnQuitOrMainMenu, 
				GameWorldEvent.LoadingWorld => WorldState.OnLoadingWorld, 
				GameWorldEvent.CanvasAwake => WorldState.OnCanvasAwake, 
				GameWorldEvent.FPControllerStarted => WorldState.OnFPControllerStarted, 
				GameWorldEvent.WorldLoaded => WorldState.OnWorldLoaded, 
				_ => null, 
			};
		}
	}
}
namespace SuperQoLity.SuperMarket.Standalone
{
	public class CopyBuildableOnCursor
	{
		private enum BuildTargetAction
		{
			Clone,
			Move
		}

		private record IndexSearchResult(bool Found, int TabIndex, int MenuIndex);

		public static void AddHotkeys()
		{
			InputManagerSMT.Instance.AddHotkeyFromConfig(ModConfig.Instance.CloneBuildHotkey, (InputState)0, HotkeyActiveContext.WorldLoadedNotPaused, BeginCloneBuildTarget);
			InputManagerSMT.Instance.AddHotkeyFromConfig(ModConfig.Instance.MoveBuildHotkey, (InputState)0, HotkeyActiveContext.WorldLoadedNotPaused, BeginMoveBuildTarget);
		}

		public static void BeginCloneBuildTarget()
		{
			BeginBuildTargetAction(BuildTargetAction.Clone);
		}

		public static void BeginMoveBuildTarget()
		{
			BeginBuildTargetAction(BuildTargetAction.Move);
		}

		private static void BeginBuildTargetAction(BuildTargetAction copyMode)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			Builder_Main val = SMTInstances.BuilderMain();
			try
			{
				if (val.cCameraController.isInCameraEvent || FirstPersonController.Instance.inVehicle || !val.pComponent.RequestGP() || !val.pComponent.RequestMP() || val.pNetworkComponent.equippedItem == 5)
				{
					return;
				}
				if (copyMode == BuildTargetAction.Move && val.recentlyMoved)
				{
					if (Object.op_Implicit((Object)(object)val.hEffect))
					{
						((Behaviour)val.hEffect).enabled = false;
					}
					if (Object.op_Implicit((Object)(object)val.hEffect2))
					{
						val.hEffect2.highlighted = false;
					}
				}
				else
				{
					RaycastHit val2 = default(RaycastHit);
					if (!Physics.Raycast(((Component)Camera.main).transform.position, ((Component)Camera.main).transform.forward, ref val2, (float)ModConfig.Instance.CloneMoveTargetDistance.Value, LayerMask.op_Implicit(val.lMask)))
					{
						return;
					}
					Transform buildObj = ((RaycastHit)(ref val2)).transform;
					IndexSearchResult indexSearchResult = FindBuildMenuIndexes(val, ref buildObj);
					if (indexSearchResult.Found)
					{
						val.currentTabIndex = indexSearchResult.TabIndex;
						switch (copyMode)
						{
						case BuildTargetAction.Clone:
							val.currentElementIndex = indexSearchResult.MenuIndex;
							break;
						case BuildTargetAction.Move:
							val.currentElementIndex = 0;
							break;
						}
						val.DeactivateBuilder();
						val.SetDummy(val.currentTabIndex, val.currentElementIndex);
						val.cCameraController.ChangeLayerMask(true);
						val.canvasBuilderOBJ.SetActive(true);
						if (copyMode == BuildTargetAction.Move && !MoveBehaviour(buildObj))
						{
							val.canvasBuilderOBJ.SetActive(false);
						}
					}
				}
			}
			finally
			{
				if (!val.canvasBuilderOBJ.activeSelf)
				{
					val.DeactivateBuilder();
				}
			}
		}

		private static IndexSearchResult FindBuildMenuIndexes(Builder_Main builderMain, ref Transform buildObj)
		{
			if (((Component)buildObj).CompareTag(Tags.Interactable))
			{
				while (Object.op_Implicit((Object)(object)buildObj.parent) && !((Component)buildObj).CompareTag(Tags.Movable) && !((Component)buildObj).CompareTag(Tags.Decoration))
				{
					buildObj = buildObj.parent;
				}
			}
			if (((Component)buildObj).CompareTag(Tags.Movable))
			{
				Data_Container component = ((Component)buildObj).GetComponent<Data_Container>();
				return FindItemIdInBuildMenu(builderMain, 0, component.containerID);
			}
			if (((Component)buildObj).CompareTag(Tags.Decoration))
			{
				BuildableInfo component2 = ((Component)buildObj).GetComponent<BuildableInfo>();
				for (int i = 1; i < builderMain.tabContainerOBJ.transform.childCount; i++)
				{
					IndexSearchResult indexSearchResult = FindItemIdInBuildMenu(builderMain, i, component2.decorationID);
					if (indexSearchResult.Found)
					{
						return indexSearchResult;
					}
				}
			}
			return new IndexSearchResult(Found: false, -1, -1);
		}

		private static IndexSearchResult FindItemIdInBuildMenu(Builder_Main builderMain, int tabIndex, int itemId)
		{
			Transform val = ((Component)builderMain.tabContainerOBJ.transform.GetChild(tabIndex)).transform.Find("Container");
			for (int i = 0; i < val.childCount; i++)
			{
				Transform child = val.GetChild(i);
				if (Object.op_Implicit((Object)(object)((Component)child).GetComponent<PlayMakerFSM>()) && ((Component)child).GetComponent<PlayMakerFSM>().FsmVariables.GetFsmInt("PropIndex").Value == itemId)
				{
					return new IndexSearchResult(Found: true, tabIndex, i);
				}
			}
			return new IndexSearchResult(Found: false, -1, -1);
		}

		private static bool MoveBehaviour(Transform rayHit)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			Builder_Main val = SMTInstances.BuilderMain();
			if (((Component)rayHit).CompareTag(Tags.Movable))
			{
				if (Object.op_Implicit((Object)(object)val.oldHitOBJ2) && (Object)(object)((Component)rayHit).gameObject != (Object)(object)val.oldHitOBJ2 && Object.op_Implicit((Object)(object)val.hEffect2))
				{
					val.hEffect2.highlighted = false;
				}
				val.hEffect2 = ((Component)rayHit).GetComponent<HighlightEffect>();
				val.hEffect2.highlighted = true;
				val.oldHitOBJ2 = ((Component)rayHit).gameObject;
				val.currentMovedOBJ = ((Component)rayHit).gameObject;
				Data_Container component = val.currentMovedOBJ.GetComponent<Data_Container>();
				component.AddMoveEffect();
				val.buildableTag = component.buildableTag;
				GameObject dummyPrefab = component.dummyPrefab;
				val.dummyOBJ = Object.Instantiate<GameObject>(dummyPrefab, Vector3.zero, val.currentMovedOBJ.transform.rotation);
				val.canPlace = false;
				val.pmakerFSM = val.dummyOBJ.GetComponent<PlayMakerFSM>();
				if (Object.op_Implicit((Object)(object)val.hEffect2))
				{
					val.hEffect2.highlighted = false;
				}
				return true;
			}
			if (((Component)rayHit).CompareTag(Tags.Decoration))
			{
				if (Object.op_Implicit((Object)(object)val.oldHitOBJ) && (Object)(object)((Component)rayHit).gameObject != (Object)(object)val.oldHitOBJ && Object.op_Implicit((Object)(object)val.hEffect))
				{
					((Behaviour)val.hEffect).enabled = false;
				}
				val.hEffect = ((Component)rayHit.Find("Mesh")).GetComponent<HighlightEffect>();
				((Behaviour)val.hEffect).enabled = true;
				val.oldHitOBJ = ((Component)rayHit).gameObject;
				val.currentMovedOBJ = ((Component)rayHit).gameObject;
				BuildableInfo component2 = val.currentMovedOBJ.GetComponent<BuildableInfo>();
				GameObject dummyPrefabOBJ = component2.dummyPrefabOBJ;
				val.dummyOBJ = Object.Instantiate<GameObject>(dummyPrefabOBJ, Vector3.zero, val.currentMovedOBJ.transform.rotation);
				val.RetrieveBuilderInfo(component2);
				val.canPlace = false;
				val.pmakerFSM = val.dummyOBJ.GetComponent<PlayMakerFSM>();
				if (Object.op_Implicit((Object)(object)val.hEffect))
				{
					((Behaviour)val.hEffect).enabled = false;
				}
				return true;
			}
			return false;
		}
	}
}
namespace SuperQoLity.SuperMarket.Standalone.MainMenuLogo
{
	public static class MainMenuLogos
	{
		private static readonly string RelativeLogosFolderPath = "Assets\\MainMenuLogos";

		public static readonly int ProductsInBetween = 5;

		public static readonly (float min, float max) LogoRotationYRange = (-30f, 70f);

		public static readonly Vector3 LogoLocalPositionOffset = new Vector3(0f, 0.05f, 0f);

		private static readonly float LogoTargetSize = 32f;

		public static async void StartProcess()
		{
			int failCounter = 5;
			PlayMakerFSM fsm = default(PlayMakerFSM);
			while (failCounter > 0)
			{
				Scene activeScene = SceneManager.GetActiveScene();
				if (((Scene)(ref activeScene)).name == "A_Intro")
				{
					GameObject val = GameObject.Find("SpawnProductBehaviour");
					if (Object.op_Implicit((Object)(object)val) && val.TryGetComponent<PlayMakerFSM>(ref fsm))
					{
						List<GameObject> objectsFromLogos = GetObjectsFromLogos(GetVanillaMainMenuProduct(fsm));
						if (objectsFromLogos.Count != 0)
						{
							ReplaceFsmActions(fsm, objectsFromLogos);
						}
						else
						{
							TimeLogger.Logger.LogWarning("No logo images where found in the subfolder '" + RelativeLogosFolderPath + "'. Make sure that the files have png or jpg extension.", (LogCategories)268435456);
						}
						break;
					}
					failCounter++;
				}
				await Task.Delay(500);
			}
		}

		private static GameObject GetVanillaMainMenuProduct(PlayMakerFSM fsm)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			return (GameObject)fsm.Fsm.GetFsmArray("PRoductArray").Get(0);
		}

		private static List<GameObject> GetObjectsFromLogos(GameObject vanillaMainMenuProduct)
		{
			List<GameObject> list = new List<GameObject>();
			foreach (string item in from file in Directory.EnumerateFiles(AssemblyUtils.GetCombinedPathFromAssemblyFolder(typeof(Plugin), RelativeLogosFolderPath), "*.*", SearchOption.TopDirectoryOnly)
				where file.ToLower().EndsWith(".png") || file.ToLower().EndsWith(".jpg")
				select file)
			{
				TimeLogger.Logger.LogInfo("Found logo file: " + item, (LogCategories)268435456);
				list.Add(CreateProductObject(vanillaMainMenuProduct, item));
			}
			return list;
		}

		private static GameObject CreateProductObject(GameObject vanillaMainMenuProduct, string filePath)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(vanillaMainMenuProduct);
			Component val = ((IEnumerable<Component>)obj.GetComponents<Component>()).FirstOrDefault((Func<Component, bool>)((Component c) => ((object)c).ToString().Contains("Combinable")));
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.DestroyImmediate((Object)(object)val);
			}
			Object.DestroyImmediate((Object)(object)obj.GetComponent<MeshRenderer>());
			Object.DestroyImmediate((Object)(object)obj.GetComponent<MeshFilter>());
			SpriteRenderer obj2 = obj.AddComponent<SpriteRenderer>();
			obj2.sprite = AssetLoading.GetSpriteFromFile(filePath, new Vector2(0.5f, 0f), (GraphicsFormat)4, true);
			Rect rect = obj2.sprite.rect;
			float num = Math.Max(((Rect)(ref rect)).width, ((Rect)(ref rect)).height);
			float num2 = (float)Math.Round(LogoTargetSize / num, 4);
			((Component)obj2).transform.localScale = new Vector3(num2, num2, num2);
			return obj;
		}

		private static void ReplaceFsmActions(PlayMakerFSM fsm, List<GameObject> mainMenuLogos)
		{
			FsmState val = ((IEnumerable<FsmState>)fsm.FsmStates).FirstOrDefault((Func<FsmState, bool>)((FsmState f) => f.Name == "SpawnRandom"));
			if (val == null)
			{
				return;
			}
			for (int i = 0; i < val.Actions.Length; i++)
			{
				FsmStateAction val2 = val.Actions[i];
				ArrayGetRandom val3 = (ArrayGetRandom)(object)((val2 is ArrayGetRandom) ? val2 : null);
				if (val3 != null)
				{
					val.Actions[i] = (FsmStateAction)(object)new ArrayGetRandomButNotReally(val3, mainMenuLogos);
					continue;
				}
				RandomFloat val4 = (RandomFloat)(object)((val2 is RandomFloat) ? val2 : null);
				if (val4 != null)
				{
					val.Actions[i] = (FsmStateAction)(object)new RandomFloatButNotReally(val4);
					continue;
				}
				SetPosition val5 = (SetPosition)(object)((val2 is SetPosition) ? val2 : null);
				if (val5 != null)
				{
					val.Actions[i] = (FsmStateAction)(object)new SetPositionOffset(val5);
				}
			}
			val.SaveActions();
		}
	}
}
namespace SuperQoLity.SuperMarket.Standalone.MainMenuLogo.Fsm
{
	[ActionCategory(/*Could not decode attribute arguments.*/)]
	public class ArrayGetRandomButNotReally : ArrayGetRandom
	{
		private static int currentLogoArrayIndex;

		private int prodsUntilLogoCounter;

		private List<GameObject> mainMenuLogos;

		public static bool IsLastItemModLogo { get; private set; }

		public ArrayGetRandomButNotReally(ArrayGetRandom instance, List<GameObject> mainMenuLogos)
		{
			this.mainMenuLogos = mainMenuLogos;
			base.array = instance.array;
			base.storeValue = instance.storeValue;
			base.index = instance.index;
			base.noRepeat = instance.noRepeat;
			base.everyFrame = instance.everyFrame;
			base.randomIndex = instance.randomIndex;
			base.lastIndex = instance.lastIndex;
			prodsUntilLogoCounter = MainMenuLogos.ProductsInBetween;
		}

		public override void Reset()
		{
			mainMenuLogos = null;
			currentLogoArrayIndex = 0;
			prodsUntilLogoCounter = 0;
			prodsUntilLogoCounter = MainMenuLogos.ProductsInBetween;
			((ArrayGetRandom)this).Reset();
		}

		public override void OnEnter()
		{
			DoGetAlmostRandomValue();
			if (!base.everyFrame)
			{
				((FsmStateAction)this).Finish();
			}
		}

		public override void OnUpdate()
		{
			DoGetAlmostRandomValue();
		}

		private void DoGetAlmostRandomValue()
		{
			if (prodsUntilLogoCounter < MainMenuLogos.ProductsInBetween)
			{
				prodsUntilLogoCounter++;
				((ArrayGetRandom)this).DoGetRandomValue();
				IsLastItemModLogo = false;
				return;
			}
			base.storeValue.SetValue((object)mainMenuLogos[currentLogoArrayIndex++]);
			IsLastItemModLogo = true;
			if (currentLogoArrayIndex >= mainMenuLogos.Count)
			{
				prodsUntilLogoCounter = 0;
				currentLogoArrayIndex = 0;
			}
		}
	}
	[ActionCategory(/*Could not decode attribute arguments.*/)]
	public class RandomFloatButNotReally : RandomFloat
	{
		public RandomFloatButNotReally(RandomFloat instance)
		{
			base.min = instance.min;
			base.max = instance.max;
			base.storeResult = instance.storeResult;
		}

		public override void OnEnter()
		{
			float value = ((!ArrayGetRandomButNotReally.IsLastItemModLogo) ? Random.Range(base.min.Value, base.max.Value) : Random.Range(MainMenuLogos.LogoRotationYRange.min, MainMenuLogos.LogoRotationYRange.max));
			base.storeResult.Value = value;
			((FsmStateAction)this).Finish();
		}
	}
	[ActionCategory(/*Could not decode attribute arguments.*/)]
	public class SetPositionOffset : SetPosition
	{
		public SetPositionOffset(SetPosition instance)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			base.gameObject = instance.gameObject;
			base.vector = instance.vector;
			base.x = instance.x;
			base.y = instance.y;
			base.z = instance.z;
			base.space = instance.space;
			base.everyFrame = instance.everyFrame;
			base.lateUpdate = instance.lateUpdate;
		}

		public override void OnEnter()
		{
			if (!base.everyFrame && !base.lateUpdate)
			{
				DoSetPositionOffset();
				((FsmStateAction)this).Finish();
			}
		}

		public override void OnUpdate()
		{
			if (!base.lateUpdate)
			{
				DoSetPositionOffset();
			}
		}

		public override void OnLateUpdate()
		{
			if (base.lateUpdate)
			{
				DoSetPositionOffset();
			}
			if (!base.everyFrame)
			{
				((FsmStateAction)this).Finish();
			}
		}

		private void DoSetPositionOffset()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			((SetPosition)this).DoSetPosition();
			if (ArrayGetRandomButNotReally.IsLastItemModLogo)
			{
				Transform cachedTransform = ((ComponentAction<Transform>)this).cachedTransform;
				cachedTransform.localPosition += MainMenuLogos.LogoLocalPositionOffset;
			}
		}
	}
}
namespace SuperQoLity.SuperMarket.Standalone.Components
{
	public class FrequencyMult_Display : MonoBehaviour
	{
		private static FrequencyMult_Display instance;

		private GameObject freqMultDisplay;

		private TextMeshProUGUI textDisplay;

		private (float employee, float customer) loopMultiplierCycles;

		private bool allowDisplay;

		private void Awake()
		{
			freqMultDisplay = GameObjectManager.CreateSuperQoLGameObject("JobWorkload_Display", TargetObject.UI_MasterCanvas, new CreationSettings(false, TransformType.Transform, TransformLocals.Inherited));
			SetupUI();
			instance = this;
		}

		private void Start()
		{
			DisplayLogicFromSetting();
			ModConfig.Instance.DisplayAutoModeFrequencyMult.SettingChanged += delegate
			{
				DisplayLogicFromSetting();
			};
			JobSchedulerManager.OnNewJobFrequencyMultiplier += UpdateFreqMultiplierDisplay;
		}

		public static void Initialize()
		{
			GameObjectManager.AddComponentTo<FrequencyMult_Display>(TargetObject.UI_MasterCanvas);
		}

		private void SetupUI()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			freqMultDisplay.layer = 5;
			RectTransform obj = freqMultDisplay.AddComponent<RectTransform>();
			RectTransformExtensions.SetAnchorAndPivot(obj, (AnchorPresets)2, (PivotPresets)2, 0, 0);
			obj.anchoredPosition = new Vector2(-10f, -60f);
			obj.sizeDelta = new Vector2(100f, 50f);
			textDisplay = freqMultDisplay.AddComponent<TextMeshProUGUI>();
			((Graphic)textDisplay).color = new Color(0.9725f, 0.3176f, 0.8948f, 1f);
			((TMP_Text)textDisplay).fontSize = 21f;
			((TMP_Text)textDisplay).fontStyle = (FontStyles)0;
			((TMP_Text)textDisplay).horizontalAlignment = (HorizontalAlignmentOptions)4;
			((TMP_Text)textDisplay).verticalAlignment = (VerticalAlignmentOptions)512;
		}

		public static void AllowDisplay()
		{
			instance.allowDisplay = true;
			instance.ShowDisplay();
		}

		public static void Destroy()
		{
			if (!((Object)(object)instance == (Object)null))
			{
				instance.allowDisplay = false;
				ModConfig.Instance.DisplayAutoModeFrequencyMult.SettingChanged -= delegate
				{
					instance.DisplayLogicFromSetting();
				};
				JobSchedulerManager.OnNewJobFrequencyMultiplier -= instance.UpdateFreqMultiplierDisplay;
				Object.Destroy((Object)(object)instance.freqMultDisplay);
				instance = null;
			}
		}

		private void DisplayLogicFromSetting()
		{
			if (ModConfig.Instance.DisplayAutoModeFrequencyMult.Value)
			{
				ShowDisplay();
			}
			else
			{
				HideDisplay();
			}
		}

		private void ShowDisplay()
		{
			if (allowDisplay && ModConfig.Instance.DisplayAutoModeFrequencyMult.Value)
			{
				UpdateDisplay(forceUpdate: true);
				freqMultDisplay.SetActive(true);
			}
		}

		private void HideDisplay()
		{
			freqMultDisplay.SetActive(false);
		}

		private void UpdateFreqMultiplierDisplay(float loopMultiplierCycleEmployee, float loopMultiplierCycleCustomer)
		{
			loopMultiplierCycles = (loopMultiplierCycleEmployee, loopMultiplierCycleCustomer);
			UpdateDisplay(forceUpdate: false);
		}

		private void UpdateDisplay(bool forceUpdate)
		{
			if (freqMultDisplay.activeSelf || forceUpdate)
			{
				((TMP_Text)textDisplay).text = "E: " + GetFrequencyString(loopMultiplierCycles.employee) + " | C: " + GetFrequencyString(loopMultiplierCycles.customer);
			}
		}

		private string GetFrequencyString(float value)
		{
			if (value > 0f)
			{
				return Math.Round(value, 2) + " x";
			}
			return "OFF";
		}
	}
	public class InputBehaviour : MonoBehaviour
	{
		public delegate void InputAction(float currentTime, Player MainPlayerControls);

		private static InputBehaviour instance;

		private Player MainPlayerControls;

		private static bool isActive;

		private static GameWorldEvent behaviourWorldEvent = GameWorldEvent.FPControllerStarted;

		private static Dictionary<Type, (GameWorldEvent worldEventToStartAt, InputAction inputAction)> subscriptedReferences;

		public static void RegisterClickAction<T>(InputAction inputAction, GameWorldEvent worldEventToStartAt) where T : class
		{
			ActivateBehaviour();
			subscriptedReferences.Add(typeof(T), (worldEventToStartAt, inputAction));
		}

		public static void UnregisterClickAction<T>() where T : class
		{
			if (subscriptedReferences != null && subscriptedReferences.Count != 0 && subscriptedReferences.ContainsKey(typeof(T)))
			{
				subscriptedReferences.Remove(typeof(T));
				if (subscriptedReferences.Count == 0)
				{
					DeactivateBehaviour();
				}
			}
		}

		private static void ActivateBehaviour()
		{
			if (isActive)
			{
				return;
			}
			subscriptedReferences = new Dictionary<Type, (GameWorldEvent, InputAction)>();
			if (!Object.op_Implicit((Object)(object)instance) || !((MonoBehaviour)instance).didAwake)
			{
				WorldState.SubscribeToWorldStateEvent(behaviourWorldEvent, AddInputBehaviourComponent);
				WorldState.GetSubscribersForWorldState(behaviourWorldEvent);
				if (WorldState.IsGameWorldAtOrAfter(behaviourWorldEvent))
				{
					AddInputBehaviourComponent();
				}
			}
			isActive = true;
			if (Object.op_Implicit((Object)(object)instance))
			{
				((Behaviour)instance).enabled = true;
			}
		}

		private static void AddInputBehaviourComponent()
		{
			if ((Object)(object)GameObjectManager.AddComponentTo<InputBehaviour>(TargetObject.LocalGamePlayer) == (Object)null)
			{
				TimeLogger.Logger.LogError("The click behaviour component could not be added and all its related logic wont work.", (LogCategories)33554432);
			}
		}

		private static void DeactivateBehaviour()
		{
			if (isActive)
			{
				subscriptedReferences = null;
				isActive = false;
				if (Object.op_Implicit((Object)(object)instance))
				{
					((Behaviour)instance).enabled = false;
				}
			}
		}

		public void Awake()
		{
			instance = this;
			KeyActions.Initialize();
			PlayerNetwork val = SMTInstances.LocalPlayerNetwork();
			MainPlayerControls = val.MainPlayer;
		}

		public void Update()
		{
			float time = Time.time;
			foreach (KeyValuePair<Type, (GameWorldEvent, InputAction)> subscriptedReference in subscriptedReferences)
			{
				if (WorldState.IsGameWorldAtOrAfter(subscriptedReference.Value.Item1))
				{
					subscriptedReference.Value.Item2(time, MainPlayerControls);
				}
			}
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct KeyActions
	{
		[StructLayout(LayoutKind.Sequential, Size = 1)]
		private readonly struct ActionNames
		{
			public static readonly string MainAction = "Main Action";

			public static readonly string SecondaryAction = "Secondary Action";
		}

		public static int MainActionId { get; private set; }

		public static int SecondaryActionId { get; private set; }

		public static void Initialize()
		{
			MainActionId = ReInput.mapping.GetActionId(ActionNames.MainAction);
			SecondaryActionId = ReInput.mapping.GetActionId(ActionNames.SecondaryAction);
			if (MainActionId < 0 && SecondaryActionId < 0)
			{
				throw new InvalidOperationException("None of the supported keys could be retrieved. SuperQoLity click behaviours wont work.");
			}
			if (MainActionId < 0)
			{
				TimeLogger.Logger.LogError("An action could not be found with name \"" + ActionNames.MainAction + "\"", (LogCategories)33554432);
			}
			if (SecondaryActionId < 0)
			{
				TimeLogger.Logger.LogError("An action could not be found with name \"" + ActionNames.MainAction + "\"", (LogCategories)33554432);
			}
		}
	}
}
namespace SuperQoLity.SuperMarket.Patches
{
	public class GameWorldEventsPatch : FullyAutoPatchedInstance
	{
		private class PauseDetection
		{
			private static readonly Stopwatch swPause = Stopwatch.StartNew();

			public static bool WasGamePaused;

			[HarmonyPatch(typeof(GameData), "Update")]
			[HarmonyPostfix]
			private static void GameCanvasUpdatePostFix(GameData __instance)
			{
				if (swPause.ElapsedMilliseconds > 20)
				{
					DetectGamePause();
					swPause.Restart();
				}
			}

			private static void DetectGamePause()
			{
				if (WorldState.IsWorldLoaded)
				{
					bool flag = Time.timeScale == 0f;
					if (flag != WasGamePaused)
					{
						EventMethods.TryTriggerEvents<bool, bool>(WorldState.OnGamePauseChanged, flag, AuxUtils.IsMainMenuOpen());
					}
					WasGamePaused = flag;
				}
			}
		}

		private class DetectGameLoadFinished
		{
			private enum DetectionState
			{
				Initial,
				Success,
				Failed
			}

			private static readonly Stopwatch sw = Stopwatch.StartNew();

			private static GameObject transitionBCKobj;

			private static DetectionState state = DetectionState.Initial;

			[HarmonyPatch(typeof(NetworkManager), "OnStartServer")]
			[HarmonyPrefix]
			public static void OnStartHostPrefixPatch()
			{
				SetLoadingWorld();
			}

			[HarmonyPatch(typeof(NetworkManager), "OnStartClient")]
			[HarmonyPrefix]
			public static void OnStartClientPrefixPatch()
			{
				if (WorldState.CurrentOnlineMode != GameOnlineMode.Host)
				{
					SetLoadingWorld();
				}
			}

			private static void SetLoadingWorld()
			{
				WorldState.CurrentOnlineMode = (NetworkServer.activeHost ? GameOnlineMode.Host : GameOnlineMode.Client);
				WorldState.SetGameWorldState(GameWorldEvent.LoadingWorld);
			}

			[HarmonyPatch(typeof(GameCanvas), "Awake")]
			[HarmonyPostfix]
			private static void GameCanvasAwake(GameCanvas __instance)
			{
				WorldState.SetGameWorldState(GameWorldEvent.CanvasAwake);
			}

			[HarmonyPatch(typeof(GameCanvas), "Update")]
			[HarmonyPostfix]
			private static void GameCanvasUpdatePostFix(GameCanvas __instance)
			{
				if (sw.ElapsedMilliseconds < 100)
				{
					return;
				}
				try
				{
					if ((Object)(object)transitionBCKobj == (Object)null)
					{
						state = DetectionState.Initial;
						transitionBCKobj = GameObject.Find("MasterOBJ/MasterCanvas/TransitionBCK");
					}
					if ((Object)(object)transitionBCKobj != (Object)null && !transitionBCKobj.activeSelf && state == DetectionState.Initial)
					{
						state = DetectionState.Success;
						WorldState.SetGameWorldState(GameWorldEvent.WorldLoaded);
					}
				}
				catch (Exception ex)
				{
					state = DetectionState.Failed;
					TimeLogger.Logger.LogExceptionWithMessage("Error while trying to detect game finished loading.", ex, (LogCategories)8);
				}
				finally
				{
					GameWorldEventsPatch instance = Container<GameWorldEventsPatch>.Instance;
					if (state == DetectionState.Failed)
					{
						TimeLogger.Logger.LogError(((AutoPatchedInstanceBase)instance).ErrorMessageOnAutoPatchFail, (LogCategories)8);
						((AutoPatchedInstanceBase)instance).UnpatchInstance();
						sw.Stop();
					}
					else
					{
						sw.Restart();
					}
				}
			}
		}

		private class FirstPersonControllerStart
		{
			[HarmonyPatch(typeof(FirstPersonController), "Start")]
			[HarmonyPostfix]
			public static void OnFirstPersonControllerStart(FirstPersonController __instance)
			{
				WorldState.SetGameWorldState(GameWorldEvent.FPControllerStarted);
			}
		}

		private class DetectQuitToMainMenu
		{
			[HarmonyPatch(typeof(CustomNetworkManager), "OnClientDisconnect")]
			[HarmonyPostfix]
			public static void OnClientDisconnectPatch(CustomNetworkManager __instance)
			{
				WorldState.CurrentOnlineMode = GameOnlineMode.None;
				WorldState.SetGameWorldState(GameWorldEvent.QuitOrMenu);
			}
		}

		private class BuildEvents
		{
			[CompilerGenerated]
			private sealed class <ProdShelfBuiltOrLoadedClient>d__4 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				public IEnumerator result;

				private Data_Container <__instance>5__2;

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

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

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

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

				private bool MoveNext()
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<__instance>5__2 = lastDataContainerActivated;
						break;
					case 1:
						<>1__state = -1;
						break;
					}
					if (result.MoveNext())
					{
						<>2__current = result.Current;
						<>1__state = 1;
						return true;
					}
					EventMethods.TryTriggerEvents<Transform, ParentContainerType>(WorldState.BuildingEvents.OnShelfBuiltOrLoaded, ((Component)<__instance>5__2).transform, ParentContainerType.ProductDisplay);
					return false;
				}

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

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

			[CompilerGenerated]
			private sealed class <StorageShelfBuiltOrLoadedClient>d__6 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				public IEnumerator result;

				private Data_Container <__instance>5__2;

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

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

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

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

				private bool MoveNext()
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<__instance>5__2 = lastDataContainerActivated;
						break;
					case 1:
						<>1__state = -1;
						break;
					}
					if (result.MoveNext())
					{
						<>2__current = result.Current;
						<>1__state = 1;
						return true;
					}
					EventMethods.TryTriggerEvents<Transform, ParentContainerType>(WorldState.BuildingEvents.OnShelfBuiltOrLoaded, ((Component)<__instance>5__2).transform, ParentContainerType.Storage);
					return false;
				}

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

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

			private static Data_Container lastDataContainerActivated;

			[HarmonyPatch(typeof(Data_Container), "ActivateShelvesFromLoad")]
			[HarmonyPostfix]
			private static void NewBuildableLoadedHost(Data_Container __instance)
			{
				DataContainerType.TypeIndex containerType = __instance.GetContainerType();
				if (containerType == DataContainerType.TypeIndex.ProductShelf || containerType == DataContainerType.TypeIndex.StorageShelf)
				{
					EventMethods.TryTriggerEvents<Transform, ParentContainerType>(WorldState.BuildingEvents.OnShelfBuiltOrLoaded, ((Component)__instance).transform, containerType.ToParentContainerType());
				}
			}

			[HarmonyPatch(typeof(NetworkSpawner), "UserCode_CmdSpawn__Int32__Vector3__Vector3")]
			[HarmonyPostfix]
			private static void NewBuildableBuiltHost(NetworkSpawner __instance, int prefabID, Vector3 pos, Vector3 rot)
			{
				int parentIndex;
				DataContainerType.TypeIndex containerType = DataContainerType.GetContainerType(prefabID, out parentIndex);
				if (containerType == DataContainerType.TypeIndex.ProductShelf || containerType == DataContainerType.TypeIndex.StorageShelf)
				{
					Transform child = __instance.levelPropsOBJ.transform.GetChild(parentIndex);
					GameObject gameObject = ((Component)child.GetChild(child.childCount - 1)).gameObject;
					EventMethods.TryTriggerEvents<Transform, ParentContainerType>(WorldState.BuildingEvents.OnShelfBuiltOrLoaded, gameObject.transform, containerType.ToParentContainerType());
				}
			}

			[HarmonyPatch(typeof(Data_Container), "DelayActivationShelves")]
			[HarmonyPostfix]
			private static void ProdShelfBuiltOrLoadedClientGetInstance(Data_Container __instance)
			{
				lastDataContainerActivated = __instance;
			}

			[IteratorStateMachine(typeof(<ProdShelfBuiltOrLoadedClient>d__4))]
			[HarmonyPatch(typeof(Data_Container), "DelayActivationShelves")]
			[HarmonyPriority(100)]
			[HarmonyPostfix]
			public static IEnumerator ProdShelfBuiltOrLoadedClient(IEnumerator result)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <ProdShelfBuiltOrLoadedClient>d__4(0)
				{
					result = result
				};
			}

			[HarmonyPatch(typeof(Data_Container), "DelayActivationStorage")]
			[HarmonyPostfix]
			private static void StorageShelfBuiltOrLoadedClientGetInstance(Data_Container __instance)
			{
				lastDataContainerActivated = __instance;
			}

			[IteratorStateMachine(typeof(<StorageShelfBuiltOrLoadedClient>d__6))]
			[HarmonyPatch(typeof(Data_Container), "DelayActivationStorage")]
			[HarmonyPriority(100)]
			[HarmonyPostfix]
			public static IEnumerator StorageShelfBuiltOrLoadedClient(IEnumerator result)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <StorageShelfBuiltOrLoadedClient>d__6(0)
				{
					result = result
				};
			}
		}

		private class ContainerEvents
		{
			private static Transform droppedInstantiatedObject;

			[HarmonyPatch(typeof(Data_Container), "BoxSpawner")]
			[HarmonyPostfix]
			private static void BoxSpawnerPatch(Data_Container __instance)
			{
				EventMethods.TryTriggerEvents<Data_Container>(WorldState.BuildingEvents.OnStorageLoadedBuiltOrUpdated, __instance);
			}

			[HarmonyPatch(typeof(Data_Container), "ItemSpawner")]
			[HarmonyPostfix]
			private static void ItemSpawnerPatch(Data_Container __instance)
			{
				EventMethods.TryTriggerEvents<Data_Container>(WorldState.BuildingEvents.OnProductShelfLoadedBuiltOrUpdated, __instance);
			}

			[HarmonyPatch(typeof(ManagerBlackboard), "UserCode_RpcParentBoxOnClient__GameObject")]
			[HarmonyPostfix]
			private static void BoxSpawned(ManagerBlackboard __instance, GameObject boxOBJ)
			{
				EventMethods.TryTriggerEvents<Transform>(WorldState.ContainerEvents.OnBoxSpawned, boxOBJ.transform);
			}

			[HarmonyPatch(typeof(PlayerNetwork), "UpdateBoxContents")]
			[HarmonyPostfix]
			private static void BoxPickUpOrUpdatedLocalPlayerPatch(PlayerNetwork __instance, int productIndex)
			{
				EventMethods.TryTriggerEvents<Transform, int>(WorldState.ContainerEvents.OnBoxEquippedOrUpdatedLocalPlayer, __instance.instantiatedOBJ.transform, productIndex);
			}

			[HarmonyPatch(typeof(PlayerNetwork), "OnChangeEquipment")]
			[HarmonyPrefix]
			private static void OnChangeEquipmentPrefix(PlayerNetwork __instance)
			{
				GameObject obj = UnityObjectExtensions.NullableObject<GameObject>(__instance.instantiatedOBJ);
				droppedInstantiatedObject = ((obj != null) ? obj.transform : null);
			}

			[HarmonyPatch(typeof(PlayerNetwork), "OnChangeEquipment")]
			[HarmonyPostfix]
			private static void OnChangeEquipmentPostfix(PlayerNetwork __instance, int oldEquippedItem, int newEquippedItem)
			{
				if (oldEquippedItem == 1)
				{
					CharacterSourceType characterSourceType = ToCharacterSource(((NetworkBehaviour)__instance).isLocalPlayer);
					EventMethods.TryTriggerEvents<Transform, CharacterSourceType>(WorldState.ContainerEvents.OnBoxDroppedByPlayer, droppedInstantiatedObject, characterSourceType);
				}
				else if (newEquippedItem == 1 && !((NetworkBehaviour)__instance).isLocalPlayer && WorldState.CurrentOnlineMode == GameOnlineMode.Client)
				{
					int syncedProductID = ((Component)__instance).GetComponent<PlayerSyncCharacter>().syncedProductID;
					EventMethods.TryTriggerEvents<Transform, Transform, int, CharacterSourceType>(WorldState.ContainerEvents.OnBoxEquippedRemotePlayerOrEmployee, ((Component)__instance).transform, __instance.instantiatedOBJ.transform, syncedProductID, CharacterSourceType.RemotePlayer);
				}
				Action<PlayerNetwork, Transform, Transform, int, int, bool> onChangeEquipment = WorldState.PlayerEvents.OnChangeEquipment;
				Transform obj = droppedInstantiatedObject;
				GameObject obj2 = UnityObjectExtensions.NullableObject<GameObject>(__instance.instantiatedOBJ);
				EventMethods.TryTriggerEvents<PlayerNetwork, Transform, Transform, int, int, bool>(onChangeEquipment, __instance, obj, (obj2 != null) ? obj2.transform : null, oldEquippedItem, newEquippedItem, ((NetworkBehaviour)__instance).isLocalPlayer);
			}

			[HarmonyPatch(typeof(PlayerSyncCharacter), "DeserializeSyncVars")]
			[HarmonyTranspiler]
			public static IEnumerable<CodeInstruction> CallOnChangeSyncedProductIDTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Expected O, but got Unknown
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Expected O, but got Unknown
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Expected O, but got Unknown
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Expected O, but got Unknown
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Expected O, but got Unknown
				//IL_013d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0143: Expected O, but got Unknown
				CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
				FieldInfo fInfo = AccessTools.Field(typeof(PlayerSyncCharacter), "syncedProductID");
				if (fInfo == null)
				{
					TimeLogger.Logger.LogError("The field PlayerSyncCharacter.syncedProductID could not be found. Highlighting of remote player held boxes wont work.", (LogCategories)67108864);
					return val.InstructionEnumeration();
				}
				val.End();
				val.MatchEndBackwards((CodeMatch[])(object)new CodeMatch[2]
				{
					new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction c) => CodeInstructionExtensions.LoadsField(c, fInfo, true)), (string)null),
					new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction c) => c.opcode == OpCodes.Ldnull), (string)null)
				});
				if (val.IsInvalid)
				{
					TimeLogger.Logger.LogError("The IL line loading the field PlayerSyncCharacter.syncedProductID could not be found. Highlighting of remote player held boxes wont work.", (LogCategories)67108864);
					return val.InstructionEnumeration();
				}
				MethodInfo methodInfo = AccessTools.Method(typeof(ContainerEvents), "OnChangeSyncedProductID", (Type[])null, (Type[])null);
				ConstructorInfo constructorInfo = AccessTools.Constructor(typeof(Action<PlayerSyncCharacter>), new Type[2]
				{
					typeof(object),
					typeof(IntPtr)
				}, false);
				val.RemoveInstruction().Insert((CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null),
					new CodeInstruction(OpCodes.Ldftn, (object)methodInfo),
					new CodeInstruction(OpCodes.Newobj, (object)constructorInfo)
				});
				return val.InstructionEnumeration();
			}

			private static void OnChangeSyncedProductID(PlayerSyncCharacter playerSync)
			{
				if (WorldState.CurrentOnlineMode == GameOnlineMode.Host)
				{
					PlayerNetwork component = ((Component)playerSync).GetComponent<PlayerNetwork>();
					if (Object.op_Implicit((Object)(object)component) && component.equippedItem == 1)
					{
						EventMethods.TryTriggerEvents<Transform, Transform, int, CharacterSourceType>(WorldState.ContainerEvents.OnBoxEquippedRemotePlayerOrEmployee, ((Component)playerSync).transform, component.instantiatedOBJ.transform, playerSync.syncedProductID, CharacterSourceType.RemotePlayer);
					}
				}
			}

			[HarmonyPatch(typeof(NPC_Info), "UserCode_RpcEquipNPCItem__Int32__Int32")]
			[HarmonyPostfix]
			private static void UserCode_RpcEquipNPCItem__Int32__Int32(NPC_Info __instance, int equippedIndex, int productID)
			{
				if (equippedIndex == 1)
				{
					EventMethods.TryTriggerEvents<Transform, Transform, int, CharacterSourceType>(WorldState.ContainerEvents.OnBoxEquippedRemotePlayerOrEmployee, ((Component)__instance).transform, __instance.instantiatedOBJ.transform, productID, CharacterSourceType.Employee);
				}
			}

			[HarmonyPatch(typeof(Data_Container), "UserCode_RpcUpdateArrayValuesStorage__Int32__Int32__Int32")]
			[HarmonyPostfix]
			private static void UserCode_RpcUpdateArrayValuesStorage__Int32__Int32__Int32(Data_Container __instance, int index, int PID, int PNUMBER)
			{
				if (PNUMBER >= 0)
				{
					EventMethods.TryTriggerEvents<Data_Container>(WorldState.ContainerEvents.OnBoxIntoStorage, __instance);
				}
			}

			[HarmonyPatch(typeof(Data_Container), "UserCode_RpcUpdateObjectOnClients__Int32__Int32__Int32__Int32")]
			[HarmonyPostfix]
			private static void UserCode_RpcUpdateObjectOnClients__Int32__Int32__Int32__Int32(Data_Container __instance, int index, int PID, int PNUMBER, int oldPID)
			{
				if (oldPID < 0 && PID >= 0)
				{
					EventMethods.TryTriggerEvents<Data_Container>(WorldState.ContainerEvents.OnProdShelfAssigned, __instance);
				}
				else if (oldPID >= 0 && PID < 0)
				{
					EventMethods.TryTriggerEvents<Data_Container>(WorldState.ContainerEvents.OnProdShelfUnassigned, __instance);
				}
			}
		}

		public class NPC_Events
		{
			[HarmonyPatch(typeof(NPC_Manager), "SpawnEmployeeByIndex")]
			[HarmonyPriority(100)]
			[HarmonyPostfix]
			private static void SpawnEmployeeByIndexPostfix(NPC_Manager __instance, int index)
			{
				NPC_Info component = __instance.employeesArray[index].GetComponent<NPC_Info>();
				EventMethods.TryTriggerEvents<NPC_Info, int>(WorldState.NPC_Events.OnEmployeeSpawned, component, index);
			}
		}

		public override bool IsAutoPatchEnabled => true;

		public override bool IsRollbackOnAutoPatchFail => false;

		public override string ErrorMessageOnAutoPatchFail { get; protected set; } = "SuperQoLity - Detection of world events patch failed. Disabled";


		public override void OnPatchFinishedVirtual(bool IsActive)
		{
			if (IsActive)
			{
				WorldState.OnWorldLoaded += delegate
				{
					PauseDetection.WasGamePaused = false;
				};
			}
		}

		public static CharacterSourceType ToCharacterSource(bool isLocalPlayer)
		{
			if (!isLocalPlayer)
			{
				return CharacterSourceType.RemotePlayer;
			}
			return CharacterSourceType.LocalPlayer;
		}
	}
	public class ShelfItemCulling
	{
		public static void Initialize()
		{
		}

		public static void ShelfBuilt(NetworkSpawner instance, int prefabID)
		{
			instance.buildables[prefabID].GetComponent<Data_Container>();
		}

		public static void CreateProductShelfBounds(Data_Container instance)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			foreach (Transform item in ((Component)instance).transform.Find("ProductContainer"))
			{
				_ = item;
			}
		}
	}
	public class StoreOpenStatusPatch : FullyAutoPatchedInstance
	{
		private static CancellableSingleTask<UniTaskDelay> storeClosedTask = new CancellableSingleTask<UniTaskDelay>(true);

		private static SemaphoreSlim semaphoreLock = new SemaphoreSlim(1, 1);

		public override bool IsAutoPatchEnabled
		{
			get
			{
				if (!ModConfig.Instance.EnableEmployeeChanges.Value)
				{
					return ModConfig.Instance.EnableTransferProducts.Value;
				}
				return true;
			}
		}

		public override string ErrorMessageOnAutoPatchFail { get; protected set; } = "SuperQoLity - Store opening state detection patch failed. Disabled";


		public static event Action<bool> OnSupermarketOpenStateChanged;

		public override void OnPatchFinishedVirtual(bool IsActive)
		{
			if (IsActive)
			{
				NetworkSpawnManager.RegisterNetwork<StoreStatusNetwork>(StoreStatusNetwork.NetworkAssetId, true);
				WorldState.OnQuitOrMainMenu += async delegate
				{
					await storeClosedTask.StopTaskAndWaitAsync(500);
				};
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPriority(600)]
		[HarmonyPrefix]
		private static bool NetworkisSupermarketOpenPrefixPatch(ref bool __state)
		{
			__state = GameData.Instance.isSupermarketOpen;
			return true;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static async void NetworkisSupermarketOpenPostfixPatch(bool __state)
		{
			if (GameData.Instance.isSupermarketOpen == __state)
			{
				return;
			}
			await storeClosedTask.StopTaskAndWaitAsync();
			await semaphoreLock.WaitAsync();
			try
			{
				bool value = true;
				if (!GameData.Instance.isSupermarketOpen)
				{
					await storeClosedTask.StartAwaitableTaskAsync((Func<Task>)CheckCustomersPendingActions, "Wait for end of customers actions", true);
					if (storeClosedTask.IsCancellationRequested)
					{
						TimeLogger.Logger.LogDebugFunc((Func<string>)(() => "Skipped to next day or quitting to main menu before customers left the store."), (LogCategories)16);
					}
					else
					{
						TimeLogger.Logger.LogDebugFunc((Func<string>)(() => "All customers are leaving or already left the supermarket."), (LogCategories)16);
					}
					value = false;
				}
				StoreStatusNetwork.IsStoreOpenOrCustomersInsideSync.Value = value;
				EventMethods.TryTriggerEvents<bool>(StoreOpenStatusPatch.OnSupermarketOpenStateChanged, SyncVar<bool>.op_Implicit(StoreStatusNetwork.IsStoreOpenOrCustomersInsideSync));
			}
			finally
			{
				semaphoreLock.Release();
			}
		}

		private static async Task CheckCustomersPendingActions()
		{
			UnityTimeStopwatch safetyTimeout = UnityTimeStopwatch.StartNew();
			try
			{
				while (HasCustomersWithPendingActions(storeClosedTask.CancellationToken) && safetyTimeout.ElapsedSeconds < 180)
				{
					await UniTask.Delay(500, false, (PlayerLoopTiming)8, storeClosedTask.CancellationToken, false);
				}
			}
			catch (OperationCanceledException)
			{
			}
		}

		private static bool HasCustomersWithPendingActions(CancellationToken cancelToken = default(CancellationToken))
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (cancelToken.IsCancellationRequested)
			{
				return false;
			}
			foreach (Transform item in NPC_Manager.Instance.customersnpcParentOBJ.transform)
			{
				if (((Component)item).gameObject.GetComponent<NPC_Info>().state < 99)
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace SuperQoLity.SuperMarket.Patches.TransferItemsModule
{
	public enum EnumItemTransferMode
	{
		[Description("Disabled")]
		Disabled,
		[Description("Only while store is closed")]
		OnlyWhileStoreClosed,
		[Description("Always on")]
		AlwaysOn
	}
	[HarmonyPatch(typeof(Data_Container))]
	public class IncreasedItemTransferPatch : FullyAutoPatchedInstance
	{
		private enum RowActionType
		{
			Add,
			Remove
		}

		public enum CharacterType
		{
			Player,
			Employee
		}

		public override bool IsAutoPatchEnabled => ModConfig.Instance.EnableTransferProducts.Value;

		public override string ErrorMessageOnAutoPatchFail { get; protected set; } = "SuperQoLity - Transfer patch failed. Item Transfer Module inactive";


		public override void OnPatchFinishedVirtual(bool IsPatchActive)
		{
			if (IsPatchActive)
			{
				NetworkSpawnManager.RegisterNetwork<ItemTransferNetwork>(ItemTransferNetwork.NetworkAssetId, true);
			}
		}

		public static int GetNumTransferItems(int giverItemCount, int receiverItemCount, int receiverMaxCapacity, CharacterType charType)
		{
			return GetNumTransferItems(giverItemCount, receiverItemCount, receiverMaxCapacity, charType, 1);
		}

		public static int GetNumTransferItems(int giverItemCount, int receiverItemCount, int receiverMaxCapacity, CharacterType charType, int numMovedProducts)
		{
			if (IsItemTransferEnabledFor(charType, numMovedProducts))
			{
				int val = receiverMaxCapacity - receiverItemCount;
				numMovedProducts = Math.Min(Math.Min((charType == CharacterType.Player) ? ((SyncVar<int>)(object)ItemTransferNetwork.ItemTransferQuantitySync).Value : int.MaxValue, giverItemCount), val);
			}
			return numMovedProducts;
		}

		public static bool IsItemTransferEnabledFor(CharacterType charType, int numMovedProducts)
		{
			if ((charType == CharacterType.Player && ((SyncVar<EnumItemTransferMode>)(object)ItemTransferNetwork.ItemTransferModeSync).Value == EnumItemTransferMode.Disabled) || (charType == CharacterType.Employee && !ModConfig.Instance.ClosedStoreEmployeeItemTransferMaxed.Value))
			{
				return false;
			}
			if (!SyncVar<bool>.op_Implicit(StoreStatusNetwork.IsStoreOpenOrCustomersInsideSync))
			{
				return true;
			}
			switch (charType)
			{
			case CharacterType.Player:
				if (ModConfig.Instance.EnableTransferProducts.Value && ((SyncVar<int>)(object)ItemTransferNetwork.ItemTransferQuantitySync).Value != numMovedProducts)
				{
					return ((SyncVar<EnumItemTransferMode>)(object)ItemTransferNetwork.ItemTransferModeSync).Value != EnumItemTransferMode.OnlyWhileStoreClosed;
				}
				return false;
			case CharacterType.Employee:
				return false;
			default:
				throw new InvalidOperationException($"{charType} is not a supported value in this method.");
			}
		}

		[HarmonyPatch("AddItemToRow")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> AddItemToRowTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
			FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerNetwork), "extraParameter2");
			Label? exitBranchLabel = null;
			int indexStart = val.End().MatchEndBackwards((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo, (string)null)
			}).MatchEndBackwards((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction c) => CodeInstructionExtensions.Branches(c, ref exitBranchLabel)), (string)null)
			})
				.Pos + 1;
			if (!exitBranchLabel.HasValue)
			{
				throw new TranspilerDefaultMsgException("Couldnt find the exit branch label for the AddItemToRow method.");
			}
			int pos = val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.labels.Contains(exitBranchLabel.Value)), (string)null)
			}).Pos;
			return ReplaceConstantsWithCallResult(val.InstructionEnumeration().ToList(), generator, indexStart, pos, RowActionType.Add);
		}

		[HarmonyPatch("RemoveItemFromRow")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> RemoveItemFromRowTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			return TranspilerChangeProductTransferCount(instructions, generator, RowActionType.Remove);
		}

		private static IEnumerable<CodeInstruction> TranspilerChangeProductTransferCount(IEnumerable<CodeInstruction> instructions, ILGenerator generator, RowActionType rowActionType)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			List<CodeInstruction> list = instructions.ToList();
			int num = -1;
			int num2 = -1;
			FieldInfo extraParameter2 = AccessTools.Field(typeof(PlayerNetwork), "extraParameter2");
			int num3 = list.FindLastIndex((CodeInstruction instruction) => CodeInstructionExtensions.LoadsField(instruction, extraParameter2, false));
			if (num3 < 0)
			{
				throw new TranspilerDefaultMsgException("Couldnt find the instruction loading the value of the field extraParameter2");
			}
			int num4 = list.FindLastIndex(num3, num3, (CodeInstruction instruction) => instruction.opcode == OpCodes.Br || instruction.opcode == OpCodes.Br_S);
			if (num4 < 0)
			{
				throw new TranspilerDefaultMsgException($"Couldnt find the Br/Br_S instruction when looking up to IL line {num3}");
			}
			Label endElseLabel = (Label)list[num4].operand;
			int num5 = list.Count - 1;
			int num6 = list.FindLastIndex(num5, num5 - num3, (CodeInstruction instruction) => instruction.labels.FirstOrDefault() == endElseLabel);
			if (num6 < 0)
			{
				throw new TranspilerDefaultMsgException($"Couldnt find IL Label {endElseLabel} when searching from IL line {num3}");
			}
			num = num4 + 1;
			num2 = num6 - 1;
			return ReplaceConstantsWithCallResult(list, generator, num, num2, rowActionType);
		}

		private static IEnumerable<CodeInstruction> ReplaceConstantsWithCallResult(List<CodeInstruction> instrList, ILGenerator generator, int indexStart, int indexEnd, RowActionType rowActionType)
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			List<CodeInstruction> list = CreateILCall_GetNumTransferItems(instrList, indexStart, indexEnd, rowActionType);
			LocalBuilder localBuilder = generator.DeclareLocal(typeof(int));
			CodeInstruction val = CodeInstructionNew.LoadLocal(localBuilder.LocalIndex, false);
			CodeInstructionExtensions.MoveLabelsTo(instrList[indexStart], list[0]);
			if (rowActionType == RowActionType.Add)
			{
				if (instrList[indexStart + 3].operand == null || !instrList[indexStart + 3].operand.ToString().Contains("AchievementPoint"))
				{
					throw new TranspilerDefaultMsgException($"The call to a method containing the text \"AchievementPoint\" wasnt found at the expected line {indexStart + 3}");
				}
				if (instrList[indexStart + 2].opcode != OpCodes.Ldc_I4_1)
				{
					throw new TranspilerDefaultMsgException($"The opcode Ldc_I4_1 for achievements wasnt found at the expected line {indexStart + 2}.");
				}
				instrList[indexStart + 2] = val;
				int num = 4;
				instrList.InsertRange(indexEnd, instrList.GetRange(indexStart, num));
				instrList.RemoveRange(indexStart, num);
				indexEnd -= num;
			}
			instrList.InsertRange(indexStart, list);
			instrList.Insert(indexStart + list.Count, CodeInstructionNew.StoreLocal(localBuilder.LocalIndex));
			indexEnd += list.Count + 1;
			CodeMatcher val2 = new CodeMatcher((IEnumerable<CodeInstruction>)instrList, (ILGenerator)null);
			int num2 = 0;
			val2.Advance(indexStart);
			while (val2.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => CodeInstructionExtensions.LoadsConstant(inst, 1L)), (string)null)
			}).IsValid && val2.Pos <= indexEnd)
			{
				val2.SetInstructionAndAdvance(val);
				num2++;
			}
			if (num2 < 2)
			{
				throw new TranspilerDefaultMsgException($"Only {num2} matches where found of the expected " + "2.");
			}
			return val2.InstructionEnumeration();
		}

		private static List<CodeInstruction> CreateILCall_GetNumTransferItems(List<CodeInstruction> instrList, int indexStart, int indexEnd, RowActionType rowActionType)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			CodeInstruction boxCountILInstruction = GetBoxCountILInstruction();
			switch (rowActionType)
			{
			case RowActionType.Add:
				list.AddRange(GetILParametersAddingItems(instrList, boxCountILInstruction));
				break;
			case RowActionType.Remove:
				list.AddRange(GetILParametersRemovingItems(instrList, boxCountILInstruction));
				break;
			default:
				throw new TranspilerDefaultMsgException($"Initial RowActionType: {rowActionType}");
			}
			list.Add(new CodeInstruction(OpCodes.Ldc_I4_S, (object)0));
			list.Add(Transpilers.EmitDelegate<Func<int, int, int, CharacterType, int>>((Func<int, int, int, CharacterType, int>)GetNumTransferItems));
			return list;
		}

		private static List<CodeInstruction> GetILParametersAddingItems(List<CodeInstruction> instrList, CodeInstruction getBoxCountILInstr)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = instrList.FindIndex((CodeInstruction instruction) => instruction.opcode == OpCodes.Ldstr && instruction.operand.ToString() == "message1");
			if (num == -1)
			{
				throw new TranspilerDefaultMsgException("Couldnt find the line loading the string \"message1\".");
			}
			int num2 = instrList.FindLastIndex(num, (CodeInstruction instruction) => CodeInstructionExtensions.IsLdloc(instruction, (LocalBuilder)null));
			if (num2 == -1)
			{
				throw new TranspilerDefaultMsgException("Couldnt find the line loading the local var \"num3\".");
			}
			int index = num2 - 1;
			int num3 = ILExtensionMethods.LocalIndex(instrList[num2]);
			int num4 = ILExtensionMethods.LocalIndex(instrList[index]);
			list.Add(getBoxCountILInstr);
			list.Add(CodeInstructionNew.LoadLocal(num4, false));
			list.Add(CodeInstructionNew.LoadLocal(num3, false));
			return list;
		}

		private static List<CodeInstruction> GetILParametersRemovingItems(List<CodeInstruction> instrList, CodeInstruction getBoxCountILInstr)
		{
			//IL_004b: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = -1;
			int num2 = 0;
			int num3 = int.MinValue;
			FieldInfo fieldInfo = AccessTools.Field(typeof(Data_Container), "productInfoArray");
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(ProductData), "maxItemsPerBox");
			if (fieldInfo == null)
			{
				throw new TranspilerDefaultMsgException("The field Data_Container.productInfoArray could not be found.");
			}
			if (fieldInfo2 == null)
			{
				throw new TranspilerDefaultMsgException("The field Data_Product.maxItemsPerBox could not be found.");
			}
			int num4 = -1;
			int num5 = -1;
			for (int i = 0; i < instrList.Count; i++)
			{
				CodeInstruction val = instrList[i];
				if (num2 < 2 && CodeInstructionExtensions.LoadsField(val, fieldInfo, false))
				{
					num2++;
					if (num2 == 2)
					{
						num3 = i + 1;
					}
				}
				else if (num5 == -1 && i >= num3 && i < num3 + 10 && CodeInstructionExtensions.IsStloc(val, (LocalBuilder)null))
				{
					num5 = ILExtensionMethods.LocalIndex(val);
				}
				else if (num < 0 && CodeInstructionExtensions.LoadsField(val, fieldInfo2, false))
				{
					num = i + 1;
				}
				else if (i == num && CodeInstructionExtensions.IsStloc(val, (LocalBuilder)null))
				{
					num4 = ILExtensionMethods.LocalIndex(val);
				}
			}
			if (num2 < 2)
			{
				throw new TranspilerDefaultMsgException($"Couldnt reach the appropiate amount of productInfoArray usages (productInfoArrayInstance = {num2})");
			}
			if (num5 == -1)
			{
				throw new TranspilerDefaultMsgException($"Couldnt find the num3 local var reference (num3IndexBeginSearch = {num3})");
			}
			if (num4 == -1)
			{
				throw new TranspilerDefaultMsgException($"Couldnt find the maxItemsPerBox local var reference (maxItemsPerBoxLocalVarIndex = {num})");
			}
			list.Add(CodeInstructionNew.LoadLocal(num5, false));
			list.Add(getBoxCountILInstr);
			list.Add(CodeInstructionNew.LoadLocal(num4, false));
			return list;
		}

		private static CodeInstruction GetBoxCountILInstruction()
		{
			return Transpilers.EmitDelegate<Func<int>>((Func<int>)(() => ((Component)FirstPersonController.Instance).GetComponent<PlayerNetwork>().extraParameter2));
		}
	}
}
namespace SuperQoLity.SuperMarket.Patches.NPC
{
	public class NpcJobSchedulerPatch : FullyAutoPatchedInstance
	{
		private static bool canEmployeesDoSomething;

		private static bool canCustomersDoSomething;

		public override bool IsAutoPatchEnabled
		{
			get
			{
				if (!ModConfig.Instance.EnableCustomerChanges.Value)
				{
					return ModConfig.Instance.EnableEmployeeChanges.Value;
				}
				return true;
			}
		}

		public override string ErrorMessageOnAutoPatchFail { get; protected set; } = "SuperQoLity - Npc slowdown fix multiplier failed. Disabled";


		public override void OnPatchFinishedVirtual(bool IsActive)
		{
			if (!IsActive)
			{
				return;
			}
			try
			{
				SetCustomPerfModeVisibility();
				ModConfig.Instance.NpcJobFrequencyMode.SettingChanged += delegate
				{
					SetCustomPerfModeVisibility();
					ConfigManagerController.RefreshGUI();
				};
				JobSchedulerManager.InitializeJobSchedulerEvents();
				if (ModConfig.Instance.EnableEmployeeChanges.Value)
				{
					RestockMatcher.Enable();
				}
			}
			catch
			{
				JobSchedulerManager.DisableJobScheduler();
				RestockMatcher.Disable();
				((AutoPatchedInstanceBase)Container<NpcJobSchedulerPatch>.Instance).UnpatchInstance();
				throw;
			}
		}

		[HarmonyPatch(typeof(NPC_Manager), "FixedUpdate")]
		[HarmonyPrefix]
		public static void FixedUpdateResetFlags(NPC_Manager __instance)
		{
			canEmployeesDoSomething = false;
			canCustomersDoSomething = false;
		}

		[HarmonyAfterInstance(new Type[] { typeof(EmployeeJobAIPatch) })]
		[HarmonyPatch(typeof(NPC_Manager), "FixedUpdate")]
		[HarmonyPostfix]
		public static void FixedUpdateProcessNPCs(NPC_Manager __instance)
		{
			if (canEmployeesDoSomething && !__instance.mainManufacturingShelfUpdateIsRunning && ((Component)GameData.Instance).GetComponent<UpgradesManager>().addonsBought[1])
			{
				((MonoBehaviour)__instance).StartCoroutine(__instance.MainManufacturingRestockUpdate());
			}
			if (canEmployeesDoSomething || canCustomersDoSomething)
			{
				JobSchedulerManager.ProcessNPCJobs(__instance, canEmployeesDoSomething, canCustomersDoSomething);
			}
		}

		[HarmonyPatch(typeof(NPC_Manager), "FixedUpdate")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> FixedUpdateNpcTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, generator);
			if (ModConfig.Instance.EnableEmployeeChanges.Value)
			{
				val = TranspileEmployeeCall(val);
			}
			if (ModConfig.Instance.EnableCustomerChanges.Value)
			{
				val = TranspileCustomerCall(val);
			}
			return val.InstructionEnumeration();
		}

		public static CodeMatcher TranspileEmployeeCall(CodeMatcher codeMatcher)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			codeMatcher.MatchForward(true, (CodeMatch[])(object)new CodeMatch[3]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => CodeInstructionExtensions.IsLdloc(inst, (LocalBuilder)null) && inst.labels.Count > 0), (string)null),
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => CodeInstructionExtensions.LoadsConstant(inst)), (string)null),
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.operand is Label), (string)null)
			});
			if (codeMatcher.IsInvalid)
			{
				throw new TranspilerDefaultMsgException("IL line \"if (childCount > 0)\" could not be found.");
			}
			int num = codeMatcher.Pos + 1;
			Label endLabel = (Label)codeMatcher.Operand;
			codeMatcher.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.labels.Contains(endLabel)), (string)null)
			});
			codeMatcher.RemoveInstructionsInRange(num, codeMatcher.Pos - 1);
			codeMatcher.Start().Advance(num).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldc_I4_1, (object)null)
			})
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstruction.StoreField(typeof(NpcJobSchedulerPatch), "canEmployeesDoSomething") });
			return codeMatcher;
		}

		private static CodeMatcher TranspileCustomerCall(CodeMatcher codeMatcher)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_0071: 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_00ea: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			codeMatcher.MatchForward(true, (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => CodeInstructionExtensions.IsLdloc(inst, (LocalBuilder)null)), (string)null),
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.opcode == OpCodes.Brtrue_S || inst.opcode == OpCodes.Brtrue), (string)null)
			});
			if (codeMatcher.IsInvalid)
			{
				throw new TranspilerDefaultMsgException("IL line \"if (childCount2 != 0)\" could not be found.");
			}
			int pos = codeMatcher.Pos;
			Label startCondLabel = (Label)codeMatcher.Operand;
			codeMatcher.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.labels.Contains(startCondLabel)), (string)null)
			});
			int pos2 = codeMatcher.Pos;
			codeMatcher.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction inst) => inst.opcode == OpCodes.Ret), (string)null)
			});
			codeMatcher.RemoveInstructionsInRange(pos2 - 1, codeMatcher.Pos - 1);
			Label label = default(Label);
			codeMatcher.Start().Advance(pos + 1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldc_I4_1, (object)null)
			})
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstruction.StoreField(typeof(NpcJobSchedulerPatch), "canCustomersDoSomething") })
				.CreateLabel(ref label)
				.Start()
				.Advance(pos)
				.Set(OpCodes.Brfalse, (object)label);
			return codeMatcher;
		}

		private void SetCustomPerfModeVisibility()
		{
			bool flag = ModConfig.Instance.NpcJobFrequencyMode.Value == EnumJobFrequencyMultMode.Auto_Custom;
			ConfigManagerExtension.SetConfigAttribute<float, bool>(ModConfig.Instance.CustomEmployeeWaitTarget, (ConfigAttributes)3, flag);
			ConfigManagerExtension.SetConfigAttribute<float, bool>(ModConfig.Instance.CustomCustomerWaitTarget, (ConfigAttributes)3, flag);
			ConfigManagerExtension.SetConfigAttribute<float, bool>(ModConfig.Instance.CustomMinimumFrequencyMult, (ConfigAttributes)3, flag);
			ConfigManagerExtension.SetConfigAttribute<float, bool>(ModConfig.Instance.CustomMaximumFrequencyMult, (ConfigAttributes)3, flag);
			ConfigManagerExtension.SetConfigAttribute<float, bool>(ModConfig.Instance.CustomMaximumFrequencyReduction, (ConfigAttributes)3, flag);
			ConfigManagerExtension.SetConfigAttribute<float, bool>(ModConfig.Instance.CustomMaximumFrequencyIncrease, (ConfigAttributes)3, flag);
		}
	}
}
namespace SuperQoLity.SuperMarket.Patches.NPC.EmployeeModule
{
	public enum EmployeeJob
	{
		Unassigned = 0,
		Cashier = 1,
		Restocker = 2,
		Storage = 3,
		Security = 4,
		Technician = 5,
		OnlineOrder = 6,
		Manufacturer = 7,
		Any = 99
	}
	public enum EnumSecurityPickUp
	{
		[Description("Disabled")]
		Disabled,
		[Description("Reduced")]
		Reduced,
		[Description("Normal")]
		Normal,
		[Description("Always Maxed")]
		AlwaysMaxed
	}
	public enum EnumSecurityEmployeeThiefChase
	{
		[Description("Disabled")]
		Disabled,
		[Description("All chase but last one")]
		AllChaseButLastOne,
		[Description("Only one per Thief")]
		OnlyOnePerThief
	}
	public class EmployeeJobAIPatch : FullyAutoPatchedInstance
	{
		[CompilerGenerated]
		private sealed class <PickupMarkedStolenProductsLoop>d__32 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					if (WorldState.CurrentGameWorldState == GameWorldEvent.QuitOrMenu)
					{
						stolenProdPickups.Clear();
						return false;
					}
				}
				else
				{
					<>1__state = -1;
				}
				if (stolenProdPickups.Count > 0)
				{
					StolenProductSpawn val = default(StolenProductSpawn);
					for (float num2 = Math.Min(5f, stolenProdPickups.Count); num2 >= 1f; num2 -= 1f)
					{
						if (Extensions.TryDequeue<StolenProductSpawn>(stolenProdPickups, ref val))
						{
							NetworkServer.UnSpawn(((Component)val).gameObject);
						}
					}
				}
				<>2__current = null;
				<>1__state = 1;
				return true;
			}

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

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

		public const bool LogEmployeeActions = false;

		private static bool newProdPickUpWorking;

		private static Queue<StolenProductSpawn> stolenProdPickups;

		private static List<EmployeeJob> taskPriorities;

		private static int currentTaskIndex;

		public override bool IsAutoPatchEnabled => ModConfig.Instance.EnableEmployeeChanges.Value;

		public override string ErrorMessageOnAutoPatchFail { get; protected set; } = "SuperQoLity - Employee patch failed. Employee Module inactive";


		public static int NumTransferItemsBase { get; } = 1;


		public static int MaxSecurityPickUpLevel { get; } = 200;


		public static float SecurityPickUpRangeLevelMult { get; } = 1.25f;


		public static int SecurityPickUpLayer { get; } = 25;


		public static float LevelsForExtraPickUp { get; } = 10f;


		public override void OnPatchFinishedVirtual(bool isActive)
		{
			if (isActive)
			{
				WorldState.NPC_Events.OnEmployeeSpawned = (Action<NPC_Info, int>)Delegate.Combine(WorldState.NPC_Events.OnEmployeeSpawned, new Action<NPC_Info, int>(EmployeeSpawned));
			}
		}

		[HarmonyPatch(typeof(NPC_Manager), "Awake")]
		[HarmonyPostfix]
		public static void AwakePatch(NPC_Manager __instance)
		{
			newProdPickUpWorking = false;
			stolenProdPickups = new Queue<StolenProductSpawn>();
			GameObject npcAgentPrefab = __instance.npcAgentPrefab;
			GameObject val = ((npcAgentPrefab == null) ? null : npcAgentPrefab.GetComponent<NPC_Info>()?.stolenProductPrefab);
			if (!Object.op_Implicit((Object)(object)val))
			{
				TimeLogger.Logger.LogFatal("An object in the chain \"NPC_Manager.npcAgentPrefab.NPC_Info.stolenProductPrefab\" is null. It was probably renamed of changed places. The employee patches cant be used and will be disabled.", (LogCategories)134217728);
				((AutoPatchedInstanceBase)Container<EmployeeJobAIPatch>.Instance).UnpatchInstance();
				TimeLogger.Logger.SendMessageNotificationError("Something changed due to a game update and the employee module can no longer work. It was disabled so the rest of the mod can still work", false);
			}
			else
			{
				val.layer = SecurityPickUpLayer;
				((MonoBehaviour)__instance).StartCoroutine(Container<EmployeeJobAIPatch>.Instance.PickupMarkedStolenProductsLoop());
				newProdPickUpWorking = true;
			}
		}

		private static void EmployeeSpawned(NPC_Info npcInfo, int index)
		{
			GenericNPC.AddSuperQolNpcObjects(((Component)npcInfo).gameObject, NPCType.Employee);
		}

		public static bool EmployeeNPCControl(NPC_Manager __instance, GameObject employeeObj, NPC_Info employee)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_3fed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0679: Unknown result type (might be due to invalid IL or missing references)
			//IL_0689: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e3d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e65: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e6a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e6f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e7b: Unknown result type (might be due to invalid IL or missing references)
			//IL_12bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_12c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_1508: Unknown result type (might be due to invalid IL or missing references)
			//IL_1530: Unknown result type (might be due to invalid IL or missing references)
			//IL_1535: Unknown result type (might be due to invalid IL or missing references)
			//IL_153a: Unknown result type (might be due to invalid IL or missing references)
			//IL_1546: Unknown result type (might be due to invalid IL or missing references)
			//IL_1611: Unknown result type (might be due to invalid IL or missing references)
			//IL_1621: Unknown result type (might be due to invalid IL or missing references)
			//IL_2538: Unknown result type (might be due to invalid IL or missing references)
			//IL_2543: Unknown result type (might be due to invalid IL or missing references)
			//IL_1f53: Unknown result type (might be due to invalid IL or missing references)
			//IL_1f63: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b10: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b20: Unknown result type (might be due to invalid IL or missing references)
			//IL_3497: Unknown result type (might be due to invalid IL or missing references)
			//IL_34bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_34c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_34c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_34d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_3df5: Unknown result type (might be due to invalid IL or missing references)
			//IL_3e1d: Unknown result type (might be due to invalid IL or missing references)
			//IL_3e22: Unknown result type (might be due to invalid IL or missing references)
			//IL_3e27: Unknown result type (might be due to invalid IL or missing references)
			//IL_3e33: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_1165: Unknown result type (might be due to invalid IL or missing references)
			//IL_1184: Unknown result type (might be due to invalid IL or missing references)
			//IL_118e: Unknown result type (might be due to invalid IL or missing references)
			//IL_11a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_11ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_11c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_24da: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b3c: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b64: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b69: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b6e: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b70: Unknown result type (might be due to invalid IL or missing references)
			//IL_3168: Unknown result type (might be due to invalid IL or missing references)
			//IL_3187: Unknown result type (might be due to invalid IL or missing references)
			//IL_3191: Unknown result type (might be due to invalid IL or missing references)
			//IL_31a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_31bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_31c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_333a: Unknown result type (might be due to invalid IL or missing references)
			//IL_333f: Unknown result type (might be due to invalid IL or missing references)
			//IL_3342: Unknown result type (might be due to invalid IL or missing references)
			//IL_3310: Unknown result type (might be due to invalid IL or missing references)
			//IL_3315: Unknown result type (might be due to invalid IL or missing references)
			//IL_3318: Unknown result type (might be due to invalid IL or missing references)
			//IL_3cdc: Unknown result type (might be due to invalid IL or missing references)
			//IL_3ce1: Unknown result type (might be due to invalid IL or missing references)
			//IL_3ce4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_081b: Unknown result type (might be due to invalid IL or missing references)
			//IL_082b: Unknown result type (might be due to invalid IL or missing references)
			//IL_07df: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_109c: Unknown result type (might be due to invalid IL or missing references)
			//IL_10b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_1889: Unknown result type (might be due to invalid IL or missing references)
			//IL_1890: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b00: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b44: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b54: Unknown result type (might be due to invalid IL or missing references)
			//IL_2b99: Unknown result type (might be due to invalid IL or missing references)
			//IL_2ed0: Unknown result type (might be due to invalid IL or missing references)
			//IL_2ed5: Unknown result type (might be due to invalid IL or missing references)
			//IL_2ed8: Unknown result type (might be due to invalid IL or missing references)
			//IL_362f: Unknown result type (might be due to invalid IL or missing references)
			//IL_3634: Unknown result type (might be due to invalid IL or missing references)
			//IL_3637: Unknown result type (might be due to invalid IL or missing references)
			//IL_3bc8: Unknown result type (might be due to invalid IL or missing references)
			//IL_3bcd: Unknown result type (might be due to invalid IL or missing references)
			//IL_3bd0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cd9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cde: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ce1: Unknown result type (might be due to invalid IL or missing references)
			//IL_10fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_13b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_13bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_13bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_18a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d15: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d34: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d3e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d50: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d6a: Unknown result type (might be due to invalid IL or missing references)
			//IL_1

BepInEx/plugins/es.damntry.SuperQoLity/UniTask.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks.CompilerServices;
using Cysharp.Threading.Tasks.Internal;
using Cysharp.Threading.Tasks.Triggers;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.LowLevel;
using UnityEngine.PlayerLoop;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("UniTask")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UniTask")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("45d5d502-bd1f-4164-8f95-a940087bd189")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("UniTask.Linq")]
[assembly: InternalsVisibleTo("UniTask.Addressables")]
[assembly: InternalsVisibleTo("UniTask.DOTween")]
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace System.Runtime.CompilerServices
{
	internal sealed class AsyncMethodBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public AsyncMethodBuilderAttribute(Type builderType)
		{
			BuilderType = builderType;
		}
	}
}
namespace Cysharp.Threading.Tasks
{
	public class AsyncLazy
	{
		private static Action<object> continuation = SetCompletionSource;

		private Func<UniTask> taskFactory;

		private UniTaskCompletionSource completionSource;

		private UniTask.Awaiter awaiter;

		private object syncLock;

		private bool initialized;

		public UniTask Task
		{
			get
			{
				EnsureInitialized();
				return completionSource.Task;
			}
		}

		public AsyncLazy(Func<UniTask> taskFactory)
		{
			this.taskFactory = taskFactory;
			completionSource = new UniTaskCompletionSource();
			syncLock = new object();
			initialized = false;
		}

		internal AsyncLazy(UniTask task)
		{
			taskFactory = null;
			completionSource = new UniTaskCompletionSource();
			syncLock = null;
			initialized = true;
			UniTask.Awaiter awaiter = task.GetAwaiter();
			if (awaiter.IsCompleted)
			{
				SetCompletionSource(in awaiter);
				return;
			}
			this.awaiter = awaiter;
			awaiter.SourceOnCompleted(continuation, this);
		}

		public UniTask.Awaiter GetAwaiter()
		{
			return Task.GetAwaiter();
		}

		private void EnsureInitialized()
		{
			if (!Volatile.Read(ref initialized))
			{
				EnsureInitializedCore();
			}
		}

		private void EnsureInitializedCore()
		{
			lock (syncLock)
			{
				if (Volatile.Read(ref initialized))
				{
					return;
				}
				Func<UniTask> func = Interlocked.Exchange(ref taskFactory, null);
				if (func != null)
				{
					UniTask.Awaiter awaiter = func().GetAwaiter();
					if (awaiter.IsCompleted)
					{
						SetCompletionSource(in awaiter);
					}
					else
					{
						this.awaiter = awaiter;
						awaiter.SourceOnCompleted(continuation, this);
					}
					Volatile.Write(ref initialized, value: true);
				}
			}
		}

		private void SetCompletionSource(in UniTask.Awaiter awaiter)
		{
			try
			{
				awaiter.GetResult();
				completionSource.TrySetResult();
			}
			catch (Exception exception)
			{
				completionSource.TrySetException(exception);
			}
		}

		private static void SetCompletionSource(object state)
		{
			AsyncLazy asyncLazy = (AsyncLazy)state;
			try
			{
				asyncLazy.awaiter.GetResult();
				asyncLazy.completionSource.TrySetResult();
			}
			catch (Exception exception)
			{
				asyncLazy.completionSource.TrySetException(exception);
			}
			finally
			{
				asyncLazy.awaiter = default(UniTask.Awaiter);
			}
		}
	}
	public class AsyncLazy<T>
	{
		private static Action<object> continuation = SetCompletionSource;

		private Func<UniTask<T>> taskFactory;

		private UniTaskCompletionSource<T> completionSource;

		private UniTask<T>.Awaiter awaiter;

		private object syncLock;

		private bool initialized;

		public UniTask<T> Task
		{
			get
			{
				EnsureInitialized();
				return completionSource.Task;
			}
		}

		public AsyncLazy(Func<UniTask<T>> taskFactory)
		{
			this.taskFactory = taskFactory;
			completionSource = new UniTaskCompletionSource<T>();
			syncLock = new object();
			initialized = false;
		}

		internal AsyncLazy(UniTask<T> task)
		{
			taskFactory = null;
			completionSource = new UniTaskCompletionSource<T>();
			syncLock = null;
			initialized = true;
			UniTask<T>.Awaiter awaiter = task.GetAwaiter();
			if (awaiter.IsCompleted)
			{
				SetCompletionSource(in awaiter);
				return;
			}
			this.awaiter = awaiter;
			awaiter.SourceOnCompleted(continuation, this);
		}

		public UniTask<T>.Awaiter GetAwaiter()
		{
			return Task.GetAwaiter();
		}

		private void EnsureInitialized()
		{
			if (!Volatile.Read(ref initialized))
			{
				EnsureInitializedCore();
			}
		}

		private void EnsureInitializedCore()
		{
			lock (syncLock)
			{
				if (Volatile.Read(ref initialized))
				{
					return;
				}
				Func<UniTask<T>> func = Interlocked.Exchange(ref taskFactory, null);
				if (func != null)
				{
					UniTask<T>.Awaiter awaiter = func().GetAwaiter();
					if (awaiter.IsCompleted)
					{
						SetCompletionSource(in awaiter);
					}
					else
					{
						this.awaiter = awaiter;
						awaiter.SourceOnCompleted(continuation, this);
					}
					Volatile.Write(ref initialized, value: true);
				}
			}
		}

		private void SetCompletionSource(in UniTask<T>.Awaiter awaiter)
		{
			try
			{
				T result = awaiter.GetResult();
				completionSource.TrySetResult(result);
			}
			catch (Exception exception)
			{
				completionSource.TrySetException(exception);
			}
		}

		private static void SetCompletionSource(object state)
		{
			AsyncLazy<T> asyncLazy = (AsyncLazy<T>)state;
			try
			{
				T result = asyncLazy.awaiter.GetResult();
				asyncLazy.completionSource.TrySetResult(result);
			}
			catch (Exception exception)
			{
				asyncLazy.completionSource.TrySetException(exception);
			}
			finally
			{
				asyncLazy.awaiter = default(UniTask<T>.Awaiter);
			}
		}
	}
	public interface IReadOnlyAsyncReactiveProperty<T> : IUniTaskAsyncEnumerable<T>
	{
		T Value { get; }

		IUniTaskAsyncEnumerable<T> WithoutCurrent();

		UniTask<T> WaitAsync(CancellationToken cancellationToken = default(CancellationToken));
	}
	public interface IAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>, IUniTaskAsyncEnumerable<T>
	{
		new T Value { get; set; }
	}
	[Serializable]
	public class AsyncReactiveProperty<T> : IAsyncReactiveProperty<T>, IReadOnlyAsyncReactiveProperty<T>, IUniTaskAsyncEnumerable<T>, IDisposable
	{
		private sealed class WaitAsyncSource : IUniTaskSource<T>, IUniTaskSource, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
		{
			private static Action<object> cancellationCallback;

			private static TaskPool<WaitAsyncSource> pool;

			private WaitAsyncSource nextNode;

			private AsyncReactiveProperty<T> parent;

			private CancellationToken cancellationToken;

			private CancellationTokenRegistration cancellationTokenRegistration;

			private UniTaskCompletionSourceCore<T> core;

			ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;

			ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }

			ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }

			static WaitAsyncSource()
			{
				cancellationCallback = CancellationCallback;
				TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
			}

			private WaitAsyncSource()
			{
			}

			public static IUniTaskSource<T> Create(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
			{
				if (cancellationToken.IsCancellationRequested)
				{
					return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
				}
				if (!pool.TryPop(out var result))
				{
					result = new WaitAsyncSource();
				}
				result.parent = parent;
				result.cancellationToken = cancellationToken;
				if (cancellationToken.CanBeCanceled)
				{
					result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
				}
				result.parent.triggerEvent.Add(result);
				token = result.core.Version;
				return result;
			}

			private bool TryReturn()
			{
				core.Reset();
				cancellationTokenRegistration.Dispose();
				cancellationTokenRegistration = default(CancellationTokenRegistration);
				parent.triggerEvent.Remove(this);
				parent = null;
				cancellationToken = default(CancellationToken);
				return pool.TryPush(this);
			}

			private static void CancellationCallback(object state)
			{
				WaitAsyncSource obj = (WaitAsyncSource)state;
				obj.OnCanceled(obj.cancellationToken);
			}

			public T GetResult(short token)
			{
				try
				{
					return core.GetResult(token);
				}
				finally
				{
					TryReturn();
				}
			}

			void IUniTaskSource.GetResult(short token)
			{
				GetResult(token);
			}

			public void OnCompleted(Action<object> continuation, object state, short token)
			{
				core.OnCompleted(continuation, state, token);
			}

			public UniTaskStatus GetStatus(short token)
			{
				return core.GetStatus(token);
			}

			public UniTaskStatus UnsafeGetStatus()
			{
				return core.UnsafeGetStatus();
			}

			public void OnCanceled(CancellationToken cancellationToken)
			{
				core.TrySetCanceled(cancellationToken);
			}

			public void OnCompleted()
			{
				core.TrySetCanceled(CancellationToken.None);
			}

			public void OnError(Exception ex)
			{
				core.TrySetException(ex);
			}

			public void OnNext(T value)
			{
				core.TrySetResult(value);
			}
		}

		private sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
		{
			private readonly AsyncReactiveProperty<T> parent;

			public WithoutCurrentEnumerable(AsyncReactiveProperty<T> parent)
			{
				this.parent = parent;
			}

			public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
			{
				return new Enumerator(parent, cancellationToken, publishCurrentValue: false);
			}
		}

		private sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, IUniTaskAsyncDisposable, ITriggerHandler<T>
		{
			private static Action<object> cancellationCallback = CancellationCallback;

			private readonly AsyncReactiveProperty<T> parent;

			private readonly CancellationToken cancellationToken;

			private readonly CancellationTokenRegistration cancellationTokenRegistration;

			private T value;

			private bool isDisposed;

			private bool firstCall;

			public T Current => value;

			ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }

			ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }

			public Enumerator(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue)
			{
				this.parent = parent;
				this.cancellationToken = cancellationToken;
				firstCall = publishCurrentValue;
				parent.triggerEvent.Add(this);
				if (cancellationToken.CanBeCanceled)
				{
					cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
				}
			}

			public UniTask<bool> MoveNextAsync()
			{
				if (firstCall)
				{
					firstCall = false;
					value = parent.Value;
					return CompletedTasks.True;
				}
				completionSource.Reset();
				return new UniTask<bool>(this, completionSource.Version);
			}

			public UniTask DisposeAsync()
			{
				if (!isDisposed)
				{
					isDisposed = true;
					completionSource.TrySetCanceled(cancellationToken);
					parent.triggerEvent.Remove(this);
				}
				return default(UniTask);
			}

			public void OnNext(T value)
			{
				this.value = value;
				completionSource.TrySetResult(result: true);
			}

			public void OnCanceled(CancellationToken cancellationToken)
			{
				DisposeAsync().Forget();
			}

			public void OnCompleted()
			{
				completionSource.TrySetResult(result: false);
			}

			public void OnError(Exception ex)
			{
				completionSource.TrySetException(ex);
			}

			private static void CancellationCallback(object state)
			{
				((Enumerator)state).DisposeAsync().Forget();
			}
		}

		private TriggerEvent<T> triggerEvent;

		[SerializeField]
		private T latestValue;

		private static bool isValueType;

		public T Value
		{
			get
			{
				return latestValue;
			}
			set
			{
				latestValue = value;
				triggerEvent.SetResult(value);
			}
		}

		public AsyncReactiveProperty(T value)
		{
			latestValue = value;
			triggerEvent = default(TriggerEvent<T>);
		}

		public IUniTaskAsyncEnumerable<T> WithoutCurrent()
		{
			return new WithoutCurrentEnumerable(this);
		}

		public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
		{
			return new Enumerator(this, cancellationToken, publishCurrentValue: true);
		}

		public void Dispose()
		{
			triggerEvent.SetCompleted();
		}

		public static implicit operator T(AsyncReactiveProperty<T> value)
		{
			return value.Value;
		}

		public override string ToString()
		{
			if (isValueType)
			{
				return latestValue.ToString();
			}
			return latestValue?.ToString();
		}

		public UniTask<T> WaitAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			short token;
			return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out token), token);
		}

		static AsyncReactiveProperty()
		{
			isValueType = typeof(T).IsValueType;
		}
	}
	public class ReadOnlyAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>, IUniTaskAsyncEnumerable<T>, IDisposable
	{
		private sealed class WaitAsyncSource : IUniTaskSource<T>, IUniTaskSource, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
		{
			private static Action<object> cancellationCallback;

			private static TaskPool<WaitAsyncSource> pool;

			private WaitAsyncSource nextNode;

			private ReadOnlyAsyncReactiveProperty<T> parent;

			private CancellationToken cancellationToken;

			private CancellationTokenRegistration cancellationTokenRegistration;

			private UniTaskCompletionSourceCore<T> core;

			ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;

			ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }

			ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }

			static WaitAsyncSource()
			{
				cancellationCallback = CancellationCallback;
				TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
			}

			private WaitAsyncSource()
			{
			}

			public static IUniTaskSource<T> Create(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
			{
				if (cancellationToken.IsCancellationRequested)
				{
					return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
				}
				if (!pool.TryPop(out var result))
				{
					result = new WaitAsyncSource();
				}
				result.parent = parent;
				result.cancellationToken = cancellationToken;
				if (cancellationToken.CanBeCanceled)
				{
					result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
				}
				result.parent.triggerEvent.Add(result);
				token = result.core.Version;
				return result;
			}

			private bool TryReturn()
			{
				core.Reset();
				cancellationTokenRegistration.Dispose();
				cancellationTokenRegistration = default(CancellationTokenRegistration);
				parent.triggerEvent.Remove(this);
				parent = null;
				cancellationToken = default(CancellationToken);
				return pool.TryPush(this);
			}

			private static void CancellationCallback(object state)
			{
				WaitAsyncSource obj = (WaitAsyncSource)state;
				obj.OnCanceled(obj.cancellationToken);
			}

			public T GetResult(short token)
			{
				try
				{
					return core.GetResult(token);
				}
				finally
				{
					TryReturn();
				}
			}

			void IUniTaskSource.GetResult(short token)
			{
				GetResult(token);
			}

			public void OnCompleted(Action<object> continuation, object state, short token)
			{
				core.OnCompleted(continuation, state, token);
			}

			public UniTaskStatus GetStatus(short token)
			{
				return core.GetStatus(token);
			}

			public UniTaskStatus UnsafeGetStatus()
			{
				return core.UnsafeGetStatus();
			}

			public void OnCanceled(CancellationToken cancellationToken)
			{
				core.TrySetCanceled(cancellationToken);
			}

			public void OnCompleted()
			{
				core.TrySetCanceled(CancellationToken.None);
			}

			public void OnError(Exception ex)
			{
				core.TrySetException(ex);
			}

			public void OnNext(T value)
			{
				core.TrySetResult(value);
			}
		}

		private sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
		{
			private readonly ReadOnlyAsyncReactiveProperty<T> parent;

			public WithoutCurrentEnumerable(ReadOnlyAsyncReactiveProperty<T> parent)
			{
				this.parent = parent;
			}

			public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
			{
				return new Enumerator(parent, cancellationToken, publishCurrentValue: false);
			}
		}

		private sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, IUniTaskAsyncDisposable, ITriggerHandler<T>
		{
			private static Action<object> cancellationCallback = CancellationCallback;

			private readonly ReadOnlyAsyncReactiveProperty<T> parent;

			private readonly CancellationToken cancellationToken;

			private readonly CancellationTokenRegistration cancellationTokenRegistration;

			private T value;

			private bool isDisposed;

			private bool firstCall;

			public T Current => value;

			ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }

			ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }

			public Enumerator(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue)
			{
				this.parent = parent;
				this.cancellationToken = cancellationToken;
				firstCall = publishCurrentValue;
				parent.triggerEvent.Add(this);
				if (cancellationToken.CanBeCanceled)
				{
					cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
				}
			}

			public UniTask<bool> MoveNextAsync()
			{
				if (firstCall)
				{
					firstCall = false;
					value = parent.Value;
					return CompletedTasks.True;
				}
				completionSource.Reset();
				return new UniTask<bool>(this, completionSource.Version);
			}

			public UniTask DisposeAsync()
			{
				if (!isDisposed)
				{
					isDisposed = true;
					completionSource.TrySetCanceled(cancellationToken);
					parent.triggerEvent.Remove(this);
				}
				return default(UniTask);
			}

			public void OnNext(T value)
			{
				this.value = value;
				completionSource.TrySetResult(result: true);
			}

			public void OnCanceled(CancellationToken cancellationToken)
			{
				DisposeAsync().Forget();
			}

			public void OnCompleted()
			{
				completionSource.TrySetResult(result: false);
			}

			public void OnError(Exception ex)
			{
				completionSource.TrySetException(ex);
			}

			private static void CancellationCallback(object state)
			{
				((Enumerator)state).DisposeAsync().Forget();
			}
		}

		private TriggerEvent<T> triggerEvent;

		private T latestValue;

		private IUniTaskAsyncEnumerator<T> enumerator;

		private static bool isValueType;

		public T Value => latestValue;

		public ReadOnlyAsyncReactiveProperty(T initialValue, IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
		{
			latestValue = initialValue;
			ConsumeEnumerator(source, cancellationToken).Forget();
		}

		public ReadOnlyAsyncReactiveProperty(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
		{
			ConsumeEnumerator(source, cancellationToken).Forget();
		}

		private async UniTaskVoid ConsumeEnumerator(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
		{
			enumerator = source.GetAsyncEnumerator(cancellationToken);
			try
			{
				while (await enumerator.MoveNextAsync())
				{
					T result = (latestValue = enumerator.Current);
					triggerEvent.SetResult(result);
				}
			}
			finally
			{
				await enumerator.DisposeAsync();
				enumerator = null;
			}
		}

		public IUniTaskAsyncEnumerable<T> WithoutCurrent()
		{
			return new WithoutCurrentEnumerable(this);
		}

		public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
		{
			return new Enumerator(this, cancellationToken, publishCurrentValue: true);
		}

		public void Dispose()
		{
			if (enumerator != null)
			{
				enumerator.DisposeAsync().Forget();
			}
			triggerEvent.SetCompleted();
		}

		public static implicit operator T(ReadOnlyAsyncReactiveProperty<T> value)
		{
			return value.Value;
		}

		public override string ToString()
		{
			if (isValueType)
			{
				return latestValue.ToString();
			}
			return latestValue?.ToString();
		}

		public UniTask<T> WaitAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			short token;
			return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out token), token);
		}

		static ReadOnlyAsyncReactiveProperty()
		{
			isValueType = typeof(T).IsValueType;
		}
	}
	public static class StateExtensions
	{
		public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
		{
			return new ReadOnlyAsyncReactiveProperty<T>(source, cancellationToken);
		}

		public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, T initialValue, CancellationToken cancellationToken)
		{
			return new ReadOnlyAsyncReactiveProperty<T>(initialValue, source, cancellationToken);
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public readonly struct AsyncUnit : IEquatable<AsyncUnit>
	{
		public static readonly AsyncUnit Default;

		public override int GetHashCode()
		{
			return 0;
		}

		public bool Equals(AsyncUnit other)
		{
			return true;
		}

		public override string ToString()
		{
			return "()";
		}
	}
	public class CancellationTokenEqualityComparer : IEqualityComparer<CancellationToken>
	{
		public static readonly IEqualityComparer<CancellationToken> Default = new CancellationTokenEqualityComparer();

		public bool Equals(CancellationToken x, CancellationToken y)
		{
			return x.Equals(y);
		}

		public int GetHashCode(CancellationToken obj)
		{
			return obj.GetHashCode();
		}
	}
	public static class CancellationTokenExtensions
	{
		private static readonly Action<object> cancellationTokenCallback = Callback;

		private static readonly Action<object> disposeCallback = DisposeCallback;

		public static CancellationToken ToCancellationToken(this UniTask task)
		{
			CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
			ToCancellationTokenCore(task, cancellationTokenSource).Forget();
			return cancellationTokenSource.Token;
		}

		public static CancellationToken ToCancellationToken(this UniTask task, CancellationToken linkToken)
		{
			if (linkToken.IsCancellationRequested)
			{
				return linkToken;
			}
			if (!linkToken.CanBeCanceled)
			{
				return task.ToCancellationToken();
			}
			CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(new CancellationToken[1] { linkToken });
			ToCancellationTokenCore(task, cancellationTokenSource).Forget();
			return cancellationTokenSource.Token;
		}

		public static CancellationToken ToCancellationToken<T>(this UniTask<T> task)
		{
			return task.AsUniTask().ToCancellationToken();
		}

		public static CancellationToken ToCancellationToken<T>(this UniTask<T> task, CancellationToken linkToken)
		{
			return task.AsUniTask().ToCancellationToken(linkToken);
		}

		private static async UniTaskVoid ToCancellationTokenCore(UniTask task, CancellationTokenSource cts)
		{
			try
			{
				await task;
			}
			catch (Exception ex)
			{
				UniTaskScheduler.PublishUnobservedTaskException(ex);
			}
			cts.Cancel();
			cts.Dispose();
		}

		public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return (UniTask.FromCanceled(cancellationToken), default(CancellationTokenRegistration));
			}
			UniTaskCompletionSource uniTaskCompletionSource = new UniTaskCompletionSource();
			return (uniTaskCompletionSource.Task, cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, uniTaskCompletionSource));
		}

		private static void Callback(object state)
		{
			((UniTaskCompletionSource)state).TrySetResult();
		}

		public static CancellationTokenAwaitable WaitUntilCanceled(this CancellationToken cancellationToken)
		{
			return new CancellationTokenAwaitable(cancellationToken);
		}

		public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback)
		{
			bool flag = false;
			if (!ExecutionContext.IsFlowSuppressed())
			{
				ExecutionContext.SuppressFlow();
				flag = true;
			}
			try
			{
				return cancellationToken.Register(callback, useSynchronizationContext: false);
			}
			finally
			{
				if (flag)
				{
					ExecutionContext.RestoreFlow();
				}
			}
		}

		public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action<object> callback, object state)
		{
			bool flag = false;
			if (!ExecutionContext.IsFlowSuppressed())
			{
				ExecutionContext.SuppressFlow();
				flag = true;
			}
			try
			{
				return cancellationToken.Register(callback, state, useSynchronizationContext: false);
			}
			finally
			{
				if (flag)
				{
					ExecutionContext.RestoreFlow();
				}
			}
		}

		public static CancellationTokenRegistration AddTo(this IDisposable disposable, CancellationToken cancellationToken)
		{
			return cancellationToken.RegisterWithoutCaptureExecutionContext(disposeCallback, disposable);
		}

		private static void DisposeCallback(object state)
		{
			((IDisposable)state).Dispose();
		}
	}
	public struct CancellationTokenAwaitable
	{
		public struct Awaiter : ICriticalNotifyCompletion, INotifyCompletion
		{
			private CancellationToken cancellationToken;

			public bool IsCompleted
			{
				get
				{
					if (cancellationToken.CanBeCanceled)
					{
						return cancellationToken.IsCancellationRequested;
					}
					return true;
				}
			}

			public Awaiter(CancellationToken cancellationToken)
			{
				this.cancellationToken = cancellationToken;
			}

			public void GetResult()
			{
			}

			public void OnCompleted(Action continuation)
			{
				UnsafeOnCompleted(continuation);
			}

			public void UnsafeOnCompleted(Action continuation)
			{
				cancellationToken.RegisterWithoutCaptureExecutionContext(continuation);
			}
		}

		private CancellationToken cancellationToken;

		public CancellationTokenAwaitable(CancellationToken cancellationToken)
		{
			this.cancellationToken = cancellationToken;
		}

		public Awaiter GetAwaiter()
		{
			return new Awaiter(cancellationToken);
		}
	}
	public static class CancellationTokenSourceExtensions
	{
		private static readonly Action<object> CancelCancellationTokenSourceStateDelegate = CancelCancellationTokenSourceState;

		private static void CancelCancellationTokenSourceState(object state)
		{
			((CancellationTokenSource)state).Cancel();
		}

		public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
		{
			return cts.CancelAfterSlim(TimeSpan.FromMilliseconds(millisecondsDelay), delayType, delayTiming);
		}

		public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
		{
			return PlayerLoopTimer.StartNew(delayTimeSpan, periodic: false, delayType, delayTiming, cts.Token, CancelCancellationTokenSourceStateDelegate, cts);
		}

		public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, Component component)
		{
			cts.RegisterRaiseCancelOnDestroy(component.gameObject);
		}

		public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, GameObject gameObject)
		{
			gameObject.GetAsyncDestroyTrigger().CancellationToken.RegisterWithoutCaptureExecutionContext(CancelCancellationTokenSourceStateDelegate, cts);
		}
	}
	public static class Channel
	{
		public static Channel<T> CreateSingleConsumerUnbounded<T>()
		{
			return new SingleConsumerUnboundedChannel<T>();
		}
	}
	public abstract class Channel<TWrite, TRead>
	{
		public ChannelReader<TRead> Reader { get; protected set; }

		public ChannelWriter<TWrite> Writer { get; protected set; }

		public static implicit operator ChannelReader<TRead>(Channel<TWrite, TRead> channel)
		{
			return channel.Reader;
		}

		public static implicit operator ChannelWriter<TWrite>(Channel<TWrite, TRead> channel)
		{
			return channel.Writer;
		}
	}
	public abstract class Channel<T> : Channel<T, T>
	{
	}
	public abstract class ChannelReader<T>
	{
		public abstract UniTask Completion { get; }

		public abstract bool TryRead(out T item);

		public abstract UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken = default(CancellationToken));

		public virtual UniTask<T> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			if (TryRead(out var item))
			{
				return UniTask.FromResult(item);
			}
			return ReadAsyncCore(cancellationToken);
		}

		private async UniTask<T> ReadAsyncCore(CancellationToken cancellationToken = default(CancellationToken))
		{
			if (await WaitToReadAsync(cancellationToken) && TryRead(out var item))
			{
				return item;
			}
			throw new ChannelClosedException();
		}

		public abstract IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default(CancellationToken));
	}
	public abstract class ChannelWriter<T>
	{
		public abstract bool TryWrite(T item);

		public abstract bool TryComplete(Exception error = null);

		public void Complete(Exception error = null)
		{
			if (!TryComplete(error))
			{
				throw new ChannelClosedException();
			}
		}
	}
	public class ChannelClosedException : InvalidOperationException
	{
		public ChannelClosedException()
			: base("Channel is already closed.")
		{
		}

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

		public ChannelClosedException(Exception innerException)
			: base("Channel is already closed", innerException)
		{
		}

		public ChannelClosedException(string message, Exception innerException)
			: base(message, innerException)
		{
		}
	}
	internal class SingleConsumerUnboundedChannel<T> : Channel<T>
	{
		private sealed class SingleConsumerUnboundedChannelWriter : ChannelWriter<T>
		{
			private readonly SingleConsumerUnboundedChannel<T> parent;

			public SingleConsumerUnboundedChannelWriter(SingleConsumerUnboundedChannel<T> parent)
			{
				this.parent = parent;
			}

			public override bool TryWrite(T item)
			{
				bool isWaiting;
				lock (parent.items)
				{
					if (parent.closed)
					{
						return false;
					}
					parent.items.Enqueue(item);
					isWaiting = parent.readerSource.isWaiting;
				}
				if (isWaiting)
				{
					parent.readerSource.SingalContinuation();
				}
				return true;
			}

			public override bool TryComplete(Exception error = null)
			{
				lock (parent.items)
				{
					if (parent.closed)
					{
						return false;
					}
					parent.closed = true;
					bool isWaiting = parent.readerSource.isWaiting;
					if (parent.items.Count == 0)
					{
						if (error == null)
						{
							if (parent.completedTaskSource != null)
							{
								parent.completedTaskSource.TrySetResult();
							}
							else
							{
								parent.completedTask = UniTask.CompletedTask;
							}
						}
						else if (parent.completedTaskSource != null)
						{
							parent.completedTaskSource.TrySetException(error);
						}
						else
						{
							parent.completedTask = UniTask.FromException(error);
						}
						if (isWaiting)
						{
							parent.readerSource.SingalCompleted(error);
						}
					}
					parent.completionError = error;
				}
				return true;
			}
		}

		private sealed class SingleConsumerUnboundedChannelReader : ChannelReader<T>, IUniTaskSource<bool>, IUniTaskSource
		{
			private sealed class ReadAllAsyncEnumerable : IUniTaskAsyncEnumerable<T>, IUniTaskAsyncEnumerator<T>, IUniTaskAsyncDisposable
			{
				private readonly Action<object> CancellationCallback1Delegate = CancellationCallback1;

				private readonly Action<object> CancellationCallback2Delegate = CancellationCallback2;

				private readonly SingleConsumerUnboundedChannelReader parent;

				private CancellationToken cancellationToken1;

				private CancellationToken cancellationToken2;

				private CancellationTokenRegistration cancellationTokenRegistration1;

				private CancellationTokenRegistration cancellationTokenRegistration2;

				private T current;

				private bool cacheValue;

				private bool running;

				public T Current
				{
					get
					{
						if (cacheValue)
						{
							return current;
						}
						parent.TryRead(out current);
						return current;
					}
				}

				public ReadAllAsyncEnumerable(SingleConsumerUnboundedChannelReader parent, CancellationToken cancellationToken)
				{
					this.parent = parent;
					cancellationToken1 = cancellationToken;
				}

				public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
				{
					if (running)
					{
						throw new InvalidOperationException("Enumerator is already running, does not allow call GetAsyncEnumerator twice.");
					}
					if (cancellationToken1 != cancellationToken)
					{
						cancellationToken2 = cancellationToken;
					}
					if (cancellationToken1.CanBeCanceled)
					{
						cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancellationCallback1Delegate, this);
					}
					if (cancellationToken2.CanBeCanceled)
					{
						cancellationTokenRegistration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(CancellationCallback2Delegate, this);
					}
					running = true;
					return this;
				}

				public UniTask<bool> MoveNextAsync()
				{
					cacheValue = false;
					return parent.WaitToReadAsync(CancellationToken.None);
				}

				public UniTask DisposeAsync()
				{
					cancellationTokenRegistration1.Dispose();
					cancellationTokenRegistration2.Dispose();
					return default(UniTask);
				}

				private static void CancellationCallback1(object state)
				{
					ReadAllAsyncEnumerable readAllAsyncEnumerable = (ReadAllAsyncEnumerable)state;
					readAllAsyncEnumerable.parent.SingalCancellation(readAllAsyncEnumerable.cancellationToken1);
				}

				private static void CancellationCallback2(object state)
				{
					ReadAllAsyncEnumerable readAllAsyncEnumerable = (ReadAllAsyncEnumerable)state;
					readAllAsyncEnumerable.parent.SingalCancellation(readAllAsyncEnumerable.cancellationToken2);
				}
			}

			private readonly Action<object> CancellationCallbackDelegate = CancellationCallback;

			private readonly SingleConsumerUnboundedChannel<T> parent;

			private CancellationToken cancellationToken;

			private CancellationTokenRegistration cancellationTokenRegistration;

			private UniTaskCompletionSourceCore<bool> core;

			internal bool isWaiting;

			public override UniTask Completion
			{
				get
				{
					if (parent.completedTaskSource != null)
					{
						return parent.completedTaskSource.Task;
					}
					if (parent.closed)
					{
						return parent.completedTask;
					}
					parent.completedTaskSource = new UniTaskCompletionSource();
					return parent.completedTaskSource.Task;
				}
			}

			public SingleConsumerUnboundedChannelReader(SingleConsumerUnboundedChannel<T> parent)
			{
				this.parent = parent;
			}

			public override bool TryRead(out T item)
			{
				lock (parent.items)
				{
					if (parent.items.Count == 0)
					{
						item = default(T);
						return false;
					}
					item = parent.items.Dequeue();
					if (parent.closed && parent.items.Count == 0)
					{
						if (parent.completionError != null)
						{
							if (parent.completedTaskSource != null)
							{
								parent.completedTaskSource.TrySetException(parent.completionError);
							}
							else
							{
								parent.completedTask = UniTask.FromException(parent.completionError);
							}
						}
						else if (parent.completedTaskSource != null)
						{
							parent.completedTaskSource.TrySetResult();
						}
						else
						{
							parent.completedTask = UniTask.CompletedTask;
						}
					}
				}
				return true;
			}

			public override UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken)
			{
				if (cancellationToken.IsCancellationRequested)
				{
					return UniTask.FromCanceled<bool>(cancellationToken);
				}
				lock (parent.items)
				{
					if (parent.items.Count != 0)
					{
						return CompletedTasks.True;
					}
					if (parent.closed)
					{
						if (parent.completionError == null)
						{
							return CompletedTasks.False;
						}
						return UniTask.FromException<bool>(parent.completionError);
					}
					cancellationTokenRegistration.Dispose();
					core.Reset();
					isWaiting = true;
					this.cancellationToken = cancellationToken;
					if (this.cancellationToken.CanBeCanceled)
					{
						cancellationTokenRegistration = this.cancellationToken.RegisterWithoutCaptureExecutionContext(CancellationCallbackDelegate, this);
					}
					return new UniTask<bool>(this, core.Version);
				}
			}

			public void SingalContinuation()
			{
				core.TrySetResult(result: true);
			}

			public void SingalCancellation(CancellationToken cancellationToken)
			{
				core.TrySetCanceled(cancellationToken);
			}

			public void SingalCompleted(Exception error)
			{
				if (error != null)
				{
					core.TrySetException(error);
				}
				else
				{
					core.TrySetResult(result: false);
				}
			}

			public override IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default(CancellationToken))
			{
				return new ReadAllAsyncEnumerable(this, cancellationToken);
			}

			bool IUniTaskSource<bool>.GetResult(short token)
			{
				return core.GetResult(token);
			}

			void IUniTaskSource.GetResult(short token)
			{
				core.GetResult(token);
			}

			UniTaskStatus IUniTaskSource.GetStatus(short token)
			{
				return core.GetStatus(token);
			}

			void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token)
			{
				core.OnCompleted(continuation, state, token);
			}

			UniTaskStatus IUniTaskSource.UnsafeGetStatus()
			{
				return core.UnsafeGetStatus();
			}

			private static void CancellationCallback(object state)
			{
				SingleConsumerUnboundedChannelReader obj = (SingleConsumerUnboundedChannelReader)state;
				obj.SingalCancellation(obj.cancellationToken);
			}
		}

		private readonly Queue<T> items;

		private readonly SingleConsumerUnboundedChannelReader readerSource;

		private UniTaskCompletionSource completedTaskSource;

		private UniTask completedTask;

		private Exception completionError;

		private bool closed;

		public SingleConsumerUnboundedChannel()
		{
			items = new Queue<T>();
			base.Writer = new SingleConsumerUnboundedChannelWriter(this);
			readerSource = new SingleConsumerUnboundedChannelReader(this);
			base.Reader = readerSource;
		}
	}
	public static class EnumerableAsyncExtensions
	{
		public static IEnumerable<UniTask> Select<T>(this IEnumerable<T> source, Func<T, UniTask> selector)
		{
			return Enumerable.Select(source, selector);
		}

		public static IEnumerable<UniTask<TR>> Select<T, TR>(this IEnumerable<T> source, Func<T, UniTask<TR>> selector)
		{
			return Enumerable.Select(source, selector);
		}

		public static IEnumerable<UniTask> Select<T>(this IEnumerable<T> source, Func<T, int, UniTask> selector)
		{
			return Enumerable.Select(source, selector);
		}

		public static IEnumerable<UniTask<TR>> Select<T, TR>(this IEnumerable<T> source, Func<T, int, UniTask<TR>> selector)
		{
			return Enumerable.Select(source, selector);
		}
	}
	public static class EnumeratorAsyncExtensions
	{
		private sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise>
		{
			private static TaskPool<EnumeratorPromise> pool;

			private EnumeratorPromise nextNode;

			private IEnumerator innerEnumerator;

			private CancellationToken cancellationToken;

			private int initialFrame;

			private bool loopRunning;

			private bool calledGetResult;

			private UniTaskCompletionSourceCore<object> core;

			private static readonly FieldInfo waitForSeconds_Seconds;

			public ref EnumeratorPromise NextNode => ref nextNode;

			static EnumeratorPromise()
			{
				waitForSeconds_Seconds = typeof(WaitForSeconds).GetField("m_Seconds", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
				TaskPool.RegisterSizeGetter(typeof(EnumeratorPromise), () => pool.Size);
			}

			private EnumeratorPromise()
			{
			}

			public static IUniTaskSource Create(IEnumerator innerEnumerator, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
			{
				if (cancellationToken.IsCancellationRequested)
				{
					return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
				}
				if (!pool.TryPop(out var result))
				{
					result = new EnumeratorPromise();
				}
				result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
				result.cancellationToken = cancellationToken;
				result.loopRunning = true;
				result.calledGetResult = false;
				result.initialFrame = -1;
				token = result.core.Version;
				if (result.MoveNext())
				{
					PlayerLoopHelper.AddAction(timing, result);
				}
				return result;
			}

			public void GetResult(short token)
			{
				try
				{
					calledGetResult = true;
					core.GetResult(token);
				}
				finally
				{
					if (!loopRunning)
					{
						TryReturn();
					}
				}
			}

			public UniTaskStatus GetStatus(short token)
			{
				return core.GetStatus(token);
			}

			public UniTaskStatus UnsafeGetStatus()
			{
				return core.UnsafeGetStatus();
			}

			public void OnCompleted(Action<object> continuation, object state, short token)
			{
				core.OnCompleted(continuation, state, token);
			}

			public bool MoveNext()
			{
				if (calledGetResult)
				{
					loopRunning = false;
					TryReturn();
					return false;
				}
				if (innerEnumerator == null)
				{
					return false;
				}
				if (cancellationToken.IsCancellationRequested)
				{
					loopRunning = false;
					core.TrySetCanceled(cancellationToken);
					return false;
				}
				if (initialFrame == -1)
				{
					if (PlayerLoopHelper.IsMainThread)
					{
						initialFrame = Time.frameCount;
					}
				}
				else if (initialFrame == Time.frameCount)
				{
					return true;
				}
				try
				{
					if (innerEnumerator.MoveNext())
					{
						return true;
					}
				}
				catch (Exception error)
				{
					loopRunning = false;
					core.TrySetException(error);
					return false;
				}
				loopRunning = false;
				core.TrySetResult(null);
				return false;
			}

			private bool TryReturn()
			{
				core.Reset();
				innerEnumerator = null;
				cancellationToken = default(CancellationToken);
				return pool.TryPush(this);
			}

			private static IEnumerator ConsumeEnumerator(IEnumerator enumerator)
			{
				while (enumerator.MoveNext())
				{
					object current = enumerator.Current;
					if (current == null)
					{
						yield return null;
						continue;
					}
					CustomYieldInstruction cyi = (CustomYieldInstruction)((current is CustomYieldInstruction) ? current : null);
					if (cyi != null)
					{
						while (cyi.keepWaiting)
						{
							yield return null;
						}
						continue;
					}
					if (current is YieldInstruction)
					{
						IEnumerator innerCoroutine2 = null;
						AsyncOperation val = (AsyncOperation)((current is AsyncOperation) ? current : null);
						if (val == null)
						{
							WaitForSeconds val2 = (WaitForSeconds)((current is WaitForSeconds) ? current : null);
							if (val2 != null)
							{
								innerCoroutine2 = UnwrapWaitForSeconds(val2);
							}
						}
						else
						{
							innerCoroutine2 = UnwrapWaitAsyncOperation(val);
						}
						if (innerCoroutine2 != null)
						{
							while (innerCoroutine2.MoveNext())
							{
								yield return null;
							}
							continue;
						}
					}
					else if (current is IEnumerator enumerator2)
					{
						IEnumerator innerCoroutine2 = ConsumeEnumerator(enumerator2);
						while (innerCoroutine2.MoveNext())
						{
							yield return null;
						}
						continue;
					}
					Debug.LogWarning((object)("yield " + current.GetType().Name + " is not supported on await IEnumerator or IEnumerator.ToUniTask(), please use ToUniTask(MonoBehaviour coroutineRunner) instead."));
					yield return null;
				}
			}

			private static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds)
			{
				float second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds);
				float elapsed = 0f;
				do
				{
					yield return null;
					elapsed += Time.deltaTime;
				}
				while (!(elapsed >= second));
			}

			private static IEnumerator UnwrapWaitAsyncOperation(AsyncOperation asyncOperation)
			{
				while (!asyncOperation.isDone)
				{
					yield return null;
				}
			}
		}

		public static UniTask.Awaiter GetAwaiter<T>(this T enumerator) where T : IEnumerator
		{
			object obj = enumerator;
			Error.ThrowArgumentNullException((IEnumerator)obj, "enumerator");
			short token;
			return new UniTask(EnumeratorPromise.Create((IEnumerator)obj, PlayerLoopTiming.Update, CancellationToken.None, out token), token).GetAwaiter();
		}

		public static UniTask WithCancellation(this IEnumerator enumerator, CancellationToken cancellationToken)
		{
			Error.ThrowArgumentNullException(enumerator, "enumerator");
			short token;
			return new UniTask(EnumeratorPromise.Create(enumerator, PlayerLoopTiming.Update, cancellationToken, out token), token);
		}

		public static UniTask ToUniTask(this IEnumerator enumerator, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
		{
			Error.ThrowArgumentNullException(enumerator, "enumerator");
			short token;
			return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out token), token);
		}

		public static UniTask ToUniTask(this IEnumerator enumerator, MonoBehaviour coroutineRunner)
		{
			AutoResetUniTaskCompletionSource autoResetUniTaskCompletionSource = AutoResetUniTaskCompletionSource.Create();
			coroutineRunner.StartCoroutine(Core(enumerator, coroutineRunner, autoResetUniTaskCompletionSource));
			return autoResetUniTaskCompletionSource.Task;
		}

		private static IEnumerator Core(IEnumerator inner, MonoBehaviour coroutineRunner, AutoResetUniTaskCompletionSource source)
		{
			yield return coroutineRunner.StartCoroutine(inner);
			source.TrySetResult();
		}
	}
	public static class ExceptionExtensions
	{
		public static bool IsOperationCanceledException(this Exception exception)
		{
			return exception is OperationCanceledException;
		}
	}
	public static class TaskTracker
	{
		private static List<KeyValuePair<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>> listPool = new List<KeyValuePair<IUniTaskSource, (string, int, DateTime, string)>>();

		private static readonly WeakDictionary<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)> tracking = new WeakDictionary<IUniTaskSource, (string, int, DateTime, string)>();

		private static bool dirty;

		[Conditional("UNITY_EDITOR")]
		public static void TrackActiveTask(IUniTaskSource task, int skipFrame)
		{
		}

		[Conditional("UNITY_EDITOR")]
		public static void RemoveTracking(IUniTaskSource task)
		{
		}

		public static bool CheckAndResetDirty()
		{
			bool result = dirty;
			dirty = false;
			return result;
		}

		public static void ForEachActiveTask(Action<int, string, UniTaskStatus, DateTime, string> action)
		{
			lock (listPool)
			{
				int num = tracking.ToList(ref listPool, clear: false);
				try
				{
					for (int i = 0; i < num; i++)
					{
						action(listPool[i].Value.trackingId, listPool[i].Value.formattedType, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace);
						listPool[i] = default(KeyValuePair<IUniTaskSource, (string, int, DateTime, string)>);
					}
				}
				catch
				{
					listPool.Clear();
					throw;
				}
			}
		}

		private static void TypeBeautify(Type type, StringBuilder sb)
		{
			if (type.IsNested)
			{
				sb.Append(type.DeclaringType.Name.ToString());
				sb.Append(".");
			}
			if (type.IsGenericType)
			{
				int num = type.Name.IndexOf("`");
				if (num != -1)
				{
					sb.Append(type.Name.Substring(0, num));
				}
				else
				{
					sb.Append(type.Name);
				}
				sb.Append("<");
				bool flag = true;
				Type[] genericArguments = type.GetGenericArguments();
				foreach (Type type2 in genericArguments)
				{
					if (!flag)
					{
						sb.Append(", ");
					}
					flag = false;
					TypeBeautify(type2, sb);
				}
				sb.Append(">");
			}
			else
			{
				sb.Append(type.Name);
			}
		}
	}
	public interface IUniTaskAsyncEnumerable<out T>
	{
		IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken));
	}
	public interface IUniTaskAsyncEnumerator<out T> : IUniTaskAsyncDisposable
	{
		T Current { get; }

		UniTask<bool> MoveNextAsync();
	}
	public interface IUniTaskAsyncDisposable
	{
		UniTask DisposeAsync();
	}
	public interface IUniTaskOrderedAsyncEnumerable<TElement> : IUniTaskAsyncEnumerable<TElement>
	{
		IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);

		IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending);

		IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending);
	}
	public interface IConnectableUniTaskAsyncEnumerable<out T> : IUniTaskAsyncEnumerable<T>
	{
		IDisposable Connect();
	}
	public static class UniTaskAsyncEnumerableExtensions
	{
		public static UniTaskCancelableAsyncEnumerable<T> WithCancellation<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
		{
			return new UniTaskCancelableAsyncEnumerable<T>(source, cancellationToken);
		}
	}
	[StructLayout(LayoutKind.Auto)]
	public readonly struct UniTaskCancelableAsyncEnumerable<T>
	{
		[StructLayout(LayoutKind.Auto)]
		public readonly struct Enumerator
		{
			private readonly IUniTaskAsyncEnumerator<T> enumerator;

			public T Current => enumerator.Current;

			internal Enumerator(IUniTaskAsyncEnumerator<T> enumerator)
			{
				this.enumerator = enumerator;
			}

			public UniTask<bool> MoveNextAsync()
			{
				return enumerator.MoveNextAsync();
			}

			public UniTask DisposeAsync()
			{
				return enumerator.DisposeAsync();
			}
		}

		private readonly IUniTaskAsyncEnumerable<T> enumerable;

		private readonly CancellationToken cancellationToken;

		internal UniTaskCancelableAsyncEnumerable(IUniTaskAsyncEnumerable<T> enumerable, CancellationToken cancellationToken)
		{
			this.enumerable = enumerable;
			this.cancellationToken = cancellationToken;
		}

		public Enumerator GetAsyncEnumerator()
		{
			return new Enumerator(enumerable.GetAsyncEnumerator(cancellationToken));
		}
	}
	public enum UniTaskStatus
	{
		Pending,
		Succeeded,
		Faulted,
		Canceled
	}
	public interface IUniTaskSource
	{
		UniTaskStatus GetStatus(short token);

		void OnCompleted(Action<object> continuation, object state, short token);

		void GetResult(short token);

		UniTaskStatus UnsafeGetStatus();
	}
	public interface IUniTaskSource<out T> : IUniTaskSource
	{
		new T GetResult(short token);
	}
	public static class UniTaskStatusExtensions
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsCompleted(this UniTaskStatus status)
		{
			return status != UniTaskStatus.Pending;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsCompletedSuccessfully(this UniTaskStatus status)
		{
			return status == UniTaskStatus.Succeeded;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsCanceled(this UniTaskStatus status)
		{
			return status == UniTaskStatus.Canceled;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool IsFaulted(this UniTaskStatus status)
		{
			return status == UniTaskStatus.Faulted;
		}
	}
	public abstract class MoveNextSource : IUniTaskSource<bool>, IUniTaskSource
	{
		protected UniTaskCompletionSourceCore<bool> completionSource;

		public bool GetResult(short token)
		{
			return completionSource.GetResult(token);
		}

		public UniTaskStatus GetStatus(short token)
		{
			return completionSource.GetStatus(token);
		}

		public void OnCompleted(Action<object> continuation, object state, short token)
		{
			completionSource.OnCompleted(continuation, state, token);
		}

		public UniTaskStatus UnsafeGetStatus()
		{
			return completionSource.UnsafeGetStatus();
		}

		void IUniTaskSource.GetResult(short token)
		{
			completionSource.GetResult(token);
		}

		protected bool TryGetResult<T>(UniTask<T>.Awaiter awaiter, out T result)
		{
			try
			{
				result = awaiter.GetResult();
				return true;
			}
			catch (Exception error)
			{
				completionSource.TrySetException(error);
				result = default(T);
				return false;
			}
		}

		protected bool TryGetResult(UniTask.Awaiter awaiter)
		{
			try
			{
				awaiter.GetResult();
				return true;
			}
			catch (Exception error)
			{
				completionSource.TrySetException(error);
				return false;
			}
		}
	}
	public static class UniTaskLoopRunners
	{
		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerInitialization
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerEarlyUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerFixedUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerPreUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerPreLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerPostLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastInitialization
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastEarlyUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastFixedUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastPreUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastPreLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastPostLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldInitialization
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldEarlyUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldFixedUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldPreUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldPreLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldPostLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldInitialization
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldEarlyUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldFixedUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldPreUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldPreLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldPostLateUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerTimeUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastTimeUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerYieldTimeUpdate
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct UniTaskLoopRunnerLastYieldTimeUpdate
		{
		}
	}
	public enum PlayerLoopTiming
	{
		Initialization,
		LastInitialization,
		EarlyUpdate,
		LastEarlyUpdate,
		FixedUpdate,
		LastFixedUpdate,
		PreUpdate,
		LastPreUpdate,
		Update,
		LastUpdate,
		PreLateUpdate,
		LastPreLateUpdate,
		PostLateUpdate,
		LastPostLateUpdate,
		TimeUpdate,
		LastTimeUpdate
	}
	[Flags]
	public enum InjectPlayerLoopTimings
	{
		All = 0xFFFF,
		Standard = 0x7555,
		Minimum = 0x2110,
		Initialization = 1,
		LastInitialization = 2,
		EarlyUpdate = 4,
		LastEarlyUpdate = 8,
		FixedUpdate = 0x10,
		LastFixedUpdate = 0x20,
		PreUpdate = 0x40,
		LastPreUpdate = 0x80,
		Update = 0x100,
		LastUpdate = 0x200,
		PreLateUpdate = 0x400,
		LastPreLateUpdate = 0x800,
		PostLateUpdate = 0x1000,
		LastPostLateUpdate = 0x2000,
		TimeUpdate = 0x4000,
		LastTimeUpdate = 0x8000
	}
	public interface IPlayerLoopItem
	{
		bool MoveNext();
	}
	public static class PlayerLoopHelper
	{
		private static readonly ContinuationQueue ThrowMarkerContinuationQueue;

		private static readonly PlayerLoopRunner ThrowMarkerPlayerLoopRunner;

		private static int mainThreadId;

		private static string applicationDataPath;

		private static SynchronizationContext unitySynchronizationContext;

		private static ContinuationQueue[] yielders;

		private static PlayerLoopRunner[] runners;

		public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContext;

		public static int MainThreadId => mainThreadId;

		internal static string ApplicationDataPath => applicationDataPath;

		public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == mainThreadId;

		internal static bool IsEditorApplicationQuitting { get; private set; }

		private static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem, bool injectOnFirst, Type loopRunnerYieldType, ContinuationQueue cq, Type loopRunnerType, PlayerLoopRunner runner)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			PlayerLoopSystem val = default(PlayerLoopSystem);
			val.type = loopRunnerYieldType;
			val.updateDelegate = new UpdateFunction(cq.Run);
			PlayerLoopSystem val2 = val;
			val = default(PlayerLoopSystem);
			val.type = loopRunnerType;
			val.updateDelegate = new UpdateFunction(runner.Run);
			PlayerLoopSystem val3 = val;
			PlayerLoopSystem[] array = RemoveRunner(loopSystem, loopRunnerYieldType, loopRunnerType);
			PlayerLoopSystem[] array2 = (PlayerLoopSystem[])(object)new PlayerLoopSystem[array.Length + 2];
			Array.Copy(array, 0, array2, injectOnFirst ? 2 : 0, array.Length);
			if (injectOnFirst)
			{
				array2[0] = val2;
				array2[1] = val3;
			}
			else
			{
				array2[^2] = val2;
				array2[^1] = val3;
			}
			return array2;
		}

		private static PlayerLoopSystem[] RemoveRunner(PlayerLoopSystem loopSystem, Type loopRunnerYieldType, Type loopRunnerType)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			return loopSystem.subSystemList.Where((PlayerLoopSystem ls) => ls.type != loopRunnerYieldType && ls.type != loopRunnerType).ToArray();
		}

		private static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			PlayerLoopSystem val = default(PlayerLoopSystem);
			val.type = typeof(UniTaskSynchronizationContext);
			val.updateDelegate = new UpdateFunction(UniTaskSynchronizationContext.Run);
			PlayerLoopSystem item = val;
			List<PlayerLoopSystem> list = new List<PlayerLoopSystem>(loopSystem.subSystemList.Where((PlayerLoopSystem ls) => ls.type != typeof(UniTaskSynchronizationContext)).ToArray());
			int num = list.FindIndex((PlayerLoopSystem x) => x.type.Name == "ScriptRunDelayedTasks");
			if (num == -1)
			{
				num = list.FindIndex((PlayerLoopSystem x) => x.type.Name == "UniTaskLoopRunnerUpdate");
			}
			list.Insert(num + 1, item);
			return list.ToArray();
		}

		[RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)]
		private static void Init()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			unitySynchronizationContext = SynchronizationContext.Current;
			mainThreadId = Thread.CurrentThread.ManagedThreadId;
			try
			{
				applicationDataPath = Application.dataPath;
			}
			catch
			{
			}
			if (runners == null)
			{
				PlayerLoopSystem playerLoop = PlayerLoop.GetCurrentPlayerLoop();
				Initialize(ref playerLoop);
			}
		}

		static PlayerLoopHelper()
		{
			ThrowMarkerContinuationQueue = new ContinuationQueue(PlayerLoopTiming.Initialization);
			ThrowMarkerPlayerLoopRunner = new PlayerLoopRunner(PlayerLoopTiming.Initialization);
			Init();
		}

		private static int FindLoopSystemIndex(PlayerLoopSystem[] playerLoopList, Type systemType)
		{
			for (int i = 0; i < playerLoopList.Length; i++)
			{
				if (playerLoopList[i].type == systemType)
				{
					return i;
				}
			}
			throw new Exception("Target PlayerLoopSystem does not found. Type:" + systemType.FullName);
		}

		private static void InsertLoop(PlayerLoopSystem[] copyList, InjectPlayerLoopTimings injectTimings, Type loopType, InjectPlayerLoopTimings targetTimings, int index, bool injectOnFirst, Type loopRunnerYieldType, Type loopRunnerType, PlayerLoopTiming playerLoopTiming)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			int num = FindLoopSystemIndex(copyList, loopType);
			if ((injectTimings & targetTimings) == targetTimings)
			{
				copyList[num].subSystemList = InsertRunner(copyList[num], injectOnFirst, loopRunnerYieldType, yielders[index] = new ContinuationQueue(playerLoopTiming), loopRunnerType, runners[index] = new PlayerLoopRunner(playerLoopTiming));
			}
			else
			{
				copyList[num].subSystemList = RemoveRunner(copyList[num], loopRunnerYieldType, loopRunnerType);
			}
		}

		public static void Initialize(ref PlayerLoopSystem playerLoop, InjectPlayerLoopTimings injectTimings = InjectPlayerLoopTimings.All)
		{
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			yielders = new ContinuationQueue[16];
			runners = new PlayerLoopRunner[16];
			PlayerLoopSystem[] array = playerLoop.subSystemList.ToArray();
			InsertLoop(array, injectTimings, typeof(Initialization), InjectPlayerLoopTimings.Initialization, 0, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), PlayerLoopTiming.Initialization);
			InsertLoop(array, injectTimings, typeof(Initialization), InjectPlayerLoopTimings.LastInitialization, 1, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), PlayerLoopTiming.LastInitialization);
			InsertLoop(array, injectTimings, typeof(EarlyUpdate), InjectPlayerLoopTimings.EarlyUpdate, 2, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), PlayerLoopTiming.EarlyUpdate);
			InsertLoop(array, injectTimings, typeof(EarlyUpdate), InjectPlayerLoopTimings.LastEarlyUpdate, 3, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), PlayerLoopTiming.LastEarlyUpdate);
			InsertLoop(array, injectTimings, typeof(FixedUpdate), InjectPlayerLoopTimings.FixedUpdate, 4, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), PlayerLoopTiming.FixedUpdate);
			InsertLoop(array, injectTimings, typeof(FixedUpdate), InjectPlayerLoopTimings.LastFixedUpdate, 5, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), PlayerLoopTiming.LastFixedUpdate);
			InsertLoop(array, injectTimings, typeof(PreUpdate), InjectPlayerLoopTimings.PreUpdate, 6, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), PlayerLoopTiming.PreUpdate);
			InsertLoop(array, injectTimings, typeof(PreUpdate), InjectPlayerLoopTimings.LastPreUpdate, 7, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), PlayerLoopTiming.LastPreUpdate);
			InsertLoop(array, injectTimings, typeof(Update), InjectPlayerLoopTimings.Update, 8, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), PlayerLoopTiming.Update);
			InsertLoop(array, injectTimings, typeof(Update), InjectPlayerLoopTimings.LastUpdate, 9, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), PlayerLoopTiming.LastUpdate);
			InsertLoop(array, injectTimings, typeof(PreLateUpdate), InjectPlayerLoopTimings.PreLateUpdate, 10, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), PlayerLoopTiming.PreLateUpdate);
			InsertLoop(array, injectTimings, typeof(PreLateUpdate), InjectPlayerLoopTimings.LastPreLateUpdate, 11, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), PlayerLoopTiming.LastPreLateUpdate);
			InsertLoop(array, injectTimings, typeof(PostLateUpdate), InjectPlayerLoopTimings.PostLateUpdate, 12, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), PlayerLoopTiming.PostLateUpdate);
			InsertLoop(array, injectTimings, typeof(PostLateUpdate), InjectPlayerLoopTimings.LastPostLateUpdate, 13, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), PlayerLoopTiming.LastPostLateUpdate);
			InsertLoop(array, injectTimings, typeof(TimeUpdate), InjectPlayerLoopTimings.TimeUpdate, 14, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerTimeUpdate), PlayerLoopTiming.TimeUpdate);
			InsertLoop(array, injectTimings, typeof(TimeUpdate), InjectPlayerLoopTimings.LastTimeUpdate, 15, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastTimeUpdate), PlayerLoopTiming.LastTimeUpdate);
			int num = FindLoopSystemIndex(array, typeof(Update));
			array[num].subSystemList = InsertUniTaskSynchronizationContext(array[num]);
			playerLoop.subSystemList = array;
			PlayerLoop.SetPlayerLoop(playerLoop);
		}

		public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action)
		{
			PlayerLoopRunner obj = runners[(int)timing];
			if (obj == null)
			{
				ThrowInvalidLoopTiming(timing);
			}
			obj.AddAction(action);
		}

		private static void ThrowInvalidLoopTiming(PlayerLoopTiming playerLoopTiming)
		{
			throw new InvalidOperationException("Target playerLoopTiming is not injected. Please check PlayerLoopHelper.Initialize. PlayerLoopTiming:" + playerLoopTiming);
		}

		public static void AddContinuation(PlayerLoopTiming timing, Action continuation)
		{
			ContinuationQueue obj = yielders[(int)timing];
			if (obj == null)
			{
				ThrowInvalidLoopTiming(timing);
			}
			obj.Enqueue(continuation);
		}

		public static void DumpCurrentPlayerLoop()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			PlayerLoopSystem currentPlayerLoop = PlayerLoop.GetCurrentPlayerLoop();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("PlayerLoop List");
			PlayerLoopSystem[] subSystemList = currentPlayerLoop.subSystemList;
			for (int i = 0; i < subSystemList.Length; i++)
			{
				PlayerLoopSystem val = subSystemList[i];
				stringBuilder.AppendFormat("------{0}------", val.type.Name);
				stringBuilder.AppendLine();
				if (val.subSystemList == null)
				{
					stringBuilder.AppendFormat("{0} has no subsystems!", ((object)(PlayerLoopSystem)(ref val)).ToString());
					stringBuilder.AppendLine();
					continue;
				}
				PlayerLoopSystem[] subSystemList2 = val.subSystemList;
				foreach (PlayerLoopSystem val2 in subSystemList2)
				{
					stringBuilder.AppendFormat("{0}", val2.type.Name);
					stringBuilder.AppendLine();
					if (val2.subSystemList != null)
					{
						Debug.LogWarning((object)("More Subsystem:" + val2.subSystemList.Length));
					}
				}
			}
			Debug.Log((object)stringBuilder.ToString());
		}

		public static bool IsInjectedUniTaskPlayerLoop()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			PlayerLoopSystem[] subSystemList = PlayerLoop.GetCurrentPlayerLoop().subSystemList;
			foreach (PlayerLoopSystem val in subSystemList)
			{
				if (val.subSystemList == null)
				{
					continue;
				}
				PlayerLoopSystem[] subSystemList2 = val.subSystemList;
				for (int j = 0; j < subSystemList2.Length; j++)
				{
					if (subSystemList2[j].type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization))
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	public abstract class PlayerLoopTimer : IDisposable, IPlayerLoopItem
	{
		private readonly CancellationToken cancellationToken;

		private readonly Action<object> timerCallback;

		private readonly object state;

		private readonly PlayerLoopTiming playerLoopTiming;

		private readonly bool periodic;

		private bool isRunning;

		private bool tryStop;

		private bool isDisposed;

		protected PlayerLoopTimer(bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
		{
			this.periodic = periodic;
			this.playerLoopTiming = playerLoopTiming;
			this.cancellationToken = cancellationToken;
			this.timerCallback = timerCallback;
			this.state = state;
		}

		public static PlayerLoopTimer Create(TimeSpan interval, bool periodic, DelayType delayType, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
		{
			return delayType switch
			{
				DelayType.UnscaledDeltaTime => new IgnoreTimeScalePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state), 
				DelayType.Realtime => new RealtimePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state), 
				_ => new DeltaTimePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state), 
			};
		}

		public static PlayerLoopTimer StartNew(TimeSpan interval, bool periodic, DelayType delayType, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
		{
			PlayerLoopTimer playerLoopTimer = Create(interval, periodic, delayType, playerLoopTiming, cancellationToken, timerCallback, state);
			playerLoopTimer.Restart();
			return playerLoopTimer;
		}

		public void Restart()
		{
			if (isDisposed)
			{
				throw new ObjectDisposedException(null);
			}
			ResetCore(null);
			if (!isRunning)
			{
				isRunning = true;
				PlayerLoopHelper.AddAction(playerLoopTiming, this);
			}
			tryStop = false;
		}

		public void Restart(TimeSpan interval)
		{
			if (isDisposed)
			{
				throw new ObjectDisposedException(null);
			}
			ResetCore(interval);
			if (!isRunning)
			{
				isRunning = true;
				PlayerLoopHelper.AddAction(playerLoopTiming, this);
			}
			tryStop = false;
		}

		public void Stop()
		{
			tryStop = true;
		}

		protected abstract void ResetCore(TimeSpan? newInterval);

		public void Dispose()
		{
			isDisposed = true;
		}

		bool IPlayerLoopItem.MoveNext()
		{
			if (isDisposed)
			{
				isRunning = false;
				return false;
			}
			if (tryStop)
			{
				isRunning = false;
				return false;
			}
			CancellationToken cancellationToken = this.cancellationToken;
			if (cancellationToken.IsCancellationRequested)
			{
				isRunning = false;
				return false;
			}
			if (!MoveNextCore())
			{
				timerCallback(state);
				if (periodic)
				{
					ResetCore(null);
					return true;
				}
				isRunning = false;
				return false;
			}
			return true;
		}

		protected abstract bool MoveNextCore();
	}
	internal sealed class DeltaTimePlayerLoopTimer : PlayerLoopTimer
	{
		private int initialFrame;

		private float elapsed;

		private float interval;

		public DeltaTimePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
			: base(periodic, playerLoopTiming, cancellationToken, timerCallback, state)
		{
			ResetCore(interval);
		}

		protected override bool MoveNextCore()
		{
			if (elapsed == 0f && initialFrame == Time.frameCount)
			{
				return true;
			}
			elapsed += Time.deltaTime;
			if (elapsed >= interval)
			{
				return false;
			}
			return true;
		}

		protected override void ResetCore(TimeSpan? interval)
		{
			elapsed = 0f;
			initialFrame = (PlayerLoopHelper.IsMainThread ? Time.frameCount : (-1));
			if (interval.HasValue)
			{
				this.interval = (float)interval.Value.TotalSeconds;
			}
		}
	}
	internal sealed class IgnoreTimeScalePlayerLoopTimer : PlayerLoopTimer
	{
		private int initialFrame;

		private float elapsed;

		private float interval;

		public IgnoreTimeScalePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
			: base(periodic, playerLoopTiming, cancellationToken, timerCallback, state)
		{
			ResetCore(interval);
		}

		protected override bool MoveNextCore()
		{
			if (elapsed == 0f && initialFrame == Time.frameCount)
			{
				return true;
			}
			elapsed += Time.unscaledDeltaTime;
			if (elapsed >= interval)
			{
				return false;
			}
			return true;
		}

		protected override void ResetCore(TimeSpan? interval)
		{
			elapsed = 0f;
			initialFrame = (PlayerLoopHelper.IsMainThread ? Time.frameCount : (-1));
			if (interval.HasValue)
			{
				this.interval = (float)interval.Value.TotalSeconds;
			}
		}
	}
	internal sealed class RealtimePlayerLoopTimer : PlayerLoopTimer
	{
		private ValueStopwatch stopwatch;

		private long intervalTicks;

		public RealtimePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state)
			: base(periodic, playerLoopTiming, cancellationToken, timerCallback, state)
		{
			ResetCore(interval);
		}

		protected override bool MoveNextCore()
		{
			if (stopwatch.ElapsedTicks >= intervalTicks)
			{
				return false;
			}
			return true;
		}

		protected override void ResetCore(TimeSpan? interval)
		{
			stopwatch = ValueStopwatch.StartNew();
			if (interval.HasValue)
			{
				intervalTicks = interval.Value.Ticks;
			}
		}
	}
	public static class Progress
	{
		private sealed class NullProgress<T> : IProgress<T>
		{
			public static readonly IProgress<T> Instance = new NullProgress<T>();

			private NullProgress()
			{
			}

			public void Report(T value)
			{
			}
		}

		private sealed class AnonymousProgress<T> : IProgress<T>
		{
			private readonly Action<T> action;

			public AnonymousProgress(Action<T> action)
			{
				this.action = action;
			}

			public void Report(T value)
			{
				action(value);
			}
		}

		private sealed class OnlyValueChangedProgress<T> : IProgress<T>
		{
			private readonly Action<T> action;

			private readonly IEqualityComparer<T> comparer;

			private bool isFirstCall;

			private T latestValue;

			public OnlyValueChangedProgress(Action<T> action, IEqualityComparer<T> comparer)
			{
				this.action = action;
				this.comparer = comparer;
				isFirstCall = true;
			}

			public void Report(T value)
			{
				if (isFirstCall)
				{
					isFirstCall = false;
				}
				else if (comparer.Equals(value, latestValue))
				{
					return;
				}
				latestValue = value;
				action(value);
			}
		}

		public static IProgress<T> Create<T>(Action<T> handler)
		{
			if (handler == null)
			{
				return NullProgress<T>.Instance;
			}
			return new AnonymousProgress<T>(handler);
		}

		public static IProgress<T> CreateOnlyValueChanged<T>(Action<T> handler, IEqualityComparer<T> comparer = null)
		{
			if (handler == null)
			{
				return NullProgress<T>.Instance;
			}
			return new OnlyValueChangedProgress<T>(handler, comparer ?? UnityEqualityComparer.GetDefault<T>());
		}
	}
	public static class TaskPool
	{
		internal static int MaxPoolSize;

		private static Dictionary<Type, Func<int>> sizes;

		static TaskPool()
		{
			sizes = new Dictionary<Type, Func<int>>();
			try
			{
				string environmentVariable = Environment.GetEnvironmentVariable("UNITASK_MAX_POOLSIZE");
				if (environmentVariable != null && int.TryParse(environmentVariable, out var result))
				{
					MaxPoolSize = result;
					return;
				}
			}
			catch
			{
			}
			MaxPoolSize = int.MaxValue;
		}

		public static void SetMaxPoolSize(int maxPoolSize)
		{
			MaxPoolSize = maxPoolSize;
		}

		public static IEnumerable<(Type, int)> GetCacheSizeInfo()
		{
			lock (sizes)
			{
				foreach (KeyValuePair<Type, Func<int>> size in sizes)
				{
					yield return (size.Key, size.Value());
				}
			}
		}

		public static void RegisterSizeGetter(Type type, Func<int> getSize)
		{
			lock (sizes)
			{
				sizes[type] = getSize;
			}
		}
	}
	public interface ITaskPoolNode<T>
	{
		ref T NextNode { get; }
	}
	[StructLayout(LayoutKind.Auto)]
	public struct TaskPool<T> where T : class, ITaskPoolNode<T>
	{
		private int gate;

		private int size;

		private T root;

		public int Size => size;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool TryPop(out T result)
		{
			if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
			{
				T val = root;
				if (val != null)
				{
					ref T nextNode = ref val.NextNode;
					root = nextNode;
					nextNode = null;
					size--;
					result = val;
					Volatile.Write(ref gate, 0);
					return true;
				}
				Volatile.Write(ref gate, 0);
			}
			result = null;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool TryPush(T item)
		{
			if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
			{
				if (size < TaskPool.MaxPoolSize)
				{
					item.NextNode = root;
					root = item;
					size++;
					Volatile.Write(ref gate, 0);
					return true;
				}
				Volatile.Write(ref gate, 0);
			}
			return false;
		}
	}
	public sealed class TimeoutController : IDisposable
	{
		private static readonly Action<object> CancelCancellationTokenSourceStateDelegate = CancelCancellationTokenSourceState;

		private CancellationTokenSource timeoutSource;

		private CancellationTokenSource linkedSource;

		private PlayerLoopTimer timer;

		private bool isDisposed;

		private readonly DelayType delayType;

		private readonly PlayerLoopTiming delayTiming;

		private readonly CancellationTokenSource originalLinkCancellationTokenSource;

		private static void CancelCancellationTokenSourceState(object state)
		{
			((CancellationTokenSource)state).Cancel();
		}

		public TimeoutController(DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
		{
			timeoutSource = new CancellationTokenSource();
			originalLinkCancellationTokenSource = null;
			linkedSource = null;
			this.delayType = delayType;
			this.delayTiming = delayTiming;
		}

		public TimeoutController(CancellationTokenSource linkCancellationTokenSource, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
		{
			timeoutSource = new CancellationTokenSource();
			originalLinkCancellationTokenSource = linkCancellationTokenSource;
			linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, linkCancellationTokenSource.Token);
			this.delayType = delayType;
			this.delayTiming = delayTiming;
		}

		public CancellationToken Timeout(int millisecondsTimeout)
		{
			return Timeout(TimeSpan.FromMilliseconds(millisecondsTimeout));
		}

		public CancellationToken Timeout(TimeSpan timeout)
		{
			if (originalLinkCancellationTokenSource != null && originalLinkCancellationTokenSource.IsCancellationRequested)
			{
				return originalLinkCancellationTokenSource.Token;
			}
			if (timeoutSource.IsCancellationRequested)
			{
				timeoutSource.Dispose();
				timeoutSource = new CancellationTokenSource();
				if (linkedSource != null)
				{
					linkedSource.Cancel();
					linkedSource.Dispose();
					linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, originalLinkCancellationTokenSource.Token);
				}
				timer?.Dispose();
				timer = null;
			}
			CancellationToken token = ((linkedSource != null) ? linkedSource : timeoutSource).Token;
			if (timer == null)
			{
				timer = PlayerLoopTimer.StartNew(timeout, periodic: false, delayType, delayTiming, token, CancelCancellationTokenSourceStateDelegate, timeoutSource);
			}
			else
			{
				timer.Restart(timeout);
			}
			return token;
		}

		public bool IsTimeout()
		{
			return timeoutSource.IsCancellationRequested;
		}

		public void Reset()
		{
			timer?.Stop();
		}

		public void Dispose()
		{
			if (isDisposed)
			{
				return;
			}
			try
			{
				timer?.Dispose();
				timeoutSource.Cancel();
				timeoutSource.Dispose();
				if (linkedSource != null)
				{
					linkedSource.Cancel();
					linkedSource.Dispose();
				}
			}
			finally
			{
				isDisposed = true;
			}
		}
	}
	public interface ITriggerHandler<T>
	{
		ITriggerHandler<T> Prev { get; set; }

		ITriggerHandler<T> Next { get; set; }

		void OnNext(T value);

		void OnError(Exception ex);

		void OnCompleted();

		void OnCanceled(CancellationToken cancellationToken);
	}
	public struct TriggerEvent<T>
	{
		private ITriggerHandler<T> head;

		private ITriggerHandler<T> iteratingHead;

		private ITriggerHandler<T> iteratingNode;

		private void LogError(Exception ex)
		{
			Debug.LogException(ex);
		}

		public void SetResult(T value)
		{
			if (iteratingNode != null)
			{
				throw new InvalidOperationException("Can not trigger itself in iterating.");
			}
			for (ITriggerHandler<T> triggerHandler = head; triggerHandler != null; triggerHandler = ((triggerHandler == iteratingNode) ? triggerHandler.Next : iteratingNode))
			{
				iteratingNode = triggerHandler;
				try
				{
					triggerHandler.OnNext(value);
				}
				catch (Exception ex)
				{
					LogError(ex);
					Remove(triggerHandler);
				}
			}
			iteratingNode = null;
			if (iteratingHead != null)
			{
				Add(iteratingHead);
				iteratingHead = null;
			}
		}

		public void SetCanceled(CancellationToken cancellationToken)
		{
			if (iteratingNode != null)
			{
				throw new InvalidOperationException("Can not trigger itself in iterating.");
			}
			ITriggerHandler<T> triggerHandler = head;
			while (triggerHandler != null)
			{
				iteratingNode = triggerHandler;
				try
				{
					triggerHandler.OnCanceled(cancellationToken);
				}
				catch (Exception ex)
				{
					LogError(ex);
				}
				ITriggerHandler<T> obj = ((triggerHandler == iteratingNode) ? triggerHandler.Next : iteratingNode);
				iteratingNode = null;
				Remove(triggerHandler);
				triggerHandler = obj;
			}
			iteratingNode = null;
			if (iteratingHead != null)
			{
				Add(iteratingHead);
				iteratingHead = null;
			}
		}

		public void SetCompleted()
		{
			if (iteratingNode != null)
			{
				throw new InvalidOperationException("Can not trigger itself in iterating.");
			}
			ITriggerHandler<T> triggerHandler = head;
			while (triggerHandler != null)
			{
				iteratingNode = triggerHandler;
				try
				{
					triggerHandler.OnCompleted();
				}
				catch (Exception ex)
				{
					LogError(ex);
				}
				ITriggerHandler<T> obj = ((triggerHandler == iteratingNode) ? triggerHandler.Next : iteratingNode);
				iteratingNode = null;
				Remove(triggerHandler);
				triggerHandler = obj;
			}
			iteratingNode = null;
			if (iteratingHead != null)
			{
				Add(iteratingHead);
				iteratingHead = null;
			}
		}

		public void SetError(Exception exception)
		{
			if (iteratingNode != null)
			{
				throw new InvalidOperationException("Can not trigger itself in iterating.");
			}
			ITriggerHandler<T> triggerHandler = head;
			while (triggerHandler != null)
			{
				iteratingNode = triggerHandler;
				try
				{
					triggerHandler.OnError(exception);
				}
				catch (Exception ex)
				{
					LogError(ex);
				}
				ITriggerHandler<T> obj = ((triggerHandler == iteratingNode) ? triggerHandler.Next : iteratingNode);
				iteratingNode = null;
				Remove(triggerHandler);
				triggerHandler = obj;
			}
			iteratingNode = null;
			if (iteratingHead != null)
			{
				Add(iteratingHead);
				iteratingHead = null;
			}
		}

		public void Add(ITriggerHandler<T> handler)
		{
			if (handler == null)
			{
				throw new ArgumentNullException("handler");
			}
			if (head == null)
			{
				head = handler;
			}
			else if (iteratingNode != null)
			{
				if (iteratingHead == null)
				{
					iteratingHead = handler;
					return;
				}
				ITriggerHandler<T> prev = iteratingHead.Prev;
				if (prev == null)
				{
					iteratingHead.Prev = handler;
					iteratingHead.Next = handler;
					handler.Prev = iteratingHead;
				}
				else
				{
					iteratingHead.Prev = handler;
					prev.Next = handler;
					handler.Prev = prev;
				}
			}
			else
			{
				ITriggerHandler<T> prev2 = head.Prev;
				if (prev2 == null)
				{
					head.Prev = handler;
					head.Next = handler;
					handler.Prev = head;
				}
				else
				{
					head.Prev = handler;
					prev2.Next = handler;
					handler.Prev = prev2;
				}
			}
		}

		public void Remove(ITriggerHandler<T> handler)
		{
			if (handler == null)
			{
				throw new ArgumentNullException("handler");
			}
			ITriggerHandler<T> prev = handler.Prev;
			ITriggerHandler<T> next = handler.Next;
			if (next != null)
			{
				next.Prev = prev;
			}
			if (handler == head)
			{
				head = next;
			}
			else if (prev != null)
			{
				prev.Next = next;
			}
			if (handler == iteratingNode)
			{
				iteratingNode = next;
			}
			if (handler == iteratingHead)
			{
				iteratingHead = next;
			}
			if (head != null && head.Prev == handler)
			{
				if (prev != head)
				{
					head.Prev = prev;
				}
				else
				{
					head.Prev = null;
				}
			}
			if (iteratingHead != null && iteratingHead.Prev == handler)
			{
				if (prev != iteratingHead.Prev)
				{
					iteratingHead.Prev = prev;
				}
				else
				{
					iteratingHead.Prev = null;
				}
			}
			handler.Prev = null;
			handler.Next = null;
		}
	}
	public static class UniTaskCancellationExtensions
	{
		public static CancellationToken GetCancellationTokenOnDestroy(this GameObject gameObject)
		{
			return gameObject.GetAsyncDestroyTrigger().CancellationToken;
		}

		public static CancellationToken GetCancellationTokenOnDestroy(this Component component)
		{
			return component.GetAsyncDestroyTrigger().CancellationToken;
		}
	}
	[StructLayout(LayoutKind.Auto)]
	[AsyncMethodBuilder(typeof(AsyncUniTaskMethodBuilder))]
	public readonly struct UniTask
	{
		private sealed class AsyncUnitSource : IUniTaskSource<AsyncUnit>, IUniTaskSource
		{
			private readonly IUniTaskSource source;

			public AsyncUnitSource(IUniTaskSource source)
			{
				this.source = source;
			}

			public AsyncUnit GetResult(short token)
			{
				source.GetResult(token);
				return AsyncUnit.Default;
			}

			public UniTaskStatus GetStatus(short token)
			{
				return source.GetStatus(token);
			}

			public void OnCompleted(Action<object> continuation, object state, short token)
			{
				source.OnCompleted(continuation, state, token);
			}

			public UniTaskStatus UnsafeGetStatus()
			{
				return source.UnsafeGetStatus();
			}

			void IUniTaskSource.GetResult(short token)
			{
				GetResult(token);
			}
		}

		private sealed class IsCanceledSource : IUniTaskSource<bool>, IUniTaskSource
		{
			private readonly IUniTaskSource source;

			public IsCanceledSource(IUniTaskSource source)
			{
				this.source = source;
			}

			public bool GetResult(short token)
			{
				if (source.GetStatus(token) == UniTaskStatus.Canceled)
				{
					return true;
				}
				source.GetResult(token);
				return false;
			}

			void IUniTaskSource.GetResult(short token)
			{
				GetResult(token);
			}

			public UniTaskStatus GetStatus(short token)
			{
				return source.GetStatus(token);
			}

			public UniTaskStatus UnsafeGetStatus()
			{
				return source.UnsafeGetStatus();
			}

			public void OnCompleted(Action<object> continuation, object state, short token)
			{
				source.OnCompleted(continuation, state, token);
			}
		}

		private sealed class MemoizeSource : IUniTaskSource
		{
			private IUniTaskSource source;

			private ExceptionDispatchInfo exception;

			private UniTaskStatus status;

			public MemoizeSource(IUniTaskSource source)
			{
				this.source = source;
			}

			public void GetResult(short token)
			{
				if (source == null)
				{
					if (exception != null)
					{
						exception.Throw();
					}
					return;
				}
				try
				{
					source.GetResult(token);
					status = UniTaskStatus.Succeeded;
				}
				catch (Exception ex)
				{
					exception = ExceptionDispatchInfo.Capture(ex);
					if (ex is OperationCanceledException)
					{
						status = UniTaskStatus.Canceled;
					}
					else
					{
						status = UniTaskStatus.Faulted;
					}
					throw;
				}
				finally
				{
					source = null;
				}
			}

			public UniTaskStatus GetStatus(short token)
			{
				if (source == null)
				{
					return status;
				}
				return source.GetStatus(token);
			}

			public void OnCompleted(Action<object> continuation, object state, short token)
			{
				if (source == null)
				{
					continuation(state);
				}
				else
				{
					source.OnCompleted(continuation, state, token);
				}
			}

			public UniTaskStatus UnsafeGetStatus()
			{
				if (source == null)
				{
					return status;
				}
				return source.UnsafeGetStatus();
			}
		}

		public readonly struct Awaiter : ICriticalNotifyCompletion, INotifyCompletion
		{
			private readonly UniTask task;

			public bool IsCompleted
			{
				[MethodImpl(MethodImplOptions.AggressiveInlining)]
				[DebuggerHidden]
				get
				{
					return task.Status.IsCompleted();
				}
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			[DebuggerHidden]
			public Awaiter(in UniTask task)
			{
				this.task = task;
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			[DebuggerHidden]
			public void GetResult()
			{
				if (task.source != null)
				{
					task.source.GetResult(task.token);
				}
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			[DebuggerHidden]
			public void OnCompleted(Action continuation)
			{
				if (task.source == null)
				{
					continuation();
				}
				else
				{
					task.source.OnCompleted(AwaiterActions.InvokeContinuationDelegate, continuation, task.token);
				}
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			[DebuggerHidden]
			public void UnsafeOnCompleted(Action continuation)
			{
				if (task.source == null)
				{
					continuation();
				}
				else
				{
					task.source.OnCompleted(AwaiterActions.InvokeContinuationDelegate, continuation, task.token);
				}
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			[DebuggerHidden]
			public void SourceOnCompleted(Action<object> continuation, object state)
			{
				if (task.source == null)
				{
					continuation(state);
				}
				else
				{
					task.source.OnCompleted(continuation, state, task.token);
				}
			}
		}

		private sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<YieldPromise>
		{
			private static TaskPool<YieldPromise> pool;

			private YieldPromise nextNode;

			private CancellationToken cancellationToken;

			private CancellationTokenRegistration cancellationTokenRegistration;

			private bool cancelImmediately;

			private UniTaskCompletionSourceCore<object> core;

			public ref YieldPromise NextNode => ref nextNode;

			static YieldPromise()
			{
				TaskPool.RegisterSizeGetter(typeof(YieldPromise), () => pool.Size);
			}

			private YieldPromise()
			{
			}

			public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
			{
				if (cancellationToken.IsCancellationRequested)
				{
					return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
				}
				if (!pool.TryPop(out var result))
				{
					result = new YieldPromise();
				}
				result.cancellationToken = cancellationToken;
				result.cancelImmediately = cancelImmediately;
				if (cancelImmediately && cancellationToken.CanBeCanceled)
				{
					result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(delegate(object state)
					{
						YieldPromise yieldPromise = (YieldPromise)state;
						yieldPromise.core.TrySetCanceled(yieldPromise.cancellationToken);
					}, result);
				}
				PlayerLoopHelper.AddAction(timing, result);
				token = result.core.Version;
				return result;
			}

			public void GetResult(short token)
			{
				try
				{
					core.GetResult(token);
				}
				finally
				{
					if (!cancelImmediately || !cancellationToken.IsCancellationRequested)
					{
						TryReturn();
					}
				}
			}

			public UniTaskStatus GetStatus(short token)
			{
				return core.GetStatus(token);
			}

			public UniTaskStatus UnsafeGetStatus()
			{
				return core.UnsafeGetStatus();
			}

			public void OnCompleted(Action<object> continuation, object state, short token)
			{
				core.OnCompleted(continuation, state, token);
			}

			public bool MoveNext()
			{
				if (cancellationToken.IsCancellationRequested)
				{
					core.TrySetCanceled(cancellationToken);
					return false;
				}
				core.TrySetResult(null);
				return false;
			}

			private bool TryReturn()
			{
				core.Reset();
				cancellationToken = default(CancellationToken);
				cancellationTokenRegistration.Dispose();
				cancelImmediately = false;
				return pool.TryPush(this);
			}
		}

		private sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise>
		{
			private static TaskPool<NextFramePromise> pool;

			private NextFramePromise nextNode;

			private int frameCount;

			private UniTaskCompletionSourceCore<AsyncUnit> core;

			private CancellationToken cancellationToken;

			private CancellationTokenRegistration cancellationTokenRegistration;

			private bool cancelImmediately;

			public ref NextFramePromise NextNode => ref nextNode;

			static NextFramePromise()
			{
				TaskPool.RegisterSizeGetter(typeof(NextFramePromise), () => pool.Size);
			}

			private NextFramePromise()
			{
			}

			public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
			{
				if (cancellationToken.IsCancellationRequested)
				{
					return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
				}
				if (!pool.TryPop(out var result))
				{
					result = new NextFramePromise();
				}
				result.frameCount = (PlayerLoopHelper.IsMainThread ? Time.frameCount : (-1));
				result.cancellationToken = cancellationToken;
				result.cancelImmediately = cancelImmediately;
				if (cancelImmediately && cancellationToken.CanBeCanceled)
				{
					result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(delegate(object state)
					{
						NextFramePromise nextFramePromise = (NextFramePromise)state;
						nextFramePromise.core.TrySetCanceled(nextFramePromise.cancellationToken);
					}, result);
				}
				PlayerLoopHelper.AddAction(timing, result);
				token = result.core.Version;
				return result;
			}

			public void GetResult(short token)
			{
				try
				{
					core.GetResult(token);
				}
				finally
				{
					if (!cancelImmediately || !cancellationToken.IsCancellationRequested)
					{
						TryReturn();
					}
				}
			}

			public UniTaskStatus GetStatus(short token)
			{
				return core.GetStatus(token);
			}

			public UniTa