mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-08 04:38:35 +00:00
Significantly improved light population performance using subchunk
direct accessing These changes produce upwards of 2x better performance (YMMV, also depends on the circumstances).
This commit is contained in:
parent
4703715063
commit
d3e5733ea0
@ -26,10 +26,10 @@ namespace pocketmine\level\light;
|
|||||||
class BlockLightUpdate extends LightUpdate{
|
class BlockLightUpdate extends LightUpdate{
|
||||||
|
|
||||||
public function getLight(int $x, int $y, int $z) : int{
|
public function getLight(int $x, int $y, int $z) : int{
|
||||||
return $this->level->getBlockLightAt($x, $y, $z);
|
return $this->subChunkHandler->currentSubChunk->getBlockLight($x & 0x0f, $y & 0x0f, $z & 0x0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setLight(int $x, int $y, int $z, int $level){
|
public function setLight(int $x, int $y, int $z, int $level){
|
||||||
$this->level->setBlockLightAt($x, $y, $z, $level);
|
$this->subChunkHandler->currentSubChunk->setBlockLight($x & 0x0f, $y & 0x0f, $z & 0x0f, $level);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,6 +26,7 @@ namespace pocketmine\level\light;
|
|||||||
use pocketmine\block\BlockFactory;
|
use pocketmine\block\BlockFactory;
|
||||||
use pocketmine\level\ChunkManager;
|
use pocketmine\level\ChunkManager;
|
||||||
use pocketmine\level\Level;
|
use pocketmine\level\Level;
|
||||||
|
use pocketmine\level\utils\SubChunkIteratorManager;
|
||||||
|
|
||||||
//TODO: make light updates asynchronous
|
//TODO: make light updates asynchronous
|
||||||
abstract class LightUpdate{
|
abstract class LightUpdate{
|
||||||
@ -42,11 +43,15 @@ abstract class LightUpdate{
|
|||||||
protected $removalQueue;
|
protected $removalQueue;
|
||||||
/** @var bool[] */
|
/** @var bool[] */
|
||||||
protected $removalVisited = [];
|
protected $removalVisited = [];
|
||||||
|
/** @var SubChunkIteratorManager */
|
||||||
|
protected $subChunkHandler;
|
||||||
|
|
||||||
public function __construct(ChunkManager $level){
|
public function __construct(ChunkManager $level){
|
||||||
$this->level = $level;
|
$this->level = $level;
|
||||||
$this->removalQueue = new \SplQueue();
|
$this->removalQueue = new \SplQueue();
|
||||||
$this->spreadQueue = new \SplQueue();
|
$this->spreadQueue = new \SplQueue();
|
||||||
|
|
||||||
|
$this->subChunkHandler = new SubChunkIteratorManager($this->level);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addSpreadNode(int $x, int $y, int $z){
|
public function addSpreadNode(int $x, int $y, int $z){
|
||||||
@ -70,6 +75,7 @@ abstract class LightUpdate{
|
|||||||
throw new \InvalidArgumentException("Already have a visit ready for this block");
|
throw new \InvalidArgumentException("Already have a visit ready for this block");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($this->subChunkHandler->moveTo($x, $y, $z)){
|
||||||
$oldLevel = $this->getLight($x, $y, $z);
|
$oldLevel = $this->getLight($x, $y, $z);
|
||||||
|
|
||||||
if($oldLevel !== $newLevel){
|
if($oldLevel !== $newLevel){
|
||||||
@ -83,6 +89,7 @@ abstract class LightUpdate{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function execute(){
|
public function execute(){
|
||||||
while(!$this->removalQueue->isEmpty()){
|
while(!$this->removalQueue->isEmpty()){
|
||||||
@ -98,16 +105,19 @@ abstract class LightUpdate{
|
|||||||
];
|
];
|
||||||
|
|
||||||
foreach($points as list($cx, $cy, $cz)){
|
foreach($points as list($cx, $cy, $cz)){
|
||||||
if(!$this->level->isInWorld($cx, $cy, $cz)){
|
if($this->subChunkHandler->moveTo($cx, $cy, $cz)){
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$this->computeRemoveLight($cx, $cy, $cz, $oldAdjacentLight);
|
$this->computeRemoveLight($cx, $cy, $cz, $oldAdjacentLight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(!$this->spreadQueue->isEmpty()){
|
while(!$this->spreadQueue->isEmpty()){
|
||||||
list($x, $y, $z) = $this->spreadQueue->dequeue();
|
list($x, $y, $z) = $this->spreadQueue->dequeue();
|
||||||
|
|
||||||
|
if(!$this->subChunkHandler->moveTo($x, $y, $z)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$newAdjacentLight = $this->getLight($x, $y, $z);
|
$newAdjacentLight = $this->getLight($x, $y, $z);
|
||||||
if($newAdjacentLight <= 0){
|
if($newAdjacentLight <= 0){
|
||||||
continue;
|
continue;
|
||||||
@ -123,13 +133,12 @@ abstract class LightUpdate{
|
|||||||
];
|
];
|
||||||
|
|
||||||
foreach($points as list($cx, $cy, $cz)){
|
foreach($points as list($cx, $cy, $cz)){
|
||||||
if(!$this->level->isInWorld($cx, $cy, $cz)){
|
if($this->subChunkHandler->moveTo($cx, $cy, $cz)){
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$this->computeSpreadLight($cx, $cy, $cz, $newAdjacentLight);
|
$this->computeSpreadLight($cx, $cy, $cz, $newAdjacentLight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function computeRemoveLight(int $x, int $y, int $z, int $oldAdjacentLevel){
|
protected function computeRemoveLight(int $x, int $y, int $z, int $oldAdjacentLevel){
|
||||||
$current = $this->getLight($x, $y, $z);
|
$current = $this->getLight($x, $y, $z);
|
||||||
@ -153,7 +162,7 @@ abstract class LightUpdate{
|
|||||||
|
|
||||||
protected function computeSpreadLight(int $x, int $y, int $z, int $newAdjacentLevel){
|
protected function computeSpreadLight(int $x, int $y, int $z, int $newAdjacentLevel){
|
||||||
$current = $this->getLight($x, $y, $z);
|
$current = $this->getLight($x, $y, $z);
|
||||||
$potentialLight = $newAdjacentLevel - BlockFactory::$lightFilter[$this->level->getBlockIdAt($x, $y, $z)];
|
$potentialLight = $newAdjacentLevel - BlockFactory::$lightFilter[$this->subChunkHandler->currentSubChunk->getBlockId($x & 0x0f, $y & 0x0f, $z & 0x0f)];
|
||||||
|
|
||||||
if($current < $potentialLight){
|
if($current < $potentialLight){
|
||||||
$this->setLight($x, $y, $z, $potentialLight);
|
$this->setLight($x, $y, $z, $potentialLight);
|
||||||
|
@ -26,10 +26,10 @@ namespace pocketmine\level\light;
|
|||||||
class SkyLightUpdate extends LightUpdate{
|
class SkyLightUpdate extends LightUpdate{
|
||||||
|
|
||||||
public function getLight(int $x, int $y, int $z) : int{
|
public function getLight(int $x, int $y, int $z) : int{
|
||||||
return $this->level->getBlockSkyLightAt($x, $y, $z);
|
return $this->subChunkHandler->currentSubChunk->getBlockSkyLight($x & 0x0f, $y & 0x0f, $z & 0x0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setLight(int $x, int $y, int $z, int $level){
|
public function setLight(int $x, int $y, int $z, int $level){
|
||||||
$this->level->setBlockSkyLightAt($x, $y, $z, $level);
|
$this->subChunkHandler->currentSubChunk->setBlockSkyLight($x & 0x0f, $y & 0x0f, $z & 0x0f, $level);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user