diff --git a/src/pocketmine/level/format/io/BaseLevelProvider.php b/src/pocketmine/level/format/io/BaseLevelProvider.php index 1a4f2e90e..664dd2586 100644 --- a/src/pocketmine/level/format/io/BaseLevelProvider.php +++ b/src/pocketmine/level/format/io/BaseLevelProvider.php @@ -61,6 +61,8 @@ abstract class BaseLevelProvider implements LevelProvider{ protected function fixLevelData() : void{ if(!$this->levelData->hasTag("generatorName", StringTag::class)){ $this->levelData->setString("generatorName", "default", true); + }elseif(($generatorName = self::hackyFixForGeneratorClasspathInLevelDat($this->levelData->getString("generatorName"))) !== null){ + $this->levelData->setString("generatorName", $generatorName); } if(!$this->levelData->hasTag("generatorOptions", StringTag::class)){ @@ -68,6 +70,35 @@ abstract class BaseLevelProvider implements LevelProvider{ } } + /** + * Hack to fix worlds broken previously by older versions of PocketMine-MP which incorrectly saved classpaths of + * generators into level.dat on imported (not generated) worlds. + * + * This should only have affected leveldb worlds as far as I know, because PC format worlds include the + * generatorName tag by default. However, MCPE leveldb ones didn't, and so they would get filled in with something + * broken. + * + * This bug took a long time to get found because previously the generator manager would just return the default + * generator silently on failure to identify the correct generator, which caused lots of unexpected bugs. + * + * Only classnames which were written into the level.dat from "fixing" the level data are included here. These are + * hardcoded to avoid problems fixing broken worlds in the future if these classes get moved, renamed or removed. + * + * @param string $className Classname saved in level.dat + * + * @return null|string Name of the correct generator to replace the broken value + */ + protected static function hackyFixForGeneratorClasspathInLevelDat(string $className) : ?string{ + switch($className){ + case 'pocketmine\level\generator\normal\Normal': + return "normal"; + case 'pocketmine\level\generator\Flat': + return "flat"; + } + + return null; + } + public function getPath() : string{ return $this->path; } diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index 1cd8b57ac..a71deb1dd 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -142,6 +142,8 @@ class LevelDB extends BaseLevelProvider{ }else{ $this->levelData->setString("generatorName", "default"); } + }elseif(($generatorName = self::hackyFixForGeneratorClasspathInLevelDat($this->levelData->getString("generatorName"))) !== null){ + $this->levelData->setString("generatorName", $generatorName); } if(!$this->levelData->hasTag("generatorOptions", StringTag::class)){