mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-10 15:59:39 +00:00
Added PlayerInfo, Player is no longer accessible during PlayerPreLoginEvent
This commit is contained in:
parent
d2082c0383
commit
9c53b41851
@ -191,11 +191,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/** @var NetworkSession */
|
||||
protected $networkSession;
|
||||
|
||||
/** @var float */
|
||||
public $creationTime = 0;
|
||||
|
||||
/** @var bool */
|
||||
public $loggedIn = false;
|
||||
protected $loggedIn = false;
|
||||
|
||||
/** @var bool */
|
||||
public $spawned = false;
|
||||
@ -212,6 +209,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
protected $xuid = "";
|
||||
/** @var bool */
|
||||
protected $authenticated = false;
|
||||
/** @var PlayerInfo|null */
|
||||
protected $playerInfo = null;
|
||||
|
||||
protected $windowCnt = 2;
|
||||
/** @var int[] */
|
||||
@ -379,9 +378,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* as SimpleAuth for authentication. This is NOT SAFE anymore as this UUID is now what was given by the client, NOT
|
||||
* a server-computed UUID.)
|
||||
*
|
||||
* @return UUID|null
|
||||
* @return UUID
|
||||
*/
|
||||
public function getUniqueId() : ?UUID{
|
||||
public function getUniqueId() : UUID{
|
||||
return parent::getUniqueId();
|
||||
}
|
||||
|
||||
@ -693,8 +692,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->chunksPerTick = (int) $this->server->getProperty("chunk-sending.per-tick", 4);
|
||||
$this->spawnThreshold = (int) (($this->server->getProperty("chunk-sending.spawn-radius", 4) ** 2) * M_PI);
|
||||
|
||||
$this->creationTime = microtime(true);
|
||||
|
||||
$this->allowMovementCheats = (bool) $this->server->getProperty("player.anti-cheat.allow-movement-cheats", false);
|
||||
}
|
||||
|
||||
@ -1741,20 +1738,25 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
public function handleLogin(LoginPacket $packet) : bool{
|
||||
$this->username = TextFormat::clean($packet->username);
|
||||
$this->playerInfo = $packet->playerInfo;
|
||||
$this->username = TextFormat::clean($this->playerInfo->getUsername());
|
||||
$this->displayName = $this->username;
|
||||
$this->iusername = strtolower($this->username);
|
||||
$this->locale = $packet->locale;
|
||||
$this->randomClientId = $packet->clientId;
|
||||
$this->locale = $this->playerInfo->getLocale();
|
||||
$this->randomClientId = $this->playerInfo->getClientId();
|
||||
|
||||
$this->uuid = UUID::fromString($packet->clientUUID);
|
||||
$this->uuid = $this->playerInfo->getUuid();
|
||||
$this->rawUUID = $this->uuid->toBinary();
|
||||
$this->xuid = $packet->xuid;
|
||||
$this->xuid = $this->playerInfo->getXuid();
|
||||
|
||||
$this->setSkin($packet->skin);
|
||||
$this->setSkin($this->playerInfo->getSkin());
|
||||
|
||||
|
||||
$ev = new PlayerPreLoginEvent($this, $this->server->requiresAuthentication());
|
||||
$ev = new PlayerPreLoginEvent(
|
||||
$this->playerInfo,
|
||||
$this->networkSession->getIp(),
|
||||
$this->networkSession->getPort(),
|
||||
$this->server->requiresAuthentication()
|
||||
);
|
||||
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers()){
|
||||
$ev->setKickReason(PlayerPreLoginEvent::KICK_REASON_SERVER_FULL, "disconnectionScreen.serverFull");
|
||||
}
|
||||
|
97
src/pocketmine/PlayerInfo.php
Normal file
97
src/pocketmine/PlayerInfo.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\entity\Skin;
|
||||
use pocketmine\utils\UUID;
|
||||
|
||||
/**
|
||||
* Encapsulates data needed to create a player.
|
||||
*/
|
||||
class PlayerInfo{
|
||||
|
||||
/** @var string */
|
||||
private $username;
|
||||
/** @var UUID */
|
||||
private $uuid;
|
||||
/** @var Skin */
|
||||
private $skin;
|
||||
/** @var string */
|
||||
private $locale;
|
||||
/** @var string */
|
||||
private $xuid;
|
||||
/** @var int */
|
||||
private $clientId;
|
||||
|
||||
public function __construct(string $username, UUID $uuid, Skin $skin, string $locale, string $xuid, int $clientId){
|
||||
$this->username = $username;
|
||||
$this->uuid = $uuid;
|
||||
$this->skin = $skin;
|
||||
$this->locale = $locale;
|
||||
$this->xuid = $xuid;
|
||||
$this->clientId = $clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUsername() : string{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UUID
|
||||
*/
|
||||
public function getUuid() : UUID{
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Skin
|
||||
*/
|
||||
public function getSkin() : Skin{
|
||||
return $this->skin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale() : string{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getXuid() : string{
|
||||
return $this->xuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getClientId() : int{
|
||||
return $this->clientId;
|
||||
}
|
||||
}
|
@ -129,9 +129,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UUID|null
|
||||
* @return UUID
|
||||
*/
|
||||
public function getUniqueId() : ?UUID{
|
||||
public function getUniqueId() : UUID{
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\event\player;
|
||||
|
||||
use pocketmine\Player;
|
||||
use pocketmine\event\Event;
|
||||
use pocketmine\PlayerInfo;
|
||||
use function array_keys;
|
||||
|
||||
/**
|
||||
@ -35,11 +36,8 @@ use function array_keys;
|
||||
*
|
||||
* WARNING: Any information about the player CANNOT be trusted at this stage, because they are not authenticated and
|
||||
* could be a hacker posing as another player.
|
||||
*
|
||||
* WARNING: Due to internal bad architecture, the player is not fully constructed at this stage, and errors might occur
|
||||
* when calling API methods on the player. Tread with caution.
|
||||
*/
|
||||
class PlayerPreLoginEvent extends PlayerEvent{
|
||||
class PlayerPreLoginEvent extends Event{
|
||||
public const KICK_REASON_PLUGIN = 0;
|
||||
public const KICK_REASON_SERVER_FULL = 1;
|
||||
public const KICK_REASON_SERVER_WHITELISTED = 2;
|
||||
@ -52,6 +50,12 @@ class PlayerPreLoginEvent extends PlayerEvent{
|
||||
self::KICK_REASON_BANNED
|
||||
];
|
||||
|
||||
/** @var PlayerInfo */
|
||||
private $playerInfo;
|
||||
/** @var string */
|
||||
private $ip;
|
||||
/** @var int */
|
||||
private $port;
|
||||
/** @var bool */
|
||||
protected $authRequired;
|
||||
|
||||
@ -59,14 +63,43 @@ class PlayerPreLoginEvent extends PlayerEvent{
|
||||
protected $kickReasons = [];
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
* @param bool $authRequired
|
||||
* @param PlayerInfo $playerInfo
|
||||
* @param string $ip
|
||||
* @param int $port
|
||||
* @param bool $authRequired
|
||||
*/
|
||||
public function __construct(Player $player, bool $authRequired){
|
||||
$this->player = $player;
|
||||
public function __construct(PlayerInfo $playerInfo, string $ip, int $port, bool $authRequired){
|
||||
$this->playerInfo = $playerInfo;
|
||||
$this->ip = $ip;
|
||||
$this->port = $port;
|
||||
$this->authRequired = $authRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object containing self-proclaimed information about the connecting player.
|
||||
* WARNING: THE PLAYER IS NOT VERIFIED DURING THIS EVENT. At this point, it's unknown if the player is real or a
|
||||
* hacker.
|
||||
*
|
||||
* @return PlayerInfo
|
||||
*/
|
||||
public function getPlayerInfo() : PlayerInfo{
|
||||
return $this->playerInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIp() : string{
|
||||
return $this->ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPort() : int{
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -60,13 +60,13 @@ class LoginSessionHandler extends SessionHandler{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!Player::isValidUserName($packet->username)){
|
||||
if(!Player::isValidUserName($packet->playerInfo->getUsername())){
|
||||
$this->session->disconnect("disconnectionScreen.invalidName");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if($packet->skin === null or !$packet->skin->isValid()){
|
||||
if(!$packet->playerInfo->getSkin()->isValid()){
|
||||
$this->session->disconnect("disconnectionScreen.invalidSkin");
|
||||
|
||||
return true;
|
||||
|
@ -29,8 +29,10 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
use Particle\Validator\Validator;
|
||||
use pocketmine\entity\Skin;
|
||||
use pocketmine\network\mcpe\handler\SessionHandler;
|
||||
use pocketmine\PlayerInfo;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\UUID;
|
||||
use function array_filter;
|
||||
use function base64_decode;
|
||||
use function count;
|
||||
@ -44,6 +46,10 @@ class LoginPacket extends DataPacket{
|
||||
|
||||
public const EDITION_POCKET = 0;
|
||||
|
||||
public const I_USERNAME = 'displayName';
|
||||
public const I_UUID = 'identity';
|
||||
public const I_XUID = 'XUID';
|
||||
|
||||
public const I_CLIENT_RANDOM_ID = 'ClientRandomId';
|
||||
public const I_SERVER_ADDRESS = 'ServerAddress';
|
||||
public const I_LANGUAGE_CODE = 'LanguageCode';
|
||||
@ -54,27 +60,16 @@ class LoginPacket extends DataPacket{
|
||||
public const I_GEOMETRY_NAME = 'SkinGeometryName';
|
||||
public const I_GEOMETRY_DATA = 'SkinGeometry';
|
||||
|
||||
/** @var string */
|
||||
public $username;
|
||||
/** @var int */
|
||||
public $protocol;
|
||||
/** @var string */
|
||||
public $clientUUID;
|
||||
/** @var int */
|
||||
public $clientId;
|
||||
/** @var string */
|
||||
public $xuid;
|
||||
/** @var string */
|
||||
public $identityPublicKey;
|
||||
/** @var string */
|
||||
public $serverAddress;
|
||||
/** @var string */
|
||||
public $locale;
|
||||
/** @var Skin|null */
|
||||
public $skin;
|
||||
|
||||
/** @var PlayerInfo */
|
||||
public $playerInfo;
|
||||
|
||||
/** @var string[] array of encoded JWT */
|
||||
public $chainDataJwt = [];
|
||||
/** @var array|null extraData index of whichever JWT has it */
|
||||
public $extraData = null;
|
||||
/** @var string */
|
||||
public $clientDataJwt;
|
||||
/** @var array decoded payload of the clientData JWT */
|
||||
@ -138,8 +133,6 @@ class LoginPacket extends DataPacket{
|
||||
self::validate($vd, "chainData", $chainData);
|
||||
|
||||
$this->chainDataJwt = $chainData['chain'];
|
||||
|
||||
$hasExtraData = false;
|
||||
foreach($this->chainDataJwt as $k => $chain){
|
||||
//validate every chain element
|
||||
$claims = Utils::getJwtClaims($chain);
|
||||
@ -147,23 +140,20 @@ class LoginPacket extends DataPacket{
|
||||
if(!is_array($claims["extraData"])){
|
||||
throw new \UnexpectedValueException("'extraData' key should be an array");
|
||||
}
|
||||
if($hasExtraData){
|
||||
if($this->extraData !== null){
|
||||
throw new \UnexpectedValueException("Found 'extraData' more than once in chainData");
|
||||
}
|
||||
$hasExtraData = true;
|
||||
|
||||
$extraV = new Validator();
|
||||
$extraV->required('displayName')->string();
|
||||
$extraV->required('identity')->uuid();
|
||||
$extraV->required('XUID')->string()->digits()->allowEmpty(true);
|
||||
$extraV->required(self::I_USERNAME)->string();
|
||||
$extraV->required(self::I_UUID)->uuid();
|
||||
$extraV->required(self::I_XUID)->string()->digits()->allowEmpty(true);
|
||||
self::validate($extraV, "chain.$k.extraData", $claims['extraData']);
|
||||
|
||||
$this->username = $claims["extraData"]["displayName"];
|
||||
$this->clientUUID = $claims["extraData"]["identity"];
|
||||
$this->xuid = $claims["extraData"]["XUID"];
|
||||
$this->extraData = $claims['extraData'];
|
||||
}
|
||||
}
|
||||
if(!$hasExtraData){
|
||||
if($this->extraData === null){
|
||||
throw new \UnexpectedValueException("'extraData' not found in chain data");
|
||||
}
|
||||
|
||||
@ -184,16 +174,19 @@ class LoginPacket extends DataPacket{
|
||||
|
||||
$this->clientData = $clientData;
|
||||
|
||||
$this->clientId = $this->clientData[self::I_CLIENT_RANDOM_ID];
|
||||
$this->serverAddress = $this->clientData[self::I_SERVER_ADDRESS];
|
||||
$this->locale = $this->clientData[self::I_LANGUAGE_CODE];
|
||||
|
||||
$this->skin = new Skin(
|
||||
$this->clientData[self::I_SKIN_ID],
|
||||
base64_decode($this->clientData[self::I_SKIN_DATA]),
|
||||
base64_decode($this->clientData[self::I_CAPE_DATA]),
|
||||
$this->clientData[self::I_GEOMETRY_NAME],
|
||||
base64_decode($this->clientData[self::I_GEOMETRY_DATA])
|
||||
$this->playerInfo = new PlayerInfo(
|
||||
$this->extraData[self::I_USERNAME],
|
||||
UUID::fromString($this->extraData[self::I_UUID]),
|
||||
new Skin(
|
||||
$this->clientData[self::I_SKIN_ID],
|
||||
base64_decode($this->clientData[self::I_SKIN_DATA]),
|
||||
base64_decode($this->clientData[self::I_CAPE_DATA]),
|
||||
$this->clientData[self::I_GEOMETRY_NAME],
|
||||
base64_decode($this->clientData[self::I_GEOMETRY_DATA])
|
||||
),
|
||||
$this->clientData[self::I_LANGUAGE_CODE],
|
||||
$this->extraData[self::I_XUID],
|
||||
$this->clientData[self::I_CLIENT_RANDOM_ID]
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user