From ccb3c3cb05e6eee8afa15d7837e256a446244fe7 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 9 Jul 2022 16:03:51 +0100 Subject: [PATCH] BlockStateData: use array instead of CompoundTag to store state properties this reduces the footprint of RuntimeBlockMapping by a further 1 MB, as well as simplifying various parts of the code, and solidifying the immutability guarantee of BlockStateData. --- build/generate-block-serializer-consts.php | 2 +- .../CraftingManagerFromDataHelper.php | 5 +- src/data/bedrock/block/BlockStateData.php | 40 +++++-- .../block/CachingBlockStateDeserializer.php | 4 +- .../block/convert/BlockStateReader.php | 11 +- .../block/convert/BlockStateWriter.php | 21 ++-- .../block/upgrade/BlockDataUpgrader.php | 2 +- .../BlockStateUpgradeSchemaBlockRemap.php | 21 +--- .../upgrade/BlockStateUpgradeSchemaUtils.php | 4 +- .../block/upgrade/BlockStateUpgrader.php | 100 +++++++++++------- .../mcpe/convert/BlockStateLookupCache.php | 3 +- .../mcpe/convert/RuntimeBlockMapping.php | 3 +- src/world/format/io/BaseWorldProvider.php | 3 +- src/world/format/io/leveldb/LevelDB.php | 2 +- .../block/upgrade/BlockStateUpgraderTest.php | 17 ++- tools/generate-block-palette-spec.php | 2 +- tools/generate-blockstate-upgrade-schema.php | 18 ++-- 17 files changed, 148 insertions(+), 110 deletions(-) diff --git a/build/generate-block-serializer-consts.php b/build/generate-block-serializer-consts.php index 9fd944157..5f82b8e58 100644 --- a/build/generate-block-serializer-consts.php +++ b/build/generate-block-serializer-consts.php @@ -74,7 +74,7 @@ function generateBlockPaletteReport(array $states) : BlockPaletteReport{ foreach($states as $stateData){ $name = $stateData->getName(); $result->seenTypes[$name] = $name; - foreach($stateData->getStates() as $k => $v){ + foreach(Utils::stringifyKeys($stateData->getStates()) as $k => $v){ $result->seenStateValues[$k][$v->getValue()] = $v->getValue(); asort($result->seenStateValues[$k]); } diff --git a/src/crafting/CraftingManagerFromDataHelper.php b/src/crafting/CraftingManagerFromDataHelper.php index db7afe52e..21e47a1e8 100644 --- a/src/crafting/CraftingManagerFromDataHelper.php +++ b/src/crafting/CraftingManagerFromDataHelper.php @@ -121,10 +121,11 @@ final class CraftingManagerFromDataHelper{ throw new SavedDataLoadingException("Meta should not be specified for blockitems"); } $blockStatesTag = $blockStatesRaw === null ? - CompoundTag::create() : + [] : (new LittleEndianNbtSerializer()) ->read(ErrorToExceptionHandler::trapAndRemoveFalse(fn() => base64_decode($blockStatesRaw, true))) - ->mustGetCompoundTag(); + ->mustGetCompoundTag() + ->getValue(); $blockStateData = new BlockStateData($blockName, $blockStatesTag, BlockStateData::CURRENT_VERSION); }else{ $blockStateData = null; diff --git a/src/data/bedrock/block/BlockStateData.php b/src/data/bedrock/block/BlockStateData.php index a5d066298..be0048c6d 100644 --- a/src/data/bedrock/block/BlockStateData.php +++ b/src/data/bedrock/block/BlockStateData.php @@ -25,6 +25,8 @@ namespace pocketmine\data\bedrock\block; use pocketmine\nbt\NbtException; use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\Tag; +use pocketmine\utils\Utils; use function array_keys; use function count; use function implode; @@ -46,15 +48,27 @@ final class BlockStateData{ public const TAG_STATES = "states"; public const TAG_VERSION = "version"; + /** + * @param Tag[] $states + * @phpstan-param array $states + */ public function __construct( private string $name, - private CompoundTag $states, + private array $states, private int $version ){} public function getName() : string{ return $this->name; } - public function getStates() : CompoundTag{ return $this->states; } + /** + * @return Tag[] + * @phpstan-return array + */ + public function getStates() : array{ return $this->states; } + + public function getState(string $name) : ?Tag{ + return $this->states[$name] ?? null; + } public function getVersion() : int{ return $this->version; } @@ -76,20 +90,30 @@ final class BlockStateData{ throw new BlockStateDeserializeException("Unexpected extra keys: " . implode(", ", array_keys($allKeys))); } - return new self($name, $states, $version); + return new self($name, $states->getValue(), $version); } public function toNbt() : CompoundTag{ + $statesTag = CompoundTag::create(); + foreach(Utils::stringifyKeys($this->states) as $key => $value){ + $statesTag->setTag($key, $value); + } return CompoundTag::create() ->setString(self::TAG_NAME, $this->name) ->setInt(self::TAG_VERSION, $this->version) - ->setTag(self::TAG_STATES, $this->states); + ->setTag(self::TAG_STATES, $statesTag); } public function equals(self $that) : bool{ - return - $this->name === $that->name && - $this->states->equals($that->states) && - $this->version === $that->version; + if($this->name !== $that->name || count($this->states) !== count($that->states)){ + return false; + } + foreach(Utils::stringifyKeys($this->states) as $k => $v){ + if(!isset($that->states[$k]) || !$that->states[$k]->equals($v)){ + return false; + } + } + + return true; } } diff --git a/src/data/bedrock/block/CachingBlockStateDeserializer.php b/src/data/bedrock/block/CachingBlockStateDeserializer.php index 3071a9eb1..2078b7cc5 100644 --- a/src/data/bedrock/block/CachingBlockStateDeserializer.php +++ b/src/data/bedrock/block/CachingBlockStateDeserializer.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace pocketmine\data\bedrock\block; +use function count; + final class CachingBlockStateDeserializer implements DelegatingBlockStateDeserializer{ /** @@ -36,7 +38,7 @@ final class CachingBlockStateDeserializer implements DelegatingBlockStateDeseria ){} public function deserialize(BlockStateData $stateData) : int{ - if($stateData->getStates()->count() === 0){ + if(count($stateData->getStates()) === 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); } diff --git a/src/data/bedrock/block/convert/BlockStateReader.php b/src/data/bedrock/block/convert/BlockStateReader.php index 0d1a0000f..67da60088 100644 --- a/src/data/bedrock/block/convert/BlockStateReader.php +++ b/src/data/bedrock/block/convert/BlockStateReader.php @@ -38,6 +38,7 @@ use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\StringTag; use pocketmine\nbt\tag\Tag; +use pocketmine\utils\Utils; use function get_class; final class BlockStateReader{ @@ -66,7 +67,7 @@ final class BlockStateReader{ /** @throws BlockStateDeserializeException */ public function readBool(string $name) : bool{ $this->usedStates[$name] = true; - $tag = $this->data->getStates()->getTag($name); + $tag = $this->data->getState($name); if($tag instanceof ByteTag){ switch($tag->getValue()){ case 0: return false; @@ -80,7 +81,7 @@ final class BlockStateReader{ /** @throws BlockStateDeserializeException */ public function readInt(string $name) : int{ $this->usedStates[$name] = true; - $tag = $this->data->getStates()->getTag($name); + $tag = $this->data->getState($name); if($tag instanceof IntTag){ return $tag->getValue(); } @@ -100,7 +101,7 @@ final class BlockStateReader{ public function readString(string $name) : string{ $this->usedStates[$name] = true; //TODO: only allow a specific set of values (strings are primarily used for enums) - $tag = $this->data->getStates()->getTag($name); + $tag = $this->data->getState($name); if($tag instanceof StringTag){ return $tag->getValue(); } @@ -314,7 +315,7 @@ final class BlockStateReader{ * Explicitly mark a property as unused, so it doesn't get flagged as an error when debug mode is enabled */ public function ignored(string $name) : void{ - if($this->data->getStates()->getTag($name) !== null){ + if($this->data->getState($name) !== null){ $this->usedStates[$name] = true; }else{ throw $this->missingOrWrongTypeException($name, null); @@ -332,7 +333,7 @@ final class BlockStateReader{ * @throws BlockStateDeserializeException */ public function checkUnreadProperties() : void{ - foreach($this->data->getStates() as $name => $tag){ + foreach(Utils::stringifyKeys($this->data->getStates()) as $name => $tag){ if(!isset($this->usedStates[$name])){ throw new BlockStateDeserializeException("Unread property \"$name\""); } diff --git a/src/data/bedrock/block/convert/BlockStateWriter.php b/src/data/bedrock/block/convert/BlockStateWriter.php index 285a52aa1..db305bb3d 100644 --- a/src/data/bedrock/block/convert/BlockStateWriter.php +++ b/src/data/bedrock/block/convert/BlockStateWriter.php @@ -35,17 +35,22 @@ use pocketmine\data\bedrock\block\BlockStateSerializeException; use pocketmine\data\bedrock\block\BlockStateStringValues as StringValues; use pocketmine\math\Axis; use pocketmine\math\Facing; -use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\ByteTag; +use pocketmine\nbt\tag\IntTag; +use pocketmine\nbt\tag\StringTag; +use pocketmine\nbt\tag\Tag; final class BlockStateWriter{ - private CompoundTag $states; + /** + * @var Tag[] + * @phpstan-var array + */ + private array $states = []; public function __construct( private string $id - ){ - $this->states = CompoundTag::create(); - } + ){} public static function create(string $id) : self{ return new self($id); @@ -53,19 +58,19 @@ final class BlockStateWriter{ /** @return $this */ public function writeBool(string $name, bool $value) : self{ - $this->states->setByte($name, $value ? 1 : 0); + $this->states[$name] = new ByteTag($value ? 1 : 0); return $this; } /** @return $this */ public function writeInt(string $name, int $value) : self{ - $this->states->setInt($name, $value); + $this->states[$name] = new IntTag($value); return $this; } /** @return $this */ public function writeString(string $name, string $value) : self{ - $this->states->setString($name, $value); + $this->states[$name] = new StringTag($value); return $this; } diff --git a/src/data/bedrock/block/upgrade/BlockDataUpgrader.php b/src/data/bedrock/block/upgrade/BlockDataUpgrader.php index a10c30d7e..785a36af8 100644 --- a/src/data/bedrock/block/upgrade/BlockDataUpgrader.php +++ b/src/data/bedrock/block/upgrade/BlockDataUpgrader.php @@ -51,7 +51,7 @@ final class BlockDataUpgrader{ $blockStateData = $this->upgradeStringIdMeta($id, $data); if($blockStateData === null){ //unknown block, invalid ID - $blockStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, CompoundTag::create(), BlockStateData::CURRENT_VERSION); + $blockStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION); } }else{ //Modern (post-1.13) blockstate diff --git a/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaBlockRemap.php b/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaBlockRemap.php index f3ef4ec92..a0659b40a 100644 --- a/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaBlockRemap.php +++ b/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaBlockRemap.php @@ -23,15 +23,9 @@ declare(strict_types=1); namespace pocketmine\data\bedrock\block\upgrade; -use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\Tag; -use pocketmine\utils\Utils; final class BlockStateUpgradeSchemaBlockRemap{ - - public CompoundTag $oldState; - public CompoundTag $newState; - /** * @param Tag[] $oldState * @param Tag[] $newState @@ -39,17 +33,8 @@ final class BlockStateUpgradeSchemaBlockRemap{ * @phpstan-param array $newState */ public function __construct( - array $oldState, + public array $oldState, public string $newName, - array $newState - ){ - $this->oldState = CompoundTag::create(); - $this->newState = CompoundTag::create(); - foreach(Utils::stringifyKeys($oldState) as $k => $v){ - $this->oldState->setTag($k, $v); - } - foreach(Utils::stringifyKeys($newState) as $k => $v){ - $this->newState->setTag($k, $v); - } - } + public array $newState + ){} } diff --git a/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaUtils.php b/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaUtils.php index e6fe5c8dc..923afde76 100644 --- a/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaUtils.php +++ b/src/data/bedrock/block/upgrade/BlockStateUpgradeSchemaUtils.php @@ -240,9 +240,9 @@ final class BlockStateUpgradeSchemaUtils{ foreach(Utils::stringifyKeys($schema->remappedStates) as $oldBlockName => $remaps){ foreach($remaps as $remap){ $result->remappedStates[$oldBlockName][] = new BlockStateUpgradeSchemaModelBlockRemap( - array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->oldState->getValue()), + array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->oldState), $remap->newName, - array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->newState->getValue()), + array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->newState), ); } } diff --git a/src/data/bedrock/block/upgrade/BlockStateUpgrader.php b/src/data/bedrock/block/upgrade/BlockStateUpgrader.php index 89a6d7b85..637674a26 100644 --- a/src/data/bedrock/block/upgrade/BlockStateUpgrader.php +++ b/src/data/bedrock/block/upgrade/BlockStateUpgrader.php @@ -24,9 +24,9 @@ declare(strict_types=1); namespace pocketmine\data\bedrock\block\upgrade; use pocketmine\data\bedrock\block\BlockStateData; -use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\Tag; use pocketmine\utils\Utils; +use function count; use function ksort; use const SORT_NUMERIC; @@ -68,12 +68,20 @@ final class BlockStateUpgrader{ } foreach($schemas as $schema){ $oldName = $blockStateData->getName(); + $oldState = $blockStateData->getStates(); if(isset($schema->remappedStates[$oldName])){ foreach($schema->remappedStates[$oldName] as $remap){ - if($blockStateData->getStates()->equals($remap->oldState)){ - $blockStateData = new BlockStateData($remap->newName, clone $remap->newState, $resultVersion); - continue 2; + if(count($oldState) !== count($remap->oldState)){ + continue; //try next state } + foreach(Utils::stringifyKeys($oldState) as $k => $v){ + if(!isset($remap->oldState[$k]) || !$remap->oldState[$k]->equals($v)){ + continue 2; //try next state + } + } + + $blockStateData = new BlockStateData($remap->newName, $remap->newState, $resultVersion); + continue 2; //try next schema } } $newName = $schema->renamedIds[$oldName] ?? null; @@ -96,42 +104,44 @@ final class BlockStateUpgrader{ return $blockStateData; } - private function cloneIfNeeded(CompoundTag $states, int &$stateChanges) : CompoundTag{ - if($stateChanges === 0){ - $states = clone $states; + /** + * @param Tag[] $states + * @phpstan-param array $states + * + * @return Tag[] + * @phpstan-return array + */ + private function applyPropertyAdded(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{ + if(isset($schema->addedProperties[$oldName])){ + foreach(Utils::stringifyKeys($schema->addedProperties[$oldName]) as $propertyName => $value){ + if(!isset($states[$propertyName])){ + $stateChanges++; + $states[$propertyName] = $value; + } + } } - $stateChanges++; return $states; } - private function applyPropertyAdded(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{ - $newStates = $states; - if(isset($schema->addedProperties[$oldName])){ - foreach(Utils::stringifyKeys($schema->addedProperties[$oldName]) as $propertyName => $value){ - $oldValue = $states->getTag($propertyName); - if($oldValue === null){ - $newStates = $this->cloneIfNeeded($newStates, $stateChanges); - $newStates->setTag($propertyName, $value); - } - } - } - - return $newStates; - } - - private function applyPropertyRemoved(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{ - $newStates = $states; + /** + * @param Tag[] $states + * @phpstan-param array $states + * + * @return Tag[] + * @phpstan-return array + */ + private function applyPropertyRemoved(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{ if(isset($schema->removedProperties[$oldName])){ foreach($schema->removedProperties[$oldName] as $propertyName){ - if($states->getTag($propertyName) !== null){ - $newStates = $this->cloneIfNeeded($newStates, $stateChanges); - $newStates->removeTag($propertyName); + if(isset($states[$propertyName])){ + $stateChanges++; + unset($states[$propertyName]); } } } - return $newStates; + return $states; } private function locateNewPropertyValue(BlockStateUpgradeSchema $schema, string $oldName, string $oldPropertyName, Tag $oldValue) : Tag{ @@ -146,18 +156,25 @@ final class BlockStateUpgrader{ return $oldValue; } - private function applyPropertyRenamedOrValueChanged(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{ + /** + * @param Tag[] $states + * @phpstan-param array $states + * + * @return Tag[] + * @phpstan-return array + */ + private function applyPropertyRenamedOrValueChanged(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{ if(isset($schema->renamedProperties[$oldName])){ foreach(Utils::stringifyKeys($schema->renamedProperties[$oldName]) as $oldPropertyName => $newPropertyName){ - $oldValue = $states->getTag($oldPropertyName); + $oldValue = $states[$oldPropertyName] ?? null; if($oldValue !== null){ - $states = $this->cloneIfNeeded($states, $stateChanges); - $states->removeTag($oldPropertyName); + $stateChanges++; + unset($states[$oldPropertyName]); //If a value remap is needed, we need to do it here, since we won't be able to locate the property //after it's been renamed - value remaps are always indexed by old property name for the sake of //being able to do changes in any order. - $states->setTag($newPropertyName, $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue)); + $states[$newPropertyName] = $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue); } } } @@ -165,15 +182,22 @@ final class BlockStateUpgrader{ return $states; } - private function applyPropertyValueChanged(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{ + /** + * @param Tag[] $states + * @phpstan-param array $states + * + * @return Tag[] + * @phpstan-return array + */ + private function applyPropertyValueChanged(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{ if(isset($schema->remappedPropertyValues[$oldName])){ foreach(Utils::stringifyKeys($schema->remappedPropertyValues[$oldName]) as $oldPropertyName => $remappedValues){ - $oldValue = $states->getTag($oldPropertyName); + $oldValue = $states[$oldPropertyName] ?? null; if($oldValue !== null){ $newValue = $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue); if($newValue !== $oldValue){ - $states = $this->cloneIfNeeded($states, $stateChanges); - $states->setTag($oldPropertyName, $newValue); + $stateChanges++; + $states[$oldPropertyName] = $newValue; } } } diff --git a/src/network/mcpe/convert/BlockStateLookupCache.php b/src/network/mcpe/convert/BlockStateLookupCache.php index 2bc5744fb..40b08e37d 100644 --- a/src/network/mcpe/convert/BlockStateLookupCache.php +++ b/src/network/mcpe/convert/BlockStateLookupCache.php @@ -74,9 +74,8 @@ final class BlockStateLookupCache{ } if(isset($this->nameToNetworkIdsLookup[$name])){ - $states = $data->getStates(); foreach($this->nameToNetworkIdsLookup[$name] as $stateId => $stateNbt){ - if($stateNbt->getStates()->equals($states)){ + if($stateNbt->equals($data)){ return $stateId; } } diff --git a/src/network/mcpe/convert/RuntimeBlockMapping.php b/src/network/mcpe/convert/RuntimeBlockMapping.php index 9c9402d31..e0acc2430 100644 --- a/src/network/mcpe/convert/RuntimeBlockMapping.php +++ b/src/network/mcpe/convert/RuntimeBlockMapping.php @@ -27,7 +27,6 @@ use pocketmine\data\bedrock\block\BlockStateData; use pocketmine\data\bedrock\block\BlockStateSerializeException; use pocketmine\data\bedrock\block\BlockStateSerializer; use pocketmine\data\bedrock\block\BlockTypeNames; -use pocketmine\nbt\tag\CompoundTag; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\SingletonTrait; use pocketmine\utils\Utils; @@ -67,7 +66,7 @@ final class RuntimeBlockMapping{ private BlockStateDictionary $blockStateDictionary, private BlockStateSerializer $blockStateSerializer ){ - $this->fallbackStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, CompoundTag::create(), BlockStateData::CURRENT_VERSION); + $this->fallbackStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION); $this->fallbackStateId = $this->blockStateDictionary->lookupStateIdFromData($this->fallbackStateData) ?? throw new AssumptionFailedError(BlockTypeNames::INFO_UPDATE . " should always exist"); } diff --git a/src/world/format/io/BaseWorldProvider.php b/src/world/format/io/BaseWorldProvider.php index 23d1ba269..dc9f296fb 100644 --- a/src/world/format/io/BaseWorldProvider.php +++ b/src/world/format/io/BaseWorldProvider.php @@ -25,7 +25,6 @@ namespace pocketmine\world\format\io; use pocketmine\data\bedrock\block\BlockStateData; use pocketmine\data\bedrock\block\BlockTypeNames; -use pocketmine\nbt\tag\CompoundTag; use pocketmine\world\format\io\exception\CorruptedWorldException; use pocketmine\world\format\io\exception\UnsupportedWorldFormatException; use pocketmine\world\format\PalettedBlockArray; @@ -63,7 +62,7 @@ abstract class BaseWorldProvider implements WorldProvider{ $newStateData = $blockDataUpgrader->upgradeIntIdMeta($legacyIdMeta >> 4, $legacyIdMeta & 0xf); if($newStateData === null){ //TODO: remember data for unknown states so we can implement them later - $newStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, CompoundTag::create(), BlockStateData::CURRENT_VERSION); + $newStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION); } $newPalette[$k] = $blockStateDeserializer->deserialize($newStateData); diff --git a/src/world/format/io/leveldb/LevelDB.php b/src/world/format/io/leveldb/LevelDB.php index 421f657b3..92e2fa853 100644 --- a/src/world/format/io/leveldb/LevelDB.php +++ b/src/world/format/io/leveldb/LevelDB.php @@ -180,7 +180,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{ //TODO: remember data for unknown states so we can implement them later //TODO: this is slow; we need to cache this //TODO: log this - $palette[] = $blockStateDeserializer->deserialize(new BlockStateData(BlockTypeNames::INFO_UPDATE, CompoundTag::create(), BlockStateData::CURRENT_VERSION)); + $palette[] = $blockStateDeserializer->deserialize(new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION)); } }catch(NbtException | BlockStateDeserializeException $e){ throw new CorruptedChunkException("Invalid blockstate NBT at offset $i in paletted storage: " . $e->getMessage(), 0, $e); diff --git a/tests/phpunit/data/bedrock/block/upgrade/BlockStateUpgraderTest.php b/tests/phpunit/data/bedrock/block/upgrade/BlockStateUpgraderTest.php index 14d3994e3..86ba0f67b 100644 --- a/tests/phpunit/data/bedrock/block/upgrade/BlockStateUpgraderTest.php +++ b/tests/phpunit/data/bedrock/block/upgrade/BlockStateUpgraderTest.php @@ -25,7 +25,6 @@ namespace pocketmine\data\bedrock\block\upgrade; use PHPUnit\Framework\TestCase; use pocketmine\data\bedrock\block\BlockStateData; -use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use const PHP_INT_MAX; @@ -81,13 +80,13 @@ class BlockStateUpgraderTest extends TestCase{ } private function getEmptyPreimage() : BlockStateData{ - return new BlockStateData(self::TEST_BLOCK, CompoundTag::create(), self::TEST_VERSION); + return new BlockStateData(self::TEST_BLOCK, [], self::TEST_VERSION); } private function getPreimageOneProperty(string $propertyName, int $value) : BlockStateData{ return new BlockStateData( self::TEST_BLOCK, - CompoundTag::create()->setInt($propertyName, $value), + [$propertyName => new IntTag($value)], self::TEST_VERSION ); } @@ -98,7 +97,7 @@ class BlockStateUpgraderTest extends TestCase{ $getStateData = fn() => $this->getEmptyPreimage(); $upgradedStateData = $this->upgrade($getStateData(), $getStateData); - self::assertSame(self::TEST_PROPERTY_VALUE_1, $upgradedStateData->getStates()->getTag(self::TEST_PROPERTY)?->getValue()); + self::assertSame(self::TEST_PROPERTY_VALUE_1, $upgradedStateData->getState(self::TEST_PROPERTY)?->getValue()); } public function testAddPropertyAlreadyExists() : void{ @@ -132,7 +131,7 @@ class BlockStateUpgraderTest extends TestCase{ $upgradedStateData = $this->upgrade($getStateData(), $getStateData); - self::assertNull($upgradedStateData->getStates()->getTag(self::TEST_PROPERTY)); + self::assertNull($upgradedStateData->getState(self::TEST_PROPERTY)); } private function prepareRenamePropertySchema(BlockStateUpgradeSchema $schema) : void{ @@ -157,7 +156,7 @@ class BlockStateUpgraderTest extends TestCase{ $upgradedStateData = $this->upgrade($getStateData(), $getStateData); - self::assertSame($valueAfter, $upgradedStateData->getStates()->getTag(self::TEST_PROPERTY_2)?->getValue()); + self::assertSame($valueAfter, $upgradedStateData->getState(self::TEST_PROPERTY_2)?->getValue()); } private function prepareRemapPropertyValueSchema(BlockStateUpgradeSchema $schema) : void{ @@ -193,7 +192,7 @@ class BlockStateUpgraderTest extends TestCase{ $upgradedStateData = $this->upgrade($getStateData(), $getStateData); - self::assertSame($upgradedStateData->getStates()->getTag(self::TEST_PROPERTY)?->getValue(), $valueAfter); + self::assertSame($upgradedStateData->getState(self::TEST_PROPERTY)?->getValue(), $valueAfter); } /** @@ -207,7 +206,7 @@ class BlockStateUpgraderTest extends TestCase{ $upgradedStateData = $this->upgrade($getStateData(), $getStateData); - self::assertSame($upgradedStateData->getStates()->getTag(self::TEST_PROPERTY_2)?->getValue(), $valueAfter); + self::assertSame($upgradedStateData->getState(self::TEST_PROPERTY_2)?->getValue(), $valueAfter); } /** @@ -228,7 +227,7 @@ class BlockStateUpgraderTest extends TestCase{ $getStateData = fn() => new BlockStateData( self::TEST_BLOCK, - CompoundTag::create(), + [], $stateVersion ); diff --git a/tools/generate-block-palette-spec.php b/tools/generate-block-palette-spec.php index b41c1334a..2bcee5a13 100644 --- a/tools/generate-block-palette-spec.php +++ b/tools/generate-block-palette-spec.php @@ -62,7 +62,7 @@ $reportMap = []; foreach($states as $state){ $name = $state->getName(); $reportMap[$name] ??= []; - foreach($state->getStates() as $propertyName => $value){ + foreach(Utils::stringifyKeys($state->getStates()) as $propertyName => $value){ if($value instanceof IntTag || $value instanceof StringTag){ $rawValue = $value->getValue(); }elseif($value instanceof ByteTag){ diff --git a/tools/generate-blockstate-upgrade-schema.php b/tools/generate-blockstate-upgrade-schema.php index 03b768323..db13f00e5 100644 --- a/tools/generate-blockstate-upgrade-schema.php +++ b/tools/generate-blockstate-upgrade-schema.php @@ -97,8 +97,8 @@ function processState(BlockStateData $old, BlockStateData $new, BlockStateUpgrad $propertyRemoved = []; $propertyAdded = []; - foreach($oldStates as $propertyName => $oldProperty){ - $newProperty = $newStates->getTag($propertyName); + foreach(Utils::stringifyKeys($oldStates) as $propertyName => $oldProperty){ + $newProperty = $new->getState($propertyName); if($newProperty === null){ $propertyRemoved[$propertyName] = $oldProperty; }elseif(!$newProperty->equals($oldProperty)){ @@ -112,8 +112,8 @@ function processState(BlockStateData $old, BlockStateData $new, BlockStateUpgrad } } - foreach($newStates as $propertyName => $value){ - if($oldStates->getTag($propertyName) === null){ + foreach(Utils::stringifyKeys($newStates) as $propertyName => $value){ + if($old->getState($propertyName) === null){ $propertyAdded[$propertyName] = $value; } } @@ -179,9 +179,9 @@ function processState(BlockStateData $old, BlockStateData $new, BlockStateUpgrad } }else{ $result->remappedStates[$oldName][] = new BlockStateUpgradeSchemaBlockRemap( - $oldStates->getValue(), + $oldStates, $new->getName(), - $newStates->getValue() + $newStates ); \GlobalLogger::get()->warning("warning: multiple properties added and removed for $oldName; added full state remap");; } @@ -231,11 +231,11 @@ function generateBlockStateUpgradeSchema(array $upgradeTable) : BlockStateUpgrad }else{ //block mapped to multiple different new IDs; we can't guess these, so we just do a plain old remap foreach($blockStateMappings as $mapping){ - if($mapping->old->getName() !== $mapping->new->getName() || !$mapping->old->getStates()->equals($mapping->new->getStates())){ + if(!$mapping->old->equals($mapping->new)){ $result->remappedStates[$mapping->old->getName()][] = new BlockStateUpgradeSchemaBlockRemap( - $mapping->old->getStates()->getValue(), + $mapping->old->getStates(), $mapping->new->getName(), - $mapping->new->getStates()->getValue() + $mapping->new->getStates() ); } }