public function updateBlockLight(int $x, int $y, int $z)
{
$lightPropagationQueue = new \SplQueue();
$lightRemovalQueue = new \SplQueue();
$visited = [];
$removalVisited = [];
$oldLevel = $this->getBlockLightAt($x, $y, $z);
$newLevel = (int) Block::$light[$this->getBlockIdAt($x, $y, $z)];
if ($oldLevel !== $newLevel) {
$this->setBlockLightAt($x, $y, $z, $newLevel);
if ($newLevel < $oldLevel) {
$removalVisited[Level::blockHash($x, $y, $z)] = true;
$lightRemovalQueue->enqueue([new Vector3($x, $y, $z), $oldLevel]);
} else {
$visited[Level::blockHash($x, $y, $z)] = true;
$lightPropagationQueue->enqueue(new Vector3($x, $y, $z));
}
}
while (!$lightRemovalQueue->isEmpty()) {
/** @var Vector3 $node */
$val = $lightRemovalQueue->dequeue();
$node = $val[0];
$lightLevel = $val[1];
$this->computeRemoveBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x + 1, $node->y, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y - 1, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y + 1, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y, $node->z - 1, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
$this->computeRemoveBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
}
while (!$lightPropagationQueue->isEmpty()) {
/** @var Vector3 $node */
$node = $lightPropagationQueue->dequeue();
$lightLevel = $this->getBlockLightAt($node->x, $node->y, $node->z) - (int) Block::$lightFilter[$this->getBlockIdAt($node->x, $node->y, $node->z)];
if ($lightLevel >= 1) {
$this->computeSpreadBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x + 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y - 1, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y + 1, $node->z, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y, $node->z - 1, $lightLevel, $lightPropagationQueue, $visited);
$this->computeSpreadBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightPropagationQueue, $visited);
}
}
}