Decompiled source of AzuExtendedPlayerInventory v2.4.2

AzuExtendedPlayerInventory.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Timers;
using APIManager;
using AzuEPI;
using AzuEPI.Core.Input;
using AzuEPI.Core.InventoryHandlers;
using AzuEPI.Core.Slots;
using AzuEPI.Core.Text;
using AzuEPI.Core.Utilities.Extensions;
using AzuEPI.EPI;
using AzuEPI.Game.Compatibility;
using AzuEPI.Game.Compatibility.AdvBackpacks;
using AzuEPI.Game.Loadout;
using AzuEPI.Game.Panels;
using AzuEPI.Game.Panels.Stats;
using AzuEPI.Game.Panels.Vanity;
using AzuEPI.Game.Patches;
using AzuEPI.Game.PlayerPreview;
using AzuEPI.Game.Slots;
using AzuEPI.Game.Slots.QAB;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Preloader;
using BepInEx.Preloader.Patching;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AzuExtendedPlayerInventory")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("AzuExtendedPlayerInventory")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("2.4.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.4.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		public ExtensionMarkerAttribute(string name)
		{
		}
	}
}
public static class ToggleExtensions
{
	[SpecialName]
	public sealed class <G>$4F220943ABCF1C1726BA9F32F1C84BFA
	{
		[SpecialName]
		public static class <M>$B886148B8B9A8A91C986883EF65534E9
		{
		}

		[ExtensionMarker("<M>$B886148B8B9A8A91C986883EF65534E9")]
		public bool isOn()
		{
			throw null;
		}

		[ExtensionMarker("<M>$B886148B8B9A8A91C986883EF65534E9")]
		public bool isOff()
		{
			throw null;
		}
	}

	public static bool isOn(this AzuExtendedPlayerInventoryPlugin.Toggle toggle)
	{
		return toggle == AzuExtendedPlayerInventoryPlugin.Toggle.On;
	}

	public static bool isOff(this AzuExtendedPlayerInventoryPlugin.Toggle toggle)
	{
		return toggle == AzuExtendedPlayerInventoryPlugin.Toggle.Off;
	}
}
namespace AzuExtendedPlayerInventory
{
	[PublicAPI]
	public class API
	{
		public delegate void SlotAddedHandler(string slotName);

		public delegate void SlotRemovedHandler(string slotName);

		private static readonly Dictionary<SlotAddedHandler, AzuEPI.API.SlotAddedHandler> _slotAddedMap = new Dictionary<SlotAddedHandler, AzuEPI.API.SlotAddedHandler>();

		private static readonly Dictionary<SlotRemovedHandler, AzuEPI.API.SlotRemovedHandler> _slotRemovedMap = new Dictionary<SlotRemovedHandler, AzuEPI.API.SlotRemovedHandler>();

		private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudAwakeMap = new Dictionary<Action<Hud>, Action<Hud>>();

		private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudAwakeCompleteMap = new Dictionary<Action<Hud>, Action<Hud>>();

		private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudUpdateMap = new Dictionary<Action<Hud>, Action<Hud>>();

		private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudUpdateCompleteMap = new Dictionary<Action<Hud>, Action<Hud>>();

		public static event SlotAddedHandler? SlotAdded
		{
			add
			{
				if (value == null || _slotAddedMap.ContainsKey(value))
				{
					return;
				}
				AzuEPI.API.SlotAddedHandler value2 = delegate(string s)
				{
					try
					{
						value(s);
					}
					catch
					{
					}
				};
				_slotAddedMap[value] = value2;
				AzuEPI.API.SlotAdded += value2;
			}
			remove
			{
				if (value != null && _slotAddedMap.TryGetValue(value, out AzuEPI.API.SlotAddedHandler value2))
				{
					AzuEPI.API.SlotAdded -= value2;
					_slotAddedMap.Remove(value);
				}
			}
		}

		public static event SlotRemovedHandler? SlotRemoved
		{
			add
			{
				if (value == null || _slotRemovedMap.ContainsKey(value))
				{
					return;
				}
				AzuEPI.API.SlotRemovedHandler value2 = delegate(string s)
				{
					try
					{
						value(s);
					}
					catch
					{
					}
				};
				_slotRemovedMap[value] = value2;
				AzuEPI.API.SlotRemoved += value2;
			}
			remove
			{
				if (value != null && _slotRemovedMap.TryGetValue(value, out AzuEPI.API.SlotRemovedHandler value2))
				{
					AzuEPI.API.SlotRemoved -= value2;
					_slotRemovedMap.Remove(value);
				}
			}
		}

		public static event Action<Hud>? OnHudAwake
		{
			add
			{
				AddHudEvent(value, _hudAwakeMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudAwake += h;
				});
			}
			remove
			{
				RemoveHudEvent(value, _hudAwakeMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudAwake -= h;
				});
			}
		}

		public static event Action<Hud>? OnHudAwakeComplete
		{
			add
			{
				AddHudEvent(value, _hudAwakeCompleteMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudAwakeComplete += h;
				});
			}
			remove
			{
				RemoveHudEvent(value, _hudAwakeCompleteMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudAwakeComplete -= h;
				});
			}
		}

		public static event Action<Hud>? OnHudUpdate
		{
			add
			{
				AddHudEvent(value, _hudUpdateMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudUpdate += h;
				});
			}
			remove
			{
				RemoveHudEvent(value, _hudUpdateMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudUpdate -= h;
				});
			}
		}

		public static event Action<Hud>? OnHudUpdateComplete
		{
			add
			{
				AddHudEvent(value, _hudUpdateCompleteMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudUpdateComplete += h;
				});
			}
			remove
			{
				RemoveHudEvent(value, _hudUpdateCompleteMap, delegate(Action<Hud> h)
				{
					AzuEPI.API.OnHudUpdateComplete -= h;
				});
			}
		}

		private static void AddHudEvent(Action<Hud>? handler, Dictionary<Action<Hud>, Action<Hud>> map, Action<Action<Hud>> subscribe)
		{
			if (handler == null || map.ContainsKey(handler))
			{
				return;
			}
			Action<Hud> action = delegate(Hud h)
			{
				try
				{
					handler(h);
				}
				catch
				{
				}
			};
			map[handler] = action;
			subscribe(action);
		}

		private static void RemoveHudEvent(Action<Hud>? handler, Dictionary<Action<Hud>, Action<Hud>> map, Action<Action<Hud>> unsubscribe)
		{
			if (handler != null && map.TryGetValue(handler, out Action<Hud> value))
			{
				unsubscribe(value);
				map.Remove(handler);
			}
		}

		public static bool IsLoaded()
		{
			return AzuEPI.API.IsLoaded();
		}

		public static bool AddSlot(string slotName, Func<Player, ItemData?> getItem, Func<ItemData, bool> isValid, int index = -1)
		{
			if (Localization.m_instance == null || Localization.m_instance.Localize(slotName).Contains("["))
			{
				Localizer.OnLocalizationComplete += delegate
				{
					AzuEPI.API.AddSlot(slotName, getItem, isValid, index);
				};
			}
			else
			{
				AzuEPI.API.AddSlot(slotName, getItem, isValid, index);
			}
			return true;
		}

		public static bool RemoveSlot(string slotName)
		{
			return AzuEPI.API.RemoveSlot(slotName);
		}

		public static SlotInfo GetSlots()
		{
			AzuEPI.SlotInfo slots = AzuEPI.API.GetSlots();
			return new SlotInfo
			{
				SlotNames = (slots.SlotNames ?? Array.Empty<string>()),
				SlotPositions = (slots.SlotPositions ?? Array.Empty<Vector2>()),
				GetItemFuncs = (slots.GetItemFuncs ?? Array.Empty<Func<Player, ItemData>>()),
				IsValidFuncs = (slots.IsValidFuncs ?? Array.Empty<Func<ItemData, bool>>())
			};
		}

		public static SlotInfo GetQuickSlots()
		{
			AzuEPI.SlotInfo quickSlots = AzuEPI.API.GetQuickSlots();
			return new SlotInfo
			{
				SlotNames = (quickSlots.SlotNames ?? Array.Empty<string>()),
				SlotPositions = (quickSlots.SlotPositions ?? Array.Empty<Vector2>()),
				GetItemFuncs = (quickSlots.GetItemFuncs ?? Array.Empty<Func<Player, ItemData>>()),
				IsValidFuncs = (quickSlots.IsValidFuncs ?? Array.Empty<Func<ItemData, bool>>())
			};
		}

		public static List<ItemData> GetQuickSlotsItems()
		{
			return AzuEPI.API.GetQuickSlotsItems();
		}

		public static int GetAddedRows(int width)
		{
			return AzuEPI.API.GetAddedRows(width);
		}

		public static void HudAwake(Hud h)
		{
			SafeInvoke(delegate
			{
				AzuEPI.API.HudAwake(h);
			});
		}

		public static void HudAwakeComplete(Hud h)
		{
			SafeInvoke(delegate
			{
				AzuEPI.API.HudAwakeComplete(h);
			});
		}

		public static void HudUpdate(Hud h)
		{
			SafeInvoke(delegate
			{
				AzuEPI.API.HudUpdate(h);
			});
		}

		public static void HudUpdateComplete(Hud h)
		{
			SafeInvoke(delegate
			{
				AzuEPI.API.HudUpdateComplete(h);
			});
		}

		private static void SafeInvoke(Action a)
		{
			try
			{
				a();
			}
			catch
			{
			}
		}
	}
	[PublicAPI]
	public class SlotInfo
	{
		public string[] SlotNames { get; set; } = Array.Empty<string>();

		public Vector2[] SlotPositions { get; set; } = Array.Empty<Vector2>();

		public Func<Player, ItemData?>?[] GetItemFuncs { get; set; } = Array.Empty<Func<Player, ItemData>>();

		public Func<ItemData, bool>?[] IsValidFuncs { get; set; } = Array.Empty<Func<ItemData, bool>>();
	}
}
namespace APIManager
{
	public static class Patcher
	{
		private class MonoAssemblyResolver : IAssemblyResolver, IDisposable
		{
			public AssemblyDefinition Resolve(AssemblyNameReference name)
			{
				return AssemblyDefinition.ReadAssembly(AppDomain.CurrentDomain.Load(name.FullName).Location);
			}

			public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
			{
				return Resolve(name);
			}

			public void Dispose()
			{
			}
		}

		private class AssemblyLoadInterceptor
		{
			private static string? assemblyPath;

			private static MethodInfo TargetMethod()
			{
				return AccessTools.DeclaredMethod(typeof(Assembly), "Load", new Type[1] { typeof(byte[]) }, (Type[])null);
			}

			private static bool Prefix(ref byte[] __0, ref Assembly? __result)
			{
				//IL_001d: 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_0032: Expected O, but got Unknown
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Expected O, but got Unknown
				//IL_00de: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e5: Expected O, but got Unknown
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0106: Expected O, but got Unknown
				//IL_011d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Expected O, but got Unknown
				//IL_0133: Unknown result type (might be due to invalid IL or missing references)
				//IL_0162: Unknown result type (might be due to invalid IL or missing references)
				//IL_0169: Expected O, but got Unknown
				//IL_0185: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0201: Unknown result type (might be due to invalid IL or missing references)
				//IL_0207: Expected O, but got Unknown
				//IL_0222: Unknown result type (might be due to invalid IL or missing references)
				//IL_0260: Unknown result type (might be due to invalid IL or missing references)
				assemblyPath = null;
				if (modifyNextLoad)
				{
					modifyNextLoad = false;
					try
					{
						AssemblyDefinition val = AssemblyDefinition.ReadAssembly((Stream)new MemoryStream(__0), new ReaderParameters
						{
							AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver()
						});
						try
						{
							((Dictionary<string, string>)typeof(EnvVars).Assembly.GetType("BepInEx.Preloader.RuntimeFixes.UnityPatches").GetProperty("AssemblyLocations").GetValue(null))[val.FullName] = currentAssemblyPath;
							FixupModuleReferences(val.MainModule);
							TypeDefinition val2 = val.MainModule.GetType("APIManager", "PatchedAttribute");
							if (val2 == null)
							{
								val2 = new TypeDefinition("APIManager", "PatchedAttribute", (TypeAttributes)3)
								{
									BaseType = val.MainModule.ImportReference(typeof(Attribute))
								};
								MethodDefinition val3 = new MethodDefinition(".ctor", (MethodAttributes)6278, val.MainModule.TypeSystem.Void);
								((MethodReference)val3).Parameters.Add(new ParameterDefinition(val.MainModule.TypeSystem.String));
								((MethodReference)val3).Parameters.Add(new ParameterDefinition(val.MainModule.TypeSystem.String));
								val3.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
								val2.Methods.Add(val3);
								val.MainModule.Types.Add(val2);
								CustomAttribute val4 = new CustomAttribute((MethodReference)(object)val3);
								val4.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)""));
								val4.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)val.MainModule.Mvid.ToString()));
								val.CustomAttributes.Add(val4);
							}
							CustomAttribute val5 = new CustomAttribute((MethodReference)(object)((IEnumerable<MethodDefinition>)val2.Methods).First((MethodDefinition m) => ((MemberReference)m).Name == ".ctor"));
							val5.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)modGUID));
							val5.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)patchingAssembly.ManifestModule.ModuleVersionId.ToString()));
							val.CustomAttributes.Add(val5);
							using MemoryStream memoryStream = new MemoryStream();
							val.Write((Stream)memoryStream);
							__0 = memoryStream.ToArray();
							string dumpedAssembliesPath = Patcher.dumpedAssembliesPath;
							char directorySeparatorChar = Path.DirectorySeparatorChar;
							string path = dumpedAssembliesPath + directorySeparatorChar + ((AssemblyNameReference)val.Name).Name + ".dll";
							Directory.CreateDirectory(Patcher.dumpedAssembliesPath);
							File.WriteAllBytes(path, __0);
							assemblyPath = path;
							__result = null;
							return false;
						}
						finally
						{
							((IDisposable)val)?.Dispose();
						}
					}
					catch (BadImageFormatException)
					{
					}
					catch (Exception ex2)
					{
						Debug.LogError((object)("Failed patching ... " + ex2));
					}
				}
				return true;
			}

			private static void Postfix(ref Assembly? __result)
			{
				if (assemblyPath != null && __result == null)
				{
					__result = Assembly.LoadFrom(assemblyPath);
					assemblyPath = null;
				}
			}
		}

		private static PluginInfo? lastPluginInfo;

		private static bool modifyNextLoad = false;

		private static string modGUID = null;

		private static HashSet<string> redirectedNamespaces = null;

		private static readonly Assembly patchingAssembly = Assembly.GetExecutingAssembly();

		private static string currentAssemblyPath = null;

		private static readonly string dumpedAssembliesPath = (string)AccessTools.DeclaredField(typeof(AssemblyPatcher), "DumpedAssembliesPath").GetValue(null);

		private static void GrabPluginInfo(PluginInfo __instance)
		{
			lastPluginInfo = __instance;
		}

		[HarmonyPriority(700)]
		private static void CheckAssemblyLoadFile(string __0)
		{
			PluginInfo? obj = lastPluginInfo;
			if (__0 == ((obj != null) ? obj.Location : null) && lastPluginInfo.Dependencies.Any((BepInDependency d) => d.DependencyGUID == modGUID))
			{
				modifyNextLoad = true;
				currentAssemblyPath = __0;
			}
			lastPluginInfo = null;
		}

		[HarmonyPriority(500)]
		private static bool InterceptAssemblyLoadFile(string __0, ref Assembly? __result)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0059: 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)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (modifyNextLoad && (object)__result == null)
			{
				string text = dumpedAssembliesPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string text2 = text + directorySeparatorChar + Path.GetFileName(__0);
				if (File.Exists(text2))
				{
					AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text2, new ReaderParameters
					{
						AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver()
					});
					try
					{
						bool flag = false;
						Enumerator<CustomAttribute> enumerator = val.CustomAttributes.GetEnumerator();
						try
						{
							while (enumerator.MoveNext())
							{
								CustomAttribute current = enumerator.Current;
								TypeReference declaringType = ((MemberReference)current.Constructor).DeclaringType;
								if (declaringType.Namespace == "APIManager" && ((MemberReference)declaringType).Name == "PatchedAttribute")
								{
									CustomAttributeArgument val2 = current.ConstructorArguments[0];
									if ((string)((CustomAttributeArgument)(ref val2)).Value == modGUID)
									{
										val2 = current.ConstructorArguments[1];
										flag = (string)((CustomAttributeArgument)(ref val2)).Value == patchingAssembly.ManifestModule.ModuleVersionId.ToString();
										break;
									}
								}
							}
						}
						finally
						{
							((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
						}
						if (flag)
						{
							return true;
						}
					}
					finally
					{
						((IDisposable)val)?.Dispose();
					}
				}
				__result = Assembly.Load(File.ReadAllBytes(__0));
				return false;
			}
			return true;
		}

		[HarmonyPriority(499)]
		private static bool ReplaceAssemblyLoadWithCache(ref string __0, ref Assembly? __result)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005a: 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)
			//IL_006f: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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)
			if (modifyNextLoad && (object)__result == null && !__0.StartsWith(dumpedAssembliesPath))
			{
				string text = dumpedAssembliesPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string text2 = text + directorySeparatorChar + Path.GetFileName(__0);
				AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text2, new ReaderParameters
				{
					AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver()
				});
				AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(__0, new ReaderParameters
				{
					AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver()
				});
				Enumerator<CustomAttribute> enumerator = val.CustomAttributes.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						CustomAttribute current = enumerator.Current;
						TypeReference declaringType = ((MemberReference)current.Constructor).DeclaringType;
						if (declaringType.Namespace == "APIManager" && ((MemberReference)declaringType).Name == "PatchedAttribute")
						{
							CustomAttributeArgument val3 = current.ConstructorArguments[0];
							string text3 = (string)((CustomAttributeArgument)(ref val3)).Value;
							bool num;
							if (!(text3 == ""))
							{
								num = !Chainloader.PluginInfos.ContainsKey(text3);
							}
							else
							{
								val3 = current.ConstructorArguments[1];
								num = (string)((CustomAttributeArgument)(ref val3)).Value != val2.MainModule.Mvid.ToString();
							}
							if (num)
							{
								val2.Dispose();
								val.Dispose();
								__result = Assembly.Load(File.ReadAllBytes(__0));
								return false;
							}
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
				((Dictionary<string, string>)typeof(EnvVars).Assembly.GetType("BepInEx.Preloader.RuntimeFixes.UnityPatches").GetProperty("AssemblyLocations").GetValue(null))[val.FullName] = __0;
				val2.Dispose();
				val.Dispose();
				__0 = text2;
			}
			modifyNextLoad = false;
			return true;
		}

		private static void FixupModuleReferences(ModuleDefinition module)
		{
			foreach (TypeDefinition type3 in module.GetTypes())
			{
				if ((object)patchingAssembly.GetType(((MemberReference)type3).FullName) == null)
				{
					Dispatch(type3);
				}
			}
			static bool AreSame(TypeReference a, TypeReference b)
			{
				return (bool)typeof(MetadataResolver).Assembly.GetType("Mono.Cecil.MetadataResolver").GetMethod("AreSame", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[2]
				{
					typeof(TypeReference),
					typeof(TypeReference)
				}, null).Invoke(null, new object[2] { a, b });
			}
			void Dispatch(TypeDefinition type)
			{
				if (type.BaseType != null && (object)type.BaseType.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(type.BaseType).Namespace))
				{
					Type type2 = patchingAssembly.GetType(((MemberReference)type.BaseType).FullName);
					if ((object)type2 != null)
					{
						type.BaseType = module.ImportReference(type2);
					}
				}
				DispatchGenericParameters((IGenericParameterProvider)(object)type, ((MemberReference)type).FullName);
				DispatchInterfaces(type, ((MemberReference)type).FullName);
				DispatchAttributes((ICustomAttributeProvider)(object)type, ((MemberReference)type).FullName);
				DispatchFields(type, ((MemberReference)type).FullName);
				DispatchProperties(type, ((MemberReference)type).FullName);
				DispatchEvents(type, ((MemberReference)type).FullName);
				DispatchMethods(type);
			}
			void DispatchAttributes(ICustomAttributeProvider provider, string referencingEntityName)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: 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_0076: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0112: 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_012b: Unknown result type (might be due to invalid IL or missing references)
				//IL_013c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0141: Unknown result type (might be due to invalid IL or missing references)
				//IL_014a: Unknown result type (might be due to invalid IL or missing references)
				//IL_014f: Unknown result type (might be due to invalid IL or missing references)
				if (!provider.HasCustomAttributes)
				{
					return;
				}
				Enumerator<CustomAttribute> enumerator2 = provider.CustomAttributes.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						CustomAttribute current2 = enumerator2.Current;
						MethodReference val = importMethodReference(current2.Constructor);
						if (val != null)
						{
							current2.Constructor = val;
						}
						else
						{
							VisitMethod(current2.Constructor, referencingEntityName);
						}
						for (int i = 0; i < current2.ConstructorArguments.Count; i++)
						{
							CustomAttributeArgument val2 = current2.ConstructorArguments[i];
							current2.ConstructorArguments[i] = new CustomAttributeArgument(VisitType(((CustomAttributeArgument)(ref val2)).Type, referencingEntityName), ((CustomAttributeArgument)(ref val2)).Value);
						}
						CustomAttributeArgument argument;
						for (int j = 0; j < current2.Properties.Count; j++)
						{
							CustomAttributeNamedArgument val3 = current2.Properties[j];
							Collection<CustomAttributeNamedArgument> properties = current2.Properties;
							int num = j;
							string name = ((CustomAttributeNamedArgument)(ref val3)).Name;
							argument = ((CustomAttributeNamedArgument)(ref val3)).Argument;
							TypeReference? obj = VisitType(((CustomAttributeArgument)(ref argument)).Type, referencingEntityName);
							argument = ((CustomAttributeNamedArgument)(ref val3)).Argument;
							properties[num] = new CustomAttributeNamedArgument(name, new CustomAttributeArgument(obj, ((CustomAttributeArgument)(ref argument)).Value));
						}
						for (int k = 0; k < current2.Fields.Count; k++)
						{
							CustomAttributeNamedArgument val4 = current2.Fields[k];
							Collection<CustomAttributeNamedArgument> fields = current2.Fields;
							int num2 = k;
							string name2 = ((CustomAttributeNamedArgument)(ref val4)).Name;
							argument = ((CustomAttributeNamedArgument)(ref val4)).Argument;
							TypeReference? obj2 = VisitType(((CustomAttributeArgument)(ref argument)).Type, referencingEntityName);
							argument = ((CustomAttributeNamedArgument)(ref val4)).Argument;
							fields[num2] = new CustomAttributeNamedArgument(name2, new CustomAttributeArgument(obj2, ((CustomAttributeArgument)(ref argument)).Value));
						}
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			void DispatchEvents(TypeDefinition type, string referencingEntityName)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<EventDefinition> enumerator2 = type.Events.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						EventDefinition current2 = enumerator2.Current;
						((EventReference)current2).EventType = VisitType(((EventReference)current2).EventType, referencingEntityName);
						DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName);
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			void DispatchFields(TypeDefinition type, string referencingEntityName)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<FieldDefinition> enumerator2 = type.Fields.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						FieldDefinition current2 = enumerator2.Current;
						((FieldReference)current2).FieldType = VisitType(((FieldReference)current2).FieldType, referencingEntityName);
						DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName);
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			void DispatchGenericArguments(IGenericInstance genericInstance, string referencingEntityName)
			{
				for (int i = 0; i < genericInstance.GenericArguments.Count; i++)
				{
					genericInstance.GenericArguments[i] = VisitType(genericInstance.GenericArguments[i], referencingEntityName);
				}
			}
			void DispatchGenericParameters(IGenericParameterProvider provider, string referencingEntityName)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<GenericParameter> enumerator2 = provider.GenericParameters.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						GenericParameter current2 = enumerator2.Current;
						DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName);
						for (int i = 0; i < current2.Constraints.Count; i++)
						{
							current2.Constraints[i] = VisitType(current2.Constraints[i], referencingEntityName);
						}
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			void DispatchInterfaces(TypeDefinition type, string referencingEntityName)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<InterfaceImplementation> enumerator2 = type.Interfaces.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						InterfaceImplementation current2 = enumerator2.Current;
						current2.InterfaceType = VisitType(current2.InterfaceType, referencingEntityName);
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			void DispatchMethod(MethodDefinition method)
			{
				//IL_003d: 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)
				((MethodReference)method).ReturnType = VisitType(((MethodReference)method).ReturnType, ((MemberReference)method).FullName);
				DispatchAttributes((ICustomAttributeProvider)(object)((MethodReference)method).MethodReturnType, ((MemberReference)method).FullName);
				DispatchGenericParameters((IGenericParameterProvider)(object)method, ((MemberReference)method).FullName);
				Enumerator<ParameterDefinition> enumerator2 = ((MethodReference)method).Parameters.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						ParameterDefinition current2 = enumerator2.Current;
						((ParameterReference)current2).ParameterType = VisitType(((ParameterReference)current2).ParameterType, ((MemberReference)method).FullName);
						DispatchAttributes((ICustomAttributeProvider)(object)current2, ((MemberReference)method).FullName);
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
				for (int i = 0; i < method.Overrides.Count; i++)
				{
					MethodReference val = importMethodReference(method.Overrides[i]);
					if (val != null)
					{
						method.Overrides[i] = val;
					}
					else
					{
						VisitMethod(method.Overrides[i], ((MemberReference)method).FullName);
					}
				}
				if (method.HasBody)
				{
					DispatchMethodBody(method.Body);
				}
			}
			void DispatchMethodBody(MethodBody body)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<VariableDefinition> enumerator2 = body.Variables.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						VariableDefinition current2 = enumerator2.Current;
						((VariableReference)current2).VariableType = VisitType(((VariableReference)current2).VariableType, ((MemberReference)body.Method).FullName);
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
				Enumerator<Instruction> enumerator3 = body.Instructions.GetEnumerator();
				try
				{
					while (enumerator3.MoveNext())
					{
						Instruction current3 = enumerator3.Current;
						object operand = current3.Operand;
						FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null);
						if (val == null)
						{
							MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
							if (val2 == null)
							{
								TypeReference val3 = (TypeReference)((operand is TypeReference) ? operand : null);
								if (val3 != null)
								{
									current3.Operand = VisitType(val3, ((MemberReference)body.Method).FullName);
								}
							}
							else
							{
								MethodReference val4 = importMethodReference(val2);
								if (val4 != null)
								{
									current3.Operand = val4;
								}
								else
								{
									VisitMethod(val2, ((MemberReference)body.Method).FullName);
								}
							}
						}
						else
						{
							FieldReference val5 = importFieldReference(val);
							if (val5 != null)
							{
								current3.Operand = val5;
							}
							else
							{
								VisitField(val, ((MemberReference)body.Method).FullName);
							}
						}
					}
				}
				finally
				{
					((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
				}
			}
			void DispatchMethods(TypeDefinition type)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<MethodDefinition> enumerator2 = type.Methods.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						MethodDefinition current2 = enumerator2.Current;
						DispatchMethod(current2);
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			void DispatchProperties(TypeDefinition type, string referencingEntityName)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<PropertyDefinition> enumerator2 = type.Properties.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						PropertyDefinition current2 = enumerator2.Current;
						((PropertyReference)current2).PropertyType = VisitType(((PropertyReference)current2).PropertyType, referencingEntityName);
						DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName);
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			TypeReference FixupType(TypeReference type)
			{
				if ((object)type.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(type).Namespace))
				{
					if (type.IsNested)
					{
						return FixupType(((MemberReference)type).DeclaringType);
					}
					Type type2 = patchingAssembly.GetType(((MemberReference)type).FullName);
					if ((object)type2 != null)
					{
						return module.ImportReference(type2);
					}
				}
				return type;
			}
			void VisitField(FieldReference? field, string referencingEntityName)
			{
				if (field != null)
				{
					field.FieldType = VisitType(field.FieldType, referencingEntityName);
					if (!(field is FieldDefinition))
					{
						((MemberReference)field).DeclaringType = VisitType(((MemberReference)field).DeclaringType, referencingEntityName);
					}
				}
			}
			void VisitMethod(MethodReference? method, string referencingEntityName)
			{
				//IL_002f: 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)
				if (method != null)
				{
					GenericInstanceMethod val = (GenericInstanceMethod)(object)((method is GenericInstanceMethod) ? method : null);
					if (val != null)
					{
						DispatchGenericArguments((IGenericInstance)(object)val, referencingEntityName);
					}
					method.ReturnType = VisitType(method.ReturnType, referencingEntityName);
					Enumerator<ParameterDefinition> enumerator2 = method.Parameters.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							ParameterDefinition current2 = enumerator2.Current;
							((ParameterReference)current2).ParameterType = VisitType(((ParameterReference)current2).ParameterType, referencingEntityName);
						}
					}
					finally
					{
						((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
					}
					if (!(method is MethodSpecification))
					{
						((MemberReference)method).DeclaringType = VisitType(((MemberReference)method).DeclaringType, referencingEntityName);
					}
				}
			}
			TypeReference? VisitType(TypeReference? type, string referencingEntityName)
			{
				if (type == null)
				{
					return type;
				}
				if (type.GetElementType().IsGenericParameter)
				{
					return type;
				}
				GenericInstanceType val = (GenericInstanceType)(object)((type is GenericInstanceType) ? type : null);
				if (val != null)
				{
					DispatchGenericArguments((IGenericInstance)(object)val, referencingEntityName);
				}
				return FixupType(type);
			}
			static TypeReference baseDeclaringType(TypeReference type)
			{
				while (((MemberReference)type).DeclaringType != null)
				{
					type = ((MemberReference)type).DeclaringType;
				}
				return type;
			}
			FieldReference? importFieldReference(FieldReference field)
			{
				if ((object)((MemberReference)field).DeclaringType.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(((MemberReference)field).DeclaringType).Namespace))
				{
					FieldInfo fieldInfo = patchingAssembly.GetType(((MemberReference)((MemberReference)field).DeclaringType).FullName)?.GetField(((MemberReference)field).Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if ((object)fieldInfo != null)
					{
						return module.ImportReference(fieldInfo);
					}
				}
				return null;
			}
			MethodReference? importMethodReference(MethodReference method)
			{
				//IL_0176: Unknown result type (might be due to invalid IL or missing references)
				//IL_017d: Expected O, but got Unknown
				if ((object)((MemberReference)method).DeclaringType.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(((MemberReference)method).DeclaringType).Namespace))
				{
					if (((MemberReference)method).Name == ".cctor")
					{
						ConstructorInfo[] array = patchingAssembly.GetType(((MemberReference)((MemberReference)method).DeclaringType).FullName)?.GetConstructors(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						if (array != null && array.Length == 1)
						{
							return module.ImportReference((MethodBase)array[0]);
						}
					}
					else if (((MemberReference)method).Name == ".ctor")
					{
						ConstructorInfo constructorInfo = patchingAssembly.GetType(((MemberReference)((MemberReference)method).DeclaringType).FullName)?.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(CompareMethods);
						if ((object)constructorInfo != null)
						{
							return module.ImportReference((MethodBase)constructorInfo);
						}
					}
					else
					{
						MethodInfo methodInfo = patchingAssembly.GetType(((MemberReference)((MemberReference)method).DeclaringType).FullName)?.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m)
						{
							if (m.Name != ((MemberReference)method).Name)
							{
								return false;
							}
							return (((MemberReference)method.ReturnType).ContainsGenericParameter == m.ReturnType.IsGenericParameter || AreSame(method.ReturnType, module.ImportReference(m.ReturnType))) && CompareMethods(m);
						});
						if ((object)methodInfo != null)
						{
							MethodReference val = module.ImportReference((MethodBase)methodInfo);
							MethodReference obj = method;
							GenericInstanceMethod val2 = (GenericInstanceMethod)(object)((obj is GenericInstanceMethod) ? obj : null);
							if (val2 != null)
							{
								GenericInstanceMethod val3 = new GenericInstanceMethod(val);
								for (int num = 0; num < val2.GenericArguments.Count; num++)
								{
									val2.GenericArguments[num] = VisitType(val2.GenericArguments[num], ((MemberReference)method).FullName);
									val3.GenericArguments.Add(val2.GenericArguments[num]);
								}
								val = (MethodReference)(object)val3;
							}
							return val;
						}
					}
				}
				return null;
				bool CompareMethods(MethodBase m)
				{
					ParameterInfo[] parameters = m.GetParameters();
					if (method.IsGenericInstance != m.IsGenericMethodDefinition || parameters.Length != 0 != method.HasParameters)
					{
						return false;
					}
					if (method.HasParameters)
					{
						if (method.Parameters.Count != parameters.Length)
						{
							return false;
						}
						for (int i = 0; i < method.Parameters.Count; i++)
						{
							if (parameters[i].ParameterType.IsGenericParameter ? (!((ParameterReference)method.Parameters[i]).ParameterType.IsGenericParameter) : (!AreSame(((ParameterReference)method.Parameters[i]).ParameterType, module.ImportReference(parameters[i].ParameterType))))
							{
								return false;
							}
						}
					}
					return true;
				}
			}
		}

		public static bool PreventHarmonyInteropFixLoad(Assembly? __0)
		{
			return __0 == null;
		}

		public static void Patch(IEnumerable<string>? extraNamespaces = null)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Expected O, but got Unknown
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Expected O, but got Unknown
			Harmony val = new Harmony("org.bepinex.plugins.APIManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(PluginInfo), "ToString", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "GrabPluginInfo", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Assembly), "LoadFile", new Type[1] { typeof(string) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "InterceptAssemblyLoadFile", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Assembly), "LoadFile", new Type[1] { typeof(string) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "CheckAssemblyLoadFile", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Assembly), "LoadFile", new Type[1] { typeof(string) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "ReplaceAssemblyLoadWithCache", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			new PatchClassProcessor(val, typeof(AssemblyLoadInterceptor), true).Patch();
			Type type = typeof(AssemblyPatcher).Assembly.GetType("BepInEx.Preloader.RuntimeFixes.HarmonyInteropFix");
			if ((object)type != null)
			{
				val.Patch((MethodBase)AccessTools.DeclaredMethod(type, "OnAssemblyLoad", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "PreventHarmonyInteropFixLoad", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			IEnumerable<TypeInfo> source;
			try
			{
				source = patchingAssembly.DefinedTypes.ToList();
			}
			catch (ReflectionTypeLoadException ex)
			{
				source = from t in ex.Types
					where t != null
					select t.GetTypeInfo();
			}
			BaseUnityPlugin val2 = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
			HashSet<string> hashSet = new HashSet<string>();
			foreach (string item in extraNamespaces ?? Array.Empty<string>())
			{
				hashSet.Add(item);
			}
			hashSet.Add(((object)val2).GetType().Namespace);
			redirectedNamespaces = hashSet;
			modGUID = val2.Info.Metadata.GUID;
		}
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		public static event Action? OnLocalizationComplete;

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
				UpdatePlaceholderText(Localization.instance, key);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			_ = plugin;
		}

		public static void LoadLocalizationLater(Localization __instance)
		{
			LoadLocalization(Localization.instance, __instance.GetSelectedLanguage());
		}

		public static void SafeCallLocalizeComplete()
		{
			Localizer.OnLocalizationComplete?.Invoke();
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1];
				if (dictionary.ContainsKey(text))
				{
					Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
				}
				else
				{
					dictionary[text] = item;
				}
			}
			byte[] array = LoadTranslationFromAssembly("English");
			if (array == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.TryGetValue(language, out var value))
				{
					text2 = File.ReadAllText(value);
				}
				else
				{
					byte[] array2 = LoadTranslationFromAssembly(language);
					if (array2 != null)
					{
						text2 = Encoding.UTF8.GetString(array2);
					}
				}
			}
			if (text2 == null && dictionary.TryGetValue("English", out var value2))
			{
				text2 = File.ReadAllText(value2);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_008e: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string>(2) { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace ItemDataManager
{
	[PublicAPI]
	public abstract class ItemData
	{
		internal static WeakReference<ItemInfo> constructingInfo = null;

		internal WeakReference<ItemInfo>? info;

		private static readonly FieldInfo parameterInfoClassImpl = AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl");

		private static Dictionary<Type, Dictionary<string, FieldInfo>> serializedFields = new Dictionary<Type, Dictionary<string, FieldInfo>>();

		public string CustomDataKey { get; internal set; }

		protected virtual bool AllowStackingIdenticalValues { get; set; }

		public string Value
		{
			get
			{
				if (!Item.m_customData.TryGetValue(CustomDataKey, out var value))
				{
					return "";
				}
				return value;
			}
			set
			{
				Item.m_customData[CustomDataKey] = value;
			}
		}

		public string Key { get; internal set; }

		public bool IsCloned => Info.isCloned.Contains(CustomDataKey);

		public bool IsAlive
		{
			get
			{
				ItemInfo target;
				return (info ?? constructingInfo).TryGetTarget(out target);
			}
		}

		public ItemData Item => Info.ItemData;

		public ItemInfo Info
		{
			get
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				if (!(info ?? constructingInfo).TryGetTarget(out ItemInfo target))
				{
					return new ItemInfo(new ItemData());
				}
				return target;
			}
		}

		public virtual void FirstLoad()
		{
		}

		public virtual void Load()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			Dictionary<string, FieldInfo> dictionary = fetchSerializedFields();
			if (dictionary == null || dictionary.Count <= 0 || Value == "")
			{
				return;
			}
			List<object> list = new List<object>();
			string[] array = Value.Split(new char[1] { '|' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length == 2 && dictionary.TryGetValue(array2[0], out var value))
				{
					ZPackage val = new ZPackage(array2[1]);
					ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
					parameterInfoClassImpl.SetValue(parameterInfo, value.FieldType);
					list.Clear();
					ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, val, ref list);
					if (list.Count > 0)
					{
						value.SetValue(this, list[0]);
					}
				}
			}
		}

		public virtual void Save()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			Dictionary<string, FieldInfo> dictionary = fetchSerializedFields();
			if (dictionary == null || dictionary.Count <= 0)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (FieldInfo value in dictionary.Values)
			{
				ZPackage val = new ZPackage();
				ZRpc.Serialize(new object[1] { value.GetValue(this) }, ref val);
				stringBuilder.Append(value.Name);
				stringBuilder.Append(':');
				stringBuilder.Append(val.GetBase64());
				stringBuilder.Append('|');
			}
			int length = stringBuilder.Length - 1;
			stringBuilder.Length = length;
			Value = stringBuilder.ToString();
		}

		public virtual void Unload()
		{
		}

		public virtual void Upgraded()
		{
		}

		public virtual string? TryStack(ItemData? data)
		{
			if (!AllowStackingIdenticalValues || !(data?.Value == Value))
			{
				return null;
			}
			return Value;
		}

		private Dictionary<string, FieldInfo> fetchSerializedFields()
		{
			Type type = GetType();
			if (serializedFields.TryGetValue(type, out Dictionary<string, FieldInfo> value))
			{
				return value;
			}
			return serializedFields[type] = (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where f.GetCustomAttributes(typeof(SerializeField), inherit: true).Length != 0
				select f).ToDictionary((FieldInfo f) => f.Name, (FieldInfo f) => f);
		}
	}
	public sealed class StringItemData : ItemData
	{
	}
	[PublicAPI]
	public class ItemInfo : IEnumerable<ItemData>, IEnumerable
	{
		public static HashSet<Type> ForceLoadTypes;

		internal static string? _modGuid;

		private static Dictionary<Type, HashSet<Type>> typeInheritorsCache;

		private static HashSet<string> knownTypes;

		private Dictionary<string, ItemData> data = new Dictionary<string, ItemData>();

		private WeakReference<ItemInfo>? selfReference;

		internal HashSet<string> isCloned = new HashSet<string>();

		private static ItemData? awakeningItem;

		private static Assembly primaryAssembly;

		private static Dictionary<Assembly, string> assemblyNameCache;

		private static Dictionary<Type, string> classKeyCache;

		private HashSet<string> fetchedClassKeys = new HashSet<string>();

		private static MethodInfo removeMethod;

		private static ItemData? checkingForStackableItemData;

		private static Dictionary<string, string>? newValuesOnStackable;

		private static ItemData? currentlyUpgradingItem;

		internal static string modGuid => _modGuid ?? (_modGuid = ((Func<string>)delegate
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable<TypeInfo> source;
			try
			{
				source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
			}
			catch (ReflectionTypeLoadException ex)
			{
				source = from t in ex.Types
					where t != null
					select t.GetTypeInfo();
			}
			return ((BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)))).Info.Metadata.GUID;
		})());

		public string Mod => modGuid;

		public ItemData ItemData { get; private set; }

		public string? this[string key]
		{
			get
			{
				return Get<StringItemData>(key)?.Value;
			}
			set
			{
				GetOrCreate<StringItemData>(key).Value = value ?? "";
			}
		}

		internal static void addTypeToInheritorsCache(Type type, string typeKey)
		{
			if (!knownTypes.Contains(typeKey))
			{
				knownTypes.Add(typeKey);
				Type type2 = type;
				while ((object)type2 != null)
				{
					AddInterfaces(type2);
					type2 = type2.BaseType;
				}
			}
			void AddInterfaces(Type baseType)
			{
				if (!typeInheritorsCache.TryGetValue(baseType, out HashSet<Type> value))
				{
					HashSet<Type> hashSet = (typeInheritorsCache[baseType] = new HashSet<Type>());
					value = hashSet;
				}
				value.Add(type);
				Type[] interfaces = baseType.GetInterfaces();
				for (int i = 0; i < interfaces.Length; i++)
				{
					AddInterfaces(interfaces[i]);
				}
			}
		}

		private static string cachedAssemblyName(Assembly assembly)
		{
			if (assemblyNameCache.TryGetValue(assembly, out string value))
			{
				return value;
			}
			return assemblyNameCache[assembly] = assembly.GetName().Name;
		}

		internal static string classKey(Type type, string key)
		{
			if (!classKeyCache.TryGetValue(type, out string value))
			{
				value = type.FullName + ((type.Assembly != primaryAssembly) ? ("," + cachedAssemblyName(type.Assembly)) : "");
				addTypeToInheritorsCache(type, value);
			}
			if (key == "")
			{
				return value;
			}
			return value + "#" + key;
		}

		internal static string dataKey(string key)
		{
			return modGuid + "#" + key;
		}

		internal ItemInfo(ItemData itemData)
		{
			ItemData = itemData;
			string text = dataKey("");
			foreach (string item in ItemData.m_customData.Keys.ToList())
			{
				if (!item.StartsWith(text))
				{
					continue;
				}
				string[] array = item.Substring(text.Length).Split(new char[1] { '#' }, 2);
				if (!knownTypes.Contains(array[0]))
				{
					Type type = Type.GetType(array[0]);
					if ((object)type != null && typeof(ItemData).IsAssignableFrom(type))
					{
						addTypeToInheritorsCache(type, array[0]);
					}
				}
			}
		}

		public T GetOrCreate<T>(string key = "") where T : ItemData, new()
		{
			return Add<T>(key) ?? Get<T>(key);
		}

		public T? Add<T>(string key = "") where T : ItemData, new()
		{
			string text = classKey(typeof(T), key);
			if (fetchedClassKeys.Contains(text) && data.ContainsKey(text))
			{
				return null;
			}
			string text2 = dataKey(text);
			if (ItemData.m_customData.ContainsKey(text2) || (awakeningItem != ItemData && data.ContainsKey(text)))
			{
				return null;
			}
			ItemData.m_customData[text2] = "";
			ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<ItemInfo>(this));
			T val = new T
			{
				info = selfReference,
				Key = key,
				CustomDataKey = text2
			};
			data[text] = val;
			val.Value = "";
			val.FirstLoad();
			return val;
		}

		public T? Get<T>(string key = "") where T : class
		{
			if (!typeInheritorsCache.TryGetValue(typeof(T), out HashSet<Type> value))
			{
				if (!typeof(ItemData).IsAssignableFrom(typeof(T)) || typeof(T) == typeof(ItemData))
				{
					throw new Exception("Trying to get value from ItemDataManager for class not inheriting from ItemData");
				}
				return null;
			}
			foreach (Type item in value)
			{
				string text = classKey(item, key);
				if (data.TryGetValue(text, out ItemData value2))
				{
					return (T)(object)value2;
				}
				if (!fetchedClassKeys.Contains(text) && awakeningItem != ItemData)
				{
					string text2 = dataKey(text);
					fetchedClassKeys.Add(text);
					if (ItemData.m_customData.ContainsKey(text2))
					{
						return (T)(object)constructDataObj(text2, text);
					}
				}
			}
			return null;
		}

		public Dictionary<string, T> GetAll<T>() where T : ItemData
		{
			LoadAll();
			return data.Values.Where((ItemData o) => o is T).ToDictionary((ItemData o) => o.Key, (ItemData o) => (T)o);
		}

		public bool Remove(string key = "")
		{
			return Remove<StringItemData>(key);
		}

		public bool Remove<T>(string key = "") where T : ItemData
		{
			string key2 = classKey(typeof(T), key);
			string key3 = dataKey(key2);
			if (ItemData.m_customData.Remove(key3))
			{
				if (data.TryGetValue(key2, out ItemData value))
				{
					value.Unload();
					data.Remove(key2);
				}
				return true;
			}
			return false;
		}

		public bool Remove<T>(T itemData) where T : ItemData
		{
			if (typeof(T) == itemData.GetType())
			{
				return Remove<T>(itemData.Key);
			}
			return (bool)removeMethod.MakeGenericMethod(itemData.GetType()).Invoke(this, new object[1] { itemData.Key });
		}

		private ItemData? constructDataObj(string fullkey, string key)
		{
			string[] array = key.Split(new char[1] { '#' }, 2);
			Type type = Type.GetType(array[0]);
			if ((object)type == null || !typeof(ItemData).IsAssignableFrom(type))
			{
				return null;
			}
			ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<ItemInfo>(this));
			ItemData itemData = (ItemData)Activator.CreateInstance(type);
			data[key] = itemData;
			itemData.info = selfReference;
			itemData.Key = ((array.Length > 1) ? array[1] : "");
			itemData.CustomDataKey = fullkey;
			itemData.Load();
			return itemData;
		}

		public void Save()
		{
			foreach (ItemData value in data.Values)
			{
				value.Save();
			}
		}

		public void LoadAll()
		{
			if (awakeningItem == ItemData)
			{
				return;
			}
			string text = dataKey("");
			foreach (string item in ItemData.m_customData.Keys.ToList())
			{
				if (item.StartsWith(text))
				{
					string key = item.Substring(text.Length);
					if (!data.ContainsKey(key))
					{
						constructDataObj(item, key);
					}
				}
			}
		}

		public IEnumerator<ItemData> GetEnumerator()
		{
			LoadAll();
			return data.Values.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		private static void SavePrefix(ItemData __instance)
		{
			SaveItem(__instance);
		}

		private static void SaveInventoryPrefix(Inventory __instance)
		{
			foreach (ItemData item in __instance.m_inventory)
			{
				SaveItem(item);
			}
		}

		private static void SaveItem(ItemData item)
		{
			if (ItemExtensions.itemInfo.TryGetValue(item, out ItemInfo value))
			{
				value.Save();
			}
		}

		public Dictionary<string, string>? IsStackableWithOtherInfo(ItemInfo? info)
		{
			LoadAll();
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			if (info != null)
			{
				info.LoadAll();
				foreach (string item in new HashSet<string>(info.data.Keys.Intersect(data.Keys)))
				{
					string text = data[item].TryStack(info.data[item]);
					if (text == null)
					{
						return null;
					}
					dictionary[item] = text;
				}
				foreach (KeyValuePair<string, ItemData> datum in info.data)
				{
					if (!dictionary.ContainsKey(datum.Key))
					{
						string text2 = info.data[datum.Key].TryStack(null);
						if (text2 == null)
						{
							return null;
						}
						dictionary[datum.Key] = text2;
					}
				}
			}
			foreach (KeyValuePair<string, ItemData> datum2 in data)
			{
				if (!dictionary.ContainsKey(datum2.Key))
				{
					string text3 = data[datum2.Key].TryStack(null);
					if (text3 == null)
					{
						return null;
					}
					dictionary[datum2.Key] = text3;
				}
			}
			return dictionary.ToDictionary((KeyValuePair<string, string> kv) => dataKey(kv.Key), (KeyValuePair<string, string> kv) => kv.Value);
		}

		private static void RegisterForceLoadedTypesAddItem(ItemData? __result)
		{
			awakeningItem = null;
			if (__result != null)
			{
				RegisterForceLoadedTypes(__result);
			}
		}

		private static void RegisterForceLoadedTypes(ItemData itemData)
		{
			foreach (Type forceLoadType in ForceLoadTypes)
			{
				string key = classKey(forceLoadType, "");
				string text = dataKey(key);
				if (itemData.m_customData.ContainsKey(text))
				{
					ItemInfo itemInfo = itemData.Data();
					if (!itemInfo.data.ContainsKey(key))
					{
						itemInfo.constructDataObj(text, key);
					}
				}
			}
		}

		private static void ItemDropAwake(ItemDrop __instance)
		{
			GameObject dropPrefab = __instance.m_itemData.m_dropPrefab;
			if (dropPrefab == null || !ItemExtensions.itemInfo.TryGetValue(dropPrefab.GetComponent<ItemDrop>().m_itemData, out ItemInfo value))
			{
				return;
			}
			ItemInfo itemInfo = __instance.m_itemData.Data();
			HashSet<string> hashSet = new HashSet<string>();
			foreach (string item in value.data.Values.Select((ItemData i) => i.CustomDataKey))
			{
				hashSet.Add(item);
			}
			itemInfo.isCloned = hashSet;
		}

		private static void ItemDropAwakeDelayed(ItemDrop __instance)
		{
			if (!ZNetView.m_forceDisableInit)
			{
				RegisterForceLoadedTypes(__instance.m_itemData);
			}
		}

		private static void ItemDataClonePrefix(ItemData __instance, ItemData __result)
		{
			SaveItem(__instance);
		}

		private static void ItemDataClonePostfix(ItemData __instance, ItemData __result)
		{
			if (!ItemExtensions.itemInfo.TryGetValue(__instance, out ItemInfo value))
			{
				return;
			}
			ItemInfo itemInfo = __result.Data();
			HashSet<string> hashSet = new HashSet<string>();
			foreach (string item in value.data.Values.Select((ItemData i) => i.CustomDataKey))
			{
				hashSet.Add(item);
			}
			itemInfo.isCloned = hashSet;
		}

		private static void ItemDataClonePostfixDelayed(ItemData __result)
		{
			RegisterForceLoadedTypes(__result);
		}

		private static void RegisterForceLoadedTypesOnPlayerLoaded(Player __instance)
		{
			foreach (Food food in __instance.m_foods)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(food.m_name);
				if (itemPrefab.GetComponent<ItemDrop>().m_itemData == food.m_item)
				{
					food.m_item = food.m_item.Clone();
					food.m_item.m_dropPrefab = itemPrefab;
				}
				RegisterForceLoadedTypes(food.m_item);
			}
		}

		private static void SaveCheckingForStackableItemData(ItemData item)
		{
			if (item == awakeningItem)
			{
				awakeningItem = null;
			}
			checkingForStackableItemData = item;
		}

		private static void ResetCheckingForStackableItemData()
		{
			checkingForStackableItemData = null;
		}

		private static IEnumerable<CodeInstruction> CheckStackableInFindFreeStackMethods(IEnumerable<CodeInstruction> instructionsEnumerable)
		{
			CodeInstruction[] instructions = instructionsEnumerable.ToArray();
			Label target = (Label)instructions.First((CodeInstruction val) => val.opcode == OpCodes.Br || val.opcode == OpCodes.Br_S).operand;
			CodeInstruction targetedInstr = instructions.First((CodeInstruction val) => val.labels.Contains(target));
			Label? label = default(Label?);
			CodeInstruction lastBranch = instructions.Reverse().First((CodeInstruction val) => CodeInstructionExtensions.Branches(val, ref label) && targetedInstr.labels.Contains(label.Value));
			CodeInstruction loadingInstruction = null;
			int i = 0;
			while (i < instructions.Length)
			{
				yield return instructions[i];
				if (loadingInstruction == null && instructions[i].opcode == OpCodes.Call && ((MethodInfo)instructions[i].operand).Name == "get_Current")
				{
					loadingInstruction = instructions[i + 1].Clone();
					loadingInstruction.opcode = new Dictionary<OpCode, OpCode>
					{
						{
							OpCodes.Stloc_0,
							OpCodes.Ldloc_0
						},
						{
							OpCodes.Stloc_1,
							OpCodes.Ldloc_1
						},
						{
							OpCodes.Stloc_2,
							OpCodes.Ldloc_2
						},
						{
							OpCodes.Stloc_3,
							OpCodes.Ldloc_3
						},
						{
							OpCodes.Stloc_S,
							OpCodes.Ldloc_S
						}
					}[loadingInstruction.opcode];
				}
				if (instructions[i] == lastBranch)
				{
					yield return loadingInstruction;
					yield return new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "checkingForStackableItemData"));
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckItemDataIsStackableFindFree", (Type[])null, (Type[])null));
					yield return new CodeInstruction(OpCodes.Brfalse, (object)target);
				}
				int num = i + 1;
				i = num;
			}
		}

		private static bool CheckItemDataIsStackableFindFree(ItemData item, ItemData? target)
		{
			if (target == null)
			{
				return true;
			}
			Dictionary<string, string> dictionary = IsStackable(item, target);
			if (dictionary != null)
			{
				newValuesOnStackable = dictionary;
				return true;
			}
			return false;
		}

		private static void ResetNewValuesOnStackable()
		{
			newValuesOnStackable = null;
		}

		private static void ApplyNewValuesOnStackable(ItemData? __result)
		{
			if (__result == null || newValuesOnStackable == null)
			{
				return;
			}
			foreach (KeyValuePair<string, string> item in newValuesOnStackable)
			{
				__result.m_customData[item.Key] = item.Value;
			}
		}

		private static Dictionary<string, string>? IsStackable(ItemData a, ItemData b)
		{
			ItemInfo itemInfo = a.Data();
			if (itemInfo != null)
			{
				return itemInfo.IsStackableWithOtherInfo(b.Data());
			}
			ItemInfo itemInfo2 = b.Data();
			if (itemInfo2 != null)
			{
				return itemInfo2.IsStackableWithOtherInfo(null);
			}
			return new Dictionary<string, string>();
		}

		private static bool CheckItemDataStackableAddItem(Inventory __instance, ItemData item, int x, int y, ref Dictionary<string, string>? __state, ref bool __result)
		{
			ItemData itemAt = __instance.GetItemAt(x, y);
			if (itemAt != null)
			{
				Dictionary<string, string> dictionary = IsStackable(item, itemAt);
				if (dictionary == null)
				{
					__result = false;
					return false;
				}
				__state = dictionary;
			}
			return true;
		}

		private static void ApplyCustomItemDataStackableAddItem(Inventory __instance, int x, int y, Dictionary<string, string>? __state, bool __result)
		{
			if (!__result || __state == null)
			{
				return;
			}
			foreach (KeyValuePair<string, string> item in __state)
			{
				__instance.GetItemAt(x, y).m_customData[item.Key] = item.Value;
			}
		}

		private static void ApplyCustomItemDataStackableAutoStack(ItemDrop item, Dictionary<string, string> customData)
		{
			item.m_itemData.m_customData = customData;
		}

		private static Dictionary<string, string>? IsStackableItemDrop(ItemDrop drop, ItemData item)
		{
			return IsStackable(drop.m_itemData, item);
		}

		private static IEnumerable<CodeInstruction> HandleAutostackableItems(IEnumerable<CodeInstruction> instructionList, ILGenerator ilg)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			List<CodeInstruction> list = instructionList.ToList();
			FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ItemData), "m_stack");
			FieldInfo fieldInfo2 = AccessTools.DeclaredField(typeof(ItemDrop), "m_itemData");
			Label? label = default(Label?);
			for (int i = 0; i < list.Count; i++)
			{
				if (!CodeInstructionExtensions.StoresField(list[i], fieldInfo))
				{
					continue;
				}
				for (int num = i; num > 0; num--)
				{
					if (CodeInstructionExtensions.Branches(list[num], ref label))
					{
						for (int num2 = num; num2 > 0; num2--)
						{
							if (CodeInstructionExtensions.LoadsField(list[num2], fieldInfo2, false))
							{
								LocalBuilder localBuilder = ilg.DeclareLocal(typeof(Dictionary<string, string>));
								LocalBuilder localBuilder2 = ilg.DeclareLocal(typeof(ItemData));
								list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyCustomItemDataStackableAutoStack", (Type[])null, (Type[])null)));
								list.Insert(i + 1, new CodeInstruction(OpCodes.Ldloc, (object)localBuilder.LocalIndex));
								list.Insert(i + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Brfalse, (object)label));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Stloc, (object)localBuilder.LocalIndex));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Dup, (object)localBuilder.LocalIndex));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "IsStackableItemDrop", (Type[])null, (Type[])null)));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Ldloc, (object)localBuilder2.LocalIndex));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
								list.Insert(num2 + 1, new CodeInstruction(OpCodes.Stloc, (object)localBuilder2.LocalIndex));
								list.Insert(num2 + 1, new CodeInstruction(OpCodes.Dup, (object)null));
								return list;
							}
						}
					}
				}
			}
			throw new Exception("Found no stack store in a branch");
		}

		private static IEnumerable<CodeInstruction> TransferCustomItemDataOnUpgrade(IEnumerable<CodeInstruction> instructions, ILGenerator ilg)
		{
			MethodInfo itemDeleter = AccessTools.DeclaredMethod(typeof(Inventory), "RemoveItem", new Type[1] { typeof(ItemData) }, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)itemDeleter))
				{
					yield return new CodeInstruction(OpCodes.Dup, (object)null);
					yield return new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "currentlyUpgradingItem"));
				}
				yield return instruction;
			}
		}

		private static void ResetCurrentlyUpgradingItem()
		{
			currentlyUpgradingItem = null;
		}

		private static void CopyCustomDataFromUpgradedItem(ItemDrop item)
		{
			if (currentlyUpgradingItem != null)
			{
				item.m_itemData.m_customData = currentlyUpgradingItem.m_customData;
				ItemInfo itemInfo = currentlyUpgradingItem.Data();
				ItemExtensions.itemInfo.Remove(currentlyUpgradingItem);
				ItemExtensions.itemInfo.Add(item.m_itemData, itemInfo);
				item.m_itemData.m_quality = currentlyUpgradingItem.m_quality + 1;
				item.m_itemData.m_variant = currentlyUpgradingItem.m_variant;
				itemInfo.ItemData = item.m_itemData;
				itemInfo.LoadAll();
				foreach (ItemData value in itemInfo.data.Values)
				{
					value.Upgraded();
				}
				currentlyUpgradingItem = null;
				awakeningItem = null;
				return;
			}
			GameObject dropPrefab = item.m_itemData.m_dropPrefab;
			if (dropPrefab == null || item.m_itemData.m_customData.Count != 0)
			{
				return;
			}
			ZNetView component = ((Component)item).GetComponent<ZNetView>();
			ZDO val = ((Object.op_Implicit((Object)(object)component) && component.IsValid()) ? component.GetZDO() : null);
			if (val != null && val.GetInt(ZDOVars.s_dataCount, -1) != -1)
			{
				return;
			}
			item.m_itemData.m_customData = new Dictionary<string, string>(dropPrefab.GetComponent<ItemDrop>().m_itemData.m_customData);
			if (val == null)
			{
				return;
			}
			int num = 0;
			val.Set(ZDOVars.s_dataCount, item.m_itemData.m_customData.Count, false);
			foreach (KeyValuePair<string, string> customDatum in item.m_itemData.m_customData)
			{
				val.Set($"data_{num}", customDatum.Key);
				val.Set($"data__{++num}", customDatum.Value);
			}
		}

		private static IEnumerable<CodeInstruction> ImportCustomDataOnUpgrade(IEnumerable<CodeInstruction> instructionList)
		{
			List<CodeInstruction> list = instructionList.ToList();
			foreach (CodeInstruction instruction in list)
			{
				yield return instruction;
				if (instruction.opcode == OpCodes.Stfld && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.DeclaredField(typeof(ItemData), "m_dropPrefab")))
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CopyCustomDataFromUpgradedItem", (Type[])null, (Type[])null));
				}
			}
		}

		private static void TrackAwakeningItem(ItemDrop __instance)
		{
			if (ZNetView.m_forceDisableInit)
			{
				awakeningItem = __instance.m_itemData;
			}
		}

		static ItemInfo()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_01d0: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_023f: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Expected O, but got Unknown
			//IL_02a1: Expected O, but got Unknown
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Expected O, but got Unknown
			//IL_0310: Expected O, but got Unknown
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Expected O, but got Unknown
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Expected O, but got Unknown
			//IL_03c0: Expected O, but got Unknown
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Expected O, but got Unknown
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Expected O, but got Unknown
			//IL_0452: Expected O, but got Unknown
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Expected O, but got Unknown
			//IL_0503: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Expected O, but got Unknown
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c9: Expected O, but got Unknown
			//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0622: Unknown result type (might be due to invalid IL or missing references)
			//IL_0629: Expected O, but got Unknown
			//IL_064f: Unknown result type (might be due to invalid IL or missing references)
			//IL_065d: Expected O, but got Unknown
			//IL_065d: Expected O, but got Unknown
			//IL_069c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a9: Expected O, but got Unknown
			//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0702: Unknown result type (might be due to invalid IL or missing references)
			//IL_070f: Expected O, but got Unknown
			//IL_070f: Expected O, but got Unknown
			//IL_074e: Unknown result type (might be due to invalid IL or missing references)
			//IL_075b: Expected O, but got Unknown
			ForceLoadTypes = new HashSet<Type>();
			typeInheritorsCache = new Dictionary<Type, HashSet<Type>>();
			knownTypes = new HashSet<string>();
			awakeningItem = null;
			primaryAssembly = Assembly.GetExecutingAssembly();
			assemblyNameCache = new Dictionary<Assembly, string>();
			classKeyCache = new Dictionary<Type, string>();
			removeMethod = typeof(ItemInfo).GetMethods().Single((MethodInfo m) => m.Name == "Remove" && m.IsGenericMethod && m.GetParameters()[0].ParameterType == typeof(string));
			Harmony val = new Harmony("org.bepinex.helpers.ItemDataManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "Save", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveInventoryPrefix", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			foreach (MethodInfo item in from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "SaveToZDO"
				select m)
			{
				val.Patch((MethodBase)item, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SavePrefix", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[4]
			{
				typeof(ItemData),
				typeof(int),
				typeof(int),
				typeof(int)
			}, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckItemDataStackableAddItem", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyCustomItemDataStackableAddItem", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "CanAddItem", new Type[2]
			{
				typeof(ItemData),
				typeof(int)
			}, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[1] { typeof(ItemData) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[2]
			{
				typeof(ItemData),
				typeof(Vector2i)
			}, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "FindFreeStackSpace", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Inventory), "FindFreeStackItem", (Type[])null, (Type[])null);
			HarmonyMethod val2 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null));
			val.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ResetNewValuesOnStackable", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyNewValuesOnStackable", (Type[])null, (Type[])null)), val2, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemDrop), "AutoStackItems", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "HandleAutostackableItems", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(InventoryGui), "DoCrafting", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "TransferCustomItemDataOnUpgrade", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ResetCurrentlyUpgradingItem", (Type[])null, (Type[])null)), (HarmonyMethod)null);
			foreach (MethodInfo item2 in from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "LoadFromZDO"
				select m)
			{
				val.Patch((MethodBase)item2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypes", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Player), "Load", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypesOnPlayerLoaded", (Type[])null, (Type[])null), 700, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[8]
			{
				typeof(string),
				typeof(int),
				typeof(int),
				typeof(int),
				typeof(long),
				typeof(string),
				typeof(Vector2i),
				typeof(bool)
			}, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypesAddItem", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(ItemDrop), "Awake", (Type[])null, (Type[])null);
			HarmonyMethod val3 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "TrackAwakeningItem", (Type[])null, (Type[])null));
			val2 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ImportCustomDataOnUpgrade", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null);
			val.Patch((MethodBase)methodInfo2, val3, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDropAwake", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), val2, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemDrop), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDropAwakeDelayed", (Type[])null, (Type[])null), 799, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemData), "Clone", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDataClonePrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDataClonePostfix", (Type[])null, (Type[])null), 500, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemData), "Clone", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDataClonePostfixDelayed", (Type[])null, (Type[])null), 499, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
	}
	[PublicAPI]
	public class ForeignItemInfo : IEnumerable<object>, IEnumerable
	{
		private readonly object foreignItemInfo;

		public string Mod => ((string)foreignItemInfo.GetType().GetProperty("Mod")?.GetValue(foreignItemInfo)) ?? "";

		public ItemData ItemData { get; private set; }

		public string? this[string key]
		{
			get
			{
				object obj = foreignItemInfo.GetType().InvokeMember("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, foreignItemInfo, new object[1] { key });
				if (obj != null)
				{
					return (string)obj.GetType().GetProperty("Value")?.GetValue(obj);
				}
				return null;
			}
			set
			{
				foreignItemInfo.GetType().GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public)?.Invoke(foreignItemInfo, new object[2] { key, value });
			}
		}

		internal ForeignItemInfo(ItemData itemData, object foreignItemInfo)
		{
			ItemData = itemData;
			this.foreignItemInfo = foreignItemInfo;
		}

		public T GetOrCreate<T>(string key = "") where T : class, new()
		{
			return Add<T>(key) ?? Get<T>(key);
		}

		private object? call(string name, object?[] values, Type?[] args, Type? generic = null)
		{
			MethodInfo[] methods = foreignItemInfo.GetType().GetMethods();
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == name && (from p in methodInfo.GetParameters()
					select (!p.ParameterType.IsGenericParameter) ? p.ParameterType : null).SequenceEqual<Type>(args) && (object)generic != null == methodInfo.IsGenericMethod)
				{
					MethodInfo methodInfo2 = methodInfo;
					if ((object)generic != null)
					{
						methodInfo2 = methodInfo2.MakeGenericMethod(generic);
					}
					return methodInfo2.Invoke(foreignItemInfo, values);
				}
			}
			return null;
		}

		public T? Add<T>(string key = "") where T : class, new()
		{
			return call("Add", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as T;
		}

		public T? Get<T>(string key = "") where T : class
		{
			return call("Get", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as T;
		}

		public Dictionary<string, T> GetAll<T>() where T : class
		{
			return ((call("GetAll", Array.Empty<object>(), Array.Empty<Type>(), typeof(T)) as T) as Dictionary<string, T>) ?? new Dictionary<string, T>();
		}

		public bool Remove(string key = "")
		{
			return call("Add", new object[1] { key }, new Type[1] { typeof(string) }) as bool? == true;
		}

		public bool Remove<T>(string key = "") where T : class
		{
			return call("Remove", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as bool? == true;
		}

		public bool Remove<T>(T itemData) where T : class
		{
			return call("Remove", new object[1] { itemData }, new Type[1], typeof(T)) as bool? == true;
		}

		public void Save()
		{
			call("Save", Array.Empty<object>(), Array.Empty<Type>());
		}

		public void LoadAll()
		{
			call("LoadAll", Array.Empty<object>(), Array.Empty<Type>());
		}

		public IEnumerator<object> GetEnumerator()
		{
			return (IEnumerator<object>)((call("GetEnumerator", Array.Empty<object>(), Array.Empty<Type>()) as IEnumerator<object>) ?? ((object)new List<object>().GetEnumerator()));
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	[PublicAPI]
	public static class ItemExtensions
	{
		[SpecialName]
		public sealed class <G>$89A7D4A522B437A8B95320B2CAC6531E
		{
			[SpecialName]
			public static class <M>$091BBA0B72542A51B2CEA87B8CA8E7DC
			{
			}

			[ExtensionMarker("<M>$091BBA0B72542A51B2CEA87B8CA8E7DC")]
			public ItemInfo Data()
			{
				throw null;
			}

			[ExtensionMarker("<M>$091BBA0B72542A51B2CEA87B8CA8E7DC")]
			public ForeignItemInfo? Data(string mod)
			{
				throw null;
			}
		}

		private const string className = "ItemDataManager.ItemExtensions";

		internal static readonly ConditionalWeakTable<ItemData, ItemInfo> itemInfo = new ConditionalWeakTable<ItemData, ItemInfo>();

		private static readonly ConditionalWeakTable<ItemData, Dictionary<string, ForeignItemInfo?>> foreignItemInfo = new ConditionalWeakTable<ItemData, Dictionary<string, ForeignItemInfo>>();

		public static ItemInfo Data(this ItemData item)
		{
			if (itemInfo.TryGetValue(item, out ItemInfo value))
			{
				return value;
			}
			itemInfo.Add(item, value = new ItemInfo(item));
			return value;
		}

		public static ForeignItemInfo? Data(this ItemData item, string mod)
		{
			Dictionary<string, ForeignItemInfo> orCreateValue = ItemExtensions.foreignItemInfo.GetOrCreateValue(item);
			if (orCreateValue.TryGetValue(mod, out var value))
			{
				return value;
			}
			if (!Chainloader.PluginInfos.TryGetValue(mod,