mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-04 23:47:59 +01:00
Fix server replaying the close window packet
This commit is contained in:
parent
f5f8e21427
commit
4ba779d3f1
@ -1758,6 +1758,39 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the player's inventory state, given a window id to compare against.
|
||||
* Note: This should only be used when receiving a {@link net.minestom.server.network.packet.client.play.ClientCloseWindowPacket}.
|
||||
* Use {@link #closeInventory()} instead for more general use.
|
||||
* @param windowId The window id to compare against.
|
||||
*/
|
||||
public void updateCloseInventoryState(byte windowId) {
|
||||
if (windowId == 0) {
|
||||
// Put cursor item back in inventory if possible
|
||||
ItemStack stack = getInventory().getCursorItem();
|
||||
boolean success = getInventory().addItemStack(stack);
|
||||
// Drop if inventory is full
|
||||
if (!success) {
|
||||
dropItem(stack);
|
||||
}
|
||||
getInventory().setCursorItem(ItemStack.AIR);
|
||||
} else {
|
||||
if (getOpenInventory() != null && windowId == getOpenInventory().getWindowId()) {
|
||||
ItemStack stack = getOpenInventory().getCursorItem(this);
|
||||
// Try to put item into our inventory
|
||||
boolean success = getInventory().addItemStack(stack);
|
||||
// Drop if inventory is full
|
||||
if (!success) {
|
||||
dropItem(stack);
|
||||
}
|
||||
getOpenInventory().setCursorItem(this, ItemStack.AIR);
|
||||
} else {
|
||||
// Something has gone wrong
|
||||
logger.warn("Tried to update inventory state with invalid window id!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used internally to prevent an inventory click to be processed
|
||||
* when the inventory listeners closed the inventory.
|
||||
|
@ -27,8 +27,6 @@ public class WindowListener {
|
||||
final byte button = packet.button();
|
||||
final ClientClickWindowPacket.ClickType clickType = packet.clickType();
|
||||
|
||||
//System.out.println("Window id: " + windowId + " | slot: " + slot + " | button: " + button + " | clickType: " + clickType);
|
||||
|
||||
boolean successful = false;
|
||||
|
||||
// prevent click in a non-interactive slot (why does it exist?)
|
||||
@ -90,7 +88,7 @@ public class WindowListener {
|
||||
InventoryCloseEvent inventoryCloseEvent = new InventoryCloseEvent(player.getOpenInventory(), player);
|
||||
EventDispatcher.call(inventoryCloseEvent);
|
||||
|
||||
player.closeInventory();
|
||||
player.updateCloseInventoryState(packet.windowId());
|
||||
|
||||
Inventory newInventory = inventoryCloseEvent.getNewInventory();
|
||||
if (newInventory != null)
|
||||
@ -103,10 +101,10 @@ public class WindowListener {
|
||||
*/
|
||||
private static void refreshCursorItem(Player player, AbstractInventory inventory) {
|
||||
ItemStack cursorItem;
|
||||
if (inventory instanceof PlayerInventory) {
|
||||
cursorItem = ((PlayerInventory) inventory).getCursorItem();
|
||||
} else if (inventory instanceof Inventory) {
|
||||
cursorItem = ((Inventory) inventory).getCursorItem(player);
|
||||
if (inventory instanceof PlayerInventory playerInventory) {
|
||||
cursorItem = playerInventory.getCursorItem();
|
||||
} else if (inventory instanceof Inventory standardInventory) {
|
||||
cursorItem = standardInventory.getCursorItem(player);
|
||||
} else {
|
||||
throw new RuntimeException("Invalid inventory: " + inventory.getClass());
|
||||
}
|
||||
@ -115,10 +113,10 @@ public class WindowListener {
|
||||
}
|
||||
|
||||
private static void setCursor(Player player, AbstractInventory inventory, ItemStack itemStack) {
|
||||
if (inventory instanceof PlayerInventory) {
|
||||
((PlayerInventory) inventory).setCursorItem(itemStack);
|
||||
} else if (inventory instanceof Inventory) {
|
||||
((Inventory) inventory).setCursorItem(player, itemStack);
|
||||
if (inventory instanceof PlayerInventory playerInventory) {
|
||||
playerInventory.setCursorItem(itemStack);
|
||||
} else if (inventory instanceof Inventory standardInventory) {
|
||||
standardInventory.setCursorItem(player, itemStack);
|
||||
} else {
|
||||
throw new RuntimeException("Invalid inventory: " + inventory.getClass());
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
package net.minestom.server.inventory;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.client.play.ClientCloseWindowPacket;
|
||||
import net.minestom.server.network.packet.server.play.CloseWindowPacket;
|
||||
import net.minestom.testing.Env;
|
||||
import net.minestom.testing.EnvTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@EnvTest
|
||||
public class InventoryCloseStateTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void doNotReceiveClosePacketFromServerWhenSendingClientCloseWindowPacket(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
var player = connection.connect(instance, new Pos(0, 42, 0)).join();
|
||||
assertEquals(instance, player.getInstance());
|
||||
|
||||
var packetTracker = connection.trackIncoming(CloseWindowPacket.class);
|
||||
var inventory = new Inventory(InventoryType.CHEST_2_ROW, Component.text("Test"));
|
||||
player.openInventory(inventory);
|
||||
player.closeInventory(); // Closes the inventory server-side, should send a CloseWindowPacket
|
||||
player.openInventory(inventory);
|
||||
// Send the close window packet
|
||||
player.addPacketToQueue(ConnectionState.PLAY, new ClientCloseWindowPacket(inventory.getWindowId()));
|
||||
player.interpretPacketQueue();
|
||||
packetTracker.assertSingle(closeWindowPacket -> assertEquals(inventory.getWindowId(), closeWindowPacket.windowId()));
|
||||
packetTracker.assertCount(1); // Assert we only get 1 close window packet from the closeInventory(); call
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user