Decompiled source of Batter v1.0.0

plugins/Batteritems/batteritems.dll

Decompiled 8 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Gungeon;
using ItemAPI;
using MonoMod.RuntimeDetour;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Mod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Mod")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d6d7a494-722e-4763-959b-c2d6b6a42b01")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace batteritems
{
	public class StripedJersey : PassiveItem
	{
		public static void Init()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			string name = "Striped Jersey";
			string resourcePath = "batteritems/Resources/striped_jersey";
			GameObject val = new GameObject();
			StripedJersey stripedJersey = val.AddComponent<StripedJersey>();
			ItemBuilder.AddSpriteToObject(name, resourcePath, val);
			string shortDesc = "It's red & white!";
			string longDesc = "Negates contact damage and increases movement speed\n\nYour very own protective gear that you're used to sprinting around in.\n";
			((PickupObject)(object)stripedJersey).SetupItem(shortDesc, longDesc, "batteritems");
			((PickupObject)(object)stripedJersey).AddPassiveStatModifier((StatType)0, 1f, (ModifyMethod)0);
			((PickupObject)stripedJersey).quality = (ItemQuality)2;
		}

		public override void Pickup(PlayerController player)
		{
			player.ReceivesTouchDamage = false;
			((PassiveItem)this).Pickup(player);
			Tools.Print("Player picked up " + ((PickupObject)this).DisplayName);
		}

		public override DebrisObject Drop(PlayerController player)
		{
			Tools.Print("Player dropped " + ((PickupObject)this).DisplayName);
			return ((PassiveItem)this).Drop(player);
		}
	}
	public class TradingCard : PassiveItem
	{
		public static void Init()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			string name = "Old Trading Card";
			string resourcePath = "batteritems/Resources/trading_card";
			GameObject val = new GameObject();
			TradingCard tradingCard = val.AddComponent<TradingCard>();
			ItemBuilder.AddSpriteToObject(name, resourcePath, val);
			string shortDesc = "Hey! That's you!";
			string longDesc = "Increases Coolness by 3\n\nWow, this trading card of you is pretty cool.\n";
			((PickupObject)(object)tradingCard).SetupItem(shortDesc, longDesc, "batteritems");
			((PickupObject)(object)tradingCard).AddPassiveStatModifier((StatType)4, 3f, (ModifyMethod)0);
			((PickupObject)tradingCard).quality = (ItemQuality)2;
		}
	}
	public class BatterItemsModule : ETGModule
	{
		public bool setup;

		private static string version = "0.0.1";

		private string[] itemList = new string[2] { "Trading Card", "Striped Jersey" };

		public override void Init()
		{
		}

		public override void Start()
		{
			Setup();
		}

		public void Setup()
		{
			if (setup)
			{
				return;
			}
			try
			{
				Tools.Init();
				ItemBuilder.Init();
				TradingCard.Init();
				StripedJersey.Init();
				setup = true;
			}
			catch (Exception e2)
			{
				Tools.PrintException(e2);
			}
			ETGModConsole.Commands.AddUnit("batteritems", (Action<string[]>)delegate
			{
				ETGModConsole.Log("Batter Items: ", false);
				string[] array = itemList;
				foreach (string text in array)
				{
					ETGModConsole.Log("    " + text, false);
				}
			});
			ETGModConsole.Log("Batter Items " + version + " Initialized", false);
		}

		public override void Exit()
		{
		}
	}
}
namespace ItemAPI
{
	public static class CompanionBuilder
	{
		public enum AnimationType
		{
			Move,
			Idle,
			Fidget,
			Flight,
			Hit,
			Talk,
			Other
		}

		private static GameObject behaviorSpeculatorPrefab;

		public static Dictionary<string, GameObject> companionDictionary = new Dictionary<string, GameObject>();

		public static void Init()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			string companionGuid = ((Component)Game.Items["dog"]).GetComponent<CompanionItem>().CompanionGuid;
			AIActor orLoadByGuid = EnemyDatabase.GetOrLoadByGuid(companionGuid);
			behaviorSpeculatorPrefab = Object.Instantiate<GameObject>(((Component)orLoadByGuid).gameObject);
			foreach (Transform item in behaviorSpeculatorPrefab.transform)
			{
				Transform val = item;
				if ((Object)(object)val != (Object)(object)behaviorSpeculatorPrefab.transform)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
			Component[] components = behaviorSpeculatorPrefab.GetComponents<Component>();
			foreach (Component val2 in components)
			{
				if ((object)((object)val2).GetType() != typeof(BehaviorSpeculator))
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			Object.DontDestroyOnLoad((Object)(object)behaviorSpeculatorPrefab);
			FakePrefab.MarkAsFakePrefab(behaviorSpeculatorPrefab);
			behaviorSpeculatorPrefab.SetActive(false);
			Hook val3 = new Hook((MethodBase)typeof(EnemyDatabase).GetMethod("GetOrLoadByGuid", BindingFlags.Static | BindingFlags.Public), typeof(CompanionBuilder).GetMethod("GetOrLoadByGuid"));
		}

		public static AIActor GetOrLoadByGuid(Func<string, AIActor> orig, string guid)
		{
			foreach (string key in companionDictionary.Keys)
			{
				if (key == guid)
				{
					return companionDictionary[key].GetComponent<AIActor>();
				}
			}
			return orig(guid);
		}

		public static GameObject BuildPrefab(string name, string guid, string defaultSpritePath, IntVector2 hitboxOffset, IntVector2 hitBoxSize)
		{
			//IL_004c: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			if (companionDictionary.ContainsKey(guid))
			{
				Tools.PrintError("CompanionBuilder: Tried to create two companion prefabs with the same GUID!");
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(behaviorSpeculatorPrefab);
			((Object)val).name = name;
			tk2dSprite component = SpriteBuilder.SpriteFromResource(defaultSpritePath, val).GetComponent<tk2dSprite>();
			component.SetUpSpeculativeRigidbody(hitboxOffset, hitBoxSize).CollideWithOthers = false;
			val.AddComponent<tk2dSpriteAnimator>();
			val.AddComponent<AIAnimator>();
			HealthHaver val2 = val.AddComponent<HealthHaver>();
			val2.RegisterBodySprite((tk2dBaseSprite)(object)component, false, 0);
			val2.PreventAllDamage = true;
			val2.SetHealthMaximum(15000f, (float?)null, false);
			val2.FullHeal();
			AIActor val3 = val.AddComponent<AIActor>();
			val3.State = (ActorState)2;
			val3.EnemyGuid = guid;
			BehaviorSpeculator component2 = val.GetComponent<BehaviorSpeculator>();
			component2.MovementBehaviors = new List<MovementBehaviorBase>();
			component2.AttackBehaviors = new List<AttackBehaviorBase>();
			component2.TargetBehaviors = new List<TargetBehaviorBase>();
			component2.OverrideBehaviors = new List<OverrideBehaviorBase>();
			component2.OtherBehaviors = new List<BehaviorBase>();
			EnemyDatabaseEntry item = new EnemyDatabaseEntry
			{
				myGuid = guid,
				placeableWidth = 2,
				placeableHeight = 2,
				isNormalEnemy = false
			};
			((AssetBundleDatabase<AIActor, EnemyDatabaseEntry>)(object)EnemyDatabase.Instance).Entries.Add(item);
			companionDictionary.Add(guid, val);
			Object.DontDestroyOnLoad((Object)(object)val);
			FakePrefab.MarkAsFakePrefab(val);
			val.SetActive(false);
			return val;
		}

		public static tk2dSpriteAnimationClip AddAnimation(this GameObject obj, string name, string spriteDirectory, int fps, AnimationType type, DirectionType directionType = 0, FlipType flipType = 0)
		{
			//IL_000a: 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_0083: Expected I4, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			AIAnimator orAddComponent = GameObjectExtensions.GetOrAddComponent<AIAnimator>(obj);
			DirectionalAnimation val = orAddComponent.GetDirectionalAnimation(name, directionType, type);
			if (val == null)
			{
				DirectionalAnimation val2 = new DirectionalAnimation();
				val2.AnimNames = new string[0];
				val2.Flipped = (FlipType[])(object)new FlipType[0];
				val2.Type = directionType;
				val2.Prefix = string.Empty;
				val = val2;
			}
			val.AnimNames = val.AnimNames.Concat(new string[1] { name }).ToArray();
			val.Flipped = val.Flipped.Concat((IEnumerable<FlipType>)(object)new FlipType[1] { (FlipType)(int)flipType }).ToArray();
			orAddComponent.AssignDirectionalAnimation(name, val, type);
			return BuildAnimation(orAddComponent, name, spriteDirectory, fps);
		}

		public static tk2dSpriteAnimationClip BuildAnimation(AIAnimator aiAnimator, string name, string spriteDirectory, int fps)
		{
			tk2dSpriteCollectionData val = ((Component)aiAnimator).GetComponent<tk2dSpriteCollectionData>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = SpriteBuilder.ConstructCollection(((Component)aiAnimator).gameObject, ((Object)aiAnimator).name + "_collection");
			}
			string[] resourceNames = ResourceExtractor.GetResourceNames();
			List<int> list = new List<int>();
			for (int i = 0; i < resourceNames.Length; i++)
			{
				if (resourceNames[i].StartsWith(spriteDirectory.Replace('/', '.'), StringComparison.OrdinalIgnoreCase))
				{
					list.Add(SpriteBuilder.AddSpriteToCollection(resourceNames[i], val));
				}
			}
			tk2dSpriteAnimationClip val2 = SpriteBuilder.AddAnimation(((BraveBehaviour)aiAnimator).spriteAnimator, val, list, name, (WrapMode)0);
			val2.fps = fps;
			return val2;
		}

		public static DirectionalAnimation GetDirectionalAnimation(this AIAnimator aiAnimator, string name, DirectionType directionType, AnimationType type)
		{
			DirectionalAnimation val = null;
			switch (type)
			{
			case AnimationType.Idle:
				val = aiAnimator.IdleAnimation;
				break;
			case AnimationType.Move:
				val = aiAnimator.MoveAnimation;
				break;
			case AnimationType.Flight:
				val = aiAnimator.FlightAnimation;
				break;
			case AnimationType.Hit:
				val = aiAnimator.HitAnimation;
				break;
			case AnimationType.Talk:
				val = aiAnimator.TalkAnimation;
				break;
			}
			if (val != null)
			{
				return val;
			}
			return null;
		}

		public static void AssignDirectionalAnimation(this AIAnimator aiAnimator, string name, DirectionalAnimation animation, AnimationType type)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			switch (type)
			{
			case AnimationType.Idle:
				aiAnimator.IdleAnimation = animation;
				return;
			case AnimationType.Move:
				aiAnimator.MoveAnimation = animation;
				return;
			case AnimationType.Flight:
				aiAnimator.FlightAnimation = animation;
				return;
			case AnimationType.Hit:
				aiAnimator.HitAnimation = animation;
				return;
			case AnimationType.Talk:
				aiAnimator.TalkAnimation = animation;
				return;
			case AnimationType.Fidget:
				aiAnimator.IdleFidgetAnimations.Add(animation);
				return;
			}
			aiAnimator.OtherAnimations.Add(new NamedDirectionalAnimation
			{
				anim = animation,
				name = name
			});
		}
	}
	public static class CustomSynergies
	{
		public static Hook synergyHook = new Hook((MethodBase)typeof(StringTableManager).GetMethod("GetSynergyString", BindingFlags.Static | BindingFlags.Public), typeof(CustomSynergies).GetMethod("SynergyStringHook"));

		public static AdvancedSynergyEntry Add(string name, List<string> mandatoryConsoleIDs, List<string> optionalConsoleIDs = null, bool ignoreLichEyeBullets = true)
		{
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			if (mandatoryConsoleIDs == null || mandatoryConsoleIDs.Count == 0)
			{
				Tools.PrintError("Synergy " + name + " has no mandatory items/guns.");
				return null;
			}
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			List<int> list3 = new List<int>();
			List<int> list4 = new List<int>();
			foreach (string mandatoryConsoleID in mandatoryConsoleIDs)
			{
				PickupObject val = Game.Items[mandatoryConsoleID];
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).GetComponent<Gun>()))
				{
					list2.Add(val.PickupObjectId);
				}
				else if (Object.op_Implicit((Object)(object)val) && (Object.op_Implicit((Object)(object)((Component)val).GetComponent<PlayerItem>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<PassiveItem>())))
				{
					list.Add(val.PickupObjectId);
				}
			}
			if (optionalConsoleIDs != null)
			{
				foreach (string optionalConsoleID in optionalConsoleIDs)
				{
					PickupObject val = Game.Items[optionalConsoleID];
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).GetComponent<Gun>()))
					{
						list4.Add(val.PickupObjectId);
					}
					else if (Object.op_Implicit((Object)(object)val) && (Object.op_Implicit((Object)(object)((Component)val).GetComponent<PlayerItem>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<PassiveItem>())))
					{
						list3.Add(val.PickupObjectId);
					}
				}
			}
			AdvancedSynergyEntry val2 = new AdvancedSynergyEntry
			{
				NameKey = name,
				MandatoryItemIDs = list,
				MandatoryGunIDs = list2,
				OptionalItemIDs = list3,
				OptionalGunIDs = list4,
				bonusSynergies = new List<CustomSynergyType>(),
				statModifiers = new List<StatModifier>()
			};
			Add(val2);
			return val2;
		}

		public static void Add(AdvancedSynergyEntry synergyEntry)
		{
			AdvancedSynergyEntry[] second = (AdvancedSynergyEntry[])(object)new AdvancedSynergyEntry[1] { synergyEntry };
			GameManager.Instance.SynergyManager.synergies = GameManager.Instance.SynergyManager.synergies.Concat(second).ToArray();
		}

		public static string SynergyStringHook(Func<string, int, string> orig, string key, int index = -1)
		{
			string text = orig(key, index);
			if (string.IsNullOrEmpty(text))
			{
				text = key;
			}
			return text;
		}

		public static bool HasMTGConsoleID(this PlayerController player, string consoleID)
		{
			if (!Game.Items.ContainsID(consoleID))
			{
				return false;
			}
			return player.HasPickupID(Game.Items[consoleID].PickupObjectId);
		}
	}
	public class FakePrefab : Component
	{
		internal static HashSet<GameObject> ExistingFakePrefabs = new HashSet<GameObject>();

		public static bool IsFakePrefab(Object o)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (o is GameObject)
			{
				return ExistingFakePrefabs.Contains((GameObject)o);
			}
			if (o is Component)
			{
				return ExistingFakePrefabs.Contains(((Component)o).gameObject);
			}
			return false;
		}

		public static void MarkAsFakePrefab(GameObject obj)
		{
			ExistingFakePrefabs.Add(obj);
			Object.DontDestroyOnLoad((Object)(object)obj);
		}

		public static GameObject Clone(GameObject obj)
		{
			bool flag = IsFakePrefab((Object)(object)obj);
			bool activeSelf = obj.activeSelf;
			if (activeSelf)
			{
				obj.SetActive(false);
			}
			GameObject val = Object.Instantiate<GameObject>(obj);
			if (activeSelf)
			{
				obj.SetActive(true);
			}
			ExistingFakePrefabs.Add(val);
			Object.DontDestroyOnLoad((Object)(object)val);
			return val;
		}

		public static Object Instantiate(Object o, Object new_o)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (o is GameObject && ExistingFakePrefabs.Contains((GameObject)o))
			{
				((GameObject)new_o).SetActive(true);
			}
			else if (o is Component && ExistingFakePrefabs.Contains(((Component)o).gameObject))
			{
				((Component)new_o).gameObject.SetActive(true);
			}
			return new_o;
		}
	}
	public static class FakePrefabHooks
	{
		public delegate TResult Func<T1, T2, T3, T4, T5, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);

		public static void Init()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			Hook val = new Hook((MethodBase)typeof(PlayerController).GetMethod("AcquirePassiveItemPrefabDirectly"), typeof(FakePrefabHooks).GetMethod("AcquirePassiveItemPrefabDirectly"));
			Hook val2 = new Hook((MethodBase)typeof(PlayerItem).GetMethod("Pickup"), typeof(FakePrefabHooks).GetMethod("ActivePickup"));
			Hook val3 = new Hook((MethodBase)typeof(Object).GetMethod("Instantiate", new Type[3]
			{
				typeof(Object),
				typeof(Transform),
				typeof(bool)
			}), typeof(FakePrefabHooks).GetMethod("InstantiateOPI"));
			Hook val4 = new Hook((MethodBase)typeof(Object).GetMethod("Instantiate", new Type[2]
			{
				typeof(Object),
				typeof(Transform)
			}), typeof(FakePrefabHooks).GetMethod("InstantiateOP"));
			Hook val5 = new Hook((MethodBase)typeof(Object).GetMethod("Instantiate", new Type[1] { typeof(Object) }), typeof(FakePrefabHooks).GetMethod("InstantiateO"));
			Hook val6 = new Hook((MethodBase)typeof(Object).GetMethod("Instantiate", new Type[3]
			{
				typeof(Object),
				typeof(Vector3),
				typeof(Quaternion)
			}), typeof(FakePrefabHooks).GetMethod("InstantiateOPR"));
			Hook val7 = new Hook((MethodBase)typeof(Object).GetMethod("Instantiate", new Type[4]
			{
				typeof(Object),
				typeof(Vector3),
				typeof(Quaternion),
				typeof(Transform)
			}), typeof(FakePrefabHooks).GetMethod("InstantiateOPRP"));
		}

		public static void AcquirePassiveItemPrefabDirectly(Action<PlayerController, PassiveItem> orig, PlayerController self, PassiveItem item)
		{
			bool flag = FakePrefab.IsFakePrefab((Object)(object)((Component)item).gameObject);
			if (flag)
			{
				((Component)item).gameObject.SetActive(true);
			}
			orig(self, item);
			if (flag)
			{
				((Component)item).gameObject.SetActive(false);
			}
		}

		public static void ActivePickup(Action<PlayerItem, PlayerController> orig, PlayerItem self, PlayerController player)
		{
			bool flag = FakePrefab.IsFakePrefab((Object)(object)((Component)self).gameObject);
			if (flag)
			{
				((Component)self).gameObject.SetActive(true);
			}
			orig(self, player);
			if (flag)
			{
				((Component)self).gameObject.SetActive(false);
			}
		}

		public static Object InstantiateOPI(Func<Object, Transform, bool, Object> orig, Object original, Transform parent, bool instantiateInWorldSpace)
		{
			return FakePrefab.Instantiate(original, orig(original, parent, instantiateInWorldSpace));
		}

		public static Object InstantiateOP(Func<Object, Transform, Object> orig, Object original, Transform parent)
		{
			return FakePrefab.Instantiate(original, orig(original, parent));
		}

		public static Object InstantiateO(Func<Object, Object> orig, Object original)
		{
			return FakePrefab.Instantiate(original, orig(original));
		}

		public static Object InstantiateOPR(Func<Object, Vector3, Quaternion, Object> orig, Object original, Vector3 position, Quaternion rotation)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return FakePrefab.Instantiate(original, orig(original, position, rotation));
		}

		public static Object InstantiateOPRP(Func<Object, Vector3, Quaternion, Transform, Object> orig, Object original, Vector3 position, Quaternion rotation, Transform parent)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return FakePrefab.Instantiate(original, orig(original, position, rotation, parent));
		}
	}
	public static class ItemBuilder
	{
		public enum CooldownType
		{
			Timed,
			Damage,
			PerRoom,
			None
		}

		public enum ShopType
		{
			Goopton,
			Flynt,
			Cursula,
			Trorc,
			OldRed
		}

		public static Dictionary<ShopType, GenericLootTable> shopInventories;

		public static void Init()
		{
			FakePrefabHooks.Init();
			CompanionBuilder.Init();
			Tools.Init();
			LoadShopTables();
		}

		private static void LoadShopTables()
		{
			shopInventories = new Dictionary<ShopType, GenericLootTable>();
			shopInventories.Add(ShopType.Flynt, LoadShopTable("Shop_Key_Items_01"));
			shopInventories.Add(ShopType.Trorc, LoadShopTable("Shop_Truck_Items_01"));
			shopInventories.Add(ShopType.Cursula, LoadShopTable("Shop_Curse_Items_01"));
			shopInventories.Add(ShopType.Goopton, LoadShopTable("Shop_Goop_Items_01"));
			shopInventories.Add(ShopType.OldRed, LoadShopTable("Shop_Blank_Items_01"));
		}

		public static GenericLootTable LoadShopTable(string assetName)
		{
			return Tools.sharedAuto1.LoadAsset<GenericLootTable>(assetName);
		}

		public static GameObject AddSpriteToObject(string name, string resourcePath, GameObject obj = null)
		{
			GameObject val = SpriteBuilder.SpriteFromResource(resourcePath, obj);
			((Object)val).name = name;
			return val;
		}

		public static void SetupItem(this PickupObject item, string shortDesc, string longDesc, string idPool = "customItems")
		{
			try
			{
				((BraveBehaviour)item).encounterTrackable = null;
				Databases.Items.SetupItem(item, ((Object)item).name);
				SpriteBuilder.AddToAmmonomicon(((BraveBehaviour)item).sprite.GetCurrentSpriteDef());
				((BraveBehaviour)item).encounterTrackable.journalData.AmmonomiconSprite = ((BraveBehaviour)item).sprite.GetCurrentSpriteDef().name;
				GunExt.SetName(item, ((Object)item).name);
				GunExt.SetShortDescription(item, shortDesc);
				GunExt.SetLongDescription(item, longDesc);
				if (item is PlayerItem)
				{
					((PlayerItem)((item is PlayerItem) ? item : null)).consumable = false;
				}
				Game.Items.Add(idPool + ":" + ((Object)item).name.ToLower().Replace(" ", "_"), item);
				Databases.Items.Add(item, false, "ANY");
				FakePrefab.MarkAsFakePrefab(((Component)item).gameObject);
				((Component)item).gameObject.SetActive(false);
			}
			catch (Exception ex)
			{
				ETGModConsole.Log(ex.Message, false);
				ETGModConsole.Log(ex.StackTrace, false);
			}
		}

		public static void AddToSubShop(this PickupObject po, ShopType type, float weight)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			WeightedGameObjectCollection defaultItemDrops = shopInventories[type].defaultItemDrops;
			WeightedGameObject val = new WeightedGameObject();
			val.pickupId = po.PickupObjectId;
			val.weight = weight;
			val.rawGameObject = ((Component)po).gameObject;
			val.forceDuplicatesPossible = false;
			val.additionalPrerequisites = (DungeonPrerequisite[])(object)new DungeonPrerequisite[0];
			defaultItemDrops.Add(val);
		}

		public static void SetCooldownType(this PlayerItem item, CooldownType cooldownType, float value)
		{
			item.damageCooldown = -1f;
			item.roomCooldown = -1;
			item.timeCooldown = -1f;
			switch (cooldownType)
			{
			case CooldownType.Timed:
				item.timeCooldown = value;
				break;
			case CooldownType.Damage:
				item.damageCooldown = value;
				break;
			case CooldownType.PerRoom:
				item.roomCooldown = (int)value;
				break;
			}
		}

		public static StatModifier AddPassiveStatModifier(this PickupObject po, StatType statType, float amount, ModifyMethod method = 0)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_000f: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			StatModifier val = new StatModifier();
			val.amount = amount;
			val.statToBoost = statType;
			val.modifyType = method;
			po.AddPassiveStatModifier(val);
			return val;
		}

		public static void AddPassiveStatModifier(this PickupObject po, StatModifier modifier)
		{
			if (po is PlayerItem)
			{
				PlayerItem val = (PlayerItem)(object)((po is PlayerItem) ? po : null);
				if (val.passiveStatModifiers == null)
				{
					val.passiveStatModifiers = (StatModifier[])(object)new StatModifier[1] { modifier };
				}
				else
				{
					val.passiveStatModifiers = val.passiveStatModifiers.Concat((IEnumerable<StatModifier>)(object)new StatModifier[1] { modifier }).ToArray();
				}
				return;
			}
			if (po is PassiveItem)
			{
				PassiveItem val2 = (PassiveItem)(object)((po is PassiveItem) ? po : null);
				if (val2.passiveStatModifiers == null)
				{
					val2.passiveStatModifiers = (StatModifier[])(object)new StatModifier[1] { modifier };
				}
				else
				{
					val2.passiveStatModifiers = val2.passiveStatModifiers.Concat((IEnumerable<StatModifier>)(object)new StatModifier[1] { modifier }).ToArray();
				}
				return;
			}
			throw new NotSupportedException("Object must be of type PlayerItem or PassiveItem");
		}

		public static bool RemovePassiveStatModifier(this PickupObject po, StatModifier modifier)
		{
			bool flag = false;
			if (po is PlayerItem)
			{
				PlayerItem val = (PlayerItem)(object)((po is PlayerItem) ? po : null);
				if (val.passiveStatModifiers == null)
				{
					return false;
				}
				List<StatModifier> list = val.passiveStatModifiers.ToList();
				flag = list.Remove(modifier);
				val.passiveStatModifiers = list.ToArray();
			}
			else
			{
				if (!(po is PassiveItem))
				{
					throw new NotSupportedException("Object must be of type PlayerItem or PassiveItem");
				}
				PassiveItem val2 = (PassiveItem)(object)((po is PassiveItem) ? po : null);
				if (val2.passiveStatModifiers == null)
				{
					return false;
				}
				List<StatModifier> list2 = val2.passiveStatModifiers.ToList();
				flag = list2.Remove(modifier);
				val2.passiveStatModifiers = list2.ToArray();
			}
			return flag;
		}

		public static IEnumerator HandleDuration(PlayerItem item, float duration, PlayerController user, Action<PlayerController> OnFinish)
		{
			if (!item.IsCurrentlyActive)
			{
				SetPrivateType<PlayerItem>(item, "m_isCurrentlyActive", value: true);
				SetPrivateType<PlayerItem>(item, "m_activeElapsed", 0f);
				SetPrivateType<PlayerItem>(item, "m_activeDuration", duration);
				item.OnActivationStatusChanged?.Invoke(item);
				GetPrivateType<PlayerItem, float>(item, "m_activeElapsed");
				GetPrivateType<PlayerItem, float>(item, "m_activeDuration");
				while (GetPrivateType<PlayerItem, float>(item, "m_activeElapsed") < GetPrivateType<PlayerItem, float>(item, "m_activeDuration") && item.IsCurrentlyActive)
				{
					yield return null;
				}
				SetPrivateType<PlayerItem>(item, "m_isCurrentlyActive", value: false);
				item.OnActivationStatusChanged?.Invoke(item);
				OnFinish?.Invoke(user);
			}
		}

		private static void SetPrivateType<T>(T obj, string field, bool value)
		{
			FieldInfo field2 = typeof(T).GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);
			field2.SetValue(obj, value);
		}

		private static void SetPrivateType<T>(T obj, string field, float value)
		{
			FieldInfo field2 = typeof(T).GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);
			field2.SetValue(obj, value);
		}

		private static T2 GetPrivateType<T, T2>(T obj, string field)
		{
			FieldInfo field2 = typeof(T).GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);
			return (T2)field2.GetValue(obj);
		}
	}
	public static class Tools
	{
		public static bool verbose = false;

		private static string defaultLog = Path.Combine(ETGMod.ResourcesDirectory, "exampleMod.txt");

		public static string modID = "EX";

		public static AssetBundle sharedAuto1 = ResourceManager.LoadAssetBundle("shared_auto_001");

		public static AssetBundle sharedAuto2 = ResourceManager.LoadAssetBundle("shared_auto_002");

		public static void Init()
		{
			if (File.Exists(defaultLog))
			{
				File.Delete(defaultLog);
			}
		}

		public static void Print<T>(T obj, string color = "FFFFFF", bool force = false)
		{
			if (verbose || force)
			{
				ETGModConsole.Log("<color=#" + color + ">" + modID + ": " + obj.ToString() + "</color>", false);
			}
			Log(obj.ToString());
		}

		public static void PrintRaw<T>(T obj, bool force = false)
		{
			if (verbose || force)
			{
				ETGModConsole.Log(obj.ToString(), false);
			}
			Log(obj.ToString());
		}

		public static void PrintError<T>(T obj, string color = "FF0000")
		{
			ETGModConsole.Log("<color=#" + color + ">" + modID + ": " + obj.ToString() + "</color>", false);
			Log(obj.ToString());
		}

		public static void PrintException(Exception e, string color = "FF0000")
		{
			ETGModConsole.Log("<color=#" + color + ">" + modID + ": " + e.Message + "</color>", false);
			ETGModConsole.Log(e.StackTrace, false);
			Log(e.Message);
			Log("\t" + e.StackTrace);
		}

		public static void Log<T>(T obj)
		{
			using StreamWriter streamWriter = new StreamWriter(Path.Combine(ETGMod.ResourcesDirectory, defaultLog), append: true);
			streamWriter.WriteLine(obj.ToString());
		}

		public static void Log<T>(T obj, string fileName)
		{
			if (!verbose)
			{
				return;
			}
			using StreamWriter streamWriter = new StreamWriter(Path.Combine(ETGMod.ResourcesDirectory, fileName), append: true);
			streamWriter.WriteLine(obj.ToString());
		}

		public static void Dissect(this GameObject obj)
		{
			Print(((Object)obj).name + " Components:");
			Component[] components = obj.GetComponents<Component>();
			foreach (Component val in components)
			{
				Print("    " + ((object)val).GetType());
			}
		}

		public static void ShowHitBox(this SpeculativeRigidbody body)
		{
			//IL_004e: 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_007b: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			PixelCollider hitboxPixelCollider = body.HitboxPixelCollider;
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = "HitboxDisplay";
			val.transform.SetParent(((BraveBehaviour)body).transform);
			Print(((Object)body).name ?? "");
			Print($"    Offset: {hitboxPixelCollider.Offset}, Dimesions: {hitboxPixelCollider.Dimensions}");
			val.transform.localScale = new Vector3((float)hitboxPixelCollider.Dimensions.x / 16f, (float)hitboxPixelCollider.Dimensions.y / 16f, 1f);
			Vector3 localPosition = new Vector3((float)hitboxPixelCollider.Offset.x + (float)hitboxPixelCollider.Dimensions.x * 0.5f, (float)hitboxPixelCollider.Offset.y + (float)hitboxPixelCollider.Dimensions.y * 0.5f, -16f) / 16f;
			val.transform.localPosition = localPosition;
		}

		public static void HideHitBox(this SpeculativeRigidbody body)
		{
			Transform val = ((BraveBehaviour)body).transform.Find("HitboxDisplay");
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.Destroy((Object)(object)val);
			}
		}

		public static void ExportTexture(Texture texture)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			File.WriteAllBytes(Path.Combine(ETGMod.ResourcesDirectory, ((Object)texture).name + ".png"), ImageConversion.EncodeToPNG((Texture2D)texture));
		}

		public static void LogPropertiesAndFields<T>(this T obj, string header = "")
		{
			Log(header);
			Log("=======================");
			if (obj == null)
			{
				Log("LogPropertiesAndFields: Null object");
				return;
			}
			Type type = obj.GetType();
			Log($"Type: {type}");
			PropertyInfo[] properties = type.GetProperties();
			Log($"{typeof(T)} Properties: ");
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				try
				{
					object value = propertyInfo.GetValue(obj, null);
					string text = value.ToString();
					if ((object)obj?.GetType().GetGenericTypeDefinition() == typeof(List<>))
					{
						List<object> list = value as List<object>;
						text = $"List[{list.Count}]";
						foreach (object item in list)
						{
							text = text + "\n\t\t" + item.ToString();
						}
					}
					Log("\t" + propertyInfo.Name + ": " + text);
				}
				catch
				{
				}
			}
			Log($"{typeof(T)} Fields: ");
			FieldInfo[] fields = type.GetFields();
			FieldInfo[] array2 = fields;
			foreach (FieldInfo fieldInfo in array2)
			{
				Log($"\t{fieldInfo.Name}: {fieldInfo.GetValue(obj)}");
			}
		}
	}
	public static class ResourceExtractor
	{
		private static string spritesDirectory = Path.Combine(ETGMod.ResourcesDirectory, "sprites");

		public static List<Texture2D> GetTexturesFromDirectory(string directoryPath)
		{
			if (!Directory.Exists(directoryPath))
			{
				Tools.PrintError(directoryPath + " not found.");
				return null;
			}
			List<Texture2D> list = new List<Texture2D>();
			string[] files = Directory.GetFiles(directoryPath);
			foreach (string text in files)
			{
				if (text.EndsWith(".png"))
				{
					Texture2D item = BytesToTexture(File.ReadAllBytes(text), Path.GetFileName(text).Replace(".png", ""));
					list.Add(item);
				}
			}
			return list;
		}

		public static Texture2D GetTextureFromFile(string fileName, string extension = ".png")
		{
			fileName = fileName.Replace(extension, "");
			string text = Path.Combine(spritesDirectory, fileName + extension);
			if (!File.Exists(text))
			{
				Tools.PrintError(text + " not found.");
				return null;
			}
			return BytesToTexture(File.ReadAllBytes(text), fileName);
		}

		public static List<string> GetCollectionFiles()
		{
			List<string> list = new List<string>();
			string[] files = Directory.GetFiles(spritesDirectory);
			foreach (string text in files)
			{
				if (text.EndsWith(".png"))
				{
					list.Add(Path.GetFileName(text).Replace(".png", ""));
				}
			}
			return list;
		}

		public static Texture2D BytesToTexture(byte[] bytes, string resourceName)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, bytes);
			((Texture)val).filterMode = (FilterMode)0;
			((Object)val).name = resourceName;
			return val;
		}

		public static string[] GetLinesFromEmbeddedResource(string filePath)
		{
			string text = BytesToString(ExtractEmbeddedResource(filePath));
			return text.Split(new char[1] { '\n' });
		}

		public static string[] GetLinesFromFile(string filePath)
		{
			string text = BytesToString(File.ReadAllBytes(filePath));
			return text.Split(new char[1] { '\n' });
		}

		public static string BytesToString(byte[] bytes)
		{
			return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
		}

		public static List<string> GetResourceFolders()
		{
			List<string> list = new List<string>();
			string path = Path.Combine(ETGMod.ResourcesDirectory, "sprites");
			if (Directory.Exists(path))
			{
				string[] directories = Directory.GetDirectories(path);
				foreach (string path2 in directories)
				{
					list.Add(Path.GetFileName(path2));
				}
			}
			return list;
		}

		public static byte[] ExtractEmbeddedResource(string filePath)
		{
			filePath = filePath.Replace("/", ".");
			filePath = filePath.Replace("\\", ".");
			Assembly callingAssembly = Assembly.GetCallingAssembly();
			using Stream stream = callingAssembly.GetManifestResourceStream(filePath);
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			return array;
		}

		public static Texture2D GetTextureFromResource(string resourceName)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			byte[] array = ExtractEmbeddedResource(resourceName);
			if (array == null)
			{
				Tools.PrintError("No bytes found in " + resourceName);
				return null;
			}
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, array);
			((Texture)val).filterMode = (FilterMode)0;
			string text = resourceName.Substring(0, resourceName.LastIndexOf('.'));
			if (text.LastIndexOf('.') >= 0)
			{
				text = text.Substring(text.LastIndexOf('.') + 1);
			}
			((Object)val).name = text;
			return val;
		}

		public static string[] GetResourceNames()
		{
			Assembly callingAssembly = Assembly.GetCallingAssembly();
			string[] manifestResourceNames = callingAssembly.GetManifestResourceNames();
			if (manifestResourceNames == null)
			{
				ETGModConsole.Log("No manifest resources found.", false);
				return null;
			}
			return manifestResourceNames;
		}
	}
	public static class SpriteBuilder
	{
		private static tk2dSpriteCollectionData itemCollection = ((BraveBehaviour)PickupObjectDatabase.GetByEncounterName("singularity")).sprite.Collection;

		private static tk2dSpriteCollectionData ammonomiconCollection = AmmonomiconController.ForceInstance.EncounterIconCollection;

		private static tk2dSprite baseSprite = ((Component)PickupObjectDatabase.GetByEncounterName("singularity")).GetComponent<tk2dSprite>();

		public static GameObject SpriteFromFile(string spriteName, GameObject obj = null)
		{
			string fileName = spriteName.Replace(".png", "");
			Texture2D textureFromFile = ResourceExtractor.GetTextureFromFile(fileName);
			if ((Object)(object)textureFromFile == (Object)null)
			{
				return null;
			}
			return SpriteFromTexture(textureFromFile, spriteName, obj);
		}

		public static GameObject SpriteFromResource(string spriteName, GameObject obj = null)
		{
			string text = ((!spriteName.EndsWith(".png")) ? ".png" : "");
			string text2 = spriteName + text;
			Texture2D textureFromResource = ResourceExtractor.GetTextureFromResource(text2);
			if ((Object)(object)textureFromResource == (Object)null)
			{
				return null;
			}
			return SpriteFromTexture(textureFromResource, text2, obj);
		}

		public static GameObject SpriteFromTexture(Texture2D texture, string spriteName, GameObject obj = null)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			if ((Object)(object)obj == (Object)null)
			{
				obj = new GameObject();
			}
			tk2dSprite val = obj.AddComponent<tk2dSprite>();
			int num = AddSpriteToCollection(spriteName, itemCollection);
			((tk2dBaseSprite)val).SetSprite(itemCollection, num);
			((tk2dBaseSprite)val).SortingOrder = 0;
			((tk2dBaseSprite)val).IsPerpendicular = true;
			obj.GetComponent<BraveBehaviour>().sprite = (tk2dBaseSprite)(object)val;
			return obj;
		}

		public static int AddSpriteToCollection(string resourcePath, tk2dSpriteCollectionData collection)
		{
			string text = ((!resourcePath.EndsWith(".png")) ? ".png" : "");
			resourcePath += text;
			Texture2D textureFromResource = ResourceExtractor.GetTextureFromResource(resourcePath);
			tk2dSpriteDefinition val = ConstructDefinition(textureFromResource);
			val.name = ((Object)textureFromResource).name;
			return AddSpriteToCollection(val, collection);
		}

		public static int AddSpriteToCollection(tk2dSpriteDefinition spriteDefinition, tk2dSpriteCollectionData collection)
		{
			tk2dSpriteDefinition[] spriteDefinitions = collection.spriteDefinitions;
			tk2dSpriteDefinition[] array = (collection.spriteDefinitions = spriteDefinitions.Concat((IEnumerable<tk2dSpriteDefinition>)(object)new tk2dSpriteDefinition[1] { spriteDefinition }).ToArray());
			FieldInfo field = typeof(tk2dSpriteCollectionData).GetField("spriteNameLookupDict", BindingFlags.Instance | BindingFlags.NonPublic);
			field.SetValue(collection, null);
			collection.InitDictionary();
			return array.Length - 1;
		}

		public static int AddToAmmonomicon(tk2dSpriteDefinition spriteDefinition)
		{
			return AddSpriteToCollection(spriteDefinition, ammonomiconCollection);
		}

		public static tk2dSpriteAnimationClip AddAnimation(tk2dSpriteAnimator animator, tk2dSpriteCollectionData collection, List<int> spriteIDs, string clipName, WrapMode wrapMode = 0)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			if ((Object)(object)animator.Library == (Object)null)
			{
				animator.Library = ((Component)animator).gameObject.AddComponent<tk2dSpriteAnimation>();
				animator.Library.clips = (tk2dSpriteAnimationClip[])(object)new tk2dSpriteAnimationClip[0];
				((Behaviour)animator.Library).enabled = true;
			}
			List<tk2dSpriteAnimationFrame> list = new List<tk2dSpriteAnimationFrame>();
			for (int i = 0; i < spriteIDs.Count; i++)
			{
				tk2dSpriteDefinition val = collection.spriteDefinitions[spriteIDs[i]];
				if (val.Valid)
				{
					list.Add(new tk2dSpriteAnimationFrame
					{
						spriteCollection = collection,
						spriteId = spriteIDs[i]
					});
				}
			}
			tk2dSpriteAnimationClip val2 = new tk2dSpriteAnimationClip
			{
				name = clipName,
				fps = 15f,
				wrapMode = wrapMode
			};
			Array.Resize(ref animator.Library.clips, animator.Library.clips.Length + 1);
			animator.Library.clips[animator.Library.clips.Length - 1] = val2;
			val2.frames = list.ToArray();
			return val2;
		}

		public static SpeculativeRigidbody SetUpSpeculativeRigidbody(this tk2dSprite sprite, IntVector2 offset, IntVector2 dimensions)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			SpeculativeRigidbody orAddComponent = GameObjectExtensions.GetOrAddComponent<SpeculativeRigidbody>(((Component)sprite).gameObject);
			PixelCollider val = new PixelCollider();
			val.ColliderGenerationMode = (PixelColliderGeneration)0;
			val.CollisionLayer = (CollisionLayer)3;
			val.ManualWidth = dimensions.x;
			val.ManualHeight = dimensions.y;
			val.ManualOffsetX = offset.x;
			val.ManualOffsetY = offset.y;
			orAddComponent.PixelColliders = new List<PixelCollider> { val };
			return orAddComponent;
		}

		public static tk2dSpriteDefinition ConstructDefinition(Texture2D texture)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_007b: 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_0096: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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_013a: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: 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_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			RuntimeAtlasSegment val = Assets.Packer.Pack(texture, false);
			Material val2 = new Material(ShaderCache.Acquire(PlayerController.DefaultShaderName));
			val2.mainTexture = (Texture)(object)val.texture;
			int width = ((Texture)texture).width;
			int height = ((Texture)texture).height;
			float num = 0f;
			float num2 = 0f;
			float num3 = (float)width / 16f;
			float num4 = (float)height / 16f;
			tk2dSpriteDefinition val3 = new tk2dSpriteDefinition();
			val3.normals = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(0f, 0f, -1f),
				new Vector3(0f, 0f, -1f),
				new Vector3(0f, 0f, -1f),
				new Vector3(0f, 0f, -1f)
			};
			val3.tangents = (Vector4[])(object)new Vector4[4]
			{
				new Vector4(1f, 0f, 0f, 1f),
				new Vector4(1f, 0f, 0f, 1f),
				new Vector4(1f, 0f, 0f, 1f),
				new Vector4(1f, 0f, 0f, 1f)
			};
			val3.texelSize = new Vector2(0.0625f, 0.0625f);
			val3.extractRegion = false;
			val3.regionX = 0;
			val3.regionY = 0;
			val3.regionW = 0;
			val3.regionH = 0;
			val3.flipped = (FlipMode)0;
			val3.complexGeometry = false;
			val3.physicsEngine = (PhysicsEngine)0;
			val3.colliderType = (ColliderType)1;
			val3.collisionLayer = (CollisionLayer)6;
			val3.position0 = new Vector3(num, num2, 0f);
			val3.position1 = new Vector3(num + num3, num2, 0f);
			val3.position2 = new Vector3(num, num2 + num4, 0f);
			val3.position3 = new Vector3(num + num3, num2 + num4, 0f);
			val3.material = val2;
			val3.materialInst = val2;
			val3.materialId = 0;
			val3.uvs = val.uvs;
			val3.boundsDataCenter = new Vector3(num3 / 2f, num4 / 2f, 0f);
			val3.boundsDataExtents = new Vector3(num3, num4, 0f);
			val3.untrimmedBoundsDataCenter = new Vector3(num3 / 2f, num4 / 2f, 0f);
			val3.untrimmedBoundsDataExtents = new Vector3(num3, num4, 0f);
			tk2dSpriteDefinition val4 = val3;
			val4.name = ((Object)texture).name;
			return val4;
		}

		public static tk2dSpriteCollectionData ConstructCollection(GameObject obj, string name)
		{
			tk2dSpriteCollectionData val = obj.AddComponent<tk2dSpriteCollectionData>();
			Object.DontDestroyOnLoad((Object)(object)val);
			val.assetName = name;
			val.spriteCollectionGUID = name;
			val.spriteCollectionName = name;
			val.spriteDefinitions = (tk2dSpriteDefinition[])(object)new tk2dSpriteDefinition[0];
			return val;
		}

		public static T CopyFrom<T>(this Component comp, T other) where T : Component
		{
			Type type = ((object)comp).GetType();
			if ((object)type != ((object)other).GetType())
			{
				return default(T);
			}
			PropertyInfo[] properties = type.GetProperties();
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				if (propertyInfo.CanWrite)
				{
					try
					{
						propertyInfo.SetValue(comp, propertyInfo.GetValue(other, null), null);
					}
					catch
					{
					}
				}
			}
			FieldInfo[] fields = type.GetFields();
			FieldInfo[] array2 = fields;
			foreach (FieldInfo fieldInfo in array2)
			{
				fieldInfo.SetValue(comp, fieldInfo.GetValue(other));
			}
			return (T)(object)((comp is T) ? comp : null);
		}

		public static void SetColor(this tk2dSprite sprite, Color color)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			((BraveBehaviour)sprite).renderer.material.SetColor("_OverrideColor", color);
		}

		public static T AddComponent<T>(this GameObject go, T toAdd) where T : Component
		{
			return ((Component)(object)go.AddComponent<T>()).CopyFrom(toAdd);
		}
	}
}

plugins/Batteritems/MonoMod.RuntimeDetour.dll

Decompiled 8 months ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using Harmony.ILCopying;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyTitle("MonoMod.RuntimeDetour")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MonoMod.RuntimeDetour")]
[assembly: AssemblyCopyright("Copyright ©  2018")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d0c584c0-81d7-486e-b70e-d7f9256e0909")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("18.9.0.42435")]
[module: UnverifiableCode]
namespace Harmony.ILCopying
{
	internal enum ExceptionBlockType
	{
		BeginExceptionBlock,
		BeginCatchBlock,
		BeginExceptFilterBlock,
		BeginFaultBlock,
		BeginFinallyBlock,
		EndExceptionBlock
	}
	internal class ExceptionBlock
	{
		public ExceptionBlockType blockType;

		public Type catchType;

		public ExceptionBlock(ExceptionBlockType blockType, Type catchType)
		{
			this.blockType = blockType;
			this.catchType = catchType;
		}
	}
	internal class ILInstruction
	{
		public int offset;

		public OpCode opcode;

		public object operand;

		public object argument;

		public List<Label> labels = new List<Label>();

		public List<ExceptionBlock> blocks = new List<ExceptionBlock>();

		public ILInstruction(OpCode opcode, object operand = null)
		{
			this.opcode = opcode;
			this.operand = operand;
			argument = operand;
		}

		public int GetSize()
		{
			int num = opcode.Size;
			switch (opcode.OperandType)
			{
			case OperandType.InlineSwitch:
				num += (1 + ((int[])operand).Length) * 4;
				break;
			case OperandType.InlineI8:
			case OperandType.InlineR:
				num += 8;
				break;
			case OperandType.InlineBrTarget:
			case OperandType.InlineField:
			case OperandType.InlineI:
			case OperandType.InlineMethod:
			case OperandType.InlineString:
			case OperandType.InlineTok:
			case OperandType.InlineType:
			case OperandType.ShortInlineR:
				num += 4;
				break;
			case OperandType.InlineVar:
				num += 2;
				break;
			case OperandType.ShortInlineBrTarget:
			case OperandType.ShortInlineI:
			case OperandType.ShortInlineVar:
				num++;
				break;
			}
			return num;
		}

		public override string ToString()
		{
			string str = "";
			AppendLabel(ref str, this);
			str = str + ": " + opcode.Name;
			if (operand == null)
			{
				return str;
			}
			str += " ";
			switch (opcode.OperandType)
			{
			case OperandType.InlineBrTarget:
			case OperandType.ShortInlineBrTarget:
				AppendLabel(ref str, operand);
				break;
			case OperandType.InlineSwitch:
			{
				ILInstruction[] array = (ILInstruction[])operand;
				for (int i = 0; i < array.Length; i++)
				{
					if (i > 0)
					{
						str += ",";
					}
					AppendLabel(ref str, array[i]);
				}
				break;
			}
			case OperandType.InlineString:
				str = string.Concat(str, "\"", operand, "\"");
				break;
			default:
				str += operand;
				break;
			}
			return str;
		}

		private static void AppendLabel(ref string str, object argument)
		{
			if (argument is ILInstruction iLInstruction)
			{
				str = str + "IL_" + iLInstruction.offset.ToString("X4");
			}
			else
			{
				str = str + "IL_" + argument;
			}
		}
	}
	internal class MethodCopier : IDisposable
	{
		private class ThisParameter : ParameterInfo
		{
			public ThisParameter(MethodBase method)
			{
				MemberImpl = method;
				ClassImpl = method.DeclaringType;
				NameImpl = "this";
				PositionImpl = -1;
			}
		}

		private readonly ILGenerator generator;

		private readonly MethodBase method;

		private readonly Module module;

		private readonly Type[] typeArguments;

		private readonly Type[] methodArguments;

		private readonly BinaryReader ilBytes;

		private readonly ParameterInfo this_parameter;

		private readonly ParameterInfo[] parameters;

		private readonly IList<LocalVariableInfo> locals;

		private readonly IList<ExceptionHandlingClause> exceptions;

		private List<ILInstruction> ilInstructions;

		private LocalBuilder[] variables;

		private static Dictionary<short, OpCode> shortJumps;

		private static readonly OpCode[] one_byte_opcodes;

		private static readonly OpCode[] two_bytes_opcodes;

		private static readonly Dictionary<Type, MethodInfo> emitMethods;

		public MethodCopier(MethodBase method, ILGenerator generator)
		{
			this.generator = generator ?? throw new ArgumentNullException("Generator cannot be null");
			this.method = method ?? throw new ArgumentNullException("Method cannot be null");
			module = method.Module;
			MethodBody methodBody = method.GetMethodBody();
			if (methodBody == null)
			{
				throw new ArgumentException("Method " + method.Name + " has no body");
			}
			byte[] iLAsByteArray = methodBody.GetILAsByteArray();
			if (iLAsByteArray == null)
			{
				throw new ArgumentException("Can not get IL bytes of method " + method.Name);
			}
			ilBytes = new BinaryReader(new MemoryStream(iLAsByteArray));
			ilInstructions = new List<ILInstruction>((iLAsByteArray.Length + 1) / 2);
			Type declaringType = method.DeclaringType;
			if (declaringType.IsGenericType)
			{
				typeArguments = declaringType.GetGenericArguments();
			}
			if (method.IsGenericMethod)
			{
				methodArguments = method.GetGenericArguments();
			}
			if (!method.IsStatic)
			{
				this_parameter = new ThisParameter(method);
			}
			parameters = method.GetParameters();
			locals = methodBody.LocalVariables;
			exceptions = methodBody.ExceptionHandlingClauses;
			DeclareVariables();
			ReadInstructions();
		}

		public void DeclareVariables()
		{
			variables = locals.Select((LocalVariableInfo lvi) => generator.DeclareLocal(lvi.LocalType, lvi.IsPinned)).ToArray();
		}

		public void ReadInstructions()
		{
			while (ilBytes.BaseStream.Position < ilBytes.BaseStream.Length)
			{
				int offset = (int)ilBytes.BaseStream.Position;
				ILInstruction iLInstruction = new ILInstruction(ReadOpCode())
				{
					offset = offset
				};
				ReadOperand(iLInstruction);
				ilInstructions.Add(iLInstruction);
			}
			ResolveBranches();
			ParseExceptions();
		}

		private void ResolveBranches()
		{
			foreach (ILInstruction ilInstruction in ilInstructions)
			{
				switch (ilInstruction.opcode.OperandType)
				{
				case OperandType.InlineBrTarget:
				case OperandType.ShortInlineBrTarget:
					ilInstruction.operand = GetInstruction((int)ilInstruction.operand, isEndOfInstruction: false);
					break;
				case OperandType.InlineSwitch:
				{
					int[] array = (int[])ilInstruction.operand;
					ILInstruction[] array2 = new ILInstruction[array.Length];
					for (int i = 0; i < array.Length; i++)
					{
						array2[i] = GetInstruction(array[i], isEndOfInstruction: false);
					}
					ilInstruction.operand = array2;
					break;
				}
				}
			}
		}

		private void ParseExceptions()
		{
			foreach (ExceptionHandlingClause exception in exceptions)
			{
				int tryOffset = exception.TryOffset;
				int num = exception.TryOffset + exception.TryLength - 1;
				int handlerOffset = exception.HandlerOffset;
				int offset = exception.HandlerOffset + exception.HandlerLength - 1;
				string text = ((exception.Flags == ExceptionHandlingClauseOptions.Clause) ? "catch" : exception.Flags.ToString().ToLower());
				ILInstruction instruction = GetInstruction(tryOffset, isEndOfInstruction: false);
				instruction.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginExceptionBlock, null));
				ILInstruction instruction2 = GetInstruction(offset, isEndOfInstruction: true);
				instruction2.blocks.Add(new ExceptionBlock(ExceptionBlockType.EndExceptionBlock, null));
				switch (exception.Flags)
				{
				case ExceptionHandlingClauseOptions.Filter:
				{
					ILInstruction instruction3 = GetInstruction(exception.FilterOffset, isEndOfInstruction: false);
					instruction3.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginExceptFilterBlock, null));
					break;
				}
				case ExceptionHandlingClauseOptions.Finally:
				{
					ILInstruction instruction3 = GetInstruction(handlerOffset, isEndOfInstruction: false);
					instruction3.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginFinallyBlock, null));
					break;
				}
				case ExceptionHandlingClauseOptions.Clause:
				{
					ILInstruction instruction3 = GetInstruction(handlerOffset, isEndOfInstruction: false);
					instruction3.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginCatchBlock, exception.CatchType));
					break;
				}
				case ExceptionHandlingClauseOptions.Fault:
				{
					ILInstruction instruction3 = GetInstruction(handlerOffset, isEndOfInstruction: false);
					instruction3.blocks.Add(new ExceptionBlock(ExceptionBlockType.BeginFaultBlock, null));
					break;
				}
				}
			}
		}

		public void Copy()
		{
			if (generator == null)
			{
				return;
			}
			foreach (ILInstruction ilInstruction in ilInstructions)
			{
				switch (ilInstruction.opcode.OperandType)
				{
				case OperandType.InlineSwitch:
					if (ilInstruction.operand is ILInstruction[] array)
					{
						List<Label> list = new List<Label>();
						ILInstruction[] array2 = array;
						foreach (ILInstruction iLInstruction2 in array2)
						{
							Label item = generator.DefineLabel();
							iLInstruction2.labels.Add(item);
							list.Add(item);
						}
						ilInstruction.argument = list.ToArray();
					}
					break;
				case OperandType.InlineBrTarget:
				case OperandType.ShortInlineBrTarget:
					if (ilInstruction.operand is ILInstruction iLInstruction)
					{
						Label label = generator.DefineLabel();
						iLInstruction.labels.Add(label);
						ilInstruction.argument = label;
					}
					break;
				}
			}
			int num = 0;
			foreach (ILInstruction ilInstruction2 in ilInstructions)
			{
				foreach (Label label3 in ilInstruction2.labels)
				{
					generator.MarkLabel(label3);
				}
				foreach (ExceptionBlock block in ilInstruction2.blocks)
				{
					switch (block.blockType)
					{
					case ExceptionBlockType.BeginExceptionBlock:
					{
						Label label2 = generator.BeginExceptionBlock();
						break;
					}
					case ExceptionBlockType.BeginCatchBlock:
						generator.BeginCatchBlock(block.catchType);
						break;
					case ExceptionBlockType.BeginExceptFilterBlock:
						generator.BeginExceptFilterBlock();
						break;
					case ExceptionBlockType.BeginFaultBlock:
						generator.BeginFaultBlock();
						break;
					case ExceptionBlockType.BeginFinallyBlock:
						generator.BeginFinallyBlock();
						break;
					}
				}
				OpCode opCode = ilInstruction2.opcode;
				object argument = ilInstruction2.argument;
				if (shortJumps.TryGetValue(opCode.Value, out var value))
				{
					opCode = value;
				}
				if (opCode.OperandType == OperandType.InlineNone)
				{
					generator.Emit(opCode);
				}
				else
				{
					if (argument == null)
					{
						throw new Exception("Wrong null argument: " + ilInstruction2);
					}
					MethodInfo methodInfo = EmitMethodForType(argument.GetType());
					if ((object)methodInfo == null)
					{
						throw new Exception(string.Concat("Unknown Emit argument type ", argument.GetType(), " in ", ilInstruction2));
					}
					methodInfo.Invoke(generator, new object[2] { opCode, argument });
				}
				foreach (ExceptionBlock block2 in ilInstruction2.blocks)
				{
					if (block2.blockType == ExceptionBlockType.EndExceptionBlock)
					{
						generator.EndExceptionBlock();
					}
				}
				num++;
			}
		}

		private static void GetMemberInfoValue(MemberInfo info, out object result)
		{
			result = null;
			switch (info.MemberType)
			{
			case MemberTypes.Constructor:
				result = (ConstructorInfo)info;
				break;
			case MemberTypes.Event:
				result = (EventInfo)info;
				break;
			case MemberTypes.Field:
				result = (FieldInfo)info;
				break;
			case MemberTypes.Method:
				result = (MethodInfo)info;
				break;
			case MemberTypes.TypeInfo:
			case MemberTypes.NestedType:
				result = (Type)info;
				break;
			case MemberTypes.Property:
				result = (PropertyInfo)info;
				break;
			}
		}

		private void ReadOperand(ILInstruction instruction)
		{
			switch (instruction.opcode.OperandType)
			{
			case OperandType.InlineNone:
				instruction.argument = null;
				break;
			case OperandType.InlineSwitch:
			{
				int num6 = ilBytes.ReadInt32();
				int num7 = (int)ilBytes.BaseStream.Position + 4 * num6;
				int[] array = new int[num6];
				for (int i = 0; i < num6; i++)
				{
					array[i] = ilBytes.ReadInt32() + num7;
				}
				instruction.operand = array;
				break;
			}
			case OperandType.ShortInlineBrTarget:
			{
				sbyte b4 = (sbyte)ilBytes.ReadByte();
				instruction.operand = b4 + (int)ilBytes.BaseStream.Position;
				break;
			}
			case OperandType.InlineBrTarget:
			{
				int num8 = ilBytes.ReadInt32();
				instruction.operand = num8 + (int)ilBytes.BaseStream.Position;
				break;
			}
			case OperandType.ShortInlineI:
				if (instruction.opcode == OpCodes.Ldc_I4_S)
				{
					sbyte b2 = (sbyte)ilBytes.ReadByte();
					instruction.operand = b2;
					instruction.argument = (sbyte)instruction.operand;
				}
				else
				{
					byte b3 = ilBytes.ReadByte();
					instruction.operand = b3;
					instruction.argument = (byte)instruction.operand;
				}
				break;
			case OperandType.InlineI:
			{
				int num5 = ilBytes.ReadInt32();
				instruction.operand = num5;
				instruction.argument = (int)instruction.operand;
				break;
			}
			case OperandType.ShortInlineR:
			{
				float num3 = ilBytes.ReadSingle();
				instruction.operand = num3;
				instruction.argument = (float)instruction.operand;
				break;
			}
			case OperandType.InlineR:
			{
				double num2 = ilBytes.ReadDouble();
				instruction.operand = num2;
				instruction.argument = (double)instruction.operand;
				break;
			}
			case OperandType.InlineI8:
			{
				long num4 = ilBytes.ReadInt64();
				instruction.operand = num4;
				instruction.argument = (long)instruction.operand;
				break;
			}
			case OperandType.InlineSig:
			{
				int metadataToken = ilBytes.ReadInt32();
				instruction.operand = module.ResolveSignature(metadataToken);
				instruction.argument = (SignatureHelper)instruction.operand;
				break;
			}
			case OperandType.InlineString:
			{
				int metadataToken6 = ilBytes.ReadInt32();
				instruction.operand = module.ResolveString(metadataToken6);
				instruction.argument = (string)instruction.operand;
				break;
			}
			case OperandType.InlineTok:
			{
				int metadataToken5 = ilBytes.ReadInt32();
				instruction.operand = module.ResolveMember(metadataToken5, typeArguments, methodArguments);
				GetMemberInfoValue((MemberInfo)instruction.operand, out instruction.argument);
				break;
			}
			case OperandType.InlineType:
			{
				int metadataToken4 = ilBytes.ReadInt32();
				instruction.operand = module.ResolveType(metadataToken4, typeArguments, methodArguments);
				instruction.argument = (Type)instruction.operand;
				break;
			}
			case OperandType.InlineMethod:
			{
				int metadataToken3 = ilBytes.ReadInt32();
				instruction.operand = module.ResolveMethod(metadataToken3, typeArguments, methodArguments);
				if (instruction.operand is ConstructorInfo)
				{
					instruction.argument = (ConstructorInfo)instruction.operand;
				}
				else
				{
					instruction.argument = (MethodInfo)instruction.operand;
				}
				break;
			}
			case OperandType.InlineField:
			{
				int metadataToken2 = ilBytes.ReadInt32();
				instruction.operand = module.ResolveField(metadataToken2, typeArguments, methodArguments);
				instruction.argument = (FieldInfo)instruction.operand;
				break;
			}
			case OperandType.ShortInlineVar:
			{
				byte b = ilBytes.ReadByte();
				if (TargetsLocalVariable(instruction.opcode))
				{
					LocalVariableInfo localVariable2 = GetLocalVariable(b);
					if (localVariable2 == null)
					{
						instruction.argument = b;
						break;
					}
					instruction.operand = localVariable2;
					instruction.argument = variables[localVariable2.LocalIndex];
				}
				else
				{
					instruction.operand = GetParameter(b);
					instruction.argument = b;
				}
				break;
			}
			case OperandType.InlineVar:
			{
				short num = ilBytes.ReadInt16();
				if (TargetsLocalVariable(instruction.opcode))
				{
					LocalVariableInfo localVariable = GetLocalVariable(num);
					if (localVariable == null)
					{
						instruction.argument = num;
						break;
					}
					instruction.operand = localVariable;
					instruction.argument = variables[localVariable.LocalIndex];
				}
				else
				{
					instruction.operand = GetParameter(num);
					instruction.argument = num;
				}
				break;
			}
			default:
				throw new NotSupportedException();
			}
		}

		private ILInstruction GetInstruction(int offset, bool isEndOfInstruction)
		{
			int num = ilInstructions.Count - 1;
			if (offset < 0 || offset > ilInstructions[num].offset)
			{
				throw new Exception("Instruction offset " + offset + " is outside valid range 0 - " + ilInstructions[num].offset);
			}
			int num2 = 0;
			int num3 = num;
			while (num2 <= num3)
			{
				int num4 = num2 + (num3 - num2) / 2;
				ILInstruction iLInstruction = ilInstructions[num4];
				if (isEndOfInstruction)
				{
					if (offset == iLInstruction.offset + iLInstruction.GetSize() - 1)
					{
						return iLInstruction;
					}
				}
				else if (offset == iLInstruction.offset)
				{
					return iLInstruction;
				}
				if (offset < iLInstruction.offset)
				{
					num3 = num4 - 1;
				}
				else
				{
					num2 = num4 + 1;
				}
			}
			throw new Exception("Cannot find instruction for " + offset.ToString("X4"));
		}

		private static bool TargetsLocalVariable(OpCode opcode)
		{
			return opcode.Name.Contains("loc");
		}

		private LocalVariableInfo GetLocalVariable(int index)
		{
			return locals?[index];
		}

		private ParameterInfo GetParameter(int index)
		{
			if (this_parameter != null)
			{
				if (index == 0)
				{
					return this_parameter;
				}
				return parameters[index - 1];
			}
			return parameters[index];
		}

		private OpCode ReadOpCode()
		{
			byte b = ilBytes.ReadByte();
			return (b != 254) ? one_byte_opcodes[b] : two_bytes_opcodes[ilBytes.ReadByte()];
		}

		private MethodInfo EmitMethodForType(Type type)
		{
			foreach (KeyValuePair<Type, MethodInfo> emitMethod in emitMethods)
			{
				if ((object)emitMethod.Key == type)
				{
					return emitMethod.Value;
				}
			}
			foreach (KeyValuePair<Type, MethodInfo> emitMethod2 in emitMethods)
			{
				if (emitMethod2.Key.IsAssignableFrom(type))
				{
					return emitMethod2.Value;
				}
			}
			return null;
		}

		public void Dispose()
		{
			((IDisposable)ilBytes).Dispose();
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		static MethodCopier()
		{
			Dictionary<short, OpCode> dictionary = new Dictionary<short, OpCode>();
			OpCode leave_S = OpCodes.Leave_S;
			dictionary.Add(leave_S.Value, OpCodes.Leave);
			leave_S = OpCodes.Brfalse_S;
			dictionary.Add(leave_S.Value, OpCodes.Brfalse);
			leave_S = OpCodes.Brtrue_S;
			dictionary.Add(leave_S.Value, OpCodes.Brtrue);
			leave_S = OpCodes.Beq_S;
			dictionary.Add(leave_S.Value, OpCodes.Beq);
			leave_S = OpCodes.Bge_S;
			dictionary.Add(leave_S.Value, OpCodes.Bge);
			leave_S = OpCodes.Bgt_S;
			dictionary.Add(leave_S.Value, OpCodes.Bgt);
			leave_S = OpCodes.Ble_S;
			dictionary.Add(leave_S.Value, OpCodes.Ble);
			leave_S = OpCodes.Blt_S;
			dictionary.Add(leave_S.Value, OpCodes.Blt);
			leave_S = OpCodes.Bne_Un_S;
			dictionary.Add(leave_S.Value, OpCodes.Bne_Un);
			leave_S = OpCodes.Bge_Un_S;
			dictionary.Add(leave_S.Value, OpCodes.Bge_Un);
			leave_S = OpCodes.Bgt_Un_S;
			dictionary.Add(leave_S.Value, OpCodes.Bgt_Un);
			leave_S = OpCodes.Ble_Un_S;
			dictionary.Add(leave_S.Value, OpCodes.Ble_Un);
			leave_S = OpCodes.Br_S;
			dictionary.Add(leave_S.Value, OpCodes.Br);
			leave_S = OpCodes.Blt_Un_S;
			dictionary.Add(leave_S.Value, OpCodes.Blt_Un);
			shortJumps = dictionary;
			one_byte_opcodes = new OpCode[225];
			two_bytes_opcodes = new OpCode[31];
			FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				OpCode opCode = (OpCode)fieldInfo.GetValue(null);
				if (opCode.OpCodeType != OpCodeType.Nternal)
				{
					if (opCode.Size == 1)
					{
						one_byte_opcodes[opCode.Value] = opCode;
					}
					else
					{
						two_bytes_opcodes[opCode.Value & 0xFF] = opCode;
					}
				}
			}
			emitMethods = new Dictionary<Type, MethodInfo>();
			foreach (MethodInfo item in typeof(ILGenerator).GetMethods().ToList())
			{
				if (item.Name != "Emit")
				{
					continue;
				}
				ParameterInfo[] array2 = item.GetParameters();
				if (array2.Length == 2)
				{
					Type[] array3 = array2.Select((ParameterInfo p) => p.ParameterType).ToArray();
					if ((object)array3[0] == typeof(OpCode))
					{
						emitMethods[array3[1]] = item;
					}
				}
			}
		}
	}
}
namespace MonoMod.RuntimeDetour
{
	public class Detour : IDetour, IDisposable
	{
		private static Dictionary<MethodBase, List<Detour>> _DetourMap = new Dictionary<MethodBase, List<Detour>>();

		private static Dictionary<MethodBase, DynamicMethod> _BackupMethods = new Dictionary<MethodBase, DynamicMethod>();

		public static Func<object, MethodBase, MethodBase, bool> OnDetour;

		public static Func<object, bool> OnUndo;

		public static Func<object, MethodBase, MethodBase> OnGenerateTrampoline;

		public readonly MethodBase Method;

		public readonly MethodBase Target;

		private NativeDetour _TopDetour;

		private DynamicMethod _ChainedTrampoline;

		public bool IsValid => _DetourMap[Method].Contains(this);

		public int Index
		{
			get
			{
				return _DetourMap[Method].IndexOf(this);
			}
			set
			{
				List<Detour> list = _DetourMap[Method];
				lock (list)
				{
					int num = list.IndexOf(this);
					if (num == -1)
					{
						throw new InvalidOperationException("This detour has been undone.");
					}
					list.RemoveAt(num);
					if (value > num)
					{
						value--;
					}
					try
					{
						list.Insert(value, this);
					}
					catch
					{
						list.Insert(num, this);
						throw;
					}
					Detour detour = list[list.Count - 1];
					if (detour != this)
					{
						_TopUndo();
					}
					detour._TopApply();
					_UpdateChainedTrampolines(Method);
				}
			}
		}

		public Detour(MethodBase from, MethodBase to)
		{
			Method = from;
			Target = to;
			Func<object, MethodBase, MethodBase, bool> onDetour = OnDetour;
			if (onDetour != null && !Extensions.InvokeWhileTrue((MulticastDelegate)onDetour, new object[3] { this, from, to }))
			{
				return;
			}
			if (!_BackupMethods.ContainsKey(Method))
			{
				_BackupMethods[Method] = Method.CreateILCopy();
			}
			ParameterInfo[] parameters = Method.GetParameters();
			Type[] array;
			if (!Method.IsStatic)
			{
				array = new Type[parameters.Length + 1];
				array[0] = Method.DeclaringType;
				for (int i = 0; i < parameters.Length; i++)
				{
					array[i + 1] = parameters[i].ParameterType;
				}
			}
			else
			{
				array = new Type[parameters.Length];
				for (int j = 0; j < parameters.Length; j++)
				{
					array[j] = parameters[j].ParameterType;
				}
			}
			_ChainedTrampoline = new DynamicMethod($"chain_{Method.Name}_{GetHashCode()}", (Method as MethodInfo)?.ReturnType ?? typeof(void), array, Method.DeclaringType, skipVisibility: false).StubCriticalDetour().Pin();
			List<Detour> value;
			lock (_DetourMap)
			{
				if (!_DetourMap.TryGetValue(Method, out value))
				{
					value = (_DetourMap[Method] = new List<Detour>());
				}
			}
			lock (value)
			{
				if (value.Count > 0)
				{
					value[value.Count - 1]._TopUndo();
				}
				_TopApply();
				NativeDetourData detour = ((value.Count <= 0) ? DetourManager.Native.Create(_ChainedTrampoline.GetNativeStart(), _BackupMethods[Method].GetNativeStart()) : DetourManager.Native.Create(_ChainedTrampoline.GetNativeStart(), value[value.Count - 1].Target.GetNativeStart()));
				DetourManager.Native.MakeWritable(detour);
				DetourManager.Native.Apply(detour);
				DetourManager.Native.MakeExecutable(detour);
				DetourManager.Native.Free(detour);
				value.Add(this);
			}
		}

		public Detour(MethodBase method, IntPtr to)
			: this(method, DetourManager.GenerateNativeProxy(to, method))
		{
		}

		public Detour(Delegate from, IntPtr to)
			: this(from.Method, to)
		{
		}

		public Detour(Delegate from, Delegate to)
			: this(from.Method, to.Method)
		{
		}

		public Detour(Expression from, IntPtr to)
			: this(((MethodCallExpression)from).Method, to)
		{
		}

		public Detour(Expression from, Expression to)
			: this(((MethodCallExpression)from).Method, ((MethodCallExpression)to).Method)
		{
		}

		public Detour(Expression<Action> from, IntPtr to)
			: this(from.Body, to)
		{
		}

		public Detour(Expression<Action> from, Expression<Action> to)
			: this(from.Body, to.Body)
		{
		}

		public void Apply()
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("This detour has been undone.");
			}
		}

		public void Undo()
		{
			Func<object, bool> onUndo = OnUndo;
			if ((onUndo != null && !Extensions.InvokeWhileTrue((MulticastDelegate)onUndo, new object[1] { this })) || !IsValid)
			{
				return;
			}
			List<Detour> list = _DetourMap[Method];
			lock (list)
			{
				list.Remove(this);
				_TopUndo();
				if (list.Count > 0)
				{
					list[list.Count - 1]._TopApply();
				}
				_UpdateChainedTrampolines(Method);
			}
		}

		public void Free()
		{
			if (IsValid)
			{
				Undo();
			}
		}

		public void Dispose()
		{
			Undo();
			Free();
		}

		public MethodBase GenerateTrampoline(MethodBase signature = null)
		{
			Func<object, MethodBase, MethodBase> onGenerateTrampoline = OnGenerateTrampoline;
			MethodBase methodBase = ((onGenerateTrampoline != null) ? Extensions.InvokeWhileNull<MethodBase>((MulticastDelegate)onGenerateTrampoline, new object[2] { this, signature }) : null);
			if ((object)methodBase != null)
			{
				return methodBase;
			}
			if ((object)signature == null)
			{
				signature = Target;
			}
			Type returnType = (signature as MethodInfo)?.ReturnType ?? typeof(void);
			ParameterInfo[] parameters = signature.GetParameters();
			Type[] array = new Type[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				array[i] = parameters[i].ParameterType;
			}
			DynamicMethod dynamicMethod = new DynamicMethod($"trampoline_{Method.Name}_{GetHashCode()}", returnType, array, Method.DeclaringType, skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			for (int j = 0; j < 10; j++)
			{
				iLGenerator.Emit(OpCodes.Nop);
			}
			iLGenerator.Emit(OpCodes.Jmp, _ChainedTrampoline);
			return dynamicMethod.Pin();
		}

		public T GenerateTrampoline<T>() where T : Delegate
		{
			if (!typeof(Delegate).IsAssignableFrom(typeof(T)))
			{
				throw new InvalidOperationException($"Type {typeof(T)} not a delegate type.");
			}
			return Extensions.CreateDelegate(GenerateTrampoline(typeof(T).GetMethod("Invoke")), typeof(T)) as T;
		}

		private void _TopUndo()
		{
			if (_TopDetour != null)
			{
				_TopDetour.Undo();
				_TopDetour.Free();
				_TopDetour = null;
			}
		}

		private void _TopApply()
		{
			if (_TopDetour == null)
			{
				_TopDetour = new NativeDetour(Method.GetNativeStart(), Target.GetNativeStart());
			}
		}

		private static void _UpdateChainedTrampolines(MethodBase method)
		{
			List<Detour> list = _DetourMap[method];
			lock (list)
			{
				if (list.Count != 0)
				{
					NativeDetourData detour;
					for (int i = 1; i < list.Count; i++)
					{
						detour = DetourManager.Native.Create(list[i]._ChainedTrampoline.GetNativeStart(), list[i - 1].Target.GetNativeStart());
						DetourManager.Native.MakeWritable(detour);
						DetourManager.Native.Apply(detour);
						DetourManager.Native.MakeExecutable(detour);
						DetourManager.Native.Free(detour);
					}
					detour = DetourManager.Native.Create(list[0]._ChainedTrampoline.GetNativeStart(), _BackupMethods[method].GetNativeStart());
					DetourManager.Native.MakeWritable(detour);
					DetourManager.Native.Apply(detour);
					DetourManager.Native.MakeExecutable(detour);
					DetourManager.Native.Free(detour);
				}
			}
		}
	}
	public class Detour<T> : Detour where T : Delegate
	{
		public Detour(T from, IntPtr to)
			: base(from, to)
		{
		}

		public Detour(T from, T to)
			: base(from, to)
		{
		}
	}
	public static class DetourManager
	{
		public static IDetourRuntimePlatform Runtime;

		public static IDetourNativePlatform Native;

		private static readonly FieldInfo _Native;

		private static readonly MethodInfo _ToNativeDetourData;

		private static readonly MethodInfo _Copy;

		private static readonly MethodInfo _Apply;

		private static readonly ConstructorInfo _ctor_Exception;

		static DetourManager()
		{
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Invalid comparison between Unknown and I4
			_Native = typeof(DetourManager).GetField("Native");
			_ToNativeDetourData = typeof(DetourManager).GetMethod("ToNativeDetourData", BindingFlags.Static | BindingFlags.NonPublic);
			_Copy = typeof(IDetourNativePlatform).GetMethod("Copy");
			_Apply = typeof(IDetourNativePlatform).GetMethod("Apply");
			_ctor_Exception = typeof(Exception).GetConstructor(new Type[1] { typeof(string) });
			if ((object)Type.GetType("Mono.Runtime") != null)
			{
				Runtime = new DetourRuntimeMonoPlatform();
			}
			else
			{
				Runtime = new DetourRuntimeNETPlatform();
			}
			typeof(object).Module.GetPEKind(out var _, out var machine);
			if (machine == ImageFileMachine.ARM)
			{
				Native = new DetourNativeARMPlatform();
			}
			else
			{
				Native = new DetourNativeX86Platform();
			}
			if ((PlatformHelper.Current & 0x25) == 37)
			{
				Native = new DetourNativeWindowsPlatform(Native);
			}
		}

		public unsafe static void Write(this IntPtr to, ref int offs, byte value)
		{
			*(byte*)((long)to + offs) = value;
			offs++;
		}

		public unsafe static void Write(this IntPtr to, ref int offs, ushort value)
		{
			*(ushort*)((long)to + offs) = value;
			offs += 2;
		}

		public unsafe static void Write(this IntPtr to, ref int offs, uint value)
		{
			*(uint*)((long)to + offs) = value;
			offs += 4;
		}

		public unsafe static void Write(this IntPtr to, ref int offs, ulong value)
		{
			*(ulong*)((long)to + offs) = value;
			offs += 8;
		}

		public static IntPtr GetNativeStart(this MethodBase method)
		{
			return Runtime.GetNativeStart(method.Pin());
		}

		public static IntPtr GetNativeStart(this Delegate method)
		{
			return method.Method.GetNativeStart();
		}

		public static IntPtr GetNativeStart(this Expression method)
		{
			return ((MethodCallExpression)method).Method.GetNativeStart();
		}

		public static DynamicMethod CreateILCopy(this MethodBase method)
		{
			return Runtime.CreateCopy(method);
		}

		public static T Pin<T>(this T method) where T : MethodBase
		{
			Runtime.Pin(method);
			return method;
		}

		public static DynamicMethod GenerateNativeProxy(IntPtr target, MethodBase signature)
		{
			Type returnType = (signature as MethodInfo)?.ReturnType ?? typeof(void);
			ParameterInfo[] parameters = signature.GetParameters();
			Type[] array = new Type[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				array[i] = parameters[i].ParameterType;
			}
			DynamicMethod method = new DynamicMethod(string.Format("native_{0}", ((long)target).ToString("X16")), returnType, array, restrictedSkipVisibility: true).StubCriticalDetour();
			NativeDetourData detour = Native.Create(method.GetNativeStart(), target);
			Native.MakeWritable(detour);
			Native.Apply(detour);
			Native.MakeExecutable(detour);
			Native.Free(detour);
			return method.Pin();
		}

		private static NativeDetourData ToNativeDetourData(IntPtr method, IntPtr target, int size, IntPtr extra)
		{
			NativeDetourData result = default(NativeDetourData);
			result.Method = method;
			result.Target = target;
			result.Size = size;
			result.Extra = extra;
			return result;
		}

		public static DynamicMethod StubCriticalDetour(this DynamicMethod dm)
		{
			ILGenerator iLGenerator = dm.GetILGenerator();
			for (int i = 0; i < 10; i++)
			{
				iLGenerator.Emit(OpCodes.Nop);
			}
			iLGenerator.Emit(OpCodes.Ldstr, $"{dm.Name} should've been detoured!");
			iLGenerator.Emit(OpCodes.Newobj, _ctor_Exception);
			iLGenerator.Emit(OpCodes.Throw);
			return dm;
		}

		public static void EmitDetourCopy(this ILGenerator il, IntPtr src, IntPtr dst, int size)
		{
			il.Emit(OpCodes.Ldsfld, _Native);
			il.Emit(OpCodes.Ldc_I8, (long)src);
			il.Emit(OpCodes.Conv_I);
			il.Emit(OpCodes.Ldc_I8, (long)dst);
			il.Emit(OpCodes.Conv_I);
			il.Emit(OpCodes.Ldc_I4, size);
			il.Emit(OpCodes.Callvirt, _Copy);
		}

		public static void EmitDetourApply(this ILGenerator il, NativeDetourData data)
		{
			il.Emit(OpCodes.Ldsfld, _Native);
			il.Emit(OpCodes.Ldc_I8, (long)data.Method);
			il.Emit(OpCodes.Conv_I);
			il.Emit(OpCodes.Ldc_I8, (long)data.Target);
			il.Emit(OpCodes.Conv_I);
			il.Emit(OpCodes.Ldc_I4, data.Size);
			il.Emit(OpCodes.Ldc_I8, (long)data.Extra);
			il.Emit(OpCodes.Conv_I);
			il.Emit(OpCodes.Call, _ToNativeDetourData);
			il.Emit(OpCodes.Callvirt, _Apply);
		}
	}
	public interface IDetourNativePlatform
	{
		NativeDetourData Create(IntPtr from, IntPtr to);

		void Free(NativeDetourData detour);

		void Apply(NativeDetourData detour);

		void Copy(IntPtr src, IntPtr dst, int size);

		void MakeWritable(NativeDetourData detour);

		void MakeExecutable(NativeDetourData detour);

		IntPtr MemAlloc(int size);

		void MemFree(IntPtr ptr);
	}
	public sealed class DetourNativeX86Platform : IDetourNativePlatform
	{
		private enum DetourSize
		{
			Rel32 = 5,
			Abs32 = 6,
			Abs64 = 14
		}

		private static bool Is64Bit(long to)
		{
			return (to & 0xFFFFFFFFu) != to;
		}

		private static DetourSize GetDetourSize(IntPtr from, IntPtr to)
		{
			long to2 = (long)to - ((long)from + 5);
			if (!Is64Bit(to2))
			{
				return DetourSize.Rel32;
			}
			if (!Is64Bit((long)to))
			{
				return DetourSize.Abs32;
			}
			return DetourSize.Abs64;
		}

		public NativeDetourData Create(IntPtr from, IntPtr to)
		{
			NativeDetourData nativeDetourData = default(NativeDetourData);
			nativeDetourData.Method = from;
			nativeDetourData.Target = to;
			NativeDetourData result = nativeDetourData;
			result.Size = (int)GetDetourSize(from, to);
			return result;
		}

		public void Free(NativeDetourData detour)
		{
		}

		public void Apply(NativeDetourData detour)
		{
			int offs = 0;
			switch ((DetourSize)detour.Size)
			{
			case DetourSize.Rel32:
				detour.Method.Write(ref offs, 233);
				detour.Method.Write(ref offs, (uint)((long)detour.Target - ((long)detour.Method + offs + 4)));
				break;
			case DetourSize.Abs32:
				detour.Method.Write(ref offs, 104);
				detour.Method.Write(ref offs, (uint)(int)detour.Target);
				detour.Method.Write(ref offs, 195);
				break;
			case DetourSize.Abs64:
				detour.Method.Write(ref offs, byte.MaxValue);
				detour.Method.Write(ref offs, 37);
				detour.Method.Write(ref offs, 0u);
				detour.Method.Write(ref offs, (ulong)(long)detour.Target);
				break;
			default:
				throw new NotSupportedException($"Unknown X86 detour size {detour.Size}");
			}
		}

		public unsafe void Copy(IntPtr src, IntPtr dst, int size)
		{
			switch ((DetourSize)size)
			{
			case DetourSize.Rel32:
				*(int*)(long)dst = *(int*)(long)src;
				*(sbyte*)((nint)(long)dst + 4) = *(sbyte*)((nint)(long)src + 4);
				break;
			case DetourSize.Abs32:
				*(int*)(long)dst = *(int*)(long)src;
				*(short*)((long)dst + 4) = *(short*)((long)src + 4);
				break;
			case DetourSize.Abs64:
				*(long*)(long)dst = *(long*)(long)src;
				*(int*)((long)dst + 8) = *(int*)((long)src + 8);
				*(short*)((long)dst + 12) = *(short*)((long)src + 12);
				break;
			default:
				throw new NotSupportedException($"Unknown X86 detour size {size}");
			}
		}

		public void MakeWritable(NativeDetourData detour)
		{
		}

		public void MakeExecutable(NativeDetourData detour)
		{
		}

		public IntPtr MemAlloc(int size)
		{
			return Marshal.AllocHGlobal(size);
		}

		public void MemFree(IntPtr ptr)
		{
			Marshal.FreeHGlobal(ptr);
		}
	}
	public sealed class DetourNativeARMPlatform : IDetourNativePlatform
	{
		private enum DetourSize
		{
			Arm32 = 8,
			Arm64 = 12
		}

		public NativeDetourData Create(IntPtr from, IntPtr to)
		{
			NativeDetourData nativeDetourData = default(NativeDetourData);
			nativeDetourData.Method = from;
			nativeDetourData.Target = to;
			NativeDetourData result = nativeDetourData;
			result.Size = ((IntPtr.Size == 4) ? 8 : 12);
			return result;
		}

		public void Free(NativeDetourData detour)
		{
		}

		public void Apply(NativeDetourData detour)
		{
			int offs = 0;
			switch ((DetourSize)detour.Size)
			{
			case DetourSize.Arm32:
				detour.Method.Write(ref offs, 4);
				detour.Method.Write(ref offs, 240);
				detour.Method.Write(ref offs, 31);
				detour.Method.Write(ref offs, 229);
				detour.Method.Write(ref offs, (uint)(int)detour.Target);
				break;
			case DetourSize.Arm64:
				detour.Method.Write(ref offs, 4);
				detour.Method.Write(ref offs, 240);
				detour.Method.Write(ref offs, 31);
				detour.Method.Write(ref offs, 229);
				detour.Method.Write(ref offs, (ulong)(long)detour.Target);
				break;
			default:
				throw new NotSupportedException($"Unknown ARM detour size {detour.Size}");
			}
		}

		public unsafe void Copy(IntPtr src, IntPtr dst, int size)
		{
			switch ((DetourSize)size)
			{
			case DetourSize.Arm32:
				*(int*)(long)dst = *(int*)(long)src;
				*(int*)((long)dst + 4) = *(int*)((nint)(long)src + (nint)4 * (nint)4);
				break;
			case DetourSize.Arm64:
				*(int*)(long)dst = *(int*)(long)src;
				*(long*)((long)dst + 4) = *(long*)((nint)(long)src + (nint)4 * (nint)8);
				break;
			default:
				throw new NotSupportedException($"Unknown ARM detour size {size}");
			}
		}

		public void MakeWritable(NativeDetourData detour)
		{
		}

		public void MakeExecutable(NativeDetourData detour)
		{
		}

		public IntPtr MemAlloc(int size)
		{
			return Marshal.AllocHGlobal(size);
		}

		public void MemFree(IntPtr ptr)
		{
			Marshal.FreeHGlobal(ptr);
		}
	}
	public sealed class DetourNativeWindowsPlatform : IDetourNativePlatform
	{
		[Flags]
		private enum Protection
		{
			PAGE_NOACCESS = 1,
			PAGE_READONLY = 2,
			PAGE_READWRITE = 4,
			PAGE_WRITECOPY = 8,
			PAGE_EXECUTE = 0x10,
			PAGE_EXECUTE_READ = 0x20,
			PAGE_EXECUTE_READWRITE = 0x40,
			PAGE_EXECUTE_WRITECOPY = 0x80,
			PAGE_GUARD = 0x100,
			PAGE_NOCACHE = 0x200,
			PAGE_WRITECOMBINE = 0x400
		}

		private IDetourNativePlatform Inner;

		public DetourNativeWindowsPlatform(IDetourNativePlatform inner)
		{
			Inner = inner;
		}

		[DllImport("kernel32.dll")]
		private static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, Protection flNewProtect, out Protection lpflOldProtect);

		public void MakeWritable(NativeDetourData detour)
		{
			if (!VirtualProtect(detour.Method, (IntPtr)detour.Size, Protection.PAGE_EXECUTE_READWRITE, out var _))
			{
				throw new Win32Exception();
			}
			Inner.MakeWritable(detour);
		}

		public void MakeExecutable(NativeDetourData detour)
		{
			if (!VirtualProtect(detour.Method, (IntPtr)detour.Size, Protection.PAGE_EXECUTE_READWRITE, out var _))
			{
				throw new Win32Exception();
			}
			Inner.MakeExecutable(detour);
		}

		public NativeDetourData Create(IntPtr from, IntPtr to)
		{
			return Inner.Create(from, to);
		}

		public void Free(NativeDetourData detour)
		{
			Inner.Free(detour);
		}

		public void Apply(NativeDetourData detour)
		{
			Inner.Apply(detour);
		}

		public void Copy(IntPtr src, IntPtr dst, int size)
		{
			Inner.Copy(src, dst, size);
		}

		public IntPtr MemAlloc(int size)
		{
			return Inner.MemAlloc(size);
		}

		public void MemFree(IntPtr ptr)
		{
			Inner.MemFree(ptr);
		}
	}
	public interface IDetourRuntimePlatform
	{
		IntPtr GetNativeStart(MethodBase method);

		DynamicMethod CreateCopy(MethodBase method);

		void Pin(MethodBase method);
	}
	public abstract class DetourRuntimeILPlatform : IDetourRuntimePlatform
	{
		protected HashSet<DynamicMethod> PinnedDynamicMethods = new HashSet<DynamicMethod>();

		protected abstract RuntimeMethodHandle GetMethodHandle(MethodBase method);

		public IntPtr GetNativeStart(MethodBase method)
		{
			return GetMethodHandle(method).GetFunctionPointer();
		}

		public void Pin(MethodBase method)
		{
			RuntimeMethodHandle methodHandle = GetMethodHandle(method);
			if (method is DynamicMethod)
			{
				DynamicMethod item = (DynamicMethod)method;
				PinnedDynamicMethods.Add(item);
			}
			RuntimeHelpers.PrepareMethod(methodHandle);
		}

		public DynamicMethod CreateCopy(MethodBase method)
		{
			MethodBody methodBody;
			try
			{
				methodBody = method.GetMethodBody();
			}
			catch (InvalidOperationException)
			{
				methodBody = null;
			}
			if (methodBody == null)
			{
				throw new InvalidOperationException("P/Invoke methods cannot be copied!");
			}
			ParameterInfo[] parameters = method.GetParameters();
			Type[] array;
			if (!method.IsStatic)
			{
				array = new Type[parameters.Length + 1];
				array[0] = method.DeclaringType;
				for (int i = 0; i < parameters.Length; i++)
				{
					array[i + 1] = parameters[i].ParameterType;
				}
			}
			else
			{
				array = new Type[parameters.Length];
				for (int j = 0; j < parameters.Length; j++)
				{
					array[j] = parameters[j].ParameterType;
				}
			}
			DynamicMethod dynamicMethod = new DynamicMethod($"orig_{method.Name}", (method as MethodInfo)?.ReturnType ?? typeof(void), array, method.DeclaringType, skipVisibility: false);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			using (MethodCopier methodCopier = new MethodCopier(method, iLGenerator))
			{
				methodCopier.Copy();
			}
			return dynamicMethod.Pin();
		}
	}
	public sealed class DetourRuntimeNETPlatform : DetourRuntimeILPlatform
	{
		private static readonly FieldInfo f_DynamicMethod_m_method = typeof(DynamicMethod).GetField("m_method", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo m_DynamicMethod_GetMethodDescriptor = typeof(DynamicMethod).GetMethod("GetMethodDescriptor", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FastReflectionDelegate dmd_DynamicMethod_GetMethodDescriptor;

		private static readonly MethodInfo m_RuntimeHelpers__CompileMethod;

		private static readonly FastReflectionDelegate dmd_RuntimeHelpers__CompileMethod;

		private static readonly bool m_RuntimeHelpers__CompileMethod_TakesIntPtr;

		private static readonly bool m_RuntimeHelpers__CompileMethod_TakesIRuntimeMethodInfo;

		private static readonly MethodInfo m_RuntimeMethodHandle_GetMethodInfo;

		private static readonly FastReflectionDelegate dmd_RuntimeMethodHandle_GetMethodInfo;

		protected override RuntimeMethodHandle GetMethodHandle(MethodBase method)
		{
			if (method is DynamicMethod)
			{
				DynamicMethod dynamicMethod = (DynamicMethod)method;
				try
				{
					dynamicMethod.CreateDelegate(typeof(MulticastDelegate));
				}
				catch
				{
				}
				if ((object)f_DynamicMethod_m_method != null)
				{
					return (RuntimeMethodHandle)f_DynamicMethod_m_method.GetValue(method);
				}
				if (dmd_DynamicMethod_GetMethodDescriptor != null)
				{
					return (RuntimeMethodHandle)dmd_DynamicMethod_GetMethodDescriptor.Invoke((object)method, new object[0]);
				}
			}
			return method.MethodHandle;
		}

		static DetourRuntimeNETPlatform()
		{
			MethodInfo dynamicMethod_GetMethodDescriptor = m_DynamicMethod_GetMethodDescriptor;
			dmd_DynamicMethod_GetMethodDescriptor = (((object)dynamicMethod_GetMethodDescriptor != null) ? FastReflectionHelper.CreateFastDelegate((MethodBase)dynamicMethod_GetMethodDescriptor, true) : null);
			m_RuntimeHelpers__CompileMethod = typeof(RuntimeHelpers).GetMethod("_CompileMethod", BindingFlags.Static | BindingFlags.NonPublic);
			MethodInfo runtimeHelpers__CompileMethod = m_RuntimeHelpers__CompileMethod;
			dmd_RuntimeHelpers__CompileMethod = (((object)runtimeHelpers__CompileMethod != null) ? FastReflectionHelper.CreateFastDelegate((MethodBase)runtimeHelpers__CompileMethod, true) : null);
			m_RuntimeHelpers__CompileMethod_TakesIntPtr = (object)m_RuntimeHelpers__CompileMethod != null && m_RuntimeHelpers__CompileMethod.GetParameters()[0].ParameterType.FullName == "System.IntPtr";
			m_RuntimeHelpers__CompileMethod_TakesIRuntimeMethodInfo = (object)m_RuntimeHelpers__CompileMethod != null && m_RuntimeHelpers__CompileMethod.GetParameters()[0].ParameterType.FullName == "System.IRuntimeMethodInfo";
			m_RuntimeMethodHandle_GetMethodInfo = typeof(RuntimeMethodHandle).GetMethod("GetMethodInfo", BindingFlags.Instance | BindingFlags.NonPublic);
			MethodInfo runtimeMethodHandle_GetMethodInfo = m_RuntimeMethodHandle_GetMethodInfo;
			dmd_RuntimeMethodHandle_GetMethodInfo = (((object)runtimeMethodHandle_GetMethodInfo != null) ? FastReflectionHelper.CreateFastDelegate((MethodBase)runtimeMethodHandle_GetMethodInfo, true) : null);
		}
	}
	public sealed class DetourRuntimeMonoPlatform : DetourRuntimeILPlatform
	{
		private static readonly MethodInfo m_DynamicMethod_CreateDynMethod = typeof(DynamicMethod).GetMethod("CreateDynMethod", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FastReflectionDelegate dmd_DynamicMethod_CreateDynMethod;

		private static readonly FieldInfo f_DynamicMethod_mhandle;

		protected override RuntimeMethodHandle GetMethodHandle(MethodBase method)
		{
			if (method is DynamicMethod)
			{
				FastReflectionDelegate obj = dmd_DynamicMethod_CreateDynMethod;
				if (obj != null)
				{
					obj.Invoke((object)method, new object[0]);
				}
				if ((object)f_DynamicMethod_mhandle != null)
				{
					return (RuntimeMethodHandle)f_DynamicMethod_mhandle.GetValue(method);
				}
			}
			return method.MethodHandle;
		}

		static DetourRuntimeMonoPlatform()
		{
			MethodInfo dynamicMethod_CreateDynMethod = m_DynamicMethod_CreateDynMethod;
			dmd_DynamicMethod_CreateDynMethod = (((object)dynamicMethod_CreateDynMethod != null) ? FastReflectionHelper.CreateFastDelegate((MethodBase)dynamicMethod_CreateDynMethod, true) : null);
			f_DynamicMethod_mhandle = typeof(DynamicMethod).GetField("mhandle", BindingFlags.Instance | BindingFlags.NonPublic);
		}
	}
	public class Hook : IDetour, IDisposable
	{
		public readonly MethodBase Method;

		public readonly MethodBase Target;

		private MethodInfo _Hook;

		private Detour _Detour;

		private int? _RefTarget;

		private int? _RefTrampoline;

		public bool IsValid => _Detour.IsValid;

		public Hook(MethodBase from, MethodInfo to, object target)
		{
			Method = from;
			_Hook = to;
			Type type = (from as MethodInfo)?.ReturnType ?? typeof(void);
			if ((object)_Hook.ReturnType != type && !_Hook.ReturnType.IsAssignableFrom(type))
			{
				throw new InvalidOperationException($"Return type of hook for {from} doesn't match, must be {((from as MethodInfo)?.ReturnType ?? typeof(void)).FullName}");
			}
			if (target == null && !to.IsStatic)
			{
				throw new InvalidOperationException($"Hook for method {from} must be static, or you must pass a target instance.");
			}
			ParameterInfo[] parameters = _Hook.GetParameters();
			ParameterInfo[] parameters2 = Method.GetParameters();
			Type[] array;
			if (!Method.IsStatic)
			{
				array = new Type[parameters2.Length + 1];
				array[0] = Method.DeclaringType;
				for (int i = 0; i < parameters2.Length; i++)
				{
					array[i + 1] = parameters2[i].ParameterType;
				}
			}
			else
			{
				array = new Type[parameters2.Length];
				for (int j = 0; j < parameters2.Length; j++)
				{
					array[j] = parameters2[j].ParameterType;
				}
			}
			Type type2 = null;
			if (parameters.Length == array.Length + 1 && typeof(Delegate).IsAssignableFrom(parameters[0].ParameterType))
			{
				type2 = parameters[0].ParameterType;
			}
			else if (parameters.Length != array.Length)
			{
				throw new InvalidOperationException($"Parameter count of hook for {from} doesn't match, must be {array.Length}");
			}
			for (int k = 0; k < array.Length; k++)
			{
				Type type3 = array[k];
				Type parameterType = parameters[k + (((object)type2 != null) ? 1 : 0)].ParameterType;
				if (!type3.IsAssignableFrom(parameterType) && !parameterType.IsAssignableFrom(type3))
				{
					throw new InvalidOperationException($"Parameter #{k} of hook for {from} doesn't match, must be {type3.FullName} or related");
				}
			}
			MethodInfo signature = type2?.GetMethod("Invoke");
			DynamicMethod dynamicMethod = new DynamicMethod($"hook_{Method.Name}_{GetHashCode()}", (Method as MethodInfo)?.ReturnType ?? typeof(void), array, Method.DeclaringType, skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			if (target != null)
			{
				_RefTarget = DynamicMethodHelper.EmitReference<object>(iLGenerator, target);
			}
			if ((object)type2 != null)
			{
				_RefTrampoline = DynamicMethodHelper.EmitReference<Delegate>(iLGenerator, (Delegate)null);
			}
			for (int l = 0; l < array.Length; l++)
			{
				iLGenerator.Emit(OpCodes.Ldarg, l);
			}
			iLGenerator.Emit(OpCodes.Call, _Hook);
			iLGenerator.Emit(OpCodes.Ret);
			Target = dynamicMethod.Pin();
			_Detour = new Detour(Method, Target);
			if ((object)type2 != null)
			{
				DynamicMethodHelper.SetReference(_RefTrampoline.Value, (object)Extensions.CreateDelegate(GenerateTrampoline(signature), type2));
			}
		}

		public Hook(MethodBase from, MethodInfo to)
			: this(from, to, null)
		{
		}

		public Hook(MethodBase method, IntPtr to)
			: this(method, DetourManager.GenerateNativeProxy(to, method), null)
		{
		}

		public Hook(MethodBase method, Delegate to)
			: this(method, to.Method, to.Target)
		{
		}

		public Hook(Delegate from, IntPtr to)
			: this(from.Method, to)
		{
		}

		public Hook(Delegate from, Delegate to)
			: this(from.Method, to)
		{
		}

		public Hook(Expression from, IntPtr to)
			: this(((MethodCallExpression)from).Method, to)
		{
		}

		public Hook(Expression from, Delegate to)
			: this(((MethodCallExpression)from).Method, to)
		{
		}

		public Hook(Expression<Action> from, IntPtr to)
			: this(from.Body, to)
		{
		}

		public Hook(Expression<Action> from, Delegate to)
			: this(from.Body, to)
		{
		}

		public void Apply()
		{
			_Detour.Apply();
		}

		public void Undo()
		{
			_Detour.Undo();
			if (!IsValid)
			{
				_Free();
			}
		}

		public void Free()
		{
			if (IsValid)
			{
				_Detour.Free();
				_Free();
			}
		}

		public void Dispose()
		{
			Undo();
			Free();
		}

		private void _Free()
		{
			if (_RefTarget.HasValue)
			{
				DynamicMethodHelper.FreeReference(_RefTarget.Value);
			}
			if (_RefTrampoline.HasValue)
			{
				DynamicMethodHelper.FreeReference(_RefTrampoline.Value);
			}
		}

		public MethodBase GenerateTrampoline(MethodBase signature = null)
		{
			return _Detour.GenerateTrampoline(signature);
		}

		public T GenerateTrampoline<T>() where T : Delegate
		{
			return _Detour.GenerateTrampoline<T>();
		}
	}
	public class Hook<T> : Hook
	{
		public Hook(Expression<Action> from, T to)
			: base(from.Body, to as Delegate)
		{
		}

		public Hook(Expression<Func<T>> from, IntPtr to)
			: base(from.Body, to)
		{
		}

		public Hook(Expression<Func<T>> from, Delegate to)
			: base(from.Body, to)
		{
		}

		public Hook(T from, IntPtr to)
			: base(from as Delegate, to)
		{
		}

		public Hook(T from, T to)
			: base(from as Delegate, to as Delegate)
		{
		}
	}
	public class Hook<TFrom, TTo> : Hook
	{
		public Hook(Expression<Func<TFrom>> from, TTo to)
			: base(from.Body, to as Delegate)
		{
		}

		public Hook(TFrom from, TTo to)
			: base(from as Delegate, to as Delegate)
		{
		}
	}
	public interface IDetour : IDisposable
	{
		bool IsValid { get; }

		void Apply();

		void Undo();

		void Free();

		MethodBase GenerateTrampoline(MethodBase signature = null);

		T GenerateTrampoline<T>() where T : Delegate;
	}
	public struct NativeDetourData
	{
		public IntPtr Method;

		public IntPtr Target;

		public int Size;

		public IntPtr Extra;
	}
	public class NativeDetour : IDetour, IDisposable
	{
		public static Func<object, MethodBase, IntPtr, IntPtr, bool> OnDetour;

		public static Func<object, bool> OnUndo;

		public static Func<object, MethodBase, MethodBase> OnGenerateTrampoline;

		public readonly NativeDetourData Data;

		public readonly MethodBase Method;

		private DynamicMethod _BackupMethod;

		private IntPtr _BackupNative;

		private bool _IsFree;

		public bool IsValid => !_IsFree;

		public NativeDetour(MethodBase method, IntPtr from, IntPtr to)
		{
			Func<object, MethodBase, IntPtr, IntPtr, bool> onDetour = OnDetour;
			if (onDetour == null || Extensions.InvokeWhileTrue((MulticastDelegate)onDetour, new object[4] { this, method, from, to }))
			{
				Data = DetourManager.Native.Create(from, to);
				Method = method;
				MethodBody methodBody;
				try
				{
					methodBody = Method?.GetMethodBody();
				}
				catch (InvalidOperationException)
				{
					methodBody = null;
				}
				if (methodBody != null)
				{
					_BackupMethod = method.CreateILCopy();
				}
				_BackupNative = DetourManager.Native.MemAlloc(Data.Size);
				DetourManager.Native.Copy(Data.Method, _BackupNative, Data.Size);
				Apply();
			}
		}

		public NativeDetour(IntPtr from, IntPtr to)
			: this(null, from, to)
		{
		}

		public NativeDetour(MethodBase from, IntPtr to)
			: this(from, from.GetNativeStart(), to)
		{
		}

		public NativeDetour(IntPtr from, MethodBase to)
			: this(from, to.GetNativeStart())
		{
		}

		public NativeDetour(MethodBase from, MethodBase to)
			: this(from, to.GetNativeStart())
		{
		}

		public NativeDetour(Delegate from, IntPtr to)
			: this(from.Method, to)
		{
		}

		public NativeDetour(IntPtr from, Delegate to)
			: this(from, to.Method)
		{
		}

		public NativeDetour(Delegate from, Delegate to)
			: this(from.Method, to.Method)
		{
		}

		public void Apply()
		{
			if (_IsFree)
			{
				throw new InvalidOperationException("Free() has been called on this detour.");
			}
			DetourManager.Native.MakeWritable(Data);
			DetourManager.Native.Apply(Data);
			DetourManager.Native.MakeExecutable(Data);
		}

		public void Undo()
		{
			Func<object, bool> onUndo = OnUndo;
			if ((onUndo == null || Extensions.InvokeWhileTrue((MulticastDelegate)onUndo, new object[1] { this })) && !_IsFree)
			{
				DetourManager.Native.Copy(_BackupNative, Data.Method, Data.Size);
			}
		}

		public void Free()
		{
			if (!_IsFree)
			{
				_IsFree = true;
				DetourManager.Native.MemFree(_BackupNative);
				DetourManager.Native.Free(Data);
			}
		}

		public void Dispose()
		{
			Undo();
			Free();
		}

		public MethodBase GenerateTrampoline(MethodBase signature = null)
		{
			Func<object, MethodBase, MethodBase> onGenerateTrampoline = OnGenerateTrampoline;
			MethodBase methodBase = ((onGenerateTrampoline != null) ? Extensions.InvokeWhileNull<MethodBase>((MulticastDelegate)onGenerateTrampoline, new object[2] { this, signature }) : null);
			if ((object)methodBase != null)
			{
				return methodBase;
			}
			if (_IsFree)
			{
				throw new InvalidOperationException("Free() has been called on this detour.");
			}
			if ((object)_BackupMethod != null)
			{
				return _BackupMethod;
			}
			if ((object)signature == null)
			{
				signature = _BackupMethod;
			}
			if ((object)signature == null)
			{
				throw new ArgumentNullException("A signature must be given if the NativeDetour doesn't hold a reference to a managed method.");
			}
			MethodBase methodBase2 = Method;
			if ((object)methodBase2 == null)
			{
				methodBase2 = DetourManager.GenerateNativeProxy(Data.Method, signature);
			}
			Type type = (signature as MethodInfo)?.ReturnType ?? typeof(void);
			ParameterInfo[] parameters = signature.GetParameters();
			Type[] array = new Type[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				array[i] = parameters[i].ParameterType;
			}
			string name = string.Format("trampoline_native_{0}_{1}", Method?.Name.ToString() ?? ((long)Data.Method).ToString("X16"), GetHashCode());
			DynamicMethod dynamicMethod = (((object)Method == null) ? new DynamicMethod(name, type, array, restrictedSkipVisibility: true) : new DynamicMethod(name, type, array, Method.DeclaringType, skipVisibility: true));
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			iLGenerator.EmitDetourCopy(_BackupNative, Data.Method, Data.Size);
			LocalBuilder localBuilder = null;
			if ((object)type != typeof(void))
			{
				localBuilder = iLGenerator.DeclareLocal(type);
			}
			Label label = iLGenerator.BeginExceptionBlock();
			for (int j = 0; j < array.Length; j++)
			{
				iLGenerator.Emit(OpCodes.Ldarg, j);
			}
			if (methodBase2 is MethodInfo)
			{
				iLGenerator.Emit(OpCodes.Call, (MethodInfo)methodBase2);
			}
			else
			{
				if (!(methodBase2 is ConstructorInfo))
				{
					throw new NotSupportedException($"Method type {methodBase2.GetType().FullName} not supported.");
				}
				iLGenerator.Emit(OpCodes.Call, (ConstructorInfo)methodBase2);
			}
			if (localBuilder != null)
			{
				iLGenerator.Emit(OpCodes.Stloc_0);
			}
			iLGenerator.BeginFinallyBlock();
			iLGenerator.EmitDetourApply(Data);
			iLGenerator.EndExceptionBlock();
			if (localBuilder != null)
			{
				iLGenerator.Emit(OpCodes.Ldloc_0);
			}
			iLGenerator.Emit(OpCodes.Ret);
			return dynamicMethod.Pin();
		}

		public T GenerateTrampoline<T>() where T : Delegate
		{
			if (!typeof(Delegate).IsAssignableFrom(typeof(T)))
			{
				throw new InvalidOperationException($"Type {typeof(T)} not a delegate type.");
			}
			return Extensions.CreateDelegate(GenerateTrampoline(typeof(T).GetMethod("Invoke")), typeof(T)) as T;
		}
	}
}
namespace MonoMod.RuntimeDetour.HookGen
{
	public static class HookExtensions
	{
		public delegate void ILManipulatorMini(MethodBody body, ILProcessor il);

		public static bool Match(this Instruction instr, OpCode opcode)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return instr.OpCode == opcode;
		}

		public static bool Match<T>(this Instruction instr, OpCode opcode, T value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			T value2;
			return instr.Match<T>(opcode, out value2) && (value2?.Equals(value) ?? (value == null));
		}

		public static bool Match<T>(this Instruction instr, OpCode opcode, out T value)
		{
			//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)
			if (instr.OpCode == opcode)
			{
				value = (T)instr.Operand;
				return false;
			}
			value = default(T);
			return false;
		}

		public static bool MatchNop(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Nop)
			{
				return true;
			}
			return false;
		}

		public static bool MatchBreak(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Break)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdarg instead.", true)]
		public static bool MatchLdarg0(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldarg_0)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdarg instead.", true)]
		public static bool MatchLdarg1(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldarg_1)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdarg instead.", true)]
		public static bool MatchLdarg2(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldarg_2)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdarg instead.", true)]
		public static bool MatchLdarg3(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldarg_3)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdloc instead.", true)]
		public static bool MatchLdloc0(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldloc_0)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdloc instead.", true)]
		public static bool MatchLdloc1(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldloc_1)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdloc instead.", true)]
		public static bool MatchLdloc2(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldloc_2)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchLdloc instead.", true)]
		public static bool MatchLdloc3(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldloc_3)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchStloc instead.", true)]
		public static bool MatchStloc0(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stloc_0)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchStloc instead.", true)]
		public static bool MatchStloc1(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stloc_1)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchStloc instead.", true)]
		public static bool MatchStloc2(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stloc_2)
			{
				return true;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use MatchStloc instead.", true)]
		public static bool MatchStloc3(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stloc_3)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdnull(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldnull)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdcI4(this Instruction instr, int value)
		{
			int value2;
			return instr.MatchLdcI4(out value2) && value2 == value;
		}

		public static bool MatchLdcI4(this Instruction instr, out int value)
		{
			//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_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_0054: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			if (instr.OpCode == OpCodes.Ldc_I4)
			{
				value = (int)instr.Operand;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_S)
			{
				value = (sbyte)instr.Operand;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_M1)
			{
				value = -1;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_0)
			{
				value = 0;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_1)
			{
				value = 1;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_2)
			{
				value = 2;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_3)
			{
				value = 3;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_4)
			{
				value = 4;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_5)
			{
				value = 5;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_6)
			{
				value = 6;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_7)
			{
				value = 7;
				return true;
			}
			if (instr.OpCode == OpCodes.Ldc_I4_8)
			{
				value = 8;
				return true;
			}
			value = 0;
			return false;
		}

		public static bool MatchLdcI8(this Instruction instr, long value)
		{
			long value2;
			return instr.MatchLdcI8(out value2) && value2 == value;
		}

		public static bool MatchLdcI8(this Instruction instr, out long value)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldc_I8)
			{
				value = (long)instr.Operand;
				return true;
			}
			value = 0L;
			return false;
		}

		public static bool MatchLdcR4(this Instruction instr, float value)
		{
			float value2;
			return instr.MatchLdcR4(out value2) && value2 == value;
		}

		public static bool MatchLdcR4(this Instruction instr, out float value)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldc_R4)
			{
				value = (float)instr.Operand;
				return true;
			}
			value = 0f;
			return false;
		}

		public static bool MatchLdcR8(this Instruction instr, double value)
		{
			double value2;
			return instr.MatchLdcR8(out value2) && value2 == value;
		}

		public static bool MatchLdcR8(this Instruction instr, out double value)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldc_R8)
			{
				value = (double)instr.Operand;
				return true;
			}
			value = 0.0;
			return false;
		}

		public static bool MatchDup(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Dup)
			{
				return true;
			}
			return false;
		}

		public static bool MatchPop(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Pop)
			{
				return true;
			}
			return false;
		}

		public static bool MatchJmp(this Instruction instr, string typeFullName, string name)
		{
			MethodReference value;
			return instr.MatchJmp(out value) && ((MemberReference)(object)value).Is(typeFullName, name);
		}

		public static bool MatchJmp<T>(this Instruction instr, string name)
		{
			MethodReference value;
			return instr.MatchJmp(out value) && ((MemberReference)(object)value).Is(typeof(T), name);
		}

		public static bool MatchJmp(this Instruction instr, Type type, string name)
		{
			MethodReference value;
			return instr.MatchJmp(out value) && ((MemberReference)(object)value).Is(type, name);
		}

		public static bool MatchJmp(this Instruction instr, MethodBase value)
		{
			MethodReference value2;
			return instr.MatchJmp(out value2) && ((MemberReference)(object)value2).Is(value);
		}

		public static bool MatchJmp(this Instruction instr, MethodReference value)
		{
			MethodReference value2;
			return instr.MatchJmp(out value2) && value2 == value;
		}

		public static bool MatchJmp(this Instruction instr, out MethodReference value)
		{
			//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)
			if (instr.OpCode == OpCodes.Jmp)
			{
				object operand = instr.Operand;
				value = (MethodReference)((operand is MethodReference) ? operand : null);
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchCall(this Instruction instr, string typeFullName, string name)
		{
			MethodReference value;
			return instr.MatchCall(out value) && ((MemberReference)(object)value).Is(typeFullName, name);
		}

		public static bool MatchCall<T>(this Instruction instr, string name)
		{
			MethodReference value;
			return instr.MatchCall(out value) && ((MemberReference)(object)value).Is(typeof(T), name);
		}

		public static bool MatchCall(this Instruction instr, Type type, string name)
		{
			MethodReference value;
			return instr.MatchCall(out value) && ((MemberReference)(object)value).Is(type, name);
		}

		public static bool MatchCall(this Instruction instr, MethodBase value)
		{
			MethodReference value2;
			return instr.MatchCall(out value2) && ((MemberReference)(object)value2).Is(value);
		}

		public static bool MatchCall(this Instruction instr, MethodReference value)
		{
			MethodReference value2;
			return instr.MatchCall(out value2) && value2 == value;
		}

		public static bool MatchCall(this Instruction instr, out MethodReference value)
		{
			//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)
			if (instr.OpCode == OpCodes.Call)
			{
				object operand = instr.Operand;
				value = (MethodReference)((operand is MethodReference) ? operand : null);
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchCalli(this Instruction instr, IMethodSignature value)
		{
			IMethodSignature value2;
			return instr.MatchCalli(out value2) && value2 == value;
		}

		public static bool MatchCalli(this Instruction instr, out IMethodSignature value)
		{
			//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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Calli)
			{
				value = (IMethodSignature)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchRet(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ret)
			{
				return true;
			}
			return false;
		}

		public static bool MatchBr(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBr(out value2) && value2 == value;
		}

		public static bool MatchBr(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Br || instr.OpCode == OpCodes.Br_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBrfalse(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBrfalse(out value2) && value2 == value;
		}

		public static bool MatchBrfalse(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Brfalse || instr.OpCode == OpCodes.Brfalse_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBrtrue(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBrtrue(out value2) && value2 == value;
		}

		public static bool MatchBrtrue(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Brtrue || instr.OpCode == OpCodes.Brtrue_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBeq(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBeq(out value2) && value2 == value;
		}

		public static bool MatchBeq(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Beq || instr.OpCode == OpCodes.Beq_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBge(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBge(out value2) && value2 == value;
		}

		public static bool MatchBge(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Bge || instr.OpCode == OpCodes.Bge_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBgt(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBgt(out value2) && value2 == value;
		}

		public static bool MatchBgt(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Bgt || instr.OpCode == OpCodes.Bgt_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBle(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBle(out value2) && value2 == value;
		}

		public static bool MatchBle(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Ble || instr.OpCode == OpCodes.Ble_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBlt(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBlt(out value2) && value2 == value;
		}

		public static bool MatchBlt(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Blt || instr.OpCode == OpCodes.Blt_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBneUn(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBneUn(out value2) && value2 == value;
		}

		public static bool MatchBneUn(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Bne_Un || instr.OpCode == OpCodes.Bne_Un_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBgeUn(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBgeUn(out value2) && value2 == value;
		}

		public static bool MatchBgeUn(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Bge_Un || instr.OpCode == OpCodes.Bge_Un_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBgtUn(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBgtUn(out value2) && value2 == value;
		}

		public static bool MatchBgtUn(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Bgt_Un || instr.OpCode == OpCodes.Bgt_Un_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBleUn(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBleUn(out value2) && value2 == value;
		}

		public static bool MatchBleUn(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Ble_Un || instr.OpCode == OpCodes.Ble_Un_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchBltUn(this Instruction instr, Instruction value)
		{
			Instruction value2;
			return instr.MatchBltUn(out value2) && value2 == value;
		}

		public static bool MatchBltUn(this Instruction instr, out Instruction value)
		{
			//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_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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (instr.OpCode == OpCodes.Blt_Un || instr.OpCode == OpCodes.Blt_Un_S)
			{
				value = (Instruction)instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchSwitch(this Instruction instr, Instruction[] value)
		{
			Instruction[] value2;
			return instr.MatchSwitch(out value2) && value2 == value;
		}

		public static bool MatchSwitch(this Instruction instr, out Instruction[] value)
		{
			//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)
			if (instr.OpCode == OpCodes.Switch)
			{
				value = (Instruction[])instr.Operand;
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchLdindI1(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_I1)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindU1(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_U1)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindI2(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_I2)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindU2(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_U2)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindI4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_I4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindU4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_U4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindI8(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_I8)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindI(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_I)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindR4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_R4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindR8(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_R8)
			{
				return true;
			}
			return false;
		}

		public static bool MatchLdindRef(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Ldind_Ref)
			{
				return true;
			}
			return false;
		}

		public static bool MatchStindRef(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stind_Ref)
			{
				return true;
			}
			return false;
		}

		public static bool MatchStindI1(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stind_I1)
			{
				return true;
			}
			return false;
		}

		public static bool MatchStindI2(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stind_I2)
			{
				return true;
			}
			return false;
		}

		public static bool MatchStindI4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stind_I4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchStindI8(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stind_I8)
			{
				return true;
			}
			return false;
		}

		public static bool MatchStindR4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stind_R4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchStindR8(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Stind_R8)
			{
				return true;
			}
			return false;
		}

		public static bool MatchAdd(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Add)
			{
				return true;
			}
			return false;
		}

		public static bool MatchSub(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Sub)
			{
				return true;
			}
			return false;
		}

		public static bool MatchMul(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Mul)
			{
				return true;
			}
			return false;
		}

		public static bool MatchDiv(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Div)
			{
				return true;
			}
			return false;
		}

		public static bool MatchDivUn(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Div_Un)
			{
				return true;
			}
			return false;
		}

		public static bool MatchRem(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Rem)
			{
				return true;
			}
			return false;
		}

		public static bool MatchRemUn(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Rem_Un)
			{
				return true;
			}
			return false;
		}

		public static bool MatchAnd(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.And)
			{
				return true;
			}
			return false;
		}

		public static bool MatchOr(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Or)
			{
				return true;
			}
			return false;
		}

		public static bool MatchXor(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Xor)
			{
				return true;
			}
			return false;
		}

		public static bool MatchShl(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Shl)
			{
				return true;
			}
			return false;
		}

		public static bool MatchShr(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Shr)
			{
				return true;
			}
			return false;
		}

		public static bool MatchShrUn(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Shr_Un)
			{
				return true;
			}
			return false;
		}

		public static bool MatchNeg(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Neg)
			{
				return true;
			}
			return false;
		}

		public static bool MatchNot(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Not)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvI1(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_I1)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvI2(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_I2)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvI4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_I4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvI8(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_I8)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvR4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_R4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvR8(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_R8)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvU4(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_U4)
			{
				return true;
			}
			return false;
		}

		public static bool MatchConvU8(this Instruction instr)
		{
			//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)
			if (instr.OpCode == OpCodes.Conv_U8)
			{
				return true;
			}
			return false;
		}

		public static bool MatchCallvirt(this Instruction instr, string typeFullName, string name)
		{
			MethodReference value;
			return instr.MatchCallvirt(out value) && ((MemberReference)(object)value).Is(typeFullName, name);
		}

		public static bool MatchCallvirt<T>(this Instruction instr, string name)
		{
			MethodReference value;
			return instr.MatchCallvirt(out value) && ((MemberReference)(object)value).Is(typeof(T), name);
		}

		public static bool MatchCallvirt(this Instruction instr, Type type, string name)
		{
			MethodReference value;
			return instr.MatchCallvirt(out value) && ((MemberReference)(object)value).Is(type, name);
		}

		public static bool MatchCallvirt(this Instruction instr, MethodBase value)
		{
			MethodReference value2;
			return instr.MatchCallvirt(out value2) && ((MemberReference)(object)value2).Is(value);
		}

		public static bool MatchCallvirt(this Instruction instr, MethodReference value)
		{
			MethodReference value2;
			return instr.MatchCallvirt(out value2) && value2 == value;
		}

		public static bool MatchCallvirt(this Instruction instr, out MethodReference value)
		{
			//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)
			if (instr.OpCode == OpCodes.Callvirt)
			{
				object operand = instr.Operand;
				value = (MethodReference)((operand is MethodReference) ? operand : null);
				return true;
			}
			value = null;
			return false;
		}

		public static bool MatchCpobj(this Instruction instr, string fullName)
		{
			TypeReference value;
			return instr.MatchCpobj(out value) && ((MemberReference)(object)value).Is(fullName);
		}

		public static bool MatchCpobj<T>(this Instruction instr)
		{
			TypeReference value;
			return instr.MatchCpobj(out value) && ((MemberReference)(object)value).Is(typeof(T));
		}

		public static bool MatchCpobj(this Instruction instr, Type valu

plugins/Batteritems/MonoMod.Utils.dll

Decompiled 8 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyTitle("MonoMod.Utils")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MonoMod.Utils")]
[assembly: AssemblyCopyright("Copyright ©  2018")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1839cfe2-3db0-45a8-b03d-9aa797479a3a")]
[assembly: AssemblyVersion("18.9.0.42433")]
namespace MonoMod
{
	internal class MonoMod__OldName__ : Attribute
	{
		public MonoMod__OldName__(string findableID)
		{
		}
	}
}
namespace MonoMod.ModInterop
{
	[AttributeUsage(AttributeTargets.Class)]
	public sealed class ModExportNameAttribute : Attribute
	{
		public string Name;

		public ModExportNameAttribute(string name)
		{
			Name = name;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)]
	public sealed class ModImportNameAttribute : Attribute
	{
		public string Name;

		public ModImportNameAttribute(string name)
		{
			Name = name;
		}
	}
	public static class ModInteropManager
	{
		private static HashSet<Type> Registered = new HashSet<Type>();

		private static Dictionary<string, List<MethodInfo>> Methods = new Dictionary<string, List<MethodInfo>>();

		private static List<FieldInfo> Fields = new List<FieldInfo>();

		public static void ModInterop(this Type type)
		{
			if (Registered.Contains(type))
			{
				return;
			}
			Registered.Add(type);
			string name = type.Assembly.GetName().Name;
			object[] customAttributes = type.GetCustomAttributes(typeof(ModExportNameAttribute), inherit: false);
			for (int i = 0; i < customAttributes.Length; i++)
			{
				ModExportNameAttribute modExportNameAttribute = (ModExportNameAttribute)customAttributes[i];
				name = modExportNameAttribute.Name;
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (typeof(Delegate).IsAssignableFrom(fieldInfo.FieldType))
				{
					Fields.Add(fieldInfo);
				}
			}
			MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
			foreach (MethodInfo method in methods)
			{
				method.RegisterModExport();
				method.RegisterModExport(name);
			}
			foreach (FieldInfo field in Fields)
			{
				if (!Methods.TryGetValue(field.GetModImportName(), out var value))
				{
					field.SetValue(null, null);
					continue;
				}
				bool flag = false;
				foreach (MethodInfo item in value)
				{
					try
					{
						field.SetValue(null, Delegate.CreateDelegate(field.FieldType, item));
						flag = true;
					}
					catch
					{
						continue;
					}
					break;
				}
				if (!flag)
				{
					field.SetValue(null, null);
				}
			}
		}

		public static void RegisterModExport(this MethodInfo method, string prefix = null)
		{
			if (!method.IsPublic || !method.IsStatic)
			{
				throw new MemberAccessException("Utility must be public static");
			}
			string text = method.Name;
			if (!string.IsNullOrEmpty(prefix))
			{
				text = prefix + "." + text;
			}
			if (!Methods.TryGetValue(text, out var value))
			{
				value = (Methods[text] = new List<MethodInfo>());
			}
			if (!value.Contains(method))
			{
				value.Add(method);
			}
		}

		private static string GetModImportName(this FieldInfo field)
		{
			object[] customAttributes = field.GetCustomAttributes(typeof(ModImportNameAttribute), inherit: false);
			int num = 0;
			if (num < customAttributes.Length)
			{
				ModImportNameAttribute modImportNameAttribute = (ModImportNameAttribute)customAttributes[num];
				return modImportNameAttribute.Name;
			}
			object[] customAttributes2 = field.DeclaringType.GetCustomAttributes(typeof(ModImportNameAttribute), inherit: false);
			int num2 = 0;
			if (num2 < customAttributes2.Length)
			{
				ModImportNameAttribute modImportNameAttribute2 = (ModImportNameAttribute)customAttributes2[num2];
				return modImportNameAttribute2.Name + "." + field.Name;
			}
			return field.Name;
		}
	}
}
namespace MonoMod.Utils
{
	public sealed class DynamicMethodDefinition : IDisposable
	{
		private class AssemblyCecilDefinitionResolver : IAssemblyResolver, IDisposable
		{
			private readonly Func<AssemblyName, ModuleDefinition> Gen;

			private readonly IAssemblyResolver Fallback;

			private readonly Dictionary<string, AssemblyDefinition> Cache = new Dictionary<string, AssemblyDefinition>();

			public AssemblyCecilDefinitionResolver(Func<AssemblyName, ModuleDefinition> moduleGen, IAssemblyResolver fallback)
			{
				Gen = moduleGen;
				Fallback = fallback;
			}

			public AssemblyDefinition Resolve(AssemblyNameReference name)
			{
				if (Cache.TryGetValue(name.FullName, out var value))
				{
					return value;
				}
				Dictionary<string, AssemblyDefinition> cache = Cache;
				string fullName = name.FullName;
				ModuleDefinition obj = Gen(new AssemblyName(name.FullName));
				return cache[fullName] = ((obj != null) ? obj.Assembly : null) ?? Fallback.Resolve(name);
			}

			public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
			{
				if (Cache.TryGetValue(name.FullName, out var value))
				{
					return value;
				}
				return Cache[name.FullName] = Gen(new AssemblyName(name.FullName)).Assembly ?? Fallback.Resolve(name, parameters);
			}

			public void Dispose()
			{
				foreach (AssemblyDefinition value in Cache.Values)
				{
					value.Dispose();
				}
				Cache.Clear();
			}
		}

		private static readonly Dictionary<short, OpCode> _ReflOpCodes;

		private static readonly Dictionary<short, OpCode> _CecilOpCodes;

		private static readonly Dictionary<Type, MethodInfo> _Emitters;

		public static readonly Dictionary<string, Assembly> AssemblyCache;

		public static readonly Dictionary<MemberReference, MemberInfo> ResolveCache;

		private static readonly Dictionary<Module, ModuleDefinition> _Modules;

		private static readonly Dictionary<Module, int> _ModuleRefs;

		private Func<AssemblyName, ModuleDefinition> _ModuleGen;

		private ModuleDefinition _Module
		{
			get
			{
				if (_Modules.TryGetValue(Method.Module, out var value))
				{
					return value;
				}
				return null;
			}
			set
			{
				_Modules[Method.Module] = value;
			}
		}

		private int _ModuleRef
		{
			get
			{
				if (_ModuleRefs.TryGetValue(Method.Module, out var value))
				{
					return value;
				}
				return 0;
			}
			set
			{
				_ModuleRefs[Method.Module] = value;
			}
		}

		public MethodBase Method { get; private set; }

		public MethodDefinition Definition
		{
			get
			{
				IMetadataTokenProvider obj = _Module.LookupToken(Method.MetadataToken);
				IMetadataTokenProvider obj2 = ((obj is MethodReference) ? obj : null);
				return ((obj2 != null) ? ((MethodReference)obj2).Resolve() : null) ?? throw new InvalidOperationException("Method definition not found");
			}
		}

		static DynamicMethodDefinition()
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			_ReflOpCodes = new Dictionary<short, OpCode>();
			_CecilOpCodes = new Dictionary<short, OpCode>();
			_Emitters = new Dictionary<Type, MethodInfo>();
			AssemblyCache = new Dictionary<string, Assembly>();
			ResolveCache = new Dictionary<MemberReference, MemberInfo>();
			_Modules = new Dictionary<Module, ModuleDefinition>();
			_ModuleRefs = new Dictionary<Module, int>();
			FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				OpCode value = (OpCode)fieldInfo.GetValue(null);
				_ReflOpCodes[value.Value] = value;
			}
			FieldInfo[] fields2 = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public);
			foreach (FieldInfo fieldInfo2 in fields2)
			{
				OpCode value2 = (OpCode)fieldInfo2.GetValue(null);
				_CecilOpCodes[((OpCode)(ref value2)).Value] = value2;
			}
			MethodInfo[] methods = typeof(ILGenerator).GetMethods();
			foreach (MethodInfo methodInfo in methods)
			{
				if (!(methodInfo.Name != "Emit"))
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length == 2 && (object)parameters[0].ParameterType == typeof(OpCode))
					{
						_Emitters[parameters[1].ParameterType] = methodInfo;
					}
				}
			}
		}

		public DynamicMethodDefinition(MethodBase method, Func<AssemblyName, ModuleDefinition> moduleGen = null)
		{
			Method = method ?? throw new ArgumentNullException("method");
			Reload(moduleGen);
		}

		public void Reload(Func<AssemblyName, ModuleDefinition> moduleGen = null, bool force = false)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			ModuleDefinition moduleTmp = null;
			if (moduleGen != null)
			{
				_ModuleGen = moduleGen;
			}
			try
			{
				ModuleDefinition val = (moduleGen ?? _ModuleGen)?.Invoke(Method.Module.Assembly.GetName());
				if (val == null)
				{
					if (_Module != null && !force)
					{
						val = _Module;
					}
					else
					{
						ModuleDefinition module = _Module;
						if (module != null)
						{
							module.Dispose();
						}
						_Module = null;
						ReaderParameters val2 = new ReaderParameters();
						if (_ModuleGen != null)
						{
							val2.AssemblyResolver = (IAssemblyResolver)(object)new AssemblyCecilDefinitionResolver(_ModuleGen, (IAssemblyResolver)(((object)val2.AssemblyResolver) ?? ((object)new DefaultAssemblyResolver())));
						}
						val = (moduleTmp = ModuleDefinition.ReadModule(Method.DeclaringType.Assembly.Location, val2));
					}
				}
				_Module = val;
				_ModuleRef++;
			}
			catch when (_DisposeEarly())
			{
			}
			bool _DisposeEarly()
			{
				if (moduleTmp != null)
				{
					moduleTmp.Dispose();
					_Module = null;
					_ModuleRef = 0;
				}
				return false;
			}
		}

		public DynamicMethod Generate()
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Invalid comparison between Unknown and I4
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Expected I4, but got Unknown
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_0606: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
			MethodDefinition definition = Definition;
			Type[] genericArgsType = (Method.DeclaringType.IsGenericType ? Method.DeclaringType.GetGenericArguments() : null);
			Type[] genericArgsMethod = (Method.IsGenericMethod ? Method.GetGenericArguments() : null);
			ParameterInfo[] parameters = Method.GetParameters();
			Type[] array;
			if (!Method.IsStatic)
			{
				array = new Type[parameters.Length + 1];
				array[0] = Method.DeclaringType;
				for (int i = 0; i < parameters.Length; i++)
				{
					array[i + 1] = parameters[i].ParameterType;
				}
			}
			else
			{
				array = new Type[parameters.Length];
				for (int j = 0; j < parameters.Length; j++)
				{
					array[j] = parameters[j].ParameterType;
				}
			}
			DynamicMethod dynamicMethod = new DynamicMethod("DynamicMethodDefinition:" + ((MemberReference)definition.DeclaringType).FullName + "::" + ((MemberReference)definition).Name, (Method as MethodInfo)?.ReturnType ?? typeof(void), array, Method.DeclaringType, skipVisibility: true);
			ILGenerator il = dynamicMethod.GetILGenerator();
			LocalBuilder[] array2 = ((IEnumerable<VariableDefinition>)definition.Body.Variables).Select((VariableDefinition var) => il.DeclareLocal(ResolveMember((MemberReference)(object)((VariableReference)var).VariableType, genericArgsType, genericArgsMethod) as Type, var.IsPinned)).ToArray();
			Dictionary<int, Label> labelMap = new Dictionary<int, Label>();
			Enumerator<Instruction> enumerator = definition.Body.Instructions.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					Instruction current = enumerator.Current;
					if (current.Operand is Instruction[] array3)
					{
						Instruction[] array4 = array3;
						foreach (Instruction val in array4)
						{
							if (!labelMap.ContainsKey(val.Offset))
							{
								labelMap[val.Offset] = il.DefineLabel();
							}
						}
					}
					else
					{
						object operand = current.Operand;
						Instruction val2;
						if ((val2 = (Instruction)((operand is Instruction) ? operand : null)) != null && !labelMap.ContainsKey(val2.Offset))
						{
							labelMap[val2.Offset] = il.DefineLabel();
						}
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			object[] array5 = new object[2];
			Enumerator<Instruction> enumerator2 = definition.Body.Instructions.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					Instruction current2 = enumerator2.Current;
					if (labelMap.TryGetValue(current2.Offset, out var value))
					{
						il.MarkLabel(value);
					}
					Enumerator<ExceptionHandler> enumerator3 = definition.Body.ExceptionHandlers.GetEnumerator();
					try
					{
						while (enumerator3.MoveNext())
						{
							ExceptionHandler current3 = enumerator3.Current;
							if (current3.TryStart == current2)
							{
								il.BeginExceptionBlock();
							}
							else if (current3.FilterStart == current2)
							{
								il.BeginExceptFilterBlock();
							}
							else if (current3.HandlerStart == current2)
							{
								ExceptionHandlerType handlerType = current3.HandlerType;
								switch ((int)handlerType)
								{
								case 0:
									il.BeginCatchBlock(ResolveMember((MemberReference)(object)current3.CatchType, genericArgsType, genericArgsMethod) as Type);
									break;
								case 2:
									il.BeginFinallyBlock();
									break;
								case 4:
									il.BeginFaultBlock();
									break;
								}
							}
						}
					}
					finally
					{
						((IDisposable)enumerator3).Dispose();
					}
					OpCode opCode = current2.OpCode;
					if ((int)((OpCode)(ref opCode)).OperandType == 5)
					{
						ILGenerator iLGenerator = il;
						Dictionary<short, OpCode> reflOpCodes = _ReflOpCodes;
						opCode = current2.OpCode;
						iLGenerator.Emit(reflOpCodes[((OpCode)(ref opCode)).Value]);
					}
					else
					{
						object obj = current2.Operand;
						Instruction val3;
						VariableDefinition val4;
						ParameterDefinition val5;
						MemberReference mref;
						if (obj is Instruction[] source)
						{
							obj = source.Select((Instruction target) => labelMap[target.Offset]).ToArray();
						}
						else if ((val3 = (Instruction)((obj is Instruction) ? obj : null)) != null)
						{
							obj = labelMap[val3.Offset];
						}
						else if ((val4 = (VariableDefinition)((obj is VariableDefinition) ? obj : null)) != null)
						{
							obj = array2[((VariableReference)val4).Index];
						}
						else if ((val5 = (ParameterDefinition)((obj is ParameterDefinition) ? obj : null)) != null)
						{
							obj = ((ParameterReference)val5).Index;
						}
						else if ((mref = (MemberReference)((obj is MemberReference) ? obj : null)) != null)
						{
							obj = ResolveMember(mref, genericArgsType, genericArgsMethod);
						}
						if (obj == null)
						{
							throw new NullReferenceException($"Unexpected null in {definition} @ {current2}");
						}
						Type operandType = obj.GetType();
						if (!_Emitters.TryGetValue(operandType, out var value2))
						{
							value2 = _Emitters.FirstOrDefault((KeyValuePair<Type, MethodInfo> kvp) => kvp.Key.IsAssignableFrom(operandType)).Value;
						}
						if ((object)value2 == null)
						{
							throw new InvalidOperationException($"Unexpected unemittable {obj.GetType().FullName} in {definition} @ {current2}");
						}
						Dictionary<short, OpCode> reflOpCodes2 = _ReflOpCodes;
						opCode = current2.OpCode;
						array5[0] = reflOpCodes2[((OpCode)(ref opCode)).Value];
						array5[1] = obj;
						value2.Invoke(il, array5);
					}
					Enumerator<ExceptionHandler> enumerator4 = definition.Body.ExceptionHandlers.GetEnumerator();
					try
					{
						while (enumerator4.MoveNext())
						{
							ExceptionHandler current4 = enumerator4.Current;
							if (current4.HandlerEnd == current2.Next)
							{
								il.EndExceptionBlock();
							}
						}
					}
					finally
					{
						((IDisposable)enumerator4).Dispose();
					}
				}
			}
			finally
			{
				((IDisposable)enumerator2).Dispose();
			}
			return dynamicMethod;
		}

		private static MemberInfo ResolveMember(MemberReference mref, Type[] genericTypeArguments, Type[] genericMethodArguments, Module module = null)
		{
			if (ResolveCache.TryGetValue(mref, out var value) && (object)value != null)
			{
				return value;
			}
			MemberReference obj = mref;
			MethodReference method;
			Type type;
			if ((method = (MethodReference)(object)((obj is MethodReference) ? obj : null)) != null && mref.DeclaringType is ArrayType)
			{
				type = ResolveMember((MemberReference)(object)mref.DeclaringType, genericTypeArguments, genericMethodArguments, module) as Type;
				string methodID = method.GetFindableID(null, null, withType: false);
				MethodInfo methodInfo = type.GetMethods().First((MethodInfo m) => m.GetFindableID(null, null, withType: false, proxyMethod: false, simple: false) == methodID);
				if ((object)methodInfo != null)
				{
					return ResolveCache[mref] = methodInfo;
				}
			}
			TypeReference val = (TypeReference)(((object)mref.DeclaringType) ?? ((object)(((mref is TypeReference) ? mref : null) ?? throw new NotSupportedException("MemberReference hasn't got a DeclaringType / isn't a TypeReference in itself"))));
			if ((object)module == null)
			{
				IMetadataScope scope = val.Scope;
				IMetadataScope val2 = scope;
				if (val2 == null)
				{
					goto IL_01c8;
				}
				AssemblyNameReference val3;
				string fullName;
				string text;
				if ((val3 = (AssemblyNameReference)(object)((val2 is AssemblyNameReference) ? val2 : null)) == null)
				{
					ModuleDefinition val4;
					if ((val4 = (ModuleDefinition)(object)((val2 is ModuleDefinition) ? val2 : null)) == null)
					{
						ModuleReference val5;
						if ((val5 = (ModuleReference)(object)((val2 is ModuleReference) ? val2 : null)) == null)
						{
							goto IL_01c8;
						}
						ModuleReference val6 = val5;
						fullName = ((MemberReference)val).Module.Assembly.FullName;
						text = ((ModuleReference)((MemberReference)val).Module).Name;
					}
					else
					{
						ModuleDefinition val7 = val4;
						fullName = val7.Assembly.FullName;
						text = ((ModuleReference)val7).Name;
					}
				}
				else
				{
					AssemblyNameReference val8 = val3;
					fullName = val8.FullName;
					text = null;
				}
				if (!AssemblyCache.TryGetValue(fullName, out var value2))
				{
					value2 = (AssemblyCache[fullName] = Assembly.Load(fullName));
				}
				module = (string.IsNullOrEmpty(text) ? value2.GetModules()[0] : value2.GetModule(text));
			}
			MemberReference obj2 = mref;
			TypeReference val9;
			if ((val9 = (TypeReference)(object)((obj2 is TypeReference) ? obj2 : null)) != null)
			{
				MemberReference obj3 = mref;
				TypeSpecification val10;
				if ((val10 = (TypeSpecification)(object)((obj3 is TypeSpecification) ? obj3 : null)) != null)
				{
					type = ResolveMember((MemberReference)(object)val10.ElementType, genericTypeArguments, genericMethodArguments, module) as Type;
					if (((TypeReference)val10).IsByReference)
					{
						return ResolveCache[mref] = type.MakeByRefType();
					}
					if (((TypeReference)val10).IsPointer)
					{
						return ResolveCache[mref] = type.MakePointerType();
					}
					if (((TypeReference)val10).IsArray)
					{
						return ResolveCache[mref] = type.MakeArrayType(((ArrayType)((val10 is ArrayType) ? val10 : null)).Dimensions.Count);
					}
					if (((TypeReference)val10).IsGenericInstance)
					{
						return ResolveCache[mref] = type.MakeGenericType(((IEnumerable<TypeReference>)((GenericInstanceType)((val10 is GenericInstanceType) ? val10 : null)).GenericArguments).Select((TypeReference arg) => ResolveMember((MemberReference)(object)arg, genericTypeArguments, genericMethodArguments) as Type).ToArray());
					}
				}
				else
				{
					type = module.GetType(mref.FullName.Replace("/", "+"));
				}
				return ResolveCache[mref] = type;
			}
			type = ResolveMember((MemberReference)(object)mref.DeclaringType, genericTypeArguments, genericMethodArguments, module) as Type;
			MemberReference obj4 = mref;
			GenericInstanceMethod val11;
			MemberInfo memberInfo7;
			if ((val11 = (GenericInstanceMethod)(object)((obj4 is GenericInstanceMethod) ? obj4 : null)) != null)
			{
				memberInfo7 = ResolveMember((MemberReference)(object)((MethodSpecification)val11).ElementMethod, genericTypeArguments, genericMethodArguments, module);
				memberInfo7 = (memberInfo7 as MethodInfo).MakeGenericMethod(((IEnumerable<TypeReference>)val11.GenericArguments).Select((TypeReference arg) => ResolveMember((MemberReference)(object)arg, genericTypeArguments, genericMethodArguments) as Type).ToArray());
			}
			else
			{
				memberInfo7 = type.GetMembers((BindingFlags)2147483647).FirstOrDefault((MemberInfo m) => mref.Is(m));
			}
			return ResolveCache[mref] = memberInfo7;
			IL_01c8:
			throw new NotSupportedException($"Unsupported scope type {((object)val.Scope).GetType().FullName}");
		}

		public void Dispose()
		{
			if (_Module != null && --_ModuleRef == 0)
			{
				_Module.Dispose();
				_Module = null;
			}
		}
	}
	public static class DynamicMethodHelper
	{
		private static List<object> References = new List<object>();

		private static readonly MethodInfo _GetMethodFromHandle = typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[1] { typeof(RuntimeMethodHandle) });

		private static readonly MethodInfo _GetReference = typeof(DynamicMethodHelper).GetMethod("GetReference");

		public static object GetReference(int id)
		{
			return References[id];
		}

		public static void SetReference(int id, object obj)
		{
			References[id] = obj;
		}

		private static int AddReference(object obj)
		{
			lock (References)
			{
				References.Add(obj);
				return References.Count - 1;
			}
		}

		public static void FreeReference(int id)
		{
			References[id] = null;
		}

		public static DynamicMethod Stub(this DynamicMethod dm)
		{
			ILGenerator iLGenerator = dm.GetILGenerator();
			for (int i = 0; i < 10; i++)
			{
				iLGenerator.Emit(OpCodes.Nop);
			}
			if ((object)dm.ReturnType != typeof(void))
			{
				iLGenerator.DeclareLocal(dm.ReturnType);
				iLGenerator.Emit(OpCodes.Ldloca_S, (sbyte)0);
				iLGenerator.Emit(OpCodes.Initobj, dm.ReturnType);
				iLGenerator.Emit(OpCodes.Ldloc_0);
			}
			iLGenerator.Emit(OpCodes.Ret);
			return dm;
		}

		public static void EmitMethodOf(this ILGenerator il, MethodBase method)
		{
			if (method is MethodInfo)
			{
				il.Emit(OpCodes.Ldtoken, (MethodInfo)method);
			}
			else
			{
				if (!(method is ConstructorInfo))
				{
					throw new NotSupportedException($"Method type {method.GetType().FullName} not supported.");
				}
				il.Emit(OpCodes.Ldtoken, (ConstructorInfo)method);
			}
			il.Emit(OpCodes.Call, _GetMethodFromHandle);
		}

		public static int EmitReference<T>(this ILGenerator il, T obj)
		{
			Type typeFromHandle = typeof(T);
			int num = AddReference(obj);
			il.Emit(OpCodes.Ldc_I4, num);
			il.Emit(OpCodes.Call, _GetReference);
			if (typeFromHandle.IsValueType)
			{
				il.Emit(OpCodes.Unbox_Any, typeFromHandle);
			}
			return num;
		}
	}
	public static class DynDll
	{
		public static Dictionary<string, string> DllMap = new Dictionary<string, string>();

		public static Dictionary<string, int> DllFlags = new Dictionary<string, int>();

		private const int RTLD_LAZY = 1;

		private const int RTLD_NOW = 2;

		private const int RTLD_LOCAL = 0;

		private const int RTLD_GLOBAL = 256;

		[DllImport("kernel32")]
		private static extern IntPtr GetModuleHandle(string lpModuleName);

		[DllImport("kernel32")]
		private static extern IntPtr LoadLibrary(string lpFileName);

		[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
		private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

		[DllImport("dl", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPTStr)] string filename, int flags);

		[DllImport("dl", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPTStr)] string symbol);

		[DllImport("dl", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr dlerror();

		public static IntPtr OpenLibrary(string name)
		{
			if (name != null && DllMap.TryGetValue(name, out var value))
			{
				name = value;
			}
			IntPtr intPtr;
			if (Environment.OSVersion.Platform == PlatformID.Win32NT)
			{
				intPtr = GetModuleHandle(name);
				if (intPtr == IntPtr.Zero)
				{
					intPtr = LoadLibrary(name);
				}
				return intPtr;
			}
			if (!DllFlags.TryGetValue(name, out var value2))
			{
				value2 = 2;
			}
			IntPtr zero = IntPtr.Zero;
			intPtr = dlopen(name, value2);
			if (intPtr == IntPtr.Zero && File.Exists(name))
			{
				intPtr = dlopen(Path.GetFullPath(name), value2);
			}
			if ((zero = dlerror()) != IntPtr.Zero)
			{
				Console.WriteLine(string.Format("DynDll can't access {0}!", name ?? "entry point"));
				Console.WriteLine("dlerror: " + Marshal.PtrToStringAnsi(zero));
				return IntPtr.Zero;
			}
			return intPtr;
		}

		public static IntPtr GetFunction(this IntPtr lib, string name)
		{
			if (lib == IntPtr.Zero)
			{
				return IntPtr.Zero;
			}
			if (Environment.OSVersion.Platform == PlatformID.Win32NT)
			{
				return GetProcAddress(lib, name);
			}
			IntPtr result = dlsym(lib, name);
			IntPtr ptr;
			if ((ptr = dlerror()) != IntPtr.Zero)
			{
				Console.WriteLine("DynDll can't access " + name + "!");
				Console.WriteLine("dlerror: " + Marshal.PtrToStringAnsi(ptr));
				return IntPtr.Zero;
			}
			return result;
		}

		public static T AsDelegate<T>(this IntPtr s) where T : class
		{
			return Marshal.GetDelegateForFunctionPointer(s, typeof(T)) as T;
		}

		public static void ResolveDynDllImports(this Type type)
		{
			FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				bool flag = true;
				object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(DynDllImportAttribute), inherit: true);
				for (int j = 0; j < customAttributes.Length; j++)
				{
					DynDllImportAttribute dynDllImportAttribute = (DynDllImportAttribute)customAttributes[j];
					flag = false;
					IntPtr intPtr = OpenLibrary(dynDllImportAttribute.DLL);
					if (intPtr == IntPtr.Zero)
					{
						continue;
					}
					string[] entryPoints = dynDllImportAttribute.EntryPoints;
					foreach (string name in entryPoints)
					{
						IntPtr function = intPtr.GetFunction(name);
						if (!(function == IntPtr.Zero))
						{
							fieldInfo.SetValue(null, Marshal.GetDelegateForFunctionPointer(function, fieldInfo.FieldType));
							flag = true;
							break;
						}
					}
					if (flag)
					{
						break;
					}
				}
				if (!flag)
				{
					throw new EntryPointNotFoundException($"No matching entry point found for {fieldInfo.Name} in {fieldInfo.DeclaringType.FullName}");
				}
			}
		}
	}
	[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
	public class DynDllImportAttribute : Attribute
	{
		public string DLL;

		public string[] EntryPoints;

		[Obsolete("Pass the entry points as parameters instead.")]
		public string EntryPoint
		{
			set
			{
				EntryPoints = new string[1] { value };
			}
		}

		public DynDllImportAttribute(string dll, params string[] entryPoints)
		{
			DLL = dll;
			EntryPoints = entryPoints;
		}
	}
	public static class Extensions
	{
		public static string ToHexadecimalString(this byte[] data)
		{
			return BitConverter.ToString(data).Replace("-", string.Empty);
		}

		public static T InvokePassing<T>(this MulticastDelegate md, T val, params object[] args)
		{
			if ((object)md == null)
			{
				return val;
			}
			object[] array = new object[args.Length + 1];
			array[0] = val;
			Array.Copy(args, 0, array, 1, args.Length);
			Delegate[] invocationList = md.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				array[0] = invocationList[i].DynamicInvoke(array);
			}
			return (T)array[0];
		}

		public static bool InvokeWhileTrue(this MulticastDelegate md, params object[] args)
		{
			if ((object)md == null)
			{
				return true;
			}
			Delegate[] invocationList = md.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				if (!(bool)invocationList[i].DynamicInvoke(args))
				{
					return false;
				}
			}
			return true;
		}

		public static bool InvokeWhileFalse(this MulticastDelegate md, params object[] args)
		{
			if ((object)md == null)
			{
				return false;
			}
			Delegate[] invocationList = md.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				if ((bool)invocationList[i].DynamicInvoke(args))
				{
					return true;
				}
			}
			return false;
		}

		public static T InvokeWhileNull<T>(this MulticastDelegate md, params object[] args) where T : class
		{
			if ((object)md == null)
			{
				return null;
			}
			Delegate[] invocationList = md.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				T val = (T)invocationList[i].DynamicInvoke(args);
				if (val != null)
				{
					return val;
				}
			}
			return null;
		}

		public static string SpacedPascalCase(this string input)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < input.Length; i++)
			{
				char c = input[i];
				if (i > 0 && char.IsUpper(c))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		public static string ReadNullTerminatedString(this BinaryReader stream)
		{
			string text = "";
			char c;
			while ((c = stream.ReadChar()) != 0)
			{
				text += c;
			}
			return text;
		}

		public static void WriteNullTerminatedString(this BinaryWriter stream, string text)
		{
			if (text != null)
			{
				foreach (char ch in text)
				{
					stream.Write(ch);
				}
			}
			stream.Write('\0');
		}

		public static T CastDelegate<T>(this Delegate source) where T : class
		{
			return source.CastDelegate(typeof(T)) as T;
		}

		public static Delegate CastDelegate(this Delegate source, Type type)
		{
			if ((object)source == null)
			{
				return null;
			}
			Delegate[] invocationList = source.GetInvocationList();
			if (invocationList.Length == 1)
			{
				return Delegate.CreateDelegate(type, invocationList[0].Target, invocationList[0].Method);
			}
			Delegate[] array = new Delegate[invocationList.Length];
			for (int i = 0; i < invocationList.Length; i++)
			{
				array[i] = invocationList[i].CastDelegate(type);
			}
			return Delegate.Combine(array);
		}

		public static bool TryCastDelegate<T>(this Delegate source, out T result) where T : class
		{
			if (source is T val)
			{
				result = val;
				return true;
			}
			Delegate result2;
			bool result3 = source.TryCastDelegate(typeof(T), out result2);
			result = result2 as T;
			return result3;
		}

		public static bool TryCastDelegate(this Delegate source, Type type, out Delegate result)
		{
			result = null;
			if ((object)source == null)
			{
				return false;
			}
			try
			{
				Delegate[] invocationList = source.GetInvocationList();
				if (invocationList.Length == 1)
				{
					result = Delegate.CreateDelegate(type, invocationList[0].Target, invocationList[0].Method);
					return true;
				}
				Delegate[] array = new Delegate[invocationList.Length];
				for (int i = 0; i < invocationList.Length; i++)
				{
					array[i] = invocationList[i].CastDelegate(type);
				}
				result = Delegate.Combine(array);
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static void LogDetailed(this Exception e, string tag = null)
		{
			if (tag == null)
			{
				Console.WriteLine("--------------------------------");
				Console.WriteLine("Detailed exception log:");
			}
			for (Exception ex = e; ex != null; ex = ex.InnerException)
			{
				Console.WriteLine("--------------------------------");
				Console.WriteLine(ex.GetType().FullName + ": " + ex.Message + "\n" + ex.StackTrace);
				if (ex is ReflectionTypeLoadException)
				{
					ReflectionTypeLoadException ex2 = (ReflectionTypeLoadException)ex;
					for (int i = 0; i < ex2.Types.Length; i++)
					{
						Console.WriteLine("ReflectionTypeLoadException.Types[" + i + "]: " + ex2.Types[i]);
					}
					for (int j = 0; j < ex2.LoaderExceptions.Length; j++)
					{
						ex2.LoaderExceptions[j].LogDetailed(tag + ((tag == null) ? "" : ", ") + "rtle:" + j);
					}
				}
				if (ex is TypeLoadException)
				{
					Console.WriteLine("TypeLoadException.TypeName: " + ((TypeLoadException)ex).TypeName);
				}
				if (ex is BadImageFormatException)
				{
					Console.WriteLine("BadImageFormatException.FileName: " + ((BadImageFormatException)ex).FileName);
				}
			}
		}

		public static Delegate CreateDelegate<T>(this MethodBase method) where T : class
		{
			return method.CreateDelegate(typeof(T), null);
		}

		public static Delegate CreateDelegate<T>(this MethodBase method, object target) where T : class
		{
			return method.CreateDelegate(typeof(T), target);
		}

		public static Delegate CreateDelegate(this MethodBase method, Type delegateType)
		{
			return method.CreateDelegate(delegateType, null);
		}

		public static Delegate CreateDelegate(this MethodBase method, Type delegateType, object target)
		{
			if (!typeof(Delegate).IsAssignableFrom(delegateType))
			{
				throw new ArgumentException("Type argument must be a delegate type!");
			}
			if (method is DynamicMethod)
			{
				return ((DynamicMethod)method).CreateDelegate(delegateType, target);
			}
			RuntimeMethodHandle methodHandle = method.MethodHandle;
			RuntimeHelpers.PrepareMethod(methodHandle);
			IntPtr functionPointer = methodHandle.GetFunctionPointer();
			return (Delegate)Activator.CreateInstance(delegateType, target, functionPointer);
		}
	}
	public class LimitedStream : MemoryStream
	{
		public Stream LimitStream;

		public long LimitOffset;

		public long LimitLength;

		public long? LimitPublicLength;

		public bool LimitStreamShared = false;

		private long _Position = 0L;

		protected byte[] CachedBuffer;

		protected long CachedOffset;

		protected long CachedLength;

		private bool _CacheBuffer = true;

		private readonly byte[] _ToArrayReadBuffer = new byte[2048];

		public bool CacheBuffer
		{
			get
			{
				return _CacheBuffer;
			}
			set
			{
				if (!value)
				{
					CachedBuffer = null;
				}
				_CacheBuffer = value;
			}
		}

		public override bool CanRead => LimitStream.CanRead;

		public override bool CanSeek => LimitStream.CanSeek;

		public override bool CanWrite => LimitStream.CanWrite;

		public override long Length => LimitPublicLength ?? LimitLength;

		public override long Position
		{
			get
			{
				return (LimitStreamShared || !CanSeek) ? _Position : (LimitStream.Position - LimitOffset);
			}
			set
			{
				if (CanSeek)
				{
					LimitStream.Position = value + LimitOffset;
				}
				_Position = value;
			}
		}

		public LimitedStream(Stream stream, long offset, long length)
		{
			LimitStream = stream;
			LimitOffset = offset;
			LimitLength = length;
			if (LimitStream.CanSeek)
			{
				LimitStream.Seek(offset, SeekOrigin.Begin);
			}
		}

		public override void Flush()
		{
			LimitStream.Flush();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			if (LimitOffset + LimitLength <= Position)
			{
				return 0;
			}
			if (LimitOffset + LimitLength <= Position + count)
			{
				count = (int)(LimitLength - (Position - LimitOffset));
			}
			int num = LimitStream.Read(buffer, offset, count);
			_Position += num;
			return num;
		}

		public override int ReadByte()
		{
			if (LimitOffset + LimitLength <= Position)
			{
				return 0;
			}
			if (LimitOffset + LimitLength <= Position + 1)
			{
				return 0;
			}
			int num = LimitStream.ReadByte();
			if (num != -1)
			{
				_Position++;
			}
			return num;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			if (!CanSeek)
			{
				throw new NotSupportedException("This stream does not support seek operations.");
			}
			switch (origin)
			{
			case SeekOrigin.Begin:
				if (LimitOffset + LimitLength <= offset)
				{
					throw new Exception("out of something");
				}
				_Position = offset;
				return LimitStream.Seek(LimitOffset + offset, SeekOrigin.Begin);
			case SeekOrigin.Current:
				if (LimitOffset + LimitLength <= Position + offset)
				{
					throw new Exception("out of something");
				}
				_Position += offset;
				return LimitStream.Seek(offset, SeekOrigin.Current);
			case SeekOrigin.End:
				if (LimitLength - offset < 0)
				{
					throw new Exception("out of something");
				}
				_Position = LimitLength - offset;
				return LimitStream.Seek(LimitOffset + LimitLength - offset, SeekOrigin.Begin);
			default:
				return 0L;
			}
		}

		public override void SetLength(long value)
		{
			if (!CanSeek)
			{
				throw new NotSupportedException("This stream does not support seek operations.");
			}
			if (LimitStreamShared)
			{
				LimitLength = value;
			}
			else
			{
				LimitStream.SetLength(LimitOffset + value + LimitLength);
			}
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			if (LimitOffset + LimitLength <= Position + count)
			{
				throw new Exception("out of something");
			}
			LimitStream.Write(buffer, offset, count);
			_Position += count;
		}

		public override byte[] GetBuffer()
		{
			if (CachedBuffer != null && CachedOffset == LimitOffset && CachedLength == LimitLength)
			{
				return CachedBuffer;
			}
			if (!_CacheBuffer)
			{
				return ToArray();
			}
			CachedOffset = LimitOffset;
			CachedLength = LimitLength;
			return CachedBuffer = ToArray();
		}

		public override byte[] ToArray()
		{
			long position = LimitStream.Position;
			if (LimitStream.CanSeek)
			{
				LimitStream.Seek(LimitOffset, SeekOrigin.Begin);
			}
			long num = ((LimitLength == 0L) ? LimitStream.Length : LimitLength);
			num -= LimitStream.Position - LimitOffset;
			byte[] result;
			int count;
			if (num == 0)
			{
				MemoryStream memoryStream = new MemoryStream();
				while (0 < (count = LimitStream.Read(_ToArrayReadBuffer, 0, _ToArrayReadBuffer.Length)))
				{
					base.Write(_ToArrayReadBuffer, 0, count);
				}
				LimitStream.Seek(position, SeekOrigin.Begin);
				result = base.ToArray();
				memoryStream.Close();
				return result;
			}
			result = new byte[num];
			for (int i = 0; i < num; i += count)
			{
				count = LimitStream.Read(result, i, result.Length - i);
			}
			if (LimitStream.CanSeek)
			{
				LimitStream.Seek(position, SeekOrigin.Begin);
			}
			return result;
		}

		public override void Close()
		{
			base.Close();
			if (!LimitStreamShared)
			{
				LimitStream.Close();
			}
		}

		protected override void Dispose(bool disposing)
		{
			if (!LimitStreamShared)
			{
				LimitStream.Dispose();
				LimitStream.Close();
			}
			base.Dispose(disposing);
		}
	}
	[MonoMod__OldName__("MonoMod.Relinker")]
	public delegate IMetadataTokenProvider Relinker(IMetadataTokenProvider mtp, IGenericParameterProvider context);
	[MonoMod__OldName__("MonoMod.MonoModExt")]
	public static class MonoModExt
	{
		public static IDictionary<string, object> SharedData = new Dictionary<string, object>
		{
			{
				"Platform",
				(PlatformHelper.Current & ~Platform.X64).ToString()
			},
			{
				"PlatformPrefix",
				(PlatformHelper.Current & ~Platform.X64).ToString().ToLowerInvariant() + "_"
			},
			{
				"Arch",
				(PlatformHelper.Current & Platform.X64).ToString()
			},
			{
				"Architecture",
				(PlatformHelper.Current & Platform.X64).ToString()
			},
			{
				"ArchPrefix",
				(PlatformHelper.Current & Platform.X64).ToString().ToLowerInvariant() + "_"
			},
			{
				"ArchitecturePrefix",
				(PlatformHelper.Current & Platform.X64).ToString().ToLowerInvariant() + "_"
			}
		};

		private static readonly Regex TypeGenericParamRegex = new Regex("\\!\\d");

		private static readonly Regex MethodGenericParamRegex = new Regex("\\!\\!\\d");

		private static Type t_ParamArrayAttribute = typeof(ParamArrayAttribute);

		public static readonly FieldInfo f_GenericParameter_position = typeof(GenericParameter).GetField("position", BindingFlags.Instance | BindingFlags.NonPublic);

		public static readonly FieldInfo f_GenericParameter_type = typeof(GenericParameter).GetField("type", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly Type t_Code = typeof(Code);

		private static readonly Type t_OpCodes = typeof(OpCodes);

		private static readonly Dictionary<int, OpCode> _ShortToLongOp = new Dictionary<int, OpCode>();

		private static readonly Dictionary<int, OpCode> _LongToShortOp = new Dictionary<int, OpCode>();

		public static ModuleDefinition ReadModule(string path, ReaderParameters rp)
		{
			while (true)
			{
				try
				{
					return ModuleDefinition.ReadModule(path, rp);
				}
				catch
				{
					if (rp.ReadSymbols)
					{
						rp.ReadSymbols = false;
						continue;
					}
					throw;
				}
			}
		}

		public static ModuleDefinition ReadModule(Stream input, ReaderParameters rp)
		{
			while (true)
			{
				try
				{
					return ModuleDefinition.ReadModule(input, rp);
				}
				catch
				{
					if (rp.ReadSymbols)
					{
						rp.ReadSymbols = false;
						continue;
					}
					throw;
				}
			}
		}

		public static MethodBody Clone(this MethodBody o, MethodDefinition m)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (o == null)
			{
				return null;
			}
			MethodBody val = new MethodBody(m);
			val.MaxStackSize = o.MaxStackSize;
			val.InitLocals = o.InitLocals;
			val.LocalVarToken = o.LocalVarToken;
			val.Instructions.AddRange<Instruction>(o.Instructions);
			val.ExceptionHandlers.AddRange<ExceptionHandler>(o.ExceptionHandlers);
			val.Variables.AddRange<VariableDefinition>(o.Variables);
			m.CustomDebugInformations.AddRange<CustomDebugInformation>(o.Method.CustomDebugInformations);
			m.DebugInformation.SequencePoints.AddRange<SequencePoint>(o.Method.DebugInformation.SequencePoints);
			return val;
		}

		public static GenericParameter Update(this GenericParameter param, GenericParameter other)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return param.Update(other.Position, other.Type);
		}

		public static GenericParameter Update(this GenericParameter param, int position, GenericParameterType type)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			f_GenericParameter_position.SetValue(param, position);
			f_GenericParameter_type.SetValue(param, type);
			return param;
		}

		public static void AddAttribute(this ICustomAttributeProvider cap, MethodReference constructor)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			MonoModExt.AddAttribute(cap, new CustomAttribute(constructor));
		}

		public static void AddAttribute(this ICustomAttributeProvider cap, CustomAttribute attr)
		{
			cap.CustomAttributes.Add(attr);
		}

		public static bool HasMMAttribute(this ICustomAttributeProvider cap, string attribute)
		{
			return cap.HasCustomAttribute("MonoMod.MonoMod" + attribute);
		}

		public static CustomAttribute GetMMAttribute(this ICustomAttributeProvider cap, string attribute)
		{
			return cap.GetCustomAttribute("MonoMod.MonoMod" + attribute);
		}

		public static CustomAttribute GetNextMMAttribute(this ICustomAttributeProvider cap, string attribute)
		{
			return cap.GetNextCustomAttribute("MonoMod.MonoMod" + attribute);
		}

		public static CustomAttribute GetCustomAttribute(this ICustomAttributeProvider cap, string attribute)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (cap == null || !cap.HasCustomAttributes)
			{
				return null;
			}
			Enumerator<CustomAttribute> enumerator = cap.CustomAttributes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttribute current = enumerator.Current;
					if (((MemberReference)current.AttributeType).FullName == attribute)
					{
						return current;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return null;
		}

		public static CustomAttribute GetNextCustomAttribute(this ICustomAttributeProvider cap, string attribute)
		{
			if (cap == null || !cap.HasCustomAttributes)
			{
				return null;
			}
			bool flag = false;
			for (int i = 0; i < cap.CustomAttributes.Count; i++)
			{
				CustomAttribute val = cap.CustomAttributes[i];
				if (!(((MemberReference)val.AttributeType).FullName != attribute))
				{
					if (flag)
					{
						return val;
					}
					cap.CustomAttributes.RemoveAt(i);
					i--;
					flag = true;
				}
			}
			return null;
		}

		public static bool HasCustomAttribute(this ICustomAttributeProvider cap, string attribute)
		{
			return cap.GetCustomAttribute(attribute) != null;
		}

		public static string GetOriginalName(this MethodDefinition method)
		{
			//IL_0008: 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_0038: 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)
			Enumerator<CustomAttribute> enumerator = method.CustomAttributes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttribute current = enumerator.Current;
					if (((MemberReference)current.AttributeType).FullName == "MonoMod.MonoModOriginalName")
					{
						CustomAttributeArgument val = current.ConstructorArguments[0];
						return (string)((CustomAttributeArgument)(ref val)).Value;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			if (((MemberReference)method).Name == ".ctor" || ((MemberReference)method).Name == ".cctor")
			{
				return "orig_ctor_" + ((MemberReference)(object)method.DeclaringType).GetPatchName();
			}
			return "orig_" + ((MemberReference)method).Name;
		}

		public static bool MatchingConditionals(this ICustomAttributeProvider cap, ModuleDefinition module)
		{
			return cap.MatchingConditionals((AssemblyNameReference)(object)module.Assembly.Name);
		}

		public static bool MatchingConditionals(this ICustomAttributeProvider cap, AssemblyNameReference asmName = null)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			if (cap == null)
			{
				return true;
			}
			if (!cap.HasCustomAttributes)
			{
				return true;
			}
			Platform current = PlatformHelper.Current;
			bool flag = true;
			Enumerator<CustomAttribute> enumerator = cap.CustomAttributes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttribute current2 = enumerator.Current;
					CustomAttributeArgument val;
					if (((MemberReference)current2.AttributeType).FullName == "MonoMod.MonoModOnPlatform")
					{
						val = current2.ConstructorArguments[0];
						CustomAttributeArgument[] array = (CustomAttributeArgument[])((CustomAttributeArgument)(ref val)).Value;
						for (int i = 0; i < array.Length; i++)
						{
							if (PlatformHelper.Is((Platform)((CustomAttributeArgument)(ref array[i])).Value))
							{
							}
						}
						flag &= array.Length == 0;
					}
					else if (((MemberReference)current2.AttributeType).FullName == "MonoMod.MonoModIfFlag")
					{
						val = current2.ConstructorArguments[0];
						string key = (string)((CustomAttributeArgument)(ref val)).Value;
						bool flag2;
						if (!SharedData.TryGetValue(key, out var value) || !(value is bool))
						{
							if (current2.ConstructorArguments.Count == 2)
							{
								val = current2.ConstructorArguments[1];
								flag2 = (bool)((CustomAttributeArgument)(ref val)).Value;
							}
							else
							{
								flag2 = true;
							}
						}
						else
						{
							flag2 = (bool)value;
						}
						flag = flag && flag2;
					}
					else if (((MemberReference)current2.AttributeType).FullName == "MonoMod.MonoModTargetModule")
					{
						val = current2.ConstructorArguments[0];
						string text = ((string)((CustomAttributeArgument)(ref val)).Value).Inject(SharedData);
						flag &= asmName.Name == text || asmName.FullName == text;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return flag;
		}

		public static string GetFindableID(this MethodReference method, string name = null, string type = null, bool withType = true, bool simple = false)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			while (method.IsGenericInstance)
			{
				method = ((MethodSpecification)(GenericInstanceMethod)method).ElementMethod;
			}
			StringBuilder stringBuilder = new StringBuilder();
			if (simple)
			{
				if (withType)
				{
					stringBuilder.Append(type ?? ((MemberReference)(object)((MemberReference)method).DeclaringType).GetPatchFullName()).Append("::");
				}
				stringBuilder.Append(name ?? ((MemberReference)method).Name);
				return stringBuilder.ToString();
			}
			stringBuilder.Append(((MemberReference)(object)method.ReturnType).GetPatchFullName()).Append(" ");
			if (withType)
			{
				stringBuilder.Append(type ?? ((MemberReference)(object)((MemberReference)method).DeclaringType).GetPatchFullName()).Append("::");
			}
			stringBuilder.Append(name ?? ((MemberReference)method).Name);
			if (method.GenericParameters.Count != 0)
			{
				stringBuilder.Append("<");
				Collection<GenericParameter> genericParameters = method.GenericParameters;
				for (int i = 0; i < genericParameters.Count; i++)
				{
					if (i > 0)
					{
						stringBuilder.Append(",");
					}
					stringBuilder.Append(((MemberReference)genericParameters[i]).Name);
				}
				stringBuilder.Append(">");
			}
			stringBuilder.Append("(");
			if (method.HasParameters)
			{
				Collection<ParameterDefinition> parameters = method.Parameters;
				for (int j = 0; j < parameters.Count; j++)
				{
					ParameterDefinition val = parameters[j];
					if (j > 0)
					{
						stringBuilder.Append(",");
					}
					if (((ParameterReference)val).ParameterType.IsSentinel)
					{
						stringBuilder.Append("...,");
					}
					stringBuilder.Append(((MemberReference)(object)((ParameterReference)val).ParameterType).GetPatchFullName());
				}
			}
			stringBuilder.Append(")");
			return stringBuilder.ToString();
		}

		public static string GetFindableID(this MethodBase method, string name = null, string type = null, bool withType = true, bool proxyMethod = false, bool simple = false)
		{
			while (method is MethodInfo && method.IsGenericMethod && !method.IsGenericMethodDefinition)
			{
				method = ((MethodInfo)method).GetGenericMethodDefinition();
			}
			StringBuilder stringBuilder = new StringBuilder();
			if (simple)
			{
				if (withType)
				{
					stringBuilder.Append(type ?? method.DeclaringType.FullName).Append("::");
				}
				stringBuilder.Append(name ?? method.Name);
				return stringBuilder.ToString();
			}
			stringBuilder.Append((method as MethodInfo)?.ReturnType?.FullName ?? "System.Void").Append(" ");
			if (withType)
			{
				stringBuilder.Append(type ?? method.DeclaringType.FullName.Replace("+", "/")).Append("::");
			}
			stringBuilder.Append(name ?? method.Name);
			if (method.ContainsGenericParameters)
			{
				stringBuilder.Append("<");
				Type[] genericArguments = method.GetGenericArguments();
				for (int i = 0; i < genericArguments.Length; i++)
				{
					if (i > 0)
					{
						stringBuilder.Append(",");
					}
					stringBuilder.Append(genericArguments[i].Name);
				}
				stringBuilder.Append(">");
			}
			stringBuilder.Append("(");
			ParameterInfo[] parameters = method.GetParameters();
			for (int j = (proxyMethod ? 1 : 0); j < parameters.Length; j++)
			{
				ParameterInfo parameterInfo = parameters[j];
				if (j > (proxyMethod ? 1 : 0))
				{
					stringBuilder.Append(",");
				}
				if (Attribute.IsDefined(parameterInfo, t_ParamArrayAttribute))
				{
					stringBuilder.Append("...,");
				}
				stringBuilder.Append(parameterInfo.ParameterType.FullName);
			}
			stringBuilder.Append(")");
			return stringBuilder.ToString();
		}

		public static bool Is(this MemberInfo minfo, MemberReference mref)
		{
			return mref.Is(minfo);
		}

		public static bool Is(this MemberReference mref, MemberInfo minfo)
		{
			if (mref == null)
			{
				return false;
			}
			GenericParameter val;
			if ((val = (GenericParameter)(object)((mref is GenericParameter) ? mref : null)) != null)
			{
				if (!(minfo is Type type) || !type.IsGenericParameter)
				{
					return false;
				}
				return val.Position == type.GenericParameterPosition;
			}
			if (!(((MemberReference)(object)mref.DeclaringType)?.Is(minfo.DeclaringType) ?? ((object)minfo.DeclaringType == null)))
			{
				return false;
			}
			if (mref.Name != minfo.Name)
			{
				return false;
			}
			if (mref is TypeReference)
			{
				if (!(minfo is Type type2))
				{
					return false;
				}
				GenericInstanceType val2;
				if ((val2 = (GenericInstanceType)(object)((mref is GenericInstanceType) ? mref : null)) != null)
				{
					if (!type2.IsGenericType)
					{
						return false;
					}
					Collection<TypeReference> genericArguments = val2.GenericArguments;
					Type[] genericArguments2 = type2.GetGenericArguments();
					if (genericArguments.Count != genericArguments2.Length)
					{
						return false;
					}
					for (int i = 0; i < genericArguments.Count; i++)
					{
						if (!((MemberReference)(object)genericArguments[i]).Is(genericArguments2[i]))
						{
							return false;
						}
					}
					return ((MemberReference)(object)((TypeSpecification)val2).ElementType).Is(type2.GetGenericTypeDefinition());
				}
				if (mref.DeclaringType != null)
				{
					return mref.Name == type2.Name;
				}
				return mref.FullName == type2.FullName;
			}
			MethodReference val3;
			if ((val3 = (MethodReference)(object)((mref is MethodReference) ? mref : null)) != null)
			{
				if (!(minfo is MethodBase methodBase))
				{
					return false;
				}
				Collection<ParameterDefinition> parameters = val3.Parameters;
				ParameterInfo[] parameters2 = methodBase.GetParameters();
				if (parameters.Count != parameters2.Length)
				{
					return false;
				}
				for (int j = 0; j < parameters.Count; j++)
				{
					TypeReference val4 = ((ParameterReference)parameters[j]).ParameterType;
					GenericParameter val5;
					if ((val5 = (GenericParameter)(object)((val4 is GenericParameter) ? val4 : null)) != null)
					{
						GenericInstanceMethod val6;
						GenericInstanceType val7;
						if (val5.Owner is MethodReference && (val6 = (GenericInstanceMethod)(object)((val3 is GenericInstanceMethod) ? val3 : null)) != null)
						{
							val4 = val6.GenericArguments[val5.Position];
						}
						else if (val5.Owner is TypeReference && (val7 = (GenericInstanceType)/*isinst with value type is only supported in some contexts*/) != null)
						{
							val4 = val7.GenericArguments[val5.Position];
						}
					}
					if (!((MemberReference)(object)val4).Is(parameters2[j].ParameterType))
					{
						return false;
					}
				}
				return true;
			}
			return true;
		}

		public static void UpdateOffsets(this MethodBody body, int instri, int delta)
		{
			int num = body.Instructions.Count - 1;
			while (instri <= num)
			{
				Instruction obj = body.Instructions[num];
				obj.Offset += delta;
				num--;
			}
		}

		public static int GetInt(this Instruction instr)
		{
			//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_0008: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00aa: 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_00bf: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			OpCode opCode = instr.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 (sbyte)instr.Operand;
			}
			return (int)instr.Operand;
		}

		public static int? GetIntOrNull(this Instruction instr)
		{
			//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_0008: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			OpCode opCode = instr.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 (sbyte)instr.Operand;
			}
			if (opCode == OpCodes.Ldc_I4)
			{
				return (int)instr.Operand;
			}
			return null;
		}

		public static ParameterDefinition GetParam(this Instruction instr, MethodDefinition method)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			OpCode opCode = instr.OpCode;
			int num = (((MethodReference)method).HasThis ? (-1) : 0);
			if (opCode == OpCodes.Ldarg_0)
			{
				return ((MethodReference)method).HasThis ? null : ((MethodReference)method).Parameters[num];
			}
			if (opCode == OpCodes.Ldarg_1)
			{
				return ((MethodReference)method).Parameters[num + 1];
			}
			if (opCode == OpCodes.Ldarg_2)
			{
				return ((MethodReference)method).Parameters[num + 2];
			}
			if (opCode == OpCodes.Ldarg_3)
			{
				return ((MethodReference)method).Parameters[num + 3];
			}
			if (opCode == OpCodes.Ldarg_S)
			{
				return (ParameterDefinition)instr.Operand;
			}
			if (opCode == OpCodes.Ldarg)
			{
				return (ParameterDefinition)instr.Operand;
			}
			return null;
		}

		public static VariableDefinition GetLocal(this Instruction instr, MethodDefinition method)
		{
			//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_0008: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			OpCode opCode = instr.OpCode;
			if (opCode == OpCodes.Ldloc_0)
			{
				return method.Body.Variables[0];
			}
			if (opCode == OpCodes.Ldloc_1)
			{
				return method.Body.Variables[1];
			}
			if (opCode == OpCodes.Ldloc_2)
			{
				return method.Body.Variables[2];
			}
			if (opCode == OpCodes.Ldloc_3)
			{
				return method.Body.Variables[3];
			}
			if (opCode == OpCodes.Ldloca_S)
			{
				return (VariableDefinition)instr.Operand;
			}
			if (opCode == OpCodes.Ldloc)
			{
				return (VariableDefinition)instr.Operand;
			}
			return null;
		}

		public static void AddRange<T>(this Collection<T> list, Collection<T> other)
		{
			for (int i = 0; i < other.Count; i++)
			{
				list.Add(other[i]);
			}
		}

		public static void AddRange(this IDictionary dict, IDictionary other)
		{
			foreach (DictionaryEntry item in other)
			{
				dict.Add(item.Key, item.Value);
			}
		}

		public static void AddRange<K, V>(this IDictionary<K, V> dict, IDictionary<K, V> other)
		{
			foreach (KeyValuePair<K, V> item in other)
			{
				dict.Add(item.Key, item.Value);
			}
		}

		public static void AddRange<K, V>(this Dictionary<K, V> dict, Dictionary<K, V> other)
		{
			foreach (KeyValuePair<K, V> item in other)
			{
				dict.Add(item.Key, item.Value);
			}
		}

		public static void PushRange<T>(this Stack<T> stack, IEnumerable<T> other)
		{
			foreach (T item in other)
			{
				stack.Push(item);
			}
		}

		public static void PopRange<T>(this Stack<T> stack, int n)
		{
			for (int i = 0; i < n; i++)
			{
				stack.Pop();
			}
		}

		public static void EnqueueRange<T>(this Queue<T> queue, IEnumerable<T> other)
		{
			foreach (T item in other)
			{
				queue.Enqueue(item);
			}
		}

		public static void DequeueRange<T>(this Queue<T> queue, int n)
		{
			for (int i = 0; i < n; i++)
			{
				queue.Dequeue();
			}
		}

		public static T[] Clone<T>(this T[] array, int length)
		{
			T[] array2 = new T[length];
			Array.Copy(array, array2, length);
			return array2;
		}

		public static GenericParameter GetGenericParameter(this IGenericParameterProvider provider, GenericParameter orig)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_002d: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			if (provider is GenericParameter && ((MemberReference)(GenericParameter)provider).Name == ((MemberReference)orig).Name)
			{
				return (GenericParameter)provider;
			}
			Enumerator<GenericParameter> enumerator = provider.GenericParameters.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					GenericParameter current = enumerator.Current;
					if (((MemberReference)current).Name == ((MemberReference)orig).Name)
					{
						return current;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			int position = orig.Position;
			if (provider is MethodReference && orig.DeclaringMethod != null)
			{
				if (position < provider.GenericParameters.Count)
				{
					return provider.GenericParameters[position];
				}
				return Update(new GenericParameter(((MemberReference)orig).Name, provider), position, (GenericParameterType)1);
			}
			if (provider is TypeReference && ((MemberReference)orig).DeclaringType != null)
			{
				if (position < provider.GenericParameters.Count)
				{
					return provider.GenericParameters[position];
				}
				return Update(new GenericParameter(((MemberReference)orig).Name, provider), position, (GenericParameterType)0);
			}
			IGenericParameterProvider obj = ((provider is TypeSpecification) ? provider : null);
			object obj2 = ((obj != null) ? ((IGenericParameterProvider)(object)((TypeSpecification)obj).ElementType).GetGenericParameter(orig) : null);
			if (obj2 == null)
			{
				IGenericParameterProvider obj3 = ((provider is MemberReference) ? provider : null);
				obj2 = ((obj3 == null) ? null : ((IGenericParameterProvider)(object)((MemberReference)obj3).DeclaringType)?.GetGenericParameter(orig));
			}
			return (GenericParameter)obj2;
		}

		public static IMetadataTokenProvider Relink(this IMetadataTokenProvider mtp, Relinker relinker, IGenericParameterProvider context)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			if (mtp is TypeReference)
			{
				return (IMetadataTokenProvider)(object)MonoModExt.Relink((TypeReference)mtp, relinker, context);
			}
			if (mtp is MethodReference)
			{
				return (IMetadataTokenProvider)(object)MonoModExt.Relink((MethodReference)mtp, relinker, context);
			}
			if (mtp is FieldReference)
			{
				return MonoModExt.Relink((FieldReference)mtp, relinker, context);
			}
			if (mtp is ParameterDefinition)
			{
				return (IMetadataTokenProvider)(object)MonoModExt.Relink((ParameterDefinition)mtp, relinker, context);
			}
			throw new InvalidOperationException($"MonoMod can't handle metadata token providers of the type {((object)mtp).GetType()}");
		}

		public static TypeReference Relink(this TypeReference type, Relinker relinker, IGenericParameterProvider context)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Expected O, but got Unknown
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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
			//IL_00aa: 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_00bf: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			if (type == null)
			{
				return null;
			}
			if (type is TypeSpecification)
			{
				TypeSpecification val = (TypeSpecification)type;
				TypeReference val2 = val.ElementType.Relink(relinker, context);
				if (type.IsSentinel)
				{
					return (TypeReference)new SentinelType(val2);
				}
				if (type.IsByReference)
				{
					return (TypeReference)new ByReferenceType(val2);
				}
				if (type.IsPointer)
				{
					return (TypeReference)new PointerType(val2);
				}
				if (type.IsPinned)
				{
					return (TypeReference)new PinnedType(val2);
				}
				if (type.IsArray)
				{
					return (TypeReference)new ArrayType(val2, ((ArrayType)type).Dimensions.Count);
				}
				if (type.IsRequiredModifier)
				{
					return (TypeReference)new RequiredModifierType(((RequiredModifierType)type).ModifierType.Relink(relinker, context), val2);
				}
				if (type.IsOptionalModifier)
				{
					return (TypeReference)new OptionalModifierType(((OptionalModifierType)type).ModifierType.Relink(relinker, context), val2);
				}
				if (type.IsGenericInstance)
				{
					GenericInstanceType val3 = new GenericInstanceType(val2);
					Enumerator<TypeReference> enumerator = ((GenericInstanceType)type).GenericArguments.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							TypeReference current = enumerator.Current;
							val3.GenericArguments.Add(current?.Relink(relinker, context));
						}
					}
					finally
					{
						((IDisposable)enumerator).Dispose();
					}
					return (TypeReference)(object)val3;
				}
				if (type.IsFunctionPointer)
				{
					FunctionPointerType val4 = (FunctionPointerType)type;
					val4.ReturnType = val4.ReturnType.Relink(relinker, context);
					for (int i = 0; i < val4.Parameters.Count; i++)
					{
						((ParameterReference)val4.Parameters[i]).ParameterType = ((ParameterReference)val4.Parameters[i]).ParameterType.Relink(relinker, context);
					}
					return (TypeReference)(object)val4;
				}
				throw new NotSupportedException($"MonoMod can't handle TypeSpecification: {((MemberReference)type).FullName} ({((object)type).GetType()})");
			}
			if (type.IsGenericParameter)
			{
				GenericParameter genericParameter = context.GetGenericParameter((GenericParameter)type);
				if (genericParameter == null)
				{
					throw new RelinkTargetNotFoundException(string.Format("{0} {1} (context: {2})", "MonoMod relinker failed finding", ((MemberReference)type).FullName, context), (IMetadataTokenProvider)(object)type, (IMetadataTokenProvider)(object)context);
				}
				for (int j = 0; j < genericParameter.Constraints.Count; j++)
				{
					if (!genericParameter.Constraints[j].IsGenericInstance)
					{
						genericParameter.Constraints[j] = genericParameter.Constraints[j].Relink(relinker, context);
					}
				}
				return (TypeReference)(object)genericParameter;
			}
			return (TypeReference)relinker((IMetadataTokenProvider)(object)type, context);
		}

		public static MethodReference Relink(this MethodReference method, Relinker relinker, IGenericParameterProvider context)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: 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_007d: Expected O, but got Unknown
			//IL_01a9: 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_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Expected O, but got Unknown
			if (method.IsGenericInstance)
			{
				GenericInstanceMethod val = (GenericInstanceMethod)method;
				GenericInstanceMethod val2 = new GenericInstanceMethod(((MethodSpecification)val).ElementMethod.Relink(relinker, context));
				Enumerator<TypeReference> enumerator = val.GenericArguments.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						TypeReference current = enumerator.Current;
						val2.GenericArguments.Add(current.Relink(relinker, context));
					}
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
				return (MethodReference)relinker((IMetadataTokenProvider)(object)val2, context);
			}
			MethodReference val3 = new MethodReference(((MemberReference)method).Name, method.ReturnType, ((MemberReference)method).DeclaringType.Relink(relinker, context));
			val3.CallingConvention = method.CallingConvention;
			val3.ExplicitThis = method.ExplicitThis;
			val3.HasThis = method.HasThis;
			Enumerator<GenericParameter> enumerator2 = method.GenericParameters.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					GenericParameter current2 = enumerator2.Current;
					GenericParameter val4 = Update(new GenericParameter(((MemberReference)current2).Name, current2.Owner)
					{
						Attributes = current2.Attributes
					}, current2);
					val3.GenericParameters.Add(val4);
					Enumerator<TypeReference> enumerator3 = current2.Constraints.GetEnumerator();
					try
					{
						while (enumerator3.MoveNext())
						{
							TypeReference current3 = enumerator3.Current;
							val4.Constraints.Add(current3.Relink(relinker, (IGenericParameterProvider)(object)val3));
						}
					}
					finally
					{
						((IDisposable)enumerator3).Dispose();
					}
				}
			}
			finally
			{
				((IDisposable)enumerator2).Dispose();
			}
			val3.ReturnType = val3.ReturnType?.Relink(relinker, (IGenericParameterProvider)(object)val3);
			Enumerator<ParameterDefinition> enumerator4 = method.Parameters.GetEnumerator();
			try
			{
				while (enumerator4.MoveNext())
				{
					ParameterDefinition current4 = enumerator4.Current;
					((ParameterReference)current4).ParameterType = ((ParameterReference)current4).ParameterType.Relink(relinker, (IGenericParameterProvider)(object)method);
					val3.Parameters.Add(current4);
				}
			}
			finally
			{
				((IDisposable)enumerator4).Dispose();
			}
			return (MethodReference)relinker((IMetadataTokenProvider)(object)val3, context);
		}

		public static IMetadataTokenProvider Relink(this FieldReference field, Relinker relinker, IGenericParameterProvider context)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			TypeReference val = ((MemberReference)field).DeclaringType.Relink(relinker, context);
			return relinker((IMetadataTokenProvider)new FieldReference(((MemberReference)field).Name, field.FieldType.Relink(relinker, (IGenericParameterProvider)(object)val), val), context);
		}

		public static ParameterDefinition Relink(this ParameterDefinition param, Relinker relinker, IGenericParameterProvider context)
		{
			//IL_0031: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			IMethodSignature method = param.Method;
			IMethodSignature obj = ((method is MethodReference) ? method : null);
			param = ((obj != null) ? ((MethodReference)obj).Parameters[((ParameterReference)param).Index] : null) ?? param;
			ParameterDefinition val = new ParameterDefinition(((ParameterReference)param).Name, param.Attributes, ((ParameterReference)param).ParameterType.Relink(relinker, context))
			{
				IsIn = param.IsIn,
				IsLcid = param.IsLcid,
				IsOptional = param.IsOptional,
				IsOut = param.IsOut,
				IsReturnValue = param.IsReturnValue,
				MarshalInfo = param.MarshalInfo
			};
			if (param.HasConstant)
			{
				val.Constant = param.Constant;
			}
			return val;
		}

		public static ParameterDefinition Clone(this ParameterDefinition param)
		{
			//IL_0008: 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)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0067: Expected O, but got Unknown
			//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)
			ParameterDefinition val = new ParameterDefinition(((ParameterReference)param).Name, param.Attributes, ((ParameterReference)param).ParameterType)
			{
				IsIn = param.IsIn,
				IsLcid = param.IsLcid,
				IsOptional = param.IsOptional,
				IsOut = param.IsOut,
				IsReturnValue = param.IsReturnValue,
				MarshalInfo = param.MarshalInfo
			};
			if (param.HasConstant)
			{
				val.Constant = param.Constant;
			}
			Enumerator<CustomAttribute> enumerator = param.CustomAttributes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttribute current = enumerator.Current;
					val.CustomAttributes.Add(current.Clone());
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return val;
		}

		public static CustomAttribute Relink(this CustomAttribute attrib, Relinker relinker, IGenericParameterProvider context)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00f8: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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)
			CustomAttribute val = new CustomAttribute(attrib.Constructor.Relink(relinker, context));
			Enumerator<CustomAttributeArgument> enumerator = attrib.ConstructorArguments.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttributeArgument current = enumerator.Current;
					val.ConstructorArguments.Add(new CustomAttributeArgument(((CustomAttributeArgument)(ref current)).Type.Relink(relinker, context), ((CustomAttributeArgument)(ref current)).Value));
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			Enumerator<CustomAttributeNamedArgument> enumerator2 = attrib.Fields.GetEnumerator();
			CustomAttributeArgument argument;
			try
			{
				while (enumerator2.MoveNext())
				{
					CustomAttributeNamedArgument current2 = enumerator2.Current;
					Collection<CustomAttributeNamedArgument> fields = val.Fields;
					string name = ((CustomAttributeNamedArgument)(ref current2)).Name;
					argument = ((CustomAttributeNamedArgument)(ref current2)).Argument;
					TypeReference obj = ((CustomAttributeArgument)(ref argument)).Type.Relink(relinker, context);
					argument = ((CustomAttributeNamedArgument)(ref current2)).Argument;
					fields.Add(new CustomAttributeNamedArgument(name, new CustomAttributeArgument(obj, ((CustomAttributeArgument)(ref argument)).Value)));
				}
			}
			finally
			{
				((IDisposable)enumerator2).Dispose();
			}
			Enumerator<CustomAttributeNamedArgument> enumerator3 = attrib.Properties.GetEnumerator();
			try
			{
				while (enumerator3.MoveNext())
				{
					CustomAttributeNamedArgument current3 = enumerator3.Current;
					Collection<CustomAttributeNamedArgument> properties = val.Properties;
					string name2 = ((CustomAttributeNamedArgument)(ref current3)).Name;
					argument = ((CustomAttributeNamedArgument)(ref current3)).Argument;
					TypeReference obj2 = ((CustomAttributeArgument)(ref argument)).Type.Relink(relinker, context);
					argument = ((CustomAttributeNamedArgument)(ref current3)).Argument;
					properties.Add(new CustomAttributeNamedArgument(name2, new CustomAttributeArgument(obj2, ((CustomAttributeArgument)(ref argument)).Value)));
				}
			}
			finally
			{
				((IDisposable)enumerator3).Dispose();
			}
			return val;
		}

		public static CustomAttribute Clone(this CustomAttribute attrib)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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)
			//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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			CustomAttribute val = new CustomAttribute(attrib.Constructor);
			Enumerator<CustomAttributeArgument> enumerator = attrib.ConstructorArguments.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttributeArgument current = enumerator.Current;
					val.ConstructorArguments.Add(new CustomAttributeArgument(((CustomAttributeArgument)(ref current)).Type, ((CustomAttributeArgument)(ref current)).Value));
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			Enumerator<CustomAttributeNamedArgument> enumerator2 = attrib.Fields.GetEnumerator();
			CustomAttributeArgument argument;
			try
			{
				while (enumerator2.MoveNext())
				{
					CustomAttributeNamedArgument current2 = enumerator2.Current;
					Collection<CustomAttributeNamedArgument> fields = val.Fields;
					string name = ((CustomAttributeNamedArgument)(ref current2)).Name;
					argument = ((CustomAttributeNamedArgument)(ref current2)).Argument;
					TypeReference type = ((CustomAttributeArgument)(ref argument)).Type;
					argument = ((CustomAttributeNamedArgument)(ref current2)).Argument;
					fields.Add(new CustomAttributeNamedArgument(name, new CustomAttributeArgument(type, ((CustomAttributeArgument)(ref argument)).Value)));
				}
			}
			finally
			{
				((IDisposable)enumerator2).Dispose();
			}
			Enumerator<CustomAttributeNamedArgument> enumerator3 = attrib.Properties.GetEnumerator();
			try
			{
				while (enumerator3.MoveNext())
				{
					CustomAttributeNamedArgument current3 = enumerator3.Current;
					Collection<CustomAttributeNamedArgument> properties = val.Properties;
					string name2 = ((CustomAttributeNamedArgument)(ref current3)).Name;
					argument = ((CustomAttributeNamedArgument)(ref current3)).Argument;
					TypeReference type2 = ((CustomAttributeArgument)(ref argument)).Type;
					argument = ((CustomAttributeNamedArgument)(ref current3)).Argument;
					properties.Add(new CustomAttributeNamedArgument(name2, new CustomAttributeArgument(type2, ((CustomAttributeArgument)(ref argument)).Value)));
				}
			}
			finally
			{
				((IDisposable)enumerator3).Dispose();
			}
			return val;
		}

		public static GenericParameter Relink(this GenericParameter param, Relinker relinker, IGenericParameterProvider context)
		{
			//IL_000d: 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_0025: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			GenericParameter val = Update(new GenericParameter(((MemberReference)param).Name, param.Owner)
			{
				Attributes = param.Attributes
			}, param);
			Enumerator<TypeReference> enumerator = param.Constraints.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					TypeReference current = enumerator.Current;
					val.Constraints.Add(current.Relink(relinker, context));
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return val;
		}

		public static GenericParameter Clone(this GenericParameter param)
		{
			//IL_000d: 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_0025: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			GenericParameter val = Update(new GenericParameter(((MemberReference)param).Name, param.Owner)
			{
				Attributes = param.Attributes
			}, param);
			Enumerator<TypeReference> enumerator = param.Constraints.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					TypeReference current = enumerator.Current;
					val.Constraints.Add(current);
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return val;
		}

		public static MethodDefinition FindMethod(this TypeDefinition type, string findableID, bool simple = true)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			if (simple && !findableID.Contains(" "))
			{
				Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						MethodDefinition current = enumerator.Current;
						if (((MethodReference)(object)current).GetFindableID(null, null, withType: true, simple: true) == findableID)
						{
							return current;
						}
					}
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
				Enumerator<MethodDefinition> enumerator2 = type.Methods.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						MethodDefinition current2 = enumerator2.Current;
						if (((MethodReference)(object)current2).GetFindableID(null, null, withType: false, simple: true) == findableID)
						{
							return current2;
						}
					}
				}
				finally
				{
					((IDisposable)enumerator2).Dispose();
				}
			}
			Enumerator<MethodDefinition> enumerator3 = type.Methods.GetEnumerator();
			try
			{
				while (enumerator3.MoveNext())
				{
					MethodDefinition current3 = enumerator3.Current;
					if (((MethodReference)(object)current3).GetFindableID() == findableID)
					{
						return current3;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator3).Dispose();
			}
			Enumerator<MethodDefinition> enumerator4 = type.Methods.GetEnumerator();
			try
			{
				while (enumerator4.MoveNext())
				{
					MethodDefinition current4 = enumerator4.Current;
					if (((MethodReference)(object)current4).GetFindableID(null, null, withType: false) == findableID)
					{
						return current4;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator4).Dispose();
			}
			return null;
		}

		public static MethodInfo FindMethod(this Type type, string findableID, bool simple = true)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo in array)
			{
				if (methodInfo.GetFindableID(null, null, withType: true, proxyMethod: false, simple: false) == findableID)
				{
					return methodInfo;
				}
			}
			MethodInfo[] array2 = methods;
			foreach (MethodInfo methodInfo2 in array2)
			{
				if (methodInfo2.GetFindableID(null, null, withType: false, proxyMethod: false, simple: false) == findableID)
				{
					return methodInfo2;
				}
			}
			if (!simple)
			{
				return null;
			}
			MethodInfo[] array3 = methods;
			foreach (MethodInfo methodInfo3 in array3)
			{
				if (methodInfo3.GetFindableID(null, null, withType: true, proxyMethod: false, simple: true) == findableID)
				{
					return methodInfo3;