mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-06 01:46:04 +00:00
Fixed resource packs/login sequence fail, added basic safety restrictions for packet sending before clients are logged in
close #452
This commit is contained in:
@ -1063,6 +1063,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return false;
|
||||
}
|
||||
|
||||
//Basic safety restriction. TODO: improve this
|
||||
if(!$this->loggedIn and !$packet->canBeSentBeforeLogin()){
|
||||
throw new \InvalidArgumentException("Attempted to send " . get_class($packet) . " to " . $this->getName() . " too early");
|
||||
}
|
||||
|
||||
$timings = Timings::getSendDataPacketTimings($packet);
|
||||
$timings->startTiming();
|
||||
|
||||
@ -1096,6 +1101,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return false;
|
||||
}
|
||||
|
||||
//Basic safety restriction. TODO: improve this
|
||||
if(!$this->loggedIn and !$packet->canBeSentBeforeLogin()){
|
||||
throw new \InvalidArgumentException("Attempted to send " . get_class($packet) . " to " . $this->getName() . " too early");
|
||||
}
|
||||
|
||||
$timings = Timings::getSendDataPacketTimings($packet);
|
||||
$timings->startTiming();
|
||||
$this->server->getPluginManager()->callEvent($ev = new DataPacketSendEvent($this, $packet));
|
||||
@ -1734,38 +1744,40 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
if($p !== $this and strtolower($p->getName()) === strtolower($this->getName())){
|
||||
if($p->kick("logged in from another location") === false){
|
||||
$this->close($this->getLeaveMessage(), "Logged in from another location");
|
||||
|
||||
return;
|
||||
}
|
||||
}elseif($p->loggedIn and $this->getUniqueId()->equals($p->getUniqueId())){
|
||||
if($p->kick("logged in from another location") === false){
|
||||
$this->close($this->getLeaveMessage(), "Logged in from another location");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$nbt = $this->server->getOfflinePlayerData($this->username);
|
||||
$this->namedtag = $this->server->getOfflinePlayerData($this->username);
|
||||
|
||||
$this->playedBefore = ($nbt["lastPlayed"] - $nbt["firstPlayed"]) > 1; // microtime(true) - microtime(true) may have less than one millisecond difference
|
||||
if(!isset($nbt->NameTag)){
|
||||
$nbt->NameTag = new StringTag("NameTag", $this->username);
|
||||
$this->playedBefore = ($this->namedtag["lastPlayed"] - $this->namedtag["firstPlayed"]) > 1; // microtime(true) - microtime(true) may have less than one millisecond difference
|
||||
if(!isset($this->namedtag->NameTag)){
|
||||
$this->namedtag->NameTag = new StringTag("NameTag", $this->username);
|
||||
}else{
|
||||
$nbt["NameTag"] = $this->username;
|
||||
$this->namedtag["NameTag"] = $this->username;
|
||||
}
|
||||
$this->gamemode = $nbt["playerGameType"] & 0x03;
|
||||
$this->gamemode = $this->namedtag["playerGameType"] & 0x03;
|
||||
if($this->server->getForceGamemode()){
|
||||
$this->gamemode = $this->server->getGamemode();
|
||||
$nbt->playerGameType = new IntTag("playerGameType", $this->gamemode);
|
||||
$this->namedtag->playerGameType = new IntTag("playerGameType", $this->gamemode);
|
||||
}
|
||||
|
||||
$this->allowFlight = (bool) ($this->gamemode & 0x01);
|
||||
|
||||
if(($level = $this->server->getLevelByName($nbt["Level"])) === null){
|
||||
if(($level = $this->server->getLevelByName($this->namedtag["Level"])) === null){
|
||||
$this->setLevel($this->server->getDefaultLevel());
|
||||
$nbt["Level"] = $this->level->getName();
|
||||
$nbt["Pos"][0] = $this->level->getSpawnLocation()->x;
|
||||
$nbt["Pos"][1] = $this->level->getSpawnLocation()->y;
|
||||
$nbt["Pos"][2] = $this->level->getSpawnLocation()->z;
|
||||
$this->namedtag["Level"] = $this->level->getName();
|
||||
$this->namedtag["Pos"][0] = $this->level->getSpawnLocation()->x;
|
||||
$this->namedtag["Pos"][1] = $this->level->getSpawnLocation()->y;
|
||||
$this->namedtag["Pos"][2] = $this->level->getSpawnLocation()->z;
|
||||
}else{
|
||||
$this->setLevel($level);
|
||||
}
|
||||
@ -1773,19 +1785,29 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->achievements = [];
|
||||
|
||||
/** @var ByteTag $achievement */
|
||||
foreach($nbt->Achievements as $achievement){
|
||||
foreach($this->namedtag->Achievements as $achievement){
|
||||
$this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false;
|
||||
}
|
||||
|
||||
$nbt->lastPlayed = new LongTag("lastPlayed", floor(microtime(true) * 1000));
|
||||
$this->namedtag->lastPlayed = new LongTag("lastPlayed", floor(microtime(true) * 1000));
|
||||
if($this->server->getAutoSave()){
|
||||
$this->server->saveOfflinePlayerData($this->username, $nbt, true);
|
||||
$this->server->saveOfflinePlayerData($this->username, $this->namedtag, true);
|
||||
}
|
||||
|
||||
parent::__construct($this->level, $nbt);
|
||||
$this->sendPlayStatus(PlayStatusPacket::LOGIN_SUCCESS);
|
||||
|
||||
$this->loggedIn = true;
|
||||
$this->server->addOnlinePlayer($this);
|
||||
|
||||
$pk = new ResourcePacksInfoPacket();
|
||||
$manager = $this->server->getResourceManager();
|
||||
$pk->resourcePackEntries = $manager->getResourceStack();
|
||||
$pk->mustAccept = $manager->resourcePacksRequired();
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
protected function completeLoginSequence(){
|
||||
parent::__construct($this->level, $this->namedtag);
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
|
||||
if($ev->isCancelled()){
|
||||
$this->close($this->getLeaveMessage(), $ev->getKickMessage());
|
||||
@ -1910,13 +1932,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
//TODO: add JWT verification, add encryption
|
||||
|
||||
$this->sendPlayStatus(PlayStatusPacket::LOGIN_SUCCESS);
|
||||
|
||||
$pk = new ResourcePacksInfoPacket();
|
||||
$manager = $this->server->getResourceManager();
|
||||
$pk->resourcePackEntries = $manager->getResourceStack();
|
||||
$pk->mustAccept = $manager->resourcePacksRequired();
|
||||
$this->dataPacket($pk);
|
||||
$this->processLogin();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1989,7 +2005,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->dataPacket($pk);
|
||||
break;
|
||||
case ResourcePackClientResponsePacket::STATUS_COMPLETED:
|
||||
$this->processLogin();
|
||||
$this->completeLoginSequence();
|
||||
break;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user