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.
This commit is contained in:
Dylan K. Taylor 2020-09-08 22:37:58 +01:00
parent 773069d1cc
commit c7070788f9
9 changed files with 51 additions and 25 deletions

View File

@ -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{

View File

@ -83,7 +83,7 @@ class BlockFactory{
* @var \SplFixedArray|bool[]
* @phpstan-var \SplFixedArray<bool>
*/
public $diffusesSkyLight;
public $blocksDirectSkyLight;
/**
* @var \SplFixedArray|float[]
* @phpstan-var \SplFixedArray<float>
@ -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();
}

View File

@ -51,7 +51,7 @@ class Cobweb extends Flowable{
return true;
}
public function diffusesSkyLight() : bool{
public function blocksDirectSkyLight() : bool{
return true;
}
}

View File

@ -63,7 +63,7 @@ class Leaves extends Transparent{
return 0b1100;
}
public function diffusesSkyLight() : bool{
public function blocksDirectSkyLight() : bool{
return true;
}

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -33,17 +33,17 @@ class SkyLightUpdate extends LightUpdate{
* @var \SplFixedArray|bool[]
* @phpstan-var \SplFixedArray<bool>
*/
private $lightDiffusers;
private $directSkyLightBlockers;
/**
* @param \SplFixedArray|int[] $lightFilters
* @param \SplFixedArray|bool[] $lightDiffusers
* @param \SplFixedArray|bool[] $directSkyLightBlockers
* @phpstan-param \SplFixedArray<int> $lightFilters
* @phpstan-param \SplFixedArray<bool> $lightDiffusers
* @phpstan-param \SplFixedArray<bool> $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]));
}
}
}

View File

@ -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