Decompiled source of Quads Gear Slots v1.3.1

plugins/GearSlots.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DHack.Shared;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (Claude Code).")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GearSlots
{
	internal static class Compat
	{
		private static readonly string[][] SlotMods = new string[5][]
		{
			new string[2] { "shudnal.ExtraSlots", "ExtraSlots" },
			new string[2] { "randyknapp.mods.equipmentandquickslots", "Equipment and Quick Slots" },
			new string[2] { "Azumatt.AzuExtendedPlayerInventory", "AzuExtendedPlayerInventory" },
			new string[2] { "aedenthorn.ExtendedPlayerInventory", "Extended Player Inventory" },
			new string[2] { "com.bruce.valheim.comfyquickslots", "ComfyQuickSlots" }
		};

		private const string BetterArchery = "ishid4.mods.betterarchery";

		private static bool _checked;

		private static string _reason;

		public static string StandDownFor
		{
			get
			{
				if (!_checked && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					_checked = true;
					_reason = Find();
					if (_reason != null)
					{
						Layout.ForgetNormalRows();
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogWarning((object)(_reason + " is installed and keeps its own slots in the same inventory cells: the gear slots are off"));
						}
					}
				}
				return _reason;
			}
		}

		public static bool StandingDown => StandDownFor != null;

		private static string Find()
		{
			string[][] slotMods = SlotMods;
			foreach (string[] array in slotMods)
			{
				if (Chainloader.PluginInfos.ContainsKey(array[0]))
				{
					return array[1];
				}
			}
			if (Chainloader.PluginInfos.TryGetValue("ishid4.mods.betterarchery", out var value))
			{
				ConfigEntry<bool> val = null;
				if (!((Object)(object)value.Instance != (Object)null) || !value.Instance.Config.TryGetEntry<bool>("Quiver", "Enable Quiver", ref val) || val.Value)
				{
					return "BetterArchery (its quiver)";
				}
			}
			return null;
		}
	}
	internal static class GameKeys
	{
		private static readonly HashSet<string> Essential = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
		{
			"Forward", "Backward", "Left", "Right", "Use", "Jump", "Inventory", "Tab", "Escape", "Map",
			"Chat", "Run", "Crouch", "Attack", "SecondaryAttack", "Block", "AltPlace", "LShift", "Console", "BuildMenu",
			"Remove", "MapZoomIn", "MapZoomOut", "Hotbar1", "Hotbar2", "Hotbar3", "Hotbar4", "Hotbar5", "Hotbar6", "Hotbar7",
			"Hotbar8", "TabRight", "ChatUp", "ChatDown"
		};

		private unsafe static string PathOf(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected I4, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected I4, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Invalid comparison between Unknown and I4
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Invalid comparison between Unknown and I4
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Invalid comparison between Unknown and I4
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Invalid comparison between Unknown and I4
			//IL_008a: 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_00a2: Expected I4, but got Unknown
			if ((int)key >= 97 && (int)key <= 122)
			{
				return "<Keyboard>/" + ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant();
			}
			if ((int)key >= 48 && (int)key <= 57)
			{
				return "<Keyboard>/" + (key - 48);
			}
			if ((int)key >= 282 && (int)key <= 293)
			{
				return "<Keyboard>/" + ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant();
			}
			if ((int)key <= 279)
			{
				if ((int)key == 96)
				{
					return "<Keyboard>/backquote";
				}
				if ((int)key == 127)
				{
					return "<Keyboard>/delete";
				}
				switch (key - 277)
				{
				case 0:
					return "<Keyboard>/insert";
				case 1:
					return "<Keyboard>/home";
				case 2:
					return "<Keyboard>/end";
				}
			}
			else
			{
				switch (key - 304)
				{
				default:
					if ((int)key != 326)
					{
						if ((int)key != 327)
						{
							break;
						}
						return "<Mouse>/forwardButton";
					}
					return "<Mouse>/backButton";
				case 4:
					return "<Keyboard>/leftAlt";
				case 3:
					return "<Keyboard>/rightAlt";
				case 2:
					return "<Keyboard>/leftCtrl";
				case 0:
					return "<Keyboard>/leftShift";
				case 1:
					break;
				}
			}
			return null;
		}

		public static List<string> Free(string owner, IEnumerable<KeyValuePair<KeyCode, string>> keys)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Invalid comparison between Unknown and I4
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			ZInput instance = ZInput.instance;
			if (instance == null)
			{
				return list;
			}
			if (!(AccessTools.Field(typeof(ZInput), "m_buttons")?.GetValue(instance) is Dictionary<string, ButtonDef> dictionary))
			{
				return list;
			}
			string text = "DHack.FreedGameKeys." + owner;
			HashSet<string> hashSet = new HashSet<string>(PlayerPrefs.GetString(text, "").Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries));
			bool flag = false;
			foreach (KeyValuePair<KeyCode, string> key in keys)
			{
				string text2 = PathOf(key.Key);
				if (text2 == null)
				{
					continue;
				}
				foreach (ButtonDef item2 in dictionary.Values.ToList())
				{
					if (item2 == null || !item2.Rebindable || (int)item2.Source == 180 || !string.Equals(item2.GetActionPath(true), text2, StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					if (Essential.Contains(item2.Name))
					{
						Debug.LogWarning((object)$"[{owner}] {key.Key} ({key.Value}) is also the game's {item2.Name} key; that one is left as it is. Choose another key in the mod's settings.");
						continue;
					}
					string item = item2.Name + ":" + text2.ToLowerInvariant();
					if (!hashSet.Contains(item))
					{
						item2.Rebind("");
						hashSet.Add(item);
						flag = true;
						list.Add(Translations.T("gearslots_key_unbound", owner, key.Key, key.Value, Nice(item2.Name)));
					}
				}
			}
			if (flag)
			{
				instance.Save();
				PlayerPrefs.SetString(text, string.Join("|", hashSet.ToArray()));
				PlayerPrefs.Save();
				foreach (string item3 in list)
				{
					Debug.Log((object)("[" + owner + "] " + item3));
				}
			}
			return list;
		}

		public static List<string> GiveBack(string owner, IEnumerable<KeyCode> inUse)
		{
			List<string> list = new List<string>();
			ZInput instance = ZInput.instance;
			if (instance == null)
			{
				return list;
			}
			if (!(AccessTools.Field(typeof(ZInput), "m_buttons")?.GetValue(instance) is Dictionary<string, ButtonDef> dictionary))
			{
				return list;
			}
			string text = "DHack.FreedGameKeys." + owner;
			HashSet<string> hashSet = new HashSet<string>(PlayerPrefs.GetString(text, "").Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries));
			HashSet<string> hashSet2 = new HashSet<string>(from p in inUse.Select(PathOf)
				where p != null
				select p.ToLowerInvariant());
			bool flag = false;
			foreach (string item in hashSet.ToList())
			{
				int num = item.IndexOf(':');
				if (num <= 0)
				{
					continue;
				}
				string text2 = item.Substring(0, num);
				string text3 = item.Substring(num + 1);
				if (!hashSet2.Contains(text3))
				{
					hashSet.Remove(item);
					flag = true;
					if (dictionary.TryGetValue(text2, out var value) && value != null && string.IsNullOrEmpty(value.GetActionPath(true)))
					{
						value.Rebind(text3);
						list.Add(Translations.T("gearslots_key_back", owner, Nice(text2), text3.Substring(text3.IndexOf('/') + 1).ToUpperInvariant()));
					}
				}
			}
			if (flag)
			{
				instance.Save();
				PlayerPrefs.SetString(text, string.Join("|", hashSet.ToArray()));
				PlayerPrefs.Save();
				foreach (string item2 in list)
				{
					Debug.Log((object)("[" + owner + "] " + item2));
				}
			}
			return list;
		}

		private static string Nice(string name)
		{
			return name switch
			{
				"AutoPickup" => Localization.instance.Localize("$settings_autopickup"), 
				"ToggleWalk" => Localization.instance.Localize("$settings_walk"), 
				"AutoRun" => Localization.instance.Localize("$settings_autorun"), 
				"OpenRadial" => Localization.instance.Localize("$settings_open_radial"), 
				"TabLeft" => Translations.T("gearslots_action_tableft"), 
				"OpenEmote" => Localization.instance.Localize("$settings_open_emote_wheel"), 
				"GP" => Localization.instance.Localize("$settings_gp"), 
				"Sit" => Localization.instance.Localize("$settings_sit"), 
				_ => name, 
			};
		}
	}
	internal class Hotbar
	{
		private class Cell
		{
			public GameObject Go;

			public Image Icon;

			public GuiBar Durability;

			public TMP_Text Amount;

			public TMP_Text Binding;

			public GameObject Equipped;

			public GameObject Queued;

			public int StackShown = -1;
		}

		private readonly List<Cell> _cells = new List<Cell>();

		private RectTransform _messageText;

		private RectTransform _messageIcon;

		private Vector2 _textHome;

		private Vector2 _iconHome;

		private bool _messagesMoved;

		public void Update(Player player, Inventory inv)
		{
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			HotkeyBar val = (((Object)(object)Hud.instance != (Object)null) ? ((Component)Hud.instance).GetComponentInChildren<HotkeyBar>(true) : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.m_elementPrefab == (Object)null)
			{
				Destroy();
				return;
			}
			if (_cells.Count != 5 || (Object)(object)_cells[0].Go == (Object)null)
			{
				Build(val);
			}
			bool flag = InventoryGui.IsVisible() || !Plugin.Instance.ShowQuickBar;
			bool flag2 = false;
			for (int i = 0; i < _cells.Count; i++)
			{
				Cell cell = _cells[i];
				Slot slot = Layout.QuickSlot(i);
				ItemData val2 = ((slot != null) ? Layout.ItemIn(inv, slot) : null);
				bool flag3 = Plugin.Instance.QuickKeyName(i).Length > 0;
				cell.Go.SetActive(!flag && val2 != null && flag3);
				if (flag || val2 == null || !flag3)
				{
					continue;
				}
				flag2 = true;
				cell.Binding.text = (ZInput.IsGamepadActive() ? "" : Plugin.Instance.QuickKeyName(i));
				((Component)cell.Icon).gameObject.SetActive(true);
				cell.Icon.sprite = val2.GetIcon();
				bool flag4 = val2.m_shared.m_useDurability && val2.m_durability < val2.GetMaxDurability();
				((Component)cell.Durability).gameObject.SetActive(flag4);
				if (flag4)
				{
					if (val2.m_durability <= 0f)
					{
						cell.Durability.SetValue(1f);
						cell.Durability.SetColor((Color)((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : new Color(0f, 0f, 0f, 0f)));
					}
					else
					{
						cell.Durability.SetValue(val2.GetDurabilityPercentage());
						cell.Durability.ResetColor();
					}
				}
				cell.Equipped.SetActive(val2.m_equipped);
				cell.Queued.SetActive(player.IsEquipActionQueued(val2));
				bool flag5 = val2.m_shared.m_maxStackSize > 1;
				((Component)cell.Amount).gameObject.SetActive(flag5);
				if (flag5 && cell.StackShown != val2.m_stack)
				{
					cell.Amount.text = $"{val2.m_stack} / {val2.m_shared.m_maxStackSize}";
					cell.StackShown = val2.m_stack;
				}
			}
			MoveMessages(flag2 ? (val.m_elementSpace + 6f) : 0f);
		}

		private void MoveMessages(float drop)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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)
			MessageHud instance = MessageHud.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_messageText == (Object)null) && !((Object)(object)instance.m_messageIcon == (Object)null))
			{
				if ((Object)(object)_messageText == (Object)null)
				{
					_messageText = instance.m_messageText.rectTransform;
					_textHome = _messageText.anchoredPosition;
					_messageIcon = ((Graphic)instance.m_messageIcon).rectTransform;
					_iconHome = _messageIcon.anchoredPosition;
				}
				if (!(drop <= 0f) || _messagesMoved)
				{
					_messageText.anchoredPosition = _textHome + new Vector2(0f, 0f - drop);
					_messageIcon.anchoredPosition = _iconHome + new Vector2(0f, 0f - drop);
					_messagesMoved = drop > 0f;
				}
			}
		}

		private void Build(HotkeyBar bar)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Destroy();
			for (int i = 0; i < 5; i++)
			{
				Cell cell = new Cell
				{
					Go = Object.Instantiate<GameObject>(bar.m_elementPrefab, ((Component)bar).transform)
				};
				((Object)cell.Go).name = "GearSlotsQuick" + (i + 1);
				cell.Go.transform.localPosition = new Vector3((float)i * bar.m_elementSpace, 0f - bar.m_elementSpace, 0f);
				Transform transform = cell.Go.transform;
				cell.Binding = ((Component)transform.Find("binding")).GetComponent<TMP_Text>();
				cell.Icon = ((Component)transform.Find("icon")).GetComponent<Image>();
				cell.Durability = ((Component)transform.Find("durability")).GetComponent<GuiBar>();
				cell.Amount = ((Component)transform.Find("amount")).GetComponent<TMP_Text>();
				cell.Equipped = ((Component)transform.Find("equiped")).gameObject;
				cell.Queued = ((Component)transform.Find("queued")).gameObject;
				Transform val = transform.Find("selected");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
				}
				_cells.Add(cell);
			}
		}

		public void Destroy()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_messageText != (Object)null && _messagesMoved)
			{
				_messageText.anchoredPosition = _textHome;
				_messageIcon.anchoredPosition = _iconHome;
			}
			_messagesMoved = false;
			_messageText = (_messageIcon = null);
			foreach (Cell cell in _cells)
			{
				if ((Object)(object)cell.Go != (Object)null)
				{
					Object.Destroy((Object)(object)cell.Go);
				}
			}
			_cells.Clear();
		}
	}
	internal static class Panel
	{
		private static readonly Color Gold = new Color(0.85f, 0.68f, 0.3f, 1f);

		private static readonly Color Dim = new Color(1f, 1f, 1f, 0.38f);

		private static RectTransform _panel;

		private static TMP_Text _title;

		private static readonly Dictionary<Slot, TMP_Text> Labels = new Dictionary<Slot, TMP_Text>();

		private static readonly FieldRef<InventoryGrid, List<InventoryElement>> ElementsField = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements");

		private const float Pad = 10f;

		private const float TitleHeight = 24f;

		private static readonly Color TitleColor = new Color(1f, 0.86f, 0.55f, 1f);

		public static void Update(InventoryGrid grid)
		{
			//IL_0106: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0472: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: 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_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_player == (Object)null)
			{
				return;
			}
			List<InventoryElement> list = ElementsField.Invoke(grid);
			Inventory inventory = grid.GetInventory();
			int width = inventory.GetWidth();
			int normalRows = Layout.NormalRows;
			if (list == null || list.Count < width * (normalRows + 2) || (Object)(object)list[0] == (Object)null)
			{
				return;
			}
			grid.m_gridRoot.SetSizeWithCurrentAnchors((Axis)1, (float)normalRows * grid.m_elementSpace);
			bool showPanel = Plugin.Instance.ShowPanel;
			EnsurePanel(instance, list[0]);
			((Component)_panel).gameObject.SetActive(showPanel);
			if ((Object)(object)_title != (Object)null)
			{
				_title.text = Translations.T("gearslots_title");
			}
			float elementSpace = grid.m_elementSpace;
			? val;
			Rect rect;
			if (!((Object)(object)list[0].GetElementRectTransform() != (Object)null))
			{
				val = new Vector2(elementSpace - 6f, elementSpace - 6f);
			}
			else
			{
				rect = list[0].GetElementRectTransform().rect;
				val = ((Rect)(ref rect)).size;
			}
			Vector2 val2 = (Vector2)val;
			if (val2.x < 8f)
			{
				((Vector2)(ref val2))..ctor(elementSpace - 6f, elementSpace - 6f);
			}
			for (int i = 0; i < 2; i++)
			{
				for (int j = 0; j < width; j++)
				{
					InventoryElement val3 = list[(normalRows + i) * width + j];
					if ((Object)(object)val3 != (Object)null && Layout.At(j, normalRows + i) == null)
					{
						((Component)val3).gameObject.SetActive(false);
					}
				}
			}
			Slot[] all = Layout.All;
			Vector2 val7 = default(Vector2);
			foreach (Slot slot in all)
			{
				InventoryElement val4 = list[(normalRows + slot.Row) * width + slot.Col];
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				Transform transform = ((Component)val4).transform;
				RectTransform val5 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if ((Object)(object)((Transform)val5).parent != (Object)(object)_panel)
				{
					rect = val5.rect;
					Vector2 val6;
					if (!(((Rect)(ref rect)).size.x > 8f))
					{
						val6 = val2;
					}
					else
					{
						rect = val5.rect;
						val6 = ((Rect)(ref rect)).size;
					}
					Vector2 sizeDelta = val6;
					((Transform)val5).SetParent((Transform)(object)_panel, false);
					((Vector2)(ref val7))..ctor(0f, 1f);
					val5.anchorMax = val7;
					val5.anchorMin = val7;
					val5.pivot = new Vector2(0f, 1f);
					val5.sizeDelta = sizeDelta;
					((Transform)val5).localScale = Vector3.one;
				}
				((Component)val4).gameObject.SetActive(showPanel);
				val5.anchoredPosition = new Vector2(10f + (float)slot.Col * elementSpace, 0f - (34f + (float)slot.Row * elementSpace));
				Transform val8 = ((Component)val4).transform.Find("binding");
				TMP_Text val9 = (((Object)(object)val8 != (Object)null) ? ((Component)val8).GetComponent<TMP_Text>() : null);
				if ((Object)(object)val9 != (Object)null && (((Behaviour)val9).enabled = slot.Quick >= 0))
				{
					val9.text = Plugin.Instance.QuickKeyName(slot.Quick);
				}
				if (!Labels.TryGetValue(slot, out var value) || (Object)(object)value == (Object)null)
				{
					value = (Labels[slot] = MakeLabel((Transform)(object)val5, slot.Name, val4.m_amount));
					value.fontSize = 11f;
					value.enableAutoSizing = true;
					value.fontSizeMin = 7f;
					value.fontSizeMax = 11f;
					value.alignment = (TextAlignmentOptions)1026;
					rect = val5.rect;
					AddSilhouette((Transform)(object)val5, slot, ((Rect)(ref rect)).size);
				}
				Transform val11 = ((Transform)val5).Find("GearSlotsIcon");
				if ((Object)(object)val11 != (Object)null)
				{
					((Component)val11).gameObject.SetActive(Layout.ItemIn(inventory, slot) == null);
				}
				if ((Object)(object)value.transform.parent != (Object)(object)val5)
				{
					value.transform.SetParent((Transform)(object)val5, false);
				}
				value.text = slot.Name;
				((Behaviour)value).enabled = Layout.ItemIn(inventory, slot) == null;
			}
			float num = 20f + 7f * elementSpace + val2.x;
			float num2 = 44f + 1f * elementSpace + val2.y;
			_panel.sizeDelta = new Vector2(num, num2);
			Place(instance.m_player, num, num2);
		}

		private static void EnsurePanel(InventoryGui gui, InventoryElement sample)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: 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_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Expected O, but got Unknown
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: 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_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_panel != (Object)null)
			{
				return;
			}
			GameObject val = new GameObject("GearSlotsPanel", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Outline)
			});
			_panel = val.GetComponent<RectTransform>();
			((Transform)_panel).SetParent((Transform)(object)gui.m_player, false);
			((Transform)_panel).SetAsFirstSibling();
			_panel.pivot = new Vector2(0f, 1f);
			Image component = val.GetComponent<Image>();
			Image val2 = FindWoodPanel(gui.m_player);
			Outline component2 = val.GetComponent<Outline>();
			if ((Object)(object)val2 != (Object)null)
			{
				component.sprite = val2.sprite;
				component.type = val2.type;
				((Graphic)component).color = ((Graphic)val2).color;
				((Graphic)component).material = ((Graphic)val2).material;
				component.pixelsPerUnitMultiplier = val2.pixelsPerUnitMultiplier;
				((Behaviour)component2).enabled = false;
			}
			else
			{
				((Graphic)component).color = new Color(0.07f, 0.055f, 0.045f, 0.92f);
				((Shadow)component2).effectColor = new Color(Gold.r, Gold.g, Gold.b, 0.55f);
				((Shadow)component2).effectDistance = new Vector2(1.5f, -1.5f);
			}
			TMP_Text val3 = Find<TMP_Text>(gui, "root/Crafting/topic");
			_title = MakeLabel((Transform)(object)_panel, Translations.T("gearslots_title"), ((Object)(object)val3 != (Object)null) ? val3 : sample.m_amount);
			_title.fontSize = (((Object)(object)val3 != (Object)null) ? 20f : 17f);
			((Graphic)_title).color = (((Object)(object)val3 != (Object)null) ? TitleColor : Gold);
			_title.alignment = (TextAlignmentOptions)257;
			RectTransform rectTransform = _title.rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = new Vector2(10f, 0f);
			rectTransform.offsetMax = new Vector2(-10f, -4f);
			Image val4 = Find<Image>(gui, "root/Crafting/BraidLineHorisontalMedium");
			if ((Object)(object)val4 != (Object)null)
			{
				GameObject val5 = new GameObject("GearSlotsBraid", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				RectTransform val6 = (RectTransform)val5.transform;
				((Transform)val6).SetParent((Transform)(object)_panel, false);
				((Transform)val6).SetSiblingIndex(1);
				val6.anchorMin = new Vector2(0f, 1f);
				val6.anchorMax = new Vector2(1f, 1f);
				val6.pivot = new Vector2(0.5f, 0.5f);
				val6.offsetMin = new Vector2(10f, 0f);
				val6.offsetMax = new Vector2(-10f, 0f);
				Rect rect = ((Graphic)val4).rectTransform.rect;
				val6.sizeDelta = new Vector2(-20f, Mathf.Clamp(((Rect)(ref rect)).height, 6f, 12f));
				val6.anchoredPosition = new Vector2(0f, -30f);
				Image component3 = val5.GetComponent<Image>();
				component3.sprite = val4.sprite;
				component3.type = val4.type;
				((Graphic)component3).material = ((Graphic)val4).material;
				((Graphic)component3).color = ((Graphic)val4).color;
				component3.pixelsPerUnitMultiplier = val4.pixelsPerUnitMultiplier;
				component3.fillCenter = val4.fillCenter;
				((Graphic)component3).raycastTarget = false;
			}
			else
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"The game's title line was not found where expected: the Gear panel's title is plain");
				}
			}
		}

		private static T Find<T>(InventoryGui gui, string path) where T : Component
		{
			Transform val = ((Component)gui).transform.Find(path);
			if (!((Object)(object)val != (Object)null))
			{
				return default(T);
			}
			return ((Component)val).GetComponent<T>();
		}

		private static Image FindWoodPanel(RectTransform inventory)
		{
			//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)
			Image result = null;
			float num = 0f;
			Image[] componentsInChildren = ((Component)inventory).GetComponentsInChildren<Image>(true);
			foreach (Image val in componentsInChildren)
			{
				if (!((Object)(object)val.sprite == (Object)null) && !((Object)(object)((Component)val).transform == (Object)(object)_panel) && (!((Object)(object)_panel != (Object)null) || !((Component)val).transform.IsChildOf((Transform)(object)_panel)) && !((Object)(object)((Component)val).GetComponentInParent<InventoryElement>() != (Object)null))
				{
					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;
		}

		private static Sprite IconOf(string prefab)
		{
			if (string.IsNullOrEmpty(prefab) || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return null;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab);
			ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.m_itemData.GetIcon();
		}

		private static void AddSilhouette(Transform parent, Slot slot, Vector2 size)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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)
			Sprite val = IconOf(slot.Icon);
			if (!((Object)(object)val == (Object)null))
			{
				GameObject val2 = new GameObject("GearSlotsIcon", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val2.transform.SetParent(parent, false);
				val2.transform.SetAsFirstSibling();
				Image component = val2.GetComponent<Image>();
				component.sprite = val;
				((Graphic)component).raycastTarget = false;
				component.preserveAspect = true;
				((Graphic)component).color = new Color(0f, 0f, 0f, 0.35f);
				RectTransform rectTransform = ((Graphic)component).rectTransform;
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(0.5f, 0.5f);
				rectTransform.anchorMax = val3;
				rectTransform.anchorMin = val3;
				rectTransform.sizeDelta = size * 0.62f;
				rectTransform.anchoredPosition = new Vector2(0f, 4f);
			}
		}

		private static TMP_Text MakeLabel(Transform parent, string text, TMP_Text font)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0072: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("GearSlotsLabel", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			bool activeSelf = val.activeSelf;
			val.SetActive(false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).font = font.font;
			val.SetActive(activeSelf);
			((TMP_Text)val2).fontSharedMaterial = font.fontSharedMaterial;
			((TMP_Text)val2).text = text;
			((TMP_Text)val2).fontSize = 12f;
			((Graphic)val2).color = Dim;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).enableWordWrapping = false;
			RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			Vector2 offsetMin = (rectTransform.offsetMax = Vector2.zero);
			rectTransform.offsetMin = offsetMin;
			return (TMP_Text)(object)val2;
		}

		private static float ReservedBelow()
		{
			object data = AppDomain.CurrentDomain.GetData("DHack.QoL.UnderInventoryHeight");
			if (data is float)
			{
				return (float)data;
			}
			return 0f;
		}

		private static void Place(RectTransform inventory, float width, float height)
		{
			//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_0011: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			RectTransform panel = _panel;
			Vector2 anchorMin = (_panel.anchorMax = inventory.pivot);
			panel.anchorMin = anchorMin;
			Rect rect = inventory.rect;
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			inventory.GetWorldCorners(array);
			float num = ((((Transform)inventory).lossyScale.x > 0f) ? ((Transform)inventory).lossyScale.x : 1f);
			Vector2 val = ((array[0].x - (width + Plugin.Instance.PanelGap) * num >= 0f) ? new Vector2(((Rect)(ref rect)).xMin - width - Plugin.Instance.PanelGap, ((Rect)(ref rect)).yMax) : new Vector2(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin - Plugin.Instance.PanelGap - ReservedBelow()));
			_panel.anchoredPosition = val + Plugin.Instance.PanelOffset;
		}

		public static void Dispose(bool restoreCells)
		{
			InventoryGui instance = InventoryGui.instance;
			if (restoreCells && (Object)(object)instance != (Object)null && (Object)(object)instance.m_playerGrid != (Object)null && (Object)(object)_panel != (Object)null)
			{
				InventoryGrid playerGrid = instance.m_playerGrid;
				foreach (InventoryElement item in ElementsField.Invoke(playerGrid))
				{
					if ((Object)(object)item != (Object)null && (Object)(object)((Component)item).transform.parent == (Object)(object)_panel)
					{
						((Component)item).transform.SetParent((Transform)(object)playerGrid.m_gridRoot, false);
						((Component)item).gameObject.SetActive(true);
					}
				}
				AccessTools.Field(typeof(InventoryGrid), "m_width").SetValue(playerGrid, -1);
			}
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_panel).gameObject);
			}
			_panel = null;
			_title = null;
			Labels.Clear();
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(Player), "Load")]
		private static class PlayerLoad
		{
			[HarmonyPriority(800)]
			private static void Postfix(Player __instance)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					if (Compat.StandingDown)
					{
						var (moved, left) = Layout.EmptyGearRows(__instance);
						Plugin.Instance?.StoodDown(moved, left);
					}
					else
					{
						Place(__instance, Layout.WorkOutBase(__instance));
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class OnSpawned
		{
			[HarmonyPriority(0)]
			private static void Postfix(Player __instance)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !Compat.StandingDown)
				{
					if ((Object)(object)__instance != (Object)(object)_placed)
					{
						Place(__instance, ((Humanoid)__instance).GetInventory().GetHeight());
					}
					if ((Object)(object)InventoryGui.instance != (Object)null)
					{
						InventoryGui.instance.SetInventorySize(Layout.NormalRows);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "SetInventorySize")]
		private static class SetInventorySize
		{
			internal static bool Resizing;

			internal static int OldBase;

			[HarmonyPriority(800)]
			private static void Prefix(Player __instance)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !Compat.StandingDown)
				{
					Resizing = true;
					OldBase = Layout.NormalRows;
				}
			}

			[HarmonyPriority(0)]
			private static void Postfix(Player __instance)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !Compat.StandingDown)
				{
					Extend(((Humanoid)__instance).GetInventory());
				}
			}

			[HarmonyFinalizer]
			private static void Finalizer()
			{
				Resizing = false;
			}
		}

		[HarmonyPatch(typeof(Humanoid), "DropInvalidItems")]
		private static class DropInvalidItems
		{
			[HarmonyPriority(800)]
			private static void Prefix(Humanoid __instance)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: 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_0130: Unknown result type (might be due to invalid IL or missing references)
				//IL_0139: Unknown result type (might be due to invalid IL or missing references)
				if (!SetInventorySize.Resizing || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				Player val = (Player)__instance;
				Inventory inventory = ((Humanoid)val).GetInventory();
				int oldBase = SetInventorySize.OldBase;
				int height = inventory.GetHeight();
				List<ItemData> list = new List<ItemData>();
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (allItem.m_gridPos.y >= oldBase && allItem.m_gridPos.y < oldBase + 2)
					{
						list.Add(allItem);
					}
				}
				foreach (ItemData item in list)
				{
					item.m_gridPos.y += height - oldBase;
				}
				Layout.RememberNormalRows(height);
				Layout.SaveBase(val, height);
				inventory.SetHeight(height + 2);
				foreach (ItemData allItem2 in inventory.GetAllItems())
				{
					if (!list.Contains(allItem2) && allItem2.m_gridPos.y >= height)
					{
						Vector2i val2 = Layout.FindFreeNormalCell(inventory, topFirst: false);
						allItem2.m_gridPos = (Vector2i)((val2.x >= 0) ? val2 : new Vector2i(-1, -1));
					}
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "FindEmptySlot")]
		private static class FindEmptySlot
		{
			private static void Postfix(Inventory __instance, bool topFirst, ref Vector2i __result)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				if (Layout.IsPlayerInventory(__instance) && __result.y >= Layout.NormalRows)
				{
					__result = Layout.FindFreeNormalCell(__instance, topFirst);
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "HaveEmptySlot")]
		private static class HaveEmptySlot
		{
			private static void Postfix(Inventory __instance, ref bool __result)
			{
				if (Layout.IsPlayerInventory(__instance))
				{
					__result = Layout.NormalItemCount(__instance) < __instance.GetWidth() * Layout.NormalRows;
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "GetEmptySlots")]
		private static class GetEmptySlots
		{
			private static void Postfix(Inventory __instance, ref int __result)
			{
				if (Layout.IsPlayerInventory(__instance))
				{
					__result = __instance.GetWidth() * Layout.NormalRows - Layout.NormalItemCount(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
		{
			typeof(ItemData),
			typeof(int)
		})]
		private static class CanAddItem
		{
			private static void Postfix(Inventory __instance, ItemData item, int stack, ref bool __result)
			{
				if (__result && Layout.IsPlayerInventory(__instance))
				{
					if (stack <= 0)
					{
						stack = item.m_stack;
					}
					int num = __instance.GetWidth() * Layout.NormalRows - Layout.NormalItemCount(__instance);
					int num2 = (int)AccessTools.Method(typeof(Inventory), "FindFreeStackSpace", (Type[])null, (Type[])null).Invoke(__instance, new object[2]
					{
						item.m_shared.m_name,
						item.m_worldLevel
					});
					__result = num2 + num * item.m_shared.m_maxStackSize >= stack;
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
		private static class DropItem
		{
			private static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, Vector2i pos, ref bool __result)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: 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)
				Inventory inventory = __instance.GetInventory();
				if (Layout.IsPlayerInventory(inventory))
				{
					Slot slot = Layout.At(pos.x, pos.y);
					if (slot != null && !Layout.Fits(slot, item))
					{
						return Refuse(item, slot, out __result);
					}
				}
				if (Layout.IsPlayerInventory(fromInventory))
				{
					Slot slot2 = Layout.At(item.m_gridPos.x, item.m_gridPos.y);
					ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
					if (slot2 != null && itemAt != null && itemAt != item && !Layout.Fits(slot2, itemAt))
					{
						return Refuse(itemAt, slot2, out __result);
					}
				}
				return true;
			}

			private static bool Refuse(ItemData item, Slot slot, out bool result)
			{
				result = false;
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, Translations.T("gearslots_doesnt_fit", Localization.instance.Localize(item.m_shared.m_name), slot.Name), 0, (Sprite)null, false);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		private static class UpdateGui
		{
			private static void Postfix(InventoryGrid __instance)
			{
				if (!((Object)(object)Plugin.Instance == (Object)null) && Layout.IsPlayerInventory(__instance.GetInventory()))
				{
					Panel.Update(__instance);
				}
			}
		}

		private static Player _placed;

		public static void Extend(Inventory inv)
		{
			if (inv != null && !Compat.StandingDown)
			{
				if (!(AppDomain.CurrentDomain.GetData("DHack.GearSlots.NormalRows") is int) && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					Layout.RememberNormalRows(Layout.WorkOutBase(Player.m_localPlayer));
				}
				int num = Layout.NormalRows + 2;
				if (inv.GetHeight() < num)
				{
					inv.SetHeight(num);
				}
			}
		}

		private static void Place(Player player, int gearBase)
		{
			Layout.RememberNormalRows(gearBase);
			Layout.SaveBase(player, gearBase);
			Inventory inventory = ((Humanoid)player).GetInventory();
			inventory.SetHeight(Mathf.Max(inventory.GetHeight(), gearBase + 2));
			_placed = player;
		}
	}
	[BepInPlugin("com.quad.gearslots", "GearSlots", "1.3.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.quad.gearslots";

		public const string OldGuid = "com.dhack.gearslots";

		public const string Name = "GearSlots";

		public const string Version = "1.3.1";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		private ConfigEntry<bool> _showPanel;

		private ConfigEntry<bool> _autoEat;

		private ConfigEntry<bool> _showMessages;

		private ConfigEntry<bool> _autoFill;

		private ConfigEntry<bool> _shieldFollows;

		private ConfigEntry<bool> _showQuickBar;

		private ConfigEntry<int> _eatBelow;

		private ConfigEntry<float> _panelGap;

		private ConfigEntry<float> _offsetX;

		private ConfigEntry<float> _offsetY;

		private ConfigEntry<KeyboardShortcut>[] _quickKeys;

		private Harmony _harmony;

		private readonly Hotbar _hotbar = new Hotbar();

		private Inventory _watched;

		private readonly Dictionary<Slot, ItemData> _last = new Dictionary<Slot, ItemData>();

		private float _nextEat;

		private float _nextFill;

		private bool _keysChecked;

		private readonly List<string> _keyNotes = new List<string>();

		private bool _toldStandDown;

		private static readonly FieldRef<Humanoid, ItemData> LeftItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_leftItem");

		private ItemData _lastWeapon;

		internal bool ShowQuickBar => _showQuickBar.Value;

		internal bool ShowPanel => _showPanel.Value;

		internal float PanelGap => _panelGap.Value;

		internal Vector2 PanelOffset => new Vector2(_offsetX.Value, _offsetY.Value);

		private void Awake()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			Migration.FromOldGuid((BaseUnityPlugin)(object)this, "com.dhack.gearslots");
			Translations.Load((BaseUnityPlugin)(object)this);
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_showPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowPanel", true, "Show the Gear panel next to your inventory. (Turn off and your gear slots hide; the items stay where they are.)");
			_showMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowMessages", true, "Short messages when something happens (auto-eat, a quick slot is empty).");
			_autoEat = ((BaseUnityPlugin)this).Config.Bind<bool>("Food", "AutoEat", false, "Eat from your Food slots by yourself: when a food you have in a slot is not active (and you have a free food slot), or its effect has dropped below half. Off by default.");
			_eatBelow = ((BaseUnityPlugin)this).Config.Bind<int>("Food", "EatBelowPercent", 20, new ConfigDescription("Auto-eat a food you are already under only once its time left drops below this percent (the game allows it from 50). Lower saves food: a meal then lasts 80% of its time instead of 50%, and its effect weakens a little towards the end.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			_shieldFollows = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShieldFollowsWeapon", true, "When you switch to a one-handed weapon, put on the shield from your Shield slot too. (Two-handed weapons and bows take the shield off, as in the game.)");
			_showQuickBar = ((BaseUnityPlugin)this).Config.Bind<bool>("Quick slots", "ShowUnderHotbar", true, "Show what is in your Quick slots, with their keys, in a row under the hotbar (the 1-8 on screen) while the inventory is closed.");
			_autoFill = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoFill", true, "When you put on a piece of gear (or the game loads with it on), move it into its matching gear slot if that slot is empty.");
			_panelGap = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Gap", 6f, "Space between the Gear panel and the inventory (UI pixels).");
			_offsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "OffsetX", 0f, "Move the Gear panel right (negative = left).");
			_offsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "OffsetY", 0f, "Move the Gear panel up (negative = down).");
			KeyCode[] array = new KeyCode[5];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			KeyCode[] array2 = (KeyCode[])(object)array;
			_quickKeys = new ConfigEntry<KeyboardShortcut>[5];
			for (int i = 0; i < 5; i++)
			{
				_quickKeys[i] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Quick slots", "Key" + (i + 1), new KeyboardShortcut(array2[i], Array.Empty<KeyCode>()), "Press to use what is in quick slot " + (i + 1) + ": equips or unequips a weapon, tool or shield, or drinks a potion. Set to None to turn it off. If the game uses the same key for something (V: auto-pickup, X: sit, C: walk), the game's key is unbound once, so only this one works; bind it again in the game's Settings, Controls.");
			}
			ConfigEntry<KeyboardShortcut>[] quickKeys = _quickKeys;
			foreach (ConfigEntry<KeyboardShortcut> val in quickKeys)
			{
				val.SettingChanged += delegate
				{
					_keysChecked = false;
				};
			}
			_harmony = new Harmony("com.quad.gearslots");
			_harmony.PatchAll();
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				Patches.Extend(((Humanoid)Player.m_localPlayer).GetInventory());
			}
			AppDomain.CurrentDomain.SetData("DHack.GearSlots.IsGear", new Func<ItemData, bool>(IsInGearSlot));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"GearSlots 1.3.1 loaded");
			if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)Chat.instance != (Object)null)
			{
				((Terminal)Chat.instance).AddString("[Mod]", "GearSlots v1.3.1 reloaded", (Type)1, false);
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Panel.Dispose(restoreCells: true);
			_hotbar.Destroy();
			Translations.Unload();
			AppDomain.CurrentDomain.SetData("DHack.GearSlots.IsGear", null);
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
				Log = null;
			}
		}

		internal unsafe string QuickKeyName(int quick)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = _quickKeys[quick].Value;
			KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
			if ((int)mainKey != 0)
			{
				return ((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString();
			}
			return "";
		}

		private static bool IsInGearSlot(ItemData item)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (item != null && (Object)(object)Player.m_localPlayer != (Object)null && !Compat.StandingDown && Layout.InExtraRows(item.m_gridPos))
			{
				return ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems().Contains(item);
			}
			return false;
		}

		private void FreeGameKeys()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (_keysChecked || ZInput.instance == null)
			{
				return;
			}
			_keysChecked = true;
			List<KeyValuePair<KeyCode, string>> list = new List<KeyValuePair<KeyCode, string>>();
			for (int i = 0; i < _quickKeys.Length; i++)
			{
				KeyboardShortcut value = _quickKeys[i].Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && !((KeyboardShortcut)(ref value)).Modifiers.Any())
				{
					list.Add(new KeyValuePair<KeyCode, string>(((KeyboardShortcut)(ref value)).MainKey, Translations.T("gearslots_quick_slot_n", i + 1)));
				}
			}
			_keyNotes.AddRange(GameKeys.Free("GearSlots", list));
			_keyNotes.AddRange(GameKeys.GiveBack("GearSlots", list.Select((KeyValuePair<KeyCode, string> k) => k.Key)));
			FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_enableAutoPickup");
			if (fieldInfo != null && !(bool)fieldInfo.GetValue(null))
			{
				ButtonDef buttonDef = ZInput.instance.GetButtonDef("AutoPickup");
				if (string.IsNullOrEmpty((buttonDef != null) ? buttonDef.GetActionPath(true) : null))
				{
					fieldInfo.SetValue(null, true);
					_keyNotes.Add(Translations.T("gearslots_autopickup_on", "GearSlots"));
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Auto-pickup was off and its key is unbound: switched it back on");
				}
			}
		}

		internal void StoodDown(int moved, int left)
		{
			if (!_toldStandDown)
			{
				_toldStandDown = true;
				string text = Translations.T("gearslots_standdown", "GearSlots", Compat.StandDownFor);
				if (moved > 0)
				{
					text = text + " " + Translations.T("gearslots_standdown_moved", moved);
				}
				if (left > 0)
				{
					text = text + " " + Translations.T("gearslots_standdown_left", left);
				}
				_keyNotes.Add(text);
				((BaseUnityPlugin)this).Logger.LogInfo((object)text);
				_keyNotes.AddRange(GameKeys.GiveBack("GearSlots", (IEnumerable<KeyCode>)(object)new KeyCode[0]));
			}
		}

		private void Update()
		{
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer != (Object)null && Compat.StandingDown)
			{
				StoodDown(0, 0);
				if (_keyNotes.Count <= 0 || !((Object)(object)Chat.instance != (Object)null))
				{
					return;
				}
				foreach (string keyNote in _keyNotes)
				{
					((Terminal)Chat.instance).AddString("[Mod]", keyNote, (Type)1, false);
				}
				_keyNotes.Clear();
				return;
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				FreeGameKeys();
			}
			if (_keyNotes.Count > 0 && (Object)(object)Chat.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				foreach (string keyNote2 in _keyNotes)
				{
					((Terminal)Chat.instance).AddString("[Mod]", keyNote2, (Type)1, false);
				}
				_keyNotes.Clear();
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			Patches.Extend(inventory);
			_hotbar.Update(localPlayer, inventory);
			if (_autoFill.Value && Time.time >= _nextFill)
			{
				_nextFill = Time.time + 0.5f;
				FillSlotsWithWornGear(localPlayer, inventory);
			}
			WearWhatArrived(localPlayer, inventory);
			if (_shieldFollows.Value)
			{
				ShieldFollowsWeapon(localPlayer, inventory);
			}
			if (_autoEat.Value && Time.time >= _nextEat)
			{
				_nextEat = Time.time + 1f;
				AutoEat(localPlayer, inventory);
			}
			if (InventoryGui.IsVisible() || TypingOrMenuOpen())
			{
				return;
			}
			for (int i = 0; i < 5; i++)
			{
				if (Pressed(_quickKeys[i].Value))
				{
					UseQuick(localPlayer, inventory, i);
				}
			}
		}

		private void WearWhatArrived(Player player, Inventory inv)
		{
			bool flag = _watched != inv;
			_watched = inv;
			Slot[] all = Layout.All;
			foreach (Slot slot in all)
			{
				if (!Layout.IsEquipment(slot))
				{
					continue;
				}
				ItemData val = Layout.ItemIn(inv, slot);
				_last.TryGetValue(slot, out var value);
				if (!flag && val != null && val != value && !((Humanoid)player).IsItemEquiped(val))
				{
					if (slot.Kind == Kind.Shield && !OneHandFree(player))
					{
						_last[slot] = val;
						continue;
					}
					((Humanoid)player).EquipItem(val, true);
				}
				_last[slot] = val;
			}
		}

		private void FillSlotsWithWornGear(Player player, Inventory inv)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			foreach (ItemData item in inv.GetAllItems().ToList())
			{
				if (item.m_gridPos.y < Layout.NormalRows && ((Humanoid)player).IsItemEquiped(item))
				{
					Slot slot = Layout.All.FirstOrDefault((Slot s) => Layout.IsEquipment(s) && Layout.Fits(s, item) && Layout.ItemIn(inv, s) == null);
					if (slot != null)
					{
						item.m_gridPos = Layout.CellOf(slot);
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Moved worn " + item.m_shared.m_name + " into the " + slot.Label + " slot"));
					}
				}
			}
		}

		private static bool OneHandFree(Player player)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			if (currentWeapon == null)
			{
				return true;
			}
			ItemType itemType = currentWeapon.m_shared.m_itemType;
			return (int)itemType == 3;
		}

		private void ShieldFollowsWeapon(Player player, Inventory inv)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			if (currentWeapon == _lastWeapon)
			{
				return;
			}
			_lastWeapon = currentWeapon;
			if (currentWeapon != null && (int)currentWeapon.m_shared.m_itemType == 3 && inv.ContainsItem(currentWeapon) && LeftItem.Invoke((Humanoid)(object)player) == null)
			{
				Slot s = Layout.All.First((Slot slot) => slot.Kind == Kind.Shield);
				ItemData val = Layout.ItemIn(inv, s);
				if (val != null && !((Humanoid)player).IsItemEquiped(val))
				{
					((Humanoid)player).EquipItem(val, true);
				}
			}
		}

		private void UseQuick(Player player, Inventory inv, int quick)
		{
			Slot s = Layout.All.First((Slot slot) => slot.Quick == quick);
			ItemData val = Layout.ItemIn(inv, s);
			if (val == null)
			{
				Tell(player, Translations.T("gearslots_quick_empty", quick + 1));
			}
			else
			{
				((Humanoid)player).UseItem(inv, val, true);
			}
		}

		private void AutoEat(Player player, Inventory inv)
		{
			List<Food> foods = player.GetFoods();
			Slot[] all = Layout.All;
			foreach (Slot slot in all)
			{
				if (slot.Kind != Kind.Food)
				{
					continue;
				}
				ItemData item = Layout.ItemIn(inv, slot);
				if (item == null)
				{
					continue;
				}
				Food val = ((IEnumerable<Food>)foods).FirstOrDefault((Func<Food, bool>)((Food f) => f.m_item.m_shared.m_name == item.m_shared.m_name));
				bool num;
				if (val == null)
				{
					num = foods.Count < 3;
				}
				else
				{
					if (!val.CanEatAgain())
					{
						continue;
					}
					num = val.m_time < val.m_item.m_shared.m_foodBurnTime * (float)_eatBelow.Value / 100f;
				}
				if (num && player.CanEat(item, false))
				{
					((Humanoid)player).UseItem(inv, item, true);
					Tell(player, Translations.T("gearslots_ate", Localization.instance.Localize(item.m_shared.m_name)));
					break;
				}
			}
		}

		private static bool Pressed(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
			}
			return false;
		}

		private static bool TypingOrMenuOpen()
		{
			if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput() && !Menu.IsVisible() && !Minimap.IsOpen())
			{
				return StoreGui.IsVisible();
			}
			return true;
		}

		private void Tell(Player player, string message)
		{
			if (_showMessages.Value)
			{
				((Character)player).Message((MessageType)1, message, 0, (Sprite)null, false);
			}
		}
	}
	internal enum Kind
	{
		Head,
		Chest,
		Legs,
		Shoulder,
		Utility,
		Trinket,
		Ammo,
		Shield,
		Food,
		Quick
	}
	internal class Slot
	{
		public string Label;

		public Kind Kind;

		public int Col;

		public int Row;

		public int Quick;

		public string Icon;

		public string Name => Localization.instance.Localize(Label);
	}
	internal static class Layout
	{
		public const int ExtraRows = 2;

		public const int Columns = 8;

		private const string RowsKey = "DHack.GearSlots.NormalRows";

		public static readonly Slot[] All = new Slot[16]
		{
			new Slot
			{
				Label = "$gearslots_slot_head",
				Kind = Kind.Head,
				Col = 0,
				Row = 0,
				Quick = -1,
				Icon = "HelmetLeather"
			},
			new Slot
			{
				Label = "$gearslots_slot_chest",
				Kind = Kind.Chest,
				Col = 1,
				Row = 0,
				Quick = -1,
				Icon = "ArmorLeatherChest"
			},
			new Slot
			{
				Label = "$gearslots_slot_legs",
				Kind = Kind.Legs,
				Col = 2,
				Row = 0,
				Quick = -1,
				Icon = "ArmorLeatherLegs"
			},
			new Slot
			{
				Label = "$gearslots_slot_cape",
				Kind = Kind.Shoulder,
				Col = 3,
				Row = 0,
				Quick = -1,
				Icon = "CapeDeerHide"
			},
			new Slot
			{
				Label = "$gearslots_slot_belt",
				Kind = Kind.Utility,
				Col = 4,
				Row = 0,
				Quick = -1,
				Icon = "BeltStrength"
			},
			new Slot
			{
				Label = "$gearslots_slot_trinket",
				Kind = Kind.Trinket,
				Col = 5,
				Row = 0,
				Quick = -1
			},
			new Slot
			{
				Label = "$gearslots_slot_ammo",
				Kind = Kind.Ammo,
				Col = 6,
				Row = 0,
				Quick = -1,
				Icon = "ArrowWood"
			},
			new Slot
			{
				Label = "$gearslots_slot_shield",
				Kind = Kind.Shield,
				Col = 7,
				Row = 0,
				Quick = -1,
				Icon = "ShieldWood"
			},
			new Slot
			{
				Label = "$gearslots_slot_food",
				Kind = Kind.Food,
				Col = 0,
				Row = 1,
				Quick = -1,
				Icon = "CookedMeat"
			},
			new Slot
			{
				Label = "$gearslots_slot_food",
				Kind = Kind.Food,
				Col = 1,
				Row = 1,
				Quick = -1,
				Icon = "CookedMeat"
			},
			new Slot
			{
				Label = "$gearslots_slot_food",
				Kind = Kind.Food,
				Col = 2,
				Row = 1,
				Quick = -1,
				Icon = "CookedMeat"
			},
			new Slot
			{
				Label = "$gearslots_slot_quick",
				Kind = Kind.Quick,
				Col = 3,
				Row = 1,
				Quick = 0
			},
			new Slot
			{
				Label = "$gearslots_slot_quick",
				Kind = Kind.Quick,
				Col = 4,
				Row = 1,
				Quick = 1
			},
			new Slot
			{
				Label = "$gearslots_slot_quick",
				Kind = Kind.Quick,
				Col = 5,
				Row = 1,
				Quick = 2
			},
			new Slot
			{
				Label = "$gearslots_slot_quick",
				Kind = Kind.Quick,
				Col = 6,
				Row = 1,
				Quick = 3
			},
			new Slot
			{
				Label = "$gearslots_slot_quick",
				Kind = Kind.Quick,
				Col = 7,
				Row = 1,
				Quick = 4
			}
		};

		public const int QuickCount = 5;

		private const string BaseKey = "DHack.GearSlots.Base";

		public static int NormalRows
		{
			get
			{
				object data = AppDomain.CurrentDomain.GetData("DHack.GearSlots.NormalRows");
				if (data is int)
				{
					return (int)data;
				}
				Inventory val = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Humanoid)Player.m_localPlayer).GetInventory() : null);
				if (val == null)
				{
					return 4;
				}
				return val.GetHeight();
			}
		}

		public static void RememberNormalRows(int rows)
		{
			AppDomain.CurrentDomain.SetData("DHack.GearSlots.NormalRows", rows);
		}

		public static void ForgetNormalRows()
		{
			AppDomain.CurrentDomain.SetData("DHack.GearSlots.NormalRows", null);
		}

		public static void SaveBase(Player player, int gearBase)
		{
			player.m_customData["DHack.GearSlots.Base"] = gearBase.ToString();
		}

		public static int WorkOutBase(Player player)
		{
			if (player.m_customData.TryGetValue("DHack.GearSlots.Base", out var value) && int.TryParse(value, out var result) && result >= 0)
			{
				return result;
			}
			string s = default(string);
			if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result2))
			{
				return Mathf.Clamp(result2, 0, 9);
			}
			return ((Humanoid)player).GetInventory().GetHeight();
		}

		public static (int moved, int left) EmptyGearRows(Player player)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if (!player.m_customData.TryGetValue("DHack.GearSlots.Base", out var value) || !int.TryParse(value, out var result))
			{
				return (moved: 0, left: 0);
			}
			string s = default(string);
			int num = ((player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result2)) ? Mathf.Clamp(result2, 0, 9) : 4);
			num = Mathf.Min(num, result);
			Inventory inventory = ((Humanoid)player).GetInventory();
			int num2 = 0;
			int num3 = 0;
			Vector2i val = default(Vector2i);
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_gridPos.y < result || allItem.m_gridPos.y >= result + 2)
				{
					continue;
				}
				((Vector2i)(ref val))..ctor(-1, -1);
				for (int i = 0; i < num; i++)
				{
					if (val.x >= 0)
					{
						break;
					}
					for (int j = 0; j < inventory.GetWidth(); j++)
					{
						if (inventory.GetItemAt(j, i) == null)
						{
							((Vector2i)(ref val))..ctor(j, i);
							break;
						}
					}
				}
				if (val.x < 0)
				{
					num3++;
					continue;
				}
				allItem.m_gridPos = val;
				num2++;
			}
			if (num3 == 0)
			{
				player.m_customData.Remove("DHack.GearSlots.Base");
			}
			return (moved: num2, left: num3);
		}

		public static Vector2i CellOf(Slot s)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2i(s.Col, NormalRows + s.Row);
		}

		public static Slot At(int x, int y)
		{
			int num = y - NormalRows;
			if (num < 0 || num >= 2)
			{
				return null;
			}
			Slot[] all = All;
			foreach (Slot slot in all)
			{
				if (slot.Col == x && slot.Row == num)
				{
					return slot;
				}
			}
			return null;
		}

		public static bool InExtraRows(Vector2i pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return pos.y >= NormalRows;
		}

		public static bool Fits(Slot s, ItemData item)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Invalid comparison between Unknown and I4
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Invalid comparison between Unknown and I4
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Invalid comparison between Unknown and I4
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Invalid comparison between Unknown and I4
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Invalid comparison between Unknown and I4
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Invalid comparison between Unknown and I4
			if (s == null || item == null)
			{
				return true;
			}
			SharedData shared = item.m_shared;
			switch (s.Kind)
			{
			case Kind.Head:
				return (int)shared.m_itemType == 6;
			case Kind.Chest:
				return (int)shared.m_itemType == 7;
			case Kind.Legs:
				return (int)shared.m_itemType == 11;
			case Kind.Shoulder:
				return (int)shared.m_itemType == 17;
			case Kind.Utility:
				return (int)shared.m_itemType == 18;
			case Kind.Trinket:
				return (int)shared.m_itemType == 24;
			case Kind.Shield:
				return (int)shared.m_itemType == 5;
			case Kind.Ammo:
				if ((int)shared.m_itemType != 9)
				{
					return (int)shared.m_itemType == 23;
				}
				return true;
			case Kind.Food:
				return IsFood(item);
			default:
				return !shared.m_questItem;
			}
		}

		public static bool IsFood(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType == 2)
			{
				if (!(item.m_shared.m_food > 0f) && !(item.m_shared.m_foodStamina > 0f))
				{
					return item.m_shared.m_foodEitr > 0f;
				}
				return true;
			}
			return false;
		}

		public static Slot QuickSlot(int quick)
		{
			Slot[] all = All;
			foreach (Slot slot in all)
			{
				if (slot.Quick == quick)
				{
					return slot;
				}
			}
			return null;
		}

		public static bool IsEquipment(Slot s)
		{
			if (s != null && s.Kind != Kind.Food)
			{
				return s.Kind != Kind.Quick;
			}
			return false;
		}

		public static ItemData ItemIn(Inventory inv, Slot s)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Vector2i val = CellOf(s);
			return inv.GetItemAt(val.x, val.y);
		}

		public static bool IsPlayerInventory(Inventory inv)
		{
			if (inv != null && (Object)(object)Player.m_localPlayer != (Object)null && inv == ((Humanoid)Player.m_localPlayer).GetInventory())
			{
				return !Compat.StandingDown;
			}
			return false;
		}

		public static int NormalItemCount(Inventory inv)
		{
			int normalRows = NormalRows;
			int num = 0;
			foreach (ItemData allItem in inv.GetAllItems())
			{
				if (allItem.m_gridPos.y < normalRows)
				{
					num++;
				}
			}
			return num;
		}

		public static Vector2i FindFreeNormalCell(Inventory inv, bool topFirst)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			int normalRows = NormalRows;
			int width = inv.GetWidth();
			for (int i = 0; i < normalRows; i++)
			{
				int num = (topFirst ? i : (normalRows - 1 - i));
				for (int j = 0; j < width; j++)
				{
					if (inv.GetItemAt(j, num) == null)
					{
						return new Vector2i(j, num);
					}
				}
			}
			return new Vector2i(-1, -1);
		}
	}
}
namespace DHack.Shared
{
	internal static class Migration
	{
		private sealed class Notice : MonoBehaviour
		{
			public string Text;

			private float _next;

			private void Update()
			{
				if (!(Time.unscaledTime < _next) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)MessageHud.instance == (Object)null))
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, Text, 0, (Sprite)null, false);
					_next = Time.unscaledTime + 60f;
				}
			}
		}

		public static void FromOldGuid(BaseUnityPlugin plugin, string oldGuid)
		{
			BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin);
			string text = ((metadata != null) ? metadata.GUID : null);
			if (string.IsNullOrEmpty(oldGuid) || string.IsNullOrEmpty(text) || oldGuid == text)
			{
				return;
			}
			ManualLogSource val = Logger.CreateLogSource(text);
			try
			{
				bool flag = false;
				if (Directory.Exists(Paths.ConfigPath))
				{
					string[] files = Directory.GetFiles(Paths.ConfigPath, oldGuid + ".*");
					foreach (string text2 in files)
					{
						string fileName = Path.GetFileName(text2);
						if (!fileName.EndsWith(".cfg") && !fileName.EndsWith(".json") && !fileName.EndsWith(".txt"))
						{
							continue;
						}
						string text3 = Path.Combine(Paths.ConfigPath, text + fileName.Substring(oldGuid.Length));
						if (!File.Exists(text3))
						{
							File.Copy(text2, text3);
							val.LogInfo((object)("Settings moved over from " + fileName + " (the mod's id is now " + text + "; the old file is kept as a backup)"));
							if (fileName == oldGuid + ".cfg")
							{
								flag = true;
							}
						}
					}
				}
				if (flag)
				{
					plugin.Config.Reload();
				}
			}
			catch (Exception ex)
			{
				val.LogWarning((object)("Couldn't move the settings over from " + oldGuid + ".cfg: " + ex.Message));
			}
			finally
			{
				Logger.Sources.Remove((ILogSource)(object)val);
			}
			((MonoBehaviour)plugin).StartCoroutine(StandDownIfTwin(plugin, oldGuid));
		}

		private static IEnumerator StandDownIfTwin(BaseUnityPlugin plugin, string oldGuid)
		{
			yield return null;
			yield return null;
			if (!((Object)(object)plugin == (Object)null) && Chainloader.PluginInfos.TryGetValue(oldGuid, out var value) && !((Object)(object)value.Instance == (Object)null) && !((Object)(object)value.Instance == (Object)(object)plugin))
			{
				BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin);
				string text = ((metadata != null) ? metadata.Name : null) ?? oldGuid;
				string text2 = (string.IsNullOrEmpty(value.Location) ? "an older copy" : value.Location);
				string text3 = text + ": two copies are installed, an old one (" + text2 + ") and this one. Both would run and do everything twice, so this one stands down. Delete the old copy, then restart the game.";
				Debug.LogError((object)("[" + text + "] " + text3));
				Object.Destroy((Object)(object)plugin);
				GameObject val = new GameObject("Migration_TwoCopies_" + text);
				Object.DontDestroyOnLoad((Object)(object)val);
				val.AddComponent<Notice>().Text = text3;
			}
		}
	}
	internal static class Translations
	{
		public static readonly string[] Shipped = new string[9] { "English", "Russian", "German", "Chinese", "Portuguese_Brazilian", "Spanish", "French", "Polish", "Turkish" };

		private static readonly Dictionary<string, Dictionary<string, string>> Languages = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);

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

		private static string _overrideDir;

		private static bool _hooked;

		private static readonly MethodInfo AddWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);

		private static readonly FieldInfo Cache = AccessTools.Field(typeof(Localization), "m_cache");

		public static void Load(BaseUnityPlugin plugin)
		{
			Languages.Clear();
			Assembly assembly = ((object)plugin).GetType().Assembly;
			foreach (string item in from n in assembly.GetManifestResourceNames()
				where n.StartsWith("translations/") && n.EndsWith(".json")
				select n)
			{
				using StreamReader streamReader = new StreamReader(assembly.GetManifestResourceStream(item));
				Languages[Path.GetFileNameWithoutExtension(item.Substring("translations/".Length))] = Parse(streamReader.ReadToEnd());
			}
			_english = (Languages.TryGetValue("English", out var value) ? value : new Dictionary<string, string>());
			_overrideDir = Path.Combine(Paths.ConfigPath, "translations", plugin.Info.Metadata.GUID);
			if (!_hooked)
			{
				Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(Apply));
				_hooked = true;
			}
			Apply();
		}

		public static void Unload()
		{
			if (_hooked)
			{
				Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(Apply));
				_hooked = false;
			}
		}

		public static string T(string key, params object[] args)
		{
			string text = ((Localization.instance != null) ? Localization.instance.Localize("$" + key) : null);
			if (string.IsNullOrEmpty(text) || text == "[" + key + "]")
			{
				text = (_english.TryGetValue(key, out var value) ? value : key);
			}
			if (args == null || args.Length == 0)
			{
				return text;
			}
			try
			{
				return string.Format(text, args);
			}
			catch (FormatException)
			{
				string value2;
				return _english.TryGetValue(key, out value2) ? SafeFormat(value2, args) : text;
			}
		}

		private static string SafeFormat(string text, object[] args)
		{
			try
			{
				return string.Format(text, args);
			}
			catch (FormatException)
			{
				return text;
			}
		}

		private static void Apply()
		{
			Localization instance = Localization.instance;
			if (instance == null || AddWord == null)
			{
				return;
			}
			string selectedLanguage = instance.GetSelectedLanguage();
			Dictionary<string, string> dictionary = new Dictionary<string, string>(_english);
			if (Languages.TryGetValue(selectedLanguage, out var value))
			{
				foreach (KeyValuePair<string, string> item in value)
				{
					dictionary[item.Key] = item.Value;
				}
			}
			try
			{
				string path = Path.Combine(_overrideDir, selectedLanguage + ".json");
				if (File.Exists(path))
				{
					foreach (KeyValuePair<string, string> item2 in Parse(File.ReadAllText(path)))
					{
						dictionary[item2.Key] = item2.Value;
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("Translations: couldn't read the player's " + selectedLanguage + " file: " + ex.Message));
			}
			foreach (KeyValuePair<string, string> item3 in dictionary)
			{
				AddWord.Invoke(instance, new object[2] { item3.Key, item3.Value });
			}
			object obj = Cache?.GetValue(instance);
			obj?.GetType().GetMethod("EvictAll")?.Invoke(obj, null);
		}

		private static Dictionary<string, string> Parse(string json)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (Match item in Regex.Matches(json, "\"((?:[^\"\\\\]|\\\\.)*)\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\""))
			{
				dictionary[Unescape(item.Groups[1].Value)] = Unescape(item.Groups[2].Value);
			}
			return dictionary;
		}

		private static string Unescape(string s)
		{
			return Regex.Replace(s, "\\\\(u[0-9a-fA-F]{4}|.)", delegate(Match m)
			{
				string value = m.Groups[1].Value;
				return value[0] switch
				{
					'n' => "\n", 
					't' => "\t", 
					'u' => ((char)Convert.ToInt32(value.Substring(1), 16)).ToString(), 
					_ => value, 
				};
			});
		}
	}
}