mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-25 04:44:03 +00:00
BlockStateUpgrader: do not apply backwards-incompatible schemas to blockstates already on the correct version
this notably led to corruption of glow_lichen and sculk_vein in 1.18.10.
This commit is contained in:
parent
8a11ed70e3
commit
905eee3198
@ -64,6 +64,8 @@ final class BlockStateUpgradeSchema{
|
|||||||
*/
|
*/
|
||||||
public array $remappedStates = [];
|
public array $remappedStates = [];
|
||||||
|
|
||||||
|
private ?bool $backwardsCompatible = null;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public int $maxVersionMajor,
|
public int $maxVersionMajor,
|
||||||
public int $maxVersionMinor,
|
public int $maxVersionMinor,
|
||||||
@ -91,4 +93,22 @@ final class BlockStateUpgradeSchema{
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isBackwardsCompatible() : bool{
|
||||||
|
if($this->backwardsCompatible === null){
|
||||||
|
$this->backwardsCompatible = true;
|
||||||
|
foreach([
|
||||||
|
$this->renamedIds,
|
||||||
|
$this->removedProperties,
|
||||||
|
$this->remappedPropertyValues,
|
||||||
|
$this->remappedStates
|
||||||
|
] as $bcBreakingRules){
|
||||||
|
if(count($bcBreakingRules) !== 0){
|
||||||
|
$this->backwardsCompatible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//schemas which only add properties are backwards compatible
|
||||||
|
return $this->backwardsCompatible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ use pocketmine\data\bedrock\blockstate\BlockStateData;
|
|||||||
use pocketmine\nbt\tag\CompoundTag;
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
use pocketmine\nbt\tag\Tag;
|
use pocketmine\nbt\tag\Tag;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
|
use function array_unshift;
|
||||||
use function ksort;
|
use function ksort;
|
||||||
use const SORT_NUMERIC;
|
use const SORT_NUMERIC;
|
||||||
|
|
||||||
@ -39,18 +40,26 @@ final class BlockStateUpgrader{
|
|||||||
* @phpstan-param array<int, BlockStateUpgradeSchema> $upgradeSchemas
|
* @phpstan-param array<int, BlockStateUpgradeSchema> $upgradeSchemas
|
||||||
*/
|
*/
|
||||||
public function __construct(array $upgradeSchemas){
|
public function __construct(array $upgradeSchemas){
|
||||||
foreach($upgradeSchemas as $priority => $schema){
|
foreach($upgradeSchemas as $schema){
|
||||||
$this->addSchema($schema, $priority);
|
$this->addSchema($schema);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addSchema(BlockStateUpgradeSchema $schema, int $priority) : void{
|
public function addSchema(BlockStateUpgradeSchema $schema) : void{
|
||||||
if(isset($this->upgradeSchemas[$schema->getVersionId()][$priority])){
|
if(!$schema->isBackwardsCompatible()){
|
||||||
throw new \InvalidArgumentException("Another schema already has this priority");
|
$schemaList = $this->upgradeSchemas[$schema->getVersionId()] ?? [];
|
||||||
|
foreach($schemaList as $otherSchema){
|
||||||
|
if(!$otherSchema->isBackwardsCompatible()){
|
||||||
|
throw new \InvalidArgumentException("Cannot add two backwards-incompatible schemas with the same version");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_unshift($schemaList, $schema);
|
||||||
|
$this->upgradeSchemas[$schema->getVersionId()] = $schemaList;
|
||||||
|
}else{
|
||||||
|
//Backwards-compatible schemas can be added in any order
|
||||||
|
$this->upgradeSchemas[$schema->getVersionId()][] = $schema;
|
||||||
}
|
}
|
||||||
$this->upgradeSchemas[$schema->getVersionId()][$priority] = $schema;
|
|
||||||
ksort($this->upgradeSchemas, SORT_NUMERIC);
|
ksort($this->upgradeSchemas, SORT_NUMERIC);
|
||||||
ksort($this->upgradeSchemas[$schema->getVersionId()], SORT_NUMERIC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function upgrade(BlockStateData $blockStateData) : BlockStateData{
|
public function upgrade(BlockStateData $blockStateData) : BlockStateData{
|
||||||
@ -62,6 +71,11 @@ final class BlockStateUpgrader{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
foreach($schemas as $schema){
|
foreach($schemas as $schema){
|
||||||
|
if(!$schema->isBackwardsCompatible() && $resultVersion === $version){
|
||||||
|
//backwards-compatible updates typically don't bump version and must always be applied because we
|
||||||
|
//can't tell any different, but backwards-incompatible ones SHOULD always get their own version bump
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$oldName = $blockStateData->getName();
|
$oldName = $blockStateData->getName();
|
||||||
if(isset($schema->remappedStates[$oldName])){
|
if(isset($schema->remappedStates[$oldName])){
|
||||||
foreach($schema->remappedStates[$oldName] as $remap){
|
foreach($schema->remappedStates[$oldName] as $remap){
|
||||||
|
@ -53,7 +53,7 @@ class BlockStateUpgraderTest extends TestCase{
|
|||||||
|
|
||||||
private function getNewSchemaVersion(int $versionId) : BlockStateUpgradeSchema{
|
private function getNewSchemaVersion(int $versionId) : BlockStateUpgradeSchema{
|
||||||
$schema = new BlockStateUpgradeSchema(($versionId >> 24) & 0xff, ($versionId >> 16) & 0xff, ($versionId >> 8) & 0xff, $versionId & 0xff);
|
$schema = new BlockStateUpgradeSchema(($versionId >> 24) & 0xff, ($versionId >> 16) & 0xff, ($versionId >> 8) & 0xff, $versionId & 0xff);
|
||||||
$this->upgrader->addSchema($schema, 0);
|
$this->upgrader->addSchema($schema);
|
||||||
return $schema;
|
return $schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user