Check for closed target Levels in Position (#241)

More foolproof
This commit is contained in:
Dylan K. Taylor 2017-01-09 13:18:28 +00:00 committed by GitHub
parent 0a3fd8737a
commit 6fbb9b6083
3 changed files with 46 additions and 4 deletions

View File

@ -260,6 +260,8 @@ class Level implements ChunkManager, Metadatable{
/** @var Generator */
private $generatorInstance;
private $closed = false;
public static function chunkHash(int $x, int $z){
return PHP_INT_SIZE === 8 ? (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF) : $x . ":" . $z;
}
@ -404,7 +406,12 @@ class Level implements ChunkManager, Metadatable{
return $this->levelId;
}
public function isClosed() : bool{
return $this->closed;
}
public function close(){
assert(!$this->closed, "Tried to close a level which is already closed");
if($this->getAutoSave()){
$this->save();
@ -421,6 +428,8 @@ class Level implements ChunkManager, Metadatable{
$this->blockMetadata = null;
$this->blockCache = [];
$this->temporalPosition = null;
$this->closed = true;
}
public function addSound(Sound $sound, array $players = null){

View File

@ -23,6 +23,7 @@ namespace pocketmine\level;
use pocketmine\math\Vector3;
use pocketmine\utils\LevelException;
use pocketmine\utils\MainLogger;
class Position extends Vector3{
@ -47,19 +48,40 @@ class Position extends Vector3{
}
/**
* @return Level
* Returns the target Level, or null if the target is not valid.
* If a reference exists to a Level which is closed, the reference will be destroyed and null will be returned.
*
* @return Level|null
*/
public function getLevel(){
if($this->level !== null and $this->level->isClosed()){
MainLogger::getLogger()->debug("Position was holding a reference to an unloaded Level");
$this->level = null;
}
return $this->level;
}
public function setLevel(Level $level){
/**
* Sets the target Level of the position.
*
* @param Level|null $level
*
* @return $this
*
* @throws \InvalidArgumentException if the specified Level has been closed
*/
public function setLevel(Level $level = null){
if($level !== null and $level->isClosed()){
throw new \InvalidArgumentException("Specified level has been unloaded and cannot be used");
}
$this->level = $level;
return $this;
}
/**
* Checks if this object has a valid reference to a Level
* Checks if this object has a valid reference to a loaded Level
*
* @return bool
*/

View File

@ -53,7 +53,18 @@ class WeakPosition extends Position{
return Server::getInstance()->getLevel($this->levelId);
}
public function setLevel(Level $level){
/**
* @param Level|null $level
*
* @return $this
*
* @throws \InvalidArgumentException if the specified Level has been closed
*/
public function setLevel(Level $level = null){
if($level !== null and $level->isClosed()){
throw new \InvalidArgumentException("Specified level has been unloaded and cannot be used");
}
$this->levelId = ($level !== null ? $level->getId() : -1);
return $this;
}