Decompiled source of HexQuickStackStorage v1.0.0

Plugins/HexQuickStackStorage.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HexQuickStackStorage.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HexQuickStackStorage")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HexQuickStackStorage")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("dfffd921-4f13-41b7-9dd6-fed57ea5fb5c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HexQuickStackStorage
{
	[BepInPlugin("com.hex.quickstackstorage", "HexQuickStackStorage", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string PluginGuid = "com.hex.quickstackstorage";

		private const string PluginName = "HexQuickStackStorage";

		private const string PluginVersion = "1.0.0";

		private ConfigEntry<float> _searchRadius;

		private ConfigEntry<KeyboardShortcut> _quickStackShortcut;

		private Harmony _harmonyInstance;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static float SearchRadius
		{
			get
			{
				if (Instance?._searchRadius == null)
				{
					return 25f;
				}
				return Instance._searchRadius.Value;
			}
		}

		internal static KeyboardShortcut QuickStackShortcut
		{
			get
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				if (Instance?._quickStackShortcut == null)
				{
					return new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>());
				}
				return Instance._quickStackShortcut.Value;
			}
		}

		private void Awake()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_searchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SearchRadius", 25f, new ConfigDescription("The radius in which to search for nearby containers when quick stacking.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 150f), Array.Empty<object>()));
			_quickStackShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "QuickStackShortcut", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Keyboard shortcut used to quick stack nearby containers.");
			TrashService.Initialize();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmonyInstance = new Harmony("com.hex.quickstackstorage");
			_harmonyInstance.PatchAll(executingAssembly);
			Log.LogInfo((object)"HexQuickStackStorage v1.0.0 loaded.");
		}

		private void Update()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (IsTypingInInputField())
			{
				return;
			}
			KeyboardShortcut quickStackShortcut = QuickStackShortcut;
			if (((KeyboardShortcut)(ref quickStackShortcut)).IsDown())
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null))
				{
					QuickStackService.QuickStack(localPlayer);
				}
			}
		}

		private void OnDestroy()
		{
			Harmony harmonyInstance = _harmonyInstance;
			if (harmonyInstance != null)
			{
				harmonyInstance.UnpatchSelf();
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"HexQuickStackStorage v1.0.0 unloaded.");
			}
			Instance = null;
		}

		private static bool IsTypingInInputField()
		{
			if ((Object)(object)EventSystem.current == (Object)null || (Object)(object)EventSystem.current.currentSelectedGameObject == (Object)null)
			{
				return false;
			}
			GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
			if (!((Object)(object)currentSelectedGameObject.GetComponent<InputField>() != (Object)null))
			{
				return (Object)(object)currentSelectedGameObject.GetComponent<TMP_InputField>() != (Object)null;
			}
			return true;
		}
	}
	internal static class ContainerService
	{
		internal static List<Container> GetNearbyContainers(Player player)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			List<Container> list = new List<Container>();
			if ((Object)(object)player == (Object)null)
			{
				return list;
			}
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			Collider[] array = Physics.OverlapSphere(((Component)player).transform.position, Plugin.SearchRadius);
			HashSet<Container> hashSet = new HashSet<Container>();
			Collider[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Container componentInParent = ((Component)array2[i]).GetComponentInParent<Container>();
				if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(componentInParent) && IsPlayerOwnedContainer(componentInParent, playerID))
				{
					list.Add(componentInParent);
				}
			}
			return list;
		}

		internal static bool IsPlayerOwnedContainer(Container container, long playerId)
		{
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			Piece componentInParent = ((Component)container).GetComponentInParent<Piece>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return false;
			}
			return componentInParent.GetCreator() == playerId;
		}
	}
	internal static class InventorySortService
	{
		private static readonly MethodInfo ChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		private static readonly object[] ChangedArguments = new object[2] { false, false };

		internal static void SortPlayerInventory()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				Inventory inventory = ((Humanoid)localPlayer).GetInventory();
				if (inventory != null)
				{
					int vanillaInventoryHeight = GetVanillaInventoryHeight(localPlayer);
					Sort(inventory, vanillaInventoryHeight, preserveHotbar: true);
				}
			}
		}

		internal static void SortContainer(Container container)
		{
			if ((Object)(object)container == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			if (ContainerService.IsPlayerOwnedContainer(container, playerID))
			{
				Inventory inventory = container.GetInventory();
				if (inventory != null)
				{
					Sort(inventory, inventory.GetHeight(), preserveHotbar: false);
				}
			}
		}

		private static void Sort(Inventory inventory, int validHeight, bool preserveHotbar)
		{
			//IL_0052: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			List<ItemData> allItems = inventory.GetAllItems();
			if (allItems == null || allItems.Count <= 1)
			{
				return;
			}
			int width = inventory.GetWidth();
			if (width <= 0 || validHeight <= 0)
			{
				return;
			}
			List<ItemData> list = new List<ItemData>(allItems.Count);
			HashSet<(int, int)> hashSet = new HashSet<(int, int)>();
			foreach (ItemData item in allItems)
			{
				if (item != null && IsValidSlot(item.m_gridPos, width, validHeight))
				{
					if (item.m_equipped)
					{
						hashSet.Add((item.m_gridPos.x, item.m_gridPos.y));
					}
					else if (preserveHotbar && item.m_gridPos.y == 0)
					{
						hashSet.Add((item.m_gridPos.x, item.m_gridPos.y));
					}
					else
					{
						list.Add(item);
					}
				}
			}
			list.Sort(CompareItems);
			int num = 0;
			for (int i = (preserveHotbar ? 1 : 0); i < validHeight; i++)
			{
				if (num >= list.Count)
				{
					break;
				}
				for (int j = 0; j < width; j++)
				{
					if (num >= list.Count)
					{
						break;
					}
					if (!hashSet.Contains((j, i)))
					{
						list[num].m_gridPos = new Vector2i(j, i);
						num++;
					}
				}
			}
			ChangedMethod?.Invoke(inventory, ChangedArguments);
		}

		private static int GetVanillaInventoryHeight(Player player)
		{
			string s = default(string);
			if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result))
			{
				return Mathf.Clamp(result, 0, 9);
			}
			return 4;
		}

		private static bool IsValidSlot(Vector2i position, int width, int height)
		{
			//IL_0000: 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)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (position.x >= 0 && position.x < width && position.y >= 0)
			{
				return position.y < height;
			}
			return false;
		}

		private static int CompareItems(ItemData a, ItemData b)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			ref ItemType itemType = ref a.m_shared.m_itemType;
			object target = b.m_shared.m_itemType;
			int num = ((Enum)Unsafe.As<ItemType, ItemType>(ref itemType)/*cast due to .constrained prefix*/).CompareTo(target);
			if (num != 0)
			{
				return num;
			}
			num = string.Compare(a.m_shared.m_name, b.m_shared.m_name, StringComparison.Ordinal);
			if (num != 0)
			{
				return num;
			}
			num = b.m_quality.CompareTo(a.m_quality);
			if (num != 0)
			{
				return num;
			}
			return b.m_stack.CompareTo(a.m_stack);
		}
	}
	internal static class QuickStackService
	{
		internal static void QuickStack(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return;
			}
			int vanillaInventoryHeight = GetVanillaInventoryHeight(player);
			foreach (Container nearbyContainer in ContainerService.GetNearbyContainers(player))
			{
				if (!((Object)(object)nearbyContainer == (Object)null))
				{
					Inventory inventory2 = nearbyContainer.GetInventory();
					if (inventory2 != null)
					{
						QuickStackIntoContainer(player, inventory, inventory2, vanillaInventoryHeight);
					}
				}
			}
		}

		private static void QuickStackIntoContainer(Player player, Inventory playerInventory, Inventory containerInventory, int vanillaHeight)
		{
			foreach (ItemData item in new List<ItemData>(playerInventory.GetAllItems()))
			{
				if (item != null && item.m_gridPos.y >= 0 && item.m_gridPos.y < vanillaHeight && item.m_gridPos.y != 0 && !((Humanoid)player).IsItemEquiped(item) && ContainerHasMatchingItem(containerInventory, item) && containerInventory.CanAddItem(item, -1) && containerInventory.AddItem(item))
				{
					playerInventory.RemoveItem(item);
				}
			}
		}

		private static bool ContainerHasMatchingItem(Inventory containerInventory, ItemData sourceItem)
		{
			foreach (ItemData allItem in containerInventory.GetAllItems())
			{
				if (allItem != null && allItem.m_shared.m_name == sourceItem.m_shared.m_name)
				{
					return true;
				}
			}
			return false;
		}

		private static int GetVanillaInventoryHeight(Player player)
		{
			string s = default(string);
			if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result))
			{
				return Mathf.Clamp(result, 0, 9);
			}
			return 4;
		}
	}
	internal static class TrashService
	{
		private const string JunkFileName = "HexQuickStackStorage.junk.txt";

		private static readonly HashSet<string> JunkItemNames = new HashSet<string>(StringComparer.Ordinal);

		private static readonly FieldInfo DragItemField = AccessTools.Field(typeof(InventoryGui), "m_dragItem");

		private static readonly FieldInfo DragInventoryField = AccessTools.Field(typeof(InventoryGui), "m_dragInventory");

		private static readonly FieldInfo DragAmountField = AccessTools.Field(typeof(InventoryGui), "m_dragAmount");

		private static readonly MethodInfo SetupDragItemMethod = AccessTools.Method(typeof(InventoryGui), "SetupDragItem", (Type[])null, (Type[])null);

		private static string JunkFilePath => Path.Combine(Paths.ConfigPath, "HexQuickStackStorage.junk.txt");

		internal static void Initialize()
		{
			LoadJunkItems();
		}

		internal static bool IsMarked(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			return JunkItemNames.Contains(item.m_shared.m_name);
		}

		internal static void ToggleMarked(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null || item.m_shared == null || !IsVanillaInventoryItem(player, item))
			{
				return;
			}
			if (!CanDeleteItem(item))
			{
				ShowProtectedItemMessage(player);
				return;
			}
			string name = item.m_shared.m_name;
			if (!JunkItemNames.Add(name))
			{
				JunkItemNames.Remove(name);
			}
			SaveJunkItems();
		}

		internal static void DeleteDraggedItem(InventoryGui inventoryGui, Player player)
		{
			if ((Object)(object)inventoryGui == (Object)null || (Object)(object)player == (Object)null)
			{
				return;
			}
			object? obj = DragItemField?.GetValue(inventoryGui);
			ItemData val = (ItemData)((obj is ItemData) ? obj : null);
			object? obj2 = DragInventoryField?.GetValue(inventoryGui);
			Inventory val2 = (Inventory)((obj2 is Inventory) ? obj2 : null);
			if (val == null || val2 == null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (val2 != inventory || !IsVanillaInventoryItem(player, val))
			{
				return;
			}
			if (!CanDeleteItem(val))
			{
				ShowProtectedItemMessage(player);
				return;
			}
			int num = Mathf.Min((!(DragAmountField != null)) ? 1 : ((int)DragAmountField.GetValue(inventoryGui)), val.m_stack);
			if (val2.RemoveItem(val, num))
			{
				SetupDragItemMethod?.Invoke(inventoryGui, new object[3] { null, null, 1 });
			}
		}

		internal static void DeleteMarkedItems(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return;
			}
			List<ItemData> list = new List<ItemData>(inventory.GetAllItems());
			bool flag = false;
			foreach (ItemData item in list)
			{
				if (item != null && item.m_shared != null && JunkItemNames.Contains(item.m_shared.m_name) && IsVanillaInventoryItem(player, item) && !CanDeleteItem(item))
				{
					flag = true;
				}
			}
			if (flag)
			{
				ShowProtectedItemMessage(player);
			}
		}

		internal static bool IsVanillaInventoryItem(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null)
			{
				return false;
			}
			int vanillaInventoryHeight = GetVanillaInventoryHeight(player);
			if (item.m_gridPos.y >= 0)
			{
				return item.m_gridPos.y < vanillaInventoryHeight;
			}
			return false;
		}

		private static bool CanDeleteItem(ItemData item)
		{
			if (item == null)
			{
				return false;
			}
			if (item.m_equipped)
			{
				return false;
			}
			if (item.m_gridPos.y == 0)
			{
				return false;
			}
			return true;
		}

		private static int GetVanillaInventoryHeight(Player player)
		{
			string s = default(string);
			if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result))
			{
				return Mathf.Clamp(result, 0, 9);
			}
			return 4;
		}

		private static void LoadJunkItems()
		{
			JunkItemNames.Clear();
			if (!File.Exists(JunkFilePath))
			{
				return;
			}
			string[] array = File.ReadAllLines(JunkFilePath);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (!string.IsNullOrEmpty(text))
				{
					JunkItemNames.Add(text);
				}
			}
		}

		private static void SaveJunkItems()
		{
			Directory.CreateDirectory(Paths.ConfigPath);
			List<string> list = new List<string>(JunkItemNames);
			list.Sort(StringComparer.Ordinal);
			File.WriteAllLines(JunkFilePath, list);
		}

		private static void ShowProtectedItemMessage(Player player)
		{
			((Character)player).Message((MessageType)2, "Can't delete equipped or hotbar items.", 0, (Sprite)null, false);
		}
	}
	internal static class InventoryUiController
	{
		private const string SortButtonName = "HexSortButton";

		private const string QuickStackButtonName = "HexQuickStackButton";

		private const string TrashButtonName = "HexTrashButton";

		private const float ButtonSize = 36f;

		private const float ButtonSpacing = 4f;

		private const float TrashIconSize = 32f;

		private const float TrashIconXOffset = 4f;

		private const float TrashIconYOffset = 0f;

		private static readonly FieldInfo CurrentContainerField = AccessTools.Field(typeof(InventoryGui), "m_currentContainer");

		private static readonly FieldInfo DragItemField = AccessTools.Field(typeof(InventoryGui), "m_dragItem");

		private static InventoryGui _inventoryGui;

		internal static void Initialize(InventoryGui inventoryGui)
		{
			if (!((Object)(object)inventoryGui == (Object)null))
			{
				_inventoryGui = inventoryGui;
				CreateButtons();
			}
		}

		private static void CreateButtons()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			if (!((Object)(object)_inventoryGui == (Object)null) && !((Object)(object)_inventoryGui.m_player == (Object)null) && !((Object)(object)_inventoryGui.m_takeAllButton == (Object)null))
			{
				Button takeAllButton = _inventoryGui.m_takeAllButton;
				CreateActionButton(takeAllButton, "HexSortButton", "S", 0, new UnityAction(OnSortClicked));
				CreateActionButton(takeAllButton, "HexQuickStackButton", "Q", 1, new UnityAction(OnQuickStackClicked));
				CreateTrashButton(new UnityAction(OnTrashClicked));
			}
		}

		private static Button CreateActionButton(Button template, string buttonName, string text, int index, UnityAction onClick)
		{
			Transform val = ((Component)_inventoryGui.m_player).transform.Find(buttonName);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).GetComponent<Button>();
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)_inventoryGui.m_player).transform);
			((Object)val2).name = buttonName;
			Button component = val2.GetComponent<Button>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			((UnityEventBase)component.onClick).RemoveAllListeners();
			((UnityEvent)component.onClick).AddListener(onClick);
			SetButtonText(val2, text);
			StyleActionButton(val2);
			PositionActionButton(val2, index);
			val2.SetActive(true);
			return component;
		}

		private static Button CreateTrashButton(UnityAction onClick)
		{
			Transform val = FindChildRecursive(((Component)_inventoryGui).transform, "HexTrashButton");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).GetComponent<Button>();
			}
			RectTransform val2 = FindStatusTab("armor");
			RectTransform val3 = FindStatusTab("weight");
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				return null;
			}
			GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, ((Transform)val3).parent);
			((Object)val4).name = "HexTrashButton";
			RectTransform component = val4.GetComponent<RectTransform>();
			Transform val5 = val4.transform.Find("weight_icon");
			Transform val6 = val4.transform.Find("weight_text");
			if ((Object)(object)val6 != (Object)null)
			{
				((Component)val6).gameObject.SetActive(false);
			}
			if ((Object)(object)val5 != (Object)null)
			{
				((Component)val5).gameObject.SetActive(false);
			}
			CreateTrashIcon(val4.transform);
			Button val7 = val4.GetComponent<Button>();
			if ((Object)(object)val7 == (Object)null)
			{
				val7 = val4.AddComponent<Button>();
			}
			Image component2 = val4.GetComponent<Image>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Selectable)val7).targetGraphic = (Graphic)(object)component2;
			}
			((UnityEventBase)val7.onClick).RemoveAllListeners();
			((UnityEvent)val7.onClick).AddListener(onClick);
			PositionTrashButton(component, val2, val3);
			int siblingIndex = Mathf.Min(((Transform)val2).GetSiblingIndex(), ((Transform)val3).GetSiblingIndex());
			((Transform)component).SetSiblingIndex(siblingIndex);
			val4.SetActive(true);
			return val7;
		}

		private static void CreateTrashIcon(Transform parent)
		{
			//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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: 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_0170: 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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: 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)
			GameObject val = new GameObject("TrashIcon", new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(32f, 32f);
			component.anchoredPosition = new Vector2(4f, 0f);
			RectTransform component2 = CreateIconPart(val.transform, "Body").GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0.2f, 0.1f);
			component2.anchorMax = new Vector2(0.8f, 0.7f);
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			RectTransform component3 = CreateIconPart(val.transform, "Lid").GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0.1f, 0.74f);
			component3.anchorMax = new Vector2(0.9f, 0.84f);
			component3.offsetMin = Vector2.zero;
			component3.offsetMax = Vector2.zero;
			RectTransform component4 = CreateIconPart(val.transform, "Handle").GetComponent<RectTransform>();
			component4.anchorMin = new Vector2(0.36f, 0.85f);
			component4.anchorMax = new Vector2(0.64f, 0.96f);
			component4.offsetMin = Vector2.zero;
			component4.offsetMax = Vector2.zero;
			CreateTrashSlot(val.transform, 0.35f);
			CreateTrashSlot(val.transform, 0.5f);
			CreateTrashSlot(val.transform, 0.65f);
		}

		private static GameObject CreateIconPart(Transform parent, string name)
		{
			//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_0033: 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_005f: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			((Transform)val.GetComponent<RectTransform>()).SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(0.72f, 0.72f, 0.72f, 1f);
			((Graphic)component).raycastTarget = false;
			return val;
		}

		private static void CreateTrashSlot(Transform parent, float x)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Slot", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			component.anchorMin = new Vector2(x, 0.18f);
			component.anchorMax = new Vector2(x, 0.6f);
			component.sizeDelta = new Vector2(2f, 0f);
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = new Color(0.2f, 0.2f, 0.2f, 1f);
			((Graphic)component2).raycastTarget = false;
		}

		private static void PositionTrashButton(RectTransform trashRect, RectTransform armorRect, RectTransform weightRect)
		{
			//IL_001e: 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_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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)trashRect == (Object)null) && !((Object)(object)armorRect == (Object)null) && !((Object)(object)weightRect == (Object)null))
			{
				trashRect.anchorMin = weightRect.anchorMin;
				trashRect.anchorMax = weightRect.anchorMax;
				trashRect.pivot = weightRect.pivot;
				trashRect.sizeDelta = weightRect.sizeDelta;
				Vector3 position = (((Transform)armorRect).position + ((Transform)weightRect).position) * 0.5f;
				((Transform)trashRect).position = position;
			}
		}

		private static RectTransform FindStatusTab(string namePart)
		{
			RectTransform[] componentsInChildren = ((Component)_inventoryGui).GetComponentsInChildren<RectTransform>(true);
			foreach (RectTransform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && ((Object)val).name.IndexOf(namePart, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return val;
				}
			}
			return null;
		}

		private static Transform FindChildRecursive(Transform parent, string childName)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if ((Object)(object)parent == (Object)null)
			{
				return null;
			}
			foreach (Transform item in parent)
			{
				Transform val = item;
				if (((Object)val).name == childName)
				{
					return val;
				}
				Transform val2 = FindChildRecursive(val, childName);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		private static void SetButtonText(GameObject buttonObject, string text)
		{
			TMP_Text componentInChildren = buttonObject.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.text = text;
				componentInChildren.alignment = (TextAlignmentOptions)514;
				return;
			}
			Text componentInChildren2 = buttonObject.GetComponentInChildren<Text>(true);
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.text = text;
				componentInChildren2.alignment = (TextAnchor)4;
			}
		}

		private static void StyleActionButton(GameObject buttonObject)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = buttonObject.GetComponent<RectTransform>();
			if (!((Object)(object)component == (Object)null))
			{
				component.sizeDelta = new Vector2(36f, 36f);
				Image component2 = buttonObject.GetComponent<Image>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.type = (Type)1;
				}
			}
		}

		private static void PositionActionButton(GameObject buttonObject, int index)
		{
			//IL_0035: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = buttonObject.GetComponent<RectTransform>();
			RectTransform component2 = ((Component)_inventoryGui.m_player).GetComponent<RectTransform>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null))
			{
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(0f, 1f);
				component.pivot = new Vector2(0f, 1f);
				Rect rect = component2.rect;
				float num = ((Rect)(ref rect)).width + 8f + (float)index * 40f;
				rect = component2.rect;
				float num2 = 0f - ((Rect)(ref rect)).height + 36f;
				component.anchoredPosition = new Vector2(num, num2);
			}
		}

		private static void OnSortClicked()
		{
			InventorySortService.SortPlayerInventory();
			if (!((Object)(object)_inventoryGui == (Object)null))
			{
				object? obj = CurrentContainerField?.GetValue(_inventoryGui);
				Container val = (Container)((obj is Container) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					InventorySortService.SortContainer(val);
				}
			}
		}

		private static void OnQuickStackClicked()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				QuickStackService.QuickStack(localPlayer);
			}
		}

		private static void OnTrashClicked()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)_inventoryGui == (Object)null))
			{
				if (DragItemField?.GetValue(_inventoryGui) is ItemData)
				{
					TrashService.DeleteDraggedItem(_inventoryGui, localPlayer);
				}
				else
				{
					TrashService.DeleteMarkedItems(localPlayer);
				}
			}
		}
	}
}
namespace HexQuickStackStorage.UI
{
	internal static class TrashBorderRenderer
	{
		private const string BorderName = "HexTrashBorder";

		private const float BorderThickness = 2f;

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

		internal static void Refresh(InventoryGrid grid)
		{
			if ((Object)(object)grid == (Object)null || grid.GetInventory() == null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || grid.GetInventory() != ((Humanoid)localPlayer).GetInventory() || !(ElementsField?.GetValue(grid) is List<InventoryElement> list))
			{
				return;
			}
			int width = grid.GetInventory().GetWidth();
			foreach (InventoryElement item in list)
			{
				if (!((Object)(object)item == (Object)null))
				{
					SetBorderVisible(item, visible: false);
				}
			}
			foreach (ItemData allItem in grid.GetInventory().GetAllItems())
			{
				if (allItem == null || !TrashService.IsMarked(allItem))
				{
					continue;
				}
				int num = allItem.m_gridPos.y * width + allItem.m_gridPos.x;
				if (num >= 0 && num < list.Count)
				{
					InventoryElement val = list[num];
					if ((Object)(object)val != (Object)null)
					{
						SetBorderVisible(val, visible: true);
					}
				}
			}
		}

		private static void SetBorderVisible(InventoryElement element, bool visible)
		{
			Transform val = ((Component)element).transform.Find("HexTrashBorder");
			GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
			if ((Object)(object)val2 == (Object)null && visible)
			{
				val2 = CreateBorder(((Component)element).transform);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				val2.SetActive(visible);
			}
		}

		private static GameObject CreateBorder(Transform parent)
		{
			//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_002d: 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_0043: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			GameObject val = new GameObject("HexTrashBorder", new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			CreateEdge(val.transform, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -2f), Vector2.zero);
			CreateEdge(val.transform, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 2f));
			CreateEdge(val.transform, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), Vector2.zero, new Vector2(2f, 0f));
			CreateEdge(val.transform, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-2f, 0f), Vector2.zero);
			((Transform)component).SetAsLastSibling();
			return val;
		}

		private static void CreateEdge(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax)
		{
			//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_0035: 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_0043: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			component.offsetMin = offsetMin;
			component.offsetMax = offsetMax;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = Color.red;
			((Graphic)component2).raycastTarget = false;
		}
	}
}
namespace HexQuickStackStorage.Patches
{
	[HarmonyPatch(typeof(Container), "RPC_OpenResponse")]
	internal static class ContainerPatch
	{
		private static void Postfix(Container __instance, bool granted)
		{
			if (granted && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
				if (ContainerService.IsPlayerOwnedContainer(__instance, playerID))
				{
					InventorySortService.SortContainer(__instance);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class InventoryGridPatch
	{
		[HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")]
		[HarmonyPrefix]
		private static bool OnRightClickItemPrefix(InventoryGrid grid, ItemData item)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)grid == (Object)null || item == null)
			{
				return true;
			}
			if (grid.GetInventory() != ((Humanoid)localPlayer).GetInventory())
			{
				return true;
			}
			if (!ZInput.GetKey((KeyCode)304, true) && !ZInput.GetKey((KeyCode)303, true))
			{
				return true;
			}
			if (!TrashService.IsVanillaInventoryItem(localPlayer, item))
			{
				return true;
			}
			TrashService.ToggleMarked(localPlayer, item);
			TrashBorderRenderer.Refresh(grid);
			return false;
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		[HarmonyPostfix]
		private static void UpdateGuiPostfix(InventoryGrid __instance)
		{
			TrashBorderRenderer.Refresh(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class InventoryGuiPatch
	{
		private static void Postfix(InventoryGui __instance)
		{
			InventoryUiController.Initialize(__instance);
		}
	}
}