Skip to content

Commit

Permalink
ChunkSelector: Improve algorithm to send chunks in proper circles, in…
Browse files Browse the repository at this point in the history
…stead of squares

this ensures that the edge of loaded terain is always the same distance
away in any direction. This also means that when flying parallel to X or
Z axes, you now have about 12% more chunks directly in front of you,
instead of to your left and right, which gives the impression that
chunks are loading faster (they aren't, they are just being ordered in a
more sensible way).
  • Loading branch information
dktapps committed Nov 6, 2021
1 parent 07b1cff commit dbf9a33
Showing 1 changed file with 35 additions and 24 deletions.
59 changes: 35 additions & 24 deletions src/player/ChunkSelector.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
namespace pocketmine\player;

use pocketmine\world\World;
use const M_SQRT2;

//TODO: turn this into an interface?
final class ChunkSelector{
Expand All @@ -33,34 +34,44 @@ final class ChunkSelector{
* @phpstan-return \Generator<int, int, void, void>
*/
public function selectChunks(int $radius, int $centerX, int $centerZ) : \Generator{
$radiusSquared = $radius ** 2;
for($subRadius = 0; $subRadius < $radius; $subRadius++){
$subRadiusSquared = $subRadius ** 2;
$nextSubRadiusSquared = ($subRadius + 1) ** 2;
$minX = (int) ($subRadius / M_SQRT2);

for($x = 0; $x < $radius; ++$x){
for($z = 0; $z <= $x; ++$z){
if(($x ** 2 + $z ** 2) > $radiusSquared){
break; //skip to next band
}
$lastZ = 0;

for($x = $subRadius; $x >= $minX; --$x){
for($z = $lastZ; $z <= $x; ++$z){
$distanceSquared = ($x ** 2 + $z ** 2);
if($distanceSquared < $subRadiusSquared){
continue;
}elseif($distanceSquared >= $nextSubRadiusSquared){
break; //skip to next X
}

//If the chunk is in the radius, others at the same offsets in different quadrants are also guaranteed to be.
$lastZ = $z;
//If the chunk is in the radius, others at the same offsets in different quadrants are also guaranteed to be.

/* Top right quadrant */
yield World::chunkHash($centerX + $x, $centerZ + $z);
/* Top left quadrant */
yield World::chunkHash($centerX - $x - 1, $centerZ + $z);
/* Bottom right quadrant */
yield World::chunkHash($centerX + $x, $centerZ - $z - 1);
/* Bottom left quadrant */
yield World::chunkHash($centerX - $x - 1, $centerZ - $z - 1);
/* Top right quadrant */
yield World::chunkHash($centerX + $x, $centerZ + $z);
/* Top left quadrant */
yield World::chunkHash($centerX - $x - 1, $centerZ + $z);
/* Bottom right quadrant */
yield World::chunkHash($centerX + $x, $centerZ - $z - 1);
/* Bottom left quadrant */
yield World::chunkHash($centerX - $x - 1, $centerZ - $z - 1);

if($x !== $z){
/* Top right quadrant mirror */
yield World::chunkHash($centerX + $z, $centerZ + $x);
/* Top left quadrant mirror */
yield World::chunkHash($centerX - $z - 1, $centerZ + $x);
/* Bottom right quadrant mirror */
yield World::chunkHash($centerX + $z, $centerZ - $x - 1);
/* Bottom left quadrant mirror */
yield World::chunkHash($centerX - $z - 1, $centerZ - $x - 1);
if($x !== $z){
/* Top right quadrant mirror */
yield World::chunkHash($centerX + $z, $centerZ + $x);
/* Top left quadrant mirror */
yield World::chunkHash($centerX - $z - 1, $centerZ + $x);
/* Bottom right quadrant mirror */
yield World::chunkHash($centerX + $z, $centerZ - $x - 1);
/* Bottom left quadrant mirror */
yield World::chunkHash($centerX - $z - 1, $centerZ - $x - 1);
}
}
}
}
Expand Down

0 comments on commit dbf9a33

Please sign in to comment.