Decompiled source of R2API Core v5.1.5

plugins/R2API.Core/R2API.Core.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HG.Reflection;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.Utils;
using On.RoR2;
using R2API.AutoVersionGen;
using R2API.Utils;
using RoR2;
using RoR2.Networking;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: InternalsVisibleTo("R2API.Items")]
[assembly: InternalsVisibleTo("R2API.ContentManagement")]
[assembly: InternalsVisibleTo("R2API.ArtifactCode")]
[assembly: InternalsVisibleTo("R2API.Difficulty")]
[assembly: InternalsVisibleTo("R2API.Elites")]
[assembly: InternalsVisibleTo("R2API.RecalculateStats")]
[assembly: InternalsVisibleTo("R2API.Prefab")]
[assembly: InternalsVisibleTo("R2API.Language")]
[assembly: InternalsVisibleTo("R2API.Unlockable")]
[assembly: InternalsVisibleTo("R2API.TempVisualEffect")]
[assembly: InternalsVisibleTo("R2API.SceneAsset")]
[assembly: InternalsVisibleTo("R2API.Orb")]
[assembly: InternalsVisibleTo("R2API.Loadout")]
[assembly: InternalsVisibleTo("R2API.Dot")]
[assembly: InternalsVisibleTo("R2API.DamageType")]
[assembly: InternalsVisibleTo("R2API.Sound")]
[assembly: InternalsVisibleTo("R2API.Director")]
[assembly: InternalsVisibleTo("R2API.Deployable")]
[assembly: InternalsVisibleTo("R2API.LobbyConfig")]
[assembly: InternalsVisibleTo("R2API.Networking")]
[assembly: InternalsVisibleTo("R2API.CommandHelper")]
[assembly: InternalsVisibleTo("R2API.Colors")]
[assembly: InternalsVisibleTo("R2API.Rules")]
[assembly: InternalsVisibleTo("R2API.Skins")]
[assembly: InternalsVisibleTo("R2API.StringSerializerExtensions")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("R2API.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("5.1.5.0")]
[assembly: AssemblyInformationalVersion("5.1.5+05cd8e34c4cfc04d651c4ce37056838a440559d2")]
[assembly: AssemblyProduct("R2API.Core")]
[assembly: AssemblyTitle("R2API.Core")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("5.1.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
}
namespace R2API
{
	public class Notification : MonoBehaviour
	{
		public GameObject? RootObject { get; set; }

		public GenericNotification? GenericNotification { get; set; }

		public Func<string>? GetTitle { get; set; }

		public Func<string>? GetDescription { get; set; }

		public Transform? Parent { get; set; }

		private void Awake()
		{
			Parent = ((Component)RoR2Application.instance.mainCanvas).transform;
			RootObject = Object.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/NotificationPanel2"));
			GenericNotification = RootObject.GetComponent<GenericNotification>();
			((Component)GenericNotification).transform.SetParent(Parent);
			((Behaviour)GenericNotification.iconImage).enabled = false;
		}

		private void Update()
		{
			if ((Object)(object)GenericNotification == (Object)null)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			GenericNotification.titleText.SetFieldValue("resolvedString", GetTitle());
			GenericNotification.titleText.InvokeMethod("UpdateLabel");
			GenericNotification.descriptionText.SetFieldValue("resolvedString", GetDescription());
			GenericNotification.descriptionText.InvokeMethod("UpdateLabel");
		}

		private void OnDestroy()
		{
			Object.Destroy((Object)(object)GenericNotification);
			Object.Destroy((Object)(object)RootObject);
		}

		public void SetIcon(Texture? texture)
		{
			((Behaviour)GenericNotification.iconImage).enabled = true;
			GenericNotification.iconImage.texture = texture;
		}

		public void SetPosition(Vector3 position)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			RootObject.transform.position = position;
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.bepis.r2api", "R2API", "5.1.5")]
	[AutoVersion]
	public class R2API : BaseUnityPlugin
	{
		public const string PluginGUID = "com.bepis.r2api";

		public const string PluginName = "R2API";

		private const string GameBuildId = "1.3.1";

		internal static HashSet<string> LoadedSubmodules;

		private NetworkCompatibilityHandler _networkCompatibilityHandler;

		public const string PluginVersion = "5.1.5";

		internal static ManualLogSource Logger { get; set; }

		public static bool DebugMode { get; private set; }

		internal static R2API Instance { get; private set; }

		internal static event EventHandler R2APIStart;

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			_networkCompatibilityHandler = new NetworkCompatibilityHandler();
			_networkCompatibilityHandler.BuildModList();
			RoR2Application.Awake += new hook_Awake(CheckIfUsedOnRightGameVersion);
		}

		private void Start()
		{
			R2API.R2APIStart?.Invoke(this, null);
		}

		private void OnDestroy()
		{
			_networkCompatibilityHandler.CleanupModList();
		}

		private static void DebugUpdate()
		{
		}

		public static void LogDebug(object debugText, [CallerMemberName] string caller = "")
		{
			Logger.LogDebug((object)(caller + " : " + debugText.ToString()));
		}

		private void CheckIfUsedOnRightGameVersion(orig_Awake orig, RoR2Application self)
		{
			orig.Invoke(self);
			string version = Application.version;
			if (!("1.3.1" == version))
			{
				Logger.LogWarning((object)("This version of R2API was built for build id \"1.3.1\", you are running \"" + version + "\"."));
				Logger.LogWarning((object)"Should any problems arise, please check for a new version before reporting issues.");
			}
		}

		public static bool IsLoaded(string submodule)
		{
			if (LoadedSubmodules == null)
			{
				Logger.LogWarning((object)"IsLoaded called before submodules were loaded, result may not reflect actual load status.");
				return false;
			}
			return LoadedSubmodules.Contains(submodule);
		}

		public static bool SupportsVersion(string? version)
		{
			Version version2 = Version.Parse("5.1.5");
			Version version3 = Version.Parse(version);
			if (version2.Major == version3.Major)
			{
				return version2.Minor <= version3.Minor;
			}
			return false;
		}
	}
}
namespace R2API.AutoVersionGen
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	internal class AutoVersionAttribute : Attribute
	{
	}
}
namespace R2API.MiscHelpers
{
	internal static class ILCursorExtensions
	{
		public static ILCursor EmitDel<TDel>(this ILCursor cursor, TDel func) where TDel : Delegate
		{
			cursor.EmitDelegate<TDel>(func);
			return cursor;
		}
	}
	public static class KeyValuePairExtensions
	{
		public static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> kvp, out TKey key, out TValue value)
		{
			key = kvp.Key;
			value = kvp.Value;
		}
	}
	public delegate T Modifier<T>(T input);
	internal static class MulticastDelegateExtensions
	{
		public static T InvokeSequential<T>(this Modifier<T> func, T initialValue, bool skipErrors = false)
		{
			Delegate[] invocationList = func.GetInvocationList();
			if (invocationList == null || invocationList.Length <= 1)
			{
				return func(initialValue);
			}
			foreach (Modifier<T> item in invocationList.Where((Delegate a) => a is Modifier<T>).Cast<Modifier<T>>())
			{
				try
				{
					initialValue = item(initialValue);
				}
				catch (Exception ex)
				{
					if (!skipErrors)
					{
						throw ex;
					}
					R2API.Logger.LogError((object)ex);
				}
			}
			return initialValue;
		}

		public static TOut InvokeSequential<TIn, TOut>(this Func<TIn, TOut> func, TIn initialValue, Func<TOut, TIn> inBetween, bool skipErrors = false)
		{
			Delegate[] invocationList = func.GetInvocationList();
			if (invocationList == null || invocationList.Length <= 1)
			{
				return func(initialValue);
			}
			TOut val = default(TOut);
			bool flag = true;
			foreach (Func<TIn, TOut> item in invocationList.Where((Delegate a) => a is Func<TIn, TOut>).Cast<Func<TIn, TOut>>())
			{
				if (flag)
				{
					try
					{
						val = item(initialValue);
						flag = false;
					}
					catch (Exception ex)
					{
						if (!skipErrors)
						{
							throw ex;
						}
						R2API.Logger.LogError((object)ex);
					}
				}
				else
				{
					val = item(inBetween(val));
				}
			}
			return val;
		}
	}
}
namespace R2API.Utils
{
	public static class EnumerableExtensions
	{
		public static void ForEachTry<T>(this IEnumerable<T>? list, Action<T>? action, IDictionary<T, Exception?>? exceptions = null)
		{
			Action<T> action2 = action;
			IDictionary<T, Exception?> exceptions2 = exceptions;
			list.ToList().ForEach(delegate(T element)
			{
				try
				{
					action2(element);
				}
				catch (Exception value)
				{
					exceptions2?.Add(element, value);
				}
			});
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
	[Obsolete("All submodules are automatically loaded and this attribute is now unused.", false)]
	public class R2APISubmoduleDependency : Attribute
	{
		public const string AttributeObsolete = "All submodules are automatically loaded and this attribute is now unused.";

		public const string PropertyObsolete = "All submodules are automatically loaded and this property is now unused";

		public string?[]? SubmoduleNames { get; }

		public R2APISubmoduleDependency(params string[] submoduleName)
		{
			SubmoduleNames = submoduleName;
		}
	}
	public static class CecilUtil
	{
		internal static bool IsSubTypeOf(this TypeDefinition typeDefinition, string typeFullName)
		{
			if (((MemberReference)typeDefinition).FullName == typeFullName)
			{
				return true;
			}
			TypeReference baseType = typeDefinition.BaseType;
			TypeDefinition val = ((baseType != null) ? baseType.Resolve() : null);
			while (val != null)
			{
				if (((MemberReference)val).FullName == typeFullName)
				{
					return true;
				}
				TypeReference baseType2 = val.BaseType;
				val = ((baseType2 != null) ? baseType2.Resolve() : null);
			}
			return false;
		}
	}
	public static class ChatMessage
	{
		public static void Send(string? message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = "{0}";
			val.paramTokens = new string[1] { message };
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
		}

		public static void Send(string? message, string? messageFrom)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = "{0}: {1}";
			val.paramTokens = new string[2] { messageFrom, message };
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
		}

		public static void SendColored(string? message, string? colorHex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = "<color=" + colorHex + ">{0}</color>";
			val.paramTokens = new string[1] { message };
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
		}

		public static void SendColored(string? message, ColorIndex color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SendColored(message, ColorCatalog.GetColorHexString(color));
		}

		public static void SendColored(string? message, Color color)
		{
			SendColored(message, ColorToHexString(color));
		}

		public static void SendColored(string? message, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SendColored(message, ColorToHexString(color));
		}

		public static void SendColored(string? message, string? colorHex, string? messageFrom)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = "<color=" + colorHex + ">{0}: {1}</color>";
			val.paramTokens = new string[2] { messageFrom, message };
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
		}

		public static void SendColored(string? message, ColorIndex color, string? messageFrom)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SendColored(message, ColorCatalog.GetColorHexString(color), messageFrom);
		}

		public static void SendColored(string? message, Color color, string? messageFrom)
		{
			SendColored(message, ColorToHexString(color), messageFrom);
		}

		public static void SendColored(string? message, Color color, string? messageFrom)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SendColored(message, ColorToHexString(color), messageFrom);
		}

		private static string ColorToHexString(Color c)
		{
			return "#" + c.R.ToString("X2") + c.G.ToString("X2") + c.B.ToString("X2");
		}

		private static string ColorToHexString(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return "#" + ColorUtility.ToHtmlStringRGB(c);
		}
	}
	internal static class CompressedFlagArrayUtilities
	{
		[StructLayout(LayoutKind.Explicit)]
		[DebuggerDisplay("{ToString()}")]
		private ref struct FullBlockMask
		{
			[FieldOffset(3)]
			private byte byte0;

			[FieldOffset(2)]
			private byte byte1;

			[FieldOffset(1)]
			private byte byte2;

			[FieldOffset(0)]
			private byte byte3;

			[FieldOffset(0)]
			public uint integer;

			public byte this[int i]
			{
				get
				{
					if (BitConverter.IsLittleEndian)
					{
						return i switch
						{
							0 => byte0, 
							1 => byte1, 
							2 => byte2, 
							3 => byte3, 
							_ => throw new IndexOutOfRangeException(), 
						};
					}
					return i switch
					{
						0 => byte3, 
						1 => byte2, 
						2 => byte1, 
						3 => byte0, 
						_ => throw new IndexOutOfRangeException(), 
					};
				}
				set
				{
					if (BitConverter.IsLittleEndian)
					{
						switch (i)
						{
						case 0:
							byte0 = value;
							break;
						case 1:
							byte1 = value;
							break;
						case 2:
							byte2 = value;
							break;
						case 3:
							byte3 = value;
							break;
						default:
							throw new IndexOutOfRangeException();
						}
					}
					else
					{
						switch (i)
						{
						case 0:
							byte3 = value;
							break;
						case 1:
							byte2 = value;
							break;
						case 2:
							byte1 = value;
							break;
						case 3:
							byte0 = value;
							break;
						default:
							throw new IndexOutOfRangeException();
						}
					}
				}
			}

			public override string ToString()
			{
				return Convert.ToString(integer, 2).PadLeft(32, '0');
			}
		}

		private static readonly byte[] tempBlockValues = new byte[18];

		private static readonly int[] tempBlockPartValuesCounts = new int[4];

		public const byte flagsPerValue = 8;

		public const byte valuesPerBlock = 18;

		public const byte flagsPerSection = 144;

		public const byte sectionsCount = 8;

		public const byte blockPartsCount = 4;

		private const uint fullBlockHeader = 4218992u;

		private const uint block1HeaderMask = 64u;

		private const uint block2HeaderMask = 96u;

		private const uint block3HeaderMask = 112u;

		private const uint block4HeaderMask = 120u;

		private const uint block1HeaderXor = 0u;

		private const uint block2HeaderXor = 64u;

		private const uint block3HeaderXor = 96u;

		private const uint block4HeaderXor = 112u;

		private const int block1HeaderSkip = 2;

		private const int block2HeaderSkip = 3;

		private const int block3HeaderSkip = 4;

		private const int block4HeaderSkip = 5;

		private const int block1HeaderValuesCount = 6;

		private const int block2HeaderValuesCount = 5;

		private const int block3HeaderValuesCount = 4;

		private const int block4HeaderValuesCount = 3;

		private const int block1HeaderOffset = -2;

		private const int block2HeaderOffset = 3;

		private const int block3HeaderOffset = 7;

		private const int block4HeaderOffset = 10;

		private const uint highestBitInByte = 128u;

		public static void Add(ref byte[] values, int index)
		{
			if (index < 0)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			int num = index / 8;
			int num2 = index - num * 8;
			ResizeIfNeeded(ref values, num);
			values[num] = (byte)(values[num] | (128u >> num2));
		}

		public static void AddImmutable(ref byte[] values, int index)
		{
			if (index < 0)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			int num = index / 8;
			int num2 = index - num * 8;
			if (!ResizeIfNeeded(ref values, num))
			{
				byte b = (byte)(values[num] | (128u >> num2));
				if (values[num] != b)
				{
					byte[] obj = values;
					values = new byte[values.Length];
					obj.CopyTo(values, 0);
					values[num] = b;
				}
			}
			else
			{
				byte b2 = (byte)(128u >> num2);
				values[num] = b2;
			}
		}

		public static void Add(ref byte[] values, byte[] operand)
		{
			ResizeIfNeeded(ref values, operand.Length);
			for (int i = 0; i < operand.Length; i++)
			{
				values[i] |= operand[i];
			}
		}

		public static bool Remove(ref byte[] values, int index)
		{
			if (index < 0)
			{
				return false;
			}
			int num = index / 8;
			if (num >= values.Length)
			{
				return false;
			}
			int num2 = index - num * 8;
			values[num] = (byte)(values[num] & ~(128 >>> num2));
			DownsizeIfNeeded(ref values);
			return true;
		}

		public static bool RemoveImmutable(ref byte[] values, int index)
		{
			if (index < 0 || values == null)
			{
				return false;
			}
			int num = index / 8;
			if (num >= values.Length)
			{
				return false;
			}
			int num2 = index - num * 8;
			byte b = (byte)(values[num] & ~(128 >>> num2));
			if (values[num] == b)
			{
				return true;
			}
			if (b == 0)
			{
				DownsizeIgnoreLast(ref values);
				if (values.Length == 0)
				{
					values = null;
				}
			}
			else
			{
				byte[] obj = values;
				values = new byte[values.Length];
				obj.CopyTo(values, 0);
				values[num] = b;
			}
			return true;
		}

		public static bool Remove(ref byte[] values, byte[] operand)
		{
			bool flag = false;
			int num = Math.Min(values.Length, operand.Length);
			for (int i = 0; i < num; i++)
			{
				flag |= (values[i] & operand[i]) != 0;
				values[i] &= (byte)(~operand[i]);
			}
			DownsizeIfNeeded(ref values);
			return flag;
		}

		public static bool Has(byte[] values, int index)
		{
			if (index < 0 || values == null)
			{
				return false;
			}
			int num = index / 8;
			if (num >= values.Length)
			{
				return false;
			}
			int num2 = index - num * 8;
			return (values[num] & (128 >>> num2)) != 0;
		}

		public static byte[] ReadFromNetworkReader(NetworkReader reader, int maxValue)
		{
			byte[] values = Array.Empty<byte>();
			byte b = reader.ReadByte();
			if (b == 0)
			{
				return values;
			}
			if (maxValue <= 8)
			{
				return new byte[1] { b };
			}
			if (maxValue <= 64)
			{
				int num = 0;
				for (int i = 0; i < 8; i++)
				{
					if ((b & (1 << i)) != 0)
					{
						num = i;
						tempBlockValues[i] = reader.ReadByte();
					}
					else
					{
						tempBlockValues[i] = 0;
					}
				}
				values = new byte[num + 1];
				Array.Copy(tempBlockValues, 0, values, 0, num + 1);
				return values;
			}
			for (int j = 0; j < 8; j++)
			{
				if ((b & (1 << j)) != 0)
				{
					ReadBlock(ref values, reader, j);
				}
			}
			return values;
		}

		public static void WriteToNetworkWriter(byte[] values, NetworkWriter writer, int maxValue)
		{
			int num = 0;
			if (maxValue <= 8)
			{
				writer.Write((byte)((values.Length != 0) ? values[0] : 0));
				return;
			}
			if (maxValue <= 64)
			{
				int num2 = 0;
				for (int num3 = Math.Min(8, values.Length) - 1; num3 >= 0; num3--)
				{
					num <<= 1;
					if (values[num3] != 0)
					{
						tempBlockValues[num2++] = values[num3];
						num |= 1;
					}
				}
				writer.Write((byte)num);
				for (int num4 = num2 - 1; num4 >= 0; num4--)
				{
					writer.Write(tempBlockValues[num4]);
				}
				return;
			}
			for (int i = 0; i < 8; i++)
			{
				if (!IsBlockEmpty(values, i, out var end))
				{
					num |= 1 << i;
				}
				if (end)
				{
					break;
				}
			}
			writer.Write((byte)num);
			for (int j = 0; j < 8; j++)
			{
				if ((num & (1 << j)) > 0)
				{
					WriteBlock(values, writer, j);
				}
			}
		}

		private static void ReadBlock(ref byte[] values, NetworkReader reader, int blockIndex)
		{
			Array.Clear(tempBlockValues, 0, 18);
			int num = 0;
			int lastValueIndex = 0;
			byte b;
			do
			{
				b = reader.ReadByte();
				var (num2, num3, fromIndex, valueBitesOffset) = GetMaskValues(num);
				while (((b & num2) ^ num3) != 0)
				{
					(num2, num3, fromIndex, valueBitesOffset) = GetMaskValues(++num);
				}
				ReadBlockValues(ref lastValueIndex, valueBitesOffset, fromIndex, 8, reader, b);
			}
			while ((b & 0x80) == 0);
			ResizeIfNeeded(ref values, blockIndex * 18 + lastValueIndex);
			Array.Copy(tempBlockValues, 0, values, blockIndex * 18, lastValueIndex + 1);
		}

		private static void ReadBlockValues(ref int lastValueIndex, int valueBitesOffset, int fromIndex, int toIndex, NetworkReader reader, byte blockByte)
		{
			for (int i = fromIndex; i < toIndex; i++)
			{
				if ((blockByte & (128u >> i)) != 0)
				{
					lastValueIndex = i + valueBitesOffset;
					tempBlockValues[lastValueIndex] = reader.ReadByte();
				}
			}
		}

		private static bool ResizeIfNeeded(ref byte[] values, int valueIndex)
		{
			if (values == null)
			{
				values = new byte[valueIndex + 1];
				return true;
			}
			if (valueIndex >= values.Length)
			{
				Array.Resize(ref values, valueIndex + 1);
				return true;
			}
			return false;
		}

		private static void DownsizeIfNeeded(ref byte[] value)
		{
			if (value.Length != 0 && value[value.Length - 1] == 0)
			{
				DownsizeIgnoreLast(ref value);
			}
		}

		private static void DownsizeIgnoreLast(ref byte[] value)
		{
			for (int num = value.Length - 2; num >= 0; num--)
			{
				if (value[num] != 0)
				{
					Array.Resize(ref value, num + 1);
					return;
				}
			}
			value = Array.Empty<byte>();
		}

		private static void WriteBlock(byte[] values, NetworkWriter writer, int blockIndex)
		{
			int blockValuesCount = 0;
			FullBlockMask fullBlockMask = default(FullBlockMask);
			PrepareBlockValues(values, blockIndex, 0, 6, ref blockValuesCount, ref fullBlockMask);
			tempBlockPartValuesCounts[0] = blockValuesCount;
			fullBlockMask.integer <<= 3;
			PrepareBlockValues(values, blockIndex, 6, 11, ref blockValuesCount, ref fullBlockMask);
			tempBlockPartValuesCounts[1] = blockValuesCount;
			fullBlockMask.integer <<= 4;
			PrepareBlockValues(values, blockIndex, 11, 15, ref blockValuesCount, ref fullBlockMask);
			tempBlockPartValuesCounts[2] = blockValuesCount;
			fullBlockMask.integer <<= 5;
			PrepareBlockValues(values, blockIndex, 15, 18, ref blockValuesCount, ref fullBlockMask);
			tempBlockPartValuesCounts[3] = blockValuesCount;
			int num = 0;
			for (int num2 = 3; num2 > 0; num2--)
			{
				if (fullBlockMask[num2] != 0)
				{
					num = num2;
					break;
				}
			}
			fullBlockMask.integer |= 4218992u;
			fullBlockMask[num] |= 128;
			int i = 0;
			for (int j = 0; j <= num; j++)
			{
				if (i != tempBlockPartValuesCounts[j])
				{
					writer.Write(fullBlockMask[j]);
					for (; i < tempBlockPartValuesCounts[j]; i++)
					{
						writer.Write(tempBlockValues[i]);
					}
				}
			}
		}

		private static void PrepareBlockValues(byte[] values, int blockIndex, int fromIndex, int toIndex, ref int blockValuesCount, ref FullBlockMask fullBlockMask)
		{
			for (int i = fromIndex; i < toIndex; i++)
			{
				fullBlockMask.integer <<= 1;
				int num = blockIndex * 18 + i;
				if (num < values.Length && values[num] != 0)
				{
					fullBlockMask.integer |= 1u;
					tempBlockValues[blockValuesCount++] = values[num];
				}
			}
		}

		private static bool IsBlockEmpty(byte[] values, int blockIndex, out bool end)
		{
			if (values.Length == 0 || values.Length / 18 < blockIndex)
			{
				end = true;
				return true;
			}
			end = false;
			int num = Math.Min((blockIndex + 1) * 18, values.Length);
			for (int i = blockIndex * 18; i < num; i++)
			{
				if (values[i] != 0)
				{
					return false;
				}
			}
			return true;
		}

		private static (uint mask, uint xor, int skip, int offset) GetMaskValues(int i)
		{
			return i switch
			{
				0 => (64u, 0u, 2, -2), 
				1 => (96u, 64u, 3, 3), 
				2 => (112u, 96u, 4, 7), 
				3 => (120u, 112u, 5, 10), 
				_ => throw new IndexOutOfRangeException(), 
			};
		}
	}
	public static class DirectMessage
	{
		private static NetworkUser[] GetConnectionNetworkUsers(NetworkConnection conn)
		{
			List<PlayerController> playerControllers = conn.playerControllers;
			NetworkUser[] array = (NetworkUser[])(object)new NetworkUser[playerControllers.Count];
			for (int i = 0; i < playerControllers.Count; i++)
			{
				array[i] = playerControllers[i].gameObject.GetComponent<NetworkUser>();
			}
			return array;
		}

		private static NetworkConnection ResolveUserToConnection(NetworkUser user)
		{
			foreach (NetworkConnection connection in NetworkServer.connections)
			{
				if (connection == null)
				{
					continue;
				}
				NetworkUser[] connectionNetworkUsers = GetConnectionNetworkUsers(connection);
				foreach (NetworkUser obj in connectionNetworkUsers)
				{
					if (((object)user).Equals((object?)obj))
					{
						return connection;
					}
				}
			}
			return null;
		}

		public static void SendDirectMessage(string? message, NetworkConnection? connection)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = "{0}";
			val.paramTokens = new string[1] { message };
			SendDirectMessage((ChatMessageBase)(object)val, connection);
		}

		public static void SendDirectMessage(string? message, NetworkUser? user)
		{
			SendDirectMessage(message, ResolveUserToConnection(user));
		}

		public static void SendDirectMessage(ChatMessageBase message, NetworkConnection? connection)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			NetworkWriter val = new NetworkWriter();
			val.StartMessage((short)59);
			val.Write(message.GetTypeIndex());
			val.Write((MessageBase)(object)message);
			val.FinishMessage();
			connection.SendWriter(val, QosChannelIndex.chat.intVal);
		}
	}
	internal static class DirectoryUtilities
	{
		private static bool _alreadyPrintedFolderStructure;

		private static bool _bepinexFolderPrinted;

		private static readonly HashSet<string> BannedFolders = new HashSet<string> { "MonoBleedingEdge", "Risk of Rain 2_Data" };

		internal static void LogFolderStructureAsTree(string directory)
		{
			if (!_alreadyPrintedFolderStructure)
			{
				WriteFolderStructure(directory);
				if (!_bepinexFolderPrinted)
				{
					WriteFolderStructure(Paths.BepInExRootPath);
				}
				_alreadyPrintedFolderStructure = true;
			}
		}

		private static void WriteFolderStructure(string directory)
		{
			R2API.Logger.LogDebug((object)"");
			R2API.Logger.LogDebug((object)("+ " + new DirectoryInfo(directory).Name));
			string[] directories = Directory.GetDirectories(directory);
			for (int i = 0; i < directories.Length; i++)
			{
				WriteFolderStructureRecursively(directories[i]);
			}
			string[] files = Directory.GetFiles(directory);
			for (int j = 1; j <= files.Length; j++)
			{
				FileInfo fileInfo = new FileInfo(files[j - 1]);
				R2API.Logger.LogDebug((object)(GenerateSpaces(0) + ((j != files.Length) ? "|" : "`") + "---- " + fileInfo.Name + " (" + ParseSize(fileInfo.Length) + ")"));
			}
		}

		private static void WriteFolderStructureRecursively(string directory, int spaces = 0)
		{
			DirectoryInfo directoryInfo = new DirectoryInfo(directory);
			R2API.Logger.LogDebug((object)(GenerateSpaces(spaces) + "|---+ " + directoryInfo.Name));
			if (!_bepinexFolderPrinted && Paths.BepInExRootPath == directory)
			{
				_bepinexFolderPrinted = true;
			}
			if (directoryInfo.Parent != null && (BannedFolders.Contains(directoryInfo.Name) || BannedFolders.Contains(directoryInfo.Parent.Name + "/" + directoryInfo.Name)))
			{
				R2API.Logger.LogDebug((object)(GenerateSpaces(spaces + 4) + "`---- (Folder content not shown)"));
				return;
			}
			string[] directories = Directory.GetDirectories(directory);
			for (int i = 0; i < directories.Length; i++)
			{
				WriteFolderStructureRecursively(directories[i], spaces + 4);
			}
			string[] files = Directory.GetFiles(directory);
			for (int j = 1; j <= files.Length; j++)
			{
				FileInfo fileInfo = new FileInfo(files[j - 1]);
				R2API.Logger.LogDebug((object)(GenerateSpaces(spaces + 4) + ((j != files.Length) ? "|" : "`") + "---- " + fileInfo.Name + " (" + ParseSize(fileInfo.Length) + ")"));
			}
		}

		private static string ParseSize(long lSize)
		{
			string[] array = new string[4] { "B", "KB", "MB", "GB" };
			float num = lSize;
			int num2 = 0;
			while (num > 1024f)
			{
				num2++;
				num /= 1024f;
			}
			return num.ToString("F2") + array[num2];
		}

		private static string GenerateSpaces(int spaces)
		{
			string text = "";
			for (int i = 1; i <= spaces; i += 4)
			{
				text += "|   ";
			}
			return text;
		}
	}
	public static class EmbeddedResources
	{
		private unsafe static readonly delegate*<Assembly, string, out int, out Module, nint> GetManifestResourceInternal = (delegate*<Assembly, string, out int, out Module, nint>)(void*)typeof(R2API).Assembly.GetType().GetMethod("GetManifestResourceInternal", (BindingFlags)(-1)).MethodHandle.GetFunctionPointer();

		[MethodImpl(MethodImplOptions.NoInlining)]
		public unsafe static (nint ptr, int size) GetEmbeddedResource(string resourceName, Assembly? owningAssembly = null)
		{
			if ((object)owningAssembly == null)
			{
				owningAssembly = Assembly.GetCallingAssembly();
			}
			int item = default(int);
			Module module = default(Module);
			return (GetManifestResourceInternal(owningAssembly, resourceName, out item, out module), item);
		}
	}
	public static class ManualLogSourceExtension
	{
		public static void LogBlockError(this ManualLogSource? logger, IEnumerable<string?>? lines, int width = 70)
		{
			logger.LogBlock((LogLevel)2, "ERROR", lines, width);
		}

		public static void LogBlockWarning(this ManualLogSource? logger, IEnumerable<string?>? lines, int width = 70)
		{
			logger.LogBlock((LogLevel)4, "WARNING", lines, width);
		}

		public static void LogBlock(this ManualLogSource? logger, LogLevel level, string? header, IEnumerable<string?>? lines, int width = 70)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource logger2 = logger;
			string text = new string('*', width + 2);
			string text2 = CenterText("", width);
			logger2.Log(level, (object)text);
			logger2.Log(level, (object)text2);
			logger2.Log(level, (object)CenterText("!" + header + "!", width));
			lines.ToList().ForEach(delegate(string x)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				logger2.Log(level, (object)CenterText(x, width));
			});
			logger2.Log(level, (object)text2);
			logger2.Log(level, (object)text);
		}

		public static string CenterText(string? text = "", int width = 70)
		{
			return string.Format("*{0," + (width / 2 + text.Length / 2) + "}{1," + (width / 2 - text.Length / 2) + "}*", text, " ");
		}
	}
	public enum CompatibilityLevel
	{
		NoNeedForSync,
		EveryoneMustHaveMod
	}
	public enum VersionStrictness
	{
		DifferentModVersionsAreOk,
		EveryoneNeedSameModVersion
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class)]
	public class NetworkCompatibility : Attribute
	{
		public CompatibilityLevel CompatibilityLevel { get; internal set; }

		public VersionStrictness VersionStrictness { get; internal set; }

		public NetworkCompatibility(CompatibilityLevel compatibility = CompatibilityLevel.EveryoneMustHaveMod, VersionStrictness versionStrictness = VersionStrictness.EveryoneNeedSameModVersion)
		{
			CompatibilityLevel = compatibility;
			VersionStrictness = versionStrictness;
		}
	}
	internal class NetworkCompatibilityHandler
	{
		internal const char ModGuidAndModVersionSeparator = ';';

		internal readonly HashSet<string> ModList = new HashSet<string>();

		internal void BuildModList()
		{
			R2API.R2APIStart += ScanPluginsForNetworkCompat;
		}

		internal void CleanupModList()
		{
			if (NetworkModCompatibilityHelper.networkModList != null && NetworkModCompatibilityHelper.networkModList.Count() > 0)
			{
				List<string> list = NetworkModCompatibilityHelper.networkModList.ToList();
				list.RemoveAll(ModList.Contains);
				NetworkModCompatibilityHelper.networkModList = list;
			}
		}

		private void ScanPluginsForNetworkCompat(object? _, EventArgs __)
		{
			foreach (var (_, val2) in Chainloader.PluginInfos)
			{
				try
				{
					string gUID = val2.Metadata.GUID;
					Version version = val2.Metadata.Version;
					if (!gUID.StartsWith("com.bepis.r2api") && !val2.Dependencies.All((BepInDependency dependency) => !dependency.DependencyGUID.StartsWith("com.bepis.r2api") || (int)dependency.Flags == 2))
					{
						TryGetNetworkCompatibility(((object)val2.Instance).GetType(), out NetworkCompatibility networkCompatibility);
						if (networkCompatibility.CompatibilityLevel == CompatibilityLevel.EveryoneMustHaveMod)
						{
							ModList.Add((networkCompatibility.VersionStrictness == VersionStrictness.EveryoneNeedSameModVersion) ? (gUID + ";" + version) : gUID);
						}
					}
				}
				catch (Exception ex)
				{
					R2API.Logger.LogError((object)("Exception in ScanPluginsForNetworkCompat while scanning plugin " + val2.Metadata.GUID));
					R2API.Logger.LogError((object)("R2API Failed to properly scan the assembly." + Environment.NewLine + "Please make sure you are compiling against net standard 2.0 and not anything else when making a plugin for Risk of Rain 2 !" + Environment.NewLine + ex));
				}
			}
			AddToNetworkModList();
			R2API.R2APIStart -= ScanPluginsForNetworkCompat;
		}

		private static void TryGetNetworkCompatibility(Type baseUnityPluginType, out NetworkCompatibility networkCompatibility)
		{
			networkCompatibility = new NetworkCompatibility();
			foreach (CustomAttributeData customAttribute in baseUnityPluginType.Assembly.CustomAttributes)
			{
				if (customAttribute.AttributeType == typeof(NetworkCompatibility))
				{
					networkCompatibility.CompatibilityLevel = (CompatibilityLevel)customAttribute.ConstructorArguments[0].Value;
					networkCompatibility.VersionStrictness = (VersionStrictness)customAttribute.ConstructorArguments[1].Value;
					return;
				}
			}
			foreach (CustomAttributeData customAttribute2 in baseUnityPluginType.CustomAttributes)
			{
				if (customAttribute2.AttributeType == typeof(NetworkCompatibility))
				{
					networkCompatibility.CompatibilityLevel = (CompatibilityLevel)customAttribute2.ConstructorArguments[0].Value;
					networkCompatibility.VersionStrictness = (VersionStrictness)customAttribute2.ConstructorArguments[1].Value;
					break;
				}
			}
		}

		private void AddToNetworkModList()
		{
			if (ModList.Count == 0)
			{
				return;
			}
			List<string> list = ModList.ToList();
			list.Sort(StringComparer.InvariantCulture);
			R2API.Logger.LogInfo((object)"[NetworkCompatibility] Adding to the networkModList : ");
			foreach (string item in list)
			{
				R2API.Logger.LogInfo((object)item);
				NetworkModCompatibilityHelper.networkModList = NetworkModCompatibilityHelper.networkModList.Append(item);
			}
		}
	}
	public static class Reflection
	{
		public delegate T GetDelegate<out T>(object? instance);

		public delegate void SetDelegate<in T>(object? instance, T value);

		public delegate void SetDelegateRef<TInstance, in TValue>(ref TInstance instance, TValue value) where TInstance : struct;

		public delegate T GetDelegateRef<TInstance, out T>(ref TInstance instance) where TInstance : struct;

		private const BindingFlags AllFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly Dictionary<(Type T, string name), FieldInfo> FieldCache = new Dictionary<(Type, string), FieldInfo>();

		private static readonly Dictionary<(Type T, string name, Type TReturn), Delegate> FieldGetDelegateCache = new Dictionary<(Type, string, Type), Delegate>();

		private static readonly Dictionary<(Type T, string name, Type TValue), Delegate> FieldSetDelegateCache = new Dictionary<(Type, string, Type), Delegate>();

		private static readonly Dictionary<(Type T, string name), PropertyInfo> PropertyCache = new Dictionary<(Type, string), PropertyInfo>();

		private static readonly Dictionary<(Type T, string name, Type TInstance, Type TReturn), Delegate> PropertyGetDelegateCache = new Dictionary<(Type, string, Type, Type), Delegate>();

		private static readonly Dictionary<(Type T, string name, Type TInstance, Type TValue), Delegate> PropertySetDelegateCache = new Dictionary<(Type, string, Type, Type), Delegate>();

		private static readonly Dictionary<(Type T, string name), MethodInfo> MethodCache = new Dictionary<(Type, string), MethodInfo>();

		private static readonly Dictionary<(Type T, string name, long argumentTypesHashCode), MethodInfo> OverloadedMethodCache = new Dictionary<(Type, string, long), MethodInfo>();

		private static readonly Dictionary<(Type T, string name), FastReflectionDelegate> MethodDelegateCache = new Dictionary<(Type, string), FastReflectionDelegate>();

		private static readonly Dictionary<(Type T, string name, long argumentTypesHashCode), FastReflectionDelegate> OverloadedMethodDelegateCache = new Dictionary<(Type, string, long), FastReflectionDelegate>();

		private static readonly Dictionary<(Type T, long argumentTypesHashCode), ConstructorInfo> ConstructorCache = new Dictionary<(Type, long), ConstructorInfo>();

		private static readonly Dictionary<(Type T, string name), Type> NestedTypeCache = new Dictionary<(Type, string), Type>();

		public static long CombineHashCode<T>(IEnumerable<T> enumerable)
		{
			long num = 0L;
			foreach (T item in enumerable)
			{
				num = num * 486187739 + EqualityComparer<T>.Default.GetHashCode(item);
			}
			return num;
		}

		public static FieldInfo GetFieldCached<T>(string? name)
		{
			return typeof(T).GetFieldCached(name);
		}

		public static FieldInfo GetFieldCached(this Type? T, string? name)
		{
			if (FieldCache.TryGetValue((T, name), out FieldInfo value))
			{
				return value;
			}
			return FieldCache[(T, name)] = T.GetFieldFull(name);
		}

		public static TReturn GetFieldValue<TReturn>(this object? instance, string? fieldName)
		{
			return instance.GetType().GetFieldGetDelegate<TReturn>(fieldName)(instance);
		}

		public static TReturn GetFieldValue<TReturn>(this Type? staticType, string? fieldName)
		{
			return staticType.GetFieldGetDelegate<TReturn>(fieldName)(null);
		}

		public static void SetFieldValue<TValue>(this object? instance, string? fieldName, TValue value)
		{
			instance.GetType().GetFieldSetDelegate<TValue>(fieldName)(instance, value);
		}

		public static void SetFieldValue<TValue>(this Type? staticType, string? fieldName, TValue value)
		{
			staticType.GetFieldSetDelegate<TValue>(fieldName)(null, value);
		}

		public static void SetStructFieldValue<TInstance, TValue>(this ref TInstance instance, string? fieldName, TValue value) where TInstance : struct
		{
			typeof(TInstance).GetFieldSetDelegateRef<TInstance, TValue>(fieldName)(ref instance, value);
		}

		private static FieldInfo GetFieldFull(this Type T, string name)
		{
			while (T != null)
			{
				FieldInfo field = T.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
				T = T.BaseType;
			}
			return null;
		}

		public static GetDelegate<TReturn> GetFieldGetDelegate<TReturn>(this Type type, string? fieldName)
		{
			if (FieldGetDelegateCache.TryGetValue((type, fieldName, typeof(TReturn)), out Delegate value))
			{
				return (GetDelegate<TReturn>)value;
			}
			Delegate delegate2 = (FieldGetDelegateCache[(type, fieldName, typeof(TReturn))] = type.GetFieldCached(fieldName).CreateGetDelegate<TReturn>());
			return (GetDelegate<TReturn>)delegate2;
		}

		public static SetDelegate<TValue> GetFieldSetDelegate<TValue>(this Type type, string? fieldName)
		{
			if (FieldSetDelegateCache.TryGetValue((type, fieldName, typeof(TValue)), out Delegate value))
			{
				return (SetDelegate<TValue>)value;
			}
			Delegate delegate2 = (FieldSetDelegateCache[(type, fieldName, typeof(TValue))] = type.GetFieldCached(fieldName).CreateSetDelegate<TValue>());
			return (SetDelegate<TValue>)delegate2;
		}

		public static SetDelegateRef<TInstance, TValue> GetFieldSetDelegateRef<TInstance, TValue>(this Type type, string? fieldName) where TInstance : struct
		{
			if (FieldSetDelegateCache.TryGetValue((type, fieldName, typeof(TValue)), out Delegate value))
			{
				return (SetDelegateRef<TInstance, TValue>)value;
			}
			Delegate delegate2 = (FieldSetDelegateCache[(type, fieldName, typeof(TValue))] = type.GetFieldCached(fieldName).CreateSetDelegateRef<TInstance, TValue>());
			return (SetDelegateRef<TInstance, TValue>)delegate2;
		}

		public static PropertyInfo GetPropertyCached<T>(string? name)
		{
			return typeof(T).GetPropertyCached(name);
		}

		public static PropertyInfo GetPropertyCached(this Type? T, string? name)
		{
			if (PropertyCache.TryGetValue((T, name), out PropertyInfo value))
			{
				return value;
			}
			return PropertyCache[(T, name)] = T.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static TReturn GetPropertyValue<TReturn>(this object? instance, string? propName)
		{
			return instance.GetType().GetPropertyGetDelegate<TReturn>(propName)(instance);
		}

		public static TReturn GetPropertyValue<TReturn>(this Type? staticType, string? propName)
		{
			return staticType.GetPropertyGetDelegate<TReturn>(propName)(null);
		}

		public static void SetPropertyValue<TValue>(this object? instance, string? propName, TValue value)
		{
			instance.GetType().GetPropertySetDelegate<TValue>(propName)(instance, value);
		}

		public static void SetPropertyValue<TValue>(this Type? staticType, string? propName, TValue value)
		{
			staticType.GetPropertySetDelegate<TValue>(propName)(null, value);
		}

		public static void SetStructPropertyValue<TInstance, TValue>(this ref TInstance instance, string? propName, TValue value) where TInstance : struct
		{
			typeof(TInstance).GetPropertySetDelegateRef<TInstance, TValue>(propName)(ref instance, value);
		}

		public static TValue GetStructPropertyValue<TInstance, TValue>(this ref TInstance instance, string? propName) where TInstance : struct
		{
			return typeof(TInstance).GetPropertyGetDelegateRef<TInstance, TValue>(propName)(ref instance);
		}

		public static MethodInfo GetPropertyGetter(this Type type, string propName)
		{
			return type.GetProperty(propName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetGetMethod(nonPublic: true);
		}

		public static MethodInfo GetPropertySetter(this Type type, string propName)
		{
			return type.GetProperty(propName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetSetMethod(nonPublic: true);
		}

		public static GetDelegate<TReturn> GetPropertyGetDelegate<TReturn>(this Type type, string? propName)
		{
			if (PropertyGetDelegateCache.TryGetValue((type, propName, typeof(object), typeof(TReturn)), out Delegate value))
			{
				return (GetDelegate<TReturn>)value;
			}
			Delegate delegate2 = (PropertyGetDelegateCache[(type, propName, typeof(object), typeof(TReturn))] = type.GetPropertyCached(propName).CreateGetDelegate<TReturn>());
			return (GetDelegate<TReturn>)delegate2;
		}

		public static GetDelegateRef<TInstance, TReturn> GetPropertyGetDelegateRef<TInstance, TReturn>(this Type type, string? propName) where TInstance : struct
		{
			if (PropertyGetDelegateCache.TryGetValue((type, propName, typeof(TInstance), typeof(TReturn)), out Delegate value))
			{
				return (GetDelegateRef<TInstance, TReturn>)value;
			}
			Delegate delegate2 = (PropertyGetDelegateCache[(type, propName, typeof(TInstance), typeof(TReturn))] = type.GetPropertyCached(propName).CreateGetDelegate<TInstance, TReturn>());
			return (GetDelegateRef<TInstance, TReturn>)delegate2;
		}

		public static SetDelegate<TValue> GetPropertySetDelegate<TValue>(this Type type, string? propName)
		{
			if (PropertySetDelegateCache.TryGetValue((type, propName, typeof(object), typeof(TValue)), out Delegate value))
			{
				return (SetDelegate<TValue>)value;
			}
			Delegate delegate2 = (PropertySetDelegateCache[(type, propName, typeof(object), typeof(TValue))] = type.GetPropertyCached(propName).CreateSetDelegate<TValue>());
			return (SetDelegate<TValue>)delegate2;
		}

		private static SetDelegateRef<TInstance, TValue> GetPropertySetDelegateRef<TInstance, TValue>(this Type type, string? propName) where TInstance : struct
		{
			if (PropertySetDelegateCache.TryGetValue((type, propName, typeof(TInstance), typeof(TValue)), out Delegate value))
			{
				return (SetDelegateRef<TInstance, TValue>)value;
			}
			Delegate delegate2 = (PropertySetDelegateCache[(type, propName, typeof(TInstance), typeof(TValue))] = type.GetPropertyCached(propName).CreateSetDelegateRef<TInstance, TValue>());
			return (SetDelegateRef<TInstance, TValue>)delegate2;
		}

		public static MethodInfo GetMethodCached<T>(string? name)
		{
			return typeof(T).GetMethodCached(name);
		}

		public static MethodInfo GetMethodCached(this Type? T, string? name)
		{
			if (MethodCache.TryGetValue((T, name), out MethodInfo value))
			{
				return value;
			}
			return MethodCache[(T, name)] = T.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static MethodInfo GetMethodWithConstructedGenericParameter(this Type? T, string? name, Type? genericTypeDefinition)
		{
			string name2 = name;
			Type genericTypeDefinition2 = genericTypeDefinition;
			return T.GetMethods().First(delegate(MethodInfo method)
			{
				if (method.Name != name2)
				{
					return false;
				}
				Type parameterType = method.GetParameters().First().ParameterType;
				if (!parameterType.IsConstructedGenericType)
				{
					return false;
				}
				Type type = parameterType.GetGenericArguments().First();
				return parameterType == genericTypeDefinition2.MakeGenericType(type);
			});
		}

		public static MethodInfo GetMethodCached<T>(string? name, Type?[]? argumentTypes)
		{
			return typeof(T).GetMethodCached(name, argumentTypes);
		}

		public static MethodInfo GetMethodCached(this Type? T, string? name, Type?[]? argumentTypes)
		{
			(Type, string, long) key = (T, name, CombineHashCode(argumentTypes));
			if (OverloadedMethodCache.TryGetValue(key, out MethodInfo value))
			{
				return value;
			}
			return OverloadedMethodCache[key] = T.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, argumentTypes, null);
		}

		public static TReturn InvokeMethod<TReturn>(this object? instance, string? methodName)
		{
			return instance.InvokeMethod<TReturn>(methodName, null);
		}

		public static TReturn InvokeMethod<TReturn>(this Type? staticType, string? methodName)
		{
			return staticType.InvokeMethod<TReturn>(methodName, null);
		}

		public static void InvokeMethod(this object? instance, string? methodName)
		{
			instance.InvokeMethod<object>(methodName);
		}

		public static void InvokeMethod(this Type? staticType, string? methodName)
		{
			staticType.InvokeMethod<object>(methodName);
		}

		public static TReturn InvokeMethod<TReturn>(this object? instance, string? methodName, params object?[]? methodParams)
		{
			if (methodParams == null)
			{
				return (TReturn)instance.GetType().GetMethodDelegateCached(methodName).Invoke(instance, methodParams);
			}
			return (TReturn)instance.GetType().GetMethodDelegateCached(methodName, methodParams.Select((object x) => x.GetType()).ToArray()).Invoke(instance, methodParams);
		}

		public static TReturn InvokeMethod<TReturn>(this Type? staticType, string? methodName, params object?[]? methodParams)
		{
			if (methodParams == null)
			{
				return (TReturn)staticType.GetMethodDelegateCached(methodName).Invoke((object)null, methodParams);
			}
			return (TReturn)staticType.GetMethodDelegateCached(methodName, methodParams.Select((object x) => x.GetType()).ToArray()).Invoke((object)null, methodParams);
		}

		public static void InvokeMethod(this object? instance, string? methodName, params object?[]? methodParams)
		{
			instance.InvokeMethod<object>(methodName, methodParams);
		}

		public static void InvokeMethod(this Type? staticType, string? methodName, params object?[]? methodParams)
		{
			staticType.InvokeMethod<object>(methodName, methodParams);
		}

		public static FastReflectionDelegate GetMethodDelegateCached(this Type type, string? methodName)
		{
			if (MethodDelegateCache.TryGetValue((type, methodName), out FastReflectionDelegate value))
			{
				return value;
			}
			return MethodDelegateCache[(type, methodName)] = type.GetMethodCached(methodName).GenerateCallDelegate();
		}

		public static FastReflectionDelegate GetMethodDelegateCached(this Type type, string? methodName, Type[] argumentTypes)
		{
			(Type, string, long) key = (type, methodName, CombineHashCode(argumentTypes));
			if (OverloadedMethodDelegateCache.TryGetValue(key, out FastReflectionDelegate value))
			{
				return value;
			}
			return OverloadedMethodDelegateCache[key] = type.GetMethodCached(methodName, argumentTypes).GenerateCallDelegate();
		}

		public static ConstructorInfo GetConstructorCached<T>(Type?[]? argumentTypes)
		{
			return typeof(T).GetConstructorCached(argumentTypes);
		}

		public static ConstructorInfo GetConstructorCached(this Type? T, Type?[]? argumentTypes)
		{
			(Type, long) key = (T, CombineHashCode(argumentTypes));
			if (ConstructorCache.TryGetValue(key, out ConstructorInfo value))
			{
				return value;
			}
			return ConstructorCache[key] = T.GetConstructor(argumentTypes);
		}

		public static Type GetNestedType<T>(string? name)
		{
			return typeof(T).GetNestedTypeCached(name);
		}

		public static Type GetNestedTypeCached<T>(string? name)
		{
			return typeof(T).GetNestedTypeCached(name);
		}

		public static Type GetNestedTypeCached(this Type? T, string? name)
		{
			if (NestedTypeCache.TryGetValue((T, name), out Type value))
			{
				return value;
			}
			return NestedTypeCache[(T, name)] = T.GetNestedType(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static object Instantiate(this Type? type)
		{
			return Activator.CreateInstance(type, nonPublic: true);
		}

		public static object Instantiate(this Type? type, params object?[]? constructorArguments)
		{
			return type.GetConstructorCached(constructorArguments.Select((object x) => x.GetType()).ToArray()).Invoke(constructorArguments);
		}

		public static object InstantiateGeneric<TClass>(this Type? typeArgument)
		{
			return typeof(TClass).MakeGenericType(typeArgument).Instantiate();
		}

		public static object InstantiateGeneric<TClass>(this Type?[]? typeArgument)
		{
			return typeof(TClass).MakeGenericType(typeArgument).Instantiate();
		}

		public static IList InstantiateList(this Type? type)
		{
			return (IList)typeof(List<>).MakeGenericType(type).Instantiate();
		}

		private static FieldInfo ThrowIfFieldTypeCannotBeAssignedTo<T>(this FieldInfo fieldInfo)
		{
			if (!typeof(T).IsAssignableFrom(fieldInfo.FieldType))
			{
				throw new InvalidCastException($"{fieldInfo.Name} is of type {fieldInfo.FieldType}, it cannot be assigned to the type {typeof(T)}.");
			}
			return fieldInfo;
		}

		private static PropertyInfo ThrowIfPropertyTypeCannotBeAssignedTo<T>(this PropertyInfo propertyInfo)
		{
			if (!typeof(T).IsAssignableFrom(propertyInfo.PropertyType))
			{
				throw new InvalidCastException($"{propertyInfo.Name} is of type {propertyInfo.PropertyType}, it cannot be assigned to the type {typeof(T)}.");
			}
			return propertyInfo;
		}

		private static FieldInfo ThrowIfTCannotBeAssignedToField<T>(this FieldInfo fieldInfo)
		{
			if (!fieldInfo.FieldType.IsAssignableFrom(typeof(T)))
			{
				throw new InvalidCastException($"{fieldInfo.Name} is of type {fieldInfo.FieldType}. An instance of {typeof(T)} cannot be assigned to it.");
			}
			return fieldInfo;
		}

		private static FieldInfo ThrowIfFieldIsConst(this FieldInfo fieldInfo)
		{
			if (fieldInfo.IsLiteral && !fieldInfo.IsInitOnly)
			{
				throw new FieldAccessException("Unable to set constant field " + fieldInfo.Name + " of type " + fieldInfo.DeclaringType.FullName + ".");
			}
			return fieldInfo;
		}

		private static PropertyInfo ThrowIfTCannotBeAssignedToProperty<T>(this PropertyInfo propertyInfo)
		{
			if (!propertyInfo.PropertyType.IsAssignableFrom(typeof(T)))
			{
				throw new InvalidCastException($"{propertyInfo.Name} is of type {propertyInfo.PropertyType}. An instance of {typeof(T)} cannot be assigned to it.");
			}
			return propertyInfo;
		}

		private static PropertyInfo ThrowIfTNotEqualToPropertyType<T>(this PropertyInfo propertyInfo)
		{
			if (propertyInfo.PropertyType != typeof(T))
			{
				throw new InvalidCastException($"{propertyInfo.Name} is of type {propertyInfo.PropertyType}. {typeof(T)} is a different type.");
			}
			return propertyInfo;
		}

		private static GetDelegate<TReturn> CreateGetDelegate<TReturn>(this FieldInfo field)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00a6: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (field == null)
			{
				throw new ArgumentException("Field cannot be null.", "field");
			}
			field.ThrowIfFieldTypeCannotBeAssignedTo<TReturn>();
			if (field.IsLiteral && !field.IsInitOnly)
			{
				object value = field.GetValue(null);
				TReturn returnValue = ((value == null) ? default(TReturn) : ((TReturn)value));
				return Extensions.CastDelegate<GetDelegate<TReturn>>((Delegate)(Func<object, TReturn>)((object _) => returnValue));
			}
			DynamicMethodDefinition val = new DynamicMethodDefinition($"{field} Getter", typeof(TReturn), new Type[1] { typeof(object) });
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				if (!field.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
					if (field.DeclaringType.GetTypeInfo().IsValueType)
					{
						Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, field.DeclaringType);
					}
				}
				Extensions.Emit(iLProcessor, (!field.IsStatic) ? OpCodes.Ldfld : OpCodes.Ldsfld, field);
				if (field.FieldType.IsValueType && !typeof(TReturn).IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, field.FieldType);
				}
				iLProcessor.Emit(OpCodes.Ret);
				return (GetDelegate<TReturn>)val.Generate().CreateDelegate(typeof(GetDelegate<TReturn>));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static SetDelegate<TValue> CreateSetDelegate<TValue>(this FieldInfo field)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_007d: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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)
			if (field == null)
			{
				throw new ArgumentException("Field cannot be null.", "field");
			}
			field.ThrowIfTCannotBeAssignedToField<TValue>();
			field.ThrowIfFieldIsConst();
			DynamicMethodDefinition val = new DynamicMethodDefinition($"{field} Setter", typeof(void), new Type[2]
			{
				typeof(object),
				typeof(TValue)
			});
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				if (!field.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
				}
				iLProcessor.Emit(OpCodes.Ldarg_1);
				if (!field.FieldType.IsValueType && typeof(TValue).IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, typeof(TValue));
				}
				Extensions.Emit(iLProcessor, (!field.IsStatic) ? OpCodes.Stfld : OpCodes.Stsfld, field);
				iLProcessor.Emit(OpCodes.Ret);
				return (SetDelegate<TValue>)val.Generate().CreateDelegate(typeof(SetDelegate<TValue>));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static SetDelegateRef<TInstance, TValue> CreateSetDelegateRef<TInstance, TValue>(this FieldInfo field) where TInstance : struct
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0082: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			if (field == null)
			{
				throw new ArgumentException("Field cannot be null.", "field");
			}
			field.ThrowIfTCannotBeAssignedToField<TValue>();
			field.ThrowIfFieldIsConst();
			DynamicMethodDefinition val = new DynamicMethodDefinition($"{field} SetterByRef", typeof(void), new Type[2]
			{
				typeof(TInstance).MakeByRefType(),
				typeof(TValue)
			});
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				if (!field.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
				}
				iLProcessor.Emit(OpCodes.Ldarg_1);
				if (!field.FieldType.IsValueType && typeof(TValue).IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, typeof(TValue));
				}
				Extensions.Emit(iLProcessor, (!field.IsStatic) ? OpCodes.Stfld : OpCodes.Stsfld, field);
				iLProcessor.Emit(OpCodes.Ret);
				return (SetDelegateRef<TInstance, TValue>)val.Generate().CreateDelegate(typeof(SetDelegateRef<TInstance, TValue>));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static GetDelegate<TReturn> CreateGetDelegate<TReturn>(this PropertyInfo property)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0071: 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_00ac: 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)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			property.ThrowIfPropertyTypeCannotBeAssignedTo<TReturn>();
			DynamicMethodDefinition val = new DynamicMethodDefinition($"{property} Getter", typeof(TReturn), new Type[1] { typeof(object) });
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				MethodInfo getMethod = property.GetGetMethod(nonPublic: true);
				if (!getMethod.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
				}
				Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)getMethod);
				if (property.PropertyType.IsValueType && !typeof(TReturn).IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, property.PropertyType);
				}
				iLProcessor.Emit(OpCodes.Ret);
				return (GetDelegate<TReturn>)val.Generate().CreateDelegate(typeof(GetDelegate<TReturn>));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static GetDelegateRef<TInstance, TReturn> CreateGetDelegate<TInstance, TReturn>(this PropertyInfo property) where TInstance : struct
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			property.ThrowIfPropertyTypeCannotBeAssignedTo<TReturn>();
			DynamicMethodDefinition val = new DynamicMethodDefinition($"{property} Getter", typeof(TReturn), new Type[1] { typeof(TInstance).MakeByRefType() });
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				MethodInfo getMethod = property.GetGetMethod(nonPublic: true);
				if (!getMethod.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
				}
				Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)getMethod);
				if (property.PropertyType.IsValueType && !typeof(TReturn).IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, property.PropertyType);
				}
				iLProcessor.Emit(OpCodes.Ret);
				return (GetDelegateRef<TInstance, TReturn>)val.Generate().CreateDelegate(typeof(GetDelegateRef<TInstance, TReturn>));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static SetDelegate<TValue> CreateSetDelegate<TValue>(this PropertyInfo property)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_007e: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			property.ThrowIfTCannotBeAssignedToProperty<TValue>();
			DynamicMethodDefinition val = new DynamicMethodDefinition($"{property} Setter", typeof(void), new Type[2]
			{
				typeof(object),
				typeof(TValue)
			});
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				MethodInfo setMethod = property.GetSetMethod(nonPublic: true);
				if (!setMethod.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
				}
				iLProcessor.Emit(OpCodes.Ldarg_1);
				if (!property.PropertyType.IsValueType && typeof(TValue).IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, typeof(TValue));
				}
				Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)setMethod);
				iLProcessor.Emit(OpCodes.Ret);
				return (SetDelegate<TValue>)val.Generate().CreateDelegate(typeof(SetDelegate<TValue>));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static SetDelegateRef<TInstance, TValue> CreateSetDelegateRef<TInstance, TValue>(this PropertyInfo property) where TInstance : struct
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0083: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			property.ThrowIfTCannotBeAssignedToProperty<TValue>();
			DynamicMethodDefinition val = new DynamicMethodDefinition($"{property} SetterByRef", typeof(void), new Type[2]
			{
				typeof(TInstance).MakeByRefType(),
				typeof(TValue)
			});
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				MethodInfo setMethod = property.GetSetMethod(nonPublic: true);
				if (!setMethod.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
				}
				iLProcessor.Emit(OpCodes.Ldarg_1);
				if (!property.PropertyType.IsValueType && typeof(TValue).IsValueType)
				{
					Extensions.Emit(iLProcessor, OpCodes.Box, typeof(TValue));
				}
				Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)setMethod);
				iLProcessor.Emit(OpCodes.Ret);
				return (SetDelegateRef<TInstance, TValue>)val.Generate().CreateDelegate(typeof(SetDelegateRef<TInstance, TValue>));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static FastReflectionDelegate GenerateCallDelegate(this MethodInfo method)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0075: 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_016d: 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_00e1: 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_0126: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			if (method == null)
			{
				throw new ArgumentException("Method cannot be null.", "method");
			}
			DynamicMethodDefinition val = new DynamicMethodDefinition("CallDelegate<" + method.Name + ">", typeof(object), new Type[2]
			{
				typeof(object),
				typeof(object[])
			});
			try
			{
				ILProcessor iLProcessor = val.GetILProcessor();
				ParameterInfo[] parameters = method.GetParameters();
				if (!method.IsStatic)
				{
					iLProcessor.Emit(OpCodes.Ldarg_0);
					if (method.DeclaringType.GetTypeInfo().IsValueType)
					{
						Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, method.DeclaringType);
					}
				}
				for (int i = 0; i < parameters.Length; i++)
				{
					Type type = parameters[i].ParameterType;
					bool isByRef = type.IsByRef;
					if (isByRef)
					{
						type = type.GetElementType();
					}
					bool isValueType = type.GetTypeInfo().IsValueType;
					if (isByRef && isValueType)
					{
						iLProcessor.Emit(OpCodes.Ldarg_1);
						iLProcessor.EmitFast_Ldc_I4(i);
					}
					iLProcessor.Emit(OpCodes.Ldarg_1);
					iLProcessor.EmitFast_Ldc_I4(i);
					if (isByRef && !isValueType)
					{
						Extensions.Emit(iLProcessor, OpCodes.Ldelema, typeof(object));
						continue;
					}
					iLProcessor.Emit(OpCodes.Ldelem_Ref);
					if (isValueType)
					{
						Extensions.Emit(iLProcessor, (!isByRef) ? OpCodes.Unbox_Any : OpCodes.Unbox, type);
					}
				}
				if (method.IsFinal || !method.IsVirtual)
				{
					Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)method);
				}
				else
				{
					Extensions.Emit(iLProcessor, OpCodes.Callvirt, (MethodBase)method);
				}
				Type type2 = (method.IsConstructor ? method.DeclaringType : method.ReturnType);
				if (type2 != typeof(void))
				{
					if (type2.GetTypeInfo().IsValueType)
					{
						Extensions.Emit(iLProcessor, OpCodes.Box, type2);
					}
				}
				else
				{
					iLProcessor.Emit(OpCodes.Ldnull);
				}
				iLProcessor.Emit(OpCodes.Ret);
				return (FastReflectionDelegate)val.Generate().CreateDelegate(typeof(FastReflectionDelegate));
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void EmitFast_Ldc_I4(this ILProcessor? il, int value)
		{
			//IL_0033: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00c9: 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)
			switch (value)
			{
			case -1:
				il.Emit(OpCodes.Ldc_I4_M1);
				return;
			case 0:
				il.Emit(OpCodes.Ldc_I4_0);
				return;
			case 1:
				il.Emit(OpCodes.Ldc_I4_1);
				return;
			case 2:
				il.Emit(OpCodes.Ldc_I4_2);
				return;
			case 3:
				il.Emit(OpCodes.Ldc_I4_3);
				return;
			case 4:
				il.Emit(OpCodes.Ldc_I4_4);
				return;
			case 5:
				il.Emit(OpCodes.Ldc_I4_5);
				return;
			case 6:
				il.Emit(OpCodes.Ldc_I4_6);
				return;
			case 7:
				il.Emit(OpCodes.Ldc_I4_7);
				return;
			case 8:
				il.Emit(OpCodes.Ldc_I4_8);
				return;
			}
			if (value > -129 && value < 128)
			{
				il.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
			}
			else
			{
				il.Emit(OpCodes.Ldc_I4, value);
			}
		}

		public static byte ReadLocalIndex(OpCode opCode, object? operand)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0045: 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_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_0061: 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_0070: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if (opCode == OpCodes.Ldloc_0 || opCode == OpCodes.Stloc_0)
			{
				return 0;
			}
			if (opCode == OpCodes.Ldloc_1 || opCode == OpCodes.Stloc_1)
			{
				return 1;
			}
			if (opCode == OpCodes.Ldloc_2 || opCode == OpCodes.Stloc_2)
			{
				return 2;
			}
			if (opCode == OpCodes.Ldloc_3 || opCode == OpCodes.Stloc_3)
			{
				return 3;
			}
			if (opCode == OpCodes.Ldloc_S || opCode == OpCodes.Stloc_S)
			{
				return (byte)operand;
			}
			throw new Exception($"Could not read index for opcode and operand: {opCode} - {operand}");
		}

		public static bool GetTypesSafe(Assembly assembly, out Type[] assemblyTypes)
		{
			try
			{
				assemblyTypes = assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				assemblyTypes = ex.Types.Where((Type t) => t != null).ToArray();
				return false;
			}
			return true;
		}

		public static FieldInfo GetNestedField(Type type, string fieldName)
		{
			Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < nestedTypes.Length; i++)
			{
				FieldInfo field = nestedTypes[i].GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
			}
			return null;
		}

		public static MethodInfo GetNestedMethod(Type type, string methodName)
		{
			Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < nestedTypes.Length; i++)
			{
				MethodInfo method = nestedTypes[i].GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					return method;
				}
			}
			return null;
		}

		public static void LogCursorOpcodes(ILCursor cursor)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			int index = cursor.Index;
			cursor.Goto(0, (MoveType)0, false);
			while (cursor.Next != null)
			{
				Debug.Log((object)cursor.Next.OpCode);
				int index2 = cursor.Index;
				cursor.Index = index2 + 1;
				cursor.Goto(cursor.Index, (MoveType)0, false);
			}
			cursor.Index = index;
		}

		public static MethodInfo GetGenericMethod(Type type, string name, Type[] parameters)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!(methodInfo.Name == name))
				{
					continue;
				}
				ParameterInfo[] parameters2 = methodInfo.GetParameters();
				if (parameters2.Length != parameters.Length)
				{
					continue;
				}
				bool flag = true;
				for (int j = 0; j < parameters.Length; j++)
				{
					if (parameters2[j].ParameterType.Name != parameters[j].Name)
					{
						flag = false;
						break;
					}
				}
				if (flag)
				{
					return methodInfo;
				}
			}
			return null;
		}

		public static bool IsSameOrSubclassOf<OtherType>(this Type type)
		{
			if (!(type == typeof(OtherType)))
			{
				return type.IsSubclassOf(typeof(OtherType));
			}
			return true;
		}
	}
	internal class StringUtils
	{
		internal static void ThrowIfStringIsNullOrWhiteSpace(string stringToCheck, string paramName)
		{
			if (string.IsNullOrWhiteSpace(stringToCheck))
			{
				throw new ArgumentNullException(paramName);
			}
		}
	}
	public static class SystemInitializerInjector
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_ExecuteStatic <0>__SystemInitializerInjectDependencies;
		}

		private static readonly Dictionary<MethodInfo, HashSet<Type>> _dependenciesToInject = new Dictionary<MethodInfo, HashSet<Type>>();

		private static bool _appliedHooks = false;

		private static void applyHooksIfNeeded()
		{
			//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_0029: Expected O, but got Unknown
			if (!_appliedHooks)
			{
				_appliedHooks = true;
				object obj = <>O.<0>__SystemInitializerInjectDependencies;
				if (obj == null)
				{
					hook_ExecuteStatic val = SystemInitializerInjectDependencies;
					<>O.<0>__SystemInitializerInjectDependencies = val;
					obj = (object)val;
				}
				SystemInitializerAttribute.ExecuteStatic += (hook_ExecuteStatic)obj;
			}
		}

		private static void SystemInitializerInjectDependencies(orig_ExecuteStatic orig)
		{
			orig.Invoke();
			foreach (SystemInitializerAttribute initializerAttribute in SystemInitializerAttribute.initializerAttributes)
			{
				injectDependencies(initializerAttribute);
			}
		}

		private static void injectDependencies(SystemInitializerAttribute attribute)
		{
			SystemInitializerAttribute attribute2 = attribute;
			if (((SearchableAttribute)attribute2).target is MethodInfo key && _dependenciesToInject.TryGetValue(key, out HashSet<Type> value))
			{
				value.RemoveWhere((Type t) => attribute2.dependencies.Contains(t));
				if (value.Count != 0)
				{
					int num = attribute2.dependencies.Length;
					Array.Resize(ref attribute2.dependencies, num + value.Count);
					value.CopyTo(attribute2.dependencies, num);
				}
			}
		}

		public static void InjectDependencies<T>(params Type[] dependenciesToInject)
		{
			ThrowIfSystemInitializerExecuted();
			Type typeFromHandle = typeof(T);
			foreach (Type dependency in dependenciesToInject)
			{
				InjectDependencyInternal(typeFromHandle, dependency);
			}
		}

		public static void InjectDependency<T>(Type dependencyToInject)
		{
			ThrowIfSystemInitializerExecuted();
			InjectDependencyInternal(typeof(T), dependencyToInject);
		}

		public static void InjectDependencies(Type typeToInject, params Type[] dependenciesToInject)
		{
			ThrowIfSystemInitializerExecuted();
			foreach (Type dependency in dependenciesToInject)
			{
				InjectDependencyInternal(typeToInject, dependency);
			}
		}

		public static void InjectDependency(Type typeToInject, Type dependencyToInject)
		{
			ThrowIfSystemInitializerExecuted();
			InjectDependencyInternal(typeToInject, dependencyToInject);
		}

		private static void InjectDependencyInternal(Type typeToInject, Type dependency)
		{
			if ((object)typeToInject == null)
			{
				throw new ArgumentNullException("typeToInject");
			}
			if ((object)dependency == null)
			{
				throw new ArgumentNullException("dependency");
			}
			foreach (MethodInfo allSystemInitializerMethod in GetAllSystemInitializerMethods(typeToInject))
			{
				InjectDependencyInternal(allSystemInitializerMethod, dependency);
			}
		}

		private static IEnumerable<MethodInfo> GetAllSystemInitializerMethods(Type type)
		{
			return from m in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where ((MemberInfo)m).GetCustomAttribute<SystemInitializerAttribute>() != null
				select m;
		}

		public static void InjectDependency(MethodInfo initializerMethod, Type dependency)
		{
			ThrowIfSystemInitializerExecuted();
			InjectDependencyInternal(initializerMethod, dependency);
		}

		public static void InjectDependencies(MethodInfo initializerMethod, params Type[] dependencies)
		{
			ThrowIfSystemInitializerExecuted();
			foreach (Type dependency in dependencies)
			{
				InjectDependencyInternal(initializerMethod, dependency);
			}
		}

		private static void InjectDependencyInternal(MethodInfo initializerMethod, Type dependency)
		{
			if ((object)dependency == null)
			{
				throw new ArgumentNullException("dependency");
			}
			if ((object)initializerMethod == null)
			{
				throw new ArgumentNullException("initializerMethod");
			}
			if (((MemberInfo)initializerMethod).GetCustomAttribute<SystemInitializerAttribute>() == null)
			{
				R2API.Logger.LogWarning((object)("Not injecting SystemInitializer dependency " + dependency.FullName + " into " + initializerMethod.DeclaringType.FullName + "." + initializerMethod.Name + ": Method is missing SystemInitializerAttribute"));
				return;
			}
			if (!_dependenciesToInject.TryGetValue(initializerMethod, out HashSet<Type> value))
			{
				_dependenciesToInject.Add(initializerMethod, value = new HashSet<Type>());
			}
			if (value.Add(dependency))
			{
				applyHooksIfNeeded();
				R2API.Logger.LogDebug((object)("Injecting SystemInitializer dependency " + dependency.FullName + " into " + initializerMethod.DeclaringType.FullName + "." + initializerMethod.Name));
			}
		}

		private static void ThrowIfSystemInitializerExecuted()
		{
			if (SystemInitializerAttribute.hasExecuted)
			{
				throw new InvalidOperationException("Cannot inject dependencies when SystemInitializer has already been executed");
			}
		}
	}
}