Decompiled source of PathfindingLagFix v1.4.0

PathfindingLagFix.dll

Decompiled 4 months 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 BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PathfindingLagFix.Patches;
using UnityEngine;

[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("1.0.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PathfindingLagFix
{
	[BepInPlugin("Zaggy1024.PathfindingLagFix", "PathfindingLagFix", "1.4.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string MOD_NAME = "PathfindingLagFix";

		private const string MOD_UNIQUE_NAME = "Zaggy1024.PathfindingLagFix";

		private const string MOD_VERSION = "1.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;
			harmony.PatchAll(typeof(PatchFlowermanAI));
			harmony.PatchAll(typeof(PatchCopyVanillaFlowermanCode));
			harmony.PatchAll(typeof(PatchCentipedeAI));
			harmony.PatchAll(typeof(PatchCopyVanillaCentipedeCode));
		}
	}
}
namespace PathfindingLagFix.Patches
{
	public class SequenceMatch
	{
		public int Start;

		public int End;

		public SequenceMatch(int start, int end)
		{
			Start = start;
			End = end;
		}
	}
	public static class Common
	{
		public static SequenceMatch FindIndexOfSequence<T>(this List<T> list, int startIndex, int count, IEnumerable<Predicate<T>> predicates)
		{
			int num;
			for (num = startIndex; num < list.Count(); num++)
			{
				IEnumerator<Predicate<T>> enumerator = predicates.GetEnumerator();
				if (!enumerator.MoveNext())
				{
					return null;
				}
				num = list.FindIndex(num, enumerator.Current);
				if (num < 0)
				{
					break;
				}
				bool flag = true;
				int num2 = 1;
				while (enumerator.MoveNext())
				{
					if (num2 >= list.Count() - num || !enumerator.Current(list[num + num2]))
					{
						flag = false;
						break;
					}
					num2++;
				}
				if (flag)
				{
					return new SequenceMatch(num, num + predicates.Count());
				}
			}
			return null;
		}

		public static SequenceMatch FindIndexOfSequence<T>(this List<T> list, int startIndex, IEnumerable<Predicate<T>> predicates)
		{
			return list.FindIndexOfSequence(startIndex, -1, predicates);
		}

		public static SequenceMatch FindIndexOfSequence<T>(this List<T> list, IEnumerable<Predicate<T>> predicates)
		{
			return list.FindIndexOfSequence(0, -1, predicates);
		}

		public static IEnumerable<T> IndexRangeView<T>(this List<T> list, int start, int end)
		{
			for (int i = start; i < end; i++)
			{
				yield return list[i];
			}
		}

		public static IEnumerable<T> IndexRangeView<T>(this List<T> list, SequenceMatch range)
		{
			return list.IndexRangeView(range.Start, range.End);
		}

		public static void RemoveIndexRange<T>(this List<T> list, int start, int end)
		{
			list.RemoveRange(start, end - start);
		}

		public static void RemoveIndicesRange<T>(this List<T> list, SequenceMatch range)
		{
			list.RemoveIndexRange(range.Start, range.End);
		}

		public static void TransferLabelsAndVariables(this IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			Dictionary<LocalBuilder, LocalBuilder> localDict = new Dictionary<LocalBuilder, LocalBuilder>();
			Dictionary<Label, Label> labelDict = new Dictionary<Label, Label>();
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.operand is LocalBuilder local2)
				{
					instruction.operand = GetLocal(local2);
				}
				for (int i = 0; i < instruction.labels.Count(); i++)
				{
					instruction.labels[i] = GetLabel(instruction.labels[i]);
				}
				if (instruction.operand is Label label2)
				{
					instruction.operand = GetLabel(label2);
				}
			}
			Label GetLabel(Label label)
			{
				if (!labelDict.ContainsKey(label))
				{
					labelDict[label] = generator.DefineLabel();
				}
				return labelDict[label];
			}
			LocalBuilder GetLocal(LocalBuilder local)
			{
				if (!localDict.ContainsKey(local))
				{
					localDict[local] = generator.DeclareLocal(local.LocalType);
				}
				return localDict[local];
			}
		}

		public static int GetLocalIndex(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Ldloc_0 || instruction.opcode == OpCodes.Stloc_0)
			{
				return 0;
			}
			if (instruction.opcode == OpCodes.Ldloc_1 || instruction.opcode == OpCodes.Stloc_1)
			{
				return 1;
			}
			if (instruction.opcode == OpCodes.Ldloc_2 || instruction.opcode == OpCodes.Stloc_2)
			{
				return 2;
			}
			if (instruction.opcode == OpCodes.Ldloc_3 || instruction.opcode == OpCodes.Stloc_3)
			{
				return 3;
			}
			if (instruction.opcode != OpCodes.Ldloc || instruction.opcode != OpCodes.Ldloc_S || instruction.opcode != OpCodes.Ldloca || instruction.opcode != OpCodes.Ldloca_S || instruction.opcode != OpCodes.Stloc || instruction.opcode != OpCodes.Stloc_S)
			{
				return -1;
			}
			return ((LocalBuilder)instruction.operand).LocalIndex;
		}

		public static int PopCount(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt)
			{
				MethodInfo obj = (MethodInfo)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"), 
				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)
			{
				if (((MethodInfo)instruction.operand).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"), 
				_ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"), 
			};
		}

		public static SequenceMatch InstructionRangeForStackItems(this List<CodeInstruction> instructions, int instructionIndex, int startIndex, int endIndex)
		{
			int num = -1;
			int num2 = -1;
			instructionIndex--;
			int num3 = 0;
			while (instructionIndex >= 0)
			{
				CodeInstruction instruction = instructions[instructionIndex];
				int num4 = instruction.PushCount();
				if (num2 == -1 && num3 == startIndex && num4 > 0)
				{
					num2 = instructionIndex + 1;
				}
				num3 += instruction.PushCount();
				num3 -= instruction.PopCount();
				if (num3 > endIndex)
				{
					num = instructionIndex;
					break;
				}
				instructionIndex--;
			}
			if (num == -1 || num2 == -1)
			{
				return null;
			}
			return new SequenceMatch(num, num2);
		}

		public static Exception PatchError(string message, string patchName)
		{
			return new Exception(message + ", " + patchName + " may not be supported on this game version");
		}

		public static Exception StubError(string name, string patchName)
		{
			return new NotSupportedException(name + " stub was called, " + patchName + " may not be supported on this game version");
		}
	}
	public static class Coroutines
	{
		public static IEnumerator<Transform> ChooseFarthestNodeFromPosition(EnemyAI enemy, Vector3 pos, bool avoidLineOfSight = false, int offset = 0)
		{
			//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)
			GameObject[] candidateNodes = enemy.allAINodes.OrderByDescending((GameObject node) => Vector3.Distance(pos, node.transform.position)).ToArray();
			yield return null;
			Transform firstAccessibleNode = null;
			int pathsRemaining = offset;
			for (int i = 0; i < candidateNodes.Length; i++)
			{
				Transform transform = candidateNodes[i].transform;
				Vector3 position = transform.position;
				if (!enemy.agent.CalculatePath(position, enemy.path1))
				{
					yield return null;
					continue;
				}
				if ((Object)(object)firstAccessibleNode == (Object)null)
				{
					firstAccessibleNode = transform;
				}
				if (Vector3.Distance(enemy.path1.corners[enemy.path1.corners.Length - 1], RoundManager.Instance.GetNavMeshPosition(position, RoundManager.Instance.navHit, 2.7f, -1)) > 1.5f)
				{
					yield return null;
					continue;
				}
				if (avoidLineOfSight)
				{
					bool flag = false;
					for (int j = 1; j < enemy.path1.corners.Length; j++)
					{
						if (flag)
						{
							break;
						}
						flag = Physics.Linecast(enemy.path1.corners[j - 1], enemy.path1.corners[j], 262144);
					}
					if (flag)
					{
						yield return null;
						continue;
					}
				}
				enemy.mostOptimalDistance = Vector3.Distance(pos, transform.position);
				yield return transform;
				if (pathsRemaining == 0)
				{
					yield break;
				}
				pathsRemaining--;
			}
			if (avoidLineOfSight)
			{
				yield return firstAccessibleNode;
			}
		}
	}
	[HarmonyPatch(typeof(CentipedeAI))]
	public class PatchCentipedeAI
	{
		private static readonly FieldInfo f_CentipedeAI_mainEntrancePosition = AccessTools.Field(typeof(CentipedeAI), "mainEntrancePosition");

		private static readonly FieldInfo f_CentipedeAI_choseHidingSpotNoPlayersNearby = AccessTools.Field(typeof(CentipedeAI), "choseHidingSpotNoPlayersNearby");

		public const string PATCH_NAME = "Snare Flea lag patch";

		public static int NoPlayerToTargetNodeVar = -1;

		public static List<CodeInstruction> NoPlayerToTargetInstructions = null;

		public static void FinishChoosingFarthestNodeFromEntrance(CentipedeAI centipede, Transform node)
		{
			throw Common.StubError("FinishChoosingFarthestNodeFromEntrance", "Snare Flea lag patch");
		}

		private static IEnumerator ChooseFarthestNodeFromEntrance(CentipedeAI centipede, Vector3 position, bool avoidLineOfSight, int offset)
		{
			//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)
			IEnumerator<Transform> farthestNodeCoroutine = Coroutines.ChooseFarthestNodeFromPosition((EnemyAI)(object)centipede, position, avoidLineOfSight, offset);
			Transform lastTransform = null;
			while (farthestNodeCoroutine.MoveNext())
			{
				if ((Object)(object)farthestNodeCoroutine.Current != (Object)null)
				{
					lastTransform = farthestNodeCoroutine.Current;
				}
				yield return null;
			}
			((EnemyAI)centipede).searchCoroutine = null;
			if (!((Object)(object)farthestNodeCoroutine.Current == (Object)null))
			{
				FinishChoosingFarthestNodeFromEntrance(centipede, lastTransform);
			}
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> DoAIIntervalTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Expected O, but got Unknown
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			list.FindIndexOfSequence(new <>z__ReadOnlyArray<Predicate<CodeInstruction>>(new Predicate<CodeInstruction>[2]
			{
				(CodeInstruction insn) => CodeInstructionExtensions.Calls(insn, Reflection.m_EnemyAI_TargetClosestPlayer),
				(CodeInstruction insn) => insn.opcode == OpCodes.Brtrue || insn.opcode == OpCodes.Brtrue_S
			}));
			SequenceMatch sequenceMatch = list.FindIndexOfSequence(new <>z__ReadOnlyArray<Predicate<CodeInstruction>>(new Predicate<CodeInstruction>[3]
			{
				(CodeInstruction insn) => CodeInstructionExtensions.IsLdarg(insn, (int?)0),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsField(insn, f_CentipedeAI_choseHidingSpotNoPlayersNearby, false),
				(CodeInstruction insn) => insn.opcode == OpCodes.Brtrue || insn.opcode == OpCodes.Brtrue_S
			}));
			Label hasChosenHidingSpotLabel = (Label)list[sequenceMatch.End - 1].operand;
			int num = list.FindIndex(sequenceMatch.End, (CodeInstruction insn) => insn.labels.Contains(hasChosenHidingSpotLabel)) - 1;
			int num2 = list.FindIndex(sequenceMatch.End, (CodeInstruction insn) => CodeInstructionExtensions.Calls(insn, Reflection.m_EnemyAI_ChooseFarthestNodeFromPosition));
			if (num2 >= num)
			{
				throw new Exception("Unexpected ordering of instructions in CentipedeAI.DoAIInterval().");
			}
			SequenceMatch sequenceMatch2 = list.InstructionRangeForStackItems(num2, 3, 6);
			NoPlayerToTargetInstructions = list.IndexRangeView(sequenceMatch.End, sequenceMatch2.Start).Append(new CodeInstruction(OpCodes.Ldarg_1, (object)null)).Concat(list.IndexRangeView(num2 + 1, num))
				.ToList();
			List<CodeInstruction> second = list.IndexRangeView(sequenceMatch2.Start, sequenceMatch2.End).ToList();
			list.RemoveIndexRange(sequenceMatch.End, num);
			IEnumerable<CodeInstruction> collection = ((IEnumerable<CodeInstruction>)(object)new CodeInstruction[5]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)Reflection.f_EnemyAI_searchCoroutine),
				new CodeInstruction(OpCodes.Brtrue_S, (object)hasChosenHidingSpotLabel),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null)
			}).Concat(second).Concat(new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3]
			{
				CodeInstruction.Call(typeof(PatchCentipedeAI), "ChooseFarthestNodeFromEntrance", new Type[4]
				{
					typeof(CentipedeAI),
					typeof(Vector3),
					typeof(bool),
					typeof(int)
				}, (Type[])null),
				new CodeInstruction(OpCodes.Call, (object)Reflection.m_MonoBehaviour_StartCoroutine),
				new CodeInstruction(OpCodes.Stfld, (object)Reflection.f_EnemyAI_searchCoroutine)
			}));
			list.InsertRange(sequenceMatch.End, collection);
			return list;
		}
	}
	[HarmonyPatch(typeof(PatchCentipedeAI))]
	internal class PatchCopyVanillaCentipedeCode
	{
		[HarmonyPatch("FinishChoosingFarthestNodeFromEntrance")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PatchCentipedeAI_FinishChoosingFarthestNodeFromEntranceTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			List<CodeInstruction> noPlayerToTargetInstructions = PatchCentipedeAI.NoPlayerToTargetInstructions;
			noPlayerToTargetInstructions.TransferLabelsAndVariables(generator);
			return noPlayerToTargetInstructions.Append(new CodeInstruction(OpCodes.Ret, (object)null));
		}
	}
	[HarmonyPatch(typeof(FlowermanAI))]
	public class PatchFlowermanAI
	{
		private static readonly FieldInfo f_FlowermanAI_mainEntrancePosition = AccessTools.Field(typeof(FlowermanAI), "mainEntrancePosition");

		public const string PATCH_NAME = "Bracken lag patch";

		public static int NoPlayerToTargetNodeVar = -1;

		public static List<CodeInstruction> NoPlayerToTargetInstructions = null;

		public static void FinishChoosingFarthestNodeFromEntrance(FlowermanAI flowerman, Transform node)
		{
			throw Common.StubError("FinishChoosingFarthestNodeFromEntrance", "Bracken lag patch");
		}

		private static IEnumerator ChooseFarthestNodeFromEntrance(FlowermanAI flowerman, Vector3 mainEntrancePosition)
		{
			//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)
			IEnumerator<Transform> farthestNodeCoroutine = Coroutines.ChooseFarthestNodeFromPosition((EnemyAI)(object)flowerman, mainEntrancePosition);
			Transform lastTransform = null;
			while (farthestNodeCoroutine.MoveNext())
			{
				if ((Object)(object)farthestNodeCoroutine.Current != (Object)null)
				{
					lastTransform = farthestNodeCoroutine.Current;
				}
				yield return null;
			}
			((EnemyAI)flowerman).searchCoroutine = null;
			if (!((Object)(object)farthestNodeCoroutine.Current == (Object)null))
			{
				FinishChoosingFarthestNodeFromEntrance(flowerman, lastTransform);
			}
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> DoAIIntervalTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Expected O, but got Unknown
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Expected O, but got Unknown
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Expected O, but got Unknown
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Expected O, but got Unknown
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Expected O, but got Unknown
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Expected O, but got Unknown
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Expected O, but got Unknown
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			Label? noPlayerTargetLabel = null;
			list.FindIndexOfSequence(new <>z__ReadOnlyArray<Predicate<CodeInstruction>>(new Predicate<CodeInstruction>[2]
			{
				(CodeInstruction insn) => CodeInstructionExtensions.Calls(insn, Reflection.m_EnemyAI_TargetClosestPlayer),
				(CodeInstruction insn) => CodeInstructionExtensions.Branches(insn, ref noPlayerTargetLabel)
			}));
			int num = list.FindIndex((CodeInstruction insn) => insn.labels.Contains(noPlayerTargetLabel.Value));
			Label afterNoPlayerTargetLabel = (Label)list[num - 1].operand;
			int end = list.FindIndex(num, (CodeInstruction insn) => insn.labels.Contains(afterNoPlayerTargetLabel));
			SequenceMatch sequenceMatch = list.FindIndexOfSequence(num, new <>z__ReadOnlyArray<Predicate<CodeInstruction>>(new Predicate<CodeInstruction>[10]
			{
				(CodeInstruction insn) => CodeInstructionExtensions.IsLdarg(insn, (int?)0),
				(CodeInstruction insn) => CodeInstructionExtensions.IsLdarg(insn, (int?)0),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsField(insn, f_FlowermanAI_mainEntrancePosition, false),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsConstant(insn, 0L),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsConstant(insn, 0L),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsConstant(insn, 0L),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsConstant(insn, 50L),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsConstant(insn, 0L),
				(CodeInstruction insn) => CodeInstructionExtensions.Calls(insn, Reflection.m_EnemyAI_ChooseFarthestNodeFromPosition),
				(CodeInstruction insn) => CodeInstructionExtensions.IsStloc(insn, (LocalBuilder)null)
			}));
			NoPlayerToTargetNodeVar = list[sequenceMatch.End - 1].GetLocalIndex();
			NoPlayerToTargetInstructions = list.IndexRangeView(sequenceMatch.End, end).ToList();
			Label[] array = list[sequenceMatch.Start].labels.ToArray();
			list.RemoveIndexRange(sequenceMatch.Start, end);
			Label label = generator.DefineLabel();
			list[sequenceMatch.Start].labels.Add(label);
			list.InsertRange(sequenceMatch.Start, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[11]
			{
				CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Ldarg_0, (object)null), array),
				new CodeInstruction(OpCodes.Ldfld, (object)Reflection.f_EnemyAI_searchCoroutine),
				new CodeInstruction(OpCodes.Brtrue_S, (object)label),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)f_FlowermanAI_mainEntrancePosition),
				CodeInstruction.Call(typeof(PatchFlowermanAI), "ChooseFarthestNodeFromEntrance", new Type[2]
				{
					typeof(FlowermanAI),
					typeof(Vector3)
				}, (Type[])null),
				new CodeInstruction(OpCodes.Callvirt, (object)Reflection.m_MonoBehaviour_StartCoroutine),
				new CodeInstruction(OpCodes.Stfld, (object)Reflection.f_EnemyAI_searchCoroutine)
			}));
			return list;
		}
	}
	[HarmonyPatch(typeof(PatchFlowermanAI))]
	internal class PatchCopyVanillaFlowermanCode
	{
		[HarmonyPatch("FinishChoosingFarthestNodeFromEntrance")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PatchFlowermanAI_FinishChoosingFarthestNodeFromEntranceTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			if (PatchFlowermanAI.NoPlayerToTargetNodeVar == -1)
			{
				throw Common.PatchError("Target node variable was not found in DoAIInterval()", "Bracken lag patch");
			}
			if (PatchFlowermanAI.NoPlayerToTargetInstructions == null)
			{
				throw Common.PatchError("Code was not copied from DoAIInterval()", "Bracken lag patch");
			}
			List<CodeInstruction> noPlayerToTargetInstructions = PatchFlowermanAI.NoPlayerToTargetInstructions;
			int noPlayerToTargetNodeVar = PatchFlowermanAI.NoPlayerToTargetNodeVar;
			PatchFlowermanAI.NoPlayerToTargetInstructions = null;
			PatchFlowermanAI.NoPlayerToTargetNodeVar = -1;
			for (int i = 0; i < noPlayerToTargetInstructions.Count(); i++)
			{
				CodeInstruction val = noPlayerToTargetInstructions[i];
				if (CodeInstructionExtensions.IsLdloc(val, (LocalBuilder)null) && val.GetLocalIndex() == noPlayerToTargetNodeVar)
				{
					noPlayerToTargetInstructions[i] = CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Ldarg_1, (object)null), (IEnumerable<Label>)val.labels);
				}
			}
			noPlayerToTargetInstructions.TransferLabelsAndVariables(generator);
			return noPlayerToTargetInstructions.Append(new CodeInstruction(OpCodes.Ret, (object)null));
		}
	}
	public static class Reflection
	{
		public static readonly MethodInfo m_Debug_Log = typeof(Debug).GetMethod("Log", new Type[1] { typeof(object) });

		public static readonly MethodInfo m_EnemyAI_DoAIInterval = typeof(EnemyAI).GetMethod("DoAIInterval", Array.Empty<Type>());

		public static readonly MethodInfo m_EnemyAI_TargetClosestPlayer = typeof(EnemyAI).GetMethod("TargetClosestPlayer", new Type[3]
		{
			typeof(float),
			typeof(bool),
			typeof(float)
		});

		public static readonly MethodInfo m_EnemyAI_ChooseFarthestNodeFromPosition = typeof(EnemyAI).GetMethod("ChooseFarthestNodeFromPosition", new Type[6]
		{
			typeof(Vector3),
			typeof(bool),
			typeof(int),
			typeof(bool),
			typeof(int),
			typeof(bool)
		});

		public static readonly MethodInfo m_EnemyAI_SetDestinationToPosition = typeof(EnemyAI).GetMethod("SetDestinationToPosition", new Type[2]
		{
			typeof(Vector3),
			typeof(bool)
		});

		public static readonly FieldInfo f_EnemyAI_targetNode = typeof(EnemyAI).GetField("targetNode");

		public static readonly FieldInfo f_EnemyAI_targetPlayer = typeof(EnemyAI).GetField("targetPlayer");

		public static readonly FieldInfo f_EnemyAI_favoriteSpot = typeof(EnemyAI).GetField("favoriteSpot");

		public static readonly FieldInfo f_EnemyAI_searchCoroutine = typeof(EnemyAI).GetField("searchCoroutine");

		public static readonly FieldInfo f_EnemyAI_currentSearch = typeof(EnemyAI).GetField("currentSearch");

		public static readonly MethodInfo m_MonoBehaviour_StartCoroutine = typeof(MonoBehaviour).GetMethod("StartCoroutine", new Type[1] { typeof(IEnumerator) });

		public static readonly MethodInfo m_MonoBehaviour_StopCoroutine = typeof(MonoBehaviour).GetMethod("StopCoroutine", new Type[1] { typeof(Coroutine) });

		public static readonly MethodInfo m_Component_get_transform = typeof(Component).GetMethod("get_transform", Array.Empty<Type>());

		public static readonly MethodInfo m_Transform_get_position = typeof(Transform).GetMethod("get_position", Array.Empty<Type>());

		public static readonly MethodInfo m_Object_op_Equality = typeof(Object).GetMethod("op_Equality", new Type[2]
		{
			typeof(Object),
			typeof(Object)
		});
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Length;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Length;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Length;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyArray(T[] items)
	{
		_items = items;
	}

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

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

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

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

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

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

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

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

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

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

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

	bool ICollection<T>.Contains(T item)
	{
		return ((ICollection<T>)_items).Contains(item);
	}

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

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

	int IList<T>.IndexOf(T item)
	{
		return ((IList<T>)_items).IndexOf(item);
	}

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

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