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