From ff4580c41ba2c87a5ce46bbc3fe59d7f89f1a05d Mon Sep 17 00:00:00 2001 From: Felix Cravic Date: Mon, 7 Dec 2020 23:57:57 +0100 Subject: [PATCH] Prevent unnecessary item copy during drop --- .../instance/palette/PaletteStorage.java | 6 ++-- .../net/minestom/server/item/ItemStack.java | 30 ++++++++++--------- .../listener/PlayerDiggingListener.java | 25 +++++++++++----- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java b/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java index bd4951aef..8d4dd6a6f 100644 --- a/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java +++ b/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java @@ -254,14 +254,13 @@ public class PaletteStorage { 8191, 16383, 32767}; private static void setBlockAt(@NotNull PaletteStorage paletteStorage, int x, int y, int z, short blockId) { - if (y < 0 || y >= Chunk.CHUNK_SIZE_Y) { + if (!MathUtils.isBetween(y, 0, Chunk.CHUNK_SIZE_Y)) { return; } final int section = ChunkUtils.getSectionAt(y); final int valuesPerLong = paletteStorage.valuesPerLong; - final int bitsPerEntry = paletteStorage.bitsPerEntry; if (paletteStorage.sectionBlocks[section].length == 0) { if (blockId == 0) { @@ -273,6 +272,7 @@ public class PaletteStorage { paletteStorage.sectionBlocks[section] = new long[getSize(valuesPerLong)]; } + // Convert world coordinates to chunk coordinates x = toChunkCoordinate(x); z = toChunkCoordinate(z); @@ -282,6 +282,8 @@ public class PaletteStorage { final int sectionIndex = getSectionIndex(x, y, z); final int index = sectionIndex / valuesPerLong; + final int bitsPerEntry = paletteStorage.bitsPerEntry; + final int bitIndex = (sectionIndex % valuesPerLong) * bitsPerEntry; final long[] sectionBlock = paletteStorage.sectionBlocks[section]; diff --git a/src/main/java/net/minestom/server/item/ItemStack.java b/src/main/java/net/minestom/server/item/ItemStack.java index 55a0ab2b0..b917144af 100644 --- a/src/main/java/net/minestom/server/item/ItemStack.java +++ b/src/main/java/net/minestom/server/item/ItemStack.java @@ -51,19 +51,6 @@ public class ItemStack implements DataContainer { private byte amount; private int damage; - public ItemStack(@NotNull Material material, byte amount, int damage) { - this.identifier = DATA_OWNERSHIP.generateIdentifier(); - this.material = material; - this.amount = amount; - this.damage = damage; - this.lore = new ArrayList<>(); - - this.enchantmentMap = new HashMap<>(); - this.attributes = new ArrayList<>(); - - this.itemMeta = findMeta(); - } - private ColoredText displayName; private boolean unbreakable; private ArrayList lore; @@ -83,6 +70,19 @@ public class ItemStack implements DataContainer { this.stackingRule = defaultStackingRule; } + public ItemStack(@NotNull Material material, byte amount, int damage) { + this.identifier = DATA_OWNERSHIP.generateIdentifier(); + this.material = material; + this.amount = amount; + this.damage = damage; + this.lore = new ArrayList<>(); + + this.enchantmentMap = new HashMap<>(); + this.attributes = new ArrayList<>(); + + this.itemMeta = findMeta(); + } + public ItemStack(@NotNull Material material, byte amount) { this(material, amount, (short) 0); } @@ -552,8 +552,10 @@ public class ItemStack implements DataContainer { /** * Copies this item stack. + *

+ * Be aware that the identifier ({@link #getIdentifier()}) will change. * - * @return a cloned item stack + * @return a cloned item stack with a different identifier */ @NotNull public synchronized ItemStack copy() { diff --git a/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java b/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java index ddfe02b28..f9cf227b9 100644 --- a/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java +++ b/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java @@ -92,19 +92,30 @@ public class PlayerDiggingListener { } break; case DROP_ITEM_STACK: - final ItemStack droppedItemStack = player.getInventory().getItemInMainHand().copy(); + final ItemStack droppedItemStack = player.getInventory().getItemInMainHand(); dropItem(player, droppedItemStack, ItemStack.getAirItem()); break; case DROP_ITEM: - ItemStack handItem = player.getInventory().getItemInMainHand().copy(); - ItemStack droppedItemStack2 = handItem.copy(); - final StackingRule handStackingRule = handItem.getStackingRule(); + final int dropAmount = 1; - droppedItemStack2 = handStackingRule.apply(droppedItemStack2, 1); + ItemStack handItem = player.getInventory().getItemInMainHand(); + final StackingRule stackingRule = handItem.getStackingRule(); + final int handAmount = stackingRule.getAmount(handItem); - handItem = handStackingRule.apply(handItem, handStackingRule.getAmount(handItem) - 1); + if (handAmount == dropAmount) { + // Drop the whole item without copy + dropItem(player, handItem, ItemStack.getAirItem()); + } else { + // Drop a single item, need a copy + ItemStack droppedItemStack2 = handItem.copy(); - dropItem(player, droppedItemStack2, handItem); + droppedItemStack2 = stackingRule.apply(droppedItemStack2, dropAmount); + + handItem = handItem.copy(); // Force the copy + handItem = stackingRule.apply(handItem, handAmount - dropAmount); + + dropItem(player, droppedItemStack2, handItem); + } break; case UPDATE_ITEM_STATE: player.refreshEating(false);