diff --git a/src/network/mcpe/InventoryManager.php b/src/network/mcpe/InventoryManager.php index 2aea0e0da..fff1e10c7 100644 --- a/src/network/mcpe/InventoryManager.php +++ b/src/network/mcpe/InventoryManager.php @@ -191,8 +191,10 @@ class InventoryManager{ */ public function addPredictedSlotChanges(array $networkInventoryActions) : void{ foreach($networkInventoryActions as $action){ - if($action->sourceType === NetworkInventoryAction::SOURCE_CONTAINER && isset($this->windowMap[$action->windowId])){ - //this won't cover stuff like crafting grid due to too much magic + if($action->sourceType === NetworkInventoryAction::SOURCE_CONTAINER && ( + isset($this->windowMap[$action->windowId]) || + ($action->windowId === ContainerIds::UI && isset($this->complexSlotToWindowMap[$action->inventorySlot])) + )){ try{ $item = TypeConverter::getInstance()->netItemStackToCore($action->newItem->getItemStack()); }catch(TypeConversionException $e){ diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 53bcd0345..970cebdc5 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -324,9 +324,7 @@ class InGamePacketHandler extends PacketHandler{ $result = $this->handleReleaseItemTransaction($packet->trData); } - if(!$result){ - $this->inventoryManager->syncAll(); - }else{ + if($this->craftingTransaction === null){ //don't sync if we're waiting to complete a crafting transaction $this->inventoryManager->syncMismatchedPredictedSlotChanges(); } return $result; @@ -361,6 +359,7 @@ class InGamePacketHandler extends PacketHandler{ return false; } } + $this->inventoryManager->addPredictedSlotChanges($data->getActions()); if($isCraftingPart){ if($this->craftingTransaction === null){ @@ -381,15 +380,9 @@ class InGamePacketHandler extends PacketHandler{ } $this->player->setUsingItem(false); try{ - $this->inventoryManager->onTransactionStart($this->craftingTransaction); $this->craftingTransaction->execute(); }catch(TransactionException $e){ $this->session->getLogger()->debug("Failed to execute crafting transaction: " . $e->getMessage()); - - //TODO: only sync slots that the client tried to change - foreach($this->craftingTransaction->getInventories() as $inventory){ - $this->inventoryManager->syncContents($inventory); - } return false; }finally{ $this->craftingTransaction = null; @@ -409,18 +402,12 @@ class InGamePacketHandler extends PacketHandler{ $this->player->setUsingItem(false); $transaction = new InventoryTransaction($this->player, $actions); - $this->inventoryManager->onTransactionStart($transaction); try{ $transaction->execute(); }catch(TransactionException $e){ $logger = $this->session->getLogger(); $logger->debug("Failed to execute inventory transaction: " . $e->getMessage()); $logger->debug("Actions: " . json_encode($data->getActions())); - - foreach($transaction->getInventories() as $inventory){ - $this->inventoryManager->syncContents($inventory); - } - return false; } } @@ -430,7 +417,6 @@ class InGamePacketHandler extends PacketHandler{ private function handleUseItemTransaction(UseItemTransactionData $data) : bool{ $this->player->selectHotbarSlot($data->getHotbarSlot()); - $this->inventoryManager->addPredictedSlotChanges($data->getActions()); switch($data->getActionType()){ case UseItemTransactionData::ACTION_CLICK_BLOCK: @@ -516,9 +502,7 @@ class InGamePacketHandler extends PacketHandler{ } $this->player->selectHotbarSlot($data->getHotbarSlot()); - $this->inventoryManager->addPredictedSlotChanges($data->getActions()); - //TODO: use transactiondata for rollbacks here switch($data->getActionType()){ case UseItemOnEntityTransactionData::ACTION_INTERACT: $this->player->interactEntity($target, $data->getClickPosition()); @@ -533,15 +517,10 @@ class InGamePacketHandler extends PacketHandler{ private function handleReleaseItemTransaction(ReleaseItemTransactionData $data) : bool{ $this->player->selectHotbarSlot($data->getHotbarSlot()); - $this->inventoryManager->addPredictedSlotChanges($data->getActions()); - //TODO: use transactiondata for rollbacks here (resending entire inventory is very wasteful) - switch($data->getActionType()){ - case ReleaseItemTransactionData::ACTION_RELEASE: - if(!$this->player->releaseHeldItem()){ - $this->inventoryManager->syncContents($this->player->getInventory()); - } - return true; + if($data->getActionType() == ReleaseItemTransactionData::ACTION_RELEASE){ + $this->player->releaseHeldItem(); + return true; } return false;