diff --git a/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php b/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php index cd6bddc97..2c423397a 100644 --- a/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php +++ b/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php @@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\protocol; #include use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\ContainerIds; use pocketmine\network\mcpe\protocol\types\NetworkInventoryAction; use function count; @@ -74,7 +75,25 @@ class InventoryTransactionPacket extends DataPacket{ $this->transactionType = $this->getUnsignedVarInt(); for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ - $this->actions[] = (new NetworkInventoryAction())->read($this); + $this->actions[] = $action = (new NetworkInventoryAction())->read($this); + + if( + $action->sourceType === NetworkInventoryAction::SOURCE_CONTAINER and + $action->windowId === ContainerIds::UI and + $action->inventorySlot === 50 + ){ + $this->isCraftingPart = true; + if(!$action->oldItem->isNull() and $action->newItem->isNull()){ + $this->isFinalCraftingPart = true; + } + }elseif( + $action->sourceType === NetworkInventoryAction::SOURCE_TODO and ( + $action->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_RESULT or + $action->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_USE_INGREDIENT + ) + ){ + $this->isCraftingPart = true; + } } $this->trData = new \stdClass(); diff --git a/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php b/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php index ecd9eff5d..54ca69682 100644 --- a/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php +++ b/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types; +use pocketmine\inventory\CraftingGrid; use pocketmine\inventory\transaction\action\CreativeInventoryAction; use pocketmine\inventory\transaction\action\DropItemAction; use pocketmine\inventory\transaction\action\InventoryAction; @@ -36,7 +37,6 @@ class NetworkInventoryAction{ public const SOURCE_WORLD = 2; //drop/pickup item entity public const SOURCE_CREATIVE = 3; - public const SOURCE_CRAFTING_GRID = 100; public const SOURCE_TODO = 99999; /** @@ -108,17 +108,8 @@ class NetworkInventoryAction{ break; case self::SOURCE_CREATIVE: break; - case self::SOURCE_CRAFTING_GRID: case self::SOURCE_TODO: $this->windowId = $packet->getVarInt(); - switch($this->windowId){ - /** @noinspection PhpMissingBreakStatementInspection */ - case self::SOURCE_TYPE_CRAFTING_RESULT: - $packet->isFinalCraftingPart = true; - case self::SOURCE_TYPE_CRAFTING_USE_INGREDIENT: - $packet->isCraftingPart = true; - break; - } break; default: throw new \UnexpectedValueException("Unknown inventory action source type $this->sourceType"); @@ -146,7 +137,6 @@ class NetworkInventoryAction{ break; case self::SOURCE_CREATIVE: break; - case self::SOURCE_CRAFTING_GRID: case self::SOURCE_TODO: $packet->putVarInt($this->windowId); break; @@ -173,9 +163,31 @@ class NetworkInventoryAction{ } switch($this->sourceType){ case self::SOURCE_CONTAINER: - $window = $player->getWindow($this->windowId); + if($this->windowId === ContainerIds::UI and $this->inventorySlot > 0){ + if($this->inventorySlot === 50){ + return null; //useless noise + } + if($this->inventorySlot >= 28 and $this->inventorySlot <= 31){ + $window = $player->getCraftingGrid(); + if($window->getGridWidth() !== CraftingGrid::SIZE_SMALL){ + throw new \UnexpectedValueException("Expected small crafting grid"); + } + $slot = $this->inventorySlot - 28; + }elseif($this->inventorySlot >= 32 and $this->inventorySlot <= 40){ + $window = $player->getCraftingGrid(); + if($window->getGridWidth() !== CraftingGrid::SIZE_BIG){ + throw new \UnexpectedValueException("Expected big crafting grid"); + } + $slot = $this->inventorySlot - 32; + }else{ + throw new \UnexpectedValueException("Unhandled magic UI slot offset $this->inventorySlot"); + } + }else{ + $window = $player->getWindow($this->windowId); + $slot = $this->inventorySlot; + } if($window !== null){ - return new SlotChangeAction($window, $this->inventorySlot, $this->oldItem, $this->newItem); + return new SlotChangeAction($window, $slot, $this->oldItem, $this->newItem); } throw new \UnexpectedValueException("Player " . $player->getName() . " has no open container with window ID $this->windowId"); @@ -199,7 +211,6 @@ class NetworkInventoryAction{ } return new CreativeInventoryAction($this->oldItem, $this->newItem, $type); - case self::SOURCE_CRAFTING_GRID: case self::SOURCE_TODO: //These types need special handling. switch($this->windowId){