From 1b48603d07433065c3852db47755a016d051e98b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 7 Feb 2022 02:41:50 +0000 Subject: [PATCH] another vague commit restructuring stuff --- .../blockstate/BlockStateDeserializer.php | 40 +++++++++++++++ .../blockstate/BlockStateSerializer.php | 40 +++++++++++++++ .../CachingBlockStateDeserializer.php | 49 +++++++++++++++++++ .../CachingBlockStateSerializer.php | 43 ++++++++++++++++ .../UpgradingBlockStateDeserializer.php | 40 +++++++++++++++ ... => BlockObjectToBlockStateSerializer.php} | 11 ++++- ...> BlockStateToBlockObjectDeserializer.php} | 15 ++++-- ...DataMap.php => LegacyBlockStateMapper.php} | 28 ++++++++--- 8 files changed, 254 insertions(+), 12 deletions(-) create mode 100644 src/data/bedrock/blockstate/BlockStateDeserializer.php create mode 100644 src/data/bedrock/blockstate/BlockStateSerializer.php create mode 100644 src/data/bedrock/blockstate/CachingBlockStateDeserializer.php create mode 100644 src/data/bedrock/blockstate/CachingBlockStateSerializer.php create mode 100644 src/data/bedrock/blockstate/UpgradingBlockStateDeserializer.php rename src/data/bedrock/blockstate/convert/{BlockStateSerializer.php => BlockObjectToBlockStateSerializer.php} (99%) rename src/data/bedrock/blockstate/convert/{BlockStateDeserializer.php => BlockStateToBlockObjectDeserializer.php} (99%) rename src/data/bedrock/blockstate/upgrade/{LegacyIdMetaToBlockStateDataMap.php => LegacyBlockStateMapper.php} (65%) diff --git a/src/data/bedrock/blockstate/BlockStateDeserializer.php b/src/data/bedrock/blockstate/BlockStateDeserializer.php new file mode 100644 index 000000000..180480bb1 --- /dev/null +++ b/src/data/bedrock/blockstate/BlockStateDeserializer.php @@ -0,0 +1,40 @@ + + */ + private array $simpleCache = []; + + public function __construct( + private BlockStateDeserializer $realDeserializer + ){} + + public function deserialize(BlockStateData $stateData) : int{ + if($stateData->getStates()->count() === 0){ + //if a block has zero properties, we can keep a map of string ID -> internal blockstate ID + return $this->simpleCache[$stateData->getName()] ??= $this->realDeserializer->deserialize($stateData); + } + + //we can't cache blocks that have properties - go ahead and deserialize the slow way + return $this->realDeserializer->deserialize($stateData); + } + + public function getRealDeserializer() : BlockStateDeserializer{ return $this->realDeserializer; } +} diff --git a/src/data/bedrock/blockstate/CachingBlockStateSerializer.php b/src/data/bedrock/blockstate/CachingBlockStateSerializer.php new file mode 100644 index 000000000..eb4cc13de --- /dev/null +++ b/src/data/bedrock/blockstate/CachingBlockStateSerializer.php @@ -0,0 +1,43 @@ + + */ + private array $cache = []; + + public function __construct( + private BlockStateSerializer $realSerializer + ){} + + public function serialize(int $stateId) : BlockStateData{ + return $this->cache[$stateId] ??= $this->realSerializer->serialize($stateId); + } + + public function getRealSerializer() : BlockStateSerializer{ return $this->realSerializer; } +} diff --git a/src/data/bedrock/blockstate/UpgradingBlockStateDeserializer.php b/src/data/bedrock/blockstate/UpgradingBlockStateDeserializer.php new file mode 100644 index 000000000..cd1c114df --- /dev/null +++ b/src/data/bedrock/blockstate/UpgradingBlockStateDeserializer.php @@ -0,0 +1,40 @@ +realDeserializer->deserialize($this->blockStateUpgrader->upgrade($stateData)); + } + + public function getRealDeserializer() : BlockStateDeserializer{ return $this->realDeserializer; } +} diff --git a/src/data/bedrock/blockstate/convert/BlockStateSerializer.php b/src/data/bedrock/blockstate/convert/BlockObjectToBlockStateSerializer.php similarity index 99% rename from src/data/bedrock/blockstate/convert/BlockStateSerializer.php rename to src/data/bedrock/blockstate/convert/BlockObjectToBlockStateSerializer.php index 31c2b232a..cfd0e3e0f 100644 --- a/src/data/bedrock/blockstate/convert/BlockStateSerializer.php +++ b/src/data/bedrock/blockstate/convert/BlockObjectToBlockStateSerializer.php @@ -32,6 +32,7 @@ use pocketmine\block\Bed; use pocketmine\block\Beetroot; use pocketmine\block\Bell; use pocketmine\block\Block; +use pocketmine\block\BlockFactory; use pocketmine\block\BlockLegacyMetadata; use pocketmine\block\BoneBlock; use pocketmine\block\BrewingStand; @@ -140,6 +141,7 @@ use pocketmine\block\Wool; use pocketmine\data\bedrock\blockstate\BlockStateData; use pocketmine\data\bedrock\blockstate\BlockStateNames as StateNames; use pocketmine\data\bedrock\blockstate\BlockStateSerializeException; +use pocketmine\data\bedrock\blockstate\BlockStateSerializer; use pocketmine\data\bedrock\blockstate\BlockStateStringValues as StringValues; use pocketmine\data\bedrock\blockstate\BlockTypeNames as Ids; use pocketmine\data\bedrock\blockstate\convert\BlockStateSerializerHelper as Helper; @@ -150,7 +152,7 @@ use pocketmine\utils\AssumptionFailedError; use function class_parents; use function get_class; -final class BlockStateSerializer{ +final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{ /** * These callables actually accept Block, but for the sake of type completeness, it has to be never, since we can't * describe the bottom type of a type hierarchy only containing Block. @@ -164,6 +166,11 @@ final class BlockStateSerializer{ $this->registerSerializers(); } + public function serialize(int $stateId) : BlockStateData{ + //TODO: singleton usage not ideal + return $this->serializeBlock(BlockFactory::getInstance()->fromFullBlock($stateId)); + } + /** * @phpstan-template TBlockType of Block * @phpstan-param TBlockType $block @@ -181,7 +188,7 @@ final class BlockStateSerializer{ * @phpstan-template TBlockType of Block * @phpstan-param TBlockType $blockState */ - public function serialize(Block $blockState) : BlockStateData{ + public function serializeBlock(Block $blockState) : BlockStateData{ $typeId = $blockState->getTypeId(); $locatedSerializer = $this->serializers[$typeId][get_class($blockState)] ?? null; diff --git a/src/data/bedrock/blockstate/convert/BlockStateDeserializer.php b/src/data/bedrock/blockstate/convert/BlockStateToBlockObjectDeserializer.php similarity index 99% rename from src/data/bedrock/blockstate/convert/BlockStateDeserializer.php rename to src/data/bedrock/blockstate/convert/BlockStateToBlockObjectDeserializer.php index 3fb4c476b..77323213b 100644 --- a/src/data/bedrock/blockstate/convert/BlockStateDeserializer.php +++ b/src/data/bedrock/blockstate/convert/BlockStateToBlockObjectDeserializer.php @@ -34,6 +34,7 @@ use pocketmine\block\utils\SlabType; use pocketmine\block\VanillaBlocks as Blocks; use pocketmine\data\bedrock\blockstate\BlockStateData; use pocketmine\data\bedrock\blockstate\BlockStateDeserializeException; +use pocketmine\data\bedrock\blockstate\BlockStateDeserializer; use pocketmine\data\bedrock\blockstate\BlockStateNames as StateNames; use pocketmine\data\bedrock\blockstate\BlockStateStringValues as StringValues; use pocketmine\data\bedrock\blockstate\BlockTypeNames as Ids; @@ -44,7 +45,7 @@ use pocketmine\math\Facing; use function array_key_exists; use function min; -final class BlockStateDeserializer{ +final class BlockStateToBlockObjectDeserializer implements BlockStateDeserializer{ /** * @var \Closure[] @@ -52,6 +53,14 @@ final class BlockStateDeserializer{ */ private array $deserializeFuncs = []; + public function __construct(){ + $this->registerDeserializers(); + } + + public function deserialize(BlockStateData $stateData) : int{ + return $this->deserializeBlock($stateData)->getFullId(); + } + /** @phpstan-param \Closure(Reader) : Block $c */ private function map(string $id, \Closure $c) : void{ if(array_key_exists($id, $this->deserializeFuncs)){ @@ -60,7 +69,7 @@ final class BlockStateDeserializer{ $this->deserializeFuncs[$id] = $c; } - public function __construct(){ + private function registerDeserializers() : void{ $this->map(Ids::ACACIA_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::ACACIA_BUTTON(), $in)); $this->map(Ids::ACACIA_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::ACACIA_DOOR(), $in)); $this->map(Ids::ACACIA_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::ACACIA_FENCE_GATE(), $in)); @@ -2502,7 +2511,7 @@ final class BlockStateDeserializer{ } /** @throws BlockStateDeserializeException */ - public function deserialize(BlockStateData $blockStateData) : Block{ + public function deserializeBlock(BlockStateData $blockStateData) : Block{ $id = $blockStateData->getName(); if(!array_key_exists($id, $this->deserializeFuncs)){ throw new BlockStateDeserializeException("Unknown block ID \"$id\""); diff --git a/src/data/bedrock/blockstate/upgrade/LegacyIdMetaToBlockStateDataMap.php b/src/data/bedrock/blockstate/upgrade/LegacyBlockStateMapper.php similarity index 65% rename from src/data/bedrock/blockstate/upgrade/LegacyIdMetaToBlockStateDataMap.php rename to src/data/bedrock/blockstate/upgrade/LegacyBlockStateMapper.php index 3ecf18a17..1a8e7186a 100644 --- a/src/data/bedrock/blockstate/upgrade/LegacyIdMetaToBlockStateDataMap.php +++ b/src/data/bedrock/blockstate/upgrade/LegacyBlockStateMapper.php @@ -24,27 +24,41 @@ declare(strict_types=1); namespace pocketmine\data\bedrock\blockstate\upgrade; use pocketmine\data\bedrock\blockstate\BlockStateData; +use pocketmine\data\bedrock\LegacyBlockIdToStringIdMap; +use pocketmine\errorhandler\ErrorToExceptionHandler; use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; use pocketmine\utils\BinaryStream; +use pocketmine\utils\SingletonTrait; +use Webmozart\PathUtil\Path; +use function file_get_contents; +use const pocketmine\BEDROCK_DATA_PATH; /** - * Interface to an upgrade schema describing how to convert 1.12 id+meta into modern blockstate NBT. + * Handles translating legacy 1.12 block ID/meta into modern blockstates. */ -final class LegacyIdMetaToBlockStateDataMap{ - +final class LegacyBlockStateMapper{ /** * @param BlockStateData[][] $mappingTable * @phpstan-param array> $mappingTable */ public function __construct( - private array $mappingTable + private array $mappingTable, + private LegacyBlockIdToStringIdMap $legacyNumericIdMap ){} - public function getDataFromLegacyIdMeta(string $id, int $meta) : ?BlockStateData{ + public function fromStringIdMeta(string $id, int $meta) : ?BlockStateData{ return $this->mappingTable[$id][$meta] ?? null; } - public static function loadFromString(string $data) : self{ + public function fromIntIdMeta(int $id, int $meta) : ?BlockStateData{ + $stringId = $this->legacyNumericIdMap->legacyToString($id); + if($stringId === null){ + return null; + } + return $this->fromStringIdMeta($stringId, $meta); + } + + public static function loadFromString(string $data, LegacyBlockIdToStringIdMap $idMap) : self{ $mappingTable = []; $legacyStateMapReader = new BinaryStream($data); @@ -59,6 +73,6 @@ final class LegacyIdMetaToBlockStateDataMap{ $mappingTable[$id][$meta] = BlockStateData::fromNbt($state); } - return new self($mappingTable); + return new self($mappingTable, $idMap); } }