Decompiled source of PackPanel v0.1.0

plugins\PackPanel.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BundlePrefabs;
using Charter;
using ConfigReload;
using HarmonyLib;
using Hotkeys;
using ItemCopies;
using Microsoft.CodeAnalysis;
using PackPanel.Backpacks;
using PackPanel.Consume;
using PackPanel.Core;
using PackPanel.Crafting;
using PackPanel.Layout;
using PackPanel.Look;
using PackPanel.Panels;
using PackPanel.Ring;
using PackPanel.Slots;
using PackPanel.Tackle;
using PackPanel.Worn;
using PatchGuard;
using PlateColumn;
using SyncedConfig;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using YamlConfig;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("PackPanel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("PackPanel: a bigger inventory, labelled slots, backpacks and a new look for Valheim")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+9a329d5c191afce69442cfc563644a5560c4fc74")]
[assembly: AssemblyProduct("PackPanel")]
[assembly: AssemblyTitle("PackPanel")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 PackPanel
{
	[BepInPlugin("milkyteam.packpanel", "PackPanel", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "milkyteam.packpanel";

		public const string PluginName = "PackPanel";

		public const string PluginVersion = "0.1.0";

		public static ManualLogSource Log { get; private set; }

		public static SyncedConfiguration Synced { get; private set; }

		public static ConfigEntry<bool> LockConfiguration { get; private set; }

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Synced = new SyncedConfiguration((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, "PackPanel", "0.1.0");
			LockConfiguration = Synced.BindLocking("General", "Lock Configuration", defaultValue: true, "[Server Only] Clients cannot change synced settings while connected to a server that has this on.");
			InventoryModule.Initialize(Synced);
			Harmony harmony = new Harmony("milkyteam.packpanel");
			int num = PatchEverything(harmony);
			BackpackPrefab.Install(harmony);
			TackleboxPrefab.Install(harmony);
			Synced.Finish(harmony);
			Log.LogInfo((object)("Loading [PackPanel 0.1.0]" + ((num > 0) ? $" with {num} failed patches, see above" : "")));
			Guard.Install(harmony, ((BaseUnityPlugin)this).Logger, Assembly.GetExecutingAssembly());
		}

		private void Update()
		{
			Synced.YamlEditor.Update();
			GamePanelTheme.Update();
		}

		private void OnGUI()
		{
			Synced.YamlEditor.OnGUI();
		}

		private static int PatchEverything(Harmony harmony)
		{
			int num = 0;
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly());
			foreach (Type type in typesFromAssembly)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0)
				{
					try
					{
						harmony.CreateClassProcessor(type).Patch();
					}
					catch (Exception ex)
					{
						num++;
						Log.LogError((object)("Patch " + type.FullName + " failed to apply: " + ex.Message));
					}
				}
			}
			return num;
		}
	}
}
namespace PackPanel.Worn
{
	public static class EquipPatches
	{
		[HarmonyPatch(typeof(Humanoid), "EquipItem")]
		public static class Equip
		{
			[HarmonyPrefix]
			public static bool Prefix(Humanoid __instance, ItemData item, bool triggerEquipEffects, ref bool __result)
			{
				WornPlacement.BeginEquip();
				if (!ExtraUtilities.Takes(__instance, item))
				{
					return true;
				}
				__result = ExtraUtilities.Wear(__instance, item, triggerEquipEffects);
				return false;
			}

			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, ItemData item, bool __result)
			{
				if (__result)
				{
					WornPlacement.OnWorn(__instance, item);
				}
			}

			[HarmonyFinalizer]
			public static void Finalizer()
			{
				WornPlacement.EndEquip();
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
		public static class Unequip
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, ItemData item)
			{
				if (item != null && !item.m_equipped)
				{
					ExtraUtilities.Forget(item);
					WornPlacement.OnTakenOff(__instance, item);
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "IsItemEquiped")]
		public static class IsEquipped
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, ItemData item, ref bool __result)
			{
				if (!__result && ExtraUtilities.IsWorn(item) && InventoryState.IsLocal(__instance))
				{
					__result = true;
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "IsItemTypeEquiped")]
		public static class IsTypeEquipped
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, ItemData item, ref bool __result)
			{
				if (__result || item == null || !InventoryState.IsLocal(__instance))
				{
					return;
				}
				foreach (ItemData item2 in ExtraUtilities.Worn)
				{
					if (item2.m_shared.m_name == item.m_shared.m_name)
					{
						__result = true;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UnequipAllItems")]
		public static class UnequipAll
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance)
			{
				if (InventoryState.IsLocal(__instance))
				{
					ExtraUtilities.TakeOffAll(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UnequipDeathDropItems")]
		public static class DeathDrop
		{
			[HarmonyPostfix]
			public static void Postfix(Player __instance)
			{
				if (InventoryState.IsLocal((Humanoid)(object)__instance))
				{
					ExtraUtilities.TakeOffAll((Humanoid)(object)__instance);
				}
			}
		}
	}
	public static class ExtraEffects
	{
		private static readonly HashSet<StatusEffect> added = new HashSet<StatusEffect>();

		public static void Reset()
		{
			added.Clear();
		}

		public static void Sync(Humanoid humanoid)
		{
			if (!InventoryState.IsLocal(humanoid))
			{
				return;
			}
			HashSet<StatusEffect> hashSet = Wanted(humanoid);
			SEMan sEMan = ((Character)humanoid).GetSEMan();
			foreach (StatusEffect item in added)
			{
				if (!hashSet.Contains(item) && !humanoid.m_equipmentStatusEffects.Contains(item))
				{
					sEMan.RemoveStatusEffect(item.NameHash(), false);
				}
			}
			foreach (StatusEffect item2 in hashSet)
			{
				if (!sEMan.HaveStatusEffect(item2.NameHash()))
				{
					sEMan.AddStatusEffect(item2, false, 0, 0f, (short)(-1));
				}
			}
			added.Clear();
			added.UnionWith(hashSet);
		}

		private static HashSet<StatusEffect> Wanted(Humanoid humanoid)
		{
			HashSet<StatusEffect> hashSet = new HashSet<StatusEffect>();
			foreach (ItemData item in ExtraUtilities.Worn)
			{
				if ((Object)(object)item.m_shared.m_equipStatusEffect != (Object)null)
				{
					hashSet.Add(item.m_shared.m_equipStatusEffect);
				}
				if (humanoid.HaveSetEffect(item))
				{
					hashSet.Add(item.m_shared.m_setStatusEffect);
				}
			}
			return hashSet;
		}
	}
	public static class ExtraUtilities
	{
		private static readonly List<ItemData> worn = new List<ItemData>();

		public static IReadOnlyList<ItemData> Worn => worn;

		public static bool IsWorn(ItemData item)
		{
			if (item != null)
			{
				return worn.Contains(item);
			}
			return false;
		}

		public static void Reset()
		{
			worn.Clear();
			ExtraEffects.Reset();
		}

		public static bool Takes(Humanoid humanoid, ItemData item)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			if (!InventoryState.IsLocal(humanoid) || !InventoryState.Active || item == null)
			{
				return false;
			}
			if ((int)item.m_shared.m_itemType != 18 || worn.Contains(item))
			{
				return false;
			}
			ItemData utilityItem = humanoid.m_utilityItem;
			if (utilityItem == null || utilityItem == item || 1 + worn.Count >= SlotCounts.Utility)
			{
				return false;
			}
			return !NameWorn(utilityItem, item);
		}

		public static bool Wear(Humanoid humanoid, ItemData item, bool triggerEquipEffects)
		{
			//IL_0030: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!CanWear(humanoid, item))
			{
				return false;
			}
			worn.Add(item);
			item.m_equipped = true;
			Transform transform = ((Component)humanoid).transform;
			item.m_shared.m_equipEffect.Create(transform.position + Vector3.up, transform.rotation, (Transform)null, 1f, -1, ((Character)humanoid).GetZDOID());
			humanoid.SetupEquipment();
			if (triggerEquipEffects)
			{
				humanoid.TriggerEquipEffect(item);
			}
			return true;
		}

		public static void Forget(ItemData item)
		{
			worn.Remove(item);
		}

		public static void TakeOffAll(Humanoid humanoid)
		{
			foreach (ItemData item in new List<ItemData>(worn))
			{
				humanoid.UnequipItem(item, false);
			}
			worn.Clear();
		}

		public static void Prune(Humanoid humanoid)
		{
			Inventory inventory = humanoid.GetInventory();
			if (worn.RemoveAll((ItemData item) => !item.m_equipped || !inventory.ContainsItem(item)) > 0)
			{
				humanoid.SetupEquipment();
			}
		}

		private static bool NameWorn(ItemData first, ItemData item)
		{
			if (first.m_shared.m_name == item.m_shared.m_name)
			{
				return true;
			}
			return worn.Exists((ItemData other) => other.m_shared.m_name == item.m_shared.m_name);
		}

		private static bool CanWear(Humanoid humanoid, ItemData item)
		{
			if (!humanoid.GetInventory().ContainsItem(item) || ((Character)humanoid).InAttack() || ((Character)humanoid).InDodge())
			{
				return false;
			}
			if (((Character)humanoid).IsSwimming() && !((Character)humanoid).IsOnGround() && !((Character)humanoid).IsDead())
			{
				return false;
			}
			if (item.m_shared.m_useDurability && item.m_durability <= 0f)
			{
				return false;
			}
			if (Game.m_worldLevel > 0 && item.m_worldLevel < Game.m_worldLevel)
			{
				((Character)humanoid).Message((MessageType)2, "$msg_ng_item_too_low", 0, (Sprite)null, false);
				return false;
			}
			return true;
		}
	}
	public static class UtilityEffectPatches
	{
		[HarmonyPatch(typeof(Humanoid), "UpdateEquipmentStatusEffects")]
		public static class StatusEffects
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance)
			{
				ExtraEffects.Sync(__instance);
			}
		}

		[HarmonyPatch(typeof(Humanoid), "GetSetCount")]
		public static class SetCount
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, string setName, ref int __result)
			{
				if (!InventoryState.IsLocal(__instance))
				{
					return;
				}
				foreach (ItemData item in ExtraUtilities.Worn)
				{
					if (item.m_shared.m_setName == setName)
					{
						__result++;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")]
		public static class EitrRegen
		{
			[HarmonyPostfix]
			public static void Postfix(Player __instance, ref float __result)
			{
				if (!InventoryState.IsLocal((Humanoid)(object)__instance))
				{
					return;
				}
				foreach (ItemData item in ExtraUtilities.Worn)
				{
					__result += item.m_shared.m_eitrRegenModifier;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateModifiers")]
		public static class Modifiers
		{
			[HarmonyPostfix]
			public static void Postfix(Player __instance)
			{
				if (!InventoryState.IsLocal((Humanoid)(object)__instance) || ExtraUtilities.Worn.Count == 0 || Player.s_equipmentModifierSourceFields == null)
				{
					return;
				}
				float[] equipmentModifierValues = __instance.m_equipmentModifierValues;
				for (int i = 0; i < equipmentModifierValues.Length; i++)
				{
					foreach (ItemData item in ExtraUtilities.Worn)
					{
						equipmentModifierValues[i] += (float)Player.s_equipmentModifierSourceFields[i].GetValue(item.m_shared);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "GetEquipmentWeight")]
		public static class Weight
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, ref float __result)
			{
				if (!InventoryState.IsLocal(__instance))
				{
					return;
				}
				foreach (ItemData item in ExtraUtilities.Worn)
				{
					__result += item.m_shared.m_weight;
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UpdateEquipment")]
		public static class Durability
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, float dt)
			{
				if (!InventoryState.IsLocal(__instance))
				{
					return;
				}
				for (int num = ExtraUtilities.Worn.Count - 1; num >= 0; num--)
				{
					ItemData val = ExtraUtilities.Worn[num];
					if (val.m_shared.m_useDurability)
					{
						__instance.DrainEquipedItemDurability(val, dt);
					}
				}
			}
		}
	}
	public static class WornPlacement
	{
		private static int suspended;

		private static int equipping;

		public static bool Suspended => suspended > 0;

		public static void BeginEquip()
		{
			equipping++;
		}

		public static void EndEquip()
		{
			equipping = ((equipping > 0) ? (equipping - 1) : 0);
		}

		public static void Suspend()
		{
			suspended++;
		}

		public static void Resume()
		{
			suspended = ((suspended > 0) ? (suspended - 1) : 0);
		}

		public static void OnWorn(Humanoid humanoid, ItemData item)
		{
			if (!Suspended && item != null && InventoryState.IsLocal(humanoid) && InventoryState.Manages(humanoid.GetInventory()))
			{
				Place(humanoid.GetInventory(), item);
			}
		}

		public static void OnTakenOff(Humanoid humanoid, ItemData item)
		{
			//IL_0038: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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)
			Inventory inventory = humanoid.GetInventory();
			if (Suspended || equipping > 0 || item == null || item.m_equipped || !InventoryState.IsLocal(humanoid) || !InventoryState.Manages(inventory))
			{
				return;
			}
			Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos);
			if (slot != null && SlotRules.IsWorn(slot.Kind) && inventory.ContainsItem(item))
			{
				Vector2i val = MainCells.FindEmpty(inventory, InventoryState.Layout, topFirst: false);
				if (val.x >= 0)
				{
					item.m_gridPos = val;
					inventory.Changed(false, false);
				}
			}
		}

		public static void SettleAll(Humanoid humanoid)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = humanoid.GetInventory();
			foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
			{
				if (item.m_equipped)
				{
					Place(inventory, item);
				}
			}
			foreach (ItemData item2 in new List<ItemData>(ExtraUtilities.Worn))
			{
				Slot slot = InventoryState.Layout.SlotAt(item2.m_gridPos);
				if (slot == null || slot.Kind != SlotKind.Utility)
				{
					humanoid.UnequipItem(item2, false);
				}
			}
		}

		private static void Place(Inventory inventory, ItemData item)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			SlotKind? slotKind = SlotRules.WornKindOf(item);
			Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos);
			if (!slotKind.HasValue || (slot != null && slot.Kind == slotKind.Value))
			{
				return;
			}
			Vector2i? val = CellFor(inventory, slotKind.Value);
			if (val.HasValue)
			{
				ItemData itemAt = inventory.GetItemAt(val.Value.x, val.Value.y);
				if (itemAt != null)
				{
					itemAt.m_gridPos = item.m_gridPos;
				}
				item.m_gridPos = val.Value;
				inventory.Changed(false, false);
			}
		}

		private static Vector2i? CellFor(Inventory inventory, SlotKind kind)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Vector2i? result = null;
			foreach (Vector2i item in InventoryState.CellsOf(kind))
			{
				ItemData itemAt = inventory.GetItemAt(item.x, item.y);
				if (itemAt == null)
				{
					return item;
				}
				if (!result.HasValue && !itemAt.m_equipped)
				{
					result = item;
				}
			}
			return result;
		}
	}
}
namespace PackPanel.Tackle
{
	public static class Tacklebox
	{
		public static bool Active
		{
			get
			{
				if (InventoryState.Active)
				{
					return InventoryState.CellsOf(SlotKind.Tackle).Count > 0;
				}
				return false;
			}
		}

		public static TackleboxKind InSlot(Inventory inventory, InventoryLayout layout)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<Vector2i> readOnlyList = layout.CellsOf(SlotKind.Tacklebox);
			if (readOnlyList.Count <= 0)
			{
				return null;
			}
			return TackleboxCatalog.Of(inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y));
		}

		public static int CellsFor(Player player)
		{
			return TackleboxSettings.Cells(InSlot(((Humanoid)player).GetInventory(), LayoutRecord.Read(player)));
		}
	}
	public static class TackleboxCatalog
	{
		private static readonly Dictionary<string, TackleboxKind> byName = new Dictionary<string, TackleboxKind>();

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

		public static IReadOnlyList<TackleboxKind> All { get; } = new List<TackleboxKind>
		{
			new TackleboxKind("PackPanel_DriftwoodTacklebox", "driftwood", "Driftwood Tacklebox", "A plain wooden box covered in furs.", 2f, new TackleboxStats("piece_workbench", 2, "Wood:10, LeatherScraps:10, DeerHide:5", 1)),
			new TackleboxKind("PackPanel_FinewoodTacklebox", "finewood", "Finewood Tacklebox", "A fine wood box wrapped in troll leather, with bronze corners and clasp.", 3f, new TackleboxStats("piece_workbench", 3, "PackPanel_DriftwoodTacklebox:1, FineWood:10, TrollHide:10, Bronze:2", 2)),
			new TackleboxKind("PackPanel_CarapaceTacklebox", "carapace", "Carapace Tacklebox", "A Yggdrasil wood box coated in carapace plates.", 3f, new TackleboxStats("blackforge", 1, "PackPanel_FinewoodTacklebox:1, Carapace:10, YggdrasilWood:10", 6)),
			new TackleboxKind("PackPanel_FlametalTacklebox", "flametal", "Flametal Tacklebox", "A flametal box covered in asksvin hide.", 4f, new TackleboxStats("blackforge", 3, "PackPanel_CarapaceTacklebox:1, FlametalNew:5, AskHide:10", 8))
		};

		public static TackleboxKind Of(ItemData item)
		{
			if (item == null || !Tables().TryGetValue(item.m_shared.m_name, out var value))
			{
				return null;
			}
			return value;
		}

		public static TackleboxKind ById(string id)
		{
			Tables();
			if (id == null || !byId.TryGetValue(id.Trim(), out var value))
			{
				return null;
			}
			return value;
		}

		private static Dictionary<string, TackleboxKind> Tables()
		{
			if (byName.Count == 0)
			{
				foreach (TackleboxKind item in All)
				{
					byName[item.Token] = item;
					byId[item.Id] = item;
				}
			}
			return byName;
		}
	}
	public static class TackleboxesFile
	{
		public const string DefaultResource = "PackPanel.config.PackPanel.Tackleboxes.yml";

		public static YamlFileSet Set { get; private set; }

		public static void Initialize(SyncedConfiguration synced)
		{
			Set = synced.AddYaml(new YamlFileSet("PackPanel.Tackleboxes*.yml", "packpanel_tackleboxes", () => new TackleboxesModel(), Apply)
			{
				DefaultContent = SyncedConfiguration.EmbeddedResource(typeof(TackleboxesFile).Assembly, "PackPanel.config.PackPanel.Tackleboxes.yml"),
				EditorLabel = () => "Edit tackleboxes"
			});
		}

		private static void Apply(YamlModel model)
		{
			TackleboxesModel tackleboxesModel = (TackleboxesModel)model;
			foreach (TackleboxKind item in TackleboxCatalog.All)
			{
				item.Stats = (tackleboxesModel.Stats.TryGetValue(item.Id, out var value) ? value : item.Defaults);
			}
			CraftRecipes.RefreshAll();
			TackleboxWords.DescribeAll();
			Plugin.Log.LogInfo((object)$"PackPanel: tackleboxes applied, {tackleboxesModel.Stats.Count} set in the file.");
		}
	}
	public sealed class TackleboxesModel : YamlModel
	{
		public const int MaxCells = 20;

		public Dictionary<string, TackleboxStats> Stats { get; } = new Dictionary<string, TackleboxStats>(StringComparer.OrdinalIgnoreCase);

		protected override void Read(YamlNode root)
		{
			YamlNode yamlNode = root.Get("tackleboxes");
			if (yamlNode.Kind == YamlNodeKind.Map)
			{
				foreach (KeyValuePair<string, YamlNode> entry in yamlNode.Entries)
				{
					ReadBox(entry.Key, entry.Value);
				}
				return;
			}
			if (yamlNode.Kind != YamlNodeKind.Missing && yamlNode.Kind != YamlNodeKind.Null)
			{
				yamlNode.Error("expected one entry per tacklebox prefab, as in 'PackPanel_FinewoodTacklebox: { cells: 3 }'");
			}
		}

		private void ReadBox(string id, YamlNode node)
		{
			TackleboxKind tackleboxKind = TackleboxCatalog.ById(id);
			if (tackleboxKind == null)
			{
				node.Warn("no tacklebox of that name; PackPanel's are PackPanel_DriftwoodTacklebox, PackPanel_FinewoodTacklebox, PackPanel_CarapaceTacklebox and PackPanel_FlametalTacklebox");
			}
			else if (node.Kind != YamlNodeKind.Map)
			{
				if (node.Kind != YamlNodeKind.Null)
				{
					node.Error("a tacklebox takes station:, level:, cost: and cells:, as in { cells: 3 }");
				}
			}
			else
			{
				TackleboxStats defaults = tackleboxKind.Defaults;
				int cells = RecipeYaml.Whole(node.Get("cells"), 0, 20, defaults.Cells);
				Stats[tackleboxKind.Id] = new TackleboxStats(RecipeYaml.Station(node, defaults), RecipeYaml.Level(node, defaults), RecipeYaml.Cost(node, defaults), cells);
			}
		}
	}
	public static class TackleboxGrave
	{
		[HarmonyPatch(typeof(TombStone), "EasyFitInInventory")]
		public static class EasyFit
		{
			[HarmonyPrefix]
			public static void Prefix(TombStone __instance, Player player)
			{
				Container component = ((Component)__instance).GetComponent<Container>();
				ExtraRoom = TackleboxSettings.Cells(TackleboxCatalog.Of((InventoryState.IsLocal((Humanoid)(object)player) && (Object)(object)component != (Object)null) ? Waiting(component.GetInventory()) : null));
			}

			[HarmonyFinalizer]
			public static void Finalizer()
			{
				ExtraRoom = 0;
			}
		}

		public static int ExtraRoom { get; private set; }

		public static void PutBackFirst(Inventory inventory, Inventory grave)
		{
			//IL_001d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = Waiting(grave);
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tacklebox);
			if (val != null && readOnlyList.Count != 0 && inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y) == null && inventory.AddItem(val, val.m_stack, readOnlyList[0].x, readOnlyList[0].y, false))
			{
				grave.RemoveItem(val);
				LayoutApply.Apply(InventoryState.Player, dropOverflow: true);
			}
		}

		private static ItemData Waiting(Inventory grave)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (grave == null || !InventoryState.Active || InventoryState.CellsOf(SlotKind.Tackle).Count > 0 || !TackleboxSettings.Active)
			{
				return null;
			}
			Vector2i val = SlotCellInGrave(grave);
			foreach (ItemData allItem in grave.GetAllItems())
			{
				if (allItem.m_gridPos == val && TackleboxCatalog.Of(allItem) != null)
				{
					return allItem;
				}
			}
			return null;
		}

		private static Vector2i SlotCellInGrave(Inventory grave)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			InventoryLayout layout = InventoryState.Layout;
			int num = layout.IndexOf(new Slot(SlotKind.Tacklebox, 1).Id);
			if (num < 0)
			{
				return new Vector2i(-1, -1);
			}
			Vector2i val = layout.CellOf(num);
			return new Vector2i(val.x, val.y + BackpackGrave.WaitingRows(grave));
		}
	}
	public sealed class TackleboxKind : CraftedKind
	{
		public TackleboxStats Defaults { get; }

		public TackleboxStats Stats { get; internal set; }

		public override CraftStats Recipe => Stats;

		public override CraftStats DefaultRecipe => Defaults;

		public override bool Craftable => TackleboxSettings.Active;

		public TackleboxKind(string id, string word, string name, string look, float weight, TackleboxStats defaults)
			: base(id, "tacklebox", word, name, look, weight)
		{
			Defaults = defaults;
			Stats = defaults;
		}
	}
	public static class TackleboxPrefab
	{
		private const string Bundle = "packpanel_tackleboxes";

		public static void Install(Harmony harmony)
		{
			NetPrefabs.OnSceneAwake(harmony, delegate(ZNetScene scene)
			{
				Setup(scene, harmony);
			});
		}

		private static void Setup(ZNetScene scene, Harmony harmony)
		{
			foreach (TackleboxKind item in TackleboxCatalog.All)
			{
				try
				{
					if ((Object)(object)item.Item == (Object)null)
					{
						Build(scene, item);
					}
					NetPrefabs.Register(scene, item.Item);
					ItemPrefabs.Register(harmony, item.Item);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("the " + item.Name + " could not be built and is not in the game: " + ex.Message));
				}
			}
			CraftRecipes.Install(ObjectDB.instance);
		}

		private static void Build(ZNetScene scene, TackleboxKind kind)
		{
			GameObject model = CraftedModels.Model("packpanel_tackleboxes", kind);
			Material look = CraftedModels.Look(scene, model);
			kind.Item = CraftedItem.Build(scene.GetPrefab("TrollHide"), CraftedModels.Dressed(model, "model", look), kind);
			Plugin.Log.LogInfo((object)(kind.Name + " ready: " + kind.Id));
		}
	}
	public static class TackleboxSettings
	{
		public const string Section = "6. Tacklebox";

		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<string> TackleItems { get; private set; }

		public static bool Active
		{
			get
			{
				if (Enabled.Value)
				{
					return InventorySettings.Enabled.Value;
				}
				return false;
			}
		}

		public static int Cells(TackleboxKind kind)
		{
			if (!Active || kind == null)
			{
				return 0;
			}
			return kind.Stats.Cells;
		}

		public static void Bind(SyncedConfiguration synced)
		{
			Enabled = synced.Bind("6. Tacklebox", "Tacklebox", true, "A Tacklebox slot right of the key ring button, and PackPanel's four tackleboxes, from the Driftwood Tacklebox to the Flametal Tacklebox (their cells, stations and costs are in PackPanel.Tackleboxes.yml). Put a box in the slot, by dropping it there or right clicking it, then right click it there to open it: a pop-up under the slot panel with its cells. Bait you pick up or take from a chest goes into it first, the fishing rod takes its bait from it first, and right clicking a bait in it fishes with that bait. Taking the box out moves what its cells hold into free cells and drops what does not fit at your feet. Off: no slot, none can be crafted.", true, null);
			TackleItems = synced.Bind("6. Tacklebox", "Tackle Items", "", "Items a tacklebox takes besides fishing bait, as prefab names, comma separated (chum, another mod's lures). Empty: bait only.", true, null);
		}
	}
	public static class TackleboxSlot
	{
		private static InventoryElement shownOn;

		private static int shownUsed = -1;

		private static int shownCells = -1;

		public static void Refresh(InventoryElement element)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)element == (Object)null || !element.m_used || !Tacklebox.Active)
			{
				return;
			}
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle);
			Inventory inventory = ((Humanoid)InventoryState.Player).GetInventory();
			int num = 0;
			foreach (Vector2i item in readOnlyList)
			{
				num += ((inventory.GetItemAt(item.x, item.y) != null) ? 1 : 0);
			}
			((Behaviour)element.m_amount).enabled = true;
			if (!((Object)(object)element == (Object)(object)shownOn) || num != shownUsed || readOnlyList.Count != shownCells)
			{
				element.m_amount.text = num + "/" + readOnlyList.Count;
				shownOn = element;
				shownUsed = num;
				shownCells = readOnlyList.Count;
			}
		}
	}
	public sealed class TackleboxStats : CraftStats
	{
		public int Cells { get; }

		public TackleboxStats(string station, int level, string cost, int cells)
			: base(station, level, cost)
		{
			Cells = cells;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	public static class TackleboxUse
	{
		[HarmonyPrefix]
		public static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!fromInventoryGui || item == null || !InventoryState.IsLocal(__instance))
			{
				return true;
			}
			Inventory val = inventory ?? __instance.GetInventory();
			if (!InventoryState.Manages(val) || !val.ContainsItem(item))
			{
				return true;
			}
			if (TackleboxCatalog.Of(item) != null)
			{
				return !Box(val, item);
			}
			if (TackleRules.IsBait(item))
			{
				Slot slot = InventoryState.SlotAt(val, item.m_gridPos);
				if (slot != null && slot.Kind == SlotKind.Tackle)
				{
					Choose(__instance, item);
					return false;
				}
			}
			return true;
		}

		private static bool Box(Inventory inventory, ItemData box)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tacklebox);
			if (readOnlyList.Count == 0)
			{
				return false;
			}
			if (box.m_gridPos == readOnlyList[0])
			{
				if (Tacklebox.Active)
				{
					TackleState.Toggle();
				}
				return true;
			}
			ItemData itemAt = inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y);
			if (itemAt != null)
			{
				itemAt.m_gridPos = box.m_gridPos;
			}
			box.m_gridPos = readOnlyList[0];
			inventory.Changed(false, false);
			return true;
		}

		private static void Choose(Humanoid player, ItemData bait)
		{
			if (bait.m_equipped)
			{
				player.UnequipItem(bait, true);
				return;
			}
			ItemData ammoItem = player.GetAmmoItem();
			if (ammoItem != null)
			{
				player.UnequipItem(ammoItem, false);
			}
			player.EquipItem(bait, true);
		}
	}
	public static class TackleboxWear
	{
		public static void Tick(Player player)
		{
			if (!((Character)player).IsDead() && InventoryState.IsLocal((Humanoid)(object)player) && InventoryState.Active)
			{
				TackleboxKind kind = Tacklebox.InSlot(((Humanoid)player).GetInventory(), InventoryState.Layout);
				if (InventoryState.CellsOf(SlotKind.Tackle).Count != TackleboxSettings.Cells(kind))
				{
					LayoutApply.Apply(player, dropOverflow: true);
				}
			}
		}
	}
	public static class TackleboxWords
	{
		public static string Tacklebox { get; private set; }

		public static string Bait { get; private set; }

		public static string Full { get; private set; }

		public static void Register()
		{
			foreach (TackleboxKind item in TackleboxCatalog.All)
			{
				Language.Add(item.Token.Substring(1), item.Name);
			}
			Tacklebox = Language.Add("packpanel_tackle", "Tackle");
			Bait = Language.Add("packpanel_bait", "Bait");
			Full = Language.Add("packpanel_tacklebox_full", "The tacklebox is full");
			DescribeAll();
		}

		public static void DescribeAll()
		{
			foreach (TackleboxKind item in TackleboxCatalog.All)
			{
				Language.Add(item.DescriptionToken.Substring(1), Describe(item));
			}
		}

		private static string Describe(TackleboxKind kind)
		{
			int cells = kind.Stats.Cells;
			string text = ((cells == 1) ? "one cell" : $"{cells} cells");
			return kind.Look + " Put it in your Tacklebox slot and right click it there to open it: " + text + " for bait, which the fishing rod takes first. Right click a bait in it to fish with that one.";
		}
	}
	public static class TackleCells
	{
		public const float CellScale = 0.8f;

		public const int Columns = 4;

		private static readonly List<InventoryElement> elements = new List<InventoryElement>();

		public static int Count => elements.Count;

		public static InventoryElement At(int number)
		{
			if (number < 1 || number > elements.Count)
			{
				return null;
			}
			return elements[number - 1];
		}

		public static void Clear()
		{
			elements.Clear();
		}

		public static bool Adopt(InventoryGui gui, InventoryElement element, Slot slot)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = TacklePopup.Find(gui);
			if ((Object)(object)val == (Object)null || slot.Number < 1)
			{
				return false;
			}
			while (elements.Count < slot.Number)
			{
				elements.Add(null);
			}
			elements[slot.Number - 1] = element;
			RectTransform val2 = (RectTransform)((Component)element).transform;
			((Transform)val2).SetParent((Transform)(object)val, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 1f);
			val2.pivot = val3;
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			((Transform)val2).localScale = Vector3.one * 0.8f;
			Image component = ((Component)element).GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				((Graphic)component).color = Color.white;
			}
			return true;
		}

		public static void Arrange(float pad, float step)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < elements.Count; i++)
			{
				if ((Object)(object)elements[i] != (Object)null)
				{
					((RectTransform)((Component)elements[i]).transform).anchoredPosition = new Vector2(pad + (float)(i % 4) * step, 0f - (pad + (float)(i / 4) * step));
				}
			}
		}

		public static bool Shows(int number)
		{
			InventoryElement val = At(number);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject.activeInHierarchy;
			}
			return false;
		}

		public static void Refresh(Inventory inventory)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			foreach (InventoryElement element in elements)
			{
				if (!((Object)(object)element == (Object)null) && element.m_used)
				{
					ItemData itemAt = inventory.GetItemAt(element.Position.x, element.Position.y);
					((Behaviour)element.m_amount).enabled = itemAt != null && itemAt.m_stack > 1;
					if (((Behaviour)element.m_amount).enabled)
					{
						element.m_amount.text = itemAt.m_stack.ToString();
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	public static class TackleClicks
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ref ItemData item, ref Vector2i pos)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance.m_dragGo == (Object)null || (Object)(object)grid != (Object)(object)__instance.m_playerGrid || !Tacklebox.Active)
			{
				return true;
			}
			Slot slot = InventoryState.SlotAt(grid.GetInventory(), pos);
			if (slot == null || slot.Kind != SlotKind.Tacklebox || !TackleRules.IsTackle(__instance.m_dragItem))
			{
				return true;
			}
			Vector2i val = Target(grid.GetInventory(), __instance.m_dragItem);
			if (val.x < 0)
			{
				Messages.Center(TackleboxWords.Full);
				return false;
			}
			pos = val;
			item = grid.GetInventory().GetItemAt(val.x, val.y);
			return true;
		}

		private static Vector2i Target(Inventory inventory, ItemData dragged)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle);
			Vector2i val = default(Vector2i);
			((Vector2i)(ref val))..ctor(-1, -1);
			foreach (Vector2i item in readOnlyList)
			{
				ItemData itemAt = inventory.GetItemAt(item.x, item.y);
				if (itemAt == null && val.x < 0)
				{
					val = item;
				}
				if (itemAt != null && itemAt != dragged && itemAt.IsSameType(dragged) && itemAt.m_quality == dragged.m_quality && itemAt.m_stack < itemAt.m_shared.m_maxStackSize)
				{
					return item;
				}
			}
			return val;
		}
	}
	public static class TackleGamepad
	{
		public static void Follow(bool open)
		{
			//IL_006a: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			InventoryGrid val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_playerGrid : null);
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle);
			IReadOnlyList<Vector2i> readOnlyList2 = InventoryState.CellsOf(SlotKind.Tacklebox);
			if ((Object)(object)val == (Object)null || readOnlyList.Count == 0 || readOnlyList2.Count == 0 || !InventoryState.Active || !ZInput.IsExclusiveGamepadActive())
			{
				return;
			}
			if (open)
			{
				KeyRingGamepad.Select(val, readOnlyList[0]);
				return;
			}
			Slot slot = InventoryState.Layout.SlotAt(val.m_selected);
			if (slot != null && slot.Kind == SlotKind.Tackle)
			{
				KeyRingGamepad.Select(val, readOnlyList2[0]);
			}
		}
	}
	public static class TacklePopup
	{
		public const string Name = "PackPanel_tacklebox";

		private static float slotLeft;

		private static float boxCentre;

		private static float top;

		private static float step = 70f;

		private static bool placed;

		private static bool fresh;

		public static RectTransform Find(InventoryGui gui)
		{
			if (!((Object)(object)gui != (Object)null))
			{
				return null;
			}
			Transform obj = ((Transform)gui.m_player).Find("PackPanel_tacklebox");
			return (RectTransform)(object)((obj is RectTransform) ? obj : null);
		}

		public static void Place(InventoryGui gui, RectTransform slotPanel, SlotPanelLayout plan, float gridStep)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			RectTransform val = Find(gui);
			placed = (Object)(object)slotPanel != (Object)null && (plan?.TackleboxCell.HasValue ?? false);
			fresh = true;
			if (!placed)
			{
				if (val != null)
				{
					((Component)val).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)val == (Object)null)
			{
				Make(gui);
			}
			step = gridStep;
			slotLeft = slotPanel.anchoredPosition.x;
			boxCentre = slotLeft + SlotPanel.CellPosition(plan.TackleboxCell.Value, step).x + 32f;
			top = slotPanel.anchoredPosition.y - slotPanel.sizeDelta.y - 12f;
		}

		public static void Refresh(InventoryGui gui)
		{
			RectTransform val = Find(gui);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			bool flag = placed && TackleState.Open && Tacklebox.Active && TackleCells.Count > 0;
			if (((Component)val).gameObject.activeSelf != flag)
			{
				((Component)val).gameObject.SetActive(flag);
			}
			if (flag)
			{
				if (fresh)
				{
					Arrange(val);
				}
				PopupPlace.Under(gui, val, slotLeft, boxCentre, top);
				TackleCells.Refresh(((Humanoid)InventoryState.Player).GetInventory());
			}
		}

		private static void Arrange(RectTransform popup)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			fresh = false;
			float num = step * 0.8f;
			float num2 = (step - 64f) * 0.8f;
			int num3 = Mathf.Min(4, TackleCells.Count);
			int num4 = (TackleCells.Count + 4 - 1) / 4;
			float pad = SlotPanel.Pad;
			popup.sizeDelta = new Vector2(pad * 2f + (float)num3 * num - num2, pad * 2f + (float)num4 * num - num2);
			GridSkin.Panel(((Component)popup).GetComponent<Image>());
			TackleCells.Arrange(pad, num);
		}

		private static void Make(InventoryGui gui)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = SlotPanel.MakePanel(gui, "PackPanel_tacklebox");
			obj.pivot = new Vector2(0f, 1f);
			GridSkin.Panel(((Component)obj).GetComponent<Image>());
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	public static class TackleRouting
	{
		[HarmonyPrefix]
		public static bool Prefix(Inventory __instance, ItemData item, ref bool __result, bool __runOriginal)
		{
			if (!__runOriginal)
			{
				return false;
			}
			if (item == null || !InventoryState.Manages(__instance) || !Tacklebox.Active || !TackleRules.IsTackle(item) || !TakeIn(__instance, item))
			{
				return true;
			}
			__result = true;
			return false;
		}

		public static bool TakeIn(Inventory inventory, ItemData item)
		{
			//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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle);
			foreach (Vector2i item2 in readOnlyList)
			{
				if (Stack(inventory, item, item2))
				{
					return true;
				}
			}
			foreach (Vector2i item3 in readOnlyList)
			{
				if (inventory.GetItemAt(item3.x, item3.y) == null)
				{
					Place(inventory, item, item3);
					return true;
				}
			}
			return false;
		}

		private static bool Stack(Inventory inventory, ItemData item, Vector2i cell)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			ItemData itemAt = inventory.GetItemAt(cell.x, cell.y);
			if (itemAt == null || itemAt == item || !itemAt.IsSameType(item) || itemAt.m_quality != item.m_quality)
			{
				return false;
			}
			int num = Math.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, item.m_stack);
			if (num <= 0)
			{
				return false;
			}
			itemAt.m_stack += num;
			item.m_stack -= num;
			inventory.Changed(false, false);
			return item.m_stack <= 0;
		}

		private static void Place(Inventory inventory, ItemData item, Vector2i cell)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			item.m_gridPos = cell;
			if (!inventory.ContainsItem(item))
			{
				inventory.m_inventory.Add(item);
			}
			inventory.Changed(false, false);
		}
	}
	public static class TackleRules
	{
		private const string Rod = "FishingRod";

		private static string baitType;

		private static string parsed;

		private static HashSet<string> listed = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		public static bool IsTackle(ItemData item)
		{
			if (item != null)
			{
				if (!IsBait(item))
				{
					if (IsListed(item) && !SlotRules.IsCoins(item))
					{
						return !KeyRing.IsKey(item);
					}
					return false;
				}
				return true;
			}
			return false;
		}

		public static bool IsBait(ItemData item)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if (item == null || (int)item.m_shared.m_itemType != 23)
			{
				return false;
			}
			string text = BaitType();
			if (text != null)
			{
				return item.m_shared.m_ammoType == text;
			}
			return true;
		}

		private static string BaitType()
		{
			if (baitType == null && (Object)(object)ObjectDB.instance != (Object)null)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("FishingRod");
				ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				string text = (((Object)(object)val != (Object)null) ? val.m_itemData.m_shared.m_ammoType : null);
				baitType = (string.IsNullOrEmpty(text) ? null : text);
			}
			return baitType;
		}

		private static bool IsListed(ItemData item)
		{
			string text = TackleboxSettings.TackleItems.Value ?? "";
			if (text != parsed)
			{
				Parse(text);
			}
			if (listed.Count > 0)
			{
				return listed.Contains(ItemNames.PrefabName(item));
			}
			return false;
		}

		private static void Parse(string value)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = value.Split(new char[1] { ',' });
			foreach (string text in array)
			{
				if (text.Trim().Length > 0)
				{
					hashSet.Add(text.Trim());
				}
			}
			listed = hashSet;
			parsed = value;
		}
	}
	public static class TackleState
	{
		[HarmonyPatch(typeof(InventoryGui), "Show")]
		public static class Shown
		{
			[HarmonyPostfix]
			public static void Postfix()
			{
				Close();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		public static class Hidden
		{
			[HarmonyPostfix]
			public static void Postfix()
			{
				Close();
			}
		}

		public static bool Open { get; private set; }

		public static void Toggle()
		{
			Open = !Open;
			if (Open)
			{
				KeyRingState.Close();
			}
			TackleGamepad.Follow(Open);
		}

		public static void Close()
		{
			if (Open)
			{
				Open = false;
				TackleGamepad.Follow(open: false);
			}
		}
	}
}
namespace PackPanel.Slots
{
	[HarmonyPatch(typeof(Inventory), "GetAmmoItem")]
	public static class AmmoSearch
	{
		[HarmonyPrefix]
		public static bool Prefix(Inventory __instance, string ammoName, string matchPrefabName, ref ItemData __result)
		{
			if (!InventoryState.Manages(__instance))
			{
				return true;
			}
			ItemData val = (Tacklebox.Active ? First(__instance, InventoryState.CellsOf(SlotKind.Tackle), ammoName, matchPrefabName) : null);
			val = val ?? First(__instance, InventoryState.CellsOf(SlotKind.Ammo), ammoName, matchPrefabName);
			if (val == null)
			{
				return true;
			}
			__result = val;
			return false;
		}

		private static ItemData First(Inventory inventory, IReadOnlyList<Vector2i> cells, string ammoName, string prefab)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			foreach (Vector2i cell in cells)
			{
				ItemData itemAt = inventory.GetItemAt(cell.x, cell.y);
				if (itemAt != null && Fits(itemAt, ammoName, prefab))
				{
					return itemAt;
				}
			}
			return null;
		}

		private static bool Fits(ItemData item, string ammoName, string prefab)
		{
			//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_000f: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			ItemType itemType = item.m_shared.m_itemType;
			if (((int)itemType == 9 || (int)itemType == 23 || (int)itemType == 2) && item.m_shared.m_ammoType == ammoName)
			{
				if (prefab != null)
				{
					if ((Object)(object)item.m_dropPrefab != (Object)null)
					{
						return ((Object)item.m_dropPrefab).name == prefab;
					}
					return false;
				}
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	public static class CoinPurse
	{
		[HarmonyPrefix]
		public static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (item == null || !InventoryState.Manages(__instance) || !SlotRules.IsCoins(item) || !TakeIn(__instance, item))
			{
				return true;
			}
			__result = true;
			return false;
		}

		private static bool TakeIn(Inventory inventory, ItemData item)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Purse);
			if (readOnlyList.Count == 0)
			{
				return false;
			}
			ItemData itemAt = inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y);
			if (itemAt == null)
			{
				item.m_gridPos = readOnlyList[0];
				inventory.m_inventory.Add(item);
				inventory.Changed(false, false);
				return true;
			}
			if (!SlotRules.IsCoins(itemAt) || itemAt.m_quality != item.m_quality || itemAt.m_worldLevel != item.m_worldLevel)
			{
				return false;
			}
			int num = Math.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, item.m_stack);
			if (num <= 0)
			{
				return false;
			}
			itemAt.m_stack += num;
			item.m_stack -= num;
			inventory.Changed(false, false);
			return item.m_stack <= 0;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	public static class DragSettle
	{
		public sealed class Pair
		{
			public ItemData Dragged;

			public ItemData Target;
		}

		[HarmonyPrefix]
		public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, out Pair __state, bool __runOriginal)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (!__runOriginal)
			{
				return false;
			}
			bool flag = (Object)(object)__instance.m_dragGo != (Object)null;
			if (flag && !SlotDrop.Allowed(grid.GetInventory(), __instance.m_dragInventory, __instance.m_dragItem, __instance.m_dragAmount, pos))
			{
				Messages.Center(Words.WrongSlot);
				return false;
			}
			if (!InventoryState.Active)
			{
				return true;
			}
			WornPlacement.Suspend();
			__state = new Pair
			{
				Dragged = (flag ? __instance.m_dragItem : null),
				Target = item
			};
			return true;
		}

		[HarmonyPostfix]
		public static void Postfix(Pair __state)
		{
			if (__state != null)
			{
				WornPlacement.Resume();
				Settle(__state.Dragged);
				Settle(__state.Target);
			}
		}

		[HarmonyFinalizer]
		public static void Finalizer(Pair __state, Exception __exception)
		{
			if (__state != null && __exception != null)
			{
				WornPlacement.Resume();
			}
		}

		private static void Settle(ItemData item)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Player player = InventoryState.Player;
			if (item == null || !InventoryState.Active || !((Humanoid)player).GetInventory().ContainsItem(item))
			{
				return;
			}
			Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos);
			SlotKind? slotKind = SlotRules.WornKindOf(item);
			if (slot != null && SlotRules.IsWorn(slot.Kind))
			{
				if (!item.m_equipped && slotKind == slot.Kind)
				{
					((Humanoid)player).EquipItem(item, true);
				}
			}
			else if (item.m_equipped && slotKind.HasValue && InventoryState.CellsOf(slotKind.Value).Count > 0)
			{
				((Humanoid)player).UnequipItem(item, true);
			}
		}
	}
	public static class FoodCount
	{
		public const int GameFoods = 3;

		private const string FeastMasterGuid = "com.FeastMaster";

		private const string FeastMasterSection = "0. Global Settings";

		private const string FeastMasterKey = "Food Slots";

		private static ConfigEntry<int> feastMaster;

		private static bool looked;

		public static event Action Changed;

		public static int Slots()
		{
			int val = (InventorySettings.FoodSlotsFollowEating.Value ? Eatable() : InventorySettings.FoodSlots.Value);
			return Math.Max(0, Math.Min(5, val));
		}

		public static int Eatable()
		{
			return FeastMasterEntry()?.Value ?? 3;
		}

		private static ConfigEntry<int> FeastMasterEntry()
		{
			if (looked)
			{
				return feastMaster;
			}
			looked = true;
			if (!Chainloader.PluginInfos.TryGetValue("com.FeastMaster", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return null;
			}
			if (!value.Instance.Config.TryGetEntry<int>("0. Global Settings", "Food Slots", ref feastMaster))
			{
				Plugin.Log.LogWarning((object)string.Format("FeastMaster is loaded but has no {0} / {1}; food slots follow the game's {2} foods", "0. Global Settings", "Food Slots", 3));
				return null;
			}
			feastMaster.SettingChanged += delegate
			{
				FoodCount.Changed?.Invoke();
			};
			Plugin.Log.LogInfo((object)$"food slots follow FeastMaster's Food Slots ({feastMaster.Value})");
			return feastMaster;
		}
	}
	public static class GravePatches
	{
		[HarmonyPatch(typeof(Player), "CreateTombStone")]
		public static class Tombstone
		{
			public sealed class Death
			{
				public KeptOnDeath Kept;
			}

			[HarmonyPrefix]
			public static void Prefix(Player __instance, out Death __state)
			{
				__state = (InventoryState.IsLocal((Humanoid)(object)__instance) ? new Death() : null);
				if (__state != null)
				{
					WornPlacement.Suspend();
					__state.Kept = KeptOnDeath.Take(__instance);
				}
			}

			[HarmonyFinalizer]
			public static void Finalizer(Player __instance, Death __state)
			{
				if (__state != null)
				{
					__state.Kept?.Return(__instance);
					WornPlacement.Resume();
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "MoveAll")]
		public static class TakeAll
		{
			[HarmonyPrefix]
			public static void Prefix(Inventory __instance, Inventory fromInventory, out bool __state)
			{
				__state = InventoryState.Manages(__instance) && IsGrave(fromInventory);
				ForeignTakeAll = InventoryState.Manages(__instance) && !__state;
				if (__state)
				{
					BackpackGrave.WearFirst(__instance, fromInventory);
					TackleboxGrave.PutBackFirst(__instance, fromInventory);
				}
			}

			[HarmonyPostfix]
			public static void Postfix(Inventory __instance, bool __state)
			{
				if (__state)
				{
					WearWhatCameBack(__instance);
				}
			}

			[HarmonyFinalizer]
			public static void Finalizer()
			{
				ForeignTakeAll = false;
			}
		}

		public static bool ForeignTakeAll { get; private set; }

		private static bool IsGrave(Inventory inventory)
		{
			TombStone[] array = Object.FindObjectsByType<TombStone>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				Container component = ((Component)array[i]).GetComponent<Container>();
				if ((Object)(object)component != (Object)null && component.GetInventory() == inventory)
				{
					return true;
				}
			}
			return false;
		}

		private static void WearWhatCameBack(Inventory inventory)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
			{
				Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos);
				if (slot != null && SlotRules.IsWorn(slot.Kind) && !item.m_equipped && SlotRules.WornKindOf(item) == slot.Kind)
				{
					((Humanoid)InventoryState.Player).EquipItem(item, false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Container), "Load")]
	public static class GraveWidth
	{
		private const int LoadWidth = 32;

		[HarmonyPrefix]
		public static void Prefix(Container __instance, out bool __state)
		{
			__state = __instance.m_inventory != null && (Object)(object)((Component)__instance).GetComponent<TombStone>() != (Object)null;
			if (__state)
			{
				__instance.m_inventory.m_width = 32;
			}
		}

		[HarmonyPostfix]
		public static void Postfix(Container __instance, bool __state)
		{
			if (!__state)
			{
				return;
			}
			int num = __instance.m_width;
			foreach (ItemData allItem in __instance.m_inventory.GetAllItems())
			{
				num = Math.Max(num, allItem.m_gridPos.x + 1);
			}
			__instance.m_inventory.m_width = num;
		}
	}
	public sealed class KeptOnDeath
	{
		private readonly List<ItemData> items = new List<ItemData>();

		private readonly HashSet<ItemData> worn = new HashSet<ItemData>();

		public static KeptOnDeath Take(Player player)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!InventorySettings.KeepSlotsOnDeath.Value || !InventoryState.Active)
			{
				return null;
			}
			KeptOnDeath keptOnDeath = new KeptOnDeath();
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
			{
				Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos);
				if (slot != null && Kept(slot.Kind))
				{
					keptOnDeath.items.Add(item);
					if (item.m_equipped)
					{
						keptOnDeath.worn.Add(item);
					}
					inventory.m_inventory.Remove(item);
				}
			}
			if (keptOnDeath.items.Count <= 0)
			{
				return null;
			}
			return keptOnDeath;
		}

		private static bool Kept(SlotKind kind)
		{
			if (kind != SlotKind.Purse && kind != SlotKind.Key && kind != SlotKind.Tackle)
			{
				return kind != SlotKind.Retired;
			}
			return false;
		}

		public void Return(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (ItemData item in items)
			{
				item.m_equipped = worn.Contains(item);
				if (!inventory.ContainsItem(item))
				{
					inventory.m_inventory.Add(item);
				}
			}
			inventory.Changed(false, false);
			Plugin.Log.LogInfo((object)$"kept {items.Count} slot items through death ({worn.Count} worn)");
		}
	}
	public sealed class Slot
	{
		public SlotKind Kind { get; }

		public int Number { get; }

		public string Id { get; }

		public Slot(SlotKind kind, int number)
		{
			Kind = kind;
			Number = number;
			Id = kind.ToString().ToLowerInvariant() + number;
		}

		public Slot(string id)
		{
			Kind = SlotKind.Retired;
			Number = 0;
			Id = id;
		}

		public override string ToString()
		{
			return Id;
		}
	}
	public static class SlotAddPatches
	{
		[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
		public static class Drop
		{
			[HarmonyPrefix]
			[HarmonyPriority(600)]
			public static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				if (SlotDrop.Allowed(__instance.GetInventory(), fromInventory, item, amount, pos))
				{
					return true;
				}
				Messages.Center(Words.WrongSlot);
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(ItemData),
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(bool)
		})]
		public static class AtCell
		{
			[HarmonyPrefix]
			public static bool Prefix(Inventory __instance, ItemData item, int x, int y, bool skipValidPositionCheck, ref bool __result)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				if (skipValidPositionCheck || !InventoryState.Manages(__instance))
				{
					return true;
				}
				Vector2i pos = default(Vector2i);
				((Vector2i)(ref pos))..ctor(x, y);
				if (InventoryState.Layout.IsMain(pos) || (!GravePatches.ForeignTakeAll && SlotDrop.Takes(__instance, pos, item)))
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(ItemData),
			typeof(Vector2i)
		})]
		public static class AtPosition
		{
			[HarmonyPrefix]
			public static bool Prefix(Inventory __instance, ItemData item, Vector2i pos, ref bool __result)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				if (SlotDrop.Takes(__instance, pos, item))
				{
					return true;
				}
				__result = __instance.AddItem(item);
				return false;
			}
		}
	}
	public static class SlotCounts
	{
		public static int Utility => Group(InventorySettings.UtilitySlots.Value);

		public static int Food
		{
			get
			{
				if (!Shared)
				{
					return FoodCount.Slots();
				}
				return Group(0);
			}
		}

		public static int Mead => Group(InventorySettings.MeadSlots.Value);

		public static int Ammo => Group(InventorySettings.AmmoSlots.Value);

		public static bool Shared => InventorySettings.SlotsPerGroup.Value > 0;

		private static int Group(int own)
		{
			int val = (Shared ? InventorySettings.SlotsPerGroup.Value : own);
			return Math.Max(0, Math.Min(5, val));
		}
	}
	public static class SlotDrop
	{
		public static bool Allowed(Inventory target, Inventory from, ItemData item, int amount, Vector2i pos)
		{
			//IL_0009: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (target == null || item == null)
			{
				return true;
			}
			ItemData itemAt = target.GetItemAt(pos.x, pos.y);
			if (itemAt == item)
			{
				return true;
			}
			if (!Takes(target, pos, item))
			{
				return false;
			}
			if (itemAt != null && Swaps(itemAt, item, amount))
			{
				return Takes(from, item.m_gridPos, itemAt);
			}
			return true;
		}

		public static bool Takes(Inventory inventory, Vector2i pos, ItemData item)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (!InventoryState.Manages(inventory) || InventoryState.Layout.IsMain(pos))
			{
				return true;
			}
			Slot slot = InventoryState.Layout.SlotAt(pos);
			if (slot != null)
			{
				return SlotRules.Accepts(slot, item);
			}
			return false;
		}

		private static bool Swaps(ItemData at, ItemData item, int amount)
		{
			if (at.m_shared.m_name != item.m_shared.m_name || (item.m_shared.m_maxQuality > 1 && at.m_quality != item.m_quality) || at.m_shared.m_maxStackSize == 1)
			{
				return item.m_stack == amount;
			}
			return false;
		}
	}
	public enum SlotKind
	{
		Head,
		Chest,
		Legs,
		Back,
		Backpack,
		Utility,
		Food,
		Mead,
		Ammo,
		Purse,
		Retired,
		Key,
		Tacklebox,
		Tackle
	}
	public static class SlotRules
	{
		public const string CoinsName = "$item_coins";

		public static bool IsWorn(SlotKind kind)
		{
			if (kind > SlotKind.Back)
			{
				return kind == SlotKind.Utility;
			}
			return true;
		}

		public static bool Accepts(Slot slot, ItemData item)
		{
			if (slot.Kind != SlotKind.Key)
			{
				return Accepts(slot.Kind, item);
			}
			if (item != null)
			{
				return KeyRing.NumberOf(item) == slot.Number;
			}
			return true;
		}

		public static bool Accepts(SlotKind kind, ItemData item)
		{
			if (item == null)
			{
				return true;
			}
			switch (kind)
			{
			case SlotKind.Backpack:
				return IsBackpack(item);
			case SlotKind.Food:
				return IsFood(item);
			case SlotKind.Mead:
				if (Is(item, (ItemType)2))
				{
					return !IsFood(item);
				}
				return false;
			case SlotKind.Ammo:
				if (!Is(item, (ItemType)9))
				{
					return Is(item, (ItemType)23);
				}
				return true;
			case SlotKind.Purse:
				return IsCoins(item);
			case SlotKind.Key:
				return KeyRing.IsKey(item);
			case SlotKind.Tacklebox:
				return TackleboxCatalog.Of(item) != null;
			case SlotKind.Tackle:
				return TackleRules.IsTackle(item);
			case SlotKind.Retired:
				return false;
			default:
				return WornKindOf(item) == kind;
			}
		}

		public static SlotKind? WornKindOf(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType <= 7)
			{
				if ((int)itemType == 6)
				{
					return SlotKind.Head;
				}
				if ((int)itemType == 7)
				{
					return SlotKind.Chest;
				}
			}
			else
			{
				if ((int)itemType == 11)
				{
					return SlotKind.Legs;
				}
				if ((int)itemType == 17)
				{
					return SlotKind.Back;
				}
				if ((int)itemType == 18)
				{
					return SlotKind.Utility;
				}
			}
			return null;
		}

		public static bool IsCoins(ItemData item)
		{
			return item.m_shared.m_name == "$item_coins";
		}

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

		public static bool IsBackpack(ItemData item)
		{
			if (BackpackCatalog.Of(item) != null)
			{
				return true;
			}
			string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : "");
			if (text.IndexOf("backpack", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			string[] array = InventorySettings.BackpackItems.Value.Split(new char[1] { ',' });
			foreach (string text2 in array)
			{
				if (text2.Trim().Length > 0 && string.Equals(text2.Trim(), text, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static bool Is(ItemData item, ItemType type)
		{
			//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)
			return item.m_shared.m_itemType == type;
		}
	}
	[HarmonyPatch(typeof(Inventory), "StackAll")]
	public static class StackAllGuard
	{
		[HarmonyPrefix]
		public static void Prefix(Inventory fromInventory, out List<ItemData> __state)
		{
			__state = (InventoryState.Manages(fromInventory) ? UnwornSlotItems(fromInventory) : null);
			if (__state == null)
			{
				return;
			}
			foreach (ItemData item in __state)
			{
				fromInventory.m_inventory.Remove(item);
			}
		}

		[HarmonyFinalizer]
		public static void Finalizer(Inventory fromInventory, List<ItemData> __state)
		{
			if (__state == null || __state.Count == 0)
			{
				return;
			}
			foreach (ItemData item in __state)
			{
				if (!fromInventory.ContainsItem(item))
				{
					fromInventory.m_inventory.Add(item);
				}
			}
			fromInventory.Changed(false, false);
		}

		public static bool InSlot(Inventory inventory, ItemData item)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (item != null)
			{
				return InventoryState.SlotAt(inventory, item.m_gridPos) != null;
			}
			return false;
		}

		private static List<ItemData> UnwornSlotItems(Inventory inventory)
		{
			List<ItemData> list = new List<ItemData>();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (InSlot(inventory, allItem) && !allItem.m_equipped)
				{
					list.Add(allItem);
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(Inventory), "MoveAll")]
	public static class TakeAllRouting
	{
		[HarmonyPrefix]
		public static void Prefix(Inventory __instance, out HashSet<ItemData> __state)
		{
			bool flag = InventoryState.Manages(__instance) && (KeyRing.Active || Tacklebox.Active);
			__state = (flag ? new HashSet<ItemData>(__instance.GetAllItems()) : null);
		}

		[HarmonyPostfix]
		public static void Postfix(Inventory __instance, HashSet<ItemData> __state)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (__state == null)
			{
				return;
			}
			foreach (ItemData item in new List<ItemData>(__instance.GetAllItems()))
			{
				if (!__state.Contains(item) && InventoryState.Layout.IsMain(item.m_gridPos) && Route(__instance, item) && item.m_stack <= 0)
				{
					__instance.RemoveItem(item);
				}
			}
		}

		private static bool Route(Inventory inventory, ItemData item)
		{
			if (KeyRing.IsKey(item))
			{
				return KeyRouting.TakeIn(inventory, item);
			}
			if (Tacklebox.Active && TackleRules.IsTackle(item))
			{
				return TackleRouting.TakeIn(inventory, item);
			}
			return false;
		}
	}
}
namespace PackPanel.Ring
{
	public static class KeyRing
	{
		private static string parsed;

		private static List<string> prefabs = new List<string>();

		private static string[] sharedNames;

		public static bool On
		{
			get
			{
				if (InventorySettings.Enabled.Value)
				{
					return KeyRingSettings.KeyRing.Value;
				}
				return false;
			}
		}

		public static bool Active
		{
			get
			{
				if (InventoryState.Active)
				{
					return InventoryState.CellsOf(SlotKind.Key).Count > 0;
				}
				return false;
			}
		}

		public static IReadOnlyList<string> Prefabs
		{
			get
			{
				Parse();
				return prefabs;
			}
		}

		public static int NumberOf(string prefab)
		{
			IReadOnlyList<string> readOnlyList = Prefabs;
			for (int i = 0; i < readOnlyList.Count; i++)
			{
				if (string.Equals(readOnlyList[i], prefab, StringComparison.OrdinalIgnoreCase))
				{
					return i + 1;
				}
			}
			return 0;
		}

		public static int NumberOf(ItemData item)
		{
			if (item == null)
			{
				return 0;
			}
			return NumberOf(ItemNames.PrefabName(item));
		}

		public static bool IsKey(ItemData item)
		{
			return NumberOf(item) > 0;
		}

		public static Vector2i CellOf(InventoryLayout layout, ItemData item)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			int num = NumberOf(item);
			IReadOnlyList<Vector2i> readOnlyList = layout?.CellsOf(SlotKind.Key);
			if (num <= 0 || readOnlyList == null || num > readOnlyList.Count)
			{
				return new Vector2i(-1, -1);
			}
			return readOnlyList[num - 1];
		}

		public static Vector2i CellOf(ItemData item)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (!InventoryState.Active)
			{
				return new Vector2i(-1, -1);
			}
			return CellOf(InventoryState.Layout, item);
		}

		public static ItemData Key(int number)
		{
			IReadOnlyList<string> readOnlyList = Prefabs;
			GameObject val = ((number >= 1 && number <= readOnlyList.Count && (Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(readOnlyList[number - 1]) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val2 != (Object)null))
			{
				return null;
			}
			return val2.m_itemData;
		}

		public static int[] Counts(Inventory inventory)
		{
			int[] array = new int[Prefabs.Count + 1];
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				for (int i = 1; i < array.Length; i++)
				{
					if (allItem.m_shared.m_name == SharedName(i))
					{
						array[i] += allItem.m_stack;
					}
				}
			}
			return array;
		}

		private static string SharedName(int number)
		{
			if (sharedNames == null || sharedNames.Length != Prefabs.Count)
			{
				sharedNames = new string[Prefabs.Count];
			}
			if (sharedNames[number - 1] == null)
			{
				sharedNames[number - 1] = Key(number)?.m_shared.m_name;
			}
			return sharedNames[number - 1];
		}

		private static void Parse()
		{
			string text = KeyRingSettings.KeyItems.Value ?? "";
			if (text == parsed)
			{
				return;
			}
			sharedNames = null;
			List<string> list = new List<string>();
			string[] array = text.Split(new char[1] { ',' });
			foreach (string text2 in array)
			{
				string name = text2.Trim();
				if (name.Length > 0 && !list.Exists((string known) => string.Equals(known, name, StringComparison.OrdinalIgnoreCase)))
				{
					list.Add(name);
				}
			}
			prefabs = list;
			parsed = text;
		}
	}
	public static class KeyRingButton
	{
		public const string Name = "PackPanel_keyring_button";

		private static InventoryElement button;

		private static string shownList;

		public static void Place(InventoryGui gui, RectTransform panel, SlotPanelLayout plan, float step, TMP_FontAsset font)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0096: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)panel != (Object)null) ? ((Transform)panel).Find("PackPanel_keyring_button") : null);
			if ((Object)(object)panel == (Object)null || plan == null || !plan.RingCell.HasValue)
			{
				if (val != null)
				{
					((Component)val).gameObject.SetActive(false);
				}
				button = null;
				return;
			}
			button = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<InventoryElement>() : Make(gui, panel));
			RectTransform val2 = (RectTransform)((Component)button).transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 1f);
			val2.pivot = val3;
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			val2.anchoredPosition = SlotPanel.CellPosition(plan.RingCell.Value, step);
			((Component)button).gameObject.SetActive(true);
			GridSkin.Cell(button);
			SlotLabels.Set(button, new Slot(SlotKind.Key, 0), font);
			shownList = null;
		}

		public static void Refresh(InventoryGui gui)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)button == (Object)null) && ((Component)button).gameObject.activeInHierarchy && KeyRing.Active)
			{
				((Behaviour)button.m_icon).enabled = !InventorySettings.SlotLabels.Value;
				button.m_icon.sprite = SlotIcons.For(SlotKind.Key);
				((Graphic)button.m_icon).color = SlotIcons.Hint;
				int[] array = KeyRing.Counts(((Humanoid)InventoryState.Player).GetInventory());
				int num = 0;
				for (int i = 1; i < array.Length; i++)
				{
					num += ((array[i] > 0) ? 1 : 0);
				}
				((Behaviour)button.m_quality).enabled = num > 0;
				button.m_quality.text = num.ToString();
				ShowList(gui, array);
				button.m_selected.SetActive(KeyRingGamepad.OnButton(gui));
				KeyRingNotice.Show(button);
			}
		}

		private static void ShowList(InventoryGui gui, int[] counts)
		{
			//IL_00b7: 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)
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 1; i < counts.Length; i++)
			{
				ItemData val = ((counts[i] > 0) ? KeyRing.Key(i) : null);
				if (val != null)
				{
					stringBuilder.Append((stringBuilder.Length > 0) ? "\n" : "").Append(val.m_shared.m_name).Append(": <color=orange>")
						.Append(counts[i])
						.Append("</color>");
				}
			}
			string text = ((stringBuilder.Length > 0) ? stringBuilder.ToString() : Words.NoKeysHeld);
			if (!(text == shownList))
			{
				shownList = text;
				button.m_tooltip.Set(Words.KeyRing, text, gui.m_playerGrid.m_tooltipAnchor, default(Vector2));
			}
		}

		private static InventoryElement Make(InventoryGui gui, RectTransform panel)
		{
			GameObject obj = Object.Instantiate<GameObject>(gui.m_playerGrid.m_elementPrefab, (Transform)(object)panel);
			((Object)obj).name = "PackPanel_keyring_button";
			InventoryElement component = obj.GetComponent<InventoryElement>();
			component.Initialize(-1, -1);
			Blank(component);
			UIInputHandler componentInChildren = obj.GetComponentInChildren<UIInputHandler>();
			componentInChildren.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(componentInChildren.m_onLeftDown, (Action<UIInputHandler>)delegate
			{
				KeyRingClicks.OnButton(InventoryGui.instance);
			});
			return component;
		}

		private static void Blank(InventoryElement element)
		{
			((Behaviour)element.m_amount).enabled = false;
			((Behaviour)element.m_quality).enabled = false;
			((Behaviour)element.m_equiped).enabled = false;
			((Behaviour)element.m_queued).enabled = false;
			((Behaviour)element.m_noteleport).enabled = false;
			((Behaviour)element.m_food).enabled = false;
			((Component)element.m_durability).gameObject.SetActive(false);
			element.m_selected.SetActive(false);
			Transform val = ((Component)element).transform.Find("binding");
			TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TMP_Text>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				((Behaviour)val2).enabled = false;
			}
		}
	}
	public static class KeyRingCells
	{
		private static readonly List<InventoryElement> elements = new List<InventoryElement>();

		public static int Count => elements.Count;

		public static InventoryElement At(int number)
		{
			if (number < 1 || number > elements.Count)
			{
				return null;
			}
			return elements[number - 1];
		}

		public static void Clear()
		{
			elements.Clear();
		}

		public static bool Adopt(InventoryGui gui, InventoryElement element, Slot slot)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = KeyRingPopup.Find(gui);
			if ((Object)(object)val == (Object)null || slot.Number < 1)
			{
				return false;
			}
			while (elements.Count < slot.Number)
			{
				elements.Add(null);
			}
			elements[slot.Number - 1] = element;
			RectTransform val2 = (RectTransform)((Component)element).transform;
			((Transform)val2).SetParent((Transform)(object)val, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.pivot = val3;
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			((Transform)val2).localScale = Vector3.one * 0.65f;
			Image component = ((Component)element).GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				((Graphic)component).color = Color.white;
			}
			return true;
		}

		public static void Found(List<int> found)
		{
			found.Clear();
			for (int i = 1; i <= elements.Count; i++)
			{
				if ((Object)(object)elements[i - 1] != (Object)null && elements[i - 1].m_used)
				{
					found.Add(i);
				}
			}
		}

		public static bool Shows(int number)
		{
			InventoryElement val = At(number);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject.activeInHierarchy;
			}
			return false;
		}

		public static void Refresh(Inventory inventory)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			foreach (InventoryElement element in elements)
			{
				if (!((Object)(object)element == (Object)null) && element.m_used && ((Component)element).gameObject.activeSelf)
				{
					ItemData itemAt = inventory.GetItemAt(element.Position.x, element.Position.y);
					((Behaviour)element.m_amount).enabled = itemAt != null && itemAt.m_stack > 1;
					if (((Behaviour)element.m_amount).enabled)
					{
						element.m_amount.text = itemAt.m_stack.ToString();
					}
				}
			}
		}
	}
	public static class KeyRingCircle
	{
		public const float CellScale = 0.65f;

		private const float Spread = 1.12f;

		private const float MinRadius = 0.95f;

		private const float Frame = 10f;

		public const float WireScale = 2.077f;

		public static float Radius(int count, float step)
		{
			float num = 0.95f * step;
			if (count >= 2)
			{
				return Mathf.Max(num, 1.12f * step / (2f * Mathf.Sin((float)Math.PI / (float)count)));
			}
			return num;
		}

		public static Vector2 Position(int index, int count, float radius)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)Math.PI / 2f - (float)Math.PI * 2f * (float)index / (float)Mathf.Max(1, count);
			return new Vector2(Mathf.Cos(num), Mathf.Sin(num)) * radius;
		}

		public static float Diameter(float radius, float cell)
		{
			return 2f * (radius + cell * 0.7072f + 10f);
		}
	}
	public static class KeyRingClicks
	{
		[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
		public static class Selected
		{
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ref ItemData item, ref Vector2i pos)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				if (RingSlot(__instance, grid, pos) == null)
				{
					return true;
				}
				if ((Object)(object)__instance.m_dragGo != (Object)null)
				{
					ToOwnCell(__instance, grid, ref item, ref pos);
					return true;
				}
				if (KeyRingState.Open)
				{
					return true;
				}
				KeyRingState.Toggle();
				return false;
			}

			private static void ToOwnCell(InventoryGui gui, InventoryGrid grid, ref ItemData item, ref Vector2i pos)
			{
				//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_0015: 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_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				Vector2i val = KeyRing.CellOf(gui.m_dragItem);
				if (val.x >= 0 && !(val == pos))
				{
					pos = val;
					item = grid.GetInventory().GetItemAt(val.x, val.y);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")]
		public static class RightClick
		{
			[HarmonyPrefix]
			public static bool Prefix(InventoryGui __instance, InventoryGrid grid, Vector2i pos)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				if (RingSlot(__instance, grid, pos) == null || KeyRingState.Open)
				{
					return true;
				}
				KeyRingState.Toggle();
				return false;
			}
		}

		public static void OnButton(InventoryGui gui)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gui == (Object)null || !KeyRing.Active)
			{
				return;
			}
			if ((Object)(object)gui.m_dragGo == (Object)null)
			{
				KeyRingState.Toggle();
				return;
			}
			Vector2i val = KeyRing.CellOf(gui.m_dragItem);
			if (val.x < 0)
			{
				Messages.Center(Words.NotAKey);
				return;
			}
			ItemData itemAt = ((Humanoid)InventoryState.Player).GetInventory().GetItemAt(val.x, val.y);
			gui.OnSelectedItem(gui.m_playerGrid, itemAt, val, (Modifier)0);
		}

		private static Slot RingSlot(InventoryGui gui, InventoryGrid grid, Vector2i pos)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Slot slot = (((Object)(object)grid == (Object)(object)gui.m_playerGrid) ? InventoryState.SlotAt(grid.GetInventory(), pos) : null);
			if (slot == null || slot.Kind != SlotKind.Key)
			{
				return null;
			}
			return slot;
		}
	}
	public static class KeyRingGamepad
	{
		[HarmonyPatch(typeof(InventoryGrid), "UpdateGamepad")]
		public static class Move
		{
			[HarmonyPrefix]
			public static void Prefix(InventoryGrid __instance, out Vector2i __state)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				__state = __instance.m_selected;
			}

			[HarmonyPostfix]
			public static void Postfix(InventoryGrid __instance, Vector2i __state)
			{
				//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_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: 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_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				if (!(__instance.m_selected == __state) && IsPlayerGrid(__instance))
				{
					Vector2i val = Settle(__instance, __state, __instance.m_selected);
					if (val != __instance.m_selected)
					{
						Select(__instance, val);
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Update")]
		public static class Back
		{
			[HarmonyPrefix]
			public static void Prefix(InventoryGui __instance)
			{
				if ((KeyRingState.Open || TackleState.Open) && ZInput.IsExclusiveGamepadActive() && InventoryGui.IsVisible() && NoDialog(__instance) && ZInput.GetButtonDown("JoyButtonB"))
				{
					ZInput.ResetButtonStatus("JoyButtonB");
					KeyRingState.Close();
					TackleState.Close();
				}
			}
		}

		private static readonly List<int> found = new List<int>();

		public static bool OnButton(InventoryGui gui)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			InventoryGrid playerGrid = gui.m_playerGrid;
			if (!playerGrid.m_uiGroup.IsActive || !ZInput.IsExclusiveGamepadActive())
			{
				return false;
			}
			Slot slot = InventoryState.Layout.SlotAt(playerGrid.m_selected);
			if (slot != null && slot.Kind == SlotKind.Key)
			{
				if (KeyRingState.Open)
				{
					return !KeyRingCells.Shows(slot.Number);
				}
				return true;
			}
			return false;
		}

		public static void Follow(bool open)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			InventoryGrid val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_playerGrid : null);
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Key);
			if ((Object)(object)val == (Object)null || readOnlyList.Count == 0 || !KeyRing.Active || !ZInput.IsExclusiveGamepadActive())
			{
				return;
			}
			Slot slot = InventoryState.Layout.SlotAt(val.m_selected);
			if (!open && slot != null && slot.Kind == SlotKind.Key)
			{
				Select(val, readOnlyList[0]);
			}
			if (open)
			{
				KeyRingCells.Found(found);
				if (found.Count > 0)
				{
					Select(val, readOnlyList[found[0] - 1]);
				}
			}
		}

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

		private static Vector2i Settle(InventoryGrid grid, Vector2i before, Vector2i landed)
		{
			//IL_0000: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			int num = Math.Sign(landed.x - before.x);
			int num2 = Math.Sign(landed.y - before.y);
			Inventory inventory = grid.GetInventory();
			Vector2i val = landed;
			while (val.x >= 0 && val.y >= 0 && val.x < inventory.GetWidth() && val.y < inventory.GetHeight())
			{
				Vector2i val2 = StandIn(val);
				if (Shows(val2))
				{
					return val2;
				}
				((Vector2i)(ref val))..ctor(val.x + num, val.y + num2);
			}
			return before;
		}

		private static Vect