From f19bf898f9435dd70a092d6a41781c040b3d6a84 Mon Sep 17 00:00:00 2001 From: GreatWyrm Date: Wed, 22 Jan 2025 12:35:50 -0800 Subject: [PATCH] Rebase and update tests --- .../player/PlayerChangeHeldSlotEvent.java | 64 +++++++++++++++++-- .../server/listener/PlayerHeldListener.java | 2 +- .../entity/PlayerHeldIntegrationTest.java | 31 +++++++-- 3 files changed, 84 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/minestom/server/event/player/PlayerChangeHeldSlotEvent.java b/src/main/java/net/minestom/server/event/player/PlayerChangeHeldSlotEvent.java index 2c2270725..90e825693 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerChangeHeldSlotEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerChangeHeldSlotEvent.java @@ -3,6 +3,7 @@ package net.minestom.server.event.player; import net.minestom.server.entity.Player; import net.minestom.server.event.trait.CancellableEvent; import net.minestom.server.event.trait.PlayerInstanceEvent; +import net.minestom.server.item.ItemStack; import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; @@ -13,22 +14,55 @@ import org.jetbrains.annotations.NotNull; public class PlayerChangeHeldSlotEvent implements PlayerInstanceEvent, CancellableEvent { private final Player player; - private byte slot; + private final byte oldSlot; + private byte newSlot; private boolean cancelled; - public PlayerChangeHeldSlotEvent(@NotNull Player player, byte slot) { + public PlayerChangeHeldSlotEvent(@NotNull Player player, byte oldSlot, byte newSlot) { this.player = player; - this.slot = slot; + this.oldSlot = oldSlot; + this.newSlot = newSlot; } /** * Gets the slot which the player will hold. - * + * @deprecated Use {@link #getNewSlot()} instead. * @return the future slot */ + @Deprecated(forRemoval = true) public byte getSlot() { - return slot; + return newSlot; + } + + /** + * Gets the slot number that the player is currently holding + * + * @return The slot index that the player currently is holding + */ + public int getOldSlot() { + return oldSlot; + } + + /** + * Gets the slot which the player will hold. + * @return the future slot + */ + public byte getNewSlot() { + return newSlot; + } + + /** + * Changes the final held slot of the player. + * + * @param slot the new held slot + * @deprecated Use {@link #setNewSlot(byte)} instead + * @throws IllegalArgumentException if slot is not between 0 and 8 + */ + @Deprecated(forRemoval = true) + public void setSlot(byte slot) { + Check.argCondition(!MathUtils.isBetween(slot, 0, 8), "The held slot needs to be between 0 and 8"); + this.newSlot = slot; } /** @@ -37,9 +71,25 @@ public class PlayerChangeHeldSlotEvent implements PlayerInstanceEvent, Cancellab * @param slot the new held slot * @throws IllegalArgumentException if slot is not between 0 and 8 */ - public void setSlot(byte slot) { + public void setNewSlot(byte slot) { Check.argCondition(!MathUtils.isBetween(slot, 0, 8), "The held slot needs to be between 0 and 8"); - this.slot = slot; + this.newSlot = slot; + } + + /** + * Gets the ItemStack in the player's currently held slot + * @return The ItemStack in the player's currently held slot + */ + public ItemStack getItemInOldSlot() { + return player.getInventory().getItemStack(oldSlot); + } + + /** + * Gets the ItemStack in the slot the player will hold + * @return The ItemStack in the final held slot of the player + */ + public ItemStack getItemInNewSlot() { + return player.getInventory().getItemStack(newSlot); } @Override diff --git a/src/main/java/net/minestom/server/listener/PlayerHeldListener.java b/src/main/java/net/minestom/server/listener/PlayerHeldListener.java index e6055b65d..4723f6880 100644 --- a/src/main/java/net/minestom/server/listener/PlayerHeldListener.java +++ b/src/main/java/net/minestom/server/listener/PlayerHeldListener.java @@ -27,7 +27,7 @@ public class PlayerHeldListener { final byte resultSlot = changeHeldSlotEvent.getNewSlot(); // If the held slot has been changed by the event, send the change to the player - if (resultSlot != oldSlot) { + if (resultSlot != newSlot) { player.setHeldItemSlot(resultSlot); } else { // Otherwise, simply refresh the player field diff --git a/src/test/java/net/minestom/server/entity/PlayerHeldIntegrationTest.java b/src/test/java/net/minestom/server/entity/PlayerHeldIntegrationTest.java index 8b0c721ef..3a7280e86 100644 --- a/src/test/java/net/minestom/server/entity/PlayerHeldIntegrationTest.java +++ b/src/test/java/net/minestom/server/entity/PlayerHeldIntegrationTest.java @@ -2,20 +2,22 @@ package net.minestom.server.entity; import net.minestom.server.coordinate.Pos; import net.minestom.server.event.player.PlayerChangeHeldSlotEvent; +import net.minestom.server.event.player.PlayerPacketOutEvent; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.network.packet.client.play.ClientHeldItemChangePacket; +import net.minestom.server.network.packet.server.play.HeldItemChangePacket; import net.minestom.testing.Env; import net.minestom.testing.EnvTest; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; @EnvTest public class PlayerHeldIntegrationTest { @Test - public void playerHeld(Env env) { + void playerHeld(Env env) { var instance = env.createFlatInstance(); var connection = env.createConnection(); var player = connection.connect(instance, new Pos(0, 40, 0)); @@ -32,7 +34,7 @@ public class PlayerHeldIntegrationTest { } @Test - public void playerHeldEvent(Env env) { + void playerHeldEvent(Env env) { var instance = env.createFlatInstance(); var connection = env.createConnection(); var player = connection.connect(instance, new Pos(0, 40, 0)); @@ -54,10 +56,10 @@ public class PlayerHeldIntegrationTest { } @Test - public void playerChangingSlots(Env env) { + void playerChangingSlots(Env env) { var instance = env.createFlatInstance(); var connection = env.createConnection(); - var player = connection.connect(instance, new Pos(0, 40, 0)).join(); + var player = connection.connect(instance, new Pos(0, 40, 0)); player.getInventory().setItemStack(1, ItemStack.of(Material.STONE)); player.getInventory().setItemStack(3, ItemStack.of(Material.OAK_PLANKS)); @@ -83,4 +85,23 @@ public class PlayerHeldIntegrationTest { }); player.interpretPacketQueue(); } + + @Test + void eventChangeIsReflectedOnClient(Env env) { + var instance = env.createFlatInstance(); + var connection = env.createConnection(); + var player = connection.connect(instance, new Pos(0, 40, 0)); + + player.eventNode().addListener(PlayerChangeHeldSlotEvent.class, event -> event.setNewSlot((byte) 0)); + + var listener = connection.trackIncoming(HeldItemChangePacket.class); + player.addPacketToQueue(new ClientHeldItemChangePacket((short) 0)); + player.interpretPacketQueue(); + listener.assertEmpty(); // Ensure we don't send an unneeded packet if there is no change + + listener = connection.trackIncoming(HeldItemChangePacket.class); // Re-register listener + player.addPacketToQueue(new ClientHeldItemChangePacket((short) 3)); + player.interpretPacketQueue(); + listener.assertSingle(packet -> assertEquals((byte) 0, packet.slot())); // Ensure packet is sent + } }