mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 12:18:46 +00:00
Support for flattening TAG_Byte and TAG_Int properties
this allows optimisation in upcoming versions.
This commit is contained in:
parent
bdb5845cec
commit
be2437ac6e
@ -23,6 +23,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\data\bedrock\block\upgrade;
|
namespace pocketmine\data\bedrock\block\upgrade;
|
||||||
|
|
||||||
|
use pocketmine\nbt\tag\ByteTag;
|
||||||
|
use pocketmine\nbt\tag\IntTag;
|
||||||
|
use pocketmine\nbt\tag\StringTag;
|
||||||
use function ksort;
|
use function ksort;
|
||||||
use const SORT_STRING;
|
use const SORT_STRING;
|
||||||
|
|
||||||
@ -31,12 +34,14 @@ final class BlockStateUpgradeSchemaFlattenedName{
|
|||||||
/**
|
/**
|
||||||
* @param string[] $flattenedValueRemaps
|
* @param string[] $flattenedValueRemaps
|
||||||
* @phpstan-param array<string, string> $flattenedValueRemaps
|
* @phpstan-param array<string, string> $flattenedValueRemaps
|
||||||
|
* @phpstan-param class-string<ByteTag>|class-string<IntTag>|class-string<StringTag>|null $flattenedPropertyType
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $prefix,
|
public string $prefix,
|
||||||
public string $flattenedProperty,
|
public string $flattenedProperty,
|
||||||
public string $suffix,
|
public string $suffix,
|
||||||
public array $flattenedValueRemaps
|
public array $flattenedValueRemaps,
|
||||||
|
public ?string $flattenedPropertyType = null
|
||||||
){
|
){
|
||||||
ksort($this->flattenedValueRemaps, SORT_STRING);
|
ksort($this->flattenedValueRemaps, SORT_STRING);
|
||||||
}
|
}
|
||||||
@ -45,6 +50,7 @@ final class BlockStateUpgradeSchemaFlattenedName{
|
|||||||
return $this->prefix === $that->prefix &&
|
return $this->prefix === $that->prefix &&
|
||||||
$this->flattenedProperty === $that->flattenedProperty &&
|
$this->flattenedProperty === $that->flattenedProperty &&
|
||||||
$this->suffix === $that->suffix &&
|
$this->suffix === $that->suffix &&
|
||||||
$this->flattenedValueRemaps === $that->flattenedValueRemaps;
|
$this->flattenedValueRemaps === $that->flattenedValueRemaps &&
|
||||||
|
$this->flattenedPropertyType === $that->flattenedPropertyType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,18 +157,29 @@ final class BlockStateUpgradeSchemaUtils{
|
|||||||
|
|
||||||
foreach(Utils::stringifyKeys($model->remappedStates ?? []) as $oldBlockName => $remaps){
|
foreach(Utils::stringifyKeys($model->remappedStates ?? []) as $oldBlockName => $remaps){
|
||||||
foreach($remaps as $remap){
|
foreach($remaps as $remap){
|
||||||
if(isset($remap->newName) === isset($remap->newFlattenedName)){
|
if(isset($remap->newName)){
|
||||||
|
$remapName = $remap->newName;
|
||||||
|
}elseif(isset($remap->newFlattenedName)){
|
||||||
|
$flattenRule = $remap->newFlattenedName;
|
||||||
|
$remapName = new BlockStateUpgradeSchemaFlattenedName(
|
||||||
|
$flattenRule->prefix,
|
||||||
|
$flattenRule->flattenedProperty,
|
||||||
|
$flattenRule->suffix,
|
||||||
|
$flattenRule->flattenedValueRemaps ?? [],
|
||||||
|
match($flattenRule->flattenedPropertyType){
|
||||||
|
"string", null => StringTag::class,
|
||||||
|
"int" => IntTag::class,
|
||||||
|
"byte" => ByteTag::class,
|
||||||
|
default => throw new \UnexpectedValueException("Unexpected flattened property type $flattenRule->flattenedPropertyType, expected 'string', 'int' or 'byte'")
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}else{
|
||||||
throw new \UnexpectedValueException("Expected exactly one of 'newName' or 'newFlattenedName' properties to be set");
|
throw new \UnexpectedValueException("Expected exactly one of 'newName' or 'newFlattenedName' properties to be set");
|
||||||
}
|
}
|
||||||
|
|
||||||
$result->remappedStates[$oldBlockName][] = new BlockStateUpgradeSchemaBlockRemap(
|
$result->remappedStates[$oldBlockName][] = new BlockStateUpgradeSchemaBlockRemap(
|
||||||
array_map(fn(BlockStateUpgradeSchemaModelTag $tag) => self::jsonModelToTag($tag), $remap->oldState ?? []),
|
array_map(fn(BlockStateUpgradeSchemaModelTag $tag) => self::jsonModelToTag($tag), $remap->oldState ?? []),
|
||||||
$remap->newName ?? new BlockStateUpgradeSchemaFlattenedName(
|
$remapName,
|
||||||
$remap->newFlattenedName->prefix,
|
|
||||||
$remap->newFlattenedName->flattenedProperty,
|
|
||||||
$remap->newFlattenedName->suffix,
|
|
||||||
$remap->newFlattenedName->flattenedValueRemaps ?? [],
|
|
||||||
),
|
|
||||||
array_map(fn(BlockStateUpgradeSchemaModelTag $tag) => self::jsonModelToTag($tag), $remap->newState ?? []),
|
array_map(fn(BlockStateUpgradeSchemaModelTag $tag) => self::jsonModelToTag($tag), $remap->newState ?? []),
|
||||||
$remap->copiedState ?? []
|
$remap->copiedState ?? []
|
||||||
);
|
);
|
||||||
@ -303,7 +314,13 @@ final class BlockStateUpgradeSchemaUtils{
|
|||||||
$remap->newName->prefix,
|
$remap->newName->prefix,
|
||||||
$remap->newName->flattenedProperty,
|
$remap->newName->flattenedProperty,
|
||||||
$remap->newName->suffix,
|
$remap->newName->suffix,
|
||||||
$remap->newName->flattenedValueRemaps
|
$remap->newName->flattenedValueRemaps,
|
||||||
|
match($remap->newName->flattenedPropertyType){
|
||||||
|
StringTag::class => null, //omit for TAG_String, as this is the common case
|
||||||
|
ByteTag::class => "byte",
|
||||||
|
IntTag::class => "int",
|
||||||
|
default => throw new \LogicException("Unexpected tag type " . $remap->newName->flattenedPropertyType . " in flattened property type")
|
||||||
|
}
|
||||||
),
|
),
|
||||||
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->newState),
|
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->newState),
|
||||||
$remap->copiedState
|
$remap->copiedState
|
||||||
|
@ -24,10 +24,14 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\data\bedrock\block\upgrade;
|
namespace pocketmine\data\bedrock\block\upgrade;
|
||||||
|
|
||||||
use pocketmine\data\bedrock\block\BlockStateData;
|
use pocketmine\data\bedrock\block\BlockStateData;
|
||||||
|
use pocketmine\nbt\tag\ByteTag;
|
||||||
|
use pocketmine\nbt\tag\IntTag;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
use pocketmine\nbt\tag\StringTag;
|
||||||
use pocketmine\nbt\tag\Tag;
|
use pocketmine\nbt\tag\Tag;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use function count;
|
use function count;
|
||||||
|
use function get_class;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
use function ksort;
|
use function ksort;
|
||||||
use function max;
|
use function max;
|
||||||
@ -141,14 +145,21 @@ final class BlockStateUpgrader{
|
|||||||
$newName = $remap->newName;
|
$newName = $remap->newName;
|
||||||
}else{
|
}else{
|
||||||
$flattenedValue = $oldState[$remap->newName->flattenedProperty] ?? null;
|
$flattenedValue = $oldState[$remap->newName->flattenedProperty] ?? null;
|
||||||
if($flattenedValue instanceof StringTag){
|
$expectedType = $remap->newName->flattenedPropertyType;
|
||||||
$embedValue = $remap->newName->flattenedValueRemaps[$flattenedValue->getValue()] ?? $flattenedValue->getValue();
|
if(!$flattenedValue instanceof $expectedType){
|
||||||
$newName = sprintf("%s%s%s", $remap->newName->prefix, $embedValue, $remap->newName->suffix);
|
//flattened property is not of the expected type, so this transformation is not applicable
|
||||||
unset($oldState[$remap->newName->flattenedProperty]);
|
|
||||||
}else{
|
|
||||||
//flattened property is not a TAG_String, so this transformation is not applicable
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$embedKey = match(get_class($flattenedValue)){
|
||||||
|
StringTag::class => $flattenedValue->getValue(),
|
||||||
|
ByteTag::class => (string) $flattenedValue->getValue(),
|
||||||
|
IntTag::class => (string) $flattenedValue->getValue(),
|
||||||
|
//flattenedPropertyType is always one of these three types, but PHPStan doesn't know that
|
||||||
|
default => throw new AssumptionFailedError("flattenedPropertyType should be one of these three types, but have " . get_class($flattenedValue)),
|
||||||
|
};
|
||||||
|
$embedValue = $remap->newName->flattenedValueRemaps[$embedKey] ?? $embedKey;
|
||||||
|
$newName = sprintf("%s%s%s", $remap->newName->prefix, $embedValue, $remap->newName->suffix);
|
||||||
|
unset($oldState[$remap->newName->flattenedProperty]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newState = $remap->newState;
|
$newState = $remap->newState;
|
||||||
|
@ -31,6 +31,7 @@ final class BlockStateUpgradeSchemaModelFlattenedName implements \JsonSerializab
|
|||||||
public string $prefix;
|
public string $prefix;
|
||||||
/** @required */
|
/** @required */
|
||||||
public string $flattenedProperty;
|
public string $flattenedProperty;
|
||||||
|
public ?string $flattenedPropertyType = null;
|
||||||
/** @required */
|
/** @required */
|
||||||
public string $suffix;
|
public string $suffix;
|
||||||
/**
|
/**
|
||||||
@ -43,11 +44,12 @@ final class BlockStateUpgradeSchemaModelFlattenedName implements \JsonSerializab
|
|||||||
* @param string[] $flattenedValueRemaps
|
* @param string[] $flattenedValueRemaps
|
||||||
* @phpstan-param array<string, string> $flattenedValueRemaps
|
* @phpstan-param array<string, string> $flattenedValueRemaps
|
||||||
*/
|
*/
|
||||||
public function __construct(string $prefix, string $flattenedProperty, string $suffix, array $flattenedValueRemaps){
|
public function __construct(string $prefix, string $flattenedProperty, string $suffix, array $flattenedValueRemaps, ?string $flattenedPropertyType = null){
|
||||||
$this->prefix = $prefix;
|
$this->prefix = $prefix;
|
||||||
$this->flattenedProperty = $flattenedProperty;
|
$this->flattenedProperty = $flattenedProperty;
|
||||||
$this->suffix = $suffix;
|
$this->suffix = $suffix;
|
||||||
$this->flattenedValueRemaps = $flattenedValueRemaps;
|
$this->flattenedValueRemaps = $flattenedValueRemaps;
|
||||||
|
$this->flattenedPropertyType = $flattenedPropertyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,6 +60,9 @@ final class BlockStateUpgradeSchemaModelFlattenedName implements \JsonSerializab
|
|||||||
if(count($this->flattenedValueRemaps) === 0){
|
if(count($this->flattenedValueRemaps) === 0){
|
||||||
unset($result["flattenedValueRemaps"]);
|
unset($result["flattenedValueRemaps"]);
|
||||||
}
|
}
|
||||||
|
if($this->flattenedPropertyType === null){
|
||||||
|
unset($result["flattenedPropertyType"]);
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,8 @@ use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaFlattenedName;
|
|||||||
use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaUtils;
|
use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaUtils;
|
||||||
use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaValueRemap;
|
use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaValueRemap;
|
||||||
use pocketmine\nbt\LittleEndianNbtSerializer;
|
use pocketmine\nbt\LittleEndianNbtSerializer;
|
||||||
|
use pocketmine\nbt\tag\ByteTag;
|
||||||
|
use pocketmine\nbt\tag\IntTag;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
use pocketmine\nbt\tag\StringTag;
|
||||||
use pocketmine\nbt\tag\Tag;
|
use pocketmine\nbt\tag\Tag;
|
||||||
use pocketmine\nbt\TreeRoot;
|
use pocketmine\nbt\TreeRoot;
|
||||||
@ -48,7 +50,10 @@ use function count;
|
|||||||
use function dirname;
|
use function dirname;
|
||||||
use function file_put_contents;
|
use function file_put_contents;
|
||||||
use function fwrite;
|
use function fwrite;
|
||||||
|
use function get_class;
|
||||||
|
use function get_debug_type;
|
||||||
use function implode;
|
use function implode;
|
||||||
|
use function is_numeric;
|
||||||
use function json_encode;
|
use function json_encode;
|
||||||
use function ksort;
|
use function ksort;
|
||||||
use function min;
|
use function min;
|
||||||
@ -312,11 +317,13 @@ function findCommonSuffix(array $strings) : string{
|
|||||||
/**
|
/**
|
||||||
* @param string[][][] $candidateFlattenedValues
|
* @param string[][][] $candidateFlattenedValues
|
||||||
* @phpstan-param array<string, array<string, array<string, string>>> $candidateFlattenedValues
|
* @phpstan-param array<string, array<string, array<string, string>>> $candidateFlattenedValues
|
||||||
|
* @param string[] $candidateFlattenPropertyTypes
|
||||||
|
* @phpstan-param array<string, class-string<ByteTag>|class-string<IntTag>|class-string<StringTag>> $candidateFlattenPropertyTypes
|
||||||
*
|
*
|
||||||
* @return BlockStateUpgradeSchemaFlattenedName[][]
|
* @return BlockStateUpgradeSchemaFlattenedName[][]
|
||||||
* @phpstan-return array<string, array<string, BlockStateUpgradeSchemaFlattenedName>>
|
* @phpstan-return array<string, array<string, BlockStateUpgradeSchemaFlattenedName>>
|
||||||
*/
|
*/
|
||||||
function buildFlattenPropertyRules(array $candidateFlattenedValues) : array{
|
function buildFlattenPropertyRules(array $candidateFlattenedValues, array $candidateFlattenPropertyTypes) : array{
|
||||||
$flattenPropertyRules = [];
|
$flattenPropertyRules = [];
|
||||||
foreach(Utils::stringifyKeys($candidateFlattenedValues) as $propertyName => $filters){
|
foreach(Utils::stringifyKeys($candidateFlattenedValues) as $propertyName => $filters){
|
||||||
foreach(Utils::stringifyKeys($filters) as $filter => $valueToId){
|
foreach(Utils::stringifyKeys($filters) as $filter => $valueToId){
|
||||||
@ -340,11 +347,26 @@ function buildFlattenPropertyRules(array $candidateFlattenedValues) : array{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$allNumeric = true;
|
||||||
|
if(count($valueMap) > 0){
|
||||||
|
foreach(Utils::stringifyKeys($valueMap) as $value => $newValue){
|
||||||
|
if(!is_numeric($value)){
|
||||||
|
$allNumeric = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($allNumeric){
|
||||||
|
//add a dummy key to force the JSON to be an object and not a list
|
||||||
|
$valueMap["dummy"] = "map_not_list";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$flattenPropertyRules[$propertyName][$filter] = new BlockStateUpgradeSchemaFlattenedName(
|
$flattenPropertyRules[$propertyName][$filter] = new BlockStateUpgradeSchemaFlattenedName(
|
||||||
$idPrefix,
|
$idPrefix,
|
||||||
$propertyName,
|
$propertyName,
|
||||||
$idSuffix,
|
$idSuffix,
|
||||||
$valueMap
|
$valueMap,
|
||||||
|
$candidateFlattenPropertyTypes[$propertyName],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,16 +429,25 @@ function processRemappedStates(array $upgradeTable) : array{
|
|||||||
$notFlattenedProperties = [];
|
$notFlattenedProperties = [];
|
||||||
|
|
||||||
$candidateFlattenedValues = [];
|
$candidateFlattenedValues = [];
|
||||||
|
$candidateFlattenedPropertyTypes = [];
|
||||||
foreach($upgradeTable as $pair){
|
foreach($upgradeTable as $pair){
|
||||||
foreach(Utils::stringifyKeys($pair->old->getStates()) as $propertyName => $propertyValue){
|
foreach(Utils::stringifyKeys($pair->old->getStates()) as $propertyName => $propertyValue){
|
||||||
if(isset($notFlattenedProperties[$propertyName])){
|
if(isset($notFlattenedProperties[$propertyName])){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(!$propertyValue instanceof StringTag){
|
if(!$propertyValue instanceof StringTag && !$propertyValue instanceof IntTag && !$propertyValue instanceof ByteTag){
|
||||||
$notFlattenedProperties[$propertyName] = true;
|
$notFlattenedProperties[$propertyName] = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$rawValue = $propertyValue->getValue();
|
$previousType = $candidateFlattenedPropertyTypes[$propertyName] ?? null;
|
||||||
|
if($previousType !== null && $previousType !== get_class($propertyValue)){
|
||||||
|
//mismatched types for the same property name - this has never happened so far, but it's not impossible
|
||||||
|
$notFlattenedProperties[$propertyName] = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$candidateFlattenedPropertyTypes[$propertyName] = get_class($propertyValue);
|
||||||
|
|
||||||
|
$rawValue = (string) $propertyValue->getValue();
|
||||||
if($rawValue === ""){
|
if($rawValue === ""){
|
||||||
$notFlattenedProperties[$propertyName] = true;
|
$notFlattenedProperties[$propertyName] = true;
|
||||||
continue;
|
continue;
|
||||||
@ -458,7 +489,7 @@ function processRemappedStates(array $upgradeTable) : array{
|
|||||||
unset($candidateFlattenedValues[$propertyName]);
|
unset($candidateFlattenedValues[$propertyName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$flattenedProperties = buildFlattenPropertyRules($candidateFlattenedValues);
|
$flattenedProperties = buildFlattenPropertyRules($candidateFlattenedValues, $candidateFlattenedPropertyTypes);
|
||||||
$flattenProperty = array_key_first($flattenedProperties);
|
$flattenProperty = array_key_first($flattenedProperties);
|
||||||
//Properties with fewer rules take up less space for the same result
|
//Properties with fewer rules take up less space for the same result
|
||||||
foreach(Utils::stringifyKeys($flattenedProperties) as $propertyName => $rules){
|
foreach(Utils::stringifyKeys($flattenedProperties) as $propertyName => $rules){
|
||||||
@ -485,8 +516,8 @@ function processRemappedStates(array $upgradeTable) : array{
|
|||||||
ksort($cleanedNewState);
|
ksort($cleanedNewState);
|
||||||
if($flattenProperty !== null){
|
if($flattenProperty !== null){
|
||||||
$flattenedValue = $cleanedOldState[$flattenProperty] ?? null;
|
$flattenedValue = $cleanedOldState[$flattenProperty] ?? null;
|
||||||
if(!$flattenedValue instanceof StringTag){
|
if(!$flattenedValue instanceof StringTag && !$flattenedValue instanceof IntTag && !$flattenedValue instanceof ByteTag){
|
||||||
throw new AssumptionFailedError("This should always be a TAG_String ($newName $flattenProperty)");
|
throw new AssumptionFailedError("Non-flattenable type of tag ($newName $flattenProperty) but have " . get_debug_type($flattenedValue));
|
||||||
}
|
}
|
||||||
unset($cleanedOldState[$flattenProperty]);
|
unset($cleanedOldState[$flattenProperty]);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user