From a988327f370f2d981164949078f689b99126fafc Mon Sep 17 00:00:00 2001 From: TheMode Date: Wed, 30 Mar 2022 17:24:16 +0200 Subject: [PATCH] Add held/left/right click integration tests Signed-off-by: TheMode --- .../integration/HeldClickIntegrationTest.java | 170 +++++++++++++++ .../integration/LeftClickIntegrationTest.java | 173 ++++++++++++++++ .../RightClickIntegrationTest.java | 194 ++++++++++++++++++ 3 files changed, 537 insertions(+) create mode 100644 src/test/java/net/minestom/server/inventory/click/integration/HeldClickIntegrationTest.java create mode 100644 src/test/java/net/minestom/server/inventory/click/integration/LeftClickIntegrationTest.java create mode 100644 src/test/java/net/minestom/server/inventory/click/integration/RightClickIntegrationTest.java diff --git a/src/test/java/net/minestom/server/inventory/click/integration/HeldClickIntegrationTest.java b/src/test/java/net/minestom/server/inventory/click/integration/HeldClickIntegrationTest.java new file mode 100644 index 000000000..b971bcc8f --- /dev/null +++ b/src/test/java/net/minestom/server/inventory/click/integration/HeldClickIntegrationTest.java @@ -0,0 +1,170 @@ +package net.minestom.server.inventory.click.integration; + +import net.minestom.server.api.Env; +import net.minestom.server.api.EnvTest; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.Inventory; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.inventory.click.ClickType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.network.packet.client.play.ClientClickWindowPacket; +import net.minestom.server.utils.inventory.PlayerInventoryUtils; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +@EnvTest +public class HeldClickIntegrationTest { + + @Test + public void heldSelf(Env env) { + var instance = env.createFlatInstance(); + var player = env.createPlayer(instance, new Pos(0, 40, 0)); + var inventory = player.getInventory(); + var listener = env.listen(InventoryPreClickEvent.class); + inventory.setItemStack(1, ItemStack.of(Material.DIAMOND)); + inventory.setItemStack(2, ItemStack.of(Material.GOLD_INGOT)); + inventory.setItemStack(5, ItemStack.of(Material.DIAMOND)); + // Empty + { + listener.followup(event -> { + assertNull(event.getInventory()); // Player inventory + assertEquals(3, event.getSlot()); + assertEquals(ClickType.CHANGE_HELD, event.getClickType()); + + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.AIR, event.getCursorItem()); + + assertEquals(ItemStack.AIR, event.getClickedItem()); + }); + heldClick(player, 3, 4); + } + // Swap air + { + listener.followup(event -> { + assertNull(event.getInventory()); // Player inventory + assertEquals(1, event.getSlot()); + assertEquals(ClickType.CHANGE_HELD, event.getClickType()); + + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.AIR, event.getCursorItem()); + + assertEquals(ItemStack.of(Material.DIAMOND), event.getClickedItem()); + }); + heldClick(player, 1, 0); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(0)); + } + // Swap items + { + listener.followup(event -> { + assertEquals(0, event.getSlot()); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + }); + heldClick(player, 0, 2); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(2)); + assertEquals(ItemStack.of(Material.GOLD_INGOT), inventory.getItemStack(0)); + } + // Cancel event + { + listener.followup(event -> event.setCancelled(true)); + heldClick(player, 2, 0); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(2)); + assertEquals(ItemStack.of(Material.GOLD_INGOT), inventory.getItemStack(0)); + } + } + + @Test + public void heldExternal(Env env) { + var instance = env.createFlatInstance(); + var player = env.createPlayer(instance, new Pos(0, 40, 0)); + var inventory = new Inventory(InventoryType.HOPPER, "test"); + var playerInv = player.getInventory(); + player.openInventory(inventory); + var listener = env.listen(InventoryPreClickEvent.class); + inventory.setItemStack(1, ItemStack.of(Material.DIAMOND)); + inventory.setItemStack(2, ItemStack.of(Material.GOLD_INGOT)); + inventory.setItemStack(4, ItemStack.of(Material.DIAMOND)); + // Empty + { + listener.followup(event -> { + assertEquals(inventory, event.getInventory()); + assertEquals(0, event.getSlot()); + assertEquals(ClickType.CHANGE_HELD, event.getClickType()); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + }); + heldClickOpenInventory(player, 0, 0); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.AIR, inventory.getItemStack(0)); + } + // Swap empty + { + listener.followup(event -> { + assertEquals(inventory, event.getInventory()); + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + }); + heldClickOpenInventory(player, 1, 0); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + assertEquals(ItemStack.of(Material.DIAMOND), playerInv.getItemStack(0)); + } + // Swap items + { + listener.followup(event -> { + assertEquals(inventory, event.getInventory()); + assertEquals(2, event.getSlot()); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + }); + heldClickOpenInventory(player, 2, 0); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(2)); + assertEquals(ItemStack.of(Material.GOLD_INGOT), playerInv.getItemStack(0)); + } + // Cancel event + { + listener.followup(event -> event.setCancelled(true)); + heldClickOpenInventory(player, 2, 0); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(2)); + assertEquals(ItemStack.of(Material.GOLD_INGOT), playerInv.getItemStack(0)); + } + } + + private void heldClickOpenInventory(Player player, int slot, int target) { + _heldClick(player.getOpenInventory(), true, player, slot, target); + } + + private void heldClick(Player player, int slot, int target) { + _heldClick(player.getOpenInventory(), false, player, slot, target); + } + + private void _heldClick(Inventory openInventory, boolean clickOpenInventory, Player player, int slot, int target) { + final byte windowId = openInventory != null ? openInventory.getWindowId() : 0; + if (clickOpenInventory) { + assert openInventory != null; + // Do not touch slot + } else { + int offset = openInventory != null ? openInventory.getInnerSize() : 0; + slot = PlayerInventoryUtils.convertToPacketSlot(slot); + if (openInventory != null) { + slot = slot - 9 + offset; + } + } + player.addPacketToQueue(new ClientClickWindowPacket(windowId, 0, (short) slot, (byte) target, + ClientClickWindowPacket.ClickType.SWAP, List.of(), ItemStack.AIR)); + player.interpretPacketQueue(); + } +} diff --git a/src/test/java/net/minestom/server/inventory/click/integration/LeftClickIntegrationTest.java b/src/test/java/net/minestom/server/inventory/click/integration/LeftClickIntegrationTest.java new file mode 100644 index 000000000..0207a001a --- /dev/null +++ b/src/test/java/net/minestom/server/inventory/click/integration/LeftClickIntegrationTest.java @@ -0,0 +1,173 @@ +package net.minestom.server.inventory.click.integration; + + +import net.minestom.server.api.Env; +import net.minestom.server.api.EnvTest; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.Inventory; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.inventory.click.ClickType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.network.packet.client.play.ClientClickWindowPacket; +import net.minestom.server.utils.inventory.PlayerInventoryUtils; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +@EnvTest +public class LeftClickIntegrationTest { + + @Test + public void leftSelf(Env env) { + var instance = env.createFlatInstance(); + var player = env.createPlayer(instance, new Pos(0, 40, 0)); + var inventory = player.getInventory(); + var listener = env.listen(InventoryPreClickEvent.class); + inventory.setItemStack(1, ItemStack.of(Material.DIAMOND)); + // Empty click + { + listener.followup(event -> { + assertNull(event.getInventory()); // Player inventory + assertEquals(0, event.getSlot()); + assertEquals(ClickType.LEFT_CLICK, event.getClickType()); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + }); + leftClick(player, 0); + } + // Pickup diamond + { + listener.followup(event -> { + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + }); + leftClick(player, 1); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + } + // Place it back + { + listener.followup(event -> { + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + }); + leftClick(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + } + // Cancel event + { + listener.followup(event -> event.setCancelled(true)); + leftClick(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem(), "Left click cancellation did not work"); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + } + // Change items + { + listener.followup(event -> { + event.setClickedItem(ItemStack.of(Material.DIAMOND, 5)); + event.setCursorItem(ItemStack.of(Material.DIAMOND)); + }); + leftClick(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND, 6), inventory.getItemStack(1)); + } + } + + @Test + public void leftExternal(Env env) { + var instance = env.createFlatInstance(); + var player = env.createPlayer(instance, new Pos(0, 40, 0)); + var inventory = new Inventory(InventoryType.HOPPER, "test"); + player.openInventory(inventory); + var listener = env.listen(InventoryPreClickEvent.class); + inventory.setItemStack(1, ItemStack.of(Material.DIAMOND)); + // Empty click in player inv + { + listener.followup(event -> { + assertNull(event.getInventory()); // Player inventory + assertEquals(0, event.getSlot()); + assertEquals(ClickType.LEFT_CLICK, event.getClickType()); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + }); + leftClick(player, 0); + } + // Pickup diamond + { + listener.followup(event -> { + assertEquals(inventory, event.getInventory()); + assertEquals(1, event.getSlot()); + // Ensure that the inventory didn't change yet + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + }); + leftClickOpenInventory(player, 1); + // Verify inventory changes + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem(player)); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + } + // Place it back + { + listener.followup(event -> { + assertEquals(inventory, event.getInventory()); + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem(player)); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + }); + leftClickOpenInventory(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + } + // Cancel event + { + listener.followup(event -> event.setCancelled(true)); + leftClickOpenInventory(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player), "Left click cancellation did not work"); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + } + // Change items + { + listener.followup(event -> { + assertNull(event.getInventory()); + assertEquals(9, event.getSlot()); + event.setClickedItem(ItemStack.of(Material.DIAMOND, 5)); + event.setCursorItem(ItemStack.of(Material.DIAMOND)); + }); + leftClick(player, 9); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND, 6), player.getInventory().getItemStack(9)); + } + } + + private void leftClickOpenInventory(Player player, int slot) { + _leftClick(player.getOpenInventory(), true, player, slot); + } + + private void leftClick(Player player, int slot) { + _leftClick(player.getOpenInventory(), false, player, slot); + } + + private void _leftClick(Inventory openInventory, boolean clickOpenInventory, Player player, int slot) { + final byte windowId = openInventory != null ? openInventory.getWindowId() : 0; + if (clickOpenInventory) { + assert openInventory != null; + // Do not touch slot + } else { + int offset = openInventory != null ? openInventory.getInnerSize() : 0; + slot = PlayerInventoryUtils.convertToPacketSlot(slot); + if (openInventory != null) { + slot = slot - 9 + offset; + } + } + player.addPacketToQueue(new ClientClickWindowPacket(windowId, 0, (short) slot, (byte) 0, + ClientClickWindowPacket.ClickType.PICKUP, List.of(), ItemStack.AIR)); + player.interpretPacketQueue(); + } +} diff --git a/src/test/java/net/minestom/server/inventory/click/integration/RightClickIntegrationTest.java b/src/test/java/net/minestom/server/inventory/click/integration/RightClickIntegrationTest.java new file mode 100644 index 000000000..ceddd0b5e --- /dev/null +++ b/src/test/java/net/minestom/server/inventory/click/integration/RightClickIntegrationTest.java @@ -0,0 +1,194 @@ +package net.minestom.server.inventory.click.integration; + +import net.minestom.server.api.Env; +import net.minestom.server.api.EnvTest; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.Inventory; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.inventory.click.ClickType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.network.packet.client.play.ClientClickWindowPacket; +import net.minestom.server.utils.inventory.PlayerInventoryUtils; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +@EnvTest +public class RightClickIntegrationTest { + + @Test + public void rightSelf(Env env) { + var instance = env.createFlatInstance(); + var player = env.createPlayer(instance, new Pos(0, 40, 0)); + var inventory = player.getInventory(); + var listener = env.listen(InventoryPreClickEvent.class); + inventory.setItemStack(1, ItemStack.of(Material.DIAMOND)); + inventory.setItemStack(2, ItemStack.of(Material.DIAMOND)); + // Empty click + { + listener.followup(event -> { + assertNull(event.getInventory()); // Player inventory + assertEquals(0, event.getSlot()); + assertEquals(ClickType.RIGHT_CLICK, event.getClickType()); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + }); + rightClick(player, 0); + } + // Pickup diamond + { + listener.followup(event -> { + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + }); + rightClick(player, 1); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + } + // Place it back + { + listener.followup(event -> { + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + }); + rightClick(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + } + // Pickup diamond + { + listener.followup(event -> { + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + }); + rightClick(player, 1); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem()); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + } + // Stack diamond + { + listener.followup(event -> { + assertEquals(2, event.getSlot()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(2)); + }); + rightClick(player, 2); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND, 2), inventory.getItemStack(2)); + } + // Cancel event + { + listener.followup(event -> event.setCancelled(true)); + rightClick(player, 2); + assertEquals(ItemStack.AIR, inventory.getCursorItem(), "Left click cancellation did not work"); + assertEquals(ItemStack.of(Material.DIAMOND, 2), inventory.getItemStack(2)); + } + // Change items + { + listener.followup(event -> { + event.setClickedItem(ItemStack.of(Material.DIAMOND, 5)); + event.setCursorItem(ItemStack.of(Material.DIAMOND)); + }); + rightClick(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem()); + assertEquals(ItemStack.of(Material.DIAMOND, 6), inventory.getItemStack(1)); + } + } + + @Test + public void rightExternal(Env env) { + var instance = env.createFlatInstance(); + var player = env.createPlayer(instance, new Pos(0, 40, 0)); + var inventory = new Inventory(InventoryType.HOPPER, "test"); + player.openInventory(inventory); + var listener = env.listen(InventoryPreClickEvent.class); + inventory.setItemStack(1, ItemStack.of(Material.DIAMOND)); + // Empty click in player inv + { + listener.followup(event -> { + assertNull(event.getInventory()); // Player inventory + assertEquals(0, event.getSlot()); + assertEquals(ClickType.RIGHT_CLICK, event.getClickType()); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + }); + rightClick(player, 0); + } + // Pickup diamond + { + listener.followup(event -> { + assertEquals(inventory, event.getInventory()); + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getItemStack(1)); + }); + rightClickOpenInventory(player, 1); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem(player)); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + } + // Place back to player inv + { + listener.followup(event -> { + assertNull(event.getInventory()); + assertEquals(1, event.getSlot()); + assertEquals(ItemStack.of(Material.DIAMOND), inventory.getCursorItem(player)); + assertEquals(ItemStack.AIR, inventory.getItemStack(1)); + assertEquals(ItemStack.AIR, player.getInventory().getItemStack(1)); + }); + rightClick(player, 1); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND), player.getInventory().getItemStack(1)); + } + // Cancel event + { + listener.followup(event -> event.setCancelled(true)); + rightClick(player, 1); + assertEquals(ItemStack.of(Material.DIAMOND), player.getInventory().getItemStack(1), "Left click cancellation did not work"); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + } + // Change items + { + listener.followup(event -> { + assertNull(event.getInventory()); + assertEquals(9, event.getSlot()); + event.setClickedItem(ItemStack.of(Material.DIAMOND, 5)); + event.setCursorItem(ItemStack.of(Material.DIAMOND)); + }); + rightClick(player, 9); + assertEquals(ItemStack.AIR, inventory.getCursorItem(player)); + assertEquals(ItemStack.of(Material.DIAMOND, 6), player.getInventory().getItemStack(9)); + } + } + + private void rightClickOpenInventory(Player player, int slot) { + _rightClick(player.getOpenInventory(), true, player, slot); + } + + private void rightClick(Player player, int slot) { + _rightClick(player.getOpenInventory(), false, player, slot); + } + + private void _rightClick(Inventory openInventory, boolean clickOpenInventory, Player player, int slot) { + final byte windowId = openInventory != null ? openInventory.getWindowId() : 0; + if (clickOpenInventory) { + assert openInventory != null; + // Do not touch slot + } else { + int offset = openInventory != null ? openInventory.getInnerSize() : 0; + slot = PlayerInventoryUtils.convertToPacketSlot(slot); + if (openInventory != null) { + slot = slot - 9 + offset; + } + } + player.addPacketToQueue(new ClientClickWindowPacket(windowId, 0, (short) slot, (byte) 1, + ClientClickWindowPacket.ClickType.PICKUP, List.of(), ItemStack.AIR)); + player.interpretPacketQueue(); + } +}