Added item stack serialize/deserialize methods

This commit is contained in:
Dylan K. Taylor 2022-06-26 17:02:55 +01:00
parent 3d61345543
commit bc5a600d59
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
5 changed files with 38 additions and 28 deletions

View File

@ -64,7 +64,7 @@ final class ItemDeserializer{
/** /**
* @throws ItemTypeDeserializeException * @throws ItemTypeDeserializeException
*/ */
public function deserialize(Data $data) : Item{ public function deserializeType(Data $data) : Item{
if(($blockData = $data->getBlock()) !== null){ if(($blockData = $data->getBlock()) !== null){
//TODO: this is rough duct tape; we need a better way to deal with this //TODO: this is rough duct tape; we need a better way to deal with this
try{ try{
@ -84,6 +84,22 @@ final class ItemDeserializer{
return ($this->deserializers[$id])($data); 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{ private function registerDeserializers() : void{
$this->map(Ids::ACACIA_BOAT, fn() => Items::ACACIA_BOAT()); $this->map(Ids::ACACIA_BOAT, fn() => Items::ACACIA_BOAT());
$this->map(Ids::ACACIA_DOOR, fn() => Blocks::ACACIA_DOOR()->asItem()); $this->map(Ids::ACACIA_DOOR, fn() => Blocks::ACACIA_DOOR()->asItem());

View File

@ -102,7 +102,7 @@ final class ItemSerializer{
* *
* @throws ItemTypeSerializeException * @throws ItemTypeSerializeException
*/ */
public function serialize(Item $item) : Data{ public function serializeType(Item $item) : Data{
if($item->isNull()){ if($item->isNull()){
throw new \InvalidArgumentException("Cannot serialize a null itemstack"); throw new \InvalidArgumentException("Cannot serialize a null itemstack");
} }
@ -128,7 +128,7 @@ final class ItemSerializer{
} }
if($locatedSerializer === null){ 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; 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-template TBlockType of Block
* @phpstan-param TBlockType $block * @phpstan-param TBlockType $block

View File

@ -32,7 +32,6 @@ use pocketmine\block\BlockToolType;
use pocketmine\block\VanillaBlocks; use pocketmine\block\VanillaBlocks;
use pocketmine\data\bedrock\EnchantmentIdMap; use pocketmine\data\bedrock\EnchantmentIdMap;
use pocketmine\data\bedrock\item\ItemTypeDeserializeException; use pocketmine\data\bedrock\item\ItemTypeDeserializeException;
use pocketmine\data\bedrock\item\SavedItemStackData;
use pocketmine\data\SavedDataLoadingException; use pocketmine\data\SavedDataLoadingException;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\item\enchantment\EnchantmentInstance; use pocketmine\item\enchantment\EnchantmentInstance;
@ -648,16 +647,7 @@ class Item implements \JsonSerializable{
* @param int $slot optional, the inventory slot of the item * @param int $slot optional, the inventory slot of the item
*/ */
public function nbtSerialize(int $slot = -1) : CompoundTag{ public function nbtSerialize(int $slot = -1) : CompoundTag{
$typeData = GlobalItemDataHandlers::getSerializer()->serialize($this); return GlobalItemDataHandlers::getSerializer()->serializeStack($this, $slot !== -1 ? $slot : null);
return (new SavedItemStackData(
$typeData,
$this->count,
$slot !== -1 ? $slot : null,
null,
[], //we currently represent canDestroy and canPlaceOn via NBT, like PC
[]
))->toNbt();
} }
/** /**
@ -668,17 +658,10 @@ class Item implements \JsonSerializable{
$itemData = GlobalItemDataHandlers::getUpgrader()->upgradeItemStackNbt($tag); $itemData = GlobalItemDataHandlers::getUpgrader()->upgradeItemStackNbt($tag);
try{ try{
$item = GlobalItemDataHandlers::getDeserializer()->deserialize($itemData->getTypeData()); return GlobalItemDataHandlers::getDeserializer()->deserializeStack($itemData);
}catch(ItemTypeDeserializeException $e){ }catch(ItemTypeDeserializeException $e){
throw new SavedDataLoadingException($e->getMessage(), 0, $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(){ public function __clone(){

View File

@ -79,7 +79,7 @@ final class ItemTranslator{
public function toNetworkId(Item $item) : array{ public function toNetworkId(Item $item) : array{
//TODO: we should probably come up with a cache for this //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()); $numericId = $this->itemTypeDictionary->fromStringId($itemData->getName());
$blockStateData = $itemData->getBlock(); $blockStateData = $itemData->getBlock();
@ -116,7 +116,7 @@ final class ItemTranslator{
} }
try{ try{
return $this->itemDeserializer->deserialize(new SavedItemData($stringId, $networkMeta, $blockStateData)); return $this->itemDeserializer->deserializeType(new SavedItemData($stringId, $networkMeta, $blockStateData));
}catch(ItemTypeDeserializeException $e){ }catch(ItemTypeDeserializeException $e){
throw TypeConversionException::wrap($e, "Invalid network itemstack data"); throw TypeConversionException::wrap($e, "Invalid network itemstack data");
} }

View File

@ -45,12 +45,12 @@ final class ItemSerializerDeserializerTest extends TestCase{
} }
try{ try{
$itemData = $this->serializer->serialize($item); $itemData = $this->serializer->serializeType($item);
}catch(ItemTypeSerializeException $e){ }catch(ItemTypeSerializeException $e){
self::fail($e->getMessage()); self::fail($e->getMessage());
} }
try{ try{
$newItem = $this->deserializer->deserialize($itemData); $newItem = $this->deserializer->deserializeType($itemData);
}catch(ItemTypeDeserializeException $e){ }catch(ItemTypeDeserializeException $e){
self::fail($e->getMessage()); self::fail($e->getMessage());
} }
@ -67,12 +67,12 @@ final class ItemSerializerDeserializerTest extends TestCase{
} }
try{ try{
$itemData = $this->serializer->serialize($item); $itemData = $this->serializer->serializeType($item);
}catch(ItemTypeSerializeException $e){ }catch(ItemTypeSerializeException $e){
self::fail($e->getMessage()); self::fail($e->getMessage());
} }
try{ try{
$newItem = $this->deserializer->deserialize($itemData); $newItem = $this->deserializer->deserializeType($itemData);
}catch(ItemTypeDeserializeException $e){ }catch(ItemTypeDeserializeException $e){
self::fail($e->getMessage()); self::fail($e->getMessage());
} }