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 NEWDropSingleItem v1.3.4
NEWDropSingleItem.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace DropSingleItem { [BepInPlugin("NEWDropSingleItem", "NEWDropSingleItem", "1.3.4")] [BepInProcess("valheim.exe")] public class DropSingleItemMod : BaseUnityPlugin { public const string NAME = "NEWDropSingleItem"; public const string GUID = "NEWDropSingleItem"; public const string VERSION = "1.3.4"; private readonly Harmony harmony = new Harmony("NEWDropSingleItem"); 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"); Type[] types = typeof(DropSingleItemMod).Assembly.GetTypes(); foreach (Type type in types) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0) { try { harmony.ProcessorForAnnotatedClass(type).Patch(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("DropSingleItem: failed to apply patch on " + type.Name + ": " + ex.Message)); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded 1.3.4 - Harmony patches applied."); } } } namespace DropSingleItem.Patch { [HarmonyPatch(typeof(InventoryGui), "Update")] internal class InventoryGui_Update_DropSingleOutside { [HarmonyPostfix] public static void Postfix(InventoryGui __instance) { if (InventoryGui.IsVisible() && !((Object)(object)__instance.dragGo() == (Object)null) && ZInput.GetMouseButtonDown(1) && !Utils.PointerOverInventoryGrid(__instance)) { if (Utils.IsShiftHeld()) { Utils.DropHalfOutside(__instance); } else { Utils.DropOneOutside(__instance); } } } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] internal class InventoryGui_OnSelectedItem_GrabFullStack { private const float DoubleClickThreshold = 0.3f; private static float LastItemClickedTime = -1f; private static Vector2i LastItemClickedPos = new Vector2i(-1, -1); private static InventoryGrid LastItemClickedGrid = null; [HarmonyPrefix] public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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) if (Utils.placingOneFromDrag) { return true; } if (ZInput.GetMouseButton(1) || ZInput.GetMouseButtonDown(1) || ZInput.GetMouseButtonUp(1)) { return true; } if ((int)mod != 0 || item == null || (Object)(object)grid == (Object)null) { return true; } if (item.m_shared == null || item.m_shared.m_maxStackSize <= 1 || item.m_stack >= item.m_shared.m_maxStackSize) { ResetDoubleClick(); return true; } bool flag = LastItemClickedPos.x == pos.x && LastItemClickedPos.y == pos.y && (Object)(object)LastItemClickedGrid == (Object)(object)grid; if (!(LastItemClickedTime >= 0f && Time.unscaledTime - LastItemClickedTime < 0.3f && flag)) { LastItemClickedTime = Time.unscaledTime; LastItemClickedPos = pos; LastItemClickedGrid = grid; return true; } ResetDoubleClick(); Utils.MergeMatchingIntoSlot(__instance, grid.GetInventory(), item); return false; } private static void ResetDoubleClick() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) LastItemClickedTime = -1f; LastItemClickedPos = new Vector2i(-1, -1); LastItemClickedGrid = null; } } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] internal class InventoryGui_OnRightClickItem { [HarmonyPrefix] public static bool Prefix(InventoryGui __instance, 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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 (flag3) { __instance.SetupDragItem(item, grid.GetInventory(), item.m_stack / 2); Utils.PlayMoveEffects(__instance); } else if (Utils.TrySplitStackIntoEmptySlot(grid.GetInventory(), item)) { Utils.PlayMoveEffects(__instance); } return false; } if (flag3) { if (flag && item == null && Utils.PlaceHalfFromDrag(__instance, grid, pos)) { Utils.PlayMoveEffects(__instance); } return false; } } if (!flag) { return flag2; } ItemData val = __instance.dragItem(); if (val == null || !Utils.CanStackItem(val, item)) { return false; } Inventory val2 = __instance.dragInventory(); int num = __instance.dragAmount(); int stack = val.m_stack; if (pos.x < 0 || pos.y < 0) { return false; } if (!Utils.PlaceOneFromDrag(__instance, grid, val, item, pos)) { return false; } num -= stack - val.m_stack; if (num > 0 && val != null && val2 != null && val2.ContainsItem(val)) { __instance.SetupDragItem(val, val2, num); } else { __instance.SetupDragItem(null, null, 1); } return false; } } [HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")] internal class InventoryGrid_UpdateInventory { [HarmonyPostfix] 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)(object)Player.m_localPlayer != (Object)null) { ((Humanoid)Player.m_localPlayer).UseItem(inventory, item, true); } } } } internal class Reflect { private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public static FieldInfo FindField(Type type, string name) { Type type2 = type; while (type2 != null) { FieldInfo field = type2.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type2 = type2.BaseType; } return null; } public static MethodInfo FindMethod(Type type, string name, Type[] paramTypes) { Type type2 = type; while (type2 != null) { MethodInfo method = type2.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes ?? Type.EmptyTypes, null); if (method != null) { return method; } type2 = type2.BaseType; } return null; } public static object Get(object instance, string name) { if (instance == null) { return null; } FieldInfo fieldInfo = FindField(instance.GetType(), name); if (!(fieldInfo == null)) { return fieldInfo.GetValue(instance); } return null; } public static void Set(object instance, string name, object value) { if (instance != null) { FieldInfo fieldInfo = FindField(instance.GetType(), name); if (fieldInfo != null) { fieldInfo.SetValue(instance, value); } } } public static object Call(object instance, string name, params object[] args) { if (instance == null) { return null; } Type[] array = Type.EmptyTypes; if (args != null && args.Length != 0) { array = new Type[args.Length]; for (int i = 0; i < args.Length; i++) { array[i] = ((args[i] == null) ? typeof(object) : args[i].GetType()); } } return CallWithTypes(instance, name, array, args); } public static object CallWithTypes(object instance, string name, Type[] paramTypes, params object[] args) { if (instance == null) { return null; } MethodInfo methodInfo = FindMethod(instance.GetType(), name, paramTypes); if (methodInfo == null) { return null; } return methodInfo.Invoke(instance, args); } public static object CallByArity(object instance, string name, int paramCount, params object[] args) { if (instance == null) { return null; } Type type = instance.GetType(); while (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == name && methodInfo.GetParameters().Length == paramCount) { return methodInfo.Invoke(instance, args); } } type = type.BaseType; } return null; } } [HarmonyPatch(typeof(InventoryGui), "UpdateItemDrag")] internal class InventoryGui_UpdateItemDrag { [HarmonyTranspiler] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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++) { CodeInstruction obj = list[i - 1]; CodeInstruction val = list[i]; if (obj.opcode == OpCodes.Ldc_I4_1 && val.opcode == OpCodes.Call && val.operand == method) { list[i - 1] = new CodeInstruction(OpCodes.Nop, (object)null); list[i] = new CodeInstruction(OpCodes.Ldc_I4_S, (object)(sbyte)0); } } return list; } } internal class Utils { public static bool placingOneFromDrag; 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0061: 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) if (inventory == null || item == null || item.m_stack < 2 || !inventory.HaveEmptySlot()) { return false; } object obj = Reflect.Call(inventory, "FindEmptySlot", true); if (obj == null) { return false; } Vector2i val = (Vector2i)obj; if (val.x < 0 || val.y < 0) { return false; } int num = item.m_stack / 2; return inventory.MoveItemToThis(inventory, item, num, val.x, val.y); } public static bool PlaceOneFromDrag(InventoryGui gui, InventoryGrid grid, ItemData dragItem, ItemData clickedItem, Vector2i pos) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gui == (Object)null || (Object)(object)grid == (Object)null || dragItem == null || pos.x < 0 || pos.y < 0) { return false; } placingOneFromDrag = true; try { Reflect.Set(gui, "m_dragAmount", 1); Reflect.CallWithTypes(gui, "OnSelectedItem", new Type[4] { typeof(InventoryGrid), typeof(ItemData), typeof(Vector2i), typeof(Modifier) }, grid, clickedItem, pos, (object)(Modifier)0); } catch (Exception ex) { Debug.LogWarning((object)("DropSingleItem: place-one failed: " + ex)); return false; } finally { placingOneFromDrag = false; } return true; } public static bool PlaceHalfFromDrag(InventoryGui gui, InventoryGrid grid, Vector2i pos) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gui == (Object)null || (Object)(object)grid == (Object)null || pos.x < 0 || pos.y < 0 || (Object)(object)gui.dragGo() == (Object)null) { return false; } ItemData val = gui.dragItem(); Inventory val2 = gui.dragInventory(); Inventory inventory = grid.GetInventory(); if (val == null || val2 == null || inventory == null) { return false; } int num = gui.dragAmount(); int num2 = num / 2; if (num2 < 1) { num2 = 1; } int stack = val.m_stack; if (!inventory.MoveItemToThis(val2, val, num2, pos.x, pos.y)) { return false; } num -= stack - val.m_stack; if (num > 0 && val2.ContainsItem(val)) { gui.SetupDragItem(val, val2, num); } else { gui.SetupDragItem(null, null, 1); } gui.UpdateCraftingPanel(); return true; } public static void MergeMatchingIntoSlot(InventoryGui gui, Inventory targetInventory, ItemData target) { if (!((Object)(object)gui == (Object)null) && targetInventory != null && target != null && target.m_shared != null && !((Object)(object)Player.m_localPlayer == (Object)null) && !placingOneFromDrag && target.m_stack < target.m_shared.m_maxStackSize && target.m_shared.m_maxStackSize > 1) { 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); } if (target.m_stack > 0) { gui.SetupDragItem(target, targetInventory, target.m_stack); } 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); int maxStackSize = target.m_shared.m_maxStackSize; for (int num = list.Count - 1; num >= 0; num--) { ItemData val = list[num]; if (val != null && val.m_stack < maxStackSize && CanStackItem(target, val)) { targetInventory.MoveItemToThis(source, val, val.m_stack, target.m_gridPos.x, target.m_gridPos.y); if (target.m_stack >= maxStackSize) { return; } } } for (int num2 = list.Count - 1; num2 >= 0; num2--) { ItemData val2 = list[num2]; if (val2 != null && val2.m_stack >= maxStackSize && CanStackItem(target, val2)) { targetInventory.MoveItemToThis(source, val2, val2.m_stack, target.m_gridPos.x, target.m_gridPos.y); if (target.m_stack >= maxStackSize) { break; } } } } 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_001e: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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 = ((!(transform is RectTransform)) ? ((RectTransform)null) : ((RectTransform)transform)); 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) { DropOutsideAmount(gui, 1); } public static void DropHalfOutside(InventoryGui gui) { int num = gui.dragAmount() / 2; if (num < 1) { num = 1; } DropOutsideAmount(gui, num); } public static void DropOutsideAmount(InventoryGui gui, int dropAmount) { 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, dropAmount)) { 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) { Reflect.CallWithTypes(instance, "SetupDragItem", new Type[3] { typeof(ItemData), typeof(Inventory), typeof(int) }, item, inventory, amount); } public static void UpdateCraftingPanel(this InventoryGui instance, bool focusView = false) { Reflect.Call(instance, "UpdateCraftingPanel", focusView); } public static void OnSelectedItem(this InventoryGui instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) Reflect.CallWithTypes(instance, "OnSelectedItem", new Type[4] { typeof(InventoryGrid), typeof(ItemData), typeof(Vector2i), typeof(Modifier) }, grid, item, pos, mod); } public static EffectList moveItemEffects(this InventoryGui instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (EffectList)Reflect.Get(instance, "m_moveItemEffects"); } public static GameObject dragGo(this InventoryGui instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (GameObject)Reflect.Get(instance, "m_dragGo"); } public static ItemData dragItem(this InventoryGui instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (ItemData)Reflect.Get(instance, "m_dragItem"); } public static Inventory dragInventory(this InventoryGui instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (Inventory)Reflect.Get(instance, "m_dragInventory"); } public static int dragAmount(this InventoryGui instance) { object obj = Reflect.Get(instance, "m_dragAmount"); if (obj is int) { return (int)obj; } return 0; } public static Container currentContainer(this InventoryGui instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (Container)Reflect.Get(instance, "m_currentContainer"); } public static InventoryGrid playerGrid(this InventoryGui instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (InventoryGrid)Reflect.Get(instance, "m_playerGrid"); } public static InventoryGrid containerGrid(this InventoryGui instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (InventoryGrid)Reflect.Get(instance, "m_containerGrid"); } } }