Player: cap maximum number of active generation requests

this fixes the horrible spotty chunk loading seen in https://twitter.com/dktapps/status/1456397007946461190?s=20.
In practice, this made chunks invisible on teleport for several tens of seconds after teleporting. Having a larger chunks-per-tick with large render distance compounded to worsen the problem.
It wasn't really noticeable on small render distances, but very obvious on large ones with fast chunk sending and slow generation.

This also fixes #4187 (at least to the extent that it works on PM3, anyway).
This commit is contained in:
Dylan K. Taylor 2021-11-05 15:09:42 +00:00
parent 579ef63663
commit 5107d0df4e
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -195,6 +195,11 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
* @phpstan-var array<int, UsedChunkStatus>
*/
protected array $usedChunks = [];
/**
* @var true[]
* @phpstan-var array<int, true>
*/
private array $activeChunkGenerationRequests = [];
/**
* @var true[] chunkHash => dummy
* @phpstan-var array<int, true>
@ -643,6 +648,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
}
$this->getNetworkSession()->stopUsingChunk($x, $z);
unset($this->usedChunks[$index]);
unset($this->activeChunkGenerationRequests[$index]);
}
$world->unregisterChunkLoader($this->chunkLoader, $x, $z);
$world->unregisterChunkListener($this, $x, $z);
@ -680,7 +686,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$count = 0;
$world = $this->getWorld();
foreach($this->loadQueue as $index => $distance){
if($count >= $this->chunksPerTick){
if($count >= $this->chunksPerTick || count($this->activeChunkGenerationRequests) >= $this->chunksPerTick){
break;
}
@ -692,6 +698,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
++$count;
$this->usedChunks[$index] = UsedChunkStatus::REQUESTED_GENERATION();
$this->activeChunkGenerationRequests[$index] = true;
unset($this->loadQueue[$index]);
$this->getWorld()->registerChunkLoader($this->chunkLoader, $X, $Z, true);
$this->getWorld()->registerChunkListener($this, $X, $Z);
@ -707,6 +714,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
//multiple callbacks for this player. In that case, only the first one matters.
return;
}
unset($this->activeChunkGenerationRequests[$index]);
$this->usedChunks[$index] = UsedChunkStatus::REQUESTED_SENDING();
$this->getNetworkSession()->startUsingChunk($X, $Z, function() use ($X, $Z, $index) : void{