From c6a28d8df0e67251182d21e75127370da29e2683 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 15 Sep 2025 17:34:35 +0100 Subject: [PATCH] InventoryManager: fixed window sending getting stuck on client rejecting window opening closes #6778 honestly, we could just stop checking the window ID entirely, considering the need for delaying and waiting for window close acks, it seems useless at this point... --- src/network/mcpe/InventoryManager.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/network/mcpe/InventoryManager.php b/src/network/mcpe/InventoryManager.php index 19bd94fce..01368ec0a 100644 --- a/src/network/mcpe/InventoryManager.php +++ b/src/network/mcpe/InventoryManager.php @@ -64,6 +64,7 @@ use pocketmine\network\mcpe\protocol\types\inventory\WindowTypes; use pocketmine\network\PacketHandlingException; use pocketmine\player\Player; use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\Binary; use pocketmine\utils\ObjectSet; use function array_fill_keys; use function array_keys; @@ -419,6 +420,15 @@ class InventoryManager{ } public function onClientRemoveWindow(int $id) : void{ + if(Binary::signByte($id) === ContainerIds::NONE){ //TODO: REMOVE signByte() once BedrockProtocol + ext-encoding are implemented + //TODO: HACK! Since 1.21.100 (and probably earlier), the client will send -1 to close windows that it can't + //view for some reason, e.g. if the chat window was already open. This is pretty awkward, since it means + //that we can only assume it refers to the most recently sent window, and if we don't handle it, + //InventoryManager will never get the green light to send subsequent windows, which breaks inventory UIs. + //Fortunately, we already wait for close acks anyway, so the window ID is technically useless...? + $this->session->getLogger()->debug("Client rejected opening of a window, assuming it was $this->lastInventoryNetworkId"); + $id = $this->lastInventoryNetworkId; + } if($id === $this->lastInventoryNetworkId){ if(isset($this->networkIdToInventoryMap[$id]) && $id !== $this->pendingCloseWindowId){ $this->remove($id);