Merge branch 'stable'

This commit is contained in:
Dylan K. Taylor 2020-04-18 13:19:31 +01:00
commit 9bfc1df486
12 changed files with 399 additions and 7 deletions

11
changelogs/3.12.md Normal file
View File

@ -0,0 +1,11 @@
**For Minecraft: Bedrock Edition 1.14.60**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 3.12.0
- Added support for Minecraft: Bedrock Edition 1.14.60
- Removed compatibility with 1.14.0-1.14.30

View File

@ -31,6 +31,10 @@ use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\LoginPacket;
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\types\login\ClientDataPersonaPieceTintColor;
use pocketmine\network\mcpe\protocol\types\login\ClientDataPersonaSkinPiece;
use pocketmine\network\mcpe\protocol\types\PersonaPieceTintColor;
use pocketmine\network\mcpe\protocol\types\PersonaSkinPiece;
use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton;
use pocketmine\network\mcpe\protocol\types\SkinAnimation;
use pocketmine\network\mcpe\protocol\types\SkinData;
@ -110,7 +114,16 @@ class LoginPacketHandler extends PacketHandler{
$clientData->PremiumSkin,
$clientData->PersonaSkin,
$clientData->CapeOnClassicSkin,
$clientData->CapeId
$clientData->CapeId,
null,
$clientData->ArmSize,
$clientData->SkinColor,
array_map(function(ClientDataPersonaSkinPiece $piece) : PersonaSkinPiece{
return new PersonaSkinPiece($piece->PieceId, $piece->PieceType, $piece->PackId, $piece->IsDefault, $piece->ProductId);
}, $clientData->PersonaPieces),
array_map(function(ClientDataPersonaPieceTintColor $tint) : PersonaPieceTintColor{
return new PersonaPieceTintColor($tint->PieceType, $tint->Colors);
}, $clientData->PieceTintColors)
);
$skin = SkinAdapterSingleton::get()->fromSkinData($skinData);

View File

@ -83,6 +83,11 @@ class PlayerListPacket extends DataPacket implements ClientboundPacket{
$this->entries[$i] = $entry;
}
if($this->type === self::TYPE_ADD){
for($i = 0; $i < $count; ++$i){
$this->entries[$i]->skinData->setVerified($in->getBool());
}
}
}
protected function encodePayload(NetworkBinaryStream $out) : void{
@ -103,6 +108,11 @@ class PlayerListPacket extends DataPacket implements ClientboundPacket{
$out->putUUID($entry->uuid);
}
}
if($this->type === self::TYPE_ADD){
foreach($this->entries as $entry){
$out->putBool($entry->skinData->isVerified());
}
}
}
public function handle(PacketHandler $handler) : bool{

View File

@ -47,6 +47,7 @@ class PlayerSkinPacket extends DataPacket implements ClientboundPacket, Serverbo
$this->skin = $in->getSkin();
$this->newSkinName = $in->getString();
$this->oldSkinName = $in->getString();
$this->skin->setVerified($in->getBool());
}
protected function encodePayload(NetworkBinaryStream $out) : void{
@ -54,6 +55,7 @@ class PlayerSkinPacket extends DataPacket implements ClientboundPacket, Serverbo
$out->putSkin($this->skin);
$out->putString($this->newSkinName);
$out->putString($this->oldSkinName);
$out->putBool($this->skin->isVerified());
}
public function handle(PacketHandler $handler) : bool{

View File

@ -41,11 +41,11 @@ final class ProtocolInfo{
*/
/** Actual Minecraft: PE protocol version */
public const CURRENT_PROTOCOL = 389;
public const CURRENT_PROTOCOL = 390;
/** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */
public const MINECRAFT_VERSION = 'v1.14.0';
public const MINECRAFT_VERSION = 'v1.14.60';
/** Version number sent to clients in ping responses. */
public const MINECRAFT_VERSION_NETWORK = '1.14.0';
public const MINECRAFT_VERSION_NETWORK = '1.14.60';
public const LOGIN_PACKET = 0x01;
public const PLAY_STATUS_PACKET = 0x02;

View File

@ -0,0 +1,55 @@
<?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\network\mcpe\protocol\types;
final class PersonaPieceTintColor{
public const PIECE_TYPE_PERSONA_EYES = "persona_eyes";
public const PIECE_TYPE_PERSONA_HAIR = "persona_hair";
public const PIECE_TYPE_PERSONA_MOUTH = "persona_mouth";
/** @var string */
private $pieceType;
/** @var string[] */
private $colors;
/**
* @param string[] $colors
*/
public function __construct(string $pieceType, array $colors){
$this->pieceType = $pieceType;
$this->colors = $colors;
}
public function getPieceType() : string{
return $this->pieceType;
}
/**
* @return string[]
*/
public function getColors() : array{
return $this->colors;
}
}

View File

@ -0,0 +1,77 @@
<?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\network\mcpe\protocol\types;
final class PersonaSkinPiece{
public const PIECE_TYPE_PERSONA_BODY = "persona_body";
public const PIECE_TYPE_PERSONA_BOTTOM = "persona_bottom";
public const PIECE_TYPE_PERSONA_EYES = "persona_eyes";
public const PIECE_TYPE_PERSONA_FACIAL_HAIR = "persona_facial_hair";
public const PIECE_TYPE_PERSONA_FEET = "persona_feet";
public const PIECE_TYPE_PERSONA_HAIR = "persona_hair";
public const PIECE_TYPE_PERSONA_MOUTH = "persona_mouth";
public const PIECE_TYPE_PERSONA_SKELETON = "persona_skeleton";
public const PIECE_TYPE_PERSONA_SKIN = "persona_skin";
public const PIECE_TYPE_PERSONA_TOP = "persona_top";
/** @var string */
private $pieceId;
/** @var string */
private $pieceType;
/** @var string */
private $packId;
/** @var bool */
private $isDefaultPiece;
/** @var string */
private $productId;
public function __construct(string $pieceId, string $pieceType, string $packId, bool $isDefaultPiece, string $productId){
$this->pieceId = $pieceId;
$this->pieceType = $pieceType;
$this->packId = $packId;
$this->isDefaultPiece = $isDefaultPiece;
$this->productId = $productId;
}
public function getPieceId() : string{
return $this->pieceId;
}
public function getPieceType() : string{
return $this->pieceType;
}
public function getPackId() : string{
return $this->packId;
}
public function isDefaultPiece() : bool{
return $this->isDefaultPiece;
}
public function getProductId() : string{
return $this->productId;
}
}

View File

@ -27,6 +27,9 @@ use pocketmine\utils\UUID;
class SkinData{
public const ARM_SIZE_SLIM = "slim";
public const ARM_SIZE_WIDE = "wide";
/** @var string */
private $skinId;
/** @var string */
@ -51,11 +54,23 @@ class SkinData{
private $capeId;
/** @var string */
private $fullSkinId;
/** @var string */
private $armSize;
/** @var string */
private $skinColor;
/** @var PersonaSkinPiece[] */
private $personaPieces;
/** @var PersonaPieceTintColor[] */
private $pieceTintColors;
/** @var bool */
private $isVerified;
/**
* @param SkinAnimation[] $animations
* @param SkinAnimation[] $animations
* @param PersonaSkinPiece[] $personaPieces
* @param PersonaPieceTintColor[] $pieceTintColors
*/
public function __construct(string $skinId, string $resourcePatch, SkinImage $skinImage, array $animations = [], SkinImage $capeImage = null, string $geometryData = "", string $animationData = "", bool $premium = false, bool $persona = false, bool $personaCapeOnClassic = false, string $capeId = "", ?string $fullSkinId = null){
public function __construct(string $skinId, string $resourcePatch, SkinImage $skinImage, array $animations = [], SkinImage $capeImage = null, string $geometryData = "", string $animationData = "", bool $premium = false, bool $persona = false, bool $personaCapeOnClassic = false, string $capeId = "", ?string $fullSkinId = null, string $armSize = self::ARM_SIZE_WIDE, string $skinColor = "", array $personaPieces = [], array $pieceTintColors = [], bool $isVerified = false){
$this->skinId = $skinId;
$this->resourcePatch = $resourcePatch;
$this->skinImage = $skinImage;
@ -69,6 +84,11 @@ class SkinData{
$this->capeId = $capeId;
//this has to be unique or the client will do stupid things
$this->fullSkinId = $fullSkinId ?? UUID::fromRandom()->toString();
$this->armSize = $armSize;
$this->skinColor = $skinColor;
$this->personaPieces = $personaPieces;
$this->pieceTintColors = $pieceTintColors;
$this->isVerified = $isVerified;
}
public function getSkinId() : string{
@ -121,4 +141,37 @@ class SkinData{
public function getFullSkinId() : string{
return $this->fullSkinId;
}
public function getArmSize() : string{
return $this->armSize;
}
public function getSkinColor() : string{
return $this->skinColor;
}
/**
* @return PersonaSkinPiece[]
*/
public function getPersonaPieces() : array{
return $this->personaPieces;
}
/**
* @return PersonaPieceTintColor[]
*/
public function getPieceTintColors() : array{
return $this->pieceTintColors;
}
public function isVerified() : bool{
return $this->isVerified;
}
/**
* @internal
*/
public function setVerified(bool $verified) : void{
$this->isVerified = $verified;
}
}

View File

@ -34,6 +34,12 @@ final class ClientData{
*/
public $AnimatedImageData;
/**
* @var string
* @required
*/
public $ArmSize;
/**
* @var string
* @required
@ -118,12 +124,24 @@ final class ClientData{
*/
public $LanguageCode;
/**
* @var ClientDataPersonaSkinPiece[]
* @required
*/
public $PersonaPieces;
/**
* @var bool
* @required
*/
public $PersonaSkin;
/**
* @var ClientDataPersonaPieceTintColor[]
* @required
*/
public $PieceTintColors;
/**
* @var string
* @required
@ -163,6 +181,12 @@ final class ClientData{
*/
public $SkinAnimationData;
/**
* @var string
* @required
*/
public $SkinColor;
/**
* @var string
* @required

View File

@ -0,0 +1,41 @@
<?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\network\mcpe\protocol\types\login;
/**
* Model class for LoginPacket JSON data for JsonMapper
*/
final class ClientDataPersonaPieceTintColor{
/**
* @var string
* @required
*/
public $PieceType;
/**
* @var string[]
* @required
*/
public $Colors;
}

View File

@ -0,0 +1,59 @@
<?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\network\mcpe\protocol\types\login;
/**
* Model class for LoginPacket JSON data for JsonMapper
*/
final class ClientDataPersonaSkinPiece{
/**
* @var string
* @required
*/
public $PieceId;
/**
* @var string
* @required
*/
public $PieceType;
/**
* @var string
* @required
*/
public $PackId;
/**
* @var bool
* @required
*/
public $IsDefault;
/**
* @var string
* @required
*/
public $ProductId;
}

View File

@ -48,6 +48,8 @@ use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\ShortMetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\Vec3MetadataProperty;
use pocketmine\network\mcpe\protocol\types\PersonaPieceTintColor;
use pocketmine\network\mcpe\protocol\types\PersonaSkinPiece;
use pocketmine\network\mcpe\protocol\types\SkinAnimation;
use pocketmine\network\mcpe\protocol\types\SkinData;
use pocketmine\network\mcpe\protocol\types\SkinImage;
@ -117,8 +119,35 @@ class NetworkBinaryStream extends BinaryStream{
$capeOnClassic = $this->getBool();
$capeId = $this->getString();
$fullSkinId = $this->getString();
$armSize = $this->getString();
$skinColor = $this->getString();
$personaPieceCount = $this->getLInt();
$personaPieces = [];
for($i = 0; $i < $personaPieceCount; ++$i){
$personaPieces[] = new PersonaSkinPiece(
$pieceId = $this->getString(),
$pieceType = $this->getString(),
$packId = $this->getString(),
$isDefaultPiece = $this->getBool(),
$productId = $this->getString()
);
}
$pieceTintColorCount = $this->getLInt();
$pieceTintColors = [];
for($i = 0; $i < $pieceTintColorCount; ++$i){
$pieceType = $this->getString();
$colorCount = $this->getLInt();
$colors = [];
for($j = 0; $j < $colorCount; ++$j){
$colors[] = $this->getString();
}
$pieceTintColors[] = new PersonaPieceTintColor(
$pieceType,
$colors
);
}
return new SkinData($skinId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $animationData, $premium, $persona, $capeOnClassic, $capeId, $fullSkinId);
return new SkinData($skinId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $animationData, $premium, $persona, $capeOnClassic, $capeId, $fullSkinId, $armSize, $skinColor, $personaPieces, $pieceTintColors);
}
public function putSkin(SkinData $skin): void{
@ -139,6 +168,24 @@ class NetworkBinaryStream extends BinaryStream{
$this->putBool($skin->isPersonaCapeOnClassic());
$this->putString($skin->getCapeId());
$this->putString($skin->getFullSkinId());
$this->putString($skin->getArmSize());
$this->putString($skin->getSkinColor());
$this->putLInt(count($skin->getPersonaPieces()));
foreach($skin->getPersonaPieces() as $piece){
$this->putString($piece->getPieceId());
$this->putString($piece->getPieceType());
$this->putString($piece->getPackId());
$this->putBool($piece->isDefaultPiece());
$this->putString($piece->getProductId());
}
$this->putLInt(count($skin->getPieceTintColors()));
foreach($skin->getPieceTintColors() as $tint){
$this->putString($tint->getPieceType());
$this->putLInt(count($tint->getColors()));
foreach($tint->getColors() as $color){
$this->putString($color);
}
}
}
private function getSkinImage() : SkinImage{