mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-13 17:29:44 +00:00
Clean up Skin error handling, close #2926
Skin->__construct() now does all the validation.
This commit is contained in:
parent
0a891f5408
commit
89242543b9
@ -820,10 +820,6 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function changeSkin(Skin $skin, string $newSkinName, string $oldSkinName) : bool{
|
public function changeSkin(Skin $skin, string $newSkinName, string $oldSkinName) : bool{
|
||||||
if(!$skin->isValid()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ev = new PlayerChangeSkinEvent($this, $this->getSkin(), $skin);
|
$ev = new PlayerChangeSkinEvent($this, $this->getSkin(), $skin);
|
||||||
$ev->call();
|
$ev->call();
|
||||||
|
|
||||||
|
@ -105,28 +105,16 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
|||||||
if($skinTag === null){
|
if($skinTag === null){
|
||||||
throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set");
|
throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set");
|
||||||
}
|
}
|
||||||
$this->skin = self::deserializeSkinNBT($skinTag); //this throws if the skin is invalid
|
$this->skin = new Skin( //this throws if the skin is invalid
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($world, $nbt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param CompoundTag $skinTag
|
|
||||||
*
|
|
||||||
* @return Skin
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
protected static function deserializeSkinNBT(CompoundTag $skinTag) : Skin{
|
|
||||||
$skin = new Skin(
|
|
||||||
$skinTag->getString("Name"),
|
$skinTag->getString("Name"),
|
||||||
$skinTag->hasTag("Data", StringTag::class) ? $skinTag->getString("Data") : $skinTag->getByteArray("Data"), //old data (this used to be saved as a StringTag in older versions of PM)
|
$skinTag->hasTag("Data", StringTag::class) ? $skinTag->getString("Data") : $skinTag->getByteArray("Data"), //old data (this used to be saved as a StringTag in older versions of PM)
|
||||||
$skinTag->getByteArray("CapeData", ""),
|
$skinTag->getByteArray("CapeData", ""),
|
||||||
$skinTag->getString("GeometryName", ""),
|
$skinTag->getString("GeometryName", ""),
|
||||||
$skinTag->getByteArray("GeometryData", "")
|
$skinTag->getByteArray("GeometryData", "")
|
||||||
);
|
);
|
||||||
$skin->validate();
|
}
|
||||||
return $skin;
|
|
||||||
|
parent::__construct($world, $nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,7 +159,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
|||||||
* @param Skin $skin
|
* @param Skin $skin
|
||||||
*/
|
*/
|
||||||
public function setSkin(Skin $skin) : void{
|
public function setSkin(Skin $skin) : void{
|
||||||
$skin->validate();
|
|
||||||
$this->skin = $skin;
|
$this->skin = $skin;
|
||||||
$this->skin->debloatGeometryData();
|
$this->skin->debloatGeometryData();
|
||||||
}
|
}
|
||||||
@ -841,8 +828,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function sendSpawnPacket(Player $player) : void{
|
protected function sendSpawnPacket(Player $player) : void{
|
||||||
$this->skin->validate();
|
|
||||||
|
|
||||||
if(!($this instanceof Player)){
|
if(!($this instanceof Player)){
|
||||||
/* we don't use Server->updatePlayerListData() because that uses batches, which could cause race conditions in async compression mode */
|
/* we don't use Server->updatePlayerListData() because that uses batches, which could cause race conditions in async compression mode */
|
||||||
$pk = new PlayerListPacket();
|
$pk = new PlayerListPacket();
|
||||||
|
@ -48,6 +48,18 @@ class Skin{
|
|||||||
private $geometryData;
|
private $geometryData;
|
||||||
|
|
||||||
public function __construct(string $skinId, string $skinData, string $capeData = "", string $geometryName = "", string $geometryData = ""){
|
public function __construct(string $skinId, string $skinData, string $capeData = "", string $geometryName = "", string $geometryData = ""){
|
||||||
|
if($skinId === ""){
|
||||||
|
throw new \InvalidArgumentException("Skin ID must not be empty");
|
||||||
|
}
|
||||||
|
$len = strlen($skinData);
|
||||||
|
if(!in_array($len, self::ACCEPTED_SKIN_SIZES, true)){
|
||||||
|
throw new \InvalidArgumentException("Invalid skin data size $len bytes (allowed sizes: " . implode(", ", self::ACCEPTED_SKIN_SIZES) . ")");
|
||||||
|
}
|
||||||
|
if($capeData !== "" and strlen($capeData) !== 8192){
|
||||||
|
throw new \InvalidArgumentException("Invalid cape data size " . strlen($capeData) . " bytes (must be exactly 8192 bytes)");
|
||||||
|
}
|
||||||
|
//TODO: validate geometry
|
||||||
|
|
||||||
$this->skinId = $skinId;
|
$this->skinId = $skinId;
|
||||||
$this->skinData = $skinData;
|
$this->skinData = $skinData;
|
||||||
$this->capeData = $capeData;
|
$this->capeData = $capeData;
|
||||||
@ -55,36 +67,6 @@ class Skin{
|
|||||||
$this->geometryData = $geometryData;
|
$this->geometryData = $geometryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isValid() : bool{
|
|
||||||
try{
|
|
||||||
$this->validate();
|
|
||||||
return true;
|
|
||||||
}catch(\InvalidArgumentException $e){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function validate() : void{
|
|
||||||
if($this->skinId === ""){
|
|
||||||
throw new \InvalidArgumentException("Skin ID must not be empty");
|
|
||||||
}
|
|
||||||
$len = strlen($this->skinData);
|
|
||||||
if(!in_array($len, self::ACCEPTED_SKIN_SIZES, true)){
|
|
||||||
throw new \InvalidArgumentException("Invalid skin data size $len bytes (allowed sizes: " . implode(", ", self::ACCEPTED_SKIN_SIZES) . ")");
|
|
||||||
}
|
|
||||||
if($this->capeData !== "" and strlen($this->capeData) !== 8192){
|
|
||||||
throw new \InvalidArgumentException("Invalid cape data size " . strlen($this->capeData) . " bytes (must be exactly 8192 bytes)");
|
|
||||||
}
|
|
||||||
//TODO: validate geometry
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -70,7 +70,6 @@ class PlayerChangeSkinEvent extends PlayerEvent implements Cancellable{
|
|||||||
* @throws \InvalidArgumentException if the specified skin is not valid
|
* @throws \InvalidArgumentException if the specified skin is not valid
|
||||||
*/
|
*/
|
||||||
public function setNewSkin(Skin $skin) : void{
|
public function setNewSkin(Skin $skin) : void{
|
||||||
$skin->validate();
|
|
||||||
$this->newSkin = $skin;
|
$this->newSkin = $skin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,7 @@ class LoginSessionHandler extends SessionHandler{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
$skin = new Skin(
|
$skin = new Skin(
|
||||||
$packet->clientData[LoginPacket::I_SKIN_ID],
|
$packet->clientData[LoginPacket::I_SKIN_ID],
|
||||||
base64_decode($packet->clientData[LoginPacket::I_SKIN_DATA]),
|
base64_decode($packet->clientData[LoginPacket::I_SKIN_DATA]),
|
||||||
@ -82,7 +83,8 @@ class LoginSessionHandler extends SessionHandler{
|
|||||||
$packet->clientData[LoginPacket::I_GEOMETRY_NAME],
|
$packet->clientData[LoginPacket::I_GEOMETRY_NAME],
|
||||||
base64_decode($packet->clientData[LoginPacket::I_GEOMETRY_DATA])
|
base64_decode($packet->clientData[LoginPacket::I_GEOMETRY_DATA])
|
||||||
);
|
);
|
||||||
if(!$skin->isValid()){
|
}catch(\InvalidArgumentException $e){
|
||||||
|
$this->session->getLogger()->debug("Invalid skin: " . $e->getMessage());
|
||||||
$this->session->disconnect("disconnectionScreen.invalidSkin");
|
$this->session->disconnect("disconnectionScreen.invalidSkin");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -27,6 +27,7 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
|
|
||||||
|
|
||||||
use pocketmine\entity\Skin;
|
use pocketmine\entity\Skin;
|
||||||
|
use pocketmine\network\BadPacketException;
|
||||||
use pocketmine\network\mcpe\handler\SessionHandler;
|
use pocketmine\network\mcpe\handler\SessionHandler;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||||
use function count;
|
use function count;
|
||||||
@ -59,6 +60,7 @@ class PlayerListPacket extends DataPacket implements ClientboundPacket{
|
|||||||
$geometryName = $this->getString();
|
$geometryName = $this->getString();
|
||||||
$geometryData = $this->getString();
|
$geometryData = $this->getString();
|
||||||
|
|
||||||
|
try{
|
||||||
$entry->skin = new Skin(
|
$entry->skin = new Skin(
|
||||||
$skinId,
|
$skinId,
|
||||||
$skinData,
|
$skinData,
|
||||||
@ -66,6 +68,9 @@ class PlayerListPacket extends DataPacket implements ClientboundPacket{
|
|||||||
$geometryName,
|
$geometryName,
|
||||||
$geometryData
|
$geometryData
|
||||||
);
|
);
|
||||||
|
}catch(\InvalidArgumentException $e){
|
||||||
|
throw new BadPacketException($e->getMessage(), 0, $e);
|
||||||
|
}
|
||||||
$entry->xboxUserId = $this->getString();
|
$entry->xboxUserId = $this->getString();
|
||||||
$entry->platformChatId = $this->getString();
|
$entry->platformChatId = $this->getString();
|
||||||
}else{
|
}else{
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
#include <rules/DataPacket.h>
|
#include <rules/DataPacket.h>
|
||||||
|
|
||||||
use pocketmine\entity\Skin;
|
use pocketmine\entity\Skin;
|
||||||
|
use pocketmine\network\BadPacketException;
|
||||||
use pocketmine\network\mcpe\handler\SessionHandler;
|
use pocketmine\network\mcpe\handler\SessionHandler;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
|
|
||||||
@ -54,7 +55,11 @@ class PlayerSkinPacket extends DataPacket implements ClientboundPacket, Serverbo
|
|||||||
$geometryModel = $this->getString();
|
$geometryModel = $this->getString();
|
||||||
$geometryData = $this->getString();
|
$geometryData = $this->getString();
|
||||||
|
|
||||||
|
try{
|
||||||
$this->skin = new Skin($skinId, $skinData, $capeData, $geometryModel, $geometryData);
|
$this->skin = new Skin($skinId, $skinData, $capeData, $geometryModel, $geometryData);
|
||||||
|
}catch(\InvalidArgumentException $e){
|
||||||
|
throw new BadPacketException($e->getMessage(), 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
$this->premiumSkin = $this->getBool();
|
$this->premiumSkin = $this->getBool();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user