Decompiled source of Aicho Dual Hotbar v1.0.0

Aicho_DualHotbar.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
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("Aicho_DualHotbar")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A second hotbar row for Valheim, swappable with a key.")]
[assembly: AssemblyFileVersion("0.7.3.0")]
[assembly: AssemblyInformationalVersion("0.7.3")]
[assembly: AssemblyProduct("Aicho Dual Hotbar")]
[assembly: AssemblyTitle("Aicho_DualHotbar")]
[assembly: AssemblyVersion("0.7.3.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 AichoDualHotbar
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("aicho.dualhotbar", "Aicho Dual Hotbar", "0.7.3")]
	public class DualHotbarPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "aicho.dualhotbar";

		public const string PluginName = "Aicho Dual Hotbar";

		public const string PluginVersion = "0.7.3";

		internal const int ExtraRows = 1;

		internal const string UnlockKey = "aicho_dualhotbar_unlocked";

		internal const string MigratedKey = "aicho_dualhotbar_migrated";

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyboardShortcut> SwapKey;

		internal static ConfigEntry<int> PurchasePrice;

		internal static ConfigEntry<string> RequiredGlobalKey;

		internal static readonly Fixed<float> SeparationGap = new Fixed<float>(20f);

		internal static readonly Fixed<bool> ShowSecondBarNumbers = new Fixed<bool>(value: true);

		internal static readonly Fixed<bool> SidePanelsBelowBars = new Fixed<bool>(value: true);

		internal static readonly Fixed<float> SidePanelsExtraOffset = new Fixed<float>(0f);

		internal static readonly Fixed<bool> EquipOnSwap = new Fixed<bool>(value: true);

		internal static readonly Fixed<bool> ProtectFromQuickStack = new Fixed<bool>(value: true);

		internal static readonly Fixed<bool> RequirePurchase = new Fixed<bool>(value: true);

		internal static readonly Fixed<bool> SwapSoundEnabled = new Fixed<bool>(value: true);

		internal static readonly Fixed<float> SwapSoundVolume = new Fixed<float>(0.5f);

		internal static readonly Fixed<bool> LogKeyPresses = new Fixed<bool>(value: false);

		internal static float AppliedGap;

		internal static DualHotbarPlugin Instance;

		private static readonly KeyCode[] AllKeys = (KeyCode[])Enum.GetValues(typeof(KeyCode));

		private static readonly string[] SoundFileNames = new string[3] { "swap.wav", "swap.ogg", "swap.mp3" };

		private string _soundFolder;

		private AudioSource _audio;

		private AudioClip _externalClip;

		private AudioClip _embeddedClip;

		private bool _embeddedTried;

		private string _clipPath;

		private DateTime _clipStamp;

		private bool _loadingClip;

		private const float MaxVolume = 8f;

		private const float LimiterKnee = 0.6f;

		private AudioClip _boostClip;

		private AudioClip _boostSource;

		private float _boostGain;

		internal const string ActiveRowKey = "aicho_dualhotbar_row";

		private const string MemoryRowsKey = "aicho_dualhotbar_rowmem";

		private const string HoldFlagKey = "aicho_dualhotbar_hold";

		internal const string ActiveBarKey = "aicho_dualhotbar_active";

		private static readonly MethodInfo ToggleEquippedMethod = AccessTools.Method(typeof(Player), "ToggleEquipped", (Type[])null, (Type[])null);

		internal static bool BarActive(Player player)
		{
			if (Enabled.Value && (Object)(object)player != (Object)null)
			{
				if (RequirePurchase.Value)
				{
					return ((Humanoid)player).HaveUniqueKey("aicho_dualhotbar_unlocked");
				}
				return true;
			}
			return false;
		}

		internal static int GetVanillaRows(Player player)
		{
			int num = 4;
			string s = default(string);
			if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result))
			{
				num = result;
			}
			return Mathf.Clamp(num, 0, 9);
		}

		internal static void LogWarning(string message)
		{
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)message);
		}

		internal static void LogInfo(string message)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
		}

		internal static float CurrentGap()
		{
			if (!BarActive(Player.m_localPlayer))
			{
				return 0f;
			}
			return Mathf.Max(0f, SeparationGap.Value);
		}

		internal static string T(string spanish, string english)
		{
			if (Localization.instance == null || !(Localization.instance.GetSelectedLanguage() == "Spanish"))
			{
				return english;
			}
			return spanish;
		}

		internal static void GrantIfAlreadyUsed(Player player, int rows)
		{
			if (!RequirePurchase.Value || player.m_customData.ContainsKey("aicho_dualhotbar_migrated"))
			{
				return;
			}
			player.m_customData["aicho_dualhotbar_migrated"] = "1";
			if (((Humanoid)player).HaveUniqueKey("aicho_dualhotbar_unlocked"))
			{
				return;
			}
			bool flag = player.m_customData.ContainsKey("aicho_dualhotbar_active") || player.m_customData.ContainsKey("aicho_dualhotbar_row");
			if (!flag && !Compat.ExtraSlotsOwnsRows)
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (allItem.m_gridPos.y >= rows && allItem.m_gridPos.x >= 0 && allItem.m_gridPos.x < inventory.GetWidth())
					{
						flag = true;
						break;
					}
				}
			}
			if (flag)
			{
				((Humanoid)player).AddUniqueKey("aicho_dualhotbar_unlocked");
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Second hotbar granted: this character already used it before it had to be bought");
			}
		}

		private void Awake()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			//IL_011f: Expected O, but got Unknown
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Turns the second hotbar row on or off. Needs a restart of the game. Empty the LAST inventory row before turning it off: that row disappears and its items would be dropped on the ground.");
			SwapKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "SwapKey", new KeyboardShortcut((KeyCode)60, Array.Empty<KeyCode>()), "Key that swaps the two hotbar rows. Default is the '<' key.");
			PurchasePrice = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "PurchasePrice", 2000, new ConfigDescription("Price in coins of the second hotbar at Haldor.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>()));
			RequiredGlobalKey = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "RequiredGlobalKey", "defeated_gdking", "World progress needed before Haldor sells it. Default defeated_gdking = The Elder (2nd boss). Other examples: defeated_eikthyr, defeated_bonemass, defeated_dragon (the first sack uses this one), defeated_queen (the second sack). Empty = always available.");
			IndicatorConfig.Bind(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				HotbarIndicator.MarkDirty();
			};
			_soundFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			RefreshSound();
			Compat.Detect();
			Harmony val = new Harmony("aicho.dualhotbar");
			val.PatchAll();
			Compat.PatchExtraSlots(val);
			Compat.PatchQuickStack(val);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Aicho Dual Hotbar 0.7.3 loaded");
		}

		private string FindSoundFile()
		{
			string[] soundFileNames = SoundFileNames;
			foreach (string path in soundFileNames)
			{
				string text = Path.Combine(_soundFolder, path);
				if (File.Exists(text))
				{
					return text;
				}
			}
			return null;
		}

		private void RefreshSound()
		{
			if (_loadingClip)
			{
				return;
			}
			string text = FindSoundFile();
			if (text == null)
			{
				if (_clipPath != null)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Swap sound file removed, using the built-in sound");
				}
				SetExternalClip(null);
				_clipPath = null;
				GetEmbeddedClip();
			}
			else
			{
				DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(text);
				if (!(text == _clipPath) || !(lastWriteTimeUtc == _clipStamp))
				{
					((MonoBehaviour)this).StartCoroutine(LoadSound(text, lastWriteTimeUtc));
				}
			}
		}

		private IEnumerator LoadSound(string path, DateTime stamp)
		{
			_loadingClip = true;
			string text = Path.GetExtension(path).ToLowerInvariant();
			AudioType val = (AudioType)((text == ".ogg") ? 14 : ((text == ".mp3") ? 13 : 20));
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, val);
			try
			{
				yield return request.SendWebRequest();
				_clipPath = path;
				_clipStamp = stamp;
				if ((int)request.result != 1)
				{
					SetExternalClip(null);
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not load swap sound " + Path.GetFileName(path) + ": " + request.error + "; using the built-in sound"));
				}
				else
				{
					AudioClip content = DownloadHandlerAudioClip.GetContent(request);
					if ((Object)(object)content == (Object)null || content.length <= 0f)
					{
						SetExternalClip(null);
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Swap sound " + Path.GetFileName(path) + " is empty or unreadable; using the built-in sound"));
					}
					else
					{
						((Object)content).name = "AichoSwap";
						SetExternalClip(content);
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"Swap sound loaded: {Path.GetFileName(path)} ({content.length:0.00} s)");
					}
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			_loadingClip = false;
		}

		private static AudioClip GetSwapClip()
		{
			DualHotbarPlugin instance = Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if (!((Object)(object)instance._externalClip != (Object)null))
			{
				return instance.GetEmbeddedClip();
			}
			return instance._externalClip;
		}

		private AudioClip GetEmbeddedClip()
		{
			if ((Object)(object)_embeddedClip == (Object)null && !_embeddedTried)
			{
				_embeddedTried = true;
				_embeddedClip = EmbeddedAssets.LoadSwapClip();
				if ((Object)(object)_embeddedClip != (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Swap sound loaded: built-in ({_embeddedClip.length:0.00} s)");
				}
			}
			return _embeddedClip;
		}

		private void SetExternalClip(AudioClip clip)
		{
			if ((Object)(object)_externalClip != (Object)null)
			{
				Object.Destroy((Object)(object)_externalClip);
			}
			_externalClip = clip;
		}

		private AudioClip GetBoostedClip(AudioClip source, float gain)
		{
			if ((Object)(object)_boostClip != (Object)null && (Object)(object)_boostSource == (Object)(object)source && Mathf.Approximately(_boostGain, gain))
			{
				return _boostClip;
			}
			float[] array = new float[source.samples * source.channels];
			if (!source.GetData(array, 0))
			{
				return source;
			}
			float num = 0.39999998f;
			for (int i = 0; i < array.Length; i++)
			{
				float num2 = array[i] * gain;
				float num3 = Mathf.Abs(num2);
				if (num3 > 0.6f)
				{
					num2 = Mathf.Sign(num2) * (0.6f + num * (float)Math.Tanh((num3 - 0.6f) / num));
				}
				array[i] = num2;
			}
			AudioClip val = AudioClip.Create("AichoSwapBoost", source.samples, source.channels, source.frequency, false);
			val.SetData(array, 0);
			if ((Object)(object)_boostClip != (Object)null)
			{
				Object.Destroy((Object)(object)_boostClip);
			}
			_boostClip = val;
			_boostSource = source;
			_boostGain = gain;
			return val;
		}

		private static AudioMixerGroup GetSfxMixerGroup()
		{
			AudioMixer val = (((Object)(object)AudioMan.instance != (Object)null) ? AudioMan.instance.m_masterMixer : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			AudioMixerGroup[] array = val.FindMatchingGroups("SFX");
			if (array == null || array.Length == 0)
			{
				return null;
			}
			return array[0];
		}

		internal static void PlaySwapSound()
		{
			DualHotbarPlugin instance = Instance;
			if ((Object)(object)instance == (Object)null || !SwapSoundEnabled.Value)
			{
				return;
			}
			instance.RefreshSound();
			float num = Mathf.Clamp(SwapSoundVolume.Value, 0f, 8f);
			AudioClip val = GetSwapClip();
			if (!((Object)(object)val == (Object)null) && !(num <= 0f))
			{
				float num2 = Mathf.Min(num, 1f);
				if (num > 1f)
				{
					val = instance.GetBoostedClip(val, num);
					num2 = 1f;
				}
				if ((Object)(object)instance._audio == (Object)null)
				{
					instance._audio = ((Component)instance).gameObject.AddComponent<AudioSource>();
					instance._audio.playOnAwake = false;
					instance._audio.spatialBlend = 0f;
				}
				if ((Object)(object)instance._audio.outputAudioMixerGroup == (Object)null)
				{
					instance._audio.outputAudioMixerGroup = GetSfxMixerGroup();
				}
				instance._audio.PlayOneShot(val, num2);
			}
		}

		private void Update()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected I4, but got Unknown
			if (!Enabled.Value)
			{
				return;
			}
			HotbarIndicator.UpdateFrame();
			if (LogKeyPresses.Value && Input.anyKeyDown)
			{
				KeyCode[] allKeys = AllKeys;
				foreach (KeyCode val in allKeys)
				{
					if (Input.GetKeyDown(val))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"Key pressed: {val} ({(int)val})");
					}
				}
			}
			KeyboardShortcut value = SwapKey.Value;
			bool flag = ((KeyboardShortcut)(ref value)).IsDown();
			if (!flag && (int)((KeyboardShortcut)(ref value)).MainKey == 60 && Input.inputString.IndexOf('<') >= 0)
			{
				flag = true;
			}
			if (flag)
			{
				TrySwapBars();
			}
		}

		private static bool CanSwapNow(Player player)
		{
			if ((Object)(object)player == (Object)null || ((Character)player).IsDead())
			{
				return false;
			}
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return false;
			}
			if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible())
			{
				return false;
			}
			return true;
		}

		internal static void TrySwapBars()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!CanSwapNow(localPlayer))
			{
				return;
			}
			if (!BarActive(localPlayer))
			{
				((Character)localPlayer).Message((MessageType)2, T("Aún no tienes la segunda barra. Cómprasela a Haldor.", "You don't have the second hotbar yet. Buy it from Haldor."), 0, (Sprite)null, false);
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory.GetHeight() >= 2)
			{
				int num = ActiveRow(localPlayer);
				int num2 = 1 - num;
				int num3 = ReadPlayerInt(localPlayer, "aicho_dualhotbar_rowmem");
				List<ItemData> held = null;
				if (EquipOnSwap.Value)
				{
					held = RememberHeldItems(inventory, num);
				}
				HotbarTransition.Begin(num, num2);
				WritePlayerInt(localPlayer, "aicho_dualhotbar_row", num2);
				if (EquipOnSwap.Value)
				{
					WritePlayerInt(localPlayer, "aicho_dualhotbar_rowmem", num3 | (1 << num));
					bool arrivingHasMemory = (num3 & (1 << num2)) != 0;
					SwapHeldItems(localPlayer, inventory, held, num2, arrivingHasMemory);
				}
				PlaySwapSound();
			}
		}

		internal static int ActiveRow(Player player)
		{
			if (!BarActive(player))
			{
				return 0;
			}
			return Mathf.Clamp(ReadPlayerInt(player, "aicho_dualhotbar_row"), 0, 1);
		}

		internal static int ReadPlayerInt(Player player, string key)
		{
			if (!player.m_customData.TryGetValue(key, out var value) || !int.TryParse(value, out var result))
			{
				return 0;
			}
			return result;
		}

		private static void WritePlayerInt(Player player, string key, int value)
		{
			player.m_customData[key] = value.ToString();
		}

		private static List<ItemData> RememberHeldItems(Inventory inventory, int row)
		{
			List<ItemData> list = new List<ItemData>();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_gridPos.y == row && IsHandItem(allItem))
				{
					if (allItem.m_equipped)
					{
						allItem.m_customData["aicho_dualhotbar_hold"] = "1";
						list.Add(allItem);
					}
					else
					{
						allItem.m_customData.Remove("aicho_dualhotbar_hold");
					}
				}
			}
			return list;
		}

		private static bool IsHandItem(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType <= 15)
			{
				if (itemType - 3 <= 2 || itemType - 14 <= 1)
				{
					goto IL_002a;
				}
			}
			else if ((int)itemType == 19 || (int)itemType == 22)
			{
				goto IL_002a;
			}
			return false;
			IL_002a:
			return true;
		}

		private static void SwapHeldItems(Player player, Inventory inventory, List<ItemData> held, int arrivingRow, bool arrivingHasMemory)
		{
			if (((Character)player).InAttack())
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (ItemData item in held)
			{
				((Humanoid)player).UnequipItem(item, true);
				if (!list.Contains(item.m_gridPos.x))
				{
					list.Add(item.m_gridPos.x);
				}
			}
			list.Sort();
			List<ItemData> list2 = new List<ItemData>();
			for (int i = 0; i < inventory.GetWidth(); i++)
			{
				ItemData itemAt = inventory.GetItemAt(i, arrivingRow);
				if (itemAt != null && IsHandItem(itemAt))
				{
					bool flag = itemAt.m_customData.ContainsKey("aicho_dualhotbar_hold");
					if (arrivingHasMemory ? flag : list.Contains(i))
					{
						list2.Add(itemAt);
					}
					itemAt.m_customData.Remove("aicho_dualhotbar_hold");
				}
			}
			foreach (ItemData item2 in list2)
			{
				if (!((Humanoid)player).IsItemEquiped(item2))
				{
					ToggleEquippedMethod.Invoke(player, new object[1] { item2 });
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SetInventorySize")]
	internal static class PlayerSetInventorySizePatch
	{
		private static bool Prefix(Player __instance, int rows)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (!DualHotbarPlugin.Enabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (Compat.ExtraSlotsOwnsRows)
			{
				return true;
			}
			rows = Mathf.Clamp(rows, 0, 9);
			DualHotbarPlugin.GrantIfAlreadyUsed(__instance, rows);
			bool flag = DualHotbarPlugin.BarActive(__instance);
			int num = rows + (flag ? 1 : 0);
			((Humanoid)__instance).GetInventory().SetHeight(num);
			__instance.AddUniqueKeyValue("invrows", rows.ToString());
			float num2 = (DualHotbarPlugin.AppliedGap = (flag ? Mathf.Max(0f, DualHotbarPlugin.SeparationGap.Value) : 0f));
			InventoryGui instance = InventoryGui.instance;
			instance.SetInventorySize(num);
			instance.m_player.sizeDelta = new Vector2(instance.m_player.sizeDelta.x, instance.m_player.sizeDelta.y + num2);
			((Humanoid)__instance).DropInvalidItems();
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class PlayerOnSpawnedPatch
	{
		private static void Postfix(Player __instance)
		{
			if (!DualHotbarPlugin.Enabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			int vanillaRows = DualHotbarPlugin.GetVanillaRows(__instance);
			bool flag = DualHotbarPlugin.BarActive(__instance);
			DualHotbarPlugin.GrantIfAlreadyUsed(__instance, vanillaRows);
			bool flag2 = DualHotbarPlugin.BarActive(__instance);
			if (Compat.ExtraSlotsOwnsRows)
			{
				if (flag2 && !flag)
				{
					__instance.SetInventorySize(vanillaRows);
				}
			}
			else
			{
				int num = vanillaRows + (flag2 ? 1 : 0);
				if (((Humanoid)__instance).GetInventory().GetHeight() != num)
				{
					__instance.SetInventorySize(vanillaRows);
				}
			}
			SidePanels.Refresh(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
	internal static class InventoryGridLayoutPatch
	{
		private static readonly FieldRef<InventoryGrid, List<InventoryElement>> ElementsRef = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements");

		private const float SecondBarNumberAlpha = 0.5f;

		private static void Postfix(InventoryGrid __instance)
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			if (!DualHotbarPlugin.BarActive(Player.m_localPlayer))
			{
				return;
			}
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)__instance != (Object)(object)instance.m_playerGrid)
			{
				return;
			}
			Inventory inventory = __instance.GetInventory();
			if (inventory == null)
			{
				return;
			}
			int width = inventory.GetWidth();
			int height = inventory.GetHeight();
			if (width <= 0 || height <= 2)
			{
				return;
			}
			bool extraSlotsOwnsRows = Compat.ExtraSlotsOwnsRows;
			int num = (extraSlotsOwnsRows ? Compat.PlayerRows(height) : height);
			List<InventoryElement> list = ElementsRef.Invoke(__instance);
			float elementSpace = __instance.m_elementSpace;
			float num2 = (extraSlotsOwnsRows ? DualHotbarPlugin.CurrentGap() : DualHotbarPlugin.AppliedGap);
			for (int i = 0; i < list.Count; i++)
			{
				int num3 = i / width;
				int col = i - num3 * width;
				InventoryElement val = list[i];
				RectTransform val2 = (RectTransform)((num3 < num) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val2 != (Object)null)
				{
					float num4 = (float)(-num3) * elementSpace - ((num3 >= 2) ? num2 : 0f);
					Vector2 anchoredPosition = val2.anchoredPosition;
					if (!Mathf.Approximately(anchoredPosition.y, num4))
					{
						val2.anchoredPosition = new Vector2(anchoredPosition.x, num4);
					}
				}
				if (num3 == 1)
				{
					ApplySecondBarLabel(list, val, col);
				}
			}
			if (!extraSlotsOwnsRows)
			{
				__instance.m_gridRoot.SetSizeWithCurrentAnchors((Axis)1, (float)height * elementSpace + num2);
			}
		}

		private static void ApplySecondBarLabel(List<InventoryElement> elements, InventoryElement element, int col)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)element).transform.Find("binding");
			TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TMP_Text>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			if (!DualHotbarPlugin.ShowSecondBarNumbers.Value)
			{
				((Behaviour)val2).enabled = false;
				return;
			}
			((Behaviour)val2).enabled = true;
			string text = (col + 1).ToString();
			if (val2.text != text)
			{
				val2.text = text;
			}
			Color color = Color.white;
			Transform val3 = ((col < elements.Count) ? ((Component)elements[col]).transform.Find("binding") : null);
			TMP_Text val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<TMP_Text>() : null);
			if ((Object)(object)val4 != (Object)null)
			{
				color = ((Graphic)val4).color;
			}
			color.a = 0.5f;
			((Graphic)val2).color = color;
		}
	}
	internal static class Compat
	{
		internal const string ExtraSlotsGuid = "shudnal.ExtraSlots";

		internal const string QuickStackGuid = "goldenrevolver.quick_stack_store";

		internal static bool ExtraSlotsOwnsRows;

		internal static bool ExtraSlotsPresent;

		internal static bool QuickStackPresent;

		private static Func<Player> s_currentPlayer;

		private static Func<int> s_playerRows;

		private static FieldInfo[] s_backgroundFields;

		private static FieldInfo s_fixContainer;

		private static Action<Humanoid> s_bumpHotbarRevision;

		private static bool s_bumpResolved;

		internal static void Detect()
		{
			ExtraSlotsPresent = Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlots");
			QuickStackPresent = Chainloader.PluginInfos.ContainsKey("goldenrevolver.quick_stack_store");
			DualHotbarPlugin.LogInfo(Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlots") ? "Extra Slots detected: the second hotbar row is added through its extra rows" : "Extra Slots not installed");
			if (QuickStackPresent)
			{
				DualHotbarPlugin.LogInfo("Quick Stack Store detected: the second bar is shielded from its actions");
			}
		}

		internal static void PatchExtraSlots(Harmony harmony)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			if (!Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlots"))
			{
				return;
			}
			try
			{
				Type type = AccessTools.TypeByName("ExtraSlots.Slots");
				MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "GetExtraRows", (Type[])null, (Type[])null) : null);
				MethodInfo methodInfo2 = ((type != null) ? AccessTools.PropertyGetter(type, "CurrentPlayer") : null);
				if (methodInfo == null)
				{
					DualHotbarPlugin.LogWarning("Extra Slots is installed but its row count method was not found; the second hotbar will use row 2 of the inventory without adding a row");
					return;
				}
				if (methodInfo2 != null)
				{
					s_currentPlayer = (Func<Player>)Delegate.CreateDelegate(typeof(Func<Player>), methodInfo2);
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Compat), "ExtraRowsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ExtraSlotsOwnsRows = true;
				DualHotbarPlugin.LogInfo("Extra Slots: second hotbar row patched into its extra rows");
				MethodInfo methodInfo3 = AccessTools.PropertyGetter(type, "InventoryHeightPlayer");
				if (methodInfo3 != null)
				{
					s_playerRows = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), methodInfo3);
				}
				Type type2 = AccessTools.TypeByName("ExtraSlots.EquipmentPanel");
				MethodInfo methodInfo4 = ((type2 != null) ? AccessTools.Method(type2, "UpdateEquipmentBackground", (Type[])null, (Type[])null) : null);
				if (methodInfo4 != null)
				{
					s_backgroundFields = new FieldInfo[3]
					{
						AccessTools.Field(type2, "inventoryBackground"),
						AccessTools.Field(type2, "inventoryDarken"),
						AccessTools.Field(type2, "inventorySelectedFrame")
					};
					Type type3 = AccessTools.TypeByName("ExtraSlots.ExtraSlots");
					s_fixContainer = ((type3 != null) ? AccessTools.Field(type3, "fixContainerPosition") : null);
					harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(Compat), "BackgroundPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					DualHotbarPlugin.LogWarning("Extra Slots panel background method not found; the gap between the bars and the inventory will not extend its panel");
				}
			}
			catch (Exception ex)
			{
				DualHotbarPlugin.LogWarning("Could not integrate with Extra Slots (" + ex.Message + "); the second hotbar will use row 2 of the inventory without adding a row");
			}
		}

		internal static void RequestHotbarRefresh(Player player)
		{
			if (!ExtraSlotsPresent || (Object)(object)player == (Object)null)
			{
				return;
			}
			if (!s_bumpResolved)
			{
				s_bumpResolved = true;
				try
				{
					Type type = AccessTools.TypeByName("ExtraSlots.HotBars.QuickBars");
					Type type2 = ((type != null) ? AccessTools.Inner(type, "HotkeyBarRefreshGate") : null);
					MethodInfo methodInfo = ((type2 != null) ? AccessTools.Method(type2, "BumpRevision", (Type[])null, (Type[])null) : null);
					if (methodInfo != null)
					{
						s_bumpHotbarRevision = (Action<Humanoid>)Delegate.CreateDelegate(typeof(Action<Humanoid>), methodInfo);
					}
					else
					{
						DualHotbarPlugin.LogWarning("Extra Slots hotbar refresh method not found; the bar change may show up to a second late");
					}
				}
				catch (Exception ex)
				{
					DualHotbarPlugin.LogWarning("Could not hook the Extra Slots hotbar refresh (" + ex.Message + ")");
				}
			}
			s_bumpHotbarRevision?.Invoke((Humanoid)(object)player);
		}

		internal static int PlayerRows(int fallback)
		{
			if (s_playerRows == null)
			{
				return fallback;
			}
			return s_playerRows();
		}

		private static void BackgroundPostfix()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			float num = DualHotbarPlugin.CurrentGap();
			if (num <= 0f || s_backgroundFields == null)
			{
				return;
			}
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_player == (Object)null)
			{
				return;
			}
			Rect rect = instance.m_player.rect;
			float height = ((Rect)(ref rect)).height;
			if (height < 1f)
			{
				return;
			}
			float num2 = num / height;
			FieldInfo[] array = s_backgroundFields;
			foreach (FieldInfo fieldInfo in array)
			{
				RectTransform val = (RectTransform)((fieldInfo != null) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val != (Object)null)
				{
					val.anchorMin = new Vector2(val.anchorMin.x, val.anchorMin.y - num2);
				}
			}
			bool flag = true;
			if (s_fixContainer != null)
			{
				object? value = s_fixContainer.GetValue(null);
				ConfigEntryBase val2 = (ConfigEntryBase)((value is ConfigEntryBase) ? value : null);
				if (val2 != null && val2.BoxedValue is bool flag2)
				{
					flag = flag2;
				}
			}
			RectTransform container = instance.m_container;
			if (flag && (Object)(object)container != (Object)null)
			{
				rect = container.rect;
				if (((Rect)(ref rect)).height > 1f)
				{
					float x = container.pivot.x;
					float y = container.pivot.y;
					rect = container.rect;
					container.pivot = new Vector2(x, y + num / ((Rect)(ref rect)).height);
				}
			}
		}

		private static void ExtraRowsPostfix(ref int __result)
		{
			if (DualHotbarPlugin.BarActive((s_currentPlayer != null) ? s_currentPlayer() : Player.m_localPlayer))
			{
				__result++;
			}
		}

		internal static void PatchQuickStack(Harmony harmony)
		{
			if (!QuickStackPresent)
			{
				return;
			}
			try
			{
				QuickStackShield.Install(harmony);
			}
			catch (Exception ex)
			{
				DualHotbarPlugin.LogWarning("Could not shield the second bar from Quick Stack Store: " + ex.Message);
			}
		}
	}
	internal static class EmbeddedAssets
	{
		internal const string SwapSound = "swap.wav";

		internal const string ShopIcon = "second_bar.png";

		internal static byte[] Read(string name)
		{
			using Stream stream = typeof(EmbeddedAssets).Assembly.GetManifestResourceStream(name);
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num <= 0)
				{
					break;
				}
			}
			return array;
		}

		internal static AudioClip LoadSwapClip()
		{
			byte[] array = Read("swap.wav");
			if (array == null)
			{
				DualHotbarPlugin.LogWarning("The built-in swap sound is missing from the DLL");
				return null;
			}
			if (!WavDecoder.TryDecode(array, out var result, out var error))
			{
				DualHotbarPlugin.LogWarning("Could not read the built-in swap sound: " + error);
				return null;
			}
			AudioClip obj = AudioClip.Create("AichoSwap", result.Samples.Length / result.Channels, result.Channels, result.Frequency, false);
			obj.SetData(result.Samples, 0);
			return obj;
		}
	}
	[HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")]
	internal static class HotkeyBarIndicatorPatch
	{
		private static void Postfix(HotkeyBar __instance, Player player)
		{
			if (((Object)__instance).name != "HotKeyBar")
			{
				HotbarIndicator.RemoveClone(__instance);
			}
			else
			{
				HotbarTransition.Reapply(__instance);
			}
		}
	}
	internal static class HotbarIndicator
	{
		private struct FontChoice
		{
			public TMP_FontAsset Font;

			public bool IsBoldAsset;
		}

		private sealed class KeyCap
		{
			public Image Box;

			public TextMeshProUGUI Text;
		}

		private const float RoundBorder = 64f;

		private static readonly Dictionary<string, string> OsFonts = new Dictionary<string, string>
		{
			{ "Arial", "Arial" },
			{ "SegoeUI", "Segoe UI" },
			{ "Verdana", "Verdana" },
			{ "Tahoma", "Tahoma" },
			{ "Calibri", "Calibri" }
		};

		private static GameObject s_root;

		private static RectTransform s_rootRect;

		private static RectTransform s_keysRect;

		private static readonly Image[] s_boxes = (Image[])(object)new Image[2];

		private static readonly Image[] s_dots = (Image[])(object)new Image[2];

		private static readonly List<KeyCap> s_caps = new List<KeyCap>();

		private static readonly Dictionary<string, FontChoice> s_fonts = new Dictionary<string, FontChoice>();

		private static Sprite s_round;

		private static Sprite s_frameSprite;

		private static TMP_FontAsset s_fallbackFont;

		private static float s_canvasPpu = 100f;

		private static bool s_failed;

		private static bool s_dirty = true;

		private static int s_lastCount = -1;

		private static int s_lastActive = -1;

		private static float s_lastY;

		private static KeyboardShortcut s_lastShortcut;

		private static bool s_hasShortcut;

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

		private static FieldInfo s_elementGoField;

		internal const string MainBarName = "HotKeyBar";

		private const string RootName = "AichoDualBarIndicator";

		private static HotkeyBar s_mainBar;

		private static readonly HashSet<int> s_cleanedBars = new HashSet<int>();

		private static readonly List<RectTransform> s_rectBuffer = new List<RectTransform>();

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

		internal static void UpdateFrame()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)Hud.instance == (Object)null)
			{
				return;
			}
			if ((Object)(object)s_mainBar == (Object)null)
			{
				Transform val = (((Object)(object)Hud.instance.m_rootObject != (Object)null) ? Hud.instance.m_rootObject.transform.Find("HotKeyBar") : null);
				s_mainBar = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<HotkeyBar>() : null);
				if ((Object)(object)s_mainBar == (Object)null)
				{
					return;
				}
			}
			HotbarTransition.Tick(s_mainBar, localPlayer);
			Refresh(s_mainBar, localPlayer);
		}

		internal static void RemoveClone(HotkeyBar bar)
		{
			if (s_cleanedBars.Add(((Object)bar).GetInstanceID()))
			{
				Transform val = ((Component)bar).transform.Find("AichoDualBarIndicator");
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		internal unsafe static void Refresh(HotkeyBar bar, Player player)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			if (s_failed)
			{
				return;
			}
			try
			{
				if ((!IndicatorConfig.ShowSquares.Value && !IndicatorConfig.ShowKey.Value) || !((Object)(object)player != (Object)null) || ((Character)player).IsDead() || !DualHotbarPlugin.BarActive(player))
				{
					if ((Object)(object)s_root != (Object)null && s_root.activeSelf)
					{
						s_root.SetActive(false);
					}
					return;
				}
				if ((Object)(object)s_root == (Object)null || (Object)(object)s_root.transform.parent != (Object)(object)((Component)bar).transform)
				{
					Build(bar);
					s_dirty = true;
				}
				if (!s_root.activeSelf)
				{
					s_root.SetActive(true);
				}
				bool flag = IndicatorConfig.ShowKey.Value && !ZInput.IsGamepadActive();
				if (((Component)s_keysRect).gameObject.activeSelf != flag)
				{
					((Component)s_keysRect).gameObject.SetActive(flag);
				}
				KeyboardShortcut value = DualHotbarPlugin.SwapKey.Value;
				bool flag2 = false;
				if (s_dirty || !s_hasShortcut || !((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).Equals((object?)s_lastShortcut))
				{
					ApplyStyle(value);
					s_lastShortcut = value;
					s_hasShortcut = true;
					s_dirty = false;
					s_lastActive = -1;
					flag2 = true;
				}
				IList list = ElementsField.GetValue(bar) as IList;
				int num = list?.Count ?? 0;
				if (flag2 || num != s_lastCount)
				{
					Layout(list, num);
					s_lastCount = num;
				}
				int num2 = HotbarTransition.DisplayedRow(DualHotbarPlugin.ActiveRow(player));
				if (num2 != s_lastActive)
				{
					((Behaviour)s_dots[0]).enabled = num2 == 0;
					((Behaviour)s_dots[1]).enabled = num2 == 1;
					s_lastActive = num2;
				}
			}
			catch (Exception ex)
			{
				s_failed = true;
				DualHotbarPlugin.LogWarning("Hotbar indicator disabled after an error: " + ex);
			}
		}

		private static void Build(HotkeyBar bar)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_root != (Object)null)
			{
				Object.Destroy((Object)(object)s_root);
			}
			s_caps.Clear();
			s_lastCount = -1;
			s_lastActive = -1;
			s_hasShortcut = false;
			Canvas val = ((Component)bar).GetComponentInParent<Canvas>();
			if ((Object)(object)val != (Object)null)
			{
				val = val.rootCanvas;
			}
			s_canvasPpu = (((Object)(object)val != (Object)null) ? val.referencePixelsPerUnit : 100f);
			if ((Object)(object)s_round == (Object)null)
			{
				s_round = MakeRoundedSprite(256, 64);
			}
			TMP_Text componentInChildren = ((Component)bar).GetComponentInChildren<TMP_Text>(true);
			s_fallbackFont = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.font : (((Object)(object)Hud.instance != (Object)null) ? ((TMP_Text)Hud.instance.m_hoverName).font : null));
			s_root = new GameObject("AichoDualBarIndicator", new Type[1] { typeof(RectTransform) });
			s_rootRect = (RectTransform)s_root.transform;
			((Transform)s_rootRect).SetParent(((Component)bar).transform, false);
			s_rootRect.pivot = new Vector2(0f, 0.5f);
			Vector2 val3 = default(Vector2);
			Vector2 val4 = default(Vector2);
			for (int i = 0; i < 2; i++)
			{
				s_boxes[i] = MakeImage("BarSquare" + (i + 1), s_rootRect);
				Image val2 = MakeImage("ActiveSquare", ((Graphic)s_boxes[i]).rectTransform);
				RectTransform rectTransform = ((Graphic)val2).rectTransform;
				RectTransform rectTransform2 = ((Graphic)val2).rectTransform;
				RectTransform rectTransform3 = ((Graphic)val2).rectTransform;
				((Vector2)(ref val3))..ctor(0.5f, 0.5f);
				rectTransform3.pivot = val3;
				val4 = (rectTransform.anchorMin = (rectTransform2.anchorMax = val3));
				((Behaviour)val2).enabled = false;
				s_dots[i] = val2;
			}
			s_keysRect = (RectTransform)new GameObject("Keys", new Type[1] { typeof(RectTransform) }).transform;
			((Transform)s_keysRect).SetParent((Transform)(object)s_rootRect, false);
			RectTransform obj = s_keysRect;
			RectTransform obj2 = s_keysRect;
			((Vector2)(ref val4))..ctor(0f, 0.5f);
			obj2.anchorMax = val4;
			obj.anchorMin = val4;
			s_keysRect.pivot = new Vector2(0f, 0.5f);
			s_keysRect.sizeDelta = Vector2.zero;
			DualHotbarPlugin.LogInfo($"Hotbar indicator built (canvas reference PPU {s_canvasPpu})");
		}

		private static Image MakeImage(string name, RectTransform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)parent, false);
			Image obj = val.AddComponent<Image>();
			obj.sprite = s_round;
			obj.type = (Type)1;
			((Graphic)obj).raycastTarget = false;
			RectTransform rectTransform = ((Graphic)obj).rectTransform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f, 0.5f);
			rectTransform.pivot = val2;
			Vector2 anchorMin = (rectTransform.anchorMax = val2);
			rectTransform.anchorMin = anchorMin;
			return obj;
		}

		private static KeyCap CapAt(int index)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			while (s_caps.Count <= index)
			{
				Image val = MakeImage("Key" + s_caps.Count, s_keysRect);
				GameObject val2 = new GameObject("KeyText", new Type[1] { typeof(RectTransform) });
				val2.transform.SetParent((Transform)(object)((Graphic)val).rectTransform, false);
				val2.SetActive(false);
				TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>();
				if ((Object)(object)s_fallbackFont != (Object)null)
				{
					((TMP_Text)val3).font = s_fallbackFont;
				}
				((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
				((TMP_Text)val3).enableWordWrapping = false;
				((TMP_Text)val3).overflowMode = (TextOverflowModes)0;
				((TMP_Text)val3).richText = false;
				((Graphic)val3).raycastTarget = false;
				RectTransform rectTransform = ((TMP_Text)val3).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				val2.SetActive(true);
				s_caps.Add(new KeyCap
				{
					Box = val,
					Text = val3
				});
			}
			return s_caps[index];
		}

		private static void ApplyStyle(KeyboardShortcut shortcut)
		{
			//IL_0033: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			float value = IndicatorConfig.SquareSize.Value;
			float value2 = IndicatorConfig.SquareGap.Value;
			float num = (value + value2) * 0.5f;
			s_rootRect.sizeDelta = new Vector2(0f, value * 2f + value2);
			Sprite val = MakeFrameSprite(value, IndicatorConfig.SquareFrameThickness.Value, IndicatorConfig.SquareRoundness.Value, IndicatorConfig.SquareColor.Value, IndicatorConfig.SquareFillColor.Value);
			for (int i = 0; i < 2; i++)
			{
				Image obj = s_boxes[i];
				((Component)obj).gameObject.SetActive(IndicatorConfig.ShowSquares.Value);
				((Graphic)obj).rectTransform.sizeDelta = new Vector2(value, value);
				((Graphic)obj).rectTransform.anchoredPosition = new Vector2(IndicatorConfig.SquareOffsetX.Value, ((i == 0) ? num : (0f - num)) + IndicatorConfig.SquareOffsetY.Value);
				obj.type = (Type)0;
				obj.sprite = val;
				((Graphic)obj).color = Color.white;
				StyleOutline(obj, IndicatorConfig.SquareOutlineOpacity.Value, IndicatorConfig.SquareOutlineThickness.Value);
				float value3 = IndicatorConfig.MarkerSize.Value;
				Image obj2 = s_dots[i];
				((Graphic)obj2).rectTransform.sizeDelta = new Vector2(value3, value3);
				((Graphic)obj2).rectTransform.anchoredPosition = new Vector2(IndicatorConfig.MarkerOffsetX.Value, IndicatorConfig.MarkerOffsetY.Value);
				((Graphic)obj2).color = IndicatorConfig.MarkerColor.Value;
				SetCorner(obj2, value3, IndicatorConfig.MarkerRoundness.Value);
			}
			if ((Object)(object)s_frameSprite != (Object)null && (Object)(object)s_frameSprite != (Object)(object)val)
			{
				Object.Destroy((Object)(object)s_frameSprite.texture);
				Object.Destroy((Object)(object)s_frameSprite);
			}
			s_frameSprite = val;
			float num2 = (IndicatorConfig.ShowSquares.Value ? (value + IndicatorConfig.GapSquaresToKey.Value) : 0f);
			s_keysRect.anchoredPosition = new Vector2(num2 + IndicatorConfig.KeyOffsetX.Value, IndicatorConfig.KeyOffsetY.Value);
			RebuildKeys(shortcut);
		}

		private static Sprite MakeFrameSprite(float sizeUnits, float thicknessUnits, float roundness, Color frame, Color fill)
		{
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			float num = 64f;
			float num2 = Mathf.Clamp01(roundness) * 0.5f * 128f;
			float num3 = Mathf.Clamp(thicknessUnits / Mathf.Max(0.01f, sizeUnits), 0f, 0.5f) * 128f;
			Color32[] array = (Color32[])(object)new Color32[16384];
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num4 = (float)j + 0.5f - num;
					float num5 = (float)i + 0.5f - num;
					float num6 = Mathf.Abs(num4) - (num - num2);
					float num7 = Mathf.Abs(num5) - (num - num2);
					float num8 = Mathf.Sqrt(Mathf.Max(num6, 0f) * Mathf.Max(num6, 0f) + Mathf.Max(num7, 0f) * Mathf.Max(num7, 0f)) + Mathf.Min(Mathf.Max(num6, num7), 0f) - num2;
					float num9 = Mathf.Clamp01(0.5f - num8);
					float num10 = Mathf.Clamp01(0.5f - (num8 + num3));
					float num11 = Mathf.Clamp01(num9 - num10);
					float num12 = frame.a * num11;
					float num13 = fill.a * num10;
					float num14 = num12 + num13;
					if (num14 <= 0.0001f)
					{
						array[i * 128 + j] = new Color32((byte)(frame.r * 255f), (byte)(frame.g * 255f), (byte)(frame.b * 255f), (byte)0);
						continue;
					}
					float num15 = (frame.r * num12 + fill.r * num13) / num14;
					float num16 = (frame.g * num12 + fill.g * num13) / num14;
					float num17 = (frame.b * num12 + fill.b * num13) / num14;
					array[i * 128 + j] = new Color32((byte)(num15 * 255f), (byte)(num16 * 255f), (byte)(num17 * 255f), (byte)(num14 * 255f));
				}
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, true)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)2
			};
			val.SetPixels32(array);
			val.Apply(true);
			return Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
		}

		private static void RebuildKeys(KeyboardShortcut shortcut)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = Tokens(shortcut);
			FontChoice font = GetFont();
			FontStyles fontStyle = (FontStyles)((IndicatorConfig.TextBold.Value && !font.IsBoldAsset) ? 1 : 0);
			float value = IndicatorConfig.KeyHeight.Value;
			float num = 0f;
			for (int i = 0; i < s_caps.Count || i < list.Count; i++)
			{
				if (i >= list.Count)
				{
					((Component)s_caps[i].Box).gameObject.SetActive(false);
					continue;
				}
				KeyCap keyCap = CapAt(i);
				((Component)keyCap.Box).gameObject.SetActive(true);
				TextMeshProUGUI text = keyCap.Text;
				if ((Object)(object)font.Font != (Object)null)
				{
					((TMP_Text)text).font = font.Font;
				}
				((TMP_Text)text).fontStyle = fontStyle;
				((TMP_Text)text).fontSize = IndicatorConfig.TextSize.Value;
				((Graphic)text).color = IndicatorConfig.TextColor.Value;
				((TMP_Text)text).text = list[i];
				((TMP_Text)text).rectTransform.offsetMin = new Vector2(IndicatorConfig.TextOffsetX.Value, IndicatorConfig.TextOffsetY.Value);
				((TMP_Text)text).rectTransform.offsetMax = new Vector2(IndicatorConfig.TextOffsetX.Value, IndicatorConfig.TextOffsetY.Value);
				float num2 = Mathf.Max(IndicatorConfig.KeyMinWidth.Value, ((TMP_Text)text).GetPreferredValues(list[i]).x + IndicatorConfig.KeyWidthPadding.Value);
				((Graphic)keyCap.Box).rectTransform.sizeDelta = new Vector2(num2, value);
				((Graphic)keyCap.Box).rectTransform.anchoredPosition = new Vector2(num, 0f);
				((Graphic)keyCap.Box).color = IndicatorConfig.KeyColor.Value;
				SetCorner(keyCap.Box, value, IndicatorConfig.KeyRoundness.Value);
				StyleOutline(keyCap.Box, IndicatorConfig.KeyOutlineOpacity.Value, IndicatorConfig.KeyOutlineThickness.Value);
				num += num2 + IndicatorConfig.KeyGap.Value;
			}
		}

		private static void Layout(IList elements, int count)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = s_lastY;
			RectTransform val = LastElementRect(elements, count);
			if ((Object)(object)val != (Object)null)
			{
				Vector3 localPosition = ((Transform)val).localPosition;
				Vector3 localScale = ((Transform)val).localScale;
				float x = localPosition.x;
				Rect rect = val.rect;
				num = x + ((Rect)(ref rect)).xMax * Mathf.Abs(localScale.x);
				float num3 = localPosition.y - HotbarTransition.OffsetY;
				rect = val.rect;
				num2 = (s_lastY = num3 + ((Rect)(ref rect)).center.y * Mathf.Abs(localScale.y));
			}
			float num4 = Mathf.Max(0.1f, IndicatorConfig.Scale.Value);
			((Transform)s_rootRect).localScale = new Vector3(num4, num4, 1f);
			((Transform)s_rootRect).localPosition = new Vector3(num + IndicatorConfig.DistanceFromBar.Value * num4 + IndicatorConfig.OffsetX.Value, num2 + IndicatorConfig.OffsetY.Value, 0f);
		}

		internal static List<RectTransform> ElementRects(HotkeyBar bar)
		{
			s_rectBuffer.Clear();
			if (!(ElementsField.GetValue(bar) is IList list))
			{
				return s_rectBuffer;
			}
			for (int i = 0; i < list.Count; i++)
			{
				object obj = list[i];
				RectTransform item = null;
				if (obj != null)
				{
					if (s_elementGoField == null)
					{
						s_elementGoField = AccessTools.Field(obj.GetType(), "m_go");
					}
					GameObject val = (GameObject)((s_elementGoField != null) ? /*isinst with value type is only supported in some contexts*/: null);
					item = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
				}
				s_rectBuffer.Add(item);
			}
			return s_rectBuffer;
		}

		private static RectTransform LastElementRect(IList elements, int count)
		{
			if (elements == null || count <= 0)
			{
				return null;
			}
			object obj = elements[count - 1];
			if (obj == null)
			{
				return null;
			}
			if (s_elementGoField == null)
			{
				s_elementGoField = AccessTools.Field(obj.GetType(), "m_go");
			}
			GameObject val = (GameObject)((s_elementGoField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			Transform transform = val.transform;
			return (RectTransform)(object)((transform is RectTransform) ? transform : null);
		}

		private static void StyleOutline(Image image, float opacity, float thickness)
		{
			//IL_004d: 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)
			Outline val = ((Component)image).GetComponent<Outline>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)image).gameObject.AddComponent<Outline>();
				((Shadow)val).useGraphicAlpha = false;
			}
			((Behaviour)val).enabled = opacity > 0.001f && thickness > 0.001f;
			((Shadow)val).effectColor = new Color(0f, 0f, 0f, opacity);
			((Shadow)val).effectDistance = new Vector2(thickness, 0f - thickness);
		}

		private static void SetCorner(Image image, float height, float roundness)
		{
			float num = height * 0.5f * Mathf.Clamp01(roundness);
			float num2 = 100f / Mathf.Max(0.01f, s_canvasPpu);
			image.pixelsPerUnitMultiplier = 64f / (Mathf.Max(0.5f, num) * num2);
		}

		private static FontChoice GetFont()
		{
			string value = IndicatorConfig.TextFont.Value;
			bool value2 = IndicatorConfig.TextBold.Value;
			string key = value + (value2 ? "|bold" : "");
			if (!s_fonts.TryGetValue(key, out var value3))
			{
				value3 = CreateFont(value, value2);
				s_fonts[key] = value3;
			}
			return value3;
		}

		private static FontChoice CreateFont(string choice, bool bold)
		{
			if (OsFonts.TryGetValue(choice, out var value))
			{
				try
				{
					TMP_FontAsset val = null;
					bool flag = false;
					if (bold)
					{
						val = TMP_FontAsset.CreateFontAsset(value, "Bold", 90);
						flag = (Object)(object)val != (Object)null;
					}
					if ((Object)(object)val == (Object)null)
					{
						val = TMP_FontAsset.CreateFontAsset(value, "Regular", 90);
					}
					if ((Object)(object)val != (Object)null)
					{
						((Object)val).name = "AichoOS-" + choice + (flag ? "-Bold" : "");
						return new FontChoice
						{
							Font = val,
							IsBoldAsset = flag
						};
					}
				}
				catch (Exception ex)
				{
					DualHotbarPlugin.LogWarning("Could not create the font '" + value + "' for the hotbar indicator: " + ex.Message);
				}
			}
			return new FontChoice
			{
				Font = s_fallbackFont,
				IsBoldAsset = false
			};
		}

		private static List<string> Tokens(KeyboardShortcut shortcut)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				list.Add(KeyName(modifier));
			}
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0)
			{
				list.Add(KeyName(((KeyboardShortcut)(ref shortcut)).MainKey));
			}
			return list;
		}

		private unsafe static string KeyName(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected I4, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected I4, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected I4, but got Unknown
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected I4, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected I4, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected I4, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			if ((int)key <= 62)
			{
				if ((int)key <= 32)
				{
					if ((int)key == 13)
					{
						return "Enter";
					}
					if ((int)key == 32)
					{
						return DualHotbarPlugin.T("Espacio", "Space");
					}
				}
				else
				{
					switch (key - 39)
					{
					default:
						switch (key - 59)
						{
						case 1:
							return "<";
						case 3:
							return ">";
						case 2:
							return "=";
						case 0:
							return ";";
						}
						break;
					case 5:
						return ",";
					case 7:
						return ".";
					case 6:
						return "-";
					case 8:
						return "/";
					case 0:
						return "'";
					case 1:
					case 2:
					case 3:
					case 4:
						break;
					}
				}
			}
			else if ((int)key <= 281)
			{
				switch (key - 91)
				{
				default:
					switch (key - 273)
					{
					case 7:
						return DualHotbarPlugin.T("RePag", "PgUp");
					case 8:
						return DualHotbarPlugin.T("AvPag", "PgDn");
					case 5:
						return DualHotbarPlugin.T("Inicio", "Home");
					case 6:
						return DualHotbarPlugin.T("Fin", "End");
					case 0:
						return "↑";
					case 1:
						return "↓";
					case 3:
						return "←";
					case 2:
						return "→";
					}
					break;
				case 1:
					return "\\";
				case 5:
					return "`";
				case 0:
					return "[";
				case 2:
					return "]";
				case 3:
				case 4:
					break;
				}
			}
			else
			{
				switch (key - 301)
				{
				default:
					switch (key - 323)
					{
					case 0:
						return "M1";
					case 1:
						return "M2";
					case 2:
						return "M3";
					case 3:
						return "M4";
					case 4:
						return "M5";
					}
					break;
				case 2:
				case 3:
					return "Shift";
				case 4:
				case 5:
					return "Ctrl";
				case 6:
				case 7:
					return "Alt";
				case 0:
					return DualHotbarPlugin.T("Bloq Mayús", "Caps");
				case 1:
					break;
				}
			}
			string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
			if (text.StartsWith("Alpha"))
			{
				return text.Substring(5);
			}
			if (text.StartsWith("Keypad"))
			{
				return "Num" + text.Substring(6);
			}
			return text;
		}

		private static Sprite MakeRoundedSprite(int size, int radius)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, true)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)2
			};
			Color32[] array = (Color32[])(object)new Color32[size * size];
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num = (float)j + 0.5f;
					float num2 = (float)i + 0.5f;
					float num3 = Mathf.Clamp(num, (float)radius, (float)(size - radius));
					float num4 = Mathf.Clamp(num2, (float)radius, (float)(size - radius));
					float num5 = Mathf.Sqrt((num - num3) * (num - num3) + (num2 - num4) * (num2 - num4));
					byte b = (byte)Mathf.RoundToInt(Mathf.Clamp01((float)radius - num5 + 0.5f) * 255f);
					array[i * size + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b);
				}
			}
			val.SetPixels32(array);
			val.Apply(true);
			return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)radius, (float)radius, (float)radius, (float)radius));
		}
	}
	internal static class HotbarRows
	{
		internal static bool Applies(Inventory inventory, out Player player)
		{
			player = Player.m_localPlayer;
			if ((Object)(object)player != (Object)null && inventory == ((Humanoid)player).GetInventory())
			{
				return DualHotbarPlugin.BarActive(player);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "GetBoundItems")]
	internal static class GetBoundItemsPatch
	{
		private static bool Prefix(Inventory __instance, List<ItemData> bound)
		{
			if (!HotbarRows.Applies(__instance, out var player))
			{
				return true;
			}
			int num = HotbarTransition.DisplayedRow(DualHotbarPlugin.ActiveRow(player));
			bound.Clear();
			foreach (ItemData allItem in __instance.GetAllItems())
			{
				if (allItem.m_gridPos.y == num)
				{
					bound.Add(allItem);
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "GetHotbar")]
	internal static class GetHotbarPatch
	{
		private static bool Prefix(Inventory __instance, bool includeEmpty, ref List<ItemData> __result)
		{
			if (!HotbarRows.Applies(__instance, out var player))
			{
				return true;
			}
			int row = DualHotbarPlugin.ActiveRow(player);
			List<ItemData> source = (from item in __instance.GetAllItems()
				where item.m_gridPos.y == row
				select item).ToList();
			if (!includeEmpty)
			{
				__result = source.OrderBy((ItemData item) => item.m_gridPos.x).ToList();
				return false;
			}
			List<ItemData> list = new List<ItemData>();
			for (int num = 0; num < 8; num++)
			{
				int column = num;
				list.Add(((IEnumerable<ItemData>)source).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => item.m_gridPos.x == column)));
			}
			__result = list;
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "UseHotbarItem")]
	internal static class UseHotbarItemPatch
	{
		private static bool Prefix(Player __instance, int index)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !DualHotbarPlugin.BarActive(__instance))
			{
				return true;
			}
			int num = DualHotbarPlugin.ActiveRow(__instance);
			if (num == 0)
			{
				return true;
			}
			ItemData itemAt = ((Humanoid)__instance).GetInventory().GetItemAt(index - 1, num);
			if (itemAt != null)
			{
				((Humanoid)__instance).UseItem((Inventory)null, itemAt, false);
			}
			return false;
		}
	}
	internal static class TransitionConfig
	{
		internal static readonly Fixed<string> Style = new Fixed<string>("Slide");

		internal static readonly Fixed<float> Duration = new Fixed<float>(0.3f);

		internal static readonly Fixed<float> SlideDistance = new Fixed<float>(18f);
	}
	internal static class HotbarTransition
	{
		private enum Phase
		{
			Idle,
			Out,
			In
		}

		private static Phase s_phase = Phase.Idle;

		private static int s_displayedRow;

		private static float s_t;

		private static float s_alpha = 1f;

		private static float s_offset;

		private static float s_fromAlpha = 1f;

		private static float s_fromOffset;

		private static float s_direction;

		private static float s_lastTick;

		internal static float OffsetY => s_offset;

		private static bool Enabled
		{
			get
			{
				if (TransitionConfig.Style.Value != "None")
				{
					return TransitionConfig.Duration.Value > 0.02f;
				}
				return false;
			}
		}

		internal static int DisplayedRow(int actualRow)
		{
			if (s_phase != Phase.Out)
			{
				return actualRow;
			}
			return s_displayedRow;
		}

		internal static void Begin(int leavingRow, int arrivingRow)
		{
			Compat.RequestHotbarRefresh(Player.m_localPlayer);
			if (!Enabled)
			{
				s_phase = Phase.Idle;
				s_alpha = 1f;
				s_offset = 0f;
				return;
			}
			if (s_phase != Phase.Out)
			{
				s_displayedRow = leavingRow;
			}
			s_direction = ((arrivingRow == 0) ? (-1f) : 1f);
			s_fromAlpha = s_alpha;
			s_fromOffset = s_offset;
			s_phase = Phase.Out;
			s_t = 0f;
			s_lastTick = Time.unscaledTime;
		}

		internal static void Reapply(HotkeyBar bar)
		{
			if (s_phase != Phase.Idle)
			{
				Apply(bar);
			}
		}

		internal static void Tick(HotkeyBar bar, Player player)
		{
			if (s_phase == Phase.Idle)
			{
				return;
			}
			Compat.RequestHotbarRefresh(player);
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime - s_lastTick > 1f)
			{
				Reset(bar);
				return;
			}
			s_lastTick = unscaledTime;
			float num = Mathf.Max(0.01f, TransitionConfig.Duration.Value * 0.5f);
			bool flag = TransitionConfig.Style.Value == "Slide";
			float value = TransitionConfig.SlideDistance.Value;
			s_t += Mathf.Min(0.1f, Time.unscaledDeltaTime) / num;
			float num2 = Ease(Mathf.Clamp01(s_t));
			if (s_phase == Phase.Out)
			{
				s_alpha = Mathf.Lerp(s_fromAlpha, 0f, num2);
				s_offset = (flag ? Mathf.Lerp(s_fromOffset, s_direction * value, num2) : 0f);
				if (s_t >= 1f)
				{
					s_phase = Phase.In;
					s_t = 0f;
				}
			}
			else
			{
				s_alpha = num2;
				s_offset = (flag ? ((0f - s_direction) * value * (1f - num2)) : 0f);
				if (s_t >= 1f)
				{
					s_phase = Phase.Idle;
					s_alpha = 1f;
					s_offset = 0f;
				}
			}
			Apply(bar);
		}

		private static float Ease(float k)
		{
			return k * k * (3f - 2f * k);
		}

		private static void Reset(HotkeyBar bar)
		{
			s_phase = Phase.Idle;
			s_alpha = 1f;
			s_offset = 0f;
			Apply(bar);
		}

		private static void Apply(HotkeyBar bar)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)bar == (Object)null)
			{
				return;
			}
			List<RectTransform> list = HotbarIndicator.ElementRects(bar);
			for (int i = 0; i < list.Count; i++)
			{
				RectTransform val = list[i];
				if (!((Object)(object)val == (Object)null))
				{
					CanvasGroup val2 = ((Component)val).GetComponent<CanvasGroup>();
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = ((Component)val).gameObject.AddComponent<CanvasGroup>();
					}
					val2.alpha = s_alpha;
					((Transform)val).localPosition = new Vector3((float)i * bar.m_elementSpace, s_offset, ((Transform)val).localPosition.z);
				}
			}
		}
	}
	internal sealed class Fixed<T>
	{
		internal T Value { get; }

		internal Fixed(T value)
		{
			Value = value;
		}
	}
	internal static class IndicatorConfig
	{
		internal static ConfigEntry<bool> ShowSquares;

		internal static ConfigEntry<bool> ShowKey;

		internal static readonly Fixed<float> Scale = new Fixed<float>(0.587f);

		internal static readonly Fixed<float> OffsetX = new Fixed<float>(0f);

		internal static readonly Fixed<float> OffsetY = new Fixed<float>(0f);

		internal static readonly Fixed<float> DistanceFromBar = new Fixed<float>(16f);

		internal static readonly Fixed<float> GapSquaresToKey = new Fixed<float>(13.979f);

		internal static readonly Fixed<float> SquareSize = new Fixed<float>(28.129f);

		internal static readonly Fixed<float> SquareGap = new Fixed<float>(9.959f);

		internal static readonly Fixed<float> SquareRoundness = new Fixed<float>(0.443f);

		internal static readonly Fixed<Color> SquareColor = new Fixed<Color>(new Color(1f, 1f, 1f, 1f));

		internal static readonly Fixed<float> SquareFrameThickness = new Fixed<float>(2f);

		internal static readonly Fixed<Color> SquareFillColor = new Fixed<Color>(new Color(0f, 0f, 0f, 0f));

		internal static readonly Fixed<float> SquareOutlineOpacity = new Fixed<float>(0f);

		internal static readonly Fixed<float> SquareOutlineThickness = new Fixed<float>(0.27f);

		internal static readonly Fixed<float> SquareOffsetX = new Fixed<float>(0f);

		internal static readonly Fixed<float> SquareOffsetY = new Fixed<float>(0f);

		internal static readonly Fixed<float> MarkerSize = new Fixed<float>(14.366f);

		internal static readonly Fixed<float> MarkerRoundness = new Fixed<float>(0.191f);

		internal static readonly Fixed<Color> MarkerColor = new Fixed<Color>(new Color(1f, 1f, 0f, 1f));

		internal static readonly Fixed<float> MarkerOffsetX = new Fixed<float>(0.3f);

		internal static readonly Fixed<float> MarkerOffsetY = new Fixed<float>(0.3f);

		internal static readonly Fixed<float> KeyHeight = new Fixed<float>(31.8f);

		internal static readonly Fixed<float> KeyMinWidth = new Fixed<float>(38.4f);

		internal static readonly Fixed<float> KeyWidthPadding = new Fixed<float>(8.98f);

		internal static readonly Fixed<float> KeyGap = new Fixed<float>(6f);

		internal static readonly Fixed<float> KeyRoundness = new Fixed<float>(0.536f);

		internal static readonly Fixed<Color> KeyColor = new Fixed<Color>(new Color(1f, 1f, 1f, 1f));

		internal static readonly Fixed<float> KeyOutlineOpacity = new Fixed<float>(0.6f);

		internal static readonly Fixed<float> KeyOutlineThickness = new Fixed<float>(0f);

		internal static readonly Fixed<float> KeyOffsetX = new Fixed<float>(0f);

		internal static readonly Fixed<float> KeyOffsetY = new Fixed<float>(0f);

		internal static readonly Fixed<float> TextSize = new Fixed<float>(34f);

		internal static readonly Fixed<Color> TextColor = new Fixed<Color>(new Color(2f / 51f, 2f / 51f, 2f / 51f, 1f));

		internal static readonly Fixed<string> TextFont = new Fixed<string>("Arial");

		internal static readonly Fixed<bool> TextBold = new Fixed<bool>(value: true);

		internal static readonly Fixed<float> TextOffsetX = new Fixed<float>(0f);

		internal static readonly Fixed<float> TextOffsetY = new Fixed<float>(0f);

		internal static void Bind(ConfigFile file)
		{
			ShowSquares = file.Bind<bool>("1 - General", "ShowSquares", true, "Shows the two squares at the end of the hotbar (the one of the active bar has a small square inside).");
			ShowKey = file.Bind<bool>("1 - General", "ShowKeyButton", true, "Shows the button with the swap key at the end of the hotbar (always hidden while using a gamepad).");
		}
	}
	internal static class QuickStackShield
	{
		private const string Namespace = "QuickStackStore.";

		private static readonly List<KeyValuePair<int, ItemData>> s_hidden = new List<KeyValuePair<int, ItemData>>();

		private static bool s_hiding;

		private static readonly MethodInfo InventoryChanged = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null);

		internal static void Install(Harmony harmony)
		{
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("QuickStackStore.UserConfig");
			Assembly assembly = ((type != null) ? type.Assembly : null);
			if (assembly == null)
			{
				DualHotbarPlugin.LogWarning("Quick Stack Store assembly not found; the second bar is not shielded from it");
				return;
			}
			int num = 0;
			num += Wrap(harmony, assembly, "QuickStackModule", "DoQuickStack", "PrefixLocalPlayer");
			num += Wrap(harmony, assembly, "RestockModule", "DoRestock", "PrefixLocalPlayer");
			num += Wrap(harmony, assembly, "StoreTakeAllModule", "MoveAllItemsInOrder", "PrefixStore");
			num += Wrap(harmony, assembly, "SortModule", "SortInternal", "PrefixInventory");
			MethodInfo method = null;
			Type[] types = assembly.GetTypes();
			foreach (Type type2 in types)
			{
				MethodInfo methodInfo = ((type2.Namespace == "QuickStackStore") ? type2.GetMethod("QuickTrash", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
				if (methodInfo != null)
				{
					method = methodInfo;
					break;
				}
			}
			num += WrapMethod(harmony, method, "PrefixLocalPlayer");
			Type type3 = assembly.GetType("QuickStackStore.SortModule");
			MethodInfo methodInfo2 = ((type3 != null) ? AccessTools.Method(type3, "GetAllowedSlots", (Type[])null, (Type[])null) : null);
			if (methodInfo2 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(QuickStackShield), "AllowedSlotsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			else
			{
				DualHotbarPlugin.LogWarning("Quick Stack Store sort slot method not found; Sort may place items in the second bar");
			}
			DualHotbarPlugin.LogInfo($"Quick Stack Store: {num} actions shielded from touching the second bar");
		}

		private static int Wrap(Harmony harmony, Assembly assembly, string typeName, string methodName, string prefixName)
		{
			Type type = assembly.GetType("QuickStackStore." + typeName);
			MethodInfo method = ((type != null) ? AccessTools.Method(type, methodName, (Type[])null, (Type[])null) : null);
			return WrapMethod(harmony, method, prefixName);
		}

		private static int WrapMethod(Harmony harmony, MethodInfo method, string prefixName)
		{
			//IL_002e: 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_0050: Expected O, but got Unknown
			//IL_0050: Expected O, but got Unknown
			if (method == null)
			{
				DualHotbarPlugin.LogWarning("Quick Stack Store method for '" + prefixName + "' not found; one action is not shielded");
				return 0;
			}
			harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(QuickStackShield), prefixName, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(QuickStackShield), "RestoreFinalizer", (Type[])null), (HarmonyMethod)null);
			return 1;
		}

		private static void PrefixLocalPlayer(out bool __state)
		{
			__state = Hide();
		}

		private static void PrefixStore(Inventory fromInventory, bool takeAllOverride, out bool __state)
		{
			__state = !takeAllOverride && IsPlayerInventory(fromInventory) && Hide();
		}

		private static void PrefixInventory(Inventory inventory, out bool __state)
		{
			__state = IsPlayerInventory(inventory) && Hide();
		}

		private static Exception RestoreFinalizer(bool __state, Exception __exception)
		{
			if (__state)
			{
				Restore();
			}
			return __exception;
		}

		private static void AllowedSlotsPostfix(Inventory inventory, ref List<Vector2i> __result)
		{
			if (__result != null && IsPlayerInventory(inventory) && DualHotbarPlugin.ProtectFromQuickStack.Value && DualHotbarPlugin.BarActive(Player.m_localPlayer))
			{
				__result.RemoveAll((Vector2i slot) => slot.y == 1);
			}
		}

		private static bool IsPlayerInventory(Inventory inventory)
		{
			Player localPlayer = Player.m_localPlayer;
			if (inventory != null && (Object)(object)localPlayer != (Object)null)
			{
				return inventory == ((Humanoid)localPlayer).GetInventory();
			}
			return false;
		}

		private static bool Hide()
		{
			if (s_hiding || !DualHotbarPlugin.ProtectFromQuickStack.Value)
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !DualHotbarPlugin.BarActive(localPlayer))
			{
				return false;
			}
			List<ItemData> allItems = ((Humanoid)localPlayer).GetInventory().GetAllItems();
			s_hidden.Clear();
			for (int i = 0; i < allItems.Count; i++)
			{
				if (allItems[i].m_gridPos.y == 1)
				{
					s_hidden.Add(new KeyValuePair<int, ItemData>(i, allItems[i]));
				}
			}
			if (s_hidden.Count == 0)
			{
				return false;
			}
			for (int num = s_hidden.Count - 1; num >= 0; num--)
			{
				allItems.RemoveAt(s_hidden[num].Key);
			}
			s_hiding = true;
			return true;
		}

		private static void Restore()
		{
			Player localPlayer = Player.m_localPlayer;
			Inventory val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetInventory() : null);
			if (val != null)
			{
				List<ItemData> allItems = val.GetAllItems();
				foreach (KeyValuePair<int, ItemData> item in s_hidden)
				{
					allItems.Insert(Math.Min(item.Key, allItems.Count), item.Value);
				}
				InventoryChanged?.Invoke(val, new object[2] { false, false });
			}
			s_hidden.Clear();
			s_hiding = false;
		}
	}
	internal static class SecondBarShop
	{
		internal const string HaldorName = "$npc_haldor";

		private const string CounterKey = "aicho_dualhotbar_bar";

		private static TradeItem s_item;

		private static Sprite s_icon;

		private static TradeItem FindSack(Trader trader)
		{
			foreach (TradeItem item in trader.m_items)
			{
				if (item.m_incrementKey == "invrows")
				{
					return item;
				}
			}
			return null;
		}

		internal static TradeItem GetItem(Trader trader)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0040: Expected O, but got Unknown
			if (s_item == null)
			{
				s_item = new TradeItem
				{
					m_stack = 1,
					m_buyKey = "aicho_dualhotbar_unlocked",
					m_incrementKey = "aicho_dualhotbar_bar",
					m_incrementAmount = 1,
					m_buyPlayerEffects = new EffectList()
				};
			}
			TradeItem val = FindSack(trader);
			if (val != null)
			{
				s_item.m_levelUpEffect = val.m_levelUpEffect;
				if (val.m_buyPlayerEffects != null)
				{
					s_item.m_buyPlayerEffects = val.m_buyPlayerEffects;
				}
			}
			s_item.m_price = Mathf.Max(0, DualHotbarPlugin.PurchasePrice.Value);
			s_item.m_requiredGlobalKey = DualHotbarPlugin.RequiredGlobalKey.Value ?? string.Empty;
			s_item.m_name = DualHotbarPlugin.T("Segunda barra rápida", "Second Hotbar");
			s_item.m_tooltip = DualHotbarPlugin.T("Añade una segunda fila de 8 espacios junto a tu barra rápida. La intercambias con la tecla de cambio de barra, y cada barra recuerda lo que llevabas equipado.", "Adds a second row of 8 slots next to your hotbar. Swap them with the bar swap key; each bar remembers what you had equipped.");
			s_item.m_icon = GetIcon();
			return s_item;
		}

		private static Sprite GetIcon()
		{
			if ((Object)(object)s_icon == (Object)null)
			{
				s_icon = BuildIcon();
			}
			return s_icon;
		}

		private static Sprite BuildIcon()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = null;
			try
			{
				byte[] array = EmbeddedAssets.Read("second_bar.png");
				if (array != null)
				{
					Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, true);
					if (ImageConversion.LoadImage(val2, array))
					{
						val2.Apply(true);
						val = val2;
					}
				}
			}
			catch (Exception ex)
			{
				DualHotbarPlugin.LogWarning("Could not load the built-in shop icon: " + ex.Message);
			}
			if ((Object)(object)val == (Object)null)
			{
				val = DrawDefaultIcon();
			}
			((Texture)val).filterMode = (FilterMode)((((Texture)val).mipmapCount <= 1) ? 1 : 2);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}

		private static Texture2D DrawDefaultIcon()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			Color32[] array = (Color32[])(object)new Color32[4096];
			Color32 val = default(Color32);
			((Color32)(ref val))..ctor((byte)0, (byte)0, (byte)0, (byte)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = val;
			}
			Color32 color = default(Color32);
			((Color32)(ref color))..ctor((byte)38, (byte)24, (byte)14, byte.MaxValue);
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor((byte)222, (byte)170, (byte)70, byte.MaxValue);
			Color32 val3 = default(Color32);
			((Color32)(ref val3))..ctor((byte)250, (byte)214, (byte)120, byte.MaxValue);
			Color32 val4 = default(Color32);
			((Color32)(ref val4))..ctor((byte)150, (byte)98, (byte)52, byte.MaxValue);
			Color32 val5 = default(Color32);
			((Color32)(ref val5))..ctor((byte)188, (byte)132, (byte)78, byte.MaxValue);
			int num = 61;
			int num2 = (64 - num) / 2;
			int[] array2 = new int[2] { 34, 17 };
			for (int j = 0; j < 2; j++)
			{
				for (int k = 0; k < 4; k++)
				{
					int num3 = num2 + k * 16;
					int num4 = array2[j];
					FillRect(array, 64, num3, num4, 13, 13, color);
					FillRect(array, 64, num3 + 1, num4 + 1, 11, 11, (j == 0) ? val2 : val4);
					FillRect(array, 64, num3 + 2, num4 + 13 - 4, 9, 2, (j == 0) ? val3 : val5);
				}
			}
			Texture2D val6 = new Texture2D(64, 64, (TextureFormat)4, false);
			val6.SetPixels32(array);
			val6.Apply();
			return val6;
		}

		private static void FillRect(Color32[] pixels, int size, int x, int y, int width, int height, Color32 color)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			for (int i = y; i < y + height; i++)
			{
				for (int j = x; j < x + width; j++)
				{
					if (j >= 0 && j < size && i >= 0 && i < size)
					{
						pixels[i * size + j] = color;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
	internal static class TraderAvailableItemsPatch
	{
		private static void Postfix(Trader __instance, List<TradeItem> __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && DualHotbarPlugin.Enabled.Value && DualHotbarPlugin.RequirePurchase.Value && !(__instance.m_name != "$npc_haldor") && !((Humanoid)localPlayer).HaveUniqueKey("aicho_dualhotbar_unlocked"))
			{
				string value = DualHotbarPlugin.RequiredGlobalKey.Value;
				if (string.IsNullOrEmpty(value) || ZoneSystem.instance.GetGlobalKey(value))
				{
					__result.Add(SecondBarShop.GetItem(__instance));
				}
			}
		}
	}
	[HarmonyPatch(typeof(StoreGui), "BuySelectedItem")]
	internal static class StoreBuyPatch
	{
		private static bool s_hadBar;

		private static void Prefix()
		{
			s_hadBar = DualHotbarPlugin.BarActive(Player.m_localPlayer);
		}

		private static void Postfix()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !s_hadBar && DualHotbarPlugin.BarActive(localPlayer))
			{
				localPlayer.SetInventorySize(DualHotbarPlugin.GetVanillaRows(localPlayer));
				SidePanels.Refresh(localPlayer);
				((Character)localPlayer).Message((MessageType)2, DualHotbarPlugin.T("Segunda barra desbloqueada", "Second hotbar unlocked"), 0, (Sprite)null, false);
			}
		}
	}
	internal static class SidePanels
	{
		private static readonly string[] PanelPaths = new string[4] { "Armor", "Weight", "selected_frame/selected (2)", "selected_frame/selected (3)" };

		private static InventoryGui s_gui;

		private static float s_applied;

		internal static void Refresh(Player player)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_player == (Object)null)
			{
				return;
			}
			if ((Object)(object)instance != (Object)(object)s_gui)
			{
				s_gui = instance;
				s_applied = 0f;
			}
			float num = 0f;
			if (DualHotbarPlugin.SidePanelsBelowBars.Value && DualHotbarPlugin.BarActive(player))
			{
				float num2 = (((Object)(object)instance.m_playerGrid != (Object)null) ? instance.m_playerGrid.m_elementSpace : 70f);
				num = 2f * num2 + DualHotbarPlugin.CurrentGap() + DualHotbarPlugin.SidePanelsExtraOffset.Value;
			}
			float num3 = num - s_applied;
			if (Mathf.Approximately(num3, 0f))
			{
				return;
			}
			string[] panelPaths = PanelPaths;
			foreach (string text in panelPaths)
			{
				Transform obj = ((Transform)instance.m_player).Find(text);
				RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.anchoredPosition += new Vector2(0f, 0f - num3);
				}
			}
			s_applied = num;
			DualHotbarPlugin.LogInfo($"Side panels moved down by {num3:0.#} (total {num:0.#})");
		}
	}
	internal static class WavDecoder
	{
		internal sealed class Result
		{
			internal float[] Samples;

			internal int Channels;

			internal int Frequency;
		}

		internal static bool TryDecode(byte[] file, out Result result, out string error)
		{
			result = null;
			error = null;
			if (file == null || file.Length < 12 || !HasTag(file, 0, "RIFF") || !HasTag(file, 8, "WAVE"))
			{
				error = "not a RIFF/WAVE file";
				return false;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = -1;
			int num6 = 0;
			int num7 = 12;
			while (num7 + 8 <= file.Length)
			{
				int num8 = BitConverter.ToInt32(file, num7 + 4);
				int num9 = num7 + 8;
				int num10 = file.Length - num9;
				int num11 = ((num8 < 0 || num8 > num10) ? num10 : num8);
				if (HasTag(file, num7, "fmt ") && num11 >= 16)
				{
					num = BitConverter.ToUInt16(file, num9);
					num2 = BitConverter.ToUInt16(file, num9 + 2);
					num3 = BitConverter.ToInt32(file, num9 + 4);
					num4 = BitConverter.ToUInt16(file, num9 + 14);
					if (num == 65534 && num11 >= 26)
					{
						num = BitConverter.ToUInt16(file, num9 + 24);
					}
				}
				else if (HasTag(file, num7, "data"))
				{
					num5 = num9;
					num6 = num11;
					break;
				}
				num7 = num9 + num11 + (num11 & 1);
			}
			if (num2 <= 0 || num3 <= 0 || num5 < 0)
			{
				error = "missing format or data chunk";
				return false;
			}
			bool num12 = num == 1;
			bool flag = num == 3;
			if ((!num12 || (num4 != 8 && num4 != 16 && num4 != 24 && num4 != 32)) && (!flag || num4 != 32))
			{
				error = $"unsupported sample format (type {num}, {num4} bit)";
				return false;
			}
			int num13 = num4 / 8;
			int num14 = num6 / num13 / num2 * num2;
			if (num14 <= 0)
			{
				error = "no audio data";
				return false;
			}
			float[] array = new float[num14];
			for (int i = 0; i < num14; i++)
			{
				int num15 = num5 + i * num13;
				switch (num4)
				{
				case 8:
					array[i] = (float)(file[num15] - 128) / 128f;
					break;
				case 16:
					array[i] = (float)BitConverter.ToInt16(file, num15) / 32768f;
					break;
				case 24:
					array[i] = (float)(((file[num15] << 8) | (file[num15 + 1] << 16) | (file[num15 + 2] << 24)) >> 8) / 8388608f;
					break;
				default:
					array[i] = (flag ? BitConverter.ToSingle(file, num15) : ((float)BitConverter.ToInt32(file, num15) / 2.1474836E+09f));
					break;
				}
			}
			result = new Result
			{
				Samples = array,
				Channels = num2,
				Frequency = num3
			};
			return true;
		}

		private static bool HasTag(byte[] data, int offset, string tag)
		{
			for (int i = 0; i < 4; i++)
			{
				if (data[offset + i] != tag[i])
				{
					return false;
				}
			}
			return true;
		}
	}
}