mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-10 15:59:39 +00:00
Server: fixed getOfflinePlayerData() trying to load terrain (?!?!?!?), closes #2725
getOfflinePlayerData() will now return NULL if there is no stored data for a given player. The responsibility of checking the spawn point is now delegated to the Player, after it registers a chunk loader on its spawn chunk.
This commit is contained in:
parent
3e58708130
commit
ad6ae20d6b
@ -45,10 +45,8 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
public function __construct(Server $server, string $name){
|
public function __construct(Server $server, string $name){
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
if($this->server->hasOfflinePlayerData($this->name)){
|
|
||||||
$this->namedtag = $this->server->getOfflinePlayerData($this->name);
|
$this->namedtag = $this->server->getOfflinePlayerData($this->name);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public function isOnline() : bool{
|
public function isOnline() : bool{
|
||||||
return $this->getPlayer() !== null;
|
return $this->getPlayer() !== null;
|
||||||
|
@ -32,6 +32,7 @@ use pocketmine\command\CommandSender;
|
|||||||
use pocketmine\entity\effect\Effect;
|
use pocketmine\entity\effect\Effect;
|
||||||
use pocketmine\entity\effect\EffectInstance;
|
use pocketmine\entity\effect\EffectInstance;
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
|
use pocketmine\entity\EntityFactory;
|
||||||
use pocketmine\entity\Human;
|
use pocketmine\entity\Human;
|
||||||
use pocketmine\entity\object\ItemEntity;
|
use pocketmine\entity\object\ItemEntity;
|
||||||
use pocketmine\entity\projectile\Arrow;
|
use pocketmine\entity\projectile\Arrow;
|
||||||
@ -1847,21 +1848,37 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
public function _actuallyConstruct(){
|
public function _actuallyConstruct(){
|
||||||
$namedtag = $this->server->getOfflinePlayerData($this->username); //TODO: make this async
|
$namedtag = $this->server->getOfflinePlayerData($this->username); //TODO: make this async
|
||||||
|
|
||||||
if(($level = $this->server->getLevelManager()->getLevelByName($namedtag->getString("Level", "", true))) === null){
|
$spawnReset = false;
|
||||||
/** @var Level $level */
|
|
||||||
$level = $this->server->getLevelManager()->getDefaultLevel(); //TODO: default level may be null
|
|
||||||
|
|
||||||
$spawnLocation = $level->getSafeSpawn();
|
|
||||||
$namedtag->setTag(new ListTag("Pos", [
|
|
||||||
new DoubleTag("", $spawnLocation->x),
|
|
||||||
new DoubleTag("", $spawnLocation->y),
|
|
||||||
new DoubleTag("", $spawnLocation->z)
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if($namedtag !== null and ($level = $this->server->getLevelManager()->getLevelByName($namedtag->getString("Level", "", true))) !== null){
|
||||||
/** @var float[] $pos */
|
/** @var float[] $pos */
|
||||||
$pos = $namedtag->getListTag("Pos")->getAllValues();
|
$pos = $namedtag->getListTag("Pos")->getAllValues();
|
||||||
$level->registerChunkLoader($this, ((int) floor($pos[0])) >> 4, ((int) floor($pos[2])) >> 4, true);
|
$spawn = new Vector3($pos[0], $pos[1], $pos[2]);
|
||||||
|
}else{
|
||||||
|
$level = $this->server->getLevelManager()->getDefaultLevel(); //TODO: default level might be null
|
||||||
|
$spawn = $level->getSpawnLocation();
|
||||||
|
$spawnReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//load the spawn chunk so we can see the terrain
|
||||||
|
$level->registerChunkLoader($this, $spawn->getFloorX() >> 4, $spawn->getFloorZ() >> 4, true);
|
||||||
|
if($spawnReset){
|
||||||
|
$spawn = $level->getSafeSpawn($spawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($namedtag === null){
|
||||||
|
$namedtag = EntityFactory::createBaseNBT($spawn);
|
||||||
|
|
||||||
|
$namedtag->setByte("OnGround", 1); //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||||
|
//TODO: old code had a TODO for SpawnForced
|
||||||
|
|
||||||
|
}elseif($spawnReset){
|
||||||
|
$namedtag->setTag(new ListTag("Pos", [
|
||||||
|
new DoubleTag("", $spawn->x),
|
||||||
|
new DoubleTag("", $spawn->y),
|
||||||
|
new DoubleTag("", $spawn->z)
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
parent::__construct($level, $namedtag);
|
parent::__construct($level, $namedtag);
|
||||||
$ev = new PlayerLoginEvent($this, "Plugin reason");
|
$ev = new PlayerLoginEvent($this, "Plugin reason");
|
||||||
|
@ -648,12 +648,12 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*
|
*
|
||||||
* @return CompoundTag
|
* @return CompoundTag|null
|
||||||
*/
|
*/
|
||||||
public function getOfflinePlayerData(string $name) : CompoundTag{
|
public function getOfflinePlayerData(string $name) : ?CompoundTag{
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
$path = $this->getDataPath() . "players/";
|
$path = $this->getDataPath() . "players/";
|
||||||
if($this->shouldSavePlayerData()){
|
|
||||||
if(file_exists($path . "$name.dat")){
|
if(file_exists($path . "$name.dat")){
|
||||||
try{
|
try{
|
||||||
return (new BigEndianNbtSerializer())->readCompressed(file_get_contents($path . "$name.dat"));
|
return (new BigEndianNbtSerializer())->readCompressed(file_get_contents($path . "$name.dat"));
|
||||||
@ -662,17 +662,7 @@ class Server{
|
|||||||
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerNotFound", [$name]));
|
return null;
|
||||||
}
|
|
||||||
$spawn = $this->levelManager->getDefaultLevel()->getSafeSpawn();
|
|
||||||
|
|
||||||
$nbt = EntityFactory::createBaseNBT($spawn);
|
|
||||||
|
|
||||||
$nbt->setString("Level", $this->levelManager->getDefaultLevel()->getFolderName());
|
|
||||||
$nbt->setByte("OnGround", 1); //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
|
||||||
//TODO: old code had a TODO for SpawnForced
|
|
||||||
|
|
||||||
return $nbt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user