Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ZenUseItem v0.4.0
plugins/ZenUseItem.dll
Decompiled 4 months agousing 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) { 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 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.4.0")] [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.4.0"; 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "ToggleEquipped", (Type[])null, (Type[])null); Func<Humanoid, ItemData, bool> func = ToggleEquipped_Intercept; Func<int> func2 = ConsumableType_Intercept; 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(new CodeInstruction(OpCodes.Call, (object)func2.Method)) .InstructionEnumeration(), (MethodBase)methodInfo, (MethodBase)func.Method); } 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); } } }