mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-06 16:37:38 +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
|
* Used internally to prevent an inventory click to be processed
|
||||||
* when the inventory listeners closed the inventory.
|
* when the inventory listeners closed the inventory.
|
||||||
|
@ -27,8 +27,6 @@ public class WindowListener {
|
|||||||
final byte button = packet.button();
|
final byte button = packet.button();
|
||||||
final ClientClickWindowPacket.ClickType clickType = packet.clickType();
|
final ClientClickWindowPacket.ClickType clickType = packet.clickType();
|
||||||
|
|
||||||
//System.out.println("Window id: " + windowId + " | slot: " + slot + " | button: " + button + " | clickType: " + clickType);
|
|
||||||
|
|
||||||
boolean successful = false;
|
boolean successful = false;
|
||||||
|
|
||||||
// prevent click in a non-interactive slot (why does it exist?)
|
// 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);
|
InventoryCloseEvent inventoryCloseEvent = new InventoryCloseEvent(player.getOpenInventory(), player);
|
||||||
EventDispatcher.call(inventoryCloseEvent);
|
EventDispatcher.call(inventoryCloseEvent);
|
||||||
|
|
||||||
player.closeInventory();
|
player.updateCloseInventoryState(packet.windowId());
|
||||||
|
|
||||||
Inventory newInventory = inventoryCloseEvent.getNewInventory();
|
Inventory newInventory = inventoryCloseEvent.getNewInventory();
|
||||||
if (newInventory != null)
|
if (newInventory != null)
|
||||||
@ -103,10 +101,10 @@ public class WindowListener {
|
|||||||
*/
|
*/
|
||||||
private static void refreshCursorItem(Player player, AbstractInventory inventory) {
|
private static void refreshCursorItem(Player player, AbstractInventory inventory) {
|
||||||
ItemStack cursorItem;
|
ItemStack cursorItem;
|
||||||
if (inventory instanceof PlayerInventory) {
|
if (inventory instanceof PlayerInventory playerInventory) {
|
||||||
cursorItem = ((PlayerInventory) inventory).getCursorItem();
|
cursorItem = playerInventory.getCursorItem();
|
||||||
} else if (inventory instanceof Inventory) {
|
} else if (inventory instanceof Inventory standardInventory) {
|
||||||
cursorItem = ((Inventory) inventory).getCursorItem(player);
|
cursorItem = standardInventory.getCursorItem(player);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Invalid inventory: " + inventory.getClass());
|
throw new RuntimeException("Invalid inventory: " + inventory.getClass());
|
||||||
}
|
}
|
||||||
@ -115,10 +113,10 @@ public class WindowListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void setCursor(Player player, AbstractInventory inventory, ItemStack itemStack) {
|
private static void setCursor(Player player, AbstractInventory inventory, ItemStack itemStack) {
|
||||||
if (inventory instanceof PlayerInventory) {
|
if (inventory instanceof PlayerInventory playerInventory) {
|
||||||
((PlayerInventory) inventory).setCursorItem(itemStack);
|
playerInventory.setCursorItem(itemStack);
|
||||||
} else if (inventory instanceof Inventory) {
|
} else if (inventory instanceof Inventory standardInventory) {
|
||||||
((Inventory) inventory).setCursorItem(player, itemStack);
|
standardInventory.setCursorItem(player, itemStack);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Invalid inventory: " + inventory.getClass());
|
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