Allow Item (de)serializer to accept dynamic BlockState(De)Serializer

This commit is contained in:
Dylan K. Taylor 2022-06-08 16:22:35 +01:00
parent c8e318df8c
commit 301b0aba82
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
4 changed files with 20 additions and 15 deletions

View File

@ -29,6 +29,7 @@ use pocketmine\block\utils\SkullType;
use pocketmine\block\utils\TreeType; use pocketmine\block\utils\TreeType;
use pocketmine\block\VanillaBlocks as Blocks; use pocketmine\block\VanillaBlocks as Blocks;
use pocketmine\data\bedrock\block\BlockStateDeserializeException; use pocketmine\data\bedrock\block\BlockStateDeserializeException;
use pocketmine\data\bedrock\block\BlockStateDeserializer;
use pocketmine\data\bedrock\CompoundTypeIds; use pocketmine\data\bedrock\CompoundTypeIds;
use pocketmine\data\bedrock\DyeColorIdMap; use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\data\bedrock\EntityLegacyIds; use pocketmine\data\bedrock\EntityLegacyIds;
@ -43,16 +44,15 @@ use pocketmine\utils\SingletonTrait;
use pocketmine\world\format\io\GlobalBlockStateHandlers; use pocketmine\world\format\io\GlobalBlockStateHandlers;
final class ItemDeserializer{ final class ItemDeserializer{
use SingletonTrait;
/** /**
* @var \Closure[] * @var \Closure[]
* @phpstan-var array<string, \Closure(Data) : Item> * @phpstan-var array<string, \Closure(Data) : Item>
*/ */
private array $deserializers = []; private array $deserializers = [];
public function __construct(){ public function __construct(
private BlockStateDeserializer $blockStateDeserializer
){
$this->registerDeserializers(); $this->registerDeserializers();
} }
@ -70,7 +70,7 @@ final class ItemDeserializer{
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{
$block = GlobalBlockStateHandlers::getDeserializer()->deserialize($blockData); $block = $this->blockStateDeserializer->deserialize($blockData);
}catch(BlockStateDeserializeException $e){ }catch(BlockStateDeserializeException $e){
throw new ItemTypeDeserializeException("Failed to deserialize item data: " . $e->getMessage(), 0, $e); throw new ItemTypeDeserializeException("Failed to deserialize item data: " . $e->getMessage(), 0, $e);
} }

View File

@ -27,6 +27,7 @@ use pocketmine\block\Block;
use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SkullType; use pocketmine\block\utils\SkullType;
use pocketmine\block\VanillaBlocks as Blocks; use pocketmine\block\VanillaBlocks as Blocks;
use pocketmine\data\bedrock\block\BlockStateSerializer;
use pocketmine\data\bedrock\item\BlockItemIdMap; use pocketmine\data\bedrock\item\BlockItemIdMap;
use pocketmine\data\bedrock\block\BlockStateSerializeException; use pocketmine\data\bedrock\block\BlockStateSerializeException;
use pocketmine\data\bedrock\CompoundTypeIds; use pocketmine\data\bedrock\CompoundTypeIds;
@ -61,7 +62,9 @@ final class ItemSerializer{
*/ */
private array $blockItemSerializers = []; private array $blockItemSerializers = [];
public function __construct(){ public function __construct(
private BlockStateSerializer $blockStateSerializer
){
$this->registerSerializers(); $this->registerSerializers();
} }
@ -170,7 +173,7 @@ final class ItemSerializer{
$serializer = $locatedSerializer; $serializer = $locatedSerializer;
$data = $serializer($block); $data = $serializer($block);
}else{ }else{
$data = self::standardBlock($block); $data = $this->standardBlock($block);
} }
return $data; return $data;
@ -179,9 +182,9 @@ final class ItemSerializer{
/** /**
* @throws ItemTypeSerializeException * @throws ItemTypeSerializeException
*/ */
private static function standardBlock(Block $block) : Data{ private function standardBlock(Block $block) : Data{
try{ try{
$blockStateData = GlobalBlockStateHandlers::getSerializer()->serialize($block->getFullId()); $blockStateData = $this->blockStateSerializer->serialize($block->getFullId());
}catch(BlockStateSerializeException $e){ }catch(BlockStateSerializeException $e){
throw new ItemTypeSerializeException($e->getMessage(), 0, $e); throw new ItemTypeSerializeException($e->getMessage(), 0, $e);
} }
@ -261,8 +264,8 @@ final class ItemSerializer{
//these are encoded as regular blocks, but they have to be accounted for explicitly since they don't use ItemBlock //these are encoded as regular blocks, but they have to be accounted for explicitly since they don't use ItemBlock
//Bamboo->getBlock() returns BambooSapling :( //Bamboo->getBlock() returns BambooSapling :(
$this->map(Items::BAMBOO(), fn() => self::standardBlock(Blocks::BAMBOO())); $this->map(Items::BAMBOO(), fn() => $this->standardBlock(Blocks::BAMBOO()));
$this->map(Items::CORAL_FAN(), fn(CoralFan $item) => self::standardBlock($item->getBlock())); $this->map(Items::CORAL_FAN(), fn(CoralFan $item) => $this->standardBlock($item->getBlock()));
$this->map(Items::ACACIA_BOAT(), self::id(Ids::ACACIA_BOAT)); $this->map(Items::ACACIA_BOAT(), self::id(Ids::ACACIA_BOAT));
$this->map(Items::ACACIA_SIGN(), self::id(Ids::ACACIA_SIGN)); $this->map(Items::ACACIA_SIGN(), self::id(Ids::ACACIA_SIGN));

View File

@ -32,6 +32,7 @@ use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary; use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait; use pocketmine\utils\SingletonTrait;
use pocketmine\world\format\io\GlobalBlockStateHandlers;
/** /**
* This class handles translation between network item ID+metadata to PocketMine-MP internal ID+metadata and vice versa. * This class handles translation between network item ID+metadata to PocketMine-MP internal ID+metadata and vice versa.
@ -45,8 +46,8 @@ final class ItemTranslator{
return new self( return new self(
GlobalItemTypeDictionary::getInstance()->getDictionary(), GlobalItemTypeDictionary::getInstance()->getDictionary(),
RuntimeBlockMapping::getInstance()->getBlockStateDictionary(), RuntimeBlockMapping::getInstance()->getBlockStateDictionary(),
new ItemSerializer(), new ItemSerializer(GlobalBlockStateHandlers::getSerializer()),
new ItemDeserializer() new ItemDeserializer(GlobalBlockStateHandlers::getDeserializer())
); );
} }

View File

@ -26,6 +26,7 @@ namespace pocketmine\data\bedrock\item;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use pocketmine\block\BlockFactory; use pocketmine\block\BlockFactory;
use pocketmine\item\ItemFactory; use pocketmine\item\ItemFactory;
use pocketmine\world\format\io\GlobalBlockStateHandlers;
final class ItemSerializerDeserializerTest extends TestCase{ final class ItemSerializerDeserializerTest extends TestCase{
@ -33,8 +34,8 @@ final class ItemSerializerDeserializerTest extends TestCase{
private ItemSerializer $serializer; private ItemSerializer $serializer;
public function setUp() : void{ public function setUp() : void{
$this->deserializer = new ItemDeserializer(); $this->deserializer = new ItemDeserializer(GlobalBlockStateHandlers::getDeserializer());
$this->serializer = new ItemSerializer(); $this->serializer = new ItemSerializer(GlobalBlockStateHandlers::getSerializer());
} }
public function testAllVanillaItemsSerializableAndDeserializable() : void{ public function testAllVanillaItemsSerializableAndDeserializable() : void{