mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 08:17:34 +00:00
SkyLightUpdate: deal with effective light during initial node discovery
this allows the propagation stage to ignore effective light, which allows for further optimisations.
This commit is contained in:
parent
d80f65ae7c
commit
d0b9234841
@ -106,9 +106,6 @@ abstract class LightUpdate{
|
||||
$context->removalQueue->enqueue([$x, $y, $z, $oldLevel]);
|
||||
}
|
||||
}
|
||||
}elseif($this->getEffectiveLight($x, $y, $z) > 0){ //outside the chunk (e.g. virtual sky light from y=256)
|
||||
$context->spreadVisited[$blockHash] = true;
|
||||
$context->spreadQueue->enqueue([$x, $y, $z]);
|
||||
}
|
||||
}
|
||||
return $context;
|
||||
@ -129,9 +126,6 @@ abstract class LightUpdate{
|
||||
|
||||
if($this->subChunkExplorer->moveTo($cx, $cy, $cz) !== SubChunkExplorerStatus::INVALID){
|
||||
$this->computeRemoveLight($cx, $cy, $cz, $oldAdjacentLight, $context);
|
||||
}elseif($this->getEffectiveLight($cx, $cy, $cz) > 0 && !isset($context->spreadVisited[$index = World::blockHash($cx, $cy, $cz)])){
|
||||
$context->spreadVisited[$index] = true;
|
||||
$context->spreadQueue->enqueue([$cx, $cy, $cz]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,7 +136,10 @@ abstract class LightUpdate{
|
||||
|
||||
unset($context->spreadVisited[World::blockHash($x, $y, $z)]);
|
||||
|
||||
$newAdjacentLight = $this->getEffectiveLight($x, $y, $z);
|
||||
if($this->subChunkExplorer->moveTo($x, $y, $z) === SubChunkExplorerStatus::INVALID){
|
||||
continue;
|
||||
}
|
||||
$newAdjacentLight = $this->getCurrentLightArray()->get($x & SubChunk::COORD_MASK, $y & SubChunk::COORD_MASK, $z & SubChunk::COORD_MASK);
|
||||
if($newAdjacentLight <= 0){
|
||||
continue;
|
||||
}
|
||||
|
@ -84,16 +84,17 @@ class SkyLightUpdate extends LightUpdate{
|
||||
$newHeightMap = $oldHeightMap;
|
||||
}
|
||||
|
||||
if($newHeightMap > $oldHeightMap){ //Heightmap increase, block placed, remove sky light
|
||||
for($i = $y; $i >= $oldHeightMap; --$i){
|
||||
if($newHeightMap >= $oldHeightMap){
|
||||
for($i = $y - 1; $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
|
||||
|
||||
//recalculate light for the placed block from its surroundings - this avoids having to check effective light during propagation
|
||||
$this->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentLight($x, $y, $z) - ($this->lightFilters[$source] ?? self::BASE_LIGHT_FILTER)));
|
||||
}else{ //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] ?? self::BASE_LIGHT_FILTER)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,35 +125,45 @@ class SkyLightUpdate extends LightUpdate{
|
||||
for($x = 0; $x < Chunk::EDGE_LENGTH; ++$x){
|
||||
for($z = 0; $z < Chunk::EDGE_LENGTH; ++$z){
|
||||
$currentHeight = $chunk->getHeightMap($x, $z);
|
||||
$maxAdjacentHeight = World::Y_MIN;
|
||||
if($x !== 0){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x - 1, $z));
|
||||
}
|
||||
if($x !== 15){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x + 1, $z));
|
||||
}
|
||||
if($z !== 0){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x, $z - 1));
|
||||
}
|
||||
if($z !== 15){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x, $z + 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* We skip the top two blocks between current height and max adjacent (if there's a difference) because:
|
||||
* - the block next to the highest adjacent will do nothing during propagation (it's surrounded by 15s)
|
||||
* - the block below that block will do the same as the node in the highest adjacent
|
||||
* NOTE: If block opacity becomes direction-aware in the future, the second point will become invalid.
|
||||
*/
|
||||
$nodeColumnEnd = max($currentHeight, $maxAdjacentHeight - 2);
|
||||
|
||||
for($y = $currentHeight; $y <= $nodeColumnEnd; $y++){
|
||||
$this->setAndUpdateLight($x + $baseX, $y, $z + $baseZ, 15);
|
||||
$lightSources++;
|
||||
}
|
||||
for($y = $nodeColumnEnd + 1, $yMax = $lowestClearSubChunk * SubChunk::EDGE_LENGTH; $y < $yMax; $y++){
|
||||
if($currentHeight === World::Y_MAX){
|
||||
//this column has a light-filtering block in the top cell - make sure it's lit from above the world
|
||||
//light from above the world bounds will not be checked during propagation
|
||||
$y = $currentHeight - 1;
|
||||
if($this->subChunkExplorer->moveTo($x + $baseX, $y, $z + $baseZ) !== SubChunkExplorerStatus::INVALID){
|
||||
$this->getCurrentLightArray()->set($x, $y & SubChunk::COORD_MASK, $z, 15);
|
||||
$block = $this->subChunkExplorer->currentSubChunk->getBlockStateId($x, $y & SubChunk::COORD_MASK, $z);
|
||||
$this->setAndUpdateLight($x + $baseX, $y, $z + $baseZ, max(0, 15 - ($this->lightFilters[$block] ?? self::BASE_LIGHT_FILTER)));
|
||||
}
|
||||
}else{
|
||||
$maxAdjacentHeight = World::Y_MIN;
|
||||
if($x !== 0){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x - 1, $z));
|
||||
}
|
||||
if($x !== 15){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x + 1, $z));
|
||||
}
|
||||
if($z !== 0){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x, $z - 1));
|
||||
}
|
||||
if($z !== 15){
|
||||
$maxAdjacentHeight = max($maxAdjacentHeight, $chunk->getHeightMap($x, $z + 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* We skip the top two blocks between current height and max adjacent (if there's a difference) because:
|
||||
* - the block next to the highest adjacent will do nothing during propagation (it's surrounded by 15s)
|
||||
* - the block below that block will do the same as the node in the highest adjacent
|
||||
* NOTE: If block opacity becomes direction-aware in the future, the second point will become invalid.
|
||||
*/
|
||||
$nodeColumnEnd = max($currentHeight, $maxAdjacentHeight - 2);
|
||||
for($y = $currentHeight; $y <= $nodeColumnEnd; $y++){
|
||||
$this->setAndUpdateLight($x + $baseX, $y, $z + $baseZ, 15);
|
||||
$lightSources++;
|
||||
}
|
||||
for($y = $nodeColumnEnd + 1, $yMax = $lowestClearSubChunk * SubChunk::EDGE_LENGTH; $y < $yMax; $y++){
|
||||
if($this->subChunkExplorer->moveTo($x + $baseX, $y, $z + $baseZ) !== SubChunkExplorerStatus::INVALID){
|
||||
$this->getCurrentLightArray()->set($x, $y & SubChunk::COORD_MASK, $z, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user