Decompiled source of ZenUseItem v1.1.1

plugins/ZenUseItem.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
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<KeyboardShortcut> InventoryUseItem;

		public static readonly ConfigEntry<KeyCode> HotbarModifierKey;

		public static readonly ConfigEntry<bool> HideHotbarNumbers;

		static Configs()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			InventoryUseItem = Config.Define<KeyboardShortcut>(false, "General", "Inventory - Use Item", new KeyboardShortcut((KeyCode)324, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Press this key combo when pointing at an item in your inventory to use it on the crosshair target.\r\n[Must use Left (Mouse0) or Right (Mouse1) button plus a single modifier key]\r\n[logout required for changes to take effect]");
			InventoryUseItem.SettingChanged += delegate
			{
				Inputs.SetupButtons();
			};
			HotbarModifierKey = Config.Define<KeyCode>(false, "General", "Hotbar - Modifier Key", (KeyCode)308, "Using items directly from your hotbar on targets via 1-8 keys.\r\nKeyboard: Hold down this key and press the hotbar number.\r\nGamepad: Hold down the Interact-Alt button while pressing up on D-pad.\r\n[Note: 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!]");
			HideHotbarNumbers = Config.Define<bool>(false, "General", "Hotbar - Hide Numbers", true, "Hide the hotbar numbers until the Modifier Key is held down while the player is standing still.\r\n[If the modifier key is \"None\" then this option will simply hide/show the numbers]");
		}
	}
	[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_009e: 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;
			}
			bool flag = Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Vector3)(ref ((Character)Player.m_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)
		{
			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();
			}
			if (!((Behaviour)InventoryGui.instance.m_playerGrid).isActiveAndEnabled)
			{
				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 prompt = Inputs.GetPrompt();
			string text3 = "<size=20>" + ItemDataExt.GetName(itemAt) + "</size>\n" + prompt + " $settings_apply";
			Sb.Append("\n");
			Sb.Append(StringExt.Localize(text3));
			return Sb.ToString();
		}
	}
	internal static class Inputs
	{
		private static readonly ActionString Hold = ControlInputs.Create((string)null);

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

		public static bool IsUseItemPressed
		{
			get
			{
				if (ZInput.GetButton(ActionString.op_Implicit(Main)))
				{
					return ZInput.GetButton(ActionString.op_Implicit(Hold));
				}
				return false;
			}
		}

		public static string GetPrompt()
		{
			string text = $"$KEY_{Hold} + $KEY_{Main}";
			if (!ZInput.IsGamepadActive())
			{
				return UI.Prompt(text);
			}
			return text;
		}

		public static void SetupButtons()
		{
			//IL_004a: 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_0052: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			Main.RemoveButtons();
			Hold.RemoveButtons();
			Main.AddButton((GamepadInput)7, false, false, false, 0f, 0f);
			Hold.AddButton((GamepadInput)17, false, false, false, 0f, 0f);
			KeyboardShortcut value = Configs.InventoryUseItem.Value;
			KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
			KeyCode[] array = ((KeyboardShortcut)(ref value)).Modifiers.ToArray();
			if (((object)(KeyboardShortcut)(ref value)).Equals((object?)KeyboardShortcut.Empty) || array.Length == 0)
			{
				KeyboardShortcut val = (KeyboardShortcut)((ConfigEntryBase)Configs.InventoryUseItem).DefaultValue;
				Logging<Plugin>.Warning((object)$"Not a valid shortcut {value}. Using default instead: {val}", 0);
				mainKey = ((KeyboardShortcut)(ref val)).MainKey;
				array = ((KeyboardShortcut)(ref val)).Modifiers.ToArray();
			}
			Main.AddButton(mainKey, false, false, false, 0f, 0f);
			Hold.AddButton(array[0], false, false, false, 0f, 0f);
		}
	}
	[BepInPlugin("ZenDragon.ZenUseItem", "ZenUseItem", "1.1.1")]
	[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 = "1.1.1";

		public const string PluginGUID = "ZenDragon.ZenUseItem";

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

		protected override void TitleScene(bool isFirstBoot)
		{
		}

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

		protected override void Shutdown()
		{
		}

		protected override HelpInfo? GetHelpInfo()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(HelpInfo.Format("How It Works", "- Put your cursor on the object that you want to apply an item to.\r\n- Open your inventory.\r\n- Point at the item in your inventory\r\n- Press the controls indicated in the center of the screen.", (string)null, false, false));
			Inputs.GetPrompt();
			stringBuilder.AppendLine(HelpInfo.Format<KeyboardShortcut>(Configs.InventoryUseItem, true, true, true));
			stringBuilder.AppendLine(HelpInfo.Format<KeyCode>(Configs.HotbarModifierKey, true, true, false));
			if (Configs.HideHotbarNumbers.Value)
			{
				stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.HideHotbarNumbers, false, true, true));
			}
			return new HelpInfo("Use Item", stringBuilder.ToString());
		}
	}
	[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 _isItemUsedOnTarget;

		private static bool IsHoverTargetInteractable
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return Object.op_Implicit((Object)(object)HumanoidExt.GetHoverInteractable((Humanoid)(object)Player.m_localPlayer));
				}
				return false;
			}
		}

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

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
		private static void InventoryGui_OnSelectedItem(InventoryGui __instance, InventoryGrid grid, ItemData item, ref bool __runOriginal)
		{
			if (TryUseItemOnTarget(__instance, grid, item))
			{
				__runOriginal = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")]
		private static void InventoryGui_OnRightClickItem(InventoryGui __instance, InventoryGrid grid, ItemData item, ref bool __runOriginal)
		{
			if (TryUseItemOnTarget(__instance, grid, item))
			{
				__runOriginal = false;
			}
		}

		private static bool TryUseItemOnTarget(InventoryGui gui, InventoryGrid grid, ItemData item)
		{
			if (!Inputs.IsUseItemPressed)
			{
				return false;
			}
			if (gui.IsContainerOpen())
			{
				return false;
			}
			if (!IsHoverTargetInteractable)
			{
				return false;
			}
			_isItemUsedOnTarget = true;
			((Humanoid)Player.m_localPlayer).UseItem(grid.GetInventory(), item, false);
			_isItemUsedOnTarget = false;
			return true;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		[HarmonyPriority(100)]
		private static IEnumerable<CodeInstruction> Humanoid_UseItem_Transpile(IEnumerable<CodeInstruction> codes)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			Func<ItemType> func = ConsumableTypeIntercept;
			CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[5]
			{
				new CodeMatch((OpCode?)OpCodes.Ldarg_2, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(ItemData), "m_shared"), (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(SharedData), "m_itemType"), (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldc_I4_2, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Bne_Un, (object)null, (string)null)
			};
			MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "ToggleEquipped", (Type[])null, (Type[])null);
			Func<Humanoid, ItemData, bool> func2 = ToggleEquippedIntercept;
			return Transpilers.MethodReplacer(new CodeMatcher(codes, (ILGenerator)null).MatchEndForward(array).ThrowIfInvalid("Unable to match IL").Advance(-1)
				.SetInstruction(new CodeInstruction(OpCodes.Call, (object)func.Method))
				.InstructionEnumeration(), (MethodBase)methodInfo, (MethodBase)func2.Method);
			static ItemType ConsumableTypeIntercept()
			{
				if (_isItemUsedOnTarget)
				{
					return (ItemType)(-1);
				}
				return (ItemType)2;
			}
			static bool ToggleEquippedIntercept(Humanoid self, ItemData item)
			{
				if (!_isItemUsedOnTarget)
				{
					return self.ToggleEquipped(item);
				}
				return false;
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(HotkeyBar), "Update")]
		private static IEnumerable<CodeInstruction> HotkeyBar_Update(IEnumerable<CodeInstruction> codes)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[3]
			{
				new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"JoyAltKeys", (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ZInput), "GetButton", (Type[])null, (Type[])null), (string)null),
				new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null)
			};
			Func<bool, bool> func = AdjustBehavior;
			return new CodeMatcher(codes, (ILGenerator)null).End().MatchEndBackwards(array).ThrowIfInvalid("Unable to match IL")
				.Insert((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)func.Method)
				})
				.InstructionEnumeration();
			static bool AdjustBehavior(bool orig)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				if ((int)Configs.HotbarModifierKey.Value == 0)
				{
					return orig;
				}
				return false;
			}
		}
	}
}