Type-hints, strict-types, doc comments and rearrangement for LevelProviders

This commit is contained in:
Dylan K. Taylor 2016-12-22 13:16:25 +00:00
parent a99d7f93d9
commit f4065dd411
4 changed files with 198 additions and 189 deletions

View File

@ -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();

View File

@ -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);
}

View File

@ -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");

View File

@ -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);
}