Decompiled source of StorageMaster v1.2.0

plugins/StorageMaster.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using StorageMaster.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("StorageMaster")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+656f6cdc0c82eef34ee69a3d2da81e2276f138ce")]
[assembly: AssemblyProduct("StorageMaster")]
[assembly: AssemblyTitle("StorageMaster")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace StorageMaster
{
	public static class ChestAccess
	{
		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPatch(typeof(Container), "RPC_StackResponse")]
			[HarmonyPrefix]
			private static bool StackResponse(Container __instance, bool granted)
			{
				if (!_waiting.TryGetValue(__instance, out var value))
				{
					return true;
				}
				_waiting.Remove(__instance);
				value(granted);
				return false;
			}

			[HarmonyPatch(typeof(Container), "GetHoverText")]
			[HarmonyPostfix]
			private static void HoverText(Container __instance, ref string __result)
			{
				string text = GetLabel(__instance);
				if (Exclusions.IsExcluded(__instance))
				{
					text = (string.IsNullOrEmpty(text) ? "" : (text + "  ")) + "<size=80%><color=#a9a49c>(skipped by Storage Master)</color></size>";
				}
				if (!string.IsNullOrEmpty(text))
				{
					__result = "<color=#ffa13c>" + text + "</color>\n" + __result;
				}
			}
		}

		private const string LabelKey = "InventoryTools.Label";

		private static readonly Dictionary<Container, Action<bool>> _waiting = new Dictionary<Container, Action<bool>>();

		public static void Request(Container c, Action<bool> onAnswer)
		{
			_waiting[c] = onAnswer;
			c.StackAll();
		}

		public static void Forget(Container c)
		{
			_waiting.Remove(c);
		}

		public static List<Container> FindNearby(float range)
		{
			//IL_006a: 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)
			List<Container> list = new List<Container>();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return list;
			}
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
			foreach (Container val in array)
			{
				if (Usable(val, localPlayer, playerID, range))
				{
					list.Add(val);
				}
			}
			Vector3 p = ((Component)localPlayer).transform.position;
			list.Sort((Container a, Container b) => Vector3.Distance(((Component)a).transform.position, p).CompareTo(Vector3.Distance(((Component)b).transform.position, p)));
			return list;
		}

		private static bool Usable(Container c, Player player, long playerID, float range)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c == (Object)null || (Object)(object)c.m_nview == (Object)null || !c.m_nview.IsValid())
			{
				return false;
			}
			if (Vector3.Distance(((Component)c).transform.position, ((Component)player).transform.position) > range)
			{
				return false;
			}
			if ((Object)(object)((Component)c).GetComponent<TombStone>() != (Object)null)
			{
				return false;
			}
			if (c.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false))
			{
				return false;
			}
			return c.CheckAccess(playerID);
		}

		public static string GetLabel(Container c)
		{
			if (!((Object)(object)c != (Object)null) || !((Object)(object)c.m_nview != (Object)null) || !c.m_nview.IsValid())
			{
				return "";
			}
			return c.m_nview.GetZDO().GetString("InventoryTools.Label", "");
		}

		public static void SetLabel(Container c, string label)
		{
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c.m_nview == (Object)null) && c.m_nview.IsValid() && c.m_nview.IsOwner())
			{
				c.m_nview.GetZDO().Set("InventoryTools.Label", (label ?? "").Trim());
			}
		}
	}
	public static class ChestRename
	{
		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
			[HarmonyPostfix]
			private static void UpdateContainer(InventoryGui __instance)
			{
				Ensure(__instance);
				if ((Object)(object)_field == (Object)null)
				{
					return;
				}
				Container currentContainer = __instance.m_currentContainer;
				bool flag = (Object)(object)currentContainer != (Object)null && (Object)(object)currentContainer.m_nview != (Object)null && currentContainer.m_nview.IsValid() && (Object)(object)((Component)currentContainer).GetComponent<TombStone>() == (Object)null;
				if ((Object)(object)currentContainer != (Object)(object)_shown)
				{
					Save();
					_shown = (flag ? currentContainer : null);
					if ((Object)(object)_shown != (Object)null)
					{
						_field.SetTextWithoutNotify(ChestAccess.GetLabel(_shown));
					}
				}
				((Component)_field).gameObject.SetActive(flag);
				((Behaviour)__instance.m_containerName).enabled = !flag;
				if (!flag)
				{
					((Component)_reset).gameObject.SetActive(false);
					return;
				}
				Position(__instance.m_containerName);
				bool flag2 = currentContainer.IsOwner();
				((Selectable)_field).interactable = flag2;
				string label = ChestAccess.GetLabel(currentContainer);
				Graphic placeholder = _field.placeholder;
				TMP_Text val = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
				if (val != null)
				{
					val.text = __instance.m_containerName.text;
				}
				if (!_field.isFocused && _field.text != label)
				{
					_field.SetTextWithoutNotify(label);
				}
				((Component)_reset).gameObject.SetActive(flag2 && label.Length > 0);
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__ResetName;
		}

		private const float FieldW = 260f;

		private const float FieldH = 38f;

		private const float ResetSize = 28f;

		private static TMP_InputField _field;

		private static Button _reset;

		private static Container _shown;

		private static int _swallowUntilFrame = -10;

		public static bool BlocksInput
		{
			get
			{
				if (!((Object)(object)_field != (Object)null) || !((Component)_field).gameObject.activeInHierarchy || !_field.isFocused)
				{
					return Time.frameCount <= _swallowUntilFrame;
				}
				return true;
			}
		}

		private static void Ensure(InventoryGui gui)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: 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_01fa: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_field != (Object)null || (Object)(object)gui.m_containerName == (Object)null || !UIKit.Init())
			{
				return;
			}
			_field = UIKit.InputField(gui.m_containerName.transform.parent, "", 260f, 38f, plain: true);
			((Object)_field).name = "StorageMaster_ChestName";
			TMP_Text[] array = (TMP_Text[])(object)new TMP_Text[2]
			{
				_field.textComponent,
				(TMP_Text)/*isinst with value type is only supported in some contexts*/
			};
			foreach (TMP_Text val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.fontSize = 22f;
					val.enableAutoSizing = false;
					val.alignment = (TextAlignmentOptions)514;
				}
			}
			((Graphic)_field.textComponent).color = UIKit.Parchment;
			_field.characterLimit = 32;
			((UnityEvent<string>)(object)_field.onEndEdit).AddListener((UnityAction<string>)delegate
			{
				Save();
				_swallowUntilFrame = Time.frameCount + 1;
				if ((Object)(object)EventSystem.current != (Object)null)
				{
					EventSystem.current.SetSelectedGameObject((GameObject)null);
				}
			});
			UIKit.Tooltip(((Component)_field).gameObject, "Click to name this chest, then press Enter. The name shows when you look at it and in the Storage window.");
			Transform transform = ((Component)_field).transform;
			object obj = <>O.<0>__ResetName;
			if (obj == null)
			{
				UnityAction val2 = ResetName;
				<>O.<0>__ResetName = val2;
				obj = (object)val2;
			}
			_reset = UIKit.Button(transform, "X", (UnityAction)obj, 28f, 28f);
			((Object)_reset).name = "StorageMaster_ResetName";
			RectTransform val3 = (RectTransform)((Component)_reset).transform;
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(1f, 0.5f);
			val3.pivot = val4;
			Vector2 anchorMin = (val3.anchorMax = val4);
			val3.anchorMin = anchorMin;
			val3.anchoredPosition = new Vector2(-5f, 0f);
			RectTransform textViewport = _field.textViewport;
			if ((Object)(object)textViewport != (Object)null)
			{
				textViewport.offsetMin = new Vector2(36f, textViewport.offsetMin.y);
				textViewport.offsetMax = new Vector2(-36f, textViewport.offsetMax.y);
			}
			UIKit.Tooltip(((Component)_reset).gameObject, "Remove the name.");
		}

		private static void Save()
		{
			if (!((Object)(object)_shown == (Object)null) && !((Object)(object)_field == (Object)null) && _field.text.Trim() != ChestAccess.GetLabel(_shown))
			{
				ChestAccess.SetLabel(_shown, _field.text);
			}
		}

		private static void ResetName()
		{
			if (!((Object)(object)_shown == (Object)null))
			{
				ChestAccess.SetLabel(_shown, "");
				_field.SetTextWithoutNotify("");
				if ((Object)(object)EventSystem.current != (Object)null)
				{
					EventSystem.current.SetSelectedGameObject((GameObject)null);
				}
			}
		}

		private static void Position(TMP_Text title)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = title.rectTransform;
			RectTransform val = (RectTransform)((Component)_field).transform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			val.pivot = val2;
			Vector2 anchorMin = (val.anchorMax = val2);
			val.anchorMin = anchorMin;
			val.sizeDelta = new Vector2(260f, 38f);
			Rect rect = rectTransform.rect;
			((Transform)val).position = ((Transform)rectTransform).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center));
		}
	}
	public static class Exclusions
	{
		private const string Key = "InventoryTools.Excluded";

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

		private static Player _loadedFor;

		public static bool IsExcluded(Container c)
		{
			string text = Id(c);
			if (text == null)
			{
				return false;
			}
			EnsureLoaded();
			return _excluded.Contains(text);
		}

		public static void Set(Container c, bool excluded)
		{
			Player localPlayer = Player.m_localPlayer;
			string text = Id(c);
			if (!((Object)(object)localPlayer == (Object)null) && text != null)
			{
				EnsureLoaded();
				if (excluded)
				{
					_excluded.Add(text);
				}
				else
				{
					_excluded.Remove(text);
				}
				localPlayer.m_customData["InventoryTools.Excluded"] = string.Join(";", _excluded);
			}
		}

		private static string Id(Container c)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c == (Object)null || (Object)(object)c.m_nview == (Object)null || !c.m_nview.IsValid())
			{
				return null;
			}
			ZDOID uid = c.m_nview.GetZDO().m_uid;
			return $"{((ZDOID)(ref uid)).UserID}:{((ZDOID)(ref uid)).ID}";
		}

		private static void EnsureLoaded()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)(object)_loadedFor)
			{
				return;
			}
			_loadedFor = localPlayer;
			_excluded.Clear();
			if (!((Object)(object)localPlayer == (Object)null) && localPlayer.m_customData.TryGetValue("InventoryTools.Excluded", out var value))
			{
				string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string item in array)
				{
					_excluded.Add(item);
				}
			}
		}
	}
	public static class ExtraSlotsCompat
	{
		public const string Guid = "shudnal.ExtraSlots";

		private static bool _looked;

		private static Func<int> _playerRows;

		private static Func<Vector2i, bool> _isSlot;

		public static bool Active
		{
			get
			{
				Init();
				return _isSlot != null;
			}
		}

		public static int PlayerRows(Inventory inventory)
		{
			Init();
			if (_playerRows == null)
			{
				return inventory.GetHeight();
			}
			return Mathf.Clamp(_playerRows(), 1, inventory.GetHeight());
		}

		public static bool IsSlot(Vector2i pos)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Init();
			if (_isSlot != null)
			{
				return _isSlot(pos);
			}
			return false;
		}

		public static bool IsOutsideRegularRows(Inventory inventory, Vector2i pos)
		{
			//IL_0000: 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)
			if (pos.y < PlayerRows(inventory))
			{
				return IsSlot(pos);
			}
			return true;
		}

		private static void Init()
		{
			if (_looked)
			{
				return;
			}
			_looked = true;
			if (Chainloader.PluginInfos.TryGetValue("shudnal.ExtraSlots", out var value) && !((Object)(object)value.Instance == (Object)null))
			{
				Type? type = ((object)value.Instance).GetType().Assembly.GetType("ExtraSlots.API");
				MethodInfo methodInfo = type?.GetMethod("GetInventoryHeightPlayer", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
				MethodInfo methodInfo2 = type?.GetMethod("IsGridPositionASlot", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Vector2i) }, null);
				if (methodInfo == null || methodInfo2 == null)
				{
					Debug.LogWarning((object)"[Storage Master] ExtraSlots is loaded, but its API wasn't found. Its slots may get sorted.");
					return;
				}
				_playerRows = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), methodInfo);
				_isSlot = (Func<Vector2i, bool>)Delegate.CreateDelegate(typeof(Func<Vector2i, bool>), methodInfo2);
			}
		}
	}
	public static class InventoryButtons
	{
		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPatch(typeof(Humanoid), "Pickup")]
			[HarmonyPostfix]
			private static void Pickup(Humanoid __instance, bool __result)
			{
				if (__result && Plugin.AutoSort.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					Sorter.SortPlayer(silent: true);
				}
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__CycleMode;

			public static UnityAction <1>__Run;

			public static UnityAction <2>__ToggleAutoSort;

			public static UnityAction <3>__Open;

			public static UnityAction <4>__Open;

			public static UnityAction <5>__Open;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__15_0;

			internal void <Ensure>b__15_0()
			{
				Sorter.SortPlayer(silent: false);
			}
		}

		private const float ButtonW = 160f;

		private const float ButtonH = 36f;

		private const float Gap = 4f;

		private const float Pad = 8f;

		private static Button _sort;

		private static Button _mode;

		private static Button _quickStack;

		private static Button _autoSort;

		private static Button _storage;

		private static Button _info;

		private static Button _options;

		private static Button _sortChest;

		private static Button _chestMode;

		private static Badge _badge;

		private static Badge _chestBadge;

		public static void Ensure()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_014e: 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)
			//IL_0159: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Expected O, but got Unknown
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Expected O, but got Unknown
			InventoryGui gui = InventoryGui.instance;
			if ((Object)(object)gui == (Object)null || (Object)(object)gui.m_player == (Object)null)
			{
				return;
			}
			if ((Object)(object)_badge != (Object)null)
			{
				if (InventoryGui.IsVisible())
				{
					_badge.Apply();
					if ((Object)(object)_chestBadge != (Object)null && ((Component)_chestBadge).gameObject.activeInHierarchy)
					{
						_chestBadge.Apply();
					}
				}
			}
			else
			{
				if (!UIKit.Init() || (Object)(object)gui.m_weight == (Object)null)
				{
					return;
				}
				RectTransform menu = Menu("StorageMaster_Menu", 7);
				object obj = <>c.<>9__15_0;
				if (obj == null)
				{
					UnityAction val = delegate
					{
						Sorter.SortPlayer(silent: false);
					};
					<>c.<>9__15_0 = val;
					obj = (object)val;
				}
				_sort = Make(menu, "Sort", (UnityAction)obj, 0, "Sorts everything below the hotbar and merges partial stacks.\nAlt + click a slot to lock it, so Sort leaves it alone.");
				object obj2 = <>O.<0>__CycleMode;
				if (obj2 == null)
				{
					UnityAction val2 = Sorter.CycleMode;
					<>O.<0>__CycleMode = val2;
					obj2 = (object)val2;
				}
				_mode = Make(menu, "", (UnityAction)obj2, 1, "Click to change what Sort orders by.");
				object obj3 = <>O.<1>__Run;
				if (obj3 == null)
				{
					UnityAction val3 = QuickStack.Run;
					<>O.<1>__Run = val3;
					obj3 = (object)val3;
				}
				_quickStack = Make(menu, "Quick stack", (UnityAction)obj3, 2, "Puts your items into nearby chests that already hold the same kind of item.\nThe hotbar, equipped items and locked slots stay with you.");
				object obj4 = <>O.<2>__ToggleAutoSort;
				if (obj4 == null)
				{
					UnityAction val4 = Plugin.ToggleAutoSort;
					<>O.<2>__ToggleAutoSort = val4;
					obj4 = (object)val4;
				}
				_autoSort = Make(menu, "", (UnityAction)obj4, 3, "Sort automatically every time you pick something up.");
				object obj5 = <>O.<3>__Open;
				if (obj5 == null)
				{
					UnityAction val5 = StorageWindow.Open;
					<>O.<3>__Open = val5;
					obj5 = (object)val5;
				}
				_storage = Make(menu, "Storage", (UnityAction)obj5, 4, "Opens every chest nearby in one window, to move, find, gather and tidy up items.");
				object obj6 = <>O.<4>__Open;
				if (obj6 == null)
				{
					UnityAction val6 = InfoWindow.Open;
					<>O.<4>__Open = val6;
					obj6 = (object)val6;
				}
				_info = Make(menu, "Info", (UnityAction)obj6, 5, "How Storage Master works, and its hotkeys.");
				object obj7 = <>O.<5>__Open;
				if (obj7 == null)
				{
					UnityAction val7 = OptionsWindow.Open;
					<>O.<5>__Open = val7;
					obj7 = (object)val7;
				}
				_options = Make(menu, "Options", (UnityAction)obj7, 6, "Hotkeys, settings, and the menu buttons' drag key and positions (Reset puts a menu button back).");
				_badge = Badge.Create(gui.m_player, BoxOf(gui.m_player, gui.m_weight), "StorageMaster_Badge", menu, Plugin.InventoryMenuOpen, Plugin.InventoryBadgeX, Plugin.InventoryBadgeY, (Transform)(((Object)(object)gui.m_armor != (Object)null) ? BoxOf(gui.m_player, gui.m_armor) : null));
				if ((Object)(object)gui.m_container != (Object)null && (Object)(object)gui.m_containerWeight != (Object)null)
				{
					RectTransform menu2 = Menu("StorageMaster_ChestMenu", 2);
					_sortChest = Make(menu2, "Sort chest", (UnityAction)delegate
					{
						Sorter.SortContainer(gui.m_currentContainer);
					}, 0, "Sorts this chest (merging partial stacks) using the same order as your inventory.");
					object obj8 = <>O.<0>__CycleMode;
					if (obj8 == null)
					{
						UnityAction val8 = Sorter.CycleMode;
						<>O.<0>__CycleMode = val8;
						obj8 = (object)val8;
					}
					_chestMode = Make(menu2, "", (UnityAction)obj8, 1, "Click to change what Sort and Sort chest order by.");
					_chestBadge = Badge.Create(gui.m_container, BoxOf(gui.m_container, gui.m_containerWeight), "StorageMaster_ChestBadge", menu2, Plugin.ChestMenuOpen, Plugin.ChestBadgeX, Plugin.ChestBadgeY);
				}
				Refresh();
			}
		}

		private static RectTransform BoxOf(RectTransform panel, TMP_Text text)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			Transform val = text.transform;
			while ((Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)panel)
			{
				val = val.parent;
			}
			return (RectTransform)(((Object)(object)val.parent == (Object)(object)panel) ? val : text.transform.parent);
		}

		public static void ApplyBadges()
		{
			if ((Object)(object)_badge != (Object)null)
			{
				_badge.Apply();
			}
			if ((Object)(object)_chestBadge != (Object)null)
			{
				_chestBadge.Apply();
			}
		}

		public static void Refresh()
		{
			Button[] array = (Button[])(object)new Button[2] { _mode, _chestMode };
			foreach (Button val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.SetLabel("By: " + Sorter.ModeLabel);
				}
			}
			if ((Object)(object)_autoSort != (Object)null)
			{
				_autoSort.SetLabel(Plugin.AutoSort.Value ? "Auto-sort: <color=#8fd16a>On</color>" : "Auto-sort: Off");
			}
		}

		private static RectTransform Menu(string name, int buttons)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = ((Graphic)UIKit.DarkPanel(UIKit.CanvasRoot, name)).rectTransform;
			rectTransform.sizeDelta = new Vector2(176f, (float)buttons * 36f + (float)(buttons - 1) * 4f + 16f);
			return rectTransform;
		}

		private static Button Make(RectTransform menu, string label, UnityAction onClick, int index, string tooltip)
		{
			//IL_0019: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0048: 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)
			Button obj = UIKit.Button((Transform)(object)menu, label, onClick, 160f, 36f);
			RectTransform val = (RectTransform)((Component)obj).transform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f, 1f);
			val.anchorMax = val2;
			val.anchorMin = val2;
			val.pivot = new Vector2(0f, 1f);
			val.anchoredPosition = new Vector2(8f, -8f - (float)index * 40f);
			UIKit.Tooltip(((Component)obj).gameObject, tooltip);
			return obj;
		}
	}
	public static class Locks
	{
		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPatch(typeof(InventoryGrid), "OnLeftDown")]
			[HarmonyPrefix]
			private static bool OnLeftDown(InventoryGrid __instance, UIInputHandler clickHandler)
			{
				//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_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				if (!AltHeld() || !IsPlayerGrid(__instance))
				{
					return true;
				}
				Vector2i buttonPos = __instance.GetButtonPos(((Component)clickHandler).gameObject);
				if (buttonPos.x >= 0)
				{
					Toggle(buttonPos);
				}
				return false;
			}

			[HarmonyPatch(typeof(InventoryGrid), "OnLeftClick")]
			[HarmonyPrefix]
			private static bool OnLeftClick(InventoryGrid __instance)
			{
				if (AltHeld())
				{
					return !IsPlayerGrid(__instance);
				}
				return true;
			}

			[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
			[HarmonyPostfix]
			private static void UpdateGui(InventoryGrid __instance)
			{
				if (IsPlayerGrid(__instance))
				{
					DrawOverlays(__instance);
				}
			}
		}

		private const string Key = "InventoryTools.Locks";

		private const string OverlayName = "StorageMaster_Lock";

		private static readonly HashSet<Vector2i> _locked = new HashSet<Vector2i>();

		private static Player _loadedFor;

		private static Sprite _lockSprite;

		private static bool _searchedSprite;

		public static bool IsLocked(int x, int y)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			EnsureLoaded();
			return _locked.Contains(new Vector2i(x, y));
		}

		public static void Toggle(Vector2i pos)
		{
			//IL_001a: 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)
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				EnsureLoaded();
				bool flag = !_locked.Remove(pos);
				if (flag)
				{
					_locked.Add(pos);
				}
				localPlayer.m_customData["InventoryTools.Locks"] = string.Join(";", _locked.Select((Vector2i p) => $"{p.x},{p.y}"));
				((Character)localPlayer).Message((MessageType)1, flag ? "Slot locked: Sort and quick stack will leave it alone" : "Slot unlocked", 0, (Sprite)null, false);
			}
		}

		private static void EnsureLoaded()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)(object)_loadedFor)
			{
				return;
			}
			_loadedFor = localPlayer;
			_locked.Clear();
			if ((Object)(object)localPlayer == (Object)null || !localPlayer.m_customData.TryGetValue("InventoryTools.Locks", out var value))
			{
				return;
			}
			string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(',');
				if (array2.Length == 2 && int.TryParse(array2[0], out var result) && int.TryParse(array2[1], out var result2))
				{
					_locked.Add(new Vector2i(result, result2));
				}
			}
		}

		private static bool IsPlayerGrid(InventoryGrid grid)
		{
			if ((Object)(object)InventoryGui.instance != (Object)null)
			{
				return (Object)(object)grid == (Object)(object)InventoryGui.instance.m_playerGrid;
			}
			return false;
		}

		private static bool AltHeld()
		{
			if (!Input.GetKey((KeyCode)308))
			{
				return Input.GetKey((KeyCode)307);
			}
			return true;
		}

		public static void DrawOverlays(InventoryGrid grid)
		{
			//IL_0020: 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)
			foreach (InventoryElement element in grid.m_elements)
			{
				if ((Object)(object)element == (Object)null)
				{
					continue;
				}
				bool flag = IsLocked(element.Position.x, element.Position.y);
				Transform val = ((Component)element).transform.Find("StorageMaster_Lock");
				if ((Object)(object)val == (Object)null)
				{
					if (!flag)
					{
						continue;
					}
					val = CreateOverlay(((Component)element).transform);
				}
				((Component)val).gameObject.SetActive(flag);
			}
		}

		private static Transform CreateOverlay(Transform slot)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if (!_searchedSprite)
			{
				_searchedSprite = true;
				string[] names = new string[6] { "lock", "Lock", "icon_lock", "padlock", "locked", "Locked" };
				_lockSprite = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => (Object)(object)s != (Object)null && names.Contains(((Object)s).name)));
			}
			RectTransform obj = UIKit.Rect(slot, "StorageMaster_Lock").Fill();
			Image obj2 = ((Component)obj).gameObject.AddComponent<Image>();
			((Graphic)obj2).color = new Color(1f, 0.631f, 0.235f, 0.18f);
			((Graphic)obj2).raycastTarget = false;
			RectTransform val = UIKit.Rect((Transform)(object)obj, "badge");
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 1f);
			val.pivot = val2;
			Vector2 anchorMin = (val.anchorMax = val2);
			val.anchorMin = anchorMin;
			val.anchoredPosition = new Vector2(-2f, -2f);
			val.sizeDelta = new Vector2(16f, 16f);
			Image val4 = ((Component)val).gameObject.AddComponent<Image>();
			((Graphic)val4).raycastTarget = false;
			if ((Object)(object)_lockSprite != (Object)null)
			{
				val4.sprite = _lockSprite;
				val4.preserveAspect = true;
				return (Transform)(object)obj;
			}
			((Graphic)val4).color = new Color(1f, 0.631f, 0.235f, 0.95f);
			val.sizeDelta = new Vector2(8f, 8f);
			return (Transform)(object)obj;
		}
	}
	[BepInPlugin("charmingbeaver.valheim.storagemaster", "Storage Master", "1.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public enum DragKeys
		{
			Ctrl,
			Shift,
			Alt
		}

		public const string Guid = "charmingbeaver.valheim.storagemaster";

		public const string Name = "Storage Master";

		public const string Version = "1.2.0";

		public static ConfigEntry<Sorter.Mode> SortMode;

		public static ConfigEntry<bool> AutoSort;

		public static ConfigEntry<float> QuickStackRange;

		public static ConfigEntry<bool> QuickStackSkipsHotbar;

		public static ConfigEntry<float> StorageRange;

		public static ConfigEntry<int> StorageMaxChests;

		public static ConfigEntry<bool> StorageShowInventory;

		public static ConfigEntry<DragKeys> DragKey;

		public static ConfigEntry<bool> InventoryMenuOpen;

		public static ConfigEntry<int> InventoryBadgeX;

		public static ConfigEntry<int> InventoryBadgeY;

		public static ConfigEntry<bool> ChestMenuOpen;

		public static ConfigEntry<int> ChestBadgeX;

		public static ConfigEntry<int> ChestBadgeY;

		public static ConfigEntry<KeyboardShortcut> StorageKey;

		public static ConfigEntry<KeyboardShortcut> SortKey;

		public static ConfigEntry<KeyboardShortcut> QuickStackKey;

		public static ConfigEntry<KeyboardShortcut> AutoSortKey;

		public static ConfigEntry<KeyboardShortcut> InfoKey;

		public static ConfigEntry<KeyboardShortcut> OptionsKey;

		public static readonly List<(ConfigEntry<KeyboardShortcut> entry, string title, string description)> Hotkeys = new List<(ConfigEntry<KeyboardShortcut>, string, string)>();

		private Harmony _harmony;

		private void Awake()
		{
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Expected O, but got Unknown
			SortMode = ((BaseUnityPlugin)this).Config.Bind<Sorter.Mode>("Sorting", "SortMode", Sorter.Mode.NameAsc, "What Sort orders by.");
			AutoSort = ((BaseUnityPlugin)this).Config.Bind<bool>("Sorting", "AutoSort", false, "Sort the inventory every time you pick something up.");
			SortMode.SettingChanged += delegate
			{
				InventoryButtons.Refresh();
			};
			AutoSort.SettingChanged += delegate
			{
				InventoryButtons.Refresh();
			};
			QuickStackRange = ((BaseUnityPlugin)this).Config.Bind<float>("QuickStack", "Range", 10f, "Meters around you in which chests are used by quick stack.");
			QuickStackSkipsHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStack", "SkipHotbar", true, "Quick stack leaves the hotbar row alone.");
			StorageRange = ((BaseUnityPlugin)this).Config.Bind<float>("Storage", "Range", 15f, "Meters around you in which chests are opened by the Storage window.");
			StorageMaxChests = ((BaseUnityPlugin)this).Config.Bind<int>("Storage", "MaxChests", 24, "Most chests the Storage window opens at once (nearest first).");
			StorageShowInventory = ((BaseUnityPlugin)this).Config.Bind<bool>("Storage", "ShowInventory", true, "Show your inventory in the Storage window. Off gives the chests the whole window.");
			DragKey = ((BaseUnityPlugin)this).Config.Bind<DragKeys>("Menus", "DragKey", DragKeys.Ctrl, "Hold this key and drag a menu button (the box with three bars) to move it.");
			InventoryMenuOpen = ((BaseUnityPlugin)this).Config.Bind<bool>("Menus", "InventoryMenuOpen", true, "Whether the menu next to your inventory is open.");
			InventoryBadgeX = ((BaseUnityPlugin)this).Config.Bind<int>("Menus", "InventoryButtonX", 0, "How far the inventory's menu button was moved to the right of its usual place (negative: to the left).");
			InventoryBadgeY = ((BaseUnityPlugin)this).Config.Bind<int>("Menus", "InventoryButtonY", 0, "How far the inventory's menu button was moved up from its usual place (negative: down).");
			ChestMenuOpen = ((BaseUnityPlugin)this).Config.Bind<bool>("Menus", "ChestMenuOpen", true, "Whether the menu next to an open chest is open.");
			ChestBadgeX = ((BaseUnityPlugin)this).Config.Bind<int>("Menus", "ChestButtonX", 0, "How far the chest's menu button was moved to the right of its usual place (negative: to the left).");
			ChestBadgeY = ((BaseUnityPlugin)this).Config.Bind<int>("Menus", "ChestButtonY", 0, "How far the chest's menu button was moved up from its usual place (negative: down).");
			StorageKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Storage", new KeyboardShortcut((KeyCode)282, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Open all nearby chests in one window.");
			SortKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "SortInventory", new KeyboardShortcut((KeyCode)285, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Sort your inventory (not the hotbar).");
			QuickStackKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "QuickStack", new KeyboardShortcut((KeyCode)284, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Put items into nearby chests that already hold the same kind of item.");
			AutoSortKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "ToggleAutoSort", KeyboardShortcut.Empty, "Switch auto-sort on pickup on or off.");
			InfoKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Info", KeyboardShortcut.Empty, "Open the Storage Master info window.");
			OptionsKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Options", new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Open the Storage Master options (where a menu button moved out of reach can be reset).");
			Hotkeys.Add((StorageKey, "Storage window", "Open all nearby chests in one window."));
			Hotkeys.Add((SortKey, "Sort inventory", "Sort everything below the hotbar."));
			Hotkeys.Add((QuickStackKey, "Quick stack", "Put items into nearby chests that already hold the same kind."));
			Hotkeys.Add((AutoSortKey, "Auto-sort on/off", "Switch sorting on pickup on or off."));
			Hotkeys.Add((InfoKey, "Info", "Open the help window."));
			Hotkeys.Add((OptionsKey, "Options", "Open this window."));
			_harmony = new Harmony("charmingbeaver.valheim.storagemaster");
			_harmony.PatchAll(typeof(Plugin).Assembly);
		}

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

		private void Update()
		{
			//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_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_0077: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			bool active = KeyCapture.Active;
			InventoryButtons.Ensure();
			QuickStack.Update();
			StorageWindow.Update();
			InfoWindow.Update();
			OptionsWindow.Update();
			if (IsTyping() || active || KeyCapture.Active)
			{
				return;
			}
			KeyboardShortcut value = InfoKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				InfoWindow.Toggle();
			}
			value = OptionsKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				OptionsWindow.Toggle();
			}
			value = StorageKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				StorageWindow.Toggle();
			}
			if (!StorageWindow.IsOpen && !ScrollWindow.AnyOpen)
			{
				value = SortKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Sorter.SortPlayer(silent: false);
				}
				value = QuickStackKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					QuickStack.Run();
				}
				value = AutoSortKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					ToggleAutoSort();
				}
			}
		}

		public static void ToggleAutoSort()
		{
			AutoSort.Value = !AutoSort.Value;
			Show("Auto-sort on pickup: " + (AutoSort.Value ? "<color=#8fd16a>ON</color>" : "<color=#ff7a6a>OFF</color>"));
			InventoryButtons.Refresh();
			if (AutoSort.Value)
			{
				Sorter.SortPlayer(silent: true);
			}
		}

		private static bool IsTyping()
		{
			if (!UIKit.TextFieldFocused() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible())
			{
				return Menu.IsVisible();
			}
			return true;
		}

		public static void Show(string text)
		{
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true);
			}
		}
	}
	public static class QuickStack
	{
		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPatch(typeof(Inventory), "StackAll")]
			[HarmonyPrefix]
			private static bool StackAll(Inventory __instance, Inventory fromInventory, bool message, ref int __result)
			{
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || fromInventory != ((Humanoid)localPlayer).GetInventory())
				{
					return true;
				}
				int num = __instance.CountItems((string)null, -1, true);
				foreach (ItemData item in new List<ItemData>(fromInventory.GetAllItems()))
				{
					bool num2;
					if (!_ours)
					{
						if (((Humanoid)localPlayer).IsItemEquiped(item) || Locks.IsLocked(item.m_gridPos.x, item.m_gridPos.y))
						{
							continue;
						}
						num2 = !ExtraSlotsCompat.IsOutsideRegularRows(fromInventory, item.m_gridPos);
					}
					else
					{
						num2 = CanMove(localPlayer, item);
					}
					if (num2 && __instance.ContainsItemByName(item.m_shared.m_name) && __instance.AddItem(item))
					{
						fromInventory.RemoveItem(item);
					}
				}
				__result = __instance.CountItems((string)null, -1, true) - num;
				if (!_ours && message)
				{
					((Character)localPlayer).Message((MessageType)2, (__result > 0) ? ("$msg_stackall " + __result) : "$msg_stackall_none", 0, (Sprite)null, false);
				}
				__instance.Changed(false, false);
				fromInventory.Changed(false, false);
				Game.instance.IncrementPlayerStat((PlayerStatType)82, 1f, false);
				return false;
			}
		}

		private static bool _ours;

		private static int _moved;

		private static int _chests;

		private static int _busy;

		private static float _reportAt = -1f;

		public static void Run()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if ((Object)(object)InventoryGui.instance != (Object)null && InventoryGui.instance.m_dragItem != null)
			{
				Plugin.Show("Put down the item you are holding first");
				return;
			}
			HashSet<string> hashSet = MovableNames(localPlayer);
			if (_reportAt < 0f)
			{
				_moved = (_chests = (_busy = 0));
			}
			int num = 0;
			if (hashSet.Count > 0)
			{
				foreach (Container item in ChestAccess.FindNearby(Plugin.QuickStackRange.Value))
				{
					if (Exclusions.IsExcluded(item) || !ContainsAny(item.GetInventory(), hashSet))
					{
						continue;
					}
					num++;
					Container chest = item;
					ChestAccess.Request(chest, delegate(bool granted)
					{
						if (granted)
						{
							StackInto(chest.GetInventory());
						}
						else
						{
							_busy++;
						}
					});
				}
			}
			if (num == 0)
			{
				Plugin.Show("No nearby chest holds any of your items");
			}
			else
			{
				_reportAt = Time.time + 1f;
			}
		}

		public static int StackInto(Inventory chest)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return 0;
			}
			_ours = true;
			int num;
			try
			{
				num = chest.StackAll(((Humanoid)localPlayer).GetInventory(), false);
			}
			finally
			{
				_ours = false;
			}
			if (num > 0)
			{
				_moved += num;
				_chests++;
			}
			return num;
		}

		public static void Update()
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (_reportAt < 0f || Time.time < _reportAt)
			{
				return;
			}
			_reportAt = -1f;
			string text = ((_moved > 0) ? string.Format("Quick stacked {0} item{1} into {2} chest{3}", _moved, (_moved == 1) ? "" : "s", _chests, (_chests == 1) ? "" : "s") : "Nothing could be stacked (the chests are full)");
			if (_busy > 0)
			{
				text += string.Format("\n<size=70%>{0} chest{1} in use by someone else</size>", _busy, (_busy == 1) ? " was" : "s were");
			}
			Plugin.Show(text);
			if (_moved > 0)
			{
				InventoryGui instance = InventoryGui.instance;
				if (instance != null)
				{
					instance.m_moveItemEffects.Create(((Component)Player.m_localPlayer).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
				}
			}
		}

		private static HashSet<string> MovableNames(Player player)
		{
			HashSet<string> hashSet = new HashSet<string>();
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				if (CanMove(player, allItem))
				{
					hashSet.Add(allItem.m_shared.m_name);
				}
			}
			return hashSet;
		}

		private static bool ContainsAny(Inventory inventory, HashSet<string> names)
		{
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (names.Contains(allItem.m_shared.m_name))
				{
					return true;
				}
			}
			return false;
		}

		public static bool CanMove(Player player, ItemData item)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (((Humanoid)player).IsItemEquiped(item))
			{
				return false;
			}
			if (Locks.IsLocked(item.m_gridPos.x, item.m_gridPos.y))
			{
				return false;
			}
			if (ExtraSlotsCompat.IsOutsideRegularRows(((Humanoid)player).GetInventory(), item.m_gridPos))
			{
				return false;
			}
			if (item.m_gridPos.y == 0)
			{
				return !Plugin.QuickStackSkipsHotbar.Value;
			}
			return true;
		}
	}
	public static class Sorter
	{
		public enum Mode
		{
			NameAsc,
			NameDesc,
			Type,
			Quality,
			Weight,
			Amount
		}

		private static readonly string[] Labels = new string[6] { "Name A-Z", "Name Z-A", "Type", "Quality", "Weight", "Amount" };

		public static string ModeLabel => Labels[(int)Plugin.SortMode.Value];

		public static void CycleMode()
		{
			int num = Labels.Length;
			Plugin.SortMode.Value = (Mode)((int)(Plugin.SortMode.Value + 1) % num);
			InventoryButtons.Refresh();
		}

		public static void SortPlayer(bool silent)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || IsDragging(silent))
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			int width = inventory.GetWidth();
			int num = ExtraSlotsCompat.PlayerRows(inventory);
			List<Vector2i> list = new List<Vector2i>();
			for (int i = 1; i < num; i++)
			{
				for (int j = 0; j < width; j++)
				{
					if (!Locks.IsLocked(j, i) && !ExtraSlotsCompat.IsSlot(new Vector2i(j, i)))
					{
						list.Add(new Vector2i(j, i));
					}
				}
			}
			List<ItemData> list2 = new List<ItemData>();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				Vector2i gridPos = allItem.m_gridPos;
				if (gridPos.y >= 1 && !Locks.IsLocked(gridPos.x, gridPos.y) && !ExtraSlotsCompat.IsOutsideRegularRows(inventory, gridPos))
				{
					list2.Add(allItem);
				}
			}
			if (list2.Count == 0)
			{
				if (!silent)
				{
					Plugin.Show("Nothing to sort");
				}
				return;
			}
			int merged = MergeStacks(inventory, list2);
			list2.Sort(Compare);
			for (int k = 0; k < list2.Count; k++)
			{
				list2[k].m_gridPos = list[k];
			}
			inventory.Changed(false, false);
			if (!silent)
			{
				Report("Inventory", merged);
			}
		}

		public static void SortContainer(Container container, bool silent = false)
		{
			//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)container == (Object)null || IsDragging(silent))
			{
				return;
			}
			if (!container.IsOwner())
			{
				Plugin.Show("$msg_inuse");
				return;
			}
			Inventory inventory = container.GetInventory();
			List<ItemData> list = new List<ItemData>(inventory.GetAllItems());
			if (list.Count != 0)
			{
				int merged = MergeStacks(inventory, list);
				list.Sort(Compare);
				int width = inventory.GetWidth();
				for (int i = 0; i < list.Count; i++)
				{
					list[i].m_gridPos = new Vector2i(i % width, i / width);
				}
				inventory.Changed(false, false);
				if (!silent)
				{
					Report("Chest", merged);
				}
			}
		}

		private static bool IsDragging(bool silent)
		{
			if ((Object)(object)InventoryGui.instance == (Object)null || InventoryGui.instance.m_dragItem == null)
			{
				return false;
			}
			if (!silent)
			{
				Plugin.Show("Put down the item you are holding first");
			}
			return true;
		}

		private static void Report(string what, int merged)
		{
			Plugin.Show(what + " sorted by " + ModeLabel + ((merged > 0) ? string.Format("\n<size=70%>{0} stack{1} merged</size>", merged, (merged == 1) ? "" : "s") : ""));
		}

		private static int MergeStacks(Inventory inventory, List<ItemData> items)
		{
			int num = 0;
			for (int i = 0; i < items.Count; i++)
			{
				ItemData val = items[i];
				int maxStackSize = val.m_shared.m_maxStackSize;
				if (maxStackSize <= 1 || val.m_stack >= maxStackSize)
				{
					continue;
				}
				for (int j = i + 1; j < items.Count; j++)
				{
					if (val.m_stack >= maxStackSize)
					{
						break;
					}
					ItemData val2 = items[j];
					if (!(val2.m_shared.m_name != val.m_shared.m_name) && val2.m_quality == val.m_quality && val2.m_worldLevel == val.m_worldLevel)
					{
						int num2 = Mathf.Min(maxStackSize - val.m_stack, val2.m_stack);
						val.m_stack += num2;
						val2.m_stack -= num2;
						if (val2.m_cheated)
						{
							val.m_cheated = true;
						}
						if (val2.m_stack <= 0)
						{
							inventory.RemoveItem(val2);
							items.RemoveAt(j);
							j--;
							num++;
						}
					}
				}
			}
			return num;
		}

		private static int Compare(ItemData a, ItemData b)
		{
			int num;
			switch (Plugin.SortMode.Value)
			{
			case Mode.NameDesc:
				return -ByName(a, b);
			case Mode.Type:
				num = TypeOrder(a).CompareTo(TypeOrder(b));
				break;
			case Mode.Quality:
				num = b.m_quality.CompareTo(a.m_quality);
				break;
			case Mode.Weight:
				num = b.GetWeight(-1).CompareTo(a.GetWeight(-1));
				break;
			case Mode.Amount:
				num = b.m_stack.CompareTo(a.m_stack);
				break;
			default:
				num = 0;
				break;
			}
			if (num != 0)
			{
				return num;
			}
			num = ByName(a, b);
			if (num == 0)
			{
				if (b.m_quality == a.m_quality)
				{
					return b.m_stack.CompareTo(a.m_stack);
				}
				return b.m_quality.CompareTo(a.m_quality);
			}
			return num;
		}

		private static int ByName(ItemData a, ItemData b)
		{
			return string.Compare(Localization.instance.Localize(a.m_shared.m_name), Localization.instance.Localize(b.m_shared.m_name), StringComparison.CurrentCultureIgnoreCase);
		}

		private static int TypeOrder(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0074: Expected I4, but got Unknown
			ItemType itemType = item.m_shared.m_itemType;
			switch (itemType - 1)
			{
			case 2:
			case 3:
			case 13:
			case 21:
				return 0;
			case 4:
				return 1;
			case 8:
			case 22:
				return 2;
			case 5:
				return 3;
			case 6:
				return 4;
			case 10:
				return 5;
			case 11:
				return 6;
			case 16:
				return 7;
			case 17:
			case 23:
				return 8;
			case 14:
			case 18:
				return 9;
			case 1:
				return 10;
			case 0:
				return 11;
			case 20:
				return 12;
			case 12:
				return 13;
			default:
				return 14;
			}
		}
	}
}
namespace StorageMaster.UI
{
	public class Badge : Button, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		private const float MenuGap = 4f;

		public RectTransform Menu;

		public Vector2 Home;

		public ConfigEntry<bool> MenuOpen;

		public ConfigEntry<int> X;

		public ConfigEntry<int> Y;

		public Transform[] Boxes;

		private bool _moving;

		private Vector2 _grab;

		private Vector2 _live;

		private static readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		public RectTransform Rect => (RectTransform)((Component)this).transform;

		private RectTransform Parent => (RectTransform)((Component)this).transform.parent;

		public static Badge Create(RectTransform panel, RectTransform below, string name, RectTransform menu, ConfigEntry<bool> menuOpen, ConfigEntry<int> x, ConfigEntry<int> y, params Transform[] boxes)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_002c: 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_0050: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: 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_018c: 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_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)below).gameObject, (Transform)(object)panel, false);
			((Object)val).name = name;
			RectTransform val2 = (RectTransform)val.transform;
			val2.pivot = new Vector2(0.5f, 0.5f);
			Image val3 = null;
			Image val5 = default(Image);
			foreach (Transform item in (Transform)val2)
			{
				Transform val4 = item;
				if (((Object)val4).name == "bkg" && (Object)(object)val3 == (Object)null && ((Component)val4).TryGetComponent<Image>(ref val5))
				{
					val3 = val5;
					OnlyLooks(((Component)val4).gameObject);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)val4).gameObject);
				}
			}
			OnlyLooks(val);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val.GetComponent<Image>() ?? val.AddComponent<Image>();
			}
			Vector2 val6 = default(Vector2);
			for (int i = -1; i <= 1; i++)
			{
				RectTransform rectTransform = ((Graphic)UIKit.Solid((Transform)(object)val2, UIKit.Parchment, "bar")).rectTransform;
				((Vector2)(ref val6))..ctor(0.5f, 0.5f);
				rectTransform.anchorMax = val6;
				rectTransform.anchorMin = val6;
				rectTransform.sizeDelta = new Vector2(30f, 4f);
				rectTransform.anchoredPosition = new Vector2(1f, (float)i * 9f);
			}
			Badge badge = ((Component)val2).gameObject.AddComponent<Badge>();
			((Selectable)badge).targetGraphic = (Graphic)(object)val3;
			ColorBlock colors = ((Selectable)badge).colors;
			((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 0.85f, 0.6f);
			((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).normalColor;
			((Selectable)badge).colors = colors;
			badge.Menu = menu;
			badge.Home = below.anchoredPosition + new Vector2(0f, below.sizeDelta.y + 12f);
			badge.Boxes = (Transform[])(object)new Transform[boxes.Length + 1];
			badge.Boxes[0] = (Transform)(object)below;
			boxes.CopyTo(badge.Boxes, 1);
			badge.MenuOpen = menuOpen;
			badge.X = x;
			badge.Y = y;
			((UnityEvent)((Button)badge).onClick).AddListener(new UnityAction(badge.Toggle));
			UIKit.ButtonSound(((Component)val2).gameObject);
			UIKit.Tooltip(((Component)val2).gameObject, " ");
			((Transform)menu).SetParent((Transform)(object)panel, false);
			val6 = (menu.anchorMin = (menu.anchorMax = val2.anchorMin));
			((Transform)menu).SetAsLastSibling();
			OnTop(((Component)menu).gameObject, on: true, 2);
			badge.Apply();
			return badge;
		}

		private static void OnlyLooks(GameObject go)
		{
			Component[] components = go.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!(val is RectTransform) && !(val is CanvasRenderer) && !(val is Image))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static void OnTop(GameObject go, bool on, int above)
		{
			Canvas val = go.GetComponent<Canvas>();
			if (!on)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Object.DestroyImmediate((Object)(object)go.GetComponent<GraphicRaycaster>());
					Object.DestroyImmediate((Object)(object)val);
				}
				return;
			}
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<Canvas>();
				go.AddComponent<GraphicRaycaster>();
			}
			Canvas componentInParent = ((Component)go.transform.parent).GetComponentInParent<Canvas>();
			int num = (((Object)(object)componentInParent != (Object)null) ? componentInParent.sortingOrder : 0) + above;
			if (!val.overrideSorting)
			{
				val.overrideSorting = true;
			}
			if (val.sortingOrder != num)
			{
				val.sortingOrder = num;
			}
		}

		private bool OverItsPanel()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)Parent, (Transform)(object)Rect);
			((Bounds)(ref val)).Expand(new Vector3(0f, 0f, 1f));
			Rect rect = Parent.rect;
			Bounds val2 = new Bounds(Vector2.op_Implicit(((Rect)(ref rect)).center), new Vector3(((Rect)(ref rect)).width, ((Rect)(ref rect)).height, 1f));
			if (((Bounds)(ref val2)).Intersects(val))
			{
				return true;
			}
			foreach (Transform item in (Transform)Parent)
			{
				Transform val3 = item;
				if (((Component)val3).gameObject.activeInHierarchy && (((Object)val3).name.StartsWith("ExtraSlots") || Array.IndexOf(Boxes, val3) >= 0))
				{
					Bounds val4 = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)Parent, val3);
					((Bounds)(ref val4)).Expand(new Vector3(0f, 0f, 1f));
					if (((Bounds)(ref val4)).size.x > 0f && ((Bounds)(ref val4)).Intersects(val))
					{
						return true;
					}
				}
			}
			return false;
		}

		public void Toggle()
		{
			MenuOpen.Value = !MenuOpen.Value;
			Apply();
		}

		public void MoveTo(Vector2 offset)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0031: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			_live = offset;
			_moving = true;
			Apply();
			_moving = false;
			Vector2 val = Rect.anchoredPosition - Home;
			X.Value = Mathf.RoundToInt(val.x);
			Y.Value = Mathf.RoundToInt(val.y);
			Apply();
		}

		public void Apply()
		{
			//IL_000d: 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_0032: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			KeepUnder();
			Rect.anchoredPosition = Home + (Vector2)(_moving ? _live : new Vector2((float)X.Value, (float)Y.Value));
			RectTransform rect = Rect;
			rect.anchoredPosition += ShiftOnScreen(Rect);
			OnTop(((Component)this).gameObject, !OverItsPanel(), 1);
			UITooltip component = ((Component)this).GetComponent<UITooltip>();
			if (component != null)
			{
				component.m_topic = "Storage Master";
				component.m_text = $"Click: open or close the menu\n{Plugin.DragKey.Value} + drag: move this button";
			}
			bool value = MenuOpen.Value;
			if (((Component)Menu).gameObject.activeSelf != value)
			{
				((Component)Menu).gameObject.SetActive(value);
			}
			if (value)
			{
				OnTop(((Component)Menu).gameObject, on: true, 2);
				Vector2 val = Rect.sizeDelta / 2f;
				Vector2 val2 = Rect.anchoredPosition + new Vector2(0f, val.y);
				Menu.pivot = new Vector2(0f, 1f);
				Menu.anchoredPosition = val2 + new Vector2(val.x + 4f, 0f);
				Vector2 val3 = ShiftOnScreen(Menu);
				if (val3.x < 0f)
				{
					Menu.pivot = new Vector2(1f, 1f);
					Menu.anchoredPosition = val2 - new Vector2(val.x + 4f, 0f);
					val3 = ShiftOnScreen(Menu);
				}
				RectTransform menu = Menu;
				menu.anchoredPosition += val3;
			}
		}

		private void KeepUnder()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			int num = int.MaxValue;
			foreach (Transform item in (Transform)Parent)
			{
				Transform val = item;
				if (((Object)val).name.StartsWith("ExtraSlots") || Array.IndexOf(Boxes, val) >= 0)
				{
					num = Mathf.Min(num, val.GetSiblingIndex());
				}
			}
			if (num < ((Component)this).transform.GetSiblingIndex())
			{
				((Component)this).transform.SetSiblingIndex(num);
			}
		}

		private static Vector2 ShiftOnScreen(RectTransform rt)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_005f: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			Transform canvasRoot = UIKit.CanvasRoot;
			RectTransform val = (RectTransform)(object)((canvasRoot is RectTransform) ? canvasRoot : null);
			if ((Object)(object)val == (Object)null)
			{
				return Vector2.zero;
			}
			rt.GetWorldCorners(_corners);
			Vector2 val2 = Vector2.op_Implicit(((Transform)val).InverseTransformPoint(_corners[0]));
			Vector2 val3 = Vector2.op_Implicit(((Transform)val).InverseTransformPoint(_corners[2]));
			Rect rect = val.rect;
			Vector2 zero = Vector2.zero;
			if (val2.x < ((Rect)(ref rect)).xMin)
			{
				zero.x = ((Rect)(ref rect)).xMin - val2.x;
			}
			else if (val3.x > ((Rect)(ref rect)).xMax)
			{
				zero.x = ((Rect)(ref rect)).xMax - val3.x;
			}
			if (val2.y < ((Rect)(ref rect)).yMin)
			{
				zero.y = ((Rect)(ref rect)).yMin - val2.y;
			}
			else if (val3.y > ((Rect)(ref rect)).yMax)
			{
				zero.y = ((Rect)(ref rect)).yMax - val3.y;
			}
			float x = ((Transform)(RectTransform)((Transform)rt).parent).lossyScale.x;
			if (!(x > 0f))
			{
				return Vector2.zero;
			}
			return zero * (((Transform)val).lossyScale.x / x);
		}

		public static bool DragKeyHeld()
		{
			switch (Plugin.DragKey.Value)
			{
			case Plugin.DragKeys.Shift:
				if (!Input.GetKey((KeyCode)304))
				{
					return Input.GetKey((KeyCode)303);
				}
				return true;
			case Plugin.DragKeys.Alt:
				if (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))
				{
					return Input.GetKey((KeyCode)313);
				}
				return true;
			default:
				if (!Input.GetKey((KeyCode)306))
				{
					return Input.GetKey((KeyCode)305);
				}
				return true;
			}
		}

		public void OnBeginDrag(PointerEventData e)
		{
			//IL_000f: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			if (DragKeyHeld() && RectTransformUtility.ScreenPointToLocalPointInRectangle(Parent, e.position, e.pressEventCamera, ref val))
			{
				_grab = val - Rect.anchoredPosition;
				_live = Rect.anchoredPosition - Home;
				_moving = true;
			}
		}

		public void OnDrag(PointerEventData e)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_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)
			Vector2 val = default(Vector2);
			if (_moving && RectTransformUtility.ScreenPointToLocalPointInRectangle(Parent, e.position, e.pressEventCamera, ref val))
			{
				_live = val - _grab - Home;
				Apply();
			}
		}

		public void OnEndDrag(PointerEventData e)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (_moving)
			{
				MoveTo(_live);
			}
		}

		public override void OnPointerClick(PointerEventData e)
		{
			if (!_moving)
			{
				((Button)this).OnPointerClick(e);
			}
		}
	}
	public static class InfoWindow
	{
		private static readonly ScrollWindow _window = new ScrollWindow("StorageMasterInfo", "Storage Master", "Version 1.2.0  ·  sorting, locked slots, quick stack and all your chests in one window", Fill)
		{
			Opened = Refresh
		};

		private static TextMeshProUGUI _hotkeys;

		public static bool IsOpen => _window.IsOpen;

		public static void Toggle()
		{
			_window.Toggle();
		}

		public static void Open()
		{
			_window.Open();
		}

		public static void Close()
		{
			_window.Close();
		}

		public static void Update()
		{
			_window.Update();
		}

		private static void Fill(RectTransform c)
		{
			ScrollWindow.Section((Transform)(object)c, "Sorting");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Sort</color> (in the menu next to your inventory) tidies everything below the hotbar. The hotbar row is never moved. Partial stacks of the same item are merged first, so three stacks of 30 wood become one of 90.");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>By: ...</color> chooses the order: Name A-Z, Name Z-A, Type (weapons, ammo, armor, tools, food, materials, trophies), Quality (best first), Weight (heaviest first) or Amount (biggest stacks first).");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Sort chest</color> is in the menu next to an open chest and sorts it the same way. <color=#ffa13c>Auto-sort</color> sorts your inventory every time you pick something up.");
			ScrollWindow.Section((Transform)(object)c, "Locked slots");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Alt + click</color> a slot in your inventory to lock or unlock it. Locked slots are tinted orange. Sort, auto-sort and quick stack never move what's in them, and neither does the game's own Place stacks button. Locks are saved with your character.");
			ScrollWindow.Section((Transform)(object)c, "Quick stack");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Quick stack</color> puts your items into nearby chests that already hold the same kind of item. Your hotbar, equipped items and locked slots stay with you, and chests marked Skip in the Storage window are left out. Each chest is handed over by whoever controls it first, so it's safe while your friend plays, and a chest they have open is skipped.");
			ScrollWindow.Section((Transform)(object)c, "Storage window");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Storage</color> opens every chest around you at once, next to your inventory.");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Click</color> picks up and puts down, like the normal chest window.  <color=#ffa13c>Shift + click</color> takes half a stack.  <color=#ffa13c>Ctrl + click</color> moves an item between you and the chests.  <color=#ffa13c>Alt + click</color> locks one of your slots.  <color=#ffa13c>Esc</color> puts a carried item back, or closes the window.");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Right-click</color> an item to choose it: every slot with it lights up and you see how many you have and where. Then <color=#ffa13c>Gather here</color> on a chest pulls all of it into that chest; what doesn't fit goes into the next chests.");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Find item</color> (or <color=#ffa13c>F</color>, as in the build menu) highlights matches in every chest.  <color=#ffa13c>Tidy up</color> brings each item that's spread over several chests into the chest holding most of it, then sorts all chests.  Click a chest's title to <color=#ffa13c>name it</color>, here or in the normal chest window (E); the name shows when you look at the chest in the world.  <color=#ffa13c>Settings</color> sets how far away and how many chests are opened (up to 20 m and about 30 chests is recommended).");
			ScrollWindow.Para((Transform)(object)c, "Tick <color=#ffa13c>Skip</color> on a chest (for example your friend's) and Quick stack, Gather here, Tidy up and Sort all leave it alone, here and with the Quick stack button. You can still move items in and out by hand. Only you see this setting.");
			ScrollWindow.Para((Transform)(object)c, "<color=#ffa13c>Hide inventory</color> gives the chests the whole window, so more of them fit side by side. Ctrl + click on a chest item still moves it to you.");
			ScrollWindow.Section((Transform)(object)c, "Menu buttons");
			ScrollWindow.Para((Transform)(object)c, "The buttons are in two menus, one next to your inventory and one next to an open chest. Click the box with three bars (above the weight) to open or close a menu; it stays the way you leave it. Hold the drag key (<color=#ffa13c>Ctrl</color> unless changed in Options) and drag the box to move it, for example when it covers another mod's window. If one ends up out of reach, <color=#ffa13c>Reset</color> in Options puts it back.");
			ScrollWindow.Section((Transform)(object)c, "Hotkeys");
			_hotkeys = ScrollWindow.Para((Transform)(object)c, "");
		}

		private static void Refresh()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			KeyboardShortcut value;
			foreach (var hotkey in Plugin.Hotkeys)
			{
				value = hotkey.entry.Value;
				string text = (((int)((KeyboardShortcut)(ref value)).MainKey == 0) ? "<color=#a8a49e>not set</color>" : ("<color=#ffa13c>" + KeyNames.Format(hotkey.entry.Value) + "</color>"));
				stringBuilder.Append(hotkey.title + ": " + text + "\n");
			}
			stringBuilder.Append("Change them in <color=#ffa13c>Options</color> (in the menu next to your inventory).");
			((TMP_Text)_hotkeys).text = stringBuilder.ToString();
			value = Plugin.OptionsKey.Value;
			string text2 = (((int)((KeyboardShortcut)(ref value)).MainKey == 0) ? "" : ("<color=#ffa13c>" + KeyNames.Format(Plugin.OptionsKey.Value) + "</color> or "));
			((TMP_Text)_window.Footer).text = "Options: " + text2 + "the Options button in the menu next to your inventory";
		}
	}
	public static class KeyCapture
	{
		public static int EscapeUsedFrame = -1;

		private static int _startFrame;

		private static readonly KeyCode[] Candidates = ((KeyCode[])Enum.GetValues(typeof(KeyCode))).Where((KeyCode k) => (int)k != 0 && (int)k < 330).Distinct().ToArray();

		public static ConfigEntry<KeyboardShortcut> Target { get; private set; }

		public static bool Active => Target != null;

		public static event Action Changed;

		public static void Begin(ConfigEntry<KeyboardShortcut> entry)
		{
			Target = entry;
			_startFrame = Time.frameCount;
			KeyCapture.Changed?.Invoke();
		}

		public static void Cancel()
		{
			if (Target != null)
			{
				Target = null;
				KeyCapture.Changed?.Invoke();
			}
		}

		public static void Update()
		{
			//IL_0035: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Invalid comparison between Unknown and I4
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Invalid comparison between Unknown and I4
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (Target == null || Time.frameCount <= _startFrame)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				EscapeUsedFrame = Time.frameCount;
				Cancel();
				return;
			}
			if (Input.GetKeyDown((KeyCode)8))
			{
				Assign(KeyboardShortcut.Empty);
				return;
			}
			KeyCode[] candidates = Candidates;
			foreach (KeyCode val in candidates)
			{
				if (!KeyNames.IsModifier(val) && Input.GetKeyDown(val))
				{
					KeyCode[] array = ((IEnumerable<KeyCode>)KeyNames.Modifiers).Where((Func<KeyCode, bool>)Input.GetKey).ToArray();
					if (((int)val == 323 || (int)val == 324) && array.Length == 0)
					{
						Plugin.Show("Left and right click need Ctrl, Alt or Shift held as well");
					}
					else
					{
						Assign(new KeyboardShortcut(val, array));
					}
					break;
				}
			}
		}

		private static void Assign(KeyboardShortcut shortcut)
		{
			//IL_001f: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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)
			//IL_0054: 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)
			ConfigEntry<KeyboardShortcut> entry = Target;
			Target = null;
			string text = "";
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0)
			{
				foreach (var hotkey in Plugin.Hotkeys)
				{
					if (hotkey.entry != entry && KeyNames.Same(hotkey.entry.Value, shortcut))
					{
						hotkey.entry.Value = KeyboardShortcut.Empty;
						text = "\n<size=70%>(removed from " + hotkey.title + ")</size>";
					}
				}
			}
			entry.Value = shortcut;
			Plugin.Show(Plugin.Hotkeys.First(((ConfigEntry<KeyboardShortcut> entry, string title, string description) h) => h.entry == entry).title + ": " + (((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0) ? "no key" : KeyNames.Format(shortcut)) + text);
			KeyCapture.Changed?.Invoke();
		}
	}
	public static class KeyNames
	{
		public static readonly KeyCode[] Modifiers;

		private static readonly (KeyCode key, bool ctrl, string what)[] HardCoded;

		public static bool IsModifier(KeyCode key)
		{
			//IL_0005: 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_0014: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			if (Array.IndexOf(Modifiers, key) < 0 && (int)key != 310 && (int)key != 309 && (int)key != 311 && (int)key != 312)
			{
				return (int)key == 313;
			}
			return true;
		}

		public static bool Same(KeyboardShortcut a, KeyboardShortcut b)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (((KeyboardShortcut)(ref a)).MainKey == ((KeyboardShortcut)(ref b)).MainKey)
			{
				return new HashSet<KeyCode>(((KeyboardShortcut)(ref a)).Modifiers).SetEquals(((KeyboardShortcut)(ref b)).Modifiers);
			}
			return false;
		}

		public static string Format(KeyboardShortcut s)
		{
			//IL_0002: 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)
			if ((int)((KeyboardShortcut)(ref s)).MainKey == 0)
			{
				return "—";
			}
			return string.Join(" + ", ((KeyboardShortcut)(ref s)).Modifiers.Select(Name).Concat(new string[1] { Name(((KeyboardShortcut)(ref s)).MainKey) }));
		}

		public unsafe static string Name(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_001a: 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_004a: Expected I4, but got Unknown
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_004a: 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_006e: Expected I4, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected I4, but got Unknown
			if ((int)key <= 96)
			{
				if ((int)key == 13)
				{
					return "Enter";
				}
				if ((int)key == 96)
				{
					return "`";
				}
			}
			else
			{
				switch (key - 273)
				{
				default:
					switch (key - 303)
					{
					case 2:
					case 3:
						return "Ctrl";
					case 0:
					case 1:
						return "Shift";
					case 4:
					case 5:
						return "Alt";
					}
					switch (key - 323)
					{
					case 0:
						return "Left click";
					case 1:
						return "Right click";
					case 2:
						return "Middle click";
					case 3:
						return "Mouse 4";
					case 4:
						return "Mouse 5";
					case 5:
						return "Mouse 6";
					case 6:
						return "Mouse 7";
					}
					break;
				case 0:
					return "Up";
				case 1:
					return "Down";
				case 3:
					return "Left";
				case 2:
					return "Right";
				case 7:
					return "Page Up";
				case 8:
					return "Page Down";
				case 4:
				case 5:
				case 6:
					break;
				}
			}
			string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
			if (text.StartsWith("Alpha"))
			{
				return text.Substring(5);
			}
			if (text.StartsWith("Keypad"))
			{
				return "Num " + text.Substring(6);
			}
			return text;
		}

		public static string ValheimConflict(KeyboardShortcut s)
		{
			//IL_0002: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Invalid comparison between Unknown and I4
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref s)).MainKey == 0)
			{
				return null;
			}
			bool flag = ((KeyboardShortcut)(ref s)).Modifiers.Contains((KeyCode)306) || ((KeyboardShortcut)(ref s)).Modifiers.Contains((KeyCode)305);
			(KeyCode, bool, string)[] hardCoded = HardCoded;
			for (int i = 0; i < hardCoded.Length; i++)
			{
				(KeyCode, bool, string) tuple = hardCoded[i];
				if (tuple.Item1 == ((KeyboardShortcut)(ref s)).MainKey && (!tuple.Item2 || flag))
				{
					return tuple.Item3;
				}
			}
			ZInput instance = ZInput.instance;
			if (instance == null)
			{
				return null;
			}
			string text;
			try
			{
				text = ZInput.KeyCodeToPath(((KeyboardShortcut)(ref s)).MainKey, false);
			}
			catch
			{
				return null;
			}
			if (string.IsNullOrEmpty(text) || text.EndsWith("/None"))
			{
				return null;
			}
			foreach (ButtonDef value in instance.m_buttons.Values)
			{
				if ((int)value.Source == 180 || !IsGameplayButton(value.Name) || value.ButtonAction == null)
				{
					continue;
				}
				Enumerator<InputBinding> enumerator2 = value.ButtonAction.bindings.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						InputBinding current2 = enumerator2.Current;
						if (string.Equals(((InputBinding)(ref current2)).effectivePath, text, StringComparison.OrdinalIgnoreCase))
						{
							return Pretty(value.Name);
						}
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			return null;
		}

		private static bool IsGameplayButton(string name)
		{
			if (!name.StartsWith("Joy") && !name.StartsWith("Mouse") && !name.Contains("Chat"))
			{
				switch (name)
				{
				default:
					if (!name.StartsWith("Radial"))
					{
						return !name.StartsWith("Cam");
					}
					break;
				case "Tab":
				case "LShift":
				case "Escape":
					break;
				}
			}
			return false;
		}

		private static string Pretty(string buttonName)
		{
			switch (buttonName)
			{
			case "GP":
				return "Forsaken power";
			case "Hide":
				return "Hide weapons";
			case "Use":
				return "Use";
			case "AltPlace":
				return "Alternative placement";
			case "BuildMenu":
				return "Build menu";
			default:
				if (buttonName.StartsWith("Hotbar"))
				{
					return "Hotbar slot " + buttonName.Substring(6);
				}
				return Regex.Replace(buttonName, "(?<=[a-z])(?=[A-Z])", " ").ToLowerInvariant();
			}
		}

		static KeyNames()
		{
			KeyCode[] array = new KeyCode[6];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Modifiers = (KeyCode[])(object)array;
			HardCoded = new(KeyCode, bool, string)[6]
			{
				((KeyCode)282, true, "freeing the mouse"),
				((KeyCode)283, false, "network stats"),
				((KeyCode)284, true, "hiding the HUD"),
				((KeyCode)290, false, "switching the controller layout"),
				((KeyCode)292, false, "screenshots"),
				((KeyCode)27, false, "the menu")
			};
		}
	}
	public static class OptionsWindow
	{
		private class KeyRow
		{
			public ConfigEntry<KeyboardShortcut> Entry;

			public Button Button;

			public TextMeshProUGUI Warning;
		}

		private static readonly ScrollWindow _window = new ScrollWindow("StorageMasterOptions", "Options", "Storage Master  ·  hotkeys, settings and the menu buttons", Fill)
		{
			Opened = Refresh,
			Closed = KeyCapture.Cancel
		};

		private static readonly List<KeyRow> _keyRows = new List<KeyRow>();

		private static readonly List<Action> _refreshers = new List<Action>();

		private static bool _listening;

		public static bool IsOpen => _window.IsOpen;

		public static void Toggle()
		{
			_window.Toggle();
		}

		public static void Open()
		{
			_window.Open();
		}

		public static void Close()
		{
			_window.Close();
		}

		public static void Update()
		{
			KeyCapture.Update();
			_window.Update();
		}

		private static void Fill(RectTransform c)
		{
			if (!_listening)
			{
				KeyCapture.Changed += delegate
				{
					if (IsOpen)
					{
						Refresh();
					}
				};
				_listening = true;
			}
			_keyRows.Clear();
			_refreshers.Clear();
			ScrollWindow.Section((Transform)(object)c, "Hotkeys");
			ScrollWindow.Para((Transform)(object)c, "Click a key to change it, then press the new key (hold Ctrl, Alt or Shift for a combination). Esc cancels, Backspace removes the key.");
			foreach (var hotkey in Plugin.Hotkeys)
			{
				_keyRows.Add(KeyRowFor((Transform)(object)c, hotkey.entry, hotkey.title, hotkey.description));
			}
			ScrollWindow.Section((Transform)(object)c, "Settings");
			CheckRow((Transform)(object)c, "Auto-sort on pickup", "Sort your inventory every time you pick something up.", Plugin.AutoSort);
			CheckRow((Transform)(object)c, "Quick stack skips the hotbar", "Keep everything in the hotbar row when quick stacking.", Plugin.QuickStackSkipsHotbar);
			NumberRow((Transform)(object)c, "Quick stack range", "How far away chests can be for quick stack.", () => $"{Plugin.QuickStackRange.Value:0} m", delegate(int d)
			{
				Plugin.QuickStackRange.Value = Mathf.Clamp(Plugin.QuickStackRange.Value + (float)d * 5f, 5f, 50f);
			});
			NumberRow((Transform)(object)c, "Storage window range", "How far away chests can be for the Storage window.", () => $"{Plugin.StorageRange.Value:0} m", delegate(int d)
			{
				Plugin.StorageRange.Value = Mathf.Clamp(Plugin.StorageRange.Value + (float)d * 5f, 5f, 50f);
			});
			NumberRow((Transform)(object)c, "Most chests in Storage", "The nearest chests are shown first.", () => Plugin.StorageMaxChests.Value.ToString(), delegate(int d)
			{
				Plugin.StorageMaxChests.Value = Mathf.Clamp(Plugin.StorageMaxChests.Value + d * 4, 4, 60);
			});
			ScrollWindow.Section((Transform)(object)c, "Menu buttons");
			ScrollWindow.Para((Transform)(object)c, "Hold the drag key and drag a menu button (the box with three bars) to move it. <color=#ffa13c>Reset</color> puts it back in its usual place, for example when it ended up out of reach.");
			ChoiceRow((Transform)(object)c, "Drag key", "Hold it to move a menu button with the mouse.", () => Plugin.DragKey.Value.ToString(), delegate
			{
				Plugin.DragKey.Value = (Plugin.DragKeys)((int)(Plugin.DragKey.Value + 1) % 3);
			});
			PositionRow((Transform)(object)c, "Inventory menu button", "How far it's moved: right (X) and up (Y).", Plugin.InventoryBadgeX, Plugin.InventoryBadgeY);
			PositionRow((Transform)(object)c, "Chest menu button", "How far it's moved: right (X) and up (Y).", Plugin.ChestBadgeX, Plugin.ChestBadgeY);
		}

		private static KeyRow KeyRowFor(Transform parent, ConfigEntry<KeyboardShortcut> entry, string title, string description)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			KeyRow obj = new KeyRow
			{
				Entry = entry
			};
			HorizontalLayoutGroup val = UIKit.HRow(parent, "key_" + title, 12f);
			((LayoutGroup)val).padding = new RectOffset(6, 6, 2, 2);
			((Component)(object)val).Size(-1f, 58f);
			VerticalLayoutGroup val2 = UIKit.VCol(((Component)val).transform, "text", 1f);
			((LayoutGroup)val2).childAlignment = (TextAnchor)3;
			((Component)(object)val2).Size(-1f, -1f, 1f);
			((Component)(object)UIKit.Text(((Component)val2).transform, title, 19f, null, (TextAlignmentOptions)4097)).Size(-1f, 22f);
			((Component)(object)UIKit.Text(((Component)val2).transform, description, 15f, UIKit.Grey, (TextAlignmentOptions)4097)).Size(-1f, 18f);
			obj.Warning = UIKit.Text(((Component)val2).transform, "", 14f, UIKit.Red, (TextAlignmentOptions)4097);
			((Component)(object)obj.Warning).Size(-1f, 16f);
			((Component)obj.Warning).gameObject.SetActive(false);
			obj.Button = UIKit.Button(((Component)val).transform, "", (UnityAction)delegate
			{
				KeyCapture.Begin(entry);
			}, 190f, 38f);
			return obj;
		}

		private static void CheckRow(Transform parent, string title, string description, ConfigEntry<bool> entry)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or mi