From e8085e22a00074638f7808e30647d69f7ddd9792 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 20 Mar 2023 18:40:18 +0000 Subject: [PATCH] Fixed crash when opening main inventory the InventoryManagerEntry was getting overwritten, since we don't expect to open the same inventory with two different window IDs. --- src/network/mcpe/InventoryManager.php | 39 ++++++++++++++++++++------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/network/mcpe/InventoryManager.php b/src/network/mcpe/InventoryManager.php index 868ccebdf..e93f2bc39 100644 --- a/src/network/mcpe/InventoryManager.php +++ b/src/network/mcpe/InventoryManager.php @@ -118,30 +118,48 @@ class InventoryManager{ }); } - private function add(int $id, Inventory $inventory) : void{ - $this->inventories[spl_object_id($inventory)] = new InventoryManagerEntry($inventory); + private function associateIdWithInventory(int $id, Inventory $inventory) : void{ $this->networkIdToInventoryMap[$id] = $inventory; } - private function addDynamic(Inventory $inventory) : int{ - $this->inventories[spl_object_id($inventory)] = new InventoryManagerEntry($inventory); + private function getNewWindowId() : int{ $this->lastInventoryNetworkId = max(ContainerIds::FIRST, ($this->lastInventoryNetworkId + 1) % ContainerIds::LAST); - $this->add($this->lastInventoryNetworkId, $inventory); return $this->lastInventoryNetworkId; } + private function add(int $id, Inventory $inventory) : void{ + if(isset($this->inventories[spl_object_id($inventory)])){ + throw new \InvalidArgumentException("Inventory " . get_class($inventory) . " is already tracked"); + } + $this->inventories[spl_object_id($inventory)] = new InventoryManagerEntry($inventory); + $this->associateIdWithInventory($id, $inventory); + } + + private function addDynamic(Inventory $inventory) : int{ + if(isset($this->inventories[spl_object_id($inventory)])){ + throw new \InvalidArgumentException("Inventory " . get_class($inventory) . " is already tracked"); + } + $this->inventories[spl_object_id($inventory)] = new InventoryManagerEntry($inventory); + $id = $this->getNewWindowId(); + $this->add($id, $inventory); + return $id; + } + /** * @param int[]|int $slotMap * @phpstan-param array|int $slotMap */ private function addComplex(array|int $slotMap, Inventory $inventory) : void{ - $entry = new ComplexInventoryMapEntry($inventory, is_int($slotMap) ? [$slotMap => 0] : $slotMap); + if(isset($this->inventories[spl_object_id($inventory)])){ + throw new \InvalidArgumentException("Inventory " . get_class($inventory) . " is already tracked"); + } + $complexSlotMap = new ComplexInventoryMapEntry($inventory, is_int($slotMap) ? [$slotMap => 0] : $slotMap); $this->inventories[spl_object_id($inventory)] = new InventoryManagerEntry( $inventory, - $entry + $complexSlotMap ); - foreach($entry->getSlotMap() as $netSlot => $coreSlot){ - $this->complexSlotToInventoryMap[$netSlot] = $entry; + foreach($complexSlotMap->getSlotMap() as $netSlot => $coreSlot){ + $this->complexSlotToInventoryMap[$netSlot] = $complexSlotMap; } } @@ -329,7 +347,8 @@ class InventoryManager{ $this->onCurrentWindowRemove(); $this->openWindowDeferred(function() : void{ - $windowId = $this->addDynamic($this->player->getInventory()); + $windowId = $this->getNewWindowId(); + $this->associateIdWithInventory($windowId, $this->player->getInventory()); $this->session->sendDataPacket(ContainerOpenPacket::entityInv( $windowId,