Decompiled source of SakeysEquipmentSlots v1.0.0

BepInEx/plugins/Sakey's Equipment Slots/SakeysEquipmentSlots.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SakeysEquipmentSlots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SakeysEquipmentSlots")]
[assembly: AssemblyTitle("SakeysEquipmentSlots")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SakeysEquipmentSlots
{
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public bool? ShowRangeAsPercent;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	[BepInPlugin("com.sakey.equipmentslots", "Sakey's Equipment Slots", "1.0.0")]
	public sealed class SakeysEquipmentSlotsPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.sakey.equipmentslots";

		public const string PluginName = "Sakey's Equipment Slots";

		public const string PluginVersion = "1.0.0";

		internal static SakeysEquipmentSlotsPlugin Instance;

		internal static Harmony Harmony;

		internal static ConfigEntry<float> EquipmentX;

		internal static ConfigEntry<float> EquipmentY;

		internal static ConfigEntry<float> EquipmentScale;

		internal static ConfigEntry<bool> EquipmentMouseMove;

		internal static ConfigEntry<float> UtilityX;

		internal static ConfigEntry<float> UtilityY;

		internal static ConfigEntry<float> UtilityScale;

		internal static ConfigEntry<bool> UtilityMouseMove;

		internal static ConfigEntry<float> CapeX;

		internal static ConfigEntry<float> CapeY;

		internal static ConfigEntry<float> CapeScale;

		internal static ConfigEntry<bool> CapeMouseMove;

		internal static ConfigEntry<bool> FoodMouseMove;

		internal static ConfigEntry<bool> MeadMouseMove;

		internal static ConfigEntry<bool> AmmoMouseMove;

		internal static ConfigEntry<bool> MiscMouseMove;

		internal static ConfigEntry<bool> SpecialMouseMove;

		internal static ConfigEntry<bool> CoinMouseMove;

		internal static ConfigEntry<float> TooltipX;

		internal static ConfigEntry<float> TooltipY;

		internal static ConfigEntry<float> FoodX;

		internal static ConfigEntry<float> FoodY;

		internal static ConfigEntry<float> FoodScale;

		internal static ConfigEntry<float> MeadX;

		internal static ConfigEntry<float> MeadY;

		internal static ConfigEntry<float> MeadScale;

		internal static ConfigEntry<float> MiscX;

		internal static ConfigEntry<float> MiscY;

		internal static ConfigEntry<float> MiscScale;

		internal static ConfigEntry<float> AmmoX;

		internal static ConfigEntry<float> AmmoY;

		internal static ConfigEntry<float> AmmoScale;

		internal static ConfigEntry<float> SpecialX;

		internal static ConfigEntry<float> SpecialY;

		internal static ConfigEntry<float> SpecialScale;

		internal static ConfigEntry<float> CoinX;

		internal static ConfigEntry<float> CoinY;

		internal static ConfigEntry<float> CoinScale;

		internal static ConfigEntry<KeyboardShortcut> CapeHotkey1;

		internal static ConfigEntry<KeyboardShortcut> CapeHotkey2;

		internal static ConfigEntry<KeyboardShortcut> FoodHotkey1;

		internal static ConfigEntry<KeyboardShortcut> FoodHotkey2;

		internal static ConfigEntry<KeyboardShortcut> FoodHotkey3;

		internal static ConfigEntry<KeyboardShortcut> FoodHotkey4;

		internal static ConfigEntry<KeyboardShortcut> FoodHotkey5;

		internal static ConfigEntry<KeyboardShortcut> MeadHotkey1;

		internal static ConfigEntry<KeyboardShortcut> MeadHotkey2;

		internal static ConfigEntry<KeyboardShortcut> MeadHotkey3;

		internal static ConfigEntry<KeyboardShortcut> MeadHotkey4;

		internal static ConfigEntry<KeyboardShortcut> MeadHotkey5;

		internal static ConfigEntry<KeyboardShortcut> AmmoHotkey1;

		internal static ConfigEntry<KeyboardShortcut> AmmoHotkey2;

		internal static ConfigEntry<KeyboardShortcut> AmmoHotkey3;

		internal static ConfigEntry<bool> ShowDebugLog;

		internal static ConfigEntry<bool> PanelBackground;

		internal static ConfigEntry<string> DisplayLanguage;

		private static readonly List<ConfigEntryBase> LocalizedConfigEntries = new List<ConfigEntryBase>();

		private static readonly Dictionary<ConfigEntryBase, Tuple<string, string, string>> LocalizedConfigMetadata = new Dictionary<ConfigEntryBase, Tuple<string, string, string>>();

		internal static ConfigEntry<string> LayoutPresetControls;

		private static ConfigEntry<string> LayoutPreset1;

		private static ConfigEntry<string> LayoutPreset2;

		private static ConfigEntry<string> LayoutPreset3;

		private static ConfigEntry<int> LayoutPresetFormat;

		private static ConfigEntry<int> LayoutPresetSelected;

		internal static ConfigEntry<float> FoodHotbarX;

		internal static ConfigEntry<float> FoodHotbarY;

		internal static ConfigEntry<float> FoodHotbarScale;

		internal static ConfigEntry<float> MeadHotbarX;

		internal static ConfigEntry<float> MeadHotbarY;

		internal static ConfigEntry<float> MeadHotbarScale;

		internal static ConfigEntry<float> AmmoHotbarX;

		internal static ConfigEntry<float> AmmoHotbarY;

		internal static ConfigEntry<float> AmmoHotbarScale;

		internal static ConfigEntry<float> CapeHotbarX;

		internal static ConfigEntry<float> CapeHotbarY;

		internal static ConfigEntry<float> CapeHotbarScale;

		private static readonly string[] LayoutFieldSuffixes = new string[3] { "X", "Y", "Scale" };

		private static bool CachedIsEnglish;

		private static bool LanguageCacheInitialized;

		private void Awake()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0697: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_070d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0748: Unknown result type (might be due to invalid IL or missing references)
			//IL_0783: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_082b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0863: Unknown result type (might be due to invalid IL or missing references)
			//IL_089b: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_090b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0943: Unknown result type (might be due to invalid IL or missing references)
			//IL_097b: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_09fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a1d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a35: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a54: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a6c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a8b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aa3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ada: Unknown result type (might be due to invalid IL or missing references)
			//IL_0af9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b0e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b2d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b61: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b76: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b95: Unknown result type (might be due to invalid IL or missing references)
			//IL_0baa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bc9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bde: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bfd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c12: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c31: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c46: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c65: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c7a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c99: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ccd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ce2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d49: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d53: Expected O, but got Unknown
			//IL_0d91: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d9b: Expected O, but got Unknown
			//IL_0dd9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0de3: Expected O, but got Unknown
			//IL_0e1d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e27: Expected O, but got Unknown
			//IL_0e61: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e6b: Expected O, but got Unknown
			//IL_0f05: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f0f: Expected O, but got Unknown
			//IL_157a: Unknown result type (might be due to invalid IL or missing references)
			//IL_1584: Expected O, but got Unknown
			Instance = this;
			DisplayLanguage = ((BaseUnityPlugin)Instance).Config.Bind<string>("UI", "Display Language", "自動", new ConfigDescription("表示言語を選択します。自動ではValheimの言語に合わせます。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "自動", "日本語", "English" }), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "UI",
					DispName = "表示言語",
					DefaultValue = "自動"
				}
			}));
			DisplayLanguage.SettingChanged += delegate
			{
				RefreshLanguageCache();
				ApplyConfigManagerLocalization();
			};
			EquipmentX = BindFloat("Equipment Panel", "Position X", 0f, "装備", "位置 X", "装備パネルのX位置。");
			EquipmentY = BindFloat("Equipment Panel", "Position Y", 0f, "装備", "位置 Y", "装備パネルのY位置。");
			EquipmentScale = BindFloat("Equipment Panel", "Scale", 1f, "装備", "サイズ", "装備パネルのサイズ。");
			EquipmentMouseMove = BindBool("Equipment Panel", "Mouse Move", value: true, "装備", "マウスで移動", "装備パネルをマウスでドラッグして移動できるようにします。");
			UtilityX = BindFloat("Utility Panel", "Position X", 0f, "ユーティリティ", "位置 X", "ユーティリティパネルのX位置。");
			UtilityY = BindFloat("Utility Panel", "Position Y", 0f, "ユーティリティ", "位置 Y", "ユーティリティパネルのY位置。");
			UtilityScale = BindFloat("Utility Panel", "Scale", 1f, "ユーティリティ", "サイズ", "ユーティリティパネルのサイズ。");
			UtilityMouseMove = BindBool("Utility Panel", "Mouse Move", value: true, "ユーティリティ", "マウスで移動", "ユーティリティパネルをマウスでドラッグして移動できるようにします。");
			CapeX = BindFloat("Cape Panel", "Position X", 0f, "マント", "位置 X", "マントパネルのX位置。");
			CapeY = BindFloat("Cape Panel", "Position Y", 0f, "マント", "位置 Y", "マントパネルのY位置。");
			CapeScale = BindFloat("Cape Panel", "Scale", 0.82f, "マント", "サイズ", "マントパネルのサイズ。");
			CapeMouseMove = BindBool("Cape Panel", "Mouse Move", value: true, "マント", "マウスで移動", "マントパネルをマウスでドラッグして移動できるようにします。");
			TooltipX = BindFloat("Inventory Tooltip", "Position X", 0f, "アイテム説明", "位置 X", "アイテム説明のX位置。");
			TooltipY = BindFloat("Inventory Tooltip", "Position Y", 62f, "アイテム説明", "位置 Y", "アイテム説明のY位置。");
			FoodX = BindFloat("Food Panel", "Position X", 0f, "食べ物", "位置 X", "食べ物パネルのX位置。");
			FoodY = BindFloat("Food Panel", "Position Y", 20f, "食べ物", "位置 Y", "食べ物パネルのY位置。");
			FoodScale = BindFloat("Food Panel", "Scale", 0.82f, "食べ物", "サイズ", "食べ物パネルのサイズ。");
			FoodMouseMove = BindBool("Food Panel", "Mouse Move", value: true, "食べ物", "マウスで移動", "食べ物パネルをマウスでドラッグして移動できるようにします。");
			MeadX = BindFloat("Mead Panel", "Position X", 190f, "蜂蜜酒", "位置 X", "蜂蜜酒パネルのX位置。");
			MeadY = BindFloat("Mead Panel", "Position Y", 0f, "蜂蜜酒", "位置 Y", "蜂蜜酒パネルのY位置。");
			MeadScale = BindFloat("Mead Panel", "Scale", 0.82f, "蜂蜜酒", "サイズ", "蜂蜜酒パネルのサイズ。");
			MeadMouseMove = BindBool("Mead Panel", "Mouse Move", value: true, "蜂蜜酒", "マウスで移動", "蜂蜜酒パネルをマウスでドラッグして移動できるようにします。");
			MiscX = BindFloat("Misc Panel", "Position X", 260f, "その他", "位置 X", "その他パネルのX位置。");
			MiscY = BindFloat("Misc Panel", "Position Y", 20f, "その他", "位置 Y", "その他パネルのY位置。");
			MiscScale = BindFloat("Misc Panel", "Scale", 0.75f, "その他", "サイズ", "その他パネルのサイズ。");
			MiscMouseMove = BindBool("Misc Panel", "Mouse Move", value: true, "その他", "マウスで移動", "その他パネルをマウスでドラッグして移動できるようにします。");
			AmmoX = BindFloat("Ammo Panel", "Position X", 150f, "矢弾", "位置 X", "矢弾パネルのX位置。");
			AmmoY = BindFloat("Ammo Panel", "Position Y", 20f, "矢弾", "位置 Y", "矢弾パネルのY位置。");
			AmmoScale = BindFloat("Ammo Panel", "Scale", 0.75f, "矢弾", "サイズ", "矢弾パネルのサイズ。");
			AmmoMouseMove = BindBool("Ammo Panel", "Mouse Move", value: true, "矢弾", "マウスで移動", "矢弾パネルをマウスでドラッグして移動できるようにします。");
			SpecialX = BindFloat("Special Panel", "Position X", 0f, "特殊", "位置 X", "鍵やライトなどの特殊アイテムパネルのX位置。");
			SpecialY = BindFloat("Special Panel", "Position Y", 20f, "特殊", "位置 Y", "鍵やライトなどの特殊アイテムパネルのY位置。");
			SpecialScale = BindFloat("Special Panel", "Scale", 0.72f, "特殊", "サイズ", "特殊アイテムパネルのサイズ。");
			SpecialMouseMove = BindBool("Special Panel", "Mouse Move", value: true, "特殊", "マウスで移動", "特殊アイテムパネルをマウスでドラッグして移動できるようにします。");
			CoinX = BindFloat("Coin Panel", "Position X", 430f, "コイン", "位置 X", "コインパネルのX位置。");
			CoinY = BindFloat("Coin Panel", "Position Y", 20f, "コイン", "位置 Y", "コインパネルのY位置。");
			CoinScale = BindFloat("Coin Panel", "Scale", 0.72f, "コイン", "サイズ", "コインパネルのサイズ。");
			CoinMouseMove = BindBool("Coin Panel", "Mouse Move", value: true, "コイン", "マウスで移動", "コインパネルをマウスでドラッグして移動できるようにします。");
			CapeHotkey1 = BindHotkey("Hotkeys - Cape", "Cape 1", new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ケープキー", "ケープ 1", "ケープスロット1を使用。");
			CapeHotkey2 = BindHotkey("Hotkeys - Cape", "Cape 2", new KeyboardShortcut((KeyCode)288, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ケープキー", "ケープ 2", "ケープスロット2を使用。");
			FoodHotkey1 = BindHotkey("Hotkeys - Food", "Food 1", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "食べ物キー", "食べ物 1", "食べ物スロット1を使用。");
			FoodHotkey2 = BindHotkey("Hotkeys - Food", "Food 2", new KeyboardShortcut((KeyCode)291, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "食べ物キー", "食べ物 2", "食べ物スロット2を使用。");
			FoodHotkey3 = BindHotkey("Hotkeys - Food", "Food 3", new KeyboardShortcut((KeyCode)277, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "食べ物キー", "食べ物 3", "食べ物スロット3を使用。");
			FoodHotkey4 = BindHotkey("Hotkeys - Food", "Food 4", new KeyboardShortcut((KeyCode)127, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "食べ物キー", "食べ物 4", "食べ物スロット4を使用。");
			FoodHotkey5 = BindHotkey("Hotkeys - Food", "Food 5", new KeyboardShortcut((KeyCode)96, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "食べ物キー", "食べ物 5", "食べ物スロット5を使用。");
			MeadHotkey1 = BindHotkey("Hotkeys - Mead", "Mead 1", new KeyboardShortcut((KeyCode)45, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ポーションキー", "ポーション 1", "ポーションスロット1を使用。");
			MeadHotkey2 = BindHotkey("Hotkeys - Mead", "Mead 2", new KeyboardShortcut((KeyCode)61, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ポーションキー", "ポーション 2", "ポーションスロット2を使用。");
			MeadHotkey3 = BindHotkey("Hotkeys - Mead", "Mead 3", new KeyboardShortcut((KeyCode)91, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ポーションキー", "ポーション 3", "ポーションスロット3を使用。");
			MeadHotkey4 = BindHotkey("Hotkeys - Mead", "Mead 4", new KeyboardShortcut((KeyCode)93, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ポーションキー", "ポーション 4", "ポーションスロット4を使用。");
			MeadHotkey5 = BindHotkey("Hotkeys - Mead", "Mead 5", new KeyboardShortcut((KeyCode)59, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "ポーションキー", "ポーション 5", "ポーションスロット5を使用。");
			AmmoHotkey1 = BindHotkey("Hotkeys - Ammo", "Ammo 1", new KeyboardShortcut((KeyCode)39, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "矢弾キー", "矢弾 1", "矢弾スロット1を使用。");
			AmmoHotkey2 = BindHotkey("Hotkeys - Ammo", "Ammo 2", new KeyboardShortcut((KeyCode)47, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "矢弾キー", "矢弾 2", "矢弾スロット2を使用。");
			AmmoHotkey3 = BindHotkey("Hotkeys - Ammo", "Ammo 3", new KeyboardShortcut((KeyCode)92, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "矢弾キー", "矢弾 3", "矢弾スロット3を使用。");
			MigrateLegacyHotkey(CapeHotkey1, new KeyboardShortcut((KeyCode)113, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(CapeHotkey2, new KeyboardShortcut((KeyCode)119, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)288, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(FoodHotkey1, new KeyboardShortcut((KeyCode)122, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(FoodHotkey2, new KeyboardShortcut((KeyCode)120, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)291, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(FoodHotkey3, new KeyboardShortcut((KeyCode)99, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)277, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(FoodHotkey4, new KeyboardShortcut((KeyCode)118, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)127, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(FoodHotkey5, new KeyboardShortcut((KeyCode)98, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)96, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(MeadHotkey1, new KeyboardShortcut((KeyCode)97, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)45, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(MeadHotkey2, new KeyboardShortcut((KeyCode)115, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)61, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(MeadHotkey3, new KeyboardShortcut((KeyCode)100, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)91, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(MeadHotkey4, new KeyboardShortcut((KeyCode)102, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)93, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(MeadHotkey5, new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)59, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(AmmoHotkey1, new KeyboardShortcut((KeyCode)49, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)39, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(AmmoHotkey2, new KeyboardShortcut((KeyCode)50, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)47, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			MigrateLegacyHotkey(AmmoHotkey3, new KeyboardShortcut((KeyCode)51, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new KeyboardShortcut((KeyCode)92, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
			PanelBackground = BindBool("UI", "Panel Background", value: true, "UI", "パネル背景", "装備スロット各パネルの背景を常時表示するかどうか。");
			LayoutPreset1 = ((BaseUnityPlugin)Instance).Config.Bind<string>("Layout Presets", "Preset 1 Data", string.Empty, new ConfigDescription("レイアウトプリセット1の保存データ。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			LayoutPreset2 = ((BaseUnityPlugin)Instance).Config.Bind<string>("Layout Presets", "Preset 2 Data", string.Empty, new ConfigDescription("レイアウトプリセット2の保存データ。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			LayoutPreset3 = ((BaseUnityPlugin)Instance).Config.Bind<string>("Layout Presets", "Preset 3 Data", string.Empty, new ConfigDescription("レイアウトプリセット3の保存データ。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			LayoutPresetFormat = ((BaseUnityPlugin)Instance).Config.Bind<int>("Layout Presets", "Preset Format", 0, new ConfigDescription("レイアウトプリセットの内部形式番号。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			LayoutPresetSelected = ((BaseUnityPlugin)Instance).Config.Bind<int>("Layout Presets", "Selected Preset", 1, new ConfigDescription("現在選択中のレイアウトプリセット番号。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			if (LayoutPresetSelected.Value < 1 || LayoutPresetSelected.Value > 3)
			{
				LayoutPresetSelected.Value = 1;
			}
			LayoutPresetControls = ((BaseUnityPlugin)Instance).Config.Bind<string>("Layout Presets", "Preset Controls", string.Empty, new ConfigDescription("現在の配置を保存したり、保存済みの配置へ切り替えます。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "レイアウトプリセット",
					DispName = "プリセット",
					HideDefaultButton = true,
					CustomDrawer = DrawPresetControls
				}
			}));
			FoodHotbarX = BindFloat("Hotbar - Food", "Position X", 40f, "食べ物クイックバー", "位置 X", "食べ物クイックバーの左上からのX位置。");
			FoodHotbarY = BindFloat("Hotbar - Food", "Position Y", 145f, "食べ物クイックバー", "位置 Y", "食べ物クイックバーの左上からのY位置。");
			FoodHotbarScale = BindFloat("Hotbar - Food", "Scale", 1f, "食べ物クイックバー", "サイズ", "食べ物クイックバーのサイズ。");
			MeadHotbarX = BindFloat("Hotbar - Mead", "Position X", 40f, "ミードクイックバー", "位置 X", "ミードクイックバーの左上からのX位置。");
			MeadHotbarY = BindFloat("Hotbar - Mead", "Position Y", 205f, "ミードクイックバー", "位置 Y", "ミードクイックバーの上端からのY位置。");
			MeadHotbarScale = BindFloat("Hotbar - Mead", "Scale", 1f, "ミードクイックバー", "サイズ", "ミードクイックバーのサイズ。");
			AmmoHotbarX = BindFloat("Hotbar - Ammo", "Position X", 180f, "矢弾クイックバー", "位置 X", "矢弾クイックバーの左上からのX位置。");
			AmmoHotbarY = BindFloat("Hotbar - Ammo", "Position Y", 85f, "矢弾クイックバー", "位置 Y", "矢弾クイックバーの左上からのY位置。");
			AmmoHotbarScale = BindFloat("Hotbar - Ammo", "Scale", 1f, "矢弾クイックバー", "サイズ", "矢弾クイックバーのサイズ。");
			CapeHotbarX = BindFloat("Hotbar - Cape", "Position X", 40f, "ケープクイックバー", "位置 X", "ケープクイックバーの左上からのX位置。");
			CapeHotbarY = BindFloat("Hotbar - Cape", "Position Y", 85f, "ケープクイックバー", "位置 Y", "ケープクイックバーの左上からのY位置。");
			CapeHotbarScale = BindFloat("Hotbar - Cape", "Scale", 1f, "ケープクイックバー", "サイズ", "ケープクイックバーのサイズ。");
			ShowDebugLog = BindBool("Debug", "Debug Log", value: false, "デバッグ", "デバッグログ", "診断ログを有効にします。");
			if (!EquipmentMouseMove.Value)
			{
				EquipmentMouseMove.Value = true;
			}
			if (!UtilityMouseMove.Value)
			{
				UtilityMouseMove.Value = true;
			}
			if (!CapeMouseMove.Value)
			{
				CapeMouseMove.Value = true;
			}
			if (Mathf.Approximately(CapeScale.Value, 1f))
			{
				CapeScale.Value = 0.82f;
			}
			if (Mathf.Approximately(FoodHotbarScale.Value, 0.72f))
			{
				FoodHotbarScale.Value = 1f;
			}
			if (Mathf.Approximately(MeadHotbarScale.Value, 0.72f))
			{
				MeadHotbarScale.Value = 1f;
			}
			if (Mathf.Approximately(AmmoHotbarScale.Value, 0.72f))
			{
				AmmoHotbarScale.Value = 1f;
			}
			if (Mathf.Approximately(CapeHotbarScale.Value, 0.72f))
			{
				CapeHotbarScale.Value = 1f;
			}
			TooltipX.Value = 0f;
			TooltipY.Value = 62f;
			if (LayoutPresetFormat.Value < 9)
			{
				LayoutPreset1.Value = BuildPreset1Layout();
				LayoutPreset2.Value = BuildPreset2Layout();
				LayoutPreset3.Value = BuildPreset3Layout(LayoutPreset3.Value);
				LayoutPresetFormat.Value = 9;
				((BaseUnityPlugin)Instance).Config.Save();
			}
			if (LayoutPresetFormat.Value < 11)
			{
				LayoutPreset1.Value = ApplyPresetOverrides(LayoutPreset1.Value, new Dictionary<string, float>
				{
					{ "AmmoHotbarScale", 0.75f },
					{ "AmmoHotbarX", 150f },
					{ "AmmoHotbarY", 120f }
				});
				LayoutPreset2.Value = ApplyPresetOverrides(LayoutPreset2.Value, new Dictionary<string, float>
				{
					{ "CapeHotbarScale", 0.75f },
					{ "CapeHotbarX", 230f },
					{ "CapeHotbarY", 870f },
					{ "FoodHotbarScale", 0.8f },
					{ "FoodHotbarX", 500f },
					{ "FoodHotbarY", 1000f },
					{ "AmmoHotbarScale", 0.9f },
					{ "AmmoHotbarX", 230f },
					{ "AmmoHotbarY", 930f },
					{ "MeadHotbarScale", 0.8f },
					{ "MeadHotbarX", 230f },
					{ "MeadHotbarY", 1000f }
				});
				LayoutPresetFormat.Value = 11;
				((BaseUnityPlugin)Instance).Config.Save();
			}
			if (LayoutPresetFormat.Value < 13)
			{
				LayoutPreset1.Value = ApplyPresetOverrides(LayoutPreset1.Value, new Dictionary<string, float>
				{
					{ "CapeScale", 0.82f },
					{ "CapeX", 260f },
					{ "CapeY", -379f },
					{ "AmmoScale", 0.75f },
					{ "AmmoX", 703f },
					{ "AmmoY", -473f },
					{ "UtilityScale", 1f },
					{ "UtilityX", 154f },
					{ "UtilityY", -109f },
					{ "MeadHotbarScale", 0.75f },
					{ "MeadHotbarX", 240f },
					{ "MeadHotbarY", 890f }
				});
				LayoutPresetFormat.Value = 13;
				((BaseUnityPlugin)Instance).Config.Save();
			}
			if (LayoutPresetFormat.Value < 15)
			{
				LayoutPreset1.Value = BuildPreset1Layout();
				LayoutPreset2.Value = BuildPreset2Layout();
				LayoutPreset3.Value = BuildPreset3Layout(LayoutPreset3.Value);
				LayoutPresetFormat.Value = 15;
				RestoreLayout(LayoutPreset1.Value);
				((BaseUnityPlugin)Instance).Config.Save();
			}
			SyncConfigManagerDefaultsToPreset1();
			RefreshLanguageCache();
			ApplyConfigManagerLocalization();
			Harmony = new Harmony("com.sakey.equipmentslots");
			Harmony.PatchAll();
			Log("Sakey's Equipment Slots started (build196).");
		}

		private static FieldInfo[] GetLayoutFields()
		{
			return (from f in typeof(SakeysEquipmentSlotsPlugin).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where f.FieldType == typeof(ConfigEntry<float>) && LayoutFieldSuffixes.Any((string s) => f.Name.EndsWith(s, StringComparison.Ordinal))
				orderby f.Name
				select f).ToArray();
		}

		private static string BuildPreset1Layout()
		{
			return string.Join(";", "EquipmentX=0", "EquipmentY=0", "EquipmentScale=1", "UtilityX=0", "UtilityY=0", "UtilityScale=1", "CapeX=0", "CapeY=0", "CapeScale=0.82", "TooltipX=0", "TooltipY=62", "FoodX=0", "FoodY=0", "FoodScale=0.82", "MeadX=0", "MeadY=0", "MeadScale=0.82", "MiscX=0", "MiscY=0", "MiscScale=0.8", "AmmoX=0", "AmmoY=0", "AmmoScale=0.75", "SpecialX=0", "SpecialY=0", "SpecialScale=0.75", "CoinX=0", "CoinY=0", "CoinScale=0.8", "FoodHotbarX=240", "FoodHotbarY=950", "FoodHotbarScale=0.8", "MeadHotbarX=240", "MeadHotbarY=890", "MeadHotbarScale=0.75", "AmmoHotbarX=150", "AmmoHotbarY=120", "AmmoHotbarScale=0.75", "CapeHotbarX=45", "CapeHotbarY=120", "CapeHotbarScale=0.75");
		}

		private static string BuildPreset2Layout()
		{
			return ApplyPresetOverrides(BuildPreset1Layout(), new Dictionary<string, float>
			{
				{ "EquipmentX", -120f },
				{ "EquipmentY", 30f },
				{ "UtilityX", -120f },
				{ "UtilityY", 30f },
				{ "CapeX", 80f },
				{ "CapeY", -20f },
				{ "FoodX", 0f },
				{ "FoodY", 40f },
				{ "MeadX", 0f },
				{ "MeadY", 40f },
				{ "MiscX", 0f },
				{ "MiscY", 40f },
				{ "AmmoX", 0f },
				{ "AmmoY", 40f },
				{ "SpecialX", 0f },
				{ "SpecialY", 40f },
				{ "CoinX", 0f },
				{ "CoinY", 40f }
			});
		}

		private static string BuildPreset3Layout(string existing)
		{
			return ApplyPresetOverrides(BuildPreset1Layout(), new Dictionary<string, float>
			{
				{ "EquipmentX", 0f },
				{ "EquipmentY", 0f },
				{ "UtilityX", 0f },
				{ "UtilityY", 0f },
				{ "CapeX", 0f },
				{ "CapeY", 0f },
				{ "FoodX", 0f },
				{ "FoodY", 0f },
				{ "MeadX", 0f },
				{ "MeadY", 0f },
				{ "MiscX", 0f },
				{ "MiscY", 0f },
				{ "AmmoX", 0f },
				{ "AmmoY", 0f },
				{ "SpecialX", 0f },
				{ "SpecialY", 0f },
				{ "CoinX", 0f },
				{ "CoinY", 0f }
			});
		}

		private static string ApplyPresetOverrides(string data, Dictionary<string, float> overrides)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			if (!string.IsNullOrEmpty(data))
			{
				string[] array = data.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
				for (int i = 0; i < array.Length; i++)
				{
					int num = array[i].IndexOf('=');
					if (num > 0 && num < array[i].Length - 1)
					{
						dictionary[array[i].Substring(0, num)] = array[i].Substring(num + 1);
					}
				}
			}
			foreach (KeyValuePair<string, float> @override in overrides)
			{
				dictionary[@override.Key] = @override.Value.ToString(CultureInfo.InvariantCulture);
			}
			return string.Join(";", from k in dictionary
				orderby k.Key
				select k.Key + "=" + k.Value);
		}

		private static string CaptureLayout()
		{
			List<string> list = new List<string>();
			FieldInfo[] layoutFields = GetLayoutFields();
			foreach (FieldInfo fieldInfo in layoutFields)
			{
				if (fieldInfo.GetValue(null) is ConfigEntry<float> val)
				{
					list.Add(fieldInfo.Name + "=" + val.Value.ToString(CultureInfo.InvariantCulture));
				}
			}
			return string.Join(";", list);
		}

		private static bool RestoreLayout(string data)
		{
			if (string.IsNullOrEmpty(data))
			{
				return false;
			}
			Dictionary<string, float> dictionary = new Dictionary<string, float>(StringComparer.Ordinal);
			string[] array = data.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				int num = array[i].IndexOf('=');
				if (num > 0 && num < array[i].Length - 1)
				{
					string key = array[i].Substring(0, num);
					if (float.TryParse(array[i].Substring(num + 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						dictionary[key] = result;
					}
				}
			}
			FieldInfo[] layoutFields = GetLayoutFields();
			foreach (FieldInfo fieldInfo in layoutFields)
			{
				if (dictionary.TryGetValue(fieldInfo.Name, out var value) && fieldInfo.GetValue(null) is ConfigEntry<float> val)
				{
					val.Value = value;
				}
			}
			EquipmentSlotsGridUI.ReloadLayoutNow();
			EquipmentSlotsUI.ReloadLayoutNow();
			SakeysQuickBarUI.ReloadLayoutNow();
			return true;
		}

		private static void SavePreset(int index)
		{
			string value = CaptureLayout();
			switch (index)
			{
			case 1:
				LayoutPreset1.Value = value;
				break;
			case 2:
				LayoutPreset2.Value = value;
				break;
			case 3:
				LayoutPreset3.Value = value;
				break;
			}
			((BaseUnityPlugin)Instance).Config.Save();
		}

		private static bool LoadPreset(int index)
		{
			bool num = RestoreLayout(index switch
			{
				2 => LayoutPreset2.Value, 
				1 => LayoutPreset1.Value, 
				_ => LayoutPreset3.Value, 
			});
			if (num)
			{
				LayoutPresetSelected.Value = index;
				((BaseUnityPlugin)Instance).Config.Save();
			}
			return num;
		}

		private static string PresetButtonText(int index)
		{
			string text = ConfigText("プリセット" + index, "Preset " + index);
			if (LayoutPresetSelected.Value != index)
			{
				return "   " + text;
			}
			return "✓ " + text;
		}

		private static void DrawPresetControls(ConfigEntryBase setting)
		{
			GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUILayout.Label(ConfigText("読み込み", "Load"), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(PresetButtonText(1), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
			{
				LoadPreset(1);
			}
			if (GUILayout.Button(PresetButtonText(2), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
			{
				LoadPreset(2);
			}
			if (GUILayout.Button(PresetButtonText(3), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
			{
				LoadPreset(3);
			}
			GUILayout.Space(4f);
			GUILayout.Label(ConfigText("保存", "Save"), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(ConfigText("プリセット1", "Preset 1"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
			{
				SavePreset(1);
			}
			if (GUILayout.Button(ConfigText("プリセット2", "Preset 2"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
			{
				SavePreset(2);
			}
			if (GUILayout.Button(ConfigText("プリセット3", "Preset 3"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
			{
				SavePreset(3);
			}
			GUILayout.EndVertical();
		}

		private static void SyncConfigManagerDefaultsToPreset1()
		{
			if (string.IsNullOrEmpty(LayoutPreset1.Value))
			{
				return;
			}
			Dictionary<string, float> dictionary = new Dictionary<string, float>(StringComparer.Ordinal);
			string[] array = LayoutPreset1.Value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				int num = array[i].IndexOf('=');
				if (num > 0 && num < array[i].Length - 1 && float.TryParse(array[i].Substring(num + 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					dictionary[array[i].Substring(0, num)] = result;
				}
			}
			FieldInfo[] layoutFields = GetLayoutFields();
			foreach (FieldInfo fieldInfo in layoutFields)
			{
				if (!dictionary.TryGetValue(fieldInfo.Name, out var value) || !(fieldInfo.GetValue(null) is ConfigEntry<float> val) || ((ConfigEntryBase)val).Description == null || ((ConfigEntryBase)val).Description.Tags == null)
				{
					continue;
				}
				object[] tags = ((ConfigEntryBase)val).Description.Tags;
				for (int k = 0; k < tags.Length; k++)
				{
					if (tags[k] is ConfigurationManagerAttributes configurationManagerAttributes)
					{
						configurationManagerAttributes.DefaultValue = value;
						break;
					}
				}
			}
		}

		private static void RefreshLanguageCache()
		{
			if (DisplayLanguage != null)
			{
				if (DisplayLanguage.Value == "English")
				{
					CachedIsEnglish = true;
					LanguageCacheInitialized = true;
					return;
				}
				if (DisplayLanguage.Value == "日本語")
				{
					CachedIsEnglish = false;
					LanguageCacheInitialized = true;
					return;
				}
			}
			bool cachedIsEnglish = false;
			try
			{
				Type type = AccessTools.TypeByName("Localization");
				if (type != null)
				{
					object obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null, null) ?? type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null);
					MethodInfo method = type.GetMethod("GetLanguage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					string text = ((method != null && obj != null) ? (method.Invoke(obj, null) as string) : null);
					cachedIsEnglish = !string.IsNullOrEmpty(text) && text.IndexOf("Japanese", StringComparison.OrdinalIgnoreCase) < 0;
				}
			}
			catch
			{
			}
			CachedIsEnglish = cachedIsEnglish;
			LanguageCacheInitialized = true;
		}

		internal static bool IsEnglish()
		{
			if (!LanguageCacheInitialized)
			{
				RefreshLanguageCache();
			}
			return CachedIsEnglish;
		}

		private static string ConfigText(string ja, string en)
		{
			if (!IsEnglish())
			{
				return ja;
			}
			return en;
		}

		private static string TranslateCategory(string ja)
		{
			return ja switch
			{
				"装備" => "Equipment", 
				"ユーティリティ" => "Utility", 
				"マント" => "Cape", 
				"アイテム説明" => "Item Tooltip", 
				"食べ物" => "Food", 
				"蜂蜜酒" => "Mead", 
				"その他" => "Misc", 
				"矢弾" => "Ammo", 
				"特殊" => "Special", 
				"コイン" => "Coin", 
				"ケープキー" => "Cape Hotkeys", 
				"食べ物キー" => "Food Hotkeys", 
				"ポーションキー" => "Mead Hotkeys", 
				"矢弾キー" => "Ammo Hotkeys", 
				"UI" => "UI", 
				"デバッグ" => "Debug", 
				"レイアウトプリセット" => "Layout Presets", 
				"食べ物クイックバー" => "Food Hotbar", 
				"ミードクイックバー" => "Mead Hotbar", 
				"矢弾クイックバー" => "Ammo Hotbar", 
				"ケープクイックバー" => "Cape Hotbar", 
				_ => ja, 
			};
		}

		private static string TranslateName(string ja)
		{
			switch (ja)
			{
			case "位置 X":
				return "Position X";
			case "位置 Y":
				return "Position Y";
			case "サイズ":
				return "Scale";
			case "マウスで移動":
				return "Mouse Move";
			case "パネル背景":
				return "Panel Background";
			case "デバッグログ":
				return "Debug Log";
			default:
				if (ja.StartsWith("ケープ "))
				{
					return "Cape " + ja.Substring(4);
				}
				if (ja.StartsWith("食べ物 "))
				{
					return "Food " + ja.Substring(4);
				}
				if (ja.StartsWith("ポーション "))
				{
					return "Mead " + ja.Substring(6);
				}
				if (ja.StartsWith("矢弾 "))
				{
					return "Ammo " + ja.Substring(3);
				}
				return ja;
			}
		}

		private static string TranslateDescription(string ja)
		{
			switch (ja)
			{
			case "装備パネルのX位置。":
				return "Equipment panel X position.";
			case "装備パネルのY位置。":
				return "Equipment panel Y position.";
			case "装備パネルのサイズ。":
				return "Equipment panel scale.";
			case "装備パネルをマウスでドラッグして移動できるようにします。":
				return "Allows the equipment panel to be moved by dragging with the mouse.";
			case "ユーティリティパネルのX位置。":
				return "Utility panel X position.";
			case "ユーティリティパネルのY位置。":
				return "Utility panel Y position.";
			case "ユーティリティパネルのサイズ。":
				return "Utility panel scale.";
			case "ユーティリティパネルをマウスでドラッグして移動できるようにします。":
				return "Allows the utility panel to be moved by dragging with the mouse.";
			case "マントパネルのX位置。":
				return "Cape panel X position.";
			case "マントパネルのY位置。":
				return "Cape panel Y position.";
			case "マントパネルのサイズ。":
				return "Cape panel scale.";
			case "マントパネルをマウスでドラッグして移動できるようにします。":
				return "Allows the cape panel to be moved by dragging with the mouse.";
			case "アイテム説明のX位置。":
				return "Item tooltip X position.";
			case "アイテム説明のY位置。":
				return "Item tooltip Y position.";
			case "食べ物パネルのX位置。":
				return "Food panel X position.";
			case "食べ物パネルのY位置。":
				return "Food panel Y position.";
			case "食べ物パネルのサイズ。":
				return "Food panel scale.";
			case "食べ物パネルをマウスでドラッグして移動できるようにします。":
				return "Allows the food panel to be moved by dragging with the mouse.";
			case "蜂蜜酒パネルのX位置。":
				return "Mead panel X position.";
			case "蜂蜜酒パネルのY位置。":
				return "Mead panel Y position.";
			case "蜂蜜酒パネルのサイズ。":
				return "Mead panel scale.";
			case "蜂蜜酒パネルをマウスでドラッグして移動できるようにします。":
				return "Allows the mead panel to be moved by dragging with the mouse.";
			case "その他パネルのX位置。":
				return "Misc panel X position.";
			case "その他パネルのY位置。":
				return "Misc panel Y position.";
			case "その他パネルのサイズ。":
				return "Misc panel scale.";
			case "その他パネルをマウスでドラッグして移動できるようにします。":
				return "Allows the misc panel to be moved by dragging with the mouse.";
			case "矢弾パネルのX位置。":
				return "Ammo panel X position.";
			case "矢弾パネルのY位置。":
				return "Ammo panel Y position.";
			case "矢弾パネルのサイズ。":
				return "Ammo panel scale.";
			case "矢弾パネルをマウスでドラッグして移動できるようにします。":
				return "Allows the ammo panel to be moved by dragging with the mouse.";
			case "鍵やライトなどの特殊アイテムパネルのX位置。":
				return "Special-item panel X position.";
			case "鍵やライトなどの特殊アイテムパネルのY位置。":
				return "Special-item panel Y position.";
			case "特殊アイテムパネルのサイズ。":
				return "Special-item panel scale.";
			case "特殊アイテムパネルをマウスでドラッグして移動できるようにします。":
				return "Allows the special-item panel to be moved by dragging with the mouse.";
			case "コインパネルのX位置。":
				return "Coin panel X position.";
			case "コインパネルのY位置。":
				return "Coin panel Y position.";
			case "コインパネルのサイズ。":
				return "Coin panel scale.";
			case "コインパネルをマウスでドラッグして移動できるようにします。":
				return "Allows the coin panel to be moved by dragging with the mouse.";
			case "食べ物クイックバーの左上からのX位置。":
				return "Food hotbar X position.";
			case "食べ物クイックバーの左上からのY位置。":
				return "Food hotbar Y position.";
			case "食べ物クイックバーのサイズ。":
				return "Food hotbar scale.";
			case "ミードクイックバーの左上からのX位置。":
				return "Mead hotbar X position.";
			case "ミードクイックバーの上端からのY位置。":
				return "Mead hotbar Y position.";
			case "ミードクイックバーのサイズ。":
				return "Mead hotbar scale.";
			case "矢弾クイックバーの左上からのX位置。":
				return "Ammo hotbar X position.";
			case "矢弾クイックバーの左上からのY位置。":
				return "Ammo hotbar Y position.";
			case "矢弾クイックバーのサイズ。":
				return "Ammo hotbar scale.";
			case "ケープクイックバーの左上からのX位置。":
				return "Cape hotbar X position.";
			case "ケープクイックバーの左上からのY位置。":
				return "Cape hotbar Y position.";
			case "ケープクイックバーのサイズ。":
				return "Cape hotbar scale.";
			case "現在の配置を保存したり、保存済みの配置へ切り替えます。":
				return "Save the current layout or switch to a saved layout.";
			case "装備スロット各パネルの背景を常時表示するかどうか。":
				return "Whether to always show the background of equipment-slot panels.";
			case "診断ログを有効にします。":
				return "Enable diagnostic logging.";
			default:
				if (ja.StartsWith("ケープスロット"))
				{
					return "Use cape slot " + ja.Substring(7).TrimEnd('。') + ".";
				}
				if (ja.StartsWith("食べ物スロット"))
				{
					return "Use food slot " + ja.Substring(7).TrimEnd('。') + ".";
				}
				if (ja.StartsWith("ポーションスロット"))
				{
					return "Use mead slot " + ja.Substring(9).TrimEnd('。') + ".";
				}
				if (ja.StartsWith("矢弾スロット"))
				{
					return "Use ammo slot " + ja.Substring(6).TrimEnd('。') + ".";
				}
				return ja;
			}
		}

		private static void ApplyConfigManagerLocalization()
		{
			object[] tags;
			foreach (ConfigEntryBase localizedConfigEntry in LocalizedConfigEntries)
			{
				if (localizedConfigEntry == null || !LocalizedConfigMetadata.TryGetValue(localizedConfigEntry, out var value) || localizedConfigEntry.Description == null || localizedConfigEntry.Description.Tags == null)
				{
					continue;
				}
				tags = localizedConfigEntry.Description.Tags;
				for (int i = 0; i < tags.Length; i++)
				{
					if (tags[i] is ConfigurationManagerAttributes configurationManagerAttributes)
					{
						configurationManagerAttributes.Category = ConfigText(value.Item1, TranslateCategory(value.Item1));
						configurationManagerAttributes.DispName = ConfigText(value.Item2, TranslateName(value.Item2));
						configurationManagerAttributes.Description = ConfigText(value.Item3, TranslateDescription(value.Item3));
					}
				}
			}
			if (DisplayLanguage != null && ((ConfigEntryBase)DisplayLanguage).Description != null && ((ConfigEntryBase)DisplayLanguage).Description.Tags != null)
			{
				tags = ((ConfigEntryBase)DisplayLanguage).Description.Tags;
				for (int i = 0; i < tags.Length; i++)
				{
					if (tags[i] is ConfigurationManagerAttributes configurationManagerAttributes2)
					{
						configurationManagerAttributes2.Category = "UI";
						configurationManagerAttributes2.DispName = ConfigText("表示言語", "Display Language");
						configurationManagerAttributes2.Description = ConfigText("表示言語を選択します。自動ではValheimの言語に合わせます。", "Select the display language. Auto follows Valheim's language.");
					}
				}
			}
			if (LayoutPresetControls == null || ((ConfigEntryBase)LayoutPresetControls).Description == null || ((ConfigEntryBase)LayoutPresetControls).Description.Tags == null)
			{
				return;
			}
			tags = ((ConfigEntryBase)LayoutPresetControls).Description.Tags;
			for (int i = 0; i < tags.Length; i++)
			{
				if (tags[i] is ConfigurationManagerAttributes configurationManagerAttributes3)
				{
					configurationManagerAttributes3.Category = ConfigText("レイアウトプリセット", "Layout Presets");
					configurationManagerAttributes3.DispName = ConfigText("プリセット", "Presets");
					configurationManagerAttributes3.Description = ConfigText("現在の配置を保存したり、保存済みの配置へ切り替えます。", "Save the current layout or switch to a saved layout.");
				}
			}
		}

		private static ConfigEntry<float> BindFloat(string section, string key, float value, string category, string name, string description)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Category = category,
				DispName = name,
				DefaultValue = value,
				Description = description
			};
			ConfigEntry<float> val = ((BaseUnityPlugin)Instance).Config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			LocalizedConfigEntries.Add((ConfigEntryBase)(object)val);
			LocalizedConfigMetadata[(ConfigEntryBase)(object)val] = Tuple.Create(category, name, description);
			return val;
		}

		private static ConfigEntry<bool> BindBool(string section, string key, bool value, string category, string name, string description)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Category = category,
				DispName = name,
				DefaultValue = value,
				Description = description
			};
			ConfigEntry<bool> val = ((BaseUnityPlugin)Instance).Config.Bind<bool>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			LocalizedConfigEntries.Add((ConfigEntryBase)(object)val);
			LocalizedConfigMetadata[(ConfigEntryBase)(object)val] = Tuple.Create(category, name, description);
			return val;
		}

		private static void MigrateLegacyHotkey(ConfigEntry<KeyboardShortcut> entry, KeyboardShortcut legacyDefault, KeyboardShortcut newDefault)
		{
			//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_0022: Unknown result type (might be due to invalid IL or missing references)
			if (entry == null)
			{
				return;
			}
			try
			{
				if (((object)entry.Value/*cast due to .constrained prefix*/).Equals((object?)legacyDefault))
				{
					entry.Value = newDefault;
				}
			}
			catch
			{
			}
		}

		private static ConfigEntry<KeyboardShortcut> BindHotkey(string section, string key, KeyboardShortcut value, string category, string name, string description)
		{
			//IL_0015: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Category = category,
				DispName = name,
				DefaultValue = value,
				Description = description
			};
			ConfigEntry<KeyboardShortcut> val = ((BaseUnityPlugin)Instance).Config.Bind<KeyboardShortcut>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			LocalizedConfigEntries.Add((ConfigEntryBase)(object)val);
			LocalizedConfigMetadata[(ConfigEntryBase)(object)val] = Tuple.Create(category, name, description);
			return val;
		}

		private void OnDestroy()
		{
			try
			{
				Harmony harmony = Harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}

		internal static void Log(string message)
		{
			if ((Object)(object)Instance != (Object)null && ShowDebugLog != null && ShowDebugLog.Value)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[Sakey's Equipment Slots] " + message));
			}
		}

		private void Update()
		{
			EquipmentSlotsGridUI.Update();
			SakeysQuickBarUI.Update();
		}

		private void LateUpdate()
		{
			EquipmentSlotsGridUI.LateUpdate();
		}

		private void OnGUI()
		{
			EquipmentSlotsGridUI.OnGUI();
			SakeysQuickBarUI.OnGUI();
		}
	}
	internal static class PlayerInventoryAccess
	{
		private static readonly FieldInfo InventoryField = AccessTools.Field(typeof(Player), "m_inventory");

		internal static Inventory Get(Player player)
		{
			if ((Object)(object)player == (Object)null || InventoryField == null)
			{
				return null;
			}
			object? value = InventoryField.GetValue(player);
			return (Inventory)((value is Inventory) ? value : null);
		}
	}
	internal static class InventoryFieldAccess
	{
		private static readonly FieldInfo HeightField = AccessTools.Field(typeof(Inventory), "m_height");

		private static readonly FieldInfo WidthField = AccessTools.Field(typeof(Inventory), "m_width");

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

		internal static int GetHeight(Inventory inv)
		{
			if (inv == null || HeightField == null)
			{
				return 0;
			}
			object value = HeightField.GetValue(inv);
			if (!(value is int))
			{
				return 0;
			}
			return (int)value;
		}

		internal static void SetHeight(Inventory inv, int value)
		{
			if (inv != null && !(HeightField == null))
			{
				HeightField.SetValue(inv, value);
			}
		}

		internal static int GetWidth(Inventory inv)
		{
			if (inv == null || WidthField == null)
			{
				return 0;
			}
			object value = WidthField.GetValue(inv);
			if (!(value is int))
			{
				return 0;
			}
			return (int)value;
		}

		internal static Vector2i GetSelected(InventoryGrid grid)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)grid == (Object)null || SelectedField == null)
			{
				return new Vector2i(0, 0);
			}
			object value = SelectedField.GetValue(grid);
			if (!(value is Vector2i))
			{
				return new Vector2i(0, 0);
			}
			return (Vector2i)value;
		}

		internal static void SetSelected(InventoryGrid grid, Vector2i value)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)grid == (Object)null) && !(SelectedField == null))
			{
				SelectedField.SetValue(grid, value);
			}
		}
	}
	internal sealed class SlotItem
	{
		internal ItemData Item;

		internal string PrefabName;

		internal string SharedName;

		internal bool Equipped;

		internal bool Empty => Item == null;

		internal void Capture(ItemData item)
		{
			Item = item;
			Equipped = item?.m_equipped ?? false;
			if (item != null)
			{
				PrefabName = ItemUtility.PrefabName(item);
				SharedName = ((item.m_shared != null) ? item.m_shared.m_name : "");
			}
		}

		internal void Clear()
		{
			Item = null;
			PrefabName = "";
			SharedName = "";
			Equipped = false;
		}
	}
	internal sealed class PlayerSlots
	{
		internal readonly SlotItem[] Utilities = new SlotItem[6];

		internal readonly SlotItem[] Capes = new SlotItem[2];

		internal int ActiveCape = -1;

		internal PlayerSlots()
		{
			for (int i = 0; i < Utilities.Length; i++)
			{
				Utilities[i] = new SlotItem();
			}
			for (int j = 0; j < Capes.Length; j++)
			{
				Capes[j] = new SlotItem();
			}
		}

		internal int FindUtility(ItemData item)
		{
			if (item == null)
			{
				return -1;
			}
			for (int i = 0; i < Utilities.Length; i++)
			{
				if (Utilities[i].Item == item)
				{
					return i;
				}
			}
			string b = ItemUtility.PrefabName(item);
			for (int j = 0; j < Utilities.Length; j++)
			{
				if (!Utilities[j].Empty && string.Equals(Utilities[j].PrefabName, b, StringComparison.Ordinal))
				{
					return j;
				}
			}
			return -1;
		}

		internal int FindEmptyUtility()
		{
			for (int i = 0; i < Utilities.Length; i++)
			{
				if (Utilities[i].Empty)
				{
					return i;
				}
			}
			return -1;
		}

		internal int FindCape(ItemData item)
		{
			if (item == null)
			{
				return -1;
			}
			for (int i = 0; i < Capes.Length; i++)
			{
				if (Capes[i].Item == item)
				{
					return i;
				}
			}
			return -1;
		}

		internal int FindEmptyCape()
		{
			for (int i = 0; i < Capes.Length; i++)
			{
				if (Capes[i].Empty)
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal static class SlotState
	{
		private sealed class State
		{
			internal readonly PlayerSlots Slots = new PlayerSlots();
		}

		private static readonly ConditionalWeakTable<Player, State> States = new ConditionalWeakTable<Player, State>();

		internal static PlayerSlots Get(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			return States.GetOrCreateValue(player).Slots;
		}

		internal static void RegisterUtility(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null || !ItemUtility.IsUtility(item))
			{
				return;
			}
			PlayerSlots playerSlots = Get(player);
			if (playerSlots.FindUtility(item) >= 0)
			{
				return;
			}
			int utilitySlot = ItemUtility.GetUtilitySlot(item);
			if (utilitySlot >= 0 && utilitySlot < playerSlots.Utilities.Length && playerSlots.Utilities[utilitySlot].Empty)
			{
				playerSlots.Utilities[utilitySlot].Capture(item);
				return;
			}
			int num = playerSlots.FindEmptyUtility();
			if (num < 0)
			{
				ItemUtility.ClearUtilitySlot(item);
				return;
			}
			playerSlots.Utilities[num].Capture(item);
			ItemUtility.SetUtilitySlot(item, num);
			SakeysEquipmentSlotsPlugin.Log("Utility registered: " + ItemUtility.PrefabName(item) + " -> U" + (num + 1));
		}

		internal static void RegisterCape(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null || !ItemUtility.IsCape(item))
			{
				return;
			}
			PlayerSlots playerSlots = Get(player);
			if (playerSlots.FindCape(item) >= 0)
			{
				return;
			}
			int capeSlot = ItemUtility.GetCapeSlot(item);
			if (capeSlot >= 0 && capeSlot < playerSlots.Capes.Length && playerSlots.Capes[capeSlot].Empty)
			{
				playerSlots.Capes[capeSlot].Capture(item);
				return;
			}
			int num = playerSlots.FindEmptyCape();
			if (num < 0)
			{
				ItemUtility.ClearCapeSlot(item);
				return;
			}
			playerSlots.Capes[num].Capture(item);
			ItemUtility.SetCapeSlot(item, num);
			if (playerSlots.ActiveCape < 0)
			{
				playerSlots.ActiveCape = num;
			}
			SakeysEquipmentSlotsPlugin.Log("Cape registered: " + ItemUtility.PrefabName(item) + " -> C" + (num + 1));
		}

		internal static void Restore(Player player)
		{
			if ((Object)(object)player == (Object)null || PlayerInventoryAccess.Get(player) == null)
			{
				return;
			}
			PlayerSlots playerSlots = Get(player);
			ItemData equipmentItem = ValheimAccess.GetEquipmentItem((Humanoid)(object)player, "m_shoulderItem");
			_ = playerSlots.ActiveCape;
			int result = -1;
			if (player.m_customData != null && player.m_customData.TryGetValue("com.sakey.equipmentslots.cape.active", out var value))
			{
				int.TryParse(value, out result);
			}
			for (int i = 0; i < playerSlots.Utilities.Length; i++)
			{
				playerSlots.Utilities[i].Clear();
			}
			for (int j = 0; j < playerSlots.Capes.Length; j++)
			{
				playerSlots.Capes[j].Clear();
			}
			playerSlots.ActiveCape = -1;
			List<ItemData> allItems = PlayerInventoryAccess.Get(player).GetAllItems();
			foreach (ItemData item in allItems)
			{
				int utilitySlot = ItemUtility.GetUtilitySlot(item);
				if (utilitySlot >= 0 && utilitySlot < playerSlots.Utilities.Length && playerSlots.Utilities[utilitySlot].Empty)
				{
					playerSlots.Utilities[utilitySlot].Capture(item);
				}
				int capeSlot = ItemUtility.GetCapeSlot(item);
				if (capeSlot >= 0 && capeSlot < playerSlots.Capes.Length && playerSlots.Capes[capeSlot].Empty)
				{
					playerSlots.Capes[capeSlot].Capture(item);
				}
			}
			foreach (ItemData item2 in allItems)
			{
				if (item2.m_customData == null || !item2.m_customData.ContainsKey("com.sakey.equipmentslots.released"))
				{
					if (ItemUtility.IsUtility(item2) && ItemUtility.GetUtilitySlot(item2) < 0 && item2.m_equipped)
					{
						RegisterUtility(player, item2);
					}
					if (ItemUtility.IsCape(item2) && ItemUtility.GetCapeSlot(item2) < 0 && item2.m_equipped)
					{
						RegisterCape(player, item2);
					}
				}
			}
			bool flag = equipmentItem?.m_customData != null && equipmentItem.m_customData.ContainsKey("com.sakey.equipmentslots.released");
			if (equipmentItem != null && !flag)
			{
				playerSlots.ActiveCape = playerSlots.FindCape(equipmentItem);
			}
			else
			{
				playerSlots.ActiveCape = -1;
			}
			for (int k = 0; k < playerSlots.Utilities.Length; k++)
			{
				playerSlots.Utilities[k].Equipped = playerSlots.Utilities[k].Item != null && playerSlots.Utilities[k].Item.m_equipped;
			}
			for (int l = 0; l < playerSlots.Capes.Length; l++)
			{
				playerSlots.Capes[l].Equipped = playerSlots.Capes[l].Item != null && playerSlots.Capes[l].Item.m_equipped;
			}
		}

		internal static void Validate(Player player)
		{
			if ((Object)(object)player == (Object)null || PlayerInventoryAccess.Get(player) == null)
			{
				return;
			}
			PlayerSlots playerSlots = Get(player);
			for (int i = 0; i < playerSlots.Utilities.Length; i++)
			{
				ItemData item = playerSlots.Utilities[i].Item;
				if (item != null && !IsStoredAnywhere(player, item))
				{
					playerSlots.Utilities[i].Clear();
				}
			}
			for (int j = 0; j < playerSlots.Capes.Length; j++)
			{
				ItemData item2 = playerSlots.Capes[j].Item;
				if (item2 != null && !IsStoredAnywhere(player, item2))
				{
					ItemUtility.ClearCapeSlot(item2);
					playerSlots.Capes[j].Clear();
					if (playerSlots.ActiveCape == j)
					{
						playerSlots.ActiveCape = -1;
					}
				}
			}
		}

		private static bool IsStoredAnywhere(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null)
			{
				return false;
			}
			Inventory val = PlayerInventoryAccess.Get(player);
			if (val != null && val.GetAllItems().Contains(item))
			{
				return true;
			}
			return EquipmentSlotsGridUI.IsBackingItem(player, item);
		}
	}
	internal static class QuickSlotState
	{
		private const string FoodKey = "com.sakey.equipmentslots.food.slot";

		private const string MeadKey = "com.sakey.equipmentslots.mead.slot";

		private const string AmmoKey = "com.sakey.equipmentslots.ammo.slot";

		private const string MiscKey = "com.sakey.equipmentslots.misc.slot";

		internal static ItemData[] GetRegistered(Player player, Func<ItemData, bool> filter, string key, int count)
		{
			ItemData[] array = (ItemData[])(object)new ItemData[count];
			if ((Object)(object)player == (Object)null || PlayerInventoryAccess.Get(player) == null)
			{
				return array;
			}
			List<ItemData> allItems = PlayerInventoryAccess.Get(player).GetAllItems();
			List<ItemData> list = new List<ItemData>();
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val = allItems[i];
				if (val != null && filter(val) && (val.m_customData == null || !val.m_customData.ContainsKey("com.sakey.equipmentslots.released")))
				{
					int slot = GetSlot(val, key);
					if (slot >= 0 && slot < count && array[slot] == null)
					{
						array[slot] = val;
					}
					else
					{
						list.Add(val);
					}
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				ItemData val2 = list[j];
				if (val2 == null)
				{
					continue;
				}
				int num = -1;
				for (int k = 0; k < count; k++)
				{
					if (array[k] == null)
					{
						num = k;
						break;
					}
				}
				if (num < 0)
				{
					if (val2.m_customData != null)
					{
						val2.m_customData.Remove(key);
						val2.m_customData.Remove("com.sakey.equipmentslots.released");
					}
				}
				else
				{
					SetSlot(val2, key, num);
					val2.m_customData?.Remove("com.sakey.equipmentslots.released");
					array[num] = val2;
				}
			}
			return array;
		}

		internal static ItemData[] GetFood(Player player)
		{
			return GetRegistered(player, IsFood, "com.sakey.equipmentslots.food.slot", 5);
		}

		internal static ItemData[] GetMead(Player player)
		{
			return GetRegistered(player, IsMead, "com.sakey.equipmentslots.mead.slot", 5);
		}

		internal static ItemData[] GetAmmo(Player player)
		{
			return GetRegistered(player, IsAmmo, "com.sakey.equipmentslots.ammo.slot", 3);
		}

		internal static ItemData[] GetMisc(Player player)
		{
			return GetRegistered(player, ItemUtility.IsMiscOrManual, "com.sakey.equipmentslots.misc.slot", 5);
		}

		private static int GetSlot(ItemData item, string key)
		{
			if (item == null || item.m_customData == null)
			{
				return -1;
			}
			if (!item.m_customData.TryGetValue(key, out var value) || !int.TryParse(value, out var result))
			{
				return -1;
			}
			return result;
		}

		private static void SetSlot(ItemData item, string key, int slot)
		{
			if (item != null)
			{
				if (item.m_customData == null)
				{
					item.m_customData = new Dictionary<string, string>();
				}
				item.m_customData[key] = slot.ToString();
			}
		}

		private static bool IsFood(ItemData item)
		{
			if (item != null && item.m_shared != null && !item.m_shared.m_isDrink)
			{
				if (!(item.m_shared.m_food > 0f) && !(item.m_shared.m_foodStamina > 0f))
				{
					return item.m_shared.m_foodEitr > 0f;
				}
				return true;
			}
			return false;
		}

		private static bool IsMead(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			if (item.m_shared.m_isDrink)
			{
				return true;
			}
			int slot = GetSlot(item, "com.sakey.equipmentslots.mead.slot");
			if (slot >= 0)
			{
				return slot < 5;
			}
			return false;
		}

		internal static bool IsAmmo(ItemData item)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			string name = Enum.GetName(typeof(ItemType), item.m_shared.m_itemType);
			if ((int)item.m_shared.m_itemType != 9 && !string.Equals(name, "AmmoNonEquipable", StringComparison.OrdinalIgnoreCase))
			{
				if (!string.IsNullOrEmpty(name))
				{
					return name.IndexOf("Ammo", StringComparison.OrdinalIgnoreCase) >= 0;
				}
				return false;
			}
			return true;
		}

		private static bool IsTrophyType(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			return (int)type == 13;
		}

		private static bool IsMisc(ItemData item)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			if ((int)item.m_shared.m_itemType == 16 && !ItemUtility.IsSpecial(item))
			{
				return !ItemUtility.IsCoin(item);
			}
			return false;
		}
	}
	internal static class ItemUtility
	{
		internal const string UtilitySlotKey = "com.sakey.equipmentslots.utility.slot";

		internal const string CapeSlotKey = "com.sakey.equipmentslots.cape.slot";

		internal static string PrefabName(ItemData item)
		{
			if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				return "";
			}
			return ((Object)item.m_dropPrefab).name.Replace("(Clone)", "").Trim();
		}

		internal static bool IsUtility(ItemData item)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			if ((int)item.m_shared.m_itemType != 18)
			{
				return IsTrinket(item);
			}
			return true;
		}

		internal static bool IsTrinket(ItemData item)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			return string.Equals(Enum.GetName(typeof(ItemType), item.m_shared.m_itemType), "Trinket", StringComparison.OrdinalIgnoreCase);
		}

		internal static bool IsCape(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			string text = PrefabName(item);
			string text2 = item.m_shared.m_name ?? "";
			if (text.IndexOf("cape", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return text2.IndexOf("cape", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		internal static bool IsSpecial(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			if (IsCape(item) || IsUtility(item) || IsCoin(item))
			{
				return false;
			}
			if (item.m_shared.m_food > 0f || item.m_shared.m_foodStamina > 0f || item.m_shared.m_foodEitr > 0f || item.m_shared.m_isDrink)
			{
				return false;
			}
			string text = PrefabName(item);
			string text2 = item.m_shared.m_name ?? "";
			string text3 = text + " " + text2;
			bool flag = text3.IndexOf("key", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("crypt", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("sealbreaker", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("blackcore", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("black core", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("surtlingcore", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("dragonegg", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("dragon egg", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("yagluthdrop", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("queendrop", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("boss", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("SakeysLight", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("Lantern", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("Sakey's Light", StringComparison.OrdinalIgnoreCase) >= 0;
			bool questItem = item.m_shared.m_questItem;
			if (!item.IsEquipable())
			{
				return flag || questItem;
			}
			return false;
		}

		internal static bool IsMisc(ItemData item)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			if ((int)item.m_shared.m_itemType == 16 && !IsSpecial(item))
			{
				return !IsCoin(item);
			}
			return false;
		}

		internal static bool IsManualMiscCandidate(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			if (GetArmorKind(item) != 0)
			{
				return false;
			}
			if (IsUtility(item) || IsCape(item) || IsSpecial(item) || IsCoin(item))
			{
				return false;
			}
			if (!item.m_shared.m_isDrink && (item.m_shared.m_food > 0f || item.m_shared.m_foodStamina > 0f || item.m_shared.m_foodEitr > 0f))
			{
				return false;
			}
			if (item.m_shared.m_isDrink)
			{
				return false;
			}
			if (QuickSlotState.IsAmmo(item))
			{
				return false;
			}
			return true;
		}

		private static int GetArmorKind(ItemData item)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (item == null || item.m_shared == null)
			{
				return 0;
			}
			string name = Enum.GetName(typeof(ItemType), item.m_shared.m_itemType);
			if (string.Equals(name, "Helmet", StringComparison.OrdinalIgnoreCase))
			{
				return 1;
			}
			if (string.Equals(name, "Chest", StringComparison.OrdinalIgnoreCase))
			{
				return 2;
			}
			if (string.Equals(name, "Legs", StringComparison.OrdinalIgnoreCase))
			{
				return 3;
			}
			return 0;
		}

		internal static bool IsMiscOrManual(ItemData item)
		{
			if (!IsMisc(item))
			{
				return IsManualMiscCandidate(item);
			}
			return true;
		}

		internal static bool IsCoin(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			string text = PrefabName(item);
			string text2 = item.m_shared.m_name ?? "";
			if (!text.Equals("Coins", StringComparison.OrdinalIgnoreCase) && text.IndexOf("coin", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return text2.IndexOf("coin", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		internal static Sprite Icon(ItemData item)
		{
			if (item == null || item.m_shared == null || item.m_shared.m_icons == null || item.m_shared.m_icons.Length == 0)
			{
				return null;
			}
			int num = Mathf.Clamp(item.m_quality - 1, 0, item.m_shared.m_icons.Length - 1);
			return item.m_shared.m_icons[num];
		}

		internal static int GetUtilitySlot(ItemData item)
		{
			return GetSlot(item, "com.sakey.equipmentslots.utility.slot");
		}

		internal static void SetUtilitySlot(ItemData item, int slot)
		{
			SetSlot(item, "com.sakey.equipmentslots.utility.slot", slot);
		}

		internal static void ClearUtilitySlot(ItemData item)
		{
			if (item?.m_customData != null)
			{
				item.m_customData.Remove("com.sakey.equipmentslots.utility.slot");
			}
		}

		internal static void GetUtilitySlotValue(ItemData item, out int slot)
		{
			slot = GetUtilitySlot(item);
		}

		internal static int GetCapeSlot(ItemData item)
		{
			return GetSlot(item, "com.sakey.equipmentslots.cape.slot");
		}

		internal static void SetCapeSlot(ItemData item, int slot)
		{
			SetSlot(item, "com.sakey.equipmentslots.cape.slot", slot);
		}

		internal static void ClearCapeSlot(ItemData item)
		{
			if (item?.m_customData != null)
			{
				item.m_customData.Remove("com.sakey.equipmentslots.cape.slot");
			}
		}

		private static int GetSlot(ItemData item, string key)
		{
			if (item == null || item.m_customData == null)
			{
				return -1;
			}
			if (!item.m_customData.TryGetValue(key, out var value) || !int.TryParse(value, out var result))
			{
				return -1;
			}
			return result;
		}

		private static void SetSlot(ItemData item, string key, int slot)
		{
			if (item != null)
			{
				if (item.m_customData == null)
				{
					item.m_customData = new Dictionary<string, string>();
				}
				item.m_customData[key] = slot.ToString();
			}
		}

		internal static bool SameItem(ItemData a, ItemData b)
		{
			if (a == null || b == null)
			{
				return false;
			}
			if (a == b)
			{
				return true;
			}
			if (string.Equals(PrefabName(a), PrefabName(b), StringComparison.Ordinal) && a.m_shared != null && b.m_shared != null)
			{
				return string.Equals(a.m_shared.m_name, b.m_shared.m_name, StringComparison.Ordinal);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	internal static class CustomSlotQuickTransferGuardPatch
	{
		private static ItemData SuppressedItem;

		private static bool SuppressEquip;

		internal static bool IsSuppressed(ItemData item)
		{
			if (SuppressEquip)
			{
				return SuppressedItem == item;
			}
			return false;
		}

		internal static bool IsQuickTransfer(ItemData item)
		{
			return IsSuppressed(item);
		}

		private static void Prefix(InventoryGrid grid, ItemData item, Modifier mod)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			SuppressEquip = false;
			SuppressedItem = null;
			InventoryGui instance = InventoryGui.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)grid == (Object)null) && item != null && (Object)(object)grid != (Object)(object)instance.m_playerGrid && (int)mod == 2)
			{
				SuppressEquip = true;
				SuppressedItem = item;
			}
		}

		private static void Postfix()
		{
			SuppressEquip = false;
			SuppressedItem = null;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class CustomSlotQuickTransferEquipGuardPatch
	{
		[HarmonyPriority(1000)]
		private static bool Prefix(ItemData item, ref bool __result)
		{
			if (!CustomSlotQuickTransferGuardPatch.IsSuppressed(item))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	internal static class CapeQuickTransferGuardPatch
	{
		private static bool SuppressEquip;

		private static ItemData SuppressedItem;

		internal static bool IsSuppressed(ItemData item)
		{
			if (SuppressEquip)
			{
				return SuppressedItem == item;
			}
			return false;
		}

		private static void Prefix(InventoryGrid grid, ItemData item, Modifier mod)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			SuppressEquip = false;
			SuppressedItem = null;
			InventoryGui instance = InventoryGui.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)grid == (Object)null) && item != null && ItemUtility.IsCape(item) && (Object)(object)grid != (Object)(object)instance.m_playerGrid && (int)mod == 2)
			{
				SuppressEquip = true;
				SuppressedItem = item;
			}
		}

		private static void Postfix()
		{
			SuppressEquip = false;
			SuppressedItem = null;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class CapeEquipPatch
	{
		private static ItemData PendingItem;

		private static Vector2i PendingSourcePosition;

		private static bool PendingSourceValid;

		internal static bool IsPending(ItemData item)
		{
			if (item != null)
			{
				return PendingItem == item;
			}
			return false;
		}

		private static void ClearPending()
		{
			//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)
			PendingItem = null;
			PendingSourcePosition = Vector2i.zero;
			PendingSourceValid = false;
		}

		private static bool IsNormalInventoryPosition(Player player, Vector2i pos)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			int baseHeightValueForPatch = EquipmentSlotsGridUI.GetBaseHeightValueForPatch(player);
			if (pos.y >= 0)
			{
				return pos.y < baseHeightValueForPatch;
			}
			return false;
		}

		private static Vector2i FindFreeNormalCell(Player player, ItemData moving)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Inventory val = PlayerInventoryAccess.Get(player);
			if (val == null)
			{
				return new Vector2i(-1, -1);
			}
			int inventoryWidthForPatch = EquipmentSlotsGridUI.GetInventoryWidthForPatch(player);
			int baseHeightValueForPatch = EquipmentSlotsGridUI.GetBaseHeightValueForPatch(player);
			for (int i = 0; i < baseHeightValueForPatch; i++)
			{
				for (int j = 0; j < inventoryWidthForPatch; j++)
				{
					ItemData itemAt = val.GetItemAt(j, i);
					if (itemAt == null || itemAt == moving)
					{
						return new Vector2i(j, i);
					}
				}
			}
			return new Vector2i(-1, -1);
		}

		private static void MoveDisplacedCapeToNormalInventory(Player player, ItemData displaced, Vector2i preferred)
		{
			//IL_0022: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || displaced == null)
			{
				return;
			}
			Inventory val = PlayerInventoryAccess.Get(player);
			if (val == null)
			{
				return;
			}
			Vector2i val2 = default(Vector2i);
			((Vector2i)(ref val2))..ctor(-1, -1);
			if (IsNormalInventoryPosition(player, preferred))
			{
				ItemData itemAt = val.GetItemAt(preferred.x, preferred.y);
				if (itemAt == null || itemAt == displaced)
				{
					val2 = preferred;
				}
			}
			if (val2.x < 0)
			{
				val2 = FindFreeNormalCell(player, displaced);
			}
			if (val2.x >= 0)
			{
				displaced.m_gridPos = val2;
			}
			displaced.m_equipped = false;
			EquipmentSlotsGridUI.ClearEquipmentSlotMarker(displaced);
			if (displaced.m_customData == null)
			{
				displaced.m_customData = new Dictionary<string, string>();
			}
			displaced.m_customData.Remove("com.sakey.equipmentslots.equipment.remember");
			displaced.m_customData["com.sakey.equipmentslots.released"] = "1";
		}

		private static void SyncActualCapeAfterNativeEquip(Player player, ItemData actual, Vector2i preferredDisplacedPosition)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || actual == null)
			{
				return;
			}
			PlayerSlots playerSlots = SlotState.Get(player);
			int num = playerSlots.FindCape(actual);
			if (num < 0)
			{
				int capeSlot = ItemUtility.GetCapeSlot(actual);
				if (capeSlot >= 0 && capeSlot < playerSlots.Capes.Length && playerSlots.Capes[capeSlot].Empty)
				{
					num = capeSlot;
				}
			}
			if (num < 0)
			{
				num = playerSlots.FindEmptyCape();
			}
			if (num < 0)
			{
				for (int i = 0; i < playerSlots.Capes.Length; i++)
				{
					ItemData item = playerSlots.Capes[i].Item;
					if (item != null && item != actual && ValheimAccess.GetEquipmentItem((Humanoid)(object)player, "m_shoulderItem") != item)
					{
						num = i;
						break;
					}
				}
			}
			if (num < 0)
			{
				num = 0;
			}
			ItemData item2 = playerSlots.Capes[num].Item;
			if (item2 != null && item2 != actual)
			{
				MoveDisplacedCapeToNormalInventory(player, item2, preferredDisplacedPosition);
			}
			playerSlots.Capes[num].Capture(actual);
			ItemUtility.SetCapeSlot(actual, num);
			actual.m_customData?.Remove("com.sakey.equipmentslots.released");
			actual.m_equipped = true;
			playerSlots.ActiveCape = num;
			for (int j = 0; j < playerSlots.Capes.Length; j++)
			{
				ItemData item3 = playerSlots.Capes[j].Item;
				bool equipped = item3 == actual;
				if (item3 != null)
				{
					item3.m_equipped = equipped;
				}
				playerSlots.Capes[j].Equipped = equipped;
			}
			if (player.m_customData == null)
			{
				player.m_customData = new Dictionary<string, string>();
			}
			player.m_customData["com.sakey.equipmentslots.cape.active"] = num.ToString();
			EquipmentSlotsGridUI.EnsureSlotPositionsAfterExternalEquipmentSwap(player);
			SakeysQuickBarUI.RefreshCustomBars(player);
			EquipmentSlotsGridUI.RefreshForInventoryUpdate(player, actual);
		}

		private static bool PrepareCapeInventoryEquip(Player player, ItemData item)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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)
			if ((Object)(object)player == (Object)null || item == null || !ItemUtility.IsCape(item))
			{
				return true;
			}
			PlayerSlots playerSlots = SlotState.Get(player);
			if (playerSlots.FindCape(item) >= 0)
			{
				return true;
			}
			int num = playerSlots.FindEmptyCape();
			if (num < 0)
			{
				ItemData val = null;
				int num2 = -1;
				ItemData equipmentItem = ValheimAccess.GetEquipmentItem((Humanoid)(object)player, "m_shoulderItem");
				for (int i = 0; i < playerSlots.Capes.Length; i++)
				{
					ItemData item2 = playerSlots.Capes[i].Item;
					if (item2 != null && item2 != equipmentItem && !item2.m_equipped)
					{
						val = item2;
						num2 = i;
						break;
					}
				}
				if (val == null)
				{
					return false;
				}
				num = num2;
				Vector2i gridPos = item.m_gridPos;
				MoveDisplacedCapeToNormalInventory(player, val, gridPos);
				ItemUtility.ClearCapeSlot(val);
				playerSlots.Capes[num].Clear();
			}
			playerSlots.Capes[num].Capture(item);
			ItemUtility.SetCapeSlot(item, num);
			item.m_customData?.Remove("com.sakey.equipmentslots.released");
			return true;
		}

		private static bool Prefix(Humanoid __instance, ItemData item, ref bool __result)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null || item == null || !ItemUtility.IsCape(item))
			{
				return true;
			}
			if (CapeController.InternalEquip)
			{
				return true;
			}
			if (CapeQuickTransferGuardPatch.IsSuppressed(item))
			{
				PlayerSlots playerSlots = SlotState.Get(val);
				if (playerSlots.FindCape(item) < 0)
				{
					int num = playerSlots.FindEmptyCape();
					if (num >= 0)
					{
						playerSlots.Capes[num].Capture(item);
						ItemUtility.SetCapeSlot(item, num);
					}
					else
					{
						ItemUtility.ClearCapeSlot(item);
					}
				}
				__result = false;
				return false;
			}
			if (!PrepareCapeInventoryEquip(val, item))
			{
				__result = false;
				return false;
			}
			PendingItem = item;
			PendingSourcePosition = item.m_gridPos;
			PendingSourceValid = true;
			return true;
		}

		private static void Postfix(Humanoid __instance, ItemData item, bool __result)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null || item == null || !ItemUtility.IsCape(item) || CapeController.InternalEquip)
			{
				return;
			}
			if (PendingItem != item)
			{
				ItemData equipmentItem = ValheimAccess.GetEquipmentItem((Humanoid)(object)val, "m_shoulderItem");
				if (equipmentItem != null && equipmentItem == item)
				{
					SyncActualCapeAfterNativeEquip(val, equipmentItem, new Vector2i(-1, -1));
				}
				return;
			}
			try
			{
				ItemData equipmentItem2 = ValheimAccess.GetEquipmentItem((Humanoid)(object)val, "m_shoulderItem");
				if (equipmentItem2 == item && __result)
				{
					Vector2i preferredDisplacedPosition = (Vector2i)(PendingSourceValid ? PendingSourcePosition : new Vector2i(-1, -1));
					SyncActualCapeAfterNativeEquip(val, equipmentItem2, preferredDisplacedPosition);
				}
				else if (equipmentItem2 != null)
				{
					CapeController.SynchronizeActualCape(val, equipmentItem2);
				}
			}
			finally
			{
				ClearPending();
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class EquipmentArmorEquipPatch
	{
		private static ItemData PendingItem;

		private static Vector2i PendingSourcePosition;

		private static bool PendingSourceValid;

		internal static bool IsPending(ItemData item)
		{
			if (item != null)
			{
				return PendingItem == item;
			}
			return false;
		}

		private static void ClearPending()
		{
			//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)
			PendingItem = null;
			PendingSourcePosition = Vector2i.zero;
			PendingSourceValid = false;
		}

		private static int BaseForKind(EquipmentSlotsGridUI.EquipmentKind kind)
		{
			return kind switch
			{
				EquipmentSlotsGridUI.EquipmentKind.Helmet => 0, 
				EquipmentSlotsGridUI.EquipmentKind.Chest => 2, 
				EquipmentSlotsGridUI.EquipmentKind.Legs => 4, 
				_ => -1, 
			};
		}

		private static ItemData GetEquipmentForKind(Player player, EquipmentSlotsGridUI.EquipmentKind kind)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			return (ItemData)(kind switch
			{
				EquipmentSlotsGridUI.EquipmentKind.Helmet => ValheimAccess.GetEquipmentItem((Humanoid)(object)player, "m_helmetItem"), 
				EquipmentSlotsGridUI.EquipmentKind.Chest => ValheimAccess.GetEquipmentItem((Humanoid)(object)player, "m_chestItem"), 
				EquipmentSlotsGridUI.EquipmentKind.Legs => ValheimAccess.GetEquipmentItem((Humanoid)(object)player, "m_legItem"), 
				_ => null, 
			});
		}

		private static bool IsNormalInventoryPosition(Player player, Vector2i pos)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			int baseHeightValueForPatch = EquipmentSlotsGridUI.GetBaseHeightValueForPatch(player);
			if (pos.y >= 0)
			{
				return pos.y < baseHeightValueForPatch;
			}
			return false;
		}

		private static Vector2i FindFreeNormalCell(Player player, ItemData moving)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Inventory val = PlayerInventoryAccess.Get(player);
			if (val == null)
			{
				return new Vector2i(-1, -1);
			}
			int inventoryWidthForPatch = EquipmentSlotsGridUI.GetInventoryWidthForPatch(player);
			int baseHeightValueForPatch = EquipmentSlotsGridUI.GetBaseHeightValueForPatch(player);
			for (int i = 0; i < baseHeightValueForPatch; i++)
			{
				for (int j = 0; j < inventoryWidthForPatch; j++)
				{
					ItemData itemAt = val.GetItemAt(j, i);
					if (itemAt == null || itemAt == moving)
					{
						return new Vector2i(j, i);
					}
				}
			}
			return new Vector2i(-1, -1);
		}

		private static void MoveDisplacedArmorToNormalInventory(Player player, ItemData displaced, Vector2i preferred)
		{
			//IL_0022: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || displaced == null)
			{
				return;
			}
			Inventory val = PlayerInventoryAccess.Get(player);
			if (val == null)
			{
				return;
			}
			Vector2i val2 = default(Vector2i);
			((Vector2i)(ref val2))..ctor(-1, -1);
			if (IsNormalInventoryPosition(player, preferred))
			{
				ItemData itemAt = val.GetItemAt(preferred.x, preferred.y);
				if (itemAt == null || itemAt == displaced)
				{
					val2 = preferred;
				}
			}
			if (val2.x < 0)
			{
				val2 = FindFreeNormalCell(player, displaced);
			}
			if (val2.x >= 0)
			{
				displaced.m_gridPos = val2;
			}
			displaced.m_equipped = false;
			EquipmentSlotsGridUI.ClearEquipmentSlotMarker(displaced);
			if (displaced.m_customData == null)
			{
				displaced.m_customData = new Dictionary<string, string>();
			}
			displaced.m_customData.Remove("com.sakey.equipmentslots.equipment.remember");
			displaced.m_customData["com.sakey.equipmentslots.released"] = "1";
		}

		private static void SyncNativeArmorAfterEquip(Player player, ItemData actual)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || actual == null)
			{
				return;
			}
			int num = BaseForKind(EquipmentSlotsGridUI.GetEquipmentKind(actual));
			if (num < 0)
			{
				return;
			}
			int num2 = -1;
			int rememberedOrActiveEquipmentSlot = EquipmentSlotsGridUI.GetRememberedOrActiveEquipmentSlot(actual);
			if (rememberedOrActiveEquipmentSlot >= num && rememberedOrActiveEquipmentSlot < num + 2 && EquipmentSlotsGridUI.GetItemMarkedForSlotForMouse(player, rememberedOrActiveEquipmentSlot) == null)
			{
				num2 = rememberedOrActiveEquipmentSlot;
			}
			if (num2 < 0)
			{
				for (int i = num; i < num + 2; i++)
				{
					if (EquipmentSlotsGridUI.EquipmentSlotMatches(actual, i) && EquipmentSlotsGridUI.GetItemMarkedForSlotForMouse(player, i) == null)
					{
						num2 = i;
						break;
					}
				}
			}
			if (num2 < 0)
			{
				EquipmentSlotsGridUI.ClearEquipmentSlotMarker(actual);
				if (actual.m_customData == null)
				{
					actual.m_customData = new Dictionary<string, string>();
				}
				actual.m_customData["com.sakey.equipmentslots.released"] = "1";
				actual.m_equipped = true;
				SyncEquippedArmorState(player);
				EquipmentSlotsGridUI.EnsureSlotPositionsAfterExternalEquipmentSwap(player);
				EquipmentSlotsGridUI.RefreshForInventoryUpdate(player, actual);
				return;
			}
			ItemData itemMarkedForSlotForMouse = EquipmentSlotsGridUI.GetItemMarkedForSlotForMouse(player, num2);
			if (itemMarkedForSlotForMouse != null && itemMarkedForSlotForMouse != actual)
			{
				MoveDisplacedArmorToNormalInventory(player, itemMarkedForSlotForMouse, (Vector2i)(PendingSourceValid ? PendingSourcePosition : new Vector2i(-1, -1)));
			}
			EquipmentSlotsGridUI.SetOwnerAndEquipmentSlot(actual, num2);
			actual.m_customData?.Remove("com.sakey.equipmentslots.released");
			actual.m_equipped = true;
			SyncEquippedArmorState(player);
			EquipmentSlotsGridUI.EnsureSlotPositionsAfterExternalEquipmentSwap(player);
			EquipmentSlotsGridUI.RefreshForInventoryUpdate(player, actual);
		}

		private static void SyncEquippedArmorState(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			Inventory val = PlayerInventoryAccess.Get(player);
			if (val == null)
			{
				return;
			}
			ItemData equipmentForKind = GetEquipmentForKind(player, EquipmentSlotsGridUI.EquipmentKind.Helmet);
			ItemData equipmentForKind2 = GetEquipmentForKind(player, EquipmentSlotsGridUI.EquipmentKind.Chest);
			ItemData equipmentForKind3 = GetEquipmentForKind(player, EquipmentSlotsGridUI.EquipmentKind.Legs);
			foreach (ItemData allItem in val.GetAllItems())
			{
				if (allItem != null)
				{
					switch (EquipmentSlotsGridUI.GetEquipmentKind(allItem))
					{
					case EquipmentSlotsGridUI.EquipmentKind.Helmet:
						allItem.m_equipped = allItem == equipmentForKind;
						break;
					case EquipmentSlotsGridUI.EquipmentKind.Chest:
						allItem.m_equipped = allItem == equipmentForKind2;
						break;
					case EquipmentSlotsGridUI.EquipmentKind.Legs:
						allItem.m_equipped = allItem == equipmentForKind3;
						break;
					}
				}
			}
		}

		private static void Prefix(Humanoid __instance, ItemData item)
		{
			//IL_0042: 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)
			if (!((Object)(object)((__instance is Player) ? __instance : null) == (Object)null) && item != null && item.IsEquipable() && !ItemUtility.IsUtility(item) && !ItemUtility.IsCape(item) && !QuickSlotState.IsAmmo(item) && EquipmentSlotsGridUI.GetEquipmentKind(item) != EquipmentSlotsGridUI.EquipmentKind.None)
			{
				PendingItem = item;
				PendingSourcePosition = item.m_gridPos;
				PendingSourceValid = true;
			}
		}

		private static void Postfix(Humanoid __instance, ItemData item)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null || item == null || PendingItem != item)
			{
				return;
			}
			try
			{
				EquipmentSlotsGridUI.EquipmentKind equipmentKind = EquipmentSlotsGridUI.GetEquipmentKind(item);
				ItemData equipmentForKind = GetEquipmentForKind(val, equipmentKind);
				if (equipmentForKind == item)
				{
					SyncNativeArmorAfterEquip(val, equipmentForKind);
				}
			}
			finally
			{
				ClearPending();
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class HumanoidEquipPatch
	{
		private static bool Prefix(Humanoid __instance, ItemData item, bool triggerEquipEffects, ref bool __result)
		{
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null || item == null || !ItemUtility.IsUtility(item))
			{
				return true;
			}
			PlayerSlots playerSlots = SlotState.Get(val);
			if (PlayerEquipInventoryItemsPatch.IsRestoring(val))
			{
				bool flag = item.m_customData != null && item.m_customData.ContainsKey("com.sakey.equipmentslots.released");
				int utilitySlot = ItemUtility.GetUtilitySlot(item);
				if ((utilitySlot >= 0 && utilitySlot < playerSlots.Utilities.Length) || flag)
				{
					if (utilitySlot >= 0 && utilitySlot < playerSlots.Utilities.Length)
					{
						playerSlots.Utilities[utilitySlot].Capture(item);
						ItemUtility.SetUtilitySlot(item, utilitySlot);
					}
					item.m_equipped = true;
					if (!flag && ValheimAccess.GetEquipme