Decompiled source of ValheimCore v1.0.1

ValheimCore.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GoblinHeim.CoreBuild;
using GoblinHeim.CoreBuilding;
using GoblinHeim.CoreCrafting;
using GoblinHeim.CoreEquipment;
using GoblinHeim.CoreInventory;
using GoblinHeim.CoreStorage;
using GoblinHeim.ValheimCore;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimCore")]
[assembly: AssemblyDescription("GoblinHeim — native F4 menu and server-admin settings")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GoblinHeim.CoreBuilding
{
	public static class BuildingModule
	{
		private static bool dirty = true;

		private static readonly FieldRef<CraftingStation, float> Timer = AccessTools.FieldRefAccess<CraftingStation, float>("m_updateExtensionTimer");

		public static void DrawSettings(bool admin, Action<string, float> set)
		{
			bool enabled = GUI.enabled;
			GUI.enabled = enabled && admin;
			GUILayout.Label("Workshop Range   " + CorePlugin.Settings.WorkshopRange.ToString("0") + " m", Array.Empty<GUILayoutOption>());
			float num = Mathf.Round(GUILayout.HorizontalSlider(CorePlugin.Settings.WorkshopRange, 20f, 180f, Array.Empty<GUILayoutOption>()));
			if (num != CorePlugin.Settings.WorkshopRange)
			{
				set("workshoprange", num);
			}
			GUI.enabled = enabled;
		}

		public static void Update()
		{
			if (dirty)
			{
				dirty = false;
				ApplyAll();
			}
		}

		public static void ApplyRangeSoon()
		{
			dirty = true;
		}

		internal static void Apply(CraftingStation station)
		{
			if (Object.op_Implicit((Object)(object)station))
			{
				station.m_rangeBuild = CorePlugin.Settings.WorkshopRange;
				Timer.Invoke(station) = 2f;
				float stationBuildRange = station.GetStationBuildRange();
				ResizeArea(station, stationBuildRange);
			}
		}

		private static void ResizeArea(CraftingStation station, float range)
		{
			Collider val = station.m_effectAreaCollider;
			if (!Object.op_Implicit((Object)(object)val))
			{
				EffectArea componentInChildren = ((Component)station).GetComponentInChildren<EffectArea>(true);
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					val = ((Component)componentInChildren).GetComponent<Collider>() ?? ((Component)componentInChildren).GetComponentInChildren<Collider>();
				}
			}
			SphereCollider val2 = (SphereCollider)(object)((val is SphereCollider) ? val : null);
			if (val2 != null)
			{
				val2.radius = range;
				return;
			}
			CapsuleCollider val3 = (CapsuleCollider)(object)((val is CapsuleCollider) ? val : null);
			if (val3 != null)
			{
				val3.radius = range;
			}
		}

		private static void ApplyAll()
		{
			foreach (IMonoUpdater instance in CraftingStation.Instances)
			{
				CraftingStation val = (CraftingStation)(object)((instance is CraftingStation) ? instance : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					Apply(val);
				}
			}
		}

		public static void WorldChanged()
		{
			dirty = true;
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "Start")]
	internal static class BuildingStationStart
	{
		[HarmonyPostfix]
		private static void Postfix(CraftingStation __instance)
		{
			BuildingModule.Apply(__instance);
		}
	}
}
namespace GoblinHeim.CoreEquipment
{
	public static class EquipmentModule
	{
		internal struct EquipState
		{
			internal ItemData Item;

			internal Vector2i From;

			internal int Target;

			internal bool Tracked;

			internal bool CustomUtility;
		}

		private const string BaseKey = "ValheimCore.Equipment.BaseRows.v2";

		private const string BackupKey = "ValheimCore.Equipment.Backup.v2";

		private const string LegacyKey = "ValheimCore.SpecialSlot.v1";

		private static readonly string[] Names = new string[16]
		{
			"Head", "Trinket", "Arrow 1", "Consumable 1", "Shoulders", "Utility 1", "Arrow 2", "Consumable 2", "Chest", "Utility 2",
			"Arrow 3", "Consumable 3", "Legs", "Utility 3", "Arrow 4", "Consumable 4"
		};

		private static ConfigEntry<KeyboardShortcut>[] arrows;

		private static ConfigEntry<KeyboardShortcut>[] quicks;

		private static ConfigEntry<KeyboardShortcut> listening;

		private static ConfigEntry<bool> minimized;

		private static ConfigEntry<bool> compact;

		private static ConfigEntry<Vector2> panelPosition;

		private static int consumed = -1;

		private static int baseRows = 4;

		private static int lastUtility = -1;

		private static int lastArrows = -1;

		private static int lastConsumables = -1;

		private static bool restoring;

		private static bool layoutLogged;

		private static bool slotsDirty = true;

		private static bool inventorySubscribed;

		private static Player owner;

		private static readonly Dictionary<ItemData, int> pendingEquipTargets = new Dictionary<ItemData, int>();

		private static readonly Dictionary<ItemData, Vector2i> pendingUnequipTargets = new Dictionary<ItemData, Vector2i>();

		private static readonly HashSet<ItemData> pendingDisplaced = new HashSet<ItemData>();

		[ThreadStatic]
		private static bool nativeTransfer;

		[ThreadStatic]
		private static bool reconciling;

		[ThreadStatic]
		private static int equipDepth;

		[ThreadStatic]
		private static int directPickup;

		private static readonly FieldRef<InventoryGui, ItemData> DragItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_dragItem");

		private static readonly FieldRef<InventoryGui, Inventory> DragInventory = AccessTools.FieldRefAccess<InventoryGui, Inventory>("m_dragInventory");

		private static readonly Action<InventoryGui, ItemData, Inventory, int> ClearDrag = AccessTools.MethodDelegate<Action<InventoryGui, ItemData, Inventory, int>>(AccessTools.Method(typeof(InventoryGui), "SetupDragItem", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Player, ItemData> QueueEquip = AccessTools.MethodDelegate<Action<Player, ItemData>>(AccessTools.Method(typeof(Player), "QueueEquipAction", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Player, ItemData> QueueUnequip = AccessTools.MethodDelegate<Action<Player, ItemData>>(AccessTools.Method(typeof(Player), "QueueUnequipAction", (Type[])null, (Type[])null), (object)null, true);

		private static readonly FieldRef<Player, List<MinorActionData>> ActionQueue = AccessTools.FieldRefAccess<Player, List<MinorActionData>>("m_actionQueue");

		private static readonly Action<Inventory, bool, bool> Notify = AccessTools.MethodDelegate<Action<Inventory, bool, bool>>(AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null), (object)null, true);

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

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

		private static readonly Action<Humanoid> SetupEquipment = AccessTools.MethodDelegate<Action<Humanoid>>(AccessTools.Method(typeof(Humanoid), "SetupEquipment", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Vector3[] HudCorners = (Vector3[])(object)new Vector3[4];

		private static readonly int[] HudSlots = new int[8] { 2, 6, 10, 14, 3, 7, 11, 15 };

		private static HotkeyBar hudBar;

		private static RectTransform hudFirst;

		private static RectTransform hudSecond;

		private static Image hudSelection;

		private static Canvas hudCanvas;

		private static GUIStyle hudStackStyle;

		public static bool InputConsumedThisFrame => consumed == Time.frameCount;

		public static bool BoundShortcutDown
		{
			get
			{
				if (CoreUiWindows.Active || arrows == null)
				{
					return false;
				}
				bool flag = false;
				for (int i = 0; i < 4; i++)
				{
					if (flag)
					{
						break;
					}
					flag = Down(arrows[i]) || Down(quicks[i]);
				}
				if (flag)
				{
					return !InventoryAccess.Typing;
				}
				return false;
			}
		}

		internal static bool Restoring => restoring;

		internal static int BaseRows => baseRows;

		internal static bool Minimized
		{
			get
			{
				if (minimized != null)
				{
					return minimized.Value;
				}
				return false;
			}
		}

		internal static bool Compact
		{
			get
			{
				if (compact != null)
				{
					return compact.Value;
				}
				return false;
			}
		}

		internal static Vector2 PanelPosition
		{
			get
			{
				//IL_001c: 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)
				if (panelPosition != null)
				{
					return panelPosition.Value;
				}
				return new Vector2(615f, 28f);
			}
			set
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (panelPosition != null)
				{
					panelPosition.Value = value;
				}
			}
		}

		private static bool Down(ConfigEntry<KeyboardShortcut> e)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = e.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
			{
				value = e.Value;
				return ((KeyboardShortcut)(ref value)).IsDown();
			}
			return false;
		}

		public static void Initialize(ConfigFile c)
		{
			//IL_0041: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			arrows = new ConfigEntry<KeyboardShortcut>[4];
			quicks = new ConfigEntry<KeyboardShortcut>[4];
			for (int i = 0; i < 4; i++)
			{
				arrows[i] = c.Bind<KeyboardShortcut>("Client.Input", "ArrowSlot" + (i + 1), new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Select ammunition slot.");
				quicks[i] = c.Bind<KeyboardShortcut>("Client.Input", "QuickSlot" + (i + 1), new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Use consumable slot.");
			}
			minimized = c.Bind<bool>("Client.UI", "EquipmentMinimized", false, "Show only the title bar.");
			compact = c.Bind<bool>("Client.UI", "EquipmentCompact", false, "Show only arrows and consumables.");
			panelPosition = c.Bind<Vector2>("Client.UI", "EquipmentPanelPosition", new Vector2(615f, 28f), "Equipment panel position relative to the Vanilla inventory.");
			if (!inventorySubscribed)
			{
				InventoryAccess.InventoryChanged += MarkSlotsDirty;
				inventorySubscribed = true;
			}
		}

		public static void Shutdown()
		{
			if (inventorySubscribed)
			{
				InventoryAccess.InventoryChanged -= MarkSlotsDirty;
				inventorySubscribed = false;
			}
			listening = null;
			owner = null;
			pendingEquipTargets.Clear();
			pendingUnequipTargets.Clear();
			pendingDisplaced.Clear();
			ClearHudCache();
			NativeEquipmentPanel.Clear();
		}

		private static void MarkSlotsDirty()
		{
			slotsDirty = true;
		}

		public static void DrawSettings(bool admin, Action<string, float> set)
		{
			GUILayout.Label("Equipment Inventory — grille 4 × 4", Array.Empty<GUILayoutOption>());
			bool enabled = GUI.enabled;
			GUI.enabled = enabled && admin;
			Count("Utility Slots", "utilityslots", CorePlugin.Settings.UtilitySlots, 1, 3, set);
			Count("Arrow Slots Active", "arrowslots", CorePlugin.Settings.ArrowSlotsActive, 1, 4, set);
			Count("Consumable Slots Active", "consumableslots", CorePlugin.Settings.ConsumableSlotsActive, 1, 4, set);
			GUI.enabled = enabled;
			for (int i = 0; i < 4; i++)
			{
				Bind("Arrow Slot " + (i + 1), arrows[i]);
			}
			GUILayout.Space(8f);
			for (int j = 0; j < 4; j++)
			{
				Bind("Consumable Slot " + (j + 1), quicks[j]);
			}
		}

		private static void Count(string l, string k, int v, int min, int max, Action<string, float> set)
		{
			GUILayout.Label(l + "   " + v, Array.Empty<GUILayoutOption>());
			int num = (int)Mathf.Round(GUILayout.HorizontalSlider((float)v, (float)min, (float)max, Array.Empty<GUILayoutOption>()));
			if (num != v)
			{
				set(k, num);
			}
			GUILayout.Space(6f);
		}

		private unsafe static void Bind(string n, ConfigEntry<KeyboardShortcut> e)
		{
			//IL_000f: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (listening != e)
			{
				KeyboardShortcut value = e.Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
				{
					value = e.Value;
					obj = ((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).ToString();
				}
				else
				{
					obj = "Non assigné";
				}
			}
			else
			{
				obj = "Appuyez sur la combinaison…";
			}
			if (GUILayout.Button(n + "   " + (string?)obj, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				listening = e;
			}
		}

		public static void Update()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			Ensure(Player.m_localPlayer);
			if (!InventoryGui.IsVisible() && !CorePlugin.visible)
			{
				listening = null;
			}
			if (listening != null && Input.anyKeyDown)
			{
				foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
				{
					if (Modifier(value) || !Input.GetKeyDown(value))
					{
						continue;
					}
					List<KeyCode> list = new List<KeyCode>();
					KeyCode[] array = new KeyCode[6];
					RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
					KeyCode[] array2 = (KeyCode[])(object)array;
					foreach (KeyCode val2 in array2)
					{
						if (Input.GetKey(val2))
						{
							list.Add(val2);
						}
					}
					listening.Value = new KeyboardShortcut(value, list.ToArray());
					listening = null;
					consumed = Time.frameCount;
					return;
				}
			}
			if (!Object.op_Implicit((Object)(object)owner))
			{
				return;
			}
			if (lastUtility != CorePlugin.Settings.UtilitySlots || lastArrows != CorePlugin.Settings.ArrowSlotsActive || lastConsumables != CorePlugin.Settings.ConsumableSlotsActive)
			{
				lastUtility = CorePlugin.Settings.UtilitySlots;
				lastArrows = CorePlugin.Settings.ArrowSlotsActive;
				lastConsumables = CorePlugin.Settings.ConsumableSlotsActive;
				slotsDirty = true;
			}
			if (slotsDirty && CorePlugin.Ready)
			{
				slotsDirty = false;
				EnforceSlots();
				ReconcileEquipment();
			}
			if (CoreUiWindows.Active)
			{
				return;
			}
			int num = -1;
			bool use = false;
			for (int j = 0; j < 4; j++)
			{
				if (num >= 0)
				{
					break;
				}
				if (Down(arrows[j]))
				{
					num = 2 + j * 4;
				}
			}
			for (int k = 0; k < 4; k++)
			{
				if (num >= 0)
				{
					break;
				}
				if (Down(quicks[k]))
				{
					num = 3 + k * 4;
					use = true;
				}
			}
			if (num >= 0 && !InventoryAccess.Typing)
			{
				Activate(num, use);
				consumed = Time.frameCount;
			}
		}

		private static bool Modifier(KeyCode k)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			if ((int)k != 306 && (int)k != 305 && (int)k != 304 && (int)k != 303 && (int)k != 308)
			{
				return (int)k == 307;
			}
			return true;
		}

		private static void Ensure(Player p)
		{
			if (Object.op_Implicit((Object)(object)p) && !((Object)(object)owner == (Object)(object)p))
			{
				owner = p;
				slotsDirty = true;
				pendingDisplaced.Clear();
				ClearHudCache();
				ReadBaseRows(p);
				Extend();
				MigrateLegacy();
				Validate(CorePlugin.Ready);
				if (CorePlugin.Ready)
				{
					ReconcileEquipment();
				}
			}
		}

		private static void ReadBaseRows(Player p)
		{
			if (!p.m_customData.TryGetValue("ValheimCore.Equipment.BaseRows.v2", out var value) || !int.TryParse(value, out baseRows) || baseRows < 1)
			{
				baseRows = Math.Max(1, Math.Min(4, ((Humanoid)p).GetInventory().GetHeight()));
			}
			p.m_customData["ValheimCore.Equipment.BaseRows.v2"] = baseRows.ToString();
		}

		private static void Extend()
		{
			if (Object.op_Implicit((Object)(object)owner))
			{
				Inventory inventory = ((Humanoid)owner).GetInventory();
				inventory.SetHeight(baseRows + (16 + inventory.GetWidth() - 1) / inventory.GetWidth());
			}
		}

		public static bool IsInSpecialRegion(ItemData i)
		{
			if (Object.op_Implicit((Object)(object)owner) && i != null)
			{
				return i.m_gridPos.y >= baseRows;
			}
			return false;
		}

		private static Vector2i Pos(int n)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			int width = ((Humanoid)owner).GetInventory().GetWidth();
			return new Vector2i(n % width, baseRows + n / width);
		}

		private static ItemData Item(int n)
		{
			//IL_000f: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)owner))
			{
				return null;
			}
			Vector2i val = Pos(n);
			return ((Humanoid)owner).GetInventory().GetItemAt(val.x, val.y);
		}

		private static void MigrateLegacy()
		{
			//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)
			foreach (ItemData allItem in ((Humanoid)owner).GetInventory().GetAllItems())
			{
				if (allItem.m_customData.TryGetValue("ValheimCore.SpecialSlot.v1", out var value))
				{
					allItem.m_customData.Remove("ValheimCore.SpecialSlot.v1");
					value = value.Replace("Quick ", "Consumable ");
					int num = Array.IndexOf(Names, value);
					if (num >= 0 && Item(num) == null)
					{
						allItem.m_gridPos = Pos(num);
					}
				}
			}
			Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
		}

		private static Vector2i EmptyBase()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = ((Humanoid)owner).GetInventory();
			for (int i = 0; i < baseRows; i++)
			{
				for (int j = 0; j < inventory.GetWidth(); j++)
				{
					if (inventory.GetItemAt(j, i) == null)
					{
						return new Vector2i(j, i);
					}
				}
			}
			return new Vector2i(-1, -1);
		}

		private static void Full()
		{
			((Character)owner).Message((MessageType)2, "Inventaire plein", 0, (Sprite)null, false);
		}

		private static bool MoveBase(ItemData i)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Vector2i val = EmptyBase();
			if (val.x < 0)
			{
				Full();
				return false;
			}
			i.m_gridPos = val;
			return true;
		}

		internal static bool Unlocked(int n)
		{
			return n switch
			{
				2 => CorePlugin.Settings.ArrowSlotsActive >= 4, 
				6 => CorePlugin.Settings.ArrowSlotsActive >= 3, 
				10 => CorePlugin.Settings.ArrowSlotsActive >= 2, 
				14 => CorePlugin.Settings.ArrowSlotsActive >= 1, 
				3 => CorePlugin.Settings.ConsumableSlotsActive >= 4, 
				7 => CorePlugin.Settings.ConsumableSlotsActive >= 3, 
				11 => CorePlugin.Settings.ConsumableSlotsActive >= 2, 
				15 => CorePlugin.Settings.ConsumableSlotsActive >= 1, 
				9 => CorePlugin.Settings.UtilitySlots >= 2, 
				13 => CorePlugin.Settings.UtilitySlots >= 3, 
				_ => true, 
			};
		}

		internal static bool Fits(int n, ItemData i)
		{
			//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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Invalid comparison between Unknown and I4
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Invalid comparison between Unknown and I4
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Invalid comparison between Unknown and I4
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Invalid comparison between Unknown and I4
			if (i == null)
			{
				return false;
			}
			ItemType itemType = i.m_shared.m_itemType;
			switch (n)
			{
			case 0:
				return (int)itemType == 6;
			case 1:
				return (int)itemType == 24;
			case 4:
				return (int)itemType == 17;
			case 8:
				return (int)itemType == 7;
			case 12:
				return (int)itemType == 11;
			case 5:
			case 9:
			case 13:
				return (int)itemType == 18;
			case 2:
			case 6:
			case 10:
			case 14:
				if ((int)itemType != 9)
				{
					return (int)itemType == 23;
				}
				return true;
			case 3:
			case 7:
			case 11:
			case 15:
				return (int)itemType == 2;
			default:
				return false;
			}
		}

		private static void Activate(int n, bool use)
		{
			if (Unlocked(n))
			{
				ItemData val = Item(n);
				if (val != null && Fits(n, val))
				{
					((Humanoid)owner).UseItem(((Humanoid)owner).GetInventory(), val, true);
				}
			}
		}

		private static bool Playable()
		{
			//IL_0033: 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)
			if (Object.op_Implicit((Object)(object)owner) && (Object)(object)owner == (Object)(object)Player.m_localPlayer && ((Component)owner).gameObject.activeInHierarchy)
			{
				ZDOID zDOID = ((Character)owner).GetZDOID();
				if (!((ZDOID)(ref zDOID)).IsNone() && Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Game.instance) && Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					return !Object.op_Implicit((Object)(object)FejdStartup.instance);
				}
			}
			return false;
		}

		public static void OnGUI()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			if ((int)Event.current.type == 7 && Playable() && !CorePlugin.visible && !InventoryGui.IsVisible())
			{
				DrawHud();
			}
		}

		private static bool ResolveHud()
		{
			if (!Object.op_Implicit((Object)(object)hudBar))
			{
				hudBar = ((Component)Hud.instance).GetComponentInChildren<HotkeyBar>(true);
			}
			if (!Object.op_Implicit((Object)(object)hudBar) || ((Component)hudBar).transform.childCount < 1)
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)hudFirst))
			{
				Transform child = ((Component)hudBar).transform.GetChild(0);
				hudFirst = (RectTransform)(object)((child is RectTransform) ? child : null);
				if (!Object.op_Implicit((Object)(object)hudFirst))
				{
					return false;
				}
				Transform val = ((Transform)hudFirst).Find("equiped") ?? ((Transform)hudFirst).Find("selected");
				hudSelection = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<Image>() : null);
				hudCanvas = ((Component)hudFirst).GetComponentInParent<Canvas>();
			}
			hudSecond = (RectTransform)((((Component)hudBar).transform.childCount > 1) ? /*isinst with value type is only supported in some contexts*/: null);
			return true;
		}

		private static void ClearHudCache()
		{
			hudBar = null;
			hudFirst = null;
			hudSecond = null;
			hudSelection = null;
			hudCanvas = null;
			hudStackStyle = null;
		}

		private static void DrawHud()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_005b: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			if (!ResolveHud())
			{
				return;
			}
			Camera val = ((Object.op_Implicit((Object)(object)hudCanvas) && (int)hudCanvas.renderMode != 0) ? hudCanvas.worldCamera : null);
			hudFirst.GetWorldCorners(HudCorners);
			Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, HudCorners[0]);
			Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, HudCorners[2]);
			float num = Mathf.Min(Mathf.Abs(val3.x - val2.x), Mathf.Abs(val3.y - val2.y));
			if (num < 1f)
			{
				return;
			}
			float num2 = num;
			if (Object.op_Implicit((Object)(object)hudSecond))
			{
				num2 = Mathf.Abs(RectTransformUtility.WorldToScreenPoint(val, ((Transform)hudSecond).position).x - RectTransformUtility.WorldToScreenPoint(val, ((Transform)hudFirst).position).x);
			}
			float x = val2.x;
			float num3 = (float)Screen.height - val2.y + 2f;
			ItemData val4 = NativeAmmo.Invoke((Humanoid)(object)owner);
			Rect r = default(Rect);
			for (int i = 0; i < 8; i++)
			{
				((Rect)(ref r))..ctor(x + (float)(i % 4) * num2, num3 + (float)(i / 4) * (num + 2f), num, num);
				ItemData val5 = Item(HudSlots[i]);
				if (i < 4 && val5 != null && val5 == val4)
				{
					DrawSelection(r, hudSelection);
				}
				DrawHudSlot(r, HudSlots[i]);
			}
		}

		private static void DrawSelection(Rect r, Image source)
		{
			//IL_001e: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)source) && Object.op_Implicit((Object)(object)source.sprite))
			{
				Sprite sprite = source.sprite;
				Rect textureRect = sprite.textureRect;
				Color color = GUI.color;
				GUI.color = ((Graphic)source).color;
				GUI.DrawTextureWithTexCoords(r, (Texture)(object)sprite.texture, new Rect(((Rect)(ref textureRect)).x / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)sprite.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)sprite.texture).height), true);
				GUI.color = color;
			}
		}

		private static void DrawHudSlot(Rect r, int n)
		{
			//IL_001e: 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_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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			ItemData val = Item(n);
			if (val != null)
			{
				Sprite icon = val.GetIcon();
				if (Object.op_Implicit((Object)(object)icon))
				{
					Rect textureRect = icon.textureRect;
					float num = Mathf.Max(3f, ((Rect)(ref r)).width * 0.08f);
					Color color = GUI.color;
					GUI.color = Color.white;
					GUI.DrawTextureWithTexCoords(new Rect(((Rect)(ref r)).x + num, ((Rect)(ref r)).y + num, ((Rect)(ref r)).width - num * 2f, ((Rect)(ref r)).height - num * 2f), (Texture)(object)icon.texture, new Rect(((Rect)(ref textureRect)).x / (float)((Texture)icon.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)icon.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)icon.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)icon.texture).height), true);
					GUI.color = color;
				}
				if (hudStackStyle == null)
				{
					hudStackStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)8,
						fontSize = 14,
						fontStyle = (FontStyle)1
					};
				}
				GUI.Label(new Rect(((Rect)(ref r)).x + 3f, ((Rect)(ref r)).y + ((Rect)(ref r)).height - 24f, ((Rect)(ref r)).width - 7f, 20f), val.m_stack.ToString(), hudStackStyle);
			}
		}

		private static int EquipmentIndex(ItemData i)
		{
			//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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected I4, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			ItemType itemType = i.m_shared.m_itemType;
			if ((int)itemType <= 17)
			{
				switch (itemType - 6)
				{
				default:
					if ((int)itemType != 17)
					{
						goto IL_00d0;
					}
					return 4;
				case 0:
					return 0;
				case 1:
					return 8;
				case 5:
					return 12;
				case 3:
					break;
				case 2:
				case 4:
					goto IL_00d0;
				}
			}
			else
			{
				if ((int)itemType == 18)
				{
					int result = 5;
					for (int j = 5; j <= 13; j += 4)
					{
						if (Unlocked(j))
						{
							result = j;
							if (Item(j) == null)
							{
								return j;
							}
						}
					}
					return result;
				}
				if ((int)itemType != 23)
				{
					if ((int)itemType != 24)
					{
						goto IL_00d0;
					}
					return 1;
				}
			}
			int result2 = -1;
			for (int k = 2; k <= 14; k += 4)
			{
				if (Unlocked(k))
				{
					result2 = k;
					if (Item(k) == null)
					{
						return k;
					}
				}
			}
			int num = ExistingIndex(NativeAmmo.Invoke((Humanoid)(object)owner));
			if (num < 0)
			{
				return result2;
			}
			return num;
			IL_00d0:
			return -1;
		}

		private static int ExistingIndex(ItemData i)
		{
			if (i == null)
			{
				return -1;
			}
			for (int j = 0; j < 16; j++)
			{
				if (Item(j) == i)
				{
					return j;
				}
			}
			return -1;
		}

		internal static bool BeforeEquip(Humanoid h, ItemData i, ref bool result, ref EquipState state)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Invalid comparison between Unknown and I4
			state.Item = i;
			state.From = (Vector2i)(((??)i?.m_gridPos) ?? new Vector2i(-1, -1));
			state.Target = -1;
			state.Tracked = false;
			state.CustomUtility = false;
			Player val = (Player)(object)((h is Player) ? h : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || nativeTransfer || reconciling)
			{
				return true;
			}
			Ensure(val);
			state.Tracked = true;
			equipDepth++;
			if (i != null && pendingEquipTargets.TryGetValue(i, out var value) && Unlocked(value) && Fits(value, i))
			{
				state.Target = value;
			}
			else
			{
				int num = ExistingIndex(i);
				state.Target = ((num >= 0) ? num : ((i == null) ? (-1) : EquipmentIndex(i)));
			}
			int target = state.Target;
			if (target < 0)
			{
				return true;
			}
			if ((int)i.m_shared.m_itemType == 18 && target != 5 && NativeUtility.Invoke(h) != null)
			{
				foreach (ItemData item in ExtraUtilities())
				{
					if (item != i && item.m_shared.m_name == i.m_shared.m_name)
					{
						result = false;
						return false;
					}
				}
				ItemData val2 = Item(target);
				if (val2 != null && val2 != i && h.IsItemEquiped(val2))
				{
					h.UnequipItem(val2, false);
				}
				i.m_equipped = true;
				state.CustomUtility = true;
				result = true;
				return false;
			}
			return true;
		}

		internal static void AfterEquip(Humanoid h, ItemData i, bool result, EquipState state)
		{
			//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_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)
			if (!result || (Object)(object)h != (Object)(object)owner || i == null)
			{
				return;
			}
			int target = state.Target;
			if (target >= 0)
			{
				ItemData val = Item(target);
				if (val != null && val != i)
				{
					val.m_gridPos = state.From;
				}
				i.m_gridPos = Pos(target);
				if (state.CustomUtility)
				{
					SetupEquipment(h);
				}
				Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
			}
		}

		internal static Exception FinishEquip(Humanoid h, EquipState state, Exception error)
		{
			if (state.Tracked && equipDepth > 0)
			{
				equipDepth--;
			}
			if (state.Tracked && state.Item != null)
			{
				pendingEquipTargets.Remove(state.Item);
			}
			if (state.Tracked && equipDepth == 0)
			{
				FlushDisplaced(h);
			}
			return error;
		}

		internal static void AfterUnequip(Humanoid h, ItemData i)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)h != (Object)(object)owner || i == null || nativeTransfer || reconciling || restoring)
			{
				return;
			}
			int n = SpecialIndex(i.m_gridPos);
			if (!IsEquipmentStateSlot(n) || h.IsItemEquiped(i))
			{
				return;
			}
			bool flag = pendingUnequipTargets.ContainsKey(i);
			if (equipDepth > 0)
			{
				if (!IsArrowSlot(n) || flag)
				{
					pendingDisplaced.Add(i);
				}
			}
			else
			{
				MoveUnequippedOut(h, i, n, flag);
			}
		}

		private static void FlushDisplaced(Humanoid h)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			while (pendingDisplaced.Count > 0)
			{
				ItemData val = null;
				using (HashSet<ItemData>.Enumerator enumerator = pendingDisplaced.GetEnumerator())
				{
					if (enumerator.MoveNext())
					{
						val = enumerator.Current;
					}
				}
				pendingDisplaced.Remove(val);
				if (val != null)
				{
					int n = SpecialIndex(val.m_gridPos);
					if (IsEquipmentStateSlot(n) && !h.IsItemEquiped(val))
					{
						MoveUnequippedOut(h, val, n, pendingUnequipTargets.ContainsKey(val));
					}
					else
					{
						pendingUnequipTargets.Remove(val);
					}
				}
			}
		}

		private static void MoveUnequippedOut(Humanoid h, ItemData i, int n, bool requested)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_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_0053: 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)
			if (!pendingUnequipTargets.TryGetValue(i, out var value))
			{
				((Vector2i)(ref value))..ctor(-1, -1);
			}
			pendingUnequipTargets.Remove(i);
			if (IsArrowSlot(n) && !requested)
			{
				return;
			}
			if (!requested || value.y < 0 || value.y >= baseRows || ((Humanoid)owner).GetInventory().GetItemAt(value.x, value.y) != null)
			{
				value = EmptyBase();
			}
			if (value.x >= 0)
			{
				i.m_gridPos = value;
				Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
				return;
			}
			Full();
			reconciling = true;
			try
			{
				((Humanoid)owner).DropItem(((Humanoid)owner).GetInventory(), i, i.m_stack);
			}
			finally
			{
				reconciling = false;
			}
			Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
		}

		private static bool ActionQueued(ItemData i, ActionType type)
		{
			//IL_003b: 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)
			if (!Object.op_Implicit((Object)(object)owner) || i == null)
			{
				return false;
			}
			foreach (MinorActionData item in ActionQueue.Invoke(owner))
			{
				if (item.m_item == i && item.m_type == type)
				{
					return true;
				}
			}
			return false;
		}

		internal static bool QueueNativeEquip(ItemData i, int n)
		{
			if (!Object.op_Implicit((Object)(object)owner) || i == null || !((Humanoid)owner).GetInventory().ContainsItem(i) || !IsEquipmentStateSlot(n) || !Unlocked(n) || !Fits(n, i))
			{
				return false;
			}
			if (((Humanoid)owner).IsItemEquiped(i))
			{
				return true;
			}
			if (ActionQueued(i, (ActionType)0))
			{
				pendingEquipTargets[i] = n;
				return true;
			}
			if (ActionQueued(i, (ActionType)1))
			{
				((Humanoid)owner).RemoveEquipAction(i);
			}
			pendingUnequipTargets.Remove(i);
			pendingEquipTargets[i] = n;
			QueueEquip(owner, i);
			Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
			CorePlugin.LogEquipment("Queued native equip " + i.m_shared.m_name + " -> " + SlotName(n));
			return ActionQueued(i, (ActionType)0);
		}

		internal static bool QueueNativeUnequip(ItemData i, Vector2i destination)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)owner) || i == null || !((Humanoid)owner).GetInventory().ContainsItem(i) || !((Humanoid)owner).IsItemEquiped(i))
			{
				return false;
			}
			if (ActionQueued(i, (ActionType)1))
			{
				pendingUnequipTargets[i] = destination;
				return true;
			}
			if (ActionQueued(i, (ActionType)0))
			{
				((Humanoid)owner).RemoveEquipAction(i);
			}
			pendingEquipTargets.Remove(i);
			pendingUnequipTargets[i] = destination;
			QueueUnequip(owner, i);
			Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
			CorePlugin.LogEquipment("Queued native unequip " + i.m_shared.m_name + " -> Inventory");
			return ActionQueued(i, (ActionType)1);
		}

		internal static void CancelPendingAction(ItemData i)
		{
			if (i != null)
			{
				pendingEquipTargets.Remove(i);
				pendingUnequipTargets.Remove(i);
			}
		}

		internal static IEnumerable<ItemData> ExtraUtilities()
		{
			for (int n = 9; n <= 13; n += 4)
			{
				ItemData val = Item(n);
				if (val != null && val.m_equipped)
				{
					yield return val;
				}
			}
		}

		private static void EnforceSlots()
		{
			for (int i = 0; i < 16; i++)
			{
				if (!Unlocked(i) && Item(i) != null)
				{
					Evict(i);
				}
			}
		}

		private static void Evict(int n)
		{
			//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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = Item(n);
			if (val == null)
			{
				return;
			}
			Vector2i val2 = EmptyBase();
			if (val2.x >= 0)
			{
				if (val.m_equipped)
				{
					((Humanoid)owner).UnequipItem(val, true);
				}
				val.m_gridPos = val2;
				Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
			}
			else
			{
				if (val.m_equipped)
				{
					((Humanoid)owner).UnequipItem(val, true);
				}
				((Humanoid)owner).DropItem(((Humanoid)owner).GetInventory(), val, val.m_stack);
			}
		}

		internal static int FreeEquipmentSlot(ItemData i)
		{
			int num = EquipmentIndex(i);
			if (num < 0 || !Unlocked(num) || Item(num) != null)
			{
				return -1;
			}
			return num;
		}

		internal static void BeginDirectPickup(Humanoid h, GameObject go)
		{
			directPickup = -1;
			Ensure((Player)(object)((h is Player) ? h : null));
			if (!((Object)(object)h != (Object)(object)owner) && !((Object)(object)go == (Object)null) && ((Humanoid)owner).GetInventory().GetEmptySlots() <= 0)
			{
				ItemDrop component = go.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					directPickup = FreeEquipmentSlot(component.m_itemData);
				}
			}
		}

		internal static void EndDirectPickup(Humanoid h, GameObject go, bool result)
		{
			if (result && directPickup >= 0 && (Object)(object)h == (Object)(object)owner)
			{
				ItemData val = Item(directPickup);
				if (val != null)
				{
					QueueNativeEquip(val, directPickup);
				}
			}
			directPickup = -1;
		}

		internal static bool CanDirectAdd(Inventory inv, ItemData i)
		{
			if (Object.op_Implicit((Object)(object)owner) && inv == ((Humanoid)owner).GetInventory() && inv.GetEmptySlots() == 0)
			{
				return FreeEquipmentSlot(i) >= 0;
			}
			return false;
		}

		internal static void DirectPosition(Inventory inv, ref Vector2i p)
		{
			//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)
			if (Object.op_Implicit((Object)(object)owner) && inv == ((Humanoid)owner).GetInventory() && directPickup >= 0)
			{
				p = Pos(directPickup);
			}
		}

		private static void Validate(bool enforceLocks)
		{
			for (int i = 0; i < 16; i++)
			{
				ItemData val = Item(i);
				if (val != null && (!Fits(i, val) || (enforceLocks && !Unlocked(i))))
				{
					MoveBase(val);
				}
			}
			Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
		}

		private static int RestoreIndex(ItemData i)
		{
			//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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			//IL_0016: 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_0036: Expected I4, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			if (i == null)
			{
				return -1;
			}
			ItemType itemType = i.m_shared.m_itemType;
			if ((int)itemType <= 17)
			{
				switch (itemType - 6)
				{
				default:
					if ((int)itemType != 17)
					{
						goto IL_008c;
					}
					return 4;
				case 0:
					return 0;
				case 1:
					return 8;
				case 5:
					return 12;
				case 3:
					break;
				case 2:
				case 4:
					goto IL_008c;
				}
			}
			else
			{
				if ((int)itemType == 18)
				{
					for (int j = 5; j <= 13; j += 4)
					{
						if (Item(j) == null)
						{
							return j;
						}
					}
					return 5;
				}
				if ((int)itemType != 23)
				{
					if ((int)itemType != 24)
					{
						goto IL_008c;
					}
					return 1;
				}
			}
			for (int k = 2; k <= 14; k += 4)
			{
				if (Item(k) == null)
				{
					return k;
				}
			}
			return 14;
			IL_008c:
			return -1;
		}

		private static void MoveOutNow(ItemData i)
		{
			if (i == null)
			{
				return;
			}
			if (((Humanoid)owner).IsItemEquiped(i))
			{
				((Humanoid)owner).UnequipItem(i, false);
			}
			if (!IsInSpecialRegion(i) || MoveBase(i))
			{
				return;
			}
			reconciling = true;
			try
			{
				((Humanoid)owner).DropItem(((Humanoid)owner).GetInventory(), i, i.m_stack);
			}
			finally
			{
				reconciling = false;
			}
		}

		private static void ReconcileEquipment()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)owner) || restoring)
			{
				return;
			}
			Inventory inventory = ((Humanoid)owner).GetInventory();
			List<ItemData> list = new List<ItemData>(inventory.GetAllItems());
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (ItemData item in list)
			{
				int num4 = SpecialIndex(item.m_gridPos);
				if (!item.m_equipped && !((Humanoid)owner).IsItemEquiped(item))
				{
					continue;
				}
				int num5 = ((num4 >= 0 && IsEquipmentStateSlot(num4) && Fits(num4, item)) ? num4 : RestoreIndex(item));
				if (num5 < 0 || num4 == num5)
				{
					continue;
				}
				Vector2i gridPos = item.m_gridPos;
				ItemData val = Item(num5);
				item.m_gridPos = new Vector2i(-100, -100);
				if (val != null && val != item)
				{
					if (gridPos.y >= 0 && gridPos.y < baseRows && inventory.GetItemAt(gridPos.x, gridPos.y) == null)
					{
						val.m_gridPos = gridPos;
					}
					else
					{
						MoveOutNow(val);
						num3++;
					}
				}
				item.m_gridPos = Pos(num5);
				num++;
			}
			int[] array = new int[8] { 0, 1, 4, 5, 8, 9, 12, 13 };
			for (int i = 0; i < array.Length; i++)
			{
				ItemData val2 = Item(array[i]);
				if (val2 != null && !((Humanoid)owner).IsItemEquiped(val2))
				{
					val2.m_equipped = false;
					if (((Humanoid)owner).EquipItem(val2, false))
					{
						num2++;
						continue;
					}
					MoveOutNow(val2);
					num3++;
				}
			}
			SetupEquipment((Humanoid)(object)owner);
			Notify(inventory, arg2: true, arg3: false);
			if (num + num2 + num3 > 0)
			{
				CorePlugin.LogEquipment("Reconnexion réconciliée : déplacés=" + num + ", équipés=" + num2 + ", sortis=" + num3);
			}
		}

		internal static void SaveBackup(Player p)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Ensure(p);
			Inventory val = new Inventory("Core Equipment backup", (Sprite)null, 4, 4);
			for (int i = 0; i < 16; i++)
			{
				ItemData val2 = Item(i);
				if (val2 != null)
				{
					val.AddItem(val2.Clone(), new Vector2i(i % 4, i / 4));
				}
			}
			ZPackage val3 = new ZPackage();
			val.Save(val3);
			p.m_customData["ValheimCore.Equipment.Backup.v2"] = val3.GetBase64();
			p.m_customData["ValheimCore.Equipment.BaseRows.v2"] = baseRows.ToString();
		}

		internal static void PrepareResize(Player p, ref int rows, out int original)
		{
			original = -1;
			if (Object.op_Implicit((Object)(object)p) && !((Object)(object)p != (Object)(object)Player.m_localPlayer))
			{
				owner = p;
				original = Math.Max(1, rows);
				baseRows = original;
				p.m_customData["ValheimCore.Equipment.BaseRows.v2"] = baseRows.ToString();
				rows = baseRows + (16 + ((Humanoid)p).GetInventory().GetWidth() - 1) / ((Humanoid)p).GetInventory().GetWidth();
			}
		}

		internal static void FinishResize(Player p, int original)
		{
			if (original >= 0 && Object.op_Implicit((Object)(object)p))
			{
				p.m_customData["ValheimCore.Equipment.BaseRows.v2"] = original.ToString();
				p.AddUniqueKeyValue("invrows", original.ToString());
				baseRows = original;
				owner = p;
				Extend();
				if (Object.op_Implicit((Object)(object)InventoryGui.instance))
				{
					InventoryGui.instance.SetInventorySize(baseRows);
				}
				Validate(CorePlugin.Ready);
				slotsDirty = true;
			}
		}

		internal static void BeginLoad(Player p)
		{
			if ((Object)(object)p == (Object)(object)Player.m_localPlayer)
			{
				owner = p;
				restoring = true;
			}
		}

		internal static void EndLoad(Player p)
		{
			if ((Object)(object)p == (Object)(object)Player.m_localPlayer && restoring)
			{
				owner = p;
				ReadBaseRows(p);
				Extend();
				MigrateLegacy();
				restoring = false;
				Validate(CorePlugin.Ready);
				ReconcileEquipment();
				slotsDirty = true;
				if (Object.op_Implicit((Object)(object)InventoryGui.instance) && DraggedItem(InventoryGui.instance) != null)
				{
					ClearDrag(InventoryGui.instance, null, null, 1);
				}
				Notify(((Humanoid)p).GetInventory(), arg2: true, arg3: false);
			}
		}

		internal static void ApplyPreviewVisuals(Player p)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Invalid comparison between Unknown and I4
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Invalid comparison between Unknown and I4
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Invalid comparison between Unknown and I4
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Invalid comparison between Unknown and I4
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Invalid comparison between Unknown and I4
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Invalid comparison between Unknown and I4
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Invalid comparison between Unknown and I4
			if (!Object.op_Implicit((Object)(object)p) || (Object)(object)p == (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			VisEquipment component = ((Component)p).GetComponent<VisEquipment>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			int num = 4;
			if (p.m_customData.TryGetValue("ValheimCore.Equipment.BaseRows.v2", out var value) && int.TryParse(value, out var result) && result > 0)
			{
				num = result;
			}
			ItemData i = null;
			ItemData val = null;
			ItemData i2 = null;
			ItemData i3 = null;
			ItemData val2 = null;
			ItemData val3 = null;
			foreach (ItemData allItem in ((Humanoid)p).GetInventory().GetAllItems())
			{
				int num2 = (allItem.m_gridPos.y - num) * ((Humanoid)p).GetInventory().GetWidth() + allItem.m_gridPos.x;
				if (num2 < 0 || num2 >= 16 || !IsWearableSlot(num2))
				{
					continue;
				}
				ItemType itemType = allItem.m_shared.m_itemType;
				if ((int)itemType <= 11)
				{
					if ((int)itemType != 6)
					{
						if ((int)itemType != 7)
						{
							if ((int)itemType == 11)
							{
								i3 = allItem;
							}
						}
						else
						{
							i2 = allItem;
						}
					}
					else
					{
						i = allItem;
					}
				}
				else if ((int)itemType != 17)
				{
					if ((int)itemType != 18)
					{
						if ((int)itemType == 24)
						{
							val2 = allItem;
						}
					}
					else if (val3 == null)
					{
						val3 = allItem;
					}
				}
				else
				{
					val = allItem;
				}
			}
			component.SetHelmetItem(Hash(i));
			component.SetShoulderItem(Hash(val), val?.m_variant ?? 0, val?.m_quality ?? 0);
			component.SetChestItem(Hash(i2));
			component.SetLegItem(Hash(i3));
			component.SetTrinketItem((val2 != null && Object.op_Implicit((Object)(object)val2.m_dropPrefab)) ? ((Object)val2.m_dropPrefab).name : "");
			component.SetUtilityItem(Hash(val3));
		}

		private static int Hash(ItemData i)
		{
			if (i == null || !Object.op_Implicit((Object)(object)i.m_dropPrefab))
			{
				return 0;
			}
			return StringExtensionMethods.GetStableHashCode(((Object)i.m_dropPrefab).name);
		}

		internal static int VisibleRows(Inventory i)
		{
			if (!Object.op_Implicit((Object)(object)owner) || i != ((Humanoid)owner).GetInventory())
			{
				return -1;
			}
			return baseRows;
		}

		internal static int SpecialIndex(Vector2i p)
		{
			//IL_000c: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)owner) || p.y < baseRows)
			{
				return -1;
			}
			int num = (p.y - baseRows) * ((Humanoid)owner).GetInventory().GetWidth() + p.x;
			if (num < 0 || num >= 16)
			{
				return -1;
			}
			return num;
		}

		internal static string SlotName(int n)
		{
			if (n < 0 || n >= Names.Length)
			{
				return "";
			}
			return Names[n];
		}

		internal static string LocationName(int n)
		{
			if (n < 0)
			{
				return "Vanilla Inventory";
			}
			return SlotName(n);
		}

		internal static bool IsWearableSlot(int n)
		{
			if (n != 0 && n != 1 && n != 4 && n != 5 && n != 8 && n != 9 && n != 12)
			{
				return n == 13;
			}
			return true;
		}

		internal static bool IsArrowSlot(int n)
		{
			if (n != 2 && n != 6 && n != 10)
			{
				return n == 14;
			}
			return true;
		}

		internal static bool IsEquipmentStateSlot(int n)
		{
			if (!IsWearableSlot(n))
			{
				return IsArrowSlot(n);
			}
			return true;
		}

		internal static void ToggleMinimized()
		{
			if (minimized != null)
			{
				if (minimized.Value)
				{
					minimized.Value = false;
					compact.Value = false;
				}
				else
				{
					minimized.Value = true;
				}
			}
		}

		internal static void ToggleCompact()
		{
			if (compact != null)
			{
				if (minimized.Value)
				{
					minimized.Value = false;
					compact.Value = true;
				}
				else
				{
					compact.Value = !compact.Value;
				}
			}
		}

		internal static void SetNativeTransfer(bool value)
		{
			nativeTransfer = value;
		}

		internal static ItemData DraggedItem(InventoryGui gui)
		{
			if (!Object.op_Implicit((Object)(object)gui))
			{
				return null;
			}
			return DragItem.Invoke(gui);
		}

		internal static Inventory DraggedInventory(InventoryGui gui)
		{
			if (!Object.op_Implicit((Object)(object)gui))
			{
				return null;
			}
			return DragInventory.Invoke(gui);
		}

		internal static void ClearNativeDrag(InventoryGui gui)
		{
			if (Object.op_Implicit((Object)(object)gui))
			{
				ClearDrag(gui, null, null, 1);
			}
		}

		internal static void NotifyInventory()
		{
			if (Object.op_Implicit((Object)(object)owner))
			{
				Notify(((Humanoid)owner).GetInventory(), arg2: true, arg3: false);
			}
		}

		internal static void LogDrag(string message)
		{
			CorePlugin.LogEquipment("Drag " + message);
		}

		internal static void LogLayoutOnce(float width, float height, float horizontalInset, float verticalInset, float step)
		{
			if (!layoutLogged)
			{
				layoutLogged = true;
				CorePlugin.LogEquipment("Layout full panel=" + width.ToString("0.#") + "x" + height.ToString("0.#") + " inset=" + horizontalInset.ToString("0.#") + "," + verticalInset.ToString("0.#") + " step=" + step.ToString("0.#"));
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Save")]
	internal static class EqSave
	{
		[HarmonyPrefix]
		private static void Prefix(Player __instance)
		{
			EquipmentModule.SaveBackup(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "SetInventorySize")]
	internal static class EqResize
	{
		[HarmonyPrefix]
		private static void Prefix(Player __instance, ref int rows, out int __state)
		{
			EquipmentModule.PrepareResize(__instance, ref rows, out __state);
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance, int __state)
		{
			EquipmentModule.FinishResize(__instance, __state);
		}
	}
	[HarmonyPatch(typeof(Inventory), "FindEmptySlot")]
	internal static class EqEmpty
	{
		[HarmonyPostfix]
		private static void Postfix(Inventory __instance, ref Vector2i __result)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			int num = EquipmentModule.VisibleRows(__instance);
			if (num < 0)
			{
				return;
			}
			if (__result.y >= num)
			{
				__result = new Vector2i(-1, -1);
				for (int i = 0; i < num; i++)
				{
					if (__result.x >= 0)
					{
						break;
					}
					for (int j = 0; j < __instance.GetWidth(); j++)
					{
						if (__instance.GetItemAt(j, i) == null)
						{
							__result = new Vector2i(j, i);
							break;
						}
					}
				}
			}
			if (__result.x < 0)
			{
				EquipmentModule.DirectPosition(__instance, ref __result);
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int)
	})]
	internal static class EqCanDirect
	{
		[HarmonyPostfix]
		private static void Postfix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (!__result && EquipmentModule.CanDirectAdd(__instance, item))
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "Pickup")]
	internal static class EqDirectPickup
	{
		[HarmonyPrefix]
		private static void Prefix(Humanoid __instance, GameObject go)
		{
			EquipmentModule.BeginDirectPickup(__instance, go);
		}

		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, GameObject go, bool __result)
		{
			EquipmentModule.EndDirectPickup(__instance, go, __result);
		}
	}
	[HarmonyPatch(typeof(Inventory), "GetEmptySlots")]
	internal static class EqEmptyCount
	{
		[HarmonyPostfix]
		private static void Postfix(Inventory __instance, ref int __result)
		{
			int num = EquipmentModule.VisibleRows(__instance);
			if (num < 0)
			{
				return;
			}
			int num2 = 0;
			foreach (ItemData allItem in __instance.GetAllItems())
			{
				if (allItem.m_gridPos.y < num)
				{
					num2++;
				}
			}
			__result = num * __instance.GetWidth() - num2;
		}
	}
	[HarmonyPatch(typeof(Player), "Load")]
	internal static class EqLoad
	{
		[HarmonyPrefix]
		private static void Prefix(Player __instance)
		{
			EquipmentModule.BeginLoad(__instance);
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			EquipmentModule.EndLoad(__instance);
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Player __instance, Exception __exception)
		{
			EquipmentModule.EndLoad(__instance);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "SetupCharacterPreview")]
	internal static class EqPreview
	{
		[HarmonyPostfix]
		private static void Postfix(FejdStartup __instance)
		{
			EquipmentModule.ApplyPreviewVisuals(__instance.GetPreviewPlayer());
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class EqEquip
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(Humanoid __instance, ItemData item, ref bool __result, ref EquipmentModule.EquipState __state)
		{
			return EquipmentModule.BeforeEquip(__instance, item, ref __result, ref __state);
		}

		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, ItemData item, bool __result, EquipmentModule.EquipState __state)
		{
			EquipmentModule.AfterEquip(__instance, item, __result, __state);
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Humanoid __instance, EquipmentModule.EquipState __state, Exception __exception)
		{
			return EquipmentModule.FinishEquip(__instance, __state, __exception);
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
	internal static class EqUnequip
	{
		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, ItemData item)
		{
			EquipmentModule.AfterUnequip(__instance, item);
		}
	}
	[HarmonyPatch(typeof(Player), "RemoveEquipAction")]
	internal static class EqCancelQueuedAction
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance, ItemData item)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				EquipmentModule.CancelPendingAction(item);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "IsItemEquiped")]
	internal static class EqIsEquipped
	{
		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, ItemData item, ref bool __result)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			int num = EquipmentModule.SpecialIndex((Vector2i)(((??)item?.m_gridPos) ?? new Vector2i(-1, -1)));
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && !EquipmentModule.Restoring && !__result && (num == 9 || num == 13) && item.m_equipped)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UpdateEquipmentStatusEffects")]
	internal static class EqEffects
	{
		private static readonly FieldRef<Humanoid, HashSet<StatusEffect>> E = AccessTools.FieldRefAccess<Humanoid, HashSet<StatusEffect>>("m_equipmentStatusEffects");

		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			foreach (ItemData item in EquipmentModule.ExtraUtilities())
			{
				if (Object.op_Implicit((Object)(object)item.m_shared.m_equipStatusEffect))
				{
					StatusEffect equipStatusEffect = item.m_shared.m_equipStatusEffect;
					E.Invoke(__instance).Add(equipStatusEffect);
					((Character)Player.m_localPlayer).GetSEMan().AddStatusEffect(equipStatusEffect, false, 0, 0f, (short)(-1));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateModifiers")]
	internal static class EqModifiers
	{
		private static readonly FieldInfo S = AccessTools.Field(typeof(Player), "s_equipmentModifierSourceFields");

		private static readonly FieldRef<Player, float[]> V = AccessTools.FieldRefAccess<Player, float[]>("m_equipmentModifierValues");

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

		private static bool Resolve()
		{
			FieldInfo[] array = (FieldInfo[])S.GetValue(null);
			if (array == null)
			{
				return false;
			}
			if (getters != null && getters.Length == array.Length)
			{
				return true;
			}
			getters = new FieldRef<SharedData, float>[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				getters[i] = AccessTools.FieldRefAccess<SharedData, float>(array[i]);
			}
			return true;
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Resolve())
			{
				return;
			}
			float[] array = V.Invoke(__instance);
			if (array == null)
			{
				return;
			}
			foreach (ItemData item in EquipmentModule.ExtraUtilities())
			{
				for (int i = 0; i < array.Length && i < getters.Length; i++)
				{
					array[i] += getters[i].Invoke(item.m_shared);
				}
			}
		}
	}
	internal static class NativeEquipmentPanel
	{
		internal sealed class PanelDragHandle : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
		{
			private bool dragging;

			private float scale = 1f;

			private Vector2 draft;

			public void OnBeginDrag(PointerEventData e)
			{
				//IL_0001: 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_0016: Unknown result type (might be due to invalid IL or missing references)
				if ((int)e.button == 0)
				{
					dragging = true;
					draft = EquipmentModule.PanelPosition;
					Canvas componentInParent = ((Component)this).GetComponentInParent<Canvas>();
					scale = ((Object.op_Implicit((Object)(object)componentInParent) && componentInParent.scaleFactor > 0f) ? componentInParent.scaleFactor : 1f);
				}
			}

			public void OnDrag(PointerEventData e)
			{
				//IL_000b: 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_001c: 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_0026: 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 (dragging)
				{
					draft += e.delta / scale;
					position = draft;
					UpdateLayout();
				}
			}

			public void OnEndDrag(PointerEventData e)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				if (dragging)
				{
					dragging = false;
					EquipmentModule.PanelPosition = draft;
					position = null;
					UpdateLayout();
				}
			}

			private void OnDisable()
			{
				if (dragging)
				{
					OnEndDrag(null);
				}
			}
		}

		private struct LayoutSignature : IEquatable<LayoutSignature>
		{
			internal bool Mini;

			internal bool Compact;

			internal bool Touch;

			internal int BaseRows;

			internal int Width;

			internal int Elements;

			internal int FirstSpecial;

			internal int UnlockMask;

			internal float Step;

			internal Vector2 Position;

			public bool Equals(LayoutSignature x)
			{
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				if (Mini == x.Mini && Compact == x.Compact && Touch == x.Touch && BaseRows == x.BaseRows && Width == x.Width && Elements == x.Elements && FirstSpecial == x.FirstSpecial && UnlockMask == x.UnlockMask && Step == x.Step)
				{
					return Position == x.Position;
				}
				return false;
			}
		}

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

		private static InventoryGui gui;

		private static InventoryGrid grid;

		private static RectTransform background;

		private static RectTransform slotRoot;

		private static RectTransform hiddenRoot;

		private static Image sourceImage;

		private static Image targetImage;

		private static TMP_Text title;

		private static Button compactButton;

		private static Button minimizeButton;

		private static Vector2? position;

		private static int lastRows = -1;

		private static bool layoutValid;

		private static LayoutSignature lastLayout;

		private static Vector2 Base => (Vector2)(((??)position) ?? EquipmentModule.PanelPosition);

		internal static void Update(InventoryGrid candidate)
		{
			if (!Object.op_Implicit((Object)(object)InventoryGui.instance) || (Object)(object)candidate != (Object)(object)InventoryGui.instance.m_playerGrid || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			if ((Object)(object)gui != (Object)(object)InventoryGui.instance)
			{
				Clear();
				gui = InventoryGui.instance;
				grid = candidate;
			}
			Ensure();
			if (Object.op_Implicit((Object)(object)background) && Object.op_Implicit((Object)(object)slotRoot))
			{
				if (lastRows != EquipmentModule.BaseRows)
				{
					gui.SetInventorySize(EquipmentModule.BaseRows);
					lastRows = EquipmentModule.BaseRows;
					layoutValid = false;
				}
				grid.m_gridRoot.SetSizeWithCurrentAnchors((Axis)1, (float)EquipmentModule.BaseRows * grid.m_elementSpace);
				UpdateLayout();
			}
		}

		private static void Ensure()
		{
			//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)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)background))
			{
				return;
			}
			Transform obj = ((Transform)gui.m_player).Find("Bkg");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				sourceImage = ((Component)val).GetComponent<Image>();
				background = Object.Instantiate<RectTransform>(val, (Transform)(object)gui.m_player, false);
				((Object)background).name = "ValheimCore Equipment Bkg";
				RectTransform obj2 = background;
				RectTransform obj3 = background;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0f, 1f);
				obj3.anchorMax = val2;
				obj2.anchorMin = val2;
				background.pivot = new Vector2(0.5f, 0.5f);
				((Transform)background).localScale = Vector3.one;
				targetImage = ((Component)background).GetComponent<Image>();
				if (Object.op_Implicit((Object)(object)targetImage))
				{
					((Graphic)targetImage).raycastTarget = true;
				}
				((Component)background).gameObject.AddComponent<PanelDragHandle>();
				slotRoot = Root("ValheimCore Equipment Slots", (Transform)(object)background, active: true);
				slotRoot.anchorMin = Vector2.zero;
				slotRoot.anchorMax = Vector2.one;
				slotRoot.pivot = new Vector2(0.5f, 0.5f);
				val2 = (slotRoot.offsetMin = (slotRoot.offsetMax = Vector2.zero));
				hiddenRoot = Root("ValheimCore Hidden Equipment Cells", (Transform)(object)gui.m_player, active: false);
				hiddenRoot.anchoredPosition = new Vector2(-100000f, -100000f);
				title = NativeUi.Text((Transform)(object)background, gui.m_playerName, "Equipment", new Vector2(180f, 24f));
				title.alignment = (TextAlignmentOptions)513;
				((Graphic)title).raycastTarget = false;
				compactButton = Button("▦", EquipmentModule.ToggleCompact);
				minimizeButton = Button("_", EquipmentModule.ToggleMinimized);
				layoutValid = false;
			}
		}

		private static RectTransform Root(string name, Transform parent, bool active)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			val.SetActive(active);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			return val2;
		}

		private static Button Button(string text, Action action)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Equipment " + text, new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent((Transform)(object)background, false);
			Image component = val.GetComponent<Image>();
			Image val2 = (Object.op_Implicit((Object)(object)gui.m_dropButton) ? ((Component)gui.m_dropButton).GetComponent<Image>() : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				component.sprite = val2.sprite;
				component.overrideSprite = val2.overrideSprite;
				component.type = val2.type;
				((Graphic)component).material = ((Graphic)val2).material;
				((Graphic)component).color = ((Graphic)val2).color;
			}
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			if (Object.op_Implicit((Object)(object)gui.m_dropButton))
			{
				((Selectable)component2).colors = ((Selectable)gui.m_dropButton).colors;
				((Selectable)component2).transition = ((Selectable)gui.m_dropButton).transition;
			}
			((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
			{
				action();
			});
			NativeUi.Text(val.transform, gui.m_playerName, text, new Vector2(24f, 22f)).rectTransform.anchoredPosition = Vector2.zero;
			return component2;
		}

		internal static void UpdateLayout()
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)gui) || !Object.op_Implicit((Object)(object)grid) || !Object.op_Implicit((Object)(object)background))
			{
				return;
			}
			List<InventoryElement> list = Elements.Invoke(grid);
			int width = grid.GetInventory().GetWidth();
			int num = EquipmentModule.BaseRows * width;
			int firstSpecial = ((num >= 0 && num < list.Count && Object.op_Implicit((Object)(object)list[num])) ? ((Object)list[num]).GetInstanceID() : 0);
			int num2 = 0;
			for (int i = 0; i < 16; i++)
			{
				if (EquipmentModule.Unlocked(i))
				{
					num2 |= 1 << i;
				}
			}
			bool minimized = EquipmentModule.Minimized;
			bool flag = EquipmentModule.Compact && !minimized;
			LayoutSignature x = new LayoutSignature
			{
				Mini = minimized,
				Compact = flag,
				Touch = ZInput.IsTouchActive(),
				BaseRows = EquipmentModule.BaseRows,
				Width = width,
				Elements = list.Count,
				FirstSpecial = firstSpecial,
				UnlockMask = num2,
				Step = grid.m_elementSpace,
				Position = Base
			};
			if (layoutValid && lastLayout.Equals(x))
			{
				return;
			}
			lastLayout = x;
			layoutValid = true;
			float num3 = Mathf.Max(60f, grid.m_elementSpace);
			float num4 = 8f;
			float num5 = 30f;
			bool flag2 = !minimized && !flag;
			int num6 = (flag ? 2 : 4);
			int num7 = ((!minimized) ? 4 : 0);
			float num8 = (flag2 ? 20 : 0);
			float num9 = num5 + (float)num7 * num3 + (flag2 ? (num8 * 2f) : num4);
			float num10 = (flag2 ? num9 : Mathf.Max(150f, (float)num6 * num3 + num4 * 2f));
			float num11 = (flag2 ? ((num10 - (float)num6 * num3) / 2f) : num4);
			Vector2 val = Base;
			SyncBackground();
			background.sizeDelta = new Vector2(num10, num9);
			background.anchoredPosition = val + new Vector2(num10 / 2f, (0f - num9) / 2f);
			Place((Component)(object)title, new Vector2(10f + (num10 - 70f) / 2f, -15f), new Vector2(num10 - 70f, 24f));
			Place((Component)(object)compactButton, new Vector2(num10 - 43f, -15f), new Vector2(24f, 22f));
			Place((Component)(object)minimizeButton, new Vector2(num10 - 16f, -15f), new Vector2(24f, 22f));
			NativeUi.SetButtonText(minimizeButton, minimized ? "□" : "_");
			int num12 = 0;
			EquipmentModule.LogLayoutOnce(num10, num9, num11, num8, num3);
			Vector2 val3 = default(Vector2);
			for (int j = 0; j < 16; j++)
			{
				int num13 = num + j;
				if (num13 < 0 || num13 >= list.Count)
				{
					continue;
				}
				InventoryElement val2 = list[num13];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)val2).gameObject;
				if (!Shown(j, minimized, flag))
				{
					Park(gameObject);
					continue;
				}
				gameObject.SetActive(true);
				if ((Object)(object)gameObject.transform.parent != (Object)(object)slotRoot)
				{
					gameObject.transform.SetParent((Transform)(object)slotRoot, false);
				}
				RectTransform elementRectTransform = val2.GetElementRectTransform();
				((Vector2)(ref val3))..ctor(0f, 1f);
				elementRectTransform.anchorMax = val3;
				elementRectTransform.anchorMin = val3;
				elementRectTransform.pivot = new Vector2(0.5f, 0.5f);
				((Transform)elementRectTransform).localScale = Vector3.one;
				int num14 = (flag ? num12++ : j);
				int num15 = (flag ? (num14 % 2) : (num14 % 4));
				int num16 = (flag ? (num14 / 2) : (num14 / 4));
				float num17 = (flag2 ? num11 : num4);
				float num18 = num5 + (flag2 ? num8 : 0f);
				elementRectTransform.anchoredPosition = new Vector2(num17 + num3 * 0.5f + (float)num15 * num3, 0f - num18 - num3 * 0.5f - (float)num16 * num3);
				((Selectable)val2.m_button).interactable = EquipmentModule.Unlocked(j);
				SetLabel(gameObject, j);
			}
			for (int k = num + 16; k < list.Count; k++)
			{
				if ((Object)(object)list[k] != (Object)null)
				{
					Park(((Component)list[k]).gameObject);
				}
			}
			((Transform)background).SetAsLastSibling();
			((Transform)slotRoot).SetAsLastSibling();
			title.transform.SetAsLastSibling();
			((Component)compactButton).transform.SetAsLastSibling();
			((Component)minimizeButton).transform.SetAsLastSibling();
		}

		private static bool Shown(int n, bool mini, bool compact)
		{
			if (!mini)
			{
				if (compact)
				{
					return n % 4 >= 2;
				}
				return true;
			}
			return false;
		}

		private static void SyncBackground()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)sourceImage) && Object.op_Implicit((Object)(object)targetImage))
			{
				targetImage.sprite = sourceImage.sprite;
				targetImage.overrideSprite = sourceImage.overrideSprite;
				((Graphic)targetImage).color = ((Graphic)sourceImage).color;
				((Graphic)targetImage).material = ((Graphic)sourceImage).material;
				targetImage.type = sourceImage.type;
				targetImage.preserveAspect = sourceImage.preserveAspect;
				targetImage.fillCenter = sourceImage.fillCenter;
				targetImage.pixelsPerUnitMultiplier = sourceImage.pixelsPerUnitMultiplier;
			}
		}

		private static void SetLabel(GameObject go, int n)
		{
			Transform val = go.transform.Find("binding");
			if (Object.op_Implicit((Object)(object)val))
			{
				TMP_Text component = ((Component)val).GetComponent<TMP_Text>();
				if (Object.op_Implicit((Object)(object)component))
				{
					((Behaviour)component).enabled = true;
					component.text = EquipmentModule.SlotName(n);
					component.enableAutoSizing = true;
					component.fontSizeMin = 8f;
					component.fontSizeMax = 12f;
					component.alignment = (TextAlignmentOptions)1026;
					((Graphic)component).raycastTarget = false;
				}
			}
		}

		private static void Park(GameObject go)
		{
			if (Object.op_Implicit((Object)(object)go))
			{
				go.SetActive(false);
				if (Object.op_Implicit((Object)(object)hiddenRoot) && (Object)(object)go.transform.parent != (Object)(object)hiddenRoot)
				{
					go.transform.SetParent((Transform)(object)hiddenRoot, false);
				}
			}
		}

		private static void Place(Component c, Vector2 center, Vector2 size)
		{
			//IL_000f: 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_0015: 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_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)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0050: 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)
			if (Object.op_Implicit((Object)(object)c))
			{
				RectTransform val = (RectTransform)c.transform;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0f, 1f);
				val.anchorMax = val2;
				val.anchorMin = val2;
				val.pivot = new Vector2(0.5f, 0.5f);
				val.anchoredPosition = center;
				val.sizeDelta = size;
				((Transform)val).localScale = Vector3.one;
			}
		}

		internal static void Clear()
		{
			if (Object.op_Implicit((Object)(object)grid) && Object.op_Implicit((Object)(object)grid.m_gridRoot))
			{
				if (Object.op_Implicit((Object)(object)slotRoot))
				{
					while (((Transform)slotRoot).childCount > 0)
					{
						((Transform)slotRoot).GetChild(0).SetParent((Transform)(object)grid.m_gridRoot, false);
					}
				}
				if (Object.op_Implicit((Object)(object)hiddenRoot))
				{
					while (((Transform)hiddenRoot).childCount > 0)
					{
						((Transform)hiddenRoot).GetChild(0).SetParent((Transform)(object)grid.m_gridRoot, false);
					}
				}
			}
			Destroy((Object)(object)background);
			Destroy((Object)(object)hiddenRoot);
			background = (slotRoot = (hiddenRoot = null));
			sourceImage = (targetImage = null);
			title = null;
			compactButton = (minimizeButton = null);
			gui = null;
			grid = null;
			position = null;
			lastRows = -1;
			layoutValid = false;
			lastLayout = default(LayoutSignature);
		}

		private static void Destroy(Object o)
		{
			if (Object.op_Implicit(o))
			{
				Object.Destroy(o);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
	internal static class NativeEquipmentGridUpdate
	{
		[HarmonyPostfix]
		private static void Postfix(InventoryGrid __instance)
		{
			NativeEquipmentPanel.Update(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnDestroy")]
	internal static class NativeEquipmentCleanup
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			NativeEquipmentPanel.Clear();
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
	internal static class NativeEquipmentDropRules
	{
		[HarmonyPrefix]
		private static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, Vector2i pos)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid || item == null)
			{
				return true;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (__instance.GetInventory() != inventory)
			{
				return true;
			}
			int num = EquipmentModule.SpecialIndex(pos);
			if (num >= 0 && (!EquipmentModule.Unlocked(num) || !EquipmentModule.Fits(num, item)))
			{
				return false;
			}
			if (fromInventory == inventory)
			{
				int num2 = EquipmentModule.SpecialIndex(item.m_gridPos);
				ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
				if (num2 >= 0 && itemAt != null && itemAt != item && !EquipmentModule.Fits(num2, itemAt))
				{
					return false;
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	internal static class NativeEquipmentDragTransition
	{
		internal struct State
		{
			internal bool Active;

			internal ItemData Drag;

			internal SharedData DragShared;

			internal int To;

			internal Vector2i TargetPos;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(InventoryGui __instance, InventoryGrid grid, Vector2i pos, out State __state)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			__state = default(State);
			Player localPlayer = Player.m_localPlayer;
			ItemData val = EquipmentModule.DraggedItem(__instance);
			Inventory val2 = EquipmentModule.DraggedInventory(__instance);
			if (!Object.op_Implicit((Object)(object)localPlayer) || val == null || (Object)(object)grid == (Object)null || val2 == null)
			{
				return true;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			bool flag = val2 == inventory;
			bool flag2 = grid.GetInventory() == inventory;
			int num = (flag ? EquipmentModule.SpecialIndex(val.m_gridPos) : (-1));
			int num2 = (flag2 ? EquipmentModule.SpecialIndex(pos) : (-1));
			if (num < 0 && num2 < 0)
			{
				return true;
			}
			ItemData itemAt = grid.GetInventory().GetItemAt(pos.x, pos.y);
			bool flag3 = ((Humanoid)localPlayer).IsItemEquiped(val);
			EquipmentModule.LogDrag("BEGIN " + val.m_shared.m_name + " " + EquipmentModule.LocationName(num) + " -> " + EquipmentModule.LocationName(num2));
			if (num2 >= 0 && EquipmentModule.IsEquipmentStateSlot(num2) && !flag3)
			{
				if (!EquipmentModule.Unlocked(num2) || !EquipmentModule.Fits(num2, val))
				{
					return false;
				}
				if (flag)
				{
					EquipmentModule.ClearNativeDrag(__instance);
					EquipmentModule.LogDrag("END native equip queued=" + EquipmentModule.QueueNativeEquip(val, num2));
					return false;
				}
				__state = new State
				{
					Active = true,
					Drag = val,
					DragShared = val.m_shared,
					To = num2,
					TargetPos = pos
				};
				EquipmentModule.SetNativeTransfer(value: true);
				return true;
			}
			if (num >= 0 && EquipmentModule.IsEquipmentStateSlot(num) && flag3 && flag2 && num2 < 0)
			{
				if (itemAt == null)
				{
					EquipmentModule.ClearNativeDrag(__instance);
					EquipmentModule.LogDrag("END native unequip queued=" + EquipmentModule.QueueNativeUnequip(val, pos));
					return false;
				}
				if (itemAt != val && EquipmentModule.Fits(num, itemAt) && !((Humanoid)localPlayer).IsItemEquiped(itemAt))
				{
					EquipmentModule.ClearNativeDrag(__instance);
					EquipmentModule.LogDrag("END native replacement queued=" + EquipmentModule.QueueNativeEquip(itemAt, num));
					return false;
				}
				EquipmentModule.LogDrag("END rejected: occupied Vanilla destination");
				return false;
			}
			__state = new State
			{
				Active = true,
				Drag = val,
				DragShared = val.m_shared,
				To = -1,
				TargetPos = pos
			};
			EquipmentModule.SetNativeTransfer(value: true);
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(State __state)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!__state.Active)
			{
				return;
			}
			EquipmentModule.SetNativeTransfer(value: false);
			if (__state.To >= 0)
			{
				Player localPlayer = Player.m_localPlayer;
				if (Object.op_Implicit((Object)(object)localPlayer))
				{
					ItemData val = At(((Humanoid)localPlayer).GetInventory(), __state.TargetPos, __state.Drag, __state.DragShared);
					EquipmentModule.LogDrag("END external native equip queued=" + (val != null && EquipmentModule.QueueNativeEquip(val, __state.To)));
				}
			}
		}

		private static ItemData At(Inventory inventory, Vector2i pos, ItemData preferred, SharedData shared)
		{
			//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(pos.x, pos.y);
			if (itemAt == preferred)
			{
				return itemAt;
			}
			if (itemAt == null || itemAt.m_shared != shared)
			{
				return null;
			}
			return itemAt;
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Exception __exception)
		{
			EquipmentModule.SetNativeTransfer(value: false);
			return __exception;
		}
	}
}
namespace GoblinHeim.CoreTame
{
	internal static class TameRules
	{
		internal static float Factor(float value)
		{
			value = Mathf.Clamp(value, -100f, 100f);
			if (value <= -100f)
			{
				return 0f;
			}
			if (value >= 100f)
			{
				return float.MaxValue;
			}
			if (!(value < 0f))
			{
				return 1f / (1f - value / 100f);
			}
			return 1f + value / 100f;
		}

		internal static float Duration(float vanilla, float percent)
		{
			float num = Factor(percent);
			if (!(num <= 0f))
			{
				if (num != float.MaxValue)
				{
					return vanilla / num;
				}
				return 0f;
			}
			return float.MaxValue;
		}
	}
	[HarmonyPatch(typeof(Tameable), "DecreaseRemainingTime")]
	internal static class TamingSpeedPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref float time)
		{
			time *= TameRules.Factor(CorePlugin.Settings.TamingSpeed);
		}
	}
	[HarmonyPatch(typeof(Growup), "GrowUpdate")]
	internal static class GrowthSpeedPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Growup __instance, out float __state)
		{
			__state = __instance.m_growTime;
			__instance.m_growTime = TameRules.Duration(__state, CorePlugin.Settings.GrowthSpeed);
		}

		[HarmonyPostfix]
		private static void Postfix(Growup __instance, float __state)
		{
			__instance.m_growTime = __state;
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Growup __instance, float __state, Exception __exception)
		{
			__instance.m_growTime = __state;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(EggGrow), "GrowUpdate")]
	internal static class EggGrowthSpeedPatch
	{
		[HarmonyPrefix]
		private static void Prefix(EggGrow __instance, out float __state)
		{
			__state = __instance.m_growTime;
			__instance.m_growTime = TameRules.Duration(__state, CorePlugin.Settings.GrowthSpeed);
		}

		[HarmonyPostfix]
		private static void Postfix(EggGrow __instance, float __state)
		{
			__instance.m_growTime = __state;
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(EggGrow __instance, float __state, Exception __exception)
		{
			__instance.m_growTime = __state;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class BirthScopePatch
	{
		internal struct State
		{
			internal int LovePoints;

			internal float PregnancyDuration;
		}

		[ThreadStatic]
		internal static bool Active;

		[HarmonyPrefix]
		private static bool Prefix(Procreation __instance, out State __state)
		{
			Active = true;
			__state = new State
			{
				LovePoints = __instance.m_requiredLovePoints,
				PregnancyDuration = __instance.m_pregnancyDuration
			};
			float num = TameRules.Factor(CorePlugin.Settings.BirthSpeed);
			if (num <= 0f)
			{
				return false;
			}
			__instance.m_requiredLovePoints = ((num == float.MaxValue) ? 1 : Math.Max(1, (int)Math.Ceiling((float)__state.LovePoints / num)));
			__instance.m_pregnancyDuration = TameRules.Duration(__state.PregnancyDuration, CorePlugin.Settings.BirthSpeed);
			return true;
		}

		[HarmonyPostfix]
		private static void Postfix(Procreation __instance, State __state)
		{
			__instance.m_requiredLovePoints = __state.LovePoints;
			__instance.m_pregnancyDuration = __state.PregnancyDuration;
			Active = false;
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Procreation __instance, State __state, Exception __exception)
		{
			__instance.m_requiredLovePoints = __state.LovePoints;
			__instance.m_pregnancyDuration = __state.PregnancyDuration;
			Active = false;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Character), "SetLevel", new Type[] { typeof(int) })]
	internal static class OffspringStarPatch
	{
		[HarmonyPrefix]
		private static void Pr