> */ private array $changedSlots = []; public function __construct( private int $requestId, private InventoryManager $inventoryManager ){} public function addSlot(int $containerInterfaceId, int $slotId) : void{ $this->changedSlots[$containerInterfaceId][$slotId] = $slotId; } /** * @phpstan-return array{Inventory, int} */ private function getInventoryAndSlot(int $containerInterfaceId, int $slotId) : ?array{ $windowId = ItemStackContainerIdTranslator::translate($containerInterfaceId, $this->inventoryManager->getCurrentWindowId()); $windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId); if($windowAndSlot === null){ return null; } [$inventory, $slot] = $windowAndSlot; if(!$inventory->slotExists($slot)){ return null; } return [$inventory, $slot]; } public function build(bool $success) : ItemStackResponse{ $responseInfosByContainer = []; foreach($this->changedSlots as $containerInterfaceId => $slotIds){ if($containerInterfaceId === ContainerUIIds::CREATED_OUTPUT){ continue; } foreach($slotIds as $slotId){ $inventoryAndSlot = $this->getInventoryAndSlot($containerInterfaceId, $slotId); if($inventoryAndSlot === null){ //a plugin may have closed the inventory during an event, or the slot may have been invalid continue; } [$inventory, $slot] = $inventoryAndSlot; $itemStackInfo = $this->inventoryManager->getItemStackInfo($inventory, $slot); if($itemStackInfo === null){ throw new AssumptionFailedError("ItemStackInfo should never be null for an open inventory"); } if($itemStackInfo->getRequestId() !== $this->requestId){ //the itemstack may have been synced due to transaction producing results that the client did not //predict correctly, which will wipe out the tracked request ID (intentionally) //TODO: is this the correct behaviour? continue; } $item = $inventory->getItem($slot); $responseInfosByContainer[$containerInterfaceId][] = new ItemStackResponseSlotInfo( $slotId, $slotId, $item->getCount(), $itemStackInfo->getStackId(), $item->getCustomName(), 0 ); } } $responseContainerInfos = []; foreach($responseInfosByContainer as $containerInterfaceId => $responseInfos){ $responseContainerInfos[] = new ItemStackResponseContainerInfo($containerInterfaceId, $responseInfos); } return new ItemStackResponse($success ? ItemStackResponse::RESULT_OK : ItemStackResponse::RESULT_ERROR, $this->requestId, $responseContainerInfos); } }