Decompiled source of PathfindingLagFix v2.4.0

PathfindingLagFix.dll

Decompiled a day 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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using HarmonyLib.Public.Patching;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using PathfindingLagFix.Patches;
using PathfindingLagFix.Utilities;
using PathfindingLagFix.Utilities.IL;
using PathfindingLib.API;
using PathfindingLib.Jobs;
using PathfindingLib.Utilities;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Netcode;
using Unity.Profiling;
using Unity.Profiling.LowLevel;
using Unity.Profiling.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Experimental.AI;
using UnityEngine.SceneManagement;
using UnityEngine.Scripting;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PathfindingLagFix")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PathfindingLagFix")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fedb984b-16ae-458c-b2cc-19590627c578")]
[assembly: AssemblyFileVersion("2.4.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PathfindingLagFix
{
	internal struct ConfigOptions
	{
		private enum ConfigPreset
		{
			OnlyFixes,
			Vanilla
		}

		private static readonly ConfigOptions OnlyFixesPreset = new ConfigOptions
		{
			DistancePathfindingFallbackNodeSelection = DistancePathfindingFallbackNodeSelectionType.BestPathable
		};

		private static readonly ConfigOptions VanillaPreset = new ConfigOptions
		{
			DistancePathfindingFallbackNodeSelection = DistancePathfindingFallbackNodeSelectionType.Vanilla
		};

		internal static ConfigOptions CurrentOptions = OnlyFixesPreset;

		private const string presetDescription = "Select a preset to use as defaults for all options that change gameplay.\n\nOnlyFixes: Options that are intended to act solely as bug fixes and should retain the intention of the original code.\nVanilla: Options that completely match vanilla as much as possible.";

		private static ConfigEntry<ConfigPreset> presetOption;

		private const string distancePathfindingFallbackNodeSelectionDescription = "How nodes should be selected if the criteria for a distance based pathfinding operation (i.e. bracken evasion) fails.\n\nUsePreset: Use the option selected by the current preset.\nBestPathable: The enemy will go to the furthest/closest node that can be reached. This is the old behavior of PathfindingLagFix, and it guarantees the bracken will not get stuck when spotted.\nVanilla: The enemy will attempt to go to the furthest/closest node, regardless of whether it can be reached. This will cause brackens to sometimes stutter step towards the furthest position instead of moving smoothly.\nDontMove: The enemy will not move until it has a valid path to follow. For the bracken, this will result in it standing still and looking at the player until they look away.";

		private static ConfigEntry<DistancePathfindingFallbackNodeSelectionType> distancePathfindingFallbackNodeSelectionOption;

		internal DistancePathfindingFallbackNodeSelectionType DistancePathfindingFallbackNodeSelection;

		internal static void BindAllOptions(ConfigFile file)
		{
			presetOption = BindOption(file, "General", "Preset", ConfigPreset.OnlyFixes, "Select a preset to use as defaults for all options that change gameplay.\n\nOnlyFixes: Options that are intended to act solely as bug fixes and should retain the intention of the original code.\nVanilla: Options that completely match vanilla as much as possible.");
			distancePathfindingFallbackNodeSelectionOption = BindOption(file, "Behavior", "DistancePathfindingFallbackNodeSelection", DistancePathfindingFallbackNodeSelectionType.UsePreset, "How nodes should be selected if the criteria for a distance based pathfinding operation (i.e. bracken evasion) fails.\n\nUsePreset: Use the option selected by the current preset.\nBestPathable: The enemy will go to the furthest/closest node that can be reached. This is the old behavior of PathfindingLagFix, and it guarantees the bracken will not get stuck when spotted.\nVanilla: The enemy will attempt to go to the furthest/closest node, regardless of whether it can be reached. This will cause brackens to sometimes stutter step towards the furthest position instead of moving smoothly.\nDontMove: The enemy will not move until it has a valid path to follow. For the bracken, this will result in it standing still and looking at the player until they look away.");
			UpdateCurrentOptions();
		}

		private static ConfigEntry<T> BindOption<T>(ConfigFile file, string section, string key, T defaultValue, string description)
		{
			ConfigEntry<T> obj = file.Bind<T>(section, key, defaultValue, description);
			obj.SettingChanged += delegate
			{
				UpdateCurrentOptions();
			};
			return obj;
		}

		private static void UpdateCurrentOptions()
		{
			CurrentOptions = presetOption.Value switch
			{
				ConfigPreset.OnlyFixes => OnlyFixesPreset, 
				ConfigPreset.Vanilla => VanillaPreset, 
				_ => throw new InvalidOperationException($"Unknown preset {presetOption.Value}"), 
			};
			if (distancePathfindingFallbackNodeSelectionOption.Value != 0)
			{
				CurrentOptions.DistancePathfindingFallbackNodeSelection = distancePathfindingFallbackNodeSelectionOption.Value;
			}
			Plugin.Instance.Logger.LogInfo((object)string.Format("{0} {1} is using preset {2} with options:", "Zaggy1024.PathfindingLagFix", "2.4.0", presetOption.Value));
			Plugin.Instance.Logger.LogInfo((object)string.Format("    {0} = {1} ({2})", "DistancePathfindingFallbackNodeSelection", CurrentOptions.DistancePathfindingFallbackNodeSelection, distancePathfindingFallbackNodeSelectionOption.Value));
		}
	}
	internal enum DistancePathfindingFallbackNodeSelectionType
	{
		UsePreset,
		BestPathable,
		Vanilla,
		DontMove
	}
	[BepInPlugin("Zaggy1024.PathfindingLagFix", "PathfindingLagFix", "2.4.0")]
	[BepInDependency("Zaggy1024.PathfindingLib", "2.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string MOD_NAME = "PathfindingLagFix";

		public const string MOD_UNIQUE_NAME = "Zaggy1024.PathfindingLagFix";

		public const string MOD_VERSION = "2.4.0";

		private readonly Harmony harmony = new Harmony("Zaggy1024.PathfindingLagFix");

		public static Plugin Instance { get; private set; }

		public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

		public void Awake()
		{
			Instance = this;
			ConfigOptions.BindAllOptions(((BaseUnityPlugin)this).Config);
			harmony.PatchAll(typeof(PatchEnemyAI));
			harmony.PatchAll(typeof(PatchFlowermanAI));
			harmony.PatchAll(typeof(PatchCentipedeAI));
			harmony.PatchAll(typeof(PatchPufferAI));
			harmony.PatchAll(typeof(PatchDoublewingAI));
			harmony.PatchAll(typeof(PatchFlowerSnakeEnemy));
			harmony.PatchAll(typeof(PatchSpringManAI));
			harmony.PatchAll(typeof(PatchBlobAI));
			harmony.PatchAll(typeof(PatchCaveDwellerAI));
			harmony.PatchAll(typeof(PatchStingrayAI));
			PatchFindMainEntrance.ApplyPatches(harmony);
		}
	}
}
namespace PathfindingLagFix.Utilities
{
	internal struct AssignGroundCastPointsAsDestinationsJob : IJobFor
	{
		[ReadOnly]
		private NativeArray<RaycastHit> Hits;

		[WriteOnly]
		private NativeArray<Vector3> Destinations;

		public void Initialize(NativeArray<RaycastHit> hits, NativeArray<Vector3> points)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Hits = hits;
			Destinations = points;
		}

		public void Execute(int index)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003e: 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)
			RaycastHit val = Hits[index];
			if (((RaycastHit)(ref val)).colliderInstanceID == 0)
			{
				Destinations[index] = FindPathsToNodesJob.INVALID_DESTINATION;
				return;
			}
			ref NativeArray<Vector3> destinations = ref Destinations;
			val = Hits[index];
			destinations[index] = ((RaycastHit)(ref val)).point;
		}
	}
	internal static class AsyncDistancePathfinding
	{
		internal class EnemyDistancePathfindingStatus
		{
			public Coroutine Coroutine;

			public int CurrentSearchTypeID = -1;

			public GameObject[] AINodes;

			public Transform[] SortedNodes;

			public Vector3[] SortedPositions;

			public FindPathsToNodesJob Job;

			public JobHandle JobHandle;

			public Transform ChosenNode;

			public float MostOptimalDistance = float.PositiveInfinity;

			public void SortNodes(EnemyAI enemy, Vector3 target, bool furthestFirst)
			{
				//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_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//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_00a3: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				int num = enemy.allAINodes.Length;
				if (enemy.allAINodes != AINodes)
				{
					AINodes = enemy.allAINodes;
					SortedNodes = (Transform[])(object)new Transform[num];
					SortedPositions = (Vector3[])(object)new Vector3[num];
					for (int i = 0; i < num; i++)
					{
						Transform transform = AINodes[i].transform;
						SortedNodes[i] = transform;
						SortedPositions[i] = transform.position;
					}
				}
				for (int j = 1; j < num; j++)
				{
					Vector3 val = SortedPositions[j] - target;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					for (int num2 = j; num2 > 0; num2--)
					{
						val = SortedPositions[num2 - 1] - target;
						if ((((Vector3)(ref val)).sqrMagnitude <= sqrMagnitude) ^ furthestFirst)
						{
							break;
						}
						Swap<Transform>(ref SortedNodes[num2 - 1], ref SortedNodes[num2]);
						Swap<Vector3>(ref SortedPositions[num2 - 1], ref SortedPositions[num2]);
					}
				}
				static void Swap<T>(ref T a, ref T b)
				{
					T val2 = b;
					T val3 = a;
					a = val2;
					b = val3;
				}
			}

			public Transform RetrieveChosenNode(out float mostOptimalDistance)
			{
				Transform chosenNode = ChosenNode;
				mostOptimalDistance = MostOptimalDistance;
				if ((Object)(object)chosenNode == (Object)null)
				{
					return null;
				}
				ChosenNode = null;
				MostOptimalDistance = float.PositiveInfinity;
				CurrentSearchTypeID = -1;
				return chosenNode;
			}

			~EnemyDistancePathfindingStatus()
			{
				Job.FreeAllResources();
			}
		}

		internal delegate IEnumerator NodeSelectionCoroutine(EnemyDistancePathfindingStatus status);

		[CompilerGenerated]
		private sealed class <ChooseNodeCoroutine>d__10 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public EnemyAI enemy;

			public EnemyDistancePathfindingStatus status;

			public Vector3 target;

			public bool farthestFirst;

			public float capDistance;

			public int offset;

			public bool avoidLineOfSight;

			private int <candidateCount>5__2;

			private FindPathsToNodesJob <job>5__3;

			private JobHandle <jobHandle>5__4;

			private int <result>5__5;

			private float <capDistanceSqr>5__6;

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

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

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

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

			private bool MoveNext()
			{
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: 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_00ba: 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_016c: 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_0173: Unknown result type (might be due to invalid IL or missing references)
				//IL_0175: Unknown result type (might be due to invalid IL or missing references)
				//IL_017f: Invalid comparison between Unknown and I4
				//IL_0143: 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)
				//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_0185: Unknown result type (might be due to invalid IL or missing references)
				//IL_0187: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: Invalid comparison between Unknown and I4
				//IL_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0239: Unknown result type (might be due to invalid IL or missing references)
				//IL_023e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0248: Invalid comparison between Unknown and I4
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (enemy.allAINodes.Length == 0 || !enemy.agent.isOnNavMesh)
					{
						status.ChosenNode = ((Component)enemy).transform;
						status.MostOptimalDistance = 0f;
						return false;
					}
					<candidateCount>5__2 = enemy.allAINodes.Length;
					StartJobs(enemy, status, target, <candidateCount>5__2, farthestFirst);
					<job>5__3 = status.Job;
					<jobHandle>5__4 = status.JobHandle;
					<result>5__5 = -1;
					<capDistanceSqr>5__6 = capDistance * capDistance;
					goto IL_01e4;
				case 1:
				{
					<>1__state = -1;
					bool flag = true;
					int num = Math.Min(offset, <candidateCount>5__2 - 1);
					Vector3 position = ((Component)enemy).transform.position;
					for (int i = 0; i < <candidateCount>5__2; i++)
					{
						if (<capDistanceSqr>5__6 > 0f)
						{
							Vector3 val = status.SortedPositions[i] - position;
							if (((Vector3)(ref val)).sqrMagnitude > <capDistanceSqr>5__6)
							{
								continue;
							}
						}
						PathQueryStatus val2 = <job>5__3.Statuses[i];
						if ((int)PathQueryStatusExtensions.GetResult(val2) == 536870912)
						{
							flag = false;
							break;
						}
						if ((int)PathQueryStatusExtensions.GetResult(val2) == 1073741824)
						{
							NativeArray<Vector3> path = <job>5__3.GetPath(i);
							if ((!avoidLineOfSight || !LineOfSight.PathIsBlockedByLineOfSight(path)) && num-- == 0)
							{
								<result>5__5 = i;
								break;
							}
						}
					}
					if (!flag)
					{
						goto IL_01e4;
					}
					goto IL_01f0;
				}
				case 2:
					{
						<>1__state = -1;
						break;
					}
					IL_01e4:
					if (<result>5__5 == -1)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					goto IL_01f0;
					IL_01f0:
					<job>5__3.Cancel();
					if (<result>5__5 == -1)
					{
						switch (ConfigOptions.CurrentOptions.DistancePathfindingFallbackNodeSelection)
						{
						case DistancePathfindingFallbackNodeSelectionType.BestPathable:
						{
							for (int j = 0; j < <candidateCount>5__2; j++)
							{
								if ((int)PathQueryStatusExtensions.GetResult(<job>5__3.Statuses[j]) == 1073741824)
								{
									<result>5__5 = j;
									break;
								}
							}
							break;
						}
						case DistancePathfindingFallbackNodeSelectionType.Vanilla:
							<result>5__5 = 0;
							break;
						}
					}
					if (<result>5__5 == -1)
					{
						status.ChosenNode = ((Component)enemy).transform;
						status.MostOptimalDistance = 0f;
					}
					else
					{
						status.ChosenNode = status.SortedNodes[<result>5__5];
						status.MostOptimalDistance = Vector3.Distance(target, status.SortedPositions[<result>5__5]);
					}
					break;
				}
				if (!((JobHandle)(ref <jobHandle>5__4)).IsCompleted)
				{
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				status.Coroutine = null;
				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();
			}
		}

		internal const float DEFAULT_CAP_DISTANCE = 40f;

		private static readonly EnemyMap<EnemyDistancePathfindingStatus> Statuses = new EnemyMap<EnemyDistancePathfindingStatus>(() => new EnemyDistancePathfindingStatus());

		internal static void RemoveStatus(EnemyAI enemy)
		{
			Statuses.Remove(enemy);
		}

		internal static EnemyDistancePathfindingStatus StartJobs(EnemyAI enemy, EnemyDistancePathfindingStatus status, Vector3 target, int count, bool farthestFirst, bool calculateDistance = false)
		{
			//IL_0009: 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_0033: 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)
			NavMeshAgent agent = enemy.agent;
			status.SortNodes(enemy, target, farthestFirst);
			ref FindPathsToNodesJob job = ref status.Job;
			job.Initialize(agent, status.SortedPositions, calculateDistance);
			status.JobHandle = IJobForExtensions.ScheduleByRef<FindPathsToNodesJob>(ref job, count, default(JobHandle));
			return status;
		}

		internal static EnemyDistancePathfindingStatus StartChoosingNode(EnemyAI enemy, int searchTypeID, NodeSelectionCoroutine coroutine)
		{
			EnemyDistancePathfindingStatus enemyDistancePathfindingStatus = Statuses[enemy];
			if (enemyDistancePathfindingStatus.CurrentSearchTypeID == searchTypeID)
			{
				return enemyDistancePathfindingStatus;
			}
			if (enemyDistancePathfindingStatus.Coroutine != null)
			{
				enemyDistancePathfindingStatus.Job.Cancel();
				return enemyDistancePathfindingStatus;
			}
			enemyDistancePathfindingStatus.RetrieveChosenNode(out var _);
			enemyDistancePathfindingStatus.CurrentSearchTypeID = searchTypeID;
			enemyDistancePathfindingStatus.Coroutine = ((MonoBehaviour)enemy).StartCoroutine(coroutine(enemyDistancePathfindingStatus));
			return enemyDistancePathfindingStatus;
		}

		private static EnemyDistancePathfindingStatus StartChoosingNode(EnemyAI enemy, int searchTypeID, Vector3 target, bool farthestFirst, bool avoidLineOfSight, int offset, float capDistance)
		{
			//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)
			return StartChoosingNode(enemy, searchTypeID, (EnemyDistancePathfindingStatus status) => ChooseNodeCoroutine(enemy, status, target, farthestFirst, avoidLineOfSight, offset, capDistance));
		}

		internal static EnemyDistancePathfindingStatus StartChoosingFarthestNodeFromPosition(EnemyAI enemy, int searchTypeID, Vector3 target, bool avoidLineOfSight = false, int offset = 0, float capDistance = 0f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return StartChoosingNode(enemy, searchTypeID, target, farthestFirst: true, avoidLineOfSight, offset, capDistance);
		}

		internal static EnemyDistancePathfindingStatus StartChoosingClosestNodeToPosition(EnemyAI enemy, int searchTypeID, Vector3 target, bool avoidLineOfSight = false, int offset = 0, float capDistance = 0f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return StartChoosingNode(enemy, searchTypeID, target, farthestFirst: false, avoidLineOfSight, offset, capDistance);
		}

		[IteratorStateMachine(typeof(<ChooseNodeCoroutine>d__10))]
		internal static IEnumerator ChooseNodeCoroutine(EnemyAI enemy, EnemyDistancePathfindingStatus status, Vector3 target, bool farthestFirst, bool avoidLineOfSight, int offset, float capDistance)
		{
			//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)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ChooseNodeCoroutine>d__10(0)
			{
				enemy = enemy,
				status = status,
				target = target,
				farthestFirst = farthestFirst,
				avoidLineOfSight = avoidLineOfSight,
				offset = offset,
				capDistance = capDistance
			};
		}
	}
	internal static class AsyncPlayerPathfinding
	{
		[Flags]
		internal enum PathOptions : byte
		{
			None = 0,
			GroundCast = 1,
			RequirePath = 2
		}

		internal class EnemyToPlayerPathfindingStatus
		{
			internal enum JobsStatus
			{
				NotStarted,
				NotRetrieved,
				RetrievedJobsDone,
				RetrievedJobsIncomplete
			}

			[CompilerGenerated]
			private PathOptions <pathFlags>P;

			internal FindPathsToNodesJob PathsToPlayersJob;

			private AssignGroundCastPointsAsDestinationsJob AssignDestinationsJob;

			internal JobHandle JobHandle;

			private NativeArray<RaycastCommand> raycastCommands;

			private NativeArray<RaycastHit> raycastHits;

			private NativeArray<Vector3> playerPositions;

			private float inFlightJobsTime;

			private float currentJobsTime;

			private bool[] playersPathable;

			public EnemyToPlayerPathfindingStatus(PathOptions pathFlags)
			{
				<pathFlags>P = pathFlags;
				inFlightJobsTime = float.NegativeInfinity;
				currentJobsTime = float.NegativeInfinity;
				playersPathable = Array.Empty<bool>();
				base..ctor();
			}

			private void StartJobs(EnemyAI enemy)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0182: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b3: 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_011f: 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_013a: Unknown result type (might be due to invalid IL or missing references)
				//IL_013c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0145: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				//IL_0166: Unknown result type (might be due to invalid IL or missing references)
				//IL_016c: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				//IL_026d: Unknown result type (might be due to invalid IL or missing references)
				//IL_026e: Unknown result type (might be due to invalid IL or missing references)
				//IL_024a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0265: Unknown result type (might be due to invalid IL or missing references)
				//IL_0266: Unknown result type (might be due to invalid IL or missing references)
				//IL_026b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
				//IL_020c: Unknown result type (might be due to invalid IL or missing references)
				//IL_020d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0212: Unknown result type (might be due to invalid IL or missing references)
				NavMeshAgent agent = enemy.agent;
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				if (playerPositions.Length != allPlayerScripts.Length)
				{
					Clear();
					playerPositions = new NativeArray<Vector3>(allPlayerScripts.Length, (Allocator)4, (NativeArrayOptions)0);
					if (<pathFlags>P.HasFlag(PathOptions.GroundCast))
					{
						raycastCommands = new NativeArray<RaycastCommand>(allPlayerScripts.Length, (Allocator)4, (NativeArrayOptions)0);
						raycastHits = new NativeArray<RaycastHit>(allPlayerScripts.Length, (Allocator)4, (NativeArrayOptions)0);
					}
				}
				for (int i = 0; i < allPlayerScripts.Length; i++)
				{
					PlayerControllerB val = allPlayerScripts[i];
					if (!enemy.PlayerIsTargetable(val, false, false, true))
					{
						playerPositions[i] = FindPathsToNodesJob.INVALID_DESTINATION;
						if (<pathFlags>P.HasFlag(PathOptions.GroundCast))
						{
							raycastCommands[i] = default(RaycastCommand);
							raycastHits[i] = default(RaycastHit);
						}
						continue;
					}
					Vector3 position = ((Component)val).transform.position;
					playerPositions[i] = position;
					if (<pathFlags>P.HasFlag(PathOptions.GroundCast))
					{
						QueryParameters @default = QueryParameters.Default;
						@default.layerMask = StartOfRound.Instance.collidersAndRoomMaskAndDefault;
						@default.hitTriggers = (QueryTriggerInteraction)1;
						QueryParameters val2 = @default;
						raycastCommands[i] = new RaycastCommand(position, Vector3.down, val2, 5f);
						raycastHits[i] = default(RaycastHit);
					}
				}
				JobHandle val3 = default(JobHandle);
				if (<pathFlags>P.HasFlag(PathOptions.GroundCast))
				{
					val3 = RaycastCommand.ScheduleBatch(raycastCommands, raycastHits, 1, val3);
				}
				if (<pathFlags>P.HasFlag(PathOptions.GroundCast) && <pathFlags>P.HasFlag(PathOptions.RequirePath))
				{
					AssignDestinationsJob.Initialize(raycastHits, playerPositions);
					val3 = IJobForExtensions.ScheduleByRef<AssignGroundCastPointsAsDestinationsJob>(ref AssignDestinationsJob, playerPositions.Length, val3);
				}
				if (<pathFlags>P.HasFlag(PathOptions.RequirePath))
				{
					PathsToPlayersJob.Initialize(agent, playerPositions.Length);
					PathsToPlayersJob.SetDestinations(playerPositions);
					val3 = IJobForExtensions.ScheduleByRef<FindPathsToNodesJob>(ref PathsToPlayersJob, playerPositions.Length, val3);
				}
				JobHandle = val3;
				inFlightJobsTime = Time.time;
			}

			internal bool AllJobsAreDone()
			{
				return ((JobHandle)(ref JobHandle)).IsCompleted;
			}

			internal float UpdatePathsAndGetCalculationTime(EnemyAI enemy)
			{
				//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_006c: 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_007a: Invalid comparison between Unknown and I4
				//IL_00bb: 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)
				if (!AllJobsAreDone())
				{
					return currentJobsTime;
				}
				if (playersPathable.Length != playerPositions.Length)
				{
					Array.Resize(ref playersPathable, playerPositions.Length);
				}
				if (<pathFlags>P.HasFlag(PathOptions.RequirePath))
				{
					for (int i = 0; i < playerPositions.Length; i++)
					{
						PathQueryStatus result = PathQueryStatusExtensions.GetResult(PathsToPlayersJob.Statuses[i]);
						playersPathable[i] = (int)result == 1073741824;
					}
				}
				else
				{
					if (!<pathFlags>P.HasFlag(PathOptions.GroundCast))
					{
						throw new InvalidOperationException("Bad path flags");
					}
					for (int j = 0; j < playerPositions.Length; j++)
					{
						bool[] array = playersPathable;
						int num = j;
						RaycastHit val = raycastHits[j];
						array[num] = ((RaycastHit)(ref val)).colliderInstanceID != 0;
					}
				}
				currentJobsTime = inFlightJobsTime;
				StartJobs(enemy);
				return currentJobsTime;
			}

			internal bool CanReachPlayer(int playerIndex)
			{
				return playersPathable[playerIndex];
			}

			internal void Invalidate()
			{
				currentJobsTime = float.NegativeInfinity;
				inFlightJobsTime = float.NegativeInfinity;
			}

			internal void Clear()
			{
				raycastCommands.Dispose();
				raycastHits.Dispose();
				playerPositions.Dispose();
				playersPathable = Array.Empty<bool>();
			}

			~EnemyToPlayerPathfindingStatus()
			{
				PathsToPlayersJob.FreeAllResources(disposeDestinations: false);
				Clear();
			}
		}

		private const byte PlayerPathFlagsMax = 3;

		private static readonly EnemyMap<EnemyToPlayerPathfindingStatus>[] Statuses = CreateStatusMaps();

		private static EnemyMap<EnemyToPlayerPathfindingStatus>[] CreateStatusMaps()
		{
			EnemyMap<EnemyToPlayerPathfindingStatus>[] array = new EnemyMap<EnemyToPlayerPathfindingStatus>[3];
			for (byte b = 0; b < 3; b++)
			{
				PathOptions flags = (PathOptions)(b + 1);
				array[b] = new EnemyMap<EnemyToPlayerPathfindingStatus>(() => new EnemyToPlayerPathfindingStatus(flags));
			}
			return array;
		}

		internal static void RemoveStatus(EnemyAI enemy)
		{
			for (byte b = 0; b < 3; b++)
			{
				Statuses[b][enemy].Invalidate();
			}
		}

		internal static EnemyToPlayerPathfindingStatus GetStatus(EnemyAI enemy, PathOptions flags)
		{
			return Statuses[(uint)(flags - 1)][enemy];
		}
	}
	internal static class AsyncRoamingPathfinding
	{
		internal class EnemyRoamingPathfindingStatus
		{
			internal FindPathsToNodesJob PathsFromEnemyJob;

			internal JobHandle PathsFromEnemyJobHandle;

			internal FindPathsToNodesJob PathsFromSearchStartJob;

			internal JobHandle PathsFromSearchStartJobHandle;

			private Vector3[] nodePositions = Array.Empty<Vector3>();

			private int nodeCount;

			internal void StartJobs(EnemyAI enemy)
			{
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: 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)
				//IL_00d5: 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_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: 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)
				AISearchRoutine currentSearch = enemy.currentSearch;
				NavMeshAgent agent = enemy.agent;
				List<GameObject> unsearchedNodes = currentSearch.unsearchedNodes;
				nodeCount = unsearchedNodes.Count;
				if (nodeCount > nodePositions.Length)
				{
					nodePositions = (Vector3[])(object)new Vector3[nodeCount];
				}
				for (int i = 0; i < unsearchedNodes.Count; i++)
				{
					nodePositions[GetJobIndex(i)] = unsearchedNodes[i].transform.position;
				}
				PathsFromEnemyJob.Initialize(agent, nodePositions, nodeCount, currentSearch.startedSearchAtSelf);
				PathsFromEnemyJobHandle = IJobForExtensions.ScheduleByRef<FindPathsToNodesJob>(ref PathsFromEnemyJob, unsearchedNodes.Count, default(JobHandle));
				if (!currentSearch.startedSearchAtSelf)
				{
					PathsFromSearchStartJob.Initialize(-1, agent.areaMask, default(Span<float>), currentSearch.currentSearchStartPosition, nodePositions, nodeCount, calculateDistance: true);
					PathsFromSearchStartJobHandle = IJobForExtensions.ScheduleByRef<FindPathsToNodesJob>(ref PathsFromSearchStartJob, unsearchedNodes.Count, default(JobHandle));
				}
			}

			internal int GetJobIndex(int index)
			{
				return nodeCount - 1 - index;
			}

			~EnemyRoamingPathfindingStatus()
			{
				PathsFromEnemyJob.FreeAllResources();
				PathsFromSearchStartJob.FreeAllResources();
			}
		}

		private static readonly EnemyMap<EnemyRoamingPathfindingStatus> Statuses = new EnemyMap<EnemyRoamingPathfindingStatus>(() => new EnemyRoamingPathfindingStatus());

		internal static void RemoveStatus(EnemyAI enemy)
		{
			Statuses.Remove(enemy);
		}

		internal static EnemyRoamingPathfindingStatus GetStatus(EnemyAI enemy)
		{
			return Statuses[enemy];
		}
	}
	public class EnemyMap<T>
	{
		private readonly Func<T> constructor;

		private Dictionary<int, T> backingDictionary;

		public T this[EnemyAI enemy] => GetItem(enemy);

		public int Count => backingDictionary.Count;

		public EnemyMap(Func<T> elementConstructor)
		{
			constructor = elementConstructor;
			backingDictionary = new Dictionary<int, T>();
			base..ctor();
		}

		public T GetItem(EnemyAI enemy)
		{
			int instanceID = ((Object)enemy).GetInstanceID();
			if (backingDictionary.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			value = constructor();
			backingDictionary[instanceID] = value;
			return value;
		}

		public void Clear()
		{
			backingDictionary = new Dictionary<int, T>();
		}

		public bool Remove(EnemyAI enemy)
		{
			return backingDictionary.Remove(((Object)enemy).GetInstanceID());
		}

		public bool Contains(EnemyAI enemy)
		{
			return backingDictionary.ContainsKey(((Object)enemy).GetInstanceID());
		}
	}
	internal struct FindPathsToNodesJob : IJobFor
	{
		public static readonly Vector3 INVALID_DESTINATION = new Vector3(float.NaN, float.NaN, float.NaN);

		[NativeDisableContainerSafetyRestriction]
		private static NativeArray<NavMeshQuery> StaticThreadQueries;

		private const float MAX_ENDPOINT_DISTANCE = 1.55f;

		private const float MAX_ENDPOINT_DISTANCE_SQR = 2.4025f;

		[ReadOnly]
		[NativeSetThreadIndex]
		internal int ThreadIndex;

		[ReadOnly]
		[NativeDisableContainerSafetyRestriction]
		[NativeDisableParallelForRestriction]
		internal NativeArray<NavMeshQuery> ThreadQueriesRef;

		[ReadOnly]
		private int AgentTypeID;

		[ReadOnly]
		private int AreaMask;

		[ReadOnly]
		private NativeArray<float> Costs;

		[ReadOnly]
		private Vector3 QueryExtents;

		[ReadOnly]
		private Vector3 Origin;

		[ReadOnly]
		[NativeDisableContainerSafetyRestriction]
		private NativeArray<Vector3> Destinations;

		[ReadOnly]
		private bool CalculateDistance;

		[ReadOnly]
		[NativeDisableContainerSafetyRestriction]
		private NativeArray<bool> Canceled;

		[WriteOnly]
		[NativeDisableContainerSafetyRestriction]
		internal NativeArray<PathQueryStatus> Statuses;

		[WriteOnly]
		[NativeDisableContainerSafetyRestriction]
		[NativeDisableParallelForRestriction]
		internal NativeArray<Vector3> Paths;

		[WriteOnly]
		[NativeDisableContainerSafetyRestriction]
		internal NativeArray<int> PathSizes;

		[WriteOnly]
		[NativeDisableContainerSafetyRestriction]
		internal NativeArray<float> PathDistances;

		public unsafe void Initialize(int agentTypeID, int areaMask, Span<float> costs, Vector3 origin, Vector3[] candidates, int count, bool calculateDistance = false)
		{
			//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_0048: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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)
			ThreadQueriesRef = Unsafe.Read<NativeArray<NavMeshQuery>>((void*)PathfindingJobSharedResources.GetPerThreadQueriesArray());
			CreateFixedArrays();
			AgentTypeID = agentTypeID;
			AreaMask = areaMask;
			if (costs == default(Span<float>))
			{
				Costs.SetAllElements(1f);
			}
			else
			{
				Costs.CopyFrom(costs);
			}
			QueryExtents = NavMeshQueryUtils.GetQueryExtents(agentTypeID);
			Origin = origin;
			CalculateDistance = calculateDistance;
			EnsureCount(count);
			Statuses.SetAllElements<PathQueryStatus>((PathQueryStatus)536870912);
			if (calculateDistance)
			{
				PathDistances.SetAllElements(0f);
			}
			Canceled[0] = false;
			if (candidates != null)
			{
				if (Destinations.IsCreated)
				{
					Destinations.Dispose();
				}
				if (count > 0)
				{
					Destinations = new NativeArray<Vector3>(count, (Allocator)4, (NativeArrayOptions)1);
					NativeArray<Vector3>.Copy(candidates, Destinations, count);
				}
			}
		}

		public void Initialize(NavMeshAgent agent, Vector3[] candidates, int count, bool calculateDistance = false)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			int agentTypeID = default(int);
			int areaMask = default(int);
			Span<float> costs = default(Span<float>);
			AgentExtensions.GetQueryFilter(agent, ref agentTypeID, ref areaMask, ref costs);
			Initialize(agentTypeID, areaMask, costs, AgentExtensions.GetPathOrigin(agent), candidates, count, calculateDistance);
		}

		public void Initialize(NavMeshAgent agent, int count, bool calculateDistance = false)
		{
			Initialize(agent, null, count, calculateDistance);
		}

		public void Initialize(int agentTypeID, int areaMask, Span<float> costs, Vector3 origin, Vector3[] candidates, bool calculateDistance = false)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			Initialize(agentTypeID, areaMask, costs, origin, candidates, candidates.Length, calculateDistance);
		}

		public void Initialize(NavMeshAgent agent, Vector3[] candidates, bool calculateDistance = false)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			int agentTypeID = default(int);
			int areaMask = default(int);
			Span<float> costs = default(Span<float>);
			AgentExtensions.GetQueryFilter(agent, ref agentTypeID, ref areaMask, ref costs);
			Initialize(agentTypeID, areaMask, costs, AgentExtensions.GetPathOrigin(agent), candidates, calculateDistance);
		}

		public void Initialize(int agentTypeID, int areaMask, Span<float> costs, Vector3 origin, List<Vector3> candidates, bool calculateDistance = false)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			Initialize(agentTypeID, areaMask, costs, origin, NoAllocHelpers.ExtractArrayFromListT<Vector3>(candidates), candidates.Count, calculateDistance);
		}

		public void Initialize(NavMeshAgent agent, List<Vector3> candidates, bool calculateDistance = false)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			int agentTypeID = default(int);
			int areaMask = default(int);
			Span<float> costs = default(Span<float>);
			AgentExtensions.GetQueryFilter(agent, ref agentTypeID, ref areaMask, ref costs);
			Initialize(agentTypeID, areaMask, costs, AgentExtensions.GetPathOrigin(agent), candidates, calculateDistance);
		}

		public void SetDestinations(NativeArray<Vector3> destinations)
		{
			//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)
			Destinations = destinations;
		}

		private void CreateFixedArrays()
		{
			//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_0022: 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)
			if (Canceled.Length != 1)
			{
				Costs = new NativeArray<float>(32, (Allocator)4, (NativeArrayOptions)1);
				Canceled = new NativeArray<bool>(1, (Allocator)4, (NativeArrayOptions)1);
			}
		}

		private void DisposeFixedArrays()
		{
			Canceled.Dispose();
		}

		private void EnsureCount(int count)
		{
			//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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (Statuses.Length < count)
			{
				DisposeResizeableArrays();
				if (count != 0)
				{
					Statuses = new NativeArray<PathQueryStatus>(count, (Allocator)4, (NativeArrayOptions)1);
					Paths = new NativeArray<Vector3>(count * 128, (Allocator)4, (NativeArrayOptions)1);
					PathSizes = new NativeArray<int>(count, (Allocator)4, (NativeArrayOptions)1);
					PathDistances = new NativeArray<float>(count, (Allocator)4, (NativeArrayOptions)1);
				}
			}
		}

		private void DisposeResizeableArrays()
		{
			if (Statuses.IsCreated)
			{
				Statuses.Dispose();
				Paths.Dispose();
				PathSizes.Dispose();
				PathDistances.Dispose();
			}
		}

		public void Cancel()
		{
			if (Canceled.IsCreated)
			{
				Canceled[0] = true;
			}
		}

		public NativeArray<Vector3> GetPathBuffer(int index)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return Paths.GetSubArray(index * 128, 128);
		}

		public NativeArray<Vector3> GetPath(int index)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			return Paths.GetSubArray(index * 128, PathSizes[index]);
		}

		public void Execute(int index)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0069: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_00ae: 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_00c4: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Invalid comparison between Unknown and I4
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Invalid comparison between Unknown and I4
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Invalid comparison between Unknown and I4
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: 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_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Invalid comparison between Unknown and I4
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			if (Canceled[0])
			{
				Statuses[index] = (PathQueryStatus)int.MinValue;
				return;
			}
			NavMeshReadLocker val = default(NavMeshReadLocker);
			((NavMeshReadLocker)(ref val))..ctor();
			try
			{
				Vector3 val2 = Destinations[index];
				if (((Vector3)(ref val2)).Equals(INVALID_DESTINATION))
				{
					Statuses[index] = (PathQueryStatus)int.MinValue;
					return;
				}
				NavMeshQuery val3 = ThreadQueriesRef[ThreadIndex];
				NavMeshLocation val4 = ((NavMeshQuery)(ref val3)).MapLocation(Origin, QueryExtents, AgentTypeID, AreaMask);
				if (!((NavMeshQuery)(ref val3)).IsValid(val4))
				{
					Statuses[index] = (PathQueryStatus)int.MinValue;
					return;
				}
				NavMeshLocation val5 = ((NavMeshQuery)(ref val3)).MapLocation(val2, QueryExtents, AgentTypeID, AreaMask);
				if (!((NavMeshQuery)(ref val3)).IsValid(val5))
				{
					Statuses[index] = (PathQueryStatus)int.MinValue;
					return;
				}
				PathQueryStatus val6 = ((NavMeshQuery)(ref val3)).BeginFindPath(val4, val5, AreaMask, Costs);
				if ((int)PathQueryStatusExtensions.GetResult(val6) == int.MinValue)
				{
					Statuses[index] = val6;
					return;
				}
				int num = default(int);
				while ((int)PathQueryStatusExtensions.GetResult(val6) == 536870912)
				{
					val6 = ((NavMeshQuery)(ref val3)).UpdateFindPath(NavMeshLock.RecommendedUpdateFindPathIterationCount, ref num);
					((NavMeshReadLocker)(ref val)).Yield();
				}
				int num2 = default(int);
				val6 = ((NavMeshQuery)(ref val3)).EndFindPath(ref num2);
				if ((int)PathQueryStatusExtensions.GetResult(val6) != 1073741824)
				{
					Statuses[index] = val6;
					return;
				}
				NativeArray<PolygonId> val7 = new NativeArray<PolygonId>(num2, (Allocator)2, (NativeArrayOptions)1);
				((NavMeshQuery)(ref val3)).GetPathResult(NativeSlice<PolygonId>.op_Implicit(val7));
				NavMeshQuery val8 = val3;
				ref Vector3 origin = ref Origin;
				NativeSlice<PolygonId> val9 = NativeSlice<PolygonId>.op_Implicit(val7);
				int num3 = num2;
				NativeArray<Vector3> pathBuffer = GetPathBuffer(index);
				int num4 = default(int);
				val6 = (PathQueryStatus)(NavMeshQueryUtils.FindStraightPath(val8, ref origin, ref val2, ref val9, num3, ref pathBuffer, ref num4) | PathQueryStatusExtensions.GetDetail(val6));
				((NavMeshReadLocker)(ref val)).Dispose();
				PathSizes[index] = num4;
				val7.Dispose();
				if ((int)PathQueryStatusExtensions.GetResult(val6) != 1073741824)
				{
					Statuses[index] = val6;
					return;
				}
				NativeArray<Vector3> path = GetPath(index);
				Vector3 val10 = path[path.Length - 1] - val2;
				if (((Vector3)(ref val10)).sqrMagnitude > 2.4025f)
				{
					Statuses[index] = (PathQueryStatus)(int.MinValue | PathQueryStatusExtensions.GetDetail(val6));
					return;
				}
				if (CalculateDistance)
				{
					float num5 = 0f;
					for (int i = 1; i < path.Length; i++)
					{
						num5 += Vector3.Distance(path[i - 1], path[i]);
					}
					PathDistances[index] = num5;
				}
				Statuses[index] = val6;
			}
			finally
			{
				((IDisposable)(NavMeshReadLocker)(ref val)).Dispose();
			}
		}

		internal void FreeAllResources(bool disposeDestinations = true)
		{
			DisposeResizeableArrays();
			DisposeFixedArrays();
			if (disposeDestinations)
			{
				Destinations.Dispose();
			}
		}
	}
	internal static class LineOfSight
	{
		private const int LINE_OF_SIGHT_LAYER_MASK = 262144;

		public static bool PathIsBlockedByLineOfSight(NativeArray<Vector3> path, out float pathDistance, Vector3? checkLOSToPosition = null)
		{
			//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)
			//IL_0033: 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_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_0045: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			pathDistance = 0f;
			if (path.Length == 0)
			{
				return true;
			}
			if (path.Length == 1)
			{
				return false;
			}
			Vector3 val = path[0];
			for (int i = 1; i < path.Length && i < 16; i++)
			{
				Vector3 val2 = path[i - 1];
				Vector3 val3 = path[i];
				pathDistance += Vector3.Distance(val2, val3);
				if (i <= 5 || !(Vector3.Distance(val, val3) < 1.7f))
				{
					val = val3;
					if (checkLOSToPosition.HasValue && !Physics.Linecast(val2, checkLOSToPosition.Value + Vector3.up * 0.3f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
					{
						return true;
					}
					if (Physics.Linecast(val2, val3, 262144))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool PathIsBlockedByLineOfSight(NativeArray<Vector3> path, Vector3? checkLOSToPosition = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			float pathDistance;
			return PathIsBlockedByLineOfSight(path, out pathDistance, checkLOSToPosition);
		}
	}
	internal static class NativeArrayUtils
	{
		internal unsafe static void SetAllElements<T>(this NativeArray<T> array, T value) where T : unmanaged
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			T* buffer = (T*)array.m_Buffer;
			int length = array.Length;
			for (int i = 0; i < length; i++)
			{
				buffer[i] = value;
			}
		}

		internal unsafe static void CopyFrom<T>(this NativeArray<T> array, Span<T> span) where T : struct
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (array.Length < span.Length)
			{
				throw new InvalidOperationException($"NativeArray size {array.Length} is smaller than span size {span.Length}.");
			}
			UnsafeUtility.MemCpy(NativeArrayUnsafeUtility.GetUnsafePtr<T>(array), UnsafeUtility.AddressOf<T>(ref span[0]), (long)span.Length);
		}
	}
	[IgnoredByDeepProfiler]
	[UsedByNativeCode]
	internal struct ProfilerMarkerWithMetadata<T> where T : unmanaged
	{
		[IgnoredByDeepProfiler]
		[UsedByNativeCode]
		public struct AutoScope : IDisposable
		{
			[NativeDisableUnsafePtrRestriction]
			internal readonly ProfilerMarkerWithMetadata<T> marker;

			internal T value;

			internal bool on;

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			public AutoScope(in ProfilerMarkerWithMetadata<T> marker, T value)
			{
				on = false;
				this.marker = marker;
				this.value = value;
				Resume();
			}

			public void Resume()
			{
				if (!on)
				{
					on = true;
					marker.Begin(in value);
				}
			}

			public void Pause()
			{
				if (on)
				{
					marker.End();
					on = false;
				}
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			public void Dispose()
			{
				Pause();
			}
		}

		private readonly IntPtr ptr;

		private ProfilerMarkerData data;

		public ProfilerMarkerWithMetadata(string name, string metadata)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			data = default(ProfilerMarkerData);
			ptr = ProfilerUnsafeUtility.CreateMarker(name, (ushort)1, (MarkerFlags)0, 0);
			if (typeof(T) == typeof(int))
			{
				data.Type = 2;
			}
			else if (typeof(T) == typeof(long))
			{
				data.Type = 4;
			}
			else if (typeof(T) == typeof(uint))
			{
				data.Type = 3;
			}
			else if (typeof(T) == typeof(ulong))
			{
				data.Type = 5;
			}
			else if (typeof(T) == typeof(float))
			{
				data.Type = 6;
			}
			else if (typeof(T) == typeof(double))
			{
				data.Type = 7;
			}
			data.Size = (uint)UnsafeUtility.SizeOf<T>();
			if (ptr != IntPtr.Zero)
			{
				ProfilerUnsafeUtility.SetMarkerMetadata(ptr, 0, metadata, data.Type, (byte)3);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe void Begin(in T value)
		{
			fixed (ProfilerMarkerData* ptr = &data)
			{
				void* ptr2 = ptr;
				fixed (T* ptr3 = &value)
				{
					void* ptr4 = ptr3;
					data.Ptr = ptr4;
					ProfilerUnsafeUtility.BeginSampleWithMetadata(this.ptr, 1, ptr2);
				}
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void End()
		{
			ProfilerUnsafeUtility.EndSample(ptr);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public AutoScope Auto(T value)
		{
			return new AutoScope(in this, value);
		}
	}
}
namespace PathfindingLagFix.Utilities.IL
{
	internal class ILInjector
	{
		[CompilerGenerated]
		private sealed class <GetRelativeInstructions>d__34 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			public ILInjector <>4__this;

			private int offset;

			public int <>3__offset;

			private int size;

			public int <>3__size;

			private int <i>5__2;

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

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

			[DebuggerHidden]
			public <GetRelativeInstructions>d__34(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				int num = <>1__state;
				ILInjector iLInjector = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<i>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__2++;
					break;
				}
				if (<i>5__2 < size)
				{
					<>2__current = iLInjector.instructions[iLInjector.index + offset + <i>5__2];
					<>1__state = 1;
					return true;
				}
				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();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<GetRelativeInstructions>d__34 <GetRelativeInstructions>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetRelativeInstructions>d__ = this;
				}
				else
				{
					<GetRelativeInstructions>d__ = new <GetRelativeInstructions>d__34(0)
					{
						<>4__this = <>4__this
					};
				}
				<GetRelativeInstructions>d__.offset = <>3__offset;
				<GetRelativeInstructions>d__.size = <>3__size;
				return <GetRelativeInstructions>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private const string INVALID = "Injector is invalid";

		private List<CodeInstruction> instructions = instructions.ToList();

		private ILGenerator generator;

		private int index;

		private int matchEnd;

		public int Index
		{
			get
			{
				return index;
			}
			set
			{
				index = value;
			}
		}

		public bool IsValid
		{
			get
			{
				if (instructions != null)
				{
					return IsIndexValid(index);
				}
				return false;
			}
		}

		public CodeInstruction Instruction
		{
			get
			{
				if (!IsIndexInRange(index))
				{
					return null;
				}
				return instructions[index];
			}
			set
			{
				if (!IsIndexInRange(index))
				{
					throw new InvalidOperationException($"Current index {index} is out of range of instruction count {instructions.Count}");
				}
				instructions[index] = value;
			}
		}

		public CodeInstruction LastMatchedInstruction
		{
			get
			{
				int num = matchEnd - 1;
				if (!IsIndexInRange(num))
				{
					return null;
				}
				return instructions[num];
			}
			set
			{
				int num = matchEnd - 1;
				if (!IsIndexInRange(num))
				{
					throw new InvalidOperationException($"Last matched index {index} is out of range of instruction count {instructions.Count}");
				}
				instructions[num] = value;
			}
		}

		public ICollection<CodeInstruction> Instructions => instructions.AsReadOnly();

		public ILInjector(IEnumerable<CodeInstruction> instructions, ILGenerator generator = null)
		{
			this.generator = generator;
			matchEnd = -1;
			base..ctor();
		}

		public ILInjector GoToStart()
		{
			matchEnd = index;
			index = 0;
			return this;
		}

		public ILInjector GoToEnd()
		{
			matchEnd = index;
			index = instructions.Count;
			return this;
		}

		public ILInjector Forward(int offset)
		{
			if (!IsValid)
			{
				return this;
			}
			matchEnd = index;
			index = Math.Clamp(index + offset, -1, instructions.Count);
			return this;
		}

		public ILInjector Back(int offset)
		{
			return Forward(-offset);
		}

		private void MarkInvalid()
		{
			index = -1;
			matchEnd = -1;
		}

		private void Search(bool forward, ILMatcher[] predicates)
		{
			if (!IsValid)
			{
				return;
			}
			int num = 1;
			if (!forward)
			{
				num = -1;
				index--;
			}
			while (forward ? (index < instructions.Count) : (index >= 0))
			{
				if (forward && index + predicates.Length > instructions.Count)
				{
					index = instructions.Count;
					break;
				}
				int i;
				for (i = 0; i < predicates.Length && predicates[i].Matches(instructions[index + i]); i++)
				{
				}
				if (i == predicates.Length)
				{
					matchEnd = index + i;
					return;
				}
				index += num;
			}
			MarkInvalid();
		}

		public ILInjector Find(params ILMatcher[] predicates)
		{
			Search(forward: true, predicates);
			return this;
		}

		public ILInjector ReverseFind(params ILMatcher[] predicates)
		{
			Search(forward: false, predicates);
			return this;
		}

		public ILInjector GoToPush(int popIndex)
		{
			if (!IsValid)
			{
				return this;
			}
			matchEnd = index;
			index--;
			int num = 0;
			while (index >= 0)
			{
				CodeInstruction instruction = instructions[index];
				num += instruction.PushCount();
				num -= instruction.PopCount();
				if (num >= popIndex)
				{
					return this;
				}
				index--;
			}
			return this;
		}

		public ILInjector SkipBranch()
		{
			if (Instruction == null)
			{
				return this;
			}
			if (!(Instruction.operand is Label label))
			{
				throw new InvalidOperationException($"Current instruction is not a branch: {Instruction}");
			}
			return FindLabel(label);
		}

		public ILInjector FindLabel(Label label)
		{
			if (label == default(Label))
			{
				return this;
			}
			matchEnd = index;
			for (index = 0; index < instructions.Count; index++)
			{
				if (instructions[index].labels.Contains(label))
				{
					return this;
				}
			}
			MarkInvalid();
			return this;
		}

		public ILInjector GoToMatchEnd()
		{
			index = matchEnd;
			return this;
		}

		public ILInjector GoToLastMatchedInstruction()
		{
			if (!IsIndexValid(matchEnd))
			{
				return this;
			}
			index = matchEnd - 1;
			return this;
		}

		private bool IsIndexValid(int index)
		{
			return index != -1;
		}

		private bool IsIndexInRange(int index)
		{
			if (index >= 0)
			{
				return index < instructions.Count;
			}
			return false;
		}

		public CodeInstruction GetRelativeInstruction(int offset)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			int num = index + offset;
			if (!IsIndexInRange(num))
			{
				throw new IndexOutOfRangeException($"Offset {offset} would read out of bounds at index {num}");
			}
			return instructions[num];
		}

		public ILInjector SetRelativeInstruction(int offset, CodeInstruction instruction)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			int num = index + offset;
			if (!IsIndexInRange(num))
			{
				throw new IndexOutOfRangeException($"Offset {offset} would write out of bounds at index {num}");
			}
			instructions[num] = instruction;
			return this;
		}

		[IteratorStateMachine(typeof(<GetRelativeInstructions>d__34))]
		public IEnumerable<CodeInstruction> GetRelativeInstructions(int offset, int size)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetRelativeInstructions>d__34(-2)
			{
				<>4__this = this,
				<>3__offset = offset,
				<>3__size = size
			};
		}

		public IEnumerable<CodeInstruction> GetRelativeInstructions(int size)
		{
			return GetRelativeInstructions(0, size);
		}

		private void GetLastMatchRangeAbsolute(out int start, out int end)
		{
			start = index;
			end = matchEnd;
			if (start > end)
			{
				int num = end;
				int num2 = start;
				start = num;
				end = num2;
			}
		}

		private void GetLastMatchRange(out int start, out int size)
		{
			GetLastMatchRangeAbsolute(out start, out var end);
			if (start < 0 || start >= instructions.Count)
			{
				throw new InvalidOperationException($"Last match range starts at invalid index {start}");
			}
			if (end < 0 || end > instructions.Count)
			{
				throw new InvalidOperationException($"Last match range ends at invalid index {end}");
			}
			size = end - start;
		}

		public List<CodeInstruction> GetLastMatch()
		{
			GetLastMatchRange(out var start, out var size);
			return instructions.GetRange(start, size);
		}

		public ILInjector DefineLabel(out Label label)
		{
			if (generator == null)
			{
				throw new InvalidOperationException("No ILGenerator was provided");
			}
			label = generator.DefineLabel();
			return this;
		}

		public ILInjector AddLabel(out Label label)
		{
			DefineLabel(out label);
			return AddLabel(label);
		}

		public ILInjector AddLabel(Label label)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Instruction = new CodeInstruction(Instruction);
			Instruction.labels.Add(label);
			return this;
		}

		public ILInjector InsertInPlace(params CodeInstruction[] instructions)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			this.instructions.InsertRange(index, instructions);
			if (matchEnd >= index)
			{
				matchEnd += instructions.Length;
			}
			return this;
		}

		public ILInjector Insert(params CodeInstruction[] instructions)
		{
			InsertInPlace(instructions);
			index += instructions.Length;
			return this;
		}

		public ILInjector InsertInPlaceAfterBranch(params CodeInstruction[] instructions)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			List<Label> labels = Instruction.labels;
			Instruction = new CodeInstruction(Instruction);
			Instruction.labels.Clear();
			this.instructions.InsertRange(index, instructions);
			Instruction.labels.AddRange(labels);
			if (matchEnd >= index)
			{
				matchEnd += instructions.Length;
			}
			return this;
		}

		public ILInjector InsertAfterBranch(params CodeInstruction[] instructions)
		{
			InsertInPlaceAfterBranch(instructions);
			index += instructions.Length;
			return this;
		}

		public ILInjector RemoveAllPreviousInstructions()
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			instructions.RemoveRange(0, index);
			matchEnd -= index;
			if (matchEnd < 0)
			{
				matchEnd = 0;
			}
			index = 0;
			return this;
		}

		public ILInjector Remove(int count = 1)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			instructions.RemoveRange(index, count);
			if (matchEnd > index)
			{
				matchEnd = Math.Max(index, matchEnd - count);
			}
			return this;
		}

		public ILInjector RemoveLastMatch()
		{
			GetLastMatchRange(out var start, out var size);
			List<Label> labels = instructions[start].labels;
			instructions.RemoveRange(start, size);
			index = start;
			matchEnd = start;
			instructions[start].labels.AddRange(labels);
			return this;
		}

		public ILInjector ReplaceLastMatch(params CodeInstruction[] replacementInstructions)
		{
			if (replacementInstructions.Length == 0)
			{
				throw new ArgumentException("Cannot replace a match with an empty array.");
			}
			GetLastMatchRange(out var start, out var size);
			List<Label> labels = instructions[start].labels;
			instructions.RemoveRange(start, size);
			instructions.InsertRange(start, replacementInstructions);
			index = start;
			matchEnd = start + replacementInstructions.Length;
			instructions[start].labels.AddRange(labels);
			return this;
		}

		public List<CodeInstruction> ReleaseInstructions()
		{
			List<CodeInstruction> result = instructions;
			instructions = null;
			return result;
		}

		public ILInjector PrintContext(int context, string header = "")
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid (" + header + ")");
			}
			StringBuilder stringBuilder = new StringBuilder(header);
			if (header.Length > 0)
			{
				stringBuilder.Append(':');
			}
			stringBuilder.AppendLine();
			GetLastMatchRangeAbsolute(out var start, out var end);
			int num = Math.Min(end + 1 + context, instructions.Count);
			for (int i = Math.Max(start - context, 0); i < num; i++)
			{
				if (end == -1 && i == index)
				{
					stringBuilder.Append("╶> ");
				}
				else
				{
					if (i >= start && i < end)
					{
						stringBuilder.Append("│");
					}
					else
					{
						stringBuilder.Append(" ");
					}
					if (i == index)
					{
						stringBuilder.Append("╶> ");
					}
					else
					{
						stringBuilder.Append("   ");
					}
				}
				stringBuilder.AppendLine($"{i}: {instructions[i]}");
			}
			Plugin.Instance.Logger.LogInfo((object)stringBuilder);
			return this;
		}

		public ILInjector PrintContext(string header = "")
		{
			return PrintContext(4, header);
		}
	}
	internal interface ILMatcher
	{
		bool Matches(CodeInstruction instruction);

		ILMatcher CaptureAs(out CodeInstruction variable)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			variable = new CodeInstruction(OpCodes.Nop, (object)null);
			return new InstructionCapturingMatcher(this, variable);
		}

		unsafe ILMatcher CaptureOperandAs<T>(out T operand) where T : unmanaged
		{
			operand = default(T);
			fixed (T* operand2 = &operand)
			{
				return new OperandCapturingMatcher<T>(this, operand2);
			}
		}

		ILMatcher Debug()
		{
			return new DebuggingMatcher(this);
		}

		static ILMatcher StackDelta(int pushes, int pops)
		{
			return new StackDeltaMatcher(pushes, pops);
		}

		static ILMatcher Push(int pushes)
		{
			return StackDelta(pushes, 0);
		}

		static ILMatcher Pop(int pops)
		{
			return StackDelta(0, pops);
		}

		static ILMatcher Not(ILMatcher matcher)
		{
			return new NotMatcher(matcher);
		}

		static ILMatcher Opcode(OpCode opcode)
		{
			return new OpcodeMatcher(opcode);
		}

		static ILMatcher Opcodes(params OpCode[] opcodes)
		{
			return new OpcodesMatcher(opcodes);
		}

		static ILMatcher OpcodeOperand(OpCode opcode, object operand)
		{
			return new OpcodeOperandMatcher(opcode, operand);
		}

		static ILMatcher Instruction(CodeInstruction instruction)
		{
			return new InstructionMatcher(instruction);
		}

		static ILMatcher Ldarg(int? arg = null)
		{
			return new LdargMatcher(arg);
		}

		static ILMatcher Ldloc(int? loc = null)
		{
			return new LdlocMatcher(loc);
		}

		static ILMatcher Stloc(int? loc = null)
		{
			return new StlocMatcher(loc);
		}

		static ILMatcher Ldc(int? value = null)
		{
			return new LdcI32Matcher(value);
		}

		static ILMatcher LdcF32(float? value = null)
		{
			return new LdcF32Matcher(value);
		}

		unsafe static ILMatcher LdlocCapture(out int localIndex)
		{
			localIndex = -1;
			fixed (int* localIndex2 = &localIndex)
			{
				return new LdlocCapturingMatcher(localIndex2);
			}
		}

		unsafe static ILMatcher LdlocFrom(in int localIndex)
		{
			fixed (int* localIndexPtr = &localIndex)
			{
				return new LdlocByRefMatcher(localIndexPtr);
			}
		}

		unsafe static ILMatcher StlocCapture(out int localIndex)
		{
			localIndex = -1;
			fixed (int* localIndex2 = &localIndex)
			{
				return new StlocCapturingMatcher(localIndex2);
			}
		}

		unsafe static ILMatcher StlocFrom(in int localIndex)
		{
			fixed (int* localIndexPtr = &localIndex)
			{
				return new StlocByRefMatcher(localIndexPtr);
			}
		}

		static ILMatcher Branch()
		{
			return new BranchMatcher();
		}

		static ILMatcher Ldfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldfld() was null at {sourceFilePath}:{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Ldfld, field);
		}

		static ILMatcher Ldsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldsfld() was null at {sourceFilePath}:{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Ldsfld, field);
		}

		static ILMatcher Stfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stfld() was null at {sourceFilePath}:{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Stfld, field);
		}

		static ILMatcher Stsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stsfld() was null at {sourceFilePath}:{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Stsfld, field);
		}

		static ILMatcher Callvirt(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (method == null)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Callvirt() was null at {sourceFilePath}:{sourceLineNumber} ({callerName})");
			}
			return OpcodeOperand(OpCodes.Callvirt, method);
		}

		static ILMatcher Call(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (method == null)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Call() was null at {sourceFilePath}:{sourceLineNumber} ({callerName})");
			}
			return OpcodeOperand(OpCodes.Call, method);
		}

		static ILMatcher Newobj(ConstructorInfo ctor, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (ctor == null)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Constructor passed to ILMatcher.Newobj() was null at {sourceFilePath}:{sourceLineNumber} ({callerName})");
			}
			return OpcodeOperand(OpCodes.Newobj, ctor);
		}

		static ILMatcher Predicate(Func<CodeInstruction, bool> predicate)
		{
			return new PredicateMatcher(predicate);
		}

		static ILMatcher Predicate(Func<FieldInfo, bool> predicate)
		{
			return new PredicateMatcher((CodeInstruction insn) => insn.operand is FieldInfo arg && predicate(arg));
		}
	}
	internal class StackDeltaMatcher : ILMatcher
	{
		private readonly int pushes;

		private readonly int pops;

		public StackDeltaMatcher(int pushes, int pops)
		{
			this.pushes = pushes;
			this.pops = pops;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (instruction.PushCount() == pushes)
			{
				return instruction.PopCount() == pops;
			}
			return false;
		}
	}
	internal class NotMatcher : ILMatcher
	{
		private readonly ILMatcher matcher;

		public NotMatcher(ILMatcher matcher)
		{
			this.matcher = matcher;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return !matcher.Matches(instruction);
		}
	}
	internal class OpcodeMatcher : ILMatcher
	{
		private readonly OpCode opcode;

		public OpcodeMatcher(OpCode opcode)
		{
			this.opcode = opcode;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return instruction.opcode == opcode;
		}
	}
	internal class OpcodesMatcher : ILMatcher
	{
		private readonly OpCode[] opcodes;

		public OpcodesMatcher(OpCode[] opcodes)
		{
			this.opcodes = opcodes;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return opcodes.Contains(instruction.opcode);
		}
	}
	internal class OpcodeOperandMatcher : ILMatcher
	{
		private readonly OpCode opcode;

		private readonly object operand;

		public OpcodeOperandMatcher(OpCode opcode, object operand)
		{
			this.opcode = opcode;
			this.operand = operand;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (instruction.opcode == opcode)
			{
				return instruction.operand == operand;
			}
			return false;
		}
	}
	internal class InstructionMatcher : ILMatcher
	{
		private readonly OpCode opcode = instruction.opcode;

		private readonly object operand = instruction.operand;

		private readonly Label[] labels = instruction.labels.ToArray();

		public InstructionMatcher(CodeInstruction instruction)
		{
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (instruction.opcode != opcode)
			{
				return false;
			}
			if (instruction.operand != operand)
			{
				return false;
			}
			if (instruction.labels.Count != labels.Length)
			{
				return false;
			}
			for (int i = 0; i < labels.Length; i++)
			{
				if (labels[i] != instruction.labels[i])
				{
					return false;
				}
			}
			return true;
		}
	}
	internal class LdargMatcher : ILMatcher
	{
		private readonly int? arg;

		public LdargMatcher(int? arg)
		{
			this.arg = arg;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!arg.HasValue)
			{
				return instruction.GetLdargIndex().HasValue;
			}
			return instruction.GetLdargIndex() == arg;
		}
	}
	internal class LdlocMatcher : ILMatcher
	{
		private readonly int? loc;

		public LdlocMatcher(int? loc)
		{
			this.loc = loc;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!loc.HasValue)
			{
				return instruction.GetLdlocIndex().HasValue;
			}
			return instruction.GetLdlocIndex() == loc;
		}
	}
	internal class StlocMatcher : ILMatcher
	{
		private readonly int? loc;

		public StlocMatcher(int? loc)
		{
			this.loc = loc;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!loc.HasValue)
			{
				return instruction.GetStlocIndex().HasValue;
			}
			return instruction.GetStlocIndex() == loc;
		}
	}
	internal class LdcI32Matcher : ILMatcher
	{
		private readonly int? value;

		public LdcI32Matcher(int? value)
		{
			this.value = value;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!value.HasValue)
			{
				return instruction.GetLdcI32().HasValue;
			}
			return instruction.GetLdcI32() == value;
		}
	}
	internal class LdcF32Matcher : ILMatcher
	{
		private readonly float? value;

		public LdcF32Matcher(float? value)
		{
			this.value = value;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Ldc_R4)
			{
				if (value.HasValue)
				{
					return (float)instruction.operand == value.Value;
				}
				return true;
			}
			return false;
		}
	}
	internal class BranchMatcher : ILMatcher
	{
		public bool Matches(CodeInstruction instruction)
		{
			Label? label = default(Label?);
			return CodeInstructionExtensions.Branches(instruction, ref label);
		}
	}
	internal class PredicateMatcher : ILMatcher
	{
		private readonly Func<CodeInstruction, bool> predicate;

		public PredicateMatcher(Func<CodeInstruction, bool> predicate)
		{
			this.predicate = predicate;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return predicate(instruction);
		}
	}
	internal class InstructionCapturingMatcher : ILMatcher
	{
		private readonly ILMatcher matcher;

		private readonly CodeInstruction variable;

		public InstructionCapturingMatcher(ILMatcher matcher, CodeInstruction variable)
		{
			this.matcher = matcher;
			this.variable = variable;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			bool num = matcher.Matches(instruction);
			if (num)
			{
				variable.opcode = instruction.opcode;
				variable.operand = instruction.operand;
				variable.blocks = instruction.blocks.ToList();
				variable.labels = instruction.labels.ToList();
			}
			return num;
		}
	}
	internal class OperandCapturingMatcher<T> : ILMatcher where T : unmanaged
	{
		private readonly ILMatcher matcher;

		private unsafe readonly T* operand;

		public unsafe OperandCapturingMatcher(ILMatcher matcher, T* operand)
		{
			this.matcher = matcher;
			this.operand = operand;
			base..ctor();
		}

		public unsafe bool Matches(CodeInstruction instruction)
		{
			bool num = matcher.Matches(instruction);
			if (num)
			{
				*operand = (T)instruction.operand;
			}
			return num;
		}
	}
	internal class LdlocCapturingMatcher : ILMatcher
	{
		private unsafe readonly int* localIndex;

		public unsafe LdlocCapturingMatcher(int* localIndex)
		{
			this.localIndex = localIndex;
			base..ctor();
		}

		public unsafe bool Matches(CodeInstruction instruction)
		{
			int? ldlocIndex = instruction.GetLdlocIndex();
			if (ldlocIndex.HasValue)
			{
				*localIndex = ldlocIndex.Value;
				return true;
			}
			return false;
		}
	}
	internal class LdlocByRefMatcher : ILMatcher
	{
		private unsafe readonly int* localIndexPtr;

		public unsafe LdlocByRefMatcher(int* localIndexPtr)
		{
			this.localIndexPtr = localIndexPtr;
			base..ctor();
		}

		public unsafe bool Matches(CodeInstruction instruction)
		{
			return instruction.GetLdlocIndex() == *localIndexPtr;
		}
	}
	internal class StlocCapturingMatcher : ILMatcher
	{
		private unsafe readonly int* localIndex;

		public unsafe StlocCapturingMatcher(int* localIndex)
		{
			this.localIndex = localIndex;
			base..ctor();
		}

		public unsafe bool Matches(CodeInstruction instruction)
		{
			int? stlocIndex = instruction.GetStlocIndex();
			if (stlocIndex.HasValue)
			{
				*localIndex = stlocIndex.Value;
				return true;
			}
			return false;
		}
	}
	internal class StlocByRefMatcher : ILMatcher
	{
		private unsafe readonly int* localIndexPtr;

		public unsafe StlocByRefMatcher(int* localIndexPtr)
		{
			this.localIndexPtr = localIndexPtr;
			base..ctor();
		}

		public unsafe bool Matches(CodeInstruction instruction)
		{
			return instruction.GetStlocIndex() == *localIndexPtr;
		}
	}
	internal class DebuggingMatcher : ILMatcher
	{
		private readonly ILMatcher matcher;

		public DebuggingMatcher(ILMatcher matcher)
		{
			this.matcher = matcher;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			bool num = matcher.Matches(instruction);
			if (num)
			{
				Plugin.Instance.Logger.LogInfo((object)$"{matcher} matched {instruction}");
			}
			return num;
		}
	}
	internal static class InstructionUtilities
	{
		public static CodeInstruction MakeLdarg(int index)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			if (index < 256)
			{
				return (CodeInstruction)(index switch
				{
					0 => (object)new CodeInstruction(OpCodes.Ldarg_0, (object)null), 
					1 => (object)new CodeInstruction(OpCodes.Ldarg_1, (object)null), 
					2 => (object)new CodeInstruction(OpCodes.Ldarg_2, (object)null), 
					3 => (object)new CodeInstruction(OpCodes.Ldarg_3, (object)null), 
					_ => (object)new CodeInstruction(OpCodes.Ldarg_S, (object)index), 
				});
			}
			return new CodeInstruction(OpCodes.Ldarg, (object)index);
		}

		public static int PopCount(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj)
			{
				MethodBase obj = (MethodBase)instruction.operand;
				int num = obj.GetParameters().Length;
				if (!obj.IsStatic)
				{
					num++;
				}
				return num;
			}
			if (instruction.opcode == OpCodes.Ret)
			{
				return 1;
			}
			return instruction.opcode.StackBehaviourPop switch
			{
				StackBehaviour.Pop0 => 0, 
				StackBehaviour.Pop1 => 1, 
				StackBehaviour.Pop1_pop1 => 2, 
				StackBehaviour.Popi => 1, 
				StackBehaviour.Popi_pop1 => 2, 
				StackBehaviour.Popi_popi => 2, 
				StackBehaviour.Popi_popi8 => 2, 
				StackBehaviour.Popi_popi_popi => 3, 
				StackBehaviour.Popi_popr4 => 2, 
				StackBehaviour.Popi_popr8 => 2, 
				StackBehaviour.Popref => 1, 
				StackBehaviour.Popref_pop1 => 2, 
				StackBehaviour.Popref_popi => 2, 
				StackBehaviour.Popref_popi_popi => 3, 
				StackBehaviour.Popref_popi_popi8 => 3, 
				StackBehaviour.Popref_popi_popr4 => 3, 
				StackBehaviour.Popref_popi_popr8 => 3, 
				StackBehaviour.Popref_popi_popref => 3, 
				StackBehaviour.Varpop => throw new NotImplementedException($"Variable pop on non-call instruction '{instruction}'"), 
				StackBehaviour.Popref_popi_pop1 => 3, 
				_ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"), 
			};
		}

		public static int PushCount(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj)
			{
				if (instruction.operand is MethodInfo methodInfo && methodInfo.ReturnType == typeof(void))
				{
					return 0;
				}
				return 1;
			}
			return instruction.opcode.StackBehaviourPush switch
			{
				StackBehaviour.Push0 => 0, 
				StackBehaviour.Push1 => 1, 
				StackBehaviour.Push1_push1 => 2, 
				StackBehaviour.Pushi => 1, 
				StackBehaviour.Pushi8 => 1, 
				StackBehaviour.Pushr4 => 1, 
				StackBehaviour.Pushr8 => 1, 
				StackBehaviour.Pushref => 1, 
				StackBehaviour.Varpush => throw new NotImplementedException($"Variable push on non-call instruction '{instruction}'"), 
				_ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"), 
			};
		}

		public static int? GetLdargIndex(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldarg_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Ldarg_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Ldarg_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Ldarg_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Ldarg_S)
			{
				return instruction.operand as byte?;
			}
			if (opcode == OpCodes.Ldarg)
			{
				return instruction.operand as int?;
			}
			return null;
		}

		public static int? GetLdlocIndex(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldloc_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Ldloc_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Ldloc_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Ldloc_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S)
			{
				return (instruction.operand as LocalBuilder)?.LocalIndex;
			}
			return null;
		}

		public static int? GetStlocIndex(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Stloc_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Stloc_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Stloc_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Stloc_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S)
			{
				return (instruction.operand as LocalBuilder)?.LocalIndex;
			}
			return null;
		}

		public static CodeInstruction LdlocToStloc(this CodeInstruction instruction)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldloc_0)
			{
				return new CodeInstruction(OpCodes.Stloc_0, (object)null);
			}
			if (opcode == OpCodes.Ldloc_1)
			{
				return new CodeInstruction(OpCodes.Stloc_1, (object)null);
			}
			if (opcode == OpCodes.Ldloc_2)
			{
				return new CodeInstruction(OpCodes.Stloc_2, (object)null);
			}
			if (opcode == OpCodes.Ldloc_3)
			{
				return new CodeInstruction(OpCodes.Stloc_3, (object)null);
			}
			if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S)
			{
				return new CodeInstruction(OpCodes.Stloc, instruction.operand);
			}
			return null;
		}

		public static CodeInstruction StlocToLdloc(this CodeInstruction instruction)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Stloc_0)
			{
				return new CodeInstruction(OpCodes.Ldloc_0, (object)null);
			}
			if (opcode == OpCodes.Stloc_1)
			{
				return new CodeInstruction(OpCodes.Ldloc_1, (object)null);
			}
			if (opcode == OpCodes.Stloc_2)
			{
				return new CodeInstruction(OpCodes.Ldloc_2, (object)null);
			}
			if (opcode == OpCodes.Stloc_3)
			{
				return new CodeInstruction(OpCodes.Ldloc_3, (object)null);
			}
			if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S)
			{
				return new CodeInstruction(OpCodes.Ldloc, instruction.operand);
			}
			return null;
		}

		public static int? GetLdcI32(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldc_I4_M1)
			{
				return -1;
			}
			if (opcode == OpCodes.Ldc_I4_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Ldc_I4_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Ldc_I4_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Ldc_I4_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Ldc_I4_4)
			{
				return 4;
			}
			if (opcode == OpCodes.Ldc_I4_5)
			{
				return 5;
			}
			if (opcode == OpCodes.Ldc_I4_6)
			{
				return 6;
			}
			if (opcode == OpCodes.Ldc_I4_7)
			{
				return 7;
			}
			if (opcode == OpCodes.Ldc_I4_8)
			{
				return 8;
			}
			if (opcode == OpCodes.Ldc_I4_S)
			{
				return instruction.operand as sbyte?;
			}
			if (opcode == OpCodes.Ldc_I4)
			{
				return instruction.operand as int?;
			}
			return null;
		}
	}
}
namespace PathfindingLagFix.Patches
{
	[HarmonyPatch(typeof(EnemyAI))]
	internal class PatchAddProfilerMarkers
	{
		private static readonly Dictionary<MethodInfo, List<int>> callOffsets = new Dictionary<MethodInfo, List<int>>();

		private static readonly Dictionary<string, ProfilerMarker> markers = new Dictionary<string, ProfilerMarker>();

		private static string currentMarkerName = "";

		internal static void ApplyPatches(Harmony harmony)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Expected O, but got Unknown
			Type[] types = typeof(EnemyAI).Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type != typeof(EnemyAI) && !type.IsSubclassOf(typeof(EnemyAI)))
				{
					continue;
				}
				foreach (MethodInfo runtimeMethod in type.GetRuntimeMethods())
				{
					if (runtimeMethod.DeclaringType != type || !MethodBaseExtensions.HasMethodBody((MethodBase)runtimeMethod))
					{
						continue;
					}
					Collection<Instruction> instructions = PatchManager.GetMethodPatcher((MethodBase)runtimeMethod).CopyOriginal().Definition.Body.Instructions;
					bool flag = false;
					Enumerator<Instruction> enumerator2 = instructions.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							Instruction current2 = enumerator2.Current;
							if (current2.OpCode != OpCodes.Call && current2.OpCode != OpCodes.Callvirt)
							{
								continue;
							}
							object operand = current2.Operand;
							MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
							if (val != null && !(((MemberReference)((MemberReference)val).DeclaringType).Name != "EnemyAI"))
							{
								switch (((MemberReference)val).Name)
								{
								case "PathIsIntersectedByLineOfSight":
								case "ChooseFarthestNodeFromPosition":
								case "ChooseClosestNodeToPosition":
									flag = true;
									GetCallOffsets(runtimeMethod).Add(current2.Offset);
									break;
								}
							}
						}
					}
					finally
					{
						((IDisposable)enumerator2).Dispose();
					}
					if (flag)
					{
						new PatchProcessor(harmony, (MethodBase)runtimeMethod).AddTranspiler(new HarmonyMethod(Reflection.GetMethod(typeof(PatchAddProfilerMarkers), "CallerTranspiler", BindingFlags.Static | BindingFlags.NonPublic, new Type[3]
						{
							typeof(IEnumerable<CodeInstruction>),
							typeof(ILGenerator),
							typeof(MethodBase)
						}))
						{
							priority = 800
						}).Patch();
					}
				}
			}
			harmony.PatchAll(typeof(PatchAddProfilerMarkers));
		}

		private static List<int> GetCallOffsets(MethodInfo method)
		{
			if (callOffsets.TryGetValue(method, out var value))
			{
				return value;
			}
			value = new List<int>();
			callOffsets[method] = value;
			return value;
		}

		private static IEnumerable<CodeInstruction> CallerTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method)
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			if (!(method is MethodInfo method2))
			{
				return instructions;
			}
			Plugin.Instance.Logger.LogInfo((object)("Begin caller transpiler for " + method.DeclaringType.FullName + "::" + method.Name));
			if (Reflection.m_EnemyAI_PathIsIntersectedByLineOfSight == null)
			{
				Plugin.Instance.Logger.LogError((object)"Method info for EnemyAI::PathIsIntersec