*/ private $directSkyLightBlockers; /** * @param \SplFixedArray|int[] $lightFilters * @param \SplFixedArray|bool[] $directSkyLightBlockers * @phpstan-param \SplFixedArray $lightFilters * @phpstan-param \SplFixedArray $directSkyLightBlockers */ public function __construct(SubChunkExplorer $subChunkExplorer, \SplFixedArray $lightFilters, \SplFixedArray $directSkyLightBlockers){ parent::__construct($subChunkExplorer, $lightFilters); $this->directSkyLightBlockers = $directSkyLightBlockers; } protected function updateLightArrayRef() : void{ $this->currentLightArray = $this->subChunkExplorer->currentSubChunk->getBlockSkyLightArray(); } protected function getEffectiveLight(int $x, int $y, int $z) : int{ if($y >= World::Y_MAX){ $this->subChunkExplorer->invalidate(); return 15; } return parent::getEffectiveLight($x, $y, $z); } public function recalculateNode(int $x, int $y, int $z) : void{ if(!$this->subChunkExplorer->moveTo($x, $y, $z, false)){ return; } $chunk = $this->subChunkExplorer->currentChunk; $oldHeightMap = $chunk->getHeightMap($x & 0xf, $z & 0xf); $source = $this->subChunkExplorer->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->directSkyLightBlockers); }elseif($yPlusOne > $oldHeightMap){ //Block changed above the heightmap. 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. return; } }else{ //Block changed below heightmap $newHeightMap = $oldHeightMap; } if($newHeightMap > $oldHeightMap){ //Heightmap increase, block placed, remove sky light for($i = $y; $i >= $oldHeightMap; --$i){ $this->setAndUpdateLight($x, $i, $z, 0); //Remove all light beneath, adjacent recalculation will handle the rest. } }elseif($newHeightMap < $oldHeightMap){ //Heightmap decrease, block changed or removed, add sky light for($i = $y; $i >= $newHeightMap; --$i){ $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])); } } }