mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-28 08:07:01 +00:00
Fixed remaining cases of undefined behaviour on ambiguous world format
It was still possible to produce undefined behaviour by creating a db folder in a region-based world, or adding regions to a leveldb world. This now solves the problem completely by refusing to load the world if multiple formats match the world.
This commit is contained in:
parent
0cc4bc48cc
commit
a273a0c8a9
@ -1035,13 +1035,17 @@ class Server{
|
||||
|
||||
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
||||
|
||||
$providerClass = LevelProviderManager::getProvider($path);
|
||||
|
||||
if($providerClass === null){
|
||||
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.loadError", [$name, "Cannot identify format of world"]));
|
||||
|
||||
$providers = LevelProviderManager::getMatchingProviders($path);
|
||||
if(count($providers) !== 1){
|
||||
$this->logger->error($this->language->translateString("pocketmine.level.loadError", [
|
||||
$name,
|
||||
empty($providers) ?
|
||||
$this->language->translateString("pocketmine.level.unknownFormat") :
|
||||
$this->language->translateString("pocketmine.level.ambiguousFormat", [implode(", ", array_keys($providers))])
|
||||
]));
|
||||
return false;
|
||||
}
|
||||
$providerClass = array_shift($providers);
|
||||
|
||||
/** @see LevelProvider::__construct() */
|
||||
$level = new Level($this, $name, new $providerClass($path));
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 7f12f293bfad76e5c07b929c893e848728064977
|
||||
Subproject commit e738dc7ca0171a1a16e3682fc2a7619c059988b9
|
@ -87,17 +87,17 @@ abstract class LevelProviderManager{
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|null
|
||||
* @return string[]|LevelProvider[]
|
||||
*/
|
||||
public static function getProvider(string $path){
|
||||
foreach(self::$providers as $provider){
|
||||
/** @var $provider LevelProvider */
|
||||
public static function getMatchingProviders(string $path) : array{
|
||||
$result = [];
|
||||
foreach(self::$providers as $alias => $provider){
|
||||
/** @var LevelProvider|string $provider */
|
||||
if($provider::isValid($path)){
|
||||
return $provider;
|
||||
$result[$alias] = $provider;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,23 +45,16 @@ abstract class RegionLevelProvider extends BaseLevelProvider{
|
||||
abstract protected static function getPcWorldFormatVersion() : int;
|
||||
|
||||
public static function isValid(string $path) : bool{
|
||||
$isValid = (file_exists($path . "/level.dat") and is_dir($path . "/region/"));
|
||||
|
||||
if($isValid){
|
||||
$files = array_filter(scandir($path . "/region/", SCANDIR_SORT_NONE), function($file){
|
||||
return substr($file, strrpos($file, ".") + 1, 2) === "mc"; //region file
|
||||
});
|
||||
|
||||
$ext = static::getRegionFileExtension();
|
||||
foreach($files as $f){
|
||||
if(substr($f, strrpos($f, ".") + 1) !== $ext){
|
||||
$isValid = false;
|
||||
break;
|
||||
if(file_exists($path . "/level.dat") and is_dir($path . "/region/")){
|
||||
foreach(scandir($path . "/region/", SCANDIR_SORT_NONE) as $file){
|
||||
if(substr($file, strrpos($file, ".") + 1) === static::getRegionFileExtension()){
|
||||
//we don't care if other region types exist, we only care if this format is possible
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $isValid;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function generate(string $path, string $name, int $seed, string $generator, array $options = []){
|
||||
|
Loading…
x
Reference in New Issue
Block a user