mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-09 11:31:49 +00:00
BlockStateUpgrader: do not use blockstate version to manage internal schemas
these are no longer reliable.
This commit is contained in:
parent
d3fff4e0b2
commit
0e15a8698a
@ -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([
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,59 +45,54 @@ 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])){
|
foreach($schema->remappedStates[$oldName] as $remap){
|
||||||
foreach($schema->remappedStates[$oldName] as $remap){
|
if(count($oldState) !== count($remap->oldState)){
|
||||||
if(count($oldState) !== count($remap->oldState)){
|
continue; //try next state
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
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;
|
}
|
||||||
|
$newName = $schema->renamedIds[$oldName] ?? null;
|
||||||
|
|
||||||
$stateChanges = 0;
|
$stateChanges = 0;
|
||||||
$states = $blockStateData->getStates();
|
$states = $blockStateData->getStates();
|
||||||
|
|
||||||
$states = $this->applyPropertyAdded($schema, $oldName, $states, $stateChanges);
|
$states = $this->applyPropertyAdded($schema, $oldName, $states, $stateChanges);
|
||||||
$states = $this->applyPropertyRemoved($schema, $oldName, $states, $stateChanges);
|
$states = $this->applyPropertyRemoved($schema, $oldName, $states, $stateChanges);
|
||||||
$states = $this->applyPropertyRenamedOrValueChanged($schema, $oldName, $states, $stateChanges);
|
$states = $this->applyPropertyRenamedOrValueChanged($schema, $oldName, $states, $stateChanges);
|
||||||
$states = $this->applyPropertyValueChanged($schema, $oldName, $states, $stateChanges);
|
$states = $this->applyPropertyValueChanged($schema, $oldName, $states, $stateChanges);
|
||||||
|
|
||||||
if($newName !== null || $stateChanges > 0){
|
if($newName !== null || $stateChanges > 0){
|
||||||
$blockStateData = new BlockStateData($newName ?? $oldName, $states, $resultVersion);
|
$blockStateData = new BlockStateData($newName ?? $oldName, $states, $resultVersion);
|
||||||
//don't break out; we may need to further upgrade the state
|
//don't break out; we may need to further upgrade the state
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user