BlockStateUpgrader: do not use blockstate version to manage internal schemas

these are no longer reliable.
This commit is contained in:
Dylan K. Taylor 2023-02-01 22:35:59 +00:00
parent d3fff4e0b2
commit 0e15a8698a
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
4 changed files with 53 additions and 55 deletions

View File

@ -69,14 +69,18 @@ final class BlockStateUpgradeSchema{
public int $maxVersionMinor, public int $maxVersionMinor,
public int $maxVersionPatch, public int $maxVersionPatch,
public int $maxVersionRevision, public int $maxVersionRevision,
private int $priority private int $schemaId
){} ){}
/**
* @deprecated This is defined by Mojang, and therefore cannot be relied on. Use getSchemaId() instead for
* internal version management.
*/
public function getVersionId() : int{ public function getVersionId() : int{
return ($this->maxVersionMajor << 24) | ($this->maxVersionMinor << 16) | ($this->maxVersionPatch << 8) | $this->maxVersionRevision; return ($this->maxVersionMajor << 24) | ($this->maxVersionMinor << 16) | ($this->maxVersionPatch << 8) | $this->maxVersionRevision;
} }
public function getPriority() : int{ return $this->priority; } public function getSchemaId() : int{ return $this->schemaId; }
public function isEmpty() : bool{ public function isEmpty() : bool{
foreach([ foreach([

View File

@ -110,13 +110,13 @@ final class BlockStateUpgradeSchemaUtils{
}; };
} }
public static function fromJsonModel(BlockStateUpgradeSchemaModel $model, int $priority) : BlockStateUpgradeSchema{ public static function fromJsonModel(BlockStateUpgradeSchemaModel $model, int $schemaId) : BlockStateUpgradeSchema{
$result = new BlockStateUpgradeSchema( $result = new BlockStateUpgradeSchema(
$model->maxVersionMajor, $model->maxVersionMajor,
$model->maxVersionMinor, $model->maxVersionMinor,
$model->maxVersionPatch, $model->maxVersionPatch,
$model->maxVersionRevision, $model->maxVersionRevision,
$priority $schemaId
); );
$result->renamedIds = $model->renamedIds ?? []; $result->renamedIds = $model->renamedIds ?? [];
$result->renamedProperties = $model->renamedProperties ?? []; $result->renamedProperties = $model->renamedProperties ?? [];
@ -250,11 +250,11 @@ final class BlockStateUpgradeSchemaUtils{
} }
/** /**
* Returns a list of schemas ordered by priority. Oldest schemas appear first. * Returns a list of schemas ordered by schema ID. Oldest schemas appear first.
* *
* @return BlockStateUpgradeSchema[] * @return BlockStateUpgradeSchema[]
*/ */
public static function loadSchemas(string $path, int $currentVersion) : array{ public static function loadSchemas(string $path, int $maxSchemaId) : array{
$iterator = new \RegexIterator( $iterator = new \RegexIterator(
new \FilesystemIterator( new \FilesystemIterator(
$path, $path,
@ -270,32 +270,30 @@ final class BlockStateUpgradeSchemaUtils{
/** @var string[] $matches */ /** @var string[] $matches */
foreach($iterator as $matches){ foreach($iterator as $matches){
$filename = $matches[0]; $filename = $matches[0];
$priority = (int) $matches[1]; $schemaId = (int) $matches[1];
if($schemaId > $maxSchemaId){
continue;
}
$fullPath = Path::join($path, $filename); $fullPath = Path::join($path, $filename);
$raw = Filesystem::fileGetContents($fullPath); $raw = Filesystem::fileGetContents($fullPath);
try{ try{
$schema = self::loadSchemaFromString($raw, $priority); $schema = self::loadSchemaFromString($raw, $schemaId);
}catch(\RuntimeException $e){ }catch(\RuntimeException $e){
throw new \RuntimeException("Loading schema file $fullPath: " . $e->getMessage(), 0, $e); throw new \RuntimeException("Loading schema file $fullPath: " . $e->getMessage(), 0, $e);
} }
if($schema->getVersionId() > $currentVersion){ $result[$schemaId] = $schema;
//this might be a beta schema which shouldn't be applicable
//TODO: why do we load the whole schema just to throw it away if it's too new? ...
continue;
}
$result[$priority] = $schema;
} }
ksort($result, SORT_NUMERIC); ksort($result, SORT_NUMERIC);
return $result; return $result;
} }
public static function loadSchemaFromString(string $raw, int $priority) : BlockStateUpgradeSchema{ public static function loadSchemaFromString(string $raw, int $schemaId) : BlockStateUpgradeSchema{
try{ try{
$json = json_decode($raw, false, flags: JSON_THROW_ON_ERROR); $json = json_decode($raw, false, flags: JSON_THROW_ON_ERROR);
}catch(\JsonException $e){ }catch(\JsonException $e){
@ -312,6 +310,6 @@ final class BlockStateUpgradeSchemaUtils{
throw new \RuntimeException($e->getMessage(), 0, $e); throw new \RuntimeException($e->getMessage(), 0, $e);
} }
return self::fromJsonModel($model, $priority); return self::fromJsonModel($model, $schemaId);
} }
} }

View File

@ -31,7 +31,7 @@ use function ksort;
use const SORT_NUMERIC; use const SORT_NUMERIC;
final class BlockStateUpgrader{ final class BlockStateUpgrader{
/** @var BlockStateUpgradeSchema[][] */ /** @var BlockStateUpgradeSchema[] */
private array $upgradeSchemas = []; private array $upgradeSchemas = [];
/** /**
@ -45,28 +45,24 @@ final class BlockStateUpgrader{
} }
public function addSchema(BlockStateUpgradeSchema $schema) : void{ public function addSchema(BlockStateUpgradeSchema $schema) : void{
$schemaList = $this->upgradeSchemas[$schema->getVersionId()] ?? []; $schemaId = $schema->getSchemaId();
if(isset($this->upgradeSchemas[$schemaId])){
$priority = $schema->getPriority(); throw new \InvalidArgumentException("Cannot add two schemas with the same schema ID");
if(isset($schemaList[$priority])){
throw new \InvalidArgumentException("Cannot add two schemas to the same version with the same priority");
} }
$schemaList[$priority] = $schema; $this->upgradeSchemas[$schemaId] = $schema;
ksort($schemaList, SORT_NUMERIC);
$this->upgradeSchemas[$schema->getVersionId()] = $schemaList;
ksort($this->upgradeSchemas, SORT_NUMERIC); ksort($this->upgradeSchemas, SORT_NUMERIC);
} }
public function upgrade(BlockStateData $blockStateData) : BlockStateData{ public function upgrade(BlockStateData $blockStateData) : BlockStateData{
$version = $blockStateData->getVersion(); $version = $blockStateData->getVersion();
foreach($this->upgradeSchemas as $resultVersion => $schemas){ foreach($this->upgradeSchemas as $schema){
$resultVersion = $schema->getVersionId();
if($version > $resultVersion){ if($version > $resultVersion){
//even if this is actually the same version, we have to apply it anyway because mojang are dumb and //even if this is actually the same version, we have to apply it anyway because mojang are dumb and
//didn't always bump the blockstate version when changing it :( //didn't always bump the blockstate version when changing it :(
continue; continue;
} }
foreach($schemas as $schema){
$oldName = $blockStateData->getName(); $oldName = $blockStateData->getName();
$oldState = $blockStateData->getStates(); $oldState = $blockStateData->getStates();
if(isset($schema->remappedStates[$oldName])){ if(isset($schema->remappedStates[$oldName])){
@ -99,7 +95,6 @@ final class BlockStateUpgrader{
//don't break out; we may need to further upgrade the state //don't break out; we may need to further upgrade the state
} }
} }
}
return $blockStateData; return $blockStateData;
} }

View File

@ -43,6 +43,7 @@ use const pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH;
* benefits for now. * benefits for now.
*/ */
final class GlobalBlockStateHandlers{ final class GlobalBlockStateHandlers{
public const MAX_BLOCKSTATE_UPGRADE_SCHEMA_ID = 151; //https://github.com/pmmp/BedrockBlockUpgradeSchema/blob/b0cc441e029cf5a6de5b05dd0f5657208855232b/nbt_upgrade_schema/0151_1.19.0.34_beta_to_1.19.20.json
private static ?BlockObjectToStateSerializer $blockStateSerializer = null; private static ?BlockObjectToStateSerializer $blockStateSerializer = null;
@ -64,7 +65,7 @@ final class GlobalBlockStateHandlers{
if(self::$blockDataUpgrader === null){ if(self::$blockDataUpgrader === null){
$blockStateUpgrader = new BlockStateUpgrader(BlockStateUpgradeSchemaUtils::loadSchemas( $blockStateUpgrader = new BlockStateUpgrader(BlockStateUpgradeSchemaUtils::loadSchemas(
Path::join(BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH, 'nbt_upgrade_schema'), Path::join(BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH, 'nbt_upgrade_schema'),
BlockStateData::CURRENT_VERSION self::MAX_BLOCKSTATE_UPGRADE_SCHEMA_ID
)); ));
self::$blockDataUpgrader = new BlockDataUpgrader( self::$blockDataUpgrader = new BlockDataUpgrader(
BlockIdMetaUpgrader::loadFromString( BlockIdMetaUpgrader::loadFromString(