use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\protocol\types\inventory\InventoryTransactionChangedSlotsHack; use pocketmine\network\mcpe\protocol\types\NetworkInventoryAction; use function count; class InventoryTransactionPacket extends DataPacket{ public const NETWORK_ID = ProtocolInfo::INVENTORY_TRANSACTION_PACKET; public const TYPE_NORMAL = 0; public const TYPE_MISMATCH = 1; public const TYPE_USE_ITEM = 2; public const TYPE_USE_ITEM_ON_ENTITY = 3; public const TYPE_RELEASE_ITEM = 4; public const USE_ITEM_ACTION_CLICK_BLOCK = 0; public const USE_ITEM_ACTION_CLICK_AIR = 1; public const USE_ITEM_ACTION_BREAK_BLOCK = 2; public const RELEASE_ITEM_ACTION_RELEASE = 0; //bow shoot public const RELEASE_ITEM_ACTION_CONSUME = 1; //eat food, drink potion public const USE_ITEM_ON_ENTITY_ACTION_INTERACT = 0; public const USE_ITEM_ON_ENTITY_ACTION_ATTACK = 1; /** @var int */ public $requestId; /** @var InventoryTransactionChangedSlotsHack[] */ public $requestChangedSlots; /** @var int */ public $transactionType; /** @var bool */ public $hasItemStackIds; /** @var NetworkInventoryAction[] */ public $actions = []; /** @var \stdClass */ public $trData; protected function decodePayload(){ $this->requestId = $this->readGenericTypeNetworkId(); $this->requestChangedSlots = []; if($this->requestId !== 0){ for($i = 0, $len = $this->getUnsignedVarInt(); $i < $len; ++$i){ $this->requestChangedSlots[] = InventoryTransactionChangedSlotsHack::read($this); } } $this->transactionType = $this->getUnsignedVarInt(); $this->hasItemStackIds = $this->getBool(); for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ $this->actions[] = $action = (new NetworkInventoryAction())->read($this, $this->hasItemStackIds); } $this->trData = new \stdClass(); switch($this->transactionType){ case self::TYPE_NORMAL: case self::TYPE_MISMATCH: //Regular ComplexInventoryTransaction doesn't read any extra data break; case self::TYPE_USE_ITEM: $this->trData->actionType = $this->getUnsignedVarInt(); $this->getBlockPosition($this->trData->x, $this->trData->y, $this->trData->z); $this->trData->face = $this->getVarInt(); $this->trData->hotbarSlot = $this->getVarInt(); $this->trData->itemInHand = $this->getSlot(); $this->trData->playerPos = $this->getVector3(); $this->trData->clickPos = $this->getVector3(); $this->trData->blockRuntimeId = $this->getUnsignedVarInt(); break; case self::TYPE_USE_ITEM_ON_ENTITY: $this->trData->entityRuntimeId = $this->getEntityRuntimeId(); $this->trData->actionType = $this->getUnsignedVarInt(); $this->trData->hotbarSlot = $this->getVarInt(); $this->trData->itemInHand = $this->getSlot(); $this->trData->playerPos = $this->getVector3(); $this->trData->clickPos = $this->getVector3(); break; case self::TYPE_RELEASE_ITEM: $this->trData->actionType = $this->getUnsignedVarInt(); $this->trData->hotbarSlot = $this->getVarInt(); $this->trData->itemInHand = $this->getSlot(); $this->trData->headPos = $this->getVector3(); break; default: throw new \UnexpectedValueException("Unknown transaction type $this->transactionType"); } } protected function encodePayload(){ $this->writeGenericTypeNetworkId($this->requestId); if($this->requestId !== 0){ $this->putUnsignedVarInt(count($this->requestChangedSlots)); foreach($this->requestChangedSlots as $changedSlots){ $changedSlots->write($this); } } $this->putUnsignedVarInt($this->transactionType); $this->putUnsignedVarInt(count($this->actions)); foreach($this->actions as $action){ $action->write($this, $this->hasItemStackIds); } switch($this->transactionType){ case self::TYPE_NORMAL: case self::TYPE_MISMATCH: break; case self::TYPE_USE_ITEM: $this->putUnsignedVarInt($this->trData->actionType); $this->putBlockPosition($this->trData->x, $this->trData->y, $this->trData->z); $this->putVarInt($this->trData->face); $this->putVarInt($this->trData->hotbarSlot); $this->putSlot($this->trData->itemInHand); $this->putVector3($this->trData->playerPos); $this->putVector3($this->trData->clickPos); $this->putUnsignedVarInt($this->trData->blockRuntimeId); break; case self::TYPE_USE_ITEM_ON_ENTITY: $this->putEntityRuntimeId($this->trData->entityRuntimeId); $this->putUnsignedVarInt($this->trData->actionType); $this->putVarInt($this->trData->hotbarSlot); $this->putSlot($this->trData->itemInHand); $this->putVector3($this->trData->playerPos); $this->putVector3($this->trData->clickPos); break; case self::TYPE_RELEASE_ITEM: $this->putUnsignedVarInt($this->trData->actionType); $this->putVarInt($this->trData->hotbarSlot); $this->putSlot($this->trData->itemInHand); $this->putVector3($this->trData->headPos); break; default: throw new \InvalidArgumentException("Unknown transaction type $this->transactionType"); } } public function handle(NetworkSession $session) : bool{ return $session->handleInventoryTransaction($this); } }