From c578898aa4c47a8d586a86531b2bad03f16b11e2 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Thu, 28 May 2015 23:13:20 +0200 Subject: [PATCH] Moved light population to an async task when needed, improved empty chunks --- src/pocketmine/level/Level.php | 5 ++ src/pocketmine/level/format/anvil/Chunk.php | 1 + .../level/format/generic/BaseFullChunk.php | 6 -- .../format/generic/EmptyChunkSection.php | 2 +- src/pocketmine/level/format/leveldb/Chunk.php | 21 +++++- .../level/format/mcregion/Chunk.php | 6 +- .../level/generator/LightPopulationTask.php | 74 +++++++++++++++++++ 7 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 src/pocketmine/level/generator/LightPopulationTask.php diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 77c21b5d8..a20b5ec18 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -70,6 +70,7 @@ use pocketmine\level\generator\GenerationTask; use pocketmine\level\generator\Generator; use pocketmine\level\generator\GeneratorRegisterTask; use pocketmine\level\generator\GeneratorUnregisterTask; +use pocketmine\level\generator\LightPopulationTask; use pocketmine\level\generator\PopulationTask; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Math; @@ -2299,6 +2300,10 @@ class Level implements ChunkManager, Metadatable{ return false; } + if(!$chunk->isLightPopulated() and $chunk->isPopulated()){ + $this->getServer()->getScheduler()->scheduleAsyncTask(new LightPopulationTask($this, $chunk)); + } + if($this->isChunkInUse($x, $z)){ foreach($this->getChunkLoaders($x, $z) as $loader){ $loader->onChunkLoaded($chunk); diff --git a/src/pocketmine/level/format/anvil/Chunk.php b/src/pocketmine/level/format/anvil/Chunk.php index 4f1298b27..f6e64e57d 100644 --- a/src/pocketmine/level/format/anvil/Chunk.php +++ b/src/pocketmine/level/format/anvil/Chunk.php @@ -31,6 +31,7 @@ use pocketmine\nbt\tag\Compound; use pocketmine\nbt\tag\Enum; use pocketmine\nbt\tag\Int; use pocketmine\nbt\tag\IntArray; +use pocketmine\nbt\tag\Long; use pocketmine\Player; use pocketmine\utils\Binary; diff --git a/src/pocketmine/level/format/generic/BaseFullChunk.php b/src/pocketmine/level/format/generic/BaseFullChunk.php index 99c5918b3..1854b6f34 100644 --- a/src/pocketmine/level/format/generic/BaseFullChunk.php +++ b/src/pocketmine/level/format/generic/BaseFullChunk.php @@ -164,12 +164,6 @@ abstract class BaseFullChunk implements FullChunk{ $this->isInit = true; } - - if(!$this->isLightPopulated() and $this->isPopulated()){ - $this->recalculateHeightMap(); - $this->populateSkyLight(); - $this->setLightPopulated(); - } } public function getX(){ diff --git a/src/pocketmine/level/format/generic/EmptyChunkSection.php b/src/pocketmine/level/format/generic/EmptyChunkSection.php index 03a31ce8e..b92b19085 100644 --- a/src/pocketmine/level/format/generic/EmptyChunkSection.php +++ b/src/pocketmine/level/format/generic/EmptyChunkSection.php @@ -109,7 +109,7 @@ class EmptyChunkSection implements ChunkSection{ } final public function getBlockSkyLight($x, $y, $z){ - return 0; + return 15; } final public function setBlockSkyLight($x, $y, $z, $level){ diff --git a/src/pocketmine/level/format/leveldb/Chunk.php b/src/pocketmine/level/format/leveldb/Chunk.php index 38d88d34e..ce9e31eba 100644 --- a/src/pocketmine/level/format/leveldb/Chunk.php +++ b/src/pocketmine/level/format/leveldb/Chunk.php @@ -29,6 +29,9 @@ use pocketmine\utils\Binary; class Chunk extends BaseFullChunk{ + const DATA_LENGTH = 16384 * (2 + 1 + 1 + 1) + 256 + 1024; + + protected $isLightPopulated = false; protected $isPopulated = false; protected $isGenerated = false; @@ -195,6 +198,20 @@ class Chunk extends BaseFullChunk{ return substr($this->blockLight, ($x << 10) + ($z << 6), 64); } + /** + * @return bool + */ + public function isLightPopulated(){ + return $this->isLightPopulated; + } + + /** + * @param int $value + */ + public function setLightPopulated($value = 1){ + $this->isLightPopulated = (bool) $value; + } + /** * @return bool */ @@ -350,7 +367,9 @@ class Chunk extends BaseFullChunk{ */ public static function getEmptyChunk($chunkX, $chunkZ, LevelProvider $provider = null){ try{ - return new Chunk($provider instanceof LevelProvider ? $provider : LevelDB::class, $chunkX, $chunkZ, str_repeat("\x00", 16384 * (2 + 1 + 1 + 1) + 256 + 1024)); + $chunk = new Chunk($provider instanceof LevelProvider ? $provider : LevelDB::class, $chunkX, $chunkZ, str_repeat("\x00", self::DATA_LENGTH)); + $chunk->skyLight = str_repeat("\xff", 16384); + return $chunk; }catch(\Exception $e){ return null; } diff --git a/src/pocketmine/level/format/mcregion/Chunk.php b/src/pocketmine/level/format/mcregion/Chunk.php index 909b79431..6236c2af9 100644 --- a/src/pocketmine/level/format/mcregion/Chunk.php +++ b/src/pocketmine/level/format/mcregion/Chunk.php @@ -238,7 +238,7 @@ class Chunk extends BaseFullChunk{ } public function setLightPopulated($value = 1){ - $this->nbt->LightPopulated = new Byte("LightPopulated", $value); + $this->nbt->LightPopulated = new Byte("LightPopulated", $value ? 1 : 0); $this->hasChanged = true; } @@ -253,7 +253,7 @@ class Chunk extends BaseFullChunk{ * @param int $value */ public function setPopulated($value = 1){ - $this->nbt->TerrainPopulated = new Byte("TerrainPopulated", (int) $value); + $this->nbt->TerrainPopulated = new Byte("TerrainPopulated", $value ? 1 : 0); $this->hasChanged = true; } @@ -428,7 +428,7 @@ class Chunk extends BaseFullChunk{ $chunk->data = str_repeat("\x00", 16384); $chunk->blocks = $chunk->data . $chunk->data; - $chunk->skyLight = $chunk->data; + $chunk->skyLight = str_repeat("\xff", 16384); $chunk->blockLight = $chunk->data; $chunk->heightMap = array_fill(0, 256, 0); diff --git a/src/pocketmine/level/generator/LightPopulationTask.php b/src/pocketmine/level/generator/LightPopulationTask.php new file mode 100644 index 000000000..7334e1f30 --- /dev/null +++ b/src/pocketmine/level/generator/LightPopulationTask.php @@ -0,0 +1,74 @@ +levelId = $level->getId(); + $this->chunk = $chunk->toFastBinary(); + $this->chunkClass = get_class($chunk); + } + + public function onRun(){ + /** @var FullChunk $chunk */ + $chunk = $this->chunkClass; + $chunk = $chunk::fromFastBinary($this->chunk); + if($chunk === null){ + //TODO error + return; + } + + $chunk->recalculateHeightMap(); + $chunk->populateSkyLight(); + $chunk->setLightPopulated(); + + $this->chunk = $chunk->toFastBinary(); + } + + public function onCompletion(Server $server){ + $level = $server->getLevel($this->levelId); + if($level !== null){ + /** @var FullChunk $chunk */ + $chunk = $this->chunkClass; + $chunk = $chunk::fromFastBinary($this->chunk, $level->getProvider()); + if($chunk === null){ + //TODO error + return; + } + $level->generateChunkCallback($chunk->getX(), $chunk->getZ(), $chunk); + } + } +}