using System;
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.Patches;
using PathfindingLib.Patches.Native;
using PathfindingLib.Utilities;
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.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("0.0.14")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.14.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace PathfindingLib
{
[BepInPlugin("Zaggy1024.PathfindingLib", "PathfindingLib", "0.0.14")]
public class PathfindingLibPlugin : BaseUnityPlugin
{
public const string PluginName = "PathfindingLib";
public const string PluginGUID = "Zaggy1024.PathfindingLib";
public const string PluginVersion = "0.0.14";
private readonly Harmony harmony = new Harmony("Zaggy1024.PathfindingLib");
internal static PathfindingLibPlugin Instance { get; private set; }
internal ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;
public void Awake()
{
Instance = this;
ApplyAllNativePatches();
harmony.PatchAll(typeof(PatchNavMeshSurface));
}
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()
{
PatchApplyCarvingResults.Apply(GetUnityPlayerModule().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;
}
}
public static class NavMeshQueryUtils
{
public const int RecommendedCornerCount = 128;
private static float CrossMagnitude(float3 u, float3 v)
{
//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)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
return u.z * v.x - u.x * v.z;
}
public static PathQueryStatus FindStraightPath(NavMeshQuery query, float3 startPos, float3 endPos, NativeSlice<PolygonId> path, int pathSize, NativeArray<NavMeshLocation> straightPath, out int straightPathCount)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: 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_0026: 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_0034: 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)
//IL_0050: 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)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: 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_0305: Unknown result type (might be due to invalid IL or missing references)
//IL_030b: Unknown result type (might be due to invalid IL or missing references)
//IL_030e: Unknown result type (might be due to invalid IL or missing references)
//IL_0311: Unknown result type (might be due to invalid IL or missing references)
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: 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_00a9: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: 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)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0161: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: 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_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: 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_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_0296: Unknown result type (might be due to invalid IL or missing references)
//IL_0298: Unknown result type (might be due to invalid IL or missing references)
//IL_029d: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_021c: Unknown result type (might be due to invalid IL or missing references)
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
//IL_0220: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_0233: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: Unknown result type (might be due to invalid IL or missing references)
//IL_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Unknown result type (might be due to invalid IL or missing references)
//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
straightPathCount = 0;
if (((NavMeshQuery)(ref query)).IsValid(path[0]))
{
NavMeshLocation lastCorner = (straightPath[0] = ((NavMeshQuery)(ref query)).CreateLocation(float3.op_Implicit(startPos), path[0]));
int num = 0;
int n = 1;
if (pathSize > 1)
{
Matrix4x4 val2 = ((NavMeshQuery)(ref query)).PolygonWorldToLocalMatrix(path[0]);
Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint(float3.op_Implicit(startPos));
Vector3 val4 = default(Vector3);
((Vector3)(ref val4))..ctor(0f, 0f, 0f);
Vector3 val5 = default(Vector3);
((Vector3)(ref val5))..ctor(0f, 0f, 0f);
int num2 = -1;
int num3 = -1;
Vector3 val8 = default(Vector3);
Vector3 val7 = default(Vector3);
for (int i = 1; i <= pathSize; i++)
{
Matrix4x4 val6 = ((NavMeshQuery)(ref query)).PolygonWorldToLocalMatrix(path[num]);
if (i == pathSize)
{
val8 = (val7 = ((Matrix4x4)(ref val6)).MultiplyPoint(float3.op_Implicit(endPos)));
}
else
{
if (!((NavMeshQuery)(ref query)).GetPortalPoints(path[i - 1], path[i], ref val8, ref val7))
{
return (PathQueryStatus)int.MinValue;
}
val8 = ((Matrix4x4)(ref val6)).MultiplyPoint(val8);
val7 = ((Matrix4x4)(ref val6)).MultiplyPoint(val7);
}
val8 -= val3;
val7 -= val3;
if (CrossMagnitude(float3.op_Implicit(val8), float3.op_Implicit(val7)) < 0f)
{
Vector3 val9 = val7;
val7 = val8;
val8 = val9;
}
if (CrossMagnitude(float3.op_Implicit(val4), float3.op_Implicit(val7)) < 0f)
{
Matrix4x4 val10 = ((NavMeshQuery)(ref query)).PolygonLocalToWorldMatrix(path[num]);
Vector3 val11 = ((Matrix4x4)(ref val10)).MultiplyPoint(val3 + val4);
RetracePortals(query, num, num2, path, ref n, float3.op_Implicit(val11), ref lastCorner, straightPath);
if (n == straightPath.Length)
{
straightPathCount = n;
return (PathQueryStatus)1073741856;
}
val3 = ((Matrix4x4)(ref val6)).MultiplyPoint(val11);
((Vector3)(ref val4))..ctor(0f, 0f, 0f);
((Vector3)(ref val5))..ctor(0f, 0f, 0f);
i = (num = num2);
}
else if (CrossMagnitude(float3.op_Implicit(val5), float3.op_Implicit(val8)) > 0f)
{
Matrix4x4 val12 = ((NavMeshQuery)(ref query)).PolygonLocalToWorldMatrix(path[num]);
Vector3 val13 = ((Matrix4x4)(ref val12)).MultiplyPoint(val3 + val5);
RetracePortals(query, num, num3, path, ref n, float3.op_Implicit(val13), ref lastCorner, straightPath);
if (n == straightPath.Length)
{
straightPathCount = n;
return (PathQueryStatus)1073741856;
}
val3 = ((Matrix4x4)(ref val6)).MultiplyPoint(val13);
((Vector3)(ref val4))..ctor(0f, 0f, 0f);
((Vector3)(ref val5))..ctor(0f, 0f, 0f);
i = (num = num3);
}
else
{
if (CrossMagnitude(float3.op_Implicit(val4), float3.op_Implicit(val8)) >= 0f)
{
val4 = val8;
num2 = i;
}
if (CrossMagnitude(float3.op_Implicit(val5), float3.op_Implicit(val7)) <= 0f)
{
val5 = val7;
num3 = i;
}
}
}
}
if (n > 0 && ((NavMeshLocation)(ref lastCorner)).position == float3.op_Implicit(endPos))
{
n--;
}
RetracePortals(query, num, pathSize - 1, path, ref n, endPos, ref lastCorner, straightPath);
if (n == straightPath.Length)
{
straightPathCount = n;
return (PathQueryStatus)1073741904;
}
straightPathCount = n;
return (PathQueryStatus)1073741824;
}
return (PathQueryStatus)int.MinValue;
}
private static void RetracePortals(NavMeshQuery query, int startIndex, int endIndex, NativeSlice<PolygonId> path, ref int n, float3 termPos, ref NavMeshLocation lastCorner, NativeArray<NavMeshLocation> straightPath)
{
//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_001d: 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_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: 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)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: 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_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: 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)
Vector3 val = default(Vector3);
Vector3 val2 = default(Vector3);
for (int i = startIndex; i < endIndex - 1; i++)
{
NavMeshPolyTypes polygonType = ((NavMeshQuery)(ref query)).GetPolygonType(path[i]);
NavMeshPolyTypes polygonType2 = ((NavMeshQuery)(ref query)).GetPolygonType(path[i + 1]);
if (polygonType != polygonType2)
{
((NavMeshQuery)(ref query)).GetPortalPoints(path[i], path[i + 1], ref val, ref val2);
SegmentSegmentCPA(out var c, out var _, float3.op_Implicit(val), float3.op_Implicit(val2), float3.op_Implicit(((NavMeshLocation)(ref lastCorner)).position), termPos);
lastCorner = ((NavMeshQuery)(ref query)).CreateLocation(float3.op_Implicit(c), path[i + 1]);
straightPath[n] = lastCorner;
if (++n == straightPath.Length)
{
return;
}
}
}
lastCorner = ((NavMeshQuery)(ref query)).CreateLocation(float3.op_Implicit(termPos), path[endIndex]);
straightPath[n++] = lastCorner;
}
private static bool SegmentSegmentCPA(out float3 c0, out float3 c1, float3 p0, float3 p1, float3 q0, float3 q1)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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_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_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: 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)
//IL_0019: 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_001b: 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)
//IL_002a: 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_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: 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_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: 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_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
float3 val = p1 - p0;
float3 val2 = q1 - q0;
float3 val3 = p0 - q0;
float num = math.dot(val, val);
float num2 = math.dot(val, val2);
float num3 = math.dot(val2, val2);
float num4 = math.dot(val, val3);
float num5 = math.dot(val2, val3);
float num6 = num * num3 - num2 * num2;
float num7;
float num8;
if (num6 == 0f)
{
num7 = 0f;
num8 = num4 / num2;
}
else
{
num7 = (num2 * num5 - num3 * num4) / (num * num3 - num2 * num2);
num8 = (num * num5 - num2 * num4) / (num * num3 - num2 * num2);
}
c0 = math.lerp(p0, p1, num7);
c1 = math.lerp(q0, q1, num8);
return num6 != 0f;
}
}
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
{
private const string INVALID = "Injector is invalid";
private List<CodeInstruction> instructions = instructions.ToList();
private ILGenerator generator;
private int index;
private int matchEnd;
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)
{
matchEnd = index + 1;
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 void 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;
}
public IEnumerable<CodeInstruction> GetRelativeInstructions(int offset, int size)
{
for (int i = 0; i < size; i++)
{
yield return instructions[index + offset + i];
}
}
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 Label AddLabel()
{
if (generator == null)
{
throw new InvalidOperationException("No ILGenerator was provided");
}
Label label = generator.DefineLabel();
Instruction.labels.Add(label);
return label;
}
public ILInjector AddLabel(Label label)
{
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)
{
if (!IsValid)
{
throw new InvalidOperationException("Injector is invalid");
}
List<Label> labels = Instruction.labels;
this.instructions.InsertRange(index, instructions);
Instruction.labels.AddRange(labels);
labels.Clear();
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);
instructions.RemoveRange(start, size);
index = start;
matchEnd = start;
return this;
}
public ILInjector ReplaceLastMatch(params CodeInstruction[] instructions)
{
RemoveLastMatch();
Insert(instructions);
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);
static NotMatcher Not(ILMatcher matcher)
{
return new NotMatcher(matcher);
}
static OpcodeMatcher Opcode(OpCode opcode)
{
return new OpcodeMatcher(opcode);
}
static OpcodesMatcher Opcodes(params OpCode[] opcodes)
{
return new OpcodesMatcher(opcodes);
}
static OpcodeOperandMatcher OpcodeOperand(OpCode opcode, object operand)
{
return new OpcodeOperandMatcher(opcode, operand);
}
static InstructionMatcher Instruction(CodeInstruction instruction)
{
return new InstructionMatcher(instruction);
}
static LdargMatcher Ldarg(int? arg = null)
{
return new LdargMatcher(arg);
}
static LdlocMatcher Ldloc(int? loc = null)
{
return new LdlocMatcher(loc);
}
static StlocMatcher Stloc(int? loc = null)
{
return new StlocMatcher(loc);
}
static LdcI32Matcher Ldc(int? value = null)
{
return new LdcI32Matcher(value);
}
static BranchMatcher Branch()
{
return new BranchMatcher();
}
static OpcodeOperandMatcher Ldfld(FieldInfo field)
{
if (field == null)
{
PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldfld() was null\n{new StackTrace()}");
}
return new OpcodeOperandMatcher(OpCodes.Ldfld, field);
}
static OpcodeOperandMatcher Ldsfld(FieldInfo field)
{
if (field == null)
{
PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Ldsfld() was null\n{new StackTrace()}");
}
return new OpcodeOperandMatcher(OpCodes.Ldsfld, field);
}
static OpcodeOperandMatcher Stfld(FieldInfo field)
{
if (field == null)
{
PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stfld() was null\n{new StackTrace()}");
}
return new OpcodeOperandMatcher(OpCodes.Stfld, field);
}
static OpcodeOperandMatcher Stsfld(FieldInfo field)
{
if (field == null)
{
PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Field passed to ILMatcher.Stsfld() was null\n{new StackTrace()}");
}
return new OpcodeOperandMatcher(OpCodes.Stsfld, field);
}
static OpcodeOperandMatcher Callvirt(MethodBase method)
{
if (method == null)
{
PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Callvirt() was null\n{new StackTrace()}");
}
return OpcodeOperand(OpCodes.Callvirt, method);
}
static OpcodeOperandMatcher Call(MethodBase method)
{
if (method == null)
{
PathfindingLibPlugin.Instance.Logger.LogWarning((object)$"Method passed to ILMatcher.Call() was null\n{new StackTrace()}");
}
return OpcodeOperand(OpCodes.Call, method);
}
static PredicateMatcher Predicate(Func<CodeInstruction, bool> predicate)
{
return new PredicateMatcher(predicate);
}
static PredicateMatcher 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 || !instruction.GetLdcI32().HasValue)
{
return instruction.GetLdcI32() == value;
}
return true;
}
}
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 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)
{
MethodInfo obj = (MethodInfo)instruction.operand;
int num = obj.GetParameters().Length;
if (!obj.IsStatic)
{
num++;
}
return num;
}
if (instruction.opcode == OpCodes.Ret)
{
return 1;
}
return instruction.opcode.StackBehaviourPop switch
{
StackBehaviour.Pop0 => 0,
StackBehaviour.Pop1 => 1,
StackBehaviour.Pop1_pop1 => 2,
StackBehaviour.Popi => 1,
StackBehaviour.Popi_pop1 => 2,
StackBehaviour.Popi_popi => 2,
StackBehaviour.Popi_popi8 => 2,
StackBehaviour.Popi_popi_popi => 3,
StackBehaviour.Popi_popr4 => 2,
StackBehaviour.Popi_popr8 => 2,
StackBehaviour.Popref => 1,
StackBehaviour.Popref_pop1 => 2,
StackBehaviour.Popref_popi => 2,
StackBehaviour.Popref_popi_popi => 3,
StackBehaviour.Popref_popi_popi8 => 3,
StackBehaviour.Popref_popi_popr4 => 3,
StackBehaviour.Popref_popi_popr8 => 3,
StackBehaviour.Popref_popi_popref => 3,
StackBehaviour.Varpop => throw new NotImplementedException($"Variable pop on non-call instruction '{instruction}'"),
StackBehaviour.Popref_popi_pop1 => 3,
_ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"),
};
}
public static int PushCount(this CodeInstruction instruction)
{
if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt)
{
if (((MethodInfo)instruction.operand).ReturnType == typeof(void))
{
return 0;
}
return 1;
}
return instruction.opcode.StackBehaviourPush switch
{
StackBehaviour.Push0 => 0,
StackBehaviour.Push1 => 1,
StackBehaviour.Push1_push1 => 2,
StackBehaviour.Pushi => 1,
StackBehaviour.Pushi8 => 1,
StackBehaviour.Pushr4 => 1,
StackBehaviour.Pushr8 => 1,
StackBehaviour.Pushref => 1,
StackBehaviour.Varpush => throw new NotImplementedException($"Variable push on non-call instruction '{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.Patches
{
[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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Expected O, but got Unknown
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Expected O, but got Unknown
ILInjector iLInjector = new ILInjector(instructions).Find(ILMatcher.Ldarg(0), ILMatcher.Call(typeof(NavMeshSurface).GetMethod("RemoveData")));
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"))).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 PatchApplyCarvingResults
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ApplyCarvingResultsDelegate(IntPtr thisNavMeshCarving);
private static readonly bool debug = Debug.isDebugBuild;
private static NativeDetour detour;
private static ApplyCarvingResultsDelegate 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 (debug)
{
num = 19667088uL;
}
IntPtr intPtr = (IntPtr)((long)baseAddress + (long)num);
IntPtr functionPointerForDelegate = Marshal.GetFunctionPointerForDelegate<ApplyCarvingResultsDelegate>(ApplyCarvingResultsDetour);
detour = new NativeDetour(intPtr, functionPointerForDelegate);
original = detour.GenerateTrampoline<ApplyCarvingResultsDelegate>();
}
private unsafe static void ApplyCarvingResultsDetour(IntPtr thisNavMeshCarving)
{
ulong num = 0uL;
ulong num2 = 0uL;
if (debug)
{
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();
}
}
}
}
namespace PathfindingLib.Jobs
{
public struct FindPathJob : IJob, IDisposable
{
private const float MaximumOriginDistance = 5f;
private const float MaximumEndpointDistance = 1.5f;
private const float MaximumEndpointDistanceSquared = 2.25f;
[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_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_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_0043: 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_004d: 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_0083: 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_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: 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_00dd: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Invalid comparison between Unknown and I4
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Invalid comparison between Unknown and I4
//IL_010c: 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_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Invalid comparison between Unknown and I4
//IL_015b: 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_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: 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_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Invalid comparison between Unknown and I4
//IL_01df: Unknown result type (might be due to invalid IL or missing references)
//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_0232: Unknown result type (might be due to invalid IL or missing references)
//IL_0237: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0244: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Unknown result type (might be due to invalid IL or missing references)
NavMeshQuery query = ThreadQueriesRef[ThreadIndex];
using PathfindingLib.Utilities.NavMeshReadLocker navMeshReadLocker = new PathfindingLib.Utilities.NavMeshReadLocker();
Vector3 val = new Vector3(5f, 5f, 5f);
NavMeshLocation val2 = ((NavMeshQuery)(ref query)).MapLocation(Origin, val, AgentTypeID, AreaMask);
if (!((NavMeshQuery)(ref query)).IsValid(((NavMeshLocation)(ref val2)).polygon))
{
Status[0] = (PathQueryStatus)int.MinValue;
return;
}
Vector3 val3 = new Vector3(1.5f, 1.5f, 1.5f);
NavMeshLocation val4 = ((NavMeshQuery)(ref query)).MapLocation(Destination, val3, AgentTypeID, AreaMask);
if (!((NavMeshQuery)(ref query)).IsValid(val4))
{
Status[0] = (PathQueryStatus)int.MinValue;
return;
}
PathQueryStatus status = ((NavMeshQuery)(ref query)).BeginFindPath(val2, val4, 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 query)).UpdateFindPath(NavMeshLock.RecommendedUpdateFindPathIterationCount, ref num);
navMeshReadLocker.Yield();
}
int num2 = default(int);
status = ((NavMeshQuery)(ref query)).EndFindPath(ref num2);
if ((int)status.GetResult() != 1073741824)
{
Status[0] = (PathQueryStatus)int.MinValue;
return;
}
NativeArray<PolygonId> val5 = new NativeArray<PolygonId>(num2, (Allocator)2, (NativeArrayOptions)1);
((NavMeshQuery)(ref query)).GetPathResult(NativeSlice<PolygonId>.op_Implicit(val5));
NativeArray<NavMeshLocation> straightPath = new NativeArray<NavMeshLocation>(128, (Allocator)2, (NativeArrayOptions)1);
try
{
int straightPathCount;
PathQueryStatus val6 = NavMeshQueryUtils.FindStraightPath(query, float3.op_Implicit(Origin), float3.op_Implicit(Destination), NativeSlice<PolygonId>.op_Implicit(val5), num2, straightPath, out straightPathCount);
val5.Dispose();
navMeshReadLocker.Dispose();
if ((int)val6.GetResult() != 1073741824)
{
Status[0] = val6;
return;
}
NavMeshLocation val7 = straightPath[straightPathCount - 1];
Vector3 val8 = ((NavMeshLocation)(ref val7)).position - Destination;
if (((Vector3)(ref val8)).sqrMagnitude > 2.25f)
{
Status[0] = (PathQueryStatus)int.MinValue;
return;
}
float num3 = 0f;
for (int i = 1; i < straightPathCount; i++)
{
float num4 = num3;
val7 = straightPath[i - 1];
Vector3 position = ((NavMeshLocation)(ref val7)).position;
val7 = straightPath[i];
num3 = num4 + Vector3.Distance(position, ((NavMeshLocation)(ref val7)).position);
}
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();
}
}
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;
}
}
}
namespace PathfindingLib.API
{
public static class NavMeshLock
{
private const int recommendedSliceCount = 128;
[ThreadStatic]
private static int threadState = 0;
private static readonly object conditionVariable = new object();
private static int readersActive = 0;
private static int writersWaiting = 0;
private static bool writerActive = false;
public static int RecommendedUpdateFindPathIterationCount => 128;
public static void BeginWrite()
{
if (threadState < 0)
{
throw CreateAndPrintInvalidOperationException("Cannot begin a navmesh write while a read is ongoing.");
}
if (threadState++ > 0)
{
return;
}
lock (conditionVariable)
{
writersWaiting++;
while (readersActive > 0 || writerActive)
{
Monitor.Wait(conditionVariable);
}
writersWaiting--;
writerActive = true;
}
}
public static void EndWrite()
{
if (threadState <= 0)
{
throw CreateAndPrintInvalidOperationException("A navmesh write has not been started.");
}
if (--threadState > 0)
{
return;
}
lock (conditionVariable)
{
if (!writerActive)
{
throw CreateAndPrintInvalidOperationException("EndWrite() was called without first calling BeginWrite.");
}
writerActive = false;
Monitor.PulseAll(conditionVariable);
}
}
public static void BeginRead()
{
if (threadState > 0)
{
throw CreateAndPrintInvalidOperationException("Cannot begin a navmesh read while a write is ongoing.");
}
if (threadState-- < 0)
{
return;
}
lock (conditionVariable)
{
while (writersWaiting > 0 || writerActive)
{
Monitor.Wait(conditionVariable);
}
readersActive++;
}
}
public static void EndRead()
{
if (threadState >= 0)
{
throw CreateAndPrintInvalidOperationException("A navmesh read has not been started.");
}
if (++threadState < 0)
{
return;
}
lock (conditionVariable)
{
readersActive--;
if (readersActive < 0)
{
throw CreateAndPrintInvalidOperationException("EndRead() was called more times than BeginRead.");
}
if (readersActive == 0)
{
Monitor.PulseAll(conditionVariable);
}
}
}
public static void YieldRead()
{
EndRead();
BeginRead();
}
private static InvalidOperationException CreateAndPrintInvalidOperationException(string message)
{
PathfindingLibPlugin.Instance.Logger.LogError((object)message);
PathfindingLibPlugin.Instance.Logger.LogError((object)"Check Unity's Player.log to see the exception's stack trace.");
return new InvalidOperationException(message);
}
}
[Obsolete("Use PathfindingLib.Utilities.NavMeshReadLocker")]
internal class NavMeshReadLocker : IDisposable
{
private bool locked;
public NavMeshReadLocker()
{
NavMeshLock.BeginRead();
locked = true;
}
public void Yield()
{
NavMeshLock.YieldRead();
}
public void Dispose()
{
if (locked)
{
locked = false;
NavMeshLock.EndRead();
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}