Decompiled source of InventorySlots v1.5.4

InventorySlots.dll

Decompiled a day 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 BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
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.RepresentationModel;
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("InventorySlots")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("InventorySlots")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("A57F2112-F59E-48EF-9D76-F2E4580F7401")]
[assembly: AssemblyFileVersion("1.5.4")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.4.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;
		}
	}
}
namespace LocalizationManager
{
	internal static class Localizer
	{
		private static readonly string[] FileExtensions = new string[2] { ".yml", ".json" };

		private static readonly ManualLogSource Log = Logger.CreateLogSource("InventorySlots.Localization");

		private static BaseUnityPlugin? _plugin;

		private static bool _loaded;

		public static event Action? OnLocalizationComplete;

		public static void Load(BaseUnityPlugin plugin)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			_plugin = plugin;
			if (_loaded)
			{
				TryLoadCurrentLanguage();
				return;
			}
			_loaded = true;
			PatchLocalization(new Harmony(plugin.Info.Metadata.GUID + ".LocalizationManager"));
			TryLoadCurrentLanguage();
		}

		private static void PatchLocalization(Harmony harmony)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Localizer), "LocalizationSetupLanguagePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Localizer), "FejdStartupSetupGuiPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void LocalizationSetupLanguagePostfix(Localization __instance, string language)
		{
			LoadLocalization(__instance, language);
		}

		private static void FejdStartupSetupGuiPostfix()
		{
			TryLoadCurrentLanguage();
		}

		private static void TryLoadCurrentLanguage()
		{
			if (Localization.instance != null)
			{
				LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
			}
		}

		private static void LoadLocalization(Localization localization, string language)
		{
			if ((Object)(object)_plugin == (Object)null || localization == null)
			{
				return;
			}
			Dictionary<string, string> dictionary = LoadLanguageDictionary("English");
			if (!string.Equals(language, "English", StringComparison.OrdinalIgnoreCase))
			{
				Merge(dictionary, LoadLanguageDictionary(language));
			}
			foreach (KeyValuePair<string, string> item in dictionary)
			{
				localization.AddWord(item.Key, item.Value);
			}
			Localizer.OnLocalizationComplete?.Invoke();
		}

		private static Dictionary<string, string> LoadLanguageDictionary(string language)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			Merge(dictionary, LoadEmbeddedLanguage(language));
			foreach (string item in FindExternalTranslationFiles(language))
			{
				try
				{
					Merge(dictionary, ParseTranslations(File.ReadAllText(item), item));
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Failed to load localization file " + item + ": " + ex.Message));
				}
			}
			return dictionary;
		}

		private static Dictionary<string, string> LoadEmbeddedLanguage(string language)
		{
			string[] fileExtensions = FileExtensions;
			foreach (string text in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + text);
				if (array != null)
				{
					return ParseTranslations(Encoding.UTF8.GetString(array), language + text);
				}
			}
			if (string.Equals(language, "English", StringComparison.OrdinalIgnoreCase))
			{
				Log.LogWarning((object)"Found no embedded English localization for InventorySlots.");
			}
			return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		}

		private static IEnumerable<string> FindExternalTranslationFiles(string language)
		{
			if ((Object)(object)_plugin == (Object)null)
			{
				yield break;
			}
			string modName = _plugin.Info.Metadata.Name;
			foreach (string root in GetExternalTranslationRoots())
			{
				if (!Directory.Exists(root))
				{
					continue;
				}
				string[] fileExtensions = FileExtensions;
				foreach (string text in fileExtensions)
				{
					string searchPattern = modName + "." + language + text;
					string[] files = Directory.GetFiles(root, searchPattern, SearchOption.AllDirectories);
					for (int j = 0; j < files.Length; j++)
					{
						yield return files[j];
					}
				}
			}
		}

		private static IEnumerable<string> GetExternalTranslationRoots()
		{
			if (!string.IsNullOrWhiteSpace(Paths.PluginPath))
			{
				yield return Paths.PluginPath;
			}
			if ((Object)(object)_plugin != (Object)null)
			{
				yield return Path.Combine(Paths.ConfigPath, _plugin.Info.Metadata.GUID + "Translations");
			}
		}

		private static Dictionary<string, string> ParseTranslations(string text, string source)
		{
			try
			{
				return new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text) ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to parse localization source " + source + ": " + ex.Message));
				return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			}
		}

		private static void Merge(Dictionary<string, string> target, Dictionary<string, string> source)
		{
			foreach (KeyValuePair<string, string> item in source)
			{
				target[item.Key] = item.Value;
			}
		}

		private static byte[]? ReadEmbeddedFileBytes(string resourceFileName)
		{
			if ((Object)(object)_plugin == (Object)null)
			{
				return null;
			}
			Assembly assembly = ((object)_plugin).GetType().Assembly;
			string text = assembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith(resourceFileName, StringComparison.OrdinalIgnoreCase));
			if (text == null)
			{
				return null;
			}
			using Stream stream = assembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace InventorySlots
{
	[BepInPlugin("sighsorry.InventorySlots", "InventorySlots", "1.5.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("Azumatt.AzuExtendedPlayerInventory")]
	[BepInIncompatibility("shudnal.ExtraSlots")]
	[BepInIncompatibility("shudnal.ExtraSlotsCustomSlots")]
	[BepInIncompatibility("randyknapp.mods.equipmentandquickslots")]
	[BepInIncompatibility("com.bruce.valheim.comfyquickslots")]
	[BepInIncompatibility("goldenrevolver.quick_stack_store")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class InventorySlotsPlugin : BaseUnityPlugin
	{
		private sealed class AzuCraftyBoxesApi
		{
			private readonly MethodInfo _getNearbyContainersMethod;

			private readonly MethodInfo _canItemBePulledMethod;

			private readonly MethodInfo? _shouldPreventMethod;

			private readonly FieldInfo? _rangeField;

			private readonly FieldInfo? _leaveOneField;

			private readonly FieldInfo? _resourceStringField;

			private readonly FieldInfo? _flashColorField;

			private readonly FieldInfo? _unFlashColorField;

			private readonly Dictionary<Type, MethodInfo?> _getPrefabNameMethods = new Dictionary<Type, MethodInfo>();

			private readonly Dictionary<Type, MethodInfo?> _itemCountMethods = new Dictionary<Type, MethodInfo>();

			private ConfigEntryBase? _rangeConfig;

			private ConfigEntryBase? _leaveOneConfig;

			private ConfigEntryBase? _resourceStringConfig;

			private ConfigEntryBase? _flashColorConfig;

			private ConfigEntryBase? _unFlashColorConfig;

			private AzuCraftyBoxesApi(MethodInfo getNearbyContainersMethod, MethodInfo canItemBePulledMethod, MethodInfo? shouldPreventMethod, FieldInfo? rangeField, FieldInfo? leaveOneField, FieldInfo? resourceStringField, FieldInfo? flashColorField, FieldInfo? unFlashColorField)
			{
				_getNearbyContainersMethod = getNearbyContainersMethod;
				_canItemBePulledMethod = canItemBePulledMethod;
				_shouldPreventMethod = shouldPreventMethod;
				_rangeField = rangeField;
				_leaveOneField = leaveOneField;
				_resourceStringField = resourceStringField;
				_flashColorField = flashColorField;
				_unFlashColorField = unFlashColorField;
			}

			public static bool TryCreate(Assembly assembly, out AzuCraftyBoxesApi? api, out string detail)
			{
				api = null;
				Type type = assembly.GetType("AzuCraftyBoxes.API");
				Type type2 = assembly.GetType("AzuCraftyBoxes.AzuCraftyBoxesPlugin");
				Type type3 = assembly.GetType("AzuCraftyBoxes.Util.Functions.MiscFunctions");
				MethodInfo methodInfo = (type?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "GetNearbyContainers" && method.IsGenericMethodDefinition && method.GetParameters().Length == 2))?.MakeGenericMethod(typeof(Player));
				MethodInfo methodInfo2 = type?.GetMethod("CanItemBePulled", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(string),
					typeof(string)
				}, null);
				if (methodInfo == null || methodInfo2 == null)
				{
					detail = "required API methods were not found";
					return false;
				}
				api = new AzuCraftyBoxesApi(methodInfo, methodInfo2, type3?.GetMethod("ShouldPrevent", BindingFlags.Static | BindingFlags.NonPublic), type2?.GetField("mRange", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("leaveOne", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("resourceString", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("flashColor", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("unFlashColor", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
				detail = "";
				return true;
			}

			public IEnumerable? GetNearbyContainers(Player player, float range)
			{
				return _getNearbyContainersMethod.Invoke(null, new object[2] { player, range }) as IEnumerable;
			}

			public bool CanItemBePulled(string containerPrefab, string itemPrefab)
			{
				try
				{
					object obj = _canItemBePulledMethod.Invoke(null, new object[2] { containerPrefab, itemPrefab });
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}

			public bool ShouldPrevent()
			{
				if (_shouldPreventMethod == null)
				{
					return false;
				}
				try
				{
					object obj = _shouldPreventMethod.Invoke(null, null);
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}

			public float GetRange()
			{
				object cachedConfigEntryValue = GetCachedConfigEntryValue(_rangeField, ref _rangeConfig);
				if (cachedConfigEntryValue == null)
				{
					return 20f;
				}
				try
				{
					return Convert.ToSingle(cachedConfigEntryValue);
				}
				catch
				{
					return 20f;
				}
			}

			public bool GetLeaveOne()
			{
				string a = GetCachedConfigEntryValue(_leaveOneField, ref _leaveOneConfig)?.ToString() ?? "";
				if (!string.Equals(a, "On", StringComparison.OrdinalIgnoreCase))
				{
					return string.Equals(a, "True", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}

			public string InvokeString(object instance, string methodName)
			{
				Type type = instance.GetType();
				if (!_getPrefabNameMethods.TryGetValue(type, out MethodInfo value))
				{
					value = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public);
					_getPrefabNameMethods[type] = value;
				}
				try
				{
					return (value?.Invoke(instance, null) as string) ?? "";
				}
				catch
				{
					return "";
				}
			}

			public int InvokeInt(object instance, string methodName, string argument)
			{
				Type type = instance.GetType();
				if (!_itemCountMethods.TryGetValue(type, out MethodInfo value))
				{
					value = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
					_itemCountMethods[type] = value;
				}
				try
				{
					return (value?.Invoke(instance, new object[1] { argument }) is int num) ? num : 0;
				}
				catch
				{
					return 0;
				}
			}

			public bool TryFormatRequirementAmount(int available, int required, out string text)
			{
				text = "";
				string text2 = (GetCachedConfigEntryValue(_resourceStringField, ref _resourceStringConfig) as string) ?? "";
				if (string.IsNullOrWhiteSpace(text2))
				{
					text = required.ToString();
					return true;
				}
				try
				{
					text = string.Format(text2, FormatThousands(available), required);
					return true;
				}
				catch
				{
					text = $"{FormatThousands(available)}/{required}";
					return true;
				}
			}

			public bool TryGetRequirementFlashColor(out Color color)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				color = default(Color);
				FieldInfo fieldInfo = ((Mathf.Sin(Time.time * 10f) > 0f) ? _flashColorField : _unFlashColorField);
				if (((fieldInfo == _flashColorField) ? GetCachedConfigEntryValue(fieldInfo, ref _flashColorConfig) : GetCachedConfigEntryValue(fieldInfo, ref _unFlashColorConfig)) is Color val)
				{
					color = val;
					return true;
				}
				return false;
			}

			private object? GetCachedConfigEntryValue(FieldInfo? field, ref ConfigEntryBase? config)
			{
				if (field == null)
				{
					return null;
				}
				try
				{
					if (config == null)
					{
						object? value = field.GetValue(null);
						config = (ConfigEntryBase?)((value is ConfigEntryBase) ? value : null);
					}
					ConfigEntryBase? obj = config;
					return (obj != null) ? obj.BoxedValue : null;
				}
				catch
				{
					config = null;
					return null;
				}
			}

			private static string FormatThousands(int number)
			{
				if (number >= 1000000)
				{
					return ((double)number / 1000000.0).ToString("0.#") + "M";
				}
				if (number < 1000)
				{
					return number.ToString();
				}
				return ((double)number / 1000.0).ToString("0.#") + "K";
			}
		}

		private sealed class AdventureBackpacksApi
		{
			private readonly MethodInfo _isBackpackMethod;

			private readonly MethodInfo? _equipItemPostfixMethod;

			private readonly MethodInfo? _unequipItemPrefixMethod;

			private readonly MethodInfo? _isBackpackEquippedMethod;

			private readonly MethodInfo? _isThisBackpackEquippedMethod;

			private readonly MethodInfo? _getEquippedBackpackMethod;

			private readonly MethodInfo? _reorderBonesMethod;

			private readonly FieldInfo? _backpackEquippedField;

			private AdventureBackpacksApi(MethodInfo isBackpackMethod, MethodInfo? equipItemPostfixMethod, MethodInfo? unequipItemPrefixMethod, MethodInfo? isBackpackEquippedMethod, MethodInfo? isThisBackpackEquippedMethod, MethodInfo? getEquippedBackpackMethod, MethodInfo? reorderBonesMethod, FieldInfo? backpackEquippedField)
			{
				_isBackpackMethod = isBackpackMethod;
				_equipItemPostfixMethod = equipItemPostfixMethod;
				_unequipItemPrefixMethod = unequipItemPrefixMethod;
				_isBackpackEquippedMethod = isBackpackEquippedMethod;
				_isThisBackpackEquippedMethod = isThisBackpackEquippedMethod;
				_getEquippedBackpackMethod = getEquippedBackpackMethod;
				_reorderBonesMethod = reorderBonesMethod;
				_backpackEquippedField = backpackEquippedField;
			}

			public static bool TryCreate(Assembly assembly, out AdventureBackpacksApi? api, out string detail)
			{
				api = null;
				MethodInfo methodInfo = assembly.GetType("AdventureBackpacks.API.ABAPI")?.GetMethod("IsBackpack", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null);
				if (methodInfo == null)
				{
					detail = "AdventureBackpacks.API.ABAPI.IsBackpack was not found";
					return false;
				}
				Type? type = assembly.GetType("AdventureBackpacks.Patches.HumanoidPatches");
				Type type2 = type?.GetNestedType("HumanoidEquipItemPatch", BindingFlags.NonPublic);
				Type type3 = type?.GetNestedType("HumanoidUnequipItemPatch", BindingFlags.NonPublic);
				Type type4 = assembly.GetType("AdventureBackpacks.Extensions.PlayerExtensions");
				Type type5 = assembly.GetType("AdventureBackpacks.Patches.InventoryGuiPatches");
				Type type6 = assembly.GetType("Vapok.Common.Tools.BoneReorder");
				api = new AdventureBackpacksApi(methodInfo, type2?.GetMethod("Postfix", BindingFlags.Static | BindingFlags.NonPublic), type3?.GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic), type4?.GetMethod("IsBackpackEquipped", BindingFlags.Static | BindingFlags.Public), type4?.GetMethod("IsThisBackpackEquipped", BindingFlags.Static | BindingFlags.Public), type4?.GetMethod("GetEquippedBackpack", BindingFlags.Static | BindingFlags.Public), AccessTools.Method(type6, "ReorderBones", (Type[])null, (Type[])null), type5?.GetField("BackpackEquipped", BindingFlags.Static | BindingFlags.Public));
				detail = "";
				return true;
			}

			public bool IsBackpack(ItemData? item)
			{
				if (item == null)
				{
					return false;
				}
				try
				{
					object obj = _isBackpackMethod.Invoke(null, new object[1] { item });
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}

			public bool IsBackpackEquippedFlagSet()
			{
				try
				{
					object obj = _backpackEquippedField?.GetValue(null);
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}

			public void OnCustomBackpackEquipped(Player player, ItemData item)
			{
				if ((Object)(object)player == (Object)null || item == null || !IsBackpack(item))
				{
					return;
				}
				try
				{
					_equipItemPostfixMethod?.Invoke(null, new object[2] { item, true });
					_backpackEquippedField?.SetValue(null, true);
				}
				catch (Exception)
				{
				}
			}

			public void OnCustomBackpackUnequipping(Player player, ItemData item)
			{
				if ((Object)(object)player == (Object)null || item == null || !IsBackpack(item))
				{
					return;
				}
				ItemData shoulderItem = ((Humanoid)player).m_shoulderItem;
				try
				{
					((Humanoid)player).m_shoulderItem = item;
					_unequipItemPrefixMethod?.Invoke(null, new object[1] { item });
				}
				catch (Exception)
				{
				}
				finally
				{
					((Humanoid)player).m_shoulderItem = shoulderItem;
				}
			}

			public void ReorderBones(VisEquipment visEquipment, int itemHash, List<GameObject>? instances)
			{
				if (_reorderBonesMethod == null || IsUnityNull((Object?)(object)visEquipment) || instances == null || instances.Count == 0)
				{
					return;
				}
				try
				{
					_reorderBonesMethod.Invoke(null, new object[3] { visEquipment, itemHash, instances });
				}
				catch
				{
				}
			}

			public void ApplyPatches(Harmony harmony)
			{
				PatchOptional(harmony, _isBackpackEquippedMethod, null, "AdventureBackpackIsBackpackEquippedPostfix", "AdventureBackpacks IsBackpackEquipped");
				PatchOptional(harmony, _isThisBackpackEquippedMethod, null, "AdventureBackpackIsThisBackpackEquippedPostfix", "AdventureBackpacks IsThisBackpackEquipped");
				PatchOptional(harmony, _getEquippedBackpackMethod, "AdventureBackpackGetEquippedBackpackPrefix", "AdventureBackpackGetEquippedBackpackPostfix", "AdventureBackpacks GetEquippedBackpack");
			}

			private static void PatchOptional(Harmony harmony, MethodInfo? target, string? prefix = null, string? postfix = null, string? label = null)
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				if (harmony != null && !(target == null))
				{
					MethodInfo methodInfo = ((prefix == null) ? null : AccessTools.Method(typeof(InventorySlotsPlugin), prefix, (Type[])null, (Type[])null));
					MethodInfo methodInfo2 = ((postfix == null) ? null : AccessTools.Method(typeof(InventorySlotsPlugin), postfix, (Type[])null, (Type[])null));
					harmony.Patch((MethodBase)target, (methodInfo == null) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo), (methodInfo2 == null) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private sealed class SmoothbrainBackpacksApi
		{
			private readonly MethodInfo _validateBackpackMethod;

			private readonly FieldInfo _visualsField;

			private readonly FieldInfo _equippedBackpackItemField;

			private readonly FieldInfo? _currentBackpackItemHashField;

			private readonly MethodInfo? _setBackpackItemMethod;

			private readonly MethodInfo? _forceSetBackpackEquippedMethod;

			private SmoothbrainBackpacksApi(MethodInfo validateBackpackMethod, FieldInfo visualsField, FieldInfo equippedBackpackItemField, FieldInfo? currentBackpackItemHashField, MethodInfo? setBackpackItemMethod, MethodInfo? forceSetBackpackEquippedMethod)
			{
				_validateBackpackMethod = validateBackpackMethod;
				_visualsField = visualsField;
				_equippedBackpackItemField = equippedBackpackItemField;
				_currentBackpackItemHashField = currentBackpackItemHashField;
				_setBackpackItemMethod = setBackpackItemMethod;
				_forceSetBackpackEquippedMethod = forceSetBackpackEquippedMethod;
			}

			public static bool TryCreate(Assembly assembly, out SmoothbrainBackpacksApi? api, out string detail)
			{
				api = null;
				Type? type = assembly.GetType("Backpacks.Backpacks");
				Type type2 = assembly.GetType("Backpacks.Visual");
				MethodInfo methodInfo = type?.GetMethod("validateBackpack", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
				FieldInfo fieldInfo = type2?.GetField("visuals", BindingFlags.Static | BindingFlags.Public);
				FieldInfo fieldInfo2 = type2?.GetField("equippedBackpackItem", BindingFlags.Instance | BindingFlags.Public);
				if (methodInfo == null || fieldInfo == null || fieldInfo2 == null)
				{
					detail = "validateBackpack or Visual fields were not found";
					return false;
				}
				api = new SmoothbrainBackpacksApi(methodInfo, fieldInfo, fieldInfo2, type2?.GetField("currentBackpackItemHash", BindingFlags.Instance | BindingFlags.Public), type2?.GetMethod("setBackpackItem", BindingFlags.Instance | BindingFlags.NonPublic), type2?.GetMethod("forceSetBackpackEquipped", BindingFlags.Instance | BindingFlags.Public));
				detail = "";
				return true;
			}

			public bool IsBackpack(ItemData? item)
			{
				if (item == null)
				{
					return false;
				}
				try
				{
					object obj = _validateBackpackMethod.Invoke(null, new object[1] { item });
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}

			public void SyncEquippedBackpack(Player player, ItemData? item)
			{
				if ((Object)(object)player == (Object)null || IsUnityNull((Object?)(object)((Humanoid)player).m_visEquipment) || !TryGetVisual(((Humanoid)player).m_visEquipment, out object visual) || visual == null)
				{
					return;
				}
				try
				{
					string text = (((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : "");
					int num = ((!string.IsNullOrWhiteSpace(text)) ? StringExtensionMethods.GetStableHashCode(text) : 0);
					if (_equippedBackpackItemField.GetValue(visual) != item)
					{
						_equippedBackpackItemField.SetValue(visual, item);
					}
					_setBackpackItemMethod?.Invoke(visual, new object[1] { text });
					if (_forceSetBackpackEquippedMethod != null && GetCurrentHash(visual) != num)
					{
						_forceSetBackpackEquippedMethod.Invoke(visual, new object[1] { num });
					}
				}
				catch (Exception)
				{
				}
			}

			private bool TryGetVisual(VisEquipment visEquipment, out object? visual)
			{
				visual = null;
				if (!(_visualsField.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(visEquipment))
				{
					return false;
				}
				visual = dictionary[visEquipment];
				return visual != null;
			}

			private int GetCurrentHash(object visual)
			{
				try
				{
					return (_currentBackpackItemHashField?.GetValue(visual) is int num) ? num : 0;
				}
				catch
				{
					return 0;
				}
			}
		}

		private sealed class RustyBagsApi
		{
			private readonly MethodInfo _isBagMethod;

			private readonly MethodInfo _isQuiverMethod;

			private readonly Type _bagEquipmentType;

			private readonly Type _bagType;

			private readonly Type _quiverType;

			private readonly MethodInfo _getBagMethod;

			private readonly MethodInfo _getQuiverMethod;

			private readonly MethodInfo _setBagMethod;

			private readonly MethodInfo _setQuiverMethod;

			private RustyBagsApi(MethodInfo isBagMethod, MethodInfo isQuiverMethod, Type bagEquipmentType, Type bagType, Type quiverType, MethodInfo getBagMethod, MethodInfo getQuiverMethod, MethodInfo setBagMethod, MethodInfo setQuiverMethod)
			{
				_isBagMethod = isBagMethod;
				_isQuiverMethod = isQuiverMethod;
				_bagEquipmentType = bagEquipmentType;
				_bagType = bagType;
				_quiverType = quiverType;
				_getBagMethod = getBagMethod;
				_getQuiverMethod = getQuiverMethod;
				_setBagMethod = setBagMethod;
				_setQuiverMethod = setQuiverMethod;
			}

			public static bool TryCreate(Assembly assembly, out RustyBagsApi? api, out string detail)
			{
				api = null;
				Type type = assembly.GetType("RustyBags.API");
				Type type2 = assembly.GetType("RustyBags.BagEquipment");
				Type type3 = assembly.GetType("RustyBags.Bag");
				Type type4 = assembly.GetType("RustyBags.Quiver");
				MethodInfo methodInfo = type?.GetMethod("IsBag", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				MethodInfo methodInfo2 = type?.GetMethod("IsQuiver", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				MethodInfo methodInfo3 = type2?.GetMethod("GetBag", BindingFlags.Instance | BindingFlags.Public);
				MethodInfo methodInfo4 = type2?.GetMethod("GetQuiver", BindingFlags.Instance | BindingFlags.Public);
				MethodInfo methodInfo5 = type2?.GetMethod("SetBag", BindingFlags.Instance | BindingFlags.NonPublic);
				MethodInfo methodInfo6 = type2?.GetMethod("SetQuiver", BindingFlags.Instance | BindingFlags.Public);
				if (methodInfo == null || methodInfo2 == null || type2 == null || type3 == null || type4 == null || methodInfo3 == null || methodInfo4 == null || methodInfo5 == null || methodInfo6 == null)
				{
					detail = "RustyBags API or BagEquipment methods were not found";
					return false;
				}
				api = new RustyBagsApi(methodInfo, methodInfo2, type2, type3, type4, methodInfo3, methodInfo4, methodInfo5, methodInfo6);
				detail = "";
				return true;
			}

			public bool IsBag(ItemData? item)
			{
				if (item?.m_shared == null)
				{
					return false;
				}
				try
				{
					object obj = _isBagMethod.Invoke(null, new object[1] { item.m_shared.m_name });
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}

			public bool IsQuiver(ItemData? item)
			{
				if (item?.m_shared == null)
				{
					return false;
				}
				try
				{
					object obj = _isQuiverMethod.Invoke(null, new object[1] { item.m_shared.m_name });
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}

			public void SyncBag(Player player, ItemData? item)
			{
				if (item == null || _bagType.IsInstanceOfType(item))
				{
					InvokeEquipmentSetter(player, _setBagMethod, item);
				}
			}

			public void SyncQuiver(Player player, ItemData? item)
			{
				if (item == null || _quiverType.IsInstanceOfType(item))
				{
					InvokeEquipmentSetter(player, _setQuiverMethod, item);
				}
			}

			public void ClearBagIfCurrent(Player player, ItemData item)
			{
				object bagEquipment = GetBagEquipment(player);
				if (bagEquipment != null && _getBagMethod.Invoke(bagEquipment, Array.Empty<object>()) == item)
				{
					_setBagMethod.Invoke(bagEquipment, new object[1]);
				}
			}

			public void ClearQuiverIfCurrent(Player player, ItemData item)
			{
				object bagEquipment = GetBagEquipment(player);
				if (bagEquipment != null && _getQuiverMethod.Invoke(bagEquipment, Array.Empty<object>()) == item)
				{
					_setQuiverMethod.Invoke(bagEquipment, new object[1]);
				}
			}

			private void InvokeEquipmentSetter(Player player, MethodInfo setter, ItemData? item)
			{
				object bagEquipment = GetBagEquipment(player);
				if (bagEquipment == null)
				{
					return;
				}
				try
				{
					setter.Invoke(bagEquipment, new object[1] { item });
				}
				catch (Exception)
				{
				}
			}

			private object? GetBagEquipment(Player player)
			{
				if ((Object)(object)player == (Object)null)
				{
					return null;
				}
				try
				{
					return ((Component)player).GetComponent(_bagEquipmentType);
				}
				catch
				{
					return null;
				}
			}
		}

		private sealed class BetterArcheryQuiverApi
		{
			private readonly FieldInfo _quiverEnabledField;

			private readonly FieldInfo _quiverRowIndexField;

			private ConfigEntry<bool>? _quiverEnabledConfig;

			private bool _quiverRowIndexResolved;

			private int _quiverRowIndex;

			private BetterArcheryQuiverApi(FieldInfo quiverEnabledField, FieldInfo quiverRowIndexField)
			{
				_quiverEnabledField = quiverEnabledField;
				_quiverRowIndexField = quiverRowIndexField;
			}

			public static bool TryCreate(Assembly assembly, out BetterArcheryQuiverApi? api, out string detail)
			{
				api = null;
				Type type = assembly.GetTypes().FirstOrDefault((Type candidate) => candidate.IsClass && candidate.Name == "BetterArchery");
				if (type == null)
				{
					detail = "BetterArchery type was not found";
					return false;
				}
				FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
				FieldInfo fieldInfo = fields.FirstOrDefault((FieldInfo field) => string.Equals(field.Name, "ConfigQuiverEnabled", StringComparison.OrdinalIgnoreCase));
				FieldInfo fieldInfo2 = fields.FirstOrDefault((FieldInfo field) => string.Equals(field.Name, "QuiverRowIndex", StringComparison.OrdinalIgnoreCase));
				if (fieldInfo == null || fieldInfo2 == null)
				{
					detail = "quiver config fields were not found";
					return false;
				}
				api = new BetterArcheryQuiverApi(fieldInfo, fieldInfo2);
				detail = "";
				return true;
			}

			public bool IsQuiverCell(Vector2i pos, bool includeRestockableSlots)
			{
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (_quiverEnabledConfig == null)
					{
						_quiverEnabledConfig = _quiverEnabledField.GetValue(null) as ConfigEntry<bool>;
					}
				}
				catch
				{
					_quiverEnabledConfig = null;
				}
				if (_quiverEnabledConfig == null || !_quiverEnabledConfig.Value)
				{
					return false;
				}
				if (!_quiverRowIndexResolved || _quiverRowIndex == 0)
				{
					try
					{
						_quiverRowIndex = ((_quiverRowIndexField.GetValue(null) is int num) ? num : 0);
					}
					catch
					{
						_quiverRowIndex = 0;
					}
					_quiverRowIndexResolved = _quiverRowIndex != 0;
				}
				if (_quiverRowIndex == 0)
				{
					return false;
				}
				if (pos.y == _quiverRowIndex - 1)
				{
					return true;
				}
				if (pos.y == _quiverRowIndex)
				{
					if (!includeRestockableSlots)
					{
						return pos.x > 2;
					}
					return true;
				}
				return false;
			}
		}

		private sealed class CircletExtendedApi
		{
			private delegate ItemData? GetCircletDelegate(Humanoid humanoid);

			private delegate ItemData? SetCircletDelegate(Humanoid humanoid, ItemData? item);

			private delegate bool IsCircletDelegate(ItemData item);

			private delegate bool CanEquipWithHelmetDelegate(ItemData? helmet);

			private readonly GetCircletDelegate _getCirclet;

			private readonly SetCircletDelegate _setCirclet;

			private readonly IsCircletDelegate _isCirclet;

			private readonly CanEquipWithHelmetDelegate _canEquipWithHelmet;

			private readonly ConfigEntry<bool> _enablePutOnTop;

			private bool _failed;

			private CircletExtendedApi(GetCircletDelegate getCirclet, SetCircletDelegate setCirclet, IsCircletDelegate isCirclet, CanEquipWithHelmetDelegate canEquipWithHelmet, ConfigEntry<bool> enablePutOnTop)
			{
				_getCirclet = getCirclet;
				_setCirclet = setCirclet;
				_isCirclet = isCirclet;
				_canEquipWithHelmet = canEquipWithHelmet;
				_enablePutOnTop = enablePutOnTop;
			}

			public static bool TryCreate(Assembly assembly, out CircletExtendedApi? api, out string detail)
			{
				api = null;
				Type type = assembly.GetType("CircletExtended.HumanoidExtension");
				Type type2 = assembly.GetType("CircletExtended.CircletItem");
				Type type3 = assembly.GetType("CircletExtended.CircletExtended");
				MethodInfo methodInfo = type?.GetMethod("GetCirclet", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Humanoid) }, null);
				MethodInfo methodInfo2 = type?.GetMethod("SetCirclet", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(Humanoid),
					typeof(ItemData)
				}, null);
				MethodInfo methodInfo3 = type2?.GetMethod("IsCircletItem", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
				MethodInfo methodInfo4 = type2?.GetMethod("CanCircletBeEquippedWithHelmet", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
				FieldInfo fieldInfo = type3?.GetField("enablePutOnTop", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (methodInfo?.ReturnType != typeof(ItemData) || methodInfo2?.ReturnType != typeof(ItemData) || methodInfo3?.ReturnType != typeof(bool) || methodInfo4?.ReturnType != typeof(bool) || fieldInfo == null || !typeof(ConfigEntryBase).IsAssignableFrom(fieldInfo.FieldType))
				{
					detail = "expected HumanoidExtension, CircletItem, or enablePutOnTop members were not found";
					return false;
				}
				try
				{
					if (!(fieldInfo.GetValue(null) is ConfigEntry<bool> enablePutOnTop))
					{
						detail = "enablePutOnTop was not initialized";
						return false;
					}
					api = new CircletExtendedApi((GetCircletDelegate)Delegate.CreateDelegate(typeof(GetCircletDelegate), methodInfo), (SetCircletDelegate)Delegate.CreateDelegate(typeof(SetCircletDelegate), methodInfo2), (IsCircletDelegate)Delegate.CreateDelegate(typeof(IsCircletDelegate), methodInfo3), (CanEquipWithHelmetDelegate)Delegate.CreateDelegate(typeof(CanEquipWithHelmetDelegate), methodInfo4), enablePutOnTop);
					detail = "";
					return true;
				}
				catch (Exception ex)
				{
					detail = "failed to bind CircletExtended delegates: " + ex.Message;
					return false;
				}
			}

			public bool TryGetPutOnTopEnabled(out bool enabled)
			{
				enabled = false;
				if (_failed)
				{
					return false;
				}
				try
				{
					enabled = _enablePutOnTop.Value;
					return true;
				}
				catch (Exception exception)
				{
					return Fail("reading enablePutOnTop", exception);
				}
			}

			public bool TryIsCircletCustomType(ItemData item, out bool isCirclet)
			{
				isCirclet = false;
				if (_failed)
				{
					return false;
				}
				try
				{
					isCirclet = _isCirclet(item);
					return true;
				}
				catch (Exception exception)
				{
					return Fail("checking the Circlet item type", exception);
				}
			}

			public bool TryCanEquipWithHelmet(ItemData? helmet, out bool compatible)
			{
				compatible = false;
				if (_failed)
				{
					return false;
				}
				try
				{
					compatible = _canEquipWithHelmet(helmet);
					return true;
				}
				catch (Exception exception)
				{
					return Fail("checking helmet compatibility", exception);
				}
			}

			public bool TrySetCirclet(Humanoid humanoid, ItemData item, out bool changed)
			{
				changed = false;
				if (!TryGetCirclet(humanoid, out ItemData item2))
				{
					return false;
				}
				if (item2 == item)
				{
					return true;
				}
				return TrySetCircletValue(humanoid, item, out changed);
			}

			public bool TryIsCurrentCirclet(Humanoid humanoid, ItemData item, out bool isCurrent)
			{
				isCurrent = false;
				if (!TryGetCirclet(humanoid, out ItemData item2))
				{
					return false;
				}
				isCurrent = item2 == item;
				return true;
			}

			public bool TryClearCirclet(Humanoid humanoid, ItemData item, out bool changed)
			{
				changed = false;
				if (!TryGetCirclet(humanoid, out ItemData item2))
				{
					return false;
				}
				if (item2 != item)
				{
					return true;
				}
				return TrySetCircletValue(humanoid, null, out changed);
			}

			private bool TryGetCirclet(Humanoid humanoid, out ItemData? item)
			{
				item = null;
				if (_failed)
				{
					return false;
				}
				try
				{
					item = _getCirclet(humanoid);
					return true;
				}
				catch (Exception exception)
				{
					return Fail("reading the equipped Circlet", exception);
				}
			}

			private bool TrySetCircletValue(Humanoid humanoid, ItemData? item, out bool changed)
			{
				changed = false;
				if (_failed)
				{
					return false;
				}
				try
				{
					if (_setCirclet(humanoid, item) != item)
					{
						return Fail("SetCirclet returned an unexpected item");
					}
					changed = true;
					return true;
				}
				catch (Exception exception)
				{
					return Fail("updating the equipped Circlet", exception);
				}
			}

			private bool Fail(string operation, Exception? exception = null)
			{
				if (!_failed)
				{
					string text = exception?.InnerException?.Message ?? exception?.Message ?? "unknown result";
					Log.LogWarning((object)("CircletExtended compatibility disabled while " + operation + ": " + text));
				}
				_failed = true;
				return false;
			}
		}

		private sealed class CompatApiRuntimeState<TApi> where TApi : class
		{
			public TApi? Api;

			public bool ReflectionFailed;
		}

		private sealed class CompatRuntimeState
		{
			public readonly CompatApiRuntimeState<AzuCraftyBoxesApi> AzuCraftyBoxes = new CompatApiRuntimeState<AzuCraftyBoxesApi>();

			public readonly CompatApiRuntimeState<JewelcraftingTooltipApi> JewelcraftingTooltip = new CompatApiRuntimeState<JewelcraftingTooltipApi>();

			public readonly CompatApiRuntimeState<JewelcraftingGemApi> JewelcraftingGem = new CompatApiRuntimeState<JewelcraftingGemApi>();

			public readonly CompatApiRuntimeState<JewelcraftingEffectApi> JewelcraftingEffect = new CompatApiRuntimeState<JewelcraftingEffectApi>();

			public readonly CompatApiRuntimeState<JewelcraftingSlotApi> JewelcraftingSlot = new CompatApiRuntimeState<JewelcraftingSlotApi>();

			public readonly CompatApiRuntimeState<JewelcraftingCraftingSocketUiApi> JewelcraftingCraftingSocketUi = new CompatApiRuntimeState<JewelcraftingCraftingSocketUiApi>();

			public readonly CompatApiRuntimeState<JewelcraftingGemCuttingApi> JewelcraftingGemCutting = new CompatApiRuntimeState<JewelcraftingGemCuttingApi>();

			public readonly CompatApiRuntimeState<JewelcraftingVisualApi> JewelcraftingVisual = new CompatApiRuntimeState<JewelcraftingVisualApi>();

			public readonly CompatApiRuntimeState<ItemRequiresSkillLevelApi> ItemRequiresSkillLevel = new CompatApiRuntimeState<ItemRequiresSkillLevelApi>();

			public readonly CompatApiRuntimeState<RecycleNReclaimApi> RecycleNReclaim = new CompatApiRuntimeState<RecycleNReclaimApi>();

			public readonly CompatApiRuntimeState<AdventureBackpacksApi> AdventureBackpacks = new CompatApiRuntimeState<AdventureBackpacksApi>();

			public readonly CompatApiRuntimeState<SmoothbrainBackpacksApi> SmoothbrainBackpacks = new CompatApiRuntimeState<SmoothbrainBackpacksApi>();

			public readonly CompatApiRuntimeState<RustyBagsApi> RustyBags = new CompatApiRuntimeState<RustyBagsApi>();

			public readonly CompatApiRuntimeState<MagicSupremacyApi> MagicSupremacy = new CompatApiRuntimeState<MagicSupremacyApi>();

			public readonly CompatApiRuntimeState<BetterArcheryQuiverApi> BetterArcheryQuiver = new CompatApiRuntimeState<BetterArcheryQuiverApi>();

			public readonly CompatApiRuntimeState<VeiledRecipesApi> VeiledRecipes = new CompatApiRuntimeState<VeiledRecipesApi>();

			public readonly CompatApiRuntimeState<CircletExtendedApi> CircletExtended = new CompatApiRuntimeState<CircletExtendedApi>();

			public readonly CompatApiRuntimeState<HipLanternApi> HipLantern = new CompatApiRuntimeState<HipLanternApi>();
		}

		private delegate bool CompatApiFactory<TApi>(Assembly assembly, out TApi? api, out string detail) where TApi : class;

		private enum ContainerAccessMode
		{
			Unavailable,
			DirectOwner,
			ExternalMultiUserChestRemote
		}

		private delegate bool TryGetContainerHoldContext(Player player, out Container container);

		private enum ContainerAreaFailure : byte
		{
			None,
			InvalidRequest,
			NotOwner,
			InUse,
			NoAccess,
			OutOfRange,
			Unavailable,
			Unsupported,
			Busy
		}

		private sealed class ContainerAreaSession
		{
			public Player Player;

			public Inventory Inventory;

			public Container Anchor;

			public ZDOID AnchorId;

			public bool QuickStack;

			public bool OpenAnchor;

			public Func<bool>? Interaction;

			public bool InteractionRunning;

			public bool InteractionSucceeded;

			public bool Completed;

			public List<Container> Targets;

			public int Next;

			public int Moved;

			public int Effects;

			public Container? Pending;

			public ContainerAreaRequestIdentity PendingIdentity;

			public long Token;

			public uint DataRevision;

			public ushort OwnerRevision;

			public long Expires;

			public ContainerAreaHandoffDecision Decision;

			public ContainerAreaActionKind Action
			{
				get
				{
					if (Interaction == null)
					{
						if (!QuickStack)
						{
							return ContainerAreaActionKind.Restock;
						}
						return ContainerAreaActionKind.QuickStack;
					}
					return ContainerAreaActionKind.Interaction;
				}
			}
		}

		private enum ContainerPreviewPhase
		{
			Hidden,
			PreviewVisible,
			RestorePending,
			RealInventoryVisible
		}

		private enum ContainerTakeStacksMode
		{
			CurrentContainerMatchingStacks,
			AreaFavoriteRestock
		}

		private sealed class ControllerActionOption
		{
			public ControllerHotkeyAction Action { get; }

			public string Label { get; }

			public ControllerActionOption(ControllerHotkeyAction action, string label)
			{
				Action = action;
				Label = label;
			}
		}

		private sealed class CraftingListDetailState
		{
			public RectTransform? Root;

			public Image? Icon;

			public TMP_Text? Title;

			public TMP_Text? Body;

			public RectTransform? GemRow;

			public readonly List<JewelcraftingGemIconData> GemIcons = new List<JewelcraftingGemIconData>();

			public string GemSignature = "";

			public RectTransform? Style;

			public TMP_Text? StyleLabel;

			public CraftingRecipeStyleButtonMarker? StyleMarker;

			public readonly ScrollableTooltipBodyState Scroll = new ScrollableTooltipBodyState();

			public CraftingTabAdapterKind Tab;

			public Recipe? Recipe;

			public ItemData? Item;

			public int Variant = -1;

			public bool CanCraft;

			public int LocalizationVersion = -1;

			public float NextRefresh;

			public string BodyText = "";

			public string TitleText = "";

			public string StatusText = "";
		}

		private readonly struct CraftingRequirementAvailabilityCacheEntry
		{
			public int Amount { get; }

			public float ExpiresAt { get; }

			public CraftingRequirementAvailabilityCacheEntry(int amount, float expiresAt)
			{
				Amount = amount;
				ExpiresAt = expiresAt;
			}
		}

		private sealed class CraftingRequirementRuntimeState
		{
			public readonly Dictionary<string, CraftingRequirementAvailabilityCacheEntry> AvailabilityCache = new Dictionary<string, CraftingRequirementAvailabilityCacheEntry>(StringComparer.OrdinalIgnoreCase);

			public readonly List<Requirement> VisibleRequirements = new List<Requirement>();

			public readonly List<Requirement> VisibleRequirementCandidates = new List<Requirement>();

			public readonly List<RectTransform?> OwnedSlots = new List<RectTransform>();

			public int AvailabilityVersion;
		}

		private sealed class CraftingRecipeRuntimeState
		{
			public readonly List<CraftingRecipeGridCell> GridCells = new List<CraftingRecipeGridCell>();

			public readonly List<CraftingRecipeViewEntry> View = new List<CraftingRecipeViewEntry>();

			public readonly Dictionary<int, int> ViewIndexByOriginal = new Dictionary<int, int>();

			public readonly List<CraftingRecipeGroupPanel> GroupPanels = new List<CraftingRecipeGroupPanel>();

			public readonly List<CraftingRecipeGroupButton> GroupButtons = new List<CraftingRecipeGroupButton>();

			public readonly Dictionary<Recipe, int> Variants = new Dictionary<Recipe, int>();

			public readonly Dictionary<CraftingRecipePairCacheKey, string> SearchTextCache = new Dictionary<CraftingRecipePairCacheKey, string>();

			public readonly Dictionary<string, CraftingHoverTooltipContent> HoverTooltipContentCache = new Dictionary<string, CraftingHoverTooltipContent>(StringComparer.Ordinal);

			public readonly List<JewelcraftingGemIconData> HoverGemIconCache = new List<JewelcraftingGemIconData>();

			public readonly Dictionary<string, string> EnglishLocalizationCache = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, string> EnglishLocalizationIndex = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<CraftingRecipePairCacheKey, SortKey> SortKeyCache = new Dictionary<CraftingRecipePairCacheKey, SortKey>();

			public readonly Dictionary<CraftingRecipePairCacheKey, Dictionary<string, bool>> GroupMatchCache = new Dictionary<CraftingRecipePairCacheKey, Dictionary<string, bool>>();

			public readonly List<CraftingRecipeGroupFilter> SelectableGroupFilterCache = new List<CraftingRecipeGroupFilter>();

			public readonly Dictionary<string, bool> GroupHasRecipesCache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
		}

		private sealed class CraftingGridRuntimeState
		{
			public RectTransform? RecipeGrid;

			public bool RecipeGridDirty = true;

			public int RecipePage;

			public CraftingRecipeGridStamp RecipeGridStamp;

			public string RecipeGridLayoutSignature = "";

			public int RecipeGridCellCapacity = -1;
		}

		private sealed class CraftingScrollbarRuntimeState
		{
			public RectTransform? RecipeScrollbar;

			public Scrollbar? RecipeScrollbarComponent;

			public bool UpdatingRecipeScrollbar;

			public bool RecipeScrollbarDirty = true;

			public CraftingRecipeScrollbarStamp RecipeScrollbarStamp;
		}

		private sealed class CraftingQueueRuntimeState
		{
			public bool ContinuingQueue;

			public int QueueTotal;

			public int QueueRemaining;

			public int QueueVariant;

			public int ProgressLabelCount;

			public int ProgressLabelVariant;

			public Recipe? QueueRecipe;

			public Recipe? ProgressLabelRecipe;

			public int InventoryLimitNoticeDepth;

			public ItemData? PendingInventoryLimitItem;

			public int PendingInventoryLimitMax = -1;
		}

		private sealed class CraftingUiRuntimeState
		{
			public GameObject? HoverTooltip;

			public RectTransform? HoverTooltipPanel;

			public TMP_Text? HoverTooltipTopic;

			public TMP_Text? HoverTooltipText;

			public readonly ScrollableTooltipBodyState HoverTooltipTextScroll = new ScrollableTooltipBodyState();

			public RectTransform? TooltipRecipeOverlay;

			public RectTransform? TooltipGemIconRow;

			public TMP_InputField? SearchInput;

			public RectTransform? SearchInputRect;

			public RectTransform? RecipeGridZoomHint;

			public RectTransform? GroupRail;

			public TMP_InputField? CountInput;

			public RectTransform? CountInputRect;

			public RectTransform? CountInputViewport;

			public RectTransform? UpgradeProgressionRect;

			public TMP_Text? UpgradeProgressionText;

			public RectTransform? SortModeButtonGroup;

			public RectTransform? ControlsBackground;

			public RectTransform? SocketWarningRect;

			public TMP_Text? SocketWarningText;

			public Transform? RequiredStationLevelOriginalRoot;

			public RectTransform? RequiredStationLevelHitbox;

			public RectTransformSnapshot? PanelRootSnapshot;

			public Vector2 PanelOriginalSizeDelta;

			public bool SearchInputDirty = true;

			public int HoveredRecipeIndex = -1;

			public CraftingSearchInputStamp SearchInputStamp;

			public string HoverTooltipSignature = "";

			public string HoverTooltipLayoutSignature = "";

			public string HoverTooltipVisualSignature = "";

			public string HoverGemIconSignature = "";

			public float HoverTooltipScrollOffset;

			public float HoverTooltipMaxScroll;

			public bool RecipeHoverMouseSyncPending;
		}

		private sealed class CraftingRefreshRuntimeState
		{
			public bool RecipeViewDirty = true;

			public string RecipeViewSignature = "";

			public bool GroupRailDirty = true;

			public CraftingGroupRailStamp GroupRailStamp;

			public bool BottomControlsDirty = true;

			public string BottomControlsSignature = "";

			public CraftingStatusHudStamp SocketWarningStamp;

			public CraftingSortModeButtonsStamp SortModeButtonsStamp;

			public CraftingFrameFastPathStamp FrameFastPathStamp;

			public string RecipeListChangeSignature = "";
		}

		private static class CraftingController
		{
			public static int HoveredRecipeIndex => CraftingUi.HoveredRecipeIndex;

			public static bool IsSearchInputDirty => CraftingUi.SearchInputDirty;

			public static bool NeedsModelRefresh(CraftingPanelUpdateReason reason, bool firstApply)
			{
				if (!firstApply && reason == CraftingPanelUpdateReason.FrameTick)
				{
					return HasModelRefreshWork();
				}
				return true;
			}

			public static bool HasModelRefreshWork()
			{
				if (!CraftingRefresh.RecipeViewDirty && !CraftingGrid.RecipeGridDirty && !CraftingScrollbar.RecipeScrollbarDirty)
				{
					return CraftingRefresh.GroupRailDirty;
				}
				return true;
			}

			public static bool HasFrameRebuildWork()
			{
				if (!HasModelRefreshWork())
				{
					return CraftingRefresh.BottomControlsDirty;
				}
				return true;
			}

			public static void MarkRecipeViewDirty()
			{
				CraftingRefresh.RecipeViewDirty = true;
				CraftingRefresh.RecipeViewSignature = "";
			}

			public static void MarkRecipeGridDirty()
			{
				CraftingGrid.RecipeGridDirty = true;
				CraftingGrid.RecipeGridStamp = default(CraftingRecipeGridStamp);
			}

			public static void MarkRecipeScrollbarDirty()
			{
				CraftingScrollbar.RecipeScrollbarDirty = true;
				CraftingScrollbar.RecipeScrollbarStamp = default(CraftingRecipeScrollbarStamp);
			}

			public static void MarkGroupRailDirty()
			{
				CraftingRefresh.GroupRailDirty = true;
				CraftingRefresh.GroupRailStamp = default(CraftingGroupRailStamp);
			}

			public static void MarkBottomControlsDirty()
			{
				CraftingRefresh.BottomControlsDirty = true;
				CraftingRefresh.BottomControlsSignature = "";
			}

			public static void MarkSearchInputDirty()
			{
				CraftingUi.SearchInputDirty = true;
				CraftingUi.SearchInputStamp = default(CraftingSearchInputStamp);
			}

			public static bool CanReuseRecipeView(string signature)
			{
				if (!CraftingRefresh.RecipeViewDirty)
				{
					return string.Equals(CraftingRefresh.RecipeViewSignature, signature, StringComparison.Ordinal);
				}
				return false;
			}

			public static void StoreRecipeViewSignature(string signature)
			{
				CraftingRefresh.RecipeViewSignature = signature;
				CraftingRefresh.RecipeViewDirty = false;
			}

			public static bool CanReuseRecipeGrid(CraftingRecipeGridStamp stamp)
			{
				if (!CraftingGrid.RecipeGridDirty)
				{
					return CraftingGrid.RecipeGridStamp.Equals(stamp);
				}
				return false;
			}

			public static void StoreRecipeGridStamp(CraftingRecipeGridStamp stamp)
			{
				CraftingGrid.RecipeGridStamp = stamp;
				CraftingGrid.RecipeGridDirty = false;
			}

			public static bool CanReuseRecipeScrollbar(CraftingRecipeScrollbarStamp stamp)
			{
				if (!CraftingScrollbar.RecipeScrollbarDirty)
				{
					return CraftingScrollbar.RecipeScrollbarStamp.Equals(stamp);
				}
				return false;
			}

			public static void StoreRecipeScrollbarStamp(CraftingRecipeScrollbarStamp stamp)
			{
				CraftingScrollbar.RecipeScrollbarStamp = stamp;
				CraftingScrollbar.RecipeScrollbarDirty = false;
			}

			public static bool CanReuseGroupRail(CraftingGroupRailStamp stamp)
			{
				if (!CraftingRefresh.GroupRailDirty)
				{
					return CraftingRefresh.GroupRailStamp.Equals(stamp);
				}
				return false;
			}

			public static void StoreGroupRailStamp(CraftingGroupRailStamp stamp)
			{
				CraftingRefresh.GroupRailStamp = stamp;
				CraftingRefresh.GroupRailDirty = false;
			}

			public static bool CanReuseSearchInput(CraftingSearchInputStamp stamp)
			{
				if (!CraftingUi.SearchInputDirty)
				{
					return CraftingUi.SearchInputStamp.Equals(stamp);
				}
				return false;
			}

			public static void StoreSearchInputStamp(CraftingSearchInputStamp stamp)
			{
				CraftingUi.SearchInputStamp = stamp;
				CraftingUi.SearchInputDirty = false;
			}

			public static bool NeedsBottomControlsLayout(string signature)
			{
				if (!CraftingRefresh.BottomControlsDirty)
				{
					return !string.Equals(CraftingRefresh.BottomControlsSignature, signature, StringComparison.Ordinal);
				}
				return true;
			}

			public static void StoreBottomControlsSignature(string signature)
			{
				CraftingRefresh.BottomControlsSignature = signature;
				CraftingRefresh.BottomControlsDirty = false;
			}

			public static bool CanReuseFrameFastPath(CraftingFrameFastPathStamp stamp)
			{
				return CraftingRefresh.FrameFastPathStamp.Equals(stamp);
			}

			public static void StoreFrameFastPathStamp(CraftingFrameFastPathStamp stamp)
			{
				CraftingRefresh.FrameFastPathStamp = stamp;
			}

			public static void ResetFrameFastPathStamp()
			{
				CraftingRefresh.FrameFastPathStamp = default(CraftingFrameFastPathStamp);
			}

			public static bool CanReuseSortModeButtons(CraftingSortModeButtonsStamp stamp)
			{
				return CraftingRefresh.SortModeButtonsStamp.Equals(stamp);
			}

			public static void StoreSortModeButtonsStamp(CraftingSortModeButtonsStamp stamp)
			{
				CraftingRefresh.SortModeButtonsStamp = stamp;
			}

			public static void ResetSortModeButtonsStamp()
			{
				CraftingRefresh.SortModeButtonsStamp = default(CraftingSortModeButtonsStamp);
			}

			public static bool CanReuseSocketWarning(CraftingStatusHudStamp stamp)
			{
				return CraftingRefresh.SocketWarningStamp.Equals(stamp);
			}

			public static void StoreSocketWarningStamp(CraftingStatusHudStamp stamp)
			{
				CraftingRefresh.SocketWarningStamp = stamp;
			}

			public static void ResetSocketWarningStamp()
			{
				CraftingRefresh.SocketWarningStamp = default(CraftingStatusHudStamp);
			}

			public static bool TryStoreRecipeListChangeSignature(string signature)
			{
				if (string.Equals(CraftingRefresh.RecipeListChangeSignature, signature, StringComparison.Ordinal))
				{
					return false;
				}
				CraftingRefresh.RecipeListChangeSignature = signature;
				return true;
			}

			public static void ResetRecipeListChangeSignature()
			{
				CraftingRefresh.RecipeListChangeSignature = "";
			}

			public static void MarkRecipeGridLayoutDirty()
			{
				MarkRecipeGridDirty();
				MarkRecipeScrollbarDirty();
				MarkBottomControlsDirty();
			}

			public static void SetHoveredRecipe(int index)
			{
				CraftingUi.HoveredRecipeIndex = index;
			}

			public static void ClearHoveredRecipe()
			{
				CraftingUi.HoveredRecipeIndex = -1;
			}

			public static bool IsHoveredRecipe(int index)
			{
				return CraftingUi.HoveredRecipeIndex == index;
			}

			public static void ClearHoveredRecipeAndRequestMouseSync()
			{
				ClearHoveredRecipe();
				CraftingUi.RecipeHoverMouseSyncPending = true;
			}

			public static bool ConsumeRecipeHoverMouseSync()
			{
				if (!CraftingUi.RecipeHoverMouseSyncPending)
				{
					return false;
				}
				CraftingUi.RecipeHoverMouseSyncPending = false;
				return true;
			}
		}

		private sealed class CustomEquipmentVisualState
		{
			public string SlotId { get; }

			public int ItemHash { get; }

			public int Variant { get; }

			public int Quality { get; }

			public string PrefabName { get; }

			public ItemType ItemType { get; }

			public bool ReorderAdventureBackpackBones { get; }

			public CustomEquipmentVisualState(string slotId, int itemHash, int variant, int quality, string prefabName, ItemType itemType, bool reorderAdventureBackpackBones)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				SlotId = slotId;
				ItemHash = itemHash;
				Variant = variant;
				Quality = quality;
				PrefabName = prefabName;
				ItemType = itemType;
				ReorderAdventureBackpackBones = reorderAdventureBackpackBones;
			}
		}

		private sealed class CustomEquipmentVisual
		{
			private readonly List<GameObject> _instances = new List<GameObject>();

			public string Key { get; }

			public VisEquipment Owner { get; }

			public string PrefabName { get; }

			public int Variant { get; }

			public int Quality { get; }

			public CustomEquipmentVisual(string key, VisEquipment owner, string prefabName, int variant, int quality)
			{
				Key = key;
				Owner = owner;
				PrefabName = prefabName;
				Variant = variant;
				Quality = quality;
			}

			public bool Matches(VisEquipment owner, string prefabName, int variant, int quality)
			{
				if (!IsUnityNull((Object?)(object)Owner) && (Object)(object)Owner == (Object)(object)owner && string.Equals(PrefabName, prefabName, StringComparison.Ordinal) && Variant == variant)
				{
					return Quality == quality;
				}
				return false;
			}

			public bool IsOwnedBy(VisEquipment owner)
			{
				if (!IsUnityNull((Object?)(object)Owner))
				{
					return (Object)(object)Owner == (Object)(object)owner;
				}
				return false;
			}

			public void Add(GameObject? instance)
			{
				if (!IsUnityNull((Object?)(object)instance))
				{
					_instances.Add(instance);
				}
			}

			public void AddRange(IEnumerable<GameObject>? instances)
			{
				if (instances == null)
				{
					return;
				}
				foreach (GameObject instance in instances)
				{
					Add(instance);
				}
			}

			public void AddActiveInstancesTo(List<GameObject> roots)
			{
				foreach (GameObject instance in _instances)
				{
					if (!IsUnityNull((Object?)(object)instance))
					{
						roots.Add(instance);
					}
				}
			}

			public void Destroy()
			{
				foreach (GameObject instance in _instances)
				{
					if (!IsUnityNull((Object?)(object)instance))
					{
						if (!IsUnityNull((Object?)(object)Owner) && !IsUnityNull((Object?)(object)Owner.m_lodGroup))
						{
							Utils.RemoveFromLodgroup(Owner.m_lodGroup, instance);
						}
						Object.Destroy((Object)(object)instance);
					}
				}
				_instances.Clear();
			}
		}

		internal sealed class KeepOnDeathItemState
		{
			public ItemData Item { get; }

			public Vector2i OriginalGridPos { get; }

			public string OriginalSlotId { get; }

			public SlotKind? OriginalSlotKind { get; }

			public bool OriginalEquipped { get; }

			public Dictionary<string, string> OriginalCustomData { get; }

			public bool WasQuickSlot => OriginalSlotKind == SlotKind.Quick;

			public bool WasSpecialSlot => OriginalSlotKind.HasValue;

			public KeepOnDeathItemState(ItemData item, Vector2i originalGridPos, string originalSlotId, SlotKind? originalSlotKind)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				Item = item;
				OriginalGridPos = originalGridPos;
				OriginalSlotId = originalSlotId;
				OriginalSlotKind = originalSlotKind;
				OriginalEquipped = item.m_equipped;
				OriginalCustomData = ((item.m_customData == null) ? new Dictionary<string, string>() : new Dictionary<string, string>(item.m_customData));
			}
		}

		internal sealed class TombStonePreparationState
		{
			public Inventory? SourceInventory { get; }

			public List<KeepOnDeathItemState> KeptItems { get; }

			public bool DeathDropUnequipPrepared { get; }

			public bool DeathDropUnequipCompleted { get; set; }

			public bool Completed { get; set; }

			public TombStonePreparationState(Inventory? sourceInventory, List<KeepOnDeathItemState> keptItems, bool deathDropUnequipPrepared)
			{
				SourceInventory = sourceInventory;
				KeptItems = keptItems;
				DeathDropUnequipPrepared = deathDropUnequipPrepared;
				DeathDropUnequipCompleted = !deathDropUnequipPrepared;
			}
		}

		private sealed class EpicLootPublicApi
		{
			public readonly Func<string, Func<ItemData, bool>, bool>? RegisterSacrificeFilter;

			public readonly Func<string, bool>? UnregisterSacrificeFilter;

			public readonly Action<Player>? InvalidatePlayerEffectCache;

			public readonly Func<GameObject, GameObject, ItemData?, bool, bool>? ApplyMagicItemBackground;

			public readonly Func<ItemData, bool>? IsShardStone;

			public readonly Func<ItemData, bool>? IsMagicCraftingMaterial;

			public EpicLootPublicApi(Type apiType)
			{
				RegisterSacrificeFilter = (Func<string, Func<ItemData, bool>, bool>)CreateDelegate(apiType, "RegisterSacrificeFilter", typeof(bool), typeof(Func<string, Func<ItemData, bool>, bool>), typeof(string), typeof(Func<ItemData, bool>));
				UnregisterSacrificeFilter = (Func<string, bool>)CreateDelegate(apiType, "UnregisterSacrificeFilter", typeof(bool), typeof(Func<string, bool>), typeof(string));
				InvalidatePlayerEffectCache = (Action<Player>)CreateDelegate(apiType, "InvalidatePlayerEffectCache", typeof(void), typeof(Action<Player>), typeof(Player));
				ApplyMagicItemBackground = (Func<GameObject, GameObject, ItemData, bool, bool>)CreateDelegate(apiType, "ApplyMagicItemBackground", typeof(bool), typeof(Func<GameObject, GameObject, ItemData, bool, bool>), typeof(GameObject), typeof(GameObject), typeof(ItemData), typeof(bool));
				IsShardStone = (Func<ItemData, bool>)CreateDelegate(apiType, "IsShardStone", typeof(bool), typeof(Func<ItemData, bool>), typeof(ItemData));
				IsMagicCraftingMaterial = (Func<ItemData, bool>)CreateDelegate(apiType, "IsMagicCraftingMaterial", typeof(bool), typeof(Func<ItemData, bool>), typeof(ItemData));
			}

			private static Delegate? CreateDelegate(Type apiType, string methodName, Type returnType, Type delegateType, params Type[] parameterTypes)
			{
				MethodInfo method = apiType.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public, null, parameterTypes, null);
				if (!(method?.ReturnType == returnType))
				{
					return null;
				}
				return Delegate.CreateDelegate(delegateType, method);
			}
		}

		private sealed class HipLanternApi
		{
			private delegate ItemData? GetLanternDelegate(Humanoid humanoid);

			private delegate ItemData? SetLanternDelegate(Humanoid humanoid, ItemData? item);

			private delegate bool IsLanternDelegate(ItemData item);

			private readonly GetLanternDelegate _getLantern;

			private readonly SetLanternDelegate _setLantern;

			private readonly IsLanternDelegate _isLantern;

			private readonly ConfigEntry<bool> _useUtilitySlot;

			private bool _failed;

			private HipLanternApi(GetLanternDelegate getLantern, SetLanternDelegate setLantern, IsLanternDelegate isLantern, ConfigEntry<bool> useUtilitySlot)
			{
				_getLantern = getLantern;
				_setLantern = setLantern;
				_isLantern = isLantern;
				_useUtilitySlot = useUtilitySlot;
			}

			public static bool TryCreate(Assembly assembly, out HipLanternApi? api, out string detail)
			{
				api = null;
				Type type = assembly.GetType("HipLantern.HumanoidExtension");
				Type type2 = assembly.GetType("HipLantern.LanternItem");
				Type type3 = assembly.GetType("HipLantern.HipLantern");
				MethodInfo methodInfo = type?.GetMethod("GetHipLantern", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Humanoid) }, null);
				MethodInfo methodInfo2 = type?.GetMethod("SetHipLantern", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(Humanoid),
					typeof(ItemData)
				}, null);
				MethodInfo methodInfo3 = type2?.GetMethod("IsLanternItem", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
				FieldInfo fieldInfo = type3?.GetField("itemSlotUtility", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (methodInfo?.ReturnType != typeof(ItemData) || methodInfo2?.ReturnType != typeof(ItemData) || methodInfo3?.ReturnType != typeof(bool) || fieldInfo == null || !typeof(ConfigEntryBase).IsAssignableFrom(fieldInfo.FieldType))
				{
					detail = "expected HumanoidExtension, LanternItem, or itemSlotUtility members were not found";
					return false;
				}
				try
				{
					if (!(fieldInfo.GetValue(null) is ConfigEntry<bool> useUtilitySlot))
					{
						detail = "itemSlotUtility was not initialized";
						return false;
					}
					api = new HipLanternApi((GetLanternDelegate)Delegate.CreateDelegate(typeof(GetLanternDelegate), methodInfo), (SetLanternDelegate)Delegate.CreateDelegate(typeof(SetLanternDelegate), methodInfo2), (IsLanternDelegate)Delegate.CreateDelegate(typeof(IsLanternDelegate), methodInfo3), useUtilitySlot);
					detail = "";
					return true;
				}
				catch (Exception ex)
				{
					detail = "failed to bind HipLantern delegates: " + ex.Message;
					return false;
				}
			}

			public bool TryGetUseUtilitySlot(out bool useUtilitySlot)
			{
				useUtilitySlot = true;
				if (_failed)
				{
					return false;
				}
				try
				{
					useUtilitySlot = _useUtilitySlot.Value;
					return true;
				}
				catch (Exception exception)
				{
					return Fail("reading itemSlotUtility", exception);
				}
			}

			public bool TryIsLanternItem(ItemData item, out bool isLantern)
			{
				isLantern = false;
				if (_failed)
				{
					return false;
				}
				try
				{
					isLantern = _isLantern(item);
					return true;
				}
				catch (Exception exception)
				{
					return Fail("checking the HipLantern item type", exception);
				}
			}

			public bool TrySetLantern(Humanoid humanoid, ItemData item, out bool changed)
			{
				changed = false;
				if (!TryGetLantern(humanoid, out ItemData item2))
				{
					return false;
				}
				if (item2 == item)
				{
					return true;
				}
				return TrySetLanternValue(humanoid, item, out changed);
			}

			public bool TryIsCurrentLantern(Humanoid humanoid, ItemData item, out bool isCurrent)
			{
				isCurrent = false;
				if (!TryGetLantern(humanoid, out ItemData item2))
				{
					return false;
				}
				isCurrent = item2 == item;
				return true;
			}

			public bool TryClearLantern(Humanoid humanoid, ItemData item, out bool changed)
			{
				changed = false;
				if (!TryGetLantern(humanoid, out ItemData item2))
				{
					return false;
				}
				if (item2 != item)
				{
					return true;
				}
				return TrySetLanternValue(humanoid, null, out changed);
			}

			public bool TryGetLantern(Humanoid humanoid, out ItemData? item)
			{
				item = null;
				if (_failed)
				{
					return false;
				}
				try
				{
					item = _getLantern(humanoid);
					return true;
				}
				catch (Exception exception)
				{
					return Fail("reading the equipped HipLantern", exception);
				}
			}

			private bool TrySetLanternValue(Humanoid humanoid, ItemData? item, out bool changed)
			{
				changed = false;
				if (_failed)
				{
					return false;
				}
				try
				{
					if (_setLantern(humanoid, item) != item)
					{
						return Fail("SetHipLantern returned an unexpected item");
					}
					changed = true;
					return true;
				}
				catch (Exception exception)
				{
					return Fail("updating the equipped HipLantern", exception);
				}
			}

			private bool Fail(string operation, Exception? exception = null)
			{
				if (!_failed)
				{
					string text = exception?.InnerException?.Message ?? exception?.Message ?? "unknown result";
					Log.LogWarning((object)("HipLantern compatibility disabled while " + operation + ": " + text));
				}
				_failed = true;
				return false;
			}
		}

		private sealed class InventoryHoverTooltipRuntimeState
		{
			public GameObject? HoverTooltip;

			public RectTransform? HoverTooltipPanel;

			public TMP_Text? HoverTooltipTopic;

			public TMP_Text? HoverTooltipText;

			public readonly ScrollableTooltipBodyState HoverTooltipTextScroll = new ScrollableTooltipBodyState();

			public readonly TooltipSourceCacheCore<UITooltip, InventoryHoverTooltipItemSource> HoverTooltipItems = new TooltipSourceCacheCore<UITooltip, InventoryHoverTooltipItemSource>(64);

			public string HoverTooltipSignature = "";

			public string HoverTooltipLayoutSignature = "";

			public float HoverTooltipScrollOffset;

			public float HoverTooltipMaxScroll;

			public bool HoverTooltipNeedsScroll;

			public RectTransform? HoverJewelcraftingTooltipRoot;

			public string HoverJewelcraftingTooltipSignature = "";

			public int HoverJewelcraftingTooltipLayoutRefreshFrames;

			public GameObject? SimpleNameTooltip;

			public RectTransform? SimpleNameTooltipRect;

			public TMP_Text? SimpleNameTooltipText;

			public string SimpleNameTooltipValue = "";

			public SimpleNameTooltipPlacement SimpleNameTooltipPlacement;

			public readonly SimpleTooltipOwnershipCore SimpleNameTooltipOwner = new SimpleTooltipOwnershipCore();

			public readonly object SimpleNameTooltipFallbackOwner = new object();

			public object? PinnedGemNameTooltipOwner;

			public float PinnedGemNameTooltipHoldUntil = -1000f;

			public UITooltip? ContainerHoverTooltipSource;

			public UITooltip? OwnedHoverTooltipSource;

			public bool LateUpdateExceptionLogged;
		}

		private enum SimpleNameTooltipPlacement
		{
			RightOfCursor,
			LeftOfCursor
		}

		private readonly struct InventoryHoverTooltipItemSource
		{
			public InventoryGrid? Grid { get; }

			public ItemData Item { get; }

			public InventoryHoverTooltipItemSource(InventoryGrid? grid, ItemData item)
			{
				Grid = grid;
				Item = item;
			}
		}

		private sealed class NativeInventoryRows
		{
			public int Rows = 4;

			public bool Loaded;
		}

		private readonly struct PlayerInventoryPanelBackgroundSnapshot
		{
			public bool ActiveSelf { get; }

			public bool ImageEnabled { get; }

			public Sprite? Sprite { get; }

			public Type Type { get; }

			public float PixelsPerUnitMultiplier { get; }

			public Material? Material { get; }

			public Color Color { get; }

			public Vector2 AnchorMax { get; }

			public Vector2 Pivot { get; }

			public Vector2 OffsetMin { get; }

			public Vector2 OffsetMax { get; }

			public Vector2 AnchoredPosition { get; }

			public Vector2 SizeDelta { get; }

			public Vector3 LocalScale { get; }

			public Quaternion LocalRotation { get; }

			public PlayerInventoryPanelBackgroundSnapshot(bool activeSelf, bool imageEnabled, Sprite? sprite, Type type, float pixelsPerUnitMultiplier, Material? material, Color color, Vector2 anchorMax, Vector2 pivot, Vector2 offsetMin, Vector2 offsetMax, Vector2 anchoredPosition, Vector2 sizeDelta, Vector3 localScale, Quaternion localRotation)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: 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_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: 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_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				ActiveSelf = activeSelf;
				ImageEnabled = imageEnabled;
				Sprite = sprite;
				Type = type;
				PixelsPerUnitMultiplier = pixelsPerUnitMultiplier;
				Material = material;
				Color = color;
				AnchorMax = anchorMax;
				Pivot = pivot;
				OffsetMin = offsetMin;
				OffsetMax = offsetMax;
				AnchoredPosition = anchoredPosition;
				SizeDelta = sizeDelta;
				LocalScale = localScale;
				LocalRotation = localRotation;
			}
		}

		internal enum InventoryStateEnsureReason
		{
			Unknown,
			PeriodicAudit,
			PlayerAwake,
			PlayerSpawned,
			PlayerLoad,
			PlayerSave,
			InventoryChanged,
			EquipmentChanged,
			InventoryLoad,
			InventoryMove,
			Tombstone,
			GuiShow,
			SlotAction,
			BackupRestore,
			YamlReload,
			JewelcraftingSlotRefresh,
			ProgressionReset,
			ConfigChanged,
			ReentrantFollowUp
		}

		internal enum InventoryStateAuditLevel
		{
			None,
			HeightOnly,
			SlotLight,
			FullIntegrity
		}

		private sealed class InventoryPanelRuntimeState
		{
			public readonly Dictionary<int, RectTransform> CustomSlotPanels = new Dictionary<int, RectTransform>();

			public readonly Dictionary<int, RectTransform> QuickSlotPanels = new Dictionary<int, RectTransform>();

			public readonly List<MovedPlayerStatPanel> MovedPlayerStatPanels = new List<MovedPlayerStatPanel>();

			public readonly Dictionary<int, Vector3> QuickSlotPanelOutroStartPositions = new Dictionary<int, Vector3>();

			public readonly Dictionary<int, GameObject> FavoriteKeyHintObjects = new Dictionary<int, GameObject>();

			public readonly Dictionary<int, GameObject> PinnedTooltipKeyHintObjects = new Dictionary<int, GameObject>();

			public RectTransform? QuickSlotsHotkeyBarRect;

			public HotkeyBar? QuickSlotsHotkeyBar;

			public RectTransform? PlayerStatPanelHost;

			public RectTransform? InventorySortPanel;

			public RectTransform? CurrencyPocketPanel;

			public Button? ContainerRestockButton;

			public Button? ContainerStoreAllButton;

			public Button? ContainerSortButton;

			public RectTransformSnapshot? TakeAllButtonOriginal;

			public RectTransformSnapshot? StackAllButtonOriginal;

			public RectTransform? TrackedContainerPanel;

			public RectTransform? TrackedContainerWeightPanel;

			public Vector3 ContainerPanelBasePosition;

			public Vector3 ContainerPanelAppliedOffset;

			public Vector3 ContainerWeightPanelBasePosition;

			public float ContainerWeightPanelAppliedYOffset;

			public RectTransform? DraggedInventoryPanel;

			public Vector2 InventoryPanelDragStartLocalMouse;

			public Vector2 InventoryPanelDragStartOffset;

			public bool ContainerPanelBasePositionSet;

			public bool ContainerWeightPanelBasePositionSet;

			public bool DraggingQuickSlotsPanelOffset;

			public bool DraggingEquipmentSlotsPanelOffset;

			public Vector2 EquipmentSlotsPanelRuntimeOffset = EquipmentSlotsPanelFixedOffset;

			public Vector2 QuickSlotsPanelRuntimeOffset = QuickSlotsPanelFixedOffset;

			public int LastExpandableInventoryRows = 4;

			public float QuickSlotPanelIntroStartTime = -1f;

			public float QuickSlotPanelIntroDuration = 0.25f;

			public float QuickSlotPanelOutroStartTime = -1f;

			public float QuickSlotPanelOutroDuration = 0.25f;

			public float QuickSlotHudElementSpace = 70f;

			public readonly ContainerHoldActionState ContainerRestockHold = new ContainerHoldActionState();

			public readonly ContainerHoldActionState ContainerQuickStackHold = new ContainerHoldActionState();

			public bool QuickSlotPanelIntroActive;

			public bool QuickSlotPanelOutroActive;

			public bool QuickSlotHudAnchorValid;

			public bool LastExpandableInventoryRowsLoaded;

			public Vector3 QuickSlotHudAnchoredPosition;
		}

		private sealed class ContainerHoldActionState
		{
			public Container? Container;

			public float StartTime = -1f;

			public bool Triggered;
		}

		private sealed class InventorySafetyRuntimeState
		{
			public readonly Dictionary<ItemData, PendingSlotEquip> PendingSlotEquips = new Dictionary<ItemData, PendingSlotEquip>();

			public readonly Dictionary<ItemData, PendingSlotUnequip> PendingSlotUnequips = new Dictionary<ItemData, PendingSlotUnequip>();

			public readonly Dictionary<Inventory, int> LoadPreservationInventoryDepth = new Dictionary<Inventory, int>();

			public readonly Stack<ItemData?> InventoryAddItemDataStackLookupItems = new Stack<ItemData>();

			public readonly HashSet<string> SlotRecoveryWarnings = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> ForeignSlotPreservationWarnings = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<ItemData, float> SlotUnequipToInventoryRequests = new Dictionary<ItemData, float>();

			public bool RoutingEquipToDedicatedSlot;

			public bool RestoringSlotBackup;

			public bool EnsuringInventoryState;

			public InventoryStateEnsureReason PendingEnsureReason;

			public InventoryStateAuditLevel PendingAuditLevel;

			public InventoryStateEnsureReason DeferredEnsureReason;

			public InventoryStateAuditLevel DeferredAuditLevel;

			public int DeferredEnsureFrame = -1;

			public float HeavyAuditDelayUntil = -1f;

			public int LastFullIntegrityAuditSignature = int.MinValue;

			public int LastSlotLightProjectionSignature = int.MinValue;

			public int InventoryPlacementCacheVersion;

			public Inventory? UsableRegularEmptyCellCacheInventory;

			public int UsableRegularEmptyCellCacheVersion = -1;

			public int UsableRegularEmptyCellCacheContext;

			public int UsableRegularEmptyCellCacheCount;

			public Inventory? DedicatedSlotRouteFailureCacheInventory;

			public int DedicatedSlotRouteFailureCacheVersion = -1;

			public int DedicatedSlotRouteFailureCacheContext;

			public int DedicatedSlotRouteFailureCacheItemKey;

			public Inventory? CanAddItemFailureCacheInventory;

			public int CanAddItemFailureCacheVersion = -1;

			public int CanAddItemFailureCacheContext;

			public int CanAddItemFailureCacheItemKey;

			public int CanAddItemFailureCacheRequestedStack;

			public Inventory? InventoryLimitCountCacheInventory;

			public int InventoryLimitCountCachePlacementVersion = -1;

			public int InventoryLimitCountCacheRuleVersion = -1;

			public readonly Dictionary<string, long> InventoryLimitCountCache = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);

			public string LastInventoryLimitMessageKey = "";

			public float LastInventoryLimitMessageTime = -1f;

			public bool SlotUnequipInProgress;

			public int SlotAutoEquipSuppressionDepth;

			public bool SuppressKnownItemRediscovery;

			public bool HandlingSlotDropOutside;

			public bool SuppressSlotAutoEquip => SlotAutoEquipSuppressionDepth > 0;
		}

		private sealed class InventoryContainerRuntimeState
		{
			public readonly List<Container> KnownContainers = new List<Container>();
		}

		private sealed class InventoryDefinitionRuntimeState
		{
			public readonly List<SlotDefinition> SlotDefinitions = new List<SlotDefinition>();

			public readonly List<SlotDefinition> CustomPanelSlotCache = new List<SlotDefinition>();

			public readonly List<SlotDefinition> VisibleCustomPanelSlotCache = new List<SlotDefinition>();

			public readonly List<SlotDefinition> QuickPanelSlotCache = new List<SlotDefinition>();

			public readonly Dictionary<int, SlotDefinition> QuickSlotDefinitionCache = new Dictionary<int, SlotDefinition>();

			public readonly Dictionary<string, bool> EquipmentSlotUnlockCache = new Dictionary<string, bool>(StringComparer.Ordinal);

			public readonly Dictionary<string, List<string>> PredefinedGroupDefinitions = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);

			public readonly List<string> PredefinedGroupOrder = new List<string>();

			public readonly Dictionary<string, List<string>> PredefinedGroupOrders = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, int> InventoryLimits = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, int> ResourceTierByToken = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> CookingStationInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> CraftingRecipeFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> CookingStationFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> FermenterInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> FermenterOutputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> FermenterFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, string> ItemNameTokens = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

			public Dictionary<string, int> RestockTargetStackLimits = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

			public int SlotDefinitionVersion;

			public int InventoryLimitVersion;

			public int CustomPanelSlotCacheVersion = -1;

			public int VisibleCustomPanelSlotCacheVersion = -1;

			public string VisibleCustomPanelSlotCacheSignature = "";

			public string EquipmentSlotUnlockCacheSignature = "";

			public int QuickPanelSlotCacheVersion = -1;

			public int QuickPanelSlotCacheUnlockedCount = -1;

			public int QuickSlotDefinitionCacheVersion = -1;

			public int CachedObjectDbItemCount = -1;

			public int CachedStationInputObjectDbItemCount = -1;

			public int CachedStationInputPrefabCount = -1;

			public int CachedStationInputRecipeCount = -1;

			public bool StationInputTokensInitialized;
		}

		private sealed class InventoryClientRuntimeState
		{
			public bool ClientStateLoaded;

			public string LoadedFavoritesPlayerId = "";

			public InventorySlotsClientState ClientState = new InventorySlotsClientState();

			public readonly HashSet<Vector2i> FavoriteSlots = new HashSet<Vector2i>();
		}

		private sealed class EquipmentVisualRuntimeState
		{
			public readonly Dictionary<string, CustomEquipmentVisual> Visuals = new Dictionary<string, CustomEquipmentVisual>(StringComparer.Ordinal);

			public readonly HashSet<StatusEffect> StatusEffects = new HashSet<StatusEffect>();

			public readonly Dictionary<StatusEffect, int> StatusEffectLevels = new Dictionary<StatusEffect, int>();

			public int LocalPlayerUpdateFrame = -1;

			public int LocalPlayerUpdateSignature = int.MinValue;

			public int LocalPlayerUpdateStateCount;
		}

		private sealed class InventorySortRuntimeState
		{
			public readonly Dictionary<string, Recipe> RecipeOutputLookupCache = new Dictionary<string, Recipe>(StringComparer.OrdinalIgnoreCase);

			public string RecipeOutputLookupSignature = "";
		}

		private sealed class ItemClassification
		{
			public readonly Dictionary<string, bool> BuiltInGroupMatches = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);

			public bool BigGroupResolved;

			public string BigGroupId = "";
		}

		private sealed class ItemClassifierRuntimeState
		{
			public readonly Dictionary<string, ItemClassification> Cache = new Dictionary<string, ItemClassification>(StringComparer.OrdinalIgnoreCase);

			public readonly HashSet<string> FeastMaterialTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public string FeastMaterialSignature = "";

			public int Version;

			public int AppliedVersion = -1;
		}

		private sealed class ItemRequiresSkillLevelApi
		{
			private readonly MethodInfo _tryGetReqForItemMethod;

			private readonly MethodInfo _tryGetReqForPrefabNameMethod;

			private readonly MethodInfo _getTextEquipMethod;

			private readonly MethodInfo _getTextCraftMethod;

			private ItemRequiresSkillLevelApi(MethodInfo tryGetReqForItemMethod, MethodInfo tryGetReqForPrefabNameMethod, MethodInfo getTextEquipMethod, MethodInfo getTextCraftMethod)
			{
				_tryGetReqForItemMethod = tryGetReqForItemMethod;
				_tryGetReqForPrefabNameMethod = tryGetReqForPrefabNameMethod;
				_getTextEquipMethod = getTextEquipMethod;
				_getTextCraftMethod = getTextCraftMethod;
			}

			public static bool TryCreate(Assembly assembly, out ItemRequiresSkillLevelApi? api, out string detail)
			{
				api = null;
				Type? type = assembly.GetType("ItemRequiresSkillLevel.Patches");
				MethodInfo methodInfo = type?.GetMethod("TryGetReqForItem", BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo methodInfo2 = type?.GetMethod("TryGetReqForPrefabName", BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo methodInfo3 = type?.GetMethod("GetTextEquip", BindingFlags.Static | BindingFlags.Public);
				MethodInfo methodInfo4 = type?.GetMethod("GetTextCraft", BindingFlags.Static | BindingFlags.Public);
				if (type == null || methodInfo == null || methodInfo2 == null || methodInfo3 == null || methodInfo4 == null)
				{
					detail = "ItemRequiresSkillLevel tooltip methods were not found";
					return false;
				}
				api = new ItemRequiresSkillLevelApi(methodInfo, methodInfo2, methodInfo3, methodInfo4);
				detail = "";
				return true;
			}

			public string GetTooltipText(ItemData? item, string? prefabName, bool includeEquip, bool includeCraft)
			{
				if (!includeEquip && !includeCraft)
				{
					return "";
				}
				if (!TryGetRequirement(item, prefabName, out object requirement) || requirement == null)
				{
					return "";
				}
				StringBuilder stringBuilder = new StringBuilder();
				if (includeEquip)
				{
					stringBuilder.Append(GetText(_getTextEquipMethod, requirement));
				}
				if (includeCraft)
				{
					stringBuilder.Append(GetText(_getTextCraftMethod, requirement));
				}
				return stringBuilder.ToString();
			}

			private bool TryGetRequirement(ItemData? item, string? prefabName, out object? requirement)
			{
				requirement = null;
				if (item != null && TryGetRequirementForItem(item, out requirement))
				{
					return true;
				}
				if (!string.IsNullOrWhiteSpace(prefabName))
				{
					return TryGetRequirementForPrefabName(prefabName, out requirement);
				}
				return false;
			}

			private bool TryGetRequirementForItem(ItemData item, out object? requirement)
			{
				requirement = null;
				try
				{
					object[] array = new object[2] { item, null };
					object obj = _tryGetReqForItemMethod.Invoke(null, array);
					bool num = obj is bool && (bool)obj;
					requirement = array[1];
					return num && requirement != null;
				}
				catch
				{
					requirement = null;
					return false;
				}
			}

			private bool TryGetRequirementForPrefabName(string prefabName, out object? requirement)
			{
				requirement = null;
				try
				{
					object[] array = new object[2] { prefabName, null };
					object obj = _tryGetReqForPrefabNameMethod.Invoke(null, array);
					bool num = obj is bool && (bool)obj;
					requirement = array[1];
					return num && requirement != null;
				}
				catch
				{
					requirement = null;
					return false;
				}
			}

			private static string GetText(MethodInfo method, object requirement)
			{
				try
				{
					return (method.Invoke(null, new object[1] { requirement }) as string) ?? "";
				}
				catch
				{
					return "";
				}
			}
		}

		private sealed class JewelcraftingCraftingSocketUiApi
		{
			private readonly FieldInfo _socketIconsField;

			private readonly FieldInfo? _socketingButtonField;

			private readonly FieldInfo? _socketTabField;

			private readonly FieldInfo? _socketCostField;

			private readonly MethodInfo? _socketTabOpenMethod;

			private JewelcraftingCraftingSocketUiApi(FieldInfo socketIconsField, FieldInfo? socketingButtonField, FieldInfo? socketTabField, FieldInfo? socketCostField, MethodInfo? socketTabOpenMethod)
			{
				_socketIconsField = socketIconsField;
				_socketingButtonField = socketingButtonField;
				_socketTabField = socketTabField;
				_socketCostField = socketCostField;
				_socketTabOpenMethod = socketTabOpenMethod;
			}

			public static bool TryCreate(Assembly assembly, out JewelcraftingCraftingSocketUiApi? api, out string detail)
			{
				api = null;
				Type type = assembly.GetType("Jewelcrafting.GemStones+AddSocketIcons");
				Type type2 = assembly.GetType("Jewelcrafting.GemStones+AddSocketAddingTab");
				Type type3 = assembly.GetType("Jewelcrafting.Jewelcrafting");
				FieldInfo fieldInfo = type?.GetField("socketIcons", BindingFlags.Static | BindingFlags.Public);
				if (fieldInfo == null)
				{
					detail = "AddSocketIcons.socketIcons was not found";
					return false;
				}
				api = new JewelcraftingCraftingSocketUiApi(fieldInfo, type?.GetField("socketingButton", BindingFlags.Static | BindingFlags.Public), type2?.GetField("tab", BindingFlags.Static | BindingFlags.Public), type3?.GetField("socketCost", BindingFlags.Static | BindingFlags.Public), type2?.GetMethod("TabOpen", BindingFlags.Static | BindingFlags.Public));
				detail = "";
				return true;
			}

			public Array? GetSocketIcons()
			{
				return _socketIconsField.GetValue(null) as Array;
			}

			public Button? GetSocketingButton()
			{
				object? obj = _socketingButtonField?.GetValue(null);
				return (Button?)((obj is Button) ? obj : null);
			}

			public Transform? GetSocketTab()
			{
				object? obj = _socketTabField?.GetValue(null);
				return (Transform?)((obj is Transform) ? obj : null);
			}

			public string GetSocketCostMode()
			{
				try
				{
					object? obj = _socketCostField?.GetValue(null);
					ConfigEntryBase val = (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null);
					return (val == null) ? "" : (val.BoxedValue?.ToString() ?? "");
				}
				catch
				{
					return "";
				}
			}

			public bool IsSocketTabOpen()
			{
				try
				{
					object obj = _socketTabOpenMethod?.Invoke(null, null);
					return obj is bool && (bool)obj;
				}
				catch
				{
					return false;
				}
			}
		}

		private enum JewelcraftingSocketTabState
		{
			Unavailable,
			PrimaryCraftingTab,
			Closed,
			Selected
		}

		private sealed class JewelcraftingEffectApi
		{
			private readonly MethodInfo _calculateEffectsMethod;

			private bool _warningLogged;

			private JewelcraftingEffectApi(MethodInfo calculateEffectsMethod)
			{
				_calculateEffectsMethod = calculateEffectsMethod;
			}

			public static bool TryCreate(Assembly assembly, out JewelcraftingEffectApi? api, out string detail)
			{
				api = null;
				MethodInfo methodInfo = assembly.GetType("Jewelcrafting.GemEffects.TrackEquipmentChanges")?.GetMethod("CalculateEffects", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Player) }, null);
				if (methodInfo == null)
				{
					detail = "TrackEquipmentChanges.CalculateEffects(Player) was not found";
					return false;
				}
				api = new JewelcraftingEffectApi(methodInfo);
				detail = "";
				return true;
			}

			public void Recalculate(Player player)
			{
				if ((Object)(object)player == (Object)null || IsUnityNull((Object?)(object)player))
				{
					return;
				}
				try
				{
					_calculateEffectsMethod.Invoke(null, new object[1] { player });
				}
				catch (Exception ex)
				{
					if (!_warningLogged)
					{
						_warningLogged = true;
						Log.LogWarning((object)("Failed to recalculate Jewelcrafting equipment effects: " + ex.GetBaseException().Message));
					}
				}
			}
		}

		private sealed class JewelcraftingGemApi
		{
			private readonly MethodInfo _getGemsMethod;

			private readonly MethodInfo? _itemDataMethod;

			private readonly MethodInfo? _itemInfoGetSocketableMethod;

			private readonly MethodInfo? _itemInfoGetItemContainerMethod;

			private readonly FieldInfo? _socketedGemsField;

			private readonly FieldInfo? _socketNameField;

			private readonly FieldInfo? _socketSeedField;

			private readonly FieldInfo? _openEquipmentField;

			private readonly FieldInfo? _openInventoryField;

			private readonly MethodInfo? _openSocketContainerMethod;

			private readonly FieldInfo? _inventoryInteractBehaviourField;

			private readonly FieldInfo? _inventorySocketingField;

			private readonly Type? _itemBagType;

			private readonly PropertyInfo? _itemInfoItemDataProperty;

			private readonly MethodInfo? _itemInfoGetAllSocketSeedsMethod;

			private readonly PropertyInfo? _socketSeedSeedProperty;

			private readonly Dictionary<Type, MemberInfo?> _gemSpriteMembers = new Dictionary<Type, MemberInfo>();

			private readonly Dictionary<Type, MemberInfo?> _gemPrefabMembers = new Dictionary<Type, MemberInfo>();

			private JewelcraftingGemApi(MethodInfo getGemsMethod, MethodInfo? itemDataMethod, MethodInfo? itemInfoGetSocketableMethod, MethodInfo? itemInfoGetItemContainerMethod, FieldInfo? socketedGemsField, FieldInfo? socketNameField, FieldInfo? socketSeedField, FieldInfo? openEquipmentField, FieldInfo? openInventoryField, MethodInfo? openSocketContainerMethod, FieldInfo? inventoryInteractBehaviourField, FieldInfo? inventorySocketingField, Type? itemBagType, PropertyInfo? itemInfoItemDataProperty, MethodInfo? itemInfoGetAllSocketSeedsMethod, PropertyInfo? socketSeedSeedProperty)
			{
				_getGemsMethod = getGemsMethod;
				_itemDataMethod = itemDataMethod;
				_itemInfoGetSocketableMethod = itemInfoGetSocketableMethod;
				_itemInfoGetItemContainerMethod = itemInfoGetItemContainerMethod;
				_socketedGemsField = socketedGemsField;
				_socketNameField = socketNameField;
				_socketSeedField = socketSeedField;
				_openEquipmentField = openEquipmentField;
				_openInventoryField = openInventoryField;
				_openSocketContainerMethod = openSocketContainerMethod;
				_inventoryInteractBehaviourField = inventoryInteractBehaviourField;
				_inventorySocketingField = inventorySocketingField;
				_itemBagType = itemBagType;
				_itemInfoItemDataProperty = itemInfoItemDataProperty;
				_itemInfoGetAllSocketSeedsMethod = itemInfoGetAllSocketSeedsMethod;
				_socketSeedSeedProperty = socketSeedSeedProperty;
			}

			public static bool TryCreate(Assembly assembly, out JewelcraftingGemApi? api, out string detail)
			{
				api = null;
				MethodInfo methodInfo = assembly.GetType("Jewelcrafting.API")?.GetMethod("GetGems", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null);
				if (methodInfo == null)
				{
					detail = "API.GetGems was not found";
					return false;
				}
				Type? type = assembly.GetType("ItemDataManager.ItemExtensions");
				Type type2 = assembly.GetType("ItemDataManager.ItemInfo");
				Type type3 = assembly.GetType("Jewelcrafting.Socketable");
				Type type4 = assembly.GetType("Jewelcrafting.ItemContainer");
				Type type5 = assembly.GetType("Jewelcrafting.ItemBag");
				Type type6 = assembly.GetType("Jewelcrafting.SocketItem");
				Type type7 = assembly.GetType("Jewelcrafting.Jewelcrafting");
				Type type8 = assembly.GetType("Jewelcrafting.GemStones+AddFakeSocketsContainer");
				Type type9 = assembly.GetType("Jewelcrafting.GemStones+OpenFakeSocketsContainer");
				Type type10 = assembly.GetType("Jewelcrafting.SocketSeed");
				MethodInfo itemDataMethod = type?.GetMethod("Data", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null);
				MethodInfo itemInfoGetAllSocketSeedsMethod = null;
				MethodInfo itemInfoGetSocketableMethod = nul