diff --git a/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStack.java b/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStack.java index fe86304..78e2b1d 100644 --- a/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStack.java +++ b/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStack.java @@ -15,6 +15,7 @@ public class InfStack { private final ItemStack comparator; private final InfStackSettings settings; private long stackSize; + private boolean manualUpdate; /** * Creates a new InfStack from the following data @@ -29,6 +30,32 @@ public class InfStack { this.comparator = comparator.clone(); this.settings = settings; this.stackSize = stackSize; + this.manualUpdate = settings.defaultManual(); + } + + /** + * Stores as much of the given ItemStack as possible + * + * @param item the item to try to fit + * @return the remaining item that was able to fit, or the same item stack if it could not fit at all + */ + public ItemStack fit(final ItemStack item) { + if (!isAir()) { + return item; + } + if (!this.comparator.isSimilar(item)) { + return item; + } + + final int amount = item.getAmount(); + int remaining = (int) fit(amount); + if (remaining == 0) { + return ItemStack.empty(); + } + + final ItemStack clone = item.clone(); + clone.setAmount(remaining); + return clone; } /** @@ -74,6 +101,27 @@ public ItemStack extract(int amount) { return extracted; } + /** + * Fits as much of the specified amount into the stack as possible + * and returns a long in the amount that could not fit + * + * @param amount the amount to try to fit into this stack + * @return the amount unable to fit + */ + public long fit(final long amount) { + if (isAir() || isEmpty()) { + return amount; + } + long potentialTotal = this.stackSize + amount; + long amountToAdd = amount; + if (potentialTotal > this.settings.maxStackSize()) { + amountToAdd = this.settings.maxStackSize() - this.stackSize; + } + this.stackSize += amountToAdd; + update(false); + return amount - amountToAdd; + } + /** * Grows the stack by a specified amount * @@ -90,7 +138,7 @@ public boolean grow(final long amount) { } this.stackSize = finalAmount; - update(); + update(false); return true; } @@ -110,11 +158,19 @@ public boolean shrink(final long amount) { } this.stackSize = finalAmount; - update(); + update(false); return true; } - private void update() { + public void update() { + update(true); + } + + private void update(boolean force) { + if (this.manualUpdate && !force) { + return; + } + this.display = this.settings.loreApplier() .apply(this.settings.lore(), this.stackSize, this.display, this.comparator, true); @@ -125,6 +181,15 @@ private void update() { this.display.setItemMeta(meta); } + /** + * Toggle whether or not this InfStack should be manually updated + * + * @param manualUpdate true to make it manual update only, otherwise false to toggle automatic updates + */ + public void manualUpdates(boolean manualUpdate) { + this.manualUpdate = manualUpdate; + } + /** * Checks if another item stack is similar to this InfStack * @@ -180,5 +245,4 @@ public ItemStack getComparator() { return this.comparator.clone(); } - } diff --git a/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStackSettings.java b/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStackSettings.java index 4be698f..64bf823 100644 --- a/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStackSettings.java +++ b/pineapple-apis/pineapple-infstack/src/main/java/sh/miles/pineapple/api/infstacks/InfStackSettings.java @@ -10,13 +10,14 @@ /** * Settings for {@link InfStack} * - * @param lore the lore style - * @param maxStackSize the max stack size - * @param loreApplier should apply lore using the pineapple component and returns a modified ItemStack + * @param lore the lore style + * @param maxStackSize the max stack size + * @param defaultManual true if by default all InfStacks are updated manually instead of automatically via their respective methods + * @param loreApplier should apply lore using the pineapple component and returns a modified ItemStack */ @NullMarked public record InfStackSettings(List lore, long maxStackSize, - LoreApplier loreApplier) { + boolean defaultManual, LoreApplier loreApplier) { public interface LoreApplier { @NotNull diff --git a/pineapple-apis/pineapple-infstack/src/test/java/sh/miles/pineapple/api/infstacks/InfStackFactoryTest.java b/pineapple-apis/pineapple-infstack/src/test/java/sh/miles/pineapple/api/infstacks/InfStackFactoryTest.java index f74b5aa..b760c4b 100644 --- a/pineapple-apis/pineapple-infstack/src/test/java/sh/miles/pineapple/api/infstacks/InfStackFactoryTest.java +++ b/pineapple-apis/pineapple-infstack/src/test/java/sh/miles/pineapple/api/infstacks/InfStackFactoryTest.java @@ -20,7 +20,7 @@ public class InfStackFactoryTest extends AbstractPluginTest { @BeforeEach public void setup() { super.setup(); - this.factory = new InfStackFactory(new InfStackSettings(List.of(PineappleChat.component("Amount %s")), Long.MAX_VALUE, + this.factory = new InfStackFactory(new InfStackSettings(List.of(PineappleChat.component("Amount %s")), Long.MAX_VALUE, false, (lore, amount, item, display, removeOldLore) -> { final ItemMeta meta = item.getItemMeta(); final var list = new ArrayList();