Decompiled source of HotbarSwitch v0.5.2

plugins\HotbarSwitch.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace HotbarSwitch;

[BepInPlugin("cjayride.HotbarSwitch", "Hotbar Switch", "0.5.2")]
public class BepInExPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Inventory), "GetItemAt", new Type[]
	{
		typeof(int),
		typeof(int)
	})]
	private static class GetItemAt_Patch
	{
		private static void Prefix(ref int y)
		{
			if (readingHotbar && y == 0)
			{
				y = HotbarY();
			}
		}
	}

	[HarmonyPatch(typeof(Inventory), "GetBoundItems")]
	private static class GetBoundItems_Patch
	{
		private static bool Prefix(Inventory __instance, List<ItemData> bound)
		{
			int num = HotbarY();
			if (num <= 0)
			{
				return true;
			}
			bound.Clear();
			int width = __instance.GetWidth();
			for (int i = 0; i < width; i++)
			{
				ItemData itemAt = __instance.GetItemAt(i, num);
				if (itemAt != null)
				{
					bound.Add(itemAt);
				}
			}
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "UseHotbarItem")]
	private static class UseHotbarItem_Patch
	{
		private static void Prefix()
		{
			readingHotbar = true;
		}

		private static void Postfix()
		{
			readingHotbar = false;
		}
	}

	[HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")]
	private static class UpdateIcons_Patch
	{
		private static void Prefix()
		{
			readingHotbar = true;
		}

		private static void Postfix()
		{
			readingHotbar = false;
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				PaintHotkeyBars(Player.m_localPlayer);
			}
		}
	}

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<int> rowsToSwitch;

	public static ConfigEntry<string> hotKey;

	internal static int activeRow;

	private static bool readingHotbar;

	private Harmony harmony;

	private static FieldInfo elementsField;

	private static FieldInfo iconField;

	private static FieldInfo amountField;

	private static FieldInfo durabilityField;

	private static FieldInfo equippedField;

	private static PropertyInfo amountText;

	private static MethodInfo durabilitySetValue;

	private static HotkeyBar[] cachedBars;

	private static float cachedBarsAt;

	private void Awake()
	{
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		rowsToSwitch = ((BaseUnityPlugin)this).Config.Bind<int>("General", "RowsToSwitch", 2, "How many inventory rows the hotkey cycles as the hotbar. Items stay in their original slots.");
		hotKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "HotKey", "`", "Hotkey to switch which inventory row is shown on the hotbar. Use https://docs.unity3d.com/Manual/ConventionalGameInput.html");
		Type type = AccessTools.Inner(typeof(HotkeyBar), "ElementData");
		if (type == null)
		{
			type = AccessTools.Inner(typeof(HotkeyBar), "Element");
		}
		elementsField = AccessTools.Field(typeof(HotkeyBar), "m_elements");
		if (type != null)
		{
			iconField = AccessTools.Field(type, "m_icon");
			amountField = AccessTools.Field(type, "m_amount");
			durabilityField = AccessTools.Field(type, "m_durability");
			equippedField = AccessTools.Field(type, "m_equiped");
			if (equippedField == null)
			{
				equippedField = AccessTools.Field(type, "m_equipped");
			}
			if (amountField != null)
			{
				amountText = amountField.FieldType.GetProperty("text");
			}
			if (durabilityField != null)
			{
				durabilitySetValue = AccessTools.Method(durabilityField.FieldType, "SetValue", new Type[1] { typeof(float) }, (Type[])null);
			}
		}
		if (modEnabled.Value)
		{
			harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), ((BaseUnityPlugin)this).Info.Metadata.GUID);
		}
	}

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

	private void Update()
	{
		if (modEnabled.Value && !AedenthornUtils.IgnoreKeyPresses() && AedenthornUtils.CheckKeyDown(hotKey.Value) && !((Object)(object)Player.m_localPlayer == (Object)null))
		{
			int num = Math.Max(1, Math.Min(((Humanoid)Player.m_localPlayer).GetInventory().GetHeight(), rowsToSwitch.Value));
			activeRow = (activeRow + 1) % num;
		}
	}

	private void LateUpdate()
	{
		if (modEnabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null))
		{
			PaintHotkeyBars(Player.m_localPlayer);
		}
	}

	internal static int HotbarY()
	{
		if (!modEnabled.Value || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return 0;
		}
		int num = Math.Max(1, Math.Min(((Humanoid)Player.m_localPlayer).GetInventory().GetHeight(), rowsToSwitch.Value));
		if (activeRow >= num)
		{
			activeRow = 0;
		}
		return activeRow;
	}

	private static void PaintHotkeyBars(Player player)
	{
		if (elementsField == null || iconField == null)
		{
			return;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		int num = HotbarY();
		int width = inventory.GetWidth();
		if (cachedBars == null || Time.unscaledTime - cachedBarsAt > 2f)
		{
			cachedBars = Resources.FindObjectsOfTypeAll<HotkeyBar>();
			cachedBarsAt = Time.unscaledTime;
		}
		HotkeyBar[] array = cachedBars;
		foreach (HotkeyBar val in array)
		{
			if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled && elementsField.GetValue(val) is IList list && IsMainHotkeyBar(val, list.Count, width))
			{
				int num2 = list.Count;
				if (num2 > width)
				{
					num2 = width;
				}
				for (int j = 0; j < num2; j++)
				{
					PaintSlot(list[j], inventory.GetItemAt(j, num));
				}
			}
		}
	}

	private static bool IsMainHotkeyBar(HotkeyBar bar, int elementCount, int width)
	{
		if (elementCount < width)
		{
			return false;
		}
		Transform val = ((Component)bar).transform;
		for (int i = 0; i < 6; i++)
		{
			if (!((Object)(object)val != (Object)null))
			{
				break;
			}
			string name = ((Object)val).name;
			if (name != null)
			{
				string text = name.ToLower();
				if (text.IndexOf("quick") >= 0 || text.IndexOf("extra") >= 0 || text.IndexOf("equip") >= 0)
				{
					return false;
				}
			}
			val = val.parent;
		}
		return true;
	}

	private static void PaintSlot(object element, ItemData item)
	{
		if (element == null)
		{
			return;
		}
		object? value = iconField.GetValue(element);
		Image val = (Image)((value is Image) ? value : null);
		if ((Object)(object)val != (Object)null)
		{
			if (item == null)
			{
				((Behaviour)val).enabled = false;
				val.sprite = null;
			}
			else
			{
				((Behaviour)val).enabled = true;
				val.sprite = item.GetIcon();
			}
		}
		if (amountField != null && amountText != null)
		{
			object value2 = amountField.GetValue(element);
			if (value2 != null)
			{
				amountText.SetValue(value2, (item != null && item.m_stack > 1) ? item.m_stack.ToString() : "", null);
			}
		}
		if (durabilityField != null)
		{
			object? value3 = durabilityField.GetValue(element);
			Component val2 = (Component)((value3 is Component) ? value3 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				bool flag = item?.m_shared.m_useDurability ?? false;
				val2.gameObject.SetActive(flag);
				if (flag && durabilitySetValue != null)
				{
					durabilitySetValue.Invoke(val2, new object[1] { item.GetDurabilityPercentage() });
				}
			}
		}
		if (equippedField != null)
		{
			object? value4 = equippedField.GetValue(element);
			GameObject val3 = (GameObject)((value4 is GameObject) ? value4 : null);
			if ((Object)(object)val3 != (Object)null)
			{
				val3.SetActive(item?.m_equipped ?? false);
			}
		}
	}
}
public class AedenthornUtils
{
	public static bool IgnoreKeyPresses(bool extra = false)
	{
		if (!extra)
		{
			if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
			{
				if ((Object)(object)Chat.instance != (Object)null)
				{
					return Chat.instance.HasFocus();
				}
				return false;
			}
			return true;
		}
		if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible())
		{
			if ((Object)(object)TextViewer.instance != (Object)null)
			{
				return TextViewer.instance.IsVisible();
			}
			return false;
		}
		return true;
	}

	public static bool CheckKeyDown(string value)
	{
		try
		{
			return Input.GetKeyDown(value.ToLower());
		}
		catch
		{
			return false;
		}
	}
}