mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-08 04:38:35 +00:00
Level: Batch light updates at the end of the tick to amortize CPU cost (#2429)
this produces a 5x performance improvement for lighting updates during water flow, and 25% improvement for lava flow.
This commit is contained in:
parent
a9fc67663c
commit
09dea035d4
@ -247,6 +247,11 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $closed = false;
|
private $closed = false;
|
||||||
|
|
||||||
|
/** @var BlockLightUpdate|null */
|
||||||
|
private $blockLightUpdate = null;
|
||||||
|
/** @var SkyLightUpdate|null */
|
||||||
|
private $skyLightUpdate = null;
|
||||||
|
|
||||||
public static function chunkHash(int $x, int $z) : int{
|
public static function chunkHash(int $x, int $z) : int{
|
||||||
return (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF);
|
return (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
@ -764,6 +769,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->tickChunks();
|
$this->tickChunks();
|
||||||
$this->timings->doTickTiles->stopTiming();
|
$this->timings->doTickTiles->stopTiming();
|
||||||
|
|
||||||
|
$this->executeQueuedLightUpdates();
|
||||||
|
|
||||||
if(count($this->changedBlocks) > 0){
|
if(count($this->changedBlocks) > 0){
|
||||||
if(count($this->players) > 0){
|
if(count($this->players) > 0){
|
||||||
foreach($this->changedBlocks as $index => $blocks){
|
foreach($this->changedBlocks as $index => $blocks){
|
||||||
@ -1417,22 +1424,21 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$newHeightMap = $oldHeightMap;
|
$newHeightMap = $oldHeightMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
$update = new SkyLightUpdate($this);
|
if($this->skyLightUpdate === null){
|
||||||
|
$this->skyLightUpdate = new SkyLightUpdate($this);
|
||||||
|
}
|
||||||
if($newHeightMap > $oldHeightMap){ //Heightmap increase, block placed, remove sky light
|
if($newHeightMap > $oldHeightMap){ //Heightmap increase, block placed, remove sky light
|
||||||
for($i = $y; $i >= $oldHeightMap; --$i){
|
for($i = $y; $i >= $oldHeightMap; --$i){
|
||||||
$update->setAndUpdateLight($x, $i, $z, 0); //Remove all light beneath, adjacent recalculation will handle the rest.
|
$this->skyLightUpdate->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
|
}elseif($newHeightMap < $oldHeightMap){ //Heightmap decrease, block changed or removed, add sky light
|
||||||
for($i = $y; $i >= $newHeightMap; --$i){
|
for($i = $y; $i >= $newHeightMap; --$i){
|
||||||
$update->setAndUpdateLight($x, $i, $z, 15);
|
$this->skyLightUpdate->setAndUpdateLight($x, $i, $z, 15);
|
||||||
}
|
}
|
||||||
}else{ //No heightmap change, block changed "underground"
|
}else{ //No heightmap change, block changed "underground"
|
||||||
$update->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentBlockSkyLight($x, $y, $z) - BlockFactory::$lightFilter[$sourceId]));
|
$this->skyLightUpdate->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentBlockSkyLight($x, $y, $z) - BlockFactory::$lightFilter[$sourceId]));
|
||||||
}
|
}
|
||||||
|
|
||||||
$update->execute();
|
|
||||||
|
|
||||||
$this->timings->doBlockSkyLightUpdates->stopTiming();
|
$this->timings->doBlockSkyLightUpdates->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1462,13 +1468,30 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$id = $this->getBlockIdAt($x, $y, $z);
|
$id = $this->getBlockIdAt($x, $y, $z);
|
||||||
$newLevel = max(BlockFactory::$light[$id], $this->getHighestAdjacentBlockLight($x, $y, $z) - BlockFactory::$lightFilter[$id]);
|
$newLevel = max(BlockFactory::$light[$id], $this->getHighestAdjacentBlockLight($x, $y, $z) - BlockFactory::$lightFilter[$id]);
|
||||||
|
|
||||||
$update = new BlockLightUpdate($this);
|
if($this->blockLightUpdate === null){
|
||||||
$update->setAndUpdateLight($x, $y, $z, $newLevel);
|
$this->blockLightUpdate = new BlockLightUpdate($this);
|
||||||
$update->execute();
|
}
|
||||||
|
$this->blockLightUpdate->setAndUpdateLight($x, $y, $z, $newLevel);
|
||||||
|
|
||||||
$this->timings->doBlockLightUpdates->stopTiming();
|
$this->timings->doBlockLightUpdates->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function executeQueuedLightUpdates() : void{
|
||||||
|
if($this->blockLightUpdate !== null){
|
||||||
|
$this->timings->doBlockLightUpdates->startTiming();
|
||||||
|
$this->blockLightUpdate->execute();
|
||||||
|
$this->blockLightUpdate = null;
|
||||||
|
$this->timings->doBlockLightUpdates->stopTiming();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->skyLightUpdate !== null){
|
||||||
|
$this->timings->doBlockSkyLightUpdates->startTiming();
|
||||||
|
$this->skyLightUpdate->execute();
|
||||||
|
$this->skyLightUpdate = null;
|
||||||
|
$this->timings->doBlockSkyLightUpdates->stopTiming();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets on Vector3 the data from a Block object,
|
* Sets on Vector3 the data from a Block object,
|
||||||
* does block updates and puts the changes to the send queue.
|
* does block updates and puts the changes to the send queue.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user