diff --git a/src/data/bedrock/item/ItemDeserializer.php b/src/data/bedrock/item/ItemDeserializer.php index 8abfb24dc..1fc93a77b 100644 --- a/src/data/bedrock/item/ItemDeserializer.php +++ b/src/data/bedrock/item/ItemDeserializer.php @@ -64,7 +64,7 @@ final class ItemDeserializer{ /** * @throws ItemTypeDeserializeException */ - public function deserialize(Data $data) : Item{ + public function deserializeType(Data $data) : Item{ if(($blockData = $data->getBlock()) !== null){ //TODO: this is rough duct tape; we need a better way to deal with this try{ @@ -84,6 +84,22 @@ final class ItemDeserializer{ return ($this->deserializers[$id])($data); } + /** + * @throws ItemTypeDeserializeException + */ + public function deserializeStack(SavedItemStackData $data) : Item{ + $itemStack = $this->deserializeType($data->getTypeData()); + + $itemStack->setCount($data->getCount()); + if(($tagTag = $data->getTypeData()->getTag()) !== null){ + $itemStack->setNamedTag(clone $tagTag); + } + + //TODO: canDestroy, canPlaceOn, wasPickedUp are currently unused + + return $itemStack; + } + private function registerDeserializers() : void{ $this->map(Ids::ACACIA_BOAT, fn() => Items::ACACIA_BOAT()); $this->map(Ids::ACACIA_DOOR, fn() => Blocks::ACACIA_DOOR()->asItem()); diff --git a/src/data/bedrock/item/ItemSerializer.php b/src/data/bedrock/item/ItemSerializer.php index 0c704fe00..5c6ed2b44 100644 --- a/src/data/bedrock/item/ItemSerializer.php +++ b/src/data/bedrock/item/ItemSerializer.php @@ -102,7 +102,7 @@ final class ItemSerializer{ * * @throws ItemTypeSerializeException */ - public function serialize(Item $item) : Data{ + public function serializeType(Item $item) : Data{ if($item->isNull()){ throw new \InvalidArgumentException("Cannot serialize a null itemstack"); } @@ -128,7 +128,7 @@ final class ItemSerializer{ } if($locatedSerializer === null){ - throw new ItemTypeSerializeException("No serializer registered for " . get_class($item) . " " . $item->getName()); + throw new ItemTypeSerializeException("No serializer registered for " . get_class($item) . " ($index) " . $item->getName()); } /** @@ -153,6 +153,17 @@ final class ItemSerializer{ return $data; } + public function serializeStack(Item $item, ?int $slot = null) : SavedItemStackData{ + return new SavedItemStackData( + $this->serializeType($item), + $item->getCount(), + $slot, + null, + [], //we currently represent canDestroy and canPlaceOn via NBT, like PC + [] + ); + } + /** * @phpstan-template TBlockType of Block * @phpstan-param TBlockType $block diff --git a/src/item/Item.php b/src/item/Item.php index 6aabbf313..abafc6e6c 100644 --- a/src/item/Item.php +++ b/src/item/Item.php @@ -32,7 +32,6 @@ use pocketmine\block\BlockToolType; use pocketmine\block\VanillaBlocks; use pocketmine\data\bedrock\EnchantmentIdMap; use pocketmine\data\bedrock\item\ItemTypeDeserializeException; -use pocketmine\data\bedrock\item\SavedItemStackData; use pocketmine\data\SavedDataLoadingException; use pocketmine\entity\Entity; use pocketmine\item\enchantment\EnchantmentInstance; @@ -648,16 +647,7 @@ class Item implements \JsonSerializable{ * @param int $slot optional, the inventory slot of the item */ public function nbtSerialize(int $slot = -1) : CompoundTag{ - $typeData = GlobalItemDataHandlers::getSerializer()->serialize($this); - - return (new SavedItemStackData( - $typeData, - $this->count, - $slot !== -1 ? $slot : null, - null, - [], //we currently represent canDestroy and canPlaceOn via NBT, like PC - [] - ))->toNbt(); + return GlobalItemDataHandlers::getSerializer()->serializeStack($this, $slot !== -1 ? $slot : null); } /** @@ -668,17 +658,10 @@ class Item implements \JsonSerializable{ $itemData = GlobalItemDataHandlers::getUpgrader()->upgradeItemStackNbt($tag); try{ - $item = GlobalItemDataHandlers::getDeserializer()->deserialize($itemData->getTypeData()); + return GlobalItemDataHandlers::getDeserializer()->deserializeStack($itemData); }catch(ItemTypeDeserializeException $e){ throw new SavedDataLoadingException($e->getMessage(), 0, $e); } - - $item->setCount($itemData->getCount()); - if(($tagTag = $itemData->getTypeData()->getTag()) !== null){ - $item->setNamedTag(clone $tagTag); - } - - return $item; } public function __clone(){ diff --git a/src/network/mcpe/convert/ItemTranslator.php b/src/network/mcpe/convert/ItemTranslator.php index 6ada7f372..b04e9f624 100644 --- a/src/network/mcpe/convert/ItemTranslator.php +++ b/src/network/mcpe/convert/ItemTranslator.php @@ -79,7 +79,7 @@ final class ItemTranslator{ public function toNetworkId(Item $item) : array{ //TODO: we should probably come up with a cache for this - $itemData = $this->itemSerializer->serialize($item); + $itemData = $this->itemSerializer->serializeType($item); $numericId = $this->itemTypeDictionary->fromStringId($itemData->getName()); $blockStateData = $itemData->getBlock(); @@ -116,7 +116,7 @@ final class ItemTranslator{ } try{ - return $this->itemDeserializer->deserialize(new SavedItemData($stringId, $networkMeta, $blockStateData)); + return $this->itemDeserializer->deserializeType(new SavedItemData($stringId, $networkMeta, $blockStateData)); }catch(ItemTypeDeserializeException $e){ throw TypeConversionException::wrap($e, "Invalid network itemstack data"); } diff --git a/tests/phpunit/data/bedrock/item/ItemSerializerDeserializerTest.php b/tests/phpunit/data/bedrock/item/ItemSerializerDeserializerTest.php index ebc7dafc8..32e8f4139 100644 --- a/tests/phpunit/data/bedrock/item/ItemSerializerDeserializerTest.php +++ b/tests/phpunit/data/bedrock/item/ItemSerializerDeserializerTest.php @@ -45,12 +45,12 @@ final class ItemSerializerDeserializerTest extends TestCase{ } try{ - $itemData = $this->serializer->serialize($item); + $itemData = $this->serializer->serializeType($item); }catch(ItemTypeSerializeException $e){ self::fail($e->getMessage()); } try{ - $newItem = $this->deserializer->deserialize($itemData); + $newItem = $this->deserializer->deserializeType($itemData); }catch(ItemTypeDeserializeException $e){ self::fail($e->getMessage()); } @@ -67,12 +67,12 @@ final class ItemSerializerDeserializerTest extends TestCase{ } try{ - $itemData = $this->serializer->serialize($item); + $itemData = $this->serializer->serializeType($item); }catch(ItemTypeSerializeException $e){ self::fail($e->getMessage()); } try{ - $newItem = $this->deserializer->deserialize($itemData); + $newItem = $this->deserializer->deserializeType($itemData); }catch(ItemTypeDeserializeException $e){ self::fail($e->getMessage()); }