mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-18 17:34:11 +00:00
LightUpdate: avoid trying to propagate light into nodes with higher light levels
Track which direction the current node's light came from, and don't check it again when we check the current node's adjacent blocks. e.g. if this node was the eastern neighbour of a light source, we don't need to check this node's western neighbour, as we already know it has a higher light level than our own. This improves performance of basic light spread in a void by about 6%, which isn't a huge amount, but it's something. I've yet to explore whether light removal could also benefit from this change.
This commit is contained in:
parent
006f78c0a7
commit
ee26d6d570
@ -28,8 +28,8 @@ final class LightPropagationContext{
|
|||||||
/** @phpstan-var \SplQueue<array{int, int, int}> */
|
/** @phpstan-var \SplQueue<array{int, int, int}> */
|
||||||
public \SplQueue $spreadQueue;
|
public \SplQueue $spreadQueue;
|
||||||
/**
|
/**
|
||||||
* @var true[]
|
* @var int[]|true[]
|
||||||
* @phpstan-var array<int, true>
|
* @phpstan-var array<int, int|true>
|
||||||
*/
|
*/
|
||||||
public array $spreadVisited = [];
|
public array $spreadVisited = [];
|
||||||
|
|
||||||
|
@ -137,6 +137,7 @@ abstract class LightUpdate{
|
|||||||
while(!$context->spreadQueue->isEmpty()){
|
while(!$context->spreadQueue->isEmpty()){
|
||||||
$touched++;
|
$touched++;
|
||||||
[$x, $y, $z] = $context->spreadQueue->dequeue();
|
[$x, $y, $z] = $context->spreadQueue->dequeue();
|
||||||
|
$from = $context->spreadVisited[World::blockHash($x, $y, $z)];
|
||||||
|
|
||||||
unset($context->spreadVisited[World::blockHash($x, $y, $z)]);
|
unset($context->spreadVisited[World::blockHash($x, $y, $z)]);
|
||||||
|
|
||||||
@ -155,7 +156,11 @@ abstract class LightUpdate{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(Facing::OFFSET as [$ox, $oy, $oz]){
|
foreach(Facing::OFFSET as $side => [$ox, $oy, $oz]){
|
||||||
|
if($from === $side){
|
||||||
|
//don't check the side that this node received its initial light from
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$cx = $x + $ox;
|
$cx = $x + $ox;
|
||||||
$cy = $y + $oy;
|
$cy = $y + $oy;
|
||||||
$cz = $z + $oz;
|
$cz = $z + $oz;
|
||||||
@ -169,7 +174,7 @@ abstract class LightUpdate{
|
|||||||
$lightArray = $this->getCurrentLightArray();
|
$lightArray = $this->getCurrentLightArray();
|
||||||
}
|
}
|
||||||
assert($subChunk !== null);
|
assert($subChunk !== null);
|
||||||
$this->computeSpreadLight($cx, $cy, $cz, $newAdjacentLight, $context, $lightArray, $subChunk);
|
$this->computeSpreadLight($cx, $cy, $cz, $newAdjacentLight, $context, $lightArray, $subChunk, $side);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +204,7 @@ abstract class LightUpdate{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function computeSpreadLight(int $x, int $y, int $z, int $newAdjacentLevel, LightPropagationContext $context, LightArray $lightArray, SubChunk $subChunk) : void{
|
protected function computeSpreadLight(int $x, int $y, int $z, int $newAdjacentLevel, LightPropagationContext $context, LightArray $lightArray, SubChunk $subChunk, int $side) : void{
|
||||||
$lx = $x & SubChunk::COORD_MASK;
|
$lx = $x & SubChunk::COORD_MASK;
|
||||||
$ly = $y & SubChunk::COORD_MASK;
|
$ly = $y & SubChunk::COORD_MASK;
|
||||||
$lz = $z & SubChunk::COORD_MASK;
|
$lz = $z & SubChunk::COORD_MASK;
|
||||||
@ -210,7 +215,11 @@ abstract class LightUpdate{
|
|||||||
$lightArray->set($lx, $ly, $lz, $potentialLight);
|
$lightArray->set($lx, $ly, $lz, $potentialLight);
|
||||||
|
|
||||||
if(!isset($context->spreadVisited[$index = World::blockHash($x, $y, $z)]) && $potentialLight > 1){
|
if(!isset($context->spreadVisited[$index = World::blockHash($x, $y, $z)]) && $potentialLight > 1){
|
||||||
$context->spreadVisited[$index] = true;
|
//Track where this node was lit from, to avoid checking the source again when we propagate from here
|
||||||
|
//TODO: In the future it might be worth tracking more than one adjacent source face in case multiple
|
||||||
|
//nodes try to light the same node. However, this is a rare case since the vast majority of calls are
|
||||||
|
//basic propagation with only one source anyway.
|
||||||
|
$context->spreadVisited[$index] = Facing::opposite($side);
|
||||||
$context->spreadQueue->enqueue([$x, $y, $z]);
|
$context->spreadQueue->enqueue([$x, $y, $z]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user