mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-11 16:29:40 +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 */
|
/** @var NetworkSession */
|
||||||
protected $networkSession;
|
protected $networkSession;
|
||||||
|
|
||||||
/** @var float */
|
|
||||||
public $creationTime = 0;
|
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $loggedIn = false;
|
protected $loggedIn = false;
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $spawned = false;
|
public $spawned = false;
|
||||||
@ -212,6 +209,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
protected $xuid = "";
|
protected $xuid = "";
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $authenticated = false;
|
protected $authenticated = false;
|
||||||
|
/** @var PlayerInfo|null */
|
||||||
|
protected $playerInfo = null;
|
||||||
|
|
||||||
protected $windowCnt = 2;
|
protected $windowCnt = 2;
|
||||||
/** @var int[] */
|
/** @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
|
* 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.)
|
* a server-computed UUID.)
|
||||||
*
|
*
|
||||||
* @return UUID|null
|
* @return UUID
|
||||||
*/
|
*/
|
||||||
public function getUniqueId() : ?UUID{
|
public function getUniqueId() : UUID{
|
||||||
return parent::getUniqueId();
|
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->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->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);
|
$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{
|
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->displayName = $this->username;
|
||||||
$this->iusername = strtolower($this->username);
|
$this->iusername = strtolower($this->username);
|
||||||
$this->locale = $packet->locale;
|
$this->locale = $this->playerInfo->getLocale();
|
||||||
$this->randomClientId = $packet->clientId;
|
$this->randomClientId = $this->playerInfo->getClientId();
|
||||||
|
|
||||||
$this->uuid = UUID::fromString($packet->clientUUID);
|
$this->uuid = $this->playerInfo->getUuid();
|
||||||
$this->rawUUID = $this->uuid->toBinary();
|
$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(
|
||||||
$ev = new PlayerPreLoginEvent($this, $this->server->requiresAuthentication());
|
$this->playerInfo,
|
||||||
|
$this->networkSession->getIp(),
|
||||||
|
$this->networkSession->getPort(),
|
||||||
|
$this->server->requiresAuthentication()
|
||||||
|
);
|
||||||
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers()){
|
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers()){
|
||||||
$ev->setKickReason(PlayerPreLoginEvent::KICK_REASON_SERVER_FULL, "disconnectionScreen.serverFull");
|
$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;
|
return $this->uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\event\player;
|
namespace pocketmine\event\player;
|
||||||
|
|
||||||
use pocketmine\Player;
|
use pocketmine\event\Event;
|
||||||
|
use pocketmine\PlayerInfo;
|
||||||
use function array_keys;
|
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
|
* 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.
|
* 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_PLUGIN = 0;
|
||||||
public const KICK_REASON_SERVER_FULL = 1;
|
public const KICK_REASON_SERVER_FULL = 1;
|
||||||
public const KICK_REASON_SERVER_WHITELISTED = 2;
|
public const KICK_REASON_SERVER_WHITELISTED = 2;
|
||||||
@ -52,6 +50,12 @@ class PlayerPreLoginEvent extends PlayerEvent{
|
|||||||
self::KICK_REASON_BANNED
|
self::KICK_REASON_BANNED
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** @var PlayerInfo */
|
||||||
|
private $playerInfo;
|
||||||
|
/** @var string */
|
||||||
|
private $ip;
|
||||||
|
/** @var int */
|
||||||
|
private $port;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $authRequired;
|
protected $authRequired;
|
||||||
|
|
||||||
@ -59,14 +63,43 @@ class PlayerPreLoginEvent extends PlayerEvent{
|
|||||||
protected $kickReasons = [];
|
protected $kickReasons = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player $player
|
* @param PlayerInfo $playerInfo
|
||||||
|
* @param string $ip
|
||||||
|
* @param int $port
|
||||||
* @param bool $authRequired
|
* @param bool $authRequired
|
||||||
*/
|
*/
|
||||||
public function __construct(Player $player, bool $authRequired){
|
public function __construct(PlayerInfo $playerInfo, string $ip, int $port, bool $authRequired){
|
||||||
$this->player = $player;
|
$this->playerInfo = $playerInfo;
|
||||||
|
$this->ip = $ip;
|
||||||
|
$this->port = $port;
|
||||||
$this->authRequired = $authRequired;
|
$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
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -60,13 +60,13 @@ class LoginSessionHandler extends SessionHandler{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Player::isValidUserName($packet->username)){
|
if(!Player::isValidUserName($packet->playerInfo->getUsername())){
|
||||||
$this->session->disconnect("disconnectionScreen.invalidName");
|
$this->session->disconnect("disconnectionScreen.invalidName");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($packet->skin === null or !$packet->skin->isValid()){
|
if(!$packet->playerInfo->getSkin()->isValid()){
|
||||||
$this->session->disconnect("disconnectionScreen.invalidSkin");
|
$this->session->disconnect("disconnectionScreen.invalidSkin");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -29,8 +29,10 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
use Particle\Validator\Validator;
|
use Particle\Validator\Validator;
|
||||||
use pocketmine\entity\Skin;
|
use pocketmine\entity\Skin;
|
||||||
use pocketmine\network\mcpe\handler\SessionHandler;
|
use pocketmine\network\mcpe\handler\SessionHandler;
|
||||||
|
use pocketmine\PlayerInfo;
|
||||||
use pocketmine\utils\BinaryStream;
|
use pocketmine\utils\BinaryStream;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
|
use pocketmine\utils\UUID;
|
||||||
use function array_filter;
|
use function array_filter;
|
||||||
use function base64_decode;
|
use function base64_decode;
|
||||||
use function count;
|
use function count;
|
||||||
@ -44,6 +46,10 @@ class LoginPacket extends DataPacket{
|
|||||||
|
|
||||||
public const EDITION_POCKET = 0;
|
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_CLIENT_RANDOM_ID = 'ClientRandomId';
|
||||||
public const I_SERVER_ADDRESS = 'ServerAddress';
|
public const I_SERVER_ADDRESS = 'ServerAddress';
|
||||||
public const I_LANGUAGE_CODE = 'LanguageCode';
|
public const I_LANGUAGE_CODE = 'LanguageCode';
|
||||||
@ -54,27 +60,16 @@ class LoginPacket extends DataPacket{
|
|||||||
public const I_GEOMETRY_NAME = 'SkinGeometryName';
|
public const I_GEOMETRY_NAME = 'SkinGeometryName';
|
||||||
public const I_GEOMETRY_DATA = 'SkinGeometry';
|
public const I_GEOMETRY_DATA = 'SkinGeometry';
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
public $username;
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $protocol;
|
public $protocol;
|
||||||
/** @var string */
|
|
||||||
public $clientUUID;
|
/** @var PlayerInfo */
|
||||||
/** @var int */
|
public $playerInfo;
|
||||||
public $clientId;
|
|
||||||
/** @var string */
|
|
||||||
public $xuid;
|
|
||||||
/** @var string */
|
|
||||||
public $identityPublicKey;
|
|
||||||
/** @var string */
|
|
||||||
public $serverAddress;
|
|
||||||
/** @var string */
|
|
||||||
public $locale;
|
|
||||||
/** @var Skin|null */
|
|
||||||
public $skin;
|
|
||||||
|
|
||||||
/** @var string[] array of encoded JWT */
|
/** @var string[] array of encoded JWT */
|
||||||
public $chainDataJwt = [];
|
public $chainDataJwt = [];
|
||||||
|
/** @var array|null extraData index of whichever JWT has it */
|
||||||
|
public $extraData = null;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $clientDataJwt;
|
public $clientDataJwt;
|
||||||
/** @var array decoded payload of the clientData JWT */
|
/** @var array decoded payload of the clientData JWT */
|
||||||
@ -138,8 +133,6 @@ class LoginPacket extends DataPacket{
|
|||||||
self::validate($vd, "chainData", $chainData);
|
self::validate($vd, "chainData", $chainData);
|
||||||
|
|
||||||
$this->chainDataJwt = $chainData['chain'];
|
$this->chainDataJwt = $chainData['chain'];
|
||||||
|
|
||||||
$hasExtraData = false;
|
|
||||||
foreach($this->chainDataJwt as $k => $chain){
|
foreach($this->chainDataJwt as $k => $chain){
|
||||||
//validate every chain element
|
//validate every chain element
|
||||||
$claims = Utils::getJwtClaims($chain);
|
$claims = Utils::getJwtClaims($chain);
|
||||||
@ -147,23 +140,20 @@ class LoginPacket extends DataPacket{
|
|||||||
if(!is_array($claims["extraData"])){
|
if(!is_array($claims["extraData"])){
|
||||||
throw new \UnexpectedValueException("'extraData' key should be an array");
|
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");
|
throw new \UnexpectedValueException("Found 'extraData' more than once in chainData");
|
||||||
}
|
}
|
||||||
$hasExtraData = true;
|
|
||||||
|
|
||||||
$extraV = new Validator();
|
$extraV = new Validator();
|
||||||
$extraV->required('displayName')->string();
|
$extraV->required(self::I_USERNAME)->string();
|
||||||
$extraV->required('identity')->uuid();
|
$extraV->required(self::I_UUID)->uuid();
|
||||||
$extraV->required('XUID')->string()->digits()->allowEmpty(true);
|
$extraV->required(self::I_XUID)->string()->digits()->allowEmpty(true);
|
||||||
self::validate($extraV, "chain.$k.extraData", $claims['extraData']);
|
self::validate($extraV, "chain.$k.extraData", $claims['extraData']);
|
||||||
|
|
||||||
$this->username = $claims["extraData"]["displayName"];
|
$this->extraData = $claims['extraData'];
|
||||||
$this->clientUUID = $claims["extraData"]["identity"];
|
|
||||||
$this->xuid = $claims["extraData"]["XUID"];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!$hasExtraData){
|
if($this->extraData === null){
|
||||||
throw new \UnexpectedValueException("'extraData' not found in chain data");
|
throw new \UnexpectedValueException("'extraData' not found in chain data");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,16 +174,19 @@ class LoginPacket extends DataPacket{
|
|||||||
|
|
||||||
$this->clientData = $clientData;
|
$this->clientData = $clientData;
|
||||||
|
|
||||||
$this->clientId = $this->clientData[self::I_CLIENT_RANDOM_ID];
|
$this->playerInfo = new PlayerInfo(
|
||||||
$this->serverAddress = $this->clientData[self::I_SERVER_ADDRESS];
|
$this->extraData[self::I_USERNAME],
|
||||||
$this->locale = $this->clientData[self::I_LANGUAGE_CODE];
|
UUID::fromString($this->extraData[self::I_UUID]),
|
||||||
|
new Skin(
|
||||||
$this->skin = new Skin(
|
|
||||||
$this->clientData[self::I_SKIN_ID],
|
$this->clientData[self::I_SKIN_ID],
|
||||||
base64_decode($this->clientData[self::I_SKIN_DATA]),
|
base64_decode($this->clientData[self::I_SKIN_DATA]),
|
||||||
base64_decode($this->clientData[self::I_CAPE_DATA]),
|
base64_decode($this->clientData[self::I_CAPE_DATA]),
|
||||||
$this->clientData[self::I_GEOMETRY_NAME],
|
$this->clientData[self::I_GEOMETRY_NAME],
|
||||||
base64_decode($this->clientData[self::I_GEOMETRY_DATA])
|
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