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();
}
}