From c9b83d72761b36034f5c2d2e8c1668ba6c55c08c Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 7 Apr 2021 18:59:01 +0100 Subject: [PATCH] Protocol changes for 1.16.220 --- src/pocketmine/Player.php | 10 +- src/pocketmine/entity/Human.php | 3 +- src/pocketmine/entity/object/ItemEntity.php | 3 +- src/pocketmine/inventory/ArmorInventory.php | 16 +- src/pocketmine/inventory/PlayerInventory.php | 3 +- .../level/particle/FloatingTextParticle.php | 3 +- .../network/mcpe/NetworkBinaryStream.php | 177 ++++++++++++------ .../mcpe/protocol/AddItemActorPacket.php | 8 +- .../network/mcpe/protocol/AddPlayerPacket.php | 8 +- .../mcpe/protocol/CraftingDataPacket.php | 12 +- .../mcpe/protocol/CraftingEventPacket.php | 14 +- .../protocol/InventoryTransactionPacket.php | 10 +- .../mcpe/protocol/MobArmorEquipmentPacket.php | 26 +-- .../mcpe/protocol/MobEquipmentPacket.php | 8 +- .../network/mcpe/protocol/ProtocolInfo.php | 6 +- .../protocol/types/NetworkInventoryAction.php | 38 ++-- .../types/inventory/CreativeContentEntry.php | 4 +- .../types/inventory/ItemStackWrapper.php | 17 +- .../inventory/ReleaseItemTransactionData.php | 11 +- .../types/inventory/TransactionData.php | 8 +- .../UseItemOnEntityTransactionData.php | 11 +- .../inventory/UseItemTransactionData.php | 11 +- ...catedCraftingResultsStackRequestAction.php | 4 +- 23 files changed, 232 insertions(+), 179 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index d090a57e0..43fe198dc 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2447,7 +2447,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_USE_INGREDIENT ) or ( $this->craftingTransaction !== null && - !$networkInventoryAction->oldItem->equalsExact($networkInventoryAction->newItem) && + !$networkInventoryAction->oldItem->getItemStack()->equalsExact($networkInventoryAction->newItem->getItemStack()) && $networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER && $networkInventoryAction->windowId === ContainerIds::UI && $networkInventoryAction->inventorySlot === UIInventorySlotOffset::CREATED_ITEM_OUTPUT @@ -2552,7 +2552,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ if($this->level->useItemOn($blockVector, $item, $face, $packet->trData->getClickPos(), $this, true)){ return true; } - }elseif(!$this->inventory->getItemInHand()->equals($packet->trData->getItemInHand())){ + }elseif(!$this->inventory->getItemInHand()->equals($packet->trData->getItemInHand()->getItemStack())){ $this->inventory->sendHeldItem($this); }else{ $item = $this->inventory->getItemInHand(); @@ -2644,7 +2644,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ if($this->isCreative()){ $item = $this->inventory->getItemInHand(); - }elseif(!$this->inventory->getItemInHand()->equals($packet->trData->getItemInHand())){ + }elseif(!$this->inventory->getItemInHand()->equals($packet->trData->getItemInHand()->getItemStack())){ $this->inventory->sendHeldItem($this); return true; }else{ @@ -2814,8 +2814,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $item = $this->inventory->getItem($packet->hotbarSlot); - if(!$item->equals($packet->item)){ - $this->server->getLogger()->debug("Tried to equip " . $packet->item . " but have " . $item . " in target slot"); + if(!$item->equals($packet->item->getItemStack())){ + $this->server->getLogger()->debug("Tried to equip " . $packet->item->getItemStack() . " but have " . $item . " in target slot"); $this->inventory->sendContents($this); return false; } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 086c8aacc..7feccd73e 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -54,6 +54,7 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayerSkinPacket; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\network\mcpe\protocol\types\PlayerListEntry; use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton; use pocketmine\Player; @@ -813,7 +814,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $pk->motion = $this->getMotion(); $pk->yaw = $this->yaw; $pk->pitch = $this->pitch; - $pk->item = $this->getInventory()->getItemInHand(); + $pk->item = ItemStackWrapper::legacy($this->getInventory()->getItemInHand()); $pk->metadata = $this->propertyManager->getAll(); $player->dataPacket($pk); diff --git a/src/pocketmine/entity/object/ItemEntity.php b/src/pocketmine/entity/object/ItemEntity.php index 5988e6136..0ea2af38c 100644 --- a/src/pocketmine/entity/object/ItemEntity.php +++ b/src/pocketmine/entity/object/ItemEntity.php @@ -30,6 +30,7 @@ use pocketmine\event\inventory\InventoryPickupItemEvent; use pocketmine\item\Item; use pocketmine\network\mcpe\protocol\AddItemActorPacket; use pocketmine\network\mcpe\protocol\TakeItemActorPacket; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\Player; use function get_class; @@ -173,7 +174,7 @@ class ItemEntity extends Entity{ $pk->entityRuntimeId = $this->getId(); $pk->position = $this->asVector3(); $pk->motion = $this->getMotion(); - $pk->item = $this->getItem(); + $pk->item = ItemStackWrapper::legacy($this->getItem()); $pk->metadata = $this->propertyManager->getAll(); $player->dataPacket($pk); diff --git a/src/pocketmine/inventory/ArmorInventory.php b/src/pocketmine/inventory/ArmorInventory.php index 9e204a157..95041c502 100644 --- a/src/pocketmine/inventory/ArmorInventory.php +++ b/src/pocketmine/inventory/ArmorInventory.php @@ -98,10 +98,10 @@ class ArmorInventory extends BaseInventory{ $pk = new MobArmorEquipmentPacket(); $pk->entityRuntimeId = $this->getHolder()->getId(); - $pk->head = $this->getHelmet(); - $pk->chest = $this->getChestplate(); - $pk->legs = $this->getLeggings(); - $pk->feet = $this->getBoots(); + $pk->head = ItemStackWrapper::legacy($this->getHelmet()); + $pk->chest = ItemStackWrapper::legacy($this->getChestplate()); + $pk->legs = ItemStackWrapper::legacy($this->getLeggings()); + $pk->feet = ItemStackWrapper::legacy($this->getBoots()); $pk->encode(); foreach($target as $player){ @@ -126,10 +126,10 @@ class ArmorInventory extends BaseInventory{ $pk = new MobArmorEquipmentPacket(); $pk->entityRuntimeId = $this->getHolder()->getId(); - $pk->head = $this->getHelmet(); - $pk->chest = $this->getChestplate(); - $pk->legs = $this->getLeggings(); - $pk->feet = $this->getBoots(); + $pk->head = ItemStackWrapper::legacy($this->getHelmet()); + $pk->chest = ItemStackWrapper::legacy($this->getChestplate()); + $pk->legs = ItemStackWrapper::legacy($this->getLeggings()); + $pk->feet = ItemStackWrapper::legacy($this->getBoots()); $pk->encode(); foreach($target as $player){ diff --git a/src/pocketmine/inventory/PlayerInventory.php b/src/pocketmine/inventory/PlayerInventory.php index ddf1dfe90..edfd0ea9c 100644 --- a/src/pocketmine/inventory/PlayerInventory.php +++ b/src/pocketmine/inventory/PlayerInventory.php @@ -30,6 +30,7 @@ use pocketmine\network\mcpe\protocol\CreativeContentPacket; use pocketmine\network\mcpe\protocol\MobEquipmentPacket; use pocketmine\network\mcpe\protocol\types\ContainerIds; use pocketmine\network\mcpe\protocol\types\inventory\CreativeContentEntry; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\Player; use function array_map; use function in_array; @@ -165,7 +166,7 @@ class PlayerInventory extends BaseInventory{ $pk = new MobEquipmentPacket(); $pk->entityRuntimeId = $this->getHolder()->getId(); - $pk->item = $item; + $pk->item = ItemStackWrapper::legacy($item); $pk->inventorySlot = $pk->hotbarSlot = $this->getHeldItemIndex(); $pk->windowId = ContainerIds::INVENTORY; diff --git a/src/pocketmine/level/particle/FloatingTextParticle.php b/src/pocketmine/level/particle/FloatingTextParticle.php index 20942ec4b..404d75c34 100644 --- a/src/pocketmine/level/particle/FloatingTextParticle.php +++ b/src/pocketmine/level/particle/FloatingTextParticle.php @@ -31,6 +31,7 @@ use pocketmine\math\Vector3; use pocketmine\network\mcpe\protocol\AddPlayerPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\RemoveActorPacket; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\network\mcpe\protocol\types\PlayerListEntry; use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton; use pocketmine\utils\UUID; @@ -104,7 +105,7 @@ class FloatingTextParticle extends Particle{ $pk->username = $name; $pk->entityRuntimeId = $this->entityId; $pk->position = $this->asVector3(); //TODO: check offset - $pk->item = ItemFactory::get(Item::AIR, 0, 0); + $pk->item = ItemStackWrapper::legacy(ItemFactory::get(Item::AIR, 0, 0)); $flags = ( 1 << Entity::DATA_FLAG_IMMOBILE diff --git a/src/pocketmine/network/mcpe/NetworkBinaryStream.php b/src/pocketmine/network/mcpe/NetworkBinaryStream.php index a045ce3e5..506b7706d 100644 --- a/src/pocketmine/network/mcpe/NetworkBinaryStream.php +++ b/src/pocketmine/network/mcpe/NetworkBinaryStream.php @@ -25,6 +25,7 @@ namespace pocketmine\network\mcpe; #include +use pocketmine\block\BlockIds; use pocketmine\entity\Attribute; use pocketmine\entity\Entity; use pocketmine\item\Durable; @@ -32,12 +33,14 @@ use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\item\ItemIds; use pocketmine\math\Vector3; +use pocketmine\nbt\LittleEndianNBTStream; use pocketmine\nbt\NetworkLittleEndianNBTStream; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\NamedTag; use pocketmine\network\mcpe\convert\ItemTranslator; use pocketmine\network\mcpe\convert\ItemTypeDictionary; +use pocketmine\network\mcpe\convert\RuntimeBlockMapping; use pocketmine\network\mcpe\protocol\types\CommandOriginData; use pocketmine\network\mcpe\protocol\types\EntityLink; use pocketmine\network\mcpe\protocol\types\GameRuleType; @@ -58,6 +61,7 @@ class NetworkBinaryStream extends BinaryStream{ private const DAMAGE_TAG = "Damage"; //TAG_Int private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___"; + private const PM_META_TAG = "___Meta___"; public function getString() : string{ return $this->get($this->getUnsignedVarInt()); @@ -193,83 +197,122 @@ class NetworkBinaryStream extends BinaryStream{ $this->putString($image->getData()); } - public function getSlot() : Item{ + public function getItemStackWithoutStackId() : Item{ + return $this->getItemStack(function() : void{ + //NOOP + }); + } + + public function putItemStackWithoutStackId(Item $item) : void{ + $this->putItemStack($item, function() : void{ + //NOOP + }); + } + + /** + * @phpstan-param \Closure(NetworkBinaryStream) : void $readExtraCrapInTheMiddle + */ + public function getItemStack(\Closure $readExtraCrapInTheMiddle) : Item{ $netId = $this->getVarInt(); if($netId === 0){ return ItemFactory::get(0, 0, 0); } - $auxValue = $this->getVarInt(); - $netData = $auxValue >> 8; - $cnt = $auxValue & 0xff; + $cnt = $this->getLShort(); + $netData = $this->getUnsignedVarInt(); [$id, $meta] = ItemTranslator::getInstance()->fromNetworkId($netId, $netData); - $nbtLen = $this->getLShort(); + $readExtraCrapInTheMiddle($this); - /** @var CompoundTag|null $nbt */ - $nbt = null; - if($nbtLen === 0xffff){ - $nbtDataVersion = $this->getByte(); - if($nbtDataVersion !== 1){ - throw new \UnexpectedValueException("Unexpected NBT data version $nbtDataVersion"); + $this->getVarInt(); + + $extraData = new NetworkBinaryStream($this->getString()); + return (static function() use ($extraData, $netId, $id, $meta, $cnt) : Item{ + $nbtLen = $extraData->getLShort(); + + /** @var CompoundTag|null $nbt */ + $nbt = null; + if($nbtLen === 0xffff){ + $nbtDataVersion = $extraData->getByte(); + if($nbtDataVersion !== 1){ + throw new \UnexpectedValueException("Unexpected NBT data version $nbtDataVersion"); + } + $decodedNBT = (new LittleEndianNBTStream())->read($extraData->buffer, false, $extraData->offset, 512); + if(!($decodedNBT instanceof CompoundTag)){ + throw new \UnexpectedValueException("Unexpected root tag type for itemstack"); + } + $nbt = $decodedNBT; + }elseif($nbtLen !== 0){ + throw new \UnexpectedValueException("Unexpected fake NBT length $nbtLen"); } - $decodedNBT = (new NetworkLittleEndianNBTStream())->read($this->buffer, false, $this->offset, 512); - if(!($decodedNBT instanceof CompoundTag)){ - throw new \UnexpectedValueException("Unexpected root tag type for itemstack"); + + //TODO + for($i = 0, $canPlaceOn = $extraData->getLInt(); $i < $canPlaceOn; ++$i){ + $extraData->get($extraData->getLShort()); } - $nbt = $decodedNBT; - }elseif($nbtLen !== 0){ - throw new \UnexpectedValueException("Unexpected fake NBT length $nbtLen"); - } - //TODO - for($i = 0, $canPlaceOn = $this->getVarInt(); $i < $canPlaceOn; ++$i){ - $this->getString(); - } + //TODO + for($i = 0, $canDestroy = $extraData->getLInt(); $i < $canDestroy; ++$i){ + $extraData->get($extraData->getLShort()); + } - //TODO - for($i = 0, $canDestroy = $this->getVarInt(); $i < $canDestroy; ++$i){ - $this->getString(); - } - - if($netId === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){ - $this->getVarLong(); //"blocking tick" (ffs mojang) - } - if($nbt !== null){ - if($nbt->hasTag(self::DAMAGE_TAG, IntTag::class)){ - $meta = $nbt->getInt(self::DAMAGE_TAG); - $nbt->removeTag(self::DAMAGE_TAG); - if(($conflicted = $nbt->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){ - $nbt->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION); - $conflicted->setName(self::DAMAGE_TAG); - $nbt->setTag($conflicted); - }elseif($nbt->count() === 0){ - $nbt = null; + if($netId === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){ + $extraData->getLLong(); //"blocking tick" (ffs mojang) + } + if($nbt !== null){ + if($nbt->hasTag(self::DAMAGE_TAG, IntTag::class)){ + $meta = $nbt->getInt(self::DAMAGE_TAG); + $nbt->removeTag(self::DAMAGE_TAG); + if(($conflicted = $nbt->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){ + $nbt->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION); + $conflicted->setName(self::DAMAGE_TAG); + $nbt->setTag($conflicted); + }elseif($nbt->count() === 0){ + $nbt = null; + } + }elseif(($metaTag = $nbt->getTag(self::PM_META_TAG)) instanceof IntTag){ + //TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the + //client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata + //client-side. Aside from being very annoying, this also breaks various server-side behaviours. + $meta = $metaTag->getValue(); + $nbt->removeTag(self::PM_META_TAG); + if($nbt->count() === 0){ + $nbt = null; + } } } - } - return ItemFactory::get($id, $meta, $cnt, $nbt); + return ItemFactory::get($id, $meta, $cnt, $nbt); + })(); } - public function putSlot(Item $item) : void{ + /** + * @phpstan-param \Closure(NetworkBinaryStream) : void $writeExtraCrapInTheMiddle + */ + public function putItemStack(Item $item, \Closure $writeExtraCrapInTheMiddle) : void{ if($item->getId() === 0){ $this->putVarInt(0); return; } - [$netId, $netData] = ItemTranslator::getInstance()->toNetworkId($item->getId(), $item->getDamage()); + $coreData = $item->getDamage(); + [$netId, $netData] = ItemTranslator::getInstance()->toNetworkId($item->getId(), $coreData); $this->putVarInt($netId); - $auxValue = (($netData & 0x7fff) << 8) | $item->getCount(); - $this->putVarInt($auxValue); + $this->putLShort($item->getCount()); + $this->putUnsignedVarInt($netData); + + $writeExtraCrapInTheMiddle($this); + + $block = $item->getBlock(); + $this->putVarInt($block->getId() === BlockIds::AIR ? 0 : RuntimeBlockMapping::toStaticRuntimeId($block->getId(), $block->getDamage())); $nbt = null; if($item->hasCompoundTag()){ $nbt = clone $item->getNamedTag(); } - if($item instanceof Durable and $item->getDamage() > 0){ + if($item instanceof Durable and $coreData > 0){ if($nbt !== null){ if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){ $nbt->removeTag(self::DAMAGE_TAG); @@ -279,23 +322,37 @@ class NetworkBinaryStream extends BinaryStream{ }else{ $nbt = new CompoundTag(); } - $nbt->setInt(self::DAMAGE_TAG, $item->getDamage()); + $nbt->setInt(self::DAMAGE_TAG, $coreData); + }elseif($block->getId() !== BlockIds::AIR && $coreData !== 0){ + //TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the + //client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata + //client-side. Aside from being very annoying, this also breaks various server-side behaviours. + if($nbt === null){ + $nbt = new CompoundTag(); + } + $nbt->setInt(self::PM_META_TAG, $coreData); } - if($nbt !== null){ - $this->putLShort(0xffff); - $this->putByte(1); //TODO: NBT data version (?) - $this->put((new NetworkLittleEndianNBTStream())->write($nbt)); - }else{ - $this->putLShort(0); - } + $this->putString( + (static function() use ($nbt, $netId) : string{ + $extraData = new NetworkBinaryStream(); - $this->putVarInt(0); //CanPlaceOn entry count (TODO) - $this->putVarInt(0); //CanDestroy entry count (TODO) + if($nbt !== null){ + $extraData->putLShort(0xffff); + $extraData->putByte(1); //TODO: NBT data version (?) + $extraData->put((new LittleEndianNBTStream())->write($nbt)); + }else{ + $extraData->putLShort(0); + } - if($netId === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){ - $this->putVarLong(0); //"blocking tick" (ffs mojang) - } + $extraData->putLInt(0); //CanPlaceOn entry count (TODO) + $extraData->putLInt(0); //CanDestroy entry count (TODO) + + if($netId === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){ + $extraData->putLLong(0); //"blocking tick" (ffs mojang) + } + return $extraData->getBuffer(); + })()); } public function getRecipeIngredient() : Item{ diff --git a/src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php b/src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php index 9e7bb0d16..dbe1fec4e 100644 --- a/src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php @@ -25,9 +25,9 @@ namespace pocketmine\network\mcpe\protocol; #include -use pocketmine\item\Item; use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; class AddItemActorPacket extends DataPacket{ public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET; @@ -36,7 +36,7 @@ class AddItemActorPacket extends DataPacket{ public $entityUniqueId = null; //TODO /** @var int */ public $entityRuntimeId; - /** @var Item */ + /** @var ItemStackWrapper */ public $item; /** @var Vector3 */ public $position; @@ -53,7 +53,7 @@ class AddItemActorPacket extends DataPacket{ protected function decodePayload(){ $this->entityUniqueId = $this->getEntityUniqueId(); $this->entityRuntimeId = $this->getEntityRuntimeId(); - $this->item = $this->getSlot(); + $this->item = ItemStackWrapper::read($this); $this->position = $this->getVector3(); $this->motion = $this->getVector3(); $this->metadata = $this->getEntityMetadata(); @@ -63,7 +63,7 @@ class AddItemActorPacket extends DataPacket{ protected function encodePayload(){ $this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId); $this->putEntityRuntimeId($this->entityRuntimeId); - $this->putSlot($this->item); + $this->item->write($this); $this->putVector3($this->position); $this->putVector3Nullable($this->motion); $this->putEntityMetadata($this->metadata); diff --git a/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php b/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php index 2e249a265..297469964 100644 --- a/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php @@ -25,11 +25,11 @@ namespace pocketmine\network\mcpe\protocol; #include -use pocketmine\item\Item; use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\protocol\types\DeviceOS; use pocketmine\network\mcpe\protocol\types\EntityLink; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\utils\UUID; use function count; @@ -56,7 +56,7 @@ class AddPlayerPacket extends DataPacket{ public $yaw = 0.0; /** @var float|null */ public $headYaw = null; //TODO - /** @var Item */ + /** @var ItemStackWrapper */ public $item; /** * @var mixed[][] @@ -98,7 +98,7 @@ class AddPlayerPacket extends DataPacket{ $this->pitch = $this->getLFloat(); $this->yaw = $this->getLFloat(); $this->headYaw = $this->getLFloat(); - $this->item = $this->getSlot(); + $this->item = ItemStackWrapper::read($this); $this->metadata = $this->getEntityMetadata(); $this->uvarint1 = $this->getUnsignedVarInt(); @@ -129,7 +129,7 @@ class AddPlayerPacket extends DataPacket{ $this->putLFloat($this->pitch); $this->putLFloat($this->yaw); $this->putLFloat($this->headYaw ?? $this->yaw); - $this->putSlot($this->item); + $this->item->write($this); $this->putEntityMetadata($this->metadata); $this->putUnsignedVarInt($this->uvarint1); diff --git a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php index 1affe2cb5..da2ad43fb 100644 --- a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php @@ -91,7 +91,7 @@ class CraftingDataPacket extends DataPacket{ $resultCount = $this->getUnsignedVarInt(); $entry["output"] = []; for($k = 0; $k < $resultCount; ++$k){ - $entry["output"][] = $this->getSlot(); + $entry["output"][] = $this->getItemStackWithoutStackId(); } $entry["uuid"] = $this->getUUID()->toString(); $entry["block"] = $this->getString(); @@ -113,7 +113,7 @@ class CraftingDataPacket extends DataPacket{ $resultCount = $this->getUnsignedVarInt(); $entry["output"] = []; for($k = 0; $k < $resultCount; ++$k){ - $entry["output"][] = $this->getSlot(); + $entry["output"][] = $this->getItemStackWithoutStackId(); } $entry["uuid"] = $this->getUUID()->toString(); $entry["block"] = $this->getString(); @@ -131,7 +131,7 @@ class CraftingDataPacket extends DataPacket{ [$inputId, $inputData] = ItemTranslator::getInstance()->fromNetworkIdWithWildcardHandling($inputIdNet, $inputMetaNet); } $entry["input"] = ItemFactory::get($inputId, $inputData); - $entry["output"] = $out = $this->getSlot(); + $entry["output"] = $out = $this->getItemStackWithoutStackId(); if($out->getDamage() === 0x7fff){ $out->setDamage(0); //TODO HACK: some 1.12 furnace recipe outputs have wildcard damage values } @@ -198,7 +198,7 @@ class CraftingDataPacket extends DataPacket{ $results = $recipe->getResults(); $stream->putUnsignedVarInt(count($results)); foreach($results as $item){ - $stream->putSlot($item); + $stream->putItemStackWithoutStackId($item); } $stream->put(str_repeat("\x00", 16)); //Null UUID @@ -223,7 +223,7 @@ class CraftingDataPacket extends DataPacket{ $results = $recipe->getResults(); $stream->putUnsignedVarInt(count($results)); foreach($results as $item){ - $stream->putSlot($item); + $stream->putItemStackWithoutStackId($item); } $stream->put(str_repeat("\x00", 16)); //Null UUID @@ -244,7 +244,7 @@ class CraftingDataPacket extends DataPacket{ } $stream->putVarInt($netId); $stream->putVarInt($netData); - $stream->putSlot($recipe->getResult()); + $stream->putItemStackWithoutStackId($recipe->getResult()); $stream->putString("furnace"); //TODO: blocktype (no prefix) (this might require internal API breaks) return CraftingDataPacket::ENTRY_FURNACE_DATA; } diff --git a/src/pocketmine/network/mcpe/protocol/CraftingEventPacket.php b/src/pocketmine/network/mcpe/protocol/CraftingEventPacket.php index 91a57e49e..b937741b2 100644 --- a/src/pocketmine/network/mcpe/protocol/CraftingEventPacket.php +++ b/src/pocketmine/network/mcpe/protocol/CraftingEventPacket.php @@ -25,8 +25,8 @@ namespace pocketmine\network\mcpe\protocol; #include -use pocketmine\item\Item; use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\utils\UUID; use function count; @@ -39,9 +39,9 @@ class CraftingEventPacket extends DataPacket{ public $type; /** @var UUID */ public $id; - /** @var Item[] */ + /** @var ItemStackWrapper[] */ public $input = []; - /** @var Item[] */ + /** @var ItemStackWrapper[] */ public $output = []; public function clean(){ @@ -57,12 +57,12 @@ class CraftingEventPacket extends DataPacket{ $size = $this->getUnsignedVarInt(); for($i = 0; $i < $size and $i < 128; ++$i){ - $this->input[] = $this->getSlot(); + $this->input[] = ItemStackWrapper::read($this); } $size = $this->getUnsignedVarInt(); for($i = 0; $i < $size and $i < 128; ++$i){ - $this->output[] = $this->getSlot(); + $this->output[] = ItemStackWrapper::read($this); } } @@ -73,12 +73,12 @@ class CraftingEventPacket extends DataPacket{ $this->putUnsignedVarInt(count($this->input)); foreach($this->input as $item){ - $this->putSlot($item); + $item->write($this); } $this->putUnsignedVarInt(count($this->output)); foreach($this->output as $item){ - $this->putSlot($item); + $item->write($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php b/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php index 0fa447ed6..aee312b45 100644 --- a/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php +++ b/src/pocketmine/network/mcpe/protocol/InventoryTransactionPacket.php @@ -49,8 +49,6 @@ class InventoryTransactionPacket extends DataPacket{ public $requestId; /** @var InventoryTransactionChangedSlotsHack[] */ public $requestChangedSlots; - /** @var bool */ - public $hasItemStackIds; /** @var TransactionData */ public $trData; @@ -66,8 +64,6 @@ class InventoryTransactionPacket extends DataPacket{ $transactionType = $in->getUnsignedVarInt(); - $this->hasItemStackIds = $in->getBool(); - switch($transactionType){ case self::TYPE_NORMAL: $this->trData = new NormalTransactionData(); @@ -88,7 +84,7 @@ class InventoryTransactionPacket extends DataPacket{ throw new PacketDecodeException("Unknown transaction type $transactionType"); } - $this->trData->decode($in, $this->hasItemStackIds); + $this->trData->decode($in); } protected function encodePayload() : void{ @@ -103,9 +99,7 @@ class InventoryTransactionPacket extends DataPacket{ $out->putUnsignedVarInt($this->trData->getTypeId()); - $out->putBool($this->hasItemStackIds); - - $this->trData->encode($out, $this->hasItemStackIds); + $this->trData->encode($out); } public function handle(PacketHandlerInterface $handler) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php b/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php index 6af905a10..0a01441c1 100644 --- a/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php +++ b/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php @@ -25,8 +25,8 @@ namespace pocketmine\network\mcpe\protocol; #include -use pocketmine\item\Item; use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; class MobArmorEquipmentPacket extends DataPacket{ public const NETWORK_ID = ProtocolInfo::MOB_ARMOR_EQUIPMENT_PACKET; @@ -36,29 +36,29 @@ class MobArmorEquipmentPacket extends DataPacket{ //this intentionally doesn't use an array because we don't want any implicit dependencies on internal order - /** @var Item */ + /** @var ItemStackWrapper */ public $head; - /** @var Item */ + /** @var ItemStackWrapper */ public $chest; - /** @var Item */ + /** @var ItemStackWrapper */ public $legs; - /** @var Item */ + /** @var ItemStackWrapper */ public $feet; protected function decodePayload(){ $this->entityRuntimeId = $this->getEntityRuntimeId(); - $this->head = $this->getSlot(); - $this->chest = $this->getSlot(); - $this->legs = $this->getSlot(); - $this->feet = $this->getSlot(); + $this->head = ItemStackWrapper::read($this); + $this->chest = ItemStackWrapper::read($this); + $this->legs = ItemStackWrapper::read($this); + $this->feet = ItemStackWrapper::read($this); } protected function encodePayload(){ $this->putEntityRuntimeId($this->entityRuntimeId); - $this->putSlot($this->head); - $this->putSlot($this->chest); - $this->putSlot($this->legs); - $this->putSlot($this->feet); + $this->head->write($this); + $this->chest->write($this); + $this->legs->write($this); + $this->feet->write($this); } public function handle(NetworkSession $session) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php b/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php index 723100c70..9d5c72f86 100644 --- a/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php +++ b/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php @@ -25,15 +25,15 @@ namespace pocketmine\network\mcpe\protocol; #include -use pocketmine\item\Item; use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; class MobEquipmentPacket extends DataPacket{ public const NETWORK_ID = ProtocolInfo::MOB_EQUIPMENT_PACKET; /** @var int */ public $entityRuntimeId; - /** @var Item */ + /** @var ItemStackWrapper */ public $item; /** @var int */ public $inventorySlot; @@ -44,7 +44,7 @@ class MobEquipmentPacket extends DataPacket{ protected function decodePayload(){ $this->entityRuntimeId = $this->getEntityRuntimeId(); - $this->item = $this->getSlot(); + $this->item = ItemStackWrapper::read($this); $this->inventorySlot = $this->getByte(); $this->hotbarSlot = $this->getByte(); $this->windowId = $this->getByte(); @@ -52,7 +52,7 @@ class MobEquipmentPacket extends DataPacket{ protected function encodePayload(){ $this->putEntityRuntimeId($this->entityRuntimeId); - $this->putSlot($this->item); + $this->item->write($this); $this->putByte($this->inventorySlot); $this->putByte($this->hotbarSlot); $this->putByte($this->windowId); diff --git a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php index ec8d667b5..8e0494ddc 100644 --- a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php +++ b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php @@ -37,11 +37,11 @@ interface ProtocolInfo{ */ /** Actual Minecraft: PE protocol version */ - public const CURRENT_PROTOCOL = 428; + public const CURRENT_PROTOCOL = 431; /** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */ - public const MINECRAFT_VERSION = 'v1.16.210'; + public const MINECRAFT_VERSION = 'v1.16.220'; /** Version number sent to clients in ping responses. */ - public const MINECRAFT_VERSION_NETWORK = '1.16.210'; + public const MINECRAFT_VERSION_NETWORK = '1.16.220'; public const LOGIN_PACKET = 0x01; public const PLAY_STATUS_PACKET = 0x02; diff --git a/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php b/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php index b06235dd2..6b582a81d 100644 --- a/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php +++ b/src/pocketmine/network/mcpe/protocol/types/NetworkInventoryAction.php @@ -30,6 +30,7 @@ use pocketmine\inventory\transaction\action\InventoryAction; use pocketmine\inventory\transaction\action\SlotChangeAction; use pocketmine\item\Item; use pocketmine\network\mcpe\NetworkBinaryStream; +use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\network\mcpe\protocol\types\inventory\UIInventorySlotOffset; use pocketmine\Player; use function array_key_exists; @@ -79,17 +80,15 @@ class NetworkInventoryAction{ public $sourceFlags = 0; /** @var int */ public $inventorySlot; - /** @var Item */ + /** @var ItemStackWrapper */ public $oldItem; - /** @var Item */ + /** @var ItemStackWrapper */ public $newItem; - /** @var int|null */ - public $newItemStackId = null; /** * @return $this */ - public function read(NetworkBinaryStream $packet, bool $hasItemStackIds){ + public function read(NetworkBinaryStream $packet){ $this->sourceType = $packet->getUnsignedVarInt(); switch($this->sourceType){ @@ -109,11 +108,8 @@ class NetworkInventoryAction{ } $this->inventorySlot = $packet->getUnsignedVarInt(); - $this->oldItem = $packet->getSlot(); - $this->newItem = $packet->getSlot(); - if($hasItemStackIds){ - $this->newItemStackId = $packet->readGenericTypeNetworkId(); - } + $this->oldItem = ItemStackWrapper::read($packet); + $this->newItem = ItemStackWrapper::read($packet); return $this; } @@ -121,7 +117,7 @@ class NetworkInventoryAction{ /** * @return void */ - public function write(NetworkBinaryStream $packet, bool $hasItemStackIds){ + public function write(NetworkBinaryStream $packet){ $packet->putUnsignedVarInt($this->sourceType); switch($this->sourceType){ @@ -141,14 +137,8 @@ class NetworkInventoryAction{ } $packet->putUnsignedVarInt($this->inventorySlot); - $packet->putSlot($this->oldItem); - $packet->putSlot($this->newItem); - if($hasItemStackIds){ - if($this->newItemStackId === null){ - throw new \InvalidStateException("Item stack ID for newItem must be provided"); - } - $packet->writeGenericTypeNetworkId($this->newItemStackId); - } + $this->oldItem->write($packet); + $this->newItem->write($packet); } /** @@ -157,7 +147,9 @@ class NetworkInventoryAction{ * @throws \UnexpectedValueException */ public function createInventoryAction(Player $player){ - if($this->oldItem->equalsExact($this->newItem)){ + $oldItem = $this->oldItem->getItemStack(); + $newItem = $this->newItem->getItemStack(); + if($oldItem->equalsExact($newItem)){ //filter out useless noise in 1.13 return null; } @@ -187,7 +179,7 @@ class NetworkInventoryAction{ $slot = $this->inventorySlot; } if($window !== null){ - return new SlotChangeAction($window, $slot, $this->oldItem, $this->newItem); + return new SlotChangeAction($window, $slot, $oldItem, $newItem); } throw new \UnexpectedValueException("Player " . $player->getName() . " has no open container with window ID $this->windowId"); @@ -196,7 +188,7 @@ class NetworkInventoryAction{ throw new \UnexpectedValueException("Only expecting drop-item world actions from the client!"); } - return new DropItemAction($this->newItem); + return new DropItemAction($newItem); case self::SOURCE_CREATIVE: switch($this->inventorySlot){ case self::ACTION_MAGIC_SLOT_CREATIVE_DELETE_ITEM: @@ -210,7 +202,7 @@ class NetworkInventoryAction{ } - return new CreativeInventoryAction($this->oldItem, $this->newItem, $type); + return new CreativeInventoryAction($oldItem, $newItem, $type); case self::SOURCE_TODO: //These types need special handling. switch($this->windowId){ diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/CreativeContentEntry.php b/src/pocketmine/network/mcpe/protocol/types/inventory/CreativeContentEntry.php index ce66c6786..185c9c489 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/CreativeContentEntry.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/CreativeContentEntry.php @@ -44,12 +44,12 @@ final class CreativeContentEntry{ public static function read(NetworkBinaryStream $in) : self{ $entryId = $in->readGenericTypeNetworkId(); - $item = $in->getSlot(); + $item = $in->getItemStackWithoutStackId(); return new self($entryId, $item); } public function write(NetworkBinaryStream $out) : void{ $out->writeGenericTypeNetworkId($this->entryId); - $out->putSlot($this->item); + $out->putItemStackWithoutStackId($this->item); } } diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/ItemStackWrapper.php b/src/pocketmine/network/mcpe/protocol/types/inventory/ItemStackWrapper.php index 44a552f39..07ce6bf73 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/ItemStackWrapper.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/ItemStackWrapper.php @@ -47,13 +47,22 @@ final class ItemStackWrapper{ public function getItemStack() : Item{ return $this->itemStack; } public static function read(NetworkBinaryStream $in) : self{ - $stackId = $in->readGenericTypeNetworkId(); - $stack = $in->getSlot(); + $stackId = 0; + $stack = $in->getItemStack(function(NetworkBinaryStream $in) use (&$stackId) : void{ + $hasNetId = $in->getBool(); + if($hasNetId){ + $stackId = $in->readGenericTypeNetworkId(); + } + }); return new self($stackId, $stack); } public function write(NetworkBinaryStream $out) : void{ - $out->writeGenericTypeNetworkId($this->stackId); - $out->putSlot($this->itemStack); + $out->putItemStack($this->itemStack, function(NetworkBinaryStream $out) : void{ + $out->putBool($this->stackId !== 0); + if($this->stackId !== 0){ + $out->writeGenericTypeNetworkId($this->stackId); + } + }); } } diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/ReleaseItemTransactionData.php b/src/pocketmine/network/mcpe/protocol/types/inventory/ReleaseItemTransactionData.php index 96b359d17..5f05af836 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/ReleaseItemTransactionData.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/ReleaseItemTransactionData.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types\inventory; -use pocketmine\item\Item as ItemStack; use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkBinaryStream as PacketSerializer; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; @@ -37,7 +36,7 @@ class ReleaseItemTransactionData extends TransactionData{ private $actionType; /** @var int */ private $hotbarSlot; - /** @var ItemStack */ + /** @var ItemStackWrapper */ private $itemInHand; /** @var Vector3 */ private $headPos; @@ -50,7 +49,7 @@ class ReleaseItemTransactionData extends TransactionData{ return $this->hotbarSlot; } - public function getItemInHand() : ItemStack{ + public function getItemInHand() : ItemStackWrapper{ return $this->itemInHand; } @@ -65,21 +64,21 @@ class ReleaseItemTransactionData extends TransactionData{ protected function decodeData(PacketSerializer $stream) : void{ $this->actionType = $stream->getUnsignedVarInt(); $this->hotbarSlot = $stream->getVarInt(); - $this->itemInHand = $stream->getSlot(); + $this->itemInHand = ItemStackWrapper::read($stream); $this->headPos = $stream->getVector3(); } protected function encodeData(PacketSerializer $stream) : void{ $stream->putUnsignedVarInt($this->actionType); $stream->putVarInt($this->hotbarSlot); - $stream->putSlot($this->itemInHand); + $this->itemInHand->write($stream); $stream->putVector3($this->headPos); } /** * @param NetworkInventoryAction[] $actions */ - public static function new(array $actions, int $actionType, int $hotbarSlot, ItemStack $itemInHand, Vector3 $headPos) : self{ + public static function new(array $actions, int $actionType, int $hotbarSlot, ItemStackWrapper $itemInHand, Vector3 $headPos) : self{ $result = new self; $result->actions = $actions; $result->actionType = $actionType; diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/TransactionData.php b/src/pocketmine/network/mcpe/protocol/types/inventory/TransactionData.php index 23089c71b..1f4cc1304 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/TransactionData.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/TransactionData.php @@ -46,10 +46,10 @@ abstract class TransactionData{ * @throws BinaryDataException * @throws PacketDecodeException */ - final public function decode(PacketSerializer $stream, bool $hasItemStackIds) : void{ + final public function decode(PacketSerializer $stream) : void{ $actionCount = $stream->getUnsignedVarInt(); for($i = 0; $i < $actionCount; ++$i){ - $this->actions[] = (new NetworkInventoryAction())->read($stream, $hasItemStackIds); + $this->actions[] = (new NetworkInventoryAction())->read($stream); } $this->decodeData($stream); } @@ -60,10 +60,10 @@ abstract class TransactionData{ */ abstract protected function decodeData(PacketSerializer $stream) : void; - final public function encode(PacketSerializer $stream, bool $hasItemStackIds) : void{ + final public function encode(PacketSerializer $stream) : void{ $stream->putUnsignedVarInt(count($this->actions)); foreach($this->actions as $action){ - $action->write($stream, $hasItemStackIds); + $action->write($stream); } $this->encodeData($stream); } diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemOnEntityTransactionData.php b/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemOnEntityTransactionData.php index f88bbca73..e77f6dc1d 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemOnEntityTransactionData.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemOnEntityTransactionData.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types\inventory; -use pocketmine\item\Item as ItemStack; use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkBinaryStream as PacketSerializer; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; @@ -39,7 +38,7 @@ class UseItemOnEntityTransactionData extends TransactionData{ private $actionType; /** @var int */ private $hotbarSlot; - /** @var ItemStack */ + /** @var ItemStackWrapper */ private $itemInHand; /** @var Vector3 */ private $playerPos; @@ -58,7 +57,7 @@ class UseItemOnEntityTransactionData extends TransactionData{ return $this->hotbarSlot; } - public function getItemInHand() : ItemStack{ + public function getItemInHand() : ItemStackWrapper{ return $this->itemInHand; } @@ -78,7 +77,7 @@ class UseItemOnEntityTransactionData extends TransactionData{ $this->entityRuntimeId = $stream->getEntityRuntimeId(); $this->actionType = $stream->getUnsignedVarInt(); $this->hotbarSlot = $stream->getVarInt(); - $this->itemInHand = $stream->getSlot(); + $this->itemInHand = ItemStackWrapper::read($stream); $this->playerPos = $stream->getVector3(); $this->clickPos = $stream->getVector3(); } @@ -87,7 +86,7 @@ class UseItemOnEntityTransactionData extends TransactionData{ $stream->putEntityRuntimeId($this->entityRuntimeId); $stream->putUnsignedVarInt($this->actionType); $stream->putVarInt($this->hotbarSlot); - $stream->putSlot($this->itemInHand); + $this->itemInHand->write($stream); $stream->putVector3($this->playerPos); $stream->putVector3($this->clickPos); } @@ -95,7 +94,7 @@ class UseItemOnEntityTransactionData extends TransactionData{ /** * @param NetworkInventoryAction[] $actions */ - public static function new(array $actions, int $entityRuntimeId, int $actionType, int $hotbarSlot, ItemStack $itemInHand, Vector3 $playerPos, Vector3 $clickPos) : self{ + public static function new(array $actions, int $entityRuntimeId, int $actionType, int $hotbarSlot, ItemStackWrapper $itemInHand, Vector3 $playerPos, Vector3 $clickPos) : self{ $result = new self; $result->actions = $actions; $result->entityRuntimeId = $entityRuntimeId; diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemTransactionData.php b/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemTransactionData.php index 5c1872bea..4eeb041b1 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemTransactionData.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/UseItemTransactionData.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types\inventory; -use pocketmine\item\Item as ItemStack; use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkBinaryStream as PacketSerializer; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; @@ -42,7 +41,7 @@ class UseItemTransactionData extends TransactionData{ private $face; /** @var int */ private $hotbarSlot; - /** @var ItemStack */ + /** @var ItemStackWrapper */ private $itemInHand; /** @var Vector3 */ private $playerPos; @@ -67,7 +66,7 @@ class UseItemTransactionData extends TransactionData{ return $this->hotbarSlot; } - public function getItemInHand() : ItemStack{ + public function getItemInHand() : ItemStackWrapper{ return $this->itemInHand; } @@ -94,7 +93,7 @@ class UseItemTransactionData extends TransactionData{ $this->blockPos = new Vector3($x, $y, $z); $this->face = $stream->getVarInt(); $this->hotbarSlot = $stream->getVarInt(); - $this->itemInHand = $stream->getSlot(); + $this->itemInHand = ItemStackWrapper::read($stream); $this->playerPos = $stream->getVector3(); $this->clickPos = $stream->getVector3(); $this->blockRuntimeId = $stream->getUnsignedVarInt(); @@ -105,7 +104,7 @@ class UseItemTransactionData extends TransactionData{ $stream->putBlockPosition($this->blockPos->x, $this->blockPos->y, $this->blockPos->z); $stream->putVarInt($this->face); $stream->putVarInt($this->hotbarSlot); - $stream->putSlot($this->itemInHand); + $this->itemInHand->write($stream); $stream->putVector3($this->playerPos); $stream->putVector3($this->clickPos); $stream->putUnsignedVarInt($this->blockRuntimeId); @@ -114,7 +113,7 @@ class UseItemTransactionData extends TransactionData{ /** * @param NetworkInventoryAction[] $actions */ - public static function new(array $actions, int $actionType, Vector3 $blockPos, int $face, int $hotbarSlot, ItemStack $itemInHand, Vector3 $playerPos, Vector3 $clickPos, int $blockRuntimeId) : self{ + public static function new(array $actions, int $actionType, Vector3 $blockPos, int $face, int $hotbarSlot, ItemStackWrapper $itemInHand, Vector3 $playerPos, Vector3 $clickPos, int $blockRuntimeId) : self{ $result = new self; $result->actions = $actions; $result->actionType = $actionType; diff --git a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/DeprecatedCraftingResultsStackRequestAction.php b/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/DeprecatedCraftingResultsStackRequestAction.php index 601d1f417..4e2f42b7a 100644 --- a/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/DeprecatedCraftingResultsStackRequestAction.php +++ b/src/pocketmine/network/mcpe/protocol/types/inventory/stackrequest/DeprecatedCraftingResultsStackRequestAction.php @@ -58,7 +58,7 @@ final class DeprecatedCraftingResultsStackRequestAction extends ItemStackRequest public static function read(NetworkBinaryStream $in) : self{ $results = []; for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){ - $results[] = $in->getSlot(); + $results[] = $in->getItemStackWithoutStackId(); } $iterations = $in->getByte(); return new self($results, $iterations); @@ -67,7 +67,7 @@ final class DeprecatedCraftingResultsStackRequestAction extends ItemStackRequest public function write(NetworkBinaryStream $out) : void{ $out->putUnsignedVarInt(count($this->results)); foreach($this->results as $result){ - $out->putSlot($result); + $out->putItemStackWithoutStackId($result); } $out->putByte($this->iterations); }