mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 08:44:01 +00:00
LevelProvider: Nuked the complicated mess out of level providers
Level providers are now cut back to just an interface to a world's data. They don't keep their own chunk registries or any stupid shit like that because the Level already does that. This furthers the goal of being able to move level I/O off the main thread, and also drastically decreases the complication of implementing level providers.
This commit is contained in:
parent
1a615591e2
commit
a46029c0f6
@ -1046,8 +1046,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
public function saveChunks(){
|
||||
foreach($this->chunks as $chunk){
|
||||
if($chunk->hasChanged() and $chunk->isGenerated()){
|
||||
$this->provider->setChunk($chunk->getX(), $chunk->getZ(), $chunk);
|
||||
$this->provider->saveChunk($chunk->getX(), $chunk->getZ());
|
||||
$this->provider->saveChunk($chunk);
|
||||
$chunk->setChanged(false);
|
||||
}
|
||||
}
|
||||
@ -2428,7 +2427,6 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
$this->provider->setChunk($chunkX, $chunkZ, $chunk);
|
||||
$this->chunks[$chunkHash] = $chunk;
|
||||
|
||||
unset($this->blockCache[$chunkHash]);
|
||||
@ -2463,7 +2461,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @return bool
|
||||
*/
|
||||
public function isChunkLoaded(int $x, int $z) : bool{
|
||||
return isset($this->chunks[Level::chunkHash($x, $z)]) or $this->provider->isChunkLoaded($x, $z);
|
||||
return isset($this->chunks[Level::chunkHash($x, $z)]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2546,7 +2544,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
$this->timings->syncChunkSendPrepareTimer->startTiming();
|
||||
|
||||
$chunk = $this->provider->getChunk($x, $z);
|
||||
$chunk = $this->chunks[$index] ?? null;
|
||||
if(!($chunk instanceof Chunk)){
|
||||
throw new ChunkException("Invalid Chunk sent");
|
||||
}
|
||||
@ -2688,8 +2686,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
$this->timings->syncChunkLoadDataTimer->startTiming();
|
||||
|
||||
$this->provider->loadChunk($x, $z, $generate);
|
||||
$chunk = $this->provider->getChunk($x, $z);
|
||||
$chunk = $this->provider->loadChunk($x, $z, $generate);
|
||||
|
||||
$this->timings->syncChunkLoadDataTimer->stopTiming();
|
||||
|
||||
@ -2770,8 +2767,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
if($chunk !== null){
|
||||
if($trySave and $this->getAutoSave() and $chunk->isGenerated()){
|
||||
if($chunk->hasChanged() or count($chunk->getTiles()) > 0 or count($chunk->getSavableEntities()) > 0){
|
||||
$this->provider->setChunk($x, $z, $chunk);
|
||||
$this->provider->saveChunk($x, $z);
|
||||
$this->provider->saveChunk($chunk);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2779,7 +2775,9 @@ class Level implements ChunkManager, Metadatable{
|
||||
$loader->onChunkUnloaded($chunk);
|
||||
}
|
||||
}
|
||||
$this->provider->unloadChunk($x, $z, $safe);
|
||||
|
||||
//TODO: not checking return value, but is it needed anyway?
|
||||
$chunk->unload($safe);
|
||||
}catch(\Throwable $e){
|
||||
$logger = $this->server->getLogger();
|
||||
$logger->error($this->server->getLanguage()->translateString("pocketmine.level.chunkUnloadError", [$e->getMessage()]));
|
||||
@ -3039,12 +3037,6 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->provider->getLoadedChunks() as $chunk){
|
||||
if(!isset($this->chunks[Level::chunkHash($chunk->getX(), $chunk->getZ())])){
|
||||
$this->provider->unloadChunk($chunk->getX(), $chunk->getZ(), false);
|
||||
}
|
||||
}
|
||||
|
||||
$this->provider->doGarbageCollection();
|
||||
|
||||
$this->timings->doChunkGC->stopTiming();
|
||||
|
@ -37,8 +37,6 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
protected $path;
|
||||
/** @var CompoundTag */
|
||||
protected $levelData;
|
||||
/** @var Chunk[] */
|
||||
protected $chunks = [];
|
||||
|
||||
public function __construct(string $path){
|
||||
$this->path = $path;
|
||||
@ -117,84 +115,20 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
file_put_contents($this->getPath() . "level.dat", $buffer);
|
||||
}
|
||||
|
||||
public function getChunk(int $chunkX, int $chunkZ){
|
||||
return $this->chunks[Level::chunkHash($chunkX, $chunkZ)] ?? null;
|
||||
}
|
||||
|
||||
public function isChunkLoaded(int $chunkX, int $chunkZ) : bool{
|
||||
return isset($this->chunks[Level::chunkHash($chunkX, $chunkZ)]);
|
||||
}
|
||||
|
||||
public function getLoadedChunks() : array{
|
||||
return $this->chunks;
|
||||
}
|
||||
|
||||
public function loadChunk(int $chunkX, int $chunkZ, bool $create = false) : bool{
|
||||
$index = Level::chunkHash($chunkX, $chunkZ);
|
||||
if(isset($this->chunks[$index])){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function loadChunk(int $chunkX, int $chunkZ, bool $create = false) : ?Chunk{
|
||||
$chunk = $this->readChunk($chunkX, $chunkZ);
|
||||
if($chunk === null and $create){
|
||||
$chunk = new Chunk($chunkX, $chunkZ);
|
||||
}
|
||||
|
||||
if($chunk !== null){
|
||||
$this->chunks[$index] = $chunk;
|
||||
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
return $chunk;
|
||||
}
|
||||
|
||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk){
|
||||
$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);
|
||||
public function saveChunk(Chunk $chunk) : void{
|
||||
if(!$chunk->isGenerated()){
|
||||
throw new \InvalidStateException("Cannot save un-generated chunk");
|
||||
}
|
||||
|
||||
$this->chunks[$index] = $chunk;
|
||||
}
|
||||
|
||||
public function saveChunks(){
|
||||
foreach($this->chunks as $chunk){
|
||||
$this->saveChunk($chunk->getX(), $chunk->getZ());
|
||||
}
|
||||
}
|
||||
|
||||
public function saveChunk(int $chunkX, int $chunkZ) : bool{
|
||||
if($this->isChunkLoaded($chunkX, $chunkZ)){
|
||||
$chunk = $this->getChunk($chunkX, $chunkZ);
|
||||
if(!$chunk->isGenerated()){
|
||||
throw new \InvalidStateException("Cannot save un-generated chunk");
|
||||
}
|
||||
$this->writeChunk($chunk);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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($safe)){
|
||||
unset($this->chunks[$index]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function unloadChunks(){
|
||||
foreach($this->chunks as $chunk){
|
||||
$this->unloadChunk($chunk->getX(), $chunk->getZ(), false);
|
||||
}
|
||||
$this->chunks = [];
|
||||
$this->writeChunk($chunk);
|
||||
}
|
||||
|
||||
abstract protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk;
|
||||
|
@ -86,60 +86,20 @@ interface LevelProvider{
|
||||
public function getGeneratorOptions() : array;
|
||||
|
||||
/**
|
||||
* Gets the Chunk object
|
||||
* This method must be implemented by all the level formats.
|
||||
*
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return Chunk|null
|
||||
*/
|
||||
public function getChunk(int $chunkX, int $chunkZ);
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param Chunk $chunk
|
||||
*/
|
||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk);
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return bool
|
||||
* @return void
|
||||
*/
|
||||
public function saveChunk(int $chunkX, int $chunkZ) : bool;
|
||||
|
||||
public function saveChunks();
|
||||
public function saveChunk(Chunk $chunk) : void;
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param bool $create
|
||||
*
|
||||
* @return bool
|
||||
* @return null|Chunk
|
||||
*/
|
||||
public function loadChunk(int $chunkX, int $chunkZ, bool $create = false) : bool;
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param bool $safe
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function unloadChunk(int $chunkX, int $chunkZ, bool $safe = true) : bool;
|
||||
|
||||
public function unloadChunks();
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isChunkLoaded(int $chunkX, int $chunkZ) : bool;
|
||||
public function loadChunk(int $chunkX, int $chunkZ, bool $create = false) : ?Chunk;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
@ -188,11 +148,6 @@ interface LevelProvider{
|
||||
*/
|
||||
public function setDifficulty(int $difficulty);
|
||||
|
||||
/**
|
||||
* @return Chunk[]
|
||||
*/
|
||||
public function getLoadedChunks() : array;
|
||||
|
||||
public function doGarbageCollection();
|
||||
|
||||
public function close();
|
||||
|
@ -527,7 +527,6 @@ class LevelDB extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
public function close(){
|
||||
$this->unloadChunks();
|
||||
$this->db->close();
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +350,6 @@ class McRegion extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
public function close(){
|
||||
$this->unloadChunks();
|
||||
foreach($this->regions as $index => $region){
|
||||
$region->close();
|
||||
unset($this->regions[$index]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user