From c7070788f964d7fc4eab8f049b9fa8280aea501c Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 8 Sep 2020 22:37:58 +0100 Subject: [PATCH] Rename and repurpose Block->diffusesSkyLight to blocksDirectSkyLight this new form allows skipping some useless checks during sky light calculation and also allows getting rid of the last hard dependency on core Block classes. We're getting real close to native light now. --- src/block/Block.php | 12 ++++++------ src/block/BlockFactory.php | 6 +++--- src/block/Cobweb.php | 2 +- src/block/Leaves.php | 2 +- src/world/World.php | 2 +- src/world/generator/PopulationTask.php | 2 +- src/world/light/LightPopulationTask.php | 2 +- src/world/light/SkyLightUpdate.php | 23 ++++++++++++----------- tests/phpstan/configs/l8-baseline.neon | 25 +++++++++++++++++++++++++ 9 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/block/Block.php b/src/block/Block.php index ee07c9c4b..2022a55be 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -292,14 +292,14 @@ class Block{ } /** - * Returns whether this block will diffuse sky light passing through it vertically. - * Diffusion means that full-strength sky light passing through this block will not be reduced, but will start being filtered below the block. - * Examples of this behaviour include leaves and cobwebs. + * Returns whether this block blocks direct sky light from passing through it. This is independent from the light + * filter value, which is used during propagation. * - * Light-diffusing blocks are included by the heightmap. + * In most cases, this is the same as isTransparent(); however, some special cases exist such as leaves and cobwebs, + * which don't have any additional effect on light propagation, but don't allow direct sky light to pass through. */ - public function diffusesSkyLight() : bool{ - return false; + public function blocksDirectSkyLight() : bool{ + return $this->getLightFilter() > 0; } public function isTransparent() : bool{ diff --git a/src/block/BlockFactory.php b/src/block/BlockFactory.php index b3283f2aa..1097dc0f7 100644 --- a/src/block/BlockFactory.php +++ b/src/block/BlockFactory.php @@ -83,7 +83,7 @@ class BlockFactory{ * @var \SplFixedArray|bool[] * @phpstan-var \SplFixedArray */ - public $diffusesSkyLight; + public $blocksDirectSkyLight; /** * @var \SplFixedArray|float[] * @phpstan-var \SplFixedArray @@ -95,7 +95,7 @@ class BlockFactory{ $this->light = \SplFixedArray::fromArray(array_fill(0, 16384, 0)); $this->lightFilter = \SplFixedArray::fromArray(array_fill(0, 16384, 1)); - $this->diffusesSkyLight = \SplFixedArray::fromArray(array_fill(0, 16384, false)); + $this->blocksDirectSkyLight = \SplFixedArray::fromArray(array_fill(0, 16384, false)); $this->blastResistance = \SplFixedArray::fromArray(array_fill(0, 16384, 0.0)); $this->register(new ActivatorRail(new BID(Ids::ACTIVATOR_RAIL), "Activator Rail")); @@ -858,7 +858,7 @@ class BlockFactory{ $this->fullList[$index] = $block; $this->light[$index] = $block->getLightLevel(); $this->lightFilter[$index] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter - $this->diffusesSkyLight[$index] = $block->diffusesSkyLight(); + $this->blocksDirectSkyLight[$index] = $block->blocksDirectSkyLight(); $this->blastResistance[$index] = $block->getBreakInfo()->getBlastResistance(); } diff --git a/src/block/Cobweb.php b/src/block/Cobweb.php index e28bf19a7..e93641d7d 100644 --- a/src/block/Cobweb.php +++ b/src/block/Cobweb.php @@ -51,7 +51,7 @@ class Cobweb extends Flowable{ return true; } - public function diffusesSkyLight() : bool{ + public function blocksDirectSkyLight() : bool{ return true; } } diff --git a/src/block/Leaves.php b/src/block/Leaves.php index 0ed48c3a9..058cdb5f9 100644 --- a/src/block/Leaves.php +++ b/src/block/Leaves.php @@ -63,7 +63,7 @@ class Leaves extends Transparent{ return 0b1100; } - public function diffusesSkyLight() : bool{ + public function blocksDirectSkyLight() : bool{ return true; } diff --git a/src/world/World.php b/src/world/World.php index 04d19825c..a457f5cb6 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -1165,7 +1165,7 @@ class World implements ChunkManager{ $blockFactory = BlockFactory::getInstance(); $this->timings->doBlockSkyLightUpdates->startTiming(); if($this->skyLightUpdate === null){ - $this->skyLightUpdate = new SkyLightUpdate($this, $blockFactory->lightFilter, $blockFactory->diffusesSkyLight); + $this->skyLightUpdate = new SkyLightUpdate($this, $blockFactory->lightFilter, $blockFactory->blocksDirectSkyLight); } $this->skyLightUpdate->recalculateNode($x, $y, $z); $this->timings->doBlockSkyLightUpdates->stopTiming(); diff --git a/src/world/generator/PopulationTask.php b/src/world/generator/PopulationTask.php index 72eee84bb..979909119 100644 --- a/src/world/generator/PopulationTask.php +++ b/src/world/generator/PopulationTask.php @@ -119,7 +119,7 @@ class PopulationTask extends AsyncTask{ $chunk->setPopulated(); $blockFactory = BlockFactory::getInstance(); - $chunk->recalculateHeightMap($blockFactory->lightFilter, $blockFactory->diffusesSkyLight); + $chunk->recalculateHeightMap($blockFactory->lightFilter, $blockFactory->blocksDirectSkyLight); $chunk->populateSkyLight($blockFactory->lightFilter); $chunk->setLightPopulated(); diff --git a/src/world/light/LightPopulationTask.php b/src/world/light/LightPopulationTask.php index b4b33ff86..e066c2f2a 100644 --- a/src/world/light/LightPopulationTask.php +++ b/src/world/light/LightPopulationTask.php @@ -61,7 +61,7 @@ class LightPopulationTask extends AsyncTask{ $chunk = FastChunkSerializer::deserialize($this->chunk); $blockFactory = BlockFactory::getInstance(); - $chunk->recalculateHeightMap($blockFactory->lightFilter, $blockFactory->diffusesSkyLight); + $chunk->recalculateHeightMap($blockFactory->lightFilter, $blockFactory->blocksDirectSkyLight); $chunk->populateSkyLight($blockFactory->lightFilter); $chunk->setLightPopulated(); diff --git a/src/world/light/SkyLightUpdate.php b/src/world/light/SkyLightUpdate.php index 7c1d5634e..ac2054339 100644 --- a/src/world/light/SkyLightUpdate.php +++ b/src/world/light/SkyLightUpdate.php @@ -33,17 +33,17 @@ class SkyLightUpdate extends LightUpdate{ * @var \SplFixedArray|bool[] * @phpstan-var \SplFixedArray */ - private $lightDiffusers; + private $directSkyLightBlockers; /** * @param \SplFixedArray|int[] $lightFilters - * @param \SplFixedArray|bool[] $lightDiffusers + * @param \SplFixedArray|bool[] $directSkyLightBlockers * @phpstan-param \SplFixedArray $lightFilters - * @phpstan-param \SplFixedArray $lightDiffusers + * @phpstan-param \SplFixedArray $directSkyLightBlockers */ - public function __construct(ChunkManager $world, \SplFixedArray $lightFilters, \SplFixedArray $lightDiffusers){ + public function __construct(ChunkManager $world, \SplFixedArray $lightFilters, \SplFixedArray $directSkyLightBlockers){ parent::__construct($world, $lightFilters); - $this->lightDiffusers = $lightDiffusers; + $this->directSkyLightBlockers = $directSkyLightBlockers; } protected function updateLightArrayRef() : void{ @@ -59,19 +59,20 @@ class SkyLightUpdate extends LightUpdate{ } public function recalculateNode(int $x, int $y, int $z) : void{ - $chunk = $this->world->getChunk($x >> 4, $z >> 4); - if($chunk === null){ + if(!$this->subChunkHandler->moveTo($x, $y, $z, false)){ return; } + $chunk = $this->subChunkHandler->currentChunk; + $oldHeightMap = $chunk->getHeightMap($x & 0xf, $z & 0xf); - $source = $this->world->getBlockAt($x, $y, $z); + $source = $this->subChunkHandler->currentSubChunk->getFullBlock($x & 0xf, $y & 0xf, $z & 0xf); $yPlusOne = $y + 1; if($yPlusOne === $oldHeightMap){ //Block changed directly beneath the heightmap. Check if a block was removed or changed to a different light-filter. - $newHeightMap = $chunk->recalculateHeightMapColumn($x & 0x0f, $z & 0x0f, $this->lightFilters, $this->lightDiffusers); + $newHeightMap = $chunk->recalculateHeightMapColumn($x & 0x0f, $z & 0x0f, $this->lightFilters, $this->directSkyLightBlockers); }elseif($yPlusOne > $oldHeightMap){ //Block changed above the heightmap. - if($source->getLightFilter() > 0 or $source->diffusesSkyLight()){ + if($this->directSkyLightBlockers[$source]){ $chunk->setHeightMap($x & 0xf, $z & 0xf, $yPlusOne); $newHeightMap = $yPlusOne; }else{ //Block changed which has no effect on direct sky light, for example placing or removing glass. @@ -90,7 +91,7 @@ class SkyLightUpdate extends LightUpdate{ $this->setAndUpdateLight($x, $i, $z, 15); } }else{ //No heightmap change, block changed "underground" - $this->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentLight($x, $y, $z) - $this->lightFilters[$source->getFullId()])); + $this->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentLight($x, $y, $z) - $this->lightFilters[$source])); } } } diff --git a/tests/phpstan/configs/l8-baseline.neon b/tests/phpstan/configs/l8-baseline.neon index 76320628e..8550477db 100644 --- a/tests/phpstan/configs/l8-baseline.neon +++ b/tests/phpstan/configs/l8-baseline.neon @@ -950,6 +950,31 @@ parameters: count: 1 path: ../../../src/world/light/SkyLightUpdate.php + - + message: "#^Cannot call method getHeightMap\\(\\) on pocketmine\\\\world\\\\format\\\\Chunk\\|null\\.$#" + count: 1 + path: ../../../src/world/light/SkyLightUpdate.php + + - + message: "#^Cannot call method getFullBlock\\(\\) on pocketmine\\\\world\\\\format\\\\SubChunk\\|null\\.$#" + count: 1 + path: ../../../src/world/light/SkyLightUpdate.php + + - + message: "#^Cannot call method recalculateHeightMapColumn\\(\\) on pocketmine\\\\world\\\\format\\\\Chunk\\|null\\.$#" + count: 1 + path: ../../../src/world/light/SkyLightUpdate.php + + - + message: "#^Only booleans are allowed in an if condition, bool\\|null given\\.$#" + count: 1 + path: ../../../src/world/light/SkyLightUpdate.php + + - + message: "#^Cannot call method setHeightMap\\(\\) on pocketmine\\\\world\\\\format\\\\Chunk\\|null\\.$#" + count: 1 + path: ../../../src/world/light/SkyLightUpdate.php + - message: "#^Only numeric types are allowed in \\-, int\\|null given on the right side\\.$#" count: 1