Decompiled source of EnemyAnimationFix v1.2.3

EnemyAnimationFix.dll

Decompiled 6 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using Enemies;
using EnemyAnimationFix.API;
using EnemyAnimationFix.NativePatches;
using EnemyAnimationFix.NativePatches.KernelTools;
using EnemyAnimationFix.Networking.Notify;
using EnemyAnimationFix.Utils;
using GTFO.API;
using GTFO.API.Utilities;
using HarmonyLib;
using Iced.Intel;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.MethodInfo;
using Microsoft.CodeAnalysis;
using SNetwork;
using StateMachines;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("EnemyAnimationFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f3e4c9b311486060eaeed7f06161ba795980221c")]
[assembly: AssemblyProduct("EnemyAnimationFix")]
[assembly: AssemblyTitle("EnemyAnimationFix")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
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 EnemyAnimationFix
{
	public static class Configuration
	{
		private static readonly ConfigFile configFile;

		public static float MinWaveSleepTime { get; private set; }

		public static float MaxWaveSleepTime { get; private set; }

		public static event Action? OnReload;

		static Configuration()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			MinWaveSleepTime = 0f;
			MaxWaveSleepTime = 6f;
			configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "EnemyAnimationFix.cfg"), true);
			BindAll(configFile);
		}

		internal static void Init()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			LiveEdit.CreateListener(Paths.ConfigPath, "EnemyAnimationFix.cfg", false).FileChanged += new LiveEditEventHandler(OnFileChanged);
		}

		private static void OnFileChanged(LiveEditEventArgs _)
		{
			configFile.Reload();
			string text = "Wave Settings";
			MinWaveSleepTime = (float)configFile[text, "Minimum Wave Inactive Time"].BoxedValue;
			MaxWaveSleepTime = (float)configFile[text, "Maximum Wave Inactive Time"].BoxedValue;
			Configuration.OnReload?.Invoke();
		}

		private static void BindAll(ConfigFile config)
		{
			string text = "Wave Settings";
			string text2 = "Minimum amount of time in seconds before enemies become active after spawning.";
			MinWaveSleepTime = config.Bind<float>(text, "Minimum Wave Inactive Time", MinWaveSleepTime, text2).Value;
			text2 = "Maximum amount of time in seconds before enemies become active after spawning.";
			MaxWaveSleepTime = config.Bind<float>(text, "Maximum Wave Inactive Time", MaxWaveSleepTime, text2).Value;
		}
	}
	[BepInPlugin("Dinorush.EnemyAnimationFix", "EnemyAnimationFix", "1.2.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public const string MODNAME = "EnemyAnimationFix";

		public override void Load()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			((BasePlugin)this).Log.LogMessage((object)"Loading EnemyAnimationFix");
			new Harmony("EnemyAnimationFix").PatchAll();
			ChangeStatePatches.ApplyNativePatch();
			ValidTargetPatches.ApplyInstructionPatch();
			Configuration.Init();
			AssetAPI.OnStartupAssetsLoaded += AssetAPI_OnStartupAssetsLoaded;
			LevelAPI.OnLevelCleanup += LevelAPI_OnLevelCleanup;
			((BasePlugin)this).Log.LogMessage((object)"Loaded EnemyAnimationFix");
		}

		private void AssetAPI_OnStartupAssetsLoaded()
		{
			NotifyManager.Init();
		}

		private void LevelAPI_OnLevelCleanup()
		{
			EB_InCombat.s_globalScreamTimer = 0f;
		}
	}
}
namespace EnemyAnimationFix.Utils
{
	internal static class DinoLogger
	{
		private static ManualLogSource logger = Logger.CreateLogSource("EnemyAnimationFix");

		public static void Log(string format, params object[] args)
		{
			Log(string.Format(format, args));
		}

		public static void Log(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)8, (object)str);
			}
		}

		public static void Warning(string format, params object[] args)
		{
			Warning(string.Format(format, args));
		}

		public static void Warning(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)4, (object)str);
			}
		}

		public static void Error(string format, params object[] args)
		{
			Error(string.Format(format, args));
		}

		public static void Error(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)2, (object)str);
			}
		}

		public static void Debug(string format, params object[] args)
		{
			Debug(string.Format(format, args));
		}

		public static void Debug(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)32, (object)str);
			}
		}
	}
}
namespace EnemyAnimationFix.Patches
{
	[HarmonyPatch]
	internal static class EnemyAttackPatches
	{
		[HarmonyPatch(typeof(ES_StrikerAttack), "OnAttackPerform")]
		[HarmonyPostfix]
		private static void Post_StrikerAttackPerform(ES_StrikerAttack __instance)
		{
			if (TryGetTentacle(__instance, out MovingEnemyTentacleBase tentacle))
			{
				tentacle.m_inAttackMove = true;
			}
		}

		[HarmonyPatch(typeof(ES_ShooterAttack), "OnAttackPerform")]
		[HarmonyPostfix]
		private static void Post_ShooterAttackPerform(ES_ShooterAttack __instance)
		{
			if (!(((ES_EnemyAttackBase)__instance).m_attackDoneTimer >= Clock.Time))
			{
				EAB_ProjectileShooter projectileAbility = __instance.m_projectileAbility;
				((ES_EnemyAttackBase)__instance).m_attackDoneTimer = Clock.Time + (projectileAbility.m_shotDelayMin + projectileAbility.m_shotDelayMax) / 2f * (float)projectileAbility.m_burstCount * 0.7f + __instance.m_burstCoolDownBeforeExit;
			}
		}

		[HarmonyPatch(typeof(ES_StrikerAttack), "CommonExit")]
		[HarmonyPostfix]
		private static void Post_StrikerAttackExit(ES_StrikerAttack __instance)
		{
			if (NotifyManager.MasterHasFix && !(Clock.Time <= ((ES_EnemyAttackBase)__instance).m_performAttackTimer) && TryGetTentacle(__instance, out MovingEnemyTentacleBase tentacle) && tentacle.m_currentRoutine != null)
			{
				tentacle.SwitchCoroutine(tentacle.AttackIn(tentacle.m_attackInDuration));
			}
		}

		private static bool TryGetTentacle(ES_StrikerAttack attack, [MaybeNullWhen(false)] out MovingEnemyTentacleBase tentacle)
		{
			tentacle = null;
			EAB_MovingEnemeyTentacle tentacleAbility = attack.m_tentacleAbility;
			if ((Object)(object)tentacleAbility == (Object)null)
			{
				return false;
			}
			tentacle = tentacleAbility.m_tentacle;
			return (Object)(object)tentacle != (Object)null;
		}

		[HarmonyPatch(typeof(ES_PathMove), "Exit")]
		[HarmonyPostfix]
		private static void Post_TankPathMoveExit(ES_PathMove __instance)
		{
			if (NotifyManager.MasterHasFix)
			{
				EnemyAbilities abilities = ((ES_Base)__instance).m_enemyAgent.Abilities;
				if (!ResetTankTongues(abilities, (AgentAbility)2))
				{
					ResetTankTongues(abilities, (AgentAbility)1);
				}
			}
		}

		private static bool ResetTankTongues(EnemyAbilities abilities, AgentAbility abilityType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			EnemyAbility ability = abilities.GetAbility(abilityType, 0);
			if ((Object)(object)ability == (Object)null)
			{
				return false;
			}
			EAB_MovingEnemyTentacleMultiple val = ((Il2CppObjectBase)ability).TryCast<EAB_MovingEnemyTentacleMultiple>();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			foreach (MovingEnemyTentacleBase item in (Il2CppArrayBase<MovingEnemyTentacleBase>)(object)val.m_tentacles)
			{
				if (item.m_currentRoutine != null)
				{
					item.SwitchCoroutine(item.AttackIn(item.m_attackInDuration));
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(ES_ShooterAttack), "CommonExit")]
		[HarmonyPostfix]
		private static void Post_ShooterAttackExit(ES_ShooterAttack __instance)
		{
			if (NotifyManager.MasterHasFix && !(Clock.Time <= ((ES_EnemyAttackBase)__instance).m_performAttackTimer))
			{
				__instance.m_projectileAbility.FireEnd();
			}
		}
	}
	[HarmonyPatch]
	internal static class EnemyGluePatches
	{
		[HarmonyPatch(typeof(Dam_EnemyDamageBase), "AddToTotalGlueVolume")]
		[HarmonyPostfix]
		private static void SyncGlueData(Dam_EnemyDamageBase __instance, GlueGunProjectile? proj, GlueVolumeDesc volume)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if ((int)__instance.Owner.Locomotion.CurrentStateEnum == 17)
			{
				ES_StuckInGlue stuckInGlue = __instance.Owner.Locomotion.StuckInGlue;
				if (stuckInGlue.m_glueFadeOutTriggered)
				{
					float num = stuckInGlue.m_fadeOutDuration - (1f - __instance.AttachedGlueRel) * __instance.Owner.EnemyBalancingData.GlueFadeOutTime;
					EnemyAppearance appearance = __instance.Owner.Appearance;
					appearance.m_lastGlueEnd = num / stuckInGlue.m_fadeOutDuration;
					appearance.SetGlueAmount(0f, num);
				}
			}
			if (SNet.IsMaster)
			{
				pMiniDamageData val = default(pMiniDamageData);
				float num2 = (((Object)(object)proj != (Object)null) ? proj.EffectMultiplier : 1f);
				((UFloat16)(ref val.damage)).Set((volume.volume + volume.expandVolume) * num2, 100f);
				((Dam_SyncedDamageBase)__instance).m_glueDamagePacket.Send(val, (SNet_ChannelType)4);
			}
		}

		[HarmonyPatch(typeof(ES_StuckInGlue), "ActivateState")]
		[HarmonyPrefix]
		private static bool StopClientStateSwitch()
		{
			return SNet.IsMaster;
		}

		[HarmonyPatch(typeof(ES_StuckInGlue), "SetAI")]
		[HarmonyPostfix]
		private static void FixFadeOutDuration(ES_StuckInGlue __instance)
		{
			__instance.m_fadeOutDuration = (__instance.m_fadeOutDuration - __instance.m_fadeInDuration) * 1.5f;
		}

		[HarmonyPatch(typeof(ES_StuckInGlue), "ActivateState")]
		[HarmonyPostfix]
		private static void FixFadeOutTime(ES_StuckInGlue __instance)
		{
			__instance.m_fadeOutTimer = __instance.m_fadeInTimer;
		}
	}
	[HarmonyPatch]
	internal static class EnemyScreamPatches
	{
		[HarmonyPatch(typeof(ES_Scream), "Enter")]
		[HarmonyPostfix]
		private static void FixScreamReset(ES_Scream __instance)
		{
			__instance.m_hasTriggeredPropagation = false;
		}
	}
	[HarmonyPatch]
	internal static class EnemyTargetPatches
	{
		[HarmonyPatch(typeof(EnemyGroup), "RegisterMember")]
		[HarmonyPostfix]
		private static void PostEnemyRegistered(EnemyAgent enemyAgent)
		{
			enemyAgent.m_hasValidTarget = false;
			enemyAgent.m_validTargetInterval = Clock.Time + Random.RandomRange(Configuration.MinWaveSleepTime, Configuration.MaxWaveSleepTime);
		}
	}
	[HarmonyPatch]
	internal static class NetworkingPatches
	{
		[HarmonyPatch(typeof(SNet_SyncManager), "OnFoundMaster")]
		[HarmonyPatch(typeof(SNet_SyncManager), "OnFoundNewMasterDuringMigration")]
		[HarmonyPostfix]
		private static void Post_Joined()
		{
			if (!SNet.IsMaster)
			{
				NotifyManager.SendNotify(SNet.Master);
			}
			else
			{
				NotifyManager.SetMaster();
			}
		}

		[HarmonyPatch(typeof(SNet_SyncManager), "OnPlayerJoinedSessionHub")]
		[HarmonyPostfix]
		private static void Post_Joined(SNet_Player player)
		{
			if (SNet.IsMaster && !player.IsLocal)
			{
				NotifyManager.SendNotify(player);
			}
		}

		[HarmonyPatch(typeof(SNet_SessionHub), "OnLeftLobby")]
		[HarmonyPatch(typeof(SNet_SessionHub), "RemovePlayerFromSession")]
		[HarmonyPrefix]
		private static void Pre_Eject(SNet_Player player)
		{
			if (SNet.IsMaster)
			{
				NotifyManager.RemoveClient(player);
			}
		}

		[HarmonyPatch(typeof(SNet_SyncManager), "OnResetSession")]
		[HarmonyPrefix]
		private static void Pre_OnReset()
		{
			NotifyManager.Reset();
		}
	}
}
namespace EnemyAnimationFix.Networking
{
	public abstract class SyncedEvent<T> where T : struct
	{
		public delegate void ReceiveHandler(T packet);

		private bool _isSetup;

		public abstract string GUID { get; }

		public bool IsSetup => _isSetup;

		public string EventName { get; private set; } = string.Empty;


		public event ReceiveHandler? OnReceive;

		public event ReceiveHandler? OnReceiveLocal;

		public void Setup()
		{
			if (!_isSetup)
			{
				EventName = "EWC" + GUID;
				NetworkAPI.RegisterEvent<T>(EventName, (Action<ulong, T>)ReceiveClient_Callback);
				_isSetup = true;
			}
		}

		public void Send(T packetData, SNet_Player? target = null, SNet_ChannelType priority = 4)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target != (Object)null)
			{
				NetworkAPI.InvokeEvent<T>(EventName, packetData, target, priority);
			}
			else
			{
				NetworkAPI.InvokeEvent<T>(EventName, packetData, priority);
			}
			ReceiveLocal_Callback(packetData);
		}

		private void ReceiveLocal_Callback(T packet)
		{
			ReceiveLocal(packet);
			this.OnReceiveLocal?.Invoke(packet);
		}

		private void ReceiveClient_Callback(ulong sender, T packet)
		{
			Receive(packet);
			this.OnReceive?.Invoke(packet);
		}

		protected virtual void ReceiveLocal(T packet)
		{
		}

		protected virtual void Receive(T packet)
		{
		}
	}
}
namespace EnemyAnimationFix.Networking.Notify
{
	internal static class NotifyManager
	{
		private static readonly NotifySync Sync = new NotifySync();

		public static readonly List<SNet_Player> FixedClients = new List<SNet_Player>();

		public static bool MasterHasFix { get; private set; } = false;


		internal static void Init()
		{
			Sync.Setup();
		}

		internal static void SendNotify(SNet_Player player)
		{
			Sync.Send(new NotifyData
			{
				lookup = SNet.LocalPlayer.Lookup
			}, player, (SNet_ChannelType)4);
		}

		internal static void ReceiveNotify(SNet_Player player)
		{
			if (SNet.IsMaster)
			{
				FixedClients.Add(player);
			}
			else
			{
				MasterHasFix = true;
			}
		}

		internal static void SetMaster()
		{
			MasterHasFix = true;
		}

		internal static void Reset()
		{
			MasterHasFix = false;
			FixedClients.Clear();
		}

		internal static void RemoveClient(SNet_Player player)
		{
			for (int num = FixedClients.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)FixedClients[num] == (Object)null || FixedClients[num].Lookup == player.Lookup)
				{
					FixedClients.RemoveAt(num);
				}
			}
		}
	}
	internal sealed class NotifySync : SyncedEvent<NotifyData>
	{
		public override string GUID => "EAFNF";

		protected override void Receive(NotifyData packet)
		{
			SNet_Player player = default(SNet_Player);
			if (SNet.TryGetPlayer(packet.lookup, ref player))
			{
				NotifyManager.ReceiveNotify(player);
			}
		}
	}
	public struct NotifyData
	{
		public ulong lookup;
	}
}
namespace EnemyAnimationFix.NativePatches
{
	internal static class ChangeStatePatches
	{
		private unsafe delegate void d_ChangeStateFromQueue(IntPtr _this, Il2CppMethodInfo* methodInfo);

		private static INativeDetour? ChangeStateDetour;

		private static d_ChangeStateFromQueue? orig_ChangeStateFromQueue;

		internal unsafe static void ApplyNativePatch()
		{
			NativePatchAPI.AddChangeStatePrefix(FixMeleeCancel);
			INativeClassStruct val = UnityVersionHandler.Wrap((Il2CppClass*)(void*)Il2CppClassPointerStore<StateMachine<ES_Base>>.NativeClassPtr);
			for (int i = 0; i < val.MethodCount; i++)
			{
				INativeMethodInfoStruct val2 = UnityVersionHandler.Wrap(val.Methods[i]);
				if (Marshal.PtrToStringAnsi(val2.Name) == "ChangeStateFromQueue")
				{
					ChangeStateDetour = INativeDetour.CreateAndApply<d_ChangeStateFromQueue>(val2.MethodPointer, (d_ChangeStateFromQueue)ChangeStatePatch, ref orig_ChangeStateFromQueue);
					break;
				}
			}
		}

		private unsafe static void ChangeStatePatch(IntPtr _this, Il2CppMethodInfo* methodInfo)
		{
			StateMachine<ES_Base> val = new StateMachine<ES_Base>(_this);
			if (val.CurrentState == null)
			{
				orig_ChangeStateFromQueue(_this, methodInfo);
				return;
			}
			ES_Base state = val.m_stateQueue.Peek();
			if (NativePatchAPI.RunChangeStatePrefix(val, state))
			{
				orig_ChangeStateFromQueue(_this, methodInfo);
			}
			else
			{
				val.m_stateQueue.Dequeue();
			}
			NativePatchAPI.RunChangeStatePostfix(val, state);
		}

		private static bool FixMeleeCancel(StateMachine<ES_Base> __instance, ES_Base newState)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			ES_Base currentState = __instance.CurrentState;
			if (!NotifyManager.MasterHasFix || (int)newState.m_stateEnum != 2 || (int)currentState.m_stateEnum != 23)
			{
				return true;
			}
			ES_StrikerMelee val = ((Il2CppObjectBase)currentState).Cast<ES_StrikerMelee>();
			return (Clock.Time - val.m_startTime) * val.m_animSpeed >= val.m_attackData.Duration;
		}
	}
	internal static class ValidTargetPatches
	{
		private const int NOP = 144;

		private const int AddssLen = 8;

		public unsafe static void ApplyInstructionPatch()
		{
			INativeClassStruct val = UnityVersionHandler.Wrap((Il2CppClass*)(void*)Il2CppClassPointerStore<EnemyAgent>.NativeClassPtr);
			for (int i = 0; i < val.MethodCount; i++)
			{
				INativeMethodInfoStruct val2 = UnityVersionHandler.Wrap(val.Methods[i]);
				if (!(Marshal.PtrToStringAnsi(val2.Name) == "HasValidTarget"))
				{
					continue;
				}
				IntPtr intPtr = FindAdd(val2.MethodPointer);
				if (intPtr == IntPtr.Zero)
				{
					DinoLogger.Error("Unable to find instruction in HasValidTarget. Not applying fix for enemies stuck on spawning.");
					break;
				}
				using (new MemoryProtectionCookie(intPtr, Kernel32.MemoryProtectionConstant.ExecuteReadWrite, new IntPtr(16)))
				{
					for (int j = 0; j < 8; j++)
					{
						*(sbyte*)((long)intPtr + (long)new IntPtr(j)) = -112;
					}
					break;
				}
			}
		}

		private unsafe static IntPtr FindAdd(IntPtr methodPointer)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Invalid comparison between Unknown and I4
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			StreamCodeReader val = new StreamCodeReader((Stream)new UnmanagedMemoryStream((byte*)(void*)methodPointer, 65536L, 65536L, FileAccess.Read));
			Decoder val2 = Decoder.Create(sizeof(void*) * 8, (CodeReader)(object)val, (DecoderOptions)0);
			val2.IP = (ulong)(long)methodPointer;
			Instruction val3 = default(Instruction);
			val2.Decode(ref val3);
			while ((int)((Instruction)(ref val3)).Mnemonic != 1620)
			{
				if ((int)((Instruction)(ref val3)).Mnemonic == 11)
				{
					if (((Instruction)(ref val3)).NextIP - ((Instruction)(ref val3)).IP != 8)
					{
						DinoLogger.Error("EnemyAnimationFix found an instruction with an unexpected width.");
						return IntPtr.Zero;
					}
					return (IntPtr)(long)((Instruction)(ref val3)).IP;
				}
				val2.Decode(ref val3);
			}
			val.Stream.Dispose();
			return IntPtr.Zero;
		}
	}
}
namespace EnemyAnimationFix.NativePatches.KernelTools
{
	internal static class Kernel32
	{
		[Flags]
		public enum MemoryAllocationConstant : uint
		{
			Commit = 0x1000u,
			Reserve = 0x2000u,
			Reset = 0x80000u,
			ResetUndo = 0x1000000u,
			LargePages = 0x20000000u,
			Physical = 0x400000u,
			TopDown = 0x100000u,
			WriteWatch = 0x200000u
		}

		[Flags]
		public enum MemoryProtectionConstant : uint
		{
			NoAccess = 1u,
			ReadOnly = 2u,
			ReadWrite = 4u,
			WriteCopy = 8u,
			Execute = 0x10u,
			ExecuteRead = 0x20u,
			ExecuteReadWrite = 0x40u,
			ExecuteWriteCopy = 0x80u
		}

		[DllImport("kernel32.dll")]
		public static extern IntPtr VirtualAlloc(IntPtr lpAddress, IntPtr dwSize, MemoryAllocationConstant flAllocationType, MemoryProtectionConstant flProtect);

		[DllImport("kernel32.dll")]
		public static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, MemoryProtectionConstant flNewProtect, out MemoryProtectionConstant lpflOldProtect);
	}
	internal struct MemoryProtectionCookie : IDisposable
	{
		private Kernel32.MemoryProtectionConstant m_OldProtection;

		private readonly IntPtr m_Address;

		private readonly IntPtr m_Size;

		public MemoryProtectionCookie(IntPtr address, Kernel32.MemoryProtectionConstant newProtection, IntPtr size)
		{
			m_Address = address;
			m_Size = size;
			if (!Kernel32.VirtualProtect(m_Address, m_Size, newProtection, out m_OldProtection))
			{
				Environment.FailFast($"Failed to protect address 0x{m_Address:X2} with protection {newProtection}");
			}
		}

		public void Dispose()
		{
			if (!Kernel32.VirtualProtect(m_Address, m_Size, m_OldProtection, out m_OldProtection))
			{
				Environment.FailFast($"Failed to revert memory protection of address 0x{m_Address:X2}");
			}
		}
	}
}
namespace EnemyAnimationFix.API
{
	public static class NativePatchAPI
	{
		public delegate bool ChangeStatePrefix(StateMachine<ES_Base> __instance, ES_Base state);

		public delegate void ChangeStatePostfix(StateMachine<ES_Base> __instance, ES_Base state);

		private static readonly List<ChangeStatePrefix> s_changePrefix = new List<ChangeStatePrefix>();

		private static readonly List<ChangeStatePostfix> s_changePostfix = new List<ChangeStatePostfix>();

		public static void AddChangeStatePrefix(ChangeStatePrefix detectPrefix)
		{
			s_changePrefix.Add(detectPrefix);
		}

		public static void AddChangeStatePostfix(ChangeStatePostfix detectPostfix)
		{
			s_changePostfix.Add(detectPostfix);
		}

		internal static bool RunChangeStatePrefix(StateMachine<ES_Base> __instance, ES_Base state)
		{
			bool flag = true;
			foreach (ChangeStatePrefix item in s_changePrefix)
			{
				flag &= item(__instance, state);
			}
			return flag;
		}

		internal static void RunChangeStatePostfix(StateMachine<ES_Base> __instance, ES_Base state)
		{
			foreach (ChangeStatePostfix item in s_changePostfix)
			{
				item(__instance, state);
			}
		}
	}
}