mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-27 13:49:55 +00:00
LightPopulationTask: Don't overwrite the whole chunk on completion
this is more efficient (less data copied for ITC), fixes #2873, and also fixes terrain changes during task run getting overwritten. This still leaves the problem that the light information provided may be out of date by the time the task completes, but this is nonetheless a step forward.
This commit is contained in:
parent
296825b87e
commit
e1352668d1
@ -620,6 +620,17 @@ class Chunk{
|
||||
return $this->heightMap->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $values
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setHeightMapArray(array $values) : void{
|
||||
if(count($values) !== 256){
|
||||
throw new \InvalidArgumentException("Expected exactly 256 values");
|
||||
}
|
||||
$this->heightMap = \SplFixedArray::fromArray($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -27,15 +27,31 @@ use pocketmine\block\BlockFactory;
|
||||
use pocketmine\scheduler\AsyncTask;
|
||||
use pocketmine\world\format\Chunk;
|
||||
use pocketmine\world\format\io\FastChunkSerializer;
|
||||
use pocketmine\world\format\LightArray;
|
||||
use pocketmine\world\World;
|
||||
use function igbinary_serialize;
|
||||
use function igbinary_unserialize;
|
||||
|
||||
class LightPopulationTask extends AsyncTask{
|
||||
private const TLS_KEY_WORLD = "world";
|
||||
|
||||
public $chunk;
|
||||
|
||||
/** @var int */
|
||||
private $chunkX;
|
||||
/** @var int */
|
||||
private $chunkZ;
|
||||
|
||||
/** @var string */
|
||||
private $resultHeightMap;
|
||||
/** @var string */
|
||||
private $resultSkyLightArrays;
|
||||
/** @var string */
|
||||
private $resultBlockLightArrays;
|
||||
|
||||
public function __construct(World $world, Chunk $chunk){
|
||||
$this->storeLocal(self::TLS_KEY_WORLD, $world);
|
||||
[$this->chunkX, $this->chunkZ] = [$chunk->getX(), $chunk->getZ()];
|
||||
$this->chunk = FastChunkSerializer::serialize($chunk);
|
||||
}
|
||||
|
||||
@ -50,16 +66,41 @@ class LightPopulationTask extends AsyncTask{
|
||||
$chunk->populateSkyLight();
|
||||
$chunk->setLightPopulated();
|
||||
|
||||
$this->chunk = FastChunkSerializer::serialize($chunk);
|
||||
$this->resultHeightMap = igbinary_serialize($chunk->getHeightMapArray());
|
||||
$skyLightArrays = [];
|
||||
$blockLightArrays = [];
|
||||
foreach($chunk->getSubChunks() as $y => $subChunk){
|
||||
$skyLightArrays[$y] = $subChunk->getBlockSkyLightArray();
|
||||
$blockLightArrays[$y] = $subChunk->getBlockLightArray();
|
||||
}
|
||||
$this->resultSkyLightArrays = igbinary_serialize($skyLightArrays);
|
||||
$this->resultBlockLightArrays = igbinary_serialize($blockLightArrays);
|
||||
}
|
||||
|
||||
public function onCompletion() : void{
|
||||
/** @var World $world */
|
||||
$world = $this->fetchLocal(self::TLS_KEY_WORLD);
|
||||
if(!$world->isClosed()){
|
||||
if(!$world->isClosed() and $world->isChunkLoaded($this->chunkX, $this->chunkZ)){
|
||||
/** @var Chunk $chunk */
|
||||
$chunk = FastChunkSerializer::deserialize($this->chunk);
|
||||
$world->generateChunkCallback($chunk->getX(), $chunk->getZ(), $chunk);
|
||||
$chunk = $world->getChunk($this->chunkX, $this->chunkZ);
|
||||
//TODO: calculated light information might not be valid if the terrain changed during light calculation
|
||||
|
||||
/** @var int[] $heightMapArray */
|
||||
$heightMapArray = igbinary_unserialize($this->resultHeightMap);
|
||||
$chunk->setHeightMapArray($heightMapArray);
|
||||
|
||||
/** @var LightArray[] $skyLightArrays */
|
||||
$skyLightArrays = igbinary_unserialize($this->resultSkyLightArrays);
|
||||
/** @var LightArray[] $blockLightArrays */
|
||||
$blockLightArrays = igbinary_unserialize($this->resultBlockLightArrays);
|
||||
|
||||
foreach($skyLightArrays as $y => $array){
|
||||
$chunk->getSubChunk($y, true)->setBlockSkyLightArray($array);
|
||||
}
|
||||
foreach($blockLightArrays as $y => $array){
|
||||
$chunk->getSubChunk($y, true)->setBlockLightArray($array);
|
||||
}
|
||||
$chunk->setLightPopulated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user