From 8b3565b75db9877dfbf0dcd789e39fa5b57905e5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 2 Nov 2021 15:40:51 +0000 Subject: [PATCH] PopulationTask no longer depends on a World object this means it's now possible to test generation offline without too much hassle. World::generateChunkCallback() has been removed from public API. --- src/world/World.php | 19 +++++++- src/world/generator/PopulationTask.php | 66 +++++++++++++------------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/world/World.php b/src/world/World.php index a54065035..246799a85 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -2889,7 +2889,22 @@ class World implements ChunkManager{ } } - $task = new PopulationTask($this, $chunkX, $chunkZ, $this->loadChunk($chunkX, $chunkZ), $temporaryChunkLoader, $chunkPopulationLockId); + $centerChunk = $this->loadChunk($chunkX, $chunkZ); + $adjacentChunks = $this->getAdjacentChunks($chunkX, $chunkZ); + $task = new PopulationTask( + $this->worldId, + $chunkX, + $chunkZ, + $centerChunk, + $adjacentChunks, + function(Chunk $centerChunk, array $adjacentChunks) use ($chunkPopulationLockId, $chunkX, $chunkZ, $temporaryChunkLoader) : void{ + if(!$this->isLoaded()){ + return; + } + + $this->generateChunkCallback($chunkPopulationLockId, $chunkX, $chunkZ, $centerChunk, $adjacentChunks, $temporaryChunkLoader); + } + ); $workerId = $this->workerPool->selectWorker(); if(!isset($this->generatorRegisteredWorkers[$workerId])){ $this->registerGeneratorToWorker($workerId); @@ -2904,7 +2919,7 @@ class World implements ChunkManager{ * @param Chunk[] $adjacentChunks chunkHash => chunk * @phpstan-param array $adjacentChunks */ - public function generateChunkCallback(ChunkLockId $chunkLockId, int $x, int $z, Chunk $chunk, array $adjacentChunks, ChunkLoader $temporaryChunkLoader) : void{ + private function generateChunkCallback(ChunkLockId $chunkLockId, int $x, int $z, Chunk $chunk, array $adjacentChunks, ChunkLoader $temporaryChunkLoader) : void{ Timings::$generationCallback->startTiming(); $dirtyChunks = 0; diff --git a/src/world/generator/PopulationTask.php b/src/world/generator/PopulationTask.php index 55b612a8a..f1f2d3858 100644 --- a/src/world/generator/PopulationTask.php +++ b/src/world/generator/PopulationTask.php @@ -26,8 +26,6 @@ namespace pocketmine\world\generator; use pocketmine\data\bedrock\BiomeIds; use pocketmine\scheduler\AsyncTask; use pocketmine\utils\AssumptionFailedError; -use pocketmine\world\ChunkLoader; -use pocketmine\world\ChunkLockId; use pocketmine\world\format\BiomeArray; use pocketmine\world\format\Chunk; use pocketmine\world\format\io\FastChunkSerializer; @@ -37,10 +35,11 @@ use function array_map; use function igbinary_serialize; use function igbinary_unserialize; +/** + * @phpstan-type OnCompletion \Closure(Chunk $centerChunk, array $adjacentChunks) : void + */ class PopulationTask extends AsyncTask{ - private const TLS_KEY_WORLD = "world"; - private const TLS_KEY_CHUNK_LOADER = "chunkLoader"; - private const TLS_KEY_LOCK_ID = "chunkLockId"; + private const TLS_KEY_ON_COMPLETION = "onCompletion"; /** @var int */ public $worldId; @@ -54,20 +53,23 @@ class PopulationTask extends AsyncTask{ private string $adjacentChunks; - public function __construct(World $world, int $chunkX, int $chunkZ, ?Chunk $chunk, ChunkLoader $temporaryChunkLoader, ChunkLockId $chunkLockId){ - $this->worldId = $world->getId(); + /** + * @param Chunk[]|null[] $adjacentChunks + * @phpstan-param array $adjacentChunks + * @phpstan-param OnCompletion $onCompletion + */ + public function __construct(int $worldId, int $chunkX, int $chunkZ, ?Chunk $chunk, array $adjacentChunks, \Closure $onCompletion){ + $this->worldId = $worldId; $this->chunkX = $chunkX; $this->chunkZ = $chunkZ; $this->chunk = $chunk !== null ? FastChunkSerializer::serializeTerrain($chunk) : null; $this->adjacentChunks = igbinary_serialize(array_map( fn(?Chunk $c) => $c !== null ? FastChunkSerializer::serializeTerrain($c) : null, - $world->getAdjacentChunks($chunkX, $chunkZ) + $adjacentChunks )) ?? throw new AssumptionFailedError("igbinary_serialize() returned null"); - $this->storeLocal(self::TLS_KEY_WORLD, $world); - $this->storeLocal(self::TLS_KEY_CHUNK_LOADER, $temporaryChunkLoader); - $this->storeLocal(self::TLS_KEY_LOCK_ID, $chunkLockId); + $this->storeLocal(self::TLS_KEY_ON_COMPLETION, $onCompletion); } public function onRun() : void{ @@ -128,30 +130,28 @@ class PopulationTask extends AsyncTask{ } public function onCompletion() : void{ - /** @var World $world */ - $world = $this->fetchLocal(self::TLS_KEY_WORLD); - /** @var ChunkLoader $temporaryChunkLoader */ - $temporaryChunkLoader = $this->fetchLocal(self::TLS_KEY_CHUNK_LOADER); - /** @var ChunkLockId $lockId */ - $lockId = $this->fetchLocal(self::TLS_KEY_LOCK_ID); - if($world->isLoaded()){ - $chunk = $this->chunk !== null ? - FastChunkSerializer::deserializeTerrain($this->chunk) : - throw new AssumptionFailedError("Center chunk should never be null"); + /** + * @var \Closure $onCompletion + * @phpstan-var OnCompletion $onCompletion + */ + $onCompletion = $this->fetchLocal(self::TLS_KEY_ON_COMPLETION); - /** - * @var string[]|null[] $serialAdjacentChunks - * @phpstan-var array $serialAdjacentChunks - */ - $serialAdjacentChunks = igbinary_unserialize($this->adjacentChunks); - $adjacentChunks = []; - foreach($serialAdjacentChunks as $relativeChunkHash => $c){ - if($c !== null){ - $adjacentChunks[$relativeChunkHash] = FastChunkSerializer::deserializeTerrain($c); - } + $chunk = $this->chunk !== null ? + FastChunkSerializer::deserializeTerrain($this->chunk) : + throw new AssumptionFailedError("Center chunk should never be null"); + + /** + * @var string[]|null[] $serialAdjacentChunks + * @phpstan-var array $serialAdjacentChunks + */ + $serialAdjacentChunks = igbinary_unserialize($this->adjacentChunks); + $adjacentChunks = []; + foreach($serialAdjacentChunks as $relativeChunkHash => $c){ + if($c !== null){ + $adjacentChunks[$relativeChunkHash] = FastChunkSerializer::deserializeTerrain($c); } - - $world->generateChunkCallback($lockId, $this->chunkX, $this->chunkZ, $chunk, $adjacentChunks, $temporaryChunkLoader); } + + $onCompletion($chunk, $adjacentChunks); } }