Decompiled source of GearSlots v0.5.1

GearSlots.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GearSlots.Configuration;
using GearSlots.Core;
using GearSlots.Patches;
using GearSlots.Runtime;
using GearSlots.UI;
using HarmonyLib;
using JG224.ModCore.API;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("GearSlots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.1.0")]
[assembly: AssemblyInformationalVersion("0.5.1")]
[assembly: AssemblyProduct("GearSlots")]
[assembly: AssemblyTitle("GearSlots")]
[assembly: AssemblyVersion("0.5.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GearSlots
{
	public static class GearSlotsApi
	{
		public static bool IsProtected(ItemData? item)
		{
			if (item != null)
			{
				return SlotStateManager.ContainsAuxiliaryItem(item);
			}
			return false;
		}

		public static bool IsProtectedInventory(Inventory? inventory)
		{
			if (inventory != null)
			{
				return SlotStateManager.IsAuxiliaryInventory(inventory);
			}
			return false;
		}
	}
	[BepInPlugin("com.jg224.gearslots", "GearSlots", "0.5.1")]
	[BepInDependency("com.jg224.modcore", "0.5.0")]
	[BepInProcess("valheim.exe")]
	public sealed class GearSlotsPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.jg224.gearslots";

		public const string PluginName = "GearSlots";

		public const string PluginVersion = "0.5.1";

		public const string ModCoreGuid = "com.jg224.modcore";

		public const int ProtocolVersion = 1;

		public static readonly ModuleId ModuleId = new ModuleId("gearslots");

		private static readonly IReadOnlyDictionary<string, string> ConflictingPlugins = new Dictionary<string, string>(StringComparer.Ordinal)
		{
			["Azumatt.AzuExtendedPlayerInventory"] = "AzuExtendedPlayerInventory",
			["randyknapp.mods.equipmentandquickslots"] = "Equipment and Quick Slots",
			["aedenthorn.ExtendedPlayerInventory"] = "Extended Player Inventory",
			["com.bruce.valheim.comfyquickslots"] = "Comfy Quick Slots",
			["shudnal.ExtraSlots"] = "Extra Slots",
			["shudnal.ExtraSlotsCustomSlots"] = "Extra Slots Custom Slots",
			["moreslots"] = "More Slots",
			["toombe.EquipMultipleUtilityItemsUpdate"] = "Equip Multiple Utility Items Update",
			["aedenthorn.EquipMultipleUtilityItems"] = "Equip Multiple Utility Items"
		};

		private Harmony? harmony;

		private readonly List<IDisposable> registrations = new List<IDisposable>();

		private bool shutDown;

		internal static ManualLogSource ModLog { get; private set; } = null;

		internal static GearSlotsConfig Settings { get; private set; } = null;

		internal static ICoreServices Core { get; private set; } = null;

		private void Awake()
		{
			//IL_022a: 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_005f: 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_0071: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Expected O, but got Unknown
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			ModLog = ((BaseUnityPlugin)this).Logger;
			try
			{
				if (!ModCoreApi.IsAvailable)
				{
					throw new InvalidOperationException("ModCore did not initialize before GearSlots.");
				}
				SemanticVersion val = default(SemanticVersion);
				if (!SemanticVersion.TryParse("0.5.1", ref val))
				{
					throw new InvalidOperationException("GearSlots has an invalid plugin version.");
				}
				Core = ModCoreApi.Services;
				registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "com.jg224.gearslots", "GearSlots", val, 1, (ModuleSide)1, (ModuleRequirement)1, 0uL, 1, 1)));
				registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)3, "com.jg224.gearslots.", 1, Array.Empty<string>()));
				registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)2, "com.jg224.gearslots.", 1, Array.Empty<string>()));
				registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)8, "gearslots.", 1, Array.Empty<string>()));
				registrations.Add(Core.Ui.Reserve(new UiReservation(ModuleId, (UiSurface)4, "dedicated-equipment-and-quick-slots", 30, false)));
				registrations.Add(Core.Ui.Reserve(new UiReservation(ModuleId, (UiSurface)1, "guardian-adjacent.quick-slots", 30, false)));
				Settings = new GearSlotsConfig(ConfigFileMigration.Open((BaseUnityPlugin)(object)this, Paths.ConfigPath, ((BaseUnityPlugin)this).Logger));
				Settings.Changed += SlotStateManager.NotifyConfigurationChanged;
				SlotStateManager.Initialize();
				NamedLoadouts.Register();
				harmony = new Harmony("com.jg224.gearslots");
				harmony.PatchAll(typeof(GearSlotsPlugin).Assembly);
				WarnAboutSlotProviders();
				Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Client-local protected slots, persistence, and UI hooks ready.");
				Game.isModded = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"GearSlots 0.5.1 loaded for BepInEx 5.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("{0} failed to initialize safely: {1}", "GearSlots", ex));
				if (Core != null)
				{
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message);
				}
				Shutdown();
				throw;
			}
		}

		private void Update()
		{
			SlotStateManager.Tick();
		}

		private void OnDestroy()
		{
			Shutdown();
		}

		private void OnGUI()
		{
			GearSlotsRecoveryScreen.Draw();
		}

		private void Shutdown()
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (shutDown)
			{
				return;
			}
			shutDown = true;
			if (Settings != null)
			{
				Settings.Changed -= SlotStateManager.NotifyConfigurationChanged;
			}
			SlotStateManager.Shutdown();
			GearSlotsRecoveryScreen.Close();
			GearSlotsUi.Destroy();
			GearSlotsUi.DestroyHud();
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			harmony = null;
			for (int num = registrations.Count - 1; num >= 0; num--)
			{
				try
				{
					registrations[num].Dispose();
				}
				catch (Exception ex)
				{
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					if (logger != null)
					{
						logger.LogWarning((object)("Registration cleanup failed: " + ex.Message));
					}
				}
			}
			registrations.Clear();
			if (Core != null)
			{
				Core.Metrics.RemoveOwner(ModuleId);
			}
			Core = null;
			Settings = null;
		}

		private void WarnAboutSlotProviders()
		{
			foreach (KeyValuePair<string, string> conflictingPlugin in ConflictingPlugins)
			{
				if (Chainloader.PluginInfos.ContainsKey(conflictingPlugin.Key))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("GearSlots detected " + conflictingPlugin.Value + " (" + conflictingPlugin.Key + "). Both mods provide overlapping equipment or quick slots; disable one provider before playing this character."));
				}
			}
		}
	}
}
namespace GearSlots.UI
{
	internal static class GearSlotsRecoveryScreen
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static WindowFunction <0>__DrawWindow;
		}

		private static bool open;

		private static Rect window = new Rect(240f, 180f, 460f, 255f);

		private static string result = "";

		internal static void Open()
		{
			open = true;
			result = "";
		}

		internal static void Close()
		{
			open = false;
		}

		internal static void Draw()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			if (open && InventoryGui.IsVisible())
			{
				Color backgroundColor = GUI.backgroundColor;
				GUI.backgroundColor = new Color(0.25f, 0.2f, 0.14f, 1f);
				Rect val = window;
				object obj = <>O.<0>__DrawWindow;
				if (obj == null)
				{
					WindowFunction val2 = DrawWindow;
					<>O.<0>__DrawWindow = val2;
					obj = (object)val2;
				}
				window = GUILayout.Window(224102, val, (WindowFunction)obj, "GearSlots — Recovery", Array.Empty<GUILayoutOption>());
				GUI.backgroundColor = backgroundColor;
			}
		}

		private static void DrawWindow(int id)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				wordWrap = true
			};
			GUILayout.Label(SlotStateManager.RecoveryStatus, val, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Return all moves complete stacks into empty main-inventory cells. If they will not all fit, everything stays where it is.", val, Array.Empty<GUILayoutOption>());
			bool enabled = GUI.enabled;
			GUI.enabled = enabled && !SlotStateManager.RecoveryBlocked;
			if (GUILayout.Button("Return all to inventory", Array.Empty<GUILayoutOption>()))
			{
				result = NamedLoadouts.ReturnAll();
			}
			GUI.enabled = enabled;
			GUI.enabled = enabled && SlotStateManager.CanRetryRecovery;
			if (GUILayout.Button("Retry load from preserved character data", Array.Empty<GUILayoutOption>()))
			{
				SlotStateManager.RetryRecovery();
			}
			GUI.enabled = enabled;
			if (result.Length != 0)
			{
				GUILayout.Label(result, val, Array.Empty<GUILayoutOption>());
			}
			if (GUILayout.Button("Close", Array.Empty<GUILayoutOption>()))
			{
				Close();
			}
			GUI.DragWindow();
		}
	}
	internal static class GearSlotsUi
	{
		private sealed class QuickHudElement
		{
			internal GameObject GameObject;

			internal Image Icon;

			internal GuiBar Durability;

			internal TMP_Text Amount;

			internal TMP_Text Binding;

			internal GameObject Equipped;

			internal GameObject Queued;

			internal GameObject Selection;

			internal UITooltip? Tooltip;
		}

		private const string GearGridName = "GearSlots_DedicatedGrid";

		private const string QuickGridName = "GearSlots_QuickGrid";

		private const string QuickHudName = "GearSlots_QuickHud";

		private const string LabelName = "GearSlots_EmptyLabel";

		private const string UtilityHeaderName = "GearSlots_UtilityHeader";

		private const string GearHeaderName = "GearSlots_GearHeader";

		private const float InventoryPanelMargin = 8f;

		private const float DedicatedHeaderHeight = 24f;

		private const int DedicatedColumns = 2;

		private const int DedicatedRows = 5;

		private static readonly MethodInfo SetupDragItemMethod = AccessTools.Method(typeof(InventoryGui), "SetupDragItem", new Type[3]
		{
			typeof(ItemData),
			typeof(Inventory),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo ShowSplitDialogMethod = AccessTools.Method(typeof(InventoryGui), "ShowSplitDialog", new Type[2]
		{
			typeof(ItemData),
			typeof(Inventory)
		}, (Type[])null);

		private static readonly MethodInfo OnSelectedItemMethod = AccessTools.Method(typeof(InventoryGui), "OnSelectedItem", new Type[4]
		{
			typeof(InventoryGrid),
			typeof(ItemData),
			typeof(Vector2i),
			typeof(Modifier)
		}, (Type[])null);

		private static readonly MethodInfo OnRightClickItemMethod = AccessTools.Method(typeof(InventoryGui), "OnRightClickItem", new Type[3]
		{
			typeof(InventoryGrid),
			typeof(ItemData),
			typeof(Vector2i)
		}, (Type[])null);

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

		private static readonly FieldInfo SelectedPositionField = AccessTools.Field(typeof(InventoryGrid), "m_selected");

		private static readonly FieldInfo DragObjectField = AccessTools.Field(typeof(InventoryGui), "m_dragGo");

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

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

		private static readonly List<RaycastResult> PointerRaycastResults = new List<RaycastResult>();

		private static InventoryGui? inventoryGui;

		private static GameObject? gearGridObject;

		private static GameObject? quickGridObject;

		private static InventoryGrid? gearGrid;

		private static InventoryGrid? quickGrid;

		private static Hud? hud;

		private static HotkeyBar? nativeHotkeyBar;

		private static RectTransform? quickHudRoot;

		private static readonly List<QuickHudElement> QuickHudElements = new List<QuickHudElement>();

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

		private static bool dirty = true;

		private static bool inventoryLayoutLogged;

		private static bool inventoryVisualsLogged;

		internal static void Create(InventoryGui gui)
		{
			Destroy();
			inventoryGui = gui;
			gearGrid = CreateGrid(gui, "GearSlots_DedicatedGrid", out gearGridObject);
			quickGrid = CreateGrid(gui, "GearSlots_QuickGrid", out quickGridObject);
			SetGridSize(gearGrid, 2, 5, 24f);
			SetGridSize(quickGrid, 3, 1, 0f);
			AppendGamepadGroups(gui, gearGrid.m_uiGroup, quickGrid.m_uiGroup);
			ApplyConfiguration();
			BindInventories();
			EnsureQuickHud();
		}

		internal static void Destroy()
		{
			if ((Object)(object)gearGridObject != (Object)null)
			{
				Object.Destroy((Object)(object)gearGridObject);
			}
			if ((Object)(object)quickGridObject != (Object)null)
			{
				Object.Destroy((Object)(object)quickGridObject);
			}
			inventoryGui = null;
			gearGridObject = null;
			quickGridObject = null;
			gearGrid = null;
			quickGrid = null;
			dirty = true;
			inventoryLayoutLogged = false;
			inventoryVisualsLogged = false;
		}

		internal static void CreateHud(Hud instance)
		{
			DestroyHud();
			hud = instance;
			EnsureQuickHud();
		}

		internal static void DestroyHud()
		{
			if ((Object)(object)quickHudRoot != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)quickHudRoot).gameObject);
			}
			hud = null;
			nativeHotkeyBar = null;
			quickHudRoot = null;
			QuickHudElements.Clear();
			dirty = true;
		}

		internal static void BindInventories()
		{
			dirty = true;
			Refresh();
		}

		internal static void UnbindInventories()
		{
			dirty = true;
		}

		internal static void MarkDirty()
		{
			dirty = true;
		}

		internal static void Tick()
		{
			EnsureQuickHud();
			bool flag = (Object)(object)inventoryGui != (Object)null && InventoryGui.IsVisible();
			InventoryGui? obj = inventoryGui;
			bool active = SlotPanelLayout.ShouldShowAuxiliaryPanels(flag, obj != null && obj.IsSkillsPanelOpen);
			if ((Object)(object)gearGridObject != (Object)null)
			{
				gearGridObject.SetActive(active);
			}
			if ((Object)(object)quickGridObject != (Object)null)
			{
				quickGridObject.SetActive(active);
			}
			if (flag)
			{
				PositionInventoryGrids();
			}
			if ((Object)(object)quickHudRoot != (Object)null)
			{
				Player currentPlayer = SlotStateManager.CurrentPlayer;
				((Component)quickHudRoot).gameObject.SetActive(!flag && (Object)(object)currentPlayer != (Object)null && !((Character)currentPlayer).IsDead());
				PositionQuickHud();
			}
			Refresh(force: true);
		}

		internal static void ApplyConfiguration()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gearGridObject != (Object)null && (Object)(object)quickGridObject != (Object)null)
			{
				float num = Mathf.Clamp(GearSlotsPlugin.Settings.UiScale.Value, 0.5f, 1.5f);
				((Transform)gearGridObject.GetComponent<RectTransform>()).localScale = Vector3.one * num;
				((Transform)quickGridObject.GetComponent<RectTransform>()).localScale = Vector3.one * num;
				PositionInventoryGrids();
			}
			PositionQuickHud();
			dirty = true;
		}

		internal static bool HandleSelected(InventoryGui gui, InventoryGrid selectedGrid, ItemData? selectedItem, Vector2i position, Modifier modifier, GameObject? dragObject, ItemData? dragItem, Inventory? dragInventory, int dragAmount)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Invalid comparison between Unknown and I4
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Invalid comparison between Unknown and I4
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			bool flag = SlotStateManager.IsAuxiliaryInventory(selectedGrid.GetInventory());
			bool flag2 = dragInventory != null && SlotStateManager.IsAuxiliaryInventory(dragInventory);
			if (!flag && !flag2)
			{
				return false;
			}
			Player currentPlayer = SlotStateManager.CurrentPlayer;
			if ((Object)(object)currentPlayer == (Object)null || ((Character)currentPlayer).IsTeleporting())
			{
				return true;
			}
			if ((Object)(object)dragObject != (Object)null && dragItem != null && dragInventory != null)
			{
				if (!dragInventory.GetAllItems().Contains(dragItem))
				{
					ClearDrag(gui);
					return true;
				}
				if ((!flag) ? SlotTransferService.TryDropOnRegularGrid(selectedGrid, dragInventory, dragItem, dragAmount, position) : (SlotStateManager.TryGetSlot(selectedGrid.GetInventory(), position, out var slot) && SlotTransferService.TryPlaceInSlot(dragInventory, dragItem, dragAmount, slot)))
				{
					PlayMoveEffect(gui);
					ClearDrag(gui);
				}
				return true;
			}
			if (!flag || selectedItem == null)
			{
				return true;
			}
			if ((int)modifier == 1)
			{
				OpenSplitDialog(gui, selectedItem, selectedGrid.GetInventory());
				return true;
			}
			if ((int)modifier != 2)
			{
				if ((int)modifier == 3)
				{
					if (SlotTransferService.TryDropAtPlayer(selectedItem))
					{
						PlayMoveEffect(gui);
					}
				}
				else
				{
					SetupDragItemMethod.Invoke(gui, new object[3]
					{
						selectedItem,
						selectedGrid.GetInventory(),
						selectedItem.m_stack
					});
				}
			}
			else if (SlotTransferService.TryMoveItemToMain(selectedItem))
			{
				PlayMoveEffect(gui);
			}
			return true;
		}

		internal static bool HandleRightClick(InventoryGrid grid, ItemData? item, Vector2i position)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!SlotStateManager.IsAuxiliaryInventory(grid.GetInventory()))
			{
				return false;
			}
			if (item != null && SlotStateManager.TryGetSlot(grid.GetInventory(), position, out var slot))
			{
				if (SlotRuleEngine.IsQuick(slot))
				{
					SlotStateManager.UseQuickSlot((int)(slot - 6));
				}
				else if (SlotTransferService.TryMoveItemToMain(item) && (Object)(object)inventoryGui != (Object)null)
				{
					PlayMoveEffect(inventoryGui);
				}
			}
			return true;
		}

		internal static bool HandleDedicatedGamepad(InventoryGrid grid)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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)
			if (grid != gearGrid)
			{
				return false;
			}
			if ((Object)(object)grid.m_uiGroup == (Object)null || !grid.m_uiGroup.IsActive || Console.IsVisible())
			{
				return true;
			}
			Vector2i val = (Vector2i)SelectedPositionField.GetValue(grid);
			int num = Mathf.Clamp(val.x, 0, SlotRuleEngine.DedicatedSlots.Count - 1);
			if (ZInput.GetButtonDown("JoyDPadUp") || ZInput.GetButtonDown("JoyLStickUp"))
			{
				num = DedicatedPanelLayout.GetNeighborIndex(num, PanelDirection.Up);
			}
			if (ZInput.GetButtonDown("JoyDPadDown") || ZInput.GetButtonDown("JoyLStickDown"))
			{
				num = DedicatedPanelLayout.GetNeighborIndex(num, PanelDirection.Down);
			}
			if (ZInput.GetButtonDown("JoyDPadLeft") || ZInput.GetButtonDown("JoyLStickLeft"))
			{
				num = DedicatedPanelLayout.GetNeighborIndex(num, PanelDirection.Left);
			}
			if (ZInput.GetButtonDown("JoyDPadRight") || ZInput.GetButtonDown("JoyLStickRight"))
			{
				num = DedicatedPanelLayout.GetNeighborIndex(num, PanelDirection.Right);
			}
			((Vector2i)(ref val))..ctor(num, 0);
			SelectedPositionField.SetValue(grid, val);
			Inventory inventory = grid.GetInventory();
			ItemData arg = ((inventory != null) ? inventory.GetItemAt(num, 0) : null);
			if (ZInput.GetButtonDown("JoyButtonA"))
			{
				Modifier arg2 = (Modifier)0;
				if (ZInput.GetButton("JoyLTrigger"))
				{
					arg2 = (Modifier)1;
				}
				if (ZInput.GetButton("JoyRTrigger"))
				{
					arg2 = (Modifier)3;
				}
				grid.m_onSelected?.Invoke(grid, arg, val, arg2);
			}
			if (ZInput.GetButtonDown("JoyButtonX"))
			{
				if (ZInput.GetButton("JoyLTrigger"))
				{
					grid.m_onSelected?.Invoke(grid, arg, val, (Modifier)2);
				}
				else
				{
					grid.m_onRightClick?.Invoke(grid, arg, val);
				}
			}
			return true;
		}

		private static InventoryGrid CreateGrid(InventoryGui gui, string name, out GameObject rootObject)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			rootObject = new GameObject(name, new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasGroup),
				typeof(UIGroupHandler),
				typeof(InventoryGrid)
			});
			rootObject.transform.SetParent(gui.m_inventoryRoot, false);
			RectTransform component = rootObject.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0f, 1f);
			RectTransform component2 = new GameObject(name + "_Root", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)component2).SetParent((Transform)(object)component, false);
			component2.anchorMin = new Vector2(0f, 1f);
			component2.anchorMax = new Vector2(0f, 1f);
			component2.pivot = new Vector2(0f, 1f);
			component2.anchoredPosition = Vector2.zero;
			InventoryGrid playerGrid = gui.m_playerGrid;
			UIGroupHandler component3 = rootObject.GetComponent<UIGroupHandler>();
			if ((Object)(object)playerGrid.m_uiGroup != (Object)null)
			{
				component3.m_defaultElementFallbackMode = playerGrid.m_uiGroup.m_defaultElementFallbackMode;
				component3.m_groupPriority = playerGrid.m_uiGroup.m_groupPriority;
				component3.m_setDefaultOnKBM = playerGrid.m_uiGroup.m_setDefaultOnKBM;
				component3.m_resetActiveElementOnStateChange = playerGrid.m_uiGroup.m_resetActiveElementOnStateChange;
			}
			component3.SetActive(false);
			InventoryGrid component4 = rootObject.GetComponent<InventoryGrid>();
			component4.m_elementPrefab = playerGrid.m_elementPrefab;
			component4.m_gridRoot = component2;
			component4.m_tooltipAnchor = playerGrid.m_tooltipAnchor;
			component4.m_elementSpace = playerGrid.m_elementSpace;
			component4.m_uiGroup = component3;
			component4.CanDropDragOntoItem = playerGrid.CanDropDragOntoItem;
			component4.m_onSelected = null;
			component4.m_onRightClick = null;
			component4.OnMoveToUpperInventoryGrid = null;
			component4.OnMoveToLowerInventoryGrid = null;
			component4.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Combine(component4.m_onSelected, (Action<InventoryGrid, ItemData, Vector2i, Modifier>)delegate(InventoryGrid selectedGrid, ItemData item, Vector2i position, Modifier modifier)
			{
				//IL_001b: 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)
				OnSelectedItemMethod.Invoke(gui, new object[4] { selectedGrid, item, position, modifier });
			});
			component4.m_onRightClick = (Action<InventoryGrid, ItemData, Vector2i>)Delegate.Combine(component4.m_onRightClick, (Action<InventoryGrid, ItemData, Vector2i>)delegate(InventoryGrid selectedGrid, ItemData item, Vector2i position)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				OnRightClickItemMethod.Invoke(gui, new object[3] { selectedGrid, item, position });
			});
			return component4;
		}

		private static void SetGridSize(InventoryGrid grid, int columns, int rows, float headerHeight)
		{
			//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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Component)grid).transform;
			val.SetSizeWithCurrentAnchors((Axis)0, (float)columns * grid.m_elementSpace);
			val.SetSizeWithCurrentAnchors((Axis)1, (float)rows * grid.m_elementSpace + headerHeight);
			grid.m_gridRoot.SetSizeWithCurrentAnchors((Axis)0, (float)columns * grid.m_elementSpace);
			grid.m_gridRoot.SetSizeWithCurrentAnchors((Axis)1, (float)rows * grid.m_elementSpace);
			grid.m_gridRoot.anchorMin = new Vector2(0f, 1f);
			grid.m_gridRoot.anchorMax = new Vector2(0f, 1f);
			grid.m_gridRoot.pivot = new Vector2(0f, 1f);
			grid.m_gridRoot.anchoredPosition = new Vector2(0f, 0f - headerHeight);
		}

		private static void AppendGamepadGroups(InventoryGui gui, params UIGroupHandler[] groups)
		{
			gui.m_uiGroups = gui.m_uiGroups.Concat(groups.Where((UIGroupHandler group) => (Object)(object)group != (Object)null)).ToArray();
		}

		private static void ConfigureInventoryTransform(RectTransform transform, Vector3 localPosition, float scale)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			transform.anchorMin = new Vector2(0.5f, 0.5f);
			transform.anchorMax = new Vector2(0.5f, 0.5f);
			transform.pivot = new Vector2(0f, 1f);
			((Transform)transform).localPosition = localPosition;
			((Transform)transform).localScale = Vector3.one * Mathf.Clamp(scale, 0.5f, 1.5f);
		}

		private static void PositionInventoryGrids()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inventoryGui == (Object)null || (Object)(object)gearGridObject == (Object)null || (Object)(object)quickGridObject == (Object)null || (Object)(object)gearGrid == (Object)null || (Object)(object)quickGrid == (Object)null)
			{
				return;
			}
			Transform inventoryRoot = inventoryGui.m_inventoryRoot;
			RectTransform val = (RectTransform)(object)((inventoryRoot is RectTransform) ? inventoryRoot : null);
			if (val != null)
			{
				Transform obj = ((Transform)inventoryGui.m_player).Find("Bkg");
				RectTransform val2 = (RectTransform)(((object)((obj is RectTransform) ? obj : null)) ?? ((object)inventoryGui.m_player));
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				val2.GetWorldCorners(array);
				Vector3 val3 = ((Transform)val).InverseTransformPoint(array[2]);
				GearSlotsConfig settings = GearSlotsPlugin.Settings;
				float num = Mathf.Clamp(settings.UiScale.Value, 0.5f, 1.5f);
				float num2 = 2f * gearGrid.m_elementSpace;
				float num3 = 5f * gearGrid.m_elementSpace + 24f;
				float num4 = 3f * quickGrid.m_elementSpace;
				float elementSpace = quickGrid.m_elementSpace;
				Rect rect = val.rect;
				float x = val3.x + settings.UiOffsetX.Value;
				float y = val3.y + settings.UiOffsetY.Value;
				string arg = "right of " + ((Object)val2).name;
				SlotPanelPlacement slotPanelPlacement = SlotPanelLayout.QuickBelowDedicated(x, y, num3, num, settings.InventoryQuickOffsetX.Value, settings.InventoryQuickOffsetY.Value);
				float x2 = slotPanelPlacement.QuickX;
				float y2 = slotPanelPlacement.QuickY;
				if (((Rect)(ref rect)).width > 0f && ((Rect)(ref rect)).height > 0f)
				{
					ClampPanelToViewport(ref x, ref y, num2 * num, num3 * num, rect);
					ClampPanelToViewport(ref x2, ref y2, num4 * num, elementSpace * num, rect);
				}
				Vector3 localPosition = default(Vector3);
				((Vector3)(ref localPosition))..ctor(x, y, val3.z);
				Vector3 localPosition2 = default(Vector3);
				((Vector3)(ref localPosition2))..ctor(x2, y2, val3.z);
				ConfigureInventoryTransform(gearGridObject.GetComponent<RectTransform>(), localPosition, num);
				ConfigureInventoryTransform(quickGridObject.GetComponent<RectTransform>(), localPosition2, num);
				if (!inventoryLayoutLogged)
				{
					inventoryLayoutLogged = true;
					GearSlotsPlugin.ModLog.LogInfo((object)($"GearSlots inventory panels anchored {arg}: dedicated=({x:0.#}, {y:0.#}), " + $"quick=({x2:0.#}, {y2:0.#}); " + $"viewport {((Rect)(ref rect)).width:0.#}x{((Rect)(ref rect)).height:0.#}."));
				}
			}
		}

		private static void ClampPanelToViewport(ref float x, ref float y, float width, float height, Rect viewport)
		{
			x = Mathf.Clamp(x, ((Rect)(ref viewport)).xMin + 8f, ((Rect)(ref viewport)).xMax - width - 8f);
			y = Mathf.Clamp(y, ((Rect)(ref viewport)).yMin + height + 8f, ((Rect)(ref viewport)).yMax - 8f);
		}

		private static void EnsureQuickHud()
		{
			//IL_007a: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			Hud instance = Hud.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (hud != instance)
			{
				DestroyHud();
				hud = instance;
			}
			if ((Object)(object)quickHudRoot != (Object)null)
			{
				return;
			}
			nativeHotkeyBar = instance.m_rootObject.GetComponentInChildren<HotkeyBar>(true);
			if (!((Object)(object)nativeHotkeyBar == (Object)null) && !((Object)(object)nativeHotkeyBar.m_elementPrefab == (Object)null))
			{
				quickHudRoot = new GameObject("GearSlots_QuickHud", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
				((Transform)quickHudRoot).SetParent(((Component)nativeHotkeyBar).transform.parent, false);
				((Transform)quickHudRoot).SetSiblingIndex(((Component)nativeHotkeyBar).transform.GetSiblingIndex() + 1);
				for (int i = 0; i < 3; i++)
				{
					GameObject val = Object.Instantiate<GameObject>(nativeHotkeyBar.m_elementPrefab, (Transform)(object)quickHudRoot);
					((Object)val).name = $"GearSlots_QuickHud_{i + 1}";
					val.SetActive(true);
					RectTransform val2 = (RectTransform)val.transform;
					val2.anchorMin = new Vector2(0.5f, 0.5f);
					val2.anchorMax = new Vector2(0.5f, 0.5f);
					val2.pivot = new Vector2(0.5f, 0.5f);
					val.transform.localPosition = new Vector3(SlotPanelLayout.GetHorizontalQuickElementX(i, 3, nativeHotkeyBar.m_elementSpace), 0f, 0f);
					QuickHudElement quickHudElement = new QuickHudElement
					{
						GameObject = val,
						Icon = ((Component)val.transform.Find("icon")).GetComponent<Image>(),
						Durability = ((Component)val.transform.Find("durability")).GetComponent<GuiBar>(),
						Amount = ((Component)val.transform.Find("amount")).GetComponent<TMP_Text>(),
						Binding = ((Component)val.transform.Find("binding")).GetComponent<TMP_Text>(),
						Equipped = ((Component)val.transform.Find("equiped")).gameObject,
						Queued = ((Component)val.transform.Find("queued")).gameObject,
						Selection = ((Component)val.transform.Find("selected")).gameObject,
						Tooltip = val.GetComponent<UITooltip>()
					};
					quickHudElement.Selection.SetActive(false);
					QuickHudElements.Add(quickHudElement);
				}
				PositionQuickHud();
				dirty = true;
			}
		}

		private static void PositionQuickHud()
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)quickHudRoot == (Object)null || (Object)(object)nativeHotkeyBar == (Object)null || (Object)(object)hud?.m_gpRoot == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)nativeHotkeyBar).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (val == null)
			{
				return;
			}
			Transform parent = ((Transform)quickHudRoot).parent;
			RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (val2 == null || QuickHudElements.Count == 0)
			{
				return;
			}
			Transform transform2 = QuickHudElements[0].GameObject.transform;
			RectTransform val3 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if (val3 != null && TryGetRectBounds(hud.m_gpRoot, val2, out var left, out var right, out var bottom, out var top, out var depth))
			{
				GearSlotsConfig settings = GearSlotsPlugin.Settings;
				HorizontalHudPlacement horizontalHudPlacement = SlotPanelLayout.HorizontalBesideBox(left, right, bottom, top, 8f, settings.QuickHudOffsetX.Value, settings.QuickHudOffsetY.Value);
				Rect rect = val3.rect;
				float num = Mathf.Max(1f, Mathf.Abs(((Rect)(ref rect)).width));
				rect = val3.rect;
				float num2 = Mathf.Max(1f, Mathf.Abs(((Rect)(ref rect)).height));
				Vector3 localScale = default(Vector3);
				((Vector3)(ref localScale))..ctor(horizontalHudPlacement.CellWidth / num, horizontalHudPlacement.CellHeight / num2, ((Transform)val).localScale.z);
				quickHudRoot.anchorMin = new Vector2(0.5f, 0.5f);
				quickHudRoot.anchorMax = new Vector2(0.5f, 0.5f);
				quickHudRoot.pivot = new Vector2(0.5f, 0.5f);
				((Transform)quickHudRoot).localPosition = new Vector3(horizontalHudPlacement.FirstCellCenterX, horizontalHudPlacement.CellCenterY, depth);
				((Transform)quickHudRoot).localRotation = ((Transform)val).localRotation;
				((Transform)quickHudRoot).localScale = localScale;
				bool flag = settings.QuickHudOrientation.Value == QuickHudOrientation.Vertical;
				quickHudRoot.sizeDelta = (flag ? new Vector2(num, num2 + nativeHotkeyBar.m_elementSpace * (float)(QuickHudElements.Count - 1)) : new Vector2(num + nativeHotkeyBar.m_elementSpace * (float)(QuickHudElements.Count - 1), num2));
				for (int i = 0; i < QuickHudElements.Count; i++)
				{
					QuickHudElements[i].GameObject.transform.localPosition = new Vector3(flag ? 0f : SlotPanelLayout.GetHorizontalQuickElementX(i, QuickHudElements.Count, nativeHotkeyBar.m_elementSpace), flag ? SlotPanelLayout.GetCenteredVerticalQuickElementY(i, QuickHudElements.Count, nativeHotkeyBar.m_elementSpace) : 0f, 0f);
				}
			}
		}

		private static bool TryGetRectBounds(RectTransform transform, RectTransform parent, out float left, out float right, out float bottom, out float top, out float depth)
		{
			//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_0046: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			left = float.PositiveInfinity;
			right = float.NegativeInfinity;
			bottom = float.PositiveInfinity;
			top = float.NegativeInfinity;
			depth = 0f;
			transform.GetWorldCorners(GuardianCorners);
			for (int i = 0; i < GuardianCorners.Length; i++)
			{
				Vector3 val = ((Transform)parent).InverseTransformPoint(GuardianCorners[i]);
				left = Mathf.Min(left, val.x);
				right = Mathf.Max(right, val.x);
				bottom = Mathf.Min(bottom, val.y);
				top = Mathf.Max(top, val.y);
				depth = val.z;
			}
			if (right > left)
			{
				return top > bottom;
			}
			return false;
		}

		private static void Refresh(bool force = false)
		{
			if ((!dirty && !force) || (Object)(object)SlotStateManager.CurrentPlayer == (Object)null || SlotStateManager.GearInventory == null || SlotStateManager.QuickInventory == null)
			{
				return;
			}
			Player currentPlayer = SlotStateManager.CurrentPlayer;
			if ((Object)(object)inventoryGui != (Object)null && (Object)(object)gearGrid != (Object)null && (Object)(object)quickGrid != (Object)null && InventoryGui.IsVisible())
			{
				gearGrid.UpdateInventory(SlotStateManager.GearInventory, currentPlayer, GetDraggedItem());
				quickGrid.UpdateInventory(SlotStateManager.QuickInventory, currentPlayer, GetDraggedItem());
				ApplyDedicatedVisualLayout(gearGrid);
				DecorateGrid(gearGrid, isGear: true);
				DecorateGrid(quickGrid, isGear: false);
				SetDefaultGamepadElement(gearGrid);
				SetDefaultGamepadElement(quickGrid);
				if (!inventoryVisualsLogged)
				{
					inventoryVisualsLogged = true;
					IList list = ElementsField.GetValue(gearGrid) as IList;
					IList list2 = ElementsField.GetValue(quickGrid) as IList;
					GearSlotsPlugin.ModLog.LogInfo((object)($"Dedicated slot visuals created: gear={list?.Count ?? 0}, quick={list2?.Count ?? 0}, " + $"active={((Component)gearGrid).gameObject.activeInHierarchy}/{((Component)quickGrid).gameObject.activeInHierarchy}."));
				}
			}
			RefreshQuickHud(currentPlayer);
			dirty = false;
		}

		private static ItemData? GetDraggedItem()
		{
			if (!((Object)(object)inventoryGui == (Object)null))
			{
				object? value = DragItemField.GetValue(inventoryGui);
				return (ItemData?)((value is ItemData) ? value : null);
			}
			return null;
		}

		internal static void BeginHeldDrag(InventoryGrid sourceGrid, Vector2i sourcePosition, PointerEventData eventData)
		{
			//IL_000e: 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)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inventoryGui == (Object)null || (int)eventData.button != 0 || DragObjectField.GetValue(inventoryGui) is GameObject || ZInput.GetKey((KeyCode)308, true) || ZInput.GetKey((KeyCode)307, true) || ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true) || ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true))
			{
				return;
			}
			Inventory inventory = sourceGrid.GetInventory();
			if (SlotStateManager.IsAuxiliaryInventory(inventory))
			{
				ItemData itemAt = inventory.GetItemAt(sourcePosition.x, sourcePosition.y);
				if (itemAt != null)
				{
					SetupDragItemMethod.Invoke(inventoryGui, new object[3] { itemAt, inventory, itemAt.m_stack });
				}
			}
		}

		internal static bool EnsureSplitDialog(InventoryGrid sourceGrid, Vector2i sourcePosition, PointerEventData eventData)
		{
			//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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			if ((Object)(object)inventoryGui == (Object)null || !SlotStateManager.IsAuxiliaryInventory(sourceGrid.GetInventory()))
			{
				return false;
			}
			Inventory inventory = sourceGrid.GetInventory();
			ItemData itemAt = inventory.GetItemAt(sourcePosition.x, sourcePosition.y);
			bool shiftHeld = ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true);
			if (itemAt == null || !AuxiliarySplitPolicy.ShouldOpen((int)eventData.button == 0, shiftHeld, itemAt.m_stack))
			{
				return false;
			}
			if (!inventoryGui.m_splitDialog.IsActive)
			{
				OpenSplitDialog(inventoryGui, itemAt, inventory);
			}
			else
			{
				((Component)inventoryGui.m_splitDialog).transform.SetAsLastSibling();
			}
			return true;
		}

		internal static void CompleteHeldDrag(InventoryGrid sourceGrid, PointerEventData eventData)
		{
			if ((Object)(object)inventoryGui == (Object)null || !SlotStateManager.IsAuxiliaryInventory(sourceGrid.GetInventory()) || !(DragObjectField.GetValue(inventoryGui) is GameObject))
			{
				return;
			}
			object? value = DragItemField.GetValue(inventoryGui);
			ItemData val = (ItemData)((value is ItemData) ? value : null);
			if (val != null)
			{
				object? value2 = DragInventoryField.GetValue(inventoryGui);
				Inventory val2 = (Inventory)((value2 is Inventory) ? value2 : null);
				if (val2 != null && SlotStateManager.IsAuxiliaryInventory(val2) && !TryCompleteHeldDragToPlayerGrid(eventData) && !IsPointerOverInventoryMenu(eventData) && SlotTransferService.TryDropAtPlayer(val))
				{
					PlayMoveEffect(inventoryGui);
					ClearDrag(inventoryGui);
				}
			}
		}

		private static bool TryCompleteHeldDragToPlayerGrid(PointerEventData eventData)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inventoryGui == (Object)null)
			{
				return false;
			}
			InventoryGrid playerGrid = inventoryGui.m_playerGrid;
			if (!(ElementsField.GetValue(playerGrid) is IList list))
			{
				return false;
			}
			int width = playerGrid.GetInventory().GetWidth();
			Vector2i val2 = default(Vector2i);
			for (int i = 0; i < list.Count; i++)
			{
				object obj = list[i];
				if (obj != null)
				{
					Transform transform = ((Component)(InventoryElement)obj).gameObject.transform;
					RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
					if (val != null && RectTransformUtility.RectangleContainsScreenPoint(val, eventData.position, eventData.enterEventCamera ?? eventData.pressEventCamera))
					{
						((Vector2i)(ref val2))..ctor(i % width, i / width);
						ItemData itemAt = playerGrid.GetInventory().GetItemAt(val2.x, val2.y);
						playerGrid.m_onSelected?.Invoke(playerGrid, itemAt, val2, (Modifier)0);
						return true;
					}
				}
			}
			return false;
		}

		private static bool IsPointerOverInventoryMenu(PointerEventData eventData)
		{
			//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)
			if ((Object)(object)inventoryGui == (Object)null || (Object)(object)EventSystem.current == (Object)null)
			{
				return false;
			}
			PointerRaycastResults.Clear();
			EventSystem.current.RaycastAll(eventData, PointerRaycastResults);
			object? value = DragObjectField.GetValue(inventoryGui);
			object? obj = ((value is GameObject) ? value : null);
			Transform val = ((obj != null) ? ((GameObject)obj).transform : null);
			foreach (RaycastResult pointerRaycastResult in PointerRaycastResults)
			{
				RaycastResult current = pointerRaycastResult;
				if (!((Object)(object)((RaycastResult)(ref current)).gameObject == (Object)null) && (!((Object)(object)val != (Object)null) || !((RaycastResult)(ref current)).gameObject.transform.IsChildOf(val)) && ((RaycastResult)(ref current)).gameObject.transform.IsChildOf(((Component)inventoryGui).transform))
				{
					return true;
				}
			}
			return false;
		}

		private static void DecorateGrid(InventoryGrid grid, bool isGear)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			if (!(ElementsField.GetValue(grid) is IList list))
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				object obj = list[i];
				if (obj != null)
				{
					Image icon = ((InventoryElement)obj).m_icon;
					ItemData itemAt = grid.GetInventory().GetItemAt(i, 0);
					SlotKind slot = (isGear ? SlotRuleEngine.GetDedicatedSlotAtPosition(i) : ((SlotKind)(6 + i)));
					GameObject gameObject = ((Component)(InventoryElement)obj).gameObject;
					UIInputHandler componentInChildren = gameObject.GetComponentInChildren<UIInputHandler>();
					GameObject val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).gameObject : gameObject);
					(val.GetComponent<AuxiliarySlotDragHandler>() ?? val.AddComponent<AuxiliarySlotDragHandler>()).Initialize(grid, new Vector2i(i, 0));
					Transform obj2 = gameObject.transform.Find("binding");
					TMP_Text val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null);
					if ((Object)(object)val2 != (Object)null)
					{
						ConfigureShortcutLabel(val2);
						((Behaviour)val2).enabled = !isGear;
						val2.text = (isGear ? string.Empty : GetQuickBinding(i));
					}
					TMP_Text orCreateLabel = GetOrCreateLabel(obj, "GearSlots_EmptyLabel", (TextAlignmentOptions)514, 14f);
					ConfigureEmptySlotLabel(orCreateLabel);
					orCreateLabel.text = SlotDisplayName.For(slot);
					bool flag = (((Behaviour)orCreateLabel).enabled = itemAt == null && !GearSlotsPlugin.Settings.HideEmptyLabels.Value);
					((Component)orCreateLabel).gameObject.SetActive(flag);
					if (flag)
					{
						orCreateLabel.transform.SetAsLastSibling();
					}
					if (itemAt == null)
					{
						((Behaviour)icon).enabled = false;
					}
					if (!SlotStateManager.IsSlotEnabled(slot))
					{
						orCreateLabel.text = SlotDisplayName.For(slot) + " (Off)";
						((Behaviour)orCreateLabel).enabled = true;
						((Component)orCreateLabel).gameObject.SetActive(true);
						orCreateLabel.transform.SetAsLastSibling();
						((Graphic)icon).color = new Color(0.55f, 0.35f, 0.35f, 0.32f);
					}
				}
			}
		}

		private static void ApplyDedicatedVisualLayout(InventoryGrid grid)
		{
			//IL_0044: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			if (!(ElementsField.GetValue(grid) is IList list) || list.Count < SlotRuleEngine.DedicatedSlots.Count)
			{
				return;
			}
			SetGridSize(grid, 2, 5, 24f);
			for (int i = 0; i < SlotRuleEngine.DedicatedSlots.Count; i++)
			{
				object obj = list[i];
				if (obj != null)
				{
					RectTransform val = (RectTransform)((Component)(InventoryElement)obj).gameObject.transform;
					SlotKind dedicatedSlotAtPosition = SlotRuleEngine.GetDedicatedSlotAtPosition(i);
					val.anchoredPosition = new Vector2((float)DedicatedPanelLayout.GetColumn(dedicatedSlotAtPosition) * grid.m_elementSpace, (float)(-DedicatedPanelLayout.GetRow(dedicatedSlotAtPosition)) * grid.m_elementSpace);
				}
			}
			GetOrCreateSectionHeader(list[4], "GearSlots_UtilityHeader", "UTILITY", 0f, grid.m_elementSpace);
			GetOrCreateSectionHeader(list[0], "GearSlots_GearHeader", "GEAR", grid.m_elementSpace, grid.m_elementSpace);
		}

		private static TMP_Text GetOrCreateSectionHeader(object templateElement, string name, string text, float x, float width)
		{
			//IL_0029: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = gearGridObject.GetComponent<RectTransform>();
			Transform val = ((Transform)component).Find(name);
			TMP_Text val2;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).GetComponent<TMP_Text>();
			}
			else
			{
				val2 = Object.Instantiate<TMP_Text>(((InventoryElement)templateElement).m_amount, (Transform)(object)component);
				((Object)val2).name = name;
				((Graphic)val2).raycastTarget = false;
				val2.alignment = (TextAlignmentOptions)514;
				val2.fontSize = 15f;
				val2.fontStyle = (FontStyles)1;
				val2.enableAutoSizing = false;
				((Graphic)val2).color = new Color(0.9f, 0.78f, 0.48f, 1f);
				RectTransform rectTransform = val2.rectTransform;
				rectTransform.anchorMin = new Vector2(0f, 1f);
				rectTransform.anchorMax = new Vector2(0f, 1f);
				rectTransform.pivot = new Vector2(0f, 1f);
				rectTransform.sizeDelta = new Vector2(width, 24f);
				rectTransform.anchoredPosition = new Vector2(x, 0f);
			}
			val2.text = text;
			((Behaviour)val2).enabled = true;
			((Component)val2).gameObject.SetActive(true);
			return val2;
		}

		private static TMP_Text GetOrCreateLabel(object element, string name, TextAlignmentOptions alignment, float fontSize)
		{
			//IL_0001: 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_0050: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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)
			GameObject gameObject = ((Component)(InventoryElement)element).gameObject;
			TMP_Text amount = ((InventoryElement)element).m_amount;
			Transform val = gameObject.transform.Find(name);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).GetComponent<TMP_Text>();
			}
			TMP_Text obj = Object.Instantiate<TMP_Text>(amount, gameObject.transform);
			((Object)obj).name = name;
			((Graphic)obj).raycastTarget = false;
			obj.alignment = alignment;
			obj.fontSize = fontSize;
			obj.enableAutoSizing = false;
			((Graphic)obj).color = new Color(0.95f, 0.82f, 0.52f, 1f);
			RectTransform rectTransform = obj.rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = new Vector2(3f, 3f);
			rectTransform.offsetMax = new Vector2(-3f, -3f);
			return obj;
		}

		private static void ConfigureEmptySlotLabel(TMP_Text label)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)label).raycastTarget = false;
			label.alignment = (TextAlignmentOptions)514;
			label.textWrappingMode = (TextWrappingModes)0;
			label.overflowMode = (TextOverflowModes)0;
			label.enableAutoSizing = true;
			label.fontSizeMin = 9f;
			label.fontSizeMax = 14f;
			label.fontStyle = (FontStyles)1;
			((Graphic)label).color = new Color(0.95f, 0.82f, 0.52f, 1f);
			RectTransform rectTransform = label.rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = new Vector2(3f, 3f);
			rectTransform.offsetMax = new Vector2(-3f, -3f);
		}

		private static void RefreshQuickHud(Player player)
		{
			//IL_012f: 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_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)quickHudRoot == (Object)null || SlotStateManager.QuickInventory == null || QuickHudElements.Count != 3)
			{
				return;
			}
			Inventory quickInventory = SlotStateManager.QuickInventory;
			for (int i = 0; i < QuickHudElements.Count; i++)
			{
				QuickHudElement quickHudElement = QuickHudElements[i];
				ItemData itemAt = quickInventory.GetItemAt(i, 0);
				ConfigureShortcutLabel(quickHudElement.Binding);
				quickHudElement.Binding.text = GetQuickBinding(i);
				((Component)quickHudElement.Binding).gameObject.SetActive(true);
				quickHudElement.Selection.SetActive(false);
				if (itemAt == null)
				{
					((Component)quickHudElement.Icon).gameObject.SetActive(false);
					((Component)quickHudElement.Durability).gameObject.SetActive(false);
					((Component)quickHudElement.Amount).gameObject.SetActive(false);
					quickHudElement.Equipped.SetActive(false);
					quickHudElement.Queued.SetActive(false);
					if ((Object)(object)quickHudElement.Tooltip != (Object)null)
					{
						quickHudElement.Tooltip.m_topic = SlotDisplayName.For((SlotKind)(6 + i));
						quickHudElement.Tooltip.m_text = string.Empty;
					}
					continue;
				}
				((Component)quickHudElement.Icon).gameObject.SetActive(true);
				quickHudElement.Icon.sprite = itemAt.GetIcon();
				((Graphic)quickHudElement.Icon).color = Color.white;
				bool flag = itemAt.m_shared.m_useDurability && itemAt.m_durability < itemAt.GetMaxDurability();
				((Component)quickHudElement.Durability).gameObject.SetActive(flag);
				if (flag)
				{
					if (itemAt.m_durability <= 0f)
					{
						quickHudElement.Durability.SetValue(1f);
						quickHudElement.Durability.SetColor((Color)((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : new Color(0f, 0f, 0f, 0f)));
					}
					else
					{
						quickHudElement.Durability.SetValue(itemAt.GetDurabilityPercentage());
						quickHudElement.Durability.ResetColor();
					}
				}
				quickHudElement.Equipped.SetActive(itemAt.m_equipped);
				quickHudElement.Queued.SetActive(player.IsEquipActionQueued(itemAt));
				bool flag2 = itemAt.m_shared.m_maxStackSize > 1;
				((Component)quickHudElement.Amount).gameObject.SetActive(flag2);
				if (flag2)
				{
					quickHudElement.Amount.text = $"{itemAt.m_stack} / {itemAt.m_shared.m_maxStackSize}";
				}
				if ((Object)(object)quickHudElement.Tooltip != (Object)null)
				{
					quickHudElement.Tooltip.Set(itemAt.m_shared.m_name, itemAt.GetTooltip(-1), quickHudRoot, default(Vector2));
				}
			}
		}

		private unsafe static string GetQuickBinding(int index)
		{
			//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_000e: 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)
			KeyboardShortcut quickKey = GearSlotsPlugin.Settings.GetQuickKey(index);
			return ShortcutLabelFormatter.Format(((object)((KeyboardShortcut)(ref quickKey)).MainKey/*cast due to .constrained prefix*/).ToString(), ((KeyboardShortcut)(ref quickKey)).Modifiers.Select((KeyCode modifier) => ((object)(*(KeyCode*)(&modifier))/*cast due to .constrained prefix*/).ToString()));
		}

		private static void ConfigureShortcutLabel(TMP_Text binding)
		{
			//IL_0052: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			binding.alignment = (TextAlignmentOptions)258;
			binding.textWrappingMode = (TextWrappingModes)0;
			binding.overflowMode = (TextOverflowModes)0;
			binding.enableAutoSizing = true;
			binding.fontSizeMin = 10f;
			binding.fontSizeMax = Mathf.Max(10f, binding.fontSize);
			RectTransform rectTransform = binding.rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 1f);
			rectTransform.anchorMax = new Vector2(1f, 1f);
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.anchoredPosition = new Vector2(0f, -2f);
			rectTransform.sizeDelta = new Vector2(-6f, 22f);
		}

		private static void SetDefaultGamepadElement(InventoryGrid grid)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (ElementsField.GetValue(grid) is IList { Count: >0 } list && (Object)(object)grid.m_uiGroup != (Object)null)
			{
				object obj = list[0];
				if (obj != null)
				{
					grid.m_uiGroup.m_defaultElement = ((Component)(InventoryElement)obj).gameObject;
				}
			}
		}

		private static void ClearDrag(InventoryGui gui)
		{
			SetupDragItemMethod.Invoke(gui, new object[3] { null, null, 1 });
		}

		private static void PlayMoveEffect(InventoryGui gui)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			gui.m_moveItemEffects.Create(((Component)gui).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
		}

		private static void OpenSplitDialog(InventoryGui gui, ItemData item, Inventory inventory)
		{
			if (item.m_stack > 1)
			{
				ShowSplitDialogMethod.Invoke(gui, new object[2] { item, inventory });
				((Component)gui.m_splitDialog).transform.SetAsLastSibling();
			}
			else
			{
				SetupDragItemMethod.Invoke(gui, new object[3] { item, inventory, item.m_stack });
			}
		}
	}
	internal sealed class AuxiliarySlotDragHandler : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler, IPointerUpHandler
	{
		private InventoryGrid? sourceGrid;

		private Vector2i sourcePosition;

		internal void Initialize(InventoryGrid grid, Vector2i position)
		{
			//IL_0008: 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)
			sourceGrid = grid;
			sourcePosition = position;
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sourceGrid != (Object)null)
			{
				GearSlotsUi.BeginHeldDrag(sourceGrid, sourcePosition, eventData);
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sourceGrid != (Object)null && (int)eventData.button == 0)
			{
				GearSlotsUi.CompleteHeldDrag(sourceGrid, eventData);
			}
		}

		public void OnPointerUp(PointerEventData eventData)
		{
			//IL_000f: 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)
			if ((Object)(object)sourceGrid != (Object)null && (int)eventData.button == 0 && !GearSlotsUi.EnsureSplitDialog(sourceGrid, sourcePosition, eventData))
			{
				GearSlotsUi.CompleteHeldDrag(sourceGrid, eventData);
			}
		}
	}
}
namespace GearSlots.Runtime
{
	internal static class CharacterPreviewService
	{
		private static readonly MethodInfo SetupEquipmentMethod = AccessTools.Method(typeof(Humanoid), "SetupEquipment", (Type[])null, (Type[])null);

		private static readonly FieldInfo HelmetItemField = AccessTools.Field(typeof(Humanoid), "m_helmetItem");

		private static readonly FieldInfo ChestItemField = AccessTools.Field(typeof(Humanoid), "m_chestItem");

		private static readonly FieldInfo LegItemField = AccessTools.Field(typeof(Humanoid), "m_legItem");

		private static readonly FieldInfo ShoulderItemField = AccessTools.Field(typeof(Humanoid), "m_shoulderItem");

		private static readonly FieldInfo UtilityItemField = AccessTools.Field(typeof(Humanoid), "m_utilityItem");

		private static readonly FieldInfo TrinketItemField = AccessTools.Field(typeof(Humanoid), "m_trinketItem");

		internal static void Apply(Player previewPlayer)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Invalid comparison between Unknown and I4
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Invalid comparison between Unknown and I4
			if ((Object)(object)previewPlayer == (Object)null || !TryLoadGearInventory(previewPlayer, out Inventory gearInventory))
			{
				return;
			}
			bool flag = false;
			flag |= ApplyItem(previewPlayer, gearInventory, SlotKind.Head, (ItemType)6, HelmetItemField);
			flag |= ApplyItem(previewPlayer, gearInventory, SlotKind.Chest, (ItemType)7, ChestItemField);
			flag |= ApplyItem(previewPlayer, gearInventory, SlotKind.Legs, (ItemType)11, LegItemField);
			flag |= ApplyItem(previewPlayer, gearInventory, SlotKind.Cape, (ItemType)17, ShoulderItemField);
			ItemData val = null;
			ItemData val2 = null;
			foreach (SlotKind utilitySlot in SlotRuleEngine.UtilitySlots)
			{
				if (GearSlotsPlugin.Settings.IsEnabled(utilitySlot))
				{
					int dedicatedPosition = SlotRuleEngine.GetDedicatedPosition(utilitySlot);
					ItemData itemAt = gearInventory.GetItemAt(dedicatedPosition, 0);
					if (itemAt != null && (int)itemAt.m_shared.m_itemType == 18 && val == null)
					{
						val = itemAt;
					}
					else if (itemAt != null && (int)itemAt.m_shared.m_itemType == 24 && val2 == null)
					{
						val2 = itemAt;
					}
				}
			}
			flag |= ApplyItem(previewPlayer, val, UtilityItemField);
			if (flag | ApplyItem(previewPlayer, val2, TrinketItemField))
			{
				SetupEquipmentMethod.Invoke(previewPlayer, Array.Empty<object>());
			}
		}

		private static bool TryLoadGearInventory(Player previewPlayer, out Inventory gearInventory)
		{
			gearInventory = CreateGearInventory(previewPlayer);
			Inventory quickInventory = CreateQuickInventory(previewPlayer);
			if (previewPlayer.m_customData.TryGetValue("com.jg224.gearslots.save.v1", out var value) && SlotPersistence.TryLoad(value, gearInventory, quickInventory, out long sequence, out string error))
			{
				return true;
			}
			gearInventory = CreateGearInventory(previewPlayer);
			quickInventory = CreateQuickInventory(previewPlayer);
			if (previewPlayer.m_customData.TryGetValue("com.jg224.gearslots.save.backup.v1", out var value2))
			{
				return SlotPersistence.TryLoad(value2, gearInventory, quickInventory, out sequence, out error);
			}
			return false;
		}

		private static Inventory CreateGearInventory(Player previewPlayer)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			return new Inventory("$gearslots_preview_gear", ((Humanoid)previewPlayer).GetInventory().GetBkg(), SlotRuleEngine.DedicatedSlots.Count, 1);
		}

		private static Inventory CreateQuickInventory(Player previewPlayer)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new Inventory("$gearslots_preview_quick", ((Humanoid)previewPlayer).GetInventory().GetBkg(), 3, 1);
		}

		private static bool ApplyItem(Player previewPlayer, Inventory gearInventory, SlotKind slot, ItemType expectedType, FieldInfo equipmentField)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!GearSlotsPlugin.Settings.IsEnabled(slot))
			{
				return false;
			}
			int dedicatedPosition = SlotRuleEngine.GetDedicatedPosition(slot);
			ItemData itemAt = gearInventory.GetItemAt(dedicatedPosition, 0);
			if (itemAt != null && itemAt.m_shared.m_itemType == expectedType)
			{
				return ApplyItem(previewPlayer, itemAt, equipmentField);
			}
			return false;
		}

		private static bool ApplyItem(Player previewPlayer, ItemData? item, FieldInfo equipmentField)
		{
			if (item == null)
			{
				return false;
			}
			item.m_equipped = true;
			equipmentField.SetValue(previewPlayer, item);
			return true;
		}
	}
	internal static class NamedLoadouts
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__1_0;

			public static Func<Inventory, Inventory> <>9__3_0;

			public static Func<Inventory, ItemData[]> <>9__3_1;

			public static Func<ItemData[], IEnumerable<ItemData>> <>9__3_2;

			public static Func<ItemData, ItemData> <>9__3_3;

			public static Func<ItemData, Vector2i> <>9__3_4;

			public static Func<ItemData, string> <>9__3_5;

			public static Func<ItemData, ItemData> <>9__3_6;

			internal void <Register>b__1_0(ConsoleEventArgs args)
			{
				try
				{
					if (args.Args.Length > 1 && args.Args[1] == "recovery")
					{
						GearSlotsRecoveryScreen.Open();
						args.Context.AddString("Open your inventory to view GearSlots recovery.");
						return;
					}
					if (args.Args.Length > 1 && args.Args[1] == "returnall")
					{
						args.Context.AddString(ReturnAll());
						return;
					}
					if (!SlotStateManager.IsReady)
					{
						throw new InvalidOperationException(SlotStateManager.RecoveryStatus);
					}
					Player currentPlayer = SlotStateManager.CurrentPlayer;
					currentPlayer.m_customData.TryGetValue("com.jg224.gearslots.loadouts.v1", out var value);
					Dictionary<string, Dictionary<SlotKind, string>> dictionary = LoadoutCodec.Decode(value);
					if (args.Args.Length < 3 || args.Args[2] == "list")
					{
						args.Context.AddString("Loadouts: " + string.Join(", ", dictionary.Keys));
						return;
					}
					if (args.Args[1] != "loadout")
					{
						throw new InvalidOperationException("Use gearslots loadout save/load/delete <name> or gearslots recovery.");
					}
					string text = string.Join(" ", args.Args.Skip(3)).Trim();
					if (!LoadoutCodec.ValidName(text))
					{
						throw new InvalidOperationException("Use a loadout name of 1–32 letters, numbers, spaces, underscores or dashes.");
					}
					switch (args.Args[2])
					{
					case "load":
					{
						if (!dictionary.TryGetValue(text, out var value2))
						{
							throw new InvalidOperationException("Loadout not found.");
						}
						args.Context.AddString(Apply(value2) ? ("Loaded " + text + ".") : "Loadout failed; original inventory restored.");
						return;
					}
					case "save":
					{
						Dictionary<SlotKind, string> dictionary2 = new Dictionary<SlotKind, string>();
						foreach (SlotKind value4 in Enum.GetValues(typeof(SlotKind)))
						{
							ItemData item = SlotStateManager.GetItem(value4);
							if (item != null)
							{
								dictionary2.Add(value4, SlotStateManager.EnsureIdentity(item));
							}
						}
						dictionary[text] = dictionary2;
						break;
					}
					case "delete":
						if (!dictionary.Remove(text))
						{
							throw new InvalidOperationException("Loadout not found.");
						}
						break;
					default:
						throw new InvalidOperationException("Use loadout save, load, delete or list.");
					}
					string value3 = LoadoutCodec.Encode(dictionary);
					currentPlayer.m_customData["com.jg224.gearslots.loadouts.v1"] = value3;
					SlotStateManager.MarkChanged();
					args.Context.AddString("Updated loadout " + text + ".");
				}
				catch (Exception ex)
				{
					args.Context.AddString("GearSlots: " + ex.Message);
				}
			}

			internal Inventory <Apply>b__3_0(Inventory inventory)
			{
				return inventory;
			}

			internal ItemData[] <Apply>b__3_1(Inventory inventory)
			{
				return inventory.GetAllItems().ToArray();
			}

			internal IEnumerable<ItemData> <Apply>b__3_2(ItemData[] items)
			{
				return items;
			}

			internal ItemData <Apply>b__3_3(ItemData item)
			{
				return item;
			}

			internal Vector2i <Apply>b__3_4(ItemData item)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return item.m_gridPos;
			}

			internal string <Apply>b__3_5(ItemData item)
			{
				return SlotStateManager.EnsureIdentity(item);
			}

			internal ItemData <Apply>b__3_6(ItemData item)
			{
				return item;
			}
		}

		private const string StorageKey = "com.jg224.gearslots.loadouts.v1";

		internal static void Register()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__1_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					try
					{
						if (args.Args.Length > 1 && args.Args[1] == "recovery")
						{
							GearSlotsRecoveryScreen.Open();
							args.Context.AddString("Open your inventory to view GearSlots recovery.");
						}
						else if (args.Args.Length > 1 && args.Args[1] == "returnall")
						{
							args.Context.AddString(ReturnAll());
						}
						else
						{
							if (!SlotStateManager.IsReady)
							{
								throw new InvalidOperationException(SlotStateManager.RecoveryStatus);
							}
							Player currentPlayer = SlotStateManager.CurrentPlayer;
							currentPlayer.m_customData.TryGetValue("com.jg224.gearslots.loadouts.v1", out var value);
							Dictionary<string, Dictionary<SlotKind, string>> dictionary = LoadoutCodec.Decode(value);
							if (args.Args.Length < 3 || args.Args[2] == "list")
							{
								args.Context.AddString("Loadouts: " + string.Join(", ", dictionary.Keys));
							}
							else
							{
								if (args.Args[1] != "loadout")
								{
									throw new InvalidOperationException("Use gearslots loadout save/load/delete <name> or gearslots recovery.");
								}
								string text = string.Join(" ", args.Args.Skip(3)).Trim();
								if (!LoadoutCodec.ValidName(text))
								{
									throw new InvalidOperationException("Use a loadout name of 1–32 letters, numbers, spaces, underscores or dashes.");
								}
								switch (args.Args[2])
								{
								case "load":
								{
									if (!dictionary.TryGetValue(text, out var value2))
									{
										throw new InvalidOperationException("Loadout not found.");
									}
									args.Context.AddString(Apply(value2) ? ("Loaded " + text + ".") : "Loadout failed; original inventory restored.");
									return;
								}
								case "save":
								{
									Dictionary<SlotKind, string> dictionary2 = new Dictionary<SlotKind, string>();
									foreach (SlotKind value4 in Enum.GetValues(typeof(SlotKind)))
									{
										ItemData item = SlotStateManager.GetItem(value4);
										if (item != null)
										{
											dictionary2.Add(value4, SlotStateManager.EnsureIdentity(item));
										}
									}
									dictionary[text] = dictionary2;
									break;
								}
								case "delete":
									if (!dictionary.Remove(text))
									{
										throw new InvalidOperationException("Loadout not found.");
									}
									break;
								default:
									throw new InvalidOperationException("Use loadout save, load, delete or list.");
								}
								string value3 = LoadoutCodec.Encode(dictionary);
								currentPlayer.m_customData["com.jg224.gearslots.loadouts.v1"] = value3;
								SlotStateManager.MarkChanged();
								args.Context.AddString("Updated loadout " + text + ".");
							}
						}
					}
					catch (Exception ex)
					{
						args.Context.AddString("GearSlots: " + ex.Message);
					}
				};
				<>c.<>9__1_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("gearslots", "loadout save/load/delete <name>, loadout list, recovery, returnall", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		internal static string ReturnAll()
		{
			try
			{
				return Apply(new Dictionary<SlotKind, string>()) ? "Returned every slot item to the main inventory." : "Return failed; original inventory restored.";
			}
			catch (Exception ex)
			{
				return ex.Message;
			}
		}

		private static bool Apply(IReadOnlyDictionary<SlotKind, string> desired)
		{
			if (!SlotStateManager.IsReady || SlotStateManager.LoadoutMutation)
			{
				throw new InvalidOperationException(SlotStateManager.RecoveryStatus);
			}
			Player player = SlotStateManager.CurrentPlayer;
			if (((Character)player).IsDead() || ((Character)player).IsTeleporting())
			{
				throw new InvalidOperationException("Wait until you are alive and teleportation has finished.");
			}
			Inventory[] inventories = (Inventory[])(object)new Inventory[3]
			{
				((Humanoid)player).GetInventory(),
				SlotStateManager.GearInventory,
				SlotStateManager.QuickInventory
			};
			Dictionary<Inventory, ItemData[]> original = inventories.ToDictionary((Inventory inventory) => inventory, (Inventory inventory) => inventory.GetAllItems().ToArray());
			ItemData[] all = original.Values.SelectMany((ItemData[] result2) => result2).ToArray();
			Dictionary<ItemData, Vector2i> positions = all.ToDictionary((ItemData item) => item, (ItemData item) => item.m_gridPos);
			ItemData[] equipped = ((IEnumerable<ItemData>)all).Where((Func<ItemData, bool>)((Humanoid)player).IsItemEquiped).ToArray();
			Dictionary<string, ItemData> identities = all.ToDictionary<ItemData, string, ItemData>((ItemData item) => SlotStateManager.EnsureIdentity(item), (ItemData item) => item, StringComparer.Ordinal);
			foreach (KeyValuePair<SlotKind, string> item in desired)
			{
				if (!identities.TryGetValue(item.Value, out var value) || !SlotStateManager.IsSlotEnabled(item.Key) || !SlotRuleAdapter.Accepts(item.Key, value))
				{
					throw new InvalidOperationException("A saved item is missing, its slot is disabled, or it no longer fits.");
				}
				if (value.m_shared.m_questItem && !SlotRuleAdapter.IsUtilityKey(value))
				{
					throw new InvalidOperationException("Quest items cannot be assigned to loadout slots.");
				}
			}
			int width = inventories[0].GetWidth();
			LoadoutItem[] items = identities.Select((KeyValuePair<string, ItemData> pair) => new LoadoutItem(pair.Key, inventories[0].ContainsItem(pair.Value) ? (pair.Value.m_gridPos.y * width + pair.Value.m_gridPos.x) : (-1))).ToArray();
			LoadoutPlan plan = LoadoutPlanner.Plan(items, desired, width * inventories[0].GetHeight());
			MethodInfo changed = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
			{
				typeof(bool),
				typeof(bool)
			}, (Type[])null);
			if (changed == null)
			{
				throw new InvalidOperationException("Inventory notification API is unavailable.");
			}
			SlotStateManager.BeginMutation();
			SlotStateManager.LoadoutMutation = true;
			try
			{
				bool result = LoadoutTransaction.Execute(delegate
				{
					//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
					//IL_0120: Unknown result type (might be due to invalid IL or missing references)
					//IL_0125: Unknown result type (might be due to invalid IL or missing references)
					ItemData[] array = all;
					foreach (ItemData val in array)
					{
						((Humanoid)player).RemoveEquipAction(val);
						if (((Humanoid)player).IsItemEquiped(val))
						{
							((Humanoid)player).UnequipItem(val, false);
						}
					}
					Inventory[] array2 = inventories;
					for (int i = 0; i < array2.Length; i++)
					{
						array2[i].GetAllItems().Clear();
					}
					foreach (KeyValuePair<string, int> mainCell in plan.MainCells)
					{
						ItemData val2 = identities[mainCell.Key];
						val2.m_gridPos = new Vector2i(mainCell.Value % width, mainCell.Value / width);
						inventories[0].GetAllItems().Add(val2);
					}
					foreach (KeyValuePair<string, SlotKind> slot in plan.Slots)
					{
						ItemData val3 = identities[slot.Key];
						val3.m_gridPos = SlotStateManager.GetPosition(slot.Value);
						SlotStateManager.GetInventory(slot.Value).GetAllItems().Add(val3);
					}
					array2 = inventories;
					foreach (Inventory obj in array2)
					{
						changed.Invoke(obj, new object[2] { false, false });
					}
					foreach (ItemData item2 in equipped.Where((ItemData item) => inventories[0].ContainsItem(item)))
					{
						((Humanoid)player).EquipItem(item2, false);
					}
					SlotStateManager.SynchronizeEquipment();
				}, delegate
				{
					//IL_0099: Unknown result type (might be due to invalid IL or missing references)
					//IL_009e: Unknown result type (might be due to invalid IL or missing references)
					ItemData[] array = all;
					foreach (ItemData val in array)
					{
						((Humanoid)player).RemoveEquipAction(val);
						if (((Humanoid)player).IsItemEquiped(val))
						{
							((Humanoid)player).UnequipItem(val, false);
						}
					}
					Inventory[] array2 = inventories;
					foreach (Inventory val2 in array2)
					{
						val2.GetAllItems().Clear();
						val2.GetAllItems().AddRange(original[val2]);
					}
					array = all;
					foreach (ItemData val3 in array)
					{
						val3.m_gridPos = positions[val3];
					}
					array2 = inventories;
					foreach (Inventory obj in array2)
					{
						changed.Invoke(obj, new object[2] { false, false });
					}
					array = equipped;
					foreach (ItemData val4 in array)
					{
						((Humanoid)player).EquipItem(val4, false);
					}
					SlotStateManager.SynchronizeEquipment();
				});
				SlotStateManager.MarkChanged();
				return result;
			}
			catch (AggregateException ex)
			{
				SlotStateManager.BlockForRecovery("Loadout rollback could not finish: " + ex.Message + ". Existing character payloads are preserved.");
				throw;
			}
			finally
			{
				SlotStateManager.LoadoutMutation = false;
				SlotStateManager.EndMutation();
			}
		}
	}
	internal static class ProtectedUpgradeService
	{
		internal static void EnsureOriginalRecovered(ProtectedUpgradeState state)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = SlotStateManager.GetInventory(state.Slot);
			Vector2i position = SlotStateManager.GetPosition(state.Slot);
			if (inventory != null && inventory.GetItemAt(position.x, position.y) == null)
			{
				RestoreOriginal(inventory, state.OriginalItem, position);
			}
		}

		internal static ItemData? CreateUpgradedItem(ProtectedUpgradeState state, int stack, int quality, int variant, long crafterId, string crafterName, bool cheated, bool pickedUp)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_011e: 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_00c8: 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_0045: 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)
			Inventory inventory = SlotStateManager.GetInventory(state.Slot);
			Vector2i position = SlotStateManager.GetPosition(state.Slot);
			ItemData originalItem = state.OriginalItem;
			if (inventory == null)
			{
				return null;
			}
			SlotStateManager.BeginMutation();
			try
			{
				ItemData itemAt = inventory.GetItemAt(position.x, position.y);
				if (itemAt != null && itemAt != originalItem)
				{
					RestoreOriginal(inventory, originalItem, position);
					return null;
				}
				if (itemAt == originalItem)
				{
					inventory.RemoveItem(originalItem);
				}
				ItemData val = originalItem.Clone();
				val.m_stack = stack;
				val.m_quality = quality;
				val.m_variant = variant;
				val.m_crafterID = crafterId;
				val.m_crafterName = crafterName;
				val.m_worldLevel = Game.m_worldLevel;
				val.m_pickedUp = pickedUp;
				val.m_cheated = cheated;
				val.m_equipped = false;
				val.m_durability = val.GetMaxDurability();
				val.m_gridPos = position;
				if (!inventory.AddItem(val, position))
				{
					RestoreOriginal(inventory, originalItem, position);
					return null;
				}
				SlotStateManager.EnsureIdentity(val);
				SlotStateManager.SynchronizeEquipment();
				return val;
			}
			catch (Exception ex)
			{
				GearSlotsPlugin.ModLog.LogError((object)("Could not return upgraded gear to its protected slot: " + ex));
				RestoreOriginal(inventory, originalItem, position);
				return null;
			}
			finally
			{
				SlotStateManager.EndMutation();
			}
		}

		private static void RestoreOriginal(Inventory destination, ItemData original, Vector2i position)
		{
			//IL_000a: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!destination.ContainsItem(original) && destination.GetItemAt(position.x, position.y) == null)
			{
				destination.AddItem(original, position);
			}
			SlotStateManager.SynchronizeEquipment();
		}
	}
	internal static class SlotPersistence
	{
		internal const string CurrentKey = "com.jg224.gearslots.save.v1";

		internal const string BackupKey = "com.jg224.gearslots.save.backup.v1";

		internal static string Serialize(long sequence, Inventory gearInventory, Inventory quickInventory)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			gearInventory.Save(val);
			ZPackage val2 = new ZPackage();
			quickInventory.Save(val2);
			return SlotPayloadCodec.Encode(new SlotSaveEnvelope(sequence, Guid.NewGuid(), val.GetArray(), val2.GetArray()));
		}

		internal static bool TryLoad(string payload, Inventory gearInventory, Inventory quickInventory, out long sequence, out string error)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			sequence = 0L;
			if (!SlotPayloadCodec.TryDecode(payload, out SlotSaveEnvelope envelope, out error) || envelope == null)
			{
				return false;
			}
			try
			{
				Inventory val = new Inventory("GearSlots validation", gearInventory.GetBkg(), gearInventory.GetWidth(), gearInventory.GetHeight());
				Inventory val2 = new Inventory("GearSlots validation", quickInventory.GetBkg(), quickInventory.GetWidth(), quickInventory.GetHeight());
				val.Load(new ZPackage(envelope.GearInventory));
				val2.Load(new ZPackage(envelope.QuickInventory));
				gearInventory.GetAllItems().Clear();
				quickInventory.GetAllItems().Clear();
				gearInventory.GetAllItems().AddRange(val.GetAllItems());
				quickInventory.GetAllItems().AddRange(val2.GetAllItems());
				AccessTools.Method(typeof(Inventory), "UpdateTotalWeight", (Type[])null, (Type[])null).Invoke(gearInventory, Array.Empty<object>());
				AccessTools.Method(typeof(Inventory), "UpdateTotalWeight", (Type[])null, (Type[])null).Invoke(quickInventory, Array.Empty<object>());
				sequence = envelope.Sequence;
				return true;
			}
			catch (Exception ex)
			{
				error = "Valheim could not restore the saved slot inventories: " + ex.Message;
				return false;
			}
		}
	}
	internal static class SlotRuleAdapter
	{
		internal static bool Accepts(SlotKind slot, ItemData item)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return SlotRuleEngine.Accepts(slot, ToCategory(item.m_shared.m_itemType), !string.IsNullOrEmpty(item.m_shared.m_ammoType), item.IsEquipable(), IsUtilityKey(item));
		}

		internal static bool TryGetDedicatedSlot(ItemData item, out SlotKind slot)
		{
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected I4, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType <= 17)
			{
				if ((int)itemType != 2)
				{
					switch (itemType - 6)
					{
					default:
						if ((int)itemType != 17)
						{
							goto IL_0082;
						}
						slot = SlotKind.Cape;
						return true;
					case 0:
						slot = SlotKind.Head;
						return true;
					case 1:
						slot = SlotKind.Chest;
						return true;
					case 5:
						slot = SlotKind.Legs;
						return true;
					case 3:
						break;
					case 2:
					case 4:
						goto IL_0082;
					}
					goto IL_0066;
				}
				if (!string.IsNullOrEmpty(item.m_shared.m_ammoType))
				{
					slot = SlotKind.Ammo;
					return true;
				}
				goto IL_0082;
			}
			if ((int)itemType != 18)
			{
				if ((int)itemType == 23)
				{
					goto IL_0066;
				}
				if ((int)itemType != 24)
				{
					goto IL_0082;
				}
			}
			slot = SlotKind.Utility;
			return true;
			IL_0066:
			slot = SlotKind.Ammo;
			return true;
			IL_0082:
			slot = SlotKind.Head;
			return false;
		}

		internal static bool IsUtilityKey(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType == 16)
			{
				if (!(item.m_shared.m_name == "$item_cryptkey"))
				{
					if ((Object)(object)item.m_dropPrefab != (Object)null)
					{
						return ((Object)item.m_dropPrefab).name == "CryptKey";
					}
					return false;
				}
				return true;
			}
			return false;
		}

		internal static ItemCategory ToCategory(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected I4, but got Unknown
			switch (type - 1)
			{
			case 0:
				return ItemCategory.Material;
			case 1:
				return ItemCategory.Consumable;
			case 2:
			case 3:
			case 13:
			case 19:
			case 21:
				return ItemCategory.Weapon;
			case 4:
				return ItemCategory.Shield;
			case 5:
				return ItemCategory.Helmet;
			case 6:
				return ItemCategory.Chest;
			case 8:
				return ItemCategory.Ammo;
			case 9:
				return ItemCategory.Customization;
			case 10:
				return ItemCategory.Legs;
			case 12:
				return ItemCategory.Trophy;
			case 14:
				return ItemCategory.Torch;
			case 15:
				return ItemCategory.Misc;
			case 16:
				return ItemCategory.Shoulder;
			case 17:
				return ItemCategory.Utility;
			case 18:
				return ItemCategory.Tool;
			case 20:
				return ItemCategory.Fish;
			case 22:
				return ItemCategory.AmmoNonEquipable;
			case 23:
				return ItemCategory.Trinket;
			default:
				return ItemCategory.None;
			}
		}
	}
	internal static class SlotStateManager
	{
		private sealed class MainInventoryRecoveryItem
		{
			internal ItemData Item { get; }

			internal string EncodedOrigin { get; }

			internal MainInventoryOrigin Origin { get; }

			internal MainInventoryRecoveryItem(ItemData item, string encodedOrigin, MainInventoryOrigin origin)
			{
				Item = item;
				EncodedOrigin = encodedOrigin;
				Origin = origin;
			}
		}

		private sealed class AutoStackTarget
		{
			internal Inventory Inventory { get; }

			internal ItemData Item { get; }

			internal AutoStackTarget(Inventory inventory, ItemData item)
			{
				Inventory = inventory;
				Item = item;
			}
		}

		internal const string ItemIdentityKey = "com.jg224.gearslots.item-id";

		internal const string TombstoneOriginKey = "com.jg224.gearslots.tombstone-origin";

		internal const string MainInventoryOriginKey = "com.jg224.gearslots.main-inventory-origin";

		private static readonly TransferGate TransferGate = new TransferGate();

		private static readonly MethodInfo SetupEquipmentMethod = AccessTools.Method(typeof(Humanoid), "SetupEquipment", (Type[])null, (Type[])null);

		private static readonly MethodInfo QueueEquipActionMethod = AccessTools.Method(typeof(Player), "QueueEquipAction", new Type[1] { typeof(ItemData) }, (Type[])null);

		private static readonly MethodInfo QueueUnequipActionMethod = AccessTools.Method(typeof(Player), "QueueUnequipAction", new Type[1] { typeof(ItemData) }, (Type[])null);

		private static readonly FieldInfo HelmetItemField = AccessTools.Field(typeof(Humanoid), "m_helmetItem");

		private static readonly FieldInfo ChestItemField = AccessTools.Field(typeof(Humanoid), "m_chestItem");

		private static readonly FieldInfo LegItemField = AccessTools.Field(typeof(Humanoid), "m_legItem");

		private static readonly FieldInfo ShoulderItemField = AccessTools.Field(typeof(Humanoid), "m_shoulderItem");

		private static readonly FieldInfo UtilityItemField = AccessTools.Field(typeof(Humanoid), "m_utilityItem");

		private static readonly FieldInfo TrinketItemField = AccessTools.Field(typeof(Humanoid), "m_trinketItem");

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

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

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

		private static Player? player;

		private static Inventory? gearInventory;

		private static Inventory? quickInventory;

		private static long saveSequence;

		private static bool suppressChanges;

		private static bool configurationDirty = true;

		private static bool stateDirty;

		private static int mutationDepth;

		private static bool recoveryBlocked;

		private static bool payloadRecoveryOnly;

		private static float nextEvacuationRetry;

		internal static bool LoadoutMutation { get; set; }

		internal static string RecoveryStatus { get; private set; } = "Slot payload is healthy.";

		internal static bool RecoveryBlocked => recoveryBlocked;

		internal static bool CanRetryRecovery
		{
			get
			{
				if (recoveryBlocked)
				{
					return payloadRecoveryOnly;
				}
				return false;
			}
		}

		internal static Player? CurrentPlayer => player;

		internal static Inventory? GearInventory => gearInventory;

		internal static Inventory? QuickInventory => quickInventory;

		internal static bool IsReady
		{
			get
			{
				if ((Object)(object)player != (Object)null && gearInventory != null && quickInventory != null)
				{
					return !recoveryBlocked;
				}
				return false;
			}
		}

		internal static void Initialize()
		{
			configurationDirty = true;
		}

		internal static void Shutdown()
		{
			Persist();
			Detach();
		}

		internal static void Tick()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (player != localPlayer)
			{
				Attach(localPlayer);
			}
			if (IsReady)
			{
				if (configurationDirty && Time.unscaledTime >= nextEvacuationRetry)
				{
					configurationDirty = false;
					EvacuateDisabledSlots();
					nextEvacuationRetry = Time.unscaledTime + 2f;
					GearSlotsUi.ApplyConfiguration();
				}
				RecoverTaggedItemsFromMainInventory();
				SynchronizeEquipment();
				HandleQuickSlotInput();
				GearSlotsUi.Tick();
			}
		}

		internal static void NotifyConfigurationChanged()
		{
			configurationDirty = true;
		}

		internal static void ReloadAfterPlayerLoad(Player loadedPlayer)
		{
			if (!((Object)(object)loadedPlayer != (Object)(object)Player.m_localPlayer))
			{
				Attach(loadedPlayer, forceReload: true);
			}
		}

		internal static void PersistBeforePlayerSave(Player savingPlayer)
		{
			if ((Object)(object)savingPlayer == (Object)(object)Player.m_localPlayer)
			{
				if (player != savingPlayer)
				{
					Attach(savingPlayer);
				}
				Persist();
			}
		}

		internal static bool IsMainInventory(Inventory inventory)
		{
			if ((Object)(object)p