From 2773a2d46ce01973ac280191245f7e32e25a1c56 Mon Sep 17 00:00:00 2001 From: TheMode Date: Fri, 23 Apr 2021 15:02:39 +0200 Subject: [PATCH] Make StackingRule an interface, support per item max size, fix double click stacking --- .../server/inventory/TransactionType.java | 9 ++++--- .../click/InventoryClickProcessor.java | 25 ++++++++++++++----- .../net/minestom/server/item/ItemStack.java | 3 +-- .../server/item/ItemStackBuilder.java | 7 +++--- .../minestom/server/item/StackingRule.java | 25 +++++++------------ .../server/item/rule/VanillaStackingRule.java | 23 ++++++++--------- 6 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/main/java/net/minestom/server/inventory/TransactionType.java b/src/main/java/net/minestom/server/inventory/TransactionType.java index 8cdf04075..de332b637 100644 --- a/src/main/java/net/minestom/server/inventory/TransactionType.java +++ b/src/main/java/net/minestom/server/inventory/TransactionType.java @@ -32,7 +32,8 @@ public interface TransactionType { } if (stackingRule.canBeStacked(itemStack, inventoryItem)) { final int itemAmount = stackingRule.getAmount(inventoryItem); - if (itemAmount == stackingRule.getMaxSize()) + final int maxSize = stackingRule.getMaxSize(inventoryItem); + if (itemAmount == maxSize) continue; if (!slotPredicate.test(i, inventoryItem)) { @@ -44,8 +45,8 @@ public interface TransactionType { 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()); + itemChangesMap.put(i, stackingRule.apply(inventoryItem, maxSize)); + itemStack = stackingRule.apply(itemStack, totalAmount - maxSize); } else { // Slot can accept the whole item itemChangesMap.put(i, stackingRule.apply(inventoryItem, totalAmount)); @@ -97,10 +98,12 @@ public interface TransactionType { final int itemAmount = stackingRule.getAmount(inventoryItem); final int itemStackAmount = stackingRule.getAmount(itemStack); if (itemStackAmount < itemAmount) { + System.out.println(1); itemChangesMap.put(i, stackingRule.apply(inventoryItem, itemAmount - itemStackAmount)); itemStack = stackingRule.apply(itemStack, 0); break; } + System.out.println(2); itemChangesMap.put(i, stackingRule.apply(inventoryItem, 0)); itemStack = stackingRule.apply(itemStack, itemStackAmount - itemAmount); if (stackingRule.getAmount(itemStack) == 0) { diff --git a/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java b/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java index 36665b092..80ce319e2 100644 --- a/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java +++ b/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java @@ -57,10 +57,11 @@ public class InventoryClickProcessor { if (cursorRule.canBeStacked(cursor, clicked)) { final int totalAmount = cursorRule.getAmount(cursor) + clickedRule.getAmount(clicked); + final int maxSize = cursorRule.getMaxSize(cursor); if (!clickedRule.canApply(clicked, totalAmount)) { - resultCursor = cursorRule.apply(cursor, totalAmount - cursorRule.getMaxSize()); - resultClicked = clickedRule.apply(clicked, clickedRule.getMaxSize()); + resultCursor = cursorRule.apply(cursor, totalAmount - maxSize); + resultClicked = clickedRule.apply(clicked, maxSize); } else { resultCursor = cursorRule.apply(cursor, 0); resultClicked = clickedRule.apply(clicked, totalAmount); @@ -256,7 +257,7 @@ public class InventoryClickProcessor { break; StackingRule slotItemRule = slotItem.getStackingRule(); - final int maxSize = stackingRule.getMaxSize(); + final int maxSize = stackingRule.getMaxSize(cursor); if (stackingRule.canBeStacked(cursor, slotItem)) { final int amount = slotItemRule.getAmount(slotItem); if (stackingRule.canApply(slotItem, amount + slotSize)) { @@ -351,7 +352,13 @@ public class InventoryClickProcessor { final StackingRule cursorRule = cursor.getStackingRule(); final int amount = cursorRule.getAmount(cursor); - final int remainingAmount = cursorRule.getMaxSize() - amount; + final int maxSize = cursorRule.getMaxSize(cursor); + final int remainingAmount = maxSize - amount; + + if (remainingAmount == 0) { + // Item is already full + return clickResult; + } ItemStack remain = cursorRule.apply(cursor, remainingAmount); @@ -386,9 +393,15 @@ public class InventoryClickProcessor { remain = func.apply(playerInventory, remain); } - final int tookAmount = remainingAmount - cursorRule.getAmount(remain); + ItemStack resultCursor; + if (remain.isAir()) { + // Item has been filled + resultCursor = cursorRule.apply(cursor, maxSize); + } else { + final int tookAmount = remainingAmount - cursorRule.getAmount(remain); + resultCursor = cursorRule.apply(cursor, amount + tookAmount); + } - ItemStack resultCursor = cursorRule.apply(cursor, amount + tookAmount); clickResult.setCursor(resultCursor); return clickResult; } diff --git a/src/main/java/net/minestom/server/item/ItemStack.java b/src/main/java/net/minestom/server/item/ItemStack.java index 5dc9b99d1..f1e1b7f7b 100644 --- a/src/main/java/net/minestom/server/item/ItemStack.java +++ b/src/main/java/net/minestom/server/item/ItemStack.java @@ -41,8 +41,7 @@ public final class ItemStack implements HoverEventSource { this.material = material; this.amount = amount; this.meta = meta; - this.stackingRule = Objects.requireNonNullElseGet(stackingRule, - () -> new VanillaStackingRule(64)); + this.stackingRule = Objects.requireNonNullElseGet(stackingRule, VanillaStackingRule::new); } @Contract(value = "_ -> new", pure = true) diff --git a/src/main/java/net/minestom/server/item/ItemStackBuilder.java b/src/main/java/net/minestom/server/item/ItemStackBuilder.java index b14a03aec..12b0b8a3a 100644 --- a/src/main/java/net/minestom/server/item/ItemStackBuilder.java +++ b/src/main/java/net/minestom/server/item/ItemStackBuilder.java @@ -109,10 +109,9 @@ public class ItemStackBuilder { @Contract(value = "-> new", pure = true) public @NotNull ItemStack build() { - if (amount <= 0) - return ItemStack.AIR; - - return new ItemStack(material, amount, metaBuilder.build(), stackingRule); + if (amount > 0) + return new ItemStack(material, amount, metaBuilder.build(), stackingRule); + return ItemStack.AIR; } private static final class DefaultMeta extends ItemMetaBuilder { diff --git a/src/main/java/net/minestom/server/item/StackingRule.java b/src/main/java/net/minestom/server/item/StackingRule.java index 68c22862e..2f216c497 100644 --- a/src/main/java/net/minestom/server/item/StackingRule.java +++ b/src/main/java/net/minestom/server/item/StackingRule.java @@ -10,13 +10,7 @@ import java.util.function.IntUnaryOperator; * This can be used to mimic the vanilla one (using the displayed item quantity) * or a complete new one which can be stored in lore, name, etc... */ -public abstract class StackingRule { - - private final int maxSize; - - public StackingRule(int maxSize) { - this.maxSize = maxSize; - } +public interface StackingRule { /** * Used to know if two {@link ItemStack} can be stacked together. @@ -26,16 +20,16 @@ public abstract class StackingRule { * @return true if both {@link ItemStack} can be stacked together * (without taking their amount in consideration) */ - public abstract boolean canBeStacked(@NotNull ItemStack item1, @NotNull ItemStack item2); + boolean canBeStacked(@NotNull ItemStack item1, @NotNull ItemStack item2); /** * Used to know if an {@link ItemStack} can have the size {@code newAmount} applied. * * @param item the {@link ItemStack} to check - * @param newAmount the desired new amount + * @param amount the desired new amount * @return true if {@code item} can have its stack size set to newAmount */ - public abstract boolean canApply(@NotNull ItemStack item, int newAmount); + boolean canApply(@NotNull ItemStack item, int amount); /** * Changes the size of the {@link ItemStack} to {@code newAmount}. @@ -46,10 +40,10 @@ public abstract class StackingRule { * @return a new {@link ItemStack item} with the specified amount */ @Contract("_, _ -> new") - public abstract @NotNull ItemStack apply(@NotNull ItemStack item, int newAmount); + @NotNull ItemStack apply(@NotNull ItemStack item, int newAmount); @Contract("_, _ -> new") - public @NotNull ItemStack apply(@NotNull ItemStack item, @NotNull IntUnaryOperator amountOperator) { + default @NotNull ItemStack apply(@NotNull ItemStack item, @NotNull IntUnaryOperator amountOperator) { return apply(item, amountOperator.applyAsInt(getAmount(item))); } @@ -60,14 +54,13 @@ public abstract class StackingRule { * @param itemStack the {@link ItemStack} to check the size * @return the correct size of {@link ItemStack} */ - public abstract int getAmount(@NotNull ItemStack itemStack); + int getAmount(@NotNull ItemStack itemStack); /** * Gets the max size of a stack. * + * @param itemStack the item to get the max size from * @return the max size of a stack */ - public int getMaxSize() { - return maxSize; - } + int getMaxSize(@NotNull ItemStack itemStack); } diff --git a/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java b/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java index 7edbf6a2a..9e6b41272 100644 --- a/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java +++ b/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java @@ -5,11 +5,7 @@ import net.minestom.server.item.StackingRule; import net.minestom.server.utils.MathUtils; import org.jetbrains.annotations.NotNull; -public class VanillaStackingRule extends StackingRule { - - public VanillaStackingRule(int maxSize) { - super(maxSize); - } +public class VanillaStackingRule implements StackingRule { @Override public boolean canBeStacked(@NotNull ItemStack item1, @NotNull ItemStack item2) { @@ -18,20 +14,23 @@ public class VanillaStackingRule extends StackingRule { @Override public boolean canApply(@NotNull ItemStack item, int newAmount) { - return MathUtils.isBetween(newAmount, 0, getMaxSize()); + return MathUtils.isBetween(newAmount, 0, getMaxSize(item)); } - @NotNull @Override - public ItemStack apply(@NotNull ItemStack item, int newAmount) { - if (newAmount <= 0) - return ItemStack.AIR; - - return item.withAmount(newAmount); + public @NotNull ItemStack apply(@NotNull ItemStack item, int amount) { + if (amount > 0) + return item.withAmount(amount); + return ItemStack.AIR; } @Override public int getAmount(@NotNull ItemStack itemStack) { return itemStack.getAmount(); } + + @Override + public int getMaxSize(@NotNull ItemStack itemStack) { + return itemStack.getMaterial().getMaxDefaultStackSize(); + } }