Please disclose if any significant portion of your mod was created 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 DropSingleItem v1.2.1
plugins\DropSingleItem.dll
Decompiled 10 hours agousing 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.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.1")] [assembly: AssemblyInformationalVersion("1.0.0+57d9ddb874359d5fc5ab99d249522b80311a94b2")] [assembly: AssemblyVersion("1.2.1.0")] namespace DropSingleItem { [BepInPlugin("TechGuard.DropSingleItem", "DropSingleItem", "1.2.1")] [BepInProcess("valheim.exe")] public class DropSingleItemMod : BaseUnityPlugin { private const string NAME = "DropSingleItem"; private const string GUID = "TechGuard.DropSingleItem"; private const string VERSION = "1.2.1"; private readonly Harmony harmony = new Harmony("TechGuard.DropSingleItem"); private static ConfigEntry<string> InventoryUseItemKeyCodeConfig; public static KeyCode InventoryUseItemKeyCode { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (Enum.TryParse<KeyCode>(InventoryUseItemKeyCodeConfig.Value, out KeyCode result)) { return result; } return (KeyCode)324; } } public void Awake() { InventoryUseItemKeyCodeConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Input", "InventoryUseItem", "Mouse1", "Keybinding for using/consuming/equipping an item in the inventory (Mouse1 = right mouse button).\nIf this is set to anything other than Mouse1, you no longer have to hold shift to split a stack when right clicking.\nAvailable KeyCodes can be found here: https://docs.unity3d.com/ScriptReference/KeyCode.html"); harmony.PatchAll(); } } } namespace DropSingleItem.Patch { [HarmonyPatch(typeof(InventoryGui), "Update")] internal class InventoryGui_Update_DropSingleOutside { public static void Postfix(InventoryGui __instance) { if (InventoryGui.IsVisible() && !((Object)(object)__instance.dragGo() == (Object)null) && ZInput.GetMouseButtonDown(1) && !Utils.PointerOverInventoryGrid(__instance)) { Utils.DropOneOutside(__instance); } } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] internal class InventoryGui_OnSelectedItem_GrabFullStack { private const float DoubleClickThreshold = 0.3f; private static float LastItemClickedTime = -1f; public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)mod != 0) { return true; } bool num = LastItemClickedTime >= 0f && Time.unscaledTime - LastItemClickedTime < 0.3f; LastItemClickedTime = Time.unscaledTime; if (!num) { return true; } ItemData val = item; Inventory val2 = (((Object)(object)grid != (Object)null) ? grid.GetInventory() : null); if (val == null && __instance.dragItem() != null) { val = __instance.dragItem(); val2 = __instance.dragInventory(); } if (val == null || val2 == null) { return true; } Utils.MergeMatchingIntoSlot(__instance, val2, val); return false; } } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] internal class InventoryGui_OnRightClickItem { public static bool Prefix(InventoryGui __instance, ref int ___m_dragAmount, InventoryGrid grid, ItemData item, Vector2i pos) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_008d: Unknown result type (might be due to invalid IL or missing references) bool flag = (Object)(object)__instance.dragGo() != (Object)null; bool flag2 = (int)DropSingleItemMod.InventoryUseItemKeyCode == 324; bool flag3 = flag2 && Utils.IsShiftHeld(); if (!flag2 || flag3) { if (!flag && item != null && item.m_stack > 1) { if (Utils.TrySplitStackIntoEmptySlot(grid.GetInventory(), item)) { Utils.PlayMoveEffects(__instance); } return false; } if (flag3) { return false; } } if (!flag) { return flag2; } ItemData val = __instance.dragItem(); if (!Utils.CanStackItem(val, item)) { return false; } Inventory val2 = __instance.dragInventory(); int num = __instance.dragAmount(); int stack = val.m_stack; ___m_dragAmount = 1; __instance.OnSelectedItem(grid, item, pos, (Modifier)0); num -= stack - val.m_stack; if (num > 0 && val != null && val2 != null && val2.ContainsItem(val)) { __instance.SetupDragItem(val, val2, num); } return false; } } [HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")] internal class InventoryGrid_UpdateInventory { public static void Postfix(InventoryGrid __instance, Inventory inventory, Player player, ItemData dragItem) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_0012: 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) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((int)DropSingleItemMod.InventoryUseItemKeyCode != 324 && dragItem == null && ZInput.GetKeyDown(DropSingleItemMod.InventoryUseItemKeyCode, true)) { ItemData item = __instance.GetItem(new Vector2i(ZInput.pointerPosition)); if (item != null && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Humanoid)Player.m_localPlayer).UseItem(inventory, item, true); } } } } [HarmonyPatch(typeof(InventoryGui), "UpdateItemDrag")] internal class InventoryGui_UpdateItemDrag { public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown MethodInfo method = typeof(ZInput).GetMethod("GetMouseButton", new Type[1] { typeof(int) }); List<CodeInstruction> list = new List<CodeInstruction>(instructions); for (int i = 1; i < list.Count; i++) { if (list[i - 1].opcode == OpCodes.Ldc_I4_1 && CodeInstructionExtensions.Calls(list[i], method)) { list[i - 1] = new CodeInstruction(OpCodes.Nop, (object)null); list[i] = new CodeInstruction(OpCodes.Ldc_I4_S, (object)0); } } return list.AsEnumerable(); } } internal class Utils { public static bool IsShiftHeld() { if (!ZInput.GetKey((KeyCode)304, true)) { return ZInput.GetKey((KeyCode)303, true); } return true; } public static bool CanStackItem(ItemData a, ItemData b) { if (a == null || b == null) { return true; } if (a == b) { return false; } if (a.m_shared.m_name != b.m_shared.m_name) { return false; } if (a.m_shared.m_maxStackSize == 1 || b.m_shared.m_maxStackSize == 1) { return false; } if ((a.m_shared.m_maxQuality > 1 || b.m_shared.m_maxQuality > 1) && a.m_quality != b.m_quality) { return false; } return true; } public static void PlayMoveEffects(InventoryGui instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) EffectList val = instance.moveItemEffects(); if (val != null) { val.Create(((Component)instance).transform.position, Quaternion.identity, (Transform)null, 1f, -1, ZDOID.None); } } public static bool TrySplitStackIntoEmptySlot(Inventory inventory, ItemData item) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || item == null || item.m_stack < 2 || !inventory.HaveEmptySlot()) { return false; } Vector2i value = Traverse.Create((object)inventory).Method("FindEmptySlot", new Type[1] { typeof(bool) }, (object[])null).GetValue<Vector2i>(new object[1] { true }); if (value.x < 0 || value.y < 0) { return false; } int num = item.m_stack / 2; return inventory.MoveItemToThis(inventory, item, num, value.x, value.y); } public static void MergeMatchingIntoSlot(InventoryGui gui, Inventory targetInventory, ItemData target) { if (!((Object)(object)gui == (Object)null) && targetInventory != null && target != null && !((Object)(object)Player.m_localPlayer == (Object)null)) { int stack = target.m_stack; Container val = gui.currentContainer(); if ((Object)(object)val != (Object)null) { MergeMatchingStacksInto(targetInventory, target, val.GetInventory()); } MergeMatchingStacksInto(targetInventory, target, ((Humanoid)Player.m_localPlayer).GetInventory()); if (target.m_stack != stack) { PlayMoveEffects(gui); } gui.SetupDragItem(null, null, 1); gui.UpdateCraftingPanel(); } } private static void MergeMatchingStacksInto(Inventory targetInventory, ItemData target, Inventory source) { if (source == null || target == null || target.m_shared == null) { return; } List<ItemData> list = new List<ItemData>(); source.GetAllItems(target.m_shared.m_name, list); while (list.Any() && target.m_stack < target.m_shared.m_maxStackSize) { ItemData val = list.Last(); list.RemoveAt(list.Count - 1); if (CanStackItem(target, val)) { targetInventory.MoveItemToThis(source, val, val.m_stack, target.m_gridPos.x, target.m_gridPos.y); } } } public static bool PointerOverInventoryGrid(InventoryGui gui) { if (!ContainsPointer((Component)(object)gui.playerGrid())) { return ContainsPointer((Component)(object)gui.containerGrid()); } return true; } private static bool ContainsPointer(Component component) { //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_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)component == (Object)null) { return false; } Transform transform = component.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { return false; } Canvas componentInParent = component.GetComponentInParent<Canvas>(); Camera val2 = null; if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) { val2 = componentInParent.worldCamera; } return RectTransformUtility.RectangleContainsScreenPoint(val, Vector2.op_Implicit(ZInput.pointerPosition), val2); } public static void DropOneOutside(InventoryGui gui) { if ((Object)(object)gui == (Object)null || (Object)(object)gui.dragGo() == (Object)null) { return; } ItemData val = gui.dragItem(); Inventory val2 = gui.dragInventory(); if (val == null || val2 == null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } int num = gui.dragAmount(); int stack = val.m_stack; if (!val2.ContainsItem(val)) { gui.SetupDragItem(null, null, 1); } else if (((Humanoid)Player.m_localPlayer).DropItem(val2, val, 1)) { PlayMoveEffects(gui); num -= stack - val.m_stack; if (val2.ContainsItem(val) && num > 0) { gui.SetupDragItem(val, val2, num); } else { gui.SetupDragItem(null, null, 1); } gui.UpdateCraftingPanel(); } } } internal static class InventoryGui_Extensions { public static void SetupDragItem(this InventoryGui instance, ItemData item, Inventory inventory, int amount) { Traverse.Create((object)instance).Method("SetupDragItem", new Type[3] { typeof(ItemData), typeof(Inventory), typeof(int) }, (object[])null).GetValue(new object[3] { item, inventory, amount }); } public static void UpdateCraftingPanel(this InventoryGui instance, bool focusView = false) { Traverse.Create((object)instance).Method("UpdateCraftingPanel", new Type[1] { typeof(bool) }, (object[])null).GetValue(new object[1] { focusView }); } public static void OnSelectedItem(this InventoryGui instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod) { //IL_005b: 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) Traverse.Create((object)instance).Method("OnSelectedItem", new Type[4] { typeof(InventoryGrid), typeof(ItemData), typeof(Vector2i), typeof(Modifier) }, (object[])null).GetValue(new object[4] { grid, item, pos, mod }); } public static EffectList moveItemEffects(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_moveItemEffects").GetValue<EffectList>(); } public static GameObject dragGo(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_dragGo").GetValue<GameObject>(); } public static ItemData dragItem(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_dragItem").GetValue<ItemData>(); } public static Inventory dragInventory(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_dragInventory").GetValue<Inventory>(); } public static int dragAmount(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_dragAmount").GetValue<int>(); } public static Container currentContainer(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_currentContainer").GetValue<Container>(); } public static InventoryGrid playerGrid(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_playerGrid").GetValue<InventoryGrid>(); } public static InventoryGrid containerGrid(this InventoryGui instance) { return Traverse.Create((object)instance).Field("m_containerGrid").GetValue<InventoryGrid>(); } } }