From 9abbef35ae6582c7c3dbfd60ea0881ec83d4cadb Mon Sep 17 00:00:00 2001 From: themode Date: Sat, 3 Apr 2021 00:03:36 +0200 Subject: [PATCH] Reduce code duplication --- .../minestom/server/inventory/Inventory.java | 33 ++++--------- .../server/inventory/InventoryModifier.java | 47 ++++++++++++++++++- .../server/inventory/PlayerInventory.java | 36 +++++--------- .../net/minestom/server/item/ItemStack.java | 2 +- 4 files changed, 66 insertions(+), 52 deletions(-) diff --git a/src/main/java/net/minestom/server/inventory/Inventory.java b/src/main/java/net/minestom/server/inventory/Inventory.java index 01286835c..3d7dce6cd 100644 --- a/src/main/java/net/minestom/server/inventory/Inventory.java +++ b/src/main/java/net/minestom/server/inventory/Inventory.java @@ -10,7 +10,6 @@ import net.minestom.server.inventory.click.InventoryClickProcessor; import net.minestom.server.inventory.click.InventoryClickResult; import net.minestom.server.inventory.condition.InventoryCondition; import net.minestom.server.item.ItemStack; -import net.minestom.server.item.StackingRule; import net.minestom.server.network.packet.server.play.OpenWindowPacket; import net.minestom.server.network.packet.server.play.SetSlotPacket; import net.minestom.server.network.packet.server.play.WindowItemsPacket; @@ -149,30 +148,14 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View @Override public synchronized boolean addItemStack(@NotNull ItemStack itemStack) { - final StackingRule stackingRule = itemStack.getStackingRule(); - for (int i = 0; i < getSize(); i++) { - ItemStack item = getItemStack(i); - final StackingRule itemStackingRule = item.getStackingRule(); - if (itemStackingRule.canBeStacked(itemStack, item)) { - final int itemAmount = itemStackingRule.getAmount(item); - if (itemAmount == stackingRule.getMaxSize()) - continue; - final int itemStackAmount = itemStackingRule.getAmount(itemStack); - final int totalAmount = itemStackAmount + itemAmount; - if (!stackingRule.canApply(itemStack, totalAmount)) { - item = itemStackingRule.apply(item, itemStackingRule.getMaxSize()); - setItemStack(i, item); - itemStack = stackingRule.apply(itemStack, totalAmount - stackingRule.getMaxSize()); - } else { - setItemStack(i, item.withAmount(totalAmount)); - return true; - } - } else if (item.isAir()) { - setItemStack(i, itemStack); - return true; - } - } - return false; + // Make the method synchronized + return InventoryModifier.super.addItemStack(itemStack); + } + + @Override + public synchronized boolean addItemStack(@NotNull ItemStack itemStack, int startSlot, int endSlot) { + // Make the method synchronized + return InventoryModifier.super.addItemStack(itemStack, startSlot, endSlot); } @Override diff --git a/src/main/java/net/minestom/server/inventory/InventoryModifier.java b/src/main/java/net/minestom/server/inventory/InventoryModifier.java index aec831624..7b90a63e5 100644 --- a/src/main/java/net/minestom/server/inventory/InventoryModifier.java +++ b/src/main/java/net/minestom/server/inventory/InventoryModifier.java @@ -1,7 +1,10 @@ package net.minestom.server.inventory; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minestom.server.inventory.condition.InventoryCondition; import net.minestom.server.item.ItemStack; +import net.minestom.server.item.StackingRule; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; @@ -28,7 +31,49 @@ public interface InventoryModifier { * @param itemStack the item to add * @return true if the item has been successfully fully added, false otherwise */ - boolean addItemStack(@NotNull ItemStack itemStack); + default boolean addItemStack(@NotNull ItemStack itemStack) { + return addItemStack(itemStack, 0, getSize()); + } + + default boolean addItemStack(@NotNull ItemStack itemStack, int startSlot, int endSlot) { + Int2ObjectMap itemChangesMap = new Int2ObjectOpenHashMap<>(); + + final StackingRule stackingRule = itemStack.getStackingRule(); + for (int i = startSlot; i < endSlot; i++) { + ItemStack inventoryItem = getItemStack(i); + if (stackingRule.canBeStacked(itemStack, inventoryItem)) { + final int itemAmount = stackingRule.getAmount(inventoryItem); + if (itemAmount == stackingRule.getMaxSize()) + continue; + final int itemStackAmount = stackingRule.getAmount(itemStack); + final int totalAmount = itemStackAmount + itemAmount; + if (!stackingRule.canApply(itemStack, totalAmount)) { + // Slot cannot accept the whole item, reduce amount to 'itemStack' + itemChangesMap.put(i, stackingRule.apply(inventoryItem, stackingRule.getMaxSize())); + itemStack = stackingRule.apply(itemStack, totalAmount - stackingRule.getMaxSize()); + } else { + // Slot can accept the whole item + itemChangesMap.put(i, inventoryItem.withAmount(totalAmount)); + itemStack = ItemStack.AIR; + break; + } + } else if (inventoryItem.isAir()) { + // Fill the slot + itemChangesMap.put(i, itemStack); + itemStack = ItemStack.AIR; + break; + } + } + + if (itemStack.isAir()) { + // Item can be fully placed inside the inventory, do so + itemChangesMap.forEach(this::setItemStack); + return true; + } else { + // Inventory cannot accept the item fully + return false; + } + } /** * Clears the inventory and send relevant update to the viewer(s). diff --git a/src/main/java/net/minestom/server/inventory/PlayerInventory.java b/src/main/java/net/minestom/server/inventory/PlayerInventory.java index 4204ff9fc..75bbcdbd6 100644 --- a/src/main/java/net/minestom/server/inventory/PlayerInventory.java +++ b/src/main/java/net/minestom/server/inventory/PlayerInventory.java @@ -12,7 +12,6 @@ import net.minestom.server.inventory.click.InventoryClickProcessor; import net.minestom.server.inventory.click.InventoryClickResult; import net.minestom.server.inventory.condition.InventoryCondition; import net.minestom.server.item.ItemStack; -import net.minestom.server.item.StackingRule; import net.minestom.server.network.packet.server.play.EntityEquipmentPacket; import net.minestom.server.network.packet.server.play.SetSlotPacket; import net.minestom.server.network.packet.server.play.WindowItemsPacket; @@ -93,31 +92,18 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler return false; itemStack = addItemStackEvent.getItemStack(); + return InventoryModifier.super.addItemStack(itemStack, 0, getSize() - 10); + } - final StackingRule stackingRule = itemStack.getStackingRule(); - for (int i = 0; i < items.length - 10; i++) { - ItemStack item = items[i]; - final StackingRule itemStackingRule = item.getStackingRule(); - if (itemStackingRule.canBeStacked(itemStack, item)) { - final int itemAmount = itemStackingRule.getAmount(item); - if (itemAmount == stackingRule.getMaxSize()) - continue; - final int itemStackAmount = itemStackingRule.getAmount(itemStack); - final int totalAmount = itemStackAmount + itemAmount; - if (!stackingRule.canApply(itemStack, totalAmount)) { - item = itemStackingRule.apply(item, itemStackingRule.getMaxSize()); - setItemStack(i, item); - itemStack = stackingRule.apply(itemStack, totalAmount - stackingRule.getMaxSize()); - } else { - setItemStack(i, item.withAmount(totalAmount)); - return true; - } - } else if (item.isAir()) { - safeItemInsert(i, itemStack); - return true; - } - } - return false; + @Override + public synchronized boolean addItemStack(@NotNull ItemStack itemStack, int startSlot, int endSlot) { + PlayerAddItemStackEvent addItemStackEvent = new PlayerAddItemStackEvent(player, itemStack); + player.callEvent(PlayerAddItemStackEvent.class, addItemStackEvent); + if (addItemStackEvent.isCancelled()) + return false; + + itemStack = addItemStackEvent.getItemStack(); + return InventoryModifier.super.addItemStack(itemStack, startSlot, endSlot); } @Override diff --git a/src/main/java/net/minestom/server/item/ItemStack.java b/src/main/java/net/minestom/server/item/ItemStack.java index d8ecf9954..a8a2dd7fe 100644 --- a/src/main/java/net/minestom/server/item/ItemStack.java +++ b/src/main/java/net/minestom/server/item/ItemStack.java @@ -128,7 +128,7 @@ public class ItemStack { @Contract(pure = true) public boolean isAir() { - return equals(AIR); + return material.equals(Material.AIR); } @Contract(pure = true)