Decompiled source of PathfindingLib v1.0.1
PathfindingLib.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using PathfindingLib.API; using PathfindingLib.API.SmartPathfinding; using PathfindingLib.Components; using PathfindingLib.Data; using PathfindingLib.Jobs; using PathfindingLib.Patches; using PathfindingLib.Patches.Native; using PathfindingLib.Utilities; using PathfindingLib.Utilities.Collections; using PathfindingLib.Utilities.Internal.IL; using Unity.AI.Navigation; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; using Unity.Jobs.LowLevel.Unsafe; using Unity.Mathematics; using Unity.Netcode; using Unity.Profiling; using Unity.Profiling.LowLevel.Unsafe; using UnityEngine; using UnityEngine.AI; using UnityEngine.Experimental.AI; using UnityEngine.Pool; using UnityEngine.Scripting; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PathfindingLib")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PathfindingLib")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("fedb984b-16ae-458c-b2cc-19590627c578")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.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; } } [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 PathfindingLib { [BepInPlugin("Zaggy1024.PathfindingLib", "PathfindingLib", "1.0.1")] public class PathfindingLibPlugin : BaseUnityPlugin { public const string PluginName = "PathfindingLib"; public const string PluginGUID = "Zaggy1024.PathfindingLib"; public const string PluginVersion = "1.0.1"; private readonly Harmony harmony = new Harmony("Zaggy1024.PathfindingLib"); internal static PathfindingLibPlugin Instance { get; private set; } internal ManualLogSource Logger => ((BaseUnityPlugin)this).Logger; public void Awake() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) Instance = this; ApplyAllNativePatches(); harmony.PatchAll(typeof(PatchNavMeshSurface)); harmony.PatchAll(typeof(PatchEntranceTeleport)); harmony.PatchAll(typeof(PatchMineshaftElevatorController)); GameObject val = new GameObject("SmartPathTaskDisposer"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<SmartPathTaskDisposer>(); } private static ProcessModule GetUnityPlayerModule() { ProcessModuleCollection modules = Process.GetCurrentProcess().Modules; for (int i = 0; i < modules.Count; i++) { ProcessModule processModule = modules[i]; if (processModule.ModuleName.Contains("UnityPlayer")) { return processModule; } } return null; } private static void ApplyAllNativePatches() { ProcessModule unityPlayerModule = GetUnityPlayerModule(); NativeFunctions.SetUpNativeMethodPointers(unityPlayerModule.BaseAddress); NavMeshQueryUtils.SetUpNativeMethodPointers(unityPlayerModule.BaseAddress); PatchApplyCarveResults.Apply(unityPlayerModule.BaseAddress); PatchNavMeshAgent.Apply(unityPlayerModule.BaseAddress); } } } namespace PathfindingLib.Utilities { public static class AgentExtensions { public static Vector3 GetPathOrigin(this NavMeshAgent agent) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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 (agent.isOnOffMeshLink) { OffMeshLinkData currentOffMeshLinkData = agent.currentOffMeshLinkData; return ((OffMeshLinkData)(ref currentOffMeshLinkData)).endPos; } return ((Component)agent).transform.position; } } internal static class NativeFunctions { [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private unsafe delegate char* GetNameDelegate(IntPtr thisComponent); internal static readonly bool IsDebugBuild = Debug.isDebugBuild; private static GetNameDelegate getNameMethod; internal static void SetUpNativeMethodPointers(IntPtr baseAddress) { SetUpGetName(baseAddress); } private static void SetUpGetName(IntPtr baseAddress) { ulong num = 3609840uL; if (IsDebugBuild) { num = 5508864uL; } getNameMethod = Marshal.GetDelegateForFunctionPointer<GetNameDelegate>((IntPtr)((long)baseAddress + (long)num)); } internal unsafe static string GetName(IntPtr thisComponent) { return Marshal.PtrToStringAnsi((IntPtr)getNameMethod(thisComponent)); } } [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct NavMeshPathNative { public int offMeshLinkModCount; public int status; public IntPtr polygons; public unsafe fixed int padding[4]; public ulong size; public ulong capacity; public Vector3 sourcePosition; public Vector3 targetPosition; public unsafe Span<PolygonId> currentPolygons => new Span<PolygonId>(polygons.ToPointer(), (int)size); public override readonly string ToString() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) return $"modcount {offMeshLinkModCount} status {status} polys {(ulong)(long)polygons:X16} source {sourcePosition} target {targetPosition} size {size} capacity {capacity}"; } public unsafe static NavMeshPathNative GetNativeData(NavMeshPath path) { return Unsafe.Read<NavMeshPathNative>(path.m_Ptr.ToPointer()); } } [Flags] public enum StraightPathFlags : byte { Start = 1, End = 2, OffMeshConnection = 4 } public static class NavMeshQueryUtils { [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private unsafe delegate PathQueryStatus FindStraightPathDelegate(NavMeshQuery self, in Vector3 startPos, in Vector3 endPos, PolygonId* path, int pathSize, Vector3* straightPath, StraightPathFlags* straightPathFlags, PolygonId* straightPathRefs, ref int straightPathCount, int maxStraightPath); public const int RecommendedCornerCount = 128; private static FindStraightPathDelegate findStraightPathMethod; public static int RequiredCornerCount(int pathPolygonCount) { return pathPolygonCount + 2; } public unsafe static PathQueryStatus FindStraightPath(this NavMeshQuery query, in Vector3 startPos, in Vector3 endPos, in NativeSlice<PolygonId> path, int pathSize, in NativeArray<Vector3> straightPath, in NativeArray<StraightPathFlags> straightPathFlags, in NativeArray<PolygonId> straightPathRefs, out int straightPathCount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (path.Stride != UnsafeUtility.SizeOf<PolygonId>()) { throw new ArgumentException("Path slice must have a stride equal to the size of PolygonId."); } if (straightPathFlags.Length < straightPath.Length) { throw new ArgumentException("Straight path flags buffer is too small."); } if (straightPathRefs.Length < straightPath.Length) { throw new ArgumentException("Straight path refs buffer is too small."); } straightPathCount = 0; Vector3 endPos2 = default(Vector3); PathQueryStatus closestPointOnPoly = NavMeshQuery.GetClosestPointOnPoly(query.m_NavMeshQuery, path[pathSize - 1], endPos, ref endPos2); if ((int)closestPointOnPoly < 0) { return closestPointOnPoly; } return findStraightPathMethod(query, in startPos, in endPos2, path.GetPtr<PolygonId>(), pathSize, straightPath.GetPtr<Vector3>(), GetPtr(in straightPathFlags), straightPathRefs.GetPtr<PolygonId>(), ref straightPathCount, straightPath.Length); } public static PathQueryStatus FindStraightPath(this NavMeshQuery query, in Vector3 startPos, in Vector3 endPos, in NativeSlice<PolygonId> path, int pathSize, in NativeArray<Vector3> straightPath, out int straightPathCount) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) NativeArray<StraightPathFlags> straightPathFlags = default(NativeArray<StraightPathFlags>); straightPathFlags..ctor(straightPath.Length, (Allocator)2, (NativeArrayOptions)1); try { NativeArray<PolygonId> straightPathRefs = new NativeArray<PolygonId>(straightPath.Length, (Allocator)2, (NativeArrayOptions)1); try { return query.FindStraightPath(in startPos, in endPos, in path, pathSize, in straightPath, in straightPathFlags, in straightPathRefs, out straightPathCount); } finally { ((IDisposable)straightPathRefs).Dispose(); } } finally { ((IDisposable)straightPathFlags).Dispose(); } } [Obsolete("Use NativeArray<Vector3> for the straightPath parameter")] public static PathQueryStatus FindStraightPath(this NavMeshQuery query, float3 startPos, float3 endPos, NativeSlice<PolygonId> path, int pathSize, NativeArray<NavMeshLocation> straightPath, out int straightPathCount) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) NativeArray<Vector3> straightPath2 = default(NativeArray<Vector3>); straightPath2..ctor(straightPath.Length, (Allocator)2, (NativeArrayOptions)1); try { NativeArray<StraightPathFlags> straightPathFlags = new NativeArray<StraightPathFlags>(straightPath.Length, (Allocator)2, (NativeArrayOptions)1); try { NativeArray<PolygonId> straightPathRefs = new NativeArray<PolygonId>(straightPath.Length, (Allocator)2, (NativeArrayOptions)1); try { Vector3 startPos2 = float3.op_Implicit(startPos); Vector3 endPos2 = float3.op_Implicit(endPos); PathQueryStatus result = query.FindStraightPath(in startPos2, in endPos2, in path, pathSize, in straightPath2, in straightPathFlags, in straightPathRefs, out straightPathCount); for (int i = 0; i < straightPathCount; i++) { straightPath[i] = new NavMeshLocation(straightPath2[i], straightPathRefs[i]); } return result; } finally { ((IDisposable)straightPathRefs).Dispose(); } } finally { ((IDisposable)straightPathFlags).Dispose(); } } finally { ((IDisposable)straightPath2).Dispose(); } } internal static void SetUpNativeMethodPointers(IntPtr baseAddress) { ulong num = 10850928uL; if (NativeFunctions.IsDebugBuild) { num = 19595328uL; } findStraightPathMethod = Marshal.GetDelegateForFunctionPointer<FindStraightPathDelegate>((IntPtr)((long)baseAddress + (long)num)); } private unsafe static T* GetPtr<T>(this in NativeArray<T> array) where T : unmanaged { return (T*)array.m_Buffer; } private unsafe static T* GetPtr<T>(this in NativeSlice<T> slice) where T : unmanaged { return (T*)slice.m_Buffer; } } public struct NavMeshReadLocker : IDisposable { private bool locked; public NavMeshReadLocker() { locked = false; NavMeshLock.BeginRead(); locked = true; } public void Yield() { NavMeshLock.YieldRead(); } public void Dispose() { if (locked) { locked = false; NavMeshLock.EndRead(); } } } public static class PathQueryStatusExtensions { public static PathQueryStatus GetResult(this PathQueryStatus status) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return (PathQueryStatus)(status & -16777216); } public static PathQueryStatus GetDetail(this PathQueryStatus status) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return (PathQueryStatus)(status & 0xFFFFFF); } } [IgnoredByDeepProfiler] [UsedByNativeCode] public struct TogglableProfilerAuto : IDisposable { [NativeDisableUnsafePtrRestriction] internal readonly IntPtr ptr; internal bool on; [MethodImpl(MethodImplOptions.AggressiveInlining)] public TogglableProfilerAuto(in ProfilerMarker marker) { ptr = marker.m_Ptr; on = true; ProfilerUnsafeUtility.BeginSample(ptr); } public void Pause() { if (on) { ProfilerUnsafeUtility.EndSample(ptr); on = false; } } public void Resume() { if (!on) { on = true; ProfilerUnsafeUtility.BeginSample(ptr); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { if (on) { ProfilerUnsafeUtility.EndSample(ptr); on = false; } } } } namespace PathfindingLib.Utilities.Internal.IL { internal class ILInjector { [CompilerGenerated] private sealed class <GetRelativeInstructions>d__34 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; public ILInjector <>4__this; private int offset; public int <>3__offset; private int size; public int <>3__size; private int <i>5__2; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetRelativeInstructions>d__34(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ILInjector iLInjector = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <i>5__2 = 0; break; case 1: <>1__state = -1; <i>5__2++; break; } if (<i>5__2 < size) { <>2__current = iLInjector.instructions[iLInjector.index + offset + <i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <GetRelativeInstructions>d__34 <GetRelativeInstructions>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <GetRelativeInstructions>d__ = this; } else { <GetRelativeInstructions>d__ = new <GetRelativeInstructions>d__34(0) { <>4__this = <>4__this }; } <GetRelativeInstructions>d__.offset = <>3__offset; <GetRelativeInstructions>d__.size = <>3__size; return <GetRelativeInstructions>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private const string INVALID = "Injector is invalid"; private List<CodeInstruction> instructions = instructions.ToList(); private ILGenerator generator; private int index; private int matchEnd; public int Index { get { return index; } set { index = value; } } public bool IsValid { get { if (instructions != null) { return IsIndexValid(index); } return false; } } public CodeInstruction Instruction { get { if (!IsIndexInRange(index)) { return null; } return instructions[index]; } set { if (!IsIndexInRange(index)) { throw new InvalidOperationException($"Current index {index} is out of range of instruction count {instructions.Count}"); } instructions[index] = value; } } public CodeInstruction LastMatchedInstruction { get { int num = matchEnd - 1; if (!IsIndexInRange(num)) { return null; } return instructions[num]; } set { int num = matchEnd - 1; if (!IsIndexInRange(num)) { throw new InvalidOperationException($"Last matched index {index} is out of range of instruction count {instructions.Count}"); } instructions[num] = value; } } public ICollection<CodeInstruction> Instructions => instructions.AsReadOnly(); public ILInjector(IEnumerable<CodeInstruction> instructions, ILGenerator generator = null) { this.generator = generator; matchEnd = -1; base..ctor(); } public ILInjector GoToStart() { matchEnd = index; index = 0; return this; } public ILInjector GoToEnd() { matchEnd = index; index = instructions.Count; return this; } public ILInjector Forward(int offset) { if (!IsValid) { return this; } matchEnd = index; index = Math.Clamp(index + offset, -1, instructions.Count); return this; } public ILInjector Back(int offset) { return Forward(-offset); } private void MarkInvalid() { index = -1; matchEnd = -1; } private void Search(bool forward, ILMatcher[] predicates) { if (!IsValid) { return; } int num = 1; if (!forward) { num = -1; index--; } while (forward ? (index < instructions.Count) : (index >= 0)) { if (forward && index + predicates.Length > instructions.Count) { index = instructions.Count; break; } int i; for (i = 0; i < predicates.Length && predicates[i].Matches(instructions[index + i]); i++) { } if (i == predicates.Length) { matchEnd = index + i; return; } index += num; } MarkInvalid(); } public ILInjector Find(params ILMatcher[] predicates) { Search(forward: true, predicates); return this; } public ILInjector ReverseFind(params ILMatcher[] predicates) { Search(forward: false, predicates); return this; } public ILInjector GoToPush(int popIndex) { if (!IsValid) { return this; } matchEnd = index; index--; int num = 0; while (index >= 0) { CodeInstruction instruction = instructions[index]; num += instruction.PushCount(); num -= instruction.PopCount(); if (num >= popIndex) { return this; } index--; } return this; } public ILInjector SkipBranch() { if (Instruction == null) { return this; } if (!(Instruction.operand is Label label)) { throw new InvalidOperationException($"Current instruction is not a branch: {Instruction}"); } return FindLabel(label); } public ILInjector FindLabel(Label label) { if (label == default(Label)) { return this; } matchEnd = index; for (index = 0; index < instructions.Count; index++) { if (instructions[index].labels.Contains(label)) { return this; } } MarkInvalid(); return this; } public ILInjector GoToMatchEnd() { index = matchEnd; return this; } public ILInjector GoToLastMatchedInstruction() { if (!IsIndexValid(matchEnd)) { return this; } index = matchEnd - 1; return this; } private bool IsIndexValid(int index) { return index != -1; } private bool IsIndexInRange(int index) { if (index >= 0) { return index < instructions.Count; } return false; } public CodeInstruction GetRelativeInstruction(int offset) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would read out of bounds at index {num}"); } return instructions[num]; } public ILInjector SetRelativeInstruction(int offset, CodeInstruction instruction) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would write out of bounds at index {num}"); } instructions[num] = instruction; return this; } [IteratorStateMachine(typeof(<GetRelativeInstructions>d__34))] public IEnumerable<CodeInstruction> GetRelativeInstructions(int offset, int size) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetRelativeInstructions>d__34(-2) { <>4__this = this, <>3__offset = offset, <>3__size = size }; } public IEnumerable<CodeInstruction> GetRelativeInstructions(int size) { return GetRelativeInstructions(0, size); } private void GetLastMatchRangeAbsolute(out int start, out int end) { start = index; end = matchEnd; if (start > end) { int num = end; int num2 = start; start = num; end = num2; } } private void GetLastMatchRange(out int start, out int size) { GetLastMatchRangeAbsolute(out start, out var end); if (start < 0 || start >= instructions.Count) { throw new InvalidOperationException($"Last match range starts at invalid index {start}"); } if (end < 0 || end > instructions.Count) { throw new InvalidOperationException($"Last match range ends at invalid index {end}"); } size = end - start; } public List<CodeInstruction> GetLastMatch() { GetLastMatchRange(out var start, out var size); return instructions.GetRange(start, size); } public ILInjector DefineLabel(out Label label) { if (generator == null) { throw new InvalidOperationException("No ILGenerator was provided"); } label = generator.DefineLabel(); return this; } public ILInjector AddLabel(out Label label) { DefineLabel(out label); return AddLabel(label); } public ILInjector AddLabel(Label label) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Instruction = new CodeInstruction(Instruction); Instruction.labels.Add(label); return this; } public ILInjector InsertInPlace(params CodeInstruction[] instructions) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } this.instructions.InsertRange(index, instructions); if (matchEnd >= index) { matchEnd += instructions.Length; } return this; } public ILInjector Insert(params CodeInstruction[] instructions) { InsertInPlace(instructions); index += instructions.Length; return this; } public ILInjector InsertInPlaceAfterBranch(params CodeInstruction[] instructions) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } List<Label> labels = Instruction.labels; Instruction = new CodeInstruction(Instruction); Instruction.labels.Clear(); this.instructions.InsertRange(index, instructions); Instruction.labels.AddRange(labels); if (matchEnd >= index) { matchEnd += instructions.Length; } return this; } public ILInjector InsertAfterBranch(params CodeInstruction[] instructions) { InsertInPlaceAfterBranch(instructions); index += instructions.Length; return this; } public ILInjector RemoveAllPreviousInstructions() { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } instructions.RemoveRange(0, index); matchEnd -= index; if (matchEnd < 0) { matchEnd = 0; } index = 0; return this; } public ILInjector Remove(int count = 1) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } instructions.RemoveRange(index, count); if (matchEnd > index) { matchEnd = Math.Max(index, matchEnd - count); } return this; } public ILInjector RemoveLastMatch() { GetLastMatchRange(out var start, out var size); List<Label> labels = instructions[start].labels; instructions.RemoveRange(start, size); index = start; matchEnd = start; instructions[start].labels.AddRange(labels); return this; } public ILInjector ReplaceLastMatch(params CodeInstruction[] replacementInstructions) { if (replacementInstructions.Length == 0) { throw new ArgumentException("Cannot replace a match with an empty array."); } GetLastMatchRange(out var start, out var size); List<Label> labels = instructions[start].labels; instructions.RemoveRange(start, size); instructions.InsertRange(start, replacementInstructions); index = start; matchEnd = start + replacementInstructions.Length; instructions[start].labels.AddRange(labels); return this; } public List<CodeInstruction> ReleaseInstructions() { List<CodeInstruction> result = instructions; instructions = null; return result; } public ILInjector PrintContext(int context, string header = "") { if (!IsValid) { throw new InvalidOperationException("Injector is invalid (" + header + ")"); } StringBuilder stringBuilder = new StringBuilder(header); if (header.Length > 0) { stringBuilder.Append(':'); } stringBuilder.AppendLine(); GetLastMatchRangeAbsolute(out var start, out var end); int num = Math.Min(end + 1 + context, instructions.Count); for (int i = Math.Max(start - context, 0); i < num; i++) { if (end == -1 && i == index) { stringBuilder.Append("╶> "); } else { if (i >= start && i < end) { stringBuilder.Append("│"); } else { stringBuilder.Append(" "); } if (i == index) { stringBuilder.Append("╶> "); } else { stringBuilder.Append(" "); } } stringBuilder.AppendLine($"{i}: {instructions[i]}"); } PathfindingLibPlugin.Instance.Logger.LogInfo((object)stringBuilder); return this; } public ILInjector PrintContext(string header = "") { return PrintContext(4, header); } } internal interface ILMatcher { bool Matches(CodeInstruction instruction); ILMatcher CaptureAs(out CodeInstruction variable) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown variable = new CodeInstruction(OpCodes.Nop, (object)null); return new InstructionCapturingMatcher(this, variable); } unsafe ILMatcher CaptureOperandAs<T>(out T operand) where T : unmanaged { operand = default(T); fixed (T* operand2 = &operand) { return new OperandCapturingMatcher<T>(this, operand2); } } ILMatcher Debug() { return new DebuggingMatcher(this); } static ILMatcher Not(ILMatcher matcher) { return new NotMatcher(matcher); } static ILMatcher Opcode(OpCode opcode) { return new OpcodeMatcher(opcode); } static ILMatcher Opcodes(params OpCode[] opcodes) { return new OpcodesMatcher(opcodes); } static ILMatcher OpcodeOperand(OpCode opcode, object operand) { return new OpcodeOperandMatcher(opcode, operand); } static ILMatcher Instruction(CodeInstruction instruction) { return new InstructionMatcher(instruction); } static ILMatcher Ldarg(int? arg = null) { return new LdargMatcher(arg); } static ILMatcher Ldloc(int? loc = null) { return new LdlocMatcher(loc); } static ILMatcher Stloc(int? loc = null) { return new StlocMatcher(loc); } static ILMatcher Ldc(int? value = null) { return new LdcI32Matcher(value); } static ILMatcher LdcF32(float? value = null) { return new LdcF32Matcher(value); } static ILMatcher Branch() { return new BranchMatcher(); } static ILMatcher Ldfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Ldfld, field); } static ILMatcher Ldsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Ldsfld, field); } static ILMatcher Stfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Stfld, field); } static ILMatcher Stsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (field == null) { PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return new OpcodeOperandMatcher(OpCodes.Stsfld, field); } static ILMatcher Callvirt(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (method == null) { PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Callvirt() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return OpcodeOperand(OpCodes.Callvirt, method); } static ILMatcher Call(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { if (method == null) { PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Call() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})"); } return OpcodeOperand(OpCodes.Call, method); } static ILMatcher Predicate(Func<CodeInstruction, bool> predicate) { return new PredicateMatcher(predicate); } static ILMatcher Predicate(Func<FieldInfo, bool> predicate) { return new PredicateMatcher((CodeInstruction insn) => insn.operand is FieldInfo arg && predicate(arg)); } } internal class NotMatcher : ILMatcher { private readonly ILMatcher matcher; public NotMatcher(ILMatcher matcher) { this.matcher = matcher; base..ctor(); } public bool Matches(CodeInstruction instruction) { return !matcher.Matches(instruction); } } internal class OpcodeMatcher : ILMatcher { private readonly OpCode opcode; public OpcodeMatcher(OpCode opcode) { this.opcode = opcode; base..ctor(); } public bool Matches(CodeInstruction instruction) { return instruction.opcode == opcode; } } internal class OpcodesMatcher : ILMatcher { private readonly OpCode[] opcodes; public OpcodesMatcher(OpCode[] opcodes) { this.opcodes = opcodes; base..ctor(); } public bool Matches(CodeInstruction instruction) { return opcodes.Contains(instruction.opcode); } } internal class OpcodeOperandMatcher : ILMatcher { private readonly OpCode opcode; private readonly object operand; public OpcodeOperandMatcher(OpCode opcode, object operand) { this.opcode = opcode; this.operand = operand; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (instruction.opcode == opcode) { return instruction.operand == operand; } return false; } } internal class InstructionMatcher : ILMatcher { private readonly OpCode opcode = instruction.opcode; private readonly object operand = instruction.operand; private readonly Label[] labels = instruction.labels.ToArray(); public InstructionMatcher(CodeInstruction instruction) { } public bool Matches(CodeInstruction instruction) { if (instruction.opcode != opcode) { return false; } if (instruction.operand != operand) { return false; } if (instruction.labels.Count != labels.Length) { return false; } for (int i = 0; i < labels.Length; i++) { if (labels[i] != instruction.labels[i]) { return false; } } return true; } } internal class LdargMatcher : ILMatcher { private readonly int? arg; public LdargMatcher(int? arg) { this.arg = arg; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!arg.HasValue) { return instruction.GetLdargIndex().HasValue; } return instruction.GetLdargIndex() == arg; } } internal class LdlocMatcher : ILMatcher { private readonly int? loc; public LdlocMatcher(int? loc) { this.loc = loc; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!loc.HasValue) { return instruction.GetLdlocIndex().HasValue; } return instruction.GetLdlocIndex() == loc; } } internal class StlocMatcher : ILMatcher { private readonly int? loc; public StlocMatcher(int? loc) { this.loc = loc; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!loc.HasValue) { return instruction.GetStlocIndex().HasValue; } return instruction.GetStlocIndex() == loc; } } internal class LdcI32Matcher : ILMatcher { private readonly int? value; public LdcI32Matcher(int? value) { this.value = value; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (!value.HasValue) { return instruction.GetLdcI32().HasValue; } return instruction.GetLdcI32() == value; } } internal class LdcF32Matcher : ILMatcher { private readonly float? value; public LdcF32Matcher(float? value) { this.value = value; base..ctor(); } public bool Matches(CodeInstruction instruction) { if (instruction.opcode == OpCodes.Ldc_R4) { if (value.HasValue) { return (float)instruction.operand == value.Value; } return true; } return false; } } internal class BranchMatcher : ILMatcher { public bool Matches(CodeInstruction instruction) { Label? label = default(Label?); return CodeInstructionExtensions.Branches(instruction, ref label); } } internal class PredicateMatcher : ILMatcher { private readonly Func<CodeInstruction, bool> predicate; public PredicateMatcher(Func<CodeInstruction, bool> predicate) { this.predicate = predicate; base..ctor(); } public bool Matches(CodeInstruction instruction) { return predicate(instruction); } } internal class InstructionCapturingMatcher : ILMatcher { private readonly ILMatcher matcher; private readonly CodeInstruction variable; public InstructionCapturingMatcher(ILMatcher matcher, CodeInstruction variable) { this.matcher = matcher; this.variable = variable; base..ctor(); } public bool Matches(CodeInstruction instruction) { bool num = matcher.Matches(instruction); if (num) { variable.opcode = instruction.opcode; variable.operand = instruction.operand; variable.blocks = instruction.blocks.ToList(); variable.labels = instruction.labels.ToList(); } return num; } } internal class OperandCapturingMatcher<T> : ILMatcher where T : unmanaged { private readonly ILMatcher matcher; private unsafe readonly T* operand; public unsafe OperandCapturingMatcher(ILMatcher matcher, T* operand) { this.matcher = matcher; this.operand = operand; base..ctor(); } public unsafe bool Matches(CodeInstruction instruction) { bool num = matcher.Matches(instruction); if (num) { *operand = (T)instruction.operand; } return num; } } internal class DebuggingMatcher : ILMatcher { private readonly ILMatcher matcher; public DebuggingMatcher(ILMatcher matcher) { this.matcher = matcher; base..ctor(); } public bool Matches(CodeInstruction instruction) { bool num = matcher.Matches(instruction); if (num) { PathfindingLibPlugin.Instance.Logger.LogInfo((object)$"{matcher} matched {instruction}"); } return num; } } internal static class InstructionUtilities { public static CodeInstruction MakeLdarg(int index) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown if (index < 256) { return (CodeInstruction)(index switch { 0 => (object)new CodeInstruction(OpCodes.Ldarg_0, (object)null), 1 => (object)new CodeInstruction(OpCodes.Ldarg_1, (object)null), 2 => (object)new CodeInstruction(OpCodes.Ldarg_2, (object)null), 3 => (object)new CodeInstruction(OpCodes.Ldarg_3, (object)null), _ => (object)new CodeInstruction(OpCodes.Ldarg_S, (object)index), }); } return new CodeInstruction(OpCodes.Ldarg, (object)index); } public static int PopCount(this CodeInstruction instruction) { if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj) { MethodBase obj = (MethodBase)instruction.operand; int num = obj.GetParameters().Length; if (!obj.IsStatic) { num++; } return num; } if (instruction.opcode == OpCodes.Ret) { return 1; } return instruction.opcode.StackBehaviourPop switch { StackBehaviour.Pop0 => 0, StackBehaviour.Pop1 => 1, StackBehaviour.Pop1_pop1 => 2, StackBehaviour.Popi => 1, StackBehaviour.Popi_pop1 => 2, StackBehaviour.Popi_popi => 2, StackBehaviour.Popi_popi8 => 2, StackBehaviour.Popi_popi_popi => 3, StackBehaviour.Popi_popr4 => 2, StackBehaviour.Popi_popr8 => 2, StackBehaviour.Popref => 1, StackBehaviour.Popref_pop1 => 2, StackBehaviour.Popref_popi => 2, StackBehaviour.Popref_popi_popi => 3, StackBehaviour.Popref_popi_popi8 => 3, StackBehaviour.Popref_popi_popr4 => 3, StackBehaviour.Popref_popi_popr8 => 3, StackBehaviour.Popref_popi_popref => 3, StackBehaviour.Varpop => throw new NotImplementedException($"Variable pop on non-call instruction '{instruction}'"), StackBehaviour.Popref_popi_pop1 => 3, _ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"), }; } public static int PushCount(this CodeInstruction instruction) { if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj) { if (instruction.operand is MethodInfo methodInfo && methodInfo.ReturnType == typeof(void)) { return 0; } return 1; } return instruction.opcode.StackBehaviourPush switch { StackBehaviour.Push0 => 0, StackBehaviour.Push1 => 1, StackBehaviour.Push1_push1 => 2, StackBehaviour.Pushi => 1, StackBehaviour.Pushi8 => 1, StackBehaviour.Pushr4 => 1, StackBehaviour.Pushr8 => 1, StackBehaviour.Pushref => 1, StackBehaviour.Varpush => throw new NotImplementedException($"Variable push on non-call instruction '{instruction}'"), _ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"), }; } public static int? GetLdargIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldarg_0) { return 0; } if (opcode == OpCodes.Ldarg_1) { return 1; } if (opcode == OpCodes.Ldarg_2) { return 2; } if (opcode == OpCodes.Ldarg_3) { return 3; } if (opcode == OpCodes.Ldarg || opcode == OpCodes.Ldarg_S) { return instruction.operand as int?; } return null; } public static int? GetLdlocIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldloc_0) { return 0; } if (opcode == OpCodes.Ldloc_1) { return 1; } if (opcode == OpCodes.Ldloc_2) { return 2; } if (opcode == OpCodes.Ldloc_3) { return 3; } if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S) { return (instruction.operand as LocalBuilder)?.LocalIndex; } return null; } public static int? GetStlocIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Stloc_0) { return 0; } if (opcode == OpCodes.Stloc_1) { return 1; } if (opcode == OpCodes.Stloc_2) { return 2; } if (opcode == OpCodes.Stloc_3) { return 3; } if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S) { return (instruction.operand as LocalBuilder)?.LocalIndex; } return null; } public static CodeInstruction LdlocToStloc(this CodeInstruction instruction) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldloc_0) { return new CodeInstruction(OpCodes.Stloc_0, (object)null); } if (opcode == OpCodes.Ldloc_1) { return new CodeInstruction(OpCodes.Stloc_1, (object)null); } if (opcode == OpCodes.Ldloc_2) { return new CodeInstruction(OpCodes.Stloc_2, (object)null); } if (opcode == OpCodes.Ldloc_3) { return new CodeInstruction(OpCodes.Stloc_3, (object)null); } if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S) { return new CodeInstruction(OpCodes.Stloc, instruction.operand); } return null; } public static CodeInstruction StlocToLdloc(this CodeInstruction instruction) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown OpCode opcode = instruction.opcode; if (opcode == OpCodes.Stloc_0) { return new CodeInstruction(OpCodes.Ldloc_0, (object)null); } if (opcode == OpCodes.Stloc_1) { return new CodeInstruction(OpCodes.Ldloc_1, (object)null); } if (opcode == OpCodes.Stloc_2) { return new CodeInstruction(OpCodes.Ldloc_2, (object)null); } if (opcode == OpCodes.Stloc_3) { return new CodeInstruction(OpCodes.Ldloc_3, (object)null); } if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S) { return new CodeInstruction(OpCodes.Ldloc, instruction.operand); } return null; } public static int? GetLdcI32(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldc_I4_M1) { return -1; } if (opcode == OpCodes.Ldc_I4_0) { return 0; } if (opcode == OpCodes.Ldc_I4_1) { return 1; } if (opcode == OpCodes.Ldc_I4_2) { return 2; } if (opcode == OpCodes.Ldc_I4_3) { return 3; } if (opcode == OpCodes.Ldc_I4_4) { return 4; } if (opcode == OpCodes.Ldc_I4_5) { return 5; } if (opcode == OpCodes.Ldc_I4_6) { return 6; } if (opcode == OpCodes.Ldc_I4_7) { return 7; } if (opcode == OpCodes.Ldc_I4_8) { return 8; } if (opcode == OpCodes.Ldc_I4_S) { return instruction.operand as sbyte?; } if (opcode == OpCodes.Ldc_I4) { return instruction.operand as int?; } return null; } } } namespace PathfindingLib.Utilities.Collections { internal struct NativeArrayBuilder<T> : IEnumerable<T>, IEnumerable, IDisposable where T : unmanaged { [CompilerGenerated] private sealed class <GetEnumerator>d__10 : IEnumerator<T>, IEnumerator, IDisposable { private int <>1__state; private T <>2__current; public NativeArrayBuilder<T> <>4__this; private int <i>5__2; T IEnumerator<T>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetEnumerator>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <i>5__2 = 0; break; case 1: <>1__state = -1; <i>5__2++; break; } if (<i>5__2 < <>4__this.size) { <>2__current = <>4__this.array[<i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <System-Collections-IEnumerable-GetEnumerator>d__11 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public NativeArrayBuilder<T> <>4__this; private int <i>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <System-Collections-IEnumerable-GetEnumerator>d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <i>5__2 = 0; break; case 1: <>1__state = -1; <i>5__2++; break; } if (<i>5__2 < <>4__this.size) { <>2__current = <>4__this.array[<i>5__2]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private NativeArray<T> array; private int size; public int Capacity { get { return array.Length; } set { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) NativeArray<T> val = default(NativeArray<T>); val..ctor(value, (Allocator)4, (NativeArrayOptions)1); array.CopyTo(val); array.Dispose(); array = val; } } public readonly int Count => size; public void Add(in T item) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (size >= Capacity) { int num; for (num = 8; num <= size; num <<= 1) { } Capacity = num; } array.GetRef<T>(size++) = item; } public void Clear() { size = 0; } public readonly NativeArray<T> Get() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return array; } [IteratorStateMachine(typeof(NativeArrayBuilder<>.<GetEnumerator>d__10))] public readonly IEnumerator<T> GetEnumerator() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetEnumerator>d__10(0) { <>4__this = this }; } [IteratorStateMachine(typeof(NativeArrayBuilder<>.<System-Collections-IEnumerable-GetEnumerator>d__11))] readonly IEnumerator IEnumerable.GetEnumerator() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <System-Collections-IEnumerable-GetEnumerator>d__11(0) { <>4__this = this }; } public void Dispose() { array.Dispose(); } } internal static class NativeArrayExtensions { internal unsafe static ref T GetRef<T>(this NativeArray<T> array, int index) where T : unmanaged { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (index < 0) { throw new IndexOutOfRangeException("Index cannot be negative."); } if (index >= array.Length) { throw new IndexOutOfRangeException($"Index {index} is not within array length of {array.Length}."); } return ref *(T*)((byte*)array.m_Buffer + (nint)index * (nint)sizeof(T)); } internal unsafe static void SetAllElements<T>(this NativeArray<T> array, T value) where T : unmanaged { //IL_0000: Unknown result type (might be due to invalid IL or missing references) T* buffer = (T*)array.m_Buffer; int length = array.Length; for (int i = 0; i < length; i++) { buffer[i] = value; } } } internal struct NativeHeapIndex { internal static readonly NativeHeapIndex Invalid = new NativeHeapIndex { TableIndex = -1 }; internal int TableIndex; internal readonly bool IsValid => TableIndex >= 0; } [NativeContainer] [DebuggerDisplay("Count = {Count}")] internal struct NativeHeap<T, U> : IDisposable where T : unmanaged where U : unmanaged, IComparer<T> { internal const int DEFAULT_CAPACITY = 128; private const int VALIDATION_ERROR_WRONG_INSTANCE = 1; private const int VALIDATION_ERROR_INVALID = 2; private const int VALIDATION_ERROR_REMOVED = 3; [NativeDisableUnsafePtrRestriction] private unsafe HeapData<T, U>* Data; private Allocator Allocator; internal unsafe int Capacity { get { return Data->Capacity; } set { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) TableValue* ptr = (TableValue*)UnsafeUtility.Malloc((long)(UnsafeUtility.SizeOf<TableValue>() * value), UnsafeUtility.AlignOf<TableValue>(), Allocator); HeapNode<T>* ptr2 = (HeapNode<T>*)UnsafeUtility.Malloc((long)(UnsafeUtility.SizeOf<HeapNode<T>>() * value), UnsafeUtility.AlignOf<HeapNode<T>>(), Allocator); int num = ((Data->Capacity < value) ? Data->Capacity : value); UnsafeUtility.MemCpy((void*)ptr, (void*)Data->Table, (long)(num * UnsafeUtility.SizeOf<TableValue>())); UnsafeUtility.MemCpy((void*)ptr2, (void*)Data->Heap, (long)(num * UnsafeUtility.SizeOf<HeapNode<T>>())); for (int i = 0; i < value - Data->Capacity; i++) { ptr2[i + Data->Capacity] = new HeapNode<T> { TableIndex = i + Data->Capacity }; } UnsafeUtility.Free((void*)Data->Table, Allocator); UnsafeUtility.Free((void*)Data->Heap, Allocator); Data->Table = ptr; Data->Heap = ptr2; Data->Capacity = value; } } internal unsafe int Count => Data->Count; internal unsafe U Comparator { get { return Data->Comparator; } set { Data->Comparator = value; } } internal NativeHeap(Allocator allocator, int initialCapacity = 128, U comparator = default(U)) : this(initialCapacity, comparator, allocator, 1) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) public unsafe void Dispose() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) Data->Count = 0; Data->Capacity = 0; UnsafeUtility.Free((void*)Data->Heap, Allocator); UnsafeUtility.Free((void*)Data->Table, Allocator); UnsafeUtility.Free((void*)Data, Allocator); } internal unsafe void Clear() { Data->Count = 0; } internal bool IsValidIndex(NativeHeapIndex index) { return true; } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] internal void AssertValidIndex(NativeHeapIndex index) { int num = 0; if (1 == 0) { switch (num) { case 1: throw new ArgumentException("The provided ItemHandle was not valid for this NativeHeap. It was taken from a different instance."); case 2: throw new ArgumentException("The provided ItemHandle was not valid for this NativeHeap."); case 3: throw new ArgumentException("The provided ItemHandle was not valid for this NativeHeap. The item it pointed to might have already been removed."); } } } internal T Peek() { if (!TryPeek(out var t)) { throw new InvalidOperationException("Cannot Peek NativeHeap when the count is zero."); } return t; } internal unsafe bool TryPeek(out T t) { if (Data->Count == 0) { t = default(T); return false; } t = Data->Heap->Item; return true; } internal T Pop() { if (!TryPop(out var t)) { throw new InvalidOperationException("Cannot Pop NativeHeap when the count is zero."); } return t; } internal unsafe bool TryPop(out T t) { if (Data->Count == 0) { t = default(T); return false; } HeapNode<T> heap = *Data->Heap; int num = --Data->Count; HeapNode<T> node = Data->Heap[num]; Data->Heap[num] = heap; InsertAndBubbleDown(node, 0); t = heap.Item; return true; } internal unsafe NativeHeapIndex Insert(in T t) { if (Data->Count == Data->Capacity) { Capacity *= 2; } HeapNode<T> node = Data->Heap[Data->Count]; node.Item = t; int insertIndex = Data->Count++; InsertAndBubbleUp(node, insertIndex); NativeHeapIndex result = default(NativeHeapIndex); result.TableIndex = node.TableIndex; return result; } internal unsafe T Remove(NativeHeapIndex index) { int heapIndex = Data->Table[index.TableIndex].HeapIndex; HeapNode<T> heapNode = Data->Heap[heapIndex]; HeapNode<T> node = Data->Heap[--Data->Count]; UnsafeUtility.WriteArrayElement<HeapNode<T>>((void*)Data->Heap, Data->Count, heapNode); if (heapIndex != 0) { int num = (heapIndex - 1) / 2; HeapNode<T> heapNode2 = Data->Heap[num]; if (Data->Comparator.Compare(node.Item, heapNode2.Item) < 0) { InsertAndBubbleUp(node, heapIndex); return heapNode.Item; } } InsertAndBubbleDown(node, heapIndex); return heapNode.Item; } internal unsafe T Get(NativeHeapIndex index) { int heapIndex = Data->Table[index.TableIndex].HeapIndex; return Data->Heap[heapIndex].Item; } private unsafe NativeHeap(int initialCapacity, U comparator, Allocator allocator, int disposeSentinelStackDepth) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Data = (HeapData<T, U>*)UnsafeUtility.Malloc((long)UnsafeUtility.SizeOf<HeapData<T, U>>(), UnsafeUtility.AlignOf<HeapData<T, U>>(), allocator); Data->Heap = (HeapNode<T>*)UnsafeUtility.Malloc((long)(UnsafeUtility.SizeOf<HeapNode<T>>() * initialCapacity), UnsafeUtility.AlignOf<HeapNode<T>>(), allocator); Data->Table = (TableValue*)UnsafeUtility.Malloc((long)(UnsafeUtility.SizeOf<TableValue>() * initialCapacity), UnsafeUtility.AlignOf<TableValue>(), allocator); Allocator = allocator; for (int i = 0; i < initialCapacity; i++) { Data->Heap[i] = new HeapNode<T> { TableIndex = i }; } Data->Count = 0; Data->Capacity = initialCapacity; Data->Comparator = comparator; } private unsafe void InsertAndBubbleDown(HeapNode<T> node, int insertIndex) { while (true) { int num = insertIndex * 2 + 1; int num2 = insertIndex * 2 + 2; if (num >= Data->Count) { break; } if (num2 >= Data->Count || Data->Comparator.Compare(Data->Heap[num].Item, Data->Heap[num2].Item) <= 0) { HeapNode<T> heapNode = Data->Heap[num]; if (Data->Comparator.Compare(node.Item, heapNode.Item) <= 0) { break; } Data->Heap[insertIndex] = heapNode; Data->Table[heapNode.TableIndex].HeapIndex = insertIndex; insertIndex = num; } else { HeapNode<T> heapNode2 = Data->Heap[num2]; if (Data->Comparator.Compare(node.Item, heapNode2.Item) <= 0) { break; } Data->Heap[insertIndex] = heapNode2; Data->Table[heapNode2.TableIndex].HeapIndex = insertIndex; insertIndex = num2; } } Data->Heap[insertIndex] = node; Data->Table[node.TableIndex].HeapIndex = insertIndex; } private unsafe void InsertAndBubbleUp(HeapNode<T> node, int insertIndex) { while (insertIndex != 0) { int num = (insertIndex - 1) / 2; HeapNode<T> heapNode = Data->Heap[num]; if (Data->Comparator.Compare(heapNode.Item, node.Item) <= 0) { break; } Data->Heap[insertIndex] = heapNode; Data->Table[heapNode.TableIndex].HeapIndex = insertIndex; insertIndex = num; } Data->Heap[insertIndex] = node; Data->Table[node.TableIndex].HeapIndex = insertIndex; } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] private void IsValidIndexInternal(NativeHeapIndex index, ref bool result, ref int errorCode) { } } internal struct TableValue { internal int HeapIndex; } internal struct HeapData<T, U> where T : unmanaged { internal int Count; internal int Capacity; internal unsafe HeapNode<T>* Heap; internal unsafe TableValue* Table; internal U Comparator; } internal struct HeapNode<T> where T : unmanaged { internal T Item; internal int TableIndex; } internal static class NativeListExtensions { internal static void Insert<T>(this ref UnsafeList<T> self, int index, T element) where T : unmanaged { self.InsertRangeWithBeginEnd(index, index + 1); self[index] = element; } public unsafe static int AddOrdered<T>(this ref UnsafeList<T> self, T item, IComparer<T> comparer) where T : unmanaged { int num = NativeSortExtension.BinarySearch<T, IComparer<T>>(self.Ptr, self.Length, item, comparer); if (num < 0) { num = ~num; } self.Insert(num, item); return num; } public static int FindIndex<T>(this in UnsafeList<T> self, Predicate<T> predicate) where T : unmanaged { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < self.Length; i++) { if (predicate(self[i])) { return i; } } return -1; } } } namespace PathfindingLib.Patches { internal static class PatchEntranceTeleport { internal static List<EntranceTeleport> allEntranceTeleports = new List<EntranceTeleport>(); [HarmonyPostfix] [HarmonyPatch(typeof(EntranceTeleport), "Awake")] private static void AwakePostfix(EntranceTeleport __instance) { allEntranceTeleports.Add(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(NetworkBehaviour), "OnDestroy")] private static void DestroyPostfix(NetworkBehaviour __instance) { EntranceTeleport val = (EntranceTeleport)(object)((__instance is EntranceTeleport) ? __instance : null); if (val != null) { allEntranceTeleports.Remove(val); SmartPathLinks.UnregisterEntranceTeleport(val); } } [HarmonyPostfix] [HarmonyPatch(typeof(RoundManager), "SetExitIDs")] private static void SetExitIDsPostfix() { foreach (EntranceTeleport allEntranceTeleport in allEntranceTeleports) { if (!((Behaviour)allEntranceTeleport).isActiveAndEnabled) { continue; } foreach (EntranceTeleport allEntranceTeleport2 in allEntranceTeleports) { if (((Behaviour)allEntranceTeleport2).isActiveAndEnabled && allEntranceTeleport.entranceId == allEntranceTeleport2.entranceId && allEntranceTeleport.isEntranceToBuilding != allEntranceTeleport2.isEntranceToBuilding) { SmartPathLinks.RegisterEntranceTeleport(allEntranceTeleport, allEntranceTeleport2.entrancePoint); break; } } } } } [HarmonyPatch(typeof(MineshaftElevatorController))] internal static class PatchMineshaftElevatorController { [HarmonyPostfix] [HarmonyPatch("OnEnable")] private static void OnEnablePostfix(MineshaftElevatorController __instance) { MineshaftElevatorAdapter mineshaftElevatorAdapter = default(MineshaftElevatorAdapter); if (((Component)__instance).TryGetComponent<MineshaftElevatorAdapter>(ref mineshaftElevatorAdapter)) { ((Behaviour)mineshaftElevatorAdapter).enabled = true; } mineshaftElevatorAdapter = ((Component)__instance).gameObject.AddComponent<MineshaftElevatorAdapter>(); mineshaftElevatorAdapter.controller = __instance; } [HarmonyPostfix] [HarmonyPatch("OnDisable")] private static void OnDisablePostfix(MineshaftElevatorController __instance) { MineshaftElevatorAdapter mineshaftElevatorAdapter = default(MineshaftElevatorAdapter); if (((Component)__instance).TryGetComponent<MineshaftElevatorAdapter>(ref mineshaftElevatorAdapter)) { ((Behaviour)mineshaftElevatorAdapter).enabled = false; } } } [HarmonyPatch(typeof(NavMeshSurface))] internal static class PatchNavMeshSurface { private static readonly MethodInfo m_BeginNavMeshWrite = typeof(NavMeshLock).GetMethod("BeginWrite", BindingFlags.Static | BindingFlags.Public); private static readonly MethodInfo m_EndNavMeshWrite = typeof(NavMeshLock).GetMethod("EndWrite", BindingFlags.Static | BindingFlags.Public); [HarmonyTranspiler] [HarmonyPatch(typeof(NavMeshSurface), "BuildNavMesh")] [HarmonyPatch(typeof(NavMeshSurface), "AddData")] [HarmonyPatch(typeof(NavMeshSurface), "RemoveData")] private static IEnumerable<CodeInstruction> LockWriteForDurationOfMethodTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown return new ILInjector(instructions).Insert(new CodeInstruction(OpCodes.Call, (object)m_BeginNavMeshWrite)).GoToEnd().ReverseFind(ILMatcher.Opcode(OpCodes.Ret)) .Insert(new CodeInstruction(OpCodes.Call, (object)m_EndNavMeshWrite)) .ReleaseInstructions(); } [HarmonyTranspiler] [HarmonyPatch("UpdateDataIfTransformChanged")] private static IEnumerable<CodeInstruction> UpdateDataIfTransformChangedTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Ldarg(0), ILMatcher.Call(typeof(NavMeshSurface).GetMethod("RemoveData"), "UpdateDataIfTransformChangedTranspiler", "E:\\Development\\Lethal Company\\Projects\\PathfindingLib\\PathfindingLib\\Patches\\PatchNavMeshSurface.cs", 43)); if (!iLInjector.IsValid) { PathfindingLibPlugin.Instance.Logger.LogError((object)"Failed to find the call to RemoveData in NavMeshSurface.UpdateDataIfTransformChanged."); return instructions; } iLInjector.Insert(new CodeInstruction(OpCodes.Call, (object)m_BeginNavMeshWrite)).Find(ILMatcher.Ldarg(0), ILMatcher.Call(typeof(NavMeshSurface).GetMethod("AddData"), "UpdateDataIfTransformChangedTranspiler", "E:\\Development\\Lethal Company\\Projects\\PathfindingLib\\PathfindingLib\\Patches\\PatchNavMeshSurface.cs", 57)).GoToMatchEnd(); if (!iLInjector.IsValid) { PathfindingLibPlugin.Instance.Logger.LogError((object)"Failed to find the call to AddData in NavMeshSurface.UpdateDataIfTransformChanged."); return instructions; } return iLInjector.Insert(new CodeInstruction(OpCodes.Call, (object)m_EndNavMeshWrite)).ReleaseInstructions(); } [HarmonyTranspiler] [HarmonyPatch("UpdateNavMesh")] private static IEnumerable<CodeInstruction> UpdateNavMeshTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown return new ILInjector(instructions).Insert(new CodeInstruction(OpCodes.Call, (object)m_BeginNavMeshWrite)).Find(ILMatcher.Opcode(OpCodes.Ret)).Insert(new CodeInstruction(OpCodes.Dup, (object)null), new CodeInstruction(OpCodes.Call, (object)typeof(PatchNavMeshSurface).GetMethod("EndNavMeshWriteAtEndOfAsyncOperation", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[1] { typeof(AsyncOperation) }, null))) .ReleaseInstructions(); } private static void EndNavMeshWriteAtEndOfAsyncOperation(AsyncOperation operation) { operation.completed += delegate { NavMeshLock.EndWrite(); }; } } } namespace PathfindingLib.Patches.Native { internal static class PatchApplyCarveResults { [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate void ApplyCarveResultsDelegate(IntPtr thisNavMeshCarving); private static NativeDetour detour; private static ApplyCarveResultsDelegate original; internal static void Apply(IntPtr baseAddress) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown ulong num = 10899072uL; if (NativeFunctions.IsDebugBuild) { num = 19667088uL; } IntPtr intPtr = (IntPtr)((long)baseAddress + (long)num); IntPtr functionPointerForDelegate = Marshal.GetFunctionPointerForDelegate<ApplyCarveResultsDelegate>(ApplyCarveResultsDetour); detour = new NativeDetour(intPtr, functionPointerForDelegate); original = detour.GenerateTrampoline<ApplyCarveResultsDelegate>(); } private unsafe static void ApplyCarveResultsDetour(IntPtr thisNavMeshCarving) { ulong num = 0uL; ulong num2 = 0uL; if (NativeFunctions.IsDebugBuild) { num = *(ulong*)((long)thisNavMeshCarving + 56); num2 = *(ulong*)((long)thisNavMeshCarving + 64); } else { num = *(ulong*)((long)thisNavMeshCarving + 40); num2 = *(ulong*)((long)thisNavMeshCarving + 48); } bool num3 = num2 > num; if (num3) { NavMeshLock.BeginWrite(); } original(thisNavMeshCarving); if (num3) { NavMeshLock.EndWrite(); } } } internal static class PatchNavMeshAgent { [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate void AwakeFromLoadDelegate(IntPtr thisNavMeshAgent, int awakeFromLoadMode); private static NativeDetour awakeFromLoadDetour; private static AwakeFromLoadDelegate awakeFromLoadOriginal; internal static void Apply(IntPtr baseAddress) { HookAwakeFromLoad(baseAddress); } private static void HookAwakeFromLoad(IntPtr baseAddress) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown ulong num = 10725392uL; if (NativeFunctions.IsDebugBuild) { num = 19479072uL; } IntPtr intPtr = (IntPtr)((long)baseAddress + (long)num); IntPtr functionPointerForDelegate = Marshal.GetFunctionPointerForDelegate<AwakeFromLoadDelegate>(AwakeFromLoadDetour); awakeFromLoadDetour = new NativeDetour(intPtr, functionPointerForDelegate); awakeFromLoadOriginal = awakeFromLoadDetour.GenerateTrampoline<AwakeFromLoadDelegate>(); } private unsafe static void AwakeFromLoadDetour(IntPtr thisNavMeshAgent, int awakeFromLoadMode) { if (awakeFromLoadMode == 3) { long num = (NativeFunctions.IsDebugBuild ? 152 : 128); ref int reference = ref *(int*)((long)thisNavMeshAgent + num); int num2 = reference; string name = NativeFunctions.GetName(thisNavMeshAgent); if (num2 != -1 && ((uint)num2 & 0x2000000u) != 0) { PathfindingLibPlugin.Instance.Logger.LogWarning((object)("Prefabbed NavMeshAgent " + name + " unexpectedly had the non-smart navmesh area enabled. This may indicate that a mod is already using this navmesh area.")); } reference |= 33554432; PathfindingLibPlugin.Instance.Logger.LogDebug((object)$"Changed prefabbed NavMeshAgent {name}'s area mask from 0x{num2:X8} to 0x{reference:X8} to allow traversal of non-smart off-mesh links."); } awakeFromLoadOriginal(thisNavMeshAgent, awakeFromLoadMode); } } } namespace PathfindingLib.Jobs { public struct FindPathJob : IJob, IDisposable { [ReadOnly] [NativeDisableContainerSafetyRestriction] private NativeArray<NavMeshQuery> ThreadQueriesRef; [ReadOnly] private int AgentTypeID; [ReadOnly] private int AreaMask; [ReadOnly] private Vector3 Origin; [ReadOnly] private Vector3 Destination; [ReadOnly] [NativeSetThreadIndex] private int ThreadIndex; [WriteOnly] private NativeArray<PathQueryStatus> Status; [WriteOnly] private NativeArray<float> PathLength; public void Initialize(Vector3 origin, Vector3 destination, NavMeshAgent agent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) ThreadQueriesRef = PathfindingJobSharedResources.GetPerThreadQueriesArray(); AgentTypeID = agent.agentTypeID; AreaMask = agent.areaMask; Origin = origin; Destination = destination; ThreadIndex = -1; CreateArrays(); Status[0] = (PathQueryStatus)536870912; PathLength[0] = float.MaxValue; } private void CreateArrays() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (Status.Length != 1) { Status = new NativeArray<PathQueryStatus>(1, (Allocator)4, (NativeArrayOptions)1); PathLength = new NativeArray<float>(1, (Allocator)4, (NativeArrayOptions)1); } } private void DisposeArrays() { Status.Dispose(); PathLength.Dispose(); } public void Execute() { //IL_000c: 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) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Invalid comparison between Unknown and I4 //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Invalid comparison between Unknown and I4 //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Invalid comparison between Unknown and I4 //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Invalid comparison between Unknown and I4 //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) NavMeshQuery val = ThreadQueriesRef[ThreadIndex]; using NavMeshReadLocker navMeshReadLocker = new NavMeshReadLocker(); NavMeshLocation val2 = ((NavMeshQuery)(ref val)).MapLocation(Origin, SharedJobValues.OriginExtents, AgentTypeID, AreaMask); if (!((NavMeshQuery)(ref val)).IsValid(((NavMeshLocation)(ref val2)).polygon)) { Status[0] = (PathQueryStatus)int.MinValue; return; } Vector3 destinationExtents = SharedJobValues.DestinationExtents; NavMeshLocation val3 = ((NavMeshQuery)(ref val)).MapLocation(Destination, destinationExtents, AgentTypeID, AreaMask); if (!((NavMeshQuery)(ref val)).IsValid(val3)) { Status[0] = (PathQueryStatus)int.MinValue; return; } PathQueryStatus status = ((NavMeshQuery)(ref val)).BeginFindPath(val2, val3, AreaMask, default(NativeArray<float>)); if ((int)status.GetResult() == int.MinValue) { Status[0] = (PathQueryStatus)int.MinValue; return; } int num = default(int); while ((int)status.GetResult() == 536870912) { status = ((NavMeshQuery)(ref val)).UpdateFindPath(NavMeshLock.RecommendedUpdateFindPathIterationCount, ref num); navMeshReadLocker.Yield(); } int num2 = default(int); status = ((NavMeshQuery)(ref val)).EndFindPath(ref num2); if ((int)status.GetResult() != 1073741824) { Status[0] = (PathQueryStatus)int.MinValue; return; } NativeArray<PolygonId> val4 = new NativeArray<PolygonId>(num2, (Allocator)2, (NativeArrayOptions)1); num2 = ((NavMeshQuery)(ref val)).GetPathResult(NativeSlice<PolygonId>.op_Implicit(val4)); NativeArray<Vector3> straightPath = new NativeArray<Vector3>(NavMeshQueryUtils.RequiredCornerCount(num2), (Allocator)2, (NativeArrayOptions)1); try { NavMeshQuery query = val; ref Vector3 origin = ref Origin; ref Vector3 destination = ref Destination; NativeSlice<PolygonId> path = NativeSlice<PolygonId>.op_Implicit(val4); int straightPathCount; PathQueryStatus val5 = query.FindStraightPath(in origin, in destination, in path, num2, in straightPath, out straightPathCount); val4.Dispose(); navMeshReadLocker.Dispose(); if ((int)val5.GetResult() != 1073741824) { Status[0] = val5; return; } Vector3 val6 = straightPath[straightPathCount - 1]; if (math.distancesq(float3.op_Implicit(Destination), float3.op_Implicit(val6)) > 2.25f) { Status[0] = (PathQueryStatus)int.MinValue; return; } float num3 = 0f; for (int i = 1; i < straightPathCount; i++) { num3 += math.distance(float3.op_Implicit(straightPath[i - 1]), float3.op_Implicit(straightPath[i])); } PathLength[0] = num3; Status[0] = (PathQueryStatus)1073741824; } finally { ((IDisposable)straightPath).Dispose(); } } public PathQueryStatus GetStatus() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Status[0]; } public float GetPathLength() { return PathLength[0]; } public void Dispose() { DisposeArrays(); } } internal struct IndexAndSize { internal int index; internal int size; public IndexAndSize(int index, int size) { this.index = index; this.size = size; } internal readonly bool IsValid<T>(List<T> list) { if (index >= 0 && index < list.Count) { return index + size <= list.Count; } return false; } } public class PooledFindPathJob { private FindPathJob job; public ref FindPathJob Job => ref job; } public static class JobPools { private static readonly ObjectPool<PooledFindPathJob> findPathPool = new ObjectPool<PooledFindPathJob>((Func<PooledFindPathJob>)(() => new PooledFindPathJob()), (Action<PooledFindPathJob>)null, (Action<PooledFindPathJob>)null, (Action<PooledFindPathJob>)delegate(PooledFindPathJob j) { j.Job.Dispose(); }, true, 10, 10000); public static PooledFindPathJob GetFindPathJob() { return findPathPool.Get(); } public static void ReleaseFindPathJob(PooledFindPathJob job) { if (job == null) { PathfindingLibPlugin.Instance.Logger.LogError((object)$"Attempted to free a null job\n{new StackTrace()}"); } else { findPathPool.Release(job); } } } public static class PathfindingJobSharedResources { public const int MaximumPathPolygonCount = 4096; [NativeDisableContainerSafetyRestriction] private static NativeArray<NavMeshQuery> StaticThreadQueries; public static ref readonly NativeArray<NavMeshQuery> GetPerThreadQueriesArray() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) int threadIndexCount = JobsUtility.ThreadIndexCount; if (StaticThreadQueries.Length >= threadIndexCount) { return ref StaticThreadQueries; } Application.quitting -= DisposeQueries; NativeArray<NavMeshQuery> staticThreadQueries = default(NativeArray<NavMeshQuery>); staticThreadQueries..ctor(threadIndexCount, (Allocator)4, (NativeArrayOptions)1); for (int i = 0; i < StaticThreadQueries.Length; i++) { staticThreadQueries[i] = StaticThreadQueries[i]; } for (int j = StaticThreadQueries.Length; j < threadIndexCount; j++) { staticThreadQueries[j] = new NavMeshQuery(NavMeshWorld.GetDefaultWorld(), (Allocator)4, 4096); } StaticThreadQueries.Dispose(); StaticThreadQueries = staticThreadQueries; Application.quitting += DisposeQueries; return ref StaticThreadQueries; } private static void DisposeQueries() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Enumerator<NavMeshQuery> enumerator = StaticThreadQueries.GetEnumerator(); try { while (enumerator.MoveNext()) { NavMeshQuery current = enumerator.Current; ((NavMeshQuery)(ref current)).Dispose(); } } finally { ((IDisposable)enumerator).Dispose(); } StaticThreadQueries.Dispose(); Application.quitting -= DisposeQueries; } } internal static class SharedJobValues { internal const float MaximumOriginDistance = 5f; internal static readonly Vector3 OriginExtents = new Vector3(5f, 5f, 5f); internal const float MaximumEndpointDistance = 1.5f; internal const float MaximumEndpointDistanceSquared = 2.25f; internal static readonly Vector3 DestinationExtents = new Vector3(1.5f, 1.5f, 1.5f); } internal struct SmartPathfindingJob : IJob { internal struct PathResult { internal static readonly PathResult InProgress = new PathResult { linkIndex = int.MinValue, linkDestinationIndex = int.MinValue, pathLength = float.PositiveInfinity }; internal static readonly PathResult Failed = new PathResult { linkIndex = -1, linkDestinationIndex = -1, pathLength = float.PositiveInfinity }; internal int linkIndex; internal int linkDestinationIndex; internal float pathLength; } private struct PathfinderMemory : IDisposable { internal delegate void EdgeProcessor(in PathEdge edge); private bool initialized; internal readonly int vertexCount; private NativeArray<PathVertex> vertices; private NativeArray<PathEdge> edges; internal NativeHeap<HeapElement, HeapElementComparer> heap; public PathfinderMemory() { throw new NotImplementedException(); } public PathfinderMemory(int vertexCount) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) this.vertexCount = vertexCount; vertices = new NativeArray<PathVertex>(vertexCount, (Allocator)2, (NativeArrayOptions)0); edges = new NativeArray<PathEdge>(vertexCount * vertexCount, (Allocator)2, (NativeArrayOptions)0); for (int i = 0; i < vertexCount * vertexCount; i++) { int destinationIndex = i / vertexCount; int sourceIndex = i % vertexCount; edges[i] = new PathEdge(sourceIndex, destinationIndex); if (i < vertexCount) { vertices[i] = new PathVertex(i); } } heap = new NativeHeap<HeapElement, HeapElementComparer>((Allocator)2, vertexCount); initialized = true; } internal readonly bool HasPredecessors(int vertexIndex, in SmartPathfindingJob job) { for (int i = 0; i < vertexCount; i++) { ref PathEdge edge = ref GetEdge(i, vertexIndex); if (edge.isValid) { edge.CalculateCostIfMissing(in job); if (!float.IsNaN(edge.cost) && !float.IsInfinity(edge.cost)) { return true; } } } return false; } internal readonly void CalculatePredecessors(int vertexIndex, in SmartPathfindingJob job) { for (int i = 0; i < vertexCount; i++) { ref PathEdge edge = ref GetEdge(i, vertexIndex); if (edge.isValid) { edge.CalculateCostIfMissing(in job); } } } internal readonly void ForEachPredecessor(int vertexIndex, EdgeProcessor processor) { for (int i = 0; i < vertexCount; i++) { ref PathEdge edge = ref GetEdge(i, vertexIndex); if (edge.isValid && !float.IsNaN(edge.cost) && !float.IsInfinity(edge.cost)) { processor(in edge); } } } internal readonly bool HasSuccessors(int vertexIndex, in SmartPathfindingJob job) { for (int i = 0; i < vertexCount; i++) { ref PathEdge edge = ref GetEdge(vertexIndex, i); if (edge.isValid) { edge.CalculateCostIfMissing(in job); if (!float.IsNaN(edge.cost) && !float.IsInfinity(edge.cost)) { return true; } } } return false; } internal readonly void ForEachSuccessor(int vertexIndex, EdgeProcessor processor) { for (int i = 0; i < vertexCount; i++) { ref PathEdge edge = ref GetEdge(vertexIndex, i); if (edge.isValid && !float.IsNaN(edge.cost) && !float.IsInfinity(edge.cost)) { processor(in edge); } } } internal readonly int GetBestSuccessor(int vertexIndex, out float cost) { int result = -1; cost = float.PositiveInfinity; for (int i = 0; i < vertexCount; i++) { ref PathEdge edge = ref GetEdge(vertexIndex, i); if (edge.isValid && !float.IsNaN(edge.cost) && !float.IsInfinity(edge.cost)) { ref PathVertex vertex = ref GetVertex(edge.destination); float num = edge.cost + vertex.g; if (!(num >= cost)) { cost = num; result = edge.destination; } } } return result; } internal readonly ref PathEdge GetEdge(int source, int destination) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ref edges.GetRef<PathEdge>(destination * vertexCount + source); } internal readonly ref PathVertex GetVertex(int vertexIndex) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ref vertices.GetRef<PathVertex>(vertexIndex); } public void Dispose() { if (initialized) { initialized = false; vertices.Dispose(); edges.Dispose(); heap.Dispose(); } } } private struct PathEdge { internal bool isValid; internal readonly int source; internal readonly int destination; internal float cost; public PathEdge(int sourceIndex, int destinationIndex) { isValid = false; source = sourceIndex; destination = destinationIndex; cost = float.NaN; } internal void CalculateCostIfMissing(in SmartPathfindingJob job) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (isValid && float.IsNaN(cost)) { Vector3 vertexPosition = job.GetVertexPosition(source); Vector3 vertexPosition2 = job.GetVertexPosition(destination); float num = job.CalculateSinglePath(vertexPosition, vertexPosition2); if (num < 0.0001f) { num = 0.0001f; } cost = num; } } } private struct PathVertex : IDisposable { internal readonly record struct VertexKey : IComparable<VertexKey> { private readonly float key1; private readonly float key2; public VertexKey(float key1, float key2) { this.key1 = key1; this.key2 = key2; } public int CompareTo(VertexKey other) { int num = key1.CompareTo(other.key1); if (num == 0) { return key2.CompareTo(other.key2); } return num; } public static bool operator <(VertexKey left, VertexKey right) { return left.CompareTo(right) < 0; } public static bool operator >(VertexKey left, VertexKey right) { return left.CompareTo(right) > 0; } public static bool operator <=(VertexKey left, VertexKey right) { return left.CompareTo(right) <= 0; } public static bool operator >=(VertexKey left, VertexKey right) { return left.CompareTo(right) >= 0; } [CompilerGenerated] private bool PrintMembers(StringBuilder builder) { return false; } [CompilerGenerated] public void Deconstruct(out float key1, out float key2) { key1 = this.key1; key2 = this.key2; } } internal int index; internal NativeHeapIndex heapIndex; internal float heuristic; internal float g; internal float rhs; internal PathVertex(int index) { this.index = index; heapIndex = NativeHeapIndex.Invalid; heuristic = float.PositiveInfinity; g = float.PositiveInfinity; rhs = float.PositiveInfinity; } public void Dispose() { heuristic = float.NaN; g = float.NaN; rhs = float.NaN; } public readonly VertexKey CalculateKey() { float num = Mathf.Min(g, rhs); return new VertexKey(num + heuristic, num); } } private readonly record struct HeapElement { internal readonly int index; internal readonly PathVertex.VertexKey key; public HeapElement(int index, PathVertex.VertexKey key) { this.index = index; this.key = key; } [CompilerGenerated] private bool PrintMembers(StringBuilder builder) { return false; } [CompilerGenerated] public void Deconstruct(out int index, out PathVertex.VertexKey key) { index = this.index; key = this.key; } } [StructLayout(LayoutKind.Sequential, Size = 1)] private readonly struct HeapElementComparer : IComparer<HeapElement> { public int Compare(HeapElement x, HeapElement y) { return x.key.CompareTo(y.key); } } internal const int PlaceholderLinkIndex = int.MinValue; internal const float MinEdgeCost = 0.0001f; private const int MaxPathsToTest = 30; [ReadOnly] [NativeDisableContainerSafetyRestriction] private NativeArray<NavMeshQuery> ThreadQueriesRef; [ReadOnly] private int agentTypeID; [ReadOnly] private int areaMask; [ReadOnly] private Vector3 start; [ReadOnly] [NativeDisableParallelForRestriction] private NativeArray<Vector3> goals; [ReadOnly] private int goalCount; [ReadOnly] [NativeDisableParallelForRestriction] private NativeArray<Vector3> linkOrigins; [ReadOnly] [NativeDisableParallelForRestriction] private NativeArray<IndexAndSize> linkDestinationSlices; [ReadOnly] [NativeDisableParallelForRestriction] private NativeArray<Vector3> linkDestinations; [ReadOnly] [NativeDisableParallelForRestriction] private NativeArray<int> linkDestinationCostOffsets; [ReadOnly] [NativeDisableParallelForRestriction] private NativeArray<float> linkDestinationCosts; [ReadOnly] private int linkCount; [ReadOnly] private int linkDestinationCount; [ReadOnly] private int vertexCount; [ReadOnly] [NativeSetThreadIndex] private int threadIndex; [WriteOnly] internal NativeArray<PathResult> results; private readonly int LinkDestinationsOffset => linkCount; private readonly int StartVertexIndex => vertexCount - 2; private readonly int GoalVertexIndex => vertexCount - 1; internal void Initialize(SmartPathJobDataContainer data) { //IL_0006: Unknow