LightUpdate: Allow a single position to be set more than once before executing

This is needed for batched lighting updates to work. It also reduces the overhead involved with simply preparing a lighting update and moves the pain to the execute() instead.
This commit is contained in:
Dylan K. Taylor 2018-09-11 11:33:20 +01:00
parent 99d6aa92cb
commit 191f0038b8

View File

@ -34,6 +34,9 @@ abstract class LightUpdate{
/** @var ChunkManager */ /** @var ChunkManager */
protected $level; protected $level;
/** @var int[] blockhash => new light level */
protected $updateNodes = [];
/** @var \SplQueue */ /** @var \SplQueue */
protected $spreadQueue; protected $spreadQueue;
/** @var bool[] */ /** @var bool[] */
@ -67,31 +70,31 @@ abstract class LightUpdate{
abstract protected function setLight(int $x, int $y, int $z, int $level); abstract protected function setLight(int $x, int $y, int $z, int $level);
public function setAndUpdateLight(int $x, int $y, int $z, int $newLevel){ public function setAndUpdateLight(int $x, int $y, int $z, int $newLevel){
if(!$this->level->isInWorld($x, $y, $z)){ $this->updateNodes[Level::blockHash($x, $y, $z)] = [$x, $y, $z, $newLevel];
throw new \InvalidArgumentException("Coordinates x=$x, y=$y, z=$z are out of range"); }
}
if(isset($this->spreadVisited[$index = Level::blockHash($x, $y, $z)]) or isset($this->removalVisited[$index])){ private function prepareNodes() : void{
throw new \InvalidArgumentException("Already have a visit ready for this block"); foreach($this->updateNodes as $blockHash => [$x, $y, $z, $newLevel]){
} if($this->subChunkHandler->moveTo($x, $y, $z)){
$oldLevel = $this->getLight($x, $y, $z);
if($this->subChunkHandler->moveTo($x, $y, $z)){ if($oldLevel !== $newLevel){
$oldLevel = $this->getLight($x, $y, $z); $this->setLight($x, $y, $z, $newLevel);
if($oldLevel < $newLevel){ //light increased
if($oldLevel !== $newLevel){ $this->spreadVisited[$blockHash] = true;
$this->setLight($x, $y, $z, $newLevel); $this->spreadQueue->enqueue([$x, $y, $z]);
if($oldLevel < $newLevel){ //light increased }else{ //light removed
$this->spreadVisited[$index] = true; $this->removalVisited[$blockHash] = true;
$this->spreadQueue->enqueue([$x, $y, $z]); $this->removalQueue->enqueue([$x, $y, $z, $oldLevel]);
}else{ //light removed }
$this->removalVisited[$index] = true;
$this->removalQueue->enqueue([$x, $y, $z, $oldLevel]);
} }
} }
} }
} }
public function execute(){ public function execute(){
$this->prepareNodes();
while(!$this->removalQueue->isEmpty()){ while(!$this->removalQueue->isEmpty()){
list($x, $y, $z, $oldAdjacentLight) = $this->removalQueue->dequeue(); list($x, $y, $z, $oldAdjacentLight) = $this->removalQueue->dequeue();