Decompiled source of Hoardkeeper v1.0.0

plugins/Hoardkeeper/Hoardkeeper.dll

Decompiled 28 minutes ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Hoardkeeper;

internal static class Actions
{
	private static readonly string[] OrderNames = new string[7] { "type", "name A-Z", "name Z-A", "quality", "weight", "amount", "value" };

	private static Container Open()
	{
		return Chests.OpenOne();
	}

	private static string L(string s)
	{
		if (Localization.instance == null)
		{
			return s;
		}
		return Localization.instance.Localize(s);
	}

	private static int Group(ItemData it)
	{
		//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 = it.m_shared.m_itemType;
		switch (itemType - 1)
		{
		case 2:
		case 3:
		case 4:
		case 13:
		case 14:
		case 21:
			return 0;
		case 8:
		case 22:
			return 1;
		case 5:
		case 6:
		case 10:
		case 16:
		case 17:
		case 23:
			return 2;
		case 18:
			return 3;
		case 1:
			return 4;
		case 0:
			return 5;
		case 12:
			return 7;
		default:
			return 6;
		}
	}

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

	private static int Compare(ItemData a, ItemData b)
	{
		int num = Plugin.Order.Value switch
		{
			Plugin.SortOrder.NameAZ => ByName(a, b), 
			Plugin.SortOrder.NameZA => ByName(b, a), 
			Plugin.SortOrder.Quality => b.m_quality.CompareTo(a.m_quality), 
			Plugin.SortOrder.Weight => b.GetWeight(-1).CompareTo(a.GetWeight(-1)), 
			Plugin.SortOrder.Amount => b.m_stack.CompareTo(a.m_stack), 
			Plugin.SortOrder.Value => (b.m_shared.m_value * b.m_stack).CompareTo(a.m_shared.m_value * a.m_stack), 
			_ => Group(a).CompareTo(Group(b)), 
		};
		if (num == 0)
		{
			num = ByName(a, b);
		}
		if (num == 0)
		{
			num = b.m_quality.CompareTo(a.m_quality);
		}
		if (num == 0)
		{
			num = b.m_stack.CompareTo(a.m_stack);
		}
		return num;
	}

	internal static string OrderName()
	{
		return OrderNames[(int)Plugin.Order.Value];
	}

	internal static void NextOrder()
	{
		Plugin.Order.Value = (Plugin.SortOrder)((int)(Plugin.Order.Value + 1) % OrderNames.Length);
		Plugin.Say("Sort by " + OrderName());
	}

	internal static void Sort(Inventory inv, Func<ItemData, bool> keep, Func<int, int, bool> blocked, int firstRow)
	{
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		List<ItemData> allItems = inv.GetAllItems();
		List<ItemData> list = new List<ItemData>();
		foreach (ItemData item in allItems)
		{
			if (!keep(item))
			{
				list.Add(item);
			}
		}
		Dictionary<string, List<ItemData>> dictionary = new Dictionary<string, List<ItemData>>();
		foreach (ItemData item2 in list)
		{
			if (item2.m_shared.m_maxStackSize > 1 && item2.m_customData.Count <= 0)
			{
				string key = item2.m_shared.m_name + "|" + item2.m_quality + "|" + item2.m_worldLevel;
				if (!dictionary.TryGetValue(key, out var value))
				{
					value = (dictionary[key] = new List<ItemData>());
				}
				value.Add(item2);
			}
		}
		foreach (List<ItemData> value2 in dictionary.Values)
		{
			if (value2.Count < 2)
			{
				continue;
			}
			int num = 0;
			foreach (ItemData item3 in value2)
			{
				num += item3.m_stack;
			}
			foreach (ItemData item4 in value2)
			{
				int num2 = (item4.m_stack = Mathf.Min(num, item4.m_shared.m_maxStackSize));
				num -= num2;
				if (num2 == 0)
				{
					allItems.Remove(item4);
					list.Remove(item4);
				}
			}
		}
		list.Sort(Compare);
		HashSet<long> hashSet = new HashSet<long>();
		foreach (ItemData item5 in allItems)
		{
			if (keep(item5))
			{
				hashSet.Add((long)item5.m_gridPos.x * 1000L + item5.m_gridPos.y);
			}
		}
		int num3 = 0;
		for (int i = firstRow; i < inv.GetHeight(); i++)
		{
			if (num3 >= list.Count)
			{
				break;
			}
			for (int j = 0; j < inv.GetWidth(); j++)
			{
				if (num3 >= list.Count)
				{
					break;
				}
				if (!hashSet.Contains((long)j * 1000L + i) && !blocked(j, i))
				{
					list[num3++].m_gridPos = new Vector2i(j, i);
				}
			}
		}
		Chests.Changed(inv);
	}

	internal static void SortMine(Player p, bool quiet = false)
	{
		Sort(((Humanoid)p).GetInventory(), (ItemData it) => Locks.Keep(p, it), (int x, int y) => Locks.IsLocked(p, x, y), 1);
		if (!quiet)
		{
			Plugin.Say("Inventory sorted by " + OrderName());
		}
	}

	internal static void SortChest(Container c)
	{
		Chests.Claim(c);
		Sort(c.GetInventory(), (ItemData it) => false, (int x, int y) => false, 0);
	}

	internal static void SortHere(Player p)
	{
		Container val = Open();
		if ((Object)(object)val != (Object)null)
		{
			SortChest(val);
			Plugin.Say("Chest sorted by " + OrderName());
		}
		else
		{
			SortMine(p);
		}
	}

	internal static void QuickStack(Player p)
	{
		Inventory inventory = ((Humanoid)p).GetInventory();
		int num = 0;
		int num2 = 0;
		foreach (Container item in Chests.Near(p, Plugin.Range.Value))
		{
			Inventory inventory2 = item.GetInventory();
			HashSet<string> hashSet = new HashSet<string>();
			foreach (ItemData allItem in inventory2.GetAllItems())
			{
				hashSet.Add(allItem.m_shared.m_name);
			}
			if (hashSet.Count == 0)
			{
				continue;
			}
			bool flag = false;
			foreach (ItemData item2 in new List<ItemData>(inventory.GetAllItems()))
			{
				if (!Locks.Keep(p, item2) && hashSet.Contains(item2.m_shared.m_name))
				{
					if (!flag)
					{
						Chests.Claim(item);
						flag = true;
					}
					num += Chests.Move(inventory, inventory2, item2, item2.m_stack);
				}
			}
			if (flag)
			{
				num2++;
			}
		}
		Plugin.Say((num > 0) ? ("Stacked " + num + " items into " + num2 + " chest" + ((num2 == 1) ? "" : "s")) : "Nothing to stack nearby");
	}

	internal static void Restock(Player p)
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Invalid comparison between Unknown and I4
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Invalid comparison between Unknown and I4
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		Inventory inventory = ((Humanoid)p).GetInventory();
		List<Container> list = Chests.Near(p, Plugin.Range.Value);
		if (list.Count == 0)
		{
			Plugin.Say("No chests nearby");
			return;
		}
		int num = 0;
		foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
		{
			if (item.m_shared.m_maxStackSize > 1 && item.m_stack < item.m_shared.m_maxStackSize && (item.m_gridPos.y == 0 || Locks.IsLocked(p, item.m_gridPos.x, item.m_gridPos.y) || (int)item.m_shared.m_itemType == 9 || (int)item.m_shared.m_itemType == 23))
			{
				num += Fill(list, inventory, item.m_shared.m_name, item.m_gridPos.x, item.m_gridPos.y, item.m_shared.m_maxStackSize - item.m_stack);
			}
		}
		foreach (KeyValuePair<Vector2i, string> item2 in Locks.All(p))
		{
			if (!string.IsNullOrEmpty(item2.Value) && inventory.GetItemAt(item2.Key.x, item2.Key.y) == null)
			{
				num += Fill(list, inventory, item2.Value, item2.Key.x, item2.Key.y, int.MaxValue);
			}
		}
		Plugin.Say((num > 0) ? ("Restocked " + num + " items") : "Nothing to restock");
	}

	private static int Fill(List<Container> near, Inventory mine, string name, int x, int y, int want)
	{
		int num = 0;
		foreach (Container item in near)
		{
			Inventory inventory = item.GetInventory();
			foreach (ItemData item2 in new List<ItemData>(inventory.GetAllItems()))
			{
				if (want <= 0)
				{
					return num;
				}
				if (item2.m_shared.m_name != name)
				{
					continue;
				}
				ItemData itemAt = mine.GetItemAt(x, y);
				if (itemAt == null || itemAt.IsSameType(item2))
				{
					int num2 = ((itemAt != null) ? (itemAt.m_shared.m_maxStackSize - itemAt.m_stack) : item2.m_shared.m_maxStackSize);
					int num3 = Mathf.Min(new int[3] { want, num2, item2.m_stack });
					if (num3 <= 0)
					{
						return num;
					}
					Chests.Claim(item);
					if (mine.MoveItemToThis(inventory, item2, num3, x, y))
					{
						num += num3;
						want -= num3;
					}
				}
			}
		}
		return num;
	}

	internal static void StoreAll(Player p)
	{
		Container val = Open();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Chests.Claim(val);
		Inventory inventory = ((Humanoid)p).GetInventory();
		Inventory inventory2 = val.GetInventory();
		int num = 0;
		foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
		{
			if (!Locks.Keep(p, item))
			{
				num += Chests.Move(inventory, inventory2, item, item.m_stack);
			}
		}
		Plugin.Say((num > 0) ? ("Stored " + num + " items") : "Nothing to store");
	}

	internal static void SortAll(List<Container> chests)
	{
		foreach (Container chest in chests)
		{
			SortChest(chest);
		}
		Plugin.Say("Sorted " + chests.Count + " chest" + ((chests.Count == 1) ? "" : "s") + " by " + OrderName());
	}

	internal static void Tidy(List<Container> chests)
	{
		Dictionary<string, Container> dictionary = new Dictionary<string, Container>();
		Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
		foreach (Container chest in chests)
		{
			Dictionary<string, int> dictionary3 = new Dictionary<string, int>();
			foreach (ItemData allItem in chest.GetInventory().GetAllItems())
			{
				dictionary3.TryGetValue(allItem.m_shared.m_name, out var value);
				dictionary3[allItem.m_shared.m_name] = value + allItem.m_stack;
			}
			foreach (KeyValuePair<string, int> item in dictionary3)
			{
				if (!dictionary2.TryGetValue(item.Key, out var value2) || item.Value > value2)
				{
					dictionary2[item.Key] = item.Value;
					dictionary[item.Key] = chest;
				}
			}
		}
		int num = 0;
		foreach (Container chest2 in chests)
		{
			foreach (ItemData item2 in new List<ItemData>(chest2.GetInventory().GetAllItems()))
			{
				if (dictionary.TryGetValue(item2.m_shared.m_name, out var value3) && !((Object)(object)value3 == (Object)(object)chest2))
				{
					Chests.Claim(chest2);
					Chests.Claim(value3);
					num += Chests.Move(chest2.GetInventory(), value3.GetInventory(), item2, item2.m_stack);
				}
			}
		}
		foreach (Container chest3 in chests)
		{
			SortChest(chest3);
		}
		Plugin.Say("Tidied up: " + num + " items moved, " + chests.Count + " chests sorted");
	}

	internal static void Gather(Player p, Container target, List<Container> chests, bool fromBag)
	{
		Inventory inventory = target.GetInventory();
		HashSet<string> hashSet = new HashSet<string>();
		foreach (ItemData allItem in inventory.GetAllItems())
		{
			hashSet.Add(allItem.m_shared.m_name);
		}
		if (hashSet.Count == 0)
		{
			Plugin.Say("Put an item in this chest first: Gather brings more of what it holds");
			return;
		}
		Chests.Claim(target);
		int num = 0;
		foreach (Container chest in chests)
		{
			if ((Object)(object)chest == (Object)(object)target)
			{
				continue;
			}
			foreach (ItemData item in new List<ItemData>(chest.GetInventory().GetAllItems()))
			{
				if (hashSet.Contains(item.m_shared.m_name))
				{
					Chests.Claim(chest);
					num += Chests.Move(chest.GetInventory(), inventory, item, item.m_stack);
				}
			}
		}
		if (fromBag)
		{
			foreach (ItemData item2 in new List<ItemData>(((Humanoid)p).GetInventory().GetAllItems()))
			{
				if (hashSet.Contains(item2.m_shared.m_name) && !Locks.Keep(p, item2))
				{
					num += Chests.Move(((Humanoid)p).GetInventory(), inventory, item2, item2.m_stack);
				}
			}
		}
		Plugin.Say((num > 0) ? ("Gathered " + num + " items into " + Chests.Title(target)) : "Nothing to gather");
	}

	internal static void TakeAll(Player p, Container c)
	{
		Chests.Claim(c);
		int num = 0;
		foreach (ItemData item in new List<ItemData>(c.GetInventory().GetAllItems()))
		{
			num += Chests.Move(c.GetInventory(), ((Humanoid)p).GetInventory(), item, item.m_stack);
		}
		Plugin.Say((num > 0) ? ("Took " + num + " items") : "Nothing taken (is your bag full?)");
	}

	internal static bool SendToChests(Player p, ItemData it, List<Container> chests)
	{
		if (it.m_shared.m_questItem)
		{
			return false;
		}
		string item = Tags.Category(it);
		List<Container> list = new List<Container>();
		List<Container> list2 = new List<Container>();
		foreach (Container chest in chests)
		{
			(Tags.Of(chest).Contains(item) ? list : list2).Add(chest);
		}
		list.AddRange(list2);
		chests = list;
		Container val = null;
		foreach (Container chest2 in chests)
		{
			if (Tags.Of(chest2).Contains(item) && Chests.Space(chest2.GetInventory(), it) > 0)
			{
				if ((Object)(object)val == (Object)null)
				{
					val = chest2;
				}
				if (Chests.Count(chest2.GetInventory(), it.m_shared.m_name) > 0)
				{
					val = chest2;
					break;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			foreach (Container chest3 in chests)
			{
				if (Chests.Count(chest3.GetInventory(), it.m_shared.m_name) > 0 && Chests.Space(chest3.GetInventory(), it) > 0)
				{
					val = chest3;
					break;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			foreach (Container chest4 in chests)
			{
				if (Chests.Space(chest4.GetInventory(), it) > 0)
				{
					val = chest4;
					break;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Say("No room in the chests");
			return false;
		}
		if (it.m_equipped)
		{
			((Humanoid)p).UnequipItem(it, false);
		}
		Chests.Claim(val);
		return Chests.Move(((Humanoid)p).GetInventory(), val.GetInventory(), it, it.m_stack) > 0;
	}

	internal static void Trash(Player p)
	{
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Expected O, but got Unknown
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Expected O, but got Unknown
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Expected O, but got Unknown
		InventoryGui instance = InventoryGui.instance;
		Traverse val = Traverse.Create((object)instance);
		ItemData drag = val.Field("m_dragItem").GetValue<ItemData>();
		Inventory from = val.Field("m_dragInventory").GetValue<Inventory>();
		if (drag == null)
		{
			Plugin.Say("Pick up an item and put it on the trash can to destroy it");
			return;
		}
		int amount = val.Field("m_dragAmount").GetValue<int>();
		if (amount <= 0 || amount > drag.m_stack)
		{
			amount = drag.m_stack;
		}
		string what = ((amount > 1) ? (amount + " ") : "") + L(drag.m_shared.m_name);
		UnifiedPopup.Push((PopupBase)new YesNoPopup("Destroy item", "Destroy " + what + "? This can't be undone.", (PopupButtonCallback)delegate
		{
			UnifiedPopup.Pop();
			if (from != null && from.ContainsItem(drag))
			{
				if (drag.m_equipped)
				{
					((Humanoid)p).UnequipItem(drag, false);
				}
				from.RemoveItem(drag, amount);
				Traverse.Create((object)InventoryGui.instance).Method("SetupDragItem", new Type[3]
				{
					typeof(ItemData),
					typeof(Inventory),
					typeof(int)
				}, (object[])null).GetValue(new object[3] { null, null, 1 });
				Plugin.Say("Destroyed " + what);
			}
		}, (PopupButtonCallback)delegate
		{
			UnifiedPopup.Pop();
		}, false, false));
	}
}
[HarmonyPatch]
internal static class AutoSort
{
	private static float _due = -1f;

	private static bool Dragging()
	{
		if ((Object)(object)InventoryGui.instance != (Object)null)
		{
			return Traverse.Create((object)InventoryGui.instance).Field("m_dragItem").GetValue<ItemData>() != null;
		}
		return false;
	}

	internal static void Tick(Player p)
	{
		if (!(_due < 0f) && !(Time.time < _due))
		{
			if (Dragging())
			{
				_due = Time.time + 0.5f;
				return;
			}
			_due = -1f;
			Actions.SortMine(p, quiet: true);
		}
	}

	[HarmonyPatch(typeof(Humanoid), "Pickup")]
	[HarmonyPostfix]
	private static void Picked(Humanoid __instance, bool __result)
	{
		if (__result && Plugin.AutoSortPickup.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
		{
			_due = Time.time + 0.4f;
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Show")]
	[HarmonyPostfix]
	private static void Opened(Container container)
	{
		if (!Plugin.AutoSortOpen.Value || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return;
		}
		try
		{
			if ((Object)(object)container != (Object)null)
			{
				Actions.SortChest(container);
			}
			else
			{
				Actions.SortMine(Player.m_localPlayer, quiet: true);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Auto sort failed: " + ex.Message));
		}
	}
}
[HarmonyPatch]
internal static class ChestName
{
	private const float ChipW = 66f;

	private const float ChipH = 26f;

	private static Button _btn;

	private static TMP_InputField _field;

	private static Container _for;

	private static RectTransform _tags;

	private static readonly List<KeyValuePair<string, Button>> _chips = new List<KeyValuePair<string, Button>>();

	internal static bool Typing()
	{
		if ((Object)(object)_field != (Object)null && ((Component)_field).gameObject.activeSelf)
		{
			return _field.isFocused;
		}
		return false;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(InventoryGui), "Update")]
	private static void Tick(InventoryGui __instance)
	{
		try
		{
			if (!((Object)(object)__instance.m_container == (Object)null) && !((Object)(object)__instance.m_takeAllButton == (Object)null))
			{
				if ((Object)(object)_btn == (Object)null)
				{
					Build(__instance);
				}
				Container val = Chests.OpenOne();
				if ((Object)(object)val == (Object)null && (Object)(object)_field != (Object)null && ((Component)_field).gameObject.activeSelf)
				{
					((Component)_field).gameObject.SetActive(false);
					_for = null;
				}
				if ((Object)(object)val == (Object)null && (Object)(object)_tags != (Object)null && ((Component)_tags).gameObject.activeSelf)
				{
					((Component)_tags).gameObject.SetActive(false);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Chest name button: " + ex.Message));
		}
	}

	private static void Build(InventoryGui gui)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Expected O, but got Unknown
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
		_btn = Ui.CloneButton(gui, (Transform)(object)gui.m_container, "Name", 60f, 26f, Start, "Give this chest a name (shown when you look at it and in the Storage window)");
		((Object)_btn).name = "Hoardkeeper_ChestName";
		RectTransform val = (RectTransform)((Component)_btn).transform;
		Vector2 anchorMin = (val.anchorMax = new Vector2(1f, 0f));
		val.anchorMin = anchorMin;
		val.pivot = new Vector2(1f, 0f);
		val.anchoredPosition = new Vector2(-12f, 12f);
		val.sizeDelta = new Vector2(60f, 26f);
		Corner(Ui.CloneButton(gui, (Transform)(object)gui.m_container, "Tags", 50f, 26f, ToggleTags, "Choose which kinds of item belong in this chest (same tags as in the Storage window)"), -76f, 50f);
		Corner(Ui.CloneButton(gui, (Transform)(object)gui.m_container, "Fill tags", 70f, 26f, FillHere, "Bring every item of this chest's tags here, from your bag and the chests nearby"), -130f, 70f);
		BuildTags(gui);
		_field = Ui.Field(gui, (Transform)(object)gui.m_container, "Chest name");
		_field.characterLimit = 30;
		((UnityEvent<string>)(object)_field.onEndEdit).AddListener((UnityAction<string>)End);
		((Component)_field).gameObject.SetActive(false);
	}

	private static void Corner(Button b, float x, float w)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//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_0024: 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_0046: 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)
		RectTransform val = (RectTransform)((Component)b).transform;
		Vector2 anchorMin = (val.anchorMax = new Vector2(1f, 0f));
		val.anchorMin = anchorMin;
		val.pivot = new Vector2(1f, 0f);
		val.anchoredPosition = new Vector2(x, 12f);
		val.sizeDelta = new Vector2(w, 26f);
	}

	private static void BuildTags(InventoryGui gui)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Expected O, but got Unknown
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: 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_0147: Expected O, but got Unknown
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: 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_016e: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
		int num = (Tags.All.Length + 4 - 1) / 4;
		GameObject val = new GameObject("Hoardkeeper_ChestTags", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		_tags = (RectTransform)val.transform;
		((Transform)_tags).SetParent((Transform)(object)gui.m_container, false);
		RectTransform tags = _tags;
		Vector2 anchorMin = (_tags.anchorMax = new Vector2(0.5f, 0f));
		tags.anchorMin = anchorMin;
		_tags.pivot = new Vector2(0.5f, 1f);
		_tags.anchoredPosition = new Vector2(0f, -4f);
		_tags.sizeDelta = new Vector2(292f, (float)num * 30f - 4f + 16f);
		Skin.Window(gui, _tags, val.GetComponent<Image>());
		for (int i = 0; i < Tags.All.Length; i++)
		{
			string tag = Tags.All[i];
			Button val3 = Ui.CloneButton(gui, (Transform)(object)_tags, tag, 66f, 26f, delegate
			{
				Container val8 = Chests.OpenOne();
				if ((Object)(object)val8 != (Object)null)
				{
					Tags.Toggle(val8, tag);
					Labels();
				}
			}, null);
			RectTransform val4 = (RectTransform)((Component)val3).transform;
			Vector2 val5 = (val4.pivot = new Vector2(0f, 1f));
			Vector2 anchorMin2 = (val4.anchorMax = val5);
			val4.anchorMin = anchorMin2;
			val4.anchoredPosition = new Vector2(8f + (float)(i % 4) * 70f, -8f - (float)(i / 4) * 30f);
			val4.sizeDelta = new Vector2(66f, 26f);
			_chips.Add(new KeyValuePair<string, Button>(tag, val3));
		}
		val.SetActive(false);
	}

	private static void Labels()
	{
		Container val = Chests.OpenOne();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		HashSet<string> hashSet = Tags.Of(val);
		foreach (KeyValuePair<string, Button> chip in _chips)
		{
			Ui.Label(chip.Value, hashSet.Contains(chip.Key) ? ("<b><color=#ffcc55>" + chip.Key + "</color></b>") : ("<color=#8a8a8a>" + chip.Key + "</color>"));
		}
	}

	private static void ToggleTags()
	{
		if (!((Object)(object)_tags == (Object)null) && !((Object)(object)Chests.OpenOne() == (Object)null))
		{
			bool flag = !((Component)_tags).gameObject.activeSelf;
			((Component)_tags).gameObject.SetActive(flag);
			if (flag)
			{
				((Transform)_tags).SetAsLastSibling();
				Labels();
			}
		}
	}

	private static void FillHere()
	{
		Player localPlayer = Player.m_localPlayer;
		Container val = Chests.OpenOne();
		if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)val == (Object)null))
		{
			Tags.Fill(localPlayer, Chests.Near(localPlayer, Plugin.Range.Value), val);
		}
	}

	private static void Start()
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: 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_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: 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_00c8: 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_00de: 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)
		InventoryGui instance = InventoryGui.instance;
		Container val = Chests.OpenOne();
		if (!((Object)(object)instance == (Object)null) && !((Object)(object)val == (Object)null))
		{
			_for = val;
			RectTransform val2 = (((Object)(object)instance.m_containerName != (Object)null) ? instance.m_containerName.rectTransform : null);
			RectTransform val3 = (RectTransform)((Component)_field).transform;
			if ((Object)(object)val2 != (Object)null)
			{
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				val2.GetWorldCorners(array);
				Vector2 anchorMin = (val3.anchorMax = new Vector2(0.5f, 0.5f));
				val3.anchorMin = anchorMin;
				val3.pivot = new Vector2(0.5f, 0.5f);
				((Transform)val3).position = (array[0] + array[2]) * 0.5f;
				Rect rect = val2.rect;
				val3.sizeDelta = new Vector2(Mathf.Max(200f, ((Rect)(ref rect)).width), 30f);
			}
			((Component)_field).transform.SetAsLastSibling();
			_field.text = Chests.Name(val);
			((Component)_field).gameObject.SetActive(true);
			((Selectable)_field).Select();
			_field.ActivateInputField();
		}
	}

	private static void End(string text)
	{
		Container val = _for;
		_for = null;
		if ((Object)(object)_field != (Object)null)
		{
			((Component)_field).gameObject.SetActive(false);
		}
		if (!((Object)(object)val == (Object)null) && text != Chests.Name(val))
		{
			Chests.SetName(val, text);
			Plugin.Say((text.Trim().Length > 0) ? ("Chest named " + text.Trim()) : "Chest name removed");
		}
	}
}
[HarmonyPatch]
internal static class Chests
{
	private const string NameKey = "Hoardkeeper_name";

	private const string SkipKey = "Hoardkeeper_skip_";

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

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

	private static readonly FieldInfo PieceF = AccessTools.Field(typeof(Container), "m_piece");

	private static readonly FieldInfo InUseF = AccessTools.Field(typeof(Container), "m_inUse");

	private static readonly MethodInfo UseVisual = AccessTools.Method(typeof(Container), "UpdateUseVisual", (Type[])null, (Type[])null);

	internal static void Changed(Inventory inv)
	{
		if (inv != null && ChangedM != null)
		{
			ChangedM.Invoke(inv, new object[2] { false, false });
		}
	}

	internal static ZNetView View(Container c)
	{
		if (!((Object)(object)c != (Object)null))
		{
			return null;
		}
		object? value = NView.GetValue(c);
		return (ZNetView)((value is ZNetView) ? value : null);
	}

	internal static Container OpenOne()
	{
		if (!((Object)(object)InventoryGui.instance != (Object)null))
		{
			return null;
		}
		return Traverse.Create((object)InventoryGui.instance).Field("m_currentContainer").GetValue<Container>();
	}

	internal static List<Container> Near(Player p, float range, bool withSkipped = false)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: 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_00ee: 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_010b: Invalid comparison between Unknown and I4
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		List<Container> list = new List<Container>();
		Container val = OpenOne();
		Vector3 at = ((Component)p).transform.position;
		Container[] array = Object.FindObjectsOfType<Container>();
		foreach (Container val2 in array)
		{
			if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).GetComponent<TombStone>() != (Object)null || Vector3.Distance(at, ((Component)val2).transform.position) > range)
			{
				continue;
			}
			ZNetView val3 = View(val2);
			if (!((Object)(object)val3 == (Object)null) && val3.IsValid() && ((Object)(object)val2 == (Object)(object)val || Storage.Holds(val2) || (!val2.IsInUse() && (val3.IsOwner() || val3.GetZDO().GetInt(ZDOVars.s_inUse, 0) != 1))))
			{
				object? value = PieceF.GetValue(val2);
				Piece val4 = (Piece)((value is Piece) ? value : null);
				if (!((Object)(object)val4 == (Object)null) && ((int)val2.m_privacy != 0 || val4.GetCreator() == p.GetPlayerID()) && (int)val2.m_privacy != 1 && PrivateArea.CheckAccess(((Component)val2).transform.position, 0f, false, false) && val2.GetInventory() != null && (withSkipped || !Skipped(val2)))
				{
					list.Add(val2);
				}
			}
		}
		list.Sort((Container a, Container b) => Vector3.Distance(at, ((Component)a).transform.position).CompareTo(Vector3.Distance(at, ((Component)b).transform.position)));
		return list;
	}

	internal static void Claim(Container c)
	{
		ZNetView val = View(c);
		if ((Object)(object)val != (Object)null && val.IsValid() && !val.IsOwner())
		{
			val.ClaimOwnership();
		}
	}

	internal static void MarkInUse(Container c, bool on)
	{
		ZNetView val = View(c);
		if (!((Object)(object)val == (Object)null) && val.IsValid() && val.IsOwner() && (bool)InUseF.GetValue(c) != on)
		{
			InUseF.SetValue(c, on);
			UseVisual.Invoke(c, null);
		}
	}

	internal static string Name(Container c)
	{
		ZNetView val = View(c);
		if (!((Object)(object)val != (Object)null) || !val.IsValid())
		{
			return "";
		}
		return val.GetZDO().GetString("Hoardkeeper_name", "");
	}

	internal static void SetName(Container c, string name)
	{
		ZNetView val = View(c);
		if (!((Object)(object)val == (Object)null) && val.IsValid())
		{
			Claim(c);
			val.GetZDO().Set("Hoardkeeper_name", (name ?? "").Trim());
		}
	}

	internal static string Title(Container c)
	{
		string text = Name(c);
		if (text.Length <= 0)
		{
			return Localization.instance.Localize(c.GetInventory().GetName());
		}
		return text;
	}

	internal static bool Skipped(Container c)
	{
		ZNetView val = View(c);
		if ((Object)(object)val != (Object)null && val.IsValid() && (Object)(object)Player.m_localPlayer != (Object)null)
		{
			return val.GetZDO().GetBool("Hoardkeeper_skip_" + Player.m_localPlayer.GetPlayerID(), false);
		}
		return false;
	}

	internal static void SetSkipped(Container c, bool on)
	{
		ZNetView val = View(c);
		if (!((Object)(object)val == (Object)null) && val.IsValid() && !((Object)(object)Player.m_localPlayer == (Object)null))
		{
			Claim(c);
			val.GetZDO().Set("Hoardkeeper_skip_" + Player.m_localPlayer.GetPlayerID(), on);
		}
	}

	[HarmonyPatch(typeof(Container), "GetHoverText")]
	[HarmonyPostfix]
	private static void Hover(Container __instance, ref string __result)
	{
		string text = Name(__instance);
		if (text.Length > 0)
		{
			__result = "<color=#ffcc66>" + text + "</color>" + (Skipped(__instance) ? " <color=#888888>(skipped)</color>" : "") + "\n" + __result;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
	private static void WindowTitle(InventoryGui __instance)
	{
		Container val = OpenOne();
		if (!((Object)(object)val == (Object)null) && !((Object)(object)__instance.m_containerName == (Object)null))
		{
			string text = Name(val);
			if (text.Length > 0)
			{
				__instance.m_containerName.text = text;
			}
		}
	}

	internal static int Space(Inventory inv, ItemData item)
	{
		int num = inv.GetWidth() * inv.GetHeight() - inv.GetAllItems().Count;
		int num2 = num * item.m_shared.m_maxStackSize;
		foreach (ItemData allItem in inv.GetAllItems())
		{
			if (allItem.m_shared.m_name == item.m_shared.m_name && allItem.m_quality == item.m_quality && allItem.m_worldLevel == item.m_worldLevel)
			{
				num2 += Mathf.Max(0, allItem.m_shared.m_maxStackSize - allItem.m_stack);
			}
		}
		return num2;
	}

	internal static int Move(Inventory from, Inventory to, ItemData item, int amount)
	{
		int num = Mathf.Min(new int[3]
		{
			amount,
			item.m_stack,
			Space(to, item)
		});
		if (num <= 0)
		{
			return 0;
		}
		ItemData val = item.Clone();
		val.m_stack = num;
		val.m_equipped = false;
		if (!to.AddItem(val))
		{
			return 0;
		}
		from.RemoveItem(item, num);
		return num;
	}

	internal static int Count(Inventory inv, string name)
	{
		int num = 0;
		foreach (ItemData allItem in inv.GetAllItems())
		{
			if (allItem.m_shared.m_name == name)
			{
				num += allItem.m_stack;
			}
		}
		return num;
	}
}
internal static class Locks
{
	private const string LockKey = "Hoardkeeper_locks";

	private const string FavKey = "Hoardkeeper_favs";

	private static Player _for;

	private static readonly Dictionary<long, string> _locks = new Dictionary<long, string>();

	private static Player _favFor;

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

	private static long K(int x, int y)
	{
		return (long)x * 1000L + y;
	}

	private static void Load(Player p)
	{
		if ((Object)(object)p == (Object)(object)_for)
		{
			return;
		}
		_for = p;
		_locks.Clear();
		if (!p.m_customData.TryGetValue("Hoardkeeper_locks", out var value))
		{
			return;
		}
		string[] array = value.Split(';');
		foreach (string text in array)
		{
			string[] array2 = text.Split(new char[1] { ',' }, 3);
			if (array2.Length >= 2 && int.TryParse(array2[0], out var result) && int.TryParse(array2[1], out var result2))
			{
				_locks[K(result, result2)] = ((array2.Length > 2) ? array2[2] : "");
			}
		}
	}

	private static void Save(Player p)
	{
		StringBuilder stringBuilder = new StringBuilder();
		foreach (KeyValuePair<long, string> @lock in _locks)
		{
			if (stringBuilder.Length > 0)
			{
				stringBuilder.Append(';');
			}
			stringBuilder.Append(@lock.Key / 1000).Append(',').Append(@lock.Key % 1000)
				.Append(',')
				.Append(@lock.Value);
		}
		p.m_customData["Hoardkeeper_locks"] = stringBuilder.ToString();
	}

	internal static bool IsLocked(Player p, int x, int y)
	{
		Load(p);
		return _locks.ContainsKey(K(x, y));
	}

	internal static string LockedItem(Player p, int x, int y)
	{
		Load(p);
		if (!_locks.TryGetValue(K(x, y), out var value))
		{
			return null;
		}
		return value;
	}

	internal static IEnumerable<KeyValuePair<Vector2i, string>> All(Player p)
	{
		Load(p);
		foreach (KeyValuePair<long, string> kv in _locks)
		{
			KeyValuePair<long, string> keyValuePair = kv;
			int num = (int)(keyValuePair.Key / 1000);
			KeyValuePair<long, string> keyValuePair2 = kv;
			Vector2i key = new Vector2i(num, (int)(keyValuePair2.Key % 1000));
			KeyValuePair<long, string> keyValuePair3 = kv;
			yield return new KeyValuePair<Vector2i, string>(key, keyValuePair3.Value);
		}
	}

	internal static void Toggle(Player p, int x, int y)
	{
		Load(p);
		long key = K(x, y);
		if (_locks.ContainsKey(key))
		{
			_locks.Remove(key);
			Plugin.Say("Slot unlocked");
		}
		else
		{
			ItemData itemAt = ((Humanoid)p).GetInventory().GetItemAt(x, y);
			_locks[key] = ((itemAt != null) ? itemAt.m_shared.m_name : "");
			Plugin.Say((itemAt != null) ? ("Slot locked for " + Localization.instance.Localize(itemAt.m_shared.m_name) + " (Restock refills it)") : "Slot locked");
		}
		Save(p);
	}

	private static void LoadFavs(Player p)
	{
		if ((Object)(object)p == (Object)(object)_favFor)
		{
			return;
		}
		_favFor = p;
		_favs.Clear();
		if (!p.m_customData.TryGetValue("Hoardkeeper_favs", out var value))
		{
			return;
		}
		string[] array = value.Split(';');
		foreach (string text in array)
		{
			if (text.Length > 0)
			{
				_favs.Add(text);
			}
		}
	}

	internal static bool IsFavorite(Player p, ItemData it)
	{
		LoadFavs(p);
		if (it != null)
		{
			return _favs.Contains(it.m_shared.m_name);
		}
		return false;
	}

	internal static void ToggleFavorite(Player p, ItemData it)
	{
		LoadFavs(p);
		string name = it.m_shared.m_name;
		string text = Localization.instance.Localize(name);
		if (_favs.Remove(name))
		{
			Plugin.Say(text + " is no longer a favorite");
		}
		else
		{
			_favs.Add(name);
			Plugin.Say(text + " is a favorite: it stays with you");
		}
		p.m_customData["Hoardkeeper_favs"] = string.Join(";", new List<string>(_favs).ToArray());
	}

	internal static bool OutsideGrid(Player p, ItemData it)
	{
		Inventory inventory = ((Humanoid)p).GetInventory();
		if (it.m_gridPos.x >= 0 && it.m_gridPos.y >= 0 && it.m_gridPos.x < inventory.GetWidth())
		{
			return it.m_gridPos.y >= inventory.GetHeight();
		}
		return true;
	}

	internal static bool Keep(Player p, ItemData it)
	{
		if (it.m_gridPos.y != 0 && !OutsideGrid(p, it) && !it.m_equipped && !IsLocked(p, it.m_gridPos.x, it.m_gridPos.y))
		{
			return IsFavorite(p, it);
		}
		return true;
	}
}
[HarmonyPatch]
[BepInPlugin("felih.Hoardkeeper", "Hoardkeeper", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	internal enum SortOrder
	{
		Type,
		NameAZ,
		NameZA,
		Quality,
		Weight,
		Amount,
		Value
	}

	internal static ConfigEntry<float> Range;

	internal static ConfigEntry<int> MaxChests;

	internal static ConfigEntry<KeyboardShortcut> StackKey;

	internal static ConfigEntry<KeyboardShortcut> RestockKey;

	internal static ConfigEntry<KeyboardShortcut> SortKey;

	internal static ConfigEntry<KeyboardShortcut> StorageKey;

	internal static ConfigEntry<Vector2> ButtonsOffset;

	internal static ConfigEntry<float> StorageHeight;

	internal static ConfigEntry<float> StorageWidth;

	internal static ConfigEntry<float> ScrollSpeed;

	internal static ConfigEntry<SortOrder> Order;

	internal static ConfigEntry<bool> AutoSortOpen;

	internal static ConfigEntry<bool> AutoSortPickup;

	internal static ConfigEntry<bool> GatherFromBag;

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		Range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChestRange", 50f, new ConfigDescription("How far (metres) Storage, Stack and Restock reach for chests.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 50f), new object[0]));
		MaxChests = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxChests", 60, new ConfigDescription("Most chests the Storage window shows (nearest first).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 60), new object[0]));
		StorageKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "Storage", new KeyboardShortcut((KeyCode)102, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Opens (or closes) the Storage window with every chest around you.");
		StackKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "Stack", new KeyboardShortcut((KeyCode)113, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Put your items into nearby chests that hold the same item.");
		RestockKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "Restock", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Top up hotbar, ammo and locked slots from nearby chests.");
		SortKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "SortKey", new KeyboardShortcut((KeyCode)116, (KeyCode[])(object)new KeyCode[0]), "With the inventory open: sorts the open chest, or your bag when no chest is open. With Shift: changes the sort order.");
		Order = ((BaseUnityPlugin)this).Config.Bind<SortOrder>("Sort", "Order", SortOrder.Type, "How Sort orders items: by Type (weapons, ammo, armor, tools, food, materials, trophies), Name A-Z / Z-A, Quality, Weight, Amount or Value.");
		AutoSortOpen = ((BaseUnityPlugin)this).Config.Bind<bool>("Sort", "AutoSortOnOpen", false, "Sort your bag when you open the inventory, and a chest when you open it.");
		AutoSortPickup = ((BaseUnityPlugin)this).Config.Bind<bool>("Sort", "AutoSortOnPickup", false, "Sort your bag after you pick something up.");
		GatherFromBag = ((BaseUnityPlugin)this).Config.Bind<bool>("Storage", "GatherFromBag", false, "Gather also takes from your bag (never the hotbar, locked, favorite or worn items). Also a toggle in the window.");
		StorageHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "WindowHeight", 0f, "Height of the Storage window. 0 = from the top of your bag down to near the bottom of the screen.");
		ScrollSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "ScrollSpeed", 3000f, "How far the mouse wheel scrolls the Storage window.");
		StorageWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "WindowWidth", 0f, "Width of the Storage window. 0 = from the button column to near the right edge of the screen.");
		ButtonsOffset = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Display", "ButtonsOffset", new Vector2(8f, 0f), "Where the button column sits, from the top-right corner of your inventory.");
		new Harmony("felih.Hoardkeeper").PatchAll(typeof(Plugin).Assembly);
	}

	private void Update()
	{
		//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_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
		{
			return;
		}
		AutoSort.Tick(localPlayer);
		if (Typing())
		{
			return;
		}
		bool flag = InventoryGui.IsVisible();
		KeyboardShortcut value = StorageKey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			Storage.Toggle();
			return;
		}
		KeyboardShortcut value2 = StackKey.Value;
		if (((KeyboardShortcut)(ref value2)).IsDown())
		{
			Actions.QuickStack(localPlayer);
			return;
		}
		KeyboardShortcut value3 = RestockKey.Value;
		if (((KeyboardShortcut)(ref value3)).IsDown())
		{
			Actions.Restock(localPlayer);
			return;
		}
		KeyboardShortcut value4 = SortKey.Value;
		if (((KeyboardShortcut)(ref value4)).IsDown() && flag)
		{
			Actions.SortHere(localPlayer);
		}
		else if (flag)
		{
			KeyboardShortcut value5 = SortKey.Value;
			if (Input.GetKeyDown(((KeyboardShortcut)(ref value5)).MainKey) && (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)))
			{
				Actions.NextOrder();
			}
		}
	}

	internal static bool Typing()
	{
		if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible())
		{
			return Storage.Typing();
		}
		return true;
	}

	internal static void Say(string msg)
	{
		if ((Object)(object)MessageHud.instance != (Object)null)
		{
			MessageHud.instance.ShowMessage((MessageType)1, msg, 0, (Sprite)null, false, true);
		}
	}
}
internal static class Skin
{
	private static Dictionary<string, Sprite> _sprites;

	private static readonly string[] Art = new string[3] { "woodpanel_playerinventory", "woodpanel_info", "woodpanel_crafting" };

	private static Sprite Find(params string[] names)
	{
		if (_sprites == null)
		{
			_sprites = new Dictionary<string, Sprite>();
			Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>();
			foreach (Sprite val in array)
			{
				if ((Object)(object)val != (Object)null && !_sprites.ContainsKey(((Object)val).name))
				{
					_sprites[((Object)val).name] = val;
				}
			}
		}
		foreach (string key in names)
		{
			if (_sprites.TryGetValue(key, out var value))
			{
				return value;
			}
		}
		return null;
	}

	internal static void Window(InventoryGui gui, RectTransform panel, Image img)
	{
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		Image val = null;
		Transform root = (((Object)(object)gui.m_player != (Object)null) ? ((Transform)gui.m_player).parent : null);
		string[] art = Art;
		foreach (string sprite in art)
		{
			val = Biggest(root, sprite, (Transform)(object)panel) ?? Biggest((Transform)(object)gui.m_player, sprite, (Transform)(object)panel);
			if ((Object)(object)val != (Object)null)
			{
				break;
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			img.sprite = val.sprite;
			img.type = val.type;
			img.fillCenter = true;
			((Graphic)img).color = ((Graphic)val).color;
			((Graphic)img).material = ((Graphic)val).material;
			img.pixelsPerUnitMultiplier = val.pixelsPerUnitMultiplier;
			Plugin.Log.LogInfo((object)("Storage background: " + ((Object)val.sprite).name + " from " + ((Object)val).name));
		}
		else
		{
			Plugin.Log.LogInfo((object)"Storage background: window art not found, plain colour");
			((Graphic)img).color = new Color(0.16f, 0.12f, 0.08f, 0.97f);
		}
	}

	private static Image Biggest(Transform root, string sprite, Transform skip)
	{
		//IL_003c: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)root == (Object)null)
		{
			return null;
		}
		Image result = null;
		float num = 0f;
		Image[] componentsInChildren = ((Component)root).GetComponentsInChildren<Image>(true);
		foreach (Image val in componentsInChildren)
		{
			if ((Object)(object)val.sprite == (Object)null || ((Graphic)val).color.a < 0.5f || ((Object)(object)skip != (Object)null && ((Component)val).transform.IsChildOf(skip)))
			{
				continue;
			}
			string name = ((Object)val.sprite).name;
			if (name.IndexOf(sprite, StringComparison.OrdinalIgnoreCase) >= 0 && name.IndexOf("mask", StringComparison.OrdinalIgnoreCase) < 0)
			{
				Rect rect = ((Graphic)val).rectTransform.rect;
				if (((Rect)(ref rect)).width * ((Rect)(ref rect)).height > num)
				{
					num = ((Rect)(ref rect)).width * ((Rect)(ref rect)).height;
					result = val;
				}
			}
		}
		return result;
	}

	internal static void Card(Image img, bool dim)
	{
		//IL_0033: 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)
		((Graphic)img).color = (dim ? new Color(0.3f, 0.06f, 0.03f, 0.35f) : new Color(0f, 0f, 0f, 0.25f));
	}
}
[HarmonyPatch]
internal static class Storage
{
	private class Section
	{
		public Container c;

		public bool skipped;

		public int muted = -1;

		public RectTransform root;

		public InventoryGrid grid;

		public TextMeshProUGUI title;

		public int rows = -1;

		public int cols = -1;

		public float btnW;

		public float h;

		public RectTransform chips;

		public readonly List<KeyValuePair<string, Button>> chipBtns = new List<KeyValuePair<string, Button>>();
	}

	[HarmonyPatch]
	private static class KeyBlock
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ZInput), "TryGetKeyStateLowLevel", (Type[])null, (Type[])null);
		}

		private static bool Prefix(KeyCode keyCode, ref bool __result)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!Typing() || Free(keyCode))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch]
	private static class ButtonBlock
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ZInput), "TryGetButtonState", (Type[])null, (Type[])null);
		}

		private static bool Prefix(string name, ref bool __result)
		{
			if (!Typing() || name == null || name.StartsWith("Mouse"))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	private const float ChipW = 66f;

	private const float ChipH = 26f;

	private const float Pad = 8f;

	private const float Gap = 8f;

	private const float SideW = 158f;

	private const float TitleH = 26f;

	private const float BtnW = 62f;

	private const float BtnH = 24f;

	private const float CardMin = 440f;

	private const float Head = 26f;

	private static readonly List<Section> _sections = new List<Section>();

	private static bool _open;

	private static RectTransform _panel;

	private static RectTransform _viewport;

	private static RectTransform _content;

	private static TMP_InputField _search;

	private static TMP_InputField _rename;

	private static Section _renaming;

	private static TextMeshProUGUI _status;

	private static Button _bagBtn;

	private static CanvasGroup _bagGroup;

	private static string _chosen;

	private static float _statusAt;

	private static int _frame;

	private static bool _logged;

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

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

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

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

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

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

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

	private static readonly FieldInfo WidthF = AccessTools.Field(typeof(InventoryGrid), "m_width");

	private static readonly FieldInfo HeightF = AccessTools.Field(typeof(InventoryGrid), "m_height");

	private static readonly FieldInfo GridF = AccessTools.Field(typeof(InventoryGui), "m_containerGrid");

	private static readonly FieldInfo TipHoveredF = AccessTools.Field(typeof(UITooltip), "m_hovered");

	private static bool _tipLogged;

	private static readonly Dictionary<string, string> _shown = new Dictionary<string, string>();

	internal static bool IsOpen()
	{
		return _open;
	}

	internal static bool Holds(Container c)
	{
		if (!_open)
		{
			return false;
		}
		foreach (Section section in _sections)
		{
			if ((Object)(object)section.c == (Object)(object)c)
			{
				return true;
			}
		}
		return false;
	}

	internal static bool Typing()
	{
		if ((!((Object)(object)_search != (Object)null) || !_search.isFocused) && (!((Object)(object)_rename != (Object)null) || !((Component)_rename).gameObject.activeSelf || !_rename.isFocused))
		{
			return ChestName.Typing();
		}
		return true;
	}

	private static List<Container> Live()
	{
		List<Container> list = new List<Container>();
		foreach (Section section in _sections)
		{
			if (!section.skipped && (Object)(object)section.c != (Object)null)
			{
				list.Add(section.c);
			}
		}
		return list;
	}

	internal static void Toggle()
	{
		try
		{
			if (_open)
			{
				Close();
			}
			else
			{
				Open();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Storage window failed: " + ex));
		}
	}

	private static void Open()
	{
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		InventoryGui instance = InventoryGui.instance;
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		if (!InventoryGui.IsVisible())
		{
			instance.Show((Container)null, 1);
		}
		if (instance.IsContainerOpen())
		{
			CloseM.Invoke(instance, null);
		}
		if ((Object)(object)_panel == (Object)null)
		{
			Build(instance);
		}
		if (!((Object)(object)_panel == (Object)null))
		{
			_open = true;
			_chosen = null;
			Fill(instance, localPlayer);
			((Component)_panel).gameObject.SetActive(true);
			((Transform)_panel).SetAsLastSibling();
			_content.anchoredPosition = Vector2.zero;
			if (_sections.Count == 0)
			{
				Plugin.Say("No chests within " + Mathf.RoundToInt(Plugin.Range.Value) + " m");
			}
		}
	}

	private static void Fill(InventoryGui gui, Player p)
	{
		List<Container> list = Chests.Near(p, Plugin.Range.Value, withSkipped: true);
		List<Container> list2 = new List<Container>();
		List<Container> list3 = new List<Container>();
		foreach (Container item in list)
		{
			(Chests.Skipped(item) ? list3 : list2).Add(item);
		}
		int value = Plugin.MaxChests.Value;
		foreach (Container item2 in list2)
		{
			if (_sections.Count < value)
			{
				Add(gui, item2, skipped: false);
			}
		}
		foreach (Container item3 in list3)
		{
			if (_sections.Count < value)
			{
				Add(gui, item3, skipped: true);
			}
		}
	}

	private static void Clear(InventoryGui gui)
	{
		if ((Object)(object)gui != (Object)null)
		{
			object? value = DragInvF.GetValue(gui);
			Inventory val = (Inventory)((value is Inventory) ? value : null);
			if (val != null && (Object)(object)Player.m_localPlayer != (Object)null && val != ((Humanoid)Player.m_localPlayer).GetInventory())
			{
				SetupDrag.Invoke(gui, new object[3] { null, null, 1 });
			}
		}
		if ((Object)(object)_rename != (Object)null)
		{
			((Component)_rename).transform.SetParent((Transform)(object)_panel, false);
			((Component)_rename).gameObject.SetActive(false);
		}
		_renaming = null;
		foreach (Section section in _sections)
		{
			if ((Object)(object)section.c != (Object)null && !section.skipped)
			{
				Chests.MarkInUse(section.c, on: false);
			}
			if ((Object)(object)section.root != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)section.root).gameObject);
			}
		}
		_sections.Clear();
	}

	private static void Close()
	{
		Clear(InventoryGui.instance);
		_open = false;
		_chosen = null;
		if ((Object)(object)_search != (Object)null)
		{
			_search.text = "";
		}
		if ((Object)(object)_panel != (Object)null)
		{
			((Component)_panel).gameObject.SetActive(false);
		}
	}

	private static void Rebuild()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		InventoryGui instance = InventoryGui.instance;
		Vector2 anchoredPosition = _content.anchoredPosition;
		Clear(instance);
		Fill(instance, Player.m_localPlayer);
		_content.anchoredPosition = anchoredPosition;
	}

	private static void ShowBag(bool on)
	{
		if (!((Object)(object)_bagGroup == (Object)null))
		{
			_bagGroup.alpha = (on ? 1f : 0f);
			_bagGroup.blocksRaycasts = on;
		}
	}

	private static void Build(InventoryGui gui)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Expected O, but got Unknown
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Expected O, but got Unknown
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Expected O, but got Unknown
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_0341: Unknown result type (might be due to invalid IL or missing references)
		//IL_0356: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0380: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Expected O, but got Unknown
		//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0408: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0434: Unknown result type (might be due to invalid IL or missing references)
		//IL_045b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0462: Expected O, but got Unknown
		//IL_0469: Unknown result type (might be due to invalid IL or missing references)
		//IL_0473: Expected O, but got Unknown
		//IL_0488: Unknown result type (might be due to invalid IL or missing references)
		//IL_0497: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0521: Unknown result type (might be due to invalid IL or missing references)
		//IL_0528: Expected O, but got Unknown
		//IL_052f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0539: Expected O, but got Unknown
		//IL_0558: Unknown result type (might be due to invalid IL or missing references)
		//IL_0571: Unknown result type (might be due to invalid IL or missing references)
		//IL_058a: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)gui.m_container == (Object)null) && !((Object)(object)gui.m_takeAllButton == (Object)null))
		{
			GameObject val = new GameObject("Hoardkeeper_Storage", new Type[1] { typeof(RectTransform) });
			_panel = (RectTransform)val.transform;
			((Transform)_panel).SetParent(((Object)(object)gui.m_inventoryRoot != (Object)null) ? gui.m_inventoryRoot : ((Transform)gui.m_container).parent, false);
			RectTransform panel = _panel;
			Vector2 anchorMin = (_panel.anchorMax = new Vector2(0.5f, 0.5f));
			panel.anchorMin = anchorMin;
			_panel.pivot = new Vector2(0f, 1f);
			Skin.Window(gui, _panel, val.AddComponent<Image>());
			_search = Ui.Field(gui, (Transform)(object)_panel, "Find item...");
			Place((RectTransform)((Component)_search).transform, 8f, -8f, 150f, 28f);
			((UnityEvent<string>)(object)_search.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				_chosen = null;
				_statusAt = 0f;
			});
			float y = -44f;
			y = Side(gui, "Sort all", y, delegate
			{
				Actions.SortAll(Live());
			}, "Sort every chest here (order: Shift + T)");
			y = Side(gui, "Tidy up", y, delegate
			{
				Actions.Tidy(Live());
			}, "Each kind of item into the chest that holds the most of it, then sort them all");
			y = Side(gui, "Stack", y, delegate
			{
				Actions.QuickStack(Player.m_localPlayer);
			}, "Your items into the chests that hold the same item (Shift + Q)");
			y = Side(gui, "Fill tags", y, delegate
			{
				Tags.Fill(Player.m_localPlayer, Live());
			}, "Send every item to the chest tagged with its category (Food, Ores, Wood...), from your bag and from chests not tagged for it. Tag a chest with its Tags button");
			_bagBtn = Ui.CloneButton(gui, (Transform)(object)_panel, "Bag: off", 150f, 28f, delegate
			{
				Plugin.GatherFromBag.Value = !Plugin.GatherFromBag.Value;
			}, "Gather also takes from your bag (never hotbar, locked, favorite or worn)");
			Place((RectTransform)((Component)_bagBtn).transform, 8f, y, 150f, 28f);
			y -= 32f;
			y = Side(gui, "Close", y, Close, "Close the Storage window (Shift + F)");
			TextMeshProUGUI val3 = Ui.Text(gui, (Transform)(object)_panel, 13f, new Color(0.85f, 0.82f, 0.75f, 1f), (TextAlignmentOptions)257);
			((TMP_Text)val3).enableWordWrapping = true;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)0;
			((TMP_Text)val3).lineSpacing = -6f;
			((TMP_Text)val3).text = "<color=#ffcc66>Keys</color>\n<color=#ffe0a0>Shift+F</color> open / close\n<color=#ffe0a0>Click</color> pick up / put\n<color=#ffe0a0>Shift+click</color> split\n<color=#ffe0a0>Ctrl+click</color> send across\n<color=#ffe0a0>Right-click</color> find all of it\n<color=#ffe0a0>T</color> sort  <color=#ffe0a0>Shift+T</color> order\n<color=#ffe0a0>Alt+click</color> lock bag slot\n<color=#ffe0a0>Alt+right-click</color> favorite\n<color=#ffe0a0>Shift+Q</color> stack nearby\n<color=#ffe0a0>Shift+R</color> restock";
			Place(((TMP_Text)val3).rectTransform, 10f, y - 6f, 148f, 300f);
			_status = Ui.Text(gui, (Transform)(object)_panel, 15f, new Color(1f, 0.85f, 0.55f, 1f), (TextAlignmentOptions)4097);
			RectTransform rectTransform = ((TMP_Text)_status).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 1f);
			rectTransform.anchorMax = new Vector2(1f, 1f);
			rectTransform.pivot = new Vector2(0f, 1f);
			rectTransform.offsetMin = new Vector2(170f, -34f);
			rectTransform.offsetMax = new Vector2(-48f, -8f);
			Button val4 = Ui.CloneButton(gui, (Transform)(object)_panel, "X", 32f, 28f, Close, "Close the Storage window (Shift + F)");
			RectTransform val5 = (RectTransform)((Component)val4).transform;
			Vector2 anchorMin2 = (val5.anchorMax = new Vector2(1f, 1f));
			val5.anchorMin = anchorMin2;
			val5.pivot = new Vector2(1f, 1f);
			val5.anchoredPosition = new Vector2(-8f, -6f);
			val5.sizeDelta = new Vector2(32f, 28f);
			GameObject val7 = new GameObject("Viewport", new Type[1] { typeof(RectTransform) });
			_viewport = (RectTransform)val7.transform;
			((Transform)_viewport).SetParent((Transform)(object)_panel, false);
			_viewport.anchorMin = Vector2.zero;
			_viewport.anchorMax = Vector2.one;
			_viewport.offsetMin = new Vector2(166f, 8f);
			_viewport.offsetMax = new Vector2(-8f, -40f);
			val7.AddComponent<RectMask2D>();
			Image val8 = val7.AddComponent<Image>();
			((Graphic)val8).color = new Color(0f, 0f, 0f, 0.001f);
			GameObject val9 = new GameObject("Content", new Type[1] { typeof(RectTransform) });
			_content = (RectTransform)val9.transform;
			((Transform)_content).SetParent((Transform)(object)_viewport, false);
			_content.anchorMin = new Vector2(0f, 1f);
			_content.anchorMax = new Vector2(1f, 1f);
			_content.pivot = new Vector2(0.5f, 1f);
			_content.sizeDelta = new Vector2(0f, 10f);
			ScrollRect val10 = val.AddComponent<ScrollRect>();
			val10.content = _content;
			val10.viewport = _viewport;
			val10.horizontal = false;
			val10.vertical = true;
			val10.movementType = (MovementType)2;
			val10.inertia = false;
			val10.scrollSensitivity = Plugin.ScrollSpeed.Value;
			_rename = Ui.Field(gui, (Transform)(object)_panel, "Chest name");
			_rename.characterLimit = 30;
			((UnityEvent<string>)(object)_rename.onEndEdit).AddListener((UnityAction<string>)EndRename);
			((Component)_rename).gameObject.SetActive(false);
			val.SetActive(false);
		}
	}

	private static float Side(InventoryGui gui, string label, float y, Action click, string tip)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		Button val = Ui.CloneButton(gui, (Transform)(object)_panel, label, 150f, 28f, click, tip);
		Place((RectTransform)((Component)val).transform, 8f, y, 150f, 28f);
		return y - 32f;
	}

	private static void Place(RectTransform r, float x, float y, float w, float h)
	{
		//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_0012: 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_0029: 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_0044: Unknown result type (might be due to invalid IL or missing references)
		Vector2 anchorMin = (r.anchorMax = new Vector2(0f, 1f));
		r.anchorMin = anchorMin;
		r.pivot = new Vector2(0f, 1f);
		r.anchoredPosition = new Vector2(x, y);
		r.sizeDelta = new Vector2(w, h);
	}

	private static void Add(InventoryGui gui, Container c, bool skipped)
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Expected O, but got Unknown
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		//IL_00c3: 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_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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: 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_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Expected O, but got Unknown
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Expected O, but got Unknown
		Section s = new Section();
		s.c = c;
		s.skipped = skipped;
		GameObject val = new GameObject("Chest", new Type[1] { typeof(RectTransform) });
		s.root = (RectTransform)val.transform;
		((Transform)s.root).SetParent((Transform)(object)_content, false);
		RectTransform root = s.root;
		Vector2 anchorMin = (s.root.anchorMax = new Vector2(0f, 1f));
		root.anchorMin = anchorMin;
		s.root.pivot = new Vector2(0f, 1f);
		Skin.Card(val.AddComponent<Image>(), skipped);
		s.title = Ui.Text(gui, (Transform)(object)s.root, 16f, skipped ? new Color(0.6f, 0.6f, 0.6f, 1f) : new Color(1f, 0.82f, 0.45f, 1f), (TextAlignmentOptions)4097);
		Place(((TMP_Text)s.title).rectTransform, 8f, -3f, 240f, 24f);
		if (skipped)
		{
			Button val3 = Ui.CloneButton(gui, (Transform)(object)s.root, "Use", 52f, 24f, delegate
			{
				if ((Object)(object)s.c != (Object)null)
				{
					Chests.SetSkipped(c, on: false);
					Rebuild();
				}
			}, "Show this chest again and let the buttons use it");
			Corner((RectTransform)((Component)val3).transform, -6f, -3f, 52f);
			s.btnW = 60f;
		}
		else
		{
			Button val4 = Ui.CloneButton(gui, (Transform)(object)s.root, "Skip", 50f, 24f, delegate
			{
				if ((Object)(object)s.c != (Object)null)
				{
					Chests.SetSkipped(c, on: true);
					Rebuild();
				}
			}, "Leave this chest out of Storage, Stack and Restock (only for you)");
			Corner((RectTransform)((Component)val4).transform, -6f, -3f, 50f);
			float x = 8f;
			x = Cmd(gui, s, "Gather", 64f, x, delegate
			{
				Actions.Gather(Player.m_localPlayer, c, Live(), Plugin.GatherFromBag.Value);
			}, "Bring here every item of the kinds this chest holds, from the other chests");
			x = Cmd(gui, s, "Sort", 48f, x, delegate
			{
				Actions.SortChest(c);
				Plugin.Say("Chest sorted by " + Actions.OrderName());
			}, "Sort this chest");
			x = Cmd(gui, s, "Take all", 66f, x, delegate
			{
				Actions.TakeAll(Player.m_localPlayer, c);
			}, "Take everything from this chest");
			x = Cmd(gui, s, "Tags", 48f, x, delegate
			{
				if ((Object)(object)s.chips != (Object)null)
				{
					((Component)s.chips).gameObject.SetActive(!((Component)s.chips).gameObject.activeSelf);
					ChipLabels(s);
				}
			}, "Choose which kinds of item belong in this chest; Fill tags sends them here");
			x = Cmd(gui, s, "Name", 52f, x, delegate
			{
				StartRename(s);
			}, "Give this chest a name (shown when you look at it)");
			s.btnW = 58f;
			BuildChips(gui, s);
			s.grid = CloneGrid(gui, (Transform)(object)s.root);
			if ((Object)(object)s.grid == (Object)null)
			{
				s.skipped = true;
			}
			else
			{
				Chests.Claim(c);
				Chests.MarkInUse(c, on: true);
			}
		}
		_sections.Add(s);
	}

	private static void Corner(RectTransform r, float x, float y, float w)
	{
		//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_0012: 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_0029: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		Vector2 anchorMin = (r.anchorMax = new Vector2(1f, 1f));
		r.anchorMin = anchorMin;
		r.pivot = new Vector2(1f, 1f);
		r.anchoredPosition = new Vector2(x, y);
		r.sizeDelta = new Vector2(w, 24f);
	}

	private static float Cmd(InventoryGui gui, Section s, string label, float w, float x, Action click, string tip)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		Button val = Ui.CloneButton(gui, (Transform)(object)s.root, label, w, 24f, delegate
		{
			if ((Object)(object)s.c != (Object)null)
			{
				click();
			}
		}, tip);
		Place((RectTransform)((Component)val).transform, x, -28f, w, 24f);
		return x + w + 4f;
	}

	private static void BuildChips(InventoryGui gui, Section s)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		GameObject val = new GameObject("Tags", new Type[1] { typeof(RectTransform) });
		s.chips = (RectTransform)val.transform;
		((Transform)s.chips).SetParent((Transform)(object)s.root, false);
		Place(s.chips, 8f, -30f, 100f, 30f);
		string[] all = Tags.All;
		foreach (string text in all)
		{
			string tag = text;
			Button value = Ui.CloneButton(gui, (Transform)(object)s.chips, tag, 66f, 26f, delegate
			{
				if ((Object)(object)s.c != (Object)null)
				{
					Tags.Toggle(s.c, tag);
					ChipLabels(s);
				}
			}, null);
			s.chipBtns.Add(new KeyValuePair<string, Button>(tag, value));
		}
		val.SetActive(false);
	}

	private static float LayChips(Section s, float width)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		int num = Mathf.Max(1, Mathf.FloorToInt((width + 4f) / 70f));
		for (int i = 0; i < s.chipBtns.Count; i++)
		{
			Place((RectTransform)((Component)s.chipBtns[i].Value).transform, (float)(i % num) * 70f, (float)(-(i / num)) * 30f, 66f, 26f);
		}
		int num2 = (s.chipBtns.Count + num - 1) / num;
		float num3 = (float)num2 * 30f;
		s.chips.sizeDelta = new Vector2(width, num3);
		return num3;
	}

	private static void ChipLabels(Section s)
	{
		if ((Object)(object)s.c == (Object)null)
		{
			return;
		}
		HashSet<string> hashSet = Tags.Of(s.c);
		foreach (KeyValuePair<string, Button> chipBtn in s.chipBtns)
		{
			Ui.Label(chipBtn.Value, hashSet.Contains(chipBtn.Key) ? ("<b><color=#ffcc55>" + chipBtn.Key + "</color></b>") : ("<color=#8a8a8a>" + chipBtn.Key + "</color>"));
		}
	}

	private static InventoryGrid CloneGrid(InventoryGui gui, Transform parent)
	{
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Expected O, but got Unknown
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b7: Expected O, but got Unknown
		//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0515: Unknown result type (might be due to invalid IL or missing references)
		//IL_052f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0549: Unknown result type (might be due to invalid IL or missing references)
		//IL_0559: Unknown result type (might be due to invalid IL or missing references)
		object? value = GridF.GetValue(gui);
		InventoryGrid val = (InventoryGrid)((value is InventoryGrid) ? value : null);
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent, false);
		((Object)val2).name = "Grid";
		val2.SetActive(true);
		InventoryGrid component = val2.GetComponent<InventoryGrid>();
		if ((Object)(object)component.m_gridRoot == (Object)null || (Object)(object)component.m_gridRoot == (Object)(object)val.m_gridRoot)
		{
			Plugin.Log.LogWarning((object)"Storage: the chest grid has an unexpected layout; can't copy it");
			Object.Destroy((Object)(object)val2);
			return null;
		}
		if (!_logged)
		{
			_logged = true;
			RectTransform gridRoot = component.m_gridRoot;
			RectTransform val3 = (RectTransform)(((Object)(object)component.m_elementPrefab != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			Plugin.Log.LogInfo((object)string.Concat("Storage grid: root under grid=", ((Transform)gridRoot).IsChildOf(val2.transform), " rootAnchors=", gridRoot.anchorMin, "-", gridRoot.anchorMax, " rootPivot=", gridRoot.pivot, " slot=", ((Object)(object)val3 != (Object)null) ? string.Concat(val3.anchorMin, "-", val3.anchorMax, " pivot ", val3.pivot, " size ", val3.sizeDelta) : "?", " space=", component.m_elementSpace, " parts=", val2.GetComponentsInChildren<Component>(true).Length));
		}
		List<GameObject> list = new List<GameObject>();
		foreach (Transform item in (Transform)component.m_gridRoot)
		{
			Transform val4 = item;
			list.Add(((Component)val4).gameObject);
		}
		foreach (GameObject item2 in list)
		{
			item2.transform.SetParent((Transform)null, false);
			Object.Destroy((Object)(object)item2);
		}
		ScrollRect[] componentsInChildren = val2.GetComponentsInChildren<ScrollRect>(true);
		foreach (ScrollRect val5 in componentsInChildren)
		{
			((Behaviour)val5).enabled = false;
		}
		RectMask2D[] componentsInChildren2 = val2.GetComponentsInChildren<RectMask2D>(true);
		foreach (RectMask2D val6 in componentsInChildren2)
		{
			Object.Destroy((Object)(object)val6);
		}
		Mask[] componentsInChildren3 = val2.GetComponentsInChildren<Mask>(true);
		foreach (Mask val7 in componentsInChildren3)
		{
			Object.Destroy((Object)(object)val7);
		}
		UIGamePad[] componentsInChildren4 = val2.GetComponentsInChildren<UIGamePad>(true);
		foreach (UIGamePad val8 in componentsInChildren4)
		{
			Object.Destroy((Object)(object)val8);
		}
		component.CanDropDragOntoItem = val.CanDropDragOntoItem ?? ((Func<ItemData, bool>)((ItemData it) => true));
		Scrollbar[] componentsInChildren5 = val2.GetComponentsInChildren<Scrollbar>(true);
		foreach (Scrollbar val9 in componentsInChildren5)
		{
			((Component)val9).gameObject.SetActive(false);
		}
		UIGroupHandler[] componentsInChildren6 = val2.GetComponentsInChildren<UIGroupHandler>(true);
		foreach (UIGroupHandler val10 in componentsInChildren6)
		{
			Object.Destroy((Object)(object)val10);
		}
		CanvasGroup[] componentsInChildren7 = val2.GetComponentsInChildren<CanvasGroup>(true);
		foreach (CanvasGroup val11 in componentsInChildren7)
		{
			val11.interactable = true;
			val11.blocksRaycasts = true;
			val11.alpha = 1f;
		}
		component.m_uiGroup = val.m_uiGroup;
		component.m_ensureVisible = null;
		ElementsF.SetValue(component, new List<InventoryElement>());
		WidthF.SetValue(component, -1);
		HeightF.SetValue(component, -1);
		component.m_onSelected = delegate(InventoryGrid g2, ItemData it, Vector2i pos, Modifier mod)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			OnSelected(g2, it, pos, mod);
		};
		component.m_onRightClick = delegate(InventoryGrid g2, ItemData it, Vector2i pos)
		{
			OnRightClick(g2, it);
		};
		component.m_onReleased = (Action<InventoryGrid, ItemData, Vector2i>)Delegate.CreateDelegate(typeof(Action<InventoryGrid, ItemData, Vector2i>), gui, ReleasedM);
		component.m_onEnter = null;
		RectTransform val12 = (RectTransform)val2.transform;
		Vector2 anchorMin = (val12.anchorMax = new Vector2(0f, 1f));
		val12.anchorMin = anchorMin;
		val12.pivot = new Vector2(0f, 1f);
		val12.anchoredPosition = new Vector2(8f, -30f);
		component.m_gridRoot.anchorMin = new Vector2(0f, 1f);
		component.m_gridRoot.anchorMax = new Vector2(1f, 1f);
		component.m_gridRoot.pivot = new Vector2(0.5f, 1f);
		component.m_gridRoot.anchoredPosition = Vector2.zero;
		return component;
	}

	private static void Mute(Section s)
	{
		if (!((Object)(object)s.grid == (Object)null) && !((Object)(object)s.grid.m_gridRoot == (Object)null) && s.muted != ((Transform)s.grid.m_gridRoot).childCount)
		{
			s.muted = ((Transform)s.grid.m_gridRoot).childCount;
			ButtonSfx[] componentsInChildren = ((Component)s.grid.m_gridRoot).GetComponentsInChildren<ButtonSfx>(true);
			foreach (ButtonSfx val in componentsInChildren)
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}

	private static void NoTipsUnder()
	{
		//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)
		if ((Object)(object)_panel == (Object)null || TipHoveredF == null)
		{
			return;
		}
		object? value = TipHoveredF.GetValue(null);
		GameObject val = (GameObject)((value is GameObject) ? value : null);
		if (!((Object)(object)val == (Object)null) && !val.transform.IsChildOf((Transform)(object)_panel) && RectTransformUtility.RectangleContainsScreenPoint(_panel, Vector2.op_Implicit(Input.mousePosition)))
		{
			if (!_tipLogged)
			{
				_tipLogged = true;
				Plugin.Log.LogInfo((object)("Storage: hid a tooltip from " + ((Object)val).name + (((Object)(object)val.transform.parent != (Object)null) ? (" < " + ((Object)val.transform.parent).name) : "")));
			}
			UITooltip.HideTooltip();
		}
	}

	private static Section Of(InventoryGrid grid)
	{
		foreach (Section section in _sections)
		{
			if ((Object)(object)section.grid == (Object)(object)grid)
			{
				return section;
			}
		}
		return null;
	}

	private static void OnSelected(InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Invalid comparison between Unknown and I4
		//IL_0096: 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)
		try
		{
			InventoryGui instance = InventoryGui.instance;
			Player localPlayer = Player.m_localPlayer;
			Section section = Of(grid);
			if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || section == null || (Object)(object)section.c == (Object)null)
			{
				return;
			}
			Chests.Claim(section.c);
			if ((int)mod == 2 && item != null && DragF.GetValue(instance) == null)
			{
				if (!item.m_shared.m_questItem)
				{
					((Humanoid)localPlayer).GetInventory().MoveItemToThis(grid.GetInventory(), item);
				}
			}
			else
			{
				SelectedM.Invoke(instance, new object[4] { grid, item, pos, mod });
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Storage click failed: " + ex));
		}
	}

	private static void OnRightClick(InventoryGrid grid, ItemData item)
	{
		_chosen = ((item == null || item.m_shared.m_name == _chosen) ? null : item.m_shared.m_name);
		_statusAt = 0f;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	private static bool BagMove(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Invalid comparison between Unknown and I4
		if (!_open || (Object)(object)grid != (Object)(object)__instance.m_playerGrid || (int)mod != 2 || item == null)
		{
			return true;
		}
		if (DragF.GetValue(__instance) != null)
		{
			return true;
		}
		Actions.SendToChests(Player.m_localPlayer, item, Live());
		return false;
	}

	[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
	[HarmonyPrefix]
	private static bool KeepHeld(InventoryGui __instance)
	{
		if (!_open || __instance.IsContainerOpen())
		{
			return true;
		}
		((Component)__instance.m_container).gameObject.SetActive(false);
		object? value = DragInvF.GetValue(__instance);
		Inventory val = (Inventory)((value is Inventory) ? value : null);
		if (val != null && (Object)(object)Player.m_localPlayer != (Object)null && val != ((Humanoid)Player.m_localPlayer).GetInventory() && !OursInv(val))
		{
			SetupDrag.Invoke(__instance, new object[3] { null, null, 1 });
		}
		return false;
	}

	private static bool OursInv(Inventory inv)
	{
		foreach (Section section in _sections)
		{
			if ((Object)(object)section.c != (Object)null && section.c.GetInventory() == inv)
			{
				return true;
			}
		}
		return false;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	private static void OnHide()
	{
		if (_open)
		{
			Close();
		}
	}

	private static void StartRename(Section s)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		_renaming = s;
		((Component)_rename).transform.SetParent((Transform)(object)s.root, false);
		RectTransform r = (RectTransform)((Component)_rename).transform;
		Place(r, 6f, -2f, 230f, 24f);
		_rename.text = Chests.Name(s.c);
		((Component)_rename).gameObject.SetActive(true);
		((Selectable)_rename).Select();
		_rename.ActivateInputField();
	}

	private static void EndRename(string text)
	{
		Section renaming = _renaming;
		_renaming = null;
		if ((Object)(object)_rename != (Object)null)
		{
			((Component)_rename).gameObject.SetActive(false);
		}
		if (renaming != null && !((Object)(object)renaming.c == (Object)null) && text != Chests.Name(renaming.c))
		{
			Chests.SetName(renaming.c, text);
			Plugin.Say((text.Trim().Length > 0) ? ("Chest named " + text.Trim()) : "Chest name removed");
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Update")]
	[HarmonyPostfix]
	private static void Tick(InventoryGui __instance)
	{
		if (!_open)
		{
			return;
		}
		try
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !InventoryGui.IsVisible() || __instance.IsContainerOpen())
			{
				Close();
				return;
			}
			Refresh(__instance, localPlayer);
			NoTipsUnder();
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Storage window: " + ex));
			Close();
		}
	}

	private static void Refresh(InventoryGui gui, Player p)
	{
		//IL_012e: 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_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: 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_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Unknown result type (might be due to invalid IL or missing references)
		//IL_077b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0419: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f3: Expected O, but got Unknown
		//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_070e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0723: Unknown result type (might be due to invalid IL or missing references)
		//IL_0529: Unknown result type (might be due to invalid IL or missing references)
		//IL_0554: Unknown result type (might be due to invalid IL or missing references)
		//IL_058c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0578: Unknown result type (might be due to invalid IL or missing references)
		_frame++;
		object? value = DragF.GetValue(gui);
		ItemData val = (ItemData)((value is ItemData) ? value : null);
		float num = Plugin.Range.Value + 8f;
		for (int num2 = _sections.Count - 1; num2 >= 0; num2--)
		{
			Section section = _sections[num2];
			ZNetView val2 = Chests.View(section.c);
			if (!((Object)(object)section.c != (Object)null) || !((Object)(object)val2 != (Object)null) || !val2.IsValid() || !(Vector3.Distance(((Component)p).transform.position, ((Component)section.c).transform.position) <= num))
			{
				if ((Object)(object)section.c != (Object)null && !section.skipped)
				{
					Chests.MarkInUse(section.c, on: false);
				}
				if ((Object)(object)section.root != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)section.root).gameObject);
				}
				_sections.RemoveAt(num2);
			}
		}
		Vector3[] array = (Vector3[])(object)new Vector3[4];
		gui.m_player.GetWorldCorners(array);
		float y = array[1].y;
		float num3 = array[2].x + 150f * ((Transform)_panel).lossyScale.x;
		RectTransform column = Ui.Column;
		if ((Object)(object)column != (Object)null && ((Component)column).gameObject.activeInHierarchy)
		{
			column.GetWorldCorners(array);
			num3 = array[2].x;
			Button[] componentsInChildren = ((Component)column).GetComponentsInChildren<Button>();
			foreach (Button val3 in componentsInChildren)
			{
				((RectTransform)((Component)val3).transform).GetWorldCorners(array);
				num3 = Mathf.Max(num3, array[2].x);
			}
		}
		num3 += 12f;
		float num4 = Mathf.Max(0.01f, ((Transform)_panel).lossyScale.x);
		float num5 = Mathf.Max(0.01f, ((Transform)_panel).lossyScale.y);
		((Transform)_panel).position = new Vector3(num3, y, ((Transform)_panel).position.z);
		float num6 = ((Plugin.StorageWidth.Value > 0f) ? Plugin.StorageWidth.Value : Mathf.Max(560f, ((float)Screen.width - 30f - num3) / num4));
		float num7 = ((Plugin.StorageHeight.Value > 0f) ? Plugin.StorageHeight.Value : Mathf.Max(300f, (y - 90f) / num5));
		_panel.sizeDelta = new Vector2(num6, num7);
		if (((Transform)_panel).GetSiblingIndex() != ((Transform)_panel).parent.childCount - 1)
		{
			((Transform)_panel).SetAsLastSibling();
		}
		Ui.Label(_bagBtn, Plugin.GatherFromBag.Value ? "Bag: on" : "Bag: off");
		if (_renaming != null && !_rename.isFocused && !((Component)_rename).gameObject.activeSelf)
		{
			_renaming = null;
		}
		Vector3[] array2 = (Vector3[])(object)new Vector3[4];
		_viewport.GetWorldCorners(array2);
		Rect rect = _content.rect;
		float width = ((Rect)(ref rect)).width;
		int num8 = Mathf.Max(2, Mathf.FloorToInt((width + 8f) / 448f));
		float num9 = (width - 8f * (float)(num8 - 1)) / (float)num8;
		foreach (Section section3 in _sections)
		{
			Inventory inventory = section3.c.GetInventory();
			string text = Tags.Shown(section3.c);
			string text2 = Chests.Title(section3.c) + (section3.skipped ? "  (skipped)" : "") + ((text.Length > 0) ? ("  <size=12><color=#8fc8ff>[" + text + "]</color></size>") : "");
			((TMP_Text)section3.title).rectTransform.sizeDelta = new Vector2(Mathf.Max(80f, num9 - 16f - section3.btnW), 24f);
			if (((TMP_Text)section3.title).text != text2)
			{
				((TMP_Text)section3.title).text = text2;
			}
			if (section3.skipped || (Object)(object)section3.grid == (Object)null)
			{
				section3.h = 34f;
				continue;
			}
			float num10 = num9 - 16f;
			float num11 = 58f;
			if (((Component)section3.chips).gameObject.activeSelf)
			{
				section3.chips.anchoredPosition = new Vector2(8f, 0f - num11);
				num11 += LayChips(section3, num10) + 4f;
			}
			int width2 = inventory.GetWidth();
			int height = inventory.GetHeight();
			float elementSpace = section3.grid.m_elementSpace;
			RectTransform val4 = (RectTransform)((Component)section3.grid).transform;
			if (width2 != section3.cols || height != section3.rows)
			{
				section3.cols = width2;
				section3.rows = height;
				val4.sizeDelta = new Vector2((float)width2 * elementSpace, (float)height * elementSpace);
			}
			float num12 = Mathf.Min(1f, num10 / Mathf.Max(1f, (float)width2 * elementSpace));
			if (Mathf.Abs(((Transform)val4).localScale.x - num12) > 0.001f)
			{
				((Transform)val4).localScale = new Vector3(num12, num12, 1f);
			}
			val4.anchoredPosition = new Vector2(8f, 0f - num11);
			section3.h = num11 + (float)height * elementSpace * num12 + 8f;
			section3.root.GetWorldCorners(array);
			bool flag = array[0].y < array2[1].y && array[1].y > array2[0].y;
			if (flag || _frame % 20 == 0 || section3.grid.GetInventory() != inventory)
			{
				ZNetView val5 = Chests.View(section3.c);
				if (!val5.IsOwner())
				{
					Chests.Claim(section3.c);
					Chests.MarkInUse(section3.c, on: true);
				}
				section3.grid.UpdateInventory(inventory, (Player)null, val);
				Mute(section3);
				if (flag)
				{
					Tint(section3.grid, inventory);
				}
			}
		}
		float num13 = 0f;
		for (int j = 0; j < _sections.Count; j += num8)
		{
			float num14 = 0f;
			for (int k = 0; k < num8 && j + k < _sections.Count; k++)
			{
				num14 = Mathf.Max(num14, _sections[j + k].h);
			}
			for (int l = 0; l < num8 && j + l < _sections.Count; l++)
			{
				Section section2 = _sections[j + l];
				section2.root.anchoredPosition = new Vector2((float)l * (num9 + 8f), 0f - num13);
				section2.root.sizeDelta = new Vector2(num9, num14);
			}
			num13 += num14 + 8f;
		}
		_content.sizeDelta = new Vector2(0f, num13);
		Tint(gui.m_playerGrid, ((Humanoid)p).GetInventory());
		if (Time.time >= _statusAt)
		{
			_statusAt = Time.time + 0.3f;
			Status(p);
		}
	}

	private static string Shown(string name)
	{
		if (!_shown.TryGetValue(name, out var value))
		{
			value = (_shown[name] = Localization.instance.Localize(name));
		}
		return value;
	}

	private static string Filter()
	{
		if (!((Object)(object)_search != (Object)null))
		{
			return "";
		}
		return _search.text.Trim();
	}

	private static bool Matches(ItemData it, string filter)
	{
		if (_chosen != null)
		{
			return it.m_shared.m_name == _chosen;
		}
		return Shown(it.m_shared.m_name).IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0;
	}

	private static void Tint(InventoryGrid grid, Inventory inv)
	{
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		if (!(ElementsF.GetValue(grid) is IList list))
		{
			return;
		}
		string text = Filter();
		bool flag = _chosen != null || text.Length > 0;
		int width = inv.GetWidth();
		bool[] array = new bool[list.Count];
		if (flag)
		{
			foreach (ItemData allItem in inv.GetAllItems())
			{
				int num = allItem.m_gridPos.y * width + allItem.m_gridPos.x;
				if (num >= 0 && num < array.Length && Matches(allItem, text))
				{
					array[num] = true;
				}
			}
		}
		for (int i = 0; i < list.Count; i++)
		{
			object? obj = list[i];
			InventoryElement val = (InventoryElement)((obj is InventoryElement) ? obj : null);
			if (!((Object)(object)val == (Object)null))
			{
				Transform val2 = ((Component)val).transform.Find("Hoardkeeper_Hit");
				bool flag2 = flag && array[i];
				if (flag2 && (Object)(object)val2 == (Object)null)
				{
					val2 = NewHit(((Component)val).transform);
				}
				if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeSelf != flag2)
				{
					((Component)val2).gameObject.SetActive(flag2);
				}
				if (flag && !array[i] && ((Behaviour)val.m_icon).enabled)
				{
					((Graphic)val.m_icon).color = new Color(1f, 1f, 1f, 0.18f);
				}
			}
		}
	}

	private static Transform NewHit(Transform slot)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		//IL_0048: 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_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Hoardkeeper_Hit", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		RectTransform val2 = (RectTransform)val.transform;
		((Transform)val2).SetParent(slot, false);
		((Transform)val2).SetAsFirstSibling();
		val2.anchorMin = Vector2.zero;
		val2.anchorMax = Vector2.one;
		val2.offsetMin = new Vector2(1f, 1f);
		val2.offsetMax = new Vector2(-1f, -1f);
		Image component = val.GetComponent<Image>();
		((Graphic)component).color = new Color(0.35f, 0.85f, 1f, 0.45f);
		((Graphic)component).raycastTarget = false;
		return (Transform)(object)val2;
	}

	private static void Status(Player p)
	{
		List<Container> list = Live();
		string text = Filter();
		string text3;
		if (_chosen != null || text.Length > 0)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (Container item in list)
			{
				bool flag = false;
				foreach (ItemData allItem in item.GetInventory().GetAllItems())
				{
					if (Matches(allItem, text))
					{
						num += allItem.m_stack;
						num2++;
						flag = true;
					}
				}
				if (flag)
				{
					num3++;
				}
			}
			int num4 = 0;
			foreach (ItemData allItem2 in ((Humanoid)p).GetInventory().GetAllItems())
			{
				if (Matches(allItem2, text))
				{
					num4 += allItem2.m_stack;
				}
			}
			string text2 = ((_chosen != null) ? Shown(_chosen) : ("\"" + text + "\""));
			text3 = text2 + ": " + num + " in " + num3 + " chest" + ((num3 == 1) ? "" : "s") + " (" + num2 + " stack" + ((num2 == 1) ? "" : "s") + ")" + ((num4 > 0) ? (", " + num4 + " in your bag") : "") + ((_chosen != null) ? "   <color=#999999>right-click again to clear</color>" : "");
		}
		else
		{
			text3 = list.Count + " chest" + ((list.Count == 1) ? "" : "s") + " within " + Mathf.RoundToInt(Plugin.Range.Value) + " m   <color=#999999>sort by " + Actions.OrderName() + " · right-click an item to find it all · Ctrl + click sends</color>";
		}
		if (((TMP_Text)_status).text != text3)
		{
			((TMP_Text)_status).text = text3;
		}
	}

	private static bool Free(KeyCode k)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Invalid comparison between Unknown and I4
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Invalid comparison between Unknown and I4
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Invalid comparison between Unknown and I4
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Invalid comparison between Unknown and I4
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		if ((int)k != 13 && (int)k != 271 && ((int)k < 323 || (int)k > 329) && (int)k != 304 && (int)k != 303 && (int)k != 306)
		{
			return (int)k == 305;
		}
		return true;
	}
}
internal static class Tags
{
	private const string Key = "Hoardkeeper_tags";

	internal static readonly string[] All = new string[20]
	{
		"Weapons", "Ammo", "Armor", "Tools", "Food", "Meads", "Meat", "Fish", "Crops", "Seeds",
		"Ores", "Metals", "Wood", "Stone", "Hides", "Creature", "Valuables", "Trophies", "Materials", "Misc"
	};

	private static bool Has(string name, params string[] parts)
	{
		foreach (string value in parts)
		{
			if (name.Contains(value))
			{
				return true;
			}
		}
		return false;
	}

	internal static string Cat