Decompiled source of ValheimChestChain v0.2.16

plugins/ValheimChestChain.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;
using ValheimChestChain.Config;
using ValheimChestChain.Input;
using ValheimChestChain.Linking;
using ValheimChestChain.Patches;
using ValheimChestChain.QuickStack;
using ValheimChestChain.UI;
using ValheimChestChain.Util;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimChestChain")]
[assembly: AssemblyDescription("Quick Stack and chest linking for Valheim")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValheimChestChain")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a1b2c3d4-e5f6-7890-abcd-ef1234567890")]
[assembly: AssemblyFileVersion("0.2.16")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.16.0")]
namespace ValheimChestChain
{
	[BepInPlugin("com.arkhamdc.valheimchestchain", "ValheimChestChain", "0.2.16")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class ChestChainPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.arkhamdc.valheimchestchain";

		public const string PluginName = "ValheimChestChain";

		public const string PluginVersion = "0.2.16";

		private Harmony _harmony;

		private InputHandler _input;

		public static ChestChainPlugin Instance { get; private set; }

		public static ModConfig ModConfig { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Instance = this;
			ModConfig = new ModConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.arkhamdc.valheimchestchain");
			InputBindings.Register(ModConfig);
			TryPatch(typeof(InventoryGui_UpdateContainer_Patch));
			TryPatch(typeof(InventoryGrid_UpdateGui_Patch));
			TryPatch(typeof(InventoryGrid_OnPointerEnter_LockPatch));
			TryPatch(typeof(InventoryGrid_OnLeftClick_LockPatch));
			TryPatch(typeof(InventoryGrid_OnLeftDown_LockPatch));
			TryPatch(typeof(Inventory_StackAll_LockPatch));
			TryPatch(typeof(Container_RPC_StackResponse_QuietClaimPatch));
			TryPatch(typeof(Container_Awake_LabelPatch));
			TryPatch(typeof(Container_OnDestroyed_LabelPatch));
			TryPatch(typeof(Container_GetHoverName_Patch));
			((Component)this).gameObject.AddComponent<ChestSurfaceLabels>();
			_input = ((Component)this).gameObject.AddComponent<InputHandler>();
			_input.Init(ModConfig, delegate
			{
				QuickStackService.TryQuickStack();
			}, delegate
			{
				ChestLinkService.TryToggleLink();
			}, delegate
			{
				ChestLinkService.TryUnlinkCurrent();
			}, delegate
			{
				ChestLinkService.ShowCurrentLink();
			}, delegate
			{
				LockService.TryToggleHovered();
			});
			Logger.LogInfo((object)"ValheimChestChain 0.2.16 loaded");
		}

		private void TryPatch(Type patchClass)
		{
			try
			{
				_harmony.CreateClassProcessor(patchClass).Patch();
				Logger.LogInfo((object)("Harmony patch OK: " + patchClass.Name));
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Harmony patch FAILED: " + patchClass.Name + " — " + ex.Message));
			}
		}

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

		public static void LogDebug(string message)
		{
			if (ModConfig != null && ModConfig.EnableDebugLogging.Value)
			{
				Logger.LogInfo((object)("[ChestChain] " + message));
			}
		}
	}
}
namespace ValheimChestChain.Util
{
	public static class InventoryUtil
	{
		public const string LockedCustomDataKey = "cc_lock";

		private const string LegacyLockedCustomDataKey = "ChestChain.Locked";

		private static readonly HashSet<ItemData> LockedRefs = new HashSet<ItemData>();

		public static bool IsPinned(ItemData item, Player player)
		{
			if (item == null)
			{
				return true;
			}
			ModConfig modConfig = ChestChainPlugin.ModConfig;
			if (modConfig != null && modConfig.SkipEquipped.Value && (item.m_equipped || ((Humanoid)player).IsItemEquiped(item)))
			{
				return true;
			}
			if (modConfig != null && modConfig.SkipHotbar.Value && item.m_gridPos.y == 0)
			{
				return true;
			}
			if (IsCustomLocked(item))
			{
				return true;
			}
			return false;
		}

		public static bool IsCustomLocked(ItemData item)
		{
			if (item == null)
			{
				return false;
			}
			if (LockedRefs.Contains(item))
			{
				return true;
			}
			if (HasLockFlag(item))
			{
				LockedRefs.Add(item);
				SetCustomLocked(item, locked: true);
				return true;
			}
			return false;
		}

		private static bool HasLockFlag(ItemData item)
		{
			if (item.m_customData == null)
			{
				return false;
			}
			if (item.m_customData.TryGetValue("cc_lock", out var value) && value == "1")
			{
				return true;
			}
			if (item.m_customData.TryGetValue("ChestChain.Locked", out value))
			{
				return value == "1";
			}
			return false;
		}

		public static void SetCustomLocked(ItemData item, bool locked)
		{
			if (item != null)
			{
				if (item.m_customData == null)
				{
					item.m_customData = new Dictionary<string, string>();
				}
				if (locked)
				{
					item.m_customData["cc_lock"] = "1";
					item.m_customData.Remove("ChestChain.Locked");
					LockedRefs.Add(item);
				}
				else
				{
					item.m_customData.Remove("cc_lock");
					item.m_customData.Remove("ChestChain.Locked");
					LockedRefs.Remove(item);
				}
			}
		}

		public static void SyncLocksFromInventory(Inventory inventory)
		{
			if (inventory == null)
			{
				return;
			}
			List<ItemData> allItems = inventory.GetAllItems();
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData item = allItems[i];
				if (HasLockFlag(item))
				{
					LockedRefs.Add(item);
				}
			}
		}

		public static bool IsMatchingStack(ItemData a, ItemData b)
		{
			if (a != null && b != null)
			{
				return a.IsSameType(b);
			}
			return false;
		}

		public static bool ContainerHasMatchingItem(Inventory inventory, ItemData item)
		{
			if (inventory == null || item == null)
			{
				return false;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsMatchingStack(allItem, item))
				{
					return true;
				}
			}
			return false;
		}

		public static bool TryMoveItem(Inventory source, Inventory destination, ItemData item, bool allowEmptySlots, out int movedAmount)
		{
			movedAmount = 0;
			if (source == null || destination == null || item == null || item.m_stack <= 0)
			{
				return false;
			}
			if (IsCustomLocked(item))
			{
				return false;
			}
			int num = item.m_stack;
			if (allowEmptySlots)
			{
				destination.MoveItemToThis(source, item);
				if (!source.ContainsItem(item))
				{
					movedAmount = num;
				}
				else
				{
					movedAmount = Mathf.Max(0, num - item.m_stack);
				}
				return movedAmount > 0;
			}
			foreach (ItemData item2 in new List<ItemData>(destination.GetAllItems()))
			{
				if (!IsMatchingStack(item2, item))
				{
					continue;
				}
				int num2 = item2.m_shared.m_maxStackSize - item2.m_stack;
				if (num2 <= 0)
				{
					continue;
				}
				int num3 = Mathf.Min(num2, item.m_stack);
				if (num3 <= 0)
				{
					continue;
				}
				if (destination.MoveItemToThis(source, item, num3, item2.m_gridPos.x, item2.m_gridPos.y))
				{
					int num4 = (source.ContainsItem(item) ? item.m_stack : 0);
					movedAmount += Mathf.Max(0, num - num4);
					num = num4;
					if (num <= 0)
					{
						break;
					}
					continue;
				}
				item2.m_stack += num3;
				item.m_stack -= num3;
				movedAmount += num3;
				if (item.m_stack <= 0)
				{
					source.RemoveItem(item);
					break;
				}
			}
			if (movedAmount > 0)
			{
				source.Changed(false, false);
				destination.Changed(false, false);
			}
			return movedAmount > 0;
		}
	}
	[HarmonyPatch(typeof(Inventory), "StackAll")]
	public static class Inventory_StackAll_LockPatch
	{
		private static bool Prefix(Inventory __instance, Inventory fromInventory, bool message, ref int __result)
		{
			__result = 0;
			if (__instance == null || fromInventory == null)
			{
				return false;
			}
			int num = __instance.CountItems((string)null, -1, true);
			List<ItemData> list = new List<ItemData>(fromInventory.GetAllItems());
			Player localPlayer = Player.m_localPlayer;
			for (int i = 0; i < list.Count; i++)
			{
				ItemData val = list[i];
				if (val != null && val.m_shared != null && __instance.ContainsItemByName(val.m_shared.m_name) && (!((Object)(object)localPlayer != (Object)null) || !InventoryUtil.IsPinned(val, localPlayer)) && __instance.AddItem(val))
				{
					fromInventory.RemoveItem(val);
				}
			}
			__result = Mathf.Max(0, __instance.CountItems((string)null, -1, true) - num);
			__instance.Changed(false, false);
			fromInventory.Changed(false, false);
			if (message && (Object)(object)localPlayer != (Object)null)
			{
				if (__result > 0)
				{
					((Character)localPlayer).Message((MessageType)2, "$msg_stackall " + __result, 0, (Sprite)null, false);
				}
				else
				{
					((Character)localPlayer).Message((MessageType)2, "$msg_stackall_none", 0, (Sprite)null, false);
				}
			}
			return false;
		}
	}
	public static class LockService
	{
		private static readonly FieldInfo TooltipCurrentField = AccessTools.Field(typeof(UITooltip), "m_current");

		private static InventoryGrid _hoverGrid;

		private static Vector2i _hoverPos;

		private static bool _hasHover;

		public static void SetHover(InventoryGrid grid, Vector2i pos)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)grid == (Object)null) && pos.x >= 0 && pos.y >= 0)
			{
				InventoryGui instance = InventoryGui.instance;
				if (!((Object)(object)instance == (Object)null) && !((Object)(object)grid != (Object)(object)instance.m_playerGrid))
				{
					_hoverGrid = grid;
					_hoverPos = pos;
					_hasHover = true;
				}
			}
		}

		public static void TrackHover(InventoryGrid grid)
		{
		}

		public static void TryToggleHovered()
		{
			Player localPlayer = Player.m_localPlayer;
			InventoryGui instance = InventoryGui.instance;
			Inventory inventory;
			ItemData item;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || !InventoryGui.IsVisible())
			{
				MessageUtil.Center("Открой инвентарь");
			}
			else if (!TryResolvePlayerItem(instance, localPlayer, out inventory, out item) || item == null)
			{
				MessageUtil.Center("Наведи курсор на предмет, затем нажми клавишу");
			}
			else
			{
				Toggle(localPlayer, inventory, item);
			}
		}

		public static bool TryToggleFromClick(InventoryGrid grid, Vector2i pos)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)grid == (Object)null || pos.x < 0 || pos.y < 0)
			{
				return false;
			}
			SetHover(grid, pos);
			Inventory inventory = grid.GetInventory();
			Player localPlayer = Player.m_localPlayer;
			if (inventory == null || (Object)(object)localPlayer == (Object)null || inventory != ((Humanoid)localPlayer).GetInventory())
			{
				return false;
			}
			ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
			if (itemAt == null)
			{
				return false;
			}
			Toggle(localPlayer, inventory, itemAt);
			return true;
		}

		private static bool TryResolvePlayerItem(InventoryGui gui, Player player, out Inventory inventory, out ItemData item)
		{
			inventory = null;
			item = null;
			InventoryGrid playerGrid = gui.m_playerGrid;
			if ((Object)(object)playerGrid == (Object)null)
			{
				return false;
			}
			inventory = playerGrid.GetInventory();
			if (inventory == null || inventory != ((Humanoid)player).GetInventory())
			{
				return false;
			}
			if (TryItemFromTooltip(playerGrid, inventory, out item))
			{
				return true;
			}
			if (TryItemUnderPointer(playerGrid, inventory, out item))
			{
				return true;
			}
			if (_hasHover && (Object)(object)_hoverGrid == (Object)(object)playerGrid && _hoverPos.x >= 0 && _hoverPos.y >= 0)
			{
				item = inventory.GetItemAt(_hoverPos.x, _hoverPos.y);
				if (item != null)
				{
					return true;
				}
			}
			return false;
		}

		private static bool TryItemFromTooltip(InventoryGrid grid, Inventory inventory, out ItemData item)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			item = null;
			if (TooltipCurrentField == null)
			{
				return false;
			}
			object? value = TooltipCurrentField.GetValue(null);
			UITooltip val = (UITooltip)((value is UITooltip) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			InventoryElement componentInParent = ((Component)val).GetComponentInParent<InventoryElement>();
			if ((Object)(object)componentInParent == (Object)null || grid.m_elements == null || !grid.m_elements.Contains(componentInParent))
			{
				return false;
			}
			Vector2i position = componentInParent.Position;
			item = inventory.GetItemAt(position.x, position.y);
			return item != null;
		}

		private static bool TryItemUnderPointer(InventoryGrid grid, Inventory inventory, out ItemData item)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			item = null;
			List<InventoryElement> elements = grid.m_elements;
			if (elements == null || elements.Count == 0)
			{
				return false;
			}
			Vector3 pointerPosition = ZInput.pointerPosition;
			InventoryElement val = null;
			for (int i = 0; i < elements.Count; i++)
			{
				InventoryElement val2 = elements[i];
				if ((Object)(object)val2 == (Object)null || !val2.m_used)
				{
					continue;
				}
				RectTransform elementRectTransform = val2.GetElementRectTransform();
				if (!((Object)(object)elementRectTransform == (Object)null))
				{
					Vector2 val3 = Vector2.op_Implicit(((Transform)elementRectTransform).InverseTransformPoint(pointerPosition));
					Rect rect = elementRectTransform.rect;
					if (((Rect)(ref rect)).Contains(val3))
					{
						val = val2;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Vector2 val4 = Vector2.op_Implicit(pointerPosition);
				for (int j = 0; j < elements.Count; j++)
				{
					InventoryElement val5 = elements[j];
					if (!((Object)(object)val5 == (Object)null) && val5.m_used)
					{
						RectTransform elementRectTransform2 = val5.GetElementRectTransform();
						if ((Object)(object)elementRectTransform2 != (Object)null && RectTransformUtility.RectangleContainsScreenPoint(elementRectTransform2, val4))
						{
							val = val5;
							break;
						}
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Vector2i position = val.Position;
			item = inventory.GetItemAt(position.x, position.y);
			if (item != null)
			{
				SetHover(grid, position);
			}
			return item != null;
		}

		private static void Toggle(Player player, Inventory inventory, ItemData item)
		{
			bool flag = InventoryUtil.IsCustomLocked(item);
			InventoryUtil.SetCustomLocked(item, !flag);
			string text = ((item.m_shared != null) ? Localization.instance.Localize(item.m_shared.m_name) : "?");
			MessageUtil.Center((flag ? "Разблок: " : "Замок: ") + text + " [" + item.m_gridPos.x + "," + item.m_gridPos.y + "]");
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "OnPointerEnter")]
	public static class InventoryGrid_OnPointerEnter_LockPatch
	{
		private static void Postfix(InventoryGrid __instance, UIInputHandler clickHandler)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)clickHandler == (Object)null)
			{
				return;
			}
			Vector2i val = __instance.GetButtonPos(((Component)clickHandler).gameObject);
			if (val.x < 0)
			{
				InventoryElement componentInParent = ((Component)clickHandler).GetComponentInParent<InventoryElement>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					val = componentInParent.Position;
				}
			}
			LockService.SetHover(__instance, val);
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "OnLeftClick")]
	public static class InventoryGrid_OnLeftClick_LockPatch
	{
		private static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler)
		{
			//IL_0056: 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_005c: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))
			{
				return true;
			}
			if ((Object)(object)__instance == (Object)null || (Object)(object)clickHandler == (Object)null || (Object)(object)InventoryGui.instance == (Object)null)
			{
				return true;
			}
			if ((Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid)
			{
				return true;
			}
			Vector2i val = __instance.GetButtonPos(((Component)clickHandler).gameObject);
			if (val.x < 0)
			{
				InventoryElement componentInParent = ((Component)clickHandler).GetComponentInParent<InventoryElement>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					val = componentInParent.Position;
				}
			}
			if (val.x < 0)
			{
				return true;
			}
			return !LockService.TryToggleFromClick(__instance, val);
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "OnLeftDown")]
	public static class InventoryGrid_OnLeftDown_LockPatch
	{
		private static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler)
		{
			//IL_0056: 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_005c: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))
			{
				return true;
			}
			if ((Object)(object)__instance == (Object)null || (Object)(object)clickHandler == (Object)null || (Object)(object)InventoryGui.instance == (Object)null)
			{
				return true;
			}
			if ((Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid)
			{
				return true;
			}
			Vector2i val = __instance.GetButtonPos(((Component)clickHandler).gameObject);
			if (val.x < 0)
			{
				InventoryElement componentInParent = ((Component)clickHandler).GetComponentInParent<InventoryElement>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					val = componentInParent.Position;
				}
			}
			if (val.x < 0)
			{
				return true;
			}
			return !LockService.TryToggleFromClick(__instance, val);
		}
	}
	public static class MessageUtil
	{
		public static void Center(string text)
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
			}
		}

		public static void TopLeft(string text)
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false);
			}
		}
	}
}
namespace ValheimChestChain.UI
{
	public static class ChestRename
	{
		private sealed class Receiver : TextReceiver
		{
			private readonly Container _container;

			public Receiver(Container container)
			{
				_container = container;
			}

			public string GetText()
			{
				return ChestNameStore.Get(_container);
			}

			public void SetText(string text)
			{
				if (!ChestNameStore.TrySet(_container, text))
				{
					MessageUtil.Center("Не удалось сохранить имя");
				}
				else
				{
					ChestSurfaceLabels.Notify(_container);
				}
			}
		}

		public static void TryOpen()
		{
			Container val = CurrentContainer();
			if ((Object)(object)val == (Object)null)
			{
				MessageUtil.Center("Смотри на сундук или открой его");
			}
			else if (!((Object)(object)TextInput.instance == (Object)null))
			{
				TextInput.instance.RequestText((TextReceiver)(object)new Receiver(val), "Имя сундука", 20);
			}
		}

		private static Container CurrentContainer()
		{
			Container val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_currentContainer : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			GameObject val2 = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Humanoid)Player.m_localPlayer).GetHoverObject() : null);
			if (!((Object)(object)val2 != (Object)null))
			{
				return null;
			}
			return val2.GetComponentInParent<Container>();
		}
	}
	public class ChestSurfaceLabels : MonoBehaviour
	{
		private sealed class Slot
		{
			public Container Container;

			public TextMesh Label;

			public string Shown;
		}

		private const float NearDistance = 10f;

		private const float TickSeconds = 0.2f;

		private static readonly List<Container> Registered = new List<Container>(64);

		private readonly List<Slot> _slots = new List<Slot>(64);

		private float _timer;

		private static Font _font;

		private static Material _labelMaterial;

		private static int _losMask = int.MinValue;

		public static void Register(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return;
			}
			for (int i = 0; i < Registered.Count; i++)
			{
				if ((Object)(object)Registered[i] == (Object)(object)container)
				{
					return;
				}
			}
			Registered.Add(container);
		}

		public static void Unregister(Container container)
		{
			Registered.Remove(container);
		}

		public static void Notify(Container container)
		{
			(((Object)(object)ChestChainPlugin.Instance != (Object)null) ? ((Component)ChestChainPlugin.Instance).GetComponent<ChestSurfaceLabels>() : null)?.RefreshOne(container);
		}

		private void Update()
		{
			//IL_005d: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			_timer += Time.unscaledDeltaTime;
			if (_timer < 0.2f)
			{
				return;
			}
			_timer = 0f;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (Registered.Count == 0)
			{
				TryScanNearby(((Component)localPlayer).transform.position);
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			float num = 100f;
			Camera main = Camera.main;
			for (int num2 = Registered.Count - 1; num2 >= 0; num2--)
			{
				Container val = Registered[num2];
				if ((Object)(object)val == (Object)null)
				{
					Registered.RemoveAt(num2);
				}
				else
				{
					Slot slot = FindSlot(val);
					Vector3 val2 = ((Component)val).transform.position - position;
					if (((Vector3)(ref val2)).sqrMagnitude > num)
					{
						SetVisible(slot, visible: false);
					}
					else
					{
						string text = ChestNameStore.Get(val);
						if (string.IsNullOrEmpty(text))
						{
							SetVisible(slot, visible: false);
						}
						else
						{
							Vector3 val3 = ((Component)val).transform.position + Vector3.up * 0.95f + ((Component)val).transform.forward * 0.35f;
							if (!HasLineOfSight(main, val3, val))
							{
								SetVisible(slot, visible: false);
							}
							else
							{
								Apply(slot, val, text, main, val3);
							}
						}
					}
				}
			}
		}

		private static void TryScanNearby(Vector3 origin)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
			foreach (Container val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Vector3 val2 = ((Component)val).transform.position - origin;
					if (((Vector3)(ref val2)).sqrMagnitude < 100f)
					{
						Register(val);
					}
				}
			}
		}

		private void RefreshOne(Container container)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)container == (Object)null))
			{
				Camera main = Camera.main;
				Vector3 val = ((Component)container).transform.position + Vector3.up * 0.95f + ((Component)container).transform.forward * 0.35f;
				if ((Object)(object)main == (Object)null || !HasLineOfSight(main, val, container))
				{
					SetVisible(FindSlot(container), visible: false);
				}
				else
				{
					Apply(FindSlot(container), container, ChestNameStore.Get(container), main, val);
				}
			}
		}

		private static bool HasLineOfSight(Camera cam, Vector3 worldPos, Container container)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)cam == (Object)null || (Object)(object)container == (Object)null)
			{
				return false;
			}
			if (_losMask == int.MinValue)
			{
				_losMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "terrain", "piece", "piece_nonsolid", "vehicle" });
			}
			Vector3 position = ((Component)cam).transform.position;
			Vector3 val = worldPos - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.05f)
			{
				return true;
			}
			Vector3 val2 = val / magnitude;
			RaycastHit val3 = default(RaycastHit);
			if (!Physics.Raycast(position, val2, ref val3, magnitude - 0.08f, _losMask, (QueryTriggerInteraction)1))
			{
				return true;
			}
			if ((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null)
			{
				return ((Component)((RaycastHit)(ref val3)).collider).transform.IsChildOf(((Component)container).transform);
			}
			return false;
		}

		private Slot FindSlot(Container container)
		{
			for (int i = 0; i < _slots.Count; i++)
			{
				if ((Object)(object)_slots[i].Container == (Object)(object)container)
				{
					return _slots[i];
				}
			}
			Slot slot = new Slot
			{
				Container = container
			};
			_slots.Add(slot);
			return slot;
		}

		private static void SetVisible(Slot slot, bool visible)
		{
			if (!((Object)(object)slot?.Label == (Object)null))
			{
				((Component)slot.Label).gameObject.SetActive(visible);
			}
		}

		private static void Apply(Slot slot, Container container, string name, Camera cam, Vector3 world)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			if (slot == null)
			{
				return;
			}
			CleanupLegacy(container);
			if (string.IsNullOrEmpty(name))
			{
				if ((Object)(object)slot.Label != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)slot.Label).gameObject);
					slot.Label = null;
				}
				slot.Shown = null;
				return;
			}
			Font font = GetFont();
			if ((Object)(object)font == (Object)null)
			{
				return;
			}
			if ((Object)(object)slot.Label == (Object)null)
			{
				GameObject val = new GameObject("ChestChainSurfaceName");
				val.transform.SetParent(((Component)container).transform, false);
				slot.Label = val.AddComponent<TextMesh>();
				slot.Label.anchor = (TextAnchor)4;
				slot.Label.alignment = (TextAlignment)1;
				slot.Label.fontSize = 48;
				slot.Label.fontStyle = (FontStyle)1;
				slot.Label.characterSize = 0.05f;
				MeshRenderer component = val.GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)component).receiveShadows = false;
					((Renderer)component).sharedMaterial = GetLabelMaterial(font);
				}
			}
			TextMesh label = slot.Label;
			label.font = font;
			Renderer component2 = ((Component)label).GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.sharedMaterial = GetLabelMaterial(font);
			}
			label.color = Color.white;
			label.characterSize = 0.05f;
			if (slot.Shown != name)
			{
				label.text = name;
				slot.Shown = name;
			}
			((Component)label).transform.position = world;
			((Component)label).transform.localScale = Vector3.one;
			if ((Object)(object)cam != (Object)null)
			{
				Vector3 val2 = ((Component)cam).transform.position - world;
				if (((Vector3)(ref val2)).sqrMagnitude > 0.001f)
				{
					((Component)label).transform.rotation = Quaternion.LookRotation(-((Vector3)(ref val2)).normalized, Vector3.up);
				}
			}
			SetVisible(slot, visible: true);
		}

		private static Material GetLabelMaterial(Font font)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			if ((Object)(object)_labelMaterial != (Object)null)
			{
				return _labelMaterial;
			}
			if ((Object)(object)font != (Object)null && (Object)(object)font.material != (Object)null)
			{
				_labelMaterial = new Material(font.material);
			}
			else
			{
				_labelMaterial = new Material(Shader.Find("GUI/Text Shader") ?? Shader.Find("Sprites/Default"));
			}
			if (_labelMaterial.HasProperty("_ZTest"))
			{
				_labelMaterial.SetInt("_ZTest", 4);
			}
			_labelMaterial.renderQueue = 2010;
			return _labelMaterial;
		}

		private static void CleanupLegacy(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)container).transform;
			for (int num = transform.childCount - 1; num >= 0; num--)
			{
				Transform child = transform.GetChild(num);
				if (!((Object)(object)child == (Object)null) && !(((Object)child).name != "ChestChainSurfaceName") && (Object)(object)((Component)child).GetComponent<TextMesh>() == (Object)null)
				{
					Object.Destroy((Object)(object)((Component)child).gameObject);
				}
			}
		}

		private static Font GetFont()
		{
			if ((Object)(object)_font != (Object)null)
			{
				return _font;
			}
			Font[] array = Resources.FindObjectsOfTypeAll<Font>();
			foreach (Font val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					_font = val;
					return _font;
				}
			}
			_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			return _font;
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	public static class Container_Awake_LabelPatch
	{
		private static void Postfix(Container __instance)
		{
			ChestSurfaceLabels.Register(__instance);
		}
	}
	[HarmonyPatch(typeof(Container), "OnDestroyed")]
	public static class Container_OnDestroyed_LabelPatch
	{
		private static void Postfix(Container __instance)
		{
			ChestSurfaceLabels.Unregister(__instance);
		}
	}
	[HarmonyPatch(typeof(Container), "GetHoverName")]
	public static class Container_GetHoverName_Patch
	{
		private static void Postfix(Container __instance, ref string __result)
		{
			string text = ChestNameStore.Get(__instance);
			if (!string.IsNullOrEmpty(text))
			{
				__result = text;
			}
		}
	}
	public class KeyBindListener : MonoBehaviour
	{
		private ConfigEntry<KeyboardShortcut> _shortcut;

		private ConfigEntry<KeyCode> _key;

		private Text _label;

		private float _armedAt;

		private bool _listening;

		public static KeyBindListener Active { get; private set; }

		public void SetupShortcut(ConfigEntry<KeyboardShortcut> entry, Text label)
		{
			_shortcut = entry;
			_key = null;
			_label = label;
		}

		public void SetupKey(ConfigEntry<KeyCode> entry, Text label)
		{
			_key = entry;
			_shortcut = null;
			_label = label;
		}

		public void BeginListen()
		{
			if ((Object)(object)Active != (Object)null && (Object)(object)Active != (Object)(object)this)
			{
				Active.Cancel();
			}
			Active = this;
			_listening = true;
			_armedAt = Time.unscaledTime + 0.2f;
			if ((Object)(object)_label != (Object)null)
			{
				_label.text = "...";
			}
		}

		public void Cancel()
		{
			_listening = false;
			if ((Object)(object)Active == (Object)(object)this)
			{
				Active = null;
			}
			RefreshLabel();
		}

		private void Update()
		{
			//IL_004b: 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_0051: 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_0057: Invalid comparison between Unknown and I4
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Invalid comparison between Unknown and I4
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			//IL_0069: 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)
			if (!_listening || Time.unscaledTime < _armedAt)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				Cancel();
			}
			else
			{
				if (!Input.anyKeyDown)
				{
					return;
				}
				foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
				{
					if ((int)value != 0 && (int)value != 27 && (int)value != 323 && (int)value != 324 && Input.GetKeyDown(value))
					{
						Apply(value);
						break;
					}
				}
			}
		}

		private void Apply(KeyCode code)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (_shortcut != null)
			{
				_shortcut.Value = new KeyboardShortcut(code, Array.Empty<KeyCode>());
			}
			else if (_key != null)
			{
				_key.Value = code;
			}
			_listening = false;
			if ((Object)(object)Active == (Object)(object)this)
			{
				Active = null;
			}
			RefreshLabel();
		}

		public void RefreshLabel()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_label == (Object)null)
			{
				return;
			}
			if (_shortcut != null)
			{
				Text label = _label;
				KeyboardShortcut value = _shortcut.Value;
				object text;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
				{
					value = _shortcut.Value;
					text = ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString().ToUpperInvariant();
				}
				else
				{
					text = "НЕТ";
				}
				label.text = (string)text;
			}
			else if (_key != null)
			{
				_label.text = (((int)_key.Value == 0) ? "НЕТ" : ((object)_key.Value/*cast due to .constrained prefix*/).ToString().ToUpperInvariant());
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Active == (Object)(object)this)
			{
				Active = null;
			}
		}
	}
	public static class ModSettingsMenu
	{
		private static GameObject _root;

		private static Font _font;

		public static bool IsOpen => (Object)(object)_root != (Object)null;

		public static void Toggle()
		{
			if (IsOpen)
			{
				Close();
			}
			else
			{
				Open();
			}
		}

		public static void Close()
		{
			if ((Object)(object)KeyBindListener.Active != (Object)null)
			{
				KeyBindListener.Active.Cancel();
			}
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
				_root = null;
			}
		}

		public static void Open()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: 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_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Expected O, but got Unknown
			//IL_04af: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0511: Unknown result type (might be due to invalid IL or missing references)
			//IL_053d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0547: Expected O, but got Unknown
			if (!IsOpen && ChestChainPlugin.ModConfig != null)
			{
				ModConfig modConfig = ChestChainPlugin.ModConfig;
				_root = new GameObject("ChestChainSettingsCanvas");
				_root.layer = 5;
				Object.DontDestroyOnLoad((Object)(object)_root);
				Canvas obj = _root.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 999;
				CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				_root.AddComponent<GraphicRaycaster>();
				GameObject val = MakeRect("Background", _root.transform, new Color(0.08f, 0.08f, 0.1f, 0.96f));
				SetRect(val, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(720f, 780f), Vector2.zero);
				Outline obj3 = val.AddComponent<Outline>();
				((Shadow)obj3).effectColor = new Color(0.85f, 0.55f, 0.15f, 0.9f);
				((Shadow)obj3).effectDistance = new Vector2(2f, -2f);
				MakeText("Header", val.transform, "НАСТРОЙКИ CHEST CHAIN", 28, new Color(1f, 0.78f, 0.25f), (FontStyle)1);
				SetRect(((Component)val.transform.Find("Header")).gameObject, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(680f, 40f), new Vector2(0f, -28f));
				GameObject val2 = MakeRect("ScrollArea", val.transform, new Color(0f, 0f, 0f, 0.25f));
				SetRect(val2, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(680f, 620f), new Vector2(0f, 10f));
				ScrollRect val3 = val2.AddComponent<ScrollRect>();
				val3.horizontal = false;
				val3.vertical = true;
				val3.movementType = (MovementType)2;
				GameObject val4 = MakeRect("Viewport", val2.transform, new Color(0f, 0f, 0f, 0.01f));
				SetRect(val4, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero);
				val4.AddComponent<RectMask2D>();
				val3.viewport = val4.GetComponent<RectTransform>();
				GameObject obj4 = MakeRect("Content", val4.transform, new Color(0f, 0f, 0f, 0f));
				RectTransform component = obj4.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(0.5f, 1f);
				component.anchoredPosition = Vector2.zero;
				component.sizeDelta = new Vector2(0f, 0f);
				VerticalLayoutGroup obj5 = obj4.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj5).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)obj5).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj5).spacing = 6f;
				((LayoutGroup)obj5).padding = new RectOffset(8, 8, 8, 8);
				obj4.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
				val3.content = component;
				AddShortcutRow(obj4.transform, "Быстрая раскладка", modConfig.QuickStackKey);
				AddShortcutRow(obj4.transform, "Связать сундук", modConfig.LinkChestKey);
				AddShortcutRow(obj4.transform, "Отвязать сундук", modConfig.UnlinkChestKey);
				AddShortcutRow(obj4.transform, "Показать связь", modConfig.ShowLinkKey);
				AddShortcutRow(obj4.transform, "Замок предмета", modConfig.LockItemKey);
				AddShortcutRow(obj4.transform, "Имя сундука", modConfig.NameChestKey);
				AddKeyRow(obj4.transform, "Горячая клавиша меню", modConfig.MenuKey);
				AddFloatRow(obj4.transform, "Радиус поиска (м)", modConfig.SearchRadius, 1f);
				AddBoolRow(obj4.transform, "Не трогать надетое", modConfig.SkipEquipped);
				AddBoolRow(obj4.transform, "Не трогать хотбар", modConfig.SkipHotbar);
				AddBoolRow(obj4.transform, "Учитывать замок", modConfig.SkipCustomLocked);
				AddBoolRow(obj4.transform, "Пустые слоты в сундуке", modConfig.AllowEmptySlotsInMatchingChest);
				AddBoolRow(obj4.transform, "Отладка в лог", modConfig.EnableDebugLogging);
				GameObject val5 = MakeRect("CloseBtn", val.transform, new Color(0.65f, 0.15f, 0.12f, 1f));
				SetRect(val5, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(320f, 48f), new Vector2(0f, 28f));
				MakeText("CloseTxt", val5.transform, "ЗАКРЫТЬ И СОХРАНИТЬ", 20, Color.white, (FontStyle)1);
				Button obj6 = val5.AddComponent<Button>();
				((Selectable)obj6).targetGraphic = (Graphic)(object)val5.GetComponent<Image>();
				((UnityEvent)obj6.onClick).AddListener(new UnityAction(Close));
			}
		}

		private static void AddShortcutRow(Transform parent, string label, ConfigEntry<KeyboardShortcut> entry)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			GameObject val = MakeRow(parent, label);
			GameObject val2 = MakeRect("KeybindBtn", val.transform, new Color(0.2f, 0.35f, 0.55f, 1f));
			LayoutElement obj = val2.AddComponent<LayoutElement>();
			obj.minWidth = 160f;
			obj.preferredWidth = 160f;
			obj.flexibleWidth = 0f;
			Text val3 = MakeText("Txt", val2.transform, FormatShortcut(entry.Value), 18, Color.white, (FontStyle)1);
			val3.alignment = (TextAnchor)4;
			KeyBindListener listener = val2.AddComponent<KeyBindListener>();
			listener.SetupShortcut(entry, val3);
			Button obj2 = val2.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val2.GetComponent<Image>();
			((UnityEvent)obj2.onClick).AddListener(new UnityAction(listener.BeginListen));
			AddReset(val.transform, delegate
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				entry.Value = (KeyboardShortcut)((ConfigEntryBase)entry).DefaultValue;
				listener.RefreshLabel();
			});
		}

		private static void AddKeyRow(Transform parent, string label, ConfigEntry<KeyCode> entry)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			GameObject val = MakeRow(parent, label);
			GameObject val2 = MakeRect("KeybindBtn", val.transform, new Color(0.2f, 0.35f, 0.55f, 1f));
			LayoutElement obj = val2.AddComponent<LayoutElement>();
			obj.minWidth = 160f;
			obj.preferredWidth = 160f;
			Text val3 = MakeText("Txt", val2.transform, ((object)entry.Value/*cast due to .constrained prefix*/).ToString().ToUpperInvariant(), 18, Color.white, (FontStyle)1);
			val3.alignment = (TextAnchor)4;
			KeyBindListener listener = val2.AddComponent<KeyBindListener>();
			listener.SetupKey(entry, val3);
			Button obj2 = val2.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val2.GetComponent<Image>();
			((UnityEvent)obj2.onClick).AddListener(new UnityAction(listener.BeginListen));
			AddReset(val.transform, delegate
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				entry.Value = (KeyCode)((ConfigEntryBase)entry).DefaultValue;
				listener.RefreshLabel();
			});
		}

		private static void AddBoolRow(Transform parent, string label, ConfigEntry<bool> entry)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			GameObject val = MakeRow(parent, label);
			GameObject val2 = MakeRect("ToggleBtn", val.transform, entry.Value ? new Color(0.2f, 0.6f, 0.2f, 1f) : new Color(0.6f, 0.2f, 0.2f, 1f));
			LayoutElement obj = val2.AddComponent<LayoutElement>();
			obj.minWidth = 180f;
			obj.preferredWidth = 180f;
			Text text = MakeText("Txt", val2.transform, entry.Value ? "ВКЛЮЧЕНО" : "ВЫКЛЮЧЕНО", 18, Color.white, (FontStyle)1);
			text.alignment = (TextAnchor)4;
			Image image = val2.GetComponent<Image>();
			Button obj2 = val2.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)image;
			((UnityEvent)obj2.onClick).AddListener((UnityAction)delegate
			{
				//IL_005b: 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)
				entry.Value = !entry.Value;
				((Graphic)image).color = (entry.Value ? new Color(0.2f, 0.6f, 0.2f, 1f) : new Color(0.6f, 0.2f, 0.2f, 1f));
				text.text = (entry.Value ? "ВКЛЮЧЕНО" : "ВЫКЛЮЧЕНО");
			});
			AddReset(val.transform, delegate
			{
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				entry.Value = (bool)((ConfigEntryBase)entry).DefaultValue;
				((Graphic)image).color = (entry.Value ? new Color(0.2f, 0.6f, 0.2f, 1f) : new Color(0.6f, 0.2f, 0.2f, 1f));
				text.text = (entry.Value ? "ВКЛЮЧЕНО" : "ВЫКЛЮЧЕНО");
			});
		}

		private static void AddFloatRow(Transform parent, string label, ConfigEntry<float> entry, float step)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00c2: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			GameObject val = MakeRow(parent, label);
			GameObject val2 = MakeRect("FloatBox", val.transform, new Color(0.12f, 0.12f, 0.14f, 1f));
			LayoutElement obj = val2.AddComponent<LayoutElement>();
			obj.minWidth = 180f;
			obj.preferredWidth = 180f;
			HorizontalLayoutGroup obj2 = val2.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 4f;
			((LayoutGroup)obj2).padding = new RectOffset(4, 4, 4, 4);
			Text fieldText = null;
			GameObject val3 = MakeRect("Minus", val2.transform, new Color(0.3f, 0.3f, 0.35f, 1f));
			val3.AddComponent<LayoutElement>().preferredWidth = 36f;
			MakeText("T", val3.transform, "-", 22, Color.white, (FontStyle)1).alignment = (TextAnchor)4;
			((UnityEvent)val3.AddComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				entry.Value = Mathf.Max(2f, entry.Value - step);
				Refresh();
			});
			GameObject val4 = MakeRect("Value", val2.transform, new Color(0.05f, 0.05f, 0.06f, 1f));
			val4.AddComponent<LayoutElement>().flexibleWidth = 1f;
			fieldText = MakeText("T", val4.transform, entry.Value.ToString("0.#", CultureInfo.InvariantCulture), 18, Color.white, (FontStyle)1);
			fieldText.alignment = (TextAnchor)4;
			GameObject val5 = MakeRect("Plus", val2.transform, new Color(0.3f, 0.3f, 0.35f, 1f));
			val5.AddComponent<LayoutElement>().preferredWidth = 36f;
			MakeText("T", val5.transform, "+", 22, Color.white, (FontStyle)1).alignment = (TextAnchor)4;
			((UnityEvent)val5.AddComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				entry.Value = Mathf.Min(80f, entry.Value + step);
				Refresh();
			});
			AddReset(val.transform, delegate
			{
				entry.Value = (float)((ConfigEntryBase)entry).DefaultValue;
				Refresh();
			});
			void Refresh()
			{
				if ((Object)(object)fieldText != (Object)null)
				{
					fieldText.text = entry.Value.ToString("0.#", CultureInfo.InvariantCulture);
				}
			}
		}

		private static GameObject MakeRow(Transform parent, string label)
		{
			//IL_0020: 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_0083: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = MakeRect("Row_" + label, parent, new Color(1f, 1f, 1f, 0.06f));
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.minHeight = 44f;
			obj.preferredHeight = 44f;
			HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 10f;
			((LayoutGroup)obj2).padding = new RectOffset(10, 10, 4, 4);
			Text obj3 = MakeText("Label", val.transform, label, 18, Color.white, (FontStyle)0);
			obj3.alignment = (TextAnchor)3;
			((Component)obj3).gameObject.AddComponent<LayoutElement>().flexibleWidth = 1f;
			return val;
		}

		private static void AddReset(Transform row, Action onReset)
		{
			//IL_0027: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			GameObject val = MakeRect("Reset", row, new Color(0.2f, 0.4f, 0.7f, 1f));
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.minWidth = 36f;
			obj.preferredWidth = 36f;
			MakeText("T", val.transform, "↺", 20, Color.white, (FontStyle)1).alignment = (TextAnchor)4;
			((UnityEvent)val.AddComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				onReset();
			});
		}

		private static string FormatShortcut(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0)
			{
				return ((object)((KeyboardShortcut)(ref shortcut)).MainKey/*cast due to .constrained prefix*/).ToString().ToUpperInvariant();
			}
			return "НЕТ";
		}

		private static GameObject MakeRect(string name, Transform parent, Color color)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			})
			{
				layer = 5
			};
			val.transform.SetParent(parent, false);
			((Graphic)val.GetComponent<Image>()).color = color;
			return val;
		}

		private static Text MakeText(string name, Transform parent, string value, int size, Color color, FontStyle style)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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(Text)
			});
			val.layer = 5;
			val.transform.SetParent(parent, false);
			Text component = val.GetComponent<Text>();
			component.font = GetFont();
			component.text = value;
			component.fontSize = size;
			((Graphic)component).color = color;
			component.fontStyle = style;
			component.alignment = (TextAnchor)4;
			RectTransform component2 = val.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			return component;
		}

		private static void SetRect(GameObject go, Vector2 anchorMin, Vector2 anchorMax, Vector2 size, Vector2 anchored)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			component.sizeDelta = size;
			component.anchoredPosition = anchored;
		}

		private static Font GetFont()
		{
			if ((Object)(object)_font != (Object)null)
			{
				return _font;
			}
			Font[] array = Resources.FindObjectsOfTypeAll<Font>();
			foreach (Font val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					_font = val;
					return _font;
				}
			}
			_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			return _font;
		}
	}
}
namespace ValheimChestChain.QuickStack
{
	public static class ContainerFinder
	{
		private static readonly Collider[] OverlapBuffer = (Collider[])(object)new Collider[256];

		private static readonly List<Container> Result = new List<Container>(32);

		private static readonly List<Piece> PieceBuffer = new List<Piece>(64);

		private static readonly HashSet<int> Seen = new HashSet<int>();

		private static int _layerMask = int.MinValue;

		public static List<Container> FindNearby(Vector3 position, float radius)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			Result.Clear();
			Seen.Clear();
			PieceBuffer.Clear();
			Piece.GetAllPiecesInRadius(position, radius, PieceBuffer);
			for (int i = 0; i < PieceBuffer.Count; i++)
			{
				Piece val = PieceBuffer[i];
				if (!((Object)(object)val == (Object)null))
				{
					TryAdd(((Component)val).GetComponent<Container>(), position, radius);
					TryAdd(((Component)val).GetComponentInChildren<Container>(), position, radius);
				}
			}
			if (_layerMask == int.MinValue)
			{
				_layerMask = LayerMask.GetMask(new string[7] { "piece", "piece_nonsolid", "Default", "static_solid", "vehicle", "character_trigger", "item" });
			}
			int num = Physics.OverlapSphereNonAlloc(position, radius, OverlapBuffer, _layerMask, (QueryTriggerInteraction)2);
			for (int j = 0; j < num; j++)
			{
				Collider val2 = OverlapBuffer[j];
				if (!((Object)(object)val2 == (Object)null))
				{
					TryAdd(((Component)val2).GetComponentInParent<Container>(), position, radius, val2);
				}
			}
			if (Result.Count > 1)
			{
				Result.Sort((Container a, Container b) => DistanceToContainer(position, a).CompareTo(DistanceToContainer(position, b)));
			}
			return Result;
		}

		private static void TryAdd(Container container, Vector3 position, float radius, Collider hit = null)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			if (!((Object)(object)container == (Object)null) && IsUsableContainer(container))
			{
				int instanceID = ((Object)container).GetInstanceID();
				if (Seen.Add(instanceID) && !((((Object)(object)hit != (Object)null) ? Vector3.Distance(position, hit.ClosestPoint(position)) : DistanceToContainer(position, container)) > radius))
				{
					Result.Add(container);
				}
			}
		}

		private static float DistanceToContainer(Vector3 position, Container container)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)container == (Object)null)
			{
				return float.MaxValue;
			}
			Collider[] componentsInChildren = ((Component)container).GetComponentsInChildren<Collider>();
			float num = Vector3.Distance(position, ((Component)container).transform.position);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && val.enabled)
				{
					float num2 = Vector3.Distance(position, val.ClosestPoint(position));
					if (num2 < num)
					{
						num = num2;
					}
				}
			}
			return num;
		}

		public static bool IsUsableContainer(Container container)
		{
			if ((Object)(object)container != (Object)null && (Object)(object)container.m_nview != (Object)null && container.m_nview.IsValid())
			{
				return container.GetInventory() != null;
			}
			return false;
		}

		public static bool CanModify(Container container, Player player)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!IsUsableContainer(container) || (Object)(object)player == (Object)null || (Object)(object)Game.instance == (Object)null)
			{
				return false;
			}
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			if (!container.CheckAccess(playerID))
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false))
			{
				return false;
			}
			Container val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_currentContainer : null);
			if (container.IsInUse() && (Object)(object)val != (Object)(object)container)
			{
				return false;
			}
			if ((Object)(object)container.m_wagon != (Object)null && container.m_wagon.InUse() && (Object)(object)val != (Object)(object)container)
			{
				return false;
			}
			return true;
		}

		public static bool TryClaimForWrite(Container container)
		{
			return ContainerOwnership.TryClaimImmediate(container);
		}
	}
	public static class ContainerOwnership
	{
		private static readonly HashSet<ZDOID> QuietClaims = new HashSet<ZDOID>();

		public static bool IsQuietClaim(ZDOID id)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!((ZDOID)(ref id)).IsNone())
			{
				return QuietClaims.Contains(id);
			}
			return false;
		}

		public static IEnumerator EnsureOwner(Container container, float timeoutSeconds = 2.5f)
		{
			if ((Object)(object)container?.m_nview == (Object)null || !container.m_nview.IsValid())
			{
				yield break;
			}
			container.Load();
			if (container.m_nview.IsOwner())
			{
				yield break;
			}
			ZDO zDO = container.m_nview.GetZDO();
			if (zDO != null && !((Object)(object)Game.instance == (Object)null))
			{
				ZDOID id = zDO.m_uid;
				QuietClaims.Add(id);
				long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
				container.m_nview.InvokeRPC("RPC_RequestStack", new object[1] { playerID });
				float elapsed = 0f;
				while (elapsed < timeoutSeconds && !((Object)(object)container == (Object)null) && !((Object)(object)container.m_nview == (Object)null) && container.m_nview.IsValid() && !container.m_nview.IsOwner())
				{
					elapsed += Time.unscaledDeltaTime;
					yield return null;
				}
				QuietClaims.Remove(id);
			}
		}

		public static bool TryClaimImmediate(Container container)
		{
			if ((Object)(object)container?.m_nview == (Object)null || !container.m_nview.IsValid())
			{
				return false;
			}
			if (!container.m_nview.IsOwner())
			{
				container.m_nview.ClaimOwnership();
			}
			return container.m_nview.IsOwner();
		}
	}
	[HarmonyPatch(typeof(Container), "RPC_StackResponse")]
	public static class Container_RPC_StackResponse_QuietClaimPatch
	{
		private static bool Prefix(Container __instance, bool granted)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (__instance == null)
			{
				obj = null;
			}
			else
			{
				ZNetView nview = __instance.m_nview;
				obj = ((nview != null) ? nview.GetZDO() : null);
			}
			ZDO val = (ZDO)obj;
			if (val == null || !ContainerOwnership.IsQuietClaim(val.m_uid))
			{
				return true;
			}
			ChestChainPlugin.LogDebug("Quiet ownership response for " + ((Object)__instance).name + " granted=" + granted);
			return false;
		}
	}
	public static class QuickStackService
	{
		private static bool _running;

		public static void TryQuickStack()
		{
			if (_running)
			{
				MessageUtil.Center("Quick Stack уже идёт…");
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsTeleporting() && !((Object)(object)ChestChainPlugin.Instance == (Object)null))
			{
				((MonoBehaviour)ChestChainPlugin.Instance).StartCoroutine(RunQuickStack(localPlayer));
			}
		}

		private static IEnumerator RunQuickStack(Player player)
		{
			_running = true;
			int movedAmount = 0;
			try
			{
				Inventory playerInventory = ((Humanoid)player).GetInventory();
				if (playerInventory == null)
				{
					yield break;
				}
				float value = ChestChainPlugin.ModConfig.SearchRadius.Value;
				bool allowEmpty = ChestChainPlugin.ModConfig.AllowEmptySlotsInMatchingChest.Value;
				List<Container> nearby = ContainerFinder.FindNearby(((Component)player).transform.position, value);
				for (int i = 0; i < nearby.Count; i++)
				{
					Container obj = nearby[i];
					if (obj != null)
					{
						obj.Load();
					}
				}
				ChestChainPlugin.LogDebug($"QuickStack: found {nearby.Count} containers in radius {value}");
				List<ItemData> list = new List<ItemData>(playerInventory.GetAllItems());
				HashSet<Container> dirty = new HashSet<Container>();
				HashSet<ZDOID> ownedVisited = new HashSet<ZDOID>();
				foreach (ItemData item in list)
				{
					if (item == null || item.m_stack <= 0 || InventoryUtil.IsPinned(item, player) || !playerInventory.ContainsItem(item))
					{
						continue;
					}
					List<Container> list2 = FindSeedContainers(nearby, item, player);
					if (list2.Count == 0)
					{
						continue;
					}
					HashSet<ZDOID> chainVisited = new HashSet<ZDOID>();
					foreach (Container item2 in list2)
					{
						if (!playerInventory.ContainsItem(item) || item.m_stack <= 0)
						{
							break;
						}
						foreach (Container container in ChestLinkStore.ExpandChain(item2))
						{
							if (!playerInventory.ContainsItem(item) || item.m_stack <= 0)
							{
								break;
							}
							ZNetView nview = container.m_nview;
							ZDO val = ((nview != null) ? nview.GetZDO() : null);
							if ((val != null && !chainVisited.Add(val.m_uid)) || !ContainerFinder.CanModify(container, player))
							{
								continue;
							}
							if (val != null && ownedVisited.Add(val.m_uid))
							{
								yield return ContainerOwnership.EnsureOwner(container);
							}
							if ((Object)(object)container.m_nview == (Object)null || !container.m_nview.IsOwner())
							{
								ChestChainPlugin.LogDebug("QuickStack: no ownership for " + ((Object)container).name);
								continue;
							}
							container.Load();
							if (TryDepositInto(container, player, playerInventory, item, allowEmpty, out var moved) && moved > 0)
							{
								dirty.Add(container);
								movedAmount += moved;
							}
						}
					}
				}
				foreach (Container item3 in dirty)
				{
					if ((Object)(object)item3 != (Object)null && (Object)(object)item3.m_nview != (Object)null && item3.m_nview.IsOwner())
					{
						item3.Save();
					}
				}
			}
			finally
			{
				_running = false;
			}
			if (movedAmount > 0)
			{
				MessageUtil.Center($"Quick Stack: {movedAmount} items");
			}
			else
			{
				MessageUtil.Center("Quick Stack: nothing to store");
			}
		}

		private static bool TryDepositInto(Container container, Player player, Inventory playerInventory, ItemData item, bool allowEmptySlots, out int moved)
		{
			moved = 0;
			if (!ContainerFinder.CanModify(container, player))
			{
				return false;
			}
			Inventory inventory = container.GetInventory();
			if (inventory == null)
			{
				return false;
			}
			if (!InventoryUtil.ContainerHasMatchingItem(inventory, item) && !allowEmptySlots)
			{
				return false;
			}
			if (!InventoryUtil.TryMoveItem(playerInventory, inventory, item, allowEmptySlots, out moved) || moved <= 0)
			{
				return false;
			}
			return true;
		}

		private static List<Container> FindSeedContainers(List<Container> nearby, ItemData item, Player player)
		{
			List<Container> list = new List<Container>();
			foreach (Container item2 in nearby)
			{
				if (ContainerFinder.CanModify(item2, player))
				{
					Inventory inventory = item2.GetInventory();
					if (inventory != null && InventoryUtil.ContainerHasMatchingItem(inventory, item))
					{
						list.Add(item2);
					}
				}
			}
			return list;
		}
	}
}
namespace ValheimChestChain.Patches
{
	[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
	public static class InventoryGui_UpdateContainer_Patch
	{
		private static Container _lastContainer;

		private static void Postfix(InventoryGui __instance, Player player)
		{
			Container currentContainer = __instance.m_currentContainer;
			if ((Object)(object)currentContainer == (Object)null)
			{
				_lastContainer = null;
			}
			else if ((Object)(object)_lastContainer != (Object)(object)currentContainer)
			{
				_lastContainer = currentContainer;
				if (ChestChainPlugin.ModConfig != null && ChestChainPlugin.ModConfig.EnableDebugLogging.Value)
				{
					ChestChainPlugin.LogDebug("Open container link: " + ChestLinkStore.DescribeLink(currentContainer));
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui", new Type[]
	{
		typeof(Player),
		typeof(ItemData)
	})]
	public static class InventoryGrid_UpdateGui_Patch
	{
		private const string BadgeName = "ChestChainLock";

		private static Sprite _sprite;

		private static void Postfix(InventoryGrid __instance, Player player)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00e7: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null || __instance.m_elements == null || __instance.GetInventory() != ((Humanoid)player).GetInventory())
			{
				return;
			}
			LockService.TrackHover(__instance);
			InventoryUtil.SyncLocksFromInventory(__instance.GetInventory());
			List<InventoryElement> elements = __instance.m_elements;
			for (int i = 0; i < elements.Count; i++)
			{
				InventoryElement val = elements[i];
				if ((Object)(object)val?.m_icon == (Object)null)
				{
					continue;
				}
				RectTransform rectTransform = ((Graphic)val.m_icon).rectTransform;
				Transform val2 = ((Transform)rectTransform).Find("ChestChainLock");
				Image val3;
				if ((Object)(object)val2 == (Object)null)
				{
					val3 = CreateBadge(rectTransform);
				}
				else
				{
					val3 = ((Component)val2).GetComponent<Image>();
					if ((Object)(object)val3 == (Object)null)
					{
						Object.Destroy((Object)(object)((Component)val2).gameObject);
						val3 = CreateBadge(rectTransform);
					}
				}
				ItemData item = null;
				if (val.m_used)
				{
					Inventory inventory = __instance.GetInventory();
					Vector2i position = val.Position;
					item = ((inventory != null) ? inventory.GetItemAt(position.x, position.y) : null);
				}
				bool flag = InventoryUtil.IsCustomLocked(item);
				if (((Behaviour)val3).enabled != flag)
				{
					((Behaviour)val3).enabled = flag;
				}
				if ((Object)(object)val.m_icon != (Object)null)
				{
					((Graphic)val.m_icon).color = (Color)(flag ? new Color(1f, 0.85f, 0.2f, 1f) : Color.white);
				}
			}
		}

		private static Image CreateBadge(RectTransform icon)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ChestChainLock", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)icon, false);
			val.transform.SetAsLastSibling();
			Image obj = val.AddComponent<Image>();
			obj.sprite = GetSprite();
			((Graphic)obj).color = new Color(1f, 0.85f, 0.1f, 1f);
			((Graphic)obj).raycastTarget = false;
			((Behaviour)obj).enabled = false;
			RectTransform rectTransform = ((Graphic)obj).rectTransform;
			rectTransform.anchorMin = new Vector2(1f, 1f);
			rectTransform.anchorMax = new Vector2(1f, 1f);
			rectTransform.pivot = new Vector2(1f, 1f);
			rectTransform.sizeDelta = new Vector2(14f, 14f);
			rectTransform.anchoredPosition = new Vector2(1f, 1f);
			return obj;
		}

		private static Sprite GetSprite()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_sprite != (Object)null)
			{
				return _sprite;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)0;
			val.SetPixels((Color[])(object)new Color[4]
			{
				Color.white,
				Color.white,
				Color.white,
				Color.white
			});
			val.Apply();
			((Object)val).hideFlags = (HideFlags)61;
			_sprite = Sprite.Create(val, new Rect(0f, 0f, 2f, 2f), new Vector2(0.5f, 0.5f), 2f);
			((Object)_sprite).hideFlags = (HideFlags)61;
			return _sprite;
		}
	}
}
namespace ValheimChestChain.Linking
{
	public static class ChestLinkService
	{
		private static ZDOID _pendingSourceId = ZDOID.None;

		public static bool HasPendingSource => !((ZDOID)(ref _pendingSourceId)).IsNone();

		public static void TryToggleLink()
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			Container openContainer = GetOpenContainer();
			if ((Object)(object)openContainer == (Object)null)
			{
				if (HasPendingSource)
				{
					MessageUtil.Center("Источник выбран. Открой второй сундук и нажми связь");
				}
				else
				{
					MessageUtil.Center("Открой сундук для связи");
				}
				return;
			}
			ZNetView nview = openContainer.m_nview;
			ZDO val = ((nview != null) ? nview.GetZDO() : null);
			if (val == null)
			{
				MessageUtil.Center("Нет сетевых данных сундука");
				return;
			}
			if (!HasPendingSource)
			{
				if (!IsValidLinkTarget(openContainer))
				{
					MessageUtil.Center("Этот сундук нельзя связать");
					return;
				}
				_pendingSourceId = val.m_uid;
				MessageUtil.Center("Источник: " + ChestLinkStore.GetChestLabel(openContainer) + ". Открой следующий и нажми связь");
				return;
			}
			if (_pendingSourceId == val.m_uid)
			{
				MessageUtil.Center("Выбери другой сундук");
				return;
			}
			Container val2 = ChestLinkStore.ResolveContainer(_pendingSourceId);
			if ((Object)(object)val2 == (Object)null)
			{
				MessageUtil.Center("Источник пропал. Выбери заново");
				ClearPending();
			}
			else if (!IsValidLinkTarget(val2) || !IsValidLinkTarget(openContainer))
			{
				MessageUtil.Center("Нельзя связать эти сундуки");
				ClearPending();
			}
			else if (!ChestLinkStore.SetNext(val2, val.m_uid))
			{
				MessageUtil.Center("Не удалось записать связь (ownership)");
			}
			else
			{
				MessageUtil.Center("Связано: " + ChestLinkStore.DescribeLink(val2));
				ChestChainPlugin.LogDebug($"Linked {_pendingSourceId} -> {val.m_uid}");
				ClearPending();
			}
		}

		public static void TryUnlinkCurrent()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Container openContainer = GetOpenContainer();
			if ((Object)(object)openContainer == (Object)null)
			{
				MessageUtil.Center("Открой сундук для отвязки");
				return;
			}
			ZDOID nextId = ChestLinkStore.GetNextId(openContainer);
			if (((ZDOID)(ref nextId)).IsNone())
			{
				MessageUtil.Center("У этого сундука нет связи");
				return;
			}
			if (!ChestLinkStore.ClearNext(openContainer))
			{
				MessageUtil.Center("Не удалось убрать связь (ownership)");
				return;
			}
			ClearPending();
			MessageUtil.Center("Отвязано: " + ChestLinkStore.GetChestLabel(openContainer));
		}

		public static void ShowCurrentLink()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Container openContainer = GetOpenContainer();
			if ((Object)(object)openContainer == (Object)null)
			{
				if (HasPendingSource)
				{
					Container val = ChestLinkStore.ResolveContainer(_pendingSourceId);
					string text = (((Object)(object)val != (Object)null) ? ChestLinkStore.GetChestLabel(val) : ChestNameStore.Get(_pendingSourceId));
					if (string.IsNullOrEmpty(text))
					{
						text = "?";
					}
					MessageUtil.Center("Ждём второй сундук. Источник: " + text);
				}
				else
				{
					MessageUtil.Center("Открой сундук, чтобы посмотреть связь");
				}
			}
			else
			{
				MessageUtil.Center("Связь: " + ChestLinkStore.DescribeLink(openContainer));
			}
		}

		public static void ClearPending()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			_pendingSourceId = ZDOID.None;
		}

		private static Container GetOpenContainer()
		{
			if (!((Object)(object)InventoryGui.instance != (Object)null))
			{
				return null;
			}
			return InventoryGui.instance.m_currentContainer;
		}

		private static bool IsValidLinkTarget(Container container)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)container != (Object)null && (Object)(object)container.m_nview != (Object)null && container.m_nview.IsValid() && container.GetInventory() != null && (Object)(object)localPlayer != (Object)null && (Object)(object)Game.instance != (Object)null)
			{
				return container.CheckAccess(Game.instance.GetPlayerProfile().GetPlayerID());
			}
			return false;
		}
	}
	public static class ChestLinkStore
	{
		public const string NextLinkKey = "ChestChain.Next";

		public static ZDOID GetNextId(Container container)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (container == null)
			{
				obj = null;
			}
			else
			{
				ZNetView nview = container.m_nview;
				obj = ((nview != null) ? nview.GetZDO() : null);
			}
			ZDO val = (ZDO)obj;
			if (val == null)
			{
				return ZDOID.None;
			}
			return val.GetZDOID("ChestChain.Next");
		}

		public static bool SetNext(Container container, ZDOID nextId)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)container?.m_nview == (Object)null || !container.m_nview.IsValid())
			{
				return false;
			}
			if (!ContainerFinder.TryClaimForWrite(container))
			{
				return false;
			}
			ZDO zDO = container.m_nview.GetZDO();
			if (zDO == null)
			{
				return false;
			}
			zDO.Set("ChestChain.Next", nextId);
			return true;
		}

		public static bool ClearNext(Container container)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return SetNext(container, ZDOID.None);
		}

		public static Container ResolveContainer(ZDOID id)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (((ZDOID)(ref id)).IsNone() || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			GameObject val = ZNetScene.instance.FindInstance(id);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<Container>();
		}

		public static List<Container> ExpandChain(Container start)
		{
			//IL_0033: 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_0063: 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)
			List<Container> list = new List<Container>();
			if ((Object)(object)start == (Object)null)
			{
				return list;
			}
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			Container val = start;
			while ((Object)(object)val != (Object)null)
			{
				ZNetView nview = val.m_nview;
				ZDO val2 = ((nview != null) ? nview.GetZDO() : null);
				if (val2 == null)
				{
					break;
				}
				if (!hashSet.Add(val2.m_uid))
				{
					ChestChainPlugin.LogDebug("Link cycle detected at " + ((Object)val).name);
					break;
				}
				list.Add(val);
				ZDOID nextId = GetNextId(val);
				if (((ZDOID)(ref nextId)).IsNone())
				{
					break;
				}
				val = ResolveContainer(nextId);
			}
			return list;
		}

		public static string DescribeLink(Container container)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)container == (Object)null)
			{
				return "нет сундука";
			}
			List<string> list = new List<string>(4);
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			Container val = container;
			while ((Object)(object)val != (Object)null && list.Count < 6)
			{
				ZNetView nview = val.m_nview;
				ZDO val2 = ((nview != null) ? nview.GetZDO() : null);
				if (val2 == null || !hashSet.Add(val2.m_uid))
				{
					break;
				}
				list.Add(GetChestLabel(val));
				ZDOID nextId = GetNextId(val);
				if (((ZDOID)(ref nextId)).IsNone())
				{
					break;
				}
				Container val3 = ResolveContainer(nextId);
				if ((Object)(object)val3 == (Object)null)
				{
					string text = ChestNameStore.Get(nextId);
					list.Add(string.IsNullOrEmpty(text) ? "?" : text);
					break;
				}
				val = val3;
			}
			if (list.Count == 0)
			{
				return GetChestLabel(container);
			}
			if (list.Count == 1)
			{
				return list[0] + " > нет";
			}
			return string.Join(" > ", list.ToArray());
		}

		public static string GetChestLabel(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return "???";
			}
			string text = ChestNameStore.Get(container);
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			string text2 = container.m_name;
			if (string.IsNullOrEmpty(text2))
			{
				text2 = ((Object)container).name;
			}
			if (Localization.instance != null)
			{
				text2 = Localization.instance.Localize(text2);
			}
			return text2;
		}
	}
	public static class ChestNameStore
	{
		public const string NameKey = "ChestChain.Name";

		public const int MaxLength = 20;

		public static string Get(Container container)
		{
			object obj;
			if (container == null)
			{
				obj = null;
			}
			else
			{
				ZNetView nview = container.m_nview;
				obj = ((nview != null) ? nview.GetZDO() : null);
			}
			ZDO val = (ZDO)obj;
			if (val != null)
			{
				return val.GetString("ChestChain.Name", "");
			}
			return "";
		}

		public static string Get(ZDOID id)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (((ZDOID)(ref id)).IsNone() || ZDOMan.instance == null)
			{
				return "";
			}
			ZDO zDO = ZDOMan.instance.GetZDO(id);
			if (zDO != null)
			{
				return zDO.GetString("ChestChain.Name", "");
			}
			return "";
		}

		public static string Sanitize(string text)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return "";
			}
			text = text.Trim().Replace("\r", "").Replace("\n", " ")
				.Replace("\t", " ")
				.Replace("<", "")
				.Replace(">", "");
			if (text.Length > 20)
			{
				text = text.Substring(0, 20);
			}
			return text.Trim();
		}

		public static bool TrySet(Container container, string text)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			text = Sanitize(text);
			if ((Object)(object)container?.m_nview == (Object)null || !container.m_nview.IsValid())
			{
				return false;
			}
			if (Get(container) == text)
			{
				return true;
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Game.instance == (Object)null)
			{
				return false;
			}
			if (!container.CheckAccess(Game.instance.GetPlayerProfile().GetPlayerID()))
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false))
			{
				return false;
			}
			if (!ContainerFinder.TryClaimForWrite(container))
			{
				return false;
			}
			ZDO zDO = container.m_nview.GetZDO();
			if (zDO == null)
			{
				return false;
			}
			zDO.Set("ChestChain.Name", text);
			return true;
		}
	}
}
namespace ValheimChestChain.Input
{
	public static class InputBindings
	{
		public const string QuickStackName = "ChestChain_QuickStack";

		public const string LinkName = "ChestChain_Link";

		public const string UnlinkName = "ChestChain_Unlink";

		public const string ShowLinkName = "ChestChain_ShowLink";

		public const string LockItemName = "ChestChain_LockItem";

		public const string NameChestName = "ChestChain_NameChest";

		private static readonly List<ButtonConfig> _buttons = new List<ButtonConfig>();

		public static bool Ready { get; private set; }

		public static IReadOnlyList<ButtonConfig> Buttons => _buttons;

		public static void Register(ModConfig config)
		{
			_buttons.Clear();
			Ready = false;
			try
			{
				Add("ChestChain_QuickStack", "Быстрая раскладка", config.QuickStackKey, activeInGui: true);
				Add("ChestChain_Link", "Связать сундук", config.LinkChestKey, activeInGui: true);
				Add("ChestChain_Unlink", "Отвязать сундук", config.UnlinkChestKey, activeInGui: true);
				Add("ChestChain_ShowLink", "Показать связь", config.ShowLinkKey, activeInGui: true);
				Add("ChestChain_LockItem", "Замок предмета", config.LockItemKey, activeInGui: true);
				Add("ChestChain_NameChest", "Имя сундука", config.NameChestKey, activeInGui: true);
				Ready = true;
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to register keybinds: " + ex.Message));
			}
		}

		public static bool IsDown(string name)
		{
			if (ZInput.instance != null)
			{
				return ZInput.GetButtonDown(name);
			}
			return false;
		}

		private static void Add(string name, string hint, ConfigEntry<KeyboardShortcut> shortcut, bool activeInGui)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			ButtonConfig val = new ButtonConfig
			{
				Name = name,
				ShortcutConfig = shortcut,
				Hint = hint,
				ActiveInGUI = activeInGui
			};
			InputManager.Instance.AddButton("com.arkhamdc.valheimchestchain", val);
			_buttons.Add(val);
		}
	}
	public class InputHandler : MonoBehaviour
	{
		private ModConfig _config;

		private Action _onQuickStack;

		private Action _onLink;

		private Action _onUnlink;

		private Action _onShowLink;

		private Action _onLockItem;

		public void Init(ModConfig config, Action onQuickStack, Action onLink, Action onUnlink, Action onShowLink, Action onLockItem)
		{
			_config = config;
			_onQuickStack = onQuickStack;
			_onLink = onLink;
			_onUnlink = onUnlink;
			_onShowLink = onShowLink;
			_onLockItem = onLockItem;
		}

		private void Update()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (_config == null)
			{
				return;
			}
			if ((Object)(object)KeyBindListener.Active == (Object)null && (int)_config.MenuKey.Value != 0 && Input.GetKeyDown(_config.MenuKey.Value))
			{
				ModSettingsMenu.Toggle();
			}
			else if (ModSettingsMenu.IsOpen)
			{
				if (Input.GetKeyDown((KeyCode)27))
				{
					ModSettingsMenu.Close();
				}
			}
			else
			{
				if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)KeyBindListener.Active != (Object)null)
				{
					return;
				}
				try
				{
					if (((Object)(object)Console.instance != (Object)null && Console.IsVisible()) || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || TextInput.IsVisible())
					{
						return;
					}
				}
				catch
				{
					return;
				}
				if (IsDown(_config.QuickStackKey))
				{
					_onQuickStack?.Invoke();
				}
				if (IsDown(_config.LinkChestKey))
				{
					_onLink?.Invoke();
				}
				if (IsDown(_config.UnlinkChestKey))
				{
					_onUnlink?.