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

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{