Decompiled source of CommonAPI v1.6.5

plugins/CommonAPI.dll

Decompiled 3 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CommonAPI.Nebula;
using CommonAPI.Patches;
using CommonAPI.ShotScene;
using CommonAPI.ShotScene.Patches;
using CommonAPI.Systems;
using CommonAPI.Systems.ModLocalization;
using CommonAPI.Systems.ModLocalization.Patch;
using CommonAPI.Systems.Patches;
using CommonAPI.Systems.UI;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.Utils;
using NebulaAPI;
using NebulaAPI.Interfaces;
using NebulaAPI.Networking;
using NebulaAPI.Packets;
using PowerNetworkStructures;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.PostProcessing;
using UnityEngine.UI;
using crecheng.DSPModSave;
using xiaoye97;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("1.6.5.1")]
[assembly: AssemblyInformationalVersion("1.6.5.1+d557386")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CommonAPI")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A modding library for Dyson Sphere Program. Provides multiple features to make adding custom content to DSP easier.")]
[assembly: AssemblyProduct("CommonAPI")]
[assembly: AssemblyTitle("CommonAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.6.5.0")]
[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;
		}
	}
}
[GeneratedCode("Nerdbank.GitVersioning.Tasks", "3.6.133.12845")]
[ExcludeFromCodeCoverage]
internal static class ThisAssembly
{
	internal const string AssemblyConfiguration = "Release";

	internal const string AssemblyFileVersion = "1.6.5.1";

	internal const string AssemblyInformationalVersion = "1.6.5.1+d557386";

	internal const string AssemblyName = "CommonAPI";

	internal const string AssemblyTitle = "CommonAPI";

	internal const string AssemblyVersion = "1.6.5.0";

	internal static readonly DateTime GitCommitDate = new DateTime(638438744160000000L, DateTimeKind.Utc);

	internal const string GitCommitId = "d557386b98f0624ede6b809bb680a66eb6bfc3a3";

	internal const bool IsPrerelease = false;

	internal const bool IsPublicRelease = true;

	internal const string RootNamespace = "CommonAPI";
}
namespace CommonAPI
{
	[BepInPlugin("dsp.common-api.CommonAPI", "DSP Common API", "1.6.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class CommonAPIPlugin : BaseUnityPlugin, IModCanSave
	{
		public const string ID = "CommonAPI";

		public const string GUID = "dsp.common-api.CommonAPI";

		public const string DISPNAME = "DSP Common API";

		public const string VERSION = "1.6.5.0";

		internal static Harmony harmony;

		internal static ICommonLogger logger;

		internal static ResourceData resource;

		internal static Action onIntoOtherSave;

		internal static SubmoduleHandler submoduleHandler;

		public static Dictionary<string, Registry> registries = new Dictionary<string, Registry>();

		public static readonly Version buildFor = GameVersionUtil.GetVersion(0, 10, 28, 21308);

		public static bool iconShotMenuEnabled;

		public static KeyCode openIconShotMenuButton;

		internal static ConfigEntry<string> forceLoaded;

		private void Awake()
		{
			//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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			logger = new LoggerWrapper(((BaseUnityPlugin)this).Logger);
			CommonLogger.SetLogger(logger);
			UnityThread.initUnityThread();
			iconShotMenuEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "enableIconShotMenu", false, "Is Icon shot menu enabled. It is useful for mod developers, because it allows to create consistent icons.").Value;
			openIconShotMenuButton = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "OpenIconShotMenuButton", (KeyCode)287, "Button used to open special Icon shot menu. It is useful for mod developers, because it allows to create consistent icons.").Value;
			harmony = new Harmony("dsp.common-api.CommonAPI");
			PluginScanner pluginScanner = new PluginScanner();
			submoduleHandler = new SubmoduleHandler(buildFor, ((BaseUnityPlugin)this).Logger);
			submoduleHandler.LoadRequested(pluginScanner);
			pluginScanner.ScanPlugins();
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			resource = new ResourceData("CommonAPI", "CommonAPI", directoryName);
			resource.LoadAssetBundle("commonapi");
			LoadSaveOnLoad.Init();
			harmony.PatchAll(typeof(VFPreloadPatch));
			CheckModuleForceLoad();
			logger.LogInfo("Common API is initialized!");
		}

		private void Update()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (iconShotMenuEnabled && DSPGame.MenuDemoLoaded && Input.GetKeyDown(openIconShotMenuButton))
			{
				GeneratorSceneController.LoadIconGeneratorScene();
			}
		}

		internal static void CheckIfUsedOnRightGameVersion()
		{
			//IL_0000: 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)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Version gameVersion = GameConfig.gameVersion;
			if (!(buildFor == gameVersion))
			{
				ICommonLogger commonLogger = logger;
				string[] obj = new string[5] { "This version of CommonAPI was built for build id \"", null, null, null, null };
				Version val = buildFor;
				obj[1] = ((Version)(ref val)).ToFullString();
				obj[2] = "\", you are running \"";
				obj[3] = ((Version)(ref gameVersion)).ToFullString();
				obj[4] = "\".";
				commonLogger.LogWarning(string.Concat(obj));
				logger.LogWarning("Should any problems arise, please check for a new version before reporting issues.");
			}
		}

		public static bool IsSubmoduleLoaded(string submodule)
		{
			return submoduleHandler.IsLoaded(submodule);
		}

		public static bool TryLoadModule(Type moduleType)
		{
			return submoduleHandler.RequestModuleLoad(moduleType);
		}

		internal static T GetModuleInstance<T>() where T : BaseSubmodule
		{
			return submoduleHandler.GetModuleInstance<T>();
		}

		public static void LoadModules(params Type[] moduleTypes)
		{
			LoadModules((IEnumerable<Type>)moduleTypes);
		}

		private void CheckModuleForceLoad()
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			List<Type> allSubmodules = submoduleHandler.allModules.Keys.ToList();
			string[] acceptableValues = CollectionExtensions.AddItem<string>(allSubmodules.Select((Type type) => type.Name), "all").ToArray();
			forceLoaded = ((BaseUnityPlugin)this).Config.Bind<string>("Debug", "ForceModuleLoad", "", new ConfigDescription("Manually force certain modules to be loaded. Do not use unless you know what you are doing.", (AcceptableValueBase)(object)new AcceptableValueOptionsList(acceptableValues), Array.Empty<object>()));
			if (string.IsNullOrWhiteSpace(forceLoaded.Value))
			{
				return;
			}
			if (forceLoaded.Value == "all")
			{
				LoadModules(allSubmodules);
				return;
			}
			IEnumerable<Type> forceLoadTypes = from name in forceLoaded.Value.Split(new char[1] { ',' })
				select allSubmodules.Find((Type type) => type.Name.Equals(name));
			LoadModules(forceLoadTypes);
		}

		private static void LoadModules(IEnumerable<Type> forceLoadTypes)
		{
			foreach (Type forceLoadType in forceLoadTypes)
			{
				if (!(forceLoadType == null))
				{
					TryLoadModule(forceLoadType);
				}
			}
		}

		public void Import(BinaryReader r)
		{
			int num = r.ReadInt32();
			while (r.ReadByte() != 0)
			{
				string key = r.ReadString();
				if (registries.ContainsKey(key))
				{
					r.ReadInt64();
					registries[key].Import(r);
				}
				else
				{
					long num2 = r.ReadInt64();
					r.ReadBytes((int)num2);
				}
			}
			StarExtensionSystem.InitOnLoad();
			StarExtensionSystem.Import(r);
			PlanetExtensionSystem.InitOnLoad();
			PlanetExtensionSystem.Import(r);
			if (num > 0)
			{
				ModProtoHistory.Import(r);
			}
		}

		public void Export(BinaryWriter w)
		{
			w.Write(1);
			foreach (KeyValuePair<string, Registry> registry in registries)
			{
				w.Write((byte)1);
				w.Write(registry.Key);
				MemoryStream memoryStream = new MemoryStream();
				BinaryWriter w2 = new BinaryWriter(memoryStream);
				registry.Value.Export(w2);
				w.Write(memoryStream.Length);
				w.Write(memoryStream.ToArray());
			}
			w.Write((byte)0);
			StarExtensionSystem.Export(w);
			PlanetExtensionSystem.Export(w);
			ModProtoHistory.Export(w);
		}

		public void IntoOtherSave()
		{
			onIntoOtherSave?.Invoke();
			StarExtensionSystem.InitOnLoad();
			PlanetExtensionSystem.InitOnLoad();
		}
	}
	[HarmonyPatch]
	public static class VFPreloadPatch
	{
		[HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")]
		[HarmonyPostfix]
		public static void OnMainMenuOpen()
		{
			CommonAPIPlugin.CheckIfUsedOnRightGameVersion();
			LoadSaveOnLoad.LoadSave();
		}
	}
	[BepInPlugin("dsp.common-tools.common-api-nebula-compat", "Common API Nebula Compatibility", "1.6.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class NebulaCompatPlugin : BaseUnityPlugin, IMultiplayerMod
	{
		public const string ID = "common-api-nebula-compat";

		public const string GUID = "dsp.common-tools.common-api-nebula-compat";

		public const string NAME = "Common API Nebula Compatibility";

		public string Version => "1.6.5.0";

		private void Start()
		{
			if (CommonAPIPlugin.IsSubmoduleLoaded("PlanetExtensionSystem"))
			{
				NebulaModAPI.OnPlanetLoadRequest = (Action<int>)Delegate.Combine(NebulaModAPI.OnPlanetLoadRequest, (Action<int>)delegate(int planetId)
				{
					NebulaModAPI.MultiplayerSession.Network.SendPacket<PlanetSystemLoadRequest>(new PlanetSystemLoadRequest(planetId));
				});
			}
			if (CommonAPIPlugin.IsSubmoduleLoaded("StarExtensionSystem"))
			{
				NebulaModAPI.OnStarLoadRequest = (Action<int>)Delegate.Combine(NebulaModAPI.OnStarLoadRequest, (Action<int>)delegate(int starIndex)
				{
					NebulaModAPI.MultiplayerSession.Network.SendPacket<StarExtensionLoadRequest>(new StarExtensionLoadRequest(starIndex));
				});
			}
			NebulaModAPI.RegisterPackets(Assembly.GetExecutingAssembly());
			CommonAPIPlugin.onIntoOtherSave = CheckNebulaInIntoOtherSave;
			PlanetExtensionSystem.onInitNewPlanet = HandleNebulaPacket;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Common API Nebula Compatibility ready!");
		}

		public static void CheckNebulaInIntoOtherSave()
		{
			if (!NebulaModAPI.IsMultiplayerActive || NebulaModAPI.MultiplayerSession.LocalPlayer.IsHost)
			{
				return;
			}
			foreach (KeyValuePair<string, Registry> registry in CommonAPIPlugin.registries)
			{
				registry.Value.InitUnitMigrationMap();
			}
		}

		public static void HandleNebulaPacket(PlanetData planet)
		{
			if (!NebulaModAPI.IsMultiplayerActive || NebulaModAPI.MultiplayerSession.LocalPlayer.IsHost || !PlanetExtensionSystem.pendingData.TryGetValue(planet.id, out var value))
			{
				return;
			}
			PlanetExtensionSystem.pendingData.Remove(planet.id);
			IReaderProvider binaryReader = NebulaModAPI.GetBinaryReader(value);
			try
			{
				for (int i = 1; i < PlanetExtensionSystem.registry.data.Count; i++)
				{
					PlanetExtensionStorage planetExtensionStorage = PlanetExtensionSystem.extensions[i];
					planetExtensionStorage.GetExtension(planet.factory).Import(binaryReader.BinaryReader);
				}
			}
			finally
			{
				((IDisposable)binaryReader)?.Dispose();
			}
		}

		public bool CheckVersion(string hostVersion, string clientVersion)
		{
			return hostVersion.Equals(clientVersion);
		}
	}
	public interface IItem
	{
		int GetItemId();

		int GetCount();

		int GetMaxStackSize();
	}
	public interface IStorage
	{
		int size { get; }

		bool changed { get; set; }

		IItem GetAt(int index);

		void SetAt(int index, IItem stack);
	}
	public class UICustomGrid : ManualBehaviour
	{
		public int colCount = 10;

		public int rowCount = 5;

		public RectTransform rectTrans;

		public RectTransform contentRect;

		public Image bgImage;

		public RawImage iconImage;

		public Text prefabNumText;

		private Material iconImageMat;

		private Material bgImageMat;

		private uint[] iconIndexArray;

		private uint[] stateArray;

		private ComputeBuffer iconIndexBuffer;

		private ComputeBuffer stateBuffer;

		private Text[] numTexts;

		private int[] itemCounts;

		protected IStorage storage;

		private StringBuilder strb = new StringBuilder("      ", 6);

		private static readonly int buffer = Shader.PropertyToID("_StateBuffer");

		private static readonly int indexBuffer = Shader.PropertyToID("_IndexBuffer");

		private static readonly int bans = Shader.PropertyToID("_Bans");

		private static readonly int gridProp = Shader.PropertyToID("_Grid");

		private static readonly int rect = Shader.PropertyToID("_Rect");

		public override void _OnCreate()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			numTexts = (Text[])(object)new Text[400];
			itemCounts = new int[400];
			iconIndexArray = new uint[1024];
			iconIndexBuffer = new ComputeBuffer(iconIndexArray.Length, 4);
			stateArray = new uint[1024];
			stateBuffer = new ComputeBuffer(stateArray.Length, 4);
			if ((Object)(object)bgImage != (Object)null)
			{
				bgImageMat = ProtoRegistry.CreateMaterial("UI Ex/Storage Bg", "storage-bg", "#FFFFFFFF", null, new string[0]);
				bgImageMat.SetBuffer(buffer, stateBuffer);
				((Graphic)bgImage).material = bgImageMat;
			}
			if ((Object)(object)iconImage != (Object)null)
			{
				iconImageMat = ProtoRegistry.CreateMaterial("UI Ex/Storage Icons", "storage-icons", "#FFFFFFFF", null, new string[0]);
				iconImageMat.SetBuffer(indexBuffer, iconIndexBuffer);
				((Graphic)iconImage).material = iconImageMat;
			}
		}

		public override void _OnDestroy()
		{
			if ((Object)(object)bgImage != (Object)null)
			{
				Object.Destroy((Object)(object)bgImageMat);
			}
			if ((Object)(object)iconImage != (Object)null)
			{
				Object.Destroy((Object)(object)iconImageMat);
			}
			iconIndexBuffer.Release();
			stateBuffer.Release();
			numTexts = null;
			itemCounts = null;
			bgImageMat = null;
			iconImageMat = null;
			iconIndexArray = null;
			iconIndexBuffer = null;
			stateArray = null;
			stateBuffer = null;
		}

		public override bool _OnInit()
		{
			if ((Object)(object)iconImage != (Object)null)
			{
				iconImage.texture = (Texture)(object)GameMain.iconSet.texture;
			}
			return true;
		}

		public override void _OnFree()
		{
			SetStorage(null);
		}

		public override void _OnClose()
		{
			OnContentMouseExit(null);
			SetStorage(null);
		}

		public override void _OnUpdate()
		{
			if (storage != null && storage.changed)
			{
				OnStorageContentChanged();
				storage.changed = false;
			}
		}

		protected int GetItemId(int gridX, int gridY)
		{
			int result = 0;
			if (gridX >= 0 && gridY >= 0)
			{
				int index = gridX + gridY * colCount;
				result = storage.GetAt(index).GetItemId();
			}
			return result;
		}

		private void OnApplicationFocus(bool focus)
		{
			if (!focus)
			{
				OnContentMouseExit(null);
			}
		}

		public void SetStorage(IStorage _storage)
		{
			if (_storage != storage)
			{
				storage = _storage;
				OnStorageDataChanged();
			}
		}

		protected void SetRectSize()
		{
			//IL_002d: 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_008e: 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)
			if (!((Object)(object)rectTrans == (Object)null))
			{
				rectTrans.sizeDelta = new Vector2((float)(colCount * 50 + 4), (float)(rowCount * 50 + 4));
				Vector4 val = default(Vector4);
				((Vector4)(ref val))..ctor((float)colCount, (float)rowCount, 0.04f, 0.04f);
				if ((Object)(object)bgImageMat != (Object)null)
				{
					bgImageMat.SetVector(gridProp, val);
				}
				if ((Object)(object)iconImageMat != (Object)null)
				{
					iconImageMat.SetVector(gridProp, val);
					Vector4 val2 = default(Vector4);
					((Vector4)(ref val2))..ctor(0.1f, 0.1f, 1.25f, 1.25f);
					iconImageMat.SetVector(rect, val2);
				}
			}
		}

		protected void CreateGridGraphic(int index)
		{
			if ((Object)(object)numTexts[index] == (Object)null)
			{
				numTexts[index] = Object.Instantiate<Text>(prefabNumText, (Transform)(object)rectTrans);
			}
			RepositionGridGraphic(index);
		}

		protected void SetGridGraphic(int index, bool newState)
		{
			if (((Component)numTexts[index]).gameObject.activeSelf != newState)
			{
				((Component)numTexts[index]).gameObject.SetActive(newState);
			}
			if (!newState)
			{
				numTexts[index].text = "";
				itemCounts[index] = 0;
				stateArray[index] = 0u;
				iconIndexArray[index] = 0u;
			}
		}

		protected void DeactiveAllGridGraphics()
		{
			for (int i = 0; i < 400; i++)
			{
				if ((Object)(object)numTexts[i] != (Object)null && ((Component)numTexts[i]).gameObject.activeSelf)
				{
					numTexts[i].text = "";
					((Component)numTexts[i]).gameObject.SetActive(false);
				}
			}
			Array.Clear(itemCounts, 0, 400);
			Array.Clear(stateArray, 0, stateArray.Length);
			Array.Clear(iconIndexArray, 0, iconIndexArray.Length);
		}

		protected void RepositionGridGraphic(int index)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			int num = index % colCount;
			int num2 = index / colCount;
			((Graphic)numTexts[index]).rectTransform.anchoredPosition = new Vector2((float)(num * 50), (float)(num2 * -50 - 34));
		}

		public void OnStorageDataChanged()
		{
			if ((Object)(object)bgImageMat != (Object)null)
			{
				Array.Clear(stateArray, 0, stateArray.Length);
				stateBuffer.SetData((Array)stateArray);
				bgImageMat.SetBuffer(buffer, stateBuffer);
			}
			if ((Object)(object)iconImageMat != (Object)null)
			{
				Array.Clear(iconIndexArray, 0, iconIndexArray.Length);
				iconIndexBuffer.SetData((Array)iconIndexArray);
				iconImageMat.SetBuffer(indexBuffer, iconIndexBuffer);
			}
			OnStorageSizeChanged();
		}

		public void OnStorageSizeChanged()
		{
			if (storage == null)
			{
				rowCount = 1;
			}
			else
			{
				rowCount = (storage.size - 1) / colCount + 1;
			}
			SetRectSize();
			DeactiveAllGridGraphics();
			for (int i = 0; i < colCount * rowCount; i++)
			{
				CreateGridGraphic(i);
			}
			OnStorageContentChanged();
		}

		public void OnStorageContentChanged()
		{
			if (storage == null)
			{
				return;
			}
			if ((storage.size - 1) / colCount + 1 != rowCount)
			{
				OnStorageSizeChanged();
			}
			for (int i = 0; i < storage.size; i++)
			{
				IItem at = storage.GetAt(i);
				if (at.GetItemId() > 0)
				{
					SetGridGraphic(i, newState: true);
					iconIndexArray[i] = GameMain.iconSet.itemIconIndex[at.GetItemId()];
					stateArray[i] = 1u;
					bool flag = itemCounts[i] != at.GetCount();
					itemCounts[i] = at.GetCount();
					if (flag)
					{
						if (at.GetMaxStackSize() > 1)
						{
							StringBuilderUtility.WriteKMG(strb, 5, (long)at.GetCount(), false);
							numTexts[i].text = strb.ToString();
						}
						else
						{
							numTexts[i].text = "";
						}
					}
				}
				else
				{
					iconIndexArray[i] = 0u;
					stateArray[i] = 0u;
					SetGridGraphic(i, newState: false);
				}
			}
			iconIndexBuffer.SetData((Array)iconIndexArray);
			stateBuffer.SetData((Array)stateArray);
		}

		public virtual void OnContentMouseEnter(BaseEventData eventData)
		{
		}

		public virtual void OnContentMouseExit(BaseEventData eventData)
		{
		}

		public void OnContentMouseDown(BaseEventData eventData)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected I4, but got Unknown
			CommonAPIPlugin.logger.LogInfo("Mouse down");
			if (GameMain.mainPlayer != null && GetGridPos(out var gridX, out var gridY))
			{
				CommonAPIPlugin.logger.LogInfo($"pos: {gridX} {gridY}");
				int grid = gridX + gridY * colCount;
				PointerEventData val = (PointerEventData)(object)((eventData is PointerEventData) ? eventData : null);
				if (val != null)
				{
					OnGridMouseDown(grid, (int)val.button, VFInput.shift, VFInput.control, GameMain.mainPlayer);
				}
			}
		}

		protected bool GetGridPos(out int gridX, out int gridY, bool filterEdges = false)
		{
			//IL_0006: 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_0030: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			gridX = -1;
			gridY = -1;
			Vector2 val = default(Vector2);
			if (!UIRoot.ScreenPointIntoRect(Input.mousePosition, contentRect, ref val))
			{
				return false;
			}
			gridX = Mathf.FloorToInt(val.x / 50f);
			gridY = Mathf.FloorToInt((0f - val.y) / 50f);
			if (gridX < 0 || gridX >= colCount)
			{
				gridX = -1;
				gridY = -1;
				return false;
			}
			if (gridY < 0 || gridY >= rowCount)
			{
				gridX = -1;
				gridY = -1;
				return false;
			}
			int num = (int)(val.x - (float)(gridX * 50));
			int num2 = (int)(0f - val.y - (float)(gridY * 50));
			if (num <= 3 || num2 <= 3 || num >= 47 || num2 >= 47)
			{
				gridX = -1;
				gridY = -1;
				return false;
			}
			return true;
		}

		public void OnContentMouseUp(BaseEventData eventData)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected I4, but got Unknown
			if (GameMain.mainPlayer != null)
			{
				PointerEventData val = (PointerEventData)(object)((eventData is PointerEventData) ? eventData : null);
				if ((int)val.button == 1)
				{
					OnGridRightMouseUp(GameMain.mainPlayer);
				}
				if (GetGridPos(out var gridX, out var gridY))
				{
					int grid = gridX + gridY * colCount;
					OnGridMouseUp(grid, (int)val.button, VFInput.shift, VFInput.control, GameMain.mainPlayer);
				}
			}
		}

		public virtual void OnSort()
		{
		}

		protected virtual void OnGridMouseDown(int grid, int button, bool shift, bool control, Player player)
		{
		}

		protected virtual void OnGridMouseUp(int grid, int button, bool shift, bool control, Player player)
		{
		}

		protected virtual void OnGridRightMouseUp(Player player)
		{
		}

		protected virtual int HandTake(Player player, int grid, int count = 0)
		{
			return 0;
		}

		protected virtual void HandPut(Player player, int grid, int count = 0)
		{
		}
	}
	public static class PrefabDescExtensions
	{
		public static bool HasProperty(this PrefabDesc desc, string name)
		{
			return desc.customData.ContainsKey(name);
		}

		public static void SetProperty<T>(this PrefabDesc desc, string name, T value)
		{
			if (desc.customData.ContainsKey(name))
			{
				desc.customData[name] = value;
			}
			else
			{
				desc.customData.Add(name, value);
			}
		}

		public static T GetProperty<T>(this PrefabDesc desc, string name)
		{
			if (desc.customData.ContainsKey(name))
			{
				return (T)desc.customData[name];
			}
			return default(T);
		}

		public static T GetOrAddProperty<T>(this PrefabDesc desc, string name) where T : new()
		{
			if (desc.customData.ContainsKey(name))
			{
				return (T)desc.customData[name];
			}
			T val = new T();
			desc.customData.Add(name, val);
			return val;
		}
	}
	public interface INetwork
	{
		int GetId();

		List<Node> GetNodes();
	}
	public struct NodeBounds
	{
		public Vector3 center;

		public Vector3 size;

		public Vector3 nodePoint;
	}
	public abstract class NetworkHandler
	{
		protected static List<int> _tmp_ints = new List<int>();

		protected static List<Node> _tmp_nodes = new List<Node>();

		protected PlanetFactory factory;

		public virtual NetworkHandler Prepare(PlanetFactory currentFactory)
		{
			factory = currentFactory;
			return this;
		}

		public abstract INetwork GetNetwork(int nodeId);

		protected abstract void RemoveNetwork(INetwork network);

		protected abstract void HandleNetworkMerge(INetwork first, INetwork second);

		protected abstract void SetNodeNetwork(Node node, INetwork network);

		protected abstract void HandleNodeRemoval(INetwork network, Node node);

		protected abstract INetwork CreateNewNetworkWith(List<Node> nodes);

		public abstract void UpdateVisualComponents(Node target);

		protected abstract bool CheckConnectionConditions(Node first, Node second, ref string errorMessage);

		public abstract string GetComponentType();

		public abstract bool IsRelatedTo(ItemProto proto);

		public abstract int GetNodeId(EntityData entity, Vector3 pos, Func<Node, bool> filter = null);

		public abstract NodeBounds GetNodeBounds(PrefabDesc prefab, int nodeId);

		public bool DisconnectAll(int nodeId)
		{
			INetwork network = GetNetwork(nodeId);
			Node nodeWithId = GetNodeWithId(nodeId);
			_tmp_nodes.Clear();
			foreach (Node conn in nodeWithId.conns)
			{
				_tmp_nodes.Add(conn);
				conn.conns.Remove(nodeWithId);
			}
			foreach (Node tmp_node in _tmp_nodes)
			{
				nodeWithId.conns.Remove(tmp_node);
			}
			_tmp_nodes.Clear();
			CreateNewNetworkWith(new List<Node> { nodeWithId });
			CheckForDisconnectedNetworks(network);
			UpdateVisualComponents(nodeWithId);
			return true;
		}

		public void DisconnectNodes(Node first, Node other)
		{
			first.conns.Remove(other);
			other.conns.Remove(first);
			INetwork network = GetNetwork(first.id);
			CheckForDisconnectedNetworks(network);
		}

		public bool ConnectNodes(Node first, Node second, ref string errorMessage)
		{
			if (!CheckConnectionConditions(first, second, ref errorMessage))
			{
				return false;
			}
			Algorithms.ListSortedAdd(first.conns, second);
			Algorithms.ListSortedAdd(second.conns, first);
			INetwork network = GetNetwork(first.id);
			INetwork network2 = GetNetwork(second.id);
			MergeNetworks(network, network2);
			return true;
		}

		public Node GetNodeWithId(int nodeId)
		{
			INetwork network = GetNetwork(nodeId);
			try
			{
				return network.GetNodes().First((Node node) => node.id == nodeId);
			}
			catch (InvalidOperationException)
			{
				throw new ArgumentException("Can't find network");
			}
		}

		public bool AreNodesConnected(Node firstNode, Node secondNode)
		{
			return firstNode.conns.Any((Node node) => node.id == secondNode.id);
		}

		private void MergeNetworks(INetwork firstNetwork, INetwork secondNetwork)
		{
			if (firstNetwork == null || secondNetwork == null || firstNetwork.GetId() == secondNetwork.GetId())
			{
				return;
			}
			foreach (Node node in secondNetwork.GetNodes())
			{
				SetNodeNetwork(node, firstNetwork);
			}
			Algorithms.ListSortedMerge(firstNetwork.GetNodes(), secondNetwork.GetNodes());
			HandleNetworkMerge(firstNetwork, secondNetwork);
			RemoveNetwork(secondNetwork);
		}

		public void CheckForDisconnectedNetworks(INetwork startNetwork)
		{
			INetwork network = startNetwork;
			int num = 0;
			do
			{
				List<Node> nodes = network.GetNodes();
				Algorithms.NodeDfs(nodes[0]);
				_tmp_nodes.Clear();
				for (int i = 0; i < nodes.Count; i++)
				{
					Node val = nodes[i];
					if (!val.flag)
					{
						_tmp_nodes.Add(val);
						HandleNodeRemoval(network, val);
						nodes.RemoveAt(i);
						i--;
					}
				}
				Algorithms.ClearNodeFlags(nodes);
				if (_tmp_nodes.Count == 0)
				{
					break;
				}
				network = CreateNewNetworkWith(_tmp_nodes);
			}
			while (num++ < 24);
			_tmp_nodes.Clear();
		}
	}
	public class NetworksSystem : BaseSubmodule
	{
		public static List<NetworkHandler> handlers = new List<NetworkHandler>();

		internal static NetworksSystem Instance => CommonAPIPlugin.GetModuleInstance<NetworksSystem>();

		internal override void Load()
		{
			AddHandler(new PowerNetworkHandler());
		}

		public static void AddHandler(NetworkHandler handler)
		{
			handlers.Add(handler);
		}

		public static bool IsConnectedToNetwork(PlanetFactory factory, int objId)
		{
			Instance.ThrowIfNotLoaded();
			try
			{
				NetworkHandler networkHandler = GetNetworkHandler(factory, objId);
				return networkHandler != null;
			}
			catch (InvalidOperationException)
			{
				return false;
			}
		}

		public static bool IsConnectedToSameNetwork(PlanetFactory factory, int firstId, int secondId)
		{
			Instance.ThrowIfNotLoaded();
			try
			{
				NetworkHandler commonNetwork = GetCommonNetwork(factory, firstId, secondId);
				return commonNetwork != null;
			}
			catch (InvalidOperationException)
			{
				return false;
			}
		}

		public static NetworkHandler GetNetworkHandler(PlanetFactory factory, int objId)
		{
			Instance.ThrowIfNotLoaded();
			if (objId == 0)
			{
				return null;
			}
			int num = ((objId > 0) ? factory.entityPool[objId].protoId : factory.prebuildPool[-objId].protoId);
			ItemProto itemProto = ((ProtoSet<ItemProto>)(object)LDB.items).Select(num);
			if (itemProto == null)
			{
				return null;
			}
			try
			{
				return handlers.First((NetworkHandler handler) => handler.IsRelatedTo(itemProto)).Prepare(factory);
			}
			catch (InvalidOperationException)
			{
				return null;
			}
		}

		public static NetworkHandler GetCommonNetwork(PlanetFactory factory, int firstId, int secondId)
		{
			Instance.ThrowIfNotLoaded();
			if (firstId == 0 || secondId == 0)
			{
				return null;
			}
			int num = ((firstId > 0) ? factory.entityPool[firstId].protoId : factory.prebuildPool[-firstId].protoId);
			int num2 = ((secondId > 0) ? factory.entityPool[secondId].protoId : factory.prebuildPool[-secondId].protoId);
			ItemProto firstItemProto = ((ProtoSet<ItemProto>)(object)LDB.items).Select(num);
			ItemProto secondItemProto = ((ProtoSet<ItemProto>)(object)LDB.items).Select(num2);
			if (firstItemProto == null || secondItemProto == null)
			{
				return null;
			}
			try
			{
				return handlers.First((NetworkHandler handler) => handler.IsRelatedTo(firstItemProto) && handler.IsRelatedTo(secondItemProto)).Prepare(factory);
			}
			catch (InvalidOperationException)
			{
				return null;
			}
		}
	}
	public static class NodeExtensions
	{
		public static Vector3 GetPoint(this Node node)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(node.x, node.y, node.z);
		}
	}
	public class PowerNetworkHandler : NetworkHandler
	{
		private PowerSystem system;

		public override NetworkHandler Prepare(PlanetFactory currentFactory)
		{
			if (factory == currentFactory)
			{
				return this;
			}
			base.Prepare(currentFactory);
			system = currentFactory.powerSystem;
			return this;
		}

		protected override void SetNodeNetwork(Node node, INetwork network)
		{
			system.nodePool[node.id].networkId = network.GetId();
		}

		public override INetwork GetNetwork(int nodeId)
		{
			int networkId = system.nodePool[nodeId].networkId;
			if (networkId == 0)
			{
				throw new ArgumentException("Zero Network id");
			}
			return new PowerNetworkWrapper(system.netPool[networkId]);
		}

		protected override void RemoveNetwork(INetwork network)
		{
			system.RemoveNetwork(network.GetId());
		}

		protected override bool CheckConnectionConditions(Node first, Node second, ref string message)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			float num = first.connDistance2;
			float connDistance = second.connDistance2;
			if (num < connDistance)
			{
				num = connDistance;
			}
			Vector3 val = first.GetPoint() - second.GetPoint();
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			message = "距离太远";
			return sqrMagnitude <= num;
		}

		public override string GetComponentType()
		{
			return "dsp.common-api.CommonAPI:PowerNetworkHandler";
		}

		public override bool IsRelatedTo(ItemProto proto)
		{
			return proto.prefabDesc.isPowerNode;
		}

		public override int GetNodeId(EntityData entity, Vector3 pos, Func<Node, bool> filter = null)
		{
			//IL_0017: 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)
			if (filter == null || filter(GetNodeWithId(entity.powerNodeId)))
			{
				return entity.powerNodeId;
			}
			return 0;
		}

		public override NodeBounds GetNodeBounds(PrefabDesc prefab, int nodeId)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_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)
			NodeBounds result = default(NodeBounds);
			result.center = prefab.selectCenter;
			result.size = prefab.selectSize;
			result.nodePoint = prefab.powerPoint;
			return result;
		}

		protected override void HandleNetworkMerge(INetwork first, INetwork second)
		{
			PowerNetwork data = ((PowerNetworkWrapper)first).data;
			PowerNetwork data2 = ((PowerNetworkWrapper)second).data;
			foreach (int consumer in data2.consumers)
			{
				system.consumerPool[consumer].networkId = first.GetId();
			}
			foreach (int generator in data2.generators)
			{
				system.genPool[generator].networkId = first.GetId();
			}
			foreach (int accumulator in data2.accumulators)
			{
				system.accPool[accumulator].networkId = first.GetId();
			}
			foreach (int exchanger in data2.exchangers)
			{
				system.excPool[exchanger].networkId = first.GetId();
			}
			Algorithms.ListSortedMerge(data.consumers, data2.consumers);
			Algorithms.ListSortedMerge(data.generators, data2.generators);
			Algorithms.ListSortedMerge(data.accumulators, data2.accumulators);
			Algorithms.ListSortedMerge(data.exchangers, data2.exchangers);
		}

		protected override void HandleNodeRemoval(INetwork network, Node node)
		{
			PowerNetwork data = ((PowerNetworkWrapper)network).data;
			foreach (int consumer in node.consumers)
			{
				data.consumers.Remove(consumer);
			}
			if (node.genId > 0)
			{
				data.generators.Remove(node.genId);
			}
			if (node.accId > 0)
			{
				data.accumulators.Remove(node.accId);
			}
			if (node.excId > 0)
			{
				data.exchangers.Remove(node.excId);
			}
		}

		protected override INetwork CreateNewNetworkWith(List<Node> nodes)
		{
			int num = system.NewNetwork();
			PowerNetwork val = system.netPool[num];
			Algorithms.ListSortedMerge(val.nodes, nodes);
			foreach (Node node in nodes)
			{
				system.nodePool[node.id].networkId = num;
				Algorithms.ListSortedMerge(val.consumers, node.consumers);
				foreach (int consumer in node.consumers)
				{
					system.consumerPool[consumer].networkId = num;
				}
				if (node.genId > 0)
				{
					Algorithms.ListSortedAdd(val.generators, node.genId);
					system.genPool[node.genId].networkId = num;
				}
				if (node.accId > 0)
				{
					Algorithms.ListSortedAdd(val.accumulators, node.accId);
					system.accPool[node.accId].networkId = num;
				}
				if (node.excId > 0)
				{
					Algorithms.ListSortedAdd(val.exchangers, node.excId);
					system.excPool[node.excId].networkId = num;
				}
			}
			return new PowerNetworkWrapper(val);
		}

		public override void UpdateVisualComponents(Node target)
		{
			system.line_arragement_for_remove_node(target);
			system.line_arragement_for_add_node(target);
			factory.planet.factoryModel.RefreshPowerNodes();
		}
	}
	public class PowerNetworkWrapper : INetwork
	{
		public PowerNetwork data;

		public PowerNetworkWrapper(PowerNetwork network)
		{
			data = network;
		}

		public int GetId()
		{
			return data.id;
		}

		public List<Node> GetNodes()
		{
			return data.nodes;
		}
	}
	public interface IPickerExtension<in T>
	{
		void Open(T picker);

		void Close(T picker);

		void OnPopup(T picker);

		void PostPopup(T picker);
	}
	public interface IMouseHandlerExtension<in T> : IPickerExtension<T>
	{
		bool OnBoxMouseDown(T picker);

		void TestMouseIndex(T picker);
	}
	public interface IUpdatePickerExtension<in T> : IPickerExtension<T>
	{
		void OnUpdate(T picker);
	}
	public interface ShowLocked
	{
	}
	public class IntPropertySerializer : IPropertySerializer
	{
		public static readonly IntPropertySerializer instance = new IntPropertySerializer();

		public void Export(object obj, BinaryWriter w)
		{
			w.Write((int)obj);
		}

		public object Import(BinaryReader r)
		{
			return r.ReadInt32();
		}

		public Type GetTargetType()
		{
			return typeof(int);
		}
	}
	public class IntArrayPropertySerializer : IPropertySerializer
	{
		public static readonly IntArrayPropertySerializer instance = new IntArrayPropertySerializer();

		public void Export(object obj, BinaryWriter w)
		{
			int[] array = (int[])obj;
			w.Write(array.Length);
			int[] array2 = array;
			foreach (int value in array2)
			{
				w.Write(value);
			}
		}

		public object Import(BinaryReader r)
		{
			int num = r.ReadInt32();
			int[] array = new int[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = r.ReadInt32();
			}
			return array;
		}

		public Type GetTargetType()
		{
			return typeof(int[]);
		}
	}
	public static class EntityDataExtensions
	{
		public static Dictionary<string, IPropertySerializer> propertySerializers = new Dictionary<string, IPropertySerializer>();

		public static void DefineProperty(string key, IPropertySerializer serializer)
		{
			if (propertySerializers.ContainsKey(key))
			{
				propertySerializers[key] = serializer;
			}
			else
			{
				propertySerializers.Add(key, serializer);
			}
		}

		public static bool HasProperty(this ref EntityData desc, string name)
		{
			if (desc.customData == null)
			{
				desc.customData = new Dictionary<string, object>();
			}
			return desc.customData.ContainsKey(name);
		}

		public static void SetProperty<T>(this ref EntityData desc, string name, T value)
		{
			if (!propertySerializers.ContainsKey(name) || propertySerializers[name] == null)
			{
				throw new ArgumentException("Can't set property " + name + " of type " + value.GetType().FullName + " because serializer for it was not defined!");
			}
			Type targetType = propertySerializers[name].GetTargetType();
			if (targetType != value.GetType())
			{
				throw new ArgumentException("Can't set property " + name + " of type " + value.GetType().FullName + " because serializer defined for " + name + " is for type " + targetType.FullName + "!");
			}
			if (desc.customData == null)
			{
				desc.customData = new Dictionary<string, object>();
			}
			if (desc.customData.ContainsKey(name))
			{
				desc.customData[name] = value;
			}
			else
			{
				desc.customData.Add(name, value);
			}
		}

		public static T GetProperty<T>(this ref EntityData desc, string name)
		{
			if (desc.customData == null)
			{
				desc.customData = new Dictionary<string, object>();
			}
			if (desc.customData.ContainsKey(name))
			{
				return (T)desc.customData[name];
			}
			return default(T);
		}

		public static T GetOrAddProperty<T>(this ref EntityData desc, string name) where T : new()
		{
			if (desc.customData == null)
			{
				desc.customData = new Dictionary<string, object>();
			}
			if (desc.customData.ContainsKey(name))
			{
				return (T)desc.customData[name];
			}
			T val = new T();
			desc.customData.Add(name, val);
			return val;
		}

		public static void ExportData(ref EntityData data, BinaryWriter w)
		{
			if (data.customData != null)
			{
				w.Write((byte)data.customData.Count);
				{
					foreach (KeyValuePair<string, object> customDatum in data.customData)
					{
						w.Write(customDatum.Key);
						IPropertySerializer propertySerializer = propertySerializers[customDatum.Key];
						propertySerializer.Export(customDatum.Value, w);
					}
					return;
				}
			}
			w.Write((byte)0);
		}

		public static void ImportData(ref EntityData data, BinaryReader r)
		{
			int num = r.ReadByte();
			for (int i = 0; i < num; i++)
			{
				string text = r.ReadString();
				IPropertySerializer propertySerializer = propertySerializers[text];
				object value = propertySerializer.Import(r);
				data.SetProperty(text, value);
			}
		}
	}
	public interface IPropertySerializer
	{
		void Export(object obj, BinaryWriter w);

		object Import(BinaryReader r);

		Type GetTargetType();
	}
	public static class ItemProtoExtenstion
	{
		public static void SetIcon(this ItemProto proto, string path, bool propageToRecipe = true)
		{
			if (!string.IsNullOrEmpty(path))
			{
				Sprite iconSprite = Resources.Load<Sprite>(path);
				proto.IconPath = path;
				proto._iconSprite = iconSprite;
				if (propageToRecipe && proto.maincraft != null)
				{
					RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(((Proto)proto.maincraft).ID);
					CommonAPIPlugin.logger.LogInfo($"Changing recipe icon: {val != null}");
					val.IconPath = "";
					val._iconSprite = iconSprite;
				}
			}
		}
	}
	[HarmonyPatch]
	public static class LoadSaveOnLoad
	{
		internal static string saveName;

		internal static bool isValid
		{
			get
			{
				if (saveName != null)
				{
					return !saveName.Equals("");
				}
				return false;
			}
		}

		internal static string GetArg(string name)
		{
			string[] commandLineArgs = Environment.GetCommandLineArgs();
			for (int i = 0; i < commandLineArgs.Length; i++)
			{
				if (commandLineArgs[i] == name && commandLineArgs.Length > i + 1)
				{
					return commandLineArgs[i + 1];
				}
			}
			return null;
		}

		internal static void Init()
		{
			saveName = GetArg("loadSave");
			if (isValid)
			{
				DSPGame.LoadFile = saveName;
				CommonAPIPlugin.logger.LogInfo("Loading save " + saveName + " by default!");
			}
		}

		internal static void LoadSave()
		{
			if (isValid && GameSave.SaveExist(saveName))
			{
				DSPGame.StartGame(saveName);
			}
		}
	}
	public class AcceptableValueOptionsList : AcceptableValueBase
	{
		public string[] AcceptableValues { get; }

		public AcceptableValueOptionsList(string[] acceptableValues)
			: base(typeof(string))
		{
			if (acceptableValues == null)
			{
				throw new ArgumentNullException("acceptableValues");
			}
			if (acceptableValues.Length == 0)
			{
				throw new ArgumentException("At least one acceptable value is needed", "acceptableValues");
			}
			AcceptableValues = acceptableValues;
		}

		public override object Clamp(object value)
		{
			if (!(value is string text))
			{
				return "";
			}
			string[] source = text.Split(new char[1] { ',' });
			return GeneralExtensions.Join<string>(from s in source
				select s.Trim() into s
				where AcceptableValues.Contains(s)
				select s, (Func<string, string>)null, ", ");
		}

		public override bool IsValid(object value)
		{
			if (!(value is string text))
			{
				return false;
			}
			string[] source = text.Split(new char[1] { ',' });
			return source.All((string s) => AcceptableValues.Contains(s.Trim()));
		}

		public override string ToDescriptionString()
		{
			return "# Acceptable values: " + string.Join(", ", AcceptableValues.Select((string x) => x.ToString()).ToArray()) + "\n# Multiple values can be set at the same time by separating them with , (e.g. Debug, Warning)";
		}
	}
	public static class Algorithms
	{
		public static void NodeDfs(Node n)
		{
			n.flag = true;
			int count = n.conns.Count;
			for (int i = 0; i < count; i += 30)
			{
				int num = 0;
				for (int j = 0; j < 30; j++)
				{
					int num2 = i + j;
					if (num2 >= count)
					{
						break;
					}
					if (!n.conns[num2].flag)
					{
						num |= 1 << j;
					}
					n.conns[num2].flag = true;
				}
				for (int k = 0; k < 30; k++)
				{
					int num3 = i + k;
					if (num3 >= count)
					{
						break;
					}
					if ((num & (1 << k)) > 0)
					{
						NodeDfs(n.conns[num3]);
					}
				}
			}
		}

		public static void ClearNodeFlags(List<Node> l)
		{
			foreach (Node item in l)
			{
				item.flag = false;
			}
		}

		public static void ListSortedMerge<T>(List<T> a, List<T> b) where T : IComparable<T>
		{
			int count = b.Count;
			int i = 0;
			for (int j = 0; j < count; j++)
			{
				int count2 = a.Count;
				T val = b[j];
				bool flag = false;
				for (; i < count2; i++)
				{
					if (a[i].CompareTo(val) == 0)
					{
						flag = true;
						break;
					}
					if (a[i].CompareTo(val) > 0)
					{
						a.Insert(i, val);
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					a.Add(val);
					i = a.Count;
				}
			}
		}

		public static void ListSortedMerge(List<Node> a, List<Node> b)
		{
			int count = b.Count;
			int i = 0;
			for (int j = 0; j < count; j++)
			{
				int count2 = a.Count;
				Node val = b[j];
				bool flag = false;
				for (; i < count2; i++)
				{
					if (a[i].id == val.id)
					{
						flag = true;
						break;
					}
					if (a[i].id > val.id)
					{
						a.Insert(i, val);
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					a.Add(val);
					i = a.Count;
				}
			}
		}

		public static void ListSortedAdd<T>(List<T> l, T n) where T : IComparable<T>
		{
			int count = l.Count;
			bool flag = false;
			for (int i = 0; i < count; i++)
			{
				if (l[i].CompareTo(n) == 0)
				{
					flag = true;
					break;
				}
				if (l[i].CompareTo(n) > 0)
				{
					l.Insert(i, n);
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				l.Add(n);
			}
		}

		public static void ListSortedAdd(List<Node> l, Node n)
		{
			int count = l.Count;
			bool flag = false;
			for (int i = 0; i < count; i++)
			{
				if (l[i].id == n.id)
				{
					flag = true;
					break;
				}
				if (l[i].id > n.id)
				{
					l.Insert(i, n);
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				l.Add(n);
			}
		}
	}
	public class InstanceRegistry<T> : Registry
	{
		public List<T> data = new List<T>();

		public InstanceRegistry()
		{
			data.Add(default(T));
		}

		public InstanceRegistry(int startId)
			: this(startId, throwErrorOnConflict: false)
		{
		}

		public InstanceRegistry(int startId, bool throwErrorOnConflict)
			: base(startId, throwErrorOnConflict)
		{
			for (int i = 0; i < startId; i++)
			{
				data.Add(default(T));
			}
		}

		public virtual int Register(string key, T item)
		{
			return Register(key, (object)item);
		}

		protected override void OnItemRegistered(string key, int id, object item)
		{
			if (item is T item2)
			{
				data.Add(item2);
				return;
			}
			throw new ArgumentException("Tried to register invalid type " + item.GetType().FullName + ", expected " + typeof(T).FullName);
		}
	}
	public interface IPoolable : ISerializeState
	{
		int GetId();

		void SetId(int id);
	}
	public interface ISerializeState
	{
		void Free();

		void Export(BinaryWriter w);

		void Import(BinaryReader r);
	}
	public class Pool<T> : ISerializeState where T : IPoolable, new()
	{
		public T[] pool;

		public int poolCursor = 1;

		protected int poolCapacity;

		protected int[] poolRecycle;

		protected int recycleCursor;

		private Action<T> _cachedInitUpdate = delegate
		{
		};

		public T this[int index] => pool[index];

		protected virtual T GetNewInstance()
		{
			return new T();
		}

		protected virtual void InitPoolItem(T item, object[] data)
		{
		}

		protected virtual void RemovePoolItem(T item)
		{
			item.Free();
		}

		public virtual void Free()
		{
			T[] array = pool;
			for (int i = 0; i < array.Length; i++)
			{
				T val = array[i];
				if (val != null && val.GetId() != 0)
				{
					val.Free();
				}
			}
			pool = null;
			poolCursor = 1;
			poolCapacity = 0;
			poolRecycle = null;
			recycleCursor = 0;
		}

		public virtual void Import(BinaryReader r)
		{
			r.ReadInt32();
			int newSize = r.ReadInt32();
			Init(newSize);
			poolCursor = r.ReadInt32();
			recycleCursor = r.ReadInt32();
			for (int i = 1; i < poolCursor; i++)
			{
				if (r.ReadByte() == 1)
				{
					pool[i] = GetNewInstance();
					pool[i].Import(r);
				}
			}
			for (int j = 0; j < recycleCursor; j++)
			{
				poolRecycle[j] = r.ReadInt32();
			}
		}

		public virtual void Export(BinaryWriter w)
		{
			w.Write(0);
			w.Write(poolCapacity);
			w.Write(poolCursor);
			w.Write(recycleCursor);
			for (int i = 1; i < poolCursor; i++)
			{
				if (pool[i] != null && pool[i].GetId() != 0)
				{
					w.Write((byte)1);
					pool[i].Export(w);
				}
				else
				{
					w.Write((byte)0);
				}
			}
			for (int j = 0; j < recycleCursor; j++)
			{
				w.Write(poolRecycle[j]);
			}
		}

		public void Init(int newSize)
		{
			T[] array = pool;
			pool = new T[newSize];
			poolRecycle = new int[newSize];
			if (array != null)
			{
				Array.Copy(array, pool, (newSize <= poolCapacity) ? newSize : poolCapacity);
			}
			poolCapacity = newSize;
		}

		public int AddPoolItem(object[] data)
		{
			return AddPoolItem(default(T), data);
		}

		public int AddPoolItem(T item, object[] data)
		{
			int num;
			if (recycleCursor > 0)
			{
				num = poolRecycle[--recycleCursor];
			}
			else
			{
				num = poolCursor++;
				if (num == poolCapacity)
				{
					Init(poolCapacity * 2);
				}
			}
			if (item != null)
			{
				pool[num] = item;
			}
			else if (pool[num] == null)
			{
				pool[num] = GetNewInstance();
			}
			pool[num].SetId(num);
			InitPoolItem(pool[num], data);
			return num;
		}

		public void RemovePoolItem(int id)
		{
			ref T reference = ref pool[id];
			T val = default(T);
			if (val == null)
			{
				val = reference;
				reference = ref val;
				if (val == null)
				{
					goto IL_0042;
				}
			}
			if (reference.GetId() == 0)
			{
				return;
			}
			goto IL_0042;
			IL_0042:
			RemovePoolItem(pool[id]);
			poolRecycle[recycleCursor++] = id;
		}

		protected virtual Action<T> InitUpdate()
		{
			return _cachedInitUpdate;
		}

		public void UpdatePool(Action<T> initFunc = null)
		{
			Action<T> action = initFunc ?? InitUpdate();
			for (int i = 1; i < poolCursor; i++)
			{
				ref T reference = ref pool[i];
				T val = default(T);
				if (val == null)
				{
					val = reference;
					reference = ref val;
					if (val == null)
					{
						continue;
					}
				}
				if (reference.GetId() == i)
				{
					action(pool[i]);
				}
			}
		}

		public void UpdatePoolMultithread(int usedThreadCount, int currentThreadIdx, int minimumCount, Action<T> initFunc = null)
		{
			Action<T> action = initFunc ?? InitUpdate();
			int num = default(int);
			int num2 = default(int);
			if (!WorkerThreadExecutor.CalculateMissionIndex(1, poolCursor - 1, usedThreadCount, currentThreadIdx, minimumCount, ref num, ref num2))
			{
				return;
			}
			for (int i = num; i < num2; i++)
			{
				ref T reference = ref pool[i];
				T val = default(T);
				if (val == null)
				{
					val = reference;
					reference = ref val;
					if (val == null)
					{
						continue;
					}
				}
				if (reference.GetId() == i)
				{
					action(pool[i]);
				}
			}
		}
	}
	public class Registry : ISerializeState
	{
		public Dictionary<string, int> idMap = new Dictionary<string, int>();

		public Dictionary<int, int> migrationMap = new Dictionary<int, int>();

		public HashSet<string> removedIds = new HashSet<string>();

		public HashSet<int> removedIntIds = new HashSet<int>();

		protected int lastId;

		protected bool throwErrorOnConflict;

		public Registry(int startId, bool throwErrorOnConflict)
		{
			lastId = startId - 1;
			this.throwErrorOnConflict = throwErrorOnConflict;
		}

		public Registry(int startId = 1)
			: this(startId, throwErrorOnConflict: false)
		{
		}

		protected virtual void OnItemRegistered(string key, int id, object item)
		{
		}

		public void InitUnitMigrationMap()
		{
			migrationMap.Clear();
			foreach (KeyValuePair<string, int> item in idMap)
			{
				migrationMap.Add(item.Value, item.Value);
			}
		}

		public int Register(string key, object item = null)
		{
			if (!idMap.ContainsKey(key))
			{
				OnItemRegistered(key, lastId + 1, item);
				idMap.Add(key, ++lastId);
				return lastId;
			}
			if (throwErrorOnConflict)
			{
				throw new InvalidOperationException("Failed to register object with key '" + key + "', because it is taken!");
			}
			return GetUniqueId(key);
		}

		public int GetUniqueId(string typeId)
		{
			if (idMap.ContainsKey(typeId))
			{
				return idMap[typeId];
			}
			throw new ArgumentException("Item with id " + typeId + " is not registered!");
		}

		public int MigrateId(int oldId)
		{
			if (migrationMap.ContainsKey(oldId))
			{
				return migrationMap[oldId];
			}
			return 0;
		}

		public void Free()
		{
		}

		public void Export(BinaryWriter w)
		{
			w.Write((byte)0);
			w.Write(idMap.Count);
			foreach (KeyValuePair<string, int> item in idMap)
			{
				w.Write(item.Key);
				w.Write(item.Value);
			}
		}

		public void Import(BinaryReader r)
		{
			migrationMap.Clear();
			r.ReadByte();
			int num = r.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				string text = r.ReadString();
				int num2 = r.ReadInt32();
				try
				{
					int uniqueId = GetUniqueId(text);
					migrationMap.Add(num2, uniqueId);
				}
				catch (ArgumentException)
				{
					removedIds.Add(text);
					removedIntIds.Add(num2);
				}
			}
		}
	}
	public class TypeRegistry<TItem, TCont> : InstanceRegistry<Type> where TCont : ISerializeState
	{
		public override int Register(string key, Type item)
		{
			if (typeof(TItem).IsAssignableFrom(item))
			{
				return base.Register(key, item);
			}
			throw new ArgumentException("Trying to register type " + item.FullName + ", which does not implement " + typeof(TItem).FullName + "!");
		}

		public TItem GetNew(int typeId)
		{
			if (typeId > 0 && typeId < data.Count)
			{
				return (TItem)Activator.CreateInstance(data[typeId]);
			}
			throw new ArgumentException($"Item with id {typeId} is not registered!");
		}

		public void ImportAndMigrate(IList<TCont> list, BinaryReader r)
		{
			while (true)
			{
				int num = r.ReadInt32();
				switch (num)
				{
				case -1:
					continue;
				case 0:
					return;
				}
				int num2 = MigrateId(num);
				if (num2 != 0)
				{
					TCont val = list[num2];
					long num3 = r.ReadInt64();
					long position = r.BaseStream.Position;
					try
					{
						val.Import(r);
					}
					catch (Exception ex)
					{
						CommonLogger.logger.LogWarning("Error importing container for type " + typeof(TItem).FullName + ", message: " + ex.Message + ", Stacktrace:\n" + ex.StackTrace);
						r.BaseStream.Position = position + num3;
					}
				}
				else
				{
					long num4 = r.ReadInt64();
					r.ReadBytes((int)num4);
				}
			}
		}

		public void ExportContainer(IList<TCont> list, BinaryWriter w)
		{
			for (int i = 1; i < list.Count; i++)
			{
				MemoryStream memoryStream = new MemoryStream();
				BinaryWriter w2 = new BinaryWriter(memoryStream);
				TCont val = list[i];
				try
				{
					val.Export(w2);
				}
				catch (Exception ex)
				{
					w.Write(-1);
					CommonLogger.logger.LogWarning("Error exporting container for type " + typeof(TItem).FullName + ", message: " + ex.Message + ", Stacktrace:\n" + ex.StackTrace);
					continue;
				}
				w.Write(i);
				w.Write(memoryStream.Length);
				w.Write(memoryStream.ToArray());
			}
			w.Write(0);
		}
	}
	public static class CecilExtension
	{
		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 CodeMatcherExtension
	{
		public static CodeMatcher GetInstructionAndAdvance(this CodeMatcher matcher, out OpCode opCode, out object operand)
		{
			opCode = matcher.Opcode;
			operand = matcher.Operand;
			matcher.Advance(1);
			return matcher;
		}

		public static CodeMatcher GetLabel(this CodeMatcher matcher, out Label label)
		{
			label = (Label)matcher.Instruction.operand;
			return matcher;
		}
	}
	public static class ConfigFileExtension
	{
		public static Type configFile;

		public static PropertyInfo OrphanedEntriesProp;

		static ConfigFileExtension()
		{
			configFile = AccessTools.TypeByName("BepInEx.Configuration.ConfigFile");
			OrphanedEntriesProp = configFile.GetProperty("OrphanedEntries", AccessTools.all);
		}

		public static void MigrateConfig<T>(this ConfigFile file, string oldSection, string newSection, string[] keyFilter)
		{
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)OrphanedEntriesProp.GetValue(file);
			List<ConfigDefinition> list = new List<ConfigDefinition>();
			ConfigEntry<T> val = default(ConfigEntry<T>);
			foreach (KeyValuePair<ConfigDefinition, string> item in dictionary)
			{
				string key = item.Key.Key;
				if (item.Key.Section.Equals(oldSection) && ((IList)keyFilter).Contains((object?)key) && file.TryGetEntry<T>(newSection, key, ref val))
				{
					((ConfigEntryBase)val).SetSerializedValue(item.Value);
					list.Add(item.Key);
					CommonAPIPlugin.logger.LogInfo("Migrating config from " + oldSection + ":" + key + " to " + newSection + ":" + key);
				}
			}
			foreach (ConfigDefinition item2 in list)
			{
				dictionary.Remove(item2);
			}
		}

		public static void MigrateConfig<T>(this ConfigFile file, string oldSection, string oldName, string newSection, string newName)
		{
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)OrphanedEntriesProp.GetValue(file);
			List<ConfigDefinition> list = new List<ConfigDefinition>();
			ConfigEntry<T> val = default(ConfigEntry<T>);
			foreach (KeyValuePair<ConfigDefinition, string> item in dictionary)
			{
				ConfigDefinition key = item.Key;
				if (key.Section.Equals(oldSection) && key.Key.Equals(oldName) && file.TryGetEntry<T>(newSection, newName, ref val))
				{
					((ConfigEntryBase)val).SetSerializedValue(item.Value);
					list.Add(key);
					CommonAPIPlugin.logger.LogInfo("Migrating config from " + oldSection + ":" + oldName + " to " + newSection + ":" + newName);
				}
			}
			foreach (ConfigDefinition item2 in list)
			{
				dictionary.Remove(item2);
			}
		}
	}
	public static class CopyPropertiesExtenstion
	{
		public static void CopyPropsTo<T1, T2>(this T1 source, ref T2 destination)
		{
			List<MemberInfo> members = GetMembers(source.GetType());
			List<MemberInfo> members2 = GetMembers(destination.GetType());
			foreach (MemberInfo sourceMember in members)
			{
				if (CanRead(sourceMember))
				{
					MemberInfo memberInfo = members2.FirstOrDefault((MemberInfo x) => x.Name.ToLower() == sourceMember.Name.ToLower());
					if (!(memberInfo == null) && CanWrite(memberInfo))
					{
						SetObjectValue(ref destination, memberInfo, GetMemberValue(source, sourceMember));
					}
				}
			}
		}

		private static void SetObjectValue<T>(ref T obj, MemberInfo member, object value)
		{
			object obj2 = (obj.GetType().IsValueType ? ((object)obj) : ((object)obj));
			SetMemberValue(ref obj2, member, value);
			obj = (T)obj2;
		}

		private static void SetMemberValue<T>(ref T obj, MemberInfo member, object value)
		{
			if (IsProperty(member))
			{
				PropertyInfo propertyInfo = (PropertyInfo)member;
				if (propertyInfo.SetMethod != null)
				{
					propertyInfo.SetValue(obj, value);
				}
			}
			else if (IsField(member))
			{
				FieldInfo fieldInfo = (FieldInfo)member;
				fieldInfo.SetValue(obj, value);
			}
		}

		private static object GetMemberValue(object obj, MemberInfo member)
		{
			object result = null;
			if (IsProperty(member))
			{
				PropertyInfo propertyInfo = (PropertyInfo)member;
				result = propertyInfo.GetValue(obj, (propertyInfo.GetIndexParameters().Count() == 1) ? new object[1] : null);
			}
			else if (IsField(member))
			{
				FieldInfo fieldInfo = (FieldInfo)member;
				result = fieldInfo.GetValue(obj);
			}
			return result;
		}

		private static bool CanWrite(MemberInfo member)
		{
			if (!IsProperty(member))
			{
				return IsField(member);
			}
			return ((PropertyInfo)member).CanWrite;
		}

		private static bool CanRead(MemberInfo member)
		{
			if (!IsProperty(member))
			{
				return IsField(member);
			}
			return ((PropertyInfo)member).CanRead;
		}

		private static bool IsProperty(MemberInfo member)
		{
			return IsType(member.GetType(), typeof(PropertyInfo));
		}

		private static bool IsField(MemberInfo member)
		{
			return IsType(member.GetType(), typeof(FieldInfo));
		}

		private static bool IsType(Type type, Type targetType)
		{
			if (!(type == targetType))
			{
				return type.IsSubclassOf(targetType);
			}
			return true;
		}

		private static List<MemberInfo> GetMembers(Type type)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			List<MemberInfo> list = new List<MemberInfo>();
			list.AddRange(type.GetProperties(bindingAttr));
			list.AddRange(type.GetFields(bindingAttr));
			return list;
		}
	}
	public static class GameVersionUtil
	{
		public static Version GetVersion(int major, int minor, int release, int build)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Version result = default(Version);
			((Version)(ref result))..ctor(major, minor, release);
			result.Build = build;
			return result;
		}

		public static bool CompatibleWith(this Version first, Version other)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_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)
			if (first.Major == other.Major && first.Minor == other.Minor)
			{
				return first.Release == other.Release;
			}
			return false;
		}
	}
	public static class GeneralExtensions
	{
		public static string[] units = new string[5] { "", "k", "M", "G", "T" };

		public static string FormatNumber(this int number)
		{
			if (number == 0)
			{
				return "0";
			}
			bool flag = false;
			if (number <= 0)
			{
				number = Math.Abs(number);
				flag = true;
			}
			int num = (int)(Math.Log10(number) / Math.Log10(1000.0));
			return string.Format("{0}{1:0.#}", flag ? "-" : "", (double)number / Math.Pow(1000.0, num)) + units[num];
		}

		public static bool IsModInstalled(this string modGUID)
		{
			if (Chainloader.PluginInfos == null)
			{
				return false;
			}
			return Chainloader.PluginInfos.ContainsKey(modGUID);
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class RegisterPatch : Attribute
	{
		public string typeKey;

		public RegisterPatch(string typeKey)
		{
			this.typeKey = typeKey;
		}
	}
	public static class HarmonyRegisterExtension
	{
		public static IEnumerable<Type> GetTypesWithAttributeInAssembly<T>(Assembly assembly) where T : Attribute
		{
			return from t in assembly.GetTypes()
				where t.GetCustomAttributes(typeof(T), inherit: true).Length != 0
				select t;
		}

		public static void PatchAll(this Harmony harmony, string typeKey)
		{
			Assembly callingAssembly = Assembly.GetCallingAssembly();
			IEnumerable<Type> typesWithAttributeInAssembly = GetTypesWithAttributeInAssembly<RegisterPatch>(callingAssembly);
			foreach (Type item in typesWithAttributeInAssembly)
			{
				if (item.IsClass)
				{
					RegisterPatch customAttribute = item.GetCustomAttribute<RegisterPatch>();
					if (customAttribute.typeKey.Equals(typeKey))
					{
						harmony.PatchAll(item);
					}
				}
				else
				{
					CommonAPIPlugin.logger.LogInfo("Failed to patch: " + item.FullName + ".");
				}
			}
		}
	}
	public static class Reflection
	{
		private delegate T GetDelegate<out T>(object instance);

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

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

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

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

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

		private static readonly ConcurrentDictionary<FieldInfo, Delegate> FieldGetDelegateCache = new ConcurrentDictionary<FieldInfo, Delegate>();

		private static readonly ConcurrentDictionary<FieldInfo, Delegate> FieldSetDelegateCache = new ConcurrentDictionary<FieldInfo, Delegate>();

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

		private static readonly ConcurrentDictionary<PropertyInfo, Delegate> PropertyGetDelegateCache = new ConcurrentDictionary<PropertyInfo, Delegate>();

		private static readonly ConcurrentDictionary<PropertyInfo, Delegate> PropertySetDelegateCache = new ConcurrentDictionary<PropertyInfo, Delegate>();

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

		private static readonly ConcurrentDictionary<(Type T, string name, Type[] argumentTypes), MethodInfo> OverloadedMethodCache = new ConcurrentDictionary<(Type, string, Type[]), MethodInfo>();

		private static readonly ConcurrentDictionary<MethodInfo, FastReflectionDelegate> DelegateCache = new ConcurrentDictionary<MethodInfo, FastReflectionDelegate>();

		private static readonly ConcurrentDictionary<(Type T, Type[] argumentTypes), ConstructorInfo> ConstructorCache = new ConcurrentDictionary<(Type, Type[]), ConstructorInfo>();

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

		private static TValue GetOrAddOnNull<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> factory)
		{
			if (dict.TryGetValue(key, out TValue value) && value != null)
			{
				return value;
			}
			return dict[key] = factory(key);
		}

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

		public static FieldInfo GetFieldCached(this Type? T, string? name)
		{
			Type T2 = T;
			string name2 = name;
			return FieldCache.GetOrAddOnNull<(Type, string), FieldInfo>((T2, name2), ((Type T, string name) x) => x.T.GetFieldFull(x.name) ?? throw new Exception("Could not find FieldInfo on " + T2.FullName + " with the name " + name2));
		}

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

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

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

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

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

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

		private static T GetMemberFull<T>(this Type type, string name) where T : MemberInfo
		{
			while (type != null)
			{
				MemberInfo[] member = type.GetMember(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (member != null)
				{
					return (T)member.First();
				}
				type = type.BaseType;
			}
			return null;
		}

		private static GetDelegate<TReturn> GetFieldGetDelegate<TReturn>(this FieldInfo field)
		{
			return Extensions.CastDelegate<GetDelegate<TReturn>>(FieldGetDelegateCache.GetOrAdd(field, (FieldInfo x) => x.CreateGetDelegate<TReturn>()));
		}

		private static SetDelegate<TValue> GetFieldSetDelegate<TValue>(this FieldInfo field)
		{
			return Extensions.CastDelegate<SetDelegate<TValue>>(FieldSetDelegateCache.GetOrAdd(field, (FieldInfo x) => x.CreateSetDelegate<TValue>()));
		}

		private static SetDelegateRef<TInstance, TValue> GetFieldSetDelegateRef<TInstance, TValue>(this FieldInfo field) where TInstance : struct
		{
			return Extensions.CastDelegate<SetDelegateRef<TInstance, TValue>>(FieldSetDelegateCache.GetOrAdd(field, (FieldInfo x) => x.CreateSetDelegateRef<TInstance, TValue>()));
		}

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

		public static PropertyInfo GetPropertyCached(this Type? T, string? name)
		{
			return PropertyCache.GetOrAddOnNull<(Type, string), PropertyInfo>((T, name), ((Type T, string name) x) => x.T.GetProperty(x.name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
		}

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

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

		public static void SetPropertyValue<TValue>(this object? instance, string? propName, TValue value)
		{
			PropertyInfo propertyCached = instance.GetType().GetPropertyCached(propName);
			if ((object)propertyCached != null)
			{
				propertyCached.GetPropertySetDelegate<TValue>()(instance, value);
			}
		}

		public static void SetPropertyValue<TValue>(this Type? staticType, string? propName, TValue value)
		{
			PropertyInfo propertyCached = staticType.GetPropertyCached(propName);
			if ((object)propertyCached != null)
			{
				propertyCached.GetPropertySetDelegate<TValue>()(null, value);
			}
		}

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

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

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

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

		private static GetDelegate<TReturn> GetPropertyGetDelegate<TReturn>(this PropertyInfo property)
		{
			return Extensions.CastDelegate<GetDelegate<TReturn>>(PropertyGetDelegateCache.GetOrAdd(property, (PropertyInfo prop) => prop.CreateGetDelegate<TReturn>()));
		}

		private static GetDelegateRef<TInstance, TReturn> GetPropertyGetDelegateRef<TInstance, TReturn>(this PropertyInfo property) where TInstance : struct
		{
			return Extensions.CastDelegate<GetDelegateRef<TInstance, TReturn>>(PropertyGetDelegateCache.GetOrAdd(property, (PropertyInfo prop) => prop.CreateGetDelegate<TInstance, TReturn>()));
		}

		private static SetDelegate<TValue> GetPropertySetDelegate<TValue>(this PropertyInfo property)
		{
			return Extensions.CastDelegate<SetDelegate<TValue>>(PropertySetDelegateCache.GetOrAdd(property, (PropertyInfo prop) => prop.CreateSetDelegate<TValue>()));
		}

		private static SetDelegateRef<TInstance, TValue> GetPropertySetDelegateRef<TInstance, TValue>(this PropertyInfo property) where TInstance : struct
		{
			return Extensions.CastDelegate<SetDelegateRef<TInstance, TValue>>(PropertySetDelegateCache.GetOrAdd(property, (PropertyInfo prop) => prop.CreateSetDelegateRef<TInstance, TValue>()));
		}

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

		public static MethodInfo GetMethodCached(this Type? T, string? name)
		{
			Type T2 = T;
			string name2 = name;
			return MethodCache.GetOrAddOnNull<(Type, string), MethodInfo>((T2, name2), ((Type T, string name) x) => x.T.GetMethod(x.name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new Exception("Could not find MethodInfo on " + T2.FullName + " with the name " + name2));
		}

		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 T2 = T;
			string name2 = name;
			Type?[] argumentTypes2 = argumentTypes;
			return OverloadedMethodCache.GetOrAddOnNull<(Type, string, Type[]), MethodInfo>((T2, name2, argumentTypes2), ((Type T, string name, Type[] argumentTypes) x) => x.T.GetMethod(x.name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, x.argumentTypes, null) ?? throw new Exception("Could not find MethodInfo on " + T2.FullName + " with the name " + name2 + " and arguments: " + string.Join(",", argumentTypes2.Select((Type a) => a.FullName))));
		}

		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)
		{
			MethodInfo methodInfo = ((methodParams == null) ? instance.GetType().GetMethodCached(methodName) : instance.GetType().GetMethodCached(methodName, methodParams.Select((object x) => x.GetType()).ToArray())) ?? throw new Exception($"Could not find method on type {instance.GetType()} with the name of {methodName} with the arguments specified.");
			return (TReturn)methodInfo.GetMethodDelegateCached().Invoke(instance, methodParams);
		}

		public static TReturn InvokeMethod<TReturn>(this Type? staticType, string? methodName, params object[] methodParams)
		{
			MethodInfo methodInfo = ((methodParams == null) ? staticType.GetMethodCached(methodName) : staticType.GetMethodCached(methodName, methodParams.Select((object x) => x.GetType()).ToArray())) ?? throw new Exception($"Could not find method on type {staticType} with the name of {methodName} with the arguments specified.");
			return (TReturn)methodInfo.GetMethodDelegateCached().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);
		}

		private static FastReflectionDelegate GetMethodDelegateCached(this MethodInfo methodInfo)
		{
			return DelegateCache.GetOrAdd(methodInfo, (Func<MethodInfo, FastReflectionDelegate>)((MethodInfo method) => method.GenerateCallDelegate()));
		}

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

		public static ConstructorInfo GetConstructorCached(this Type? T, Type?[]? argumentTypes)
		{
			Type T2 = T;
			Type?[] argumentTypes2 = argumentTypes;
			return ConstructorCache.GetOrAddOnNull<(Type, Type[]), ConstructorInfo>((T2, argumentTypes2), ((Type T, Type[] argumentTypes) x) => x.T.GetConstructor(x.argumentTypes) ?? throw new Exception("Could not find ConstructorInfo on " + T2.FullName + " with the arguments " + string.Join(",", argumentTypes2.Select((Type a) => a.FullName))));
		}

		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)
		{
			Type T2 = T;
			string name2 = name;
			return NestedTypeCache.GetOrAddOnNull<(Type, string), Type>((T2, name2), ((Type T, string name) x) => x.T.GetNestedType(x.name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new Exception("Could not find nested Type on " + T2.FullName + " with the name " + name2));
		}

		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 GetDelegate<TReturn> CreateGetDelegate<TReturn>(this FieldInfo field)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (field == null)
			{
				throw new ArgumentException("Field cannot be null.", "field");
			}
			if (!typeof(TReturn).IsAssignableFrom(field.FieldType))
			{
				throw new Exception($"Field type {field.FieldType} does not match the requested type {typeof(TReturn)}.");
			}
			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);
				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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00a6: 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_00c0: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (field == null)
			{
				throw new ArgumentException("Field cannot be null.", "field");
			}
			if (!field.FieldType.IsAssignableFrom(typeof(TValue)))
			{
				throw new Exception($"Value type type {typeof(TValue)} does not match the requested type {field.FieldType}.");
			}
			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);
				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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (field == null)
			{
				throw new ArgumentException("Field cannot be null.", "field");
			}
			if (field.FieldType != typeof(TValue))
			{
				throw new Exception($"Value type type {typeof(TValue)} does not match the requested type {field.FieldType}.");
			}
			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);
				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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_00a1: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			if (!typeof(TReturn).IsAssignableFrom(property.PropertyType))
			{
				throw new Exception($"Field type {property.PropertyType} does not match the requested type {typeof(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);
				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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00a6: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			if (!typeof(TReturn).IsAssignableFrom(property.PropertyType))
			{
				throw new Exception($"Field type {property.PropertyType} does not match the requested type {typeof(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);
				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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00ae: 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_00c5: 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)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			if (!property.PropertyType.IsAssignableFrom(typeof(TValue)))
			{
				throw new Exception($"Value type type {typeof(TValue)} does not match the requested type {property.PropertyType}.");
			}
			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);
				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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00b3: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (property == null)
			{
				throw new ArgumentException("Property cannot be null.", "property");
			}
			if (!property.PropertyType.IsAssignableFrom(typeof(TValue)))
			{
				throw new Exception($"Value type type {typeof(TValue)} does not match the requested type {property.PropertyType}.");
			}
			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);
				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 FieldInfo GetNestedField(Type type, string fieldName)
		{
			Type[] nestedTypes = type.GetNestedTypes(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			Type[] array = nestedTypes;
			foreach (Type type2 in array)
			{
				FieldInfo field = type2.GetField(fieldName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
			}
			return nul

patchers/CommonAPIPreloader.dll

Decompiled 3 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Logging;
using Mono.Cecil;
using Mono.Cecil.Rocks;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("1.6.5.1")]
[assembly: AssemblyInformationalVersion("1.6.5.1+d557386")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CommonAPIPreloader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyProduct("CommonAPIPreloader")]
[assembly: AssemblyTitle("CommonAPIPreloader")]
[assembly: AssemblyVersion("1.6.5.0")]
[GeneratedCode("Nerdbank.GitVersioning.Tasks", "3.6.133.12845")]
[ExcludeFromCodeCoverage]
internal static class ThisAssembly
{
	internal const string AssemblyConfiguration = "Release";

	internal const string AssemblyFileVersion = "1.6.5.1";

	internal const string AssemblyInformationalVersion = "1.6.5.1+d557386";

	internal const string AssemblyName = "CommonAPIPreloader";

	internal const string AssemblyTitle = "CommonAPIPreloader";

	internal const string AssemblyVersion = "1.6.5.0";

	internal static readonly DateTime GitCommitDate = new DateTime(638438744160000000L, DateTimeKind.Utc);

	internal const string GitCommitId = "d557386b98f0624ede6b809bb680a66eb6bfc3a3";

	internal const bool IsPrerelease = false;

	internal const bool IsPublicRelease = true;

	internal const string RootNamespace = "CommonAPIPreloader";
}
namespace CommonAPI;

public static class Preloader
{
	public static ManualLogSource logSource;

	public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" };


	public static void Initialize()
	{
		logSource = Logger.CreateLogSource("Common API Preloader");
	}

	public static void Patch(AssemblyDefinition assembly)
	{
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Expected O, but got Unknown
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Expected O, but got Unknown
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Expected O, but got Unknown
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Expected O, but got Unknown
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Expected O, but got Unknown
		ModuleDefinition mainModule = assembly.MainModule;
		TypeDefinition val = ((IEnumerable<TypeDefinition>)mainModule.Types).First((TypeDefinition t) => ((MemberReference)t).FullName == "EntityData");
		TypeDefinition val2 = ((IEnumerable<TypeDefinition>)mainModule.Types).First((TypeDefinition t) => ((MemberReference)t).FullName == "PrefabDesc");
		TypeDefinition val3 = ((IEnumerable<TypeDefinition>)mainModule.Types).First((TypeDefinition t) => ((MemberReference)t).FullName == "ERecipeType");
		if (val == null || val2 == null || val3 == null)
		{
			logSource.LogInfo((object)"Preloader patching failed!");
			return;
		}
		FieldDefinition val4 = new FieldDefinition("Custom", (FieldAttributes)32854, (TypeReference)(object)val3)
		{
			Constant = 20
		};
		val3.Fields.Add(val4);
		val.Fields.Add(new FieldDefinition("customId", (FieldAttributes)6, mainModule.ImportReference(typeof(int))));
		val.Fields.Add(new FieldDefinition("customType", (FieldAttributes)6, mainModule.ImportReference(typeof(int))));
		val.Fields.Add(new FieldDefinition("customData", (FieldAttributes)6, (TypeReference)(object)TypeReferenceRocks.MakeGenericInstanceType(mainModule.ImportReference(typeof(Dictionary<, >)), (TypeReference[])(object)new TypeReference[2]
		{
			mainModule.TypeSystem.String,
			mainModule.TypeSystem.Object
		})));
		val2.Fields.Add(new FieldDefinition("customData", (FieldAttributes)6, (TypeReference)(object)TypeReferenceRocks.MakeGenericInstanceType(mainModule.ImportReference(typeof(Dictionary<, >)), (TypeReference[])(object)new TypeReference[2]
		{
			mainModule.TypeSystem.String,
			mainModule.TypeSystem.Object
		})));
		logSource.LogInfo((object)"Preloader patching is successful!");
	}
}