World: added requestSafeSpawn() (async)

this simplifies usages of safe spawns, since the caller doesn't need to know which chunks will be needed for the spawn to be selected.

We'll need this in the future, because safe spawns may also get diverted horizontally as well as vertically, which might require loading adjacent chunks as well as the chunk the position is actually in.
This commit is contained in:
Dylan K. Taylor 2023-01-14 17:42:17 +00:00
parent 1bbe053848
commit 7d59bafd83
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -2836,6 +2836,36 @@ class World implements ChunkManager{
}
/**
* Requests a safe spawn position near the given position, or near the world's spawn position if not provided.
* Terrain near the position will be loaded or generated as needed.
*
* @return Promise Resolved to a Position object, or rejected if the world is unloaded.
* @phpstan-return Promise<Position>
*/
public function requestSafeSpawn(?Vector3 $spawn = null) : Promise{
$resolver = new PromiseResolver();
$spawn ??= $this->getSpawnLocation();
/*
* TODO: this relies on the assumption that getSafeSpawn() will only alter the Y coordinate of the provided
* position, which is currently OK, but might be a problem in the future.
*/
$this->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
function() use ($spawn, $resolver) : void{
$spawn = $this->getSafeSpawn($spawn);
$resolver->resolve($spawn);
},
function() use ($resolver) : void{
$resolver->reject();
}
);
return $resolver->getPromise();
}
/**
* Returns a safe spawn position near the given position, or near the world's spawn position if not provided.
* This function will throw an exception if the terrain is not already generated in advance.
*
* @throws WorldException if the terrain is not generated
*/
public function getSafeSpawn(?Vector3 $spawn = null) : Position{