Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LostEnemyFix v1.1.1
BepInEx/plugins/LostEnemyFix/LostEnemyFix.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LostEnemyFix.Patches; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LostEnemyFix")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LostEnemyFix")] [assembly: AssemblyTitle("LostEnemyFix")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace LostEnemyFix { [BepInPlugin("JacobG5.LostEnemyFix", "LostEnemyFix", "1.1.1")] public class LostEnemyFix : BaseUnityPlugin { public enum KillLostEnemies { Aggressive, Reasonable, Off } private const string modGUID = "JacobG5.LostEnemyFix"; private const string modName = "LostEnemyFix"; private const string modVersion = "1.1.1"; private readonly Harmony harmony = new Harmony("JacobG5.LostEnemyFix"); internal ManualLogSource mls; public static LostEnemyFix Instance; public static ConfigEntry<KillLostEnemies> killLostEnemiesMode; public static ConfigEntry<bool> attemptRelocation; public void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } killLostEnemiesMode = ((BaseUnityPlugin)this).Config.Bind<KillLostEnemies>("Main", "Kill Lost Enemies Mode", KillLostEnemies.Reasonable, "Aggressive: Kills enemies when they throw a NavMesh error.\nReasonable: Kills enemies after they have thrown 8 NavMesh errors.\nOff: Vanilla behavior"); attemptRelocation = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Attempt Relocation", true, "When instructed to kill an enemy based on the selected mode when enabled will attempt to search for a nearby navmesh first and teleport to the enemy to that. If no navmesh is found will kill the enemy."); mls = Logger.CreateLogSource("JacobG5.LostEnemyFix"); harmony.PatchAll(typeof(EnemyAIPatch)); harmony.PatchAll(typeof(RoundManagerPatch)); } } } namespace LostEnemyFix.Patches { [HarmonyPatch(typeof(EnemyAI))] internal class EnemyAIPatch { [CompilerGenerated] private sealed class <Transpiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private MethodInfo <SetDestinationCall>5__1; private MethodInfo <OnNavMesh>5__2; private MethodInfo <ReplacementMethod>5__3; private int <setDestinationCalls>5__4; private int <isOnNavCalls>5__5; private List<CodeInstruction> <newInstructions>5__6; private IEnumerator<CodeInstruction> <>s__7; private CodeInstruction <instruction>5__8; private List<CodeInstruction>.Enumerator <>s__9; private CodeInstruction <instruction>5__10; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <SetDestinationCall>5__1 = null; <OnNavMesh>5__2 = null; <ReplacementMethod>5__3 = null; <newInstructions>5__6 = null; <>s__7 = null; <instruction>5__8 = null; <>s__9 = default(List<CodeInstruction>.Enumerator); <instruction>5__10 = null; <>1__state = -2; } private bool MoveNext() { //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <SetDestinationCall>5__1 = AccessTools.Method(typeof(NavMeshAgent), "SetDestination", new Type[1] { typeof(Vector3) }, (Type[])null); <OnNavMesh>5__2 = AccessTools.Method(typeof(NavMeshAgent), "get_isOnNavMesh", (Type[])null, (Type[])null); <ReplacementMethod>5__3 = AccessTools.Method(typeof(EnemyAIPatch), "SetAgentDestination", new Type[1] { typeof(EnemyAI) }, (Type[])null); <setDestinationCalls>5__4 = 0; <isOnNavCalls>5__5 = 0; <newInstructions>5__6 = new List<CodeInstruction>(); <>s__7 = instructions.GetEnumerator(); try { while (<>s__7.MoveNext()) { <instruction>5__8 = <>s__7.Current; if (<instruction>5__8.opcode == OpCodes.Callvirt) { if (CodeInstructionExtensions.Calls(<instruction>5__8, <SetDestinationCall>5__1)) { <setDestinationCalls>5__4++; <newInstructions>5__6.RemoveAt(<newInstructions>5__6.Count - 1); <newInstructions>5__6.RemoveAt(<newInstructions>5__6.Count - 1); <newInstructions>5__6.RemoveAt(<newInstructions>5__6.Count - 1); <newInstructions>5__6.Add(new CodeInstruction(OpCodes.Call, (object)<ReplacementMethod>5__3)); } else if (CodeInstructionExtensions.Calls(<instruction>5__8, <OnNavMesh>5__2)) { <isOnNavCalls>5__5++; <newInstructions>5__6.RemoveAt(<newInstructions>5__6.Count - 1); <newInstructions>5__6.RemoveAt(<newInstructions>5__6.Count - 1); <newInstructions>5__6.Add(new CodeInstruction(OpCodes.Ldc_I4_1, (object)null)); } } else { <newInstructions>5__6.Add(<instruction>5__8); } <instruction>5__8 = null; } } finally { if (<>s__7 != null) { <>s__7.Dispose(); } } <>s__7 = null; <>s__9 = <newInstructions>5__6.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; <instruction>5__10 = null; break; } if (<>s__9.MoveNext()) { <instruction>5__10 = <>s__9.Current; <>2__current = <instruction>5__10; <>1__state = 1; return true; } <>m__Finally1(); <>s__9 = default(List<CodeInstruction>.Enumerator); LostEnemyFix.Instance.mls.LogInfo((object)$"Patched Enemy AI: dest = {<setDestinationCalls>5__4} | onNav = {<isOnNavCalls>5__5}"); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__9).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__2 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__2(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } public static readonly Dictionary<EnemyAI, int> EnemyErrors = new Dictionary<EnemyAI, int>(); public static bool SetAgentDestination(EnemyAI enemy) { //IL_0028: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) if (enemy.agent.isOnNavMesh || enemy.agent.isOnOffMeshLink) { return enemy.agent.SetDestination(enemy.destination); } bool flag = false; switch (LostEnemyFix.killLostEnemiesMode.Value) { case LostEnemyFix.KillLostEnemies.Reasonable: if (EnemyErrors.ContainsKey(enemy)) { EnemyErrors[enemy]++; if (EnemyErrors[enemy] > 8) { flag = true; } } else { EnemyErrors.Add(enemy, 1); } break; case LostEnemyFix.KillLostEnemies.Aggressive: flag = true; break; } string text = (((Object)(object)enemy.enemyType == (Object)null) ? ((Object)enemy).name : enemy.enemyType.enemyName); LostEnemyFix.Instance.mls.LogWarning((object)$"{text} Failed to locate NavMesh.\nEnemy Position: {((Component)enemy).transform.position} Target Destination: {enemy.destination} IsOutside: {enemy.isOutside} State: {enemy.currentBehaviourState.name}"); if (flag && ((NetworkBehaviour)enemy).IsOwner) { NavMeshHit val = default(NavMeshHit); if (LostEnemyFix.attemptRelocation.Value && NavMesh.SamplePosition(((Component)enemy).transform.position, ref val, 50f, enemy.agent.areaMask)) { LostEnemyFix.Instance.mls.LogInfo((object)$"Relocating {text} to {((NavMeshHit)(ref val)).position} to prevent further errors."); enemy.agent.Warp(((NavMeshHit)(ref val)).position); } else { LostEnemyFix.Instance.mls.LogInfo((object)("Killing " + text + " to prevent further errors.")); enemy.KillEnemyServerRpc(true); } } return false; } [IteratorStateMachine(typeof(<Transpiler>d__2))] [HarmonyPatch("DoAIInterval")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__2(-2) { <>3__instructions = instructions }; } } [HarmonyPatch(typeof(RoundManager))] internal class RoundManagerPatch { [HarmonyPatch("ResetEnemyVariables")] [HarmonyPrefix] public static void patchResetEnemyVariables() { EnemyAIPatch.EnemyErrors.Clear(); LostEnemyFix.Instance.mls.LogInfo((object)"Clearing Enemy Error List"); } } }