Decompiled source of ZenUseItem v0.3.2

plugins\ZenUseItem.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using Zen;
using Zen.Lib;
using Zen.Lib.Config;
using Zen.Lib.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenUseItem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenUseItem")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ZenUseItem
{
	internal static class Configs
	{
		public static readonly ConfigEntry<bool> HideHotbarNumbers = Config.Define<bool>(false, "General", "Hotbar - Hide Numbers", true, "Hide the hotbar 1-8 numbers until the modifier key is held down while the player is standing still.\r\nIf the modifier key is \"None\" then this option will simply hide/show the numbers.");

		public static readonly ConfigEntry<KeyCode> HotbarModifierKey = Config.Define<KeyCode>(false, "General", "Hotbar - Modifier Key", (KeyCode)304, "In addition to using items directly from your inventory you can also use items from the hotbar keys 1-8.\r\nKeyboard: Hold down this modifier key and press the hotbar number.\r\nGamepad: Hold down the alt interact button while pressing up on D-pad to use a the hotbar item.\r\nAlt interact is either LB, LT, RB, or RT depending on how you have configured your gamepad layout.\r\nNote: If you set this to \"None\" it will revert to vanilla 1-8 hotbar behavior and you will not need to hold a modifier button.\r\nCaution: Without a modifier it's quite easy to attach your hammer to an item stand or launch your sword with a catapult!");
	}
	[HarmonyPatch]
	internal static class HotbarUI
	{
		private static bool _isShowNumbers;

		public static void Init()
		{
			_isShowNumbers = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		private static void InventoryGui_Hide()
		{
			Init();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HotkeyBar), "ToggleBindingHint")]
		private static void HotkeyBar_ToggleBindingHint(bool bShouldEnable)
		{
			_isShowNumbers = bShouldEnable;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HotkeyBar), "Update")]
		private static void HotkeyBar_Update(HotkeyBar __instance)
		{
			UpdateHotbarNumbers(__instance);
		}

		private static void UpdateHotbarNumbers(HotkeyBar hotkeyBar)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if (ZInput.IsGamepadActive())
			{
				return;
			}
			if ((int)Configs.HotbarModifierKey.Value == 0)
			{
				if (_isShowNumbers != !Configs.HideHotbarNumbers.Value)
				{
					hotkeyBar.ToggleBindingHint(!Configs.HideHotbarNumbers.Value);
				}
				return;
			}
			if (!Configs.HideHotbarNumbers.Value)
			{
				if (!_isShowNumbers)
				{
					hotkeyBar.ToggleBindingHint(true);
				}
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			bool flag = localPlayer != null && ((Vector3)(ref ((Character)localPlayer).m_currentVel)).sqrMagnitude < 1f;
			bool flag2 = TextInput.IsVisible() || Console.IsVisible() || Chat.instance.IsChatDialogWindowVisible();
			bool flag3 = ZInput.GetKey(Configs.HotbarModifierKey.Value, true) && flag && !flag2 && !Minimap.IsOpen();
			if (flag3 != _isShowNumbers)
			{
				Logging<Plugin>.Info((object)$"Show hotbar numbers: {flag3}", 0);
				hotkeyBar.ToggleBindingHint(flag3);
			}
		}
	}
	[HarmonyPatch]
	internal static class HudHoverText
	{
		private static readonly StringBuilder Sb = new StringBuilder();

		private static string Pattern(string p)
		{
			return StringExt.RegexPattern(p, (Func<string, string>)((string s) => StringExt.GlyphFix(s, true)), true);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
		private static void Hud_UpdateCrosshair(Hud __instance)
		{
			TextMeshProUGUI hoverName = __instance.m_hoverName;
			if (Object.op_Implicit((Object)(object)hoverName) && !Utility.IsNullOrWhiteSpace(((TMP_Text)hoverName).text))
			{
				Sb.Clear();
				((TMP_Text)hoverName).text = (InventoryGui.IsVisible() ? GetInventoryOpenText(((TMP_Text)hoverName).text) : GetInventoryClosedText(((TMP_Text)hoverName).text));
			}
		}

		private static string GetInventoryClosedText(string text)
		{
			string pattern = "^" + Pattern(UI.PromptInteract) + " *(.+)$";
			Match match = Regex.Match(text, pattern, RegexOptions.Multiline);
			string useItemText = (match.Success ? match.Groups[1].Value : string.Empty);
			string pattern2 = "^" + Pattern(UI.PromptUseItem) + " *(.+)\n?";
			text = Regex.Replace(text, pattern2, delegate(Match m)
			{
				string value = m.Groups[1].Value;
				return (value == useItemText) ? string.Empty : StringExt.GlyphFix(StringExt.Localize(UI.Prompt("$KEY_Inventory") + " " + value + "\n"), true);
			}, RegexOptions.Multiline);
			return text;
		}

		private static string GetInventoryOpenText(string text)
		{
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			string[] array = text.Split(new char[1] { '\n' });
			string value = StringExt.GlyphFix(StringExt.Localize(UI.PromptInteract), true);
			string value2 = StringExt.GlyphFix(StringExt.Localize(UI.PromptInteractAlt), true);
			string oldValue = StringExt.GlyphFix(StringExt.Localize(UI.PromptUseItem), true);
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				if (!text2.StartsWith(value) && !text2.StartsWith(value2))
				{
					Sb.Append(text2.Replace(oldValue, string.Empty).Trim() + "\n");
				}
			}
			if (InventoryGui.instance.IsContainerOpen())
			{
				return Sb.ToString();
			}
			InventoryGrid playerGrid = InventoryGui.instance.m_playerGrid;
			Inventory inventory = playerGrid.GetInventory();
			Element val = ((playerGrid.m_uiGroup.IsActive && ZInput.IsGamepadActive()) ? playerGrid.GetElement(playerGrid.m_selected.x, playerGrid.m_selected.y, inventory.GetWidth()) : playerGrid.GetHoveredElement());
			if (val == null)
			{
				return Sb.ToString();
			}
			ItemData itemAt = inventory.GetItemAt(val.m_pos.x, val.m_pos.y);
			if (itemAt == null)
			{
				return Sb.ToString();
			}
			string arg = (ZInput.IsGamepadActive() ? $"$KEY_{Inputs.Hold} + $KEY_{Inputs.Main}" : UI.Prompt($"$KEY_{Inputs.Hold} + $KEY_{Inputs.Main}"));
			string text3 = $"<color={UIColor.White}><size=20>{ItemDataExt.GetName(itemAt)}</size></color>\n{arg} $settings_apply";
			Sb.Append("\n");
			Sb.Append(StringExt.Localize(text3));
			return Sb.ToString();
		}
	}
	internal static class Inputs
	{
		public static readonly ActionString Hold = ControlInputs.Create((string)null);

		public static readonly ActionString Main = ControlInputs.Create((string)null);

		public static void Setup()
		{
			Main.AddButton((GamepadInput)7, false, false, false, 0f, 0f);
			Hold.AddButton((GamepadInput)17, false, false, false, 0f, 0f);
			Main.AddButton((KeyCode)323, false, false, false, 0f, 0f);
			Hold.AddButton((KeyCode)306, false, false, false, 0f, 0f);
		}
	}
	[BepInPlugin("ZenDragon.ZenUseItem", "ZenUseItem", "0.3.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : ZenMod<Plugin>
	{
		public const string PluginName = "ZenUseItem";

		public const string PluginVersion = "0.3.2";

		public const string PluginGUID = "ZenDragon.ZenUseItem";

		protected override void Setup()
		{
			base.RegisterInputs += Inputs.Setup;
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
			UseItem.Init();
			HotbarUI.Init();
		}

		protected override void Shutdown()
		{
		}
	}
	[HarmonyPatch]
	internal static class UseItem
	{
		[HarmonyPatch(typeof(Player), "UseHotbarItem")]
		private static class PlayerUseHotbarItem
		{
			[UsedImplicitly]
			private static void Prefix()
			{
				_isUsedFromHotbar = true;
			}

			[UsedImplicitly]
			private static void Postfix()
			{
				_isUsedFromHotbar = false;
			}
		}

		private static bool _isUsedFromHotbar;

		private static bool _isItemUsed;

		private static bool IsInteractable
		{
			get
			{
				Player localPlayer = Player.m_localPlayer;
				return Object.op_Implicit((Object)(object)((localPlayer != null) ? HumanoidExt.GetHoverInteractable((Humanoid)(object)localPlayer) : null));
			}
		}

		public static void Init()
		{
			KeyHint.SetEvent((HintType)4, (Action)UpdateKeyHints);
		}

		private static void UpdateKeyHints()
		{
			KeyHint.SetVisible("Drop", ZInput.IsGamepadActive() || !IsInteractable);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private static void Prefix(Humanoid __instance, Inventory inventory, ItemData item, ref bool fromInventoryGui, ref bool __runOriginal)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (_isUsedFromHotbar)
			{
				if ((int)Configs.HotbarModifierKey.Value == 0)
				{
					fromInventoryGui = false;
				}
				else if (ZInput.IsGamepadActive())
				{
					fromInventoryGui = !ZInput.GetButton(ActionString.op_Implicit(Inputs.InteractAlt));
				}
				else
				{
					fromInventoryGui = !ZInput.GetKey(Configs.HotbarModifierKey.Value, true);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
		private static void InventoryGui_OnSelectedItem(InventoryGui __instance, InventoryGrid grid, Modifier mod, ItemData item, ref bool __runOriginal)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			if (!__instance.IsContainerOpen() && (int)mod == 2 && IsInteractable)
			{
				__runOriginal = false;
				_isItemUsed = true;
				((Humanoid)Player.m_localPlayer).UseItem(grid.GetInventory(), item, false);
				_isItemUsed = false;
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private static IEnumerable<CodeInstruction> HumanoidUseItem_Transpile(IEnumerable<CodeInstruction> codes)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "ToggleEquipped", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(UseItem), "ToggleEquipped_Intercept", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(new CodeMatcher(codes, (ILGenerator)null).MatchEndForward((CodeMatch[])(object)new CodeMatch[4]
			{
				new CodeMatch((OpCode?)OpCodes.Ldarg_2, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldc_I4_2, (object)null, (string)null)
			}).ThrowIfInvalid("Unable to match IL").SetInstruction(CodeInstruction.Call(typeof(UseItem), "ConsumableType_Intercept", (Type[])null, (Type[])null))
				.InstructionEnumeration(), (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		private static int ConsumableType_Intercept()
		{
			if (_isItemUsed)
			{
				return -1;
			}
			return 2;
		}

		private static bool ToggleEquipped_Intercept(Humanoid self, ItemData item)
		{
			if (_isItemUsed)
			{
				return false;
			}
			return self.ToggleEquipped(item);
		}
	}
}