Decompiled source of PackPanel v0.17.2

plugins\PackPanel.dll

Decompiled a week 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 EliteCraftingLink;
using HarmonyLib;
using Hotkeys;
using ItemCopies;
using MagicaCloth2;
using Microsoft.CodeAnalysis;
using PackPanel.Backpacks;
using PackPanel.Consume;
using PackPanel.Core;
using PackPanel.Crafting;
using PackPanel.Elite;
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 Translations;
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.RepresentationModel;
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.17.2.0")]
[assembly: AssemblyInformationalVersion("0.17.2+729815001313894f23d648ee59b26618052e26dd")]
[assembly: AssemblyProduct("PackPanel")]
[assembly: AssemblyTitle("PackPanel")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.17.2.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.17.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "milkyteam.packpanel";

		public const string PluginName = "PackPanel";

		public const string PluginVersion = "0.17.2";

		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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony harmony = new Harmony("milkyteam.packpanel");
			Lang.Install(harmony, Assembly.GetExecutingAssembly(), "PackPanel", ((BaseUnityPlugin)this).Logger);
			Synced = new SyncedConfiguration((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, "PackPanel", "0.17.2");
			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);
			EliteSetup.Register();
			int num = PatchEverything(harmony);
			BackpackPrefab.Install(harmony);
			TackleboxPrefab.Install(harmony);
			Synced.Finish(harmony);
			Log.LogInfo((object)("Loading [PackPanel 0.17.2]" + ((num > 0) ? $" with {num} failed patches, see above" : "")));
			Guard.Install(harmony, ((BaseUnityPlugin)this).Logger, Assembly.GetExecutingAssembly());
		}

		private void Update()
		{
			GamePanelTheme.Update();
			NightShade.Update();
		}

		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
{
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	public static class ChestWear
	{
		[HarmonyPrefix]
		public static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
		{
			if (!fromInventoryGui || inventory == null || item == null || !GearKeep.On || !InventoryState.IsLocal(__instance))
			{
				return true;
			}
			if (InventoryState.Manages(inventory) || !inventory.ContainsItem(item))
			{
				return true;
			}
			SlotKind? slotKind = SlotRules.WornKindOf(item);
			if (!slotKind.HasValue || InventoryState.CellsOf(slotKind.Value).Count == 0 || !Wearable(__instance, item, slotKind.Value))
			{
				return true;
			}
			Wear(__instance, inventory, item, slotKind.Value);
			return false;
		}

		private static bool Wearable(Humanoid humanoid, ItemData item, SlotKind kind)
		{
			if (kind != SlotKind.Backpack)
			{
				return WearCheck.Guards(humanoid, item, tell: true);
			}
			if (BackpackCatalog.Of(item) != null)
			{
				return BackpackSettings.Active;
			}
			return false;
		}

		private static void Wear(Humanoid humanoid, Inventory chest, ItemData item, SlotKind kind)
		{
			//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)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = humanoid.GetInventory();
			Vector2i val = Target(humanoid, item, kind);
			ItemData itemAt = inventory.GetItemAt(val.x, val.y);
			if (itemAt != null && !GearOut.HasRoom(inventory, kind))
			{
				Messages.Center(Lang.Get("packpanel_noroomoff"));
				return;
			}
			if (itemAt != null)
			{
				TakeOut(humanoid, itemAt, kind);
			}
			if (inventory.GetItemAt(val.x, val.y) == null)
			{
				inventory.MoveItemToThis(chest, item, item.m_stack, val.x, val.y);
				ItemData itemAt2 = inventory.GetItemAt(val.x, val.y);
				if (itemAt2 != null)
				{
					humanoid.EquipItem(itemAt2, true);
				}
			}
		}

		private static Vector2i Target(Humanoid humanoid, ItemData item, SlotKind kind)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_003e: 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)
			IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(kind);
			if (kind != SlotKind.Utility)
			{
				return readOnlyList[0];
			}
			if (WearCheck.Beside(humanoid, item))
			{
				return BesideCell(humanoid, readOnlyList);
			}
			Vector2i val = WearCheck.Replaced(humanoid, item, readOnlyList);
			if (val.x < 0)
			{
				return readOnlyList[0];
			}
			return val;
		}

		private static Vector2i BesideCell(Humanoid humanoid, IReadOnlyList<Vector2i> cells)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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)
			Inventory inventory = humanoid.GetInventory();
			Vector2i result = cells[0];
			bool flag = false;
			for (int i = 0; i < cells.Count; i++)
			{
				ItemData itemAt = inventory.GetItemAt(cells[i].x, cells[i].y);
				if (itemAt == null)
				{
					return cells[i];
				}
				if (!flag && !humanoid.IsItemEquiped(itemAt))
				{
					result = cells[i];
					flag = true;
				}
			}
			return result;
		}

		private static void TakeOut(Humanoid humanoid, ItemData there, SlotKind kind)
		{
			if (humanoid.IsItemEquiped(there))
			{
				WornPlacement.Suspend();
				try
				{
					humanoid.UnequipItem(there, true);
				}
				finally
				{
					WornPlacement.Resume();
				}
			}
			GearOut.Away(humanoid, there, kind);
		}
	}
	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 (BackpackEquip.Takes(item))
				{
					__result = BackpackEquip.Wear(__instance, item, triggerEquipEffects);
				}
				else
				{
					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), "EquipItem")]
		public static class EquipBoots
		{
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			public static void Prefix(ItemData item)
			{
				if (EliteEquipmentLink.IsBoots(item))
				{
					WornPlacement.BeginEquip();
				}
			}

			[HarmonyFinalizer]
			public static void Finalizer(ItemData item)
			{
				if (EliteEquipmentLink.IsBoots(item))
				{
					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), "DrainEquipedItemDurability")]
		public static class Break
		{
			[HarmonyPrefix]
			public static void Prefix()
			{
				WornPlacement.BeginBreak();
			}

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

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

		[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);
					BackpackEquip.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);
					BackpackEquip.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)
		{
			if (worn.Count == 0)
			{
				return;
			}
			Inventory inventory = humanoid.GetInventory();
			bool flag = false;
			for (int num = worn.Count - 1; num >= 0; num--)
			{
				if (!worn[num].m_equipped || !inventory.ContainsItem(worn[num]))
				{
					worn.RemoveAt(num);
					flag = true;
				}
			}
			if (flag)
			{
				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 GearKeep
	{
		private static readonly SlotKind[] Kinds = new SlotKind[7]
		{
			SlotKind.Head,
			SlotKind.Chest,
			SlotKind.Legs,
			SlotKind.Feet,
			SlotKind.Back,
			SlotKind.Utility,
			SlotKind.Trinket
		};

		private static readonly List<ItemData> leftOff = new List<ItemData>();

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

		public static void LeaveOff(ItemData item)
		{
			if (!leftOff.Contains(item))
			{
				leftOff.Add(item);
			}
		}

		public static void Tick(Player player)
		{
			if (!On || ((Character)player).IsDead())
			{
				leftOff.Clear();
			}
			else if (!WornPlacement.Suspended && !Dragging())
			{
				Forget(player);
				WearAll(player);
			}
		}

		private static void Forget(Player player)
		{
			for (int num = leftOff.Count - 1; num >= 0; num--)
			{
				if (!GearOut.LiesUnworn((Humanoid)(object)player, leftOff[num], out var _))
				{
					leftOff.RemoveAt(num);
				}
			}
		}

		private static void WearAll(Player player)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = ((Humanoid)player).GetInventory();
			SlotKind[] kinds = Kinds;
			foreach (SlotKind kind in kinds)
			{
				IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(kind);
				for (int j = 0; j < readOnlyList.Count; j++)
				{
					Wear(player, inventory.GetItemAt(readOnlyList[j].x, readOnlyList[j].y), kind);
				}
			}
		}

		private static void Wear(Player player, ItemData item, SlotKind kind)
		{
			if (item != null && SlotRules.WornKindOf(item) == kind && !((Humanoid)player).IsItemEquiped(item) && !leftOff.Contains(item) && WearCheck.Guards((Humanoid)(object)player, item, tell: false) && WearCheck.Beside((Humanoid)(object)player, item) && !((Humanoid)player).EquipItem(item, true))
			{
				leftOff.Add(item);
			}
		}

		private static bool Dragging()
		{
			if ((Object)(object)InventoryGui.instance != (Object)null)
			{
				return (Object)(object)InventoryGui.instance.m_dragGo != (Object)null;
			}
			return false;
		}
	}
	public static class GearOut
	{
		public static Vector2i FreeCell(Inventory inventory, SlotKind kind)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (kind != SlotKind.Backpack)
			{
				return MainCells.FindEmpty(inventory, InventoryState.Layout, topFirst: false);
			}
			return MainCells.FindEmptyOffPack(inventory, InventoryState.Layout);
		}

		public static bool HasRoom(Inventory inventory, SlotKind kind)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return FreeCell(inventory, kind).x >= 0;
		}

		public static bool Away(Humanoid humanoid, ItemData item, SlotKind kind)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = humanoid.GetInventory();
			Vector2i val = FreeCell(inventory, kind);
			if (val.x < 0)
			{
				return false;
			}
			item.m_gridPos = val;
			inventory.Changed(false, false);
			return true;
		}

		public static bool LiesUnworn(Humanoid humanoid, ItemData item, out SlotKind kind)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			kind = SlotKind.Retired;
			if (!humanoid.GetInventory().ContainsItem(item) || humanoid.IsItemEquiped(item))
			{
				return false;
			}
			Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos);
			if (slot == null || !SlotRules.IsWorn(slot.Kind) || SlotRules.WornKindOf(item) != slot.Kind)
			{
				return false;
			}
			kind = slot.Kind;
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "ToggleEquipped")]
	public static class InstantEquip
	{
		[HarmonyPrefix]
		public static bool Prefix(Player __instance, ItemData item, ref bool __result)
		{
			if (!InventorySettings.Enabled.Value || !InventorySettings.InstantEquip.Value || item == null || !item.IsEquipable() || ((Character)__instance).InAttack() || item.m_shared.m_equipDuration <= 0f)
			{
				return true;
			}
			if (((Humanoid)__instance).IsItemEquiped(item))
			{
				((Humanoid)__instance).UnequipItem(item, true);
			}
			else
			{
				((Humanoid)__instance).EquipItem(item, true);
			}
			__result = true;
			return false;
		}
	}
	public static class ModifierFields
	{
		private static FieldInfo[] madeFrom;

		private static FieldRef<SharedData, float>[] getters = new FieldRef<SharedData, float>[0];

		public static FieldRef<SharedData, float>[] Get()
		{
			FieldInfo[] s_equipmentModifierSourceFields = Player.s_equipmentModifierSourceFields;
			if (s_equipmentModifierSourceFields == null || s_equipmentModifierSourceFields == madeFrom)
			{
				return getters;
			}
			FieldRef<SharedData, float>[] array = new FieldRef<SharedData, float>[s_equipmentModifierSourceFields.Length];
			for (int i = 0; i < s_equipmentModifierSourceFields.Length; i++)
			{
				array[i] = AccessTools.FieldRefAccess<SharedData, float>(s_equipmentModifierSourceFields[i]);
			}
			getters = array;
			madeFrom = s_equipmentModifierSourceFields;
			return getters;
		}
	}
	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)
			{
				IReadOnlyList<ItemData> worn = ExtraUtilities.Worn;
				if (worn.Count == 0 || !InventoryState.IsLocal(__instance))
				{
					return;
				}
				for (int i = 0; i < worn.Count; i++)
				{
					if (worn[i].m_shared.m_setName == setName)
					{
						__result++;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")]
		public static class EitrRegen
		{
			[HarmonyPostfix]
			public static void Postfix(Player __instance, ref float __result)
			{
				IReadOnlyList<ItemData> worn = ExtraUtilities.Worn;
				if (worn.Count != 0 && InventoryState.IsLocal((Humanoid)(object)__instance))
				{
					for (int i = 0; i < worn.Count; i++)
					{
						__result += worn[i].m_shared.m_eitrRegenModifier;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateModifiers")]
		public static class Modifiers
		{
			[HarmonyPostfix]
			public static void Postfix(Player __instance)
			{
				if (Player.s_equipmentModifierSourceFields != null && InventoryState.IsLocal((Humanoid)(object)__instance))
				{
					float[] equipmentModifierValues = __instance.m_equipmentModifierValues;
					AddUtilities(equipmentModifierValues);
					if (equipmentModifierValues.Length != 0)
					{
						equipmentModifierValues[0] += BackpackLevels.WornSpeed(__instance);
					}
				}
			}

			private static void AddUtilities(float[] values)
			{
				IReadOnlyList<ItemData> worn = ExtraUtilities.Worn;
				if (worn.Count == 0)
				{
					return;
				}
				FieldRef<SharedData, float>[] array = ModifierFields.Get();
				int num = Math.Min(values.Length, array.Length);
				for (int i = 0; i < worn.Count; i++)
				{
					SharedData shared = worn[i].m_shared;
					for (int j = 0; j < num; j++)
					{
						values[j] += array[j].Invoke(shared);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "GetEquipmentWeight")]
		public static class Weight
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, ref float __result)
			{
				IReadOnlyList<ItemData> worn = ExtraUtilities.Worn;
				if (worn.Count != 0 && InventoryState.IsLocal(__instance))
				{
					for (int i = 0; i < worn.Count; i++)
					{
						__result += worn[i].m_shared.m_weight;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UpdateEquipment")]
		public static class Durability
		{
			[HarmonyPostfix]
			public static void Postfix(Humanoid __instance, float dt)
			{
				if (ExtraUtilities.Worn.Count == 0 || !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 WearCheck
	{
		public static bool Guards(Humanoid humanoid, ItemData item, bool tell)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Invalid comparison between Unknown and I4
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			if (((Character)humanoid).InAttack() || ((Character)humanoid).InDodge() || (((Character)humanoid).IsSwimming() && !((Character)humanoid).IsOnGround()))
			{
				return false;
			}
			if (item.m_shared.m_useDurability && item.m_durability <= 0f)
			{
				return false;
			}
			if (item.m_shared.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(item.m_shared.m_dlc))
			{
				return Refuse(humanoid, tell, "$msg_dlcrequired");
			}
			if (((int)item.m_shared.m_itemType == 18 || (int)item.m_shared.m_itemType == 24) && Game.m_worldLevel > 0 && item.m_worldLevel < Game.m_worldLevel)
			{
				return Refuse(humanoid, tell, "$msg_ng_item_too_low");
			}
			return true;
		}

		public static bool Beside(Humanoid humanoid, ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType == 18 && humanoid.m_utilityItem != null)
			{
				return ExtraUtilities.Takes(humanoid, item);
			}
			return true;
		}

		public static Vector2i Replaced(Humanoid humanoid, ItemData item, IReadOnlyList<Vector2i> cells)
		{
			//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)
			//IL_0082: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = humanoid.GetInventory();
			Vector2i result = default(Vector2i);
			((Vector2i)(ref result))..ctor(-1, -1);
			for (int i = 0; i < cells.Count; i++)
			{
				ItemData itemAt = inventory.GetItemAt(cells[i].x, cells[i].y);
				if (itemAt != null && humanoid.IsItemEquiped(itemAt))
				{
					if (itemAt.m_shared.m_name == item.m_shared.m_name)
					{
						return cells[i];
					}
					if (itemAt == humanoid.m_utilityItem)
					{
						result = cells[i];
					}
				}
			}
			return result;
		}

		private static bool Refuse(Humanoid humanoid, bool tell, string message)
		{
			if (tell)
			{
				((Character)humanoid).Message((MessageType)2, message, 0, (Sprite)null, false);
			}
			return false;
		}
	}
	public static class WornPlacement
	{
		private static int suspended;

		private static int equipping;

		private static int breaking;

		public static bool Suspended => suspended > 0;

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

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

		public static void BeginBreak()
		{
			breaking++;
		}

		public static void EndBreak()
		{
			breaking = ((breaking > 0) ? (breaking - 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_0034: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = humanoid.GetInventory();
			if (!Suspended && equipping <= 0 && breaking <= 0 && item != null && !item.m_equipped && InventoryState.IsLocal(humanoid))
			{
				Slot slot = InventoryState.SlotAt(inventory, item.m_gridPos);
				if (slot != null && SlotRules.IsWorn(slot.Kind) && SlotRules.WornKindOf(item) == slot.Kind && inventory.ContainsItem(item) && !GearOut.Away(humanoid, item, slot.Kind))
				{
					GearKeep.LeaveOff(item);
				}
			}
		}

		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", 2f, new TackleboxStats("piece_workbench", 2, "Wood:10, LeatherScraps:10, DeerHide:5", 1)),
			new TackleboxKind("PackPanel_FinewoodTacklebox", "finewood", 3f, new TackleboxStats("piece_workbench", 3, "PackPanel_DriftwoodTacklebox:1, FineWood:10, TrollHide:10, Bronze:2", 2)),
			new TackleboxKind("PackPanel_CarapaceTacklebox", "carapace", 3f, new TackleboxStats("blackforge", 1, "PackPanel_FinewoodTacklebox:1, Carapace:10, YggdrasilWood:10", 6)),
			new TackleboxKind("PackPanel_FlametalTacklebox", "flametal", 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();
			CraftedWords.WriteAll();
			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(YamlConfig.YamlNode root)
		{
			YamlConfig.YamlNode yamlNode = root.Get("tackleboxes");
			if (yamlNode.Kind == YamlNodeKind.Map)
			{
				foreach (KeyValuePair<string, YamlConfig.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, YamlConfig.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
	{
		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, float weight, TackleboxStats defaults)
			: base(id, "tacklebox", word, 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.Id + " 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.Id + " ready"));
		}
	}
	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;

		private static string shownText;

		public static void Refresh(InventoryElement element)
		{
			//IL_005a: 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)
			if ((Object)(object)element == (Object)null || !Tacklebox.Active)
			{
				return;
			}
			TMP_Text amount = element.m_amount;
			if (((Behaviour)amount).enabled != element.m_used)
			{
				((Behaviour)amount).enabled = element.m_used;
			}
			if (element.m_used)
			{
				IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle);
				Inventory inventory = ((Humanoid)InventoryState.Player).GetInventory();
				int num = 0;
				for (int i = 0; i < readOnlyList.Count; i++)
				{
					num += ((inventory.GetItemAt(readOnlyList[i].x, readOnlyList[i].y) != null) ? 1 : 0);
				}
				if (!((Object)(object)element == (Object)(object)shownOn) || num != shownUsed || readOnlyList.Count != shownCells || !(amount.text == shownText))
				{
					shownText = num + "/" + readOnlyList.Count;
					amount.text = shownText;
					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 void DescribeAll()
		{
			foreach (TackleboxKind item in TackleboxCatalog.All)
			{
				Lang.Add(item.DescriptionToken, Describe(item));
			}
		}

		private static string Describe(TackleboxKind kind)
		{
			int cells = kind.Stats.Cells;
			string text = ((cells == 1) ? Lang.Get("packpanel_tacklebox_one_cell") : Lang.Format("packpanel_tacklebox_cells", cells));
			return Lang.Format("packpanel_tacklebox_describe", Lang.Get(kind.LookKey), text);
		}
	}
	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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			foreach (InventoryElement element in elements)
			{
				if (!((Object)(object)element == (Object)null))
				{
					ItemData item = (element.m_used ? inventory.GetItemAt(element.Position.x, element.Position.y) : null);
					NumberText.ShowCount(element.m_amount, item);
				}
			}
		}
	}
	[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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			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(Lang.Get("packpanel_tacklebox_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;

		private static readonly PanelFind popupFind = new PanelFind("PackPanel_tacklebox");

		public static RectTransform Find(InventoryGui gui)
		{
			return popupFind.In(gui);
		}

		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_0023: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = SlotPanel.MakePanel(gui, "PackPanel_tacklebox");
			popupFind.Made(gui, val);
			val.pivot = new Vector2(0f, 1f);
			GridSkin.Panel(((Component)val).GetComponent<Image>());
		}
	}
	public static class TackleRouting
	{
		public static bool TakeIn(Inventory inventory, ItemData item)
		{
			return SlotFill.TakeIn(inventory, item, InventoryState.CellsOf(SlotKind.Tackle));
		}
	}
	public static class TackleRules
	{
		private const string Rod = "FishingRod";

		private const string GameBait = "$item_fishingbait";

		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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if (item == null)
			{
				return false;
			}
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType == 9 || (int)itemType == 23)
			{
				return item.m_shared.m_ammoType == (BaitType() ?? "$item_fishingbait");
			}
			return false;
		}

		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), "AddItem", new Type[] { typeof(ItemData) })]
	public static class AddRouting
	{
		[HarmonyPrefix]
		public static bool Prefix(Inventory __instance, ItemData item, ref bool __result, bool __runOriginal)
		{
			if (!__runOriginal)
			{
				return false;
			}
			if (item == null || !InventoryState.Manages(__instance) || !Routed(__instance, item))
			{
				return true;
			}
			__result = true;
			return false;
		}

		private static bool Routed(Inventory inventory, ItemData item)
		{
			if (SlotRules.IsCoins(item) && CoinPurse.TakeIn(inventory, item))
			{
				return true;
			}
			if (KeyRouting.TakeIn(inventory, item))
			{
				return true;
			}
			if (Tacklebox.Active && TackleRules.IsTackle(item) && TackleRouting.TakeIn(inventory, item))
			{
				return true;
			}
			if (AmmoRouting.IsAmmo(item))
			{
				return AmmoRouting.TakeIn(inventory, item);
			}
			return false;
		}
	}
	public static class AmmoRouting
	{
		public static bool IsAmmo(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType == 9)
			{
				return !TackleRules.IsBait(item);
			}
			return false;
		}

		public static bool TakeIn(Inventory inventory, ItemData item)
		{
			return SlotFill.TakeIn(inventory, item, InventoryState.CellsOf(SlotKind.Ammo));
		}
	}
	[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;
		}
	}
	public static class CoinPurse
	{
		public 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(Lang.Get("packpanel_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) && slotKind == slot.Kind)
			{
				if (!item.m_equipped)
				{
					((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;
		}
	}
	[HarmonyPatch(typeof(TombStone), "EasyFitInInventory")]
	public static class GraveFit
	{
		[HarmonyPrefix]
		public static bool Prefix(TombStone __instance, Player player, ref bool __result)
		{
			Container component = ((Component)__instance).GetComponent<Container>();
			if (!InventoryState.IsLocal((Humanoid)(object)player) || !InventoryState.Manages(((Humanoid)player).GetInventory()) || (Object)(object)component == (Object)null)
			{
				return true;
			}
			__result = Fits(player, component.GetInventory());
			return false;
		}

		private static bool Fits(Player player, Inventory grave)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			InventoryLayout layout = InventoryState.Layout;
			ItemData val = BackpackGrave.WaitingPack(grave);
			BackpackKind kind = BackpackCatalog.Of(val);
			int num = BackpackSettings.SlotsOf(val);
			int num2 = BackpackGrave.RowsAdded(layout, num);
			int num3 = MainCells.CountEmpty(inventory, layout) + num;
			if (GridItems(inventory, grave, val, layout.MainRows + num2, num2) > num3)
			{
				return false;
			}
			float num4 = player.GetMaxCarryWeight() + BackpackSettings.Carry(kind) * Game.m_carryWeightRate;
			return inventory.GetTotalWeight() + grave.GetTotalWeight() <= num4;
		}

		private static int GridItems(Inventory inventory, Inventory grave, ItemData pack, int mainRows, int shift)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (ItemData allItem in grave.GetAllItems())
			{
				if (allItem != pack)
				{
					Vector2i gridPos = allItem.m_gridPos;
					if ((gridPos.y < mainRows || inventory.GetItemAt(gridPos.x, gridPos.y - shift) != null) && inventory.FindFreeStackSpace(allItem.m_shared.m_name, (float)allItem.m_worldLevel) < allItem.m_stack)
					{
						num++;
					}
				}
			}
			return num;
		}
	}
	public static class GravePatches
	{
		[HarmonyPatch(typeof(Container), "RPC_TakeAllResponse")]
		public static class Granted
		{
			[HarmonyPrefix]
			public static void Prefix(Container __instance)
			{
				grantedFrom = __instance;
			}

			[HarmonyFinalizer]
			public static void Finalizer()
			{
				grantedFrom = null;
			}
		}

		[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;
			}
		}

		private static Container grantedFrom;

		public static bool ForeignTakeAll { get; private set; }

		private static bool IsGrave(Inventory inventory)
		{
			if (From(((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_currentContainer : null, inventory, out var grave) || From(grantedFrom, inventory, out grave))
			{
				return grave;
			}
			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 bool From(Container container, Inventory inventory, out bool grave)
		{
			grave = false;
			if ((Object)(object)container == (Object)null || container.GetInventory() != inventory)
			{
				return false;
			}
			grave = (Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null;
			return true;
		}

		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;
		}
	}
	[Flags]
	public enum KeptGroups
	{
		None = 0,
		Gear = 1,
		Backpack = 2,
		Utility = 4,
		Trinket = 8,
		Food = 0x10,
		Mead = 0x20,
		Ammo = 0x40,
		Tacklebox = 0x80
	}
	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_0047: Unknown result type (might be due to invalid IL or missing references)
			KeptGroups value = InventorySettings.KeepOnDeath.Value;
			if (value == KeptGroups.None || !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 && (value & GroupOf(slot.Kind)) != KeptGroups.None)
				{
					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 KeptGroups GroupOf(SlotKind kind)
		{
			switch (kind)
			{
			case SlotKind.Head:
			case SlotKind.Chest:
			case SlotKind.Legs:
			case SlotKind.Back:
			case SlotKind.Feet:
				return KeptGroups.Gear;
			case SlotKind.Backpack:
				return KeptGroups.Backpack;
			case SlotKind.Utility:
				return KeptGroups.Utility;
			case SlotKind.Trinket:
				return KeptGroups.Trinket;
			case SlotKind.Food:
				return KeptGroups.Food;
			case SlotKind.Mead:
				return KeptGroups.Mead;
			case SlotKind.Ammo:
				return KeptGroups.Ammo;
			case SlotKind.Tacklebox:
				return KeptGroups.Tacklebox;
			default:
				return KeptGroups.None;
			}
		}

		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
	{
		private static readonly SlotKind[] kinds = (SlotKind[])Enum.GetValues(typeof(SlotKind));

		private static readonly string[] prefixes = Prefixes();

		public SlotKind Kind { get; }

		public int Number { get; }

		public string Id { get; }

		public static IReadOnlyList<SlotKind> Kinds => kinds;

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

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

		public override string ToString()
		{
			return Id;
		}

		public static string Prefix(SlotKind kind)
		{
			int num = (int)kind;
			if (num < 0 || num >= prefixes.Length || prefixes[num] == null)
			{
				return kind.ToString().ToLowerInvariant();
			}
			return prefixes[num];
		}

		private static string[] Prefixes()
		{
			int num = 0;
			SlotKind[] array = kinds;
			foreach (SlotKind slotKind in array)
			{
				num = Math.Max(num, (int)(slotKind + 1));
			}
			string[] array2 = new string[num];
			array = kinds;
			for (int i = 0; i < array.Length; i++)
			{
				SlotKind slotKind2 = array[i];
				if (slotKind2 >= SlotKind.Head)
				{
					array2[(int)slotKind2] = slotKind2.ToString().ToLowerInvariant();
				}
			}
			return array2;
		}
	}
	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(Lang.Get("packpanel_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 static class SlotFill
	{
		public static bool TakeIn(Inventory inventory, ItemData item, IReadOnlyList<Vector2i> cells)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0049: 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)
			foreach (Vector2i cell in cells)
			{
				if (Stack(inventory, item, cell))
				{
					return true;
				}
			}
			foreach (Vector2i cell2 in cells)
			{
				if (inventory.GetItemAt(cell2.x, cell2.y) == null)
				{
					Place(inventory, item, cell2);
					return true;
				}
			}
			return false;
		}

		public static int EmptyRoom(Inventory inventory, IReadOnlyList<Vector2i> cells, ItemData item)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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)
			int num = 0;
			foreach (Vector2i cell in cells)
			{
				num += ((inventory.GetItemAt(cell.x, cell.y) == null) ? 1 : 0);
			}
			return num * item.m_shared.m_maxStackSize;
		}

		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 enum SlotKind
	{
		Head,
		Chest,
		Legs,
		Back,
		Backpack,
		Utility,
		Food,
		Mead,
		Ammo,
		Purse,
		Retired,
		Key,
		Tacklebox,
		Tackle,
		Trinket,
		Feet
	}
	public static class SlotRules
	{
		public const string CoinsName = "$item_coins";

		private static HashSet<string> listedPacks;

		private static bool watchingList;

		public static bool IsWorn(SlotKind kind)
		{
			if (kind > SlotKind.Utility && kind != SlotKind.Trinket)
			{
				return kind == SlotKind.Feet;
			}
			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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			if (BackpackCatalog.Of(item) != null)
			{
				return SlotKind.Backpack;
			}
			if (EliteEquipmentLink.IsBoots(item))
			{
				return SlotKind.Feet;
			}
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType <= 11)
			{
				if ((int)itemType == 6)
				{
					return SlotKind.Head;
				}
				if ((int)itemType == 7)
				{
					return SlotKind.Chest;
				}
				if ((int)itemType == 11)
				{
					return SlotKind.Legs;
				}
			}
			else
			{
				if ((int)itemType == 17)
				{
					return SlotKind.Back;
				}
				if ((int)itemType == 18)
				{
					return SlotKind.Utility;
				}
				if ((int)itemType == 24)
				{
					return SlotKind.Trinket;
				}
			}
			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) ? ItemNames.PrefabName(item) : "");
			if (text.IndexOf("backpack", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return ListedPacks().Contains(text);
		}

		private static HashSet<string> ListedPacks()
		{
			if (listedPacks != null)
			{
				return listedPacks;
			}
			if (!watchingList)
			{
				watchingList = true;
				InventorySettings.BackpackItems.SettingChanged += delegate
				{
					listedPacks = null;
				};
			}
			listedPacks = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = InventorySettings.BackpackItems.Value.Split(new char[1] { ',' });
			foreach (string text in array)
			{
				if (text.Trim().Length > 0)
				{
					listedPacks.Add(text.Trim());
				}
			}
			return listedPacks;
		}

		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
	{
		private static readonly HashSet<ItemData> before = new HashSet<ItemData>();

		[HarmonyPrefix]
		public static void Prefix(Inventory __instance, out bool __state)
		{
			__state = InventoryState.Manages(__instance) && (KeyRing.Active || Tacklebox.Active || InventoryState.CellsOf(SlotKind.Ammo).Count > 0);
			if (__state)
			{
				before.Clear();
				before.UnionWith(__instance.GetAllItems());
			}
		}

		[HarmonyPostfix]
		public static void Postfix(Inventory __instance, bool __state)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!__state)
			{
				return;
			}
			foreach (ItemData item in new List<ItemData>(__instance.GetAllItems()))
			{
				if (!before.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 (AmmoRouting.IsAmmo(item))
			{
				return AmmoRouting.TakeIn(inventory, item);
			}
			if (Tacklebox.Active && TackleRules.IsTackle(item))
			{
				return TackleRouting.TakeIn(inventory, item);
			}
			return false;
		}
	}
}
namespace PackPanel.Ring
{
	public static class KeyNames
	{
		private static readonly Dictionary<string, List<int>> numbers = new Dictionary<string, List<int>>();

		private static IReadOnlyList<string> madeFor;

		private static ObjectDB madeFrom;

		private static int madeItems = -1;

		public static int Version { get; private set; }

		public static Dictionary<string, List<int>> Get()
		{
			IReadOnlyList<string> prefabs = KeyRing.Prefabs;
			ObjectDB instance = ObjectDB.instance;
			int num = (((Object)(object)instance != (Object)null) ? instance.m_items.Count : (-1));
			if (prefabs == madeFor && instance == madeFrom && num == madeItems)
			{
				return numbers;
			}
			Make(prefabs.Count);
			madeFor = prefabs;
			madeFrom = instance;
			madeItems = num;
			Version++;
			return numbers;
		}

		private static void Make(int keys)
		{
			numbers.Clear();
			for (int i = 1; i <= keys; i++)
			{
				string text = KeyRing.Key(i)?.m_shared.m_name;
				if (text != null)
				{
					if (!numbers.TryGetValue(text, out var value))
					{
						value = (numbers[text] = new List<int>());
					}
					value.Add(i);
				}
			}
		}
	}
	public static class KeyRing
	{
		private static string parsed;

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

		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(I