From 83ddcce987bdc1b52256150cd42896ec82bca39d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 12 Nov 2022 16:57:35 +0000 Subject: [PATCH] World: Considerably simplify ticked chunk selection WARNING: This WILL have a performance impact on larger servers, but that's the price to pay for having crops actually grow. The old overengineered method for doing this was causing glacially slow crop growth, vanilla parity issues and really just didn't make much sense. This method is probably incorrect too, but it will at least produce visible results. --- resources/pocketmine.yml | 2 -- src/world/World.php | 30 +++++++++++++++--------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/resources/pocketmine.yml b/resources/pocketmine.yml index 4ad8ea9c0..ac60afe53 100644 --- a/resources/pocketmine.yml +++ b/resources/pocketmine.yml @@ -119,8 +119,6 @@ chunk-sending: spawn-radius: 4 chunk-ticking: - #Max amount of chunks processed each tick - per-tick: 40 #Radius of chunks around a player to tick tick-radius: 3 #Number of blocks inside ticking areas' subchunks that get ticked every tick. Higher values will accelerate events diff --git a/src/world/World.php b/src/world/World.php index f820a787f..e9441e9bb 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -66,6 +66,7 @@ use pocketmine\network\mcpe\protocol\BlockActorDataPacket; use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\types\BlockPosition; use pocketmine\network\mcpe\protocol\UpdateBlockPacket; +use pocketmine\player\ChunkSelector; use pocketmine\player\Player; use pocketmine\promise\Promise; use pocketmine\promise\PromiseResolver; @@ -317,7 +318,6 @@ class World implements ChunkManager{ private int $sleepTicks = 0; private int $chunkTickRadius; - private int $chunksPerTick; private int $tickedBlocksPerSubchunkPerTick = self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK; /** * @var true[] @@ -493,7 +493,11 @@ class World implements ChunkManager{ $cfg = $this->server->getConfigGroup(); $this->chunkTickRadius = min($this->server->getViewDistance(), max(1, $cfg->getPropertyInt("chunk-ticking.tick-radius", 4))); - $this->chunksPerTick = $cfg->getPropertyInt("chunk-ticking.per-tick", 40); + if($cfg->getPropertyInt("chunk-ticking.per-tick", 40) <= 0){ + //TODO: this needs l10n + $this->logger->warning("\"chunk-ticking.per-tick\" setting is deprecated, but you've used it to disable chunk ticking. Set \"chunk-ticking.tick-radius\" to 0 in \"pocketmine.yml\" instead."); + $this->chunkTickRadius = 0; + } $this->tickedBlocksPerSubchunkPerTick = $cfg->getPropertyInt("chunk-ticking.blocks-per-subchunk-per-tick", self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK); $this->maxConcurrentChunkPopulationTasks = $cfg->getPropertyInt("chunk-generation.population-queue-size", 2); @@ -1101,7 +1105,7 @@ class World implements ChunkManager{ } private function tickChunks() : void{ - if($this->chunksPerTick <= 0 || count($this->tickingLoaders) === 0){ + if($this->chunkTickRadius <= 0 || count($this->tickingLoaders) === 0){ return; } @@ -1110,19 +1114,15 @@ class World implements ChunkManager{ /** @var bool[] $chunkTickList chunkhash => dummy */ $chunkTickList = []; - $chunksPerLoader = min(200, max(1, (int) ((($this->chunksPerTick - count($this->tickingLoaders)) / count($this->tickingLoaders)) + 0.5))); - $randRange = 3 + $chunksPerLoader / 30; - $randRange = (int) ($randRange > $this->chunkTickRadius ? $this->chunkTickRadius : $randRange); - + $selector = new ChunkSelector(); foreach($this->tickingLoaders as $loader){ - $chunkX = (int) floor($loader->getX()) >> Chunk::COORD_BIT_SIZE; - $chunkZ = (int) floor($loader->getZ()) >> Chunk::COORD_BIT_SIZE; - - for($chunk = 0; $chunk < $chunksPerLoader; ++$chunk){ - $dx = mt_rand(-$randRange, $randRange); - $dz = mt_rand(-$randRange, $randRange); - $hash = World::chunkHash($dx + $chunkX, $dz + $chunkZ); - if(!isset($chunkTickList[$hash]) && isset($this->chunks[$hash]) && $this->isChunkTickable($dx + $chunkX, $dz + $chunkZ)){ + foreach($selector->selectChunks( + $this->chunkTickRadius, + (int) floor($loader->getX()) >> Chunk::COORD_BIT_SIZE, + (int) floor($loader->getZ()) >> Chunk::COORD_BIT_SIZE + ) as $hash){ + World::getXZ($hash, $chunkX, $chunkZ); + if(!isset($chunkTickList[$hash]) && isset($this->chunks[$hash]) && $this->isChunkTickable($chunkX, $chunkZ)){ $chunkTickList[$hash] = true; } }