Decompiled source of SODCommon v2.0.2

SOD.Common.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Castle.DynamicProxy;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using Rewired;
using SOD.Common.BepInEx;
using SOD.Common.BepInEx.Configuration;
using SOD.Common.BepInEx.Proxies;
using SOD.Common.ConfigBindings;
using SOD.Common.Custom;
using SOD.Common.Extensions;
using SOD.Common.Extensions.Internal;
using SOD.Common.Helpers;
using SOD.Common.Helpers.DialogObjects;
using SOD.Common.Helpers.SyncDiskObjects;
using UnityEngine;
using UniverseLib;
using UniverseLib.Config;
using UniverseLib.Utility;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Venomaus, Spyraxi")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Common library for SOD modding.")]
[assembly: AssemblyFileVersion("2.0.2.0")]
[assembly: AssemblyInformationalVersion("2.0.2+63c441585b50157ea1c42077c66e925d203e0b73")]
[assembly: AssemblyProduct("SOD.Common")]
[assembly: AssemblyTitle("SOD.Common")]
[assembly: AssemblyVersion("2.0.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SOD.Common
{
	public class Lib
	{
		public static GameMessage GameMessage { get; } = new GameMessage();


		public static Time Time { get; } = new Time();


		public static SaveGame SaveGame { get; } = new SaveGame();


		public static InputDetection InputDetection { get; } = new InputDetection();


		public static Interaction Interaction { get; } = new Interaction();


		public static SyncDisks SyncDisks { get; } = new SyncDisks();


		public static DdsStrings DdsStrings { get; } = new DdsStrings();


		public static Dialog Dialogs { get; } = new Dialog();


		public static PluginDetection PluginDetection { get; } = new PluginDetection();


		public static PlayerStatus PlayerStatus { get; } = new PlayerStatus();


		public static RestoredUnityEngine RestoredEngineFunctions { get; } = new RestoredUnityEngine();

	}
	[BepInPlugin("Venomaus.SOD.Common", "SOD.Common", "2.0.2")]
	public class Plugin : PluginController<Plugin, IPluginBindings>
	{
		public const string PLUGIN_GUID = "Venomaus.SOD.Common";

		public const string PLUGIN_NAME = "SOD.Common";

		public const string PLUGIN_VERSION = "2.0.2";

		public override void Load()
		{
			//IL_0009: 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)
			Universe.Init(0f, (Action)null, (Action<string, LogType>)null, new UniverseLibConfig
			{
				Unhollowed_Modules_Folder = Path.Combine(Paths.BepInExRootPath, "interop")
			});
			base.Harmony.PatchAll(Assembly.GetExecutingAssembly());
			PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Plugin is patched.");
		}
	}
	public sealed class RestoredUnityEngine
	{
		public static class JsonUtility
		{
			private delegate IntPtr Delegate_FromJsonInternal(IntPtr json, IntPtr scriptableObject, IntPtr type);

			private delegate IntPtr Delegate_ToJsonInternal(IntPtr json, bool prettyPrint);

			private static Delegate_FromJsonInternal _iCallFromJsonInternal;

			private static Delegate_ToJsonInternal _iCallToJsonInternal;

			public static T FromJsonInternal<T>(string json, T scriptableObject) where T : Object
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				if (_iCallFromJsonInternal == null)
				{
					_iCallFromJsonInternal = IL2CPP.ResolveICall<Delegate_FromJsonInternal>("UnityEngine.JsonUtility::FromJsonInternal");
				}
				IntPtr json2 = IL2CPP.ManagedStringToIl2Cpp(json);
				IntPtr scriptableObject2 = (IntPtr)typeof(T).GetMethod("get_Pointer").Invoke(scriptableObject, null);
				IntPtr pointer = ((Il2CppObjectBase)Il2CppType.Of<T>()).Pointer;
				return new Il2CppObjectBase(_iCallFromJsonInternal(json2, scriptableObject2, pointer)).TryCast<T>();
			}

			public static string ToJsonInternal(Il2CppObjectBase obj, bool prettyPrint)
			{
				if (_iCallToJsonInternal == null)
				{
					_iCallToJsonInternal = IL2CPP.ResolveICall<Delegate_ToJsonInternal>("UnityEngine.JsonUtility::ToJsonInternal");
				}
				IntPtr json = (IntPtr)typeof(ScriptableObject).GetMethod("get_Pointer").Invoke(obj, null);
				return IL2CPP.Il2CppStringToManaged(_iCallToJsonInternal(json, prettyPrint));
			}
		}

		internal RestoredUnityEngine()
		{
		}
	}
}
namespace SOD.Common.Patches
{
	internal class AssetLoaderPatches
	{
		[HarmonyPatch(typeof(AssetLoader), "GetAllPresets")]
		internal static class AssetLoader_GetAllPresets
		{
			private static bool _loaded;

			[HarmonyPostfix]
			internal static void Postfix(List<ScriptableObject> __result)
			{
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_0150: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b3: Expected O, but got Unknown
				if (_loaded)
				{
					return;
				}
				_loaded = true;
				HashSet<string> sprites = Lib.SyncDisks.RegisteredSyncDisks.SelectMany((SyncDisk a) => a.Icons).ToHashSet<string>(StringComparer.OrdinalIgnoreCase);
				Dictionary<string, Sprite> gameSprites = (from a in (IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()
					where sprites.Contains(((Object)a).name)
					group a by ((Object)a).name).ToDictionary((IGrouping<string, Sprite> a) => a.Key, (IGrouping<string, Sprite> a) => a.First());
				foreach (SyncDisk registeredSyncDisk in Lib.SyncDisks.RegisteredSyncDisks)
				{
					SyncDiskPreset preset = registeredSyncDisk.Preset;
					_createdSyncDiskPresets.Add(preset);
					preset.interactable = SyncDisk.SyncDiskInteractablePreset.Value;
					if ((int)preset.mainEffect1 != 0)
					{
						preset.mainEffect1Icon = GetSprite(gameSprites, registeredSyncDisk.Icons[0]);
					}
					if ((int)preset.mainEffect2 != 0)
					{
						preset.mainEffect2Icon = GetSprite(gameSprites, registeredSyncDisk.Icons[1]);
					}
					if ((int)preset.mainEffect3 != 0)
					{
						preset.mainEffect3Icon = GetSprite(gameSprites, registeredSyncDisk.Icons[2]);
					}
					__result.Add((ScriptableObject)(object)preset);
				}
				if (Lib.SyncDisks.RegisteredSyncDisks.Count > 0)
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Lib.SyncDisks.RegisteredSyncDisks.Count);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" custom sync disks.");
					}
					log.LogInfo(val);
				}
				Lib.SyncDisks.RegisteredSyncDisks.ForEach(delegate(SyncDisk a)
				{
					a.Icons = null;
				});
			}

			private static Sprite GetSprite(Dictionary<string, Sprite> gameSprites, string spriteName)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				if (!gameSprites.TryGetValue(spriteName, out var value))
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(71, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not find sprite with name \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(spriteName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\", falling back to default dna sprite.");
					}
					log.LogError(val);
				}
				return value ?? gameSprites["IconDNA"];
			}
		}

		[HarmonyPatch(typeof(Toolbox), "LoadAll")]
		internal static class Toolbox_LoadAll
		{
			private static bool _loaded;

			[HarmonyPostfix]
			internal static void Postfix()
			{
				LoadDDSEntries();
				if (_loaded)
				{
					return;
				}
				_loaded = true;
				int count = Toolbox.Instance.allSyncDisks.Count;
				foreach (SyncDiskPreset createdSyncDiskPreset in _createdSyncDiskPresets)
				{
					createdSyncDiskPreset.syncDiskNumber = count++;
				}
				_createdSyncDiskPresets = null;
				Lazy<Il2CppArrayBase<MenuPreset>> lazy = new Lazy<Il2CppArrayBase<MenuPreset>>((Func<Il2CppArrayBase<MenuPreset>>)Resources.FindObjectsOfTypeAll<MenuPreset>);
				if (PluginController<Plugin, IPluginBindings>.Instance.Config.DebugMode)
				{
					foreach (string item in ((IEnumerable<MenuPreset>)lazy.Value).Select((MenuPreset a) => ((SoCustomComparison)a).GetPresetName()).Except<string>(from a in Enum.GetValues<SyncDiskBuilder.SyncDiskSaleLocation>()
						select a.ToString(), StringComparer.OrdinalIgnoreCase))
					{
						PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)("[UpdateRequired] Missing following new sale locations in enum: " + item));
					}
				}
				AddToMenuPresets(Lib.SyncDisks.RegisteredSyncDisks.Where((SyncDisk a) => a.MenuPresetLocations.Count > 0), lazy);
			}

			private static void AddToMenuPresets(IEnumerable<SyncDisk> syncDisk, Lazy<Il2CppArrayBase<MenuPreset>> menus)
			{
				Dictionary<string, SyncDiskPreset[]> dictionary = (from x in syncDisk.SelectMany((SyncDisk a) => a.MenuPresetLocations.Select((string saleLocation) => new
					{
						Preset = a.Preset,
						SaleLocation = saleLocation
					}))
					group x by x.SaleLocation).ToDictionary(group => group.Key, group => group.Select(item => item.Preset).ToArray(), StringComparer.OrdinalIgnoreCase);
				if (dictionary.Count == 0)
				{
					return;
				}
				foreach (MenuPreset item in menus.Value)
				{
					string presetName = ((SoCustomComparison)item).GetPresetName();
					if (dictionary.TryGetValue(presetName, out var value))
					{
						SyncDiskPreset[] array = value;
						foreach (SyncDiskPreset val in array)
						{
							item.syncDisks.Add(val);
						}
					}
				}
				Lib.SyncDisks.RegisteredSyncDisks.ForEach(delegate(SyncDisk a)
				{
					a.MenuPresetLocations = null;
				});
			}

			private static void LoadDDSEntries()
			{
				foreach (SyncDisk registeredSyncDisk in Lib.SyncDisks.RegisteredSyncDisks)
				{
					Lib.DdsStrings["evidence.syncdisks", ((Object)registeredSyncDisk.Preset).name] = registeredSyncDisk.Name;
					for (int i = 0; i < registeredSyncDisk.Effects.Length; i++)
					{
						string text = i switch
						{
							1 => registeredSyncDisk.Preset.mainEffect2Name, 
							0 => registeredSyncDisk.Preset.mainEffect1Name, 
							_ => registeredSyncDisk.Preset.mainEffect3Name, 
						};
						string text2 = i switch
						{
							1 => registeredSyncDisk.Preset.mainEffect2Description, 
							0 => registeredSyncDisk.Preset.mainEffect1Description, 
							_ => registeredSyncDisk.Preset.mainEffect3Description, 
						};
						Lib.DdsStrings.AddOrUpdateEntries("evidence.syncdisks", (text, SyncDisk.GetName(text)), (text2, SyncDisk.GetName(text2)));
					}
					for (int j = 0; j < registeredSyncDisk.UpgradeOptions.Length; j++)
					{
						List<string> val = (List<string>)(j switch
						{
							1 => registeredSyncDisk.Preset.option2UpgradeNameReferences, 
							0 => registeredSyncDisk.Preset.option1UpgradeNameReferences, 
							_ => registeredSyncDisk.Preset.option3UpgradeNameReferences, 
						});
						for (int k = 0; k < val.Count; k++)
						{
							Lib.DdsStrings["evidence.syncdisks", val[k]] = SyncDisk.GetName(val[k]);
						}
					}
					if (registeredSyncDisk.SideEffect.HasValue)
					{
						Lib.DdsStrings["evidence.syncdisks", registeredSyncDisk.SideEffect.Value.DdsIdentifier] = registeredSyncDisk.SideEffect.Value.Name;
					}
				}
				if (Lib.SyncDisks.RegisteredSyncDisks.Any())
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Loaded custom sync disk dds entries.");
				}
				foreach (DialogObject registeredDialog in Lib.Dialogs.RegisteredDialogs)
				{
					if (registeredDialog.Text != null)
					{
						Lib.DdsStrings["dds.blocks", registeredDialog.BlockId] = registeredDialog.Text;
					}
					foreach (DialogResponse response in registeredDialog.Responses)
					{
						if (response.Text != null)
						{
							Lib.DdsStrings["dds.blocks", response.BlockId] = response.Text;
						}
					}
					foreach (DDSBlockSave block in registeredDialog.Blocks)
					{
						Toolbox.Instance.allDDSBlocks.Add(((DDSComponent)block).id, block);
					}
					foreach (DDSMessageSave message in registeredDialog.Messages)
					{
						Toolbox.Instance.allDDSMessages.Add(((DDSComponent)message).id, message);
					}
				}
				if (Lib.Dialogs.RegisteredDialogs.Any())
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Loaded custom dialog dds entries.");
				}
			}
		}

		internal static List<SyncDiskPreset> _createdSyncDiskPresets = new List<SyncDiskPreset>();
	}
	internal class DialogControllerPatches
	{
		[HarmonyPatch(typeof(DialogController), "Start")]
		internal static class DialogController_Start
		{
			[HarmonyPostfix]
			internal static void Postfix(DialogController __instance)
			{
				//IL_0115: Unknown result type (might be due to invalid IL or missing references)
				//IL_011c: Expected O, but got Unknown
				foreach (DialogObject registeredDialog in Lib.Dialogs.RegisteredDialogs)
				{
					Toolbox.Instance.allDialog.Add(registeredDialog.Preset);
					if (registeredDialog.Preset.defaultOption)
					{
						Toolbox.Instance.defaultDialogOptions.Add(registeredDialog.Preset);
					}
					MethodInfo val = null;
					Enumerator<DialogPreset> enumerator2 = Toolbox.Instance.allDialog.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						DialogPreset current2 = enumerator2.Current;
						if (((Object)current2).name == "WarnNotewriter")
						{
							val = __instance.dialogRef[current2];
							break;
						}
					}
					if (val == (MethodInfo)null)
					{
						PluginController<Plugin, IPluginBindings>.Log.LogError((object)"Warn note writer is no longer present in this version of the game. Dialog mods will no longer work at the moment.");
						break;
					}
					__instance.dialogRef.Add(registeredDialog.Preset, val);
					_customDialogInterceptors[((Object)registeredDialog.Preset).name] = registeredDialog;
				}
				if (Lib.Dialogs.RegisteredDialogs.Count > 0)
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Loaded ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Lib.Dialogs.RegisteredDialogs.Count);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" custom dialogs.");
					}
					log.LogInfo(val2);
				}
			}
		}

		[HarmonyPatch(typeof(DialogController), "WarnNotewriter")]
		public class DialogController_WarnNotewriter
		{
			[HarmonyPrefix]
			internal static bool Prefix(DialogController __instance, Citizen saysTo, Interactable saysToInteractable, NewNode where, Actor saidBy, bool success, NewRoom roomRef, SideJob jobRef)
			{
				if (_customDialogInterceptors.TryGetValue(((Object)__instance.preset).name, out var value) && value.DialogLogic != null)
				{
					value.DialogLogic.OnDialogExecute(__instance, saysTo, saysToInteractable, where, saidBy, success, roomRef, jobRef);
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(DialogController), "TestSpecialCaseAvailability")]
		public class DialogController_TestSpecialCaseAvailability
		{
			[HarmonyPrefix]
			internal static bool Prefix(ref bool __result, DialogPreset preset, Citizen saysTo, SideJob jobRef)
			{
				if (_customDialogInterceptors.TryGetValue(((Object)preset).name, out var value) && value.DialogLogic != null)
				{
					__result = value.DialogLogic.IsDialogShown(preset, saysTo, jobRef);
					if (__result)
					{
						value.UpdateDynamicText();
					}
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(DialogController), "ExecuteDialog")]
		public class DialogController_ExecuteDialog
		{
			[HarmonyPrefix]
			internal static void Prefix(DialogController __instance, DialogOption dialog, Interactable saysTo, NewNode where, Actor saidBy, ref ForceSuccess forceSuccess)
			{
				//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Expected I4, but got Unknown
				if ((int)forceSuccess == 0 && _customDialogInterceptors.TryGetValue(((Object)dialog.preset).name, out var value) && value.DialogLogic != null)
				{
					Citizen saysTo2 = (Citizen)((dynamic)saysTo.isActor).Cast<Citizen>();
					forceSuccess = (ForceSuccess)(int)value.DialogLogic.ShouldDialogSucceedOverride(__instance, dialog, saysTo2, where, saidBy);
					value.UpdateDynamicText();
				}
			}
		}

		private static readonly Dictionary<string, DialogObject> _customDialogInterceptors = new Dictionary<string, DialogObject>();
	}
	internal class InputControllerPatches
	{
		[HarmonyPatch(typeof(InputController), "Update")]
		internal class InputController_Update
		{
			private static readonly List<string> _actionNames = new List<string>();

			private static readonly Dictionary<string, InteractionKey> _gameMappedKeyDictionary = new Dictionary<string, InteractionKey>();

			[HarmonyPrefix]
			internal static void Prefix(InputController __instance)
			{
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0109: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: Unknown result type (might be due to invalid IL or missing references)
				//IL_0146: Unknown result type (might be due to invalid IL or missing references)
				if (!((Behaviour)__instance).enabled || !ReInput.isReady || __instance.player == null)
				{
					return;
				}
				if (_actionNames.Count == 0)
				{
					foreach (InputAction item in MappingHelper.Instance.Actions.ToList<InputAction>())
					{
						_actionNames.Add(item.name);
					}
				}
				if (_gameMappedKeyDictionary.Count == 0)
				{
					string[] names = Enum.GetNames(typeof(InteractionKey));
					foreach (string text in names)
					{
						string text2 = text.Substring(0, 1).ToUpper() + text.Substring(1);
						if (_actionNames.Contains(text2))
						{
							_gameMappedKeyDictionary.Add(text2, Enum.Parse<InteractionKey>(text, ignoreCase: true));
						}
					}
				}
				foreach (string actionName in _actionNames)
				{
					InteractionKey key = (InteractionKey)(_gameMappedKeyDictionary.ContainsKey(actionName) ? ((int)_gameMappedKeyDictionary[actionName]) : 0);
					if (__instance.player.GetButtonDown(actionName))
					{
						Lib.InputDetection.ReportButtonStateChange(actionName, key, isDown: true);
					}
					else if (__instance.player.GetButtonUp(actionName))
					{
						Lib.InputDetection.ReportButtonStateChange(actionName, key, isDown: false);
					}
				}
			}
		}
	}
	internal class InteractionControllerPatches
	{
		[HarmonyPatch(typeof(InteractionController), "SetCurrentPlayerInteraction")]
		internal class InteractionController_SetCurrentPlayerInteraction
		{
			[HarmonyPrefix]
			internal static void Prefix(InteractionKey key, Interactable newInteractable, InteractableCurrentAction newCurrentAction, bool fpsItem = false)
			{
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				Interaction.SimpleActionArgs currentPlayerInteraction = Lib.Interaction.CurrentPlayerInteraction;
				if (!Lib.Interaction.LongActionInProgress || currentPlayerInteraction == null)
				{
					if (currentPlayerInteraction != null)
					{
						currentPlayerInteraction.CurrentAction = newCurrentAction ?? null;
						currentPlayerInteraction.Action = ((newCurrentAction != null) ? newCurrentAction.currentAction : null) ?? null;
						currentPlayerInteraction.Key = key;
						currentPlayerInteraction.InteractableInstanceData = newInteractable;
						currentPlayerInteraction.IsFpsItemTarget = fpsItem;
					}
					else
					{
						Lib.Interaction.CurrentPlayerInteraction = new Interaction.SimpleActionArgs
						{
							CurrentAction = (newCurrentAction ?? null),
							Action = (((newCurrentAction != null) ? newCurrentAction.currentAction : null) ?? null),
							Key = key,
							InteractableInstanceData = newInteractable,
							IsFpsItemTarget = fpsItem
						};
					}
				}
			}
		}

		[HarmonyPatch(typeof(Interactable), "OnInteraction", new Type[]
		{
			typeof(InteractionAction),
			typeof(Actor),
			typeof(bool),
			typeof(float)
		})]
		internal class Interactable_OnInteraction
		{
			[HarmonyPrefix]
			internal static void Prefix(Interactable __instance, out Interaction.SimpleActionArgs __state, InteractionAction action, Actor who)
			{
				__state = null;
				if (!((Object)(object)who == (Object)null) && who.isPlayer)
				{
					__state = new Interaction.SimpleActionArgs
					{
						Action = action,
						InteractableInstanceData = __instance,
						IsFpsItemTarget = false
					};
					Lib.Interaction.OnActionStarted(__state, after: false);
				}
			}

			[HarmonyPostfix]
			internal static void Postfix(Interaction.SimpleActionArgs __state, Actor who)
			{
				if (__state != null && !((Object)(object)who == (Object)null) && who.isPlayer)
				{
					Lib.Interaction.OnActionStarted(__state, after: true);
				}
			}
		}

		[HarmonyPatch(typeof(InteractionController), "SetIllegalActionActive")]
		internal static class InteractionController_SetIllegalActionActive
		{
			[HarmonyPrefix]
			internal static void Prefix(out PlayerStatus.IllegalActionStatusArgs __state, bool val)
			{
				__state = null;
				if (!((Object)(object)Player.Instance == (Object)null) && val != ((Actor)Player.Instance).illegalActionActive)
				{
					__state = new PlayerStatus.IllegalActionStatusArgs(((Actor)Player.Instance).illegalActionActive, val);
					Lib.PlayerStatus.OnSetIllegalActionStatus(__state, after: false);
				}
			}

			[HarmonyPostfix]
			internal static void Postfix(PlayerStatus.IllegalActionStatusArgs __state)
			{
				if (__state != null)
				{
					Lib.PlayerStatus.OnSetIllegalActionStatus(__state, after: true);
				}
			}
		}
	}
	internal class InteriorCreatorPatches
	{
		[HarmonyPatch(typeof(InteriorCreator), "StartLoading")]
		internal class InteriorCreator_StartLoading
		{
			[HarmonyPrefix]
			internal static void Prefix()
			{
				_isGeneratingChunk = true;
				foreach (SyncDisk item in Lib.SyncDisks.RegisteredSyncDisks.Where((SyncDisk a) => !a.EnableWorldSpawn))
				{
					if (_removedPresets == null)
					{
						_removedPresets = new List<SyncDiskPreset>();
					}
					_removedPresets.Add(item.Preset);
					Toolbox.Instance.allSyncDisks.Remove(item.Preset);
				}
			}
		}

		[HarmonyPatch(typeof(Creator), "SetComplete")]
		internal class Creator_SetComplete
		{
			[HarmonyPrefix]
			internal static void Prefix()
			{
				if (!_isGeneratingChunk)
				{
					return;
				}
				_isGeneratingChunk = false;
				if (_removedPresets == null)
				{
					return;
				}
				foreach (SyncDiskPreset removedPreset in _removedPresets)
				{
					Toolbox.Instance.allSyncDisks.Add(removedPreset);
				}
				_removedPresets = null;
			}
		}

		private static bool _isGeneratingChunk;

		private static List<SyncDiskPreset> _removedPresets;
	}
	internal class SaveStateControllerPatches
	{
		[HarmonyPatch(typeof(CityConstructor), "StartLoading")]
		internal class CityConstructor_StartLoading
		{
			[HarmonyPrefix]
			internal static void Prefix(CityConstructor __instance)
			{
				if (__instance.generateNew || RestartSafeController.Instance.newGameLoadCity)
				{
					_isStartingNewGame = true;
					SessionDataPatches.SessionData_Update.LastTime = null;
					Lib.Time.InitializeTime(reset: true);
					Lib.SaveGame.OnNewGame(after: false);
				}
				else if (RestartSafeController.Instance.loadSaveGame)
				{
					SessionDataPatches.SessionData_Update.LastTime = null;
					Lib.Time.InitializeTime(reset: true);
					FileInfo saveStateFileInfo = RestartSafeController.Instance.saveStateFileInfo;
					string path = ((saveStateFileInfo != null) ? ((FileSystemInfo)saveStateFileInfo).FullPath : null);
					Lib.SaveGame.OnLoad(path, after: false);
				}
			}
		}

		[HarmonyPatch(typeof(MurderController), "OnStartGame")]
		internal class MurderController_OnStartGame
		{
			internal static Action InteractionActionCancelled = Lib.Interaction.OnLongActionCancelled;

			internal static Action InteractionActionCompleted = Lib.Interaction.OnLongActionCompleted;

			[HarmonyPrefix]
			internal static void Prefix()
			{
				if (_isStartingNewGame)
				{
					_isStartingNewGame = false;
					Lib.SaveGame.OnNewGame(after: true);
					return;
				}
				FileInfo saveStateFileInfo = RestartSafeController.Instance.saveStateFileInfo;
				string path = ((saveStateFileInfo != null) ? ((FileSystemInfo)saveStateFileInfo).FullPath : null);
				Lib.SaveGame.OnLoad(path, after: true);
				InteractionController.Instance.OnInteractionActionCancelled -= InteractionActionCancelled.op_Implicit(InteractionActionCancelled);
				InteractionController.Instance.OnInteractionActionCancelled += InteractionActionCancelled.op_Implicit(InteractionActionCancelled);
				InteractionController.Instance.OnInteractionActionCompleted -= InteractionActionCompleted.op_Implicit(InteractionActionCompleted);
				InteractionController.Instance.OnInteractionActionCompleted += InteractionActionCompleted.op_Implicit(InteractionActionCompleted);
			}
		}

		[HarmonyPatch(typeof(MainMenuController), "OnMenuComponentSwitchComplete")]
		internal class MainMenuController_OnMenuComponentSwitchComplete
		{
			private static Component? _previousComponentCompleted;

			private static bool _wasDirty;

			[HarmonyPrefix]
			internal static bool Prefix(MainMenuController __instance)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				if (__instance.currentComponent == null || !_previousComponentCompleted.HasValue)
				{
					return true;
				}
				if (__instance.currentComponent.component == __instance.previousComponent)
				{
					return true;
				}
				if ((Component?)__instance.currentComponent.component == _previousComponentCompleted && SessionData.Instance.dirtyScene == _wasDirty)
				{
					return false;
				}
				return true;
			}

			[HarmonyPostfix]
			internal static void Postfix(MainMenuController __instance)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				MenuComponent currentComponent = __instance.currentComponent;
				_previousComponentCompleted = ((currentComponent != null) ? new Component?(currentComponent.component) : null);
				_wasDirty = SessionData.Instance.dirtyScene;
			}
		}

		[HarmonyPatch(typeof(SaveStateController), "CaptureSaveStateAsync")]
		internal class SaveStateController_CaptureSaveStateAsync
		{
			[HarmonyPrefix]
			internal static void Prefix(string path)
			{
				if (path != null && Game.Instance.useSaveGameCompression && path.EndsWith(".sod"))
				{
					path += "b";
				}
				path = path.Replace('/', '\\');
				Lib.SaveGame.OnSave(path, after: false);
			}

			[HarmonyPostfix]
			internal static void Postfix(string path)
			{
				if (path != null && Game.Instance.useSaveGameCompression && path.EndsWith(".sod"))
				{
					path += "b";
				}
				path = path.Replace('/', '\\');
				Lib.SaveGame.OnSave(path, after: true);
			}
		}

		[HarmonyPatch(typeof(MainMenuController), "DeleteSave")]
		internal class MainMenuController_DeleteSave
		{
			private static bool _delete;

			private static FileInfo _fileInfo;

			[HarmonyPrefix]
			internal static void Prefix(MainMenuController __instance)
			{
				if ((Object)(object)__instance.selectedSave != (Object)null && !__instance.selectedSave.isInternal && __instance.selectedSave.info != null && File.Exists(((FileSystemInfo)__instance.selectedSave.info).FullName))
				{
					_delete = true;
					_fileInfo = __instance.selectedSave.info;
					Lib.SaveGame.OnDelete(((FileSystemInfo)_fileInfo).FullName, after: false);
				}
			}

			[HarmonyPostfix]
			internal static void Postfix()
			{
				if (_delete)
				{
					_delete = false;
					string fullPath = ((FileSystemInfo)_fileInfo).FullPath;
					_fileInfo = null;
					Lib.SaveGame.OnDelete(fullPath, after: true);
				}
			}
		}

		private static bool _isStartingNewGame;
	}
	internal class SessionDataPatches
	{
		[HarmonyPatch(typeof(SessionData), "PauseGame")]
		internal static class SessionDataPauseGame
		{
			[HarmonyPostfix]
			internal static void Postfix()
			{
				if (!_wasPaused)
				{
					_wasPaused = true;
					Lib.Time.IsGamePaused = true;
					Lib.Time.OnPauseModeChanged(paused: true);
				}
			}
		}

		[HarmonyPatch(typeof(SessionData), "ResumeGame")]
		internal static class SessionDataResumeGame
		{
			[HarmonyPostfix]
			internal static void Postfix()
			{
				if (_wasPaused)
				{
					_wasPaused = false;
					Lib.Time.IsGamePaused = false;
					Lib.Time.OnPauseModeChanged(paused: false);
				}
			}
		}

		[HarmonyPatch(typeof(SessionData), "Update")]
		internal static class SessionData_Update
		{
			internal static Time.TimeData? LastTime;

			[HarmonyPostfix]
			internal static void Postfix()
			{
				if (SessionData.Instance.play)
				{
					if (!Lib.Time.IsInitialized)
					{
						Lib.Time.InitializeTime();
					}
					Time.TimeData currentDateTime = Lib.Time.CurrentDateTime;
					if (!LastTime.HasValue)
					{
						LastTime = currentDateTime;
					}
					if (!LastTime.Equals(currentDateTime))
					{
						Lib.Time.OnTimeChanged(LastTime.Value, currentDateTime);
						LastTime = currentDateTime;
					}
				}
			}
		}

		[HarmonyPatch(typeof(SessionData), "Start")]
		internal static class SessionData_Start
		{
			[HarmonyPostfix]
			internal static void Postfix()
			{
				Lib.Time.InitializeTime();
			}
		}

		private static bool _wasPaused;
	}
	internal class UpgradesControllerPatches
	{
		[HarmonyPatch(typeof(UpgradesController), "InstallSyncDisk")]
		internal class InstallSyncDiskHook
		{
			[HarmonyPrefix]
			internal static void Prefix(Upgrades application)
			{
				if (application != null && !((SoCustomComparison)(object)application.preset == (SoCustomComparison)null))
				{
					Lib.SyncDisks.RaiseSyncDiskEvent(SyncDisks.SyncDiskEvent.OnInstall, after: false, application);
				}
			}

			[HarmonyPostfix]
			public static void Postfix(Upgrades application)
			{
				if (application != null && !((SoCustomComparison)(object)application.preset == (SoCustomComparison)null))
				{
					Lib.SyncDisks.RaiseSyncDiskEvent(SyncDisks.SyncDiskEvent.OnInstall, after: true, application);
				}
			}
		}

		[HarmonyPatch(typeof(UpgradesController), "UpgradeSyncDisk")]
		internal class UpgradeSyncDiskHook
		{
			[HarmonyPrefix]
			public static void Prefix(Upgrades upgradeThis)
			{
				if (upgradeThis != null && !((SoCustomComparison)(object)upgradeThis.preset == (SoCustomComparison)null))
				{
					Lib.SyncDisks.RaiseSyncDiskEvent(SyncDisks.SyncDiskEvent.OnUpgrade, after: false, upgradeThis);
				}
			}

			[HarmonyPostfix]
			public static void Postfix(Upgrades upgradeThis)
			{
				if (upgradeThis != null && !((SoCustomComparison)(object)upgradeThis.preset == (SoCustomComparison)null))
				{
					Lib.SyncDisks.RaiseSyncDiskEvent(SyncDisks.SyncDiskEvent.OnUpgrade, after: true, upgradeThis);
				}
			}
		}

		[HarmonyPatch(typeof(UpgradesController), "UninstallSyncDisk")]
		internal class UninstallSyncDiskHook
		{
			[HarmonyPrefix]
			public static void Prefix(Upgrades removal)
			{
				if (removal != null && !((SoCustomComparison)(object)removal.preset == (SoCustomComparison)null))
				{
					Lib.SyncDisks.RaiseSyncDiskEvent(SyncDisks.SyncDiskEvent.OnUninstall, after: false, removal);
				}
			}

			[HarmonyPostfix]
			public static void Postfix(Upgrades removal)
			{
				if (removal != null && !((SoCustomComparison)(object)removal.preset == (SoCustomComparison)null))
				{
					Lib.SyncDisks.RaiseSyncDiskEvent(SyncDisks.SyncDiskEvent.OnUninstall, after: true, removal);
				}
			}
		}
	}
}
namespace SOD.Common.ConfigBindings
{
	public interface IPluginBindings
	{
		[Binding(false, "Enables extra logging for development.", null)]
		bool DebugMode { get; set; }
	}
}
namespace SOD.Common.Helpers
{
	public sealed class DdsStrings
	{
		public string this[string dictionary, string key]
		{
			get
			{
				if ((Object)(object)Strings.Instance == (Object)null || Strings.stringTable == null)
				{
					return null;
				}
				if (!Strings.textFilesLoaded)
				{
					Strings.Instance.LoadTextFiles();
				}
				Dictionary<string, DisplayString> val = default(Dictionary<string, DisplayString>);
				DisplayString val2 = default(DisplayString);
				if (Strings.stringTable.TryGetValue(dictionary.ToLower(), ref val) && val.TryGetValue(key.ToLower(), ref val2))
				{
					return val2.displayStr;
				}
				return null;
			}
			set
			{
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Expected O, but got Unknown
				//IL_009a: 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_00ab: Expected O, but got Unknown
				if ((Object)(object)Strings.Instance == (Object)null || Strings.stringTable == null)
				{
					throw new Exception("DDS Strings are not yet initialized at this point.");
				}
				if (!Strings.textFilesLoaded)
				{
					Strings.Instance.LoadTextFiles();
				}
				string text = dictionary.ToLower();
				string text2 = key.ToLower();
				Dictionary<string, DisplayString> val = default(Dictionary<string, DisplayString>);
				if (Strings.stringTable.TryGetValue(text, ref val))
				{
					DisplayString val2 = default(DisplayString);
					if (val.TryGetValue(text2, ref val2))
					{
						if (value == null)
						{
							val.Remove(text2);
							if (val.Count == 0)
							{
								Strings.stringTable.Remove(text);
							}
						}
						else
						{
							val2.displayStr = value;
						}
					}
					else if (value == null)
					{
						if (val.Count == 0)
						{
							Strings.stringTable.Remove(text);
						}
					}
					else
					{
						val[text2] = new DisplayString
						{
							displayStr = value
						};
					}
				}
				else if (value != null)
				{
					Dictionary<string, DisplayString> val3 = new Dictionary<string, DisplayString>();
					val3.Add(text2, new DisplayString
					{
						displayStr = value
					});
					Strings.stringTable.Add(text, val3);
				}
			}
		}

		internal DdsStrings()
		{
		}

		public void AddOrUpdate(string dictionary, string key, string value)
		{
			this[dictionary, key] = value;
		}

		public void Remove(string dictionary, string key)
		{
			this[dictionary, key] = null;
		}

		public string Get(string dictionary, string key)
		{
			return this[dictionary, key] ?? string.Empty;
		}

		public bool Exists(string dictionary, string key)
		{
			return this[dictionary, key] != null;
		}

		public void AddOrUpdateEntries(string dictionary, params (string key, string value)[] entries)
		{
			if (entries != null)
			{
				for (int i = 0; i < entries.Length; i++)
				{
					(string key, string value) tuple = entries[i];
					string item = tuple.key;
					string item2 = tuple.value;
					this[dictionary, item] = item2;
				}
			}
		}

		public void RemoveEntries(string dictionary, params string[] entries)
		{
			if (entries != null)
			{
				foreach (string key in entries)
				{
					this[dictionary, key] = null;
				}
			}
		}
	}
	public sealed class Dialog
	{
		internal List<DialogObject> RegisteredDialogs = new List<DialogObject>();

		public IReadOnlyList<DialogObject> KnownModDialogs => RegisteredDialogs;

		internal Dialog()
		{
		}

		public DialogBuilder Builder(string dialogName = null)
		{
			return new DialogBuilder(dialogName);
		}
	}
	public sealed class GameMessage
	{
		private readonly HashSet<string> _queuedPlayerSpeechMessages = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal GameMessage()
		{
		}

		public void Broadcast(string message, GameMessageType messageType = 0, Icon icon = 21, Color? color = null, float delay = 0f)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!color.HasValue)
			{
				color = InterfaceControls.Instance.messageRed;
			}
			InterfaceController.Instance.NewGameMessage(messageType, 0, message, icon, (AudioEvent)null, true, color.Value, -1, delay, (RectTransform)null, (PingOnComplete)0, (Evidence)null, (List<DataKey>)null, (Sprite)null);
		}

		public void ShowPlayerSpeech(string message, float durationSec, bool doNotQueueMultiple = true)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (!doNotQueueMultiple || !_queuedPlayerSpeechMessages.Contains(message))
			{
				_queuedPlayerSpeechMessages.Add(message);
				((Actor)Player.Instance).speechController.Speak("", "temp", false, false, true, 0f, true, Color.white, (Human)null, false, false, (SideJob)null, (DialogPreset)null, (AISpeechPreset)null, (Interactable)null);
				RuntimeHelper.StartCoroutine(ShowPlayerSpeechWaitForBubble(message, durationSec));
			}
		}

		private IEnumerator ShowPlayerSpeechWaitForBubble(string message, float durationSec)
		{
			SpeechController speechController = ((Actor)Player.Instance).speechController;
			while (UnityHelpers.IsNullOrDestroyed((object)speechController.activeSpeechBubble, true) || speechController.activeSpeechBubble.actualString != string.Empty)
			{
				yield return (object)new WaitForEndOfFrame();
			}
			SpeechBubbleController activeSpeechBubble = speechController.activeSpeechBubble;
			activeSpeechBubble.actualString = message;
			activeSpeechBubble.oncreenTime = durationSec;
			while (!UnityHelpers.IsNullOrDestroyed((object)speechController.activeSpeechBubble, true) && speechController.activeSpeechBubble.actualString == message)
			{
				yield return (object)new WaitForEndOfFrame();
			}
			_queuedPlayerSpeechMessages.Remove(message);
		}
	}
	public sealed class InputDetection
	{
		public event EventHandler<InputDetectionEventArgs> OnButtonStateChanged;

		internal InputDetection()
		{
		}

		internal void ReportButtonStateChange(string actionName, InteractionKey key, bool isDown)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			this.OnButtonStateChanged?.Invoke(this, new InputDetectionEventArgs(actionName, key, isDown));
		}
	}
	public sealed class InputDetectionEventArgs : EventArgs
	{
		public string ActionName { get; }

		public InteractionKey Key { get; }

		public bool IsDown { get; }

		internal InputDetectionEventArgs(string actionName, InteractionKey key, bool isDown)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			ActionName = actionName;
			Key = key;
			IsDown = isDown;
		}
	}
	public sealed class Interaction
	{
		public class SimpleActionArgs : EventArgs
		{
			internal InteractionAction Action { get; set; }

			internal InteractableCurrentAction CurrentAction { get; set; }

			public InteractionKey Key { get; set; }

			public InteractableInstanceData InteractableInstanceData { get; internal set; }

			public bool IsFpsItemTarget { get; internal set; }

			internal SimpleActionArgs()
			{
			}

			public bool TryGetAction(out InteractionAction action)
			{
				action = Action;
				return action != null;
			}

			public bool TryGetCurrentAction(out InteractableCurrentAction currentAction)
			{
				currentAction = CurrentAction;
				return currentAction != null;
			}
		}

		internal SimpleActionArgs CurrentPlayerInteraction;

		internal bool LongActionInProgress;

		public event EventHandler<SimpleActionArgs> OnBeforeActionStarted;

		public event EventHandler<SimpleActionArgs> OnAfterActionStarted;

		public event EventHandler<SimpleActionArgs> OnAfterLongActionCancelled;

		public event EventHandler<SimpleActionArgs> OnAfterLongActionCompleted;

		internal Interaction()
		{
		}

		internal void OnLongActionCancelled()
		{
			LongActionInProgress = false;
			this.OnAfterLongActionCancelled?.Invoke(this, CurrentPlayerInteraction);
		}

		internal void OnLongActionCompleted()
		{
			LongActionInProgress = false;
			this.OnAfterLongActionCompleted?.Invoke(this, CurrentPlayerInteraction);
		}

		internal void OnActionStarted(SimpleActionArgs args, bool after)
		{
			if (after)
			{
				this.OnAfterActionStarted?.Invoke(this, args);
			}
			else
			{
				this.OnBeforeActionStarted?.Invoke(this, args);
			}
		}
	}
	public sealed class PlayerStatus
	{
		public sealed class IllegalActionStatusArgs : EventArgs
		{
			public bool PreviousIllegalStatus { get; }

			public bool NewIllegalStatus { get; }

			internal IllegalActionStatusArgs(bool previous, bool @new)
			{
				PreviousIllegalStatus = previous;
				NewIllegalStatus = @new;
			}
		}

		internal Dictionary<string, IllegalStatusModifier> IllegalStatusModifierDictionary { get; private set; }

		public event EventHandler<IllegalActionStatusArgs> OnBeforeSetIllegalStatus;

		public event EventHandler<IllegalActionStatusArgs> OnAfterSetIllegalStatus;

		internal PlayerStatus()
		{
		}

		public void SetIllegalStatusModifier(string key, TimeSpan? duration = null, bool overwrite = false)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentException("Key cannot be null or empty.", "key");
			}
			if (IllegalStatusModifierDictionary == null)
			{
				Dictionary<string, IllegalStatusModifier> dictionary2 = (IllegalStatusModifierDictionary = new Dictionary<string, IllegalStatusModifier>());
			}
			if (IllegalStatusModifierDictionary.TryGetValue(key, out var value))
			{
				if (!overwrite)
				{
					return;
				}
				value.Stop();
				IllegalStatusModifierDictionary.Remove(key);
			}
			value = new IllegalStatusModifier(key, duration);
			IllegalStatusModifierDictionary.Add(key, value);
			value.Start();
			UpdatePlayerIllegalStatus();
		}

		public void RemoveIllegalStatusModifier(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentException("Key cannot be null or empty.", "key");
			}
			if (IllegalStatusModifierDictionary != null && IllegalStatusModifierDictionary.TryGetValue(key, out var value))
			{
				value.Stop();
				IllegalStatusModifierDictionary.Remove(key);
				UpdatePlayerIllegalStatus();
			}
		}

		public bool ModifierExists(string key, out TimeSpan? timeLeft)
		{
			timeLeft = null;
			if (IllegalStatusModifierDictionary != null && IllegalStatusModifierDictionary.TryGetValue(key, out var value))
			{
				if (value.TimeRemainingSec > 0f)
				{
					timeLeft = TimeSpan.FromSeconds(value.TimeRemainingSec);
				}
				return true;
			}
			return false;
		}

		internal void UpdatePlayerIllegalStatus()
		{
			if (IllegalStatusModifierDictionary != null && IllegalStatusModifierDictionary.Any())
			{
				AdjustIllegalStatus(((Actor)Player.Instance).illegalStatus, newStatus: true);
			}
			else
			{
				AdjustIllegalStatus(((Actor)Player.Instance).illegalStatus, newStatus: false);
			}
		}

		internal void Load(string path)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(path);
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "playerstatus_" + uniqueString + ".json");
			if (!File.Exists(savestoreDirectoryPath))
			{
				return;
			}
			List<IllegalStatusModifier.JsonData> list = JsonSerializer.Deserialize<List<IllegalStatusModifier.JsonData>>(File.ReadAllText(savestoreDirectoryPath));
			if (list.Count <= 0)
			{
				return;
			}
			IllegalStatusModifierDictionary = new Dictionary<string, IllegalStatusModifier>();
			foreach (IllegalStatusModifier.JsonData item in list)
			{
				IllegalStatusModifier illegalStatusModifier = new IllegalStatusModifier(item.Key, (item.Time == 0f) ? null : new TimeSpan?(TimeSpan.FromSeconds(item.Time)));
				IllegalStatusModifierDictionary[item.Key] = illegalStatusModifier;
				illegalStatusModifier.Start();
			}
			UpdatePlayerIllegalStatus();
		}

		internal void Save(string path)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(path);
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "playerstatus_" + uniqueString + ".json");
			if (IllegalStatusModifierDictionary == null || IllegalStatusModifierDictionary.Count == 0)
			{
				if (File.Exists(savestoreDirectoryPath))
				{
					File.Delete(savestoreDirectoryPath);
				}
				return;
			}
			string contents = JsonSerializer.Serialize(IllegalStatusModifierDictionary.Select((KeyValuePair<string, IllegalStatusModifier> a) => new IllegalStatusModifier.JsonData
			{
				Key = a.Key,
				Time = a.Value.TimeRemainingSec
			}).ToList(), new JsonSerializerOptions
			{
				WriteIndented = false
			});
			File.WriteAllText(savestoreDirectoryPath, contents);
		}

		internal void ResetStatusTracking()
		{
			if (IllegalStatusModifierDictionary == null)
			{
				return;
			}
			foreach (IllegalStatusModifier value in IllegalStatusModifierDictionary.Values)
			{
				value.Stop();
			}
			IllegalStatusModifierDictionary = null;
		}

		private static void AdjustIllegalStatus(bool previousStatus, bool newStatus)
		{
			if (previousStatus != newStatus)
			{
				IllegalActionStatusArgs eventArgs = new IllegalActionStatusArgs(previousStatus, newStatus);
				Lib.PlayerStatus.OnSetIllegalActionStatus(eventArgs, after: false);
				((Actor)Player.Instance).illegalActionActive = newStatus;
				Player.Instance.illegalActionTimer = (newStatus ? float.MaxValue : 0f);
				((Actor)Player.Instance).UpdateIllegalStatus();
				Lib.PlayerStatus.OnSetIllegalActionStatus(eventArgs, newStatus);
			}
		}

		internal void OnSetIllegalActionStatus(IllegalActionStatusArgs eventArgs, bool after)
		{
			if (after)
			{
				this.OnAfterSetIllegalStatus?.Invoke(this, eventArgs);
			}
			else
			{
				this.OnBeforeSetIllegalStatus?.Invoke(this, eventArgs);
			}
		}
	}
	public sealed class PluginDetection
	{
		public bool AllPluginsFinishedLoading { get; private set; }

		public event EventHandler OnAllPluginsFinishedLoading;

		internal PluginDetection()
		{
			((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Finished += OnAllPluginsFinishedLoadingListener;
		}

		private void OnAllPluginsFinishedLoadingListener()
		{
			AllPluginsFinishedLoading = true;
			this.OnAllPluginsFinishedLoading?.Invoke(this, EventArgs.Empty);
			((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Finished -= OnAllPluginsFinishedLoadingListener;
		}

		public bool IsPluginLoaded(string pluginGuid)
		{
			return ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey(pluginGuid);
		}

		public bool TryGetPluginInfo(string pluginGuid, out PluginInfo info)
		{
			return ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue(pluginGuid, out info);
		}

		public PluginInfo GetPluginInfo(string pluginGuid)
		{
			if (!TryGetPluginInfo(pluginGuid, out var info))
			{
				throw new KeyNotFoundException("Plugin GUID (" + pluginGuid + ") not found.");
			}
			return info;
		}

		public T GetPluginConfigEntryValue<T>(string pluginGuid, string section, string key)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<T> val = default(ConfigEntry<T>);
			if (!((BasePlugin)ReflectionExtensions.TryCast(GetPluginInfo(pluginGuid).Instance, typeof(BasePlugin))).Config.TryGetEntry<T>(section, key, ref val))
			{
				throw new InvalidOperationException($"No configuration entry found for ({section}, {key}).");
			}
			return val.Value;
		}

		public void AddPluginConfigEntryChangedListener(string pluginGuid, Action<SettingChangedEventArgs> listener)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			((BasePlugin)ReflectionExtensions.TryCast(GetPluginInfo(pluginGuid).Instance, typeof(BasePlugin))).Config.SettingChanged += delegate(object? _, SettingChangedEventArgs args)
			{
				listener(args);
			};
		}
	}
	public sealed class SaveGame
	{
		private const uint FnvPrime = 16777619u;

		private const uint FnvOffsetBasis = 2166136261u;

		internal bool IsSaving { get; private set; }

		public event EventHandler<SaveGameArgs> OnBeforeSave;

		public event EventHandler<SaveGameArgs> OnAfterSave;

		public event EventHandler<SaveGameArgs> OnBeforeLoad;

		public event EventHandler<SaveGameArgs> OnAfterLoad;

		public event EventHandler<SaveGameArgs> OnBeforeDelete;

		public event EventHandler<SaveGameArgs> OnAfterDelete;

		public event EventHandler OnBeforeNewGame;

		public event EventHandler OnAfterNewGame;

		internal SaveGame()
		{
		}

		public string GetUniqueString(string value)
		{
			return GetFnvHash(value).ToString();
		}

		public uint GetUniqueNumber(string value)
		{
			return GetFnvHash(value);
		}

		private static uint GetFnvHash(string value)
		{
			if (value == null)
			{
				throw new ArgumentNullException("value");
			}
			uint num = 2166136261u;
			foreach (char c in value)
			{
				num ^= c;
				num *= 16777619;
			}
			return num;
		}

		public string GetSavestoreDirectoryPath(Assembly executingAssembly, string fileName)
		{
			string text = GetSavestoreDirectoryPath(executingAssembly);
			if (!string.IsNullOrWhiteSpace(fileName))
			{
				text = Path.Combine(text, fileName);
			}
			return text;
		}

		public string GetSavestoreDirectoryPath(Assembly executingAssembly)
		{
			string text = Path.Combine(Path.GetDirectoryName(executingAssembly.Location), "Savestore");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			return text;
		}

		public string GetPluginDirectoryPath(Assembly executingAssembly)
		{
			string directoryName = Path.GetDirectoryName(executingAssembly.Location);
			if (!Directory.Exists(directoryName))
			{
				throw new Exception("There is no plugin directory for this assembly location: " + directoryName);
			}
			return directoryName;
		}

		internal void OnSave(string path, bool after)
		{
			if (after)
			{
				this.OnAfterSave?.Invoke(this, new SaveGameArgs(path));
			}
			else
			{
				this.OnBeforeSave?.Invoke(this, new SaveGameArgs(path));
			}
			if (after)
			{
				IsSaving = false;
				if (Lib.PlayerStatus.IllegalStatusModifierDictionary != null && Lib.PlayerStatus.IllegalStatusModifierDictionary.Count > 0)
				{
					Player.Instance.illegalActionTimer = float.MaxValue;
				}
				Lib.SyncDisks.CheckForSyncDiskData(onLoad: false, path);
				Lib.PlayerStatus.Save(path);
			}
			else
			{
				IsSaving = true;
				if (Lib.PlayerStatus.IllegalStatusModifierDictionary != null && Lib.PlayerStatus.IllegalStatusModifierDictionary.Count > 0)
				{
					Player.Instance.illegalActionTimer = 1f;
				}
			}
		}

		internal void OnLoad(string path, bool after)
		{
			if (after)
			{
				this.OnAfterLoad?.Invoke(this, new SaveGameArgs(path));
			}
			else
			{
				this.OnBeforeLoad?.Invoke(this, new SaveGameArgs(path));
			}
			if (after)
			{
				Lib.SyncDisks.CheckForSyncDiskData(onLoad: true, path);
				Lib.PlayerStatus.Load(path);
			}
			else
			{
				Lib.PlayerStatus.ResetStatusTracking();
			}
		}

		internal void OnDelete(string path, bool after)
		{
			if (after)
			{
				this.OnAfterDelete?.Invoke(this, new SaveGameArgs(path));
			}
			else
			{
				this.OnBeforeDelete?.Invoke(this, new SaveGameArgs(path));
			}
			string uniqueString = Lib.SaveGame.GetUniqueString(path);
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "syncdiskdata_" + uniqueString + ".json");
			if (File.Exists(savestoreDirectoryPath))
			{
				File.Delete(savestoreDirectoryPath);
			}
			string savestoreDirectoryPath2 = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "playerstatus_" + uniqueString + ".json");
			if (File.Exists(savestoreDirectoryPath2))
			{
				File.Delete(savestoreDirectoryPath2);
			}
		}

		internal void OnNewGame(bool after)
		{
			if (after)
			{
				this.OnAfterNewGame?.Invoke(this, EventArgs.Empty);
			}
			else
			{
				Lib.PlayerStatus.ResetStatusTracking();
				this.OnBeforeNewGame?.Invoke(this, EventArgs.Empty);
			}
			Lib.SyncDisks.InstalledSyncDisks.Clear();
		}
	}
	public sealed class SaveGameArgs : EventArgs
	{
		public string FilePath { get; }

		internal SaveGameArgs(string filePath)
		{
			FilePath = filePath;
		}
	}
	public sealed class SyncDisks
	{
		internal class InstalledSyncDiskData
		{
			public string SyncDiskName { get; set; }

			public string Effect { get; set; }

			public List<string> UpgradeOptions { get; set; }

			public InstalledSyncDiskData()
			{
			}

			internal InstalledSyncDiskData(string name, string effectName)
			{
				SyncDiskName = name;
				Effect = effectName;
				UpgradeOptions = new List<string>();
			}
		}

		internal class SyncDiskJsonData
		{
			public List<InstalledSyncDiskData> SyncDiskData { get; set; }
		}

		internal enum SyncDiskEvent
		{
			OnInstall,
			OnUninstall,
			OnUpgrade
		}

		public readonly struct Effect : IEquatable<Effect>
		{
			public readonly int Id;

			public readonly string Name;

			internal readonly string DdsIdentifier;

			internal Effect(int id, string name)
			{
				Id = id;
				Name = SyncDisk.GetName(name);
				DdsIdentifier = name;
			}

			public bool Equals(Effect other)
			{
				return Id == other.Id;
			}

			public override bool Equals(object obj)
			{
				if (obj is Effect other)
				{
					return Equals(other);
				}
				return false;
			}

			public static bool operator ==(Effect left, Effect right)
			{
				return left.Equals(right);
			}

			public static bool operator !=(Effect left, Effect right)
			{
				return !(left == right);
			}

			public override int GetHashCode()
			{
				return Id.GetHashCode();
			}
		}

		public readonly struct UpgradeOption : IEquatable<UpgradeOption>
		{
			public readonly int? Id1;

			public readonly int? Id2;

			public readonly int? Id3;

			public readonly string Name1;

			public readonly string Name2;

			public readonly string Name3;

			internal readonly SyncDiskBuilder.Options Options;

			internal bool HasOptions
			{
				get
				{
					if (string.IsNullOrWhiteSpace(Name1) && string.IsNullOrWhiteSpace(Name2))
					{
						return !string.IsNullOrWhiteSpace(Name3);
					}
					return true;
				}
			}

			internal UpgradeOption(SyncDiskBuilder.Options options)
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Expected I4, but got Unknown
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Expected I4, but got Unknown
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Expected I4, but got Unknown
				Id1 = null;
				Id2 = null;
				Id3 = null;
				Name1 = null;
				Name2 = null;
				Name3 = null;
				Options = options;
				if (!string.IsNullOrWhiteSpace(options.Option1))
				{
					Id1 = (int)options.Option1Effect;
					Name1 = SyncDisk.GetName(options.Option1);
				}
				if (!string.IsNullOrWhiteSpace(options.Option2))
				{
					Id2 = (int)options.Option2Effect;
					Name2 = SyncDisk.GetName(options.Option2);
				}
				if (!string.IsNullOrWhiteSpace(options.Option3))
				{
					Id3 = (int)options.Option3Effect;
					Name3 = SyncDisk.GetName(options.Option3);
				}
			}

			public bool Equals(UpgradeOption other)
			{
				if (Id1 == other.Id1 && Id2 == other.Id2)
				{
					return Id3 == other.Id3;
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is UpgradeOption other)
				{
					return Equals(other);
				}
				return false;
			}

			public static bool operator ==(UpgradeOption left, UpgradeOption right)
			{
				return left.Equals(right);
			}

			public static bool operator !=(UpgradeOption left, UpgradeOption right)
			{
				return !(left == right);
			}

			public override int GetHashCode()
			{
				return HashCode.Combine(Id1, Id2, Id3);
			}
		}

		private static int? _currentSyncDiskEffectId;

		private static int? _currentSyncDiskOptionId;

		internal readonly Dictionary<string, List<InstalledSyncDiskData>> InstalledSyncDisks = new Dictionary<string, List<InstalledSyncDiskData>>();

		internal List<SyncDisk> RegisteredSyncDisks = new List<SyncDisk>();

		public IReadOnlyList<SyncDisk> KnownModSyncDisks => RegisteredSyncDisks;

		public event EventHandler<SyncDiskArgs> OnBeforeSyncDiskInstalled;

		public event EventHandler<SyncDiskArgs> OnAfterSyncDiskInstalled;

		public event EventHandler<SyncDiskArgs> OnBeforeSyncDiskUpgraded;

		public event EventHandler<SyncDiskArgs> OnAfterSyncDiskUpgraded;

		public event EventHandler<SyncDiskArgs> OnBeforeSyncDiskUninstalled;

		public event EventHandler<SyncDiskArgs> OnAfterSyncDiskUninstalled;

		internal SyncDisks()
		{
		}

		internal static int GetNewSyncDiskEffectId()
		{
			if (!_currentSyncDiskEffectId.HasValue)
			{
				int[] source = (int[])Enum.GetValues(typeof(Effect));
				_currentSyncDiskEffectId = source.DefaultIfEmpty().Max();
			}
			_currentSyncDiskEffectId++;
			return _currentSyncDiskEffectId.Value;
		}

		internal static int GetNewSyncDiskOptionId()
		{
			if (!_currentSyncDiskOptionId.HasValue)
			{
				int[] source = (int[])Enum.GetValues(typeof(UpgradeEffect));
				_currentSyncDiskOptionId = source.DefaultIfEmpty().Max();
			}
			_currentSyncDiskOptionId++;
			return _currentSyncDiskOptionId.Value;
		}

		public SyncDiskBuilder Builder(string syncDiskName, string pluginGuid, bool reRaiseEventsOnSaveLoad = true)
		{
			if (string.IsNullOrWhiteSpace(syncDiskName))
			{
				throw new ArgumentException("Parameter cannot be empty or whitespace.", "syncDiskName");
			}
			if (string.IsNullOrWhiteSpace(pluginGuid))
			{
				throw new ArgumentException("Parameter cannot be empty or whitespace.", "pluginGuid");
			}
			return new SyncDiskBuilder(syncDiskName, pluginGuid, reRaiseEventsOnSaveLoad);
		}

		internal void CheckForSyncDiskData(bool onLoad, string saveFilePath)
		{
			//IL_0501: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Expected O, but got Unknown
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Expected O, but got Unknown
			if (onLoad)
			{
				InstalledSyncDisks.Clear();
			}
			string uniqueString = Lib.SaveGame.GetUniqueString(saveFilePath);
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "syncdiskdata_" + uniqueString + ".json");
			if (onLoad && !File.Exists(savestoreDirectoryPath))
			{
				return;
			}
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val;
			if (onLoad)
			{
				SyncDiskJsonData syncDiskJsonData = JsonSerializer.Deserialize<SyncDiskJsonData>(File.ReadAllText(savestoreDirectoryPath));
				if (syncDiskJsonData == null || syncDiskJsonData.SyncDiskData == null)
				{
					return;
				}
				{
					foreach (InstalledSyncDiskData disk in syncDiskJsonData.SyncDiskData)
					{
						SyncDisk syncDisk = RegisteredSyncDisks.FirstOrDefault((SyncDisk a) => ((Object)a.Preset).name.Equals(disk.SyncDiskName));
						if (syncDisk == null)
						{
							ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
							val = new BepInExInfoLogInterpolatedStringHandler(67, 1, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Skipped]: Could not find registered sync disk with preset name \"");
								((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(disk.SyncDiskName));
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
							}
							log.LogInfo(val);
							continue;
						}
						if (!syncDisk.Effects.Any((Effect a) => a.Name.Equals(disk.Effect)))
						{
							ManualLogSource log2 = PluginController<Plugin, IPluginBindings>.Log;
							val = new BepInExInfoLogInterpolatedStringHandler(56, 2, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Skipped]: Could not find effect \"");
								((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(disk.Effect);
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" within sync disk \"");
								((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(disk.SyncDiskName));
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
							}
							log2.LogInfo(val);
							continue;
						}
						Effect effect = syncDisk.Effects.First((Effect a) => a.Name.Equals(disk.Effect));
						int num = Array.IndexOf(syncDisk.Effects, effect);
						this.OnAfterSyncDiskInstalled?.Invoke(this, new SyncDiskArgs(syncDisk, effect));
						ManualLogSource log3 = PluginController<Plugin, IPluginBindings>.Log;
						val = new BepInExInfoLogInterpolatedStringHandler(58, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded savegame, raised install event for custom disk: ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(disk.SyncDiskName));
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" | ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(effect.Name);
						}
						log3.LogInfo(val);
						if (disk.UpgradeOptions != null && syncDisk.UpgradeOptions.Length > num)
						{
							UpgradeOption upgradeOption = syncDisk.UpgradeOptions[num];
							foreach (string upgradeOption2 in disk.UpgradeOptions)
							{
								int? num2 = ((upgradeOption.Name1 != null && upgradeOption.Name1.Equals(upgradeOption2)) ? upgradeOption.Id1 : ((upgradeOption.Name2 != null && upgradeOption.Name2.Equals(upgradeOption2)) ? upgradeOption.Id2 : upgradeOption.Id3));
								if (!num2.HasValue)
								{
									ManualLogSource log4 = PluginController<Plugin, IPluginBindings>.Log;
									val = new BepInExInfoLogInterpolatedStringHandler(64, 2, ref flag);
									if (flag)
									{
										((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Skipped]: Could not find upgrade option \"");
										((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(upgradeOption2);
										((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" within sync disk \"");
										((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(disk.SyncDiskName));
										((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
									}
									log4.LogInfo(val);
									continue;
								}
								this.OnAfterSyncDiskUpgraded?.Invoke(this, new SyncDiskArgs(syncDisk, effect, new SyncDiskArgs.Option(num2.Value, upgradeOption2)));
								ManualLogSource log5 = PluginController<Plugin, IPluginBindings>.Log;
								val = new BepInExInfoLogInterpolatedStringHandler(54, 3, ref flag);
								if (flag)
								{
									((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded savegame, raised upgrade event for disk: ");
									((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(disk.SyncDiskName));
									((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" | ");
									((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(effect.Name);
									((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" | ");
									((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(upgradeOption2);
								}
								log5.LogInfo(val);
							}
						}
						if (!InstalledSyncDisks.TryGetValue(disk.SyncDiskName, out var value))
						{
							InstalledSyncDisks.Add(disk.SyncDiskName, value = new List<InstalledSyncDiskData>());
						}
						value.Add(disk);
					}
					return;
				}
			}
			if (InstalledSyncDisks.Count == 0)
			{
				if (File.Exists(savestoreDirectoryPath))
				{
					File.Delete(savestoreDirectoryPath);
				}
				return;
			}
			string contents = JsonSerializer.Serialize(new SyncDiskJsonData
			{
				SyncDiskData = (from a in InstalledSyncDisks.Values.SelectMany((List<InstalledSyncDiskData> a) => a)
					orderby a.SyncDiskName
					select a).ToList()
			}, new JsonSerializerOptions
			{
				WriteIndented = false
			});
			File.WriteAllText(savestoreDirectoryPath, contents);
			ManualLogSource log6 = PluginController<Plugin, IPluginBindings>.Log;
			val = new BepInExInfoLogInterpolatedStringHandler(63, 0, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Saving game, writing custom sync disk data to common savestore.");
			}
			log6.LogInfo(val);
		}

		internal void RaiseSyncDiskEvent(SyncDiskEvent syncDiskEvent, bool after, Upgrades upgrade)
		{
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Expected O, but got Unknown
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Expected O, but got Unknown
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Expected O, but got Unknown
			bool flag = default(bool);
			switch (syncDiskEvent)
			{
			case SyncDiskEvent.OnInstall:
			{
				SyncDiskArgs syncDiskArgs = new SyncDiskArgs(upgrade, setEffect: true, setUpgradeOption: false);
				if (after)
				{
					this.OnAfterSyncDiskInstalled?.Invoke(this, syncDiskArgs);
				}
				else
				{
					this.OnBeforeSyncDiskInstalled?.Invoke(this, syncDiskArgs);
				}
				if (after && ((Object)syncDiskArgs.SyncDisk.Preset).name.StartsWith($"{SyncDisk.UniqueDiskIdentifier}_") && syncDiskArgs.SyncDisk.ReRaiseEventsOnSaveLoad && syncDiskArgs.Effect.HasValue)
				{
					if (!InstalledSyncDisks.TryGetValue(((Object)syncDiskArgs.SyncDisk.Preset).name, out var value3))
					{
						value3 = new List<InstalledSyncDiskData>();
						InstalledSyncDisks.Add(((Object)syncDiskArgs.SyncDisk.Preset).name, value3);
					}
					value3.Add(new InstalledSyncDiskData(((Object)syncDiskArgs.SyncDisk.Preset).name, syncDiskArgs.Effect.Value.Name));
				}
				break;
			}
			case SyncDiskEvent.OnUninstall:
			{
				SyncDiskArgs uninstallArgs = new SyncDiskArgs(upgrade, setEffect: true, setUpgradeOption: false);
				if (after)
				{
					this.OnAfterSyncDiskUninstalled?.Invoke(this, uninstallArgs);
				}
				else
				{
					this.OnBeforeSyncDiskUninstalled?.Invoke(this, uninstallArgs);
				}
				if (!after || !uninstallArgs.Effect.HasValue || !((Object)uninstallArgs.SyncDisk.Preset).name.StartsWith($"{SyncDisk.UniqueDiskIdentifier}_") || !uninstallArgs.SyncDisk.ReRaiseEventsOnSaveLoad)
				{
					break;
				}
				if (!InstalledSyncDisks.TryGetValue(((Object)uninstallArgs.SyncDisk.Preset).name, out var value2))
				{
					ManualLogSource log3 = PluginController<Plugin, IPluginBindings>.Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(54, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not find uninstall data for custom sync disk \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(((Object)uninstallArgs.SyncDisk.Preset).name));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
					}
					log3.LogWarning(val);
					break;
				}
				InstalledSyncDiskData installedSyncDiskData2 = value2.FirstOrDefault((InstalledSyncDiskData a) => a.Effect.Equals(uninstallArgs.Effect.Value.Name));
				if (installedSyncDiskData2 == null)
				{
					ManualLogSource log4 = PluginController<Plugin, IPluginBindings>.Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(61, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not find uninstall effect data for custom sync disk \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(((Object)uninstallArgs.SyncDisk.Preset).name));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
					}
					log4.LogWarning(val);
				}
				else
				{
					value2.Remove(installedSyncDiskData2);
					if (value2.Count == 0)
					{
						InstalledSyncDisks.Remove(((Object)uninstallArgs.SyncDisk.Preset).name);
					}
				}
				break;
			}
			case SyncDiskEvent.OnUpgrade:
			{
				SyncDiskArgs upgradeArgs = new SyncDiskArgs(upgrade);
				if (after)
				{
					this.OnAfterSyncDiskUpgraded?.Invoke(this, upgradeArgs);
				}
				else
				{
					this.OnBeforeSyncDiskUpgraded?.Invoke(this, upgradeArgs);
				}
				if (!after || !upgradeArgs.Effect.HasValue || !((Object)upgradeArgs.SyncDisk.Preset).name.StartsWith($"{SyncDisk.UniqueDiskIdentifier}_") || !upgradeArgs.SyncDisk.ReRaiseEventsOnSaveLoad)
				{
					break;
				}
				if (!InstalledSyncDisks.TryGetValue(((Object)upgradeArgs.SyncDisk.Preset).name, out var value))
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(52, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not find upgrade data for custom sync disk \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(((Object)upgradeArgs.SyncDisk.Preset).name));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
					}
					log.LogWarning(val);
					break;
				}
				InstalledSyncDiskData installedSyncDiskData = value.FirstOrDefault((InstalledSyncDiskData a) => a.Effect.Equals(upgradeArgs.Effect.Value.Name));
				if (!upgradeArgs.UpgradeOption.HasValue || installedSyncDiskData == null)
				{
					ManualLogSource log2 = PluginController<Plugin, IPluginBindings>.Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(45, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not find ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((!upgradeArgs.UpgradeOption.HasValue) ? "upgrade option" : "effect");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" data for custom sync disk \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SyncDisk.GetSyncDiskNameFromPreset(((Object)upgradeArgs.SyncDisk.Preset).name));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
					}
					log2.LogWarning(val);
				}
				else
				{
					installedSyncDiskData.UpgradeOptions.Add(upgradeArgs.UpgradeOption.Value.Name);
				}
				break;
			}
			default:
				throw new NotSupportedException($"Invalid event: {syncDiskEvent}");
			}
		}
	}
	public sealed class Time
	{
		public readonly struct TimeData : IEquatable<TimeData>, IComparable<TimeData>, IComparable
		{
			public int Year { get; }

			public int Month { get; }

			public int Day { get; }

			public int Hour { get; }

			public int Minute { get; }

			public WeekDay DayEnum => SessionData.Instance.WeekdayFromInt(Day - 1);

			public Month MonthEnum => SessionData.Instance.MonthFromInt(Month - 1);

			public TimeData(int year, int month, int day, int hour, int minute)
			{
				Year = year;
				Month = month;
				Day = day;
				Hour = hour;
				Minute = minute;
			}

			public string Serialize()
			{
				return $"{Year}|{Month}|{Day}|{Hour}|{Minute}";
			}

			public static TimeData Deserialize(string serializedString)
			{
				int[] array = serializedString.Split('|').Select(int.Parse).ToArray();
				if (array.Length != 5)
				{
					throw new Exception("Invalid timedata serialize string, use method .Serialize() on TimeData instance.");
				}
				return new TimeData(array[0], array[1], array[2], array[3], array[4]);
			}

			public override string ToString()
			{
				return ToString("MM/dd/yyyy HH:mm");
			}

			public string ToString(string format)
			{
				return format.Replace("dd", Day.ToString("00")).Replace("MM", Month.ToString("00")).Replace("yyyy", Year.ToString())
					.Replace("HH", Hour.ToString("00"))
					.Replace("mm", Minute.ToString("00"));
			}

			public bool Equals(TimeData other)
			{
				if (other.Year == Year && other.Month == Month && other.Day == Day && other.Hour == Hour)
				{
					return other.Minute == Minute;
				}
				return false;
			}

			public override int GetHashCode()
			{
				return HashCode.Combine(Year, Month, Day, Hour, Minute);
			}

			public override bool Equals(object obj)
			{
				if (obj is TimeData other)
				{
					return Equals(other);
				}
				return false;
			}

			public TimeData AddDays(int days)
			{
				return AddHours(days * 24);
			}

			public TimeData AddHours(int hours)
			{
				return AddMinutes(hours * 60);
			}

			public TimeData AddMinutes(int minutes)
			{
				DateTime dateTime = new DateTime(Year, (Month == 0) ? (Month + 1) : Month, (Day == 0) ? (Day + 1) : Day, Hour, Minute, 0);
				DateTime dateTime2 = dateTime.AddMinutes(minutes);
				return new TimeData(dateTime2.Year, (Month == 0) ? (dateTime2.Month - 1) : dateTime2.Month, (Day == 0) ? (dateTime2.Day - 1) : dateTime2.Day, dateTime2.Hour, dateTime2.Minute);
			}

			public int CompareTo(TimeData other)
			{
				int num = Year.CompareTo(other.Year);
				if (num != 0)
				{
					return num;
				}
				num = Month.CompareTo(other.Month);
				if (num != 0)
				{
					return num;
				}
				num = Day.CompareTo(other.Day);
				if (num != 0)
				{
					return num;
				}
				num = Hour.CompareTo(other.Hour);
				if (num != 0)
				{
					return num;
				}
				return Minute.CompareTo(other.Minute);
			}

			public int CompareTo(object obj)
			{
				if (obj == null)
				{
					return 1;
				}
				if (obj is TimeData other)
				{
					return CompareTo(other);
				}
				throw new ArgumentException("Object is not a TimeData");
			}

			public static bool operator ==(TimeData left, TimeData right)
			{
				return left.Equals(right);
			}

			public static bool operator !=(TimeData left, TimeData right)
			{
				return !(left == right);
			}

			public static bool operator <(TimeData t1, TimeData t2)
			{
				if (t1.Year < t2.Year)
				{
					return true;
				}
				if (t1.Year == t2.Year)
				{
					if (t1.Month < t2.Month)
					{
						return true;
					}
					if (t1.Month == t2.Month)
					{
						if (t1.Day < t2.Day)
						{
							return true;
						}
						if (t1.Day == t2.Day)
						{
							if (t1.Hour < t2.Hour)
							{
								return true;
							}
							if (t1.Hour == t2.Hour && t1.Minute < t2.Minute)
							{
								return true;
							}
						}
					}
				}
				return false;
			}

			public static bool operator >(TimeData t1, TimeData t2)
			{
				return t2 < t1;
			}

			public static bool operator <=(TimeData t1, TimeData t2)
			{
				if (!(t1 < t2))
				{
					return t1 == t2;
				}
				return true;
			}

			public static bool operator >=(TimeData t1, TimeData t2)
			{
				if (!(t1 > t2))
				{
					return t1 == t2;
				}
				return true;
			}

			public static TimeSpan operator -(TimeData left, TimeData right)
			{
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Expected O, but got Unknown
				try
				{
					DateTime dateTime = new DateTime(left.Year, (left.Month == 0) ? (left.Month + 1) : left.Month, (left.Day == 0) ? (left.Day + 1) : left.Day, left.Hour, left.Minute, 0);
					DateTime dateTime2 = new DateTime(right.Year, (right.Month == 0) ? (right.Month + 1) : right.Month, (right.Day == 0) ? (right.Day + 1) : right.Day, right.Hour, right.Minute, 0);
					return dateTime - dateTime2;
				}
				catch (Exception)
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(38, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Date information]: Left (");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<TimeData>(left);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") | Right (");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<TimeData>(right);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
					}
					log.LogError(val);
					throw;
				}
			}
		}

		private bool _initialized;

		private float? _currentGameTime;

		private TimeData? _currentTimeData;

		private TimeData? _currentDateData;

		public bool IsInitialized => _initialized;

		public bool IsGamePaused { get; internal set; }

		public TimeData CurrentDateTime
		{
			get
			{
				if (!IsInitialized)
				{
					throw new Exception("Time is not initialized at this state of the game, check for the property \"Lib.Time.IsInitialized\".");
				}
				if (!_currentGameTime.HasValue || !_currentGameTime.Value.Equals(SessionData.Instance.gameTime))
				{
					_currentGameTime = SessionData.Instance.gameTime;
					GetGameTimeInfo(out _currentTimeData, out _currentDateData);
				}
				return _currentTimeData.Value;
			}
		}

		public TimeData CurrentDate
		{
			get
			{
				if (!IsInitialized)
				{
					throw new Exception("Time is not initialized at this state of the game, check for the property \"Lib.Time.IsInitialized\".");
				}
				if (!_currentGameTime.HasValue || !_currentGameTime.Value.Equals(SessionData.Instance.gameTime))
				{
					_currentGameTime = SessionData.Instance.gameTime;
					GetGameTimeInfo(out _currentTimeData, out _currentDateData);
				}
				return _currentDateData.Value;
			}
		}

		public WeekDay CurrentDayEnum => SessionData.Instance.WeekdayFromInt(CurrentDateTime.Day);

		public Month CurrentMonthEnum => SessionData.Instance.MonthFromInt(CurrentDateTime.Month);

		public event EventHandler OnGamePaused;

		public event EventHandler OnGameResumed;

		public event EventHandler<TimeChangedArgs> OnMinuteChanged;

		public event EventHandler<TimeChangedArgs> OnHourChanged;

		public event EventHandler<TimeChangedArgs> OnDayChanged;

		public event EventHandler<TimeChangedArgs> OnMonthChanged;

		public event EventHandler<TimeChangedArgs> OnYearChanged;

		public event EventHandler<TimeChangedArgs> OnTimeInitialized;

		internal Time()
		{
		}

		public void ResumeGame()
		{
			SessionData.Instance.ResumeGame();
		}

		public void PauseGame(bool showPauseText = true, bool openDesktopMode = true, bool delayOverride = false)
		{
			SessionData.Instance.PauseGame(showPauseText, delayOverride, openDesktopMode);
		}

		private static void GetGameTimeInfo(out TimeData? dateTime, out TimeData? date)
		{
			float num = SessionData.Instance.gameTime;
			SessionData instance = SessionData.Instance;
			int num2 = 0;
			int num3 = GameplayControls.Instance.yearZeroLeapYearCycle;
			int num4 = GameplayControls.Instance.dayZero;
			int num5 = 0;
			int num6 = GameplayControls.Instance.publicYearZero + GameplayControls.Instance.startingYear;
			while (num >= 24f)
			{
				num -= 24f;
				num4++;
				num2++;
				if (num4 >= 7)
				{
					num4 -= 7;
				}
				int num7 = instance.daysInMonths[num5];
				if (num3 == 3 && num5 == 1)
				{
					num7++;
				}
				if (num2 < num7)
				{
					continue;
				}
				num2 -= num7;
				num5++;
				if (num5 >= 12)
				{
					num5 -= 12;
					num6++;
					for (num3++; num3 >= 4; num3 -= 4)
					{
					}
				}
			}
			float num8 = instance.FloatMinutes24H(num);
			int num9 = Mathf.FloorToInt(num8);
			int minute = Mathf.RoundToInt((num8 - (float)num9) * 100f);
			num5++;
			num4++;
			date = new TimeData(num6, num5, num4, 0, 0);
			dateTime = new TimeData(num6, num5, num4, num9, minute);
		}

		internal void OnTimeChanged(TimeData previous, TimeData current)
		{
			if (previous.Minute != current.Minute)
			{
				this.OnMinuteChanged?.Invoke(this, new TimeChangedArgs(previous, current));
			}
			if (previous.Hour != current.Hour)
			{
				this.OnHourChanged?.Invoke(this, new TimeChangedArgs(previous, current));
			}
			if (previous.Day != current.Day)
			{
				this.OnDayChanged?.Invoke(this, new TimeChangedArgs(previous, current));
			}
			if (previous.Month != current.Month)
			{
				this.OnMonthChanged?.Invoke(this, new TimeChangedArgs(previous, current));
			}
			if (previous.Year != current.Year)
			{
				this.OnYearChanged?.Invoke(this, new TimeChangedArgs(previous, current));
			}
		}

		internal void OnPauseModeChanged(bool paused)
		{
			if (paused)
			{
				this.OnGamePaused?.Invoke(this, EventArgs.Empty);
			}
			else
			{
				this.OnGameResumed?.Invoke(this, EventArgs.Empty);
			}
		}

		internal void InitializeTime(bool reset = false)
		{
			if (reset)
			{
				_initialized = false;
				_currentGameTime = null;
				_currentDateData = null;
				_currentTimeData = null;
			}
			else if (!_initialized)
			{
				_initialized = true;
				this.OnTimeInitialized?.Invoke(this, new TimeChangedArgs(CurrentDateTime, CurrentDateTime));
			}
		}
	}
	public sealed class TimeChangedArgs : EventArgs
	{
		public Time.TimeData Previous { get; }

		public Time.TimeData Current { get; }

		public bool IsMinuteChanged { get; }

		public bool IsHourChanged { get; }

		public bool IsDayChanged { get; }

		public bool IsMonthChanged { get; }

		public bool IsYearChanged { get; }

		internal TimeChangedArgs(Time.TimeData previous, Time.TimeData current)
		{
			Previous = previous;
			Current = current;
			IsMinuteChanged = previous.Minute != current.Minute;
			IsHourChanged = previous.Hour != current.Hour;
			IsDayChanged = previous.Day != current.Day;
			IsMonthChanged = previous.Month != current.Month;
			IsYearChanged = previous.Year != current.Year;
		}
	}
}
namespace SOD.Common.Helpers.SyncDiskObjects
{
	public sealed class SyncDisk
	{
		internal static Lazy<InteractablePreset> SyncDiskInteractablePreset = new Lazy<InteractablePreset>((Func<InteractablePreset>)delegate
		{
			InteractablePreset val = ((IEnumerable<InteractablePreset>)Resources.FindObjectsOfTypeAll<InteractablePreset>()).Where((InteractablePreset preset) => ((SoCustomComparison)preset).presetName == "SyncDisk").LastOrDefault();
			if (!((SoCustomComparison)(object)val == (SoCustomComparison)null))
			{
				return val;
			}
			throw new Exception("Could not find sync disk interactable, did something change in this game version?");
		});

		private SyncDisks.Effect? _sideEffect;

		internal string[] Icons;

		internal static int UniqueDiskIdentifier = "Venomaus.SOD.Common".GetFnvHashCode();

		public bool RegisteredInGame
		{
			get
			{
				if (Lib.SyncDisks.RegisteredSyncDisks.Contains(this))
				{
					return true;
				}
				if ((Object)(object)Toolbox.Instance == (Object)null)
				{
					return false;
				}
				if (Toolbox.Instance.allSyncDisks == null)
				{
					return false;
				}
				if ((SoCustomComparison)(object)Preset == (SoCustomComparison)null)
				{
					return false;
				}
				return Toolbox.Instance.allSyncDisks.Contains(Preset);
			}
		}

		public SyncDiskPreset Preset { get; private set; }

		internal string Hash { get; private set; }

		internal bool ReRaiseEventsOnSaveLoad { get; private set; }

		public string Name { get; private set; }

		public int Number => Preset.syncDiskNumber;

		public int Price => Preset.price;

		public bool EnableWorldSpawn { get; private set; } = true;


		public Rarity Rarity => Preset.rarity;

		public Manufacturer Manufacturer => Preset.manufacturer;

		public SyncDisks.Effect[] Effects => new SyncDisks.Effect[3]
		{
			new SyncDisks.Effect((int)Preset.mainEffect1, Preset.mainEffect1Name),
			new SyncDisks.Effect((int)Preset.mainEffect2, Preset.mainEffect2Name),
			new SyncDisks.Effect((int)Preset.mainEffect3, Preset.mainEffect3Name)
		}.Where((SyncDisks.Effect a) => a.Id != 0).ToArray();

		public SyncDisks.Effect? SideEffect
		{
			get
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Expected I4, but got Unknown
				if (!_sideEffect.HasValue && (int)Preset.sideEffect != 0)
				{
					SyncDisks.Effect valueOrDefault = _sideEffect.GetValueOrDefault();
					if (!_sideEffect.HasValue)
					{
						valueOrDefault = new SyncDisks.Effect((int)Preset.sideEffect, Preset.sideEffectDescription);
						_sideEffect = valueOrDefault;
					}
				}
				return _sideEffect;
			}
		}

		public SyncDisks.UpgradeOption[] UpgradeOptions => new SyncDisks.UpgradeOption[3]
		{
			new SyncDisks.UpgradeOption(new SyncDiskBuilder.Options(Preset, 1)),
			new SyncDisks.UpgradeOption(new SyncDiskBuilder.Options(Preset, 2)),
			new SyncDisks.UpgradeOption(new SyncDiskBuilder.Options(Preset, 3))
		}.Where((SyncDisks.UpgradeOption a) => a.HasOptions).ToArray();

		internal HashSet<string> MenuPresetLocations { get; set; }

		private SyncDisk(bool createPresetInstance = true)
		{
			if (createPresetInstance)
			{
				Preset = ScriptableObject.CreateInstance<SyncDiskPreset>();
			}
		}

		public void Register()
		{
			if (!RegisteredInGame)
			{
				Lib.SyncDisks.RegisteredSyncDisks.Add(this);
			}
		}

		internal static string GetName(string name)
		{
			if (name == null)
			{
				return null;
			}
			if (name.StartsWith($"{UniqueDiskIdentifier}_"))
			{
				string[] array = name.Split('_');
				int length = (array[0] + "_" + array[1] + "_").Length;
				return name.Substring(length, name.Length - length);
			}
			return name;
		}

		internal static SyncDisk ConvertFrom(SyncDiskBuilder builder)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Expected I4, but got Unknown
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0632: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_072e: Unknown result type (might be due to invalid IL or missing references)
			SyncDisk syncDisk = new SyncDisk
			{
				Name = builder.Name,
				Hash = Lib.SaveGame.GetUniqueString(builder.PluginGuid + "_" + builder.Name),
				ReRaiseEventsOnSaveLoad = builder.ReRaiseEventsOnSaveLoad,
				EnableWorldSpawn = builder.EnableWorldSpawn
			};
			((Object)syncDisk.Preset).name = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{syncDisk.ReRaiseEventsOnSaveLoad}_{builder.Name}";
			((SoCustomComparison)syncDisk.Preset).presetName = ((Object)syncDisk.Preset).name;
			syncDisk.Preset.price = builder.Price;
			syncDisk.Preset.rarity = builder.Rarity;
			syncDisk.Preset.manufacturer = builder.Manufacturer;
			syncDisk.Preset.canBeSideJobReward = builder.CanBeSideJobReward;
			if (builder.OccupationPresets != null && builder.OccupationPresets.Length != 0)
			{
				syncDisk.Preset.occupation = new List<OccupationPreset>();
				((IEnumerable<OccupationPreset>)builder.OccupationPresets).ForEach((Action<OccupationPreset>)syncDisk.Preset.occupation.Add);
				syncDisk.Preset.occupationWeight = builder.OccupationWeight;
			}
			if (builder.Traits != null && builder.Traits.Length != 0)
			{
				syncDisk.Preset.traits = new List<TraitPick>();
				((IEnumerable<TraitPick>)builder.Traits).ForEach((Action<TraitPick>)syncDisk.Preset.traits.Add);
				syncDisk.Preset.traitWeight = builder.TraitWeight;
			}
			syncDisk.MenuPresetLocations = builder.MenuPresetLocations;
			syncDisk.Icons = new string[builder.Effects.Count];
			for (int i = 0; i < builder.Effects.Count; i++)
			{
				SyncDiskBuilder.Effect effect = builder.Effects[i];
				syncDisk.Icons[i] = effect.Icon;
				switch (i)
				{
				case 0:
					syncDisk.Preset.mainEffect1 = effect.EffectValue;
					syncDisk.Preset.mainEffect1Name = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{effect.Name}";
					syncDisk.Preset.mainEffect1Description = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{effect.Description}";
					break;
				case 1:
					syncDisk.Preset.mainEffect2 = effect.EffectValue;
					syncDisk.Preset.mainEffect2Name = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{effect.Name}";
					syncDisk.Preset.mainEffect2Description = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{effect.Description}";
					break;
				default:
					syncDisk.Preset.mainEffect3 = effect.EffectValue;
					syncDisk.Preset.mainEffect3Name = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{effect.Name}";
					syncDisk.Preset.mainEffect3Description = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{effect.Description}";
					break;
				}
			}
			if (builder.SideEffect != null)
			{
				syncDisk.Preset.sideEffect = builder.SideEffect.EffectValue;
				syncDisk.Preset.sideEffectDescription = $"{UniqueDiskIdentifier}_{syncDisk.Hash}_{builder.SideEffect.Description}";
				syncDisk._sideEffect = new SyncDisks.Effect((int)builder.SideEffect.EffectValue, syncDisk.Preset.sideEffectDescription);
			}
			for (int j = 0; j < builder.UpgradeOptions.Count; j++)
			{
				SyncDiskBuilder.Options options = builder.UpgradeOptions[j];
				List<string> val = (List<string>)(j switch
				{
					1 => syncDisk.Preset.option2UpgradeNameReferences, 
					0 => syncDisk.Preset.option1UpgradeNameReferences, 
					_ => syncDisk.Preset.option3UpgradeNameReferences, 
				});
				List<UpgradeEffect> val2 = (List<UpgradeEffect>)(j switch
				{
					1 => syncDisk.Preset.option2UpgradeEffects, 
					0 => syncDisk.Preset.option1UpgradeEffects, 
					_ => syncDisk.Preset.option3UpgradeEffects, 
				});
				List<float> val3 = (List<float>)(j switch
				{
					1 => syncDisk.Preset.option2UpgradeValues, 
					0 => syncDisk.Preset.option1UpgradeValues, 
					_ => syncDisk.Preset.option3UpgradeValues, 
				});
				if (!string.IsNullOrWhiteSpace(options.Option1))
				{
					val.Add($"{UniqueDiskIdentifier}_{syncDisk.Hash}_{options.Option1}");
					val2.Add(options.Option1Effect);
					val3.Add(0f);
				}
				if (!string.IsNullOrWhiteSpace(options.Option2))
				{
					val.Add($"{UniqueDiskIdentifier}_{syncDisk.Hash}_{options.Option2}");
					val2.Add(options.Option2Effect);
					val3.Add(0f);
				}
				if (!string.IsNullOrWhiteSpace(options.Option3))
				{
					val.Add($"{UniqueDiskIdentifier}_{syncDisk.Hash}_{options.Option3}");
					val2.Add(options.Option3Effect);
					val3.Add(0f);
				}
			}
			return syncDisk;
		}

		internal static SyncDisk ConvertFrom(SyncDiskPreset preset)
		{
			if (!((Object)preset).name.StartsWith($"{UniqueDiskIdentifier}_"))
			{
				return new SyncDisk(createPresetInstance: false)
				{
					Name = ((Object)preset).name,
					Preset = preset
				};
			}
			string[] array = ((Object)preset).name.Split('_');
			string text = array[1];
			bool flag = bool.Parse(array[2]);
			string obj = $"{array[0]}_{text}_{flag}_";
			string name = ((Object)preset).name;
			int length = obj.Length;
			string name2 = name.Substring(length, name.Length - length);
			return new SyncDisk(createPresetInstance: false)
			{
				Name = name2,
				Preset = preset,
				Hash = text,
				ReRaiseEventsOnSaveLoad = flag
			};
		}

		internal static string GetSyncDiskNameFromPreset(string presetName)
		{
			if (presetName == null || !presetName.StartsWith($"{UniqueDiskIdentifier}_"))
			{
				return presetName;
			}
			string[] array = presetName.Split('_');
			int length = $"{array[0]}_{array[1]}_{array[2]}_".Length;
			return presetName.Substring(length, presetName.Length - length);
		}
	}
	public sealed class SyncDiskArgs : EventArgs
	{
		public readonly struct Option
		{
			public readonly int Id;

			public readonly string Name;

			public Option(int id, string name)
			{
				Id = id;
				Name = name;
			}
		}

		public Upgrades SyncDiskChange { get; }

		public SyncDisk SyncDisk { get; }

		public int Number => SyncDisk.Number;

		public SyncDisks.Effect? Effect { get; }

		public Option? UpgradeOption { get; }

		internal SyncDiskArgs(SyncDisk syncDisk, SyncDisks.Effect effect, Option? option = null)
		{
			SyncDisk = syncDisk;
			Effect = effect;
			UpgradeOption = option;
		}

		internal SyncDiskArgs(Upgrades upgrades, bool setEffect = true, bool setUpgradeOption = true)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected I4, but got Unknown
			SyncDiskChange = upgrades;
			SyncDisk = SyncDisk.ConvertFrom(upgrades.preset);
			int num = (int)upgrades.state;
			if (setEffect)
			{
				if (num == 0)
				{
					Effect = null;
				}
				else
				{
					int num2 = num - 1;
					if (SyncDisk.Effects.Length > num2)
					{
						Effect = SyncDisk.Effects[num2];
					}
				}
			}
			if (!setUpgradeOption)
			{
				return;
			}
			int level = upgrades.level;
			if (level == 0 || num == 0)
			{
				UpgradeOption = null;
				return;
			}
			int num3 = num - 1;
			if (SyncDisk.UpgradeOptions.Length > num3)
			{
				SyncDisks.UpgradeOption upgradeOption = SyncDisk.UpgradeOptions[num3];
				if (level == 1 && upgradeOption.Id1.HasValue)
				{
					UpgradeOption = new Option(upgradeOption.Id1.Value, upgradeOption.Name1);
				}
				else if (level == 2 && upgradeOption.Id2.HasValue)
				{
					UpgradeOption = new Option(upgradeOption.Id2.Value, upgradeOption.Name2);
				}
				else if (level == 3 && upgradeOption.Id3.HasValue)
				{
					UpgradeOption = new Option(upgradeOption.Id3.Value, upgradeOption.Name3);
				}
			}
		}
	}
	public sealed class SyncDiskBuilder
	{
		internal class Effect
		{
			internal const string DefaultSprite = "IconDNA";

			public string Name { get; }

			public string Description { get; }

			public string Icon { get; }

			public Effect EffectValue { get; }

			internal Effect(int id, string name, string description, string icon)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				EffectValue = (Effect)id;
				Name = name;
				Description = description;
				Icon = ((!string.IsNullOrWhiteSpace(icon)) ? icon : "IconDNA");
			}
		}

		public struct Options
		{
			public readonly string Option1;

			public readonly string Option2;

			public readonly string Option3;

			internal UpgradeEffect Option1Effect;

			internal UpgradeEffect Option2Effect;

			internal UpgradeEffect Option3Effect;

			internal Options(SyncDiskPreset preset, int count)
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c7: 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)
				Option1 = null;
				Option2 = null;
				Option3 = null;
				Option1Effect = (UpgradeEffect)0;
				Option2Effect = (UpgradeEffect)0;
				Option3Effect = (UpgradeEffect)0;
				List<string> val = (List<string>)(count switch
				{
					2 => preset.option2UpgradeNameReferences, 
					1 => preset.option1UpgradeNameReferences, 
					_ => preset.option3UpgradeNameReferences, 
				});
				List<UpgradeEffect> val2 = (List<UpgradeEffect>)(count switch
				{
					2 => preset.option2UpgradeEffects, 
					1 => preset.option1UpgradeEffects, 
					_ => preset.option3UpgradeEffects, 
				});
				if (val.Count >= 1)
				{
					Option1 = val[0];
					Option1Effect = val2[0];
				}
				if (val.Count >= 2)
				{
					Option2 = val[1];
					Option2Effect = val2[1];
				}
				if (val.Count == 3)
				{
					Option3 = val[2];
					Option3Effect = val2[2];
				}
			}

			public Options(string option1)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				Option2 = null;
				Option3 = null;
				Option1Effect = (UpgradeEffect)0;
				Option2Effect = (UpgradeEffect)0;
				Option3Effect = (UpgradeEffect)0;
				Option1 = option1;
			}

			public Options(string option1, string option2)
				: this(option1)
			{
				Option2 = option2;
			}

			public Options(string option1, string option2, string option3)
				: this(option1, option2)
			{
				Option3 = option3;
			}
		}

		public readonly struct OptionIds
		{
			public readonly int Option1Id;

			public readonly int Option2Id;

			public readonly int Option3Id;

			internal OptionIds(ref Options options)
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				Option1Id = 0;
				Option2Id = 0;
				Option3Id = 0;
				if (!string.IsNullOrWhiteSpace(options.Option1))
				{
					Option1Id = SyncDisks.GetNewSyncDiskOptionId();
					options.Option1Effect = (UpgradeEffect)Option1Id;
				}
				if (!string.IsNullOrWhiteSpace(options.Option2))
				{
					Option2Id = SyncDisks.GetNewSyncDiskOptionId();
					options.Option2Effect = (UpgradeEffect)Option2Id;
				}
				if (!string.IsNullOrWhiteSpace(options.Option3))
				{
					Option3Id = SyncDisks.GetNewSyncDiskOptionId();
					options.Option3Effect = (UpgradeEffect)Option3Id;
				}
			}
		}

		public enum SyncDiskSaleLocation
		{
			CigaretteMachine,
			AmericanDiner,
			SupermarketFridge,
			CoffeeMachine,
			BlackmarketSyncClinic,
			StreetVendorSnacks,
			ElGenMachine,
			PawnShop,
			KolaMachine,
			SupermarketMagazines,
			AmericanBar,
			SupermarketFruit,
			Chinese,
			Newsstand,
			Supermarket,
			Chemist,
			Hardware,
			SupermarketDrinksCooler,
			SupermarketShelf,
			PoliceAutomat,
			SupermarketFreezer,
			HomeCoffee,
			NewspaperBox,
			BlackmarketTrader,
			WeaponsDealer,
			SyncClinic,
			LoanShark
		}

		internal string Name { get; private set; }

		intern

Castle.Core.dll

Decompiled a week ago
#define TRACE
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Mail;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;
using System.Xml.Xsl;
using Castle.Components.DictionaryAdapter.Xml;
using Castle.Core;
using Castle.Core.Internal;
using Castle.Core.Logging;
using Castle.DynamicProxy.Contributors;
using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Generators.Emitters;
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
using Castle.DynamicProxy.Internal;
using Castle.DynamicProxy.Serialization;
using Castle.DynamicProxy.Tokens;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Castle.Core.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010077f5e87030dadccce6902c6adab7a987bd69cb5819991531f560785eacfc89b6fcddf6bb2a00743a7194e454c0273447fc6eec36474ba8e5a3823147d214298e4f9a631b1afee1a51ffeae4672d498f14b000e3d321453cdd8ac064de7e1cf4d222b7e81f54d4fd46725370d702a05b48738cc29d09228f1aa722ae1a9ca02fb")]
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Castle Project Contributors")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2004-2022 Castle Project - http://www.castleproject.org/ ")]
[assembly: AssemblyDescription("Castle Core, including DynamicProxy, Logging Abstractions and DictionaryAdapter")]
[assembly: AssemblyFileVersion("5.1.1")]
[assembly: AssemblyInformationalVersion("5.1.1")]
[assembly: AssemblyProduct("Castle Core")]
[assembly: AssemblyTitle("Castle Core")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/castleproject/Core")]
[assembly: AssemblyVersion("5.0.0.0")]
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;
		}
	}
}
namespace Castle.DynamicProxy
{
	public abstract class AbstractInvocation : IInvocation
	{
		private sealed class ProceedInfo : IInvocationProceedInfo
		{
			private readonly AbstractInvocation invocation;

			private readonly int interceptorIndex;

			public ProceedInfo(AbstractInvocation invocation)
			{
				this.invocation = invocation;
				interceptorIndex = invocation.currentInterceptorIndex;
			}

			public void Invoke()
			{
				int currentInterceptorIndex = invocation.currentInterceptorIndex;
				try
				{
					invocation.currentInterceptorIndex = interceptorIndex;
					invocation.Proceed();
				}
				finally
				{
					invocation.currentInterceptorIndex = currentInterceptorIndex;
				}
			}
		}

		private readonly IInterceptor[] interceptors;

		private readonly object[] arguments;

		private int currentInterceptorIndex = -1;

		private Type[] genericMethodArguments;

		private readonly MethodInfo proxiedMethod;

		protected readonly object proxyObject;

		public abstract object InvocationTarget { get; }

		public abstract Type TargetType { get; }

		public abstract MethodInfo MethodInvocationTarget { get; }

		public Type[] GenericArguments => genericMethodArguments;

		public object Proxy => proxyObject;

		public MethodInfo Method => proxiedMethod;

		public object ReturnValue { get; set; }

		public object[] Arguments => arguments;

		protected AbstractInvocation(object proxy, IInterceptor[] interceptors, MethodInfo proxiedMethod, object[] arguments)
		{
			proxyObject = proxy;
			this.interceptors = interceptors;
			this.proxiedMethod = proxiedMethod;
			this.arguments = arguments;
		}

		public void SetGenericMethodArguments(Type[] arguments)
		{
			genericMethodArguments = arguments;
		}

		public MethodInfo GetConcreteMethod()
		{
			return EnsureClosedMethod(Method);
		}

		public MethodInfo GetConcreteMethodInvocationTarget()
		{
			return MethodInvocationTarget;
		}

		public void SetArgumentValue(int index, object value)
		{
			arguments[index] = value;
		}

		public object GetArgumentValue(int index)
		{
			return arguments[index];
		}

		public void Proceed()
		{
			if (interceptors == null)
			{
				InvokeMethodOnTarget();
				return;
			}
			currentInterceptorIndex++;
			try
			{
				if (currentInterceptorIndex == interceptors.Length)
				{
					InvokeMethodOnTarget();
					return;
				}
				if (currentInterceptorIndex > interceptors.Length)
				{
					throw new InvalidOperationException("Cannot proceed past the end of the interception pipeline. This likely signifies a bug in the calling code.");
				}
				interceptors[currentInterceptorIndex].Intercept(this);
			}
			finally
			{
				currentInterceptorIndex--;
			}
		}

		public IInvocationProceedInfo CaptureProceedInfo()
		{
			return new ProceedInfo(this);
		}

		protected abstract void InvokeMethodOnTarget();

		protected void ThrowOnNoTarget()
		{
			string text = ((interceptors.Length != 0) ? "The interceptor attempted to 'Proceed'" : "There are no interceptors specified");
			string text2;
			string text3;
			if (Method.DeclaringType.IsClass && Method.IsAbstract)
			{
				text2 = "is abstract";
				text3 = "an abstract method";
			}
			else
			{
				text2 = "has no target";
				text3 = "method without target";
			}
			throw new NotImplementedException($"This is a DynamicProxy2 error: {text} for method '{Method}' which {text2}. When calling {text3} there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc)");
		}

		private MethodInfo EnsureClosedMethod(MethodInfo method)
		{
			if (method.ContainsGenericParameters)
			{
				return method.GetGenericMethodDefinition().MakeGenericMethod(genericMethodArguments);
			}
			return method;
		}
	}
	public class AllMethodsHook : IProxyGenerationHook
	{
		protected static readonly ICollection<Type> SkippedTypes = new Type[3]
		{
			typeof(object),
			typeof(MarshalByRefObject),
			typeof(ContextBoundObject)
		};

		public virtual bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
		{
			return !SkippedTypes.Contains(methodInfo.DeclaringType);
		}

		public virtual void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
		{
		}

		public virtual void MethodsInspected()
		{
		}

		public override bool Equals(object obj)
		{
			if (obj != null)
			{
				return obj.GetType() == GetType();
			}
			return false;
		}

		public override int GetHashCode()
		{
			return GetType().GetHashCode();
		}
	}
	public class CustomAttributeInfo : IEquatable<CustomAttributeInfo>
	{
		private class AttributeArgumentValueEqualityComparer : IEqualityComparer<object>
		{
			bool IEqualityComparer<object>.Equals(object x, object y)
			{
				if (x == y)
				{
					return true;
				}
				if (x == null || y == null)
				{
					return false;
				}
				if (x.GetType() != y.GetType())
				{
					return false;
				}
				if (x.GetType().IsArray)
				{
					return AsObjectEnumerable(x).SequenceEqual(AsObjectEnumerable(y));
				}
				return x.Equals(y);
			}

			int IEqualityComparer<object>.GetHashCode(object obj)
			{
				if (obj == null)
				{
					return 0;
				}
				if (obj.GetType().IsArray)
				{
					return CombineHashCodes(AsObjectEnumerable(obj));
				}
				return obj.GetHashCode();
			}

			private static IEnumerable<object> AsObjectEnumerable(object array)
			{
				if (array.GetType().GetElementType().IsValueType)
				{
					return ((Array)array).Cast<object>();
				}
				return (IEnumerable<object>)array;
			}
		}

		private static readonly PropertyInfo[] EmptyProperties = new PropertyInfo[0];

		private static readonly FieldInfo[] EmptyFields = new FieldInfo[0];

		private static readonly object[] EmptyValues = new object[0];

		private static readonly IEqualityComparer<object> ValueComparer = new AttributeArgumentValueEqualityComparer();

		private readonly CustomAttributeBuilder builder;

		private readonly ConstructorInfo constructor;

		private readonly object[] constructorArgs;

		private readonly IDictionary<string, object> properties;

		private readonly IDictionary<string, object> fields;

		internal CustomAttributeBuilder Builder => builder;

		public CustomAttributeInfo(ConstructorInfo constructor, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues)
		{
			builder = new CustomAttributeBuilder(constructor, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
			this.constructor = constructor;
			this.constructorArgs = ((constructorArgs.Length == 0) ? EmptyValues : constructorArgs.ToArray());
			properties = MakeNameValueDictionary(namedProperties, propertyValues);
			fields = MakeNameValueDictionary(namedFields, fieldValues);
		}

		public CustomAttributeInfo(ConstructorInfo constructor, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues)
			: this(constructor, constructorArgs, namedProperties, propertyValues, EmptyFields, EmptyValues)
		{
		}

		public CustomAttributeInfo(ConstructorInfo constructor, object[] constructorArgs, FieldInfo[] namedFields, object[] fieldValues)
			: this(constructor, constructorArgs, EmptyProperties, EmptyValues, namedFields, fieldValues)
		{
		}

		public CustomAttributeInfo(ConstructorInfo constructor, object[] constructorArgs)
			: this(constructor, constructorArgs, EmptyProperties, EmptyValues, EmptyFields, EmptyValues)
		{
		}

		public static CustomAttributeInfo FromExpression(Expression<Func<Attribute>> expression)
		{
			List<PropertyInfo> list = new List<PropertyInfo>();
			List<object> list2 = new List<object>();
			List<FieldInfo> list3 = new List<FieldInfo>();
			List<object> list4 = new List<object>();
			Expression expression2 = UnwrapBody(expression.Body);
			NewExpression newExpression = expression2 as NewExpression;
			if (newExpression == null)
			{
				MemberInitExpression obj = (expression2 as MemberInitExpression) ?? throw new ArgumentException("The expression must be either a simple constructor call or an object initializer expression");
				newExpression = obj.NewExpression;
				foreach (MemberBinding binding in obj.Bindings)
				{
					if (!(binding is MemberAssignment memberAssignment))
					{
						throw new ArgumentException("Only assignment bindings are supported");
					}
					object attributeArgumentValue = GetAttributeArgumentValue(memberAssignment.Expression, allowArray: true);
					PropertyInfo propertyInfo = memberAssignment.Member as PropertyInfo;
					if (propertyInfo != null)
					{
						list.Add(propertyInfo);
						list2.Add(attributeArgumentValue);
						continue;
					}
					FieldInfo fieldInfo = memberAssignment.Member as FieldInfo;
					if (fieldInfo != null)
					{
						list3.Add(fieldInfo);
						list4.Add(attributeArgumentValue);
						continue;
					}
					throw new ArgumentException("Only property and field assignments are supported");
				}
			}
			List<object> list5 = new List<object>();
			foreach (Expression argument in newExpression.Arguments)
			{
				object attributeArgumentValue2 = GetAttributeArgumentValue(argument, allowArray: true);
				list5.Add(attributeArgumentValue2);
			}
			return new CustomAttributeInfo(newExpression.Constructor, list5.ToArray(), list.ToArray(), list2.ToArray(), list3.ToArray(), list4.ToArray());
		}

		private static Expression UnwrapBody(Expression body)
		{
			if (body is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert)
			{
				return unaryExpression.Operand;
			}
			return body;
		}

		private static object GetAttributeArgumentValue(Expression arg, bool allowArray)
		{
			switch (arg.NodeType)
			{
			case ExpressionType.Constant:
				return ((ConstantExpression)arg).Value;
			case ExpressionType.MemberAccess:
			{
				MemberExpression memberExpression = (MemberExpression)arg;
				if (memberExpression.Member is FieldInfo fieldInfo && memberExpression.Expression is ConstantExpression constantExpression && IsCompilerGenerated(constantExpression.Type) && constantExpression.Value != null)
				{
					return fieldInfo.GetValue(constantExpression.Value);
				}
				break;
			}
			case ExpressionType.NewArrayInit:
			{
				if (!allowArray)
				{
					break;
				}
				System.Linq.Expressions.NewArrayExpression newArrayExpression = (System.Linq.Expressions.NewArrayExpression)arg;
				Array array = Array.CreateInstance(newArrayExpression.Type.GetElementType(), newArrayExpression.Expressions.Count);
				int num = 0;
				{
					foreach (Expression expression in newArrayExpression.Expressions)
					{
						object attributeArgumentValue = GetAttributeArgumentValue(expression, allowArray: false);
						array.SetValue(attributeArgumentValue, num);
						num++;
					}
					return array;
				}
			}
			}
			throw new ArgumentException("Only constant, local variables, method parameters and single-dimensional array expressions are supported");
		}

		private static bool IsCompilerGenerated(Type type)
		{
			return type.IsDefined(typeof(CompilerGeneratedAttribute));
		}

		public bool Equals(CustomAttributeInfo other)
		{
			if (other == null)
			{
				return false;
			}
			if (this == other)
			{
				return true;
			}
			if (constructor.Equals(other.constructor) && constructorArgs.SequenceEqual(other.constructorArgs, ValueComparer) && AreMembersEquivalent(properties, other.properties))
			{
				return AreMembersEquivalent(fields, other.fields);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (this == obj)
			{
				return true;
			}
			if (obj.GetType() != GetType())
			{
				return false;
			}
			return Equals((CustomAttributeInfo)obj);
		}

		public override int GetHashCode()
		{
			return (((((constructor.GetHashCode() * 397) ^ CombineHashCodes(constructorArgs)) * 397) ^ CombineMemberHashCodes(properties)) * 397) ^ CombineMemberHashCodes(fields);
		}

		private static bool AreMembersEquivalent(IDictionary<string, object> x, IDictionary<string, object> y)
		{
			if (x.Count != y.Count)
			{
				return false;
			}
			foreach (KeyValuePair<string, object> item in x)
			{
				if (!y.TryGetValue(item.Key, out var value))
				{
					return false;
				}
				if (!ValueComparer.Equals(item.Value, value))
				{
					return false;
				}
			}
			return true;
		}

		private static int CombineHashCodes(IEnumerable<object> values)
		{
			int num = 173;
			foreach (object value in values)
			{
				num = (num * 397) ^ ValueComparer.GetHashCode(value);
			}
			return num;
		}

		private static int CombineMemberHashCodes(IDictionary<string, object> dict)
		{
			int num = 0;
			foreach (KeyValuePair<string, object> item in dict)
			{
				int hashCode = item.Key.GetHashCode();
				int hashCode2 = ValueComparer.GetHashCode(item.Value);
				num += (hashCode * 397) ^ hashCode2;
			}
			return num;
		}

		private IDictionary<string, object> MakeNameValueDictionary<T>(T[] members, object[] values) where T : MemberInfo
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			for (int i = 0; i < members.Length; i++)
			{
				dictionary.Add(members[i].Name, values[i]);
			}
			return dictionary;
		}
	}
	public class DefaultProxyBuilder : IProxyBuilder
	{
		private readonly ModuleScope scope;

		private ILogger logger = NullLogger.Instance;

		public ILogger Logger
		{
			get
			{
				return logger;
			}
			set
			{
				logger = value;
			}
		}

		public ModuleScope ModuleScope => scope;

		public DefaultProxyBuilder()
			: this(new ModuleScope())
		{
		}

		public DefaultProxyBuilder(ModuleScope scope)
		{
			this.scope = scope;
		}

		public Type CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			AssertValidType(classToProxy, "classToProxy");
			AssertValidTypes(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			AssertValidMixins(options, "options");
			return new ClassProxyGenerator(scope, classToProxy, additionalInterfacesToProxy, options)
			{
				Logger = logger
			}.GetProxyType();
		}

		public Type CreateClassProxyTypeWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			AssertValidType(classToProxy, "classToProxy");
			AssertValidTypes(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			AssertValidMixins(options, "options");
			return new ClassProxyWithTargetGenerator(scope, classToProxy, additionalInterfacesToProxy, options)
			{
				Logger = logger
			}.GetProxyType();
		}

		public Type CreateInterfaceProxyTypeWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, Type targetType, ProxyGenerationOptions options)
		{
			AssertValidType(interfaceToProxy, "interfaceToProxy");
			AssertValidTypes(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			AssertValidMixins(options, "options");
			return new InterfaceProxyWithTargetGenerator(scope, interfaceToProxy, additionalInterfacesToProxy, targetType, options)
			{
				Logger = logger
			}.GetProxyType();
		}

		public Type CreateInterfaceProxyTypeWithTargetInterface(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			AssertValidType(interfaceToProxy, "interfaceToProxy");
			AssertValidTypes(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			AssertValidMixins(options, "options");
			return new InterfaceProxyWithTargetInterfaceGenerator(scope, interfaceToProxy, additionalInterfacesToProxy, interfaceToProxy, options)
			{
				Logger = logger
			}.GetProxyType();
		}

		public Type CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			AssertValidType(interfaceToProxy, "interfaceToProxy");
			AssertValidTypes(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			AssertValidMixins(options, "options");
			return new InterfaceProxyWithoutTargetGenerator(scope, interfaceToProxy, additionalInterfacesToProxy, typeof(object), options)
			{
				Logger = logger
			}.GetProxyType();
		}

		private void AssertValidMixins(ProxyGenerationOptions options, string paramName)
		{
			try
			{
				options.Initialize();
			}
			catch (InvalidOperationException ex)
			{
				throw new ArgumentException(ex.Message, paramName, ex.InnerException);
			}
		}

		private void AssertValidType(Type target, string paramName)
		{
			AssertValidTypeForTarget(target, target, paramName);
		}

		private void AssertValidTypeForTarget(Type type, Type target, string paramName)
		{
			if (type.IsGenericTypeDefinition)
			{
				throw new ArgumentException($"Can not create proxy for type {target.GetBestName()} because type {type.GetBestName()} is an open generic type.", paramName);
			}
			if (!ProxyUtil.IsAccessibleType(type))
			{
				throw new ArgumentException(ExceptionMessageBuilder.CreateMessageForInaccessibleType(type, target), paramName);
			}
			Type[] genericArguments = type.GetGenericArguments();
			foreach (Type type2 in genericArguments)
			{
				AssertValidTypeForTarget(type2, target, paramName);
			}
		}

		private void AssertValidTypes(IEnumerable<Type> targetTypes, string paramName)
		{
			if (targetTypes == null)
			{
				return;
			}
			foreach (Type targetType in targetTypes)
			{
				AssertValidType(targetType, paramName);
			}
		}
	}
	[Serializable]
	public sealed class DynamicProxyException : Exception
	{
		internal DynamicProxyException(string message)
			: base(message)
		{
		}

		internal DynamicProxyException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		internal DynamicProxyException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}
	}
	internal static class ExceptionMessageBuilder
	{
		internal static string CreateInstructionsToMakeVisible(Assembly targetAssembly)
		{
			string arg = " not";
			string arg2 = "\"DynamicProxyGenAssembly2\"";
			if (targetAssembly.IsAssemblySigned())
			{
				arg = "";
				arg2 = (ReferencesCastleCore(targetAssembly) ? "InternalsVisible.ToDynamicProxyGenAssembly2" : "\"DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7\"");
			}
			return $"Make it public, or internal and mark your assembly with [assembly: InternalsVisibleTo({arg2})] attribute, because assembly {targetAssembly.GetName().Name} is{arg} strong-named.";
			static bool ReferencesCastleCore(Assembly ia)
			{
				return ia.GetReferencedAssemblies().Any((AssemblyName r) => r.FullName == Assembly.GetExecutingAssembly().FullName);
			}
		}

		public static string CreateMessageForInaccessibleType(Type inaccessibleType, Type typeToProxy)
		{
			Assembly assembly = typeToProxy.Assembly;
			string arg = ((inaccessibleType == typeToProxy) ? "it" : ("type " + inaccessibleType.GetBestName()));
			string text = $"Can not create proxy for type {typeToProxy.GetBestName()} because {arg} is not accessible. ";
			string text2 = CreateInstructionsToMakeVisible(assembly);
			return text + text2;
		}
	}
	public interface IChangeProxyTarget
	{
		void ChangeInvocationTarget(object target);

		[Obsolete("Use ((IProxyTargetAccessor)invocation.Proxy).DynProxySetTarget(target) instead.")]
		void ChangeProxyTarget(object target);
	}
	public interface IInterceptor
	{
		void Intercept(IInvocation invocation);
	}
	public interface IInterceptorSelector
	{
		IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors);
	}
	public interface IInvocation
	{
		object[] Arguments { get; }

		Type[] GenericArguments { get; }

		object InvocationTarget { get; }

		MethodInfo Method { get; }

		MethodInfo MethodInvocationTarget { get; }

		object Proxy { get; }

		object ReturnValue { get; set; }

		Type TargetType { get; }

		object GetArgumentValue(int index);

		MethodInfo GetConcreteMethod();

		MethodInfo GetConcreteMethodInvocationTarget();

		void Proceed();

		IInvocationProceedInfo CaptureProceedInfo();

		void SetArgumentValue(int index, object value);
	}
	public interface IInvocationProceedInfo
	{
		void Invoke();
	}
	public interface IProxyBuilder
	{
		ILogger Logger { get; set; }

		ModuleScope ModuleScope { get; }

		Type CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options);

		Type CreateClassProxyTypeWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options);

		Type CreateInterfaceProxyTypeWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, Type targetType, ProxyGenerationOptions options);

		Type CreateInterfaceProxyTypeWithTargetInterface(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options);

		Type CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options);
	}
	public interface IProxyGenerationHook
	{
		void MethodsInspected();

		void NonProxyableMemberNotification(Type type, MemberInfo memberInfo);

		bool ShouldInterceptMethod(Type type, MethodInfo methodInfo);
	}
	[CLSCompliant(true)]
	public interface IProxyGenerator
	{
		ILogger Logger { get; set; }

		IProxyBuilder ProxyBuilder { get; }

		TInterface CreateInterfaceProxyWithTarget<TInterface>(TInterface target, params IInterceptor[] interceptors) where TInterface : class;

		TInterface CreateInterfaceProxyWithTarget<TInterface>(TInterface target, ProxyGenerationOptions options, params IInterceptor[] interceptors) where TInterface : class;

		object CreateInterfaceProxyWithTarget(Type interfaceToProxy, object target, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithTarget(Type interfaceToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, object target, params IInterceptor[] interceptors);

		TInterface CreateInterfaceProxyWithTargetInterface<TInterface>(TInterface target, params IInterceptor[] interceptors) where TInterface : class;

		TInterface CreateInterfaceProxyWithTargetInterface<TInterface>(TInterface target, ProxyGenerationOptions options, params IInterceptor[] interceptors) where TInterface : class;

		object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		TInterface CreateInterfaceProxyWithoutTarget<TInterface>(IInterceptor interceptor) where TInterface : class;

		TInterface CreateInterfaceProxyWithoutTarget<TInterface>(params IInterceptor[] interceptors) where TInterface : class;

		TInterface CreateInterfaceProxyWithoutTarget<TInterface>(ProxyGenerationOptions options, params IInterceptor[] interceptors) where TInterface : class;

		object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, IInterceptor interceptor);

		object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		TClass CreateClassProxyWithTarget<TClass>(TClass target, params IInterceptor[] interceptors) where TClass : class;

		TClass CreateClassProxyWithTarget<TClass>(TClass target, ProxyGenerationOptions options, params IInterceptor[] interceptors) where TClass : class;

		object CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, object target, params IInterceptor[] interceptors);

		object CreateClassProxyWithTarget(Type classToProxy, object target, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors);

		object CreateClassProxyWithTarget(Type classToProxy, object target, object[] constructorArguments, params IInterceptor[] interceptors);

		object CreateClassProxyWithTarget(Type classToProxy, object target, params IInterceptor[] interceptors);

		object CreateClassProxyWithTarget(Type classToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors);

		TClass CreateClassProxy<TClass>(params IInterceptor[] interceptors) where TClass : class;

		TClass CreateClassProxy<TClass>(ProxyGenerationOptions options, params IInterceptor[] interceptors) where TClass : class;

		object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, params IInterceptor[] interceptors);

		object CreateClassProxy(Type classToProxy, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors);

		object CreateClassProxy(Type classToProxy, object[] constructorArguments, params IInterceptor[] interceptors);

		object CreateClassProxy(Type classToProxy, params IInterceptor[] interceptors);

		object CreateClassProxy(Type classToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors);

		object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors);
	}
	public interface IProxyTargetAccessor
	{
		object DynProxyGetTarget();

		void DynProxySetTarget(object target);

		IInterceptor[] GetInterceptors();
	}
	public class MixinData
	{
		private readonly Dictionary<Type, int> mixinPositions = new Dictionary<Type, int>();

		private readonly List<object> mixinsImpl = new List<object>();

		private int delegateMixinCount;

		public IEnumerable<Type> MixinInterfaces => mixinPositions.Keys;

		public IEnumerable<object> Mixins => mixinsImpl;

		public MixinData(IEnumerable<object> mixinInstances)
		{
			if (mixinInstances == null)
			{
				return;
			}
			List<Type> list = new List<Type>();
			Dictionary<Type, object> dictionary = new Dictionary<Type, object>();
			delegateMixinCount = 0;
			foreach (object mixinInstance in mixinInstances)
			{
				Type[] array;
				object value;
				if (mixinInstance is Delegate)
				{
					delegateMixinCount++;
					array = new Type[1] { mixinInstance.GetType() };
					value = mixinInstance;
				}
				else if (mixinInstance is Type type && type.IsDelegateType())
				{
					delegateMixinCount++;
					array = new Type[1] { type };
					value = null;
				}
				else
				{
					array = mixinInstance.GetType().GetInterfaces();
					value = mixinInstance;
				}
				Type[] array2 = array;
				foreach (Type type2 in array2)
				{
					list.Add(type2);
					if (dictionary.TryGetValue(type2, out var value2))
					{
						string message = ((value2 == null) ? $"The list of mixins already contains a mixin for delegate type '{type2.FullName}'." : $"The list of mixins contains two mixins implementing the same interface '{type2.FullName}': {value2.GetType().Name} and {mixinInstance.GetType().Name}. An interface cannot be added by more than one mixin.");
						throw new ArgumentException(message, "mixinInstances");
					}
					dictionary[type2] = value;
				}
			}
			if (delegateMixinCount > 1)
			{
				HashSet<MethodInfo> hashSet = new HashSet<MethodInfo>();
				foreach (Type key2 in dictionary.Keys)
				{
					if (key2.IsDelegateType())
					{
						MethodInfo method = key2.GetMethod("Invoke");
						if (hashSet.Contains(method, MethodSignatureComparer.Instance))
						{
							throw new ArgumentException("The list of mixins contains at least two delegate mixins for the same delegate signature.", "mixinInstances");
						}
						hashSet.Add(method);
					}
				}
			}
			list.Sort((Type x, Type y) => string.CompareOrdinal(x.FullName, y.FullName));
			for (int j = 0; j < list.Count; j++)
			{
				Type key = list[j];
				object item = dictionary[key];
				mixinPositions[key] = j;
				mixinsImpl.Add(item);
			}
		}

		public bool ContainsMixin(Type mixinInterfaceType)
		{
			return mixinPositions.ContainsKey(mixinInterfaceType);
		}

		public override bool Equals(object obj)
		{
			if (this == obj)
			{
				return true;
			}
			if (!(obj is MixinData mixinData))
			{
				return false;
			}
			if (mixinsImpl.Count != mixinData.mixinsImpl.Count)
			{
				return false;
			}
			if (delegateMixinCount != mixinData.delegateMixinCount)
			{
				return false;
			}
			for (int i = 0; i < mixinsImpl.Count; i++)
			{
				if (mixinsImpl[i]?.GetType() != mixinData.mixinsImpl[i]?.GetType())
				{
					return false;
				}
			}
			if (delegateMixinCount > 0)
			{
				IEnumerable<Type> first = mixinPositions.Select((KeyValuePair<Type, int> m) => m.Key).Where(TypeUtil.IsDelegateType);
				IEnumerable<Type> second = mixinData.mixinPositions.Select((KeyValuePair<Type, int> m) => m.Key).Where(TypeUtil.IsDelegateType);
				return first.SequenceEqual(second);
			}
			return true;
		}

		public override int GetHashCode()
		{
			int num = 0;
			foreach (object item in mixinsImpl)
			{
				num = (29 * num + item?.GetType().GetHashCode()) ?? 307;
			}
			return num;
		}

		public object GetMixinInstance(Type mixinInterfaceType)
		{
			return mixinsImpl[mixinPositions[mixinInterfaceType]];
		}

		public int GetMixinPosition(Type mixinInterfaceType)
		{
			return mixinPositions[mixinInterfaceType];
		}
	}
	public class ModuleScope
	{
		public static readonly string DEFAULT_FILE_NAME = "CastleDynProxy2.dll";

		public static readonly string DEFAULT_ASSEMBLY_NAME = "DynamicProxyGenAssembly2";

		private ModuleBuilder moduleBuilderWithStrongName;

		private ModuleBuilder moduleBuilder;

		private readonly string strongAssemblyName;

		private readonly string weakAssemblyName;

		private readonly string strongModulePath;

		private readonly string weakModulePath;

		private readonly SynchronizedDictionary<CacheKey, Type> typeCache = new SynchronizedDictionary<CacheKey, Type>();

		private readonly object moduleLocker = new object();

		private readonly bool savePhysicalAssembly;

		private readonly bool disableSignedModule;

		private readonly INamingScope namingScope;

		internal INamingScope NamingScope => namingScope;

		internal SynchronizedDictionary<CacheKey, Type> TypeCache => typeCache;

		internal ModuleBuilder StrongNamedModule => moduleBuilderWithStrongName;

		public string StrongNamedModuleName => Path.GetFileName(strongModulePath);

		internal ModuleBuilder WeakNamedModule => moduleBuilder;

		public string WeakNamedModuleName => Path.GetFileName(weakModulePath);

		public ModuleScope()
			: this(savePhysicalAssembly: false, disableSignedModule: false)
		{
		}

		public ModuleScope(bool savePhysicalAssembly)
			: this(savePhysicalAssembly, disableSignedModule: false)
		{
		}

		public ModuleScope(bool savePhysicalAssembly, bool disableSignedModule)
			: this(savePhysicalAssembly, disableSignedModule, DEFAULT_ASSEMBLY_NAME, DEFAULT_FILE_NAME, DEFAULT_ASSEMBLY_NAME, DEFAULT_FILE_NAME)
		{
		}

		public ModuleScope(bool savePhysicalAssembly, bool disableSignedModule, string strongAssemblyName, string strongModulePath, string weakAssemblyName, string weakModulePath)
			: this(savePhysicalAssembly, disableSignedModule, new NamingScope(), strongAssemblyName, strongModulePath, weakAssemblyName, weakModulePath)
		{
		}

		internal ModuleScope(bool savePhysicalAssembly, bool disableSignedModule, INamingScope namingScope, string strongAssemblyName, string strongModulePath, string weakAssemblyName, string weakModulePath)
		{
			this.savePhysicalAssembly = savePhysicalAssembly;
			this.disableSignedModule = disableSignedModule;
			this.namingScope = namingScope;
			this.strongAssemblyName = strongAssemblyName;
			this.strongModulePath = strongModulePath;
			this.weakAssemblyName = weakAssemblyName;
			this.weakModulePath = weakModulePath;
		}

		public static byte[] GetKeyPair()
		{
			using Stream stream = typeof(ModuleScope).Assembly.GetManifestResourceStream("Castle.DynamicProxy.DynProxy.snk");
			if (stream == null)
			{
				throw new MissingManifestResourceException("Should have a Castle.DynamicProxy.DynProxy.snk as an embedded resource, so Dynamic Proxy could sign generated assembly");
			}
			int num = (int)stream.Length;
			byte[] array = new byte[num];
			stream.Read(array, 0, num);
			return array;
		}

		internal ModuleBuilder ObtainDynamicModule(bool isStrongNamed)
		{
			if (isStrongNamed)
			{
				return ObtainDynamicModuleWithStrongName();
			}
			return ObtainDynamicModuleWithWeakName();
		}

		internal ModuleBuilder ObtainDynamicModuleWithStrongName()
		{
			if (disableSignedModule)
			{
				throw new InvalidOperationException("Usage of signed module has been disabled. Use unsigned module or enable signed module.");
			}
			lock (moduleLocker)
			{
				if (moduleBuilderWithStrongName == null)
				{
					moduleBuilderWithStrongName = CreateModule(signStrongName: true);
				}
				return moduleBuilderWithStrongName;
			}
		}

		internal ModuleBuilder ObtainDynamicModuleWithWeakName()
		{
			lock (moduleLocker)
			{
				if (moduleBuilder == null)
				{
					moduleBuilder = CreateModule(signStrongName: false);
				}
				return moduleBuilder;
			}
		}

		private ModuleBuilder CreateModule(bool signStrongName)
		{
			AssemblyName assemblyName = GetAssemblyName(signStrongName);
			string name = (signStrongName ? StrongNamedModuleName : WeakNamedModuleName);
			return AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run).DefineDynamicModule(name);
		}

		private AssemblyName GetAssemblyName(bool signStrongName)
		{
			AssemblyName assemblyName = new AssemblyName
			{
				Name = (signStrongName ? strongAssemblyName : weakAssemblyName)
			};
			if (signStrongName)
			{
				assemblyName.SetPublicKey(InternalsVisible.DynamicProxyGenAssembly2PublicKey);
			}
			return assemblyName;
		}

		internal TypeBuilder DefineType(bool inSignedModulePreferably, string name, TypeAttributes flags)
		{
			return ObtainDynamicModule(!disableSignedModule && inSignedModulePreferably).DefineType(name, flags);
		}
	}
	public class ProxyGenerationOptions
	{
		public static readonly ProxyGenerationOptions Default = new ProxyGenerationOptions();

		private List<object> mixins;

		private readonly IList<CustomAttributeInfo> additionalAttributes = new List<CustomAttributeInfo>();

		private MixinData mixinData;

		public IProxyGenerationHook Hook { get; set; }

		public IInterceptorSelector Selector { get; set; }

		public Type BaseTypeForInterfaceProxy { get; set; }

		public IList<CustomAttributeInfo> AdditionalAttributes => additionalAttributes;

		public MixinData MixinData
		{
			get
			{
				if (mixinData == null)
				{
					throw new InvalidOperationException("Call Initialize before accessing the MixinData property.");
				}
				return mixinData;
			}
		}

		public bool HasMixins
		{
			get
			{
				if (mixins != null)
				{
					return mixins.Count != 0;
				}
				return false;
			}
		}

		public ProxyGenerationOptions(IProxyGenerationHook hook)
		{
			BaseTypeForInterfaceProxy = typeof(object);
			Hook = hook;
		}

		public ProxyGenerationOptions()
			: this(new AllMethodsHook())
		{
		}

		public void Initialize()
		{
			if (mixinData == null)
			{
				try
				{
					mixinData = new MixinData(mixins);
				}
				catch (ArgumentException innerException)
				{
					throw new InvalidOperationException("There is a problem with the mixins added to this ProxyGenerationOptions. See the inner exception for details.", innerException);
				}
			}
		}

		public void AddDelegateTypeMixin(Type delegateType)
		{
			if (delegateType == null)
			{
				throw new ArgumentNullException("delegateType");
			}
			if (!delegateType.IsDelegateType())
			{
				throw new ArgumentException("Type must be a delegate type.", "delegateType");
			}
			AddMixinImpl(delegateType);
		}

		public void AddDelegateMixin(Delegate @delegate)
		{
			if ((object)@delegate == null)
			{
				throw new ArgumentNullException("delegate");
			}
			AddMixinImpl(@delegate);
		}

		public void AddMixinInstance(object instance)
		{
			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}
			if (instance is Type)
			{
				throw new ArgumentException("You may not mix in types using this method.", "instance");
			}
			AddMixinImpl(instance);
		}

		private void AddMixinImpl(object instanceOrType)
		{
			if (mixins == null)
			{
				mixins = new List<object>();
			}
			mixins.Add(instanceOrType);
			mixinData = null;
		}

		public object[] MixinsAsArray()
		{
			if (mixins == null)
			{
				return new object[0];
			}
			return mixins.ToArray();
		}

		public override bool Equals(object obj)
		{
			if (this == obj)
			{
				return true;
			}
			if (!(obj is ProxyGenerationOptions proxyGenerationOptions))
			{
				return false;
			}
			Initialize();
			proxyGenerationOptions.Initialize();
			if (!object.Equals(Hook, proxyGenerationOptions.Hook))
			{
				return false;
			}
			if (!object.Equals(Selector == null, proxyGenerationOptions.Selector == null))
			{
				return false;
			}
			if (!object.Equals(MixinData, proxyGenerationOptions.MixinData))
			{
				return false;
			}
			if (!object.Equals(BaseTypeForInterfaceProxy, proxyGenerationOptions.BaseTypeForInterfaceProxy))
			{
				return false;
			}
			if (!HasEquivalentAdditionalAttributes(proxyGenerationOptions))
			{
				return false;
			}
			return true;
		}

		public override int GetHashCode()
		{
			Initialize();
			int num = ((Hook != null) ? Hook.GetType().GetHashCode() : 0);
			num = 29 * num + ((Selector != null) ? 1 : 0);
			num = 29 * num + MixinData.GetHashCode();
			num = 29 * num + ((BaseTypeForInterfaceProxy != null) ? BaseTypeForInterfaceProxy.GetHashCode() : 0);
			return 29 * num + GetAdditionalAttributesHashCode();
		}

		private int GetAdditionalAttributesHashCode()
		{
			int num = 0;
			for (int i = 0; i < additionalAttributes.Count; i++)
			{
				if (additionalAttributes[i] != null)
				{
					num += additionalAttributes[i].GetHashCode();
				}
			}
			return num;
		}

		private bool HasEquivalentAdditionalAttributes(ProxyGenerationOptions other)
		{
			IList<CustomAttributeInfo> list = additionalAttributes;
			IList<CustomAttributeInfo> list2 = other.additionalAttributes;
			if (list.Count != list2.Count)
			{
				return false;
			}
			List<CustomAttributeInfo> list3 = list2.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				bool flag = false;
				for (int j = 0; j < list3.Count; j++)
				{
					if (object.Equals(list[i], list3[j]))
					{
						flag = true;
						list3.RemoveAt(j);
						break;
					}
				}
				if (!flag)
				{
					return false;
				}
			}
			return true;
		}
	}
	[CLSCompliant(true)]
	public class ProxyGenerator : IProxyGenerator
	{
		private ILogger logger = NullLogger.Instance;

		private readonly IProxyBuilder proxyBuilder;

		public ILogger Logger
		{
			get
			{
				return logger;
			}
			set
			{
				logger = value;
				proxyBuilder.Logger = value;
			}
		}

		public IProxyBuilder ProxyBuilder => proxyBuilder;

		public ProxyGenerator(IProxyBuilder builder)
		{
			proxyBuilder = builder;
			Logger = new TraceLogger("Castle.DynamicProxy", LoggerLevel.Warn);
		}

		public ProxyGenerator()
			: this(new DefaultProxyBuilder())
		{
		}

		public ProxyGenerator(bool disableSignedModule)
			: this(new DefaultProxyBuilder(new ModuleScope(savePhysicalAssembly: false, disableSignedModule)))
		{
		}

		public TInterface CreateInterfaceProxyWithTarget<TInterface>(TInterface target, params IInterceptor[] interceptors) where TInterface : class
		{
			return (TInterface)CreateInterfaceProxyWithTarget(typeof(TInterface), target, ProxyGenerationOptions.Default, interceptors);
		}

		public TInterface CreateInterfaceProxyWithTarget<TInterface>(TInterface target, ProxyGenerationOptions options, params IInterceptor[] interceptors) where TInterface : class
		{
			return (TInterface)CreateInterfaceProxyWithTarget(typeof(TInterface), target, options, interceptors);
		}

		public object CreateInterfaceProxyWithTarget(Type interfaceToProxy, object target, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithTarget(interfaceToProxy, target, ProxyGenerationOptions.Default, interceptors);
		}

		public object CreateInterfaceProxyWithTarget(Type interfaceToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithTarget(interfaceToProxy, null, target, options, interceptors);
		}

		public object CreateInterfaceProxyWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithTarget(interfaceToProxy, additionalInterfacesToProxy, target, ProxyGenerationOptions.Default, interceptors);
		}

		public virtual object CreateInterfaceProxyWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			if (interfaceToProxy == null)
			{
				throw new ArgumentNullException("interfaceToProxy");
			}
			if (target == null)
			{
				throw new ArgumentNullException("target");
			}
			if (interceptors == null)
			{
				throw new ArgumentNullException("interceptors");
			}
			if (!interfaceToProxy.IsInterface)
			{
				throw new ArgumentException("Specified type is not an interface", "interfaceToProxy");
			}
			Type type = target.GetType();
			if (!interfaceToProxy.IsAssignableFrom(type))
			{
				throw new ArgumentException("Target does not implement interface " + interfaceToProxy.FullName, "target");
			}
			CheckNotGenericTypeDefinition(interfaceToProxy, "interfaceToProxy");
			CheckNotGenericTypeDefinitions(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			Type type2 = CreateInterfaceProxyTypeWithTarget(interfaceToProxy, additionalInterfacesToProxy, type, options);
			List<object> constructorArguments = GetConstructorArguments(target, interceptors, options);
			return Activator.CreateInstance(type2, constructorArguments.ToArray());
		}

		protected List<object> GetConstructorArguments(object target, IInterceptor[] interceptors, ProxyGenerationOptions options)
		{
			List<object> list = new List<object>(options.MixinData.Mixins) { interceptors, target };
			if (options.Selector != null)
			{
				list.Add(options.Selector);
			}
			return list;
		}

		public object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, object target, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithTargetInterface(interfaceToProxy, target, ProxyGenerationOptions.Default, interceptors);
		}

		public TInterface CreateInterfaceProxyWithTargetInterface<TInterface>(TInterface target, params IInterceptor[] interceptors) where TInterface : class
		{
			return (TInterface)CreateInterfaceProxyWithTargetInterface(typeof(TInterface), target, ProxyGenerationOptions.Default, interceptors);
		}

		public TInterface CreateInterfaceProxyWithTargetInterface<TInterface>(TInterface target, ProxyGenerationOptions options, params IInterceptor[] interceptors) where TInterface : class
		{
			return (TInterface)CreateInterfaceProxyWithTargetInterface(typeof(TInterface), target, options, interceptors);
		}

		public object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithTargetInterface(interfaceToProxy, additionalInterfacesToProxy, target, ProxyGenerationOptions.Default, interceptors);
		}

		public object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithTargetInterface(interfaceToProxy, null, target, options, interceptors);
		}

		public virtual object CreateInterfaceProxyWithTargetInterface(Type interfaceToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			if (interfaceToProxy == null)
			{
				throw new ArgumentNullException("interfaceToProxy");
			}
			if (target != null && !interfaceToProxy.IsInstanceOfType(target))
			{
				throw new ArgumentException("Target does not implement interface " + interfaceToProxy.FullName, "target");
			}
			if (interceptors == null)
			{
				throw new ArgumentNullException("interceptors");
			}
			if (!interfaceToProxy.IsInterface)
			{
				throw new ArgumentException("Specified type is not an interface", "interfaceToProxy");
			}
			if (target != null && OperatingSystem.IsWindows() && Marshal.IsComObject(target))
			{
				Guid iid = interfaceToProxy.GUID;
				if (iid != Guid.Empty)
				{
					IntPtr iUnknownForObject = Marshal.GetIUnknownForObject(target);
					IntPtr ppv = IntPtr.Zero;
					int num = Marshal.QueryInterface(iUnknownForObject, ref iid, out ppv);
					bool flag = ppv == IntPtr.Zero;
					Marshal.Release(iUnknownForObject);
					if (!flag)
					{
						Marshal.Release(ppv);
					}
					if (num == 0 && flag)
					{
						throw new ArgumentException("Target COM object does not implement interface " + interfaceToProxy.FullName, "target");
					}
				}
			}
			CheckNotGenericTypeDefinition(interfaceToProxy, "interfaceToProxy");
			CheckNotGenericTypeDefinitions(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			Type type = CreateInterfaceProxyTypeWithTargetInterface(interfaceToProxy, additionalInterfacesToProxy, options);
			List<object> constructorArguments = GetConstructorArguments(target, interceptors, options);
			return Activator.CreateInstance(type, constructorArguments.ToArray());
		}

		public TInterface CreateInterfaceProxyWithoutTarget<TInterface>(IInterceptor interceptor) where TInterface : class
		{
			return (TInterface)CreateInterfaceProxyWithoutTarget(typeof(TInterface), interceptor);
		}

		public TInterface CreateInterfaceProxyWithoutTarget<TInterface>(params IInterceptor[] interceptors) where TInterface : class
		{
			return (TInterface)CreateInterfaceProxyWithoutTarget(typeof(TInterface), interceptors);
		}

		public TInterface CreateInterfaceProxyWithoutTarget<TInterface>(ProxyGenerationOptions options, params IInterceptor[] interceptors) where TInterface : class
		{
			return (TInterface)CreateInterfaceProxyWithoutTarget(typeof(TInterface), Type.EmptyTypes, options, interceptors);
		}

		public object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, IInterceptor interceptor)
		{
			return CreateInterfaceProxyWithoutTarget(interfaceToProxy, Type.EmptyTypes, ProxyGenerationOptions.Default, interceptor);
		}

		public object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithoutTarget(interfaceToProxy, Type.EmptyTypes, ProxyGenerationOptions.Default, interceptors);
		}

		public object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithoutTarget(interfaceToProxy, additionalInterfacesToProxy, ProxyGenerationOptions.Default, interceptors);
		}

		public object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			return CreateInterfaceProxyWithoutTarget(interfaceToProxy, Type.EmptyTypes, options, interceptors);
		}

		public virtual object CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			if (interfaceToProxy == null)
			{
				throw new ArgumentNullException("interfaceToProxy");
			}
			if (interceptors == null)
			{
				throw new ArgumentNullException("interceptors");
			}
			if (!interfaceToProxy.IsInterface)
			{
				throw new ArgumentException("Specified type is not an interface", "interfaceToProxy");
			}
			CheckNotGenericTypeDefinition(interfaceToProxy, "interfaceToProxy");
			CheckNotGenericTypeDefinitions(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			Type type = CreateInterfaceProxyTypeWithoutTarget(interfaceToProxy, additionalInterfacesToProxy, options);
			List<object> constructorArguments = GetConstructorArguments(null, interceptors, options);
			return Activator.CreateInstance(type, constructorArguments.ToArray());
		}

		public TClass CreateClassProxyWithTarget<TClass>(TClass target, params IInterceptor[] interceptors) where TClass : class
		{
			return (TClass)CreateClassProxyWithTarget(typeof(TClass), Type.EmptyTypes, target, ProxyGenerationOptions.Default, new object[0], interceptors);
		}

		public TClass CreateClassProxyWithTarget<TClass>(TClass target, ProxyGenerationOptions options, params IInterceptor[] interceptors) where TClass : class
		{
			return (TClass)CreateClassProxyWithTarget(typeof(TClass), Type.EmptyTypes, target, options, new object[0], interceptors);
		}

		public object CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, object target, params IInterceptor[] interceptors)
		{
			return CreateClassProxyWithTarget(classToProxy, additionalInterfacesToProxy, target, ProxyGenerationOptions.Default, new object[0], interceptors);
		}

		public object CreateClassProxyWithTarget(Type classToProxy, object target, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors)
		{
			return CreateClassProxyWithTarget(classToProxy, Type.EmptyTypes, target, options, constructorArguments, interceptors);
		}

		public object CreateClassProxyWithTarget(Type classToProxy, object target, object[] constructorArguments, params IInterceptor[] interceptors)
		{
			return CreateClassProxyWithTarget(classToProxy, Type.EmptyTypes, target, ProxyGenerationOptions.Default, constructorArguments, interceptors);
		}

		public object CreateClassProxyWithTarget(Type classToProxy, object target, params IInterceptor[] interceptors)
		{
			return CreateClassProxyWithTarget(classToProxy, Type.EmptyTypes, target, ProxyGenerationOptions.Default, new object[0], interceptors);
		}

		public object CreateClassProxyWithTarget(Type classToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			return CreateClassProxyWithTarget(classToProxy, Type.EmptyTypes, target, options, new object[0], interceptors);
		}

		public object CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			return CreateClassProxyWithTarget(classToProxy, additionalInterfacesToProxy, target, options, new object[0], interceptors);
		}

		public virtual object CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, object target, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors)
		{
			if (classToProxy == null)
			{
				throw new ArgumentNullException("classToProxy");
			}
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (!classToProxy.IsClass)
			{
				throw new ArgumentException("'classToProxy' must be a class", "classToProxy");
			}
			CheckNotGenericTypeDefinition(classToProxy, "classToProxy");
			CheckNotGenericTypeDefinitions(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			Type proxyType = CreateClassProxyTypeWithTarget(classToProxy, additionalInterfacesToProxy, options);
			List<object> list = BuildArgumentListForClassProxyWithTarget(target, options, interceptors);
			if (constructorArguments != null && constructorArguments.Length != 0)
			{
				list.AddRange(constructorArguments);
			}
			return CreateClassProxyInstance(proxyType, list, classToProxy, constructorArguments);
		}

		public TClass CreateClassProxy<TClass>(params IInterceptor[] interceptors) where TClass : class
		{
			return (TClass)CreateClassProxy(typeof(TClass), ProxyGenerationOptions.Default, interceptors);
		}

		public TClass CreateClassProxy<TClass>(ProxyGenerationOptions options, params IInterceptor[] interceptors) where TClass : class
		{
			return (TClass)CreateClassProxy(typeof(TClass), options, interceptors);
		}

		public object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, params IInterceptor[] interceptors)
		{
			return CreateClassProxy(classToProxy, additionalInterfacesToProxy, ProxyGenerationOptions.Default, interceptors);
		}

		public object CreateClassProxy(Type classToProxy, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors)
		{
			return CreateClassProxy(classToProxy, null, options, constructorArguments, interceptors);
		}

		public object CreateClassProxy(Type classToProxy, object[] constructorArguments, params IInterceptor[] interceptors)
		{
			return CreateClassProxy(classToProxy, null, ProxyGenerationOptions.Default, constructorArguments, interceptors);
		}

		public object CreateClassProxy(Type classToProxy, params IInterceptor[] interceptors)
		{
			return CreateClassProxy(classToProxy, null, ProxyGenerationOptions.Default, null, interceptors);
		}

		public object CreateClassProxy(Type classToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			return CreateClassProxy(classToProxy, null, options, interceptors);
		}

		public object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, params IInterceptor[] interceptors)
		{
			return CreateClassProxy(classToProxy, additionalInterfacesToProxy, options, null, interceptors);
		}

		public virtual object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors)
		{
			if (classToProxy == null)
			{
				throw new ArgumentNullException("classToProxy");
			}
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (!classToProxy.IsClass)
			{
				throw new ArgumentException("'classToProxy' must be a class", "classToProxy");
			}
			CheckNotGenericTypeDefinition(classToProxy, "classToProxy");
			CheckNotGenericTypeDefinitions(additionalInterfacesToProxy, "additionalInterfacesToProxy");
			Type proxyType = CreateClassProxyType(classToProxy, additionalInterfacesToProxy, options);
			List<object> list = BuildArgumentListForClassProxy(options, interceptors);
			if (constructorArguments != null && constructorArguments.Length != 0)
			{
				list.AddRange(constructorArguments);
			}
			return CreateClassProxyInstance(proxyType, list, classToProxy, constructorArguments);
		}

		protected object CreateClassProxyInstance(Type proxyType, List<object> proxyArguments, Type classToProxy, object[] constructorArguments)
		{
			try
			{
				return Activator.CreateInstance(proxyType, proxyArguments.ToArray());
			}
			catch (MissingMethodException innerException)
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendFormat("Can not instantiate proxy of class: {0}.", classToProxy.FullName);
				stringBuilder.AppendLine();
				if (constructorArguments == null || constructorArguments.Length == 0)
				{
					stringBuilder.Append("Could not find a parameterless constructor.");
				}
				else
				{
					stringBuilder.AppendLine("Could not find a constructor that would match given arguments:");
					foreach (object obj in constructorArguments)
					{
						string value = ((obj == null) ? "<null>" : obj.GetType().ToString());
						stringBuilder.AppendLine(value);
					}
				}
				throw new ArgumentException(stringBuilder.ToString(), "constructorArguments", innerException);
			}
		}

		protected void CheckNotGenericTypeDefinition(Type type, string argumentName)
		{
			if (type != null && type.IsGenericTypeDefinition)
			{
				throw new ArgumentException("Can not create proxy for type " + type.GetBestName() + " because it is an open generic type.", argumentName);
			}
		}

		protected void CheckNotGenericTypeDefinitions(IEnumerable<Type> types, string argumentName)
		{
			if (types == null)
			{
				return;
			}
			foreach (Type type in types)
			{
				CheckNotGenericTypeDefinition(type, argumentName);
			}
		}

		protected List<object> BuildArgumentListForClassProxyWithTarget(object target, ProxyGenerationOptions options, IInterceptor[] interceptors)
		{
			List<object> list = new List<object>();
			list.Add(target);
			list.AddRange(options.MixinData.Mixins);
			list.Add(interceptors);
			if (options.Selector != null)
			{
				list.Add(options.Selector);
			}
			return list;
		}

		protected List<object> BuildArgumentListForClassProxy(ProxyGenerationOptions options, IInterceptor[] interceptors)
		{
			List<object> list = new List<object>(options.MixinData.Mixins) { interceptors };
			if (options.Selector != null)
			{
				list.Add(options.Selector);
			}
			return list;
		}

		protected Type CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			return ProxyBuilder.CreateClassProxyType(classToProxy, additionalInterfacesToProxy, options);
		}

		protected Type CreateInterfaceProxyTypeWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, Type targetType, ProxyGenerationOptions options)
		{
			return ProxyBuilder.CreateInterfaceProxyTypeWithTarget(interfaceToProxy, additionalInterfacesToProxy, targetType, options);
		}

		protected Type CreateInterfaceProxyTypeWithTargetInterface(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			return ProxyBuilder.CreateInterfaceProxyTypeWithTargetInterface(interfaceToProxy, additionalInterfacesToProxy, options);
		}

		protected Type CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			return ProxyBuilder.CreateInterfaceProxyTypeWithoutTarget(interfaceToProxy, additionalInterfacesToProxy, options);
		}

		protected Type CreateClassProxyTypeWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
		{
			return ProxyBuilder.CreateClassProxyTypeWithTarget(classToProxy, additionalInterfacesToProxy, options);
		}
	}
	public static class ProxyUtil
	{
		private static readonly SynchronizedDictionary<Assembly, bool> internalsVisibleToDynamicProxy = new SynchronizedDictionary<Assembly, bool>();

		public static TDelegate CreateDelegateToMixin<TDelegate>(object proxy)
		{
			return (TDelegate)(object)CreateDelegateToMixin(proxy, typeof(TDelegate));
		}

		public static Delegate CreateDelegateToMixin(object proxy, Type delegateType)
		{
			if (proxy == null)
			{
				throw new ArgumentNullException("proxy");
			}
			if (delegateType == null)
			{
				throw new ArgumentNullException("delegateType");
			}
			if (!delegateType.IsDelegateType())
			{
				throw new ArgumentException("Type is not a delegate type.", "delegateType");
			}
			MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
			MethodInfo methodInfo = proxy.GetType().GetMember("Invoke", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Cast<MethodInfo>()
				.FirstOrDefault((MethodInfo m) => MethodSignatureComparer.Instance.EqualParameters(m, invokeMethod));
			if (methodInfo == null)
			{
				throw new MissingMethodException("The proxy does not have an Invoke method that is compatible with the requested delegate type.");
			}
			return Delegate.CreateDelegate(delegateType, proxy, methodInfo);
		}

		public static object GetUnproxiedInstance(object instance)
		{
			if (instance is IProxyTargetAccessor proxyTargetAccessor)
			{
				instance = proxyTargetAccessor.DynProxyGetTarget();
			}
			return instance;
		}

		public static Type GetUnproxiedType(object instance)
		{
			if (instance is IProxyTargetAccessor proxyTargetAccessor)
			{
				object obj = proxyTargetAccessor.DynProxyGetTarget();
				if (obj != null)
				{
					if (obj == instance)
					{
						return instance.GetType().BaseType;
					}
					instance = obj;
				}
			}
			return instance.GetType();
		}

		public static bool IsProxy(object instance)
		{
			return instance is IProxyTargetAccessor;
		}

		public static bool IsProxyType(Type type)
		{
			return typeof(IProxyTargetAccessor).IsAssignableFrom(type);
		}

		public static bool IsAccessible(MethodBase method)
		{
			if (IsAccessibleMethod(method))
			{
				return IsAccessibleType(method.DeclaringType);
			}
			return false;
		}

		public static bool IsAccessible(MethodBase method, out string message)
		{
			if (IsAccessible(method))
			{
				message = null;
				return true;
			}
			message = CreateMessageForInaccessibleMethod(method);
			return false;
		}

		public static bool IsAccessible(Type type)
		{
			return IsAccessibleType(type);
		}

		internal static bool AreInternalsVisibleToDynamicProxy(Assembly asm)
		{
			return internalsVisibleToDynamicProxy.GetOrAdd(asm, (Assembly a) => asm.GetCustomAttributes<InternalsVisibleToAttribute>().Any((InternalsVisibleToAttribute attr) => attr.AssemblyName.Contains(ModuleScope.DEFAULT_ASSEMBLY_NAME)));
		}

		internal static bool IsAccessibleType(Type target)
		{
			if (target.IsPublic || target.IsNestedPublic)
			{
				return true;
			}
			bool isNested = target.IsNested;
			bool flag = isNested && (target.IsNestedAssembly || target.IsNestedFamORAssem);
			if (((!target.IsVisible && !isNested) || flag) && AreInternalsVisibleToDynamicProxy(target.Assembly))
			{
				return true;
			}
			return false;
		}

		internal static bool IsAccessibleMethod(MethodBase method)
		{
			if (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly)
			{
				return true;
			}
			if (method.IsAssembly || method.IsFamilyAndAssembly)
			{
				return AreInternalsVisibleToDynamicProxy(method.DeclaringType.Assembly);
			}
			return false;
		}

		internal static bool IsInternal(MethodBase method)
		{
			if (!method.IsAssembly)
			{
				if (method.IsFamilyAndAssembly)
				{
					return !method.IsFamilyOrAssembly;
				}
				return false;
			}
			return true;
		}

		private static string CreateMessageForInaccessibleMethod(MethodBase inaccessibleMethod)
		{
			Assembly assembly = inaccessibleMethod.DeclaringType.Assembly;
			string text = $"Can not create proxy for method {inaccessibleMethod} because it or its declaring type is not accessible. ";
			string text2 = ExceptionMessageBuilder.CreateInstructionsToMakeVisible(assembly);
			return text + text2;
		}
	}
	public class StandardInterceptor : IInterceptor
	{
		public void Intercept(IInvocation invocation)
		{
			PreProceed(invocation);
			PerformProceed(invocation);
			PostProceed(invocation);
		}

		protected virtual void PerformProceed(IInvocation invocation)
		{
			invocation.Proceed();
		}

		protected virtual void PreProceed(IInvocation invocation)
		{
		}

		protected virtual void PostProceed(IInvocation invocation)
		{
		}
	}
}
namespace Castle.DynamicProxy.Tokens
{
	internal static class DelegateMethods
	{
		public static readonly MethodInfo CreateDelegate = typeof(Delegate).GetMethod("CreateDelegate", new Type[3]
		{
			typeof(Type),
			typeof(object),
			typeof(MethodInfo)
		});
	}
	internal static class InterceptorSelectorMethods
	{
		public static readonly MethodInfo SelectInterceptors = typeof(IInterceptorSelector).GetMethod("SelectInterceptors", BindingFlags.Instance | BindingFlags.Public);
	}
	internal static class InvocationMethods
	{
		public static readonly ConstructorInfo CompositionInvocationConstructor = typeof(CompositionInvocation).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[5]
		{
			typeof(object),
			typeof(object),
			typeof(IInterceptor[]),
			typeof(MethodInfo),
			typeof(object[])
		}, null);

		public static readonly MethodInfo CompositionInvocationEnsureValidTarget = typeof(CompositionInvocation).GetMethod("EnsureValidTarget", BindingFlags.Instance | BindingFlags.NonPublic);

		public static readonly MethodInfo GetArgumentValue = typeof(AbstractInvocation).GetMethod("GetArgumentValue");

		public static readonly MethodInfo GetArguments = typeof(AbstractInvocation).GetMethod("get_Arguments");

		public static readonly MethodInfo GetReturnValue = typeof(AbstractInvocation).GetMethod("get_ReturnValue");

		public static readonly ConstructorInfo InheritanceInvocationConstructor = typeof(InheritanceInvocation).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[5]
		{
			typeof(Type),
			typeof(object),
			typeof(IInterceptor[]),
			typeof(MethodInfo),
			typeof(object[])
		}, null);

		public static readonly ConstructorInfo InheritanceInvocationConstructorWithSelector = typeof(InheritanceInvocation).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[7]
		{
			typeof(Type),
			typeof(object),
			typeof(IInterceptor[]),
			typeof(MethodInfo),
			typeof(object[]),
			typeof(IInterceptorSelector),
			typeof(IInterceptor[]).MakeByRefType()
		}, null);

		public static readonly MethodInfo Proceed = typeof(AbstractInvocation).GetMethod("Proceed", BindingFlags.Instance | BindingFlags.Public);

		public static readonly FieldInfo ProxyObject = typeof(AbstractInvocation).GetField("proxyObject", BindingFlags.Instance | BindingFlags.NonPublic);

		public static readonly MethodInfo SetArgumentValue = typeof(AbstractInvocation).GetMethod("SetArgumentValue");

		public static readonly MethodInfo SetGenericMethodArguments = typeof(AbstractInvocation).GetMethod("SetGenericMethodArguments", new Type[1] { typeof(Type[]) });

		public static readonly MethodInfo SetReturnValue = typeof(AbstractInvocation).GetMethod("set_ReturnValue");

		public static readonly FieldInfo CompositionInvocationTarget = typeof(CompositionInvocation).GetField("target", BindingFlags.Instance | BindingFlags.NonPublic);

		public static readonly MethodInfo ThrowOnNoTarget = typeof(AbstractInvocation).GetMethod("ThrowOnNoTarget", BindingFlags.Instance | BindingFlags.NonPublic);

		public static readonly MethodInfo EnsureValidTarget = CompositionInvocationEnsureValidTarget;

		public static readonly FieldInfo Target = CompositionInvocationTarget;
	}
	internal static class MethodBaseMethods
	{
		public static readonly MethodInfo GetMethodFromHandle = typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[2]
		{
			typeof(RuntimeMethodHandle),
			typeof(RuntimeTypeHandle)
		});
	}
	internal static class TypeMethods
	{
		public static readonly MethodInfo GetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");

		public static readonly MethodInfo StaticGetType = typeof(Type).GetMethod("GetType", new Type[3]
		{
			typeof(string),
			typeof(bool),
			typeof(bool)
		});
	}
	internal static class TypeUtilMethods
	{
		public static readonly MethodInfo Sort = typeof(TypeUtil).GetMethod("Sort", BindingFlags.Static | BindingFlags.Public);

		public static readonly MethodInfo GetTypeOrNull = typeof(TypeUtil).GetMethod("GetTypeOrNull", BindingFlags.Static | BindingFlags.Public);
	}
}
namespace Castle.DynamicProxy.Serialization
{
	internal static class ProxyTypeConstants
	{
		public static readonly string Class = "class";

		public static readonly string ClassWithTarget = "class.with.target";

		public static readonly string InterfaceWithTarget = "interface.with.target";

		public static readonly string InterfaceWithTargetInterface = "interface.with.target.interface";

		public static readonly string InterfaceWithoutTarget = "interface.without.target";
	}
}
namespace Castle.DynamicProxy.Internal
{
	internal static class AttributeUtil
	{
		public static CustomAttributeInfo CreateInfo(CustomAttributeData attribute)
		{
			object[] arguments = GetArguments(attribute.ConstructorArguments);
			GetSettersAndFields(attribute.AttributeType, attribute.NamedArguments, out var properties, out var propertyValues, out var fields, out var fieldValues);
			return new CustomAttributeInfo(attribute.Constructor, arguments, properties, propertyValues, fields, fieldValues);
		}

		private static object[] GetArguments(IList<CustomAttributeTypedArgument> constructorArguments)
		{
			object[] array = new object[constructorArguments.Count];
			for (int i = 0; i < constructorArguments.Count; i++)
			{
				array[i] = ReadAttributeValue(constructorArguments[i]);
			}
			return array;
		}

		private static object ReadAttributeValue(CustomAttributeTypedArgument argument)
		{
			object value = argument.Value;
			if (argument.ArgumentType.IsArray && value is IList<CustomAttributeTypedArgument> constructorArguments)
			{
				object[] arguments = GetArguments(constructorArguments);
				object[] array = new object[arguments.Length];
				arguments.CopyTo(array, 0);
				return array;
			}
			return value;
		}

		private static void GetSettersAndFields(Type attributeType, IEnumerable<CustomAttributeNamedArgument> namedArguments, out PropertyInfo[] properties, out object[] propertyValues, out FieldInfo[] fields, out object[] fieldValues)
		{
			List<PropertyInfo> list = new List<PropertyInfo>();
			List<object> list2 = new List<object>();
			List<FieldInfo> list3 = new List<FieldInfo>();
			List<object> list4 = new List<object>();
			foreach (CustomAttributeNamedArgument namedArgument in namedArguments)
			{
				if (namedArgument.IsField)
				{
					list3.Add(attributeType.GetField(namedArgument.MemberName));
					list4.Add(ReadAttributeValue(namedArgument.TypedValue));
				}
				else
				{
					list.Add(attributeType.GetProperty(namedArgument.MemberName));
					list2.Add(ReadAttributeValue(namedArgument.TypedValue));
				}
			}
			properties = list.ToArray();
			propertyValues = list2.ToArray();
			fields = list3.ToArray();
			fieldValues = list4.ToArray();
		}

		public static IEnumerable<CustomAttributeInfo> GetNonInheritableAttributes(this MemberInfo member)
		{
			IEnumerable<CustomAttributeData> customAttributes = member.CustomAttributes;
			foreach (CustomAttributeData item in customAttributes)
			{
				Type attributeType = item.AttributeType;
				if (!ShouldSkipAttributeReplication(attributeType, ignoreInheritance: false))
				{
					CustomAttributeInfo customAttributeInfo;
					try
					{
						customAttributeInfo = CreateInfo(item);
					}
					catch (ArgumentException innerException)
					{
						throw new NotSupportedException(string.Format("Due to limitations in CLR, DynamicProxy was unable to successfully replicate non-inheritable attribute {0} on {1}{2}. To avoid this error you can chose not to replicate this attribute type by calling '{3}.Add(typeof({0}))'.", attributeType.FullName, member.DeclaringType.FullName, (member is TypeInfo) ? "" : ("." + member.Name), typeof(AttributesToAvoidReplicating).FullName), innerException);
					}
					if (customAttributeInfo != null)
					{
						yield return customAttributeInfo;
					}
				}
			}
		}

		public static IEnumerable<CustomAttributeInfo> GetNonInheritableAttributes(this ParameterInfo parameter)
		{
			IEnumerable<CustomAttributeData> customAttributes = parameter.CustomAttributes;
			bool ignoreInheritance = parameter.Member is ConstructorInfo;
			foreach (CustomAttributeData item in customAttributes)
			{
				if (!ShouldSkipAttributeReplication(item.AttributeType, ignoreInheritance))
				{
					CustomAttributeInfo customAttributeInfo = CreateInfo(item);
					if (customAttributeInfo != null)
					{
						yield return customAttributeInfo;
					}
				}
			}
		}

		private static bool ShouldSkipAttributeReplication(Type attribute, bool ignoreInheritance)
		{
			if (!attribute.IsPublic && !attribute.IsNestedPublic)
			{
				return true;
			}
			if (AttributesToAvoidReplicating.ShouldAvoid(attribute))
			{
				return true;
			}
			if (attribute == typeof(ParamArrayAttribute))
			{
				return false;
			}
			if (!ignoreInheritance)
			{
				AttributeUsageAttribute[] array = attribute.GetCustomAttributes<AttributeUsageAttribute>(inherit: true).ToArray();
				if (array.Length != 0)
				{
					return array[0].Inherited;
				}
				return true;
			}
			return false;
		}

		public static CustomAttributeInfo CreateInfo<TAttribute>() where TAttribute : Attribute, new()
		{
			return new CustomAttributeInfo(typeof(TAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
		}

		public static CustomAttributeInfo CreateInfo(Type attribute, object[] constructorArguments)
		{
			return new CustomAttributeInfo(attribute.GetConstructor(GetTypes(constructorArguments)), constructorArguments);
		}

		private static Type[] GetTypes(object[] objects)
		{
			Type[] array = new Type[objects.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = objects[i].GetType();
			}
			return array;
		}
	}
	public abstract class CompositionInvocation : AbstractInvocation
	{
		protected object target;

		public override object InvocationTarget => target;

		public override MethodInfo MethodInvocationTarget => InvocationHelper.GetMethodOnObject(target, base.Method);

		public override Type TargetType => TypeUtil.GetTypeOrNull(target);

		protected CompositionInvocation(object target, object proxy, IInterceptor[] interceptors, MethodInfo proxiedMethod, object[] arguments)
			: base(proxy, interceptors, proxiedMethod, arguments)
		{
			this.target = target;
		}

		protected void EnsureValidProxyTarget(object newTarget)
		{
			if (newTarget == null)
			{
				throw new ArgumentNullException("newTarget");
			}
			if (newTarget != proxyObject)
			{
				return;
			}
			throw new InvalidOperationException("This is a DynamicProxy2 error: target of proxy has been set to the proxy itself. This would result in recursively calling proxy methods over and over again until stack overflow, which may destabilize your program.This usually signifies a bug in the calling code. Make sure no interceptor sets proxy as its own target.");
		}

		protected void EnsureValidTarget()
		{
			if (target == null)
			{
				ThrowOnNoTarget();
			}
			if (target != proxyObject)
			{
				return;
			}
			throw new InvalidOperationException("This is a DynamicProxy2 error: target of invocation has been set to the proxy itself. This may result in recursively calling the method over and over again until stack overflow, which may destabilize your program.This usually signifies a bug in the calling code. Make sure no interceptor sets proxy as its invocation target.");
		}
	}
	public abstract class InheritanceInvocation : AbstractInvocation
	{
		private readonly Type targetType;

		public override object InvocationTarget => base.Proxy;

		public override MethodInfo MethodInvocationTarget => InvocationHelper.GetMethodOnType(targetType, base.Method);

		public override Type TargetType => targetType;

		protected InheritanceInvocation(Type targetType, object proxy, IInterceptor[] interceptors, MethodInfo proxiedMethod, object[] arguments)
			: base(proxy, interceptors, proxiedMethod, arguments)
		{
			this.targetType = targetType;
		}

		protected abstract override void InvokeMethodOnTarget();
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public sealed class InheritanceInvocationWithoutTarget : InheritanceInvocation
	{
		public InheritanceInvocationWithoutTarget(Type targetType, object proxy, IInterceptor[] interceptors, MethodInfo proxiedMethod, object[] arguments)
			: base(targetType, proxy, interceptors, proxiedMethod, arguments)
		{
		}

		protected override void InvokeMethodOnTarget()
		{
			ThrowOnNoTarget();
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public sealed class InterfaceMethodWithoutTargetInvocation : AbstractInvocation
	{
		public override object InvocationTarget => null;

		public override MethodInfo MethodInvocationTarget => null;

		public override Type TargetType => null;

		public InterfaceMethodWithoutTargetInvocation(object target, object proxy, IInterceptor[] interceptors, MethodInfo proxiedMethod, object[] arguments)
			: base(proxy, interceptors, proxiedMethod, arguments)
		{
		}

		protected override void InvokeMethodOnTarget()
		{
			ThrowOnNoTarget();
		}
	}
	internal static class InvocationHelper
	{
		private struct CacheKey : IEquatable<CacheKey>
		{
			public MethodInfo Method { get; }

			public Type Type { get; }

			public CacheKey(MethodInfo method, Type type)
			{
				Method = method;
				Type = type;
			}

			public bool Equals(CacheKey other)
			{
				if ((object)Method == other.Method)
				{
					return (object)Type == other.Type;
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj == null)
				{
					return false;
				}
				if (obj is CacheKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (((Method != null) ? Method.GetHashCode() : 0) * 397) ^ ((Type != null) ? Type.GetHashCode() : 0);
			}
		}

		private static readonly SynchronizedDictionary<CacheKey, MethodInfo> cache = new SynchronizedDictionary<CacheKey, MethodInfo>();

		public static MethodInfo GetMethodOnObject(object target, MethodInfo proxiedMethod)
		{
			if (target == null)
			{
				return null;
			}
			return GetMethodOnType(target.GetType(), proxiedMethod);
		}

		public static MethodInfo GetMethodOnType(Type type, MethodInfo proxiedMethod)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			CacheKey key = new CacheKey(proxiedMethod, type);
			return cache.GetOrAdd(key, (CacheKey ck) => ObtainMethod(proxiedMethod, type));
		}

		private static MethodInfo ObtainMethod(MethodInfo proxiedMethod, Type type)
		{
			Type[] array = null;
			if (proxiedMethod.IsGenericMethod)
			{
				array = proxiedMethod.GetGenericArguments();
				proxiedMethod = proxiedMethod.GetGenericMethodDefinition();
			}
			Type declaringType = proxiedMethod.DeclaringType;
			MethodInfo methodInfo = null;
			if (declaringType.IsInterface)
			{
				InterfaceMapping interfaceMap = type.GetInterfaceMap(declaringType);
				int num = Array.IndexOf(interfaceMap.InterfaceMethods, proxiedMethod);
				methodInfo = interfaceMap.TargetMethods[num];
			}
			else
			{
				MethodInfo[] allInstanceMethods = MethodFinder.GetAllInstanceMethods(type, BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo2 in allInstanceMethods)
				{
					if (MethodSignatureComparer.Instance.Equals(methodInfo2.GetBaseDefinition(), proxiedMethod))
					{
						methodInfo = methodInfo2;
						break;
					}
				}
			}
			if (methodInfo == null)
			{
				throw new ArgumentException($"Could not find method overriding {proxiedMethod} on type {type}. This is most likely a bug. Please report it.");
			}
			if (array == null)
			{
				return methodInfo;
			}
			return methodInfo.MakeGenericMethod(array);
		}
	}
	public static class TypeUtil
	{
		private sealed class TypeNameComparer : IComparer<Type>
		{
			public static readonly TypeNameComparer Instance = new TypeNameComparer();

			public int Compare(Type x, Type y)
			{
				int num = string.CompareOrdinal(x.FullName, y.FullName);
				if (num == 0)
				{
					return string.CompareOrdinal(x.Assembly.FullName, y.Assembly.FullName);
				}
				return num;
			}
		}

		internal static bool IsNullableType(this Type type)
		{
			if (type.IsGenericType)
			{
				return type.GetGenericTypeDefinition() == typeof(Nullable<>);
			}
			return false;
		}

		internal static FieldInfo[] GetAllFields(this Type type)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (!type.IsClass)
			{
				throw new ArgumentException($"Type {type} is not a class type. This method supports only classes");
			}
			List<FieldInfo> list = new List<FieldInfo>();
			Type type2 = type;
			while (type2 != typeof(object))
			{
				FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				list.AddRange(fields);
				type2 = type2.BaseType;
			}
			return list.ToArray();
		}

		internal static Type[] GetAllInterfaces(params Type[] types)
		{
			if (types == null)
			{
				return Type.EmptyTypes;
			}
			HashSet<Type> hashSet = new HashSet<Type>();
			foreach (Type type in types)
			{
				if (!(type == null) && (!type.IsInterface || hashSet.Add(type)))
				{
					Type[] interfaces = type.GetInterfaces();
					foreach (Type item in interfaces)
					{
						hashSet.Add(item);
					}
				}
			}
			return Sort(hashSet);
		}

		public static Type[] GetAllInterfaces(this Type type)
		{
			return GetAllInterfaces(new Type[1] { type });
		}

		public static Type GetTypeOrNull(object target)
		{
			return target?.GetType();
		}

		internal static Type[] AsTypeArray(this GenericTypeParameterBuilder[] typeInfos)
		{
			Type[] array = new Type[typeInfos.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = typeInfos[i];
			}
			return array;
		}

		internal static bool IsFinalizer(this MethodInfo methodInfo)
		{
			if (string.Equals("Finalize", methodInfo.Name))
			{
				return methodInfo.GetBaseDefinition().DeclaringType == typeof(object);
			}
			return false;
		}

		internal static bool IsGetType(this MethodInfo methodInfo)
		{
			if (methodInfo.DeclaringType == typeof(object))
			{
				return string.Equals("GetType", methodInfo.Name, StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		internal static bool IsMemberwiseClone(this MethodInfo methodInfo)
		{
			if (methodInfo.DeclaringType == typeof(object))
			{
				return string.Equals("MemberwiseClone", methodInfo.Name, StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		internal static void SetStaticField(this Type type, string fieldName, BindingFlags additionalFlags, object value)
		{
			BindingFlags bindingAttr = additionalFlags | BindingFlags.Static;
			FieldInfo field = type.GetField(fieldName, bindingAttr);
			if (field == null)
			{
				throw new DynamicProxyException($"Could not find field named '{fieldName}' on type {type}. This is likely a bug in DynamicProxy. Please report it.");
			}
			try
			{
				field.SetValue(null, value);
			}
			catch (MissingFieldException innerException)
			{
				throw new DynamicProxyException($"Could not find field named '{fieldName}' on type {type}. This is likely a bug in DynamicProxy. Please report it.", innerException);
			}
			catch (TargetException innerException2)
			{
				throw new DynamicProxyException($"There was an error trying to set field named '{fieldName}' on type {type}. This is likely a bug in DynamicProxy. Please report it.", innerException2);
			}
			catch (TargetInvocationException ex)
			{
				if (!(ex.InnerException is TypeInitializationException))
				{
					throw;
				}
				throw new DynamicProxyException($"There was an error in static constructor on type {type}. This is likely a bug in DynamicProxy. Please report it.", ex);
			}
		}

		public static MemberInfo[] Sort(MemberInfo[] members)
		{
			MemberInfo[] array = new MemberInfo[members.Length];
			Array.Copy(members, array, members.Length);
			Array.Sort(array, (MemberInfo l, MemberInfo r) => string.Compare(l.Name, r.Name, StringComparison.OrdinalIgnoreCase));
			return array;
		}

		internal static bool IsDelegateType(this Type type)
		{
			return type.BaseType == typeof(MulticastDelegate);
		}

		private static Type[] Sort(ICollection<Type> types)
		{
			Type[] array = new Type[types.Count];
			types.CopyTo(array, 0);
			Array.Sort(array, TypeNameComparer.Instance);
			return array;
		}
	}
}
namespace Castle.DynamicProxy.Generators
{
	public static class AttributesToAvoidReplicating
	{
		private static readonly object lockObject;

		private static IList<Type> attributes;

		static AttributesToAvoidReplicating()
		{
			lockObject = new object();
			attributes = new List<Type>
			{
				typeof(ComImportAttribute),
				typeof(MarshalAsAttribute),
				typeof(TypeIdentifierAttribute),
				typeof(SecurityAttribute)
			};
		}

		public static void Add(Type attribute)
		{
			lock (lockObject)
			{
				attributes = new List<Type>(attributes) { attribute };
			}
		}

		public static void Add<T>()
		{
			Add(typeof(T));
		}

		public static bool Contains(Type attribute)
		{
			return attributes.Contains(attribute);
		}

		internal static bool ShouldAvoid(Type attribute)
		{
			return attributes.Any((Type attr) => attr.IsAssignableFrom(attribute));
		}
	}
	internal abstract class BaseClassProxyGenerator : BaseProxyGenerator
	{
		protected abstract FieldReference TargetField { get; }

		protected BaseClassProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, ProxyGenerationOptions options)
			: base(scope, targetType, interfaces, options)
		{
			EnsureDoesNotImplementIProxyTargetAccessor(targetType, "targetType");
		}

		protected abstract CompositeTypeContributor GetProxyTargetContributor(INamingScope namingScope);

		protected abstract ProxyTargetAccessorContributor GetProxyTargetAccessorContributor();

		protected sealed override Type GenerateType(string name, INamingScope namingScope)
		{
			IEnumerable<ITypeContributor> contributors;
			IEnumerable<Type> typeImplementerMapping = GetTypeImplementerMapping(out contributors, namingScope);
			MetaType model = new MetaType();
			foreach (ITypeContributor item in contributors)
			{
				item.CollectElementsToProxy(base.ProxyGenerationOptions.Hook, model);
			}
			base.ProxyGenerationOptions.Hook.MethodsInspected();
			ClassEmitter classEmitter = BuildClassEmitter(name, targetType, typeImplementerMapping);
			CreateFields(classEmitter);
			CreateTypeAttributes(classEmitter);
			ConstructorEmitter constructorEmitter = GenerateStaticConstructor(classEmitter);
			List<FieldReference> list = new List<FieldReference>();
			FieldReference targetField = TargetField;
			if (targetField != null)
			{
				list.Add(targetField);
			}
			foreach (ITypeContributor item2 in contributors)
			{
				item2.Generate(classEmitter);
				if (item2 is MixinContributor mixinContributor)
				{
					list.AddRange(mixinContributor.Fields);
				}
			}
			FieldReference field = classEmitter.GetField("__interceptors");
			list.Add(field);
			FieldReference field2 = classEmitter.GetField("__selector");
			if (field2 != null)
			{
				list.Add(field2);
			}
			GenerateConstructors(classEmitter, targetType, list.ToArray());
			GenerateParameterlessConstructor(classEmitter, targetType, field);
			CompleteInitCacheMethod(constructorEmitter.CodeBuilder);
			new NonInheritableAttributesContributor(targetType).Generate(classEmitter);
			Type type = classEmitter.BuildType();
			InitializeStaticFields(type);
			return type;
		}

		private IEnumerable<Type> GetTypeImplementerMapping(out IEnumerable<ITypeContributor> contributors, INamingScope namingScope)
		{
			List<ITypeContributor> list = new List<ITypeContributor>(5);
			Type[] allInterfaces = targetType.GetAllInterfaces();
			Dictionary<Type, ITypeContributor> dictionary = new Dictionary<Type, ITypeContributor>();
			CompositeTypeContributor proxyTargetContributor = GetProxyTargetContributor(namingScope);
			list.Add(proxyTargetContributor);
			if (base.ProxyGenerationOptions.HasMixins)
			{
				MixinContributor mixinContributor = new MixinContributor(namingScope, canChangeTarget: false)
				{
					Logger = base.Logger
				};
				list.Add(mixinContributor);
				foreach (Type mixinInterface in base.ProxyGenerationOptions.MixinData.MixinInterfaces)
				{
					if (allInterfaces.Contains(mixinInterface))
					{
						if (interfaces.Contains(mixinInterface) && !dictionary.ContainsKey(mixinInterface))
						{
							AddMappingNoCheck(mixinInterface, proxyTargetContributor, dictionary);
							proxyTargetContributor.AddInterfaceToProxy(mixinInterface);
						}
						mixinContributor.AddEmptyInterface(mixinInterface);
					}
					else if (!dictionary.ContainsKey(mixinInterface))
					{
						mixinContributor.AddInterfaceToProxy(mixinInterface);
						AddMappingNoCheck(mixinInterface, mixinContributor, dictionary);
					}
				}
			}
			if (interfaces.Length != 0)
			{
				InterfaceProxyWithoutTargetContributor interfaceProxyWithoutTargetContributor = new InterfaceProxyWithoutTargetContributor(namingScope, (ClassEmitter c, MethodInfo m) => NullExpression.Instance)
				{
					Logger = base.Logger
				};
				list.Add(interfaceProxyWithoutTargetContributor);
				Type[] array = interfaces;
				foreach (Type type in array)
				{
					if (allInterfaces.Contains(type))
					{
						if (!dictionary.ContainsKey(type))
						{
							AddMappingNoCheck(type, proxyTargetContributor, dictionary);
							proxyTargetContributor.AddInterfaceToProxy(type);
						}
					}
					else if (!base.ProxyGenerationOptions.MixinData.ContainsMixin(type))
					{
						interfaceProxyWithoutTargetContributor.AddInterfaceToProxy(type);
						AddMapping(type, interfaceProxyWithoutTargetContributor, dictionary);
					}
				}
			}
			ProxyTargetAccessorContributor proxyTargetAccessorContributor = GetProxyTargetAccessorContributor();
			list.Add(proxyTargetAccessorContributor);
			try
			{
				AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyTargetAccessorContributor, dictionary);
			}
			catch (ArgumentException)
			{
				HandleExplicitlyPassedProxyTargetAccessor(allInterfaces);
			}
			contributors = list;
			return dictionary.Keys;
		}

		private void EnsureDoesNotImplementIProxyTargetAccessor(Type type, string name)
		{
			if (!typeof(IProxyTargetAccessor).IsAssignableFrom(type))
			{
				return;
			}
			throw new ArgumentException($"Target type for the proxy implements {typeof(IProxyTargetAccessor)} which is a DynamicProxy infrastructure interface and you should never implement it yourself. Are you trying to proxy an existing proxy?", name);
		}
	}
	internal abstract class BaseInterfaceProxyGenerator : BaseProxyGenerator
	{
		protected readonly Type proxyTargetType;

		protected FieldReference targetField;

		protected abstract bool AllowChangeTarget { get; }

		protected abstract string GeneratorType { get; }

		protected BaseInterfaceProxyGenerator(ModuleScope scope, Type targetType, Type[] interfaces, Type proxyTargetType, ProxyGenerationOptions options)
			: base(scope, targetType, interfaces, options)
		{
			CheckNotGenericTypeDefinition(proxyTargetType, "proxyTargetType");
			EnsureValidBaseType(base.ProxyGenerationOptions.BaseTypeForInterfaceProxy);
			this.proxyTargetType = proxyTargetType;
		}

		protected abstract CompositeTypeContributor GetProxyTargetContributor(Type proxyTargetType, INamingScope namingScope);

		protected abstract ProxyTargetAccessorContributor GetProxyTargetAccessorContributor();

		protected abstract void AddMappingForAdditionalInterfaces(CompositeTypeContributor contributor, Type[] proxiedInterfaces, IDictionary<Type, ITypeContributor> typeImplementerMapping, ICollection<Type> targetInterfaces);

		protected virtual ITypeContributor AddMappingForTargetType(IDictionary<Type, ITypeContributor> typeImplementerMapping, Type proxyTargetType, ICollection<Type> targetInterfaces, INamingScope namingScope)
		{
			CompositeTypeContributor proxyTargetContributor = GetProxyTargetContributor(proxyTargetType, namingScope);
			Type[] allInterfaces = targetType.GetAllInterfaces();
			Type[] array = allInterfaces;
			foreach (Type @interface in array)
			{
				proxyTargetContributor.AddInterfaceToProxy(@interface);
				AddMappingNoCheck(@interface, proxyTargetContributor, typeImplementerMapping);
			}
			AddMappingForAdditionalInterfaces(proxyTargetContributor, allInterfaces, typeImplementerMapping, targetInterfaces);
			return proxyTargetContributor;
		}

		protected override CacheKey GetCacheKey()
		{
			return new CacheKey(proxyTargetType, targetType, interfaces, base.ProxyGenerationOptions);
		}

		protected override Type GenerateType(string typeName, INamingScope namingScope)
		{
			IEnumerable<ITypeContributor> contributors;
			IEnumerable<Type> typeImplementerMapping = GetTypeImplementerMapping(proxyTargetType, out contributors, namingScope);
			MetaType model = new MetaType();
			foreach (ITypeContributor item in contributors)
			{
				item.CollectElementsToProxy(base.ProxyGenerationOptions.Hook, model);
			}
			base.ProxyGenerationOptions.Hook.MethodsInspected();
			ClassEmitter emitter;
			FieldReference interceptorsField;
			Type baseType = Init(typeName, out emitter, proxyTargetType, out interceptorsField, typeImplementerMapping);
			ConstructorEmitter constructorEmitter = GenerateStaticConstructor(emitter);
			List<FieldReference> list = new List<FieldReference>();
			foreach (ITypeContributor item2 in contributors)
			{
				item2.Generate(emitter);
				if (item2 is MixinContributor)
				{
					list.AddRange((item2 as MixinContributor).Fields);
				}
			}
			list.Add(interceptorsField);
			list.Add(targetField);
			FieldReference field = emitter.GetField("__selector");
			if (field != null)
			{
				list.Add(field);
			}
			GenerateConstructors(emitter, baseType, list.ToArray());
			CompleteInitCacheMethod(constructorEmitter.CodeBuilder);
			new NonInheritableAttributesContributor(targetType).Generate(emitter);
			Type type = emitter.BuildType();
			InitializeStaticFields(type);
			return type;
		}

		protected virtual InterfaceProxyWithoutTargetContributor GetContributorForAdditionalInterfaces(INamingScope namingScope)
		{
			return new InterfaceProxyWithoutTargetContributor(namingScope, (ClassEmitter c, MethodInfo m) => NullExpression.Instance)
			{
				Logger = base.Logger
			};
		}

		protected virtual IEnumerable<Type> GetTypeImplementerMapping(Type proxyTargetType, out IEnumerable<ITypeContributor> contributors, INamingScope namingScope)
		{
			List<ITypeContributor> list = new List<ITypeContributor>(5);
			Type[] allInterfaces = proxyTargetType.GetAllInterfaces();
			Dictionary<Type, ITypeContributor> dictionary = new Dictionary<Type, ITypeContributor>();
			ITypeContributor typeContributor = AddMappingForTargetType(dictionary, proxyTargetType, allInterfaces, namingScope);
			list.Add(typeContributor);
			if (base.ProxyGenerationOptions.HasMixins)
			{
				MixinContributor mixinContributor = new MixinContributor(namingScope, AllowChangeTarget)
				{
					Logger = base.Logger
				};
				list.Add(mixinContributor);
				foreach (Type mixinInterface in base.ProxyGenerationOptions.MixinData.MixinInterfaces)
				{
					if (allInterfaces.Contains(mixinInterface))
					{
						if (interfaces.Contains(mixinInterface))
						{
							AddMapping(mixinInterface, typeContributor, dictionary);
						}
						mixinContributor.AddEmptyInterface(mixinInterface);
					}
					else if (!dictionary.ContainsKey(mixinInterface))
					{
						mixinContributor.AddInterfaceToProxy(mixinInterface);
						dictionary.Add(mixinInterface, mixinContributor);
					}
				}
			}
			if (interfaces.Length != 0)
			{
				InterfaceProxyWithoutTargetContributor contributorForAdditionalInterfaces = GetContributorForAdditionalInterfaces(namingScope);
				list.Add(contributorForAdditionalInterfaces);
				Type[] array = interfaces;
				foreach (Type type in array)
				{
					if (!dictionary.ContainsKey(type) && !base.ProxyGenerationOptions.MixinData.ContainsMixin(type))
					{
						contributorForAdditionalInterfaces.AddInterfaceToProxy(type);
						AddMappingNoCheck(type, contributorForAdditionalInterfaces, dictionary);
					}
				}
			}
			ProxyTargetAccessorContributor proxyTargetAccessorContributor = GetProxyTargetAccessorContributor();
			list.Add(proxyTargetAccessorContributor);
			try
			{
				AddMappingNoCheck(typeof(IProxyTargetAccessor), proxyTargetAccessorContributor, dictionary);
			}
			catch (ArgumentException)
			{
				HandleExplicitlyPassedProxyTargetAccessor(allInterfaces);
			}
			contributors = list;
			return dictionary.Keys;
		}

		protected virtual Type Init(string typeName, out ClassEmitter emitter, Type proxyTargetType, out FieldReference interceptorsField, IEnumerable<Type> allInterfaces)
		{
			Type baseTypeForInterfaceProxy = base.ProxyGenerationOptions.BaseTypeForInterfaceProxy;
			emitter = BuildClassEmitter(typeName, baseTypeForInterfaceProxy, allInterfaces);
			CreateFields(emitter, proxyTargetType);
			CreateTypeAttributes(emitter);
			interceptorsField = emitter.GetField("__interceptors");
			return baseTypeForInterfaceProxy;
		}

		private void CreateFields(ClassEmitter emitter, Type proxyTargetType)
		{
			base.CreateFields(emitter);
			targetField = emitter.CreateField("__target", proxyTargetType);
		}

		private void EnsureValidBaseType(Type type)
		{
			if (type == null)
			{
				throw new ArgumentException("Base type for proxy is null reference. Please set it to System.Object or some other valid type.");
			}
			if (!type.IsClass)
			{
				ThrowInvalidBaseType(type, "it is not a class type");
			}
			if (type.IsSealed)
			{
				ThrowInvalidBaseType(type, "it is sealed");
			}
			ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (constructor == null || constructor.IsPrivate)
			{
				ThrowInvalidBaseType(type, "it does not have accessible parameterless constructor");
			}
		}

		private void ThrowInvalidBaseType(Type type, string doesNotHaveAccessibleParameterlessConstructor

UniverseLib.IL2CPP.Interop.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using HarmonyLib;
using Il2CppInterop.Common;
using Il2CppInterop.Common.Attributes;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppSystem;
using Il2CppSystem.Collections;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Il2CppSystem.Threading;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UniverseLib.Config;
using UniverseLib.Input;
using UniverseLib.Reflection;
using UniverseLib.Runtime;
using UniverseLib.Runtime.Il2Cpp;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.ObjectPool;
using UniverseLib.UI.Panels;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("UniverseLib")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Sinai")]
[assembly: AssemblyProduct("UniverseLib")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b21dbde3-5d6f-4726-93ab-cc3cc68bae7d")]
[assembly: AssemblyFileVersion("1.5.1")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.1.0")]
[module: UnverifiableCode]
namespace UniverseLib
{
	public static class ReflectionExtensions
	{
		public static Type GetActualType(this object obj)
		{
			return ReflectionUtility.Instance.Internal_GetActualType(obj);
		}

		public static object TryCast(this object obj)
		{
			return ReflectionUtility.Instance.Internal_TryCast(obj, ReflectionUtility.Instance.Internal_GetActualType(obj));
		}

		public static object TryCast(this object obj, Type castTo)
		{
			return ReflectionUtility.Instance.Internal_TryCast(obj, castTo);
		}

		public static T TryCast<T>(this object obj)
		{
			try
			{
				return (T)ReflectionUtility.Instance.Internal_TryCast(obj, typeof(T));
			}
			catch
			{
				return default(T);
			}
		}

		[Obsolete("This method is no longer necessary, just use Assembly.GetTypes().", false)]
		public static IEnumerable<Type> TryGetTypes(this Assembly asm)
		{
			return asm.GetTypes();
		}

		public static bool ReferenceEqual(this object objA, object objB)
		{
			if (objA == objB)
			{
				return true;
			}
			Object val = (Object)((objA is Object) ? objA : null);
			if (val != null)
			{
				Object val2 = (Object)((objB is Object) ? objB : null);
				if (val2 != null && Object.op_Implicit(val) && Object.op_Implicit(val2) && val.m_CachedPtr == val2.m_CachedPtr)
				{
					return true;
				}
			}
			Object val3 = (Object)((objA is Object) ? objA : null);
			if (val3 != null)
			{
				Object val4 = (Object)((objB is Object) ? objB : null);
				if (val4 != null && ((Il2CppObjectBase)val3).Pointer == ((Il2CppObjectBase)val4).Pointer)
				{
					return true;
				}
			}
			return false;
		}

		public static string ReflectionExToString(this Exception e, bool innerMost = true)
		{
			if (e == null)
			{
				return "The exception was null.";
			}
			if (innerMost)
			{
				e = e.GetInnerMostException();
			}
			return $"{e.GetType()}: {e.Message}";
		}

		public static Exception GetInnerMostException(this Exception e)
		{
			while (e != null && e.InnerException != null && !(e.InnerException is RuntimeWrappedException))
			{
				e = e.InnerException;
			}
			return e;
		}
	}
	internal class Il2CppDictionary : IEnumerator<DictionaryEntry>, IEnumerator, IDisposable
	{
		private readonly Il2CppEnumerator keysEnumerator;

		private readonly Il2CppEnumerator valuesEnumerator;

		public object Current => new DictionaryEntry(keysEnumerator.Current, valuesEnumerator.Current);

		DictionaryEntry IEnumerator<DictionaryEntry>.Current => new DictionaryEntry(keysEnumerator.Current, valuesEnumerator.Current);

		public Il2CppDictionary(Il2CppEnumerator keysEnumerator, Il2CppEnumerator valuesEnumerator)
		{
			this.keysEnumerator = keysEnumerator;
			this.valuesEnumerator = valuesEnumerator;
		}

		public bool MoveNext()
		{
			return keysEnumerator.MoveNext() && valuesEnumerator.MoveNext();
		}

		public void Dispose()
		{
			throw new NotImplementedException();
		}

		public void Reset()
		{
			throw new NotImplementedException();
		}
	}
	internal class Il2CppEnumerator : IEnumerator
	{
		private readonly object enumerator;

		private readonly MethodInfo m_GetEnumerator;

		private readonly object instanceForMoveNext;

		private readonly MethodInfo m_MoveNext;

		private readonly object instanceForCurrent;

		private readonly MethodInfo p_Current;

		public object Current => p_Current.Invoke(instanceForCurrent, null);

		public bool MoveNext()
		{
			return (bool)m_MoveNext.Invoke(instanceForMoveNext, null);
		}

		public void Reset()
		{
			throw new NotImplementedException();
		}

		public Il2CppEnumerator(object instance, Type type)
		{
			m_GetEnumerator = type.GetMethod("GetEnumerator") ?? type.GetMethod("System_Collections_IEnumerable_GetEnumerator", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			enumerator = m_GetEnumerator.Invoke(instance.TryCast(m_GetEnumerator.DeclaringType), ArgumentUtility.EmptyArgs);
			if (enumerator == null)
			{
				throw new Exception("GetEnumerator returned null");
			}
			Type actualType = enumerator.GetActualType();
			m_MoveNext = actualType.GetMethod("MoveNext") ?? actualType.GetMethod("System_Collections_IEnumerator_MoveNext", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			instanceForMoveNext = enumerator.TryCast(m_MoveNext.DeclaringType);
			p_Current = actualType.GetProperty("Current")?.GetGetMethod() ?? actualType.GetMethod("System_Collections_IEnumerator_get_Current", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			instanceForCurrent = enumerator.TryCast(p_Current.DeclaringType);
		}
	}
	public class Il2CppReflection : ReflectionUtility
	{
		internal Stopwatch initStopwatch = new Stopwatch();

		internal static readonly Dictionary<string, MethodInfo> unboxMethods = new Dictionary<string, MethodInfo>();

		internal static readonly Dictionary<string, Type> il2cppPrimitivesToMono = new Dictionary<string, Type>
		{
			{
				"Il2CppSystem.Boolean",
				typeof(bool)
			},
			{
				"Il2CppSystem.Byte",
				typeof(byte)
			},
			{
				"Il2CppSystem.SByte",
				typeof(sbyte)
			},
			{
				"Il2CppSystem.Char",
				typeof(char)
			},
			{
				"Il2CppSystem.Double",
				typeof(double)
			},
			{
				"Il2CppSystem.Single",
				typeof(float)
			},
			{
				"Il2CppSystem.Int32",
				typeof(int)
			},
			{
				"Il2CppSystem.UInt32",
				typeof(uint)
			},
			{
				"Il2CppSystem.Int64",
				typeof(long)
			},
			{
				"Il2CppSystem.UInt64",
				typeof(ulong)
			},
			{
				"Il2CppSystem.Int16",
				typeof(short)
			},
			{
				"Il2CppSystem.UInt16",
				typeof(ushort)
			},
			{
				"Il2CppSystem.IntPtr",
				typeof(IntPtr)
			},
			{
				"Il2CppSystem.UIntPtr",
				typeof(UIntPtr)
			}
		};

		private const string IL2CPP_STRING_FULLNAME = "Il2CppSystem.String";

		private const string STRING_FULLNAME = "System.String";

		private static readonly Dictionary<string, IntPtr> cppClassPointers = new Dictionary<string, IntPtr>();

		private static readonly Dictionary<string, Type> obfuscatedToDeobfuscatedTypes = new Dictionary<string, Type>();

		private static readonly Dictionary<string, string> deobfuscatedToObfuscatedNames = new Dictionary<string, string>();

		internal static IntPtr cppIEnumerablePointer;

		internal static IntPtr cppIDictionaryPointer;

		protected override void Initialize()
		{
			base.Initialize();
			ReflectionUtility.Initializing = true;
			((MonoBehaviour)UniversalBehaviour.Instance).StartCoroutine(InitCoroutine().WrapToIl2Cpp());
		}

		private IEnumerator InitCoroutine()
		{
			initStopwatch.Start();
			Stopwatch sw = new Stopwatch();
			sw.Start();
			IEnumerator coro = TryLoadGameModules();
			while (coro.MoveNext())
			{
				yield return null;
			}
			Universe.Log($"Loaded Unhollowed modules in {(float)sw.ElapsedMilliseconds * 0.001f} seconds.");
			sw.Reset();
			sw.Start();
			BuildDeobfuscationCache();
			Universe.Log($"Setup deobfuscation cache in {(float)sw.ElapsedMilliseconds * 0.001f} seconds.");
			ReflectionUtility.OnTypeLoaded += TryCacheDeobfuscatedType;
			ReflectionUtility.Initializing = false;
		}

		internal override Type Internal_GetTypeByName(string fullName)
		{
			if (obfuscatedToDeobfuscatedTypes.TryGetValue(fullName, out var value))
			{
				return value;
			}
			return base.Internal_GetTypeByName(fullName);
		}

		internal override Type Internal_GetActualType(object obj)
		{
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			try
			{
				if (il2cppPrimitivesToMono.TryGetValue(type.FullName, out var value))
				{
					return value;
				}
				Il2CppObjectBase val = (Il2CppObjectBase)((obj is Il2CppObjectBase) ? obj : null);
				if (val != null)
				{
					if (type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(Il2CppArrayBase<>))
					{
						return type;
					}
					IntPtr intPtr = IL2CPP.il2cpp_object_get_class(val.Pointer);
					Object val2 = (Object)((obj is Object) ? obj : null);
					Type cppType = ((val2 == null) ? Il2CppType.TypeFromPointer(intPtr, "<unknown type>") : val2.GetIl2CppType());
					return GetUnhollowedType(cppType) ?? type;
				}
			}
			catch (Exception ex)
			{
				Universe.LogWarning("Exception in IL2CPP GetActualType: " + ex);
			}
			return type;
		}

		public static Type GetUnhollowedType(Type cppType)
		{
			if (cppType.IsArray)
			{
				return GetArrayBaseForArray(cppType);
			}
			if (ReflectionUtility.AllTypes.TryGetValue(cppType.FullName, out var value) && value.IsPrimitive)
			{
				return value;
			}
			if (IsString(cppType))
			{
				return typeof(string);
			}
			string text = cppType.FullName;
			if (obfuscatedToDeobfuscatedTypes.TryGetValue(text, out var value2))
			{
				return value2;
			}
			if (text.StartsWith("System."))
			{
				text = "Il2Cpp" + text;
			}
			if (!ReflectionUtility.AllTypes.TryGetValue(text, out var value3))
			{
				string text2;
				try
				{
					text2 = Il2CppTypeRedirector.GetAssemblyQualifiedName(cppType);
				}
				catch
				{
					text2 = cppType.AssemblyQualifiedName;
				}
				for (int i = 0; i < text2.Length; i++)
				{
					char c = text2[i];
					if (c == '<' || c == '>')
					{
						text2 = text2.Remove(i, 1);
						text2 = text2.Insert(i, "_");
					}
				}
				value3 = Type.GetType(text2);
				if (value3 == null)
				{
					Universe.LogWarning($"Failed to get Unhollowed type from '{text2}' (originally '{cppType.AssemblyQualifiedName}')!");
				}
			}
			return value3;
		}

		internal static Type GetArrayBaseForArray(Type cppType)
		{
			Type unhollowedType = GetUnhollowedType(cppType.GetElementType());
			if (unhollowedType == null)
			{
				throw new Exception("Could not get unhollowed Element type for Array: " + cppType.FullName);
			}
			if (unhollowedType.IsValueType)
			{
				return typeof(Il2CppStructArray<>).MakeGenericType(unhollowedType);
			}
			if (unhollowedType == typeof(string))
			{
				return typeof(Il2CppStringArray);
			}
			return typeof(Il2CppReferenceArray<>).MakeGenericType(unhollowedType);
		}

		internal override object Internal_TryCast(object obj, Type toType)
		{
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			if (type == toType)
			{
				return obj;
			}
			if (type.IsValueType)
			{
				if (IsIl2CppPrimitive(type) && toType.IsPrimitive)
				{
					return MakeMonoPrimitive(obj);
				}
				if (IsIl2CppPrimitive(toType))
				{
					return MakeIl2CppPrimitive(toType, obj);
				}
				if (typeof(Object).IsAssignableFrom(toType))
				{
					return BoxIl2CppObject(obj).TryCast(toType);
				}
				return obj;
			}
			if (obj is string && typeof(Object).IsAssignableFrom(toType))
			{
				return BoxStringToType(obj, toType);
			}
			Il2CppObjectBase val = (Il2CppObjectBase)((obj is Il2CppObjectBase) ? obj : null);
			if (val == null)
			{
				return obj;
			}
			if (toType.IsValueType)
			{
				return UnboxCppObject(val, toType);
			}
			if (toType == typeof(string))
			{
				return UnboxString(obj);
			}
			if (toType.IsSubclassOf(typeof(Il2CppObjectBase)))
			{
				if (!Il2CppTypeNotNull(toType, out var il2cppPtr))
				{
					return obj;
				}
				IntPtr intPtr = IL2CPP.il2cpp_object_get_class(val.Pointer);
				if (!IL2CPP.il2cpp_class_is_assignable_from(il2cppPtr, intPtr))
				{
					return obj;
				}
				if (RuntimeSpecificsStore.IsInjected(il2cppPtr))
				{
					object monoObjectFromIl2CppPointer = ClassInjectorBase.GetMonoObjectFromIl2CppPointer(val.Pointer);
					if (monoObjectFromIl2CppPointer != null)
					{
						return monoObjectFromIl2CppPointer;
					}
				}
				try
				{
					return Activator.CreateInstance(toType, val.Pointer);
				}
				catch
				{
					return obj;
				}
			}
			return obj;
		}

		public static object UnboxCppObject(Il2CppObjectBase cppObj, Type toType)
		{
			if (!toType.IsValueType)
			{
				return null;
			}
			try
			{
				if (toType.IsEnum)
				{
					Type type = ((object)cppObj).GetType();
					if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
					{
						object obj = cppObj.TryCast(type);
						PropertyInfo property = type.GetProperty("HasValue");
						if ((bool)property.GetValue(obj, null))
						{
							PropertyInfo property2 = type.GetProperty("Value");
							return Enum.Parse(toType, property2.GetValue(obj, null).ToString());
						}
						return cppObj;
					}
					return Enum.Parse(toType, ((Object)cppObj.TryCast<Enum>()).ToString());
				}
				string assemblyQualifiedName = toType.AssemblyQualifiedName;
				if (!unboxMethods.ContainsKey(assemblyQualifiedName))
				{
					unboxMethods.Add(assemblyQualifiedName, typeof(Il2CppObjectBase).GetMethod("Unbox").MakeGenericMethod(toType));
				}
				return unboxMethods[assemblyQualifiedName].Invoke(cppObj, ArgumentUtility.EmptyArgs);
			}
			catch (Exception ex)
			{
				Universe.LogWarning("Exception Unboxing Il2Cpp object to struct: " + ex);
				return null;
			}
		}

		public static Object BoxIl2CppObject(object value)
		{
			if (value == null)
			{
				return null;
			}
			try
			{
				Type type = value.GetType();
				if (!type.IsValueType)
				{
					return null;
				}
				if (type.IsEnum)
				{
					return Enum.Parse(Il2CppType.From(type), value.ToString());
				}
				if (type.IsPrimitive && ReflectionUtility.AllTypes.TryGetValue("Il2Cpp" + type.FullName, out var value2))
				{
					return BoxIl2CppObject(MakeIl2CppPrimitive(value2, value), value2);
				}
				return BoxIl2CppObject(value, type);
			}
			catch (Exception ex)
			{
				Universe.LogWarning("Exception in BoxIl2CppObject: " + ex);
				return null;
			}
		}

		private static Object BoxIl2CppObject(object cppStruct, Type structType)
		{
			object? obj = AccessTools.Method(structType, "BoxIl2CppObject", ArgumentUtility.EmptyTypes, (Type[])null).Invoke(cppStruct, ArgumentUtility.EmptyArgs);
			return (Object)((obj is Object) ? obj : null);
		}

		public static bool IsIl2CppPrimitive(object obj)
		{
			return IsIl2CppPrimitive(obj.GetType());
		}

		public static bool IsIl2CppPrimitive(Type type)
		{
			return il2cppPrimitivesToMono.ContainsKey(type.FullName);
		}

		public static object MakeMonoPrimitive(object cppPrimitive)
		{
			return AccessTools.Field(cppPrimitive.GetType(), "m_value").GetValue(cppPrimitive);
		}

		public static object MakeIl2CppPrimitive(Type cppType, object monoValue)
		{
			object obj = Activator.CreateInstance(cppType);
			AccessTools.Field(cppType, "m_value").SetValue(obj, monoValue);
			return obj;
		}

		public static bool IsString(object obj)
		{
			if (obj is string || obj is String)
			{
				return true;
			}
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != null)
			{
				Type il2CppType = val.GetIl2CppType();
				return il2CppType.FullName == "Il2CppSystem.String" || il2CppType.FullName == "System.String";
			}
			return false;
		}

		public static bool IsString(Type type)
		{
			return type == typeof(string) || type == typeof(String);
		}

		public static bool IsString(Type cppType)
		{
			return cppType.FullName == "System.String" || cppType.FullName == "Il2CppSystem.String";
		}

		public static object BoxStringToType(object value, Type castTo)
		{
			if (castTo == typeof(String))
			{
				return String.op_Implicit(value as string);
			}
			return Object.op_Implicit(value as string);
		}

		public static string UnboxString(object value)
		{
			if (value == null)
			{
				throw new ArgumentNullException("value");
			}
			if (value is string result)
			{
				return result;
			}
			Object val = (Object)((value is Object) ? value : null);
			if (val == null)
			{
				throw new NotSupportedException("Unable to unbox string from type " + value.GetActualType().FullName + ".");
			}
			string text = String.op_Implicit((String)(object)((val is String) ? val : null));
			if (string.IsNullOrEmpty(text))
			{
				text = val.ToString();
			}
			return text;
		}

		public static bool Il2CppTypeNotNull(Type type)
		{
			IntPtr il2cppPtr;
			return Il2CppTypeNotNull(type, out il2cppPtr);
		}

		public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
		{
			if (!cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
			{
				il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>).MakeGenericType(type).GetField("NativeClassPtr", BindingFlags.Static | BindingFlags.Public).GetValue(null);
				cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
			}
			return il2cppPtr != IntPtr.Zero;
		}

		private static void BuildDeobfuscationCache()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type[] types = assembly.GetTypes();
				foreach (Type type in types)
				{
					TryCacheDeobfuscatedType(type);
				}
			}
		}

		private static void TryCacheDeobfuscatedType(Type type)
		{
			try
			{
				if (!type.CustomAttributes.Any())
				{
					return;
				}
				foreach (CustomAttributeData customAttribute in type.CustomAttributes)
				{
					if (customAttribute.AttributeType == typeof(ObfuscatedNameAttribute))
					{
						string text = customAttribute.ConstructorArguments[0].Value.ToString();
						obfuscatedToDeobfuscatedTypes.Add(text, type);
						deobfuscatedToObfuscatedNames.Add(type.FullName, text);
						break;
					}
				}
			}
			catch
			{
			}
		}

		internal override string Internal_ProcessTypeInString(string theString, Type type)
		{
			if (deobfuscatedToObfuscatedNames.TryGetValue(type.FullName, out var value))
			{
				return theString.Replace(value, type.FullName);
			}
			return theString;
		}

		internal override void Internal_FindSingleton(string[] possibleNames, Type type, BindingFlags flags, List<object> instances)
		{
			foreach (string name in possibleNames)
			{
				PropertyInfo property = type.GetProperty(name, flags);
				if (property != null)
				{
					object value = property.GetValue(null, null);
					if (value != null)
					{
						instances.Add(value);
						return;
					}
				}
			}
			base.Internal_FindSingleton(possibleNames, type, flags, instances);
		}

		internal IEnumerator TryLoadGameModules()
		{
			string dir = ConfigManager.Unhollowed_Modules_Folder;
			if (Directory.Exists(dir))
			{
				string[] files = Directory.GetFiles(dir, "*.dll");
				foreach (string filePath in files)
				{
					if (initStopwatch.ElapsedMilliseconds > 10)
					{
						yield return null;
						initStopwatch.Reset();
						initStopwatch.Start();
					}
					DoLoadModule(filePath);
				}
			}
			else
			{
				Universe.LogWarning("Expected Unhollowed folder path does not exist: '" + dir + "'. If you are using the standalone release, you can specify the Unhollowed modules path when you call CreateInstance().");
			}
		}

		internal bool DoLoadModule(string fullPath)
		{
			if (string.IsNullOrEmpty(fullPath) || !File.Exists(fullPath))
			{
				return false;
			}
			try
			{
				Assembly.LoadFrom(fullPath);
				return true;
			}
			catch
			{
				return false;
			}
		}

		protected override bool Internal_IsEnumerable(Type type)
		{
			if (base.Internal_IsEnumerable(type))
			{
				return true;
			}
			try
			{
				if (cppIEnumerablePointer == IntPtr.Zero)
				{
					Il2CppTypeNotNull(typeof(IEnumerable), out cppIEnumerablePointer);
				}
				if (cppIEnumerablePointer != IntPtr.Zero && Il2CppTypeNotNull(type, out var il2cppPtr) && IL2CPP.il2cpp_class_is_assignable_from(cppIEnumerablePointer, il2cppPtr))
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		protected override bool Internal_TryGetEntryType(Type enumerableType, out Type type)
		{
			if (base.Internal_TryGetEntryType(enumerableType, out type))
			{
				return true;
			}
			if (type.IsGenericType)
			{
				type = type.GetGenericArguments()[0];
				return true;
			}
			type = typeof(object);
			return false;
		}

		protected override bool Internal_TryGetEnumerator(object instance, out IEnumerator enumerator)
		{
			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}
			if (instance is IEnumerable)
			{
				return base.Internal_TryGetEnumerator(instance, out enumerator);
			}
			enumerator = null;
			Type actualType = instance.GetActualType();
			try
			{
				enumerator = new Il2CppEnumerator(instance, actualType);
				return true;
			}
			catch (Exception value)
			{
				Universe.LogWarning($"IEnumerable of type {actualType.FullName} failed to get enumerator: {value}");
				return false;
			}
		}

		protected override bool Internal_IsDictionary(Type type)
		{
			if (base.Internal_IsDictionary(type))
			{
				return true;
			}
			try
			{
				if (cppIDictionaryPointer == IntPtr.Zero && !Il2CppTypeNotNull(typeof(IDictionary), out cppIDictionaryPointer))
				{
					return false;
				}
				if (Il2CppTypeNotNull(type, out var il2cppPtr) && IL2CPP.il2cpp_class_is_assignable_from(cppIDictionaryPointer, il2cppPtr))
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		protected override bool Internal_TryGetEntryTypes(Type type, out Type keys, out Type values)
		{
			if (base.Internal_TryGetEntryTypes(type, out keys, out values))
			{
				return true;
			}
			if (type.IsGenericType)
			{
				Type[] genericArguments = type.GetGenericArguments();
				if (genericArguments.Length == 2)
				{
					keys = genericArguments[0];
					values = genericArguments[1];
					return true;
				}
			}
			keys = typeof(object);
			values = typeof(object);
			return false;
		}

		protected override bool Internal_TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
		{
			if (dictionary is IDictionary)
			{
				return base.Internal_TryGetDictEnumerator(dictionary, out dictEnumerator);
			}
			try
			{
				Type actualType = dictionary.GetActualType();
				if (typeof(Hashtable).IsAssignableFrom(actualType))
				{
					dictEnumerator = EnumerateCppHashTable(dictionary.TryCast<Hashtable>());
					return true;
				}
				PropertyInfo property = actualType.GetProperty("Keys");
				object value = property.GetValue(dictionary.TryCast(property.DeclaringType), null);
				PropertyInfo property2 = actualType.GetProperty("Values");
				object value2 = property2.GetValue(dictionary.TryCast(property2.DeclaringType), null);
				Il2CppEnumerator keysEnumerator = new Il2CppEnumerator(value, value.GetActualType());
				Il2CppEnumerator valuesEnumerator = new Il2CppEnumerator(value2, value2.GetActualType());
				dictEnumerator = new Il2CppDictionary(keysEnumerator, valuesEnumerator);
				return true;
			}
			catch (Exception value3)
			{
				Universe.Log($"IDictionary failed to enumerate: {value3}");
				dictEnumerator = null;
				return false;
			}
		}

		private static IEnumerator<DictionaryEntry> EnumerateCppHashTable(Hashtable hashtable)
		{
			for (int i = 0; i < ((Il2CppArrayBase<bucket>)(object)hashtable.buckets).Count; i++)
			{
				bucket bucket = ((Il2CppArrayBase<bucket>)(object)hashtable.buckets)[i];
				if (bucket != null && bucket.key != null)
				{
					yield return new DictionaryEntry(bucket.key, bucket.val);
				}
			}
		}
	}
	internal static class ReflectionPatches
	{
		internal static void Init()
		{
			Universe.Patch(typeof(Assembly), "GetTypes", (MethodType)0, new Type[0], null, null, AccessTools.Method(typeof(ReflectionPatches), "Finalizer_Assembly_GetTypes", (Type[])null, (Type[])null));
		}

		public static Exception Finalizer_Assembly_GetTypes(Assembly __instance, Exception __exception, ref Type[] __result)
		{
			if (__exception != null)
			{
				if (__exception is ReflectionTypeLoadException e)
				{
					__result = ReflectionUtility.TryExtractTypesFromException(e);
				}
				else
				{
					try
					{
						__result = __instance.GetExportedTypes();
					}
					catch (ReflectionTypeLoadException e2)
					{
						__result = ReflectionUtility.TryExtractTypesFromException(e2);
					}
					catch
					{
						__result = ArgumentUtility.EmptyTypes;
					}
				}
			}
			return null;
		}
	}
	public class ReflectionUtility
	{
		public static bool Initializing;

		public const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public static readonly SortedDictionary<string, Type> AllTypes = new SortedDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);

		public static readonly List<string> AllNamespaces = new List<string>();

		private static readonly HashSet<string> uniqueNamespaces = new HashSet<string>();

		private static string[] allTypeNamesArray;

		private static readonly Dictionary<string, Type> shorthandToType = new Dictionary<string, Type>
		{
			{
				"object",
				typeof(object)
			},
			{
				"string",
				typeof(string)
			},
			{
				"bool",
				typeof(bool)
			},
			{
				"byte",
				typeof(byte)
			},
			{
				"sbyte",
				typeof(sbyte)
			},
			{
				"char",
				typeof(char)
			},
			{
				"decimal",
				typeof(decimal)
			},
			{
				"double",
				typeof(double)
			},
			{
				"float",
				typeof(float)
			},
			{
				"int",
				typeof(int)
			},
			{
				"uint",
				typeof(uint)
			},
			{
				"long",
				typeof(long)
			},
			{
				"ulong",
				typeof(ulong)
			},
			{
				"short",
				typeof(short)
			},
			{
				"ushort",
				typeof(ushort)
			},
			{
				"void",
				typeof(void)
			}
		};

		internal static readonly Dictionary<string, Type[]> baseTypes = new Dictionary<string, Type[]>();

		internal static ReflectionUtility Instance { get; private set; }

		public static event Action<Type> OnTypeLoaded;

		internal static void Init()
		{
			ReflectionPatches.Init();
			Instance = new Il2CppReflection();
			Instance.Initialize();
		}

		protected virtual void Initialize()
		{
			SetupTypeCache();
			Initializing = false;
		}

		public static string[] GetTypeNameArray()
		{
			if (allTypeNamesArray == null || allTypeNamesArray.Length != AllTypes.Count)
			{
				allTypeNamesArray = new string[AllTypes.Count];
				int num = 0;
				foreach (string key in AllTypes.Keys)
				{
					allTypeNamesArray[num] = key;
					num++;
				}
			}
			return allTypeNamesArray;
		}

		private static void SetupTypeCache()
		{
			if (Universe.Context == RuntimeContext.Mono)
			{
				ForceLoadManagedAssemblies();
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly asm in assemblies)
			{
				CacheTypes(asm);
			}
			AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
		}

		private static void AssemblyLoaded(object sender, AssemblyLoadEventArgs args)
		{
			if (!(args.LoadedAssembly == null) && !(args.LoadedAssembly.GetName().Name == "completions"))
			{
				CacheTypes(args.LoadedAssembly);
			}
		}

		private static void ForceLoadManagedAssemblies()
		{
			string path = Path.Combine(Application.dataPath, "Managed");
			if (!Directory.Exists(path))
			{
				return;
			}
			string[] files = Directory.GetFiles(path, "*.dll");
			foreach (string path2 in files)
			{
				try
				{
					Assembly assembly = Assembly.LoadFile(path2);
					assembly.GetTypes();
				}
				catch
				{
				}
			}
		}

		internal static void CacheTypes(Assembly asm)
		{
			Type[] types = asm.GetTypes();
			foreach (Type type in types)
			{
				if (!string.IsNullOrEmpty(type.Namespace) && !uniqueNamespaces.Contains(type.Namespace))
				{
					uniqueNamespaces.Add(type.Namespace);
					int j;
					for (j = 0; j < AllNamespaces.Count && type.Namespace.CompareTo(AllNamespaces[j]) >= 0; j++)
					{
					}
					AllNamespaces.Insert(j, type.Namespace);
				}
				AllTypes[type.FullName] = type;
				ReflectionUtility.OnTypeLoaded?.Invoke(type);
			}
		}

		public static Type GetTypeByName(string fullName)
		{
			return Instance.Internal_GetTypeByName(fullName);
		}

		internal virtual Type Internal_GetTypeByName(string fullName)
		{
			if (shorthandToType.TryGetValue(fullName, out var value))
			{
				return value;
			}
			AllTypes.TryGetValue(fullName, out var value2);
			if (value2 == null)
			{
				value2 = Type.GetType(fullName);
			}
			return value2;
		}

		internal virtual Type Internal_GetActualType(object obj)
		{
			return obj?.GetType();
		}

		internal virtual object Internal_TryCast(object obj, Type castTo)
		{
			return obj;
		}

		public static string ProcessTypeInString(Type type, string theString)
		{
			return Instance.Internal_ProcessTypeInString(theString, type);
		}

		internal virtual string Internal_ProcessTypeInString(string theString, Type type)
		{
			return theString;
		}

		public static void FindSingleton(string[] possibleNames, Type type, BindingFlags flags, List<object> instances)
		{
			Instance.Internal_FindSingleton(possibleNames, type, flags, instances);
		}

		internal virtual void Internal_FindSingleton(string[] possibleNames, Type type, BindingFlags flags, List<object> instances)
		{
			foreach (string name in possibleNames)
			{
				FieldInfo field = type.GetField(name, flags);
				if (field != null)
				{
					object value = field.GetValue(null);
					if (value != null)
					{
						instances.Add(value);
						break;
					}
				}
			}
		}

		public static Type[] TryExtractTypesFromException(ReflectionTypeLoadException e)
		{
			try
			{
				return e.Types.Where((Type it) => it != null).ToArray();
			}
			catch
			{
				return ArgumentUtility.EmptyTypes;
			}
		}

		public static Type[] GetAllBaseTypes(object obj)
		{
			return GetAllBaseTypes(obj?.GetActualType());
		}

		public static Type[] GetAllBaseTypes(Type type)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			string assemblyQualifiedName = type.AssemblyQualifiedName;
			if (baseTypes.TryGetValue(assemblyQualifiedName, out var value))
			{
				return value;
			}
			List<Type> list = new List<Type>();
			while (type != null)
			{
				list.Add(type);
				type = type.BaseType;
			}
			value = list.ToArray();
			baseTypes.Add(assemblyQualifiedName, value);
			return value;
		}

		public static void GetImplementationsOf(Type baseType, Action<HashSet<Type>> onResultsFetched, bool allowAbstract, bool allowGeneric, bool allowEnum)
		{
			RuntimeHelper.StartCoroutine(DoGetImplementations(onResultsFetched, baseType, allowAbstract, allowGeneric, allowEnum));
		}

		private static IEnumerator DoGetImplementations(Action<HashSet<Type>> onResultsFetched, Type baseType, bool allowAbstract, bool allowGeneric, bool allowEnum)
		{
			List<Type> resolvedTypes = new List<Type>();
			OnTypeLoaded += ourListener;
			HashSet<Type> set = new HashSet<Type>();
			IEnumerator coro2 = GetImplementationsAsync(baseType, set, allowAbstract, allowGeneric, allowEnum, DefaultTypesEnumerator());
			while (coro2.MoveNext())
			{
				yield return null;
			}
			OnTypeLoaded -= ourListener;
			if (resolvedTypes.Count > 0)
			{
				coro2 = GetImplementationsAsync(baseType, set, allowAbstract, allowGeneric, allowEnum, resolvedTypes.GetEnumerator());
				while (coro2.MoveNext())
				{
					yield return null;
				}
			}
			onResultsFetched(set);
			void ourListener(Type t)
			{
				resolvedTypes.Add(t);
			}
		}

		private static IEnumerator<Type> DefaultTypesEnumerator()
		{
			string[] names = GetTypeNameArray();
			foreach (string name in names)
			{
				yield return AllTypes[name];
			}
		}

		private static IEnumerator GetImplementationsAsync(Type baseType, HashSet<Type> set, bool allowAbstract, bool allowGeneric, bool allowEnum, IEnumerator<Type> enumerator)
		{
			Stopwatch sw = new Stopwatch();
			sw.Start();
			bool isGenericParam = baseType != null && baseType.IsGenericParameter;
			while (enumerator.MoveNext())
			{
				if (sw.ElapsedMilliseconds > 10)
				{
					yield return null;
					sw.Reset();
					sw.Start();
				}
				try
				{
					Type type = enumerator.Current;
					if (set.Contains(type) || (!allowAbstract && type.IsAbstract) || (!allowGeneric && type.IsGenericType) || (!allowEnum && type.IsEnum) || type.FullName.Contains("PrivateImplementationDetails") || type.FullName.Contains("DisplayClass") || type.FullName.Contains('<'))
					{
						continue;
					}
					if (!isGenericParam)
					{
						if (!(baseType != null) || baseType.IsAssignableFrom(type))
						{
							goto IL_0275;
						}
					}
					else if ((!type.IsClass || !baseType.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) && (!type.IsValueType || !baseType.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) && !baseType.GetGenericParameterConstraints().Any((Type it) => !it.IsAssignableFrom(type)))
					{
						goto IL_0275;
					}
					goto end_IL_00a5;
					IL_0275:
					set.Add(type);
					end_IL_00a5:;
				}
				catch
				{
				}
			}
		}

		public static bool IsEnumerable(Type type)
		{
			return Instance.Internal_IsEnumerable(type);
		}

		protected virtual bool Internal_IsEnumerable(Type type)
		{
			return typeof(IEnumerable).IsAssignableFrom(type);
		}

		public static bool TryGetEnumerator(object ienumerable, out IEnumerator enumerator)
		{
			return Instance.Internal_TryGetEnumerator(ienumerable, out enumerator);
		}

		protected virtual bool Internal_TryGetEnumerator(object list, out IEnumerator enumerator)
		{
			enumerator = (list as IEnumerable).GetEnumerator();
			return true;
		}

		public static bool TryGetEntryType(Type enumerableType, out Type type)
		{
			return Instance.Internal_TryGetEntryType(enumerableType, out type);
		}

		protected virtual bool Internal_TryGetEntryType(Type enumerableType, out Type type)
		{
			if (enumerableType.IsArray)
			{
				type = enumerableType.GetElementType();
				return true;
			}
			Type[] interfaces = enumerableType.GetInterfaces();
			foreach (Type type2 in interfaces)
			{
				if (type2.IsGenericType)
				{
					Type genericTypeDefinition = type2.GetGenericTypeDefinition();
					if (genericTypeDefinition == typeof(IEnumerable<>) || genericTypeDefinition == typeof(IList<>) || genericTypeDefinition == typeof(ICollection<>))
					{
						type = type2.GetGenericArguments()[0];
						return true;
					}
				}
			}
			type = typeof(object);
			return false;
		}

		public static bool IsDictionary(Type type)
		{
			return Instance.Internal_IsDictionary(type);
		}

		protected virtual bool Internal_IsDictionary(Type type)
		{
			return typeof(IDictionary).IsAssignableFrom(type);
		}

		public static bool TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
		{
			return Instance.Internal_TryGetDictEnumerator(dictionary, out dictEnumerator);
		}

		protected virtual bool Internal_TryGetDictEnumerator(object dictionary, out IEnumerator<DictionaryEntry> dictEnumerator)
		{
			dictEnumerator = EnumerateDictionary((IDictionary)dictionary);
			return true;
		}

		private IEnumerator<DictionaryEntry> EnumerateDictionary(IDictionary dict)
		{
			IDictionaryEnumerator enumerator = dict.GetEnumerator();
			while (enumerator.MoveNext())
			{
				yield return new DictionaryEntry(enumerator.Key, enumerator.Value);
			}
		}

		public static bool TryGetEntryTypes(Type dictionaryType, out Type keys, out Type values)
		{
			return Instance.Internal_TryGetEntryTypes(dictionaryType, out keys, out values);
		}

		protected virtual bool Internal_TryGetEntryTypes(Type dictionaryType, out Type keys, out Type values)
		{
			Type[] interfaces = dictionaryType.GetInterfaces();
			foreach (Type type in interfaces)
			{
				if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<, >))
				{
					Type[] genericArguments = type.GetGenericArguments();
					keys = genericArguments[0];
					values = genericArguments[1];
					return true;
				}
			}
			keys = typeof(object);
			values = typeof(object);
			return false;
		}
	}
	public abstract class RuntimeHelper
	{
		internal static RuntimeHelper Instance { get; private set; }

		internal static void Init()
		{
			Instance = new Il2CppProvider();
			Instance.OnInitialize();
		}

		protected internal abstract void OnInitialize();

		public static Coroutine StartCoroutine(IEnumerator routine)
		{
			return Instance.Internal_StartCoroutine(routine);
		}

		protected internal abstract Coroutine Internal_StartCoroutine(IEnumerator routine);

		public static void StopCoroutine(Coroutine coroutine)
		{
			Instance.Internal_StopCoroutine(coroutine);
		}

		protected internal abstract void Internal_StopCoroutine(Coroutine coroutine);

		public static T AddComponent<T>(GameObject obj, Type type) where T : Component
		{
			return Instance.Internal_AddComponent<T>(obj, type);
		}

		protected internal abstract T Internal_AddComponent<T>(GameObject obj, Type type) where T : Component;

		public static ScriptableObject CreateScriptable(Type type)
		{
			return Instance.Internal_CreateScriptable(type);
		}

		protected internal abstract ScriptableObject Internal_CreateScriptable(Type type);

		public static string LayerToName(int layer)
		{
			return Instance.Internal_LayerToName(layer);
		}

		protected internal abstract string Internal_LayerToName(int layer);

		public static T[] FindObjectsOfTypeAll<T>() where T : Object
		{
			return Instance.Internal_FindObjectsOfTypeAll<T>();
		}

		public static Object[] FindObjectsOfTypeAll(Type type)
		{
			return Instance.Internal_FindObjectsOfTypeAll(type);
		}

		protected internal abstract T[] Internal_FindObjectsOfTypeAll<T>() where T : Object;

		protected internal abstract Object[] Internal_FindObjectsOfTypeAll(Type type);

		public static void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list)
		{
			Instance.Internal_GraphicRaycast(raycaster, data, list);
		}

		protected internal abstract void Internal_GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list);

		public static GameObject[] GetRootGameObjects(Scene scene)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return Instance.Internal_GetRootGameObjects(scene);
		}

		protected internal abstract GameObject[] Internal_GetRootGameObjects(Scene scene);

		public static int GetRootCount(Scene scene)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return Instance.Internal_GetRootCount(scene);
		}

		protected internal abstract int Internal_GetRootCount(Scene scene);

		public static void SetColorBlockAuto(Selectable selectable, Color baseColor)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Instance.Internal_SetColorBlock(selectable, baseColor, baseColor * 1.2f, baseColor * 0.8f);
		}

		public static void SetColorBlock(Selectable selectable, ColorBlock colors)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Instance.Internal_SetColorBlock(selectable, colors);
		}

		protected internal abstract void Internal_SetColorBlock(Selectable selectable, ColorBlock colors);

		public static void SetColorBlock(Selectable selectable, Color? normal = null, Color? highlighted = null, Color? pressed = null, Color? disabled = null)
		{
			Instance.Internal_SetColorBlock(selectable, normal, highlighted, pressed, disabled);
		}

		protected internal abstract void Internal_SetColorBlock(Selectable selectable, Color? normal = null, Color? highlighted = null, Color? pressed = null, Color? disabled = null);
	}
	public class AssetBundle : Object
	{
		internal delegate IntPtr d_LoadFromFile(IntPtr path, uint crc, ulong offset);

		private delegate IntPtr d_LoadFromMemory(IntPtr binary, uint crc);

		public delegate IntPtr d_GetAllLoadedAssetBundles_Native();

		internal delegate IntPtr d_LoadAssetWithSubAssets_Internal(IntPtr _this, IntPtr name, IntPtr type);

		internal delegate IntPtr d_LoadAsset_Internal(IntPtr _this, IntPtr name, IntPtr type);

		internal delegate void d_Unload(IntPtr _this, bool unloadAllLoadedObjects);

		public readonly IntPtr m_bundlePtr = IntPtr.Zero;

		static AssetBundle()
		{
			ClassInjector.RegisterTypeInIl2Cpp<AssetBundle>();
		}

		[HideFromIl2Cpp]
		public static AssetBundle LoadFromFile(string path)
		{
			IntPtr intPtr = ICallManager.GetICallUnreliable<d_LoadFromFile>(new string[2] { "UnityEngine.AssetBundle::LoadFromFile_Internal", "UnityEngine.AssetBundle::LoadFromFile" })(IL2CPP.ManagedStringToIl2Cpp(path), 0u, 0uL);
			return (intPtr != IntPtr.Zero) ? new AssetBundle(intPtr) : null;
		}

		[HideFromIl2Cpp]
		public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0u)
		{
			IntPtr intPtr = ICallManager.GetICallUnreliable<d_LoadFromMemory>(new string[2] { "UnityEngine.AssetBundle::LoadFromMemory_Internal", "UnityEngine.AssetBundle::LoadFromMemory" })(((Il2CppObjectBase)Il2CppStructArray<byte>.op_Implicit(binary)).Pointer, crc);
			return (intPtr != IntPtr.Zero) ? new AssetBundle(intPtr) : null;
		}

		[HideFromIl2Cpp]
		public static AssetBundle[] GetAllLoadedAssetBundles()
		{
			IntPtr intPtr = ICallManager.GetICall<d_GetAllLoadedAssetBundles_Native>("UnityEngine.AssetBundle::GetAllLoadedAssetBundles_Native")();
			return (intPtr != IntPtr.Zero) ? Il2CppArrayBase<AssetBundle>.op_Implicit((Il2CppArrayBase<AssetBundle>)(object)new Il2CppReferenceArray<AssetBundle>(intPtr)) : null;
		}

		public AssetBundle(IntPtr ptr)
			: base(ptr)
		{
			m_bundlePtr = ptr;
		}

		[HideFromIl2Cpp]
		public Object[] LoadAllAssets()
		{
			IntPtr intPtr = ICallManager.GetICall<d_LoadAssetWithSubAssets_Internal>("UnityEngine.AssetBundle::LoadAssetWithSubAssets_Internal")(m_bundlePtr, IL2CPP.ManagedStringToIl2Cpp(""), ((Il2CppObjectBase)Il2CppType.Of<Object>()).Pointer);
			return (Object[])((intPtr != IntPtr.Zero) ? ((Array)Il2CppArrayBase<Object>.op_Implicit((Il2CppArrayBase<Object>)(object)new Il2CppReferenceArray<Object>(intPtr))) : ((Array)new Object[0]));
		}

		[HideFromIl2Cpp]
		public T LoadAsset<T>(string name) where T : Object
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			IntPtr intPtr = ICallManager.GetICall<d_LoadAsset_Internal>("UnityEngine.AssetBundle::LoadAsset_Internal")(m_bundlePtr, IL2CPP.ManagedStringToIl2Cpp(name), ((Il2CppObjectBase)Il2CppType.Of<T>()).Pointer);
			return (intPtr != IntPtr.Zero) ? ((Il2CppObjectBase)new Object(intPtr)).TryCast<T>() : default(T);
		}

		[HideFromIl2Cpp]
		public void Unload(bool unloadAllLoadedObjects)
		{
			ICallManager.GetICall<d_Unload>("UnityEngine.AssetBundle::Unload")(m_bundlePtr, unloadAllLoadedObjects);
		}
	}
	public static class Il2CppExtensions
	{
		public static void AddListener(this UnityEvent action, Action listener)
		{
			action.AddListener(UnityAction.op_Implicit(listener));
		}

		public static void AddListener<T>(this UnityEvent<T> action, Action<T> listener)
		{
			action.AddListener(UnityAction<T>.op_Implicit(listener));
		}

		public static void RemoveListener(this UnityEvent action, Action listener)
		{
			action.RemoveListener(UnityAction.op_Implicit(listener));
		}

		public static void RemoveListener<T>(this UnityEvent<T> action, Action<T> listener)
		{
			action.RemoveListener(UnityAction<T>.op_Implicit(listener));
		}

		public static void SetChildControlHeight(this HorizontalOrVerticalLayoutGroup group, bool value)
		{
			group.childControlHeight = value;
		}

		public static void SetChildControlWidth(this HorizontalOrVerticalLayoutGroup group, bool value)
		{
			group.childControlWidth = value;
		}
	}
	internal class UniversalBehaviour : MonoBehaviour
	{
		private static Delegate queuedDelegate;

		internal static UniversalBehaviour Instance { get; private set; }

		internal static void Setup()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			ClassInjector.RegisterTypeInIl2Cpp<UniversalBehaviour>();
			GameObject val = new GameObject("UniverseLibBehaviour");
			Object.DontDestroyOnLoad((Object)(object)val);
			((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D);
			Instance = val.AddComponent<UniversalBehaviour>();
		}

		internal void Update()
		{
			Universe.Update();
		}

		public UniversalBehaviour(IntPtr ptr)
			: base(ptr)
		{
		}

		internal static void InvokeDelegate(Delegate method)
		{
			queuedDelegate = method;
			((MonoBehaviour)Instance).Invoke("InvokeQueuedAction", 0f);
		}

		private void InvokeQueuedAction()
		{
			try
			{
				Delegate @delegate = queuedDelegate;
				queuedDelegate = null;
				@delegate?.DynamicInvoke();
			}
			catch (Exception value)
			{
				Universe.LogWarning($"Exception invoking action from IL2CPP thread: {value}");
			}
		}
	}
	public class Universe
	{
		public enum GlobalState
		{
			WaitingToSetup,
			SettingUp,
			SetupCompleted
		}

		public const string NAME = "UniverseLib";

		public const string VERSION = "1.5.1";

		public const string AUTHOR = "Sinai";

		public const string GUID = "com.sinai.universelib";

		private static float startupDelay;

		private static Action<string, LogType> logHandler;

		public static RuntimeContext Context { get; } = RuntimeContext.IL2CPP;


		public static GlobalState CurrentGlobalState { get; private set; }

		internal static Harmony Harmony { get; } = new Harmony("com.sinai.universelib");


		private static event Action OnInitialized;

		public static void Init(Action onInitialized = null, Action<string, LogType> logHandler = null)
		{
			Init(1f, onInitialized, logHandler, default(UniverseLibConfig));
		}

		public static void Init(float startupDelay, Action onInitialized, Action<string, LogType> logHandler, UniverseLibConfig config)
		{
			if (CurrentGlobalState == GlobalState.SetupCompleted)
			{
				InvokeOnInitialized(onInitialized);
				return;
			}
			if (startupDelay > Universe.startupDelay)
			{
				Universe.startupDelay = startupDelay;
			}
			ConfigManager.LoadConfig(config);
			OnInitialized += onInitialized;
			if (logHandler != null && Universe.logHandler == null)
			{
				Universe.logHandler = logHandler;
			}
			if (CurrentGlobalState == GlobalState.WaitingToSetup)
			{
				CurrentGlobalState = GlobalState.SettingUp;
				Log("UniverseLib 1.5.1 initializing...");
				UniversalBehaviour.Setup();
				ReflectionUtility.Init();
				RuntimeHelper.Init();
				RuntimeHelper.Instance.Internal_StartCoroutine(SetupCoroutine());
				Log("Finished UniverseLib initial setup.");
			}
		}

		internal static void Update()
		{
			UniversalUI.Update();
		}

		private static IEnumerator SetupCoroutine()
		{
			yield return null;
			Stopwatch sw = new Stopwatch();
			sw.Start();
			while (ReflectionUtility.Initializing || (float)sw.ElapsedMilliseconds * 0.001f < startupDelay)
			{
				yield return null;
			}
			InputManager.Init();
			UniversalUI.Init();
			Log("UniverseLib 1.5.1 initialized.");
			CurrentGlobalState = GlobalState.SetupCompleted;
			InvokeOnInitialized(Universe.OnInitialized);
		}

		private static void InvokeOnInitialized(Action onInitialized)
		{
			if (onInitialized == null)
			{
				return;
			}
			Delegate[] invocationList = onInitialized.GetInvocationList();
			foreach (Delegate @delegate in invocationList)
			{
				try
				{
					@delegate.DynamicInvoke();
				}
				catch (Exception value)
				{
					LogWarning($"Exception invoking onInitialized callback! {value}");
				}
			}
		}

		internal static void Log(object message)
		{
			Log(message, (LogType)3);
		}

		internal static void LogWarning(object message)
		{
			Log(message, (LogType)2);
		}

		internal static void LogError(object message)
		{
			Log(message, (LogType)0);
		}

		private static void Log(object message, LogType logType)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (logHandler != null)
			{
				logHandler("[UniverseLib] " + (message?.ToString() ?? string.Empty), logType);
			}
		}

		internal static bool Patch(Type type, string methodName, MethodType methodType, Type[] arguments = null, MethodInfo prefix = null, MethodInfo postfix = null, MethodInfo finalizer = null)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			try
			{
				string text = (((int)methodType == 1) ? "get_" : (((int)methodType != 2) ? string.Empty : "set_"));
				string text2 = text;
				MethodInfo methodInfo = ((arguments == null) ? type.GetMethod(text2 + methodName, AccessTools.all) : type.GetMethod(text2 + methodName, AccessTools.all, null, arguments, null));
				if (methodInfo == null)
				{
					return false;
				}
				if (Il2CppType.From(type, false) != (Type)null && Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod((MethodBase)methodInfo) == null)
				{
					Log("\t IL2CPP method has no corresponding pointer, aborting patch of " + type.FullName + "." + methodName);
					return false;
				}
				PatchProcessor val = Harmony.CreateProcessor((MethodBase)methodInfo);
				if (prefix != null)
				{
					val.AddPrefix(new HarmonyMethod(prefix));
				}
				if (postfix != null)
				{
					val.AddPostfix(new HarmonyMethod(postfix));
				}
				if (finalizer != null)
				{
					val.AddFinalizer(new HarmonyMethod(finalizer));
				}
				val.Patch();
				return true;
			}
			catch (Exception value)
			{
				LogWarning($"\t Exception patching {type.FullName}.{methodName}: {value}");
				return false;
			}
		}

		internal static bool Patch(Type type, string[] possibleNames, MethodType methodType, Type[] arguments = null, MethodInfo prefix = null, MethodInfo postfix = null, MethodInfo finalizer = null)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			foreach (string methodName in possibleNames)
			{
				if (Patch(type, methodName, methodType, arguments, prefix, postfix, finalizer))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool Patch(Type type, string[] possibleNames, MethodType methodType, Type[][] possibleArguments, MethodInfo prefix = null, MethodInfo postfix = null, MethodInfo finalizer = null)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			foreach (string methodName in possibleNames)
			{
				foreach (Type[] arguments in possibleArguments)
				{
					if (Patch(type, methodName, methodType, arguments, prefix, postfix, finalizer))
					{
						return true;
					}
				}
			}
			return false;
		}

		internal static bool Patch(Type type, string methodName, MethodType methodType, Type[][] possibleArguments, MethodInfo prefix = null, MethodInfo postfix = null, MethodInfo finalizer = null)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			foreach (Type[] arguments in possibleArguments)
			{
				if (Patch(type, methodName, methodType, arguments, prefix, postfix, finalizer))
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace UniverseLib.Utility
{
	public static class ArgumentUtility
	{
		public static readonly Type[] EmptyTypes = new Type[0];

		public static readonly object[] EmptyArgs = new object[0];

		public static readonly Type[] ParseArgs = new Type[1] { typeof(string) };
	}
	public static class IOUtility
	{
		private static readonly char[] invalidDirectoryCharacters = Path.GetInvalidPathChars();

		private static readonly char[] invalidFilenameCharacters = Path.GetInvalidFileNameChars();

		public static string EnsureValidFilePath(string fullPathWithFile)
		{
			fullPathWithFile = string.Concat(fullPathWithFile.Split(invalidDirectoryCharacters));
			Directory.CreateDirectory(Path.GetDirectoryName(fullPathWithFile));
			return fullPathWithFile;
		}

		public static string EnsureValidFilename(string filename)
		{
			return string.Concat(filename.Split(invalidFilenameCharacters));
		}
	}
	public static class MiscUtility
	{
		public static bool ContainsIgnoreCase(this string _this, string s)
		{
			return CultureInfo.CurrentCulture.CompareInfo.IndexOf(_this, s, CompareOptions.IgnoreCase) >= 0;
		}

		public static bool HasFlag(this Enum flags, Enum value)
		{
			try
			{
				ulong num = Convert.ToUInt64(value);
				return (Convert.ToUInt64(flags) & num) == num;
			}
			catch
			{
				long num2 = Convert.ToInt64(value);
				return (Convert.ToInt64(flags) & num2) == num2;
			}
		}

		public static bool EndsWith(this StringBuilder sb, string _string)
		{
			int length = _string.Length;
			if (sb.Length < length)
			{
				return false;
			}
			int num = 0;
			int num2 = sb.Length - length;
			while (num2 < sb.Length)
			{
				if (sb[num2] != _string[num])
				{
					return false;
				}
				num2++;
				num++;
			}
			return true;
		}
	}
	public static class ParseUtility
	{
		internal delegate object ParseMethod(string input);

		internal delegate string ToStringMethod(object obj);

		public static readonly string NumberFormatString = "0.####";

		private static readonly Dictionary<int, string> numSequenceStrings = new Dictionary<int, string>();

		private static readonly HashSet<Type> nonPrimitiveTypes = new HashSet<Type>
		{
			typeof(string),
			typeof(decimal),
			typeof(DateTime)
		};

		private static readonly HashSet<Type> formattedTypes = new HashSet<Type>
		{
			typeof(float),
			typeof(double),
			typeof(decimal)
		};

		private static readonly Dictionary<string, string> typeInputExamples = new Dictionary<string, string>();

		private static readonly Dictionary<string, ParseMethod> customTypes = new Dictionary<string, ParseMethod>
		{
			{
				typeof(Vector2).FullName,
				TryParseVector2
			},
			{
				typeof(Vector3).FullName,
				TryParseVector3
			},
			{
				typeof(Vector4).FullName,
				TryParseVector4
			},
			{
				typeof(Quaternion).FullName,
				TryParseQuaternion
			},
			{
				typeof(Rect).FullName,
				TryParseRect
			},
			{
				typeof(Color).FullName,
				TryParseColor
			},
			{
				typeof(Color32).FullName,
				TryParseColor32
			},
			{
				typeof(LayerMask).FullName,
				TryParseLayerMask
			}
		};

		private static readonly Dictionary<string, ToStringMethod> customTypesToString = new Dictionary<string, ToStringMethod>
		{
			{
				typeof(Vector2).FullName,
				Vector2ToString
			},
			{
				typeof(Vector3).FullName,
				Vector3ToString
			},
			{
				typeof(Vector4).FullName,
				Vector4ToString
			},
			{
				typeof(Quaternion).FullName,
				QuaternionToString
			},
			{
				typeof(Rect).FullName,
				RectToString
			},
			{
				typeof(Color).FullName,
				ColorToString
			},
			{
				typeof(Color32).FullName,
				Color32ToString
			},
			{
				typeof(LayerMask).FullName,
				LayerMaskToString
			}
		};

		public static string FormatDecimalSequence(params object[] numbers)
		{
			if (numbers.Length == 0)
			{
				return null;
			}
			return string.Format(CultureInfo.CurrentCulture, GetSequenceFormatString(numbers.Length), numbers);
		}

		internal static string GetSequenceFormatString(int count)
		{
			if (count <= 0)
			{
				return null;
			}
			if (numSequenceStrings.ContainsKey(count))
			{
				return numSequenceStrings[count];
			}
			string[] array = new string[count];
			for (int i = 0; i < count; i++)
			{
				array[i] = $"{{{i}:{NumberFormatString}}}";
			}
			string text = string.Join(" ", array);
			numSequenceStrings.Add(count, text);
			return text;
		}

		public static bool CanParse(Type type)
		{
			return !string.IsNullOrEmpty(type?.FullName) && (type.IsPrimitive || type.IsEnum || nonPrimitiveTypes.Contains(type) || customTypes.ContainsKey(type.FullName));
		}

		public static bool CanParse<T>()
		{
			return CanParse(typeof(T));
		}

		public static bool TryParse<T>(string input, out T obj, out Exception parseException)
		{
			object obj2;
			bool result = TryParse(input, typeof(T), out obj2, out parseException);
			if (obj2 != null)
			{
				obj = (T)obj2;
			}
			else
			{
				obj = default(T);
			}
			return result;
		}

		public static bool TryParse(string input, Type type, out object obj, out Exception parseException)
		{
			obj = null;
			parseException = null;
			if (type == null)
			{
				return false;
			}
			if (type == typeof(string))
			{
				obj = input;
				return true;
			}
			if (type.IsEnum)
			{
				try
				{
					obj = Enum.Parse(type, input);
					return true;
				}
				catch (Exception e)
				{
					parseException = e.GetInnerMostException();
					return false;
				}
			}
			try
			{
				if (customTypes.ContainsKey(type.FullName))
				{
					obj = customTypes[type.FullName](input);
				}
				else
				{
					obj = AccessTools.Method(type, "Parse", ArgumentUtility.ParseArgs, (Type[])null).Invoke(null, new object[1] { input });
				}
				return true;
			}
			catch (Exception e2)
			{
				Exception innerMostException = e2.GetInnerMostException();
				parseException = innerMostException;
			}
			return false;
		}

		public static string ToStringForInput<T>(object obj)
		{
			return ToStringForInput(obj, typeof(T));
		}

		public static string ToStringForInput(object obj, Type type)
		{
			if (type == null || obj == null)
			{
				return null;
			}
			if (type == typeof(string))
			{
				return obj as string;
			}
			if (type.IsEnum)
			{
				return Enum.IsDefined(type, obj) ? Enum.GetName(type, obj) : obj.ToString();
			}
			try
			{
				if (customTypes.ContainsKey(type.FullName))
				{
					return customTypesToString[type.FullName](obj);
				}
				if (formattedTypes.Contains(type))
				{
					return AccessTools.Method(type, "ToString", new Type[2]
					{
						typeof(string),
						typeof(IFormatProvider)
					}, (Type[])null).Invoke(obj, new object[2]
					{
						NumberFormatString,
						CultureInfo.CurrentCulture
					}) as string;
				}
				return obj.ToString();
			}
			catch (Exception value)
			{
				Universe.LogWarning($"Exception formatting object for input: {value}");
				return null;
			}
		}

		public static string GetExampleInput<T>()
		{
			return GetExampleInput(typeof(T));
		}

		public static string GetExampleInput(Type type)
		{
			if (!typeInputExamples.ContainsKey(type.AssemblyQualifiedName))
			{
				try
				{
					if (type.IsEnum)
					{
						typeInputExamples.Add(type.AssemblyQualifiedName, Enum.GetNames(type).First());
					}
					else
					{
						object obj = Activator.CreateInstance(type);
						typeInputExamples.Add(type.AssemblyQualifiedName, ToStringForInput(obj, type));
					}
				}
				catch (Exception message)
				{
					Universe.LogWarning("Exception generating default instance for example input for '" + type.FullName + "'");
					Universe.Log(message);
					return "";
				}
			}
			return typeInputExamples[type.AssemblyQualifiedName];
		}

		internal static object TryParseVector2(string input)
		{
			//IL_0003: 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)
			Vector2 val = default(Vector2);
			string[] array = input.Split(' ');
			val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			return val;
		}

		internal static string Vector2ToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!(obj is Vector2 val) || 1 == 0)
			{
				return null;
			}
			return FormatDecimalSequence(val.x, val.y);
		}

		internal static object TryParseVector3(string input)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			string[] array = input.Split(' ');
			val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			val.z = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
			return val;
		}

		internal static string Vector3ToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!(obj is Vector3 val) || 1 == 0)
			{
				return null;
			}
			return FormatDecimalSequence(val.x, val.y, val.z);
		}

		internal static object TryParseVector4(string input)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Vector4 val = default(Vector4);
			string[] array = input.Split(' ');
			val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			val.z = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
			val.w = float.Parse(array[3].Trim(), CultureInfo.CurrentCulture);
			return val;
		}

		internal static string Vector4ToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (!(obj is Vector4 val) || 1 == 0)
			{
				return null;
			}
			return FormatDecimalSequence(val.x, val.y, val.z, val.w);
		}

		internal static object TryParseQuaternion(string input)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			string[] array = input.Split(' ');
			if (array.Length == 4)
			{
				Quaternion val2 = default(Quaternion);
				val2.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
				val2.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
				val2.z = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
				val2.w = float.Parse(array[3].Trim(), CultureInfo.CurrentCulture);
				return val2;
			}
			val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			val.z = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
			return Quaternion.Euler(val);
		}

		internal static string QuaternionToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (!(obj is Quaternion val) || 1 == 0)
			{
				return null;
			}
			Vector3 eulerAngles = ((Quaternion)(ref val)).eulerAngles;
			return FormatDecimalSequence(eulerAngles.x, eulerAngles.y, eulerAngles.z);
		}

		internal static object TryParseRect(string input)
		{
			//IL_0003: 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)
			Rect val = default(Rect);
			string[] array = input.Split(' ');
			((Rect)(ref val)).x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			((Rect)(ref val)).y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			((Rect)(ref val)).width = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
			((Rect)(ref val)).height = float.Parse(array[3].Trim(), CultureInfo.CurrentCulture);
			return val;
		}

		internal static string RectToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!(obj is Rect val) || 1 == 0)
			{
				return null;
			}
			return FormatDecimalSequence(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, ((Rect)(ref val)).height);
		}

		internal static object TryParseColor(string input)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			string[] array = input.Split(' ');
			val.r = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.g = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			val.b = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
			if (array.Length > 3)
			{
				val.a = float.Parse(array[3].Trim(), CultureInfo.CurrentCulture);
			}
			else
			{
				val.a = 1f;
			}
			return val;
		}

		internal static string ColorToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (!(obj is Color val) || 1 == 0)
			{
				return null;
			}
			return FormatDecimalSequence(val.r, val.g, val.b, val.a);
		}

		internal static object TryParseColor32(string input)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			Color32 val = default(Color32);
			string[] array = input.Split(' ');
			val.r = byte.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
			val.g = byte.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
			val.b = byte.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
			if (array.Length > 3)
			{
				val.a = byte.Parse(array[3].Trim(), CultureInfo.CurrentCulture);
			}
			else
			{
				val.a = byte.MaxValue;
			}
			return val;
		}

		internal static string Color32ToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0060: 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)
			if (!(obj is Color32 val))
			{
				return null;
			}
			return $"{val.r} {val.g} {val.b} {val.a}";
		}

		internal static object TryParseLayerMask(string input)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return LayerMask.op_Implicit(int.Parse(input));
		}

		internal static string LayerMaskToString(object obj)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!(obj is LayerMask val) || 1 == 0)
			{
				return null;
			}
			return ((LayerMask)(ref val)).value.ToString();
		}
	}
	public static class SignatureHighlighter
	{
		public const string NAMESPACE = "#a8a8a8";

		public const string CONST = "#92c470";

		public const string CLASS_STATIC = "#3a8d71";

		public const string CLASS_INSTANCE = "#2df7b2";

		public const string STRUCT = "#0fba3a";

		public const string INTERFACE = "#9b9b82";

		public const string FIELD_STATIC = "#8d8dc6";

		public const string FIELD_INSTANCE = "#c266ff";

		public const string METHOD_STATIC = "#b55b02";

		public const string METHOD_INSTANCE = "#ff8000";

		public const string PROP_STATIC = "#588075";

		public const string PROP_INSTANCE = "#55a38e";

		public const string LOCAL_ARG = "#a6e9e9";

		public const string OPEN_COLOR = "<color=";

		public const string CLOSE_COLOR = "</color>";

		public const string OPEN_ITALIC = "<i>";

		public const string CLOSE_ITALIC = "</i>";

		public static readonly Regex ArrayTokenRegex = new Regex("\\[,*?\\]");

		private static readonly Regex colorTagRegex = new Regex("<color=#?[\\d|\\w]*>");

		public static readonly Color StringOrange = new Color(0.83f, 0.61f, 0.52f);

		public static readonly Color EnumGreen = new Color(0.57f, 0.76f, 0.43f);

		public static readonly Color KeywordBlue = new Color(0.3f, 0.61f, 0.83f);

		public static readonly string keywordBlueHex = KeywordBlue.ToHex();

		public static readonly Color NumberGreen = new Color(0.71f, 0.8f, 0.65f);

		private static readonly Dictionary<string, string> typeToRichType = new Dictionary<string, string>();

		private static readonly Dictionary<string, string> highlightedMethods = new Dictionary<string, string>();

		private static readonly Dictionary<Type, string> builtInTypesToShorthand = new Dictionary<Type, string>
		{
			{
				typeof(object),
				"object"
			},
			{
				typeof(string),
				"string"
			},
			{
				typeof(bool),
				"bool"
			},
			{
				typeof(byte),
				"byte"
			},
			{
				typeof(sbyte),
				"sbyte"
			},
			{
				typeof(char),
				"char"
			},
			{
				typeof(decimal),
				"decimal"
			},
			{
				typeof(double),
				"double"
			},
			{
				typeof(float),
				"float"
			},
			{
				typeof(int),
				"int"
			},
			{
				typeof(uint),
				"uint"
			},
			{
				typeof(long),
				"long"
			},
			{
				typeof(ulong),
				"ulong"
			},
			{
				typeof(short),
				"short"
			},
			{
				typeof(ushort),
				"ushort"
			},
			{
				typeof(void),
				"void"
			}
		};

		public static string Parse(Type type, bool includeNamespace, MemberInfo memberInfo = null)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (memberInfo is MethodInfo method)
			{
				return ParseMethod(method);
			}
			if (memberInfo is ConstructorInfo ctor)
			{
				return ParseConstructor(ctor);
			}
			StringBuilder stringBuilder = new StringBuilder();
			if (type.IsByRef)
			{
				AppendOpenColor(stringBuilder, "#" + keywordBlueHex).Append("ref ").Append("</color>");
			}
			Type type2 = type;
			while (type2.HasElementType)
			{
				type2 = type2.GetElementType();
			}
			includeNamespace &= !builtInTypesToShorthand.ContainsKey(type2);
			if (!type.IsGenericParameter && (!type.HasElementType || !type.GetElementType().IsGenericParameter) && includeNamespace && TryGetNamespace(type, out var ns))
			{
				AppendOpenColor(stringBuilder, "#a8a8a8").Append(ns).Append("</color>").Append('.');
			}
			stringBuilder.Append(ProcessType(type));
			if (memberInfo != null)
			{
				stringBuilder.Append('.');
				int index = stringBuilder.Length - 1;
				AppendOpenColor(stringBuilder, GetMemberInfoColor(memberInfo, out var isStatic)).Append(memberInfo.Name).Append("</color>");
				if (isStatic)
				{
					stringBuilder.Insert(index, "<i>");
					stringBuilder.Append("</i>");
				}
			}
			return stringBuilder.ToString();
		}

		private static string ProcessType(Type type)
		{
			string key = type.ToString();
			if (typeToRichType.ContainsKey(key))
			{
				return typeToRichType[key];
			}
			StringBuilder stringBuilder = new StringBuilder();
			if (!type.IsGenericParameter)
			{
				int length = stringBuilder.Length;
				Type declaringType = type.DeclaringType;
				while (declaringType != null)
				{
					stringBuilder.Insert(length, HighlightType(declaringType) + ".");
					declaringType = declaringType.DeclaringType;
				}
				stringBuilder.Append(HighlightType(type));
				if (type.IsGenericType)
				{
					ProcessGenericArguments(type, stringBuilder);
				}
			}
			else
			{
				stringBuilder.Append("<color=").Append("#92c470").Append('>')
					.Append(type.Name)
					.Append("</color>");
			}
			string text = stringBuilder.ToString();
			typeToRichType.Add(key, text);
			return text;
		}

		internal static string GetClassColor(Type type)
		{
			if (type.IsAbstract && type.IsSealed)
			{
				return "#3a8d71";
			}
			if (type.IsEnum || type.IsGenericParameter)
			{
				return "#92c470";
			}
			if (type.IsValueType)
			{
				return "#0fba3a";
			}
			if (type.IsInterface)
			{
				return "#9b9b82";
			}
			return "#2df7b2";
		}

		private static bool TryGetNamespace(Type type, out string ns)
		{
			return !string.IsNullOrEmpty(ns = type.Namespace?.Trim());
		}

		private static StringBuilder AppendOpenColor(StringBuilder sb, string color)
		{
			return sb.Append("<color=").Append(color).Append('>');
		}

		private static string HighlightType(Type type)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (type.IsByRef)
			{
				type = type.GetElementType();
			}
			int num = 0;
			Match match = ArrayTokenRegex.Match(type.Name);
			if (match != null && match.Success)
			{
				num = 1 + match.Value.Count((char c) => c == ',');
				type = type.GetElementType();
			}
			if (builtInTypesToShorthand.TryGetValue(type, out var value))
			{
				AppendOpenColor(stringBuilder, "#" + keywordBlueHex).Append(value).Append("</color>");
			}
			else
			{
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(1, 2, stringBuilder2);
				handler.AppendFormatted("<color=");
				handler.AppendFormatted(GetClassColor(type));
				handler.AppendLiteral(">");
				stringBuilder2.Append(ref handler).Append(type.Name).Append("</color>");
			}
			if (num > 0)
			{
				stringBuilder.Append('[').Append(new string(',', num - 1)).Append(']');
			}
			return stringBuilder.ToString();
		}

		private static void ProcessGenericArguments(Type type, StringBuilder sb)
		{
			List<Type> list = type.GetGenericArguments().ToList();
			for (int i = 0; i < sb.Length; i++)
			{
				if (!list.Any())
				{
					break;
				}
				if (sb[i] != '`')
				{
					continue;
				}
				int num = i;
				i++;
				StringBuilder stringBuilder = new StringBuilder();
				for (; char.IsDigit(sb[i]); i++)
				{
					stringBuilder.Append(sb[i]);
				}
				string text = stringBuilder.ToString();
				int num2 = int.Parse(text);
				sb.Remove(num, text.Length + 1);
				int num3 = 1;
				num++;
				while (num3 < "</color>".Length && sb[num] == "</color>"[num3])
				{
					num3++;
					num++;
				}
				sb.Insert(num, '<');
				num++;
				int length = sb.Length;
				while (num2 > 0 && list.Any())
				{
					num2--;
					Type type2 = list.First();
					list.RemoveAt(0);
					sb.Insert(num, ProcessType(type2));
					if (num2 > 0)
					{
						num += sb.Length - length;
						sb.Insert(num, ", ");
						num += 2;
						length = sb.Length;
					}
				}
				sb.Insert(num + sb.Length - length, '>');
			}
		}

		public static string RemoveHighlighting(string _string)
		{
			if (_string == null)
			{
				throw new ArgumentNullException("_string");
			}
			_string = _string.Replace("<i>", string.Empty);
			_string = _string.Replace("</i>", string.Empty);
			_string = colorTagRegex.Replace(_string, string.Empty);
			_string = _string.Replace("</color>", string.Empty);
			return _string;
		}

		[Obsolete("Use 'ParseMethod(MethodInfo)' instead (rename).")]
		public static string HighlightMethod(MethodInfo method)
		{
			return ParseMethod(method);
		}

		public static string ParseMethod(MethodInfo method)
		{
			string key = GeneralExtensions.FullDescription((MethodBase)method);
			if (highlightedMethods.ContainsKey(key))
			{
				return highlightedMethods[key];
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(Parse(method.DeclaringType, includeNamespace: false));
			stringBuilder.Append('.');
			string value = ((!method.IsStatic) ? "#ff8000" : "#b55b02");
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(16, 2, stringBuilder2);
			handler.AppendLiteral("<color=");
			handler.AppendFormatted(value);
			handler.AppendLiteral(">");
			handler.AppendFormatted(method.Name);
			handler.AppendLiteral("</color>");
			stringBuilder3.Append(ref handler);
			if (method.IsGenericMethod)
			{
				stringBuilder.Append("<");
				Type[] genericArguments = method.GetGenericArguments();
				for (int i = 0; i < genericArguments.Length; i++)
				{
					Type type = genericArguments[i];
					if (type.IsGenericParameter)
					{
						stringBuilder2 = stringBuilder;
						StringBuilder stringBuilder4 = stringBuilder2;
						handler = new StringBuilder.AppendInterpolatedStringHandler(16, 2, stringBuilder2);
						handler.AppendLiteral("<color=");
						handler.AppendFormatted("#92c470");
						handler.AppendLiteral(">");
						handler.AppendFormatted(genericArguments[i].Name);
						handler.AppendLiteral("</color>");
						stringBuilder4.Append(ref handler);
					}
					else
					{
						stringBuilder.Append(Parse(type, includeNamespace: false));
					}
					if (i < genericArguments.Length - 1)
					{
						stringBuilder.Append(", ");
					}
				}
				stringBuilder.Append(">");
			}
			stringBuilder.Append('(');
			ParameterInfo[] parameters = method.GetParameters();
			for (int j = 0; j < parameters.Length; j++)
			{
				ParameterInfo parameterInfo = parameters[j];
				stringBuilder.Append(Parse(parameterInfo.ParameterType, includeNamespace: false));
				if (j < parameters.Length - 1)
				{
					stringBuilder.Append(", ");
				}
			}
			stringBuilder.Append(')');
			string text = stringBuilder.ToString();
			highlightedMethods.Add(key, text);
			return text;
		}

		[Obsolete("Use 'ParseConstructor(ConstructorInfo)' instead (rename).")]
		public static string HighlightConstructor(ConstructorInfo ctor)
		{
			return ParseConstructor(ctor);
		}

		public static string ParseConstructor(ConstructorInfo ctor)
		{
			string key = GeneralExtensions.FullDescription((MethodBase)ctor);
			if (highlightedMethods.ContainsKey(key))
			{
				return highlightedMethods[key];
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(Parse(ctor.DeclaringType, includeNamespace: false));
			string value = stringBuilder.ToString();
			stringBuilder.Append('.');
			stringBuilder.Append(value);
			stringBuilder.Append('(');
			ParameterInfo[] parameters = ctor.GetParameters();
			for (int i = 0; i < parameters.Length; i++)
			{
				ParameterInfo parameterInfo = parameters[i];
				stringBuilder.Append(Parse(parameterInfo.ParameterType, includeNamespace: false));
				if (i < parameters.Length - 1)
				{
					stringBuilder.Append(", ");
				}
			}
			stringBuilder.Append(')');
			string text = stringBuilder.ToString();
			highlightedMethods.Add(key, text);
			return text;
		}

		public static string GetMemberInfoColor(MemberInfo memberInfo, out bool isStatic)
		{
			isStatic = false;
			if (memberInfo is FieldInfo fieldInfo)
			{
				if (fieldInfo.IsStatic)
				{
					isStatic = true;
					return "#8d8dc6";
				}
				return "#c266ff";
			}
			if (memberInfo is MethodInfo methodInfo)
			{
				if (methodInfo.IsStatic)
				{
					isStatic = true;
					return "#b55b02";
				}
				return "#ff8000";
			}
			if (memberInfo is PropertyInfo propertyInfo)
			{
				if (propertyInfo.GetAccessors(nonPublic: true)[0].IsStatic)
				{
					isStatic = true;
					return "#588075";
				}
				return "#55a38e";
			}
			if (memberInfo is ConstructorInfo)
			{
				isStatic = true;
				return "#2df7b2";
			}
			throw new NotImplementedException(memberInfo.GetType().Name + " is not supported");
		}
	}
	public static class ToStringUtility
	{
		internal static Dictionary<string, MethodInfo> toStringMethods = new Dictionary<string, MethodInfo>();

		private const string nullString = "<color=grey>null</color>";

		private const string nullUnknown = "<color=grey>null</color> (?)";

		private const string destroyedString = "<color=red>Destroyed</color>";

		private const string untitledString = "<i><color=grey>untitled</color></i>";

		private const string eventSystemNamespace = "UnityEngine.EventSystem";

		public static string PruneString(string s, int chars = 200, int lines = 5)
		{
			if (string.IsNullOrEmpty(s))
			{
				return s;
			}
			StringBuilder stringBuilder = new StringBuilder(Math.Max(chars, s.Length));
			int num = 0;
			for (int i = 0; i < s.Length; i++)
			{
				if (num >= lines || i >= chars)
				{
					stringBuilder.Append("...");
					break;
				}
				char c = s[i];
				if (c == '\r' || c == '\n')
				{
					num++;
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		public static string ToStringWithType(object value, Type fallbackType, bool includeNamespace = true)
		{
			if (value.IsNullOrDestroyed() && fallbackType == null)
			{
				return "<color=grey>null</color> (?)";
			}
			Type type = value?.GetActualType() ?? fallbackType;
			string text = SignatureHighlighter.Parse(type, includeNamespace);
			StringBuilder stringBuilder = new StringBuilder();
			if (value.IsNullOrDestroyed())
			{
				if (value == null)
				{
					stringBuilder.Append("<color=grey>null</color>");
					AppendRichType(stringBuilder, text);
					return stringBuilder.ToString();
				}
				stringBuilder.Append("<color=red>Destroyed</color>");
				AppendRichType(stringBuilder, text);
				return stringBuilder.ToString();
			}
			Object val = (Object)((value is Object) ? value : null);
			if (val != null)
			{
				if (string.IsNullOrEmpty(val.name))
				{
					stringBuilder.Append("<i><color=grey>untitled</color></i>");
				}
				else
				{
					stringBuilder.Append('"');
					stringBuilder.Append(PruneString(val.name, 50, 1));
					stringBuilder.Append('"');
				}
				AppendRichType(stringBuilder, text);
			}
			else if (type.FullName.StartsWith("UnityEngine.EventSystem"))
			{
				stringBuilder.Append(text);
			}
			else
			{
				string text2 = ToString(value);
				if (type.IsGenericType || text2 == type.FullName || text2 == type.FullName + " " + type.FullName || text2 == "Il2Cpp" + type.FullName || type.FullName == "Il2Cpp" + text2)
				{
					stringBuilder.Append(text);
				}
				else
				{
					stringBuilder.Append(PruneString(text2));
					AppendRichType(stringBuilder, text);
				}
			}
			return stringBuilder.ToString();
		}

		private static void AppendRichType(StringBuilder sb, string richType)
		{
			sb.Append(' ');
			sb.Append('(');
			sb.Append(richType);
			sb.Append(')');
		}

		private static string ToString(object value)
		{
			if (value.IsNullOrDestroyed())
			{
				if (value == null)
				{
					return "<color=grey>null</color>";
				}
				return "<color=red>Destroyed</color>";
			}
			Type actualType = value.GetActualType();
			if (!toStringMethods.ContainsKey(actualType.AssemblyQualifiedName))
			{
				MethodInfo method = actualType.GetMethod("ToString", ArgumentUtility.EmptyTypes);
				toStringMethods.Add(actualType.AssemblyQualifiedName, method);
			}
			value = value.TryCast(actualType);
			string theString;
			try
			{
				theString = (string)toStringMethods[actualType.AssemblyQualifiedName].Invoke(value, ArgumentUtility.EmptyArgs);
			}
			catch (Exception e)
			{
				theString = e.ReflectionExToString();
			}
			theString = ReflectionUtility.ProcessTypeInString(actualType, theString);
			Type val = (Type)((value is Type) ? value : null);
			if (val != null)
			{
				Type unhollowedType = Il2CppReflection.GetUnhollowedType(val);
				if (unhollowedType != null)
				{
					theString = ReflectionUtility.ProcessTypeInString(unhollowedType, theString);
				}
			}
			return theString;
		}
	}
	public static class UnityHelpers
	{
		private static PropertyInfo onEndEdit;

		public static bool OccuredEarlierThanDefault(this float time)
		{
			return Time.realtimeSinceStartup - 0.01f >= time;
		}

		public static bool OccuredEarlierThan(this float time, float secondsAgo)
		{
			return Time.realtimeSinceStartup - secondsAgo >= time;
		}

		public static bool IsNullOrDestroyed(this object obj, bool suppressWarning = true)
		{
			try
			{
				if (obj == null)
				{
					if (!suppressWarning)
					{
						Universe.LogWarning("The target instance is null!");
					}
					return true;
				}
				Object val = (Object)((obj is Object) ? obj : null);
				if (val != null && !Object.op_Implicit(val))
				{
					if (!suppressWarning)
					{
						Universe.LogWarning("The target UnityEngine.Object was destroyed!");
					}
					return true;
				}
				return false;
			}
			catch
			{
				return true;
			}
		}

		public static string GetTransformPath(this Transform transform, bool includeSelf = false)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (includeSelf)
			{
				stringBuilder.Append(((Object)transform).name);
			}
			while (Object.op_Implicit((Object)(object)transform.parent))
			{
				transform = transform.parent;
				stringBuilder.Insert(0, '/');
				stringBuilder.Insert(0, ((Object)transform).name);
			}
			return stringBuilder.ToString();
		}

		public static string ToHex(this Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			byte value = (byte)Mathf.Clamp(Mathf.RoundToInt(color.r * 255f), 0, 255);
			byte value2 = (byte)Mathf.Clamp(Mathf.RoundToInt(color.g * 255f), 0, 255);
			byte value3 = (byte)Mathf.Clamp(Mathf.RoundToInt(color.b * 255f), 0, 255);
			return $"{value:X2}{value2:X2}{value3:X2}";
		}

		public static Color ToColor(this string _string)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			_string = _string.Replace("#", "");
			if (_string.Length != 6)
			{
				return Color.magenta;
			}
			byte b = byte.Parse(_string.Substring(0, 2), NumberStyles.HexNumber);
			byte b2 = byte.Parse(_string.Substring(2, 2), NumberStyles.HexNumber);
			byte b3 = byte.Parse(_string.Substring(4, 2), NumberStyles.HexNumber);
			Color result = default(Color);
			result.r = (float)((decimal)b / 255m);
			result.g = (float)((decimal)b2 / 255m);
			result.b = (float)((decimal)b3 / 255m);
			result.a = 1f;
			return result;
		}

		public static UnityEvent<string> GetOnEndEdit(this InputField _this)
		{
			if (onEndEdit == null)
			{
				onEndEdit = AccessTools.Property(typeof(InputField), "onEndEdit") ?? throw new Exception("Could not get InputField.onEndEdit property!");
			}
			return onEndEdit.GetValue(_this, null).TryCast<UnityEvent<string>>();
		}
	}
}
namespace UniverseLib.UI
{
	public class UIBase
	{
		internal static readonly int TOP_SORTORDER = 30000;

		public string ID { get; }

		public GameObject RootObject { get; }

		public RectTransform RootRect { get; }

		public Canvas Canvas { get; }

		public Action UpdateMethod { get; }

		public PanelManager Panels { get; }

		public bool Enabled
		{
			get
			{
				return Object.op_Implicit((Object)(object)RootObject) && RootObject.activeSelf;
			}
			set
			{
				UniversalUI.SetUIActive(ID, value);
			}
		}

		public UIBase(string id, Action updateMethod)
		{
			//IL_0063: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(id))
			{
				throw new ArgumentException("Cannot register a UI with a null or empty id!");
			}
			if (UniversalUI.registeredUIs.ContainsKey(id))
			{
				throw new ArgumentException("A UI with the id '" + id + "' is already registered!");
			}
			ID = id;
			UpdateMethod = updateMethod;
			RootObject = UIFactory.CreateUIObject(id + "_Root", UniversalUI.CanvasRoot);
			RootObject.SetActive(false);
			RootRect = RootObject.GetComponent<RectTransform>();
			Canvas = RootObject.AddComponent<Canvas>();
			Canvas.renderMode = (RenderMode)1;
			Canvas.referencePixelsPerUnit = 100f;
			Canvas.sortingOrder = TOP_SORTORDER;
			Canvas.overrideSorting = true;
			CanvasScaler val = RootObject.AddComponent<CanvasScaler>();
			val.referenceResolution = new Vector2(1920f, 1080f);
			val.screenMatchMode = (ScreenMatchMode)1;
			RootObject.AddComponent<GraphicRaycaster>();
			RectTransform component = RootObject.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.pivot = new Vector2(0.5f, 0.5f);
			Panels = CreatePanelManager();
			RootObject.SetActive(true);
			UniversalUI.registeredUIs.Add(id, this);
			UniversalUI.uiBases.Add(this);
		}

		protected virtual PanelManager CreatePanelManager()
		{
			return new PanelManager(this);
		}

		public void SetOnTop()
		{
			RootObject.transform.SetAsLastSibling();
			foreach (UIBase uiBasis in UniversalUI.uiBases)
			{
				int num = UniversalUI.CanvasRoot.transform.childCount - ((Transform)uiBasis.RootRect).GetSiblingIndex();
				uiBasis.Canvas.sortingOrder = TOP_SORTORDER - num;
			}
			UniversalUI.uiBases.Sort((UIBase a, UIBase b) => b.RootObject.transform.GetSiblingIndex().CompareTo(a.RootObject.transform.GetSiblingIndex()));
		}

		internal void Update()
		{
			try
			{
				Panels.Update();
				UpdateMethod?.Invoke();
			}
			catch (Exception value)
			{
				Universe.LogWarning($"Exception invoking update method for {ID}: {value}");
			}
		}
	}
	public static class UIFactory
	{
		internal static Vector2 largeElementSize = new Vector2(100f, 30f);

		internal static Vector2 smallElementSize = new Vector2(25f, 25f);

		internal static Color defaultTextColor = Color.white;

		public static GameObject CreateUIObject(string name, GameObject parent, Vector2 sizeDelta = default(Vector2))
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = 5,
				hideFlags = (HideFlags)61
			};
			if (Object.op_Implicit((Object)(object)parent))
			{
				val.transform.SetParent(parent.transform, false);
			}
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.sizeDelta = sizeDelta;
			return val;
		}

		internal static void SetDefaultTextValues(Text text)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)text).color = defaultTextColor;
			text.font = UniversalUI.DefaultFont;
			text.fontSize = 14;
		}

		internal static void SetDefaultSelectableValues(Selectable selectable)
		{
			//IL_002d: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			Navigation navigation = selectable.navigation;
			navigation.mode = (Mode)4;
			selectable.navigation = navigation;
			RuntimeHelper.Instance.Internal_SetColorBlock(selectable, (Color?)new Color(0.2f, 0.2f, 0.2f), (Color?)new Color(0.3f, 0.3f, 0.3f), (Color?)new Color(0.15f, 0.15f, 0.15f), (Color?)null);
		}

		public static LayoutElement SetLayoutElement(GameObject gameObject, int? minWidth = null, int? minHeight = null, int? flexibleWidth = null, int? flexibleHeight = null, int? preferredWidth = null, int? preferredHeight = null, bool? ignoreLayout = null)
		{
			LayoutElement val = gameObject.GetComponent<LayoutElement>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = gameObject.AddComponent<LayoutElement>();
			}
			if (minWidth.HasValue)
			{
				val.minWidth = minWidth.Value;
			}
			if (minHeight.HasValue)
			{
				val.minHeight = minHeight.Value;
			}
			if (flexibleWidth.HasValue)
			{
				val.flexibleWidth = flexibleWidth.Value;
			}
			if (flexibleHeight.HasValue)
			{
				val.flexibleHeight = flexibleHeight.Value;
			}
			if (preferredWidth.HasValue)
			{
				val.preferredWidth = preferredWidth.Value;
			}
			if (preferredHeight.HasValue)
			{
				val.preferredHeight = preferredHeight.Value;
			}
			if (ignoreLayout.HasValue)
			{
				val.ignoreLayout = ignoreLayout.Value;
			}
			return val;
		}

		public static T SetLayoutGroup<T>(GameObject gameObject, bool? forceWidth = null, bool? forceHeight = null, bool? childControlWidth = null, bool? childControlHeight = null, int? spacing = null, int? padTop = null, int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null) where T : HorizontalOrVerticalLayoutGroup
		{
			T val = gameObject.GetComponent<T>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = gameObject.AddComponent<T>();
			}
			return SetLayoutGroup(val, forceWidth, forceHeight, childControlWidth, childControlHeight, spacing, padTop, padBottom, padLeft, padRight, childAlignment);
		}

		public static T SetLayoutGroup<T>(T group, bool? forceWidth = null, bool? forceHeight = null, bool? childControlWidth = null, bool? childControlHeight = null, int? spacing = null, int? padTop = null, int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null) where T : HorizontalOrVerticalLayoutGroup
		{
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			if (forceWidth.HasValue)
			{
				((HorizontalOrVerticalLayoutGroup)group).childForceExpandWidth = forceWidth.Value;
			}
			if (forceHeight.HasValue)
			{
				((HorizontalOrVerticalLayoutGroup)group).childForceExpandHeight = forceHeight.Value;
			}
			if (childControlWidth.HasValue)
			{
				((HorizontalOrVerticalLayoutGroup)(object)group).SetChildControlWidth(childControlWidth.Value);
			}
			if (childControlHeight.HasValue)
			{
				((HorizontalOrVerticalLayoutGroup)(object)group).SetChildControlHeight(childControlHeight.Value);
			}
			if (spacing.HasValue)
			{
				((HorizontalOrVerticalLayoutGroup)group).spacing = spacing.Value;
			}
			if (padTop.HasValue)
			{
				((LayoutGroup)(object)group).padding.top = padTop.Value;
			}
			if (padBottom.HasValue)
			{
				((LayoutGroup)(object)group).padding.bottom = padBottom.Value;
			}
			if (padLeft.HasValue)
			{
				((LayoutGroup)(object)group).padding.left = padLeft.Value;
			}
			if (padRight.HasValue)
			{
				((LayoutGroup)(object)group).padding.right = padRight.Value;
			}
			if (childAlignment.HasValue)
			{
				((LayoutGroup)(object)group).childAlignment = childAlignment.Value;
			}
			return group;
		}

		public static GameObject CreatePanel(string name, GameObject parent, out GameObject contentHolder, Color? bgColor = null)
		{
			//IL_0005: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = CreateUIObject(name, parent);
			UIFactory.SetLayoutGroup<VerticalLayoutGroup>(val, (bool?)true, (bool?)true, (bool?)true, (bool?)true, (int?)0, (int?)1, (int?)1, (int?)1, (int?)1, (TextAnchor?)null);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.anchoredPosition = Vector2.zero;
			component.sizeDelta = Vector2.zero;
			((Graphic)val.AddComponent<Image>()).color = Color.black;
			val.AddComponent<RectMask2D>();
			contentHolder = CreateUIObject("Content", val);
			Image val2 = contentHolder.AddComponent<Image>();
			val2.type = (Type)3;
			((Graphic)val2).color = (Color)((!bgColor.HasValue) ? new Color(0.07f, 0.07f, 0.07f) : bgColor.Value);
			UIFactory.SetLayoutGroup<VerticalLayoutGroup>(contentHolder, (bool?)true, (bool?)true, (bool?)true, (bool?)true, (int?)3, (int?)3, (int?)3, (int?)3, (int?)3, (TextAnchor?)null);
			return val;
		}

		public static GameObject CreateVerticalGroup(GameObject parent, string name, bool forceWidth, bool forceHeight, bool childControlWidth, bool childControlHeight, int spacing = 0, Vector4 padding = default(Vector4), Color bgColor = default(Color), TextAnchor? childAlignment = null)
		{
			//IL_0005: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0