From d4b127244e95e617b488bc18f8ec71df108d62df Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Thu, 21 Mar 2019 01:44:33 +0100 Subject: [PATCH] Disable tool on drop: Only cancel dropping if there is space for that item --- .../LogBlock/listeners/ToolListener.java | 6 +- src/main/java/de/diddiz/util/BukkitUtils.java | 64 +++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java b/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java index 9c680e7..342eb39 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java @@ -116,8 +116,8 @@ public class ToolListener implements Listener { if (item == tool.item && toolData.enabled) { if (tool.dropToDisable) { toolData.enabled = false; + ItemStack stack = event.getItemDrop().getItemStack(); if (tool.removeOnDisable && logblock.hasPermission(player, "logblock.spawnTools")) { - ItemStack stack = event.getItemDrop().getItemStack(); if (stack.isSimilar(new ItemStack(item))) { if (stack.getAmount() > 1) { stack.setAmount(stack.getAmount() - 1); @@ -127,7 +127,9 @@ public class ToolListener implements Listener { } } } - event.setCancelled(true); + if (BukkitUtils.hasInventoryStorageSpaceFor(player.getInventory(), stack)) { + event.setCancelled(true); + } player.sendMessage(ChatColor.GREEN + "Tool disabled."); } else if (!tool.canDrop) { player.sendMessage(ChatColor.RED + "You cannot drop this tool."); diff --git a/src/main/java/de/diddiz/util/BukkitUtils.java b/src/main/java/de/diddiz/util/BukkitUtils.java index 5cf05aa..baebf31 100644 --- a/src/main/java/de/diddiz/util/BukkitUtils.java +++ b/src/main/java/de/diddiz/util/BukkitUtils.java @@ -829,4 +829,68 @@ public class BukkitUtils { stand.getEquipment().setHelmet(stack); } } + + public static ItemStack[] deepCopy(ItemStack[] of) { + ItemStack[] result = new ItemStack[of.length]; + for (int i = 0; i < result.length; i++) { + result[i] = of[i] == null ? null : new ItemStack(of[i]); + } + return result; + } + + private static int getFirstPartialItemStack(ItemStack item, ItemStack[] contents, int start) { + for (int i = start; i < contents.length; i++) { + ItemStack content = contents[i]; + if (content != null && content.isSimilar(item) && content.getAmount() < content.getMaxStackSize()) { + return i; + } + } + return -1; + } + + private static int getFirstFreeItemStack(ItemStack[] contents, int start) { + for (int i = start; i < contents.length; i++) { + ItemStack content = contents[i]; + if (content == null || content.getAmount() == 0 || content.getType() == Material.AIR) { + return i; + } + } + return -1; + } + + public static boolean hasInventoryStorageSpaceFor(Inventory inv, ItemStack... items) { + ItemStack[] contents = deepCopy(inv.getStorageContents()); + for (ItemStack item : items) { + if (item != null && item.getType() != Material.AIR) { + int remaining = item.getAmount(); + // fill partial stacks + int firstPartial = -1; + while (remaining > 0) { + firstPartial = getFirstPartialItemStack(item, contents, firstPartial + 1); + if (firstPartial < 0) { + break; + } + ItemStack content = contents[firstPartial]; + int add = Math.min(content.getMaxStackSize() - content.getAmount(), remaining); + content.setAmount(content.getAmount() + add); + remaining -= add; + } + // create new stacks + int firstFree = -1; + while (remaining > 0) { + firstFree = getFirstFreeItemStack(contents, firstFree + 1); + if (firstFree < 0) { + return false; // no free place found + } + ItemStack content = new ItemStack(item); + contents[firstFree] = content; + // max stack size might return -1, in this case assume 1 + int add = Math.min(Math.max(content.getMaxStackSize(), 1), remaining); + content.setAmount(add); + remaining -= add; + } + } + } + return true; + } }