From be07fdb6470b4c0f2835362ab70f3ea80c092be6 Mon Sep 17 00:00:00 2001 From: TheMode Date: Wed, 11 Aug 2021 20:35:30 +0200 Subject: [PATCH] Simplify InventoryClickProcessor --- .../click/InventoryClickProcessor.java | 281 ++++++------------ 1 file changed, 96 insertions(+), 185 deletions(-) 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 bae89f770..57dec9420 100644 --- a/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java +++ b/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java @@ -20,7 +20,6 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -28,155 +27,103 @@ import java.util.function.BiConsumer; import java.util.function.BiFunction; @ApiStatus.Internal -public class InventoryClickProcessor { - +public final class InventoryClickProcessor { // Dragging maps private final Map leftDraggingMap = new ConcurrentHashMap<>(); private final Map rightDraggingMap = new ConcurrentHashMap<>(); - @NotNull - public InventoryClickResult leftClick(@Nullable Inventory inventory, @NotNull Player player, int slot, - @NotNull ItemStack clicked, @NotNull ItemStack cursor) { - final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.LEFT_CLICK, clicked, cursor); - clicked = clickResult.getClicked(); - cursor = clickResult.getCursor(); - - if (clickResult.isCancel()) { - return clickResult; - } - - if (cursor.isAir() && clicked.isAir()) { - clickResult.setCancel(true); - return clickResult; - } - + public @NotNull InventoryClickResult leftClick(@Nullable Inventory inventory, @NotNull Player player, int slot, + @NotNull ItemStack clicked, @NotNull ItemStack cursor) { + final var result = startCondition(inventory, player, slot, ClickType.LEFT_CLICK, clicked, cursor); + if (result.isCancel()) return result; + clicked = result.getClicked(); + cursor = result.getCursor(); final StackingRule cursorRule = cursor.getStackingRule(); final StackingRule clickedRule = clicked.getStackingRule(); - - ItemStack resultCursor; - ItemStack resultClicked; - if (cursorRule.canBeStacked(cursor, clicked)) { + // Try to stack items 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 - maxSize); - resultClicked = clickedRule.apply(clicked, maxSize); + // Size is too big, stack as much as possible into clicked + result.setCursor(cursorRule.apply(cursor, totalAmount - maxSize)); + result.setClicked(clickedRule.apply(clicked, maxSize)); } else { - resultCursor = cursorRule.apply(cursor, 0); - resultClicked = clickedRule.apply(clicked, totalAmount); + // Merge cursor item clicked + result.setCursor(cursorRule.apply(cursor, 0)); + result.setClicked(clickedRule.apply(clicked, totalAmount)); } } else { - resultCursor = clicked; - resultClicked = cursor; + // Items are not compatible, swap them + result.setCursor(clicked); + result.setClicked(cursor); } - - clickResult.setClicked(resultClicked); - clickResult.setCursor(resultCursor); - - return clickResult; + return result; } - @NotNull - public InventoryClickResult rightClick(@Nullable Inventory inventory, @NotNull Player player, int slot, - @NotNull ItemStack clicked, @NotNull ItemStack cursor) { - final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.RIGHT_CLICK, clicked, cursor); - - if (clickResult.isCancel()) { - return clickResult; - } - - if (cursor.isAir() && clicked.isAir()) { - clickResult.setCancel(true); - return clickResult; - } - + public @NotNull InventoryClickResult rightClick(@Nullable Inventory inventory, @NotNull Player player, + int slot, + @NotNull ItemStack clicked, @NotNull ItemStack cursor) { + final var result = startCondition(inventory, player, slot, ClickType.RIGHT_CLICK, clicked, cursor); + if (result.isCancel()) return result; + clicked = result.getClicked(); + cursor = result.getCursor(); final StackingRule cursorRule = cursor.getStackingRule(); final StackingRule clickedRule = clicked.getStackingRule(); - - ItemStack resultCursor; - ItemStack resultClicked; - if (clickedRule.canBeStacked(clicked, cursor)) { + // Items can be stacked final int amount = clickedRule.getAmount(clicked) + 1; if (!clickedRule.canApply(clicked, amount)) { - return clickResult; + // Size too large, stop here + return result; } else { - resultCursor = cursorRule.apply(cursor, operand -> operand - 1); - resultClicked = clickedRule.apply(clicked, amount); + // Add 1 to clicked + result.setCursor(cursorRule.apply(cursor, operand -> operand - 1)); + result.setClicked(clickedRule.apply(clicked, amount)); } } else { + // Items cannot be stacked if (cursor.isAir()) { + // Take half of clicked final int amount = (int) Math.ceil((double) clickedRule.getAmount(clicked) / 2d); - resultCursor = cursorRule.apply(clicked, amount); - resultClicked = clickedRule.apply(clicked, operand -> operand / 2); + result.setCursor(cursorRule.apply(clicked, amount)); + result.setClicked(clickedRule.apply(clicked, operand -> operand / 2)); } else { if (clicked.isAir()) { - resultCursor = cursorRule.apply(cursor, operand -> operand - 1); - resultClicked = clickedRule.apply(cursor, 1); + // Put 1 to clicked + result.setCursor(cursorRule.apply(cursor, operand -> operand - 1)); + result.setClicked(clickedRule.apply(cursor, 1)); } else { - resultCursor = clicked; - resultClicked = cursor; + // Swap items + result.setCursor(clicked); + result.setClicked(cursor); } } } - - clickResult.setClicked(resultClicked); - clickResult.setCursor(resultCursor); - - return clickResult; + return result; } - @NotNull - public InventoryClickResult changeHeld(@Nullable Inventory inventory, @NotNull Player player, int slot, int key, - @NotNull ItemStack clicked, @NotNull ItemStack cursor) { + public @NotNull InventoryClickResult changeHeld(@Nullable Inventory inventory, @NotNull Player player, + int slot, int key, + @NotNull ItemStack clicked, @NotNull ItemStack cursor) { // Verify the clicked item InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.CHANGE_HELD, clicked, cursor); if (clickResult.isCancel()) return clickResult; // Verify the destination (held bar) clickResult = startCondition(null, player, key, ClickType.CHANGE_HELD, clicked, cursor); if (clickResult.isCancel()) return clickResult; - - if (cursor.isAir() && clicked.isAir()) { - clickResult.setCancel(true); - return clickResult; - } - - ItemStack resultClicked; - ItemStack resultHeld; - if (clicked.isAir()) { - // Set held item [key] to slot - resultClicked = cursor; - resultHeld = ItemStack.AIR; - } else { - if (cursor.isAir()) { - // if held item [key] is air then set clicked to held - resultClicked = ItemStack.AIR; - } else { - // Otherwise, replace held item and held - resultClicked = cursor; - } - resultHeld = clicked; - } - - clickResult.setClicked(resultClicked); - clickResult.setCursor(resultHeld); + // Swap items + clickResult.setClicked(cursor); + clickResult.setCursor(clicked); return clickResult; } public @Nullable InventoryClickResult shiftClick(AbstractInventory targetInventory, @Nullable Inventory inventory, @NotNull Player player, int slot, @NotNull ItemStack clicked, @NotNull ItemStack cursor) { InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.START_SHIFT_CLICK, clicked, cursor); - - if (clickResult.isCancel()) { - return clickResult; - } - - if (clicked.isAir()) - return null; - - var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> { + if (clickResult.isCancel()) return clickResult; + if (clicked.isAir()) return null; + final var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> { InventoryClickResult result = startCondition(targetInventory, player, index, ClickType.SHIFT_CLICK, itemStack, cursor); if (result.isCancel()) { clickResult.setRefresh(true); @@ -184,7 +131,6 @@ public class InventoryClickProcessor { } return true; }); - ItemStack itemResult = TransactionOption.ALL.fill(targetInventory, pair.left(), pair.right()); clickResult.setClicked(itemResult); return clickResult; @@ -193,15 +139,9 @@ public class InventoryClickProcessor { public @Nullable InventoryClickResult shiftClick(@NotNull AbstractInventory targetInventory, int start, int end, int step, @NotNull Player player, int slot, @NotNull ItemStack clicked, @NotNull ItemStack cursor) { InventoryClickResult clickResult = startCondition(null, player, slot, ClickType.START_SHIFT_CLICK, clicked, cursor); - - if (clickResult.isCancel()) { - return clickResult; - } - - if (clicked.isAir()) - return null; - - var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> { + if (clickResult.isCancel()) return clickResult; + if (clicked.isAir()) return null; + final var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> { if (index == slot) // Prevent item lose/duplication return false; InventoryClickResult result = startCondition(targetInventory, player, index, ClickType.SHIFT_CLICK, itemStack, cursor); @@ -211,18 +151,16 @@ public class InventoryClickProcessor { } return true; }, start, end, step); - ItemStack itemResult = TransactionOption.ALL.fill(targetInventory, pair.left(), pair.right()); clickResult.setClicked(itemResult); return clickResult; } - @Nullable - public InventoryClickResult dragging(@Nullable Inventory inventory, @NotNull Player player, - int slot, int button, - @NotNull ItemStack clicked, @NotNull ItemStack cursor, - @NotNull Int2ObjectFunction itemGetter, - @NotNull BiConsumer itemSetter) { + public @Nullable InventoryClickResult dragging(@Nullable Inventory inventory, @NotNull Player player, + int slot, int button, + @NotNull ItemStack clicked, @NotNull ItemStack cursor, + @NotNull Int2ObjectFunction itemGetter, + @NotNull BiConsumer itemSetter) { InventoryClickResult clickResult = null; final StackingRule stackingRule = cursor.getStackingRule(); @@ -232,13 +170,11 @@ public class InventoryClickProcessor { if (button == 0) { // Start left clickResult = startCondition(inventory, player, slot, ClickType.START_LEFT_DRAGGING, clicked, cursor); - if (!clickResult.isCancel()) this.leftDraggingMap.put(player, new IntOpenHashSet()); } else if (button == 4) { // Start right clickResult = startCondition(inventory, player, slot, ClickType.START_RIGHT_DRAGGING, clicked, cursor); - if (!clickResult.isCancel()) this.rightDraggingMap.put(player, new IntOpenHashSet()); } else if (button == 2) { @@ -255,12 +191,9 @@ public class InventoryClickProcessor { for (int s : slots) { ItemStack slotItem = itemGetter.apply(s); - clickResult = startCondition(inventory, player, s, ClickType.LEFT_DRAGGING, slotItem, cursor); - if (clickResult.isCancel()) { cancel = true; - break; } } @@ -381,17 +314,11 @@ public class InventoryClickProcessor { return clickResult; } - @Nullable - public InventoryClickResult doubleClick(@NotNull AbstractInventory clickedInventory, @Nullable Inventory inventory, @NotNull Player player, int slot, - @NotNull final ItemStack cursor) { + public @Nullable InventoryClickResult doubleClick(@NotNull AbstractInventory clickedInventory, @Nullable Inventory inventory, @NotNull Player player, int slot, + @NotNull final ItemStack cursor) { InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.START_DOUBLE_CLICK, ItemStack.AIR, cursor); - - if (clickResult.isCancel()) { - return clickResult; - } - - if (cursor.isAir()) - return null; + if (clickResult.isCancel()) return clickResult; + if (cursor.isAir()) return null; final StackingRule cursorRule = cursor.getStackingRule(); final int amount = cursorRule.getAmount(cursor); @@ -418,7 +345,6 @@ public class InventoryClickProcessor { }; var playerInventory = player.getInventory(); - if (Objects.equals(clickedInventory, inventory)) { // Clicked inside inventory remain = func.apply(inventory, remain); @@ -449,10 +375,9 @@ public class InventoryClickProcessor { return clickResult; } - @NotNull - public InventoryClickResult drop(@Nullable Inventory inventory, @NotNull Player player, - boolean all, int slot, int button, - @NotNull ItemStack clicked, @NotNull ItemStack cursor) { + public @NotNull InventoryClickResult drop(@Nullable Inventory inventory, @NotNull Player player, + boolean all, int slot, int button, + @NotNull ItemStack clicked, @NotNull ItemStack cursor) { final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.DROP, clicked, cursor); if (clickResult.isCancel()) { @@ -465,7 +390,6 @@ public class InventoryClickProcessor { ItemStack resultClicked = clicked; ItemStack resultCursor = cursor; - if (slot == -999) { // Click outside if (button == 0) { @@ -518,9 +442,10 @@ public class InventoryClickProcessor { return clickResult; } - @NotNull - private InventoryClickResult startCondition(@NotNull InventoryClickResult clickResult, @Nullable Inventory inventory, - @NotNull Player player, int slot, @NotNull ClickType clickType) { + private @NotNull InventoryClickResult startCondition(@Nullable Inventory inventory, + @NotNull Player player, int slot, @NotNull ClickType clickType, + @NotNull ItemStack clicked, @NotNull ItemStack cursor) { + final InventoryClickResult clickResult = new InventoryClickResult(clicked, cursor); boolean isPlayerInventory = inventory == null; final int inventorySlot = isPlayerInventory ? 0 : inventory.getSize(); isPlayerInventory = isPlayerInventory ? isPlayerInventory : slot >= inventorySlot; @@ -531,81 +456,67 @@ public class InventoryClickProcessor { slot = slot - inventorySlot + PlayerInventoryUtils.OFFSET; } - // Call ItemStack#onInventoryClick - { - //clickResult.getClicked().onInventoryClick(player, clickType, slot, isPlayerInventory); - } - // Reset the didCloseInventory field // Wait for inventory conditions + events to possibly close the inventory player.UNSAFE_changeDidCloseInventory(false); - - // PreClickEvent + // InventoryPreClickEvent { InventoryPreClickEvent inventoryPreClickEvent = new InventoryPreClickEvent(inventory, player, slot, clickType, clickResult.getClicked(), clickResult.getCursor()); EventDispatcher.call(inventoryPreClickEvent); clickResult.setCursor(inventoryPreClickEvent.getCursorItem()); clickResult.setClicked(inventoryPreClickEvent.getClickedItem()); - if (inventoryPreClickEvent.isCancelled()) { clickResult.setRefresh(true); clickResult.setCancel(true); } } - // Inventory conditions - final List inventoryConditions = isPlayerInventory ? - player.getInventory().getInventoryConditions() : inventory.getInventoryConditions(); - if (!inventoryConditions.isEmpty()) { + { + final var inventoryConditions = isPlayerInventory ? + player.getInventory().getInventoryConditions() : inventory.getInventoryConditions(); + if (!inventoryConditions.isEmpty()) { + for (InventoryCondition inventoryCondition : inventoryConditions) { + var result = new InventoryConditionResult(clickResult.getClicked(), clickResult.getCursor()); + inventoryCondition.accept(player, slot, clickType, result); - for (InventoryCondition inventoryCondition : inventoryConditions) { - InventoryConditionResult result = new InventoryConditionResult(clickResult.getClicked(), clickResult.getCursor()); - inventoryCondition.accept(player, slot, clickType, result); - - clickResult.setCursor(result.getCursorItem()); - clickResult.setClicked(result.getClickedItem()); - - if (result.isCancel()) { - clickResult.setRefresh(true); + clickResult.setCursor(result.getCursorItem()); + clickResult.setClicked(result.getClickedItem()); + if (result.isCancel()) { + clickResult.setRefresh(true); + clickResult.setCancel(true); + } + } + // Cancel the click if the inventory has been closed by Player#closeInventory within an inventory listener + if (player.didCloseInventory()) { clickResult.setCancel(true); + player.UNSAFE_changeDidCloseInventory(false); } } - - // Cancel the click if the inventory has been closed by Player#closeInventory within an inventory listener - if (player.didCloseInventory()) { + } + // Sanity check + { + if (clickResult.getCursor().isAir() && clickResult.getClicked().isAir()) { + // One of the item must not be air clickResult.setCancel(true); - player.UNSAFE_changeDidCloseInventory(false); } - - } return clickResult; } - @NotNull - private InventoryClickResult startCondition(@Nullable Inventory inventory, @NotNull Player player, int slot, - @NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) { - final InventoryClickResult clickResult = new InventoryClickResult(clicked, cursor); - return startCondition(clickResult, inventory, player, slot, clickType); - } - - @NotNull - private InventoryClickResult startCondition(@Nullable AbstractInventory inventory, @NotNull Player player, int slot, - @NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) { + private @NotNull InventoryClickResult startCondition(@Nullable AbstractInventory inventory, @NotNull Player player, int slot, + @NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) { return startCondition(inventory instanceof Inventory ? (Inventory) inventory : null, player, slot, clickType, clicked, cursor); } private void callClickEvent(@NotNull Player player, @Nullable Inventory inventory, int slot, @NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) { - InventoryClickEvent inventoryClickEvent = new InventoryClickEvent(inventory, player, slot, clickType, clicked, cursor); - EventDispatcher.call(inventoryClickEvent); + EventDispatcher.call(new InventoryClickEvent(inventory, player, slot, clickType, clicked, cursor)); } public void clearCache(@NotNull Player player) { this.leftDraggingMap.remove(player); this.rightDraggingMap.remove(player); } - }