LevelProvider: Remove cyclic dependency between Level and LevelProvider

This will now allow LevelProviders to be constructed on threads.
This commit is contained in:
Dylan K. Taylor 2017-12-31 17:06:18 +00:00
parent d19683b7dd
commit 1a615591e2
5 changed files with 17 additions and 29 deletions

View File

@ -343,7 +343,7 @@ class Level implements ChunkManager, Metadatable{
/** @var LevelProvider $provider */
if(is_subclass_of($provider, LevelProvider::class, true)){
$this->provider = new $provider($this, $path);
$this->provider = new $provider($path);
}else{
throw new LevelException("Provider is not a subclass of LevelProvider");
}
@ -2546,7 +2546,7 @@ class Level implements ChunkManager, Metadatable{
}
$this->timings->syncChunkSendPrepareTimer->startTiming();
$chunk = $this->provider->getChunk($x, $z, false);
$chunk = $this->provider->getChunk($x, $z);
if(!($chunk instanceof Chunk)){
throw new ChunkException("Invalid Chunk sent");
}
@ -2686,7 +2686,13 @@ class Level implements ChunkManager, Metadatable{
$this->cancelUnloadChunkRequest($x, $z);
$chunk = $this->provider->getChunk($x, $z, $generate);
$this->timings->syncChunkLoadDataTimer->startTiming();
$this->provider->loadChunk($x, $z, $generate);
$chunk = $this->provider->getChunk($x, $z);
$this->timings->syncChunkLoadDataTimer->stopTiming();
if($chunk === null){
if($generate){
throw new \InvalidStateException("Could not create new Chunk");

View File

@ -33,8 +33,6 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\StringTag;
abstract class BaseLevelProvider implements LevelProvider{
/** @var Level */
protected $level;
/** @var string */
protected $path;
/** @var CompoundTag */
@ -42,8 +40,7 @@ abstract class BaseLevelProvider implements LevelProvider{
/** @var Chunk[] */
protected $chunks = [];
public function __construct(Level $level, string $path){
$this->level = $level;
public function __construct(string $path){
$this->path = $path;
if(!file_exists($this->path)){
mkdir($this->path, 0777, true);
@ -120,15 +117,8 @@ abstract class BaseLevelProvider implements LevelProvider{
file_put_contents($this->getPath() . "level.dat", $buffer);
}
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 getChunk(int $chunkX, int $chunkZ){
return $this->chunks[Level::chunkHash($chunkX, $chunkZ)] ?? null;
}
public function isChunkLoaded(int $chunkX, int $chunkZ) : bool{
@ -145,12 +135,10 @@ abstract class BaseLevelProvider implements LevelProvider{
return true;
}
$this->level->timings->syncChunkLoadDataTimer->startTiming();
$chunk = $this->readChunk($chunkX, $chunkZ);
if($chunk === null and $create){
$chunk = new Chunk($chunkX, $chunkZ);
}
$this->level->timings->syncChunkLoadDataTimer->stopTiming();
if($chunk !== null){
$this->chunks[$index] = $chunk;

View File

@ -24,16 +24,14 @@ declare(strict_types=1);
namespace pocketmine\level\format\io;
use pocketmine\level\format\Chunk;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
interface LevelProvider{
/**
* @param Level $level
* @param string $path
*/
public function __construct(Level $level, string $path);
public function __construct(string $path);
/**
* Returns the full provider name, like "anvil" or "mcregion", will be used to find the correct format.
@ -91,13 +89,12 @@ interface LevelProvider{
* Gets the Chunk object
* This method must be implemented by all the level formats.
*
* @param int $chunkX
* @param int $chunkZ
* @param bool $create
* @param int $chunkX
* @param int $chunkZ
*
* @return Chunk|null
*/
public function getChunk(int $chunkX, int $chunkZ, bool $create = false);
public function getChunk(int $chunkX, int $chunkZ);
/**
* @param int $chunkX

View File

@ -87,10 +87,9 @@ class LevelDB extends BaseLevelProvider{
}
}
public function __construct(Level $level, string $path){
public function __construct(string $path){
self::checkForLevelDBExtension();
$this->level = $level;
$this->path = $path;
if(!file_exists($this->path)){
mkdir($this->path, 0777, true);
@ -530,6 +529,5 @@ class LevelDB extends BaseLevelProvider{
public function close(){
$this->unloadChunks();
$this->db->close();
$this->level = null;
}
}

View File

@ -355,7 +355,6 @@ class McRegion extends BaseLevelProvider{
$region->close();
unset($this->regions[$index]);
}
$this->level = null;
}
protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk{