mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 08:44:01 +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 $maxVersionPatch,
|
||||
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{
|
||||
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{
|
||||
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(
|
||||
$model->maxVersionMajor,
|
||||
$model->maxVersionMinor,
|
||||
$model->maxVersionPatch,
|
||||
$model->maxVersionRevision,
|
||||
$priority
|
||||
$schemaId
|
||||
);
|
||||
$result->renamedIds = $model->renamedIds ?? [];
|
||||
$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[]
|
||||
*/
|
||||
public static function loadSchemas(string $path, int $currentVersion) : array{
|
||||
public static function loadSchemas(string $path, int $maxSchemaId) : array{
|
||||
$iterator = new \RegexIterator(
|
||||
new \FilesystemIterator(
|
||||
$path,
|
||||
@ -270,32 +270,30 @@ final class BlockStateUpgradeSchemaUtils{
|
||||
/** @var string[] $matches */
|
||||
foreach($iterator as $matches){
|
||||
$filename = $matches[0];
|
||||
$priority = (int) $matches[1];
|
||||
$schemaId = (int) $matches[1];
|
||||
|
||||
if($schemaId > $maxSchemaId){
|
||||
continue;
|
||||
}
|
||||
|
||||
$fullPath = Path::join($path, $filename);
|
||||
|
||||
$raw = Filesystem::fileGetContents($fullPath);
|
||||
|
||||
try{
|
||||
$schema = self::loadSchemaFromString($raw, $priority);
|
||||
$schema = self::loadSchemaFromString($raw, $schemaId);
|
||||
}catch(\RuntimeException $e){
|
||||
throw new \RuntimeException("Loading schema file $fullPath: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
if($schema->getVersionId() > $currentVersion){
|
||||
//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;
|
||||
$result[$schemaId] = $schema;
|
||||
}
|
||||
|
||||
ksort($result, SORT_NUMERIC);
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function loadSchemaFromString(string $raw, int $priority) : BlockStateUpgradeSchema{
|
||||
public static function loadSchemaFromString(string $raw, int $schemaId) : BlockStateUpgradeSchema{
|
||||
try{
|
||||
$json = json_decode($raw, false, flags: JSON_THROW_ON_ERROR);
|
||||
}catch(\JsonException $e){
|
||||
@ -312,6 +310,6 @@ final class BlockStateUpgradeSchemaUtils{
|
||||
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;
|
||||
|
||||
final class BlockStateUpgrader{
|
||||
/** @var BlockStateUpgradeSchema[][] */
|
||||
/** @var BlockStateUpgradeSchema[] */
|
||||
private array $upgradeSchemas = [];
|
||||
|
||||
/**
|
||||
@ -45,59 +45,54 @@ final class BlockStateUpgrader{
|
||||
}
|
||||
|
||||
public function addSchema(BlockStateUpgradeSchema $schema) : void{
|
||||
$schemaList = $this->upgradeSchemas[$schema->getVersionId()] ?? [];
|
||||
|
||||
$priority = $schema->getPriority();
|
||||
if(isset($schemaList[$priority])){
|
||||
throw new \InvalidArgumentException("Cannot add two schemas to the same version with the same priority");
|
||||
$schemaId = $schema->getSchemaId();
|
||||
if(isset($this->upgradeSchemas[$schemaId])){
|
||||
throw new \InvalidArgumentException("Cannot add two schemas with the same schema ID");
|
||||
}
|
||||
$schemaList[$priority] = $schema;
|
||||
ksort($schemaList, SORT_NUMERIC);
|
||||
$this->upgradeSchemas[$schema->getVersionId()] = $schemaList;
|
||||
$this->upgradeSchemas[$schemaId] = $schema;
|
||||
|
||||
ksort($this->upgradeSchemas, SORT_NUMERIC);
|
||||
}
|
||||
|
||||
public function upgrade(BlockStateData $blockStateData) : BlockStateData{
|
||||
$version = $blockStateData->getVersion();
|
||||
foreach($this->upgradeSchemas as $resultVersion => $schemas){
|
||||
foreach($this->upgradeSchemas as $schema){
|
||||
$resultVersion = $schema->getVersionId();
|
||||
if($version > $resultVersion){
|
||||
//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 :(
|
||||
continue;
|
||||
}
|
||||
foreach($schemas as $schema){
|
||||
$oldName = $blockStateData->getName();
|
||||
$oldState = $blockStateData->getStates();
|
||||
if(isset($schema->remappedStates[$oldName])){
|
||||
foreach($schema->remappedStates[$oldName] as $remap){
|
||||
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
|
||||
$oldName = $blockStateData->getName();
|
||||
$oldState = $blockStateData->getStates();
|
||||
if(isset($schema->remappedStates[$oldName])){
|
||||
foreach($schema->remappedStates[$oldName] as $remap){
|
||||
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;
|
||||
}
|
||||
$newName = $schema->renamedIds[$oldName] ?? null;
|
||||
|
||||
$stateChanges = 0;
|
||||
$states = $blockStateData->getStates();
|
||||
$stateChanges = 0;
|
||||
$states = $blockStateData->getStates();
|
||||
|
||||
$states = $this->applyPropertyAdded($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyRemoved($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyRenamedOrValueChanged($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyValueChanged($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyAdded($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyRemoved($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyRenamedOrValueChanged($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyValueChanged($schema, $oldName, $states, $stateChanges);
|
||||
|
||||
if($newName !== null || $stateChanges > 0){
|
||||
$blockStateData = new BlockStateData($newName ?? $oldName, $states, $resultVersion);
|
||||
//don't break out; we may need to further upgrade the state
|
||||
}
|
||||
if($newName !== null || $stateChanges > 0){
|
||||
$blockStateData = new BlockStateData($newName ?? $oldName, $states, $resultVersion);
|
||||
//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.
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -64,7 +65,7 @@ final class GlobalBlockStateHandlers{
|
||||
if(self::$blockDataUpgrader === null){
|
||||
$blockStateUpgrader = new BlockStateUpgrader(BlockStateUpgradeSchemaUtils::loadSchemas(
|
||||
Path::join(BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH, 'nbt_upgrade_schema'),
|
||||
BlockStateData::CURRENT_VERSION
|
||||
self::MAX_BLOCKSTATE_UPGRADE_SCHEMA_ID
|
||||
));
|
||||
self::$blockDataUpgrader = new BlockDataUpgrader(
|
||||
BlockIdMetaUpgrader::loadFromString(
|
||||
|
Loading…
x
Reference in New Issue
Block a user