Decompiled source of HotDeposit v1.0.2

HotDeposit.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("HotDeposit")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("HotDeposit")]
[assembly: AssemblyTitle("HotDeposit")]
[assembly: AssemblyVersion("1.0.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 HotDeposit
{
	[BepInPlugin("Moopfam.HotDeposit", "HotDeposit", "1.0.2")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class InputVisibilityProbe
		{
			internal MethodInfo Method;

			internal PropertyInfo Property;

			internal FieldInfo InstanceField;

			internal PropertyInfo InstanceProperty;

			internal bool Check()
			{
				try
				{
					MethodInfo methodInfo = ((Property != null) ? Property.GetGetMethod(nonPublic: true) : null);
					bool flag = ((Method != null) ? Method.IsStatic : (methodInfo != null && methodInfo.IsStatic));
					object obj = null;
					if (!flag)
					{
						if (InstanceField != null)
						{
							obj = InstanceField.GetValue(null);
						}
						else if (InstanceProperty != null)
						{
							obj = InstanceProperty.GetValue(null, null);
						}
						if (obj == null)
						{
							return false;
						}
					}
					object obj2 = ((Method != null) ? Method.Invoke(obj, null) : Property.GetValue(obj, null));
					return obj2 is bool && (bool)obj2;
				}
				catch
				{
					return false;
				}
			}
		}

		private sealed class PlayerDepositItem
		{
			internal ItemData Item;

			internal string ItemKey;

			internal string DisplayName;
		}

		private sealed class RegisteredContainer
		{
			internal Container Container;

			internal int InstanceId;

			internal Piece Piece;

			internal bool IsTombStone;

			internal bool MetadataInitialized;

			internal bool PlayerBuiltConfirmed;

			internal Inventory Inventory;

			internal Vector3 CachedPosition;

			internal bool IsDynamic;

			internal int CellX;

			internal int CellZ;
		}

		private sealed class ItemGridPositionComparer : IComparer<ItemData>
		{
			internal static readonly ItemGridPositionComparer Instance = new ItemGridPositionComparer();

			public int Compare(ItemData x, ItemData y)
			{
				return CompareItemGridPosition(x, y);
			}
		}

		private sealed class ContainerTarget
		{
			internal Container Container;

			internal Inventory Inventory;

			internal float DistanceSq;

			internal int OwnershipState;

			internal Dictionary<string, List<ItemData>> ItemStacksByKey;
		}

		public const string PluginGuid = "Moopfam.HotDeposit";

		public const string PluginName = "HotDeposit";

		public const string PluginVersion = "1.0.2";

		internal const string LockDataKey = "Moopfam.HotDeposit.Locked";

		internal const string LockIconObjectName = "HotDepositLockIcon";

		private const string VanillaInventoryRowsKey = "invrows";

		private const int VanillaInventoryBaseRows = 4;

		private const int VanillaInventoryMaxRows = 9;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> EnableKeyBinds;

		internal static ConfigEntry<KeyCode> AllDepositKey;

		internal static ConfigEntry<KeyCode> HoveredChestKey;

		internal static ConfigEntry<KeyboardShortcut> LockKeybind;

		internal static ConfigEntry<float> DepositDistance;

		internal static ConfigEntry<bool> IgnoreHotbar;

		internal static ConfigEntry<bool> IgnoreEquipped;

		internal static ConfigEntry<bool> HoveredChestDepositAll;

		internal static ConfigEntry<bool> ShowHoverPrompt;

		internal static ConfigEntry<bool> ShowLockIcon;

		internal static ConfigEntry<bool> ShowDepositPopup;

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private static readonly MethodInfo ContainerGetInventoryMethod = AccessTools.Method(typeof(Container), "GetInventory", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo ContainerCheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null);

		private static readonly MethodInfo ContainerIsInUseMethod = AccessTools.Method(typeof(Container), "IsInUse", Type.EmptyTypes, (Type[])null);

		private static readonly FieldInfo ContainerNViewField = AccessTools.Field(typeof(Container), "m_nview");

		private static readonly MethodInfo ZNetViewIsOwnerMethod = AccessTools.Method(typeof(ZNetView), "IsOwner", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo ZNetViewClaimOwnershipMethod = AccessTools.Method(typeof(ZNetView), "ClaimOwnership", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo InventoryGetAllItemsMethod = AccessTools.Method(typeof(Inventory), "GetAllItems", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo InventoryMoveItemToThisMethod = AccessTools.Method(typeof(Inventory), "MoveItemToThis", new Type[2]
		{
			typeof(Inventory),
			typeof(ItemData)
		}, (Type[])null);

		private static readonly MethodInfo InventoryChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		private static readonly MethodInfo InventoryFindFreeStackItemMethod = AccessTools.Method(typeof(Inventory), "FindFreeStackItem", new Type[3]
		{
			typeof(string),
			typeof(int),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo InventoryFindEmptySlotMethod = AccessTools.Method(typeof(Inventory), "FindEmptySlot", new Type[1] { typeof(bool) }, (Type[])null);

		private static readonly MethodInfo InventoryTopFirstMethod = AccessTools.Method(typeof(Inventory), "TopFirst", new Type[1] { typeof(ItemData) }, (Type[])null);

		private static readonly FieldInfo ItemStackField = AccessTools.Field(typeof(ItemData), "m_stack");

		private static readonly FieldInfo ItemEquippedField = AccessTools.Field(typeof(ItemData), "m_equipped");

		private static readonly FieldInfo ItemGridPosField = AccessTools.Field(typeof(ItemData), "m_gridPos");

		private static readonly FieldInfo ItemDropPrefabField = AccessTools.Field(typeof(ItemData), "m_dropPrefab");

		private static readonly FieldInfo ItemSharedField = AccessTools.Field(typeof(ItemData), "m_shared");

		private static readonly FieldInfo ItemCustomDataField = AccessTools.Field(typeof(ItemData), "m_customData");

		private static readonly FieldInfo InventoryGridElementsField = AccessTools.Field(typeof(InventoryGrid), "m_elements");

		private static readonly FieldInfo InventoryGridInventoryField = AccessTools.Field(typeof(InventoryGrid), "m_inventory");

		private static readonly MethodInfo InventoryGetWidthMethod = AccessTools.Method(typeof(Inventory), "GetWidth", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo InventoryGetItemAtMethod = AccessTools.Method(typeof(Inventory), "GetItemAt", new Type[2]
		{
			typeof(int),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo PlayerGetHoverObjectMethod = AccessTools.Method(typeof(Player), "GetHoverObject", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo PieceGetCreatorMethod = AccessTools.Method(typeof(Piece), "GetCreator", Type.EmptyTypes, (Type[])null);

		private static Sprite _lockSprite;

		private static bool _modCompatibilityInitialized;

		private static bool _supportedSlotModLoaded;

		private static readonly List<MethodInfo> ModProtectionBoolMethods = new List<MethodInfo>();

		private static readonly List<MethodInfo> ModProtectionItemListMethods = new List<MethodInfo>();

		private static readonly List<InputVisibilityProbe> InputVisibilityProbes = new List<InputVisibilityProbe>();

		private static readonly List<RegisteredContainer> ContainerRegistry = new List<RegisteredContainer>();

		private static readonly Dictionary<int, RegisteredContainer> ContainerRegistryById = new Dictionary<int, RegisteredContainer>();

		private const float ContainerSpatialCellSize = 32f;

		private static readonly Dictionary<long, List<RegisteredContainer>> StaticContainerBuckets = new Dictionary<long, List<RegisteredContainer>>();

		private static readonly List<RegisteredContainer> DynamicContainers = new List<RegisteredContainer>();

		private static readonly Type RigidbodyType = AccessTools.TypeByName("UnityEngine.Rigidbody");

		private static bool _containerRegistrySeeded;

		private void Awake()
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "Enabled", true, "Enable or disable HotDeposit.");
			EnableKeyBinds = ((BaseUnityPlugin)this).Config.Bind<bool>("02 - Hotkeys", "EnableKeyBinds", true, "Enable or disable all HotDeposit keyboard/mouse shortcuts.");
			AllDepositKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("02 - Hotkeys", "AllDeposit", (KeyCode)104, "Spread matching inventory items across nearby storage that already contains those item types.");
			HoveredChestKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("02 - Hotkeys", "HoveredChest", (KeyCode)104, "Hovered-chest action. This key only activates while hovering an eligible player-built chest.");
			LockKeybind = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("02 - Hotkeys", "LockKeybind", new KeyboardShortcut((KeyCode)323, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Combined shortcut used to lock or unlock a normal inventory item.");
			DepositDistance = ((BaseUnityPlugin)this).Config.Bind<float>("03 - Storage", "DepositDistance", 10f, new ConfigDescription("Maximum hot-deposit distance in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 300f), Array.Empty<object>()));
			IgnoreHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "IgnoreHotbar", true, "Do not hot-deposit items located in the hotbar row.");
			IgnoreEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "IgnoreEquipped", true, "Do not hot-deposit currently equipped items.");
			HoveredChestDepositAll = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "HoveredChestDepositAll", true, "When true, HoveredChest performs Hot Deposit All across matching nearby storage. When false, it uses the hovered chest and only deposits matching item types.");
			ShowHoverPrompt = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "ShowHoverPrompt", true, "Retained for config compatibility. The per-container hover-text hook is disabled in 1.0.1 performance mode to avoid chest-area FPS loss.");
			ShowLockIcon = ((BaseUnityPlugin)this).Config.Bind<bool>("04 - Item Lock", "ShowLockIcon", true, "Show a visible padlock marker on locked inventory items.");
			ShowDepositPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("05 - Notifications", "ShowDepositPopup", true, "Show a level-up-style notification after a successful deposit.");
			EnsureLockSprite();
			InitializeInputVisibilityChecks();
			_harmony = new Harmony("Moopfam.HotDeposit");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("HotDeposit 1.0.2 loaded. " + $"AllDeposit={AllDepositKey.Value}, HoveredChest={HoveredChestKey.Value}, " + $"Lock={LockKeybind.Value}, " + $"Distance={DepositDistance.Value:0.#}m."));
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled == null || !Enabled.Value || EnableKeyBinds == null || !EnableKeyBinds.Value)
			{
				return;
			}
			KeyCode val = (KeyCode)((AllDepositKey != null) ? ((int)AllDepositKey.Value) : 0);
			KeyCode val2 = (KeyCode)((HoveredChestKey != null) ? ((int)HoveredChestKey.Value) : 0);
			bool flag = (int)val != 0 && (int)val2 != 0 && val == val2;
			bool flag2 = (int)val != 0 && Input.GetKeyDown(val);
			bool flag3 = (int)val2 != 0 && Input.GetKeyDown(val2);
			if (!flag2 && !flag3)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || IsTypingOrConsoleOpen())
			{
				return;
			}
			try
			{
				ContainerTarget hoveredEligibleTarget = GetHoveredEligibleTarget(localPlayer);
				if (flag)
				{
					if (flag2)
					{
						if (hoveredEligibleTarget != null)
						{
							HotDepositHoveredChest(localPlayer, hoveredEligibleTarget);
						}
						else
						{
							HotDepositNearby(localPlayer);
						}
					}
				}
				else if (flag3 && hoveredEligibleTarget != null)
				{
					HotDepositHoveredChest(localPlayer, hoveredEligibleTarget);
				}
				else if (flag2)
				{
					HotDepositNearby(localPlayer);
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)string.Format("{0}: hot deposit failed: {1}", "HotDeposit", arg));
				}
				ShowMessage(localPlayer, "Hot Deposit failed. Check BepInEx log.");
			}
		}

		private static ContainerTarget GetHoveredEligibleTarget(Player player)
		{
			Container hoveredContainer = GetHoveredContainer(player);
			if ((Object)(object)hoveredContainer == (Object)null)
			{
				return null;
			}
			return CreateContainerTarget(player, hoveredContainer, enforceDepositDistance: false);
		}

		private static void HotDepositNearby(Player player)
		{
			List<ContainerTarget> list = FindEligibleContainers(player);
			if (list.Count == 0)
			{
				ShowMessage(player, "No storage nearby");
			}
			else
			{
				DepositIntoTargets(player, list, requireExistingMatch: true, "No items to deposit", "All Deposit");
			}
		}

		private static void HotDepositHoveredChest(Player player, ContainerTarget hoveredTarget)
		{
			if (hoveredTarget == null)
			{
				return;
			}
			if (HoveredChestDepositAll != null && HoveredChestDepositAll.Value)
			{
				List<ContainerTarget> list = FindEligibleContainers(player);
				if (list.Count == 0)
				{
					ShowMessage(player, "No storage nearby");
				}
				else
				{
					DepositIntoTargets(player, list, requireExistingMatch: true, "No items to deposit", "Hot Deposit All");
				}
			}
			else
			{
				DepositIntoTargets(player, new List<ContainerTarget> { hoveredTarget }, requireExistingMatch: true, "No items to deposit", "Hot Deposit");
			}
		}

		private static void DepositIntoTargets(Player player, List<ContainerTarget> targets, bool requireExistingMatch, string noMatchMessage, string successTitle)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null || targets == null || targets.Count == 0)
			{
				return;
			}
			List<ItemData> list = GetInventoryItems(inventory).ToList();
			List<PlayerDepositItem> list2 = new List<PlayerDepositItem>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (ItemData item2 in list)
			{
				if (item2 != null && item2.m_stack > 0 && !IsLocked(item2) && !ShouldSkipPlayerItem(item2))
				{
					string itemKey = GetItemKey(item2);
					if (!string.IsNullOrEmpty(itemKey))
					{
						list2.Add(new PlayerDepositItem
						{
							Item = item2,
							ItemKey = itemKey,
							DisplayName = GetItemDisplayName(item2)
						});
						hashSet.Add(itemKey);
					}
				}
			}
			if (list2.Count == 0)
			{
				ShowMessage(player, noMatchMessage);
				return;
			}
			Dictionary<string, List<ContainerTarget>> dictionary = BuildTargetItemIndex(targets, hashSet);
			int num = 0;
			HashSet<Container> hashSet2 = new HashSet<Container>();
			Dictionary<string, int> dictionary2 = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
			foreach (PlayerDepositItem item3 in list2)
			{
				ItemData item = item3.Item;
				if (item == null || item.m_stack <= 0)
				{
					continue;
				}
				string itemKey2 = item3.ItemKey;
				string displayName = item3.DisplayName;
				List<ContainerTarget> value;
				if (requireExistingMatch)
				{
					if (!dictionary.TryGetValue(itemKey2, out value) || value == null || value.Count == 0)
					{
						continue;
					}
				}
				else
				{
					value = targets;
				}
				int stack = item.m_stack;
				if (requireExistingMatch)
				{
					foreach (ContainerTarget item4 in value)
					{
						if (item.m_stack <= 0)
						{
							break;
						}
						if (EnsureContainerOwnership(item4))
						{
							int num2 = TransferIntoExistingStacksIndexed(item4, item, itemKey2, item.m_stack);
							if (num2 > 0)
							{
								num += num2;
								hashSet2.Add(item4.Container);
							}
						}
					}
					bool flag = true;
					while (item.m_stack > 0 && flag)
					{
						flag = false;
						foreach (ContainerTarget item5 in value)
						{
							if (item.m_stack <= 0)
							{
								break;
							}
							if (EnsureContainerOwnership(item5))
							{
								int num3 = ((item.m_shared != null) ? item.m_shared.m_maxStackSize : item.m_stack);
								int num4 = TransferIntoNewStacksIndexed(item5, item, itemKey2, Mathf.Min(item.m_stack, num3), 1);
								if (num4 > 0)
								{
									num += num4;
									hashSet2.Add(item5.Container);
									flag = true;
								}
							}
						}
					}
					if (item.m_stack <= 0)
					{
						try
						{
							inventory.RemoveItem(item);
						}
						catch
						{
						}
					}
				}
				else
				{
					foreach (ContainerTarget item6 in value)
					{
						if (item.m_stack <= 0)
						{
							break;
						}
						if (EnsureContainerOwnership(item6))
						{
							int num5 = TransferItemAmount(inventory, item6.Inventory, item, item.m_stack);
							if (num5 > 0)
							{
								num += num5;
								hashSet2.Add(item6.Container);
							}
						}
					}
				}
				int num6 = Mathf.Max(0, stack - item.m_stack);
				if (num6 > 0)
				{
					dictionary2.TryGetValue(displayName, out var value2);
					dictionary2[displayName] = value2 + num6;
				}
			}
			if (num > 0)
			{
				NotifyInventoryChanged(inventory);
				foreach (ContainerTarget target in targets)
				{
					if (target != null && target.Inventory != null && (Object)(object)target.Container != (Object)null && hashSet2.Contains(target.Container))
					{
						NotifyInventoryChanged(target.Inventory);
					}
				}
				ShowDepositNotification(player, successTitle, dictionary2);
			}
			else
			{
				ShowMessage(player, noMatchMessage);
			}
		}

		private static Dictionary<string, List<ContainerTarget>> BuildTargetItemIndex(List<ContainerTarget> targets, HashSet<string> requiredItemKeys)
		{
			Dictionary<string, List<ContainerTarget>> dictionary = new Dictionary<string, List<ContainerTarget>>(StringComparer.OrdinalIgnoreCase);
			foreach (ContainerTarget target in targets)
			{
				if (target == null || target.Inventory == null)
				{
					continue;
				}
				PrepareTargetItemIndex(target, requiredItemKeys);
				foreach (string key in target.ItemStacksByKey.Keys)
				{
					if (!dictionary.TryGetValue(key, out var value))
					{
						value = (dictionary[key] = new List<ContainerTarget>());
					}
					value.Add(target);
				}
			}
			return dictionary;
		}

		private static void PrepareTargetItemIndex(ContainerTarget target, HashSet<string> requiredItemKeys)
		{
			target.ItemStacksByKey = new Dictionary<string, List<ItemData>>(StringComparer.OrdinalIgnoreCase);
			foreach (ItemData inventoryItem in GetInventoryItems(target.Inventory))
			{
				if (inventoryItem == null || inventoryItem.m_stack <= 0)
				{
					continue;
				}
				string itemKey = GetItemKey(inventoryItem);
				if (!string.IsNullOrEmpty(itemKey) && (requiredItemKeys == null || requiredItemKeys.Contains(itemKey)))
				{
					if (!target.ItemStacksByKey.TryGetValue(itemKey, out var value))
					{
						value = new List<ItemData>();
						target.ItemStacksByKey[itemKey] = value;
					}
					value.Add(inventoryItem);
				}
			}
			foreach (List<ItemData> value2 in target.ItemStacksByKey.Values)
			{
				value2.Sort(CompareItemGridPosition);
			}
		}

		private static int CompareItemGridPosition(ItemData a, ItemData b)
		{
			if (a == b)
			{
				return 0;
			}
			if (a == null)
			{
				return 1;
			}
			if (b == null)
			{
				return -1;
			}
			int num = a.m_gridPos.y.CompareTo(b.m_gridPos.y);
			return (num != 0) ? num : a.m_gridPos.x.CompareTo(b.m_gridPos.x);
		}

		private static bool EnsureContainerOwnership(ContainerTarget target)
		{
			if (target == null || (Object)(object)target.Container == (Object)null)
			{
				return false;
			}
			if (target.OwnershipState > 0)
			{
				return true;
			}
			if (target.OwnershipState < 0)
			{
				return false;
			}
			bool flag = ClaimContainerOwnership(target.Container);
			target.OwnershipState = (flag ? 1 : (-1));
			return flag;
		}

		private static int TransferIntoExistingStacksIndexed(ContainerTarget target, ItemData source, string itemKey, int requestedAmount)
		{
			if (target == null || target.Inventory == null || target.ItemStacksByKey == null || source == null || source.m_shared == null || requestedAmount <= 0)
			{
				return 0;
			}
			if (!target.ItemStacksByKey.TryGetValue(itemKey, out var value) || value == null)
			{
				return 0;
			}
			int num = Mathf.Min(requestedAmount, source.m_stack);
			int num2 = 0;
			foreach (ItemData item in value)
			{
				if (num <= 0 || source.m_stack <= 0)
				{
					break;
				}
				if (item != null && item.m_shared != null && item.m_stack > 0 && item.m_stack < item.m_shared.m_maxStackSize && item.m_quality == source.m_quality && item.m_worldLevel == source.m_worldLevel)
				{
					int num3 = item.m_shared.m_maxStackSize - item.m_stack;
					if (num3 > 0)
					{
						int num4 = Mathf.Min(num, Mathf.Min(source.m_stack, num3));
						item.m_stack += num4;
						source.m_stack -= num4;
						num -= num4;
						num2 += num4;
					}
				}
			}
			return num2;
		}

		private static int TransferIntoNewStacksIndexed(ContainerTarget target, ItemData item, string itemKey, int requestedAmount, int maxNewStacks)
		{
			//IL_0051: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (target == null || target.Inventory == null || item == null || item.m_shared == null || requestedAmount <= 0 || maxNewStacks <= 0)
			{
				return 0;
			}
			int num = Mathf.Min(requestedAmount, item.m_stack);
			int num2 = 0;
			int num3 = 0;
			while (num > 0 && item.m_stack > 0 && num3 < maxNewStacks)
			{
				Vector2i val = FindEmptySlot(target.Inventory, item);
				if (val.x < 0 || val.y < 0)
				{
					break;
				}
				int num4 = Mathf.Min(num, Mathf.Min(item.m_stack, item.m_shared.m_maxStackSize));
				ItemData val2 = item.Clone();
				val2.m_stack = num4;
				val2.m_gridPos = val;
				target.Inventory.GetAllItems().Add(val2);
				if (target.ItemStacksByKey == null)
				{
					target.ItemStacksByKey = new Dictionary<string, List<ItemData>>(StringComparer.OrdinalIgnoreCase);
				}
				if (!target.ItemStacksByKey.TryGetValue(itemKey, out var value))
				{
					value = new List<ItemData>();
					target.ItemStacksByKey[itemKey] = value;
				}
				int num5 = value.BinarySearch(val2, ItemGridPositionComparer.Instance);
				if (num5 < 0)
				{
					num5 = ~num5;
				}
				value.Insert(num5, val2);
				item.m_stack -= num4;
				num -= num4;
				num2 += num4;
				num3++;
			}
			return num2;
		}

		private static int TransferItemAmount(Inventory fromInventory, Inventory toInventory, ItemData item, int requestedAmount)
		{
			if (fromInventory == null || toInventory == null || item == null || item.m_shared == null || requestedAmount <= 0)
			{
				return 0;
			}
			int num = Mathf.Min(requestedAmount, GetStack(item));
			int num2 = 0;
			int num3 = TransferIntoExistingStacks(toInventory, item, num);
			num2 += num3;
			num -= num3;
			if (num > 0 && GetStack(item) > 0)
			{
				int num4 = TransferIntoNewStacks(toInventory, item, num, int.MaxValue);
				num2 += num4;
			}
			if (GetStack(item) <= 0)
			{
				try
				{
					fromInventory.RemoveItem(item);
				}
				catch
				{
				}
			}
			return num2;
		}

		private static int TransferIntoExistingStacks(Inventory toInventory, ItemData source, int requestedAmount)
		{
			if (toInventory == null || source == null || source.m_shared == null || requestedAmount <= 0)
			{
				return 0;
			}
			int num = Mathf.Min(requestedAmount, GetStack(source));
			int num2 = 0;
			List<ItemData> list = (from destination in GetInventoryItems(toInventory)
				where IsCompatiblePartialStack(destination, source)
				orderby destination.m_gridPos.y, destination.m_gridPos.x
				select destination).ToList();
			foreach (ItemData item in list)
			{
				if (num <= 0 || GetStack(source) <= 0)
				{
					break;
				}
				int num3 = item.m_shared.m_maxStackSize - item.m_stack;
				if (num3 > 0)
				{
					int num4 = Mathf.Min(num, Mathf.Min(GetStack(source), num3));
					item.m_stack += num4;
					ItemData obj = source;
					obj.m_stack -= num4;
					num -= num4;
					num2 += num4;
				}
			}
			return num2;
		}

		private static bool IsCompatiblePartialStack(ItemData destination, ItemData source)
		{
			if (destination == null || source == null || destination.m_shared == null || source.m_shared == null)
			{
				return false;
			}
			if (destination.m_stack <= 0 || destination.m_stack >= destination.m_shared.m_maxStackSize)
			{
				return false;
			}
			if (!string.Equals(GetItemKey(destination), GetItemKey(source), StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			if (destination.m_quality != source.m_quality)
			{
				return false;
			}
			if (destination.m_worldLevel != source.m_worldLevel)
			{
				return false;
			}
			return true;
		}

		private static int TransferIntoNewStacks(Inventory toInventory, ItemData item, int requestedAmount, int maxNewStacks)
		{
			//IL_0043: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (toInventory == null || item == null || item.m_shared == null || requestedAmount <= 0 || maxNewStacks <= 0)
			{
				return 0;
			}
			int num = Mathf.Min(requestedAmount, GetStack(item));
			int num2 = 0;
			int num3 = 0;
			while (num > 0 && GetStack(item) > 0 && num3 < maxNewStacks)
			{
				Vector2i val = FindEmptySlot(toInventory, item);
				if (val.x < 0 || val.y < 0)
				{
					break;
				}
				int num4 = Mathf.Min(num, Mathf.Min(GetStack(item), item.m_shared.m_maxStackSize));
				ItemData val2 = item.Clone();
				val2.m_stack = num4;
				val2.m_gridPos = val;
				toInventory.GetAllItems().Add(val2);
				item.m_stack -= num4;
				num -= num4;
				num2 += num4;
				num3++;
			}
			return num2;
		}

		private static string GetItemDisplayName(ItemData item)
		{
			if (item == null || item.m_shared == null || string.IsNullOrEmpty(item.m_shared.m_name))
			{
				string itemKey = GetItemKey(item);
				return string.IsNullOrEmpty(itemKey) ? "Item" : itemKey;
			}
			return item.m_shared.m_name.TrimStart(new char[1] { '$' });
		}

		private static Vector2i FindEmptySlot(Inventory inventory, ItemData item)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			Vector2i result = default(Vector2i);
			((Vector2i)(ref result))..ctor(-1, -1);
			if (inventory == null || item == null || InventoryFindEmptySlotMethod == null || InventoryTopFirstMethod == null)
			{
				return result;
			}
			try
			{
				bool flag = Convert.ToBoolean(InventoryTopFirstMethod.Invoke(inventory, new object[1] { item }));
				if (InventoryFindEmptySlotMethod.Invoke(inventory, new object[1] { flag }) is Vector2i result2)
				{
					return result2;
				}
			}
			catch
			{
			}
			return result;
		}

		private static void NotifyInventoryChanged(Inventory inventory)
		{
			if (inventory == null || InventoryChangedMethod == null)
			{
				return;
			}
			try
			{
				InventoryChangedMethod.Invoke(inventory, new object[2] { false, false });
			}
			catch
			{
			}
		}

		internal static string GetHoveredChestPrompt(Container container)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled == null || !Enabled.Value || EnableKeyBinds == null || !EnableKeyBinds.Value || ShowHoverPrompt == null || !ShowHoverPrompt.Value || HoveredChestKey == null || (int)HoveredChestKey.Value == 0 || (Object)(object)container == (Object)null)
			{
				return string.Empty;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return string.Empty;
			}
			RegisteredContainer orCreateContainerEntry = GetOrCreateContainerEntry(container);
			if (orCreateContainerEntry == null)
			{
				return string.Empty;
			}
			EnsureContainerMetadata(orCreateContainerEntry);
			if (orCreateContainerEntry.IsTombStone || !IsPlayerBuiltStorage(orCreateContainerEntry))
			{
				return string.Empty;
			}
			bool flag = HoveredChestDepositAll != null && HoveredChestDepositAll.Value;
			string text = $"<color=#FFFF00>{HoveredChestKey.Value}</color>";
			return flag ? ("[" + text + "] Hot Deposit All") : ("[" + text + "] Hot Deposit");
		}

		private static Container GetHoveredContainer(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			GameObject val = null;
			try
			{
				if (PlayerGetHoverObjectMethod != null)
				{
					object? obj = PlayerGetHoverObjectMethod.Invoke(player, null);
					val = (GameObject)((obj is GameObject) ? obj : null);
				}
			}
			catch
			{
				return null;
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Container val2 = val.GetComponent<Container>() ?? val.GetComponentInParent<Container>();
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			return val.GetComponentInChildren<Container>();
		}

		private static ContainerTarget CreateContainerTarget(Player player, Container container, bool enforceDepositDistance)
		{
			RegisteredContainer orCreateContainerEntry = GetOrCreateContainerEntry(container);
			return CreateContainerTarget(player, orCreateContainerEntry, enforceDepositDistance);
		}

		private static ContainerTarget CreateContainerTarget(Player player, RegisteredContainer entry, bool enforceDepositDistance)
		{
			//IL_0033: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || entry == null || (Object)(object)entry.Container == (Object)null)
			{
				return null;
			}
			Container container = entry.Container;
			Vector3 val = entry.CachedPosition;
			if (entry.IsDynamic)
			{
				try
				{
					val = (entry.CachedPosition = ((Component)container).transform.position);
				}
				catch
				{
					return null;
				}
			}
			Vector3 val2 = val - ((Component)player).transform.position;
			float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
			if (enforceDepositDistance)
			{
				float num = ((DepositDistance != null) ? Mathf.Max(1f, DepositDistance.Value) : 10f);
				if (sqrMagnitude > num * num)
				{
					return null;
				}
			}
			if (!((Component)container).gameObject.activeInHierarchy)
			{
				return null;
			}
			EnsureContainerMetadata(entry);
			if (entry.IsTombStone)
			{
				return null;
			}
			if (!IsPlayerBuiltStorage(entry))
			{
				return null;
			}
			if (!CheckContainerAccess(container, player.GetPlayerID()))
			{
				return null;
			}
			if (IsContainerInUse(container))
			{
				return null;
			}
			Inventory val3 = entry.Inventory;
			if (val3 == null)
			{
				val3 = (entry.Inventory = GetContainerInventory(container));
			}
			if (val3 == null)
			{
				return null;
			}
			return new ContainerTarget
			{
				Container = container,
				Inventory = val3,
				DistanceSq = sqrMagnitude
			};
		}

		internal static void RegisterContainer(Container container)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)container == (Object)null)
			{
				return;
			}
			int instanceID;
			try
			{
				instanceID = ((Object)container).GetInstanceID();
			}
			catch
			{
				return;
			}
			if (ContainerRegistryById.TryGetValue(instanceID, out var value))
			{
				if (value != null && (Object)(object)value.Container != (Object)null && value.Container == container)
				{
					return;
				}
				if (value != null)
				{
					RemoveFromSpatialIndex(value);
					ContainerRegistry.Remove(value);
				}
				ContainerRegistryById.Remove(instanceID);
			}
			RegisteredContainer registeredContainer = new RegisteredContainer
			{
				Container = container,
				InstanceId = instanceID
			};
			try
			{
				registeredContainer.CachedPosition = ((Component)container).transform.position;
				if (RigidbodyType != null)
				{
					registeredContainer.IsDynamic = (Object)(object)((Component)container).GetComponentInParent(RigidbodyType) != (Object)null;
				}
			}
			catch
			{
				registeredContainer.CachedPosition = Vector3.zero;
				registeredContainer.IsDynamic = true;
			}
			ContainerRegistry.Add(registeredContainer);
			ContainerRegistryById[instanceID] = registeredContainer;
			AddToSpatialIndex(registeredContainer);
		}

		private static int GetSpatialCell(float coordinate)
		{
			return Mathf.FloorToInt(coordinate / 32f);
		}

		private static long GetSpatialCellKey(int x, int z)
		{
			return ((long)x << 32) ^ (uint)z;
		}

		private static void AddToSpatialIndex(RegisteredContainer entry)
		{
			if (entry == null)
			{
				return;
			}
			if (entry.IsDynamic)
			{
				DynamicContainers.Add(entry);
				return;
			}
			entry.CellX = GetSpatialCell(entry.CachedPosition.x);
			entry.CellZ = GetSpatialCell(entry.CachedPosition.z);
			long spatialCellKey = GetSpatialCellKey(entry.CellX, entry.CellZ);
			if (!StaticContainerBuckets.TryGetValue(spatialCellKey, out var value))
			{
				value = new List<RegisteredContainer>();
				StaticContainerBuckets[spatialCellKey] = value;
			}
			value.Add(entry);
		}

		private static void RemoveFromSpatialIndex(RegisteredContainer entry)
		{
			if (entry == null)
			{
				return;
			}
			if (entry.IsDynamic)
			{
				DynamicContainers.Remove(entry);
				return;
			}
			long spatialCellKey = GetSpatialCellKey(entry.CellX, entry.CellZ);
			if (StaticContainerBuckets.TryGetValue(spatialCellKey, out var value))
			{
				value.Remove(entry);
				if (value.Count == 0)
				{
					StaticContainerBuckets.Remove(spatialCellKey);
				}
			}
		}

		private static RegisteredContainer GetOrCreateContainerEntry(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return null;
			}
			int instanceID;
			try
			{
				instanceID = ((Object)container).GetInstanceID();
			}
			catch
			{
				return null;
			}
			if (ContainerRegistryById.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			RegisterContainer(container);
			ContainerRegistryById.TryGetValue(instanceID, out value);
			return value;
		}

		private static void EnsureContainerRegistrySeeded()
		{
			if (_containerRegistrySeeded)
			{
				return;
			}
			_containerRegistrySeeded = true;
			if (ContainerRegistry.Count <= 0)
			{
				Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
				Container[] array2 = array;
				foreach (Container container in array2)
				{
					RegisterContainer(container);
				}
			}
		}

		private static void PruneDestroyedContainers()
		{
			for (int num = ContainerRegistry.Count - 1; num >= 0; num--)
			{
				RegisteredContainer registeredContainer = ContainerRegistry[num];
				if (registeredContainer == null || !((Object)(object)registeredContainer.Container != (Object)null))
				{
					if (registeredContainer != null)
					{
						RemoveFromSpatialIndex(registeredContainer);
						ContainerRegistryById.Remove(registeredContainer.InstanceId);
					}
					ContainerRegistry.RemoveAt(num);
				}
			}
		}

		private static void EnsureContainerMetadata(RegisteredContainer entry)
		{
			if (entry == null || (Object)(object)entry.Container == (Object)null || entry.MetadataInitialized)
			{
				return;
			}
			entry.MetadataInitialized = true;
			try
			{
				entry.Piece = ((Component)entry.Container).GetComponentInParent<Piece>();
				entry.IsTombStone = (Object)(object)((Component)entry.Container).GetComponentInParent<TombStone>() != (Object)null;
			}
			catch
			{
			}
		}

		private static bool IsPlayerBuiltStorage(RegisteredContainer entry)
		{
			if (entry == null || (Object)(object)entry.Container == (Object)null)
			{
				return false;
			}
			EnsureContainerMetadata(entry);
			if (entry.PlayerBuiltConfirmed)
			{
				return true;
			}
			Piece val = entry.Piece;
			if ((Object)(object)val == (Object)null)
			{
				try
				{
					val = (entry.Piece = ((Component)entry.Container).GetComponentInParent<Piece>());
				}
				catch
				{
					return false;
				}
			}
			if ((Object)(object)val == (Object)null || PieceGetCreatorMethod == null)
			{
				return false;
			}
			try
			{
				object value = PieceGetCreatorMethod.Invoke(val, null);
				long num = Convert.ToInt64(value);
				if (num != 0)
				{
					entry.PlayerBuiltConfirmed = true;
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsPlayerBuiltStorage(Container container)
		{
			return IsPlayerBuiltStorage(GetOrCreateContainerEntry(container));
		}

		private static List<ContainerTarget> FindEligibleContainers(Player player)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return new List<ContainerTarget>();
			}
			EnsureContainerRegistrySeeded();
			List<ContainerTarget> list = new List<ContainerTarget>();
			float num = ((DepositDistance != null) ? Mathf.Max(1f, DepositDistance.Value) : 10f);
			Vector3 position = ((Component)player).transform.position;
			int spatialCell = GetSpatialCell(position.x - num);
			int spatialCell2 = GetSpatialCell(position.x + num);
			int spatialCell3 = GetSpatialCell(position.z - num);
			int spatialCell4 = GetSpatialCell(position.z + num);
			for (int i = spatialCell; i <= spatialCell2; i++)
			{
				for (int j = spatialCell3; j <= spatialCell4; j++)
				{
					if (!StaticContainerBuckets.TryGetValue(GetSpatialCellKey(i, j), out var value) || value == null)
					{
						continue;
					}
					for (int num2 = value.Count - 1; num2 >= 0; num2--)
					{
						RegisteredContainer registeredContainer = value[num2];
						if (registeredContainer == null || (Object)(object)registeredContainer.Container == (Object)null)
						{
							if (registeredContainer != null)
							{
								ContainerRegistryById.Remove(registeredContainer.InstanceId);
							}
							value.RemoveAt(num2);
						}
						else
						{
							ContainerTarget containerTarget = CreateContainerTarget(player, registeredContainer, enforceDepositDistance: true);
							if (containerTarget != null)
							{
								list.Add(containerTarget);
							}
						}
					}
					if (value.Count == 0)
					{
						StaticContainerBuckets.Remove(GetSpatialCellKey(i, j));
					}
				}
			}
			for (int num3 = DynamicContainers.Count - 1; num3 >= 0; num3--)
			{
				RegisteredContainer registeredContainer2 = DynamicContainers[num3];
				if (registeredContainer2 == null || (Object)(object)registeredContainer2.Container == (Object)null)
				{
					if (registeredContainer2 != null)
					{
						ContainerRegistryById.Remove(registeredContainer2.InstanceId);
					}
					DynamicContainers.RemoveAt(num3);
				}
				else
				{
					ContainerTarget containerTarget2 = CreateContainerTarget(player, registeredContainer2, enforceDepositDistance: true);
					if (containerTarget2 != null)
					{
						list.Add(containerTarget2);
					}
				}
			}
			list.Sort((ContainerTarget a, ContainerTarget b) => a.DistanceSq.CompareTo(b.DistanceSq));
			return list;
		}

		private static bool ShouldSkipPlayerItem(ItemData item)
		{
			if (item == null)
			{
				return true;
			}
			if (IsProtectedBySupportedInventoryMods(item))
			{
				return true;
			}
			if (IgnoreEquipped != null && IgnoreEquipped.Value && IsItemEquipped(item))
			{
				return true;
			}
			if (IgnoreHotbar != null && IgnoreHotbar.Value && IsItemInHotbar(item))
			{
				return true;
			}
			return false;
		}

		private static bool IsProtectedBySupportedInventoryMods(ItemData item)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			if (item == null)
			{
				return false;
			}
			EnsureModCompatibility();
			if (_supportedSlotModLoaded)
			{
				try
				{
					Vector2i gridPos = item.m_gridPos;
					int nativePlayerInventoryRows = GetNativePlayerInventoryRows();
					if (gridPos.y < 0 || gridPos.y >= nativePlayerInventoryRows)
					{
						return true;
					}
				}
				catch
				{
				}
			}
			foreach (MethodInfo modProtectionBoolMethod in ModProtectionBoolMethods)
			{
				try
				{
					if (!TryBuildCompatibilityArguments(modProtectionBoolMethod.GetParameters(), item, out var args) || !(modProtectionBoolMethod.Invoke(null, args) is int num) || num == 0)
					{
						continue;
					}
					return true;
				}
				catch
				{
				}
			}
			foreach (MethodInfo modProtectionItemListMethod in ModProtectionItemListMethods)
			{
				try
				{
					if (!TryBuildCompatibilityArguments(modProtectionItemListMethod.GetParameters(), item, out var args2) || !(modProtectionItemListMethod.Invoke(null, args2) is IEnumerable enumerable))
					{
						continue;
					}
					foreach (object item2 in enumerable)
					{
						if (item2 == item)
						{
							return true;
						}
					}
				}
				catch
				{
				}
			}
			return false;
		}

		private static int GetNativePlayerInventoryRows()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return 4;
			}
			try
			{
				string s = null;
				if (localPlayer.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result))
				{
					return Mathf.Clamp(result, 4, 9);
				}
			}
			catch
			{
			}
			if (!_supportedSlotModLoaded)
			{
				try
				{
					Inventory inventory = ((Humanoid)localPlayer).GetInventory();
					if (inventory != null)
					{
						return Mathf.Clamp(inventory.GetHeight(), 4, 9);
					}
				}
				catch
				{
				}
			}
			return 4;
		}

		private static void EnsureModCompatibility()
		{
			if (_modCompatibilityInitialized)
			{
				return;
			}
			_modCompatibilityInitialized = true;
			string[] source = new string[2] { "EquipmentAndQuickSlots", "BetterArchery" };
			string[] source2 = new string[5] { "IsGridPositionASlot", "IsEquipmentSlotItem", "IsItemInEquipmentSlot", "IsCustomSlotItem", "IsQuiverSlot" };
			string[] source3 = new string[3] { "GetAllSlotItems", "GetQuickSlotItems", "GetEquipmentSlotItems" };
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				string assemblyName = null;
				try
				{
					assemblyName = assembly.GetName().Name;
				}
				catch
				{
				}
				if (!source.Any((string supportedName) => string.Equals(supportedName, assemblyName, StringComparison.OrdinalIgnoreCase)))
				{
					continue;
				}
				_supportedSlotModLoaded = true;
				Type[] array;
				try
				{
					array = assembly.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					array = ex.Types.Where((Type type2) => type2 != null).ToArray();
				}
				catch
				{
					continue;
				}
				Type[] array2 = array;
				foreach (Type type in array2)
				{
					if (type == null)
					{
						continue;
					}
					MethodInfo[] methods;
					try
					{
						methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					}
					catch
					{
						continue;
					}
					MethodInfo[] array3 = methods;
					foreach (MethodInfo methodInfo in array3)
					{
						if (methodInfo == null || methodInfo.ContainsGenericParameters)
						{
							continue;
						}
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (methodInfo.ReturnType == typeof(bool) && source2.Contains(methodInfo.Name) && CanBuildCompatibilityArguments(parameters))
						{
							if (!ModProtectionBoolMethods.Contains(methodInfo))
							{
								ModProtectionBoolMethods.Add(methodInfo);
							}
						}
						else if (source3.Contains(methodInfo.Name) && typeof(IEnumerable).IsAssignableFrom(methodInfo.ReturnType) && CanBuildCompatibilityArguments(parameters) && !ModProtectionItemListMethods.Contains(methodInfo))
						{
							ModProtectionItemListMethods.Add(methodInfo);
						}
					}
				}
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)("HotDeposit: BetterArchery / EquipmentAndQuickSlots " + $"protection hooks: {ModProtectionBoolMethods.Count} checks, " + $"{ModProtectionItemListMethods.Count} item lists."));
			}
		}

		private static bool CanBuildCompatibilityArguments(ParameterInfo[] parameters)
		{
			if (parameters == null)
			{
				return true;
			}
			foreach (ParameterInfo parameterInfo in parameters)
			{
				Type parameterType = parameterInfo.ParameterType;
				if (parameterType == typeof(ItemData) || parameterType == typeof(Vector2i) || parameterType == typeof(Inventory) || parameterType == typeof(Player))
				{
					continue;
				}
				if (parameterType == typeof(int))
				{
					string text = (parameterInfo.Name ?? string.Empty).ToLowerInvariant();
					if (text == "x" || text == "y" || text.Contains("row") || text.Contains("column"))
					{
						continue;
					}
				}
				if (parameterInfo.HasDefaultValue)
				{
					continue;
				}
				return false;
			}
			return true;
		}

		private static bool TryBuildCompatibilityArguments(ParameterInfo[] parameters, ItemData item, out object[] args)
		{
			//IL_0043: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			args = new object[(parameters != null) ? parameters.Length : 0];
			if (parameters == null || parameters.Length == 0)
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			Inventory val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetInventory() : null);
			Vector2i gridPos = item.m_gridPos;
			for (int i = 0; i < parameters.Length; i++)
			{
				ParameterInfo parameterInfo = parameters[i];
				Type parameterType = parameterInfo.ParameterType;
				if (parameterType == typeof(ItemData))
				{
					args[i] = item;
					continue;
				}
				if (parameterType == typeof(Vector2i))
				{
					args[i] = gridPos;
					continue;
				}
				if (parameterType == typeof(Inventory))
				{
					if (val == null)
					{
						return false;
					}
					args[i] = val;
					continue;
				}
				if (parameterType == typeof(Player))
				{
					if ((Object)(object)localPlayer == (Object)null)
					{
						return false;
					}
					args[i] = localPlayer;
					continue;
				}
				if (parameterType == typeof(int))
				{
					string text = (parameterInfo.Name ?? string.Empty).ToLowerInvariant();
					if (text == "x" || text.Contains("column"))
					{
						args[i] = gridPos.x;
						continue;
					}
					if (text == "y" || text.Contains("row"))
					{
						args[i] = gridPos.y;
						continue;
					}
				}
				if (parameterInfo.HasDefaultValue)
				{
					args[i] = parameterInfo.DefaultValue;
					continue;
				}
				return false;
			}
			return true;
		}

		internal static bool TryHandleLockClick(object[] args)
		{
			if (Enabled == null || !Enabled.Value || EnableKeyBinds == null || !EnableKeyBinds.Value)
			{
				return false;
			}
			if (!IsLockHotkeyHeld())
			{
				return false;
			}
			ItemData val = FindItemArg(args);
			if (val == null || !IsPlayerInventoryItem(val))
			{
				return false;
			}
			if (IsItemInHotbar(val))
			{
				ShowMessage(Player.m_localPlayer, "Hotbar items are already protected");
				return true;
			}
			if (IsProtectedBySupportedInventoryMods(val))
			{
				ShowMessage(Player.m_localPlayer, "Equipment / quiver items are already protected");
				return true;
			}
			bool flag = ToggleLock(val);
			ShowMessage(Player.m_localPlayer, flag ? "Item locked" : "Item unlocked");
			RefreshInventoryGui();
			return true;
		}

		private static bool IsLockHotkeyHeld()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (LockKeybind == null)
			{
				return false;
			}
			try
			{
				KeyboardShortcut value = LockKeybind.Value;
				return ((KeyboardShortcut)(ref value)).IsPressed();
			}
			catch
			{
				return false;
			}
		}

		private static ItemData FindItemArg(object[] args)
		{
			if (args == null)
			{
				return null;
			}
			foreach (object obj in args)
			{
				ItemData val = (ItemData)((obj is ItemData) ? obj : null);
				if (val != null)
				{
					return val;
				}
			}
			return null;
		}

		private static bool IsPlayerInventoryItem(ItemData item)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || item == null)
			{
				return false;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory == null)
			{
				return false;
			}
			foreach (ItemData inventoryItem in GetInventoryItems(inventory))
			{
				if (inventoryItem == item)
				{
					return true;
				}
			}
			return false;
		}

		internal static bool IsLocked(ItemData item)
		{
			IDictionary customData = GetCustomData(item);
			if (customData == null || !customData.Contains("Moopfam.HotDeposit.Locked"))
			{
				return false;
			}
			object obj = customData["Moopfam.HotDeposit.Locked"];
			return obj != null && string.Equals(obj.ToString(), "1", StringComparison.OrdinalIgnoreCase);
		}

		private static bool ToggleLock(ItemData item)
		{
			IDictionary customData = GetCustomData(item);
			if (customData == null)
			{
				return false;
			}
			bool flag = !IsLocked(item);
			if (flag)
			{
				customData["Moopfam.HotDeposit.Locked"] = "1";
			}
			else if (customData.Contains("Moopfam.HotDeposit.Locked"))
			{
				customData.Remove("Moopfam.HotDeposit.Locked");
			}
			return flag;
		}

		private static IDictionary GetCustomData(ItemData item)
		{
			if (item == null || ItemCustomDataField == null)
			{
				return null;
			}
			try
			{
				object value = ItemCustomDataField.GetValue(item);
				return value as IDictionary;
			}
			catch
			{
				return null;
			}
		}

		internal static void UpdateLockVisuals(InventoryGrid grid)
		{
			if ((Object)(object)grid == (Object)null || ShowLockIcon == null || !ShowLockIcon.Value || InventoryGridElementsField == null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Inventory val = null;
			try
			{
				val = grid.GetInventory();
			}
			catch
			{
				return;
			}
			if (val == null || val != ((Humanoid)localPlayer).GetInventory())
			{
				return;
			}
			IList list = null;
			try
			{
				list = InventoryGridElementsField.GetValue(grid) as IList;
			}
			catch
			{
			}
			if (list == null)
			{
				return;
			}
			int width = val.GetWidth();
			if (width <= 0)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				object obj3 = list[i];
				Component val2 = (Component)((obj3 is Component) ? obj3 : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					int x = i % width;
					int y = i / width;
					ItemData inventoryItemAt = GetInventoryItemAt(val, x, y);
					SetLockVisual(val2.transform, inventoryItemAt != null && !IsItemInHotbar(inventoryItemAt) && !IsProtectedBySupportedInventoryMods(inventoryItemAt) && IsLocked(inventoryItemAt));
				}
			}
		}

		private static ItemData GetInventoryItemAt(Inventory inventory, int x, int y)
		{
			if (inventory == null || x < 0 || y < 0 || InventoryGetItemAtMethod == null)
			{
				return null;
			}
			try
			{
				object? obj = InventoryGetItemAtMethod.Invoke(inventory, new object[2] { x, y });
				return (ItemData)((obj is ItemData) ? obj : null);
			}
			catch
			{
				return null;
			}
		}

		private static void SetLockVisual(Transform parent, bool visible)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parent == (Object)null)
			{
				return;
			}
			Transform val = parent.Find("HotDepositLockBorder");
			GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
			if ((Object)(object)val2 == (Object)null && visible)
			{
				val2 = CreateLockBorder(parent, new Color(1f, 0.75f, 0f, 1f));
			}
			if ((Object)(object)val2 != (Object)null)
			{
				val2.SetActive(visible);
				if (visible)
				{
					val2.transform.SetAsLastSibling();
				}
			}
			Transform val3 = parent.Find("HotDepositLockIcon");
			GameObject val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject : null);
			if ((Object)(object)val4 == (Object)null && visible)
			{
				EnsureLockSprite();
				val4 = new GameObject("HotDepositLockIcon", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				RectTransform component = val4.GetComponent<RectTransform>();
				((Transform)component).SetParent(parent, false);
				component.anchorMin = new Vector2(1f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(1f, 1f);
				component.anchoredPosition = new Vector2(-4f, -4f);
				component.sizeDelta = new Vector2(22f, 22f);
				Image component2 = val4.GetComponent<Image>();
				component2.sprite = _lockSprite;
				((Graphic)component2).raycastTarget = false;
				((Graphic)component2).color = Color.white;
			}
			if ((Object)(object)val4 != (Object)null)
			{
				val4.SetActive(visible);
				if (visible)
				{
					val4.transform.SetAsLastSibling();
				}
			}
		}

		private static GameObject CreateLockBorder(Transform parent, Color color)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("HotDepositLockBorder", new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = new Vector2(0f, -2f);
			component.offsetMax = new Vector2(0f, -2f);
			CreateBorderEdge(val.transform, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -3f), Vector2.zero, color);
			CreateBorderEdge(val.transform, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 3f), color);
			CreateBorderEdge(val.transform, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), Vector2.zero, new Vector2(3f, 0f), color);
			CreateBorderEdge(val.transform, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-3f, 0f), Vector2.zero, color);
			val.transform.SetAsLastSibling();
			return val;
		}

		private static void CreateBorderEdge(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color color)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0046: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			component.offsetMin = offsetMin;
			component.offsetMax = offsetMax;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = color;
			((Graphic)component2).raycastTarget = false;
		}

		private static void EnsureLockSprite()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_lockSprite != (Object)null)
			{
				return;
			}
			Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
			((Object)val).name = "HotDepositLockTexture";
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.08f, 0.08f, 0.08f, 0.95f);
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(1f, 0.85f, 0.15f, 1f);
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					val.SetPixel(j, i, val2);
				}
			}
			for (int k = 8; k <= 13; k++)
			{
				for (int l = 4; l <= 11; l++)
				{
					if (l == 4 || l == 11 || k == 13)
					{
						val.SetPixel(l, k, val3);
					}
				}
			}
			for (int m = 9; m <= 13; m++)
			{
				val.SetPixel(5, m, val4);
				val.SetPixel(10, m, val4);
			}
			for (int n = 6; n <= 9; n++)
			{
				val.SetPixel(n, 13, val4);
			}
			for (int num = 2; num <= 8; num++)
			{
				for (int num2 = 3; num2 <= 12; num2++)
				{
					bool flag = num2 == 3 || num2 == 12 || num == 2 || num == 8;
					val.SetPixel(num2, num, flag ? val3 : val4);
				}
			}
			val.SetPixel(7, 5, val3);
			val.SetPixel(8, 5, val3);
			val.SetPixel(7, 4, val3);
			val.SetPixel(8, 4, val3);
			val.Apply();
			_lockSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f), 100f);
			((Object)_lockSprite).name = "HotDepositLockSprite";
		}

		private static void RefreshInventoryGui()
		{
			try
			{
				InventoryGui instance = InventoryGui.instance;
				if (!((Object)(object)instance == (Object)null))
				{
					MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "UpdateInventory", new Type[1] { typeof(Player) }, (Type[])null);
					if (methodInfo != null && (Object)(object)Player.m_localPlayer != (Object)null)
					{
						methodInfo.Invoke(instance, new object[1] { Player.m_localPlayer });
					}
					object? obj = AccessTools.Field(typeof(InventoryGui), "m_playerGrid")?.GetValue(instance);
					InventoryGrid val = (InventoryGrid)((obj is InventoryGrid) ? obj : null);
					if ((Object)(object)val != (Object)null)
					{
						UpdateLockVisuals(val);
					}
				}
			}
			catch
			{
			}
		}

		private static Inventory GetContainerInventory(Container container)
		{
			if ((Object)(object)container == (Object)null || ContainerGetInventoryMethod == null)
			{
				return null;
			}
			try
			{
				object? obj = ContainerGetInventoryMethod.Invoke(container, null);
				return (Inventory)((obj is Inventory) ? obj : null);
			}
			catch
			{
				return null;
			}
		}

		private static IEnumerable<ItemData> GetInventoryItems(Inventory inventory)
		{
			if (inventory == null || InventoryGetAllItemsMethod == null)
			{
				yield break;
			}
			object value;
			try
			{
				value = InventoryGetAllItemsMethod.Invoke(inventory, null);
			}
			catch
			{
				yield break;
			}
			if (!(value is IEnumerable enumerable))
			{
				yield break;
			}
			foreach (object entry in enumerable)
			{
				ItemData item = (ItemData)((entry is ItemData) ? entry : null);
				if (item != null)
				{
					yield return item;
				}
			}
		}

		private static bool InventoryContainsItemKey(Inventory inventory, string key)
		{
			foreach (ItemData inventoryItem in GetInventoryItems(inventory))
			{
				if (string.Equals(GetItemKey(inventoryItem), key, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static string GetItemKey(ItemData item)
		{
			if (item == null)
			{
				return string.Empty;
			}
			try
			{
				object? obj = ItemDropPrefabField?.GetValue(item);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name))
				{
					return ((Object)val).name;
				}
			}
			catch
			{
			}
			try
			{
				object obj3 = ItemSharedField?.GetValue(item);
				if (obj3 == null)
				{
					return string.Empty;
				}
				return (AccessTools.Field(obj3.GetType(), "m_name")?.GetValue(obj3) as string) ?? string.Empty;
			}
			catch
			{
				return string.Empty;
			}
		}

		private static int GetStack(ItemData item)
		{
			if (item == null || ItemStackField == null)
			{
				return 0;
			}
			try
			{
				object value = ItemStackField.GetValue(item);
				return (value != null) ? Convert.ToInt32(value) : 0;
			}
			catch
			{
				return 0;
			}
		}

		private static bool IsItemEquipped(ItemData item)
		{
			if (item == null || ItemEquippedField == null)
			{
				return false;
			}
			try
			{
				object value = ItemEquippedField.GetValue(item);
				return value is bool && (bool)value;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsItemInHotbar(ItemData item)
		{
			if (item == null || ItemGridPosField == null)
			{
				return false;
			}
			try
			{
				object value = ItemGridPosField.GetValue(item);
				if (value == null)
				{
					return false;
				}
				Type type = value.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "y") ?? AccessTools.Field(type, "Y");
				if (fieldInfo != null)
				{
					return Convert.ToInt32(fieldInfo.GetValue(value)) == 0;
				}
				PropertyInfo propertyInfo = AccessTools.Property(type, "y") ?? AccessTools.Property(type, "Y");
				return propertyInfo != null && Convert.ToInt32(propertyInfo.GetValue(value, null)) == 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool CheckContainerAccess(Container container, long playerId)
		{
			if ((Object)(object)container == (Object)null || ContainerCheckAccessMethod == null)
			{
				return false;
			}
			try
			{
				object obj = ContainerCheckAccessMethod.Invoke(container, new object[1] { playerId });
				return obj is bool && (bool)obj;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsContainerInUse(Container container)
		{
			if ((Object)(object)container == (Object)null || ContainerIsInUseMethod == null)
			{
				return false;
			}
			try
			{
				object obj = ContainerIsInUseMethod.Invoke(container, null);
				return obj is bool && (bool)obj;
			}
			catch
			{
				return true;
			}
		}

		private static bool ClaimContainerOwnership(Container container)
		{
			if ((Object)(object)container == (Object)null || ContainerNViewField == null || ZNetViewIsOwnerMethod == null || ZNetViewClaimOwnershipMethod == null)
			{
				return false;
			}
			try
			{
				object? value = ContainerNViewField.GetValue(container);
				ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
				if ((Object)(object)val == (Object)null || !val.IsValid())
				{
					return false;
				}
				if (!(ZNetViewIsOwnerMethod.Invoke(val, null) is int num) || num == 0)
				{
					ZNetViewClaimOwnershipMethod.Invoke(val, null);
				}
				object obj = ZNetViewIsOwnerMethod.Invoke(val, null);
				return obj is bool && (bool)obj;
			}
			catch
			{
				return false;
			}
		}

		private static void InitializeInputVisibilityChecks()
		{
			InputVisibilityProbes.Clear();
			AddInputVisibilityProbe("TextInput", "IsVisible");
			AddInputVisibilityProbe("TextInput", "HasFocus");
			AddInputVisibilityProbe("TextInput", "InTextInput");
			AddInputVisibilityProbe("Console", "IsVisible");
			AddInputVisibilityProbe("Console", "HasFocus");
			AddInputVisibilityProbe("Chat", "HasFocus");
			AddInputVisibilityProbe("Chat", "IsChatDialogWindowVisible");
		}

		private static void AddInputVisibilityProbe(string typeName, string memberName)
		{
			Type type = FindTypeSilent(typeName);
			if (type == null)
			{
				return;
			}
			MethodInfo method = type.GetMethod(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			PropertyInfo propertyInfo = null;
			if (method == null)
			{
				propertyInfo = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (propertyInfo != null && propertyInfo.PropertyType != typeof(bool))
				{
					propertyInfo = null;
				}
			}
			if ((method == null && propertyInfo == null) || (method != null && method.ReturnType != typeof(bool)))
			{
				return;
			}
			MethodInfo methodInfo = ((propertyInfo != null) ? propertyInfo.GetGetMethod(nonPublic: true) : null);
			bool flag = ((method != null) ? method.IsStatic : (methodInfo != null && methodInfo.IsStatic));
			FieldInfo fieldInfo = null;
			PropertyInfo propertyInfo2 = null;
			if (!flag)
			{
				fieldInfo = type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				propertyInfo2 = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (fieldInfo == null && propertyInfo2 == null)
				{
					return;
				}
			}
			InputVisibilityProbes.Add(new InputVisibilityProbe
			{
				Method = method,
				Property = propertyInfo,
				InstanceField = fieldInfo,
				InstanceProperty = propertyInfo2
			});
		}

		private static Type FindTypeSilent(string typeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(typeName, throwOnError: false);
					if (type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static bool IsTypingOrConsoleOpen()
		{
			foreach (InputVisibilityProbe inputVisibilityProbe in InputVisibilityProbes)
			{
				if (inputVisibilityProbe != null && inputVisibilityProbe.Check())
				{
					return true;
				}
			}
			return false;
		}

		private static void ShowDepositNotification(Player player, string title, Dictionary<string, int> movedByItem)
		{
			if ((Object)(object)player == (Object)null || movedByItem == null || movedByItem.Count == 0)
			{
				return;
			}
			List<string> list = new List<string> { title };
			foreach (KeyValuePair<string, int> item in movedByItem.OrderBy((KeyValuePair<string, int> pair) => pair.Key))
			{
				list.Add($"{item.Key} x{item.Value}");
			}
			string text = string.Join("\n", list.ToArray());
			if (ShowDepositPopup != null && ShowDepositPopup.Value)
			{
				try
				{
					((Character)player).Message((MessageType)1, text, 0, (Sprite)null, false);
					return;
				}
				catch
				{
				}
			}
			ShowMessage(player, text);
		}

		private static void ShowMessage(Player player, string message)
		{
			if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(message))
			{
				return;
			}
			try
			{
				((Character)player).Message((MessageType)2, message, 0, (Sprite)null, false);
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class ContainerRegistryAwakePatch
	{
		private static void Postfix(Container __instance)
		{
			Plugin.RegisterContainer(__instance);
		}
	}
	[HarmonyPatch]
	internal static class InventoryGuiSelectedItemPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(InventoryGui), "OnSelectedItem", (Type[])null, (Type[])null);
		}

		private static bool Prefix(object[] __args)
		{
			return !Plugin.TryHandleLockClick(__args);
		}
	}
	[HarmonyPatch]
	internal static class InventoryGridUpdateGuiPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from method in typeof(InventoryGrid).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where method.Name == "UpdateGui"
				select method;
		}

		private static void Postfix(InventoryGrid __instance)
		{
			Plugin.UpdateLockVisuals(__instance);
		}
	}
}