diff --git a/src/pocketmine/level/format/LevelProvider.php b/src/pocketmine/level/format/LevelProvider.php index 04488fc76..ab82b7116 100644 --- a/src/pocketmine/level/format/LevelProvider.php +++ b/src/pocketmine/level/format/LevelProvider.php @@ -19,6 +19,8 @@ * */ +declare(strict_types = 1); + namespace pocketmine\level\format; use pocketmine\level\format\Chunk; @@ -27,26 +29,18 @@ use pocketmine\math\Vector3; interface LevelProvider{ - const ORDER_YZX = 0; - const ORDER_ZXY = 1; - /** * @param Level $level * @param string $path */ - public function __construct(Level $level, $path); + public function __construct(Level $level, string $path); /** * Returns the full provider name, like "anvil" or "mcregion", will be used to find the correct format. * * @return string */ - public static function getProviderName(); - - /** - * @return int - */ - public static function getProviderOrder(); + public static function getProviderName() : string; /** * Gets the build height limit of this world @@ -56,17 +50,9 @@ interface LevelProvider{ public function getWorldHeight() : int; /** - * Requests a MC: PE network chunk to be sent - * - * @param int $x - * @param int $z - * - * @return \pocketmine\scheduler\AsyncTask|null + * @return string */ - public function requestChunkTask($x, $z); - - /** @return string */ - public function getPath(); + public function getPath() : string; /** * Tells if the path is a valid level. @@ -74,105 +60,113 @@ interface LevelProvider{ * * @param string $path * - * @return true + * @return bool */ - public static function isValid($path); + public static function isValid(string $path) : bool; /** * Generate the needed files in the path given * - * @param string $path - * @param string $name - * @param int $seed - * @param string $generator - * @param array[] $options + * @param string $path + * @param string $name + * @param int|string $seed + * @param string $generator + * @param array[] $options */ - public static function generate($path, $name, $seed, $generator, array $options = []); + public static function generate(string $path, string $name, $seed, string $generator, array $options = []); /** * Returns the generator name * * @return string */ - public function getGenerator(); + public function getGenerator() : string; /** * @return array */ - public function getGeneratorOptions(); + public function getGeneratorOptions() : array; /** * Gets the Chunk object * This method must be implemented by all the level formats. * - * @param int $X absolute Chunk X value - * @param int $Z absolute Chunk Z value - * @param bool $create Whether to generate the chunk if it does not exist + * @param int $chunkX + * @param int $chunkZ + * @param bool $create * - * @return Chunk + * @return Chunk|null */ - public function getChunk($X, $Z, $create = false); + public function getChunk(int $chunkX, int $chunkZ, bool $create = false); + + /** + * @param int $chunkX + * @param int $chunkZ + * @param Chunk $chunk + */ + public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk); + + /** + * @param int $chunkX + * @param int $chunkZ + */ + public function saveChunk(int $chunkX, int $chunkZ) : bool; public function saveChunks(); /** - * @param int $X - * @param int $Z - */ - public function saveChunk($X, $Z); - - public function unloadChunks(); - - /** - * @param int $X - * @param int $Z + * @param int $chunkX + * @param int $chunkZ * @param bool $create * * @return bool */ - public function loadChunk($X, $Z, $create = false); + public function loadChunk(int $chunkX, int $chunkZ, bool $create = false) : bool; /** - * @param int $X - * @param int $Z + * @param int $chunkX + * @param int $chunkZ * @param bool $safe * * @return bool */ - public function unloadChunk($X, $Z, $safe = true); + public function unloadChunk(int $chunkX, int $chunkZ, bool $safe = true) : bool; + + public function unloadChunks(); /** - * @param int $X - * @param int $Z + * @param int $chunkX + * @param int $chunkZ * * @return bool */ - public function isChunkGenerated($X, $Z); + public function isChunkLoaded(int $chunkX, int $chunkZ) : bool; /** - * @param int $X - * @param int $Z + * @param int $chunkX + * @param int $chunkZ * * @return bool */ - public function isChunkPopulated($X, $Z); + public function isChunkGenerated(int $chunkX, int $chunkZ) : bool; /** - * @param int $X - * @param int $Z + * @param int $chunkX + * @param int $chunkZ * * @return bool */ - public function isChunkLoaded($X, $Z); + public function isChunkPopulated(int $chunkX, int $chunkZ) : bool; /** - * @param int $chunkX - * @param int $chunkZ - * @param Chunk $chunk + * Requests a MC: PE network chunk to be sent * - * @return mixed + * @param int $x + * @param int $z + * + * @return \pocketmine\scheduler\AsyncTask|null */ - public function setChunk($chunkX, $chunkZ, Chunk $chunk); + public function requestChunkTask(int $x, int $z); /** * @return string @@ -187,7 +181,7 @@ interface LevelProvider{ /** * @param int $value */ - public function setTime($value); + public function setTime(int $value); /** * @return int|string int, or the string numeric representation of a long in 32-bit systems @@ -195,14 +189,14 @@ interface LevelProvider{ public function getSeed(); /** - * @param int $value + * @param int|string $value */ public function setSeed($value); /** * @return Vector3 */ - public function getSpawn(); + public function getSpawn() : Vector3; /** * @param Vector3 $pos @@ -212,7 +206,7 @@ interface LevelProvider{ /** * @return Chunk[] */ - public function getLoadedChunks(); + public function getLoadedChunks() : array; public function doGarbageCollection(); diff --git a/src/pocketmine/level/format/anvil/Anvil.php b/src/pocketmine/level/format/anvil/Anvil.php index 00ba634e1..6ad4cada8 100644 --- a/src/pocketmine/level/format/anvil/Anvil.php +++ b/src/pocketmine/level/format/anvil/Anvil.php @@ -19,6 +19,8 @@ * */ +declare(strict_types = 1); + namespace pocketmine\level\format\anvil; use pocketmine\level\format\Chunk; @@ -156,18 +158,14 @@ class Anvil extends McRegion{ /** @var RegionLoader[] */ protected $regions = []; - /** @var AnvilChunk[] */ + /** @var Chunk[] */ protected $chunks = []; - public static function getProviderName(){ + public static function getProviderName() : string{ return "anvil"; } - public static function getProviderOrder(){ - return self::ORDER_YZX; - } - - public static function isValid($path){ + public static function isValid(string $path) : bool{ $isValid = (file_exists($path . "/level.dat") and is_dir($path . "/region/")); if($isValid){ @@ -189,16 +187,16 @@ class Anvil extends McRegion{ } /** - * @param $x - * @param $z + * @param int $x + * @param int $z * * @return RegionLoader */ - protected function getRegion($x, $z){ + protected function getRegion(int $x, int $z){ return $this->regions[Level::chunkHash($x, $z)] ?? null; } - protected function loadRegion($x, $z){ + protected function loadRegion(int $x, int $z){ if(!isset($this->regions[$index = Level::chunkHash($x, $z)])){ $this->regions[$index] = new RegionLoader($this, $x, $z); } diff --git a/src/pocketmine/level/format/generic/BaseLevelProvider.php b/src/pocketmine/level/format/generic/BaseLevelProvider.php index e6f6937cd..dcf303ec1 100644 --- a/src/pocketmine/level/format/generic/BaseLevelProvider.php +++ b/src/pocketmine/level/format/generic/BaseLevelProvider.php @@ -19,6 +19,8 @@ * */ +declare(strict_types = 1); + namespace pocketmine\level\format\generic; use pocketmine\level\format\LevelProvider; @@ -40,7 +42,7 @@ abstract class BaseLevelProvider implements LevelProvider{ /** @var CompoundTag */ protected $levelData; - public function __construct(Level $level, $path){ + public function __construct(Level $level, string $path){ $this->level = $level; $this->path = $path; if(!file_exists($this->path)){ @@ -64,7 +66,7 @@ abstract class BaseLevelProvider implements LevelProvider{ } } - public function getPath(){ + public function getPath() : string{ return $this->path; } @@ -76,15 +78,15 @@ abstract class BaseLevelProvider implements LevelProvider{ return $this->level; } - public function getName(){ + public function getName() : string{ return $this->levelData["LevelName"]; } - public function getTime(){ + public function getTime() : int{ return $this->levelData["Time"]; } - public function setTime($value){ + public function setTime(int $value){ $this->levelData->Time = new IntTag("Time", (int) $value); } @@ -96,7 +98,7 @@ abstract class BaseLevelProvider implements LevelProvider{ $this->levelData->RandomSeed = new LongTag("RandomSeed", $value); } - public function getSpawn(){ + public function getSpawn() : Vector3{ return new Vector3((float) $this->levelData["SpawnX"], (float) $this->levelData["SpawnY"], (float) $this->levelData["SpawnZ"]); } @@ -113,7 +115,7 @@ abstract class BaseLevelProvider implements LevelProvider{ /** * @return CompoundTag */ - public function getLevelData(){ + public function getLevelData() : CompoundTag{ return $this->levelData; } @@ -126,7 +128,7 @@ abstract class BaseLevelProvider implements LevelProvider{ file_put_contents($this->getPath() . "level.dat", $buffer); } - public function requestChunkTask($x, $z){ + public function requestChunkTask(int $x, int $z){ $chunk = $this->getChunk($x, $z, false); if(!($chunk instanceof GenericChunk)){ throw new ChunkException("Invalid Chunk sent"); diff --git a/src/pocketmine/level/format/mcregion/McRegion.php b/src/pocketmine/level/format/mcregion/McRegion.php index bb9edce03..3fb8533db 100644 --- a/src/pocketmine/level/format/mcregion/McRegion.php +++ b/src/pocketmine/level/format/mcregion/McRegion.php @@ -19,6 +19,8 @@ * */ +declare(strict_types = 1); + namespace pocketmine\level\format\mcregion; use pocketmine\level\format\Chunk; @@ -36,6 +38,11 @@ use pocketmine\utils\MainLogger; class McRegion extends BaseLevelProvider{ + /** + * @param GenericChunk $chunk + * + * @return string + */ public static function nbtSerialize(GenericChunk $chunk) : string{ $nbt = new CompoundTag("Level", []); $nbt->xPos = new IntTag("xPos", $chunk->getX()); @@ -101,6 +108,12 @@ class McRegion extends BaseLevelProvider{ return $writer->writeCompressed(ZLIB_ENCODING_DEFLATE, RegionLoader::$COMPRESSION_LEVEL); } + /** + * @param string $data + * @param LevelProvider $provider + * + * @return GenericChunk|null + */ public static function nbtDeserialize(string $data, LevelProvider $provider = null){ $nbt = new NBT(NBT::BIG_ENDIAN); try{ @@ -179,18 +192,19 @@ class McRegion extends BaseLevelProvider{ /** @var RegionLoader[] */ protected $regions = []; - /** @var GenericChunk[] */ + /** @var Chunk[] */ protected $chunks = []; - public static function getProviderName(){ + public static function getProviderName() : string{ return "mcregion"; } - public static function getProviderOrder(){ - return self::ORDER_ZXY; + public function getWorldHeight() : int{ + //TODO: add world height options + return 128; } - public static function isValid($path){ + public static function isValid(string $path) : bool{ $isValid = (file_exists($path . "/level.dat") and is_dir($path . "/region/")); if($isValid){ @@ -206,12 +220,7 @@ class McRegion extends BaseLevelProvider{ return $isValid; } - public function getWorldHeight() : int{ - //TODO: add world height options - return 128; - } - - public static function generate($path, $name, $seed, $generator, array $options = []){ + public static function generate(string $path, string $name, $seed, string $generator, array $options = []){ if(!file_exists($path)){ mkdir($path, 0777, true); } @@ -247,32 +256,51 @@ class McRegion extends BaseLevelProvider{ file_put_contents($path . "level.dat", $buffer); } - public static function getRegionIndex($chunkX, $chunkZ, &$x, &$z){ - $x = $chunkX >> 5; - $z = $chunkZ >> 5; - } - - public function unloadChunks(){ - foreach($this->chunks as $chunk){ - $this->unloadChunk($chunk->getX(), $chunk->getZ(), false); - } - $this->chunks = []; - } - - public function getGenerator(){ + public function getGenerator() : string{ return $this->levelData["generatorName"]; } - public function getGeneratorOptions(){ + public function getGeneratorOptions() : array{ return ["preset" => $this->levelData["generatorOptions"]]; } - public function getLoadedChunks(){ - return $this->chunks; + public function getChunk(int $chunkX, int $chunkZ, bool $create = false){ + $index = Level::chunkHash($chunkX, $chunkZ); + if(isset($this->chunks[$index])){ + return $this->chunks[$index]; + }else{ + $this->loadChunk($chunkX, $chunkZ, $create); + + return $this->chunks[$index] ?? null; + } } - public function isChunkLoaded($x, $z){ - return isset($this->chunks[Level::chunkHash($x, $z)]); + public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk){ + + $chunk->setProvider($this); + + self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ); + $this->loadRegion($regionX, $regionZ); + + $chunk->setX($chunkX); + $chunk->setZ($chunkZ); + + + if(isset($this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)]) and $this->chunks[$index] !== $chunk){ + $this->unloadChunk($chunkX, $chunkZ, false); + } + + $this->chunks[$index] = $chunk; + } + + public function saveChunk(int $chunkX, int $chunkZ) : bool{ + if($this->isChunkLoaded($chunkX, $chunkZ)){ + $this->getRegion($chunkX >> 5, $chunkZ >> 5)->writeChunk($this->getChunk($chunkX, $chunkZ)); + + return true; + } + + return false; } public function saveChunks(){ @@ -281,17 +309,7 @@ class McRegion extends BaseLevelProvider{ } } - public function doGarbageCollection(){ - $limit = time() - 300; - foreach($this->regions as $index => $region){ - if($region->lastUsed <= $limit){ - $region->close(); - unset($this->regions[$index]); - } - } - } - - public function loadChunk($chunkX, $chunkZ, $create = false){ + public function loadChunk(int $chunkX, int $chunkZ, bool $create = false) : bool{ $index = Level::chunkHash($chunkX, $chunkZ); if(isset($this->chunks[$index])){ return true; @@ -314,12 +332,8 @@ class McRegion extends BaseLevelProvider{ } } - public function getEmptyChunk($chunkX, $chunkZ){ - return GenericChunk::getEmptyChunk($chunkX, $chunkZ, $this); - } - - public function unloadChunk($x, $z, $safe = true){ - $chunk = $this->chunks[$index = Level::chunkHash($x, $z)] ?? null; + public function unloadChunk(int $chunkX, int $chunkZ, bool $safe = true) : bool{ + $chunk = $this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)] ?? null; if($chunk instanceof Chunk and $chunk->unload(false, $safe)){ unset($this->chunks[$index]); return true; @@ -328,66 +342,18 @@ class McRegion extends BaseLevelProvider{ return false; } - public function saveChunk($x, $z){ - if($this->isChunkLoaded($x, $z)){ - $this->getRegion($x >> 5, $z >> 5)->writeChunk($this->getChunk($x, $z)); - - return true; + public function unloadChunks(){ + foreach($this->chunks as $chunk){ + $this->unloadChunk($chunk->getX(), $chunk->getZ(), false); } - - return false; + $this->chunks = []; } - /** - * @param $x - * @param $z - * - * @return RegionLoader - */ - protected function getRegion($x, $z){ - return $this->regions[Level::chunkHash($x, $z)] ?? null; + public function isChunkLoaded(int $chunkX, int $chunkZ) : bool{ + return isset($this->chunks[Level::chunkHash($chunkX, $chunkZ)]); } - /** - * @param int $chunkX - * @param int $chunkZ - * @param bool $create - * - * @return Chunk - */ - public function getChunk($chunkX, $chunkZ, $create = false){ - $index = Level::chunkHash($chunkX, $chunkZ); - if(isset($this->chunks[$index])){ - return $this->chunks[$index]; - }else{ - $this->loadChunk($chunkX, $chunkZ, $create); - - return isset($this->chunks[$index]) ? $this->chunks[$index] : null; - } - } - - public function setChunk($chunkX, $chunkZ, Chunk $chunk){ - if(!($chunk instanceof GenericChunk)){ - throw new ChunkException("Invalid Chunk class"); - } - - $chunk->setProvider($this); - - self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ); - $this->loadRegion($regionX, $regionZ); - - $chunk->setX($chunkX); - $chunk->setZ($chunkZ); - - - if(isset($this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)]) and $this->chunks[$index] !== $chunk){ - $this->unloadChunk($chunkX, $chunkZ, false); - } - - $this->chunks[$index] = $chunk; - } - - public function isChunkGenerated($chunkX, $chunkZ){ + public function isChunkGenerated(int $chunkX, int $chunkZ) : bool{ if(($region = $this->getRegion($chunkX >> 5, $chunkZ >> 5)) !== null){ return $region->chunkExists($chunkX - $region->getX() * 32, $chunkZ - $region->getZ() * 32) and $this->getChunk($chunkX - $region->getX() * 32, $chunkZ - $region->getZ() * 32, true)->isGenerated(); } @@ -395,7 +361,7 @@ class McRegion extends BaseLevelProvider{ return false; } - public function isChunkPopulated($chunkX, $chunkZ){ + public function isChunkPopulated(int $chunkX, int $chunkZ) : bool{ $chunk = $this->getChunk($chunkX, $chunkZ); if($chunk !== null){ return $chunk->isPopulated(); @@ -404,7 +370,56 @@ class McRegion extends BaseLevelProvider{ } } - protected function loadRegion($x, $z){ + public function getLoadedChunks() : array{ + return $this->chunks; + } + + public function doGarbageCollection(){ + $limit = time() - 300; + foreach($this->regions as $index => $region){ + if($region->lastUsed <= $limit){ + $region->close(); + unset($this->regions[$index]); + } + } + } + + /** + * @param int $chunkX + * @param int $chunkZ + * @param int &$x + * @param int &$z + */ + public static function getRegionIndex(int $chunkX, int $chunkZ, &$x, &$z){ + $x = $chunkX >> 5; + $z = $chunkZ >> 5; + } + + /** + * @param int $chunkX + * @param int $chunkZ + * + * @return GenericChunk + */ + public function getEmptyChunk(int $chunkX, int $chunkZ){ + return GenericChunk::getEmptyChunk($chunkX, $chunkZ, $this); + } + + /** + * @param int $x + * @param int $z + * + * @return RegionLoader + */ + protected function getRegion(int $x, int $z){ + return $this->regions[Level::chunkHash($x, $z)] ?? null; + } + + /** + * @param int $x + * @param int $z + */ + protected function loadRegion(int $x, int $z){ if(!isset($this->regions[$index = Level::chunkHash($x, $z)])){ $this->regions[$index] = new RegionLoader($this, $x, $z); }