Decompiled source of ILUtils v1.0.4

plugins/ILUtils.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using ILUtils.HarmonyXtensions;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("DBJ")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("BepInEx Transpiler Tools")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4+d27649a62bda6708d5643ed084212d173d522337")]
[assembly: AssemblyProduct("ILUtils")]
[assembly: AssemblyTitle("com.github.decibillyjoel.ILUtils")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/DecibillyJoel/ILUtils")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.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.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;
		}
	}
}
internal static class BepPluginInfo
{
	public const string PLUGIN_GUID = "com.github.decibillyjoel.ILUtils";

	public const string PLUGIN_NAME = "ILUtils";

	public const string PLUGIN_TS_TEAM = "DBJ";

	public const string PLUGIN_VERSION = "1.0.4";
}
namespace ILUtils
{
	public static class ILPatterns
	{
		public static int? StackSizeDelta(StackBehaviour stackBehaviour)
		{
			switch (stackBehaviour)
			{
			case StackBehaviour.Pop0:
				return 0;
			case StackBehaviour.Pop1:
				return -1;
			case StackBehaviour.Pop1_pop1:
				return -2;
			case StackBehaviour.Popi:
				return -1;
			case StackBehaviour.Popi_pop1:
				return -2;
			case StackBehaviour.Popi_popi:
				return -2;
			case StackBehaviour.Popi_popi8:
				return -2;
			case StackBehaviour.Popi_popi_popi:
				return -3;
			case StackBehaviour.Popi_popr4:
				return -2;
			case StackBehaviour.Popi_popr8:
				return -2;
			case StackBehaviour.Popref:
				return -1;
			case StackBehaviour.Popref_pop1:
				return -2;
			case StackBehaviour.Popref_popi:
				return -2;
			case StackBehaviour.Popref_popi_popi:
				return -3;
			case StackBehaviour.Popref_popi_popi8:
				return -3;
			case StackBehaviour.Popref_popi_popr4:
				return -3;
			case StackBehaviour.Popref_popi_popr8:
				return -3;
			case StackBehaviour.Popref_popi_popref:
				return -3;
			case StackBehaviour.Push0:
				return 0;
			case StackBehaviour.Push1:
				return 1;
			case StackBehaviour.Push1_push1:
				return 2;
			case StackBehaviour.Pushi:
				return 1;
			case StackBehaviour.Pushi8:
				return 1;
			case StackBehaviour.Pushr4:
				return 1;
			case StackBehaviour.Pushr8:
				return 1;
			case StackBehaviour.Pushref:
				return 1;
			case StackBehaviour.Popref_popi_pop1:
				return -3;
			case StackBehaviour.Varpop:
			case StackBehaviour.Varpush:
				return null;
			default:
				throw new ArgumentOutOfRangeException($"stackBehaviour {stackBehaviour} is an invalid value");
			}
		}

		public static int? StackSizeDelta(OpCode opCode, object operand)
		{
			if (opCode == OpCodes.Calli)
			{
				return null;
			}
			if (opCode.FlowControl == FlowControl.Call)
			{
				MethodInfo methodInfo = operand as MethodInfo;
				if (methodInfo == null)
				{
					return null;
				}
				int num = -methodInfo.GetParameters().Count();
				if (opCode != OpCodes.Newobj && methodInfo.CallingConvention.HasFlag(CallingConventions.HasThis) && !methodInfo.CallingConvention.HasFlag(CallingConventions.ExplicitThis))
				{
					num--;
				}
				if (opCode == OpCodes.Newobj || methodInfo.ReturnType != typeof(void))
				{
					num++;
				}
				return num;
			}
			int? num2 = StackSizeDelta(opCode.StackBehaviourPush);
			int? num3 = StackSizeDelta(opCode.StackBehaviourPop);
			if (!num2.HasValue || !num3.HasValue)
			{
				return null;
			}
			return num2 + num3;
		}

		public static int? StackSizeDelta(CodeInstruction code)
		{
			return StackSizeDelta(code.opcode, code.operand);
		}

		public static bool EmptiesStack(OpCode opcode)
		{
			FlowControl flowControl = opcode.FlowControl;
			if (flowControl == FlowControl.Branch || (uint)(flowControl - 7) <= 1u)
			{
				return true;
			}
			return false;
		}

		public static bool EmptiesStack(CodeInstruction code)
		{
			return EmptiesStack(code.opcode);
		}

		public static Func<CodeInstruction, int, bool> NextEmptyStack(int startSize = 0)
		{
			return delegate(CodeInstruction code, int index)
			{
				if (EmptiesStack(code))
				{
					return true;
				}
				int num = StackSizeDelta(code) ?? throw new ArgumentException($"[ILStepper.ILPatterns.NextEmptyStack] Encountered uncountable instruction [{index}] {code}");
				return (startSize += num) == 0;
			};
		}
	}
	public class ILStepper
	{
		public readonly List<CodeInstruction> Instructions;

		public int CurrentIndex;

		public readonly ILGenerator Generator;

		public readonly Dictionary<int, LocalVariableInfo> Locals;

		public readonly Dictionary<int, Label> Labels;

		public CodeInstruction CurrentInstruction => Instructions[CurrentIndex];

		public OpCode CurrentOpCode => CurrentInstruction.opcode;

		public object? CurrentOperand => CurrentInstruction.operand;

		public ILStepper(IEnumerable<CodeInstruction> codes, ILGenerator generator, MethodBase original, int index = 0)
		{
			Instructions = codes.ToList();
			CurrentIndex = index;
			Generator = generator;
			Locals = (from code in Instructions
				select code.operand as LocalVariableInfo into local
				where local != null
				select local).Distinct().ToDictionary((LocalVariableInfo local) => local.LocalIndex, (LocalVariableInfo local) => local);
			Labels = Instructions.SelectMany((CodeInstruction code) => code.labels).Distinct().ToDictionary((Label label) => label.GetHashCode(), (Label label) => label);
			CollectionExtensions.DoIf<LocalVariableInfo>((IEnumerable<LocalVariableInfo>)original.GetMethodBody().LocalVariables, (Func<LocalVariableInfo, bool>)((LocalVariableInfo local) => !Locals.ContainsKey(local.LocalIndex)), (Action<LocalVariableInfo>)delegate(LocalVariableInfo local)
			{
				Locals.Add(local.LocalIndex, local);
			});
			Instructions.ForEach(delegate(CodeInstruction code)
			{
				TrySetLocal(code, code);
			});
		}

		public Label DeclareLabel()
		{
			Label label = Generator.DefineLabel();
			Labels.Add(label.GetHashCode(), label);
			return label;
		}

		public LocalVariableInfo DeclareLocal(Type type, bool pinned = false)
		{
			LocalVariableInfo localVariableInfo = Generator.DeclareLocal(type, pinned);
			Locals.Add(localVariableInfo.LocalIndex, localVariableInfo);
			return localVariableInfo;
		}

		public LocalVariableInfo? TryGetLocal(int localIndex)
		{
			if (!Locals.TryGetValue(localIndex, out LocalVariableInfo value))
			{
				return null;
			}
			return value;
		}

		public LocalVariableInfo? TryGetLocal(CodeInstruction codeWithLocal)
		{
			if (!CodeInstructionExtensions.IsLdloc(codeWithLocal, (LocalBuilder)null) && !CodeInstructionExtensions.IsStloc(codeWithLocal, (LocalBuilder)null))
			{
				return null;
			}
			return TryGetLocal(codeWithLocal.LocalIndex());
		}

		public LocalVariableInfo GetLocal(int localIndex, string errorMessage = "No such local variable!")
		{
			return TryGetLocal(localIndex) ?? throw new Exception($"[ILStepper.ILStepper.GetLocal] [{localIndex}] | {errorMessage}");
		}

		public LocalVariableInfo GetLocal(CodeInstruction codeWithLocal, string errorMessage = "No such local variable!")
		{
			return TryGetLocal(codeWithLocal) ?? throw new Exception($"[ILStepper.ILStepper.GetLocal] [{codeWithLocal}] | {errorMessage}");
		}

		public LocalVariableInfo? TrySetLocal(CodeInstruction code, LocalVariableInfo local)
		{
			CodeInstruction val;
			if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null))
			{
				val = CodeInstructionPolyfills.LoadLocal(local, code.opcode == OpCodes.Ldloca || code.opcode == OpCodes.Ldloca_S);
			}
			else
			{
				if (!CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null))
				{
					return null;
				}
				val = CodeInstructionPolyfills.StoreLocal(local);
			}
			code.opcode = val.opcode;
			code.operand = val.operand;
			return local;
		}

		public LocalVariableInfo? TrySetLocal(CodeInstruction code, int localIndex)
		{
			LocalVariableInfo localVariableInfo = TryGetLocal(localIndex);
			if (localVariableInfo == null)
			{
				return null;
			}
			return TrySetLocal(code, localVariableInfo);
		}

		public LocalVariableInfo? TrySetLocal(CodeInstruction code, CodeInstruction codeWithLocal)
		{
			LocalVariableInfo localVariableInfo = TryGetLocal(codeWithLocal);
			if (localVariableInfo == null)
			{
				return null;
			}
			return TrySetLocal(code, localVariableInfo);
		}

		public LocalVariableInfo SetLocal(CodeInstruction code, LocalVariableInfo local, string errorMessage = "Could not set local!")
		{
			return TrySetLocal(code, local) ?? throw new Exception($"[ILStepper.ILStepper.SetLocal] [{code}, {local}] | {errorMessage}");
		}

		public LocalVariableInfo SetLocal(CodeInstruction code, int localIndex, string errorMessage = "Could not set local!")
		{
			return TrySetLocal(code, localIndex) ?? throw new Exception($"[ILStepper.ILStepperSetLocal] [{code}, {localIndex}] | {errorMessage}");
		}

		public LocalVariableInfo SetLocal(CodeInstruction code, CodeInstruction codeWithLocal, string errorMessage = "Could not set local!")
		{
			return TrySetLocal(code, codeWithLocal) ?? throw new Exception($"[ILStepper.ILStepperSetLocal] [{code}, {codeWithLocal}] | {errorMessage}");
		}

		public int? TryFindIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
		{
			index = (index ?? CurrentIndex) + offset + (reverse ? (-1) : 0);
			while (index >= 0 && index < Instructions.Count)
			{
				if (searchCondition(Instructions[index.Value], index.Value))
				{
					return index;
				}
				index += ((!reverse) ? 1 : (-1));
			}
			return null;
		}

		public int? TryFindIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
		{
			Func<CodeInstruction, bool> searchCondition2 = searchCondition;
			return TryFindIL((CodeInstruction code, int index) => searchCondition2(code), index, offset, reverse);
		}

		public int FindIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepperFindIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
		}

		public int FindIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepperFindIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
		}

		public int? TryGotoIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
		{
			index = TryFindIL(searchCondition, index, offset, reverse);
			CurrentIndex = index ?? CurrentIndex;
			return index;
		}

		public int? TryGotoIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
		{
			index = TryFindIL(searchCondition, index, offset, reverse);
			CurrentIndex = index ?? CurrentIndex;
			return index;
		}

		public int GotoIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return CurrentIndex = TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepper.GotoIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
		}

		public int GotoIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return CurrentIndex = TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepper.GotoIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
		}

		public int? TryFindIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1)
		{
			index = (index ?? CurrentIndex) + offset;
			if (index < leftBoundOffset || index > Instructions.Count - 1 + rightBoundOffset)
			{
				return null;
			}
			return index;
		}

		public int FindIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset) ?? throw new Exception($"[ILStepper.ILStepper.FindIndex] [{index + offset} ({index} + {offset}), {leftBoundOffset} (0 + {leftBoundOffset}), {Instructions.Count - 1 + rightBoundOffset} ({Instructions.Count - 1} + {rightBoundOffset})] | {errorMessage}");
		}

		public int? TryGotoIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1)
		{
			index = TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset);
			CurrentIndex = index ?? CurrentIndex;
			return index;
		}

		public int GotoIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return CurrentIndex = TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset) ?? throw new Exception($"[ILStepper.ILStepper.GotoIndex] [{index + offset} ({index} + {offset}), {leftBoundOffset} (0 + {leftBoundOffset}), {Instructions.Count - 1 + rightBoundOffset} ({Instructions.Count - 1} + {rightBoundOffset})] | {errorMessage}");
		}

		public List<CodeInstruction>? TryInsertIL(List<CodeInstruction> codeRange, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true)
		{
			index = TryFindIndex(index);
			if (!index.HasValue)
			{
				return null;
			}
			codeRange = ((IEnumerable<CodeInstruction>)codeRange).Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction code) => new CodeInstruction(code))).ToList();
			if (index < Instructions.Count && codeRange.Count > 0)
			{
				if (pinLabels)
				{
					CodeInstructionExtensions.MoveLabelsTo(Instructions[index.Value], codeRange[0]);
				}
				if (pinBlocks)
				{
					CodeInstructionExtensions.MoveBlocksTo(Instructions[index.Value], codeRange[0]);
				}
			}
			Instructions.InsertRange(index.Value, codeRange);
			if (shiftCurrentIndex && CurrentIndex >= index)
			{
				CurrentIndex += codeRange.Count;
			}
			return codeRange;
		}

		public List<CodeInstruction>? TryInsertIL(CodeInstruction? code, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true)
		{
			return TryInsertIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, shiftCurrentIndex, pinLabels, pinBlocks);
		}

		public List<CodeInstruction> InsertIL(List<CodeInstruction> codeRange, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return TryInsertIL(codeRange, index, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[ILStepper.ILStepper.InsertIL] [{0}, {1}, {2} ({3})] | {4}", codeRange, index, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage));
		}

		public List<CodeInstruction> InsertIL(CodeInstruction? code, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return TryInsertIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[ILStepper.ILStepper.InsertIL] [{0}, {1}, {2} ({3})] | {4}", code, index, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage));
		}

		public List<CodeInstruction>? TryRemoveIL(int? startIndex = null, int? endIndex = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true)
		{
			startIndex = TryFindIndex(startIndex);
			endIndex = TryFindIndex(endIndex);
			if (!startIndex.HasValue || !endIndex.HasValue)
			{
				return null;
			}
			if (startIndex > endIndex)
			{
				int? num = endIndex;
				endIndex = startIndex;
				startIndex = num;
			}
			if (endIndex >= Instructions.Count)
			{
				return null;
			}
			int num2 = endIndex.Value - startIndex.Value;
			List<CodeInstruction> range = Instructions.GetRange(startIndex.Value, num2);
			Instructions.RemoveRange(startIndex.Value, num2);
			if (startIndex < Instructions.Count)
			{
				range.ForEach(delegate(CodeInstruction code)
				{
					if (pinLabels)
					{
						CodeInstructionExtensions.MoveLabelsFrom(Instructions[startIndex.Value], code);
					}
					if (pinBlocks)
					{
						CodeInstructionExtensions.MoveBlocksFrom(Instructions[startIndex.Value], code);
					}
				});
			}
			if (shiftCurrentIndex && CurrentIndex > startIndex)
			{
				CurrentIndex = Math.Max(startIndex.Value, CurrentIndex - num2);
			}
			return range;
		}

		public List<CodeInstruction> RemoveIL(int? startIndex = null, int? endIndex = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = startIndex.GetValueOrDefault();
			if (!startIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				startIndex = valueOrDefault;
			}
			valueOrDefault = endIndex.GetValueOrDefault();
			if (!endIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				endIndex = valueOrDefault;
			}
			return TryRemoveIL(startIndex, endIndex, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[ILStepper.ILStepper.RemoveIL] [{0}, {1}, {2} ({3})] | {4}", startIndex, endIndex, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage));
		}

		public List<CodeInstruction>? TryGetIL(int? startIndex = null, int? endIndex = null)
		{
			startIndex = TryFindIndex(startIndex);
			endIndex = TryFindIndex(endIndex);
			if (!startIndex.HasValue || !endIndex.HasValue)
			{
				return null;
			}
			if (startIndex > endIndex)
			{
				int? num = endIndex;
				endIndex = startIndex;
				startIndex = num;
			}
			if (endIndex >= Instructions.Count)
			{
				return null;
			}
			int count = endIndex.Value - startIndex.Value;
			return Instructions.GetRange(startIndex.Value, count);
		}

		public List<CodeInstruction> GetIL(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = startIndex.GetValueOrDefault();
			if (!startIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				startIndex = valueOrDefault;
			}
			valueOrDefault = endIndex.GetValueOrDefault();
			if (!endIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				endIndex = valueOrDefault;
			}
			return TryGetIL(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.GetIL] [{startIndex}, {endIndex}] | {errorMessage}");
		}

		public List<Label>? TryMoveAllLabels(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange)
		{
			List<CodeInstruction> destinationCodeRange2 = destinationCodeRange;
			if (sourceCodeRange.Count != destinationCodeRange2.Count)
			{
				return null;
			}
			return sourceCodeRange.SelectMany(delegate(CodeInstruction sourceCode, int sourceCodeIndex)
			{
				List<Label> list = CodeInstructionExtensions.ExtractLabels(sourceCode);
				destinationCodeRange2[sourceCodeIndex].labels.AddRange(list);
				return list;
			}).ToList();
		}

		public List<Label>? TryMoveAllLabels(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode)
		{
			return TryMoveAllLabels(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList());
		}

		public List<Label> MoveAllLabels(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange, string errorMessage = "Source and destination instruction count don't match!")
		{
			return TryMoveAllLabels(sourceCodeRange, destinationCodeRange) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllLabels] [{sourceCodeRange}, {destinationCodeRange}] | {errorMessage}");
		}

		public List<Label> MoveAllLabels(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode, string errorMessage = "Source and destination instruction count don't match!")
		{
			return TryMoveAllLabels(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllLabels] [{sourceCodeRange}, {{{destinationCode}, ...}}] | {errorMessage}");
		}

		public List<Label>? TryShiftAllLabels(int? startIndex = null, int? endIndex = null, int shiftBy = 1)
		{
			List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
			if (list == null)
			{
				return null;
			}
			int? startIndex2 = TryFindIndex(startIndex, shiftBy);
			int? endIndex2 = TryFindIndex(endIndex, shiftBy);
			if (!startIndex2.HasValue || !endIndex2.HasValue)
			{
				return null;
			}
			List<CodeInstruction> list2 = TryGetIL(startIndex2, endIndex2);
			if (list2 == null)
			{
				return null;
			}
			return TryMoveAllLabels(list, list2);
		}

		public List<Label> ShiftAllLabels(int? startIndex = null, int? endIndex = null, int shiftBy = 1, string errorMessage = "Source and/or destination instructions out of bounds!")
		{
			int valueOrDefault = startIndex.GetValueOrDefault();
			if (!startIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				startIndex = valueOrDefault;
			}
			valueOrDefault = endIndex.GetValueOrDefault();
			if (!endIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				endIndex = valueOrDefault;
			}
			return TryShiftAllLabels(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ShiftAllLabels] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] | {errorMessage}");
		}

		public List<ExceptionBlock>? TryMoveAllBlocks(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange)
		{
			List<CodeInstruction> destinationCodeRange2 = destinationCodeRange;
			if (sourceCodeRange.Count != destinationCodeRange2.Count)
			{
				return null;
			}
			return sourceCodeRange.SelectMany(delegate(CodeInstruction sourceCode, int sourceCodeIndex)
			{
				List<ExceptionBlock> list = CodeInstructionExtensions.ExtractBlocks(sourceCode);
				destinationCodeRange2[sourceCodeIndex].blocks.AddRange(list);
				return list;
			}).ToList();
		}

		public List<ExceptionBlock>? TryMoveAllBlocks(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode)
		{
			return TryMoveAllBlocks(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList());
		}

		public List<ExceptionBlock> MoveAllBlocks(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange, string errorMessage = "Source and destination instruction count don't match!")
		{
			return TryMoveAllBlocks(sourceCodeRange, destinationCodeRange) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllBlocks] [{sourceCodeRange}, {destinationCodeRange}] | {errorMessage}");
		}

		public List<ExceptionBlock> MoveAllBlocks(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode, string errorMessage = "Source and destination instruction count don't match!")
		{
			return TryMoveAllBlocks(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllBlocks] [{sourceCodeRange}, {{{destinationCode}, ...}}] | {errorMessage}");
		}

		public List<ExceptionBlock>? TryShiftAllBlocks(int? startIndex = null, int? endIndex = null, int shiftBy = 1)
		{
			List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
			if (list == null)
			{
				return null;
			}
			int? startIndex2 = TryFindIndex(startIndex, shiftBy);
			int? endIndex2 = TryFindIndex(endIndex, shiftBy);
			if (!startIndex2.HasValue || !endIndex2.HasValue)
			{
				return null;
			}
			List<CodeInstruction> list2 = TryGetIL(startIndex2, endIndex2);
			if (list2 == null)
			{
				return null;
			}
			return TryMoveAllBlocks(list, list2);
		}

		public List<ExceptionBlock> ShiftAllBlocks(int? startIndex = null, int? endIndex = null, int shiftBy = 1, string errorMessage = "Source and/or destination instructions out of bounds!")
		{
			int valueOrDefault = startIndex.GetValueOrDefault();
			if (!startIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				startIndex = valueOrDefault;
			}
			valueOrDefault = endIndex.GetValueOrDefault();
			if (!endIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				endIndex = valueOrDefault;
			}
			return TryShiftAllBlocks(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ShiftAllBlocks] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] | {errorMessage}");
		}

		public List<Label> ExtractAllLabels(List<CodeInstruction> codeRange)
		{
			return codeRange.SelectMany((CodeInstruction code) => CodeInstructionExtensions.ExtractLabels(code)).ToList();
		}

		public List<Label>? TryExtractAllLabels(int? startIndex = null, int? endIndex = null)
		{
			List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
			if (list == null)
			{
				return null;
			}
			return ExtractAllLabels(list);
		}

		public List<Label> ExtractAllLabels(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = startIndex.GetValueOrDefault();
			if (!startIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				startIndex = valueOrDefault;
			}
			return TryExtractAllLabels(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ExtractAllLabels] [{startIndex}, {endIndex}] | {errorMessage}");
		}

		public List<Label> ExtractAllBlocks(List<CodeInstruction> codeRange)
		{
			return codeRange.SelectMany((CodeInstruction code) => CodeInstructionExtensions.ExtractLabels(code)).ToList();
		}

		public List<Label>? TryExtractAllBlocks(int? startIndex = null, int? endIndex = null)
		{
			List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
			if (list == null)
			{
				return null;
			}
			return ExtractAllBlocks(list);
		}

		public List<Label> ExtractAllBlocks(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = startIndex.GetValueOrDefault();
			if (!startIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				startIndex = valueOrDefault;
			}
			valueOrDefault = endIndex.GetValueOrDefault();
			if (!endIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				endIndex = valueOrDefault;
			}
			return TryExtractAllBlocks(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ExtractAllBlocks] [{startIndex}, {endIndex}] | {errorMessage}");
		}

		public List<CodeInstruction>? TryShiftIL(int? startIndex = null, int? endIndex = null, int shiftBy = 1, bool shiftCurrentIndex = true)
		{
			startIndex = TryFindIndex(startIndex);
			endIndex = TryFindIndex(endIndex);
			if (!startIndex.HasValue || !endIndex.HasValue)
			{
				return null;
			}
			if (startIndex > endIndex)
			{
				int? num = endIndex;
				endIndex = startIndex;
				startIndex = num;
			}
			if (endIndex >= Instructions.Count)
			{
				return null;
			}
			int num2 = endIndex.Value - startIndex.Value;
			int? index = TryFindIndex(startIndex, shiftBy, 0, -num2 + 1);
			if (!index.HasValue)
			{
				return null;
			}
			if (shiftCurrentIndex && CurrentIndex >= startIndex && CurrentIndex < endIndex)
			{
				CurrentIndex += shiftBy;
				shiftCurrentIndex = false;
			}
			string errorMessage = $"[ILStepper.ILStepper.TryShiftIL] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] Somehow calculated invalid parameters. This should never happen!";
			List<CodeInstruction> codeRange = RemoveIL(startIndex, endIndex, shiftCurrentIndex, pinLabels: false, pinBlocks: false, errorMessage);
			return InsertIL(codeRange, index, shiftCurrentIndex, pinLabels: false, pinBlocks: false, errorMessage);
		}

		public List<CodeInstruction> ShiftIL(int? startIndex = null, int? endIndex = null, int shiftBy = 1, bool shiftCurrentIndex = true, string errorMessage = "Source and/or destination instructions out of bounds!")
		{
			int valueOrDefault = startIndex.GetValueOrDefault();
			if (!startIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				startIndex = valueOrDefault;
			}
			valueOrDefault = endIndex.GetValueOrDefault();
			if (!endIndex.HasValue)
			{
				valueOrDefault = CurrentIndex;
				endIndex = valueOrDefault;
			}
			return TryShiftIL(startIndex, endIndex, shiftBy, shiftCurrentIndex) ?? throw new Exception($"[ILStepper.ILStepper.ShiftIL] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] | {errorMessage}");
		}

		public List<CodeInstruction>? TryOverwriteIL(List<CodeInstruction> codeRange, int? index = null, bool pinLabels = true, bool pinBlocks = true)
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			List<CodeInstruction> removedIL = TryRemoveIL(index, index + codeRange.Count(), shiftCurrentIndex: false, pinLabels: false, pinBlocks: false);
			if (removedIL == null)
			{
				return null;
			}
			codeRange = codeRange.Select(delegate(CodeInstruction code, int i)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Expected O, but got Unknown
				code = new CodeInstruction(code);
				if (pinLabels)
				{
					CodeInstructionExtensions.MoveLabelsTo(removedIL[i], code);
				}
				if (pinBlocks)
				{
					CodeInstructionExtensions.MoveBlocksTo(removedIL[i], code);
				}
				return code;
			}).ToList();
			return TryInsertIL(codeRange, index, shiftCurrentIndex: false, pinLabels: false, pinBlocks: false);
		}

		public List<CodeInstruction>? TryOverwriteIL(CodeInstruction? code, int? index = null, bool pinLabels = true, bool pinBlocks = true)
		{
			return TryOverwriteIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, pinLabels, pinBlocks);
		}

		public List<CodeInstruction> OverwriteIL(List<CodeInstruction> codeRange, int? index = null, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return TryOverwriteIL(codeRange, index, pinLabels, pinBlocks) ?? throw new Exception($"[ILStepper.ILStepper.OverwriteIL] [{codeRange}, {index}, {index + codeRange.Count()} ({index} + {codeRange.Count()})] | {errorMessage}");
		}

		public List<CodeInstruction> OverwriteIL(CodeInstruction? code, int? index = null, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
		{
			int valueOrDefault = index.GetValueOrDefault();
			if (!index.HasValue)
			{
				valueOrDefault = CurrentIndex;
				index = valueOrDefault;
			}
			return TryOverwriteIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, pinLabels, pinBlocks) ?? throw new Exception($"[ILStepper.ILStepper.OverwriteIL] [{code}, {index}, {index + ((code != null) ? 1 : 0)} ({index} + {((code != null) ? 1 : 0)})] | {errorMessage}");
		}
	}
	[BepInPlugin("com.github.decibillyjoel.ILUtils", "DBJ.ILUtils", "1.0.4")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PLUGIN_GUID = "com.github.decibillyjoel.ILUtils";

		public const string PLUGIN_NAME = "ILUtils";

		public const string PLUGIN_VERSION = "1.0.4";

		public const string PLUGIN_TS_TEAM = "DBJ";

		public static ManualLogSource PluginLogger;

		public static void Log(LogLevel logLevel, string logMessage)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			PluginLogger.Log(logLevel, (object)(logMessage ?? ""));
		}

		public static void Log(string logMessage)
		{
			Log((LogLevel)16, logMessage);
		}

		private void Awake()
		{
			PluginLogger = ((BaseUnityPlugin)this).Logger;
			Log("[v1.0.4] Finished loading!");
		}
	}
}
namespace ILUtils.HarmonyXtensions
{
	public static class CodeInstructionPolyfills
	{
		public static readonly OpCode[] ARGUMENTED_LOCAL_INSTRUCTS = new OpCode[6]
		{
			OpCodes.Ldloc,
			OpCodes.Stloc,
			OpCodes.Ldloca,
			OpCodes.Ldloc_S,
			OpCodes.Stloc_S,
			OpCodes.Ldloca_S
		};

		public static readonly OpCode[] LOAD_FIELD_INSTRUCTS = new OpCode[4]
		{
			OpCodes.Ldfld,
			OpCodes.Ldsfld,
			OpCodes.Ldflda,
			OpCodes.Ldsflda
		};

		public static readonly OpCode[] STORE_FIELD_INSTRUCTS = new OpCode[2]
		{
			OpCodes.Stfld,
			OpCodes.Stsfld
		};

		public static bool IsValid(this OpCode code)
		{
			return code.Size > 0;
		}

		public static CodeInstruction Call(Type type, string name, Type[]? parameters = null, Type[]? generics = null)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(type, name, parameters, generics) ?? throw new ArgumentException($"No method found for type={type}, name={name}, parameters={GeneralExtensions.Description(parameters)}, generics={GeneralExtensions.Description(generics)}");
			return new CodeInstruction(OpCodes.Call, (object)methodInfo);
		}

		public static bool Calls(this CodeInstruction codeInstruction, Type type, string name, Type[]? parameters = null, Type[]? generics = null)
		{
			MethodInfo methodInfo = AccessTools.Method(type, name, parameters, generics) ?? throw new ArgumentException($"No method found for type={type}, name={name}, parameters={GeneralExtensions.Description(parameters)}, generics={GeneralExtensions.Description(generics)}");
			return CodeInstructionExtensions.Calls(codeInstruction, methodInfo);
		}

		public static CodeInstruction Call(string typeColonMethodname, Type[]? parameters = null, Type[]? generics = null)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeColonMethodname, parameters, generics) ?? throw new ArgumentException("No method found for " + typeColonMethodname + ", parameters=" + GeneralExtensions.Description(parameters) + ", generics=" + GeneralExtensions.Description(generics));
			return new CodeInstruction(OpCodes.Call, (object)methodInfo);
		}

		public static bool Calls(this CodeInstruction codeInstruction, string typeColonMethodname, Type[]? parameters = null, Type[]? generics = null)
		{
			MethodInfo methodInfo = AccessTools.Method(typeColonMethodname, parameters, generics) ?? throw new ArgumentException("No method found for " + typeColonMethodname + ", parameters=" + GeneralExtensions.Description(parameters) + ", generics=" + GeneralExtensions.Description(generics));
			return CodeInstructionExtensions.Calls(codeInstruction, methodInfo);
		}

		public static CodeInstruction Call(Expression<Action> expression)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo(expression));
		}

		public static CodeInstruction Call<T>(Expression<Action<T>> expression)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo<T>(expression));
		}

		public static CodeInstruction Call<T, TResult>(Expression<Func<T, TResult>> expression)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo<T, TResult>(expression));
		}

		public static CodeInstruction Call(LambdaExpression expression)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo(expression));
		}

		public static CodeInstruction CallClosure<T>(T closure) where T : Delegate
		{
			return Transpilers.EmitDelegate<T>(closure);
		}

		public static CodeInstruction CallConstructor(Type type, Type[]? parameters = null, bool searchForStatic = false)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			ConstructorInfo constructorInfo = AccessTools.Constructor(type, parameters, searchForStatic) ?? throw new ArgumentException($"No constructor found for type={type}, parameters={GeneralExtensions.Description(parameters)}, searchForStatic={searchForStatic}");
			return new CodeInstruction(OpCodes.Newobj, (object)constructorInfo);
		}

		public static CodeInstruction LoadField(Type type, string name, bool useAddress = false)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			FieldInfo fieldInfo = AccessTools.Field(type, name) ?? throw new ArgumentException($"No field found for {type} and {name}");
			return new CodeInstruction((!useAddress) ? (fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld) : (fieldInfo.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda), (object)fieldInfo);
		}

		public static CodeInstruction StoreField(Type type, string name)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			FieldInfo fieldInfo = AccessTools.Field(type, name) ?? throw new ArgumentException($"No field found for {type} and {name}");
			return new CodeInstruction(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, (object)fieldInfo);
		}

		public static bool LoadsField(this CodeInstruction codeInstruction, Type type, string name, bool byAddress = false)
		{
			FieldInfo fieldInfo = AccessTools.DeclaredField(type, name);
			if (fieldInfo != null)
			{
				return CodeInstructionExtensions.LoadsField(codeInstruction, fieldInfo, byAddress);
			}
			return false;
		}

		public static bool StoresField(this CodeInstruction codeInstruction, Type type, string name)
		{
			FieldInfo fieldInfo = AccessTools.DeclaredField(type, name);
			if (fieldInfo != null)
			{
				return CodeInstructionExtensions.StoresField(codeInstruction, fieldInfo);
			}
			return false;
		}

		public static int LocalIndex(this CodeInstruction code)
		{
			if (code.opcode == OpCodes.Ldloc_0 || code.opcode == OpCodes.Stloc_0)
			{
				return 0;
			}
			if (code.opcode == OpCodes.Ldloc_1 || code.opcode == OpCodes.Stloc_1)
			{
				return 1;
			}
			if (code.opcode == OpCodes.Ldloc_2 || code.opcode == OpCodes.Stloc_2)
			{
				return 2;
			}
			if (code.opcode == OpCodes.Ldloc_3 || code.opcode == OpCodes.Stloc_3)
			{
				return 3;
			}
			if (ARGUMENTED_LOCAL_INSTRUCTS.Contains(code.opcode))
			{
				int? num = (code.operand as LocalVariableInfo)?.LocalIndex;
				return Convert.ToInt32(num.HasValue ? ((object)num.GetValueOrDefault()) : code.operand);
			}
			throw new ArgumentException("Instruction is not a load or store", "code");
		}

		public static CodeInstruction LoadLocal(int index, bool useAddress = false)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			if (useAddress)
			{
				if (index < 256)
				{
					return new CodeInstruction(OpCodes.Ldloca_S, (object)Convert.ToByte(index));
				}
				return new CodeInstruction(OpCodes.Ldloca, (object)index);
			}
			if (index < 256)
			{
				return (CodeInstruction)(index switch
				{
					0 => (object)new CodeInstruction(OpCodes.Ldloc_0, (object)null), 
					1 => (object)new CodeInstruction(OpCodes.Ldloc_1, (object)null), 
					2 => (object)new CodeInstruction(OpCodes.Ldloc_2, (object)null), 
					3 => (object)new CodeInstruction(OpCodes.Ldloc_3, (object)null), 
					_ => (object)new CodeInstruction(OpCodes.Ldloc_S, (object)Convert.ToByte(index)), 
				});
			}
			return new CodeInstruction(OpCodes.Ldloc, (object)index);
		}

		public static CodeInstruction LoadLocal(LocalVariableInfo local, bool useAddress = false)
		{
			return LoadLocal(local.LocalIndex, useAddress);
		}

		public static CodeInstruction StoreLocal(int index)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			if (index < 256)
			{
				return (CodeInstruction)(index switch
				{
					0 => (object)new CodeInstruction(OpCodes.Stloc_0, (object)null), 
					1 => (object)new CodeInstruction(OpCodes.Stloc_1, (object)null), 
					2 => (object)new CodeInstruction(OpCodes.Stloc_2, (object)null), 
					3 => (object)new CodeInstruction(OpCodes.Stloc_3, (object)null), 
					_ => (object)new CodeInstruction(OpCodes.Stloc_S, (object)Convert.ToByte(index)), 
				});
			}
			return new CodeInstruction(OpCodes.Stloc, (object)index);
		}

		public static CodeInstruction StoreLocal(LocalVariableInfo local)
		{
			return StoreLocal(local.LocalIndex);
		}

		public static bool LoadsLocal(this CodeInstruction code, LocalVariableInfo? local = null)
		{
			if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null))
			{
				if (local != null)
				{
					return code.LocalIndex() == local.LocalIndex;
				}
				return true;
			}
			return false;
		}

		public static bool LoadsLocal(this CodeInstruction code, int index)
		{
			if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null))
			{
				return code.LocalIndex() == index;
			}
			return false;
		}

		public static bool StoresLocal(this CodeInstruction code, LocalVariableInfo? local = null)
		{
			if (CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null))
			{
				if (local != null)
				{
					return code.LocalIndex() == local.LocalIndex;
				}
				return true;
			}
			return false;
		}

		public static bool StoresLocal(this CodeInstruction code, int index)
		{
			if (CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null))
			{
				return code.LocalIndex() == index;
			}
			return false;
		}

		public static CodeInstruction LoadArgument(int index, bool useAddress = false)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			if (useAddress)
			{
				if (index >= 256)
				{
					return new CodeInstruction(OpCodes.Ldarga, (object)index);
				}
				return new CodeInstruction(OpCodes.Ldarga_S, (object)Convert.ToByte(index));
			}
			if (index != 0)
			{
				if (index != 1)
				{
					if (index != 2)
					{
						if (index != 3)
						{
							if (index >= 256)
							{
								return new CodeInstruction(OpCodes.Ldarg, (object)index);
							}
							return new CodeInstruction(OpCodes.Ldarg_S, (object)Convert.ToByte(index));
						}
						return new CodeInstruction(OpCodes.Ldarg_3, (object)null);
					}
					return new CodeInstruction(OpCodes.Ldarg_2, (object)null);
				}
				return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
			}
			return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
		}

		public static int ArgumentIndex(this CodeInstruction code)
		{
			if (code.opcode == OpCodes.Ldarg_0)
			{
				return 0;
			}
			if (code.opcode == OpCodes.Ldarg_1)
			{
				return 1;
			}
			if (code.opcode == OpCodes.Ldarg_2)
			{
				return 2;
			}
			if (code.opcode == OpCodes.Ldarg_3)
			{
				return 3;
			}
			if (code.opcode == OpCodes.Ldarg_S || code.opcode == OpCodes.Ldarg)
			{
				return Convert.ToInt32(code.operand);
			}
			if (code.opcode == OpCodes.Starg_S || code.opcode == OpCodes.Starg)
			{
				return Convert.ToInt32(code.operand);
			}
			if (code.opcode == OpCodes.Ldarga_S || code.opcode == OpCodes.Ldarga)
			{
				return Convert.ToInt32(code.operand);
			}
			throw new ArgumentException("Instruction is not a load or store", "code");
		}

		public static CodeInstruction StoreArgument(int index)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (index >= 256)
			{
				return new CodeInstruction(OpCodes.Starg, (object)index);
			}
			return new CodeInstruction(OpCodes.Starg_S, (object)Convert.ToByte(index));
		}

		public static bool LoadsString(this CodeInstruction code, string str)
		{
			if (code.opcode != OpCodes.Ldstr)
			{
				return false;
			}
			string text = Convert.ToString(code.operand);
			return text == str;
		}

		public static CodeInstruction LoadConstant(sbyte number)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			return (CodeInstruction)(number switch
			{
				-1 => (object)new CodeInstruction(OpCodes.Ldc_I4_M1, (object)null), 
				0 => (object)new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), 
				1 => (object)new CodeInstruction(OpCodes.Ldc_I4_1, (object)null), 
				2 => (object)new CodeInstruction(OpCodes.Ldc_I4_2, (object)null), 
				3 => (object)new CodeInstruction(OpCodes.Ldc_I4_3, (object)null), 
				4 => (object)new CodeInstruction(OpCodes.Ldc_I4_4, (object)null), 
				5 => (object)new CodeInstruction(OpCodes.Ldc_I4_5, (object)null), 
				6 => (object)new CodeInstruction(OpCodes.Ldc_I4_6, (object)null), 
				7 => (object)new CodeInstruction(OpCodes.Ldc_I4_7, (object)null), 
				8 => (object)new CodeInstruction(OpCodes.Ldc_I4_8, (object)null), 
				_ => (object)new CodeInstruction(OpCodes.Ldc_I4_S, (object)number), 
			});
		}

		public static CodeInstruction LoadConstant(int number)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (number >= -128 && number <= 127)
			{
				return LoadConstant(Convert.ToSByte(number));
			}
			return new CodeInstruction(OpCodes.Ldc_I4, (object)number);
		}

		public static CodeInstruction LoadConstant(long number)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Ldc_I8, (object)number);
		}

		public static CodeInstruction LoadConstant(Enum e)
		{
			return (CodeInstruction)(e.GetTypeCode() switch
			{
				TypeCode.Int64 => LoadConstant(Convert.ToInt64(e)), 
				TypeCode.SByte => LoadConstant(Convert.ToSByte(e)), 
				_ => LoadConstant(Convert.ToInt32(e)), 
			});
		}

		public static CodeInstruction[] LoadLongOptimally(long number)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			if (number >= -128)
			{
				if (number <= 127)
				{
					return (CodeInstruction[])(object)new CodeInstruction[2]
					{
						LoadConstant(Convert.ToSByte(number)),
						new CodeInstruction(OpCodes.Conv_I8, (object)null)
					};
				}
				if (number <= int.MaxValue)
				{
					goto IL_0047;
				}
			}
			else if (number >= int.MinValue)
			{
				goto IL_0047;
			}
			return (CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldc_I8, (object)number)
			};
			IL_0047:
			return (CodeInstruction[])(object)new CodeInstruction[2]
			{
				LoadConstant(Convert.ToInt32(number)),
				new CodeInstruction(OpCodes.Conv_I8, (object)null)
			};
		}

		public static CodeInstruction[] LoadEnumOptimally(Enum e)
		{
			return e.GetTypeCode() switch
			{
				TypeCode.Int64 => LoadLongOptimally(Convert.ToInt64(e)), 
				TypeCode.SByte => (CodeInstruction[])(object)new CodeInstruction[1] { LoadConstant(Convert.ToSByte(e)) }, 
				_ => (CodeInstruction[])(object)new CodeInstruction[1] { LoadConstant(Convert.ToInt32(e)) }, 
			};
		}

		public static CodeInstruction LoadString(string str)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Ldstr, (object)str);
		}

		public static CodeInstruction LoadNull()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Ldnull, (object)null);
		}

		public static bool LoadsNull(this CodeInstruction code)
		{
			return object.Equals(code.opcode, OpCodes.Ldnull);
		}

		public static bool LoadsProperty(this CodeInstruction code, PropertyInfo property)
		{
			return CodeInstructionExtensions.Calls(code, property.GetGetMethod(nonPublic: true));
		}

		public static bool LoadsProperty(this CodeInstruction code, Type type, string name)
		{
			PropertyInfo propertyInfo = AccessTools.DeclaredProperty(type, name);
			if (propertyInfo != null)
			{
				return code.LoadsProperty(propertyInfo);
			}
			return false;
		}

		public static bool StoresProperty(this CodeInstruction code, PropertyInfo property)
		{
			return CodeInstructionExtensions.Calls(code, property.GetSetMethod(nonPublic: true));
		}

		public static bool StoresProperty(this CodeInstruction code, Type type, string name)
		{
			PropertyInfo propertyInfo = AccessTools.DeclaredProperty(type, name);
			if (propertyInfo != null)
			{
				return code.StoresProperty(propertyInfo);
			}
			return false;
		}

		public static CodeInstruction LoadProperty(PropertyInfo property)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Call, (object)property.GetGetMethod(nonPublic: true));
		}

		public static CodeInstruction LoadProperty(Type type, string name)
		{
			PropertyInfo property = AccessTools.Property(type, name) ?? throw new ArgumentException($"No property found for type={type}, name={name}");
			return LoadProperty(property);
		}

		public static CodeInstruction StoreProperty(PropertyInfo property)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return new CodeInstruction(OpCodes.Call, (object)property.GetSetMethod(nonPublic: true));
		}

		public static CodeInstruction StoreProperty(Type type, string name)
		{
			PropertyInfo property = AccessTools.Property(type, name) ?? throw new ArgumentException($"No property found for type={type}, name={name}");
			return StoreProperty(property);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}