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,9 +45,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
public function __construct(Server $server, string $name){
|
||||
$this->server = $server;
|
||||
$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{
|
||||
|
@ -32,6 +32,7 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\entity\effect\Effect;
|
||||
use pocketmine\entity\effect\EffectInstance;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\EntityFactory;
|
||||
use pocketmine\entity\Human;
|
||||
use pocketmine\entity\object\ItemEntity;
|
||||
use pocketmine\entity\projectile\Arrow;
|
||||
@ -1847,21 +1848,37 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
public function _actuallyConstruct(){
|
||||
$namedtag = $this->server->getOfflinePlayerData($this->username); //TODO: make this async
|
||||
|
||||
if(($level = $this->server->getLevelManager()->getLevelByName($namedtag->getString("Level", "", true))) === null){
|
||||
/** @var Level $level */
|
||||
$level = $this->server->getLevelManager()->getDefaultLevel(); //TODO: default level may be null
|
||||
$spawnReset = false;
|
||||
|
||||
$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 */
|
||||
$pos = $namedtag->getListTag("Pos")->getAllValues();
|
||||
$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;
|
||||
}
|
||||
|
||||
/** @var float[] $pos */
|
||||
$pos = $namedtag->getListTag("Pos")->getAllValues();
|
||||
$level->registerChunkLoader($this, ((int) floor($pos[0])) >> 4, ((int) floor($pos[2])) >> 4, 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);
|
||||
$ev = new PlayerLoginEvent($this, "Plugin reason");
|
||||
|
@ -648,31 +648,21 @@ class Server{
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return CompoundTag
|
||||
* @return CompoundTag|null
|
||||
*/
|
||||
public function getOfflinePlayerData(string $name) : CompoundTag{
|
||||
public function getOfflinePlayerData(string $name) : ?CompoundTag{
|
||||
$name = strtolower($name);
|
||||
$path = $this->getDataPath() . "players/";
|
||||
if($this->shouldSavePlayerData()){
|
||||
if(file_exists($path . "$name.dat")){
|
||||
try{
|
||||
return (new BigEndianNbtSerializer())->readCompressed(file_get_contents($path . "$name.dat"));
|
||||
}catch(NbtDataException $e){ //zlib decode error / corrupt data
|
||||
rename($path . "$name.dat", $path . "$name.dat.bak");
|
||||
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
||||
}
|
||||
|
||||
if(file_exists($path . "$name.dat")){
|
||||
try{
|
||||
return (new BigEndianNbtSerializer())->readCompressed(file_get_contents($path . "$name.dat"));
|
||||
}catch(NbtDataException $e){ //zlib decode error / corrupt data
|
||||
rename($path . "$name.dat", $path . "$name.dat.bak");
|
||||
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
||||
}
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerNotFound", [$name]));
|
||||
}
|
||||
$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;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user