Make StackingRule an interface, support per item max size, fix double click stacking

This commit is contained in:
TheMode 2021-04-23 15:02:39 +02:00
parent f432308197
commit 2773a2d46c
6 changed files with 49 additions and 43 deletions

View File

@ -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) {

View File

@ -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;
}

View File

@ -41,8 +41,7 @@ public final class ItemStack implements HoverEventSource<HoverEvent.ShowItem> {
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)

View File

@ -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 {

View File

@ -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);
}

View File

@ -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();
}
}