From 30c5487f9402a68c23c1996d1340acadab4d8bb1 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 8 Jul 2017 17:13:22 +0100 Subject: [PATCH] Drastically improved performance of basic chunk sky-light population back 2 commits: 53ms per chunk back 1 commit: 27ms per chunk this commit: 3ms per chunk (on my machine, of course) --- src/pocketmine/level/format/Chunk.php | 37 +++++++++++++++++-- src/pocketmine/level/format/EmptySubChunk.php | 8 ++++ src/pocketmine/level/format/SubChunk.php | 12 +++++- .../level/format/SubChunkInterface.php | 10 +++++ 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/pocketmine/level/format/Chunk.php b/src/pocketmine/level/format/Chunk.php index 985d96d31..1ae0f5532 100644 --- a/src/pocketmine/level/format/Chunk.php +++ b/src/pocketmine/level/format/Chunk.php @@ -313,6 +313,17 @@ class Chunk{ } } + /** + * @param int $level + */ + public function setAllBlockSkyLight(int $level){ + $char = chr(($level & 0x0f) | ($level << 4)); + $data = str_repeat($char, 2048); + for($y = $this->getHighestSubChunkIndex(); $y >= 0; --$y){ + $this->getSubChunk($y, true)->setBlockSkyLightArray($data); + } + } + /** * Returns the block light level at the specified chunk block coordinates * @@ -340,6 +351,17 @@ class Chunk{ } } + /** + * @param int $level + */ + public function setAllBlockLight(int $level){ + $char = chr(($level & 0x0f) | ($level << 4)); + $data = str_repeat($char, 2048); + for($y = $this->getHighestSubChunkIndex(); $y >= 0; --$y){ + $this->getSubChunk($y, true)->setBlockLightArray($data); + } + } + /** * Returns the Y coordinate of the highest non-air block at the specified X/Z chunk block coordinates * @@ -366,6 +388,10 @@ class Chunk{ return -1; } + public function getMaxY() : int{ + return ($this->getHighestSubChunkIndex() << 4) | 0x0f; + } + /** * Returns the heightmap value at the specified X/Z chunk block coordinates * @@ -427,7 +453,10 @@ class Chunk{ * TODO: fast adjacent light spread */ public function populateSkyLight(){ - $maxY = ($this->getHighestSubChunkIndex() + 1) << 4; + $maxY = $this->getMaxY(); + + $this->setAllBlockSkyLight(0); + for($x = 0; $x < 16; ++$x){ for($z = 0; $z < 16; ++$z){ $heightMap = $this->getHeightMap($x, $z); @@ -437,11 +466,11 @@ class Chunk{ } $light = 15; - for(; $y > 0; --$y){ + for(; $y >= 0; --$y){ if($light > 0){ $light -= Block::$lightFilter[$this->getBlockId($x, $y, $z)]; - if($light < 0){ - $light = 0; + if($light <= 0){ + break; } } $this->setBlockSkyLight($x, $y, $z, $light); diff --git a/src/pocketmine/level/format/EmptySubChunk.php b/src/pocketmine/level/format/EmptySubChunk.php index f946d4083..88d002429 100644 --- a/src/pocketmine/level/format/EmptySubChunk.php +++ b/src/pocketmine/level/format/EmptySubChunk.php @@ -101,10 +101,18 @@ class EmptySubChunk implements SubChunkInterface{ return str_repeat("\x00", 2048); } + public function setBlockLightArray(string $data){ + + } + public function getBlockSkyLightArray() : string{ return str_repeat("\xff", 2048); } + public function setBlockSkyLightArray(string $data){ + + } + public function networkSerialize() : string{ return "\x00" . str_repeat("\x00", 10240); } diff --git a/src/pocketmine/level/format/SubChunk.php b/src/pocketmine/level/format/SubChunk.php index 56db712f1..d69fbf0a3 100644 --- a/src/pocketmine/level/format/SubChunk.php +++ b/src/pocketmine/level/format/SubChunk.php @@ -30,7 +30,7 @@ class SubChunk implements SubChunkInterface{ protected $blockLight; protected $skyLight; - private static function assignData(&$target, $data, $length, $value = "\x00"){ + private static function assignData(&$target, string $data, int $length, string $value = "\x00"){ if(strlen($data) !== $length){ assert($data === "", "Invalid non-zero length given, expected $length, got " . strlen($data)); $target = str_repeat($value, $length); @@ -203,11 +203,21 @@ class SubChunk implements SubChunkInterface{ return $this->skyLight; } + public function setBlockSkyLightArray(string $data){ + assert(strlen($data) === 2048, "Wrong length of skylight array, expecting 2048 bytes, got " . strlen($data)); + $this->skyLight = $data; + } + public function getBlockLightArray() : string{ assert(strlen($this->blockLight) === 2048, "Wrong length of light array, expecting 2048 bytes, got " . strlen($this->blockLight)); return $this->blockLight; } + public function setBlockLightArray(string $data){ + assert(strlen($data) === 2048, "Wrong length of light array, expecting 2048 bytes, got " . strlen($data)); + $this->blockLight = $data; + } + public function networkSerialize() : string{ // storage version, ids, data, skylight, blocklight return "\x00" . $this->ids . $this->data . $this->skyLight . $this->blockLight; diff --git a/src/pocketmine/level/format/SubChunkInterface.php b/src/pocketmine/level/format/SubChunkInterface.php index a0001b12f..182c06e43 100644 --- a/src/pocketmine/level/format/SubChunkInterface.php +++ b/src/pocketmine/level/format/SubChunkInterface.php @@ -182,11 +182,21 @@ interface SubChunkInterface{ */ public function getBlockSkyLightArray() : string; + /** + * @param string $data + */ + public function setBlockSkyLightArray(string $data); + /** * @return string */ public function getBlockLightArray() : string; + /** + * @param string $data + */ + public function setBlockLightArray(string $data); + /** * @return string */