mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-12 22:45:28 +00:00
Make use of World::requestSafeSpawn()
This commit is contained in:
parent
7d59bafd83
commit
289e86e899
@ -106,12 +106,12 @@ use pocketmine\utils\SignalHandler;
|
|||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\world\format\Chunk;
|
|
||||||
use pocketmine\world\format\io\WorldProviderManager;
|
use pocketmine\world\format\io\WorldProviderManager;
|
||||||
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
||||||
use pocketmine\world\generator\Generator;
|
use pocketmine\world\generator\Generator;
|
||||||
use pocketmine\world\generator\GeneratorManager;
|
use pocketmine\world\generator\GeneratorManager;
|
||||||
use pocketmine\world\generator\InvalidGeneratorOptionsException;
|
use pocketmine\world\generator\InvalidGeneratorOptionsException;
|
||||||
|
use pocketmine\world\Position;
|
||||||
use pocketmine\world\World;
|
use pocketmine\world\World;
|
||||||
use pocketmine\world\WorldCreationOptions;
|
use pocketmine\world\WorldCreationOptions;
|
||||||
use pocketmine\world\WorldManager;
|
use pocketmine\world\WorldManager;
|
||||||
@ -554,49 +554,45 @@ class Server{
|
|||||||
|
|
||||||
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString(Player::TAG_LEVEL, ""))) !== null){
|
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString(Player::TAG_LEVEL, ""))) !== null){
|
||||||
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
|
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
|
||||||
$spawn = $playerPos->asVector3();
|
|
||||||
}else{
|
}else{
|
||||||
$world = $this->worldManager->getDefaultWorld();
|
$world = $this->worldManager->getDefaultWorld();
|
||||||
if($world === null){
|
if($world === null){
|
||||||
throw new AssumptionFailedError("Default world should always be loaded");
|
throw new AssumptionFailedError("Default world should always be loaded");
|
||||||
}
|
}
|
||||||
$playerPos = null;
|
$playerPos = null;
|
||||||
$spawn = $world->getSpawnLocation();
|
|
||||||
}
|
}
|
||||||
/** @phpstan-var PromiseResolver<Player> $playerPromiseResolver */
|
/** @phpstan-var PromiseResolver<Player> $playerPromiseResolver */
|
||||||
$playerPromiseResolver = new PromiseResolver();
|
$playerPromiseResolver = new PromiseResolver();
|
||||||
$world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
|
|
||||||
function() use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
|
|
||||||
if(!$session->isConnected()){
|
|
||||||
$playerPromiseResolver->reject();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stick with the original spawn at the time of generation request, even if it changed since then.
|
$createPlayer = function(Location $location) use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $offlinePlayerData) : void{
|
||||||
* This is because we know for sure that that chunk will be generated, but the one at the new location
|
$player = new $class($this, $session, $playerInfo, $authenticated, $location, $offlinePlayerData);
|
||||||
* might not be, and it would be much more complex to go back and redo the whole thing.
|
if(!$player->hasPlayedBefore()){
|
||||||
*
|
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||||
* TODO: this relies on the assumption that getSafeSpawn() will only alter the Y coordinate of the
|
|
||||||
* provided position. If this assumption is broken, we'll start seeing crashes in here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Player::__construct()
|
|
||||||
* @var Player $player
|
|
||||||
*/
|
|
||||||
$player = new $class($this, $session, $playerInfo, $authenticated, $playerPos ?? Location::fromObject($world->getSafeSpawn($spawn), $world), $offlinePlayerData);
|
|
||||||
if(!$player->hasPlayedBefore()){
|
|
||||||
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
|
||||||
}
|
|
||||||
$playerPromiseResolver->resolve($player);
|
|
||||||
},
|
|
||||||
static function() use ($playerPromiseResolver, $session) : void{
|
|
||||||
if($session->isConnected()){
|
|
||||||
$session->disconnect("Spawn terrain generation failed");
|
|
||||||
}
|
|
||||||
$playerPromiseResolver->reject();
|
|
||||||
}
|
}
|
||||||
);
|
$playerPromiseResolver->resolve($player);
|
||||||
|
};
|
||||||
|
|
||||||
|
if($playerPos === null){ //new player or no valid position due to world not being loaded
|
||||||
|
$world->requestSafeSpawn()->onCompletion(
|
||||||
|
function(Position $spawn) use ($createPlayer, $playerPromiseResolver, $session, $world) : void{
|
||||||
|
if(!$session->isConnected()){
|
||||||
|
$playerPromiseResolver->reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$createPlayer(Location::fromObject($spawn, $world));
|
||||||
|
},
|
||||||
|
function() use ($playerPromiseResolver, $session) : void{
|
||||||
|
if($session->isConnected()){
|
||||||
|
//TODO: this needs to be localized - this might be reached if the spawn world was unloaded while the player was logging in
|
||||||
|
$session->disconnect("Failed to find a safe spawn location");
|
||||||
|
}
|
||||||
|
$playerPromiseResolver->reject();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}else{ //returning player with a valid position - safe spawn not required
|
||||||
|
$createPlayer($playerPos);
|
||||||
|
}
|
||||||
|
|
||||||
return $playerPromiseResolver->getPromise();
|
return $playerPromiseResolver->getPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2311,16 +2311,15 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
|||||||
}
|
}
|
||||||
$this->respawnLocked = true;
|
$this->respawnLocked = true;
|
||||||
|
|
||||||
$this->logger->debug("Waiting for spawn terrain generation for respawn");
|
$this->logger->debug("Waiting for safe respawn position to be located");
|
||||||
$spawn = $this->getSpawn();
|
$spawn = $this->getSpawn();
|
||||||
$spawn->getWorld()->orderChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
|
$spawn->getWorld()->requestSafeSpawn($spawn)->onCompletion(
|
||||||
function() use ($spawn) : void{
|
function(Position $safeSpawn) : void{
|
||||||
if(!$this->isConnected()){
|
if(!$this->isConnected()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->logger->debug("Spawn terrain generation done, completing respawn");
|
$this->logger->debug("Respawn position located, completing respawn");
|
||||||
$spawn = $spawn->getWorld()->getSafeSpawn($spawn);
|
$ev = new PlayerRespawnEvent($this, $safeSpawn);
|
||||||
$ev = new PlayerRespawnEvent($this, $spawn);
|
|
||||||
$ev->call();
|
$ev->call();
|
||||||
|
|
||||||
$realSpawn = Position::fromObject($ev->getRespawnPosition()->add(0.5, 0, 0.5), $ev->getRespawnPosition()->getWorld());
|
$realSpawn = Position::fromObject($ev->getRespawnPosition()->add(0.5, 0, 0.5), $ev->getRespawnPosition()->getWorld());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user