mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-12 00:39:45 +00:00
Initial update to 1.13
This commit is contained in:
parent
5edff79f5f
commit
cd2b60a860
@ -160,6 +160,8 @@ use pocketmine\tile\ItemFrame;
|
||||
use pocketmine\tile\Spawnable;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\SerializedImage;
|
||||
use pocketmine\utils\SkinAnimation;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\UUID;
|
||||
use function abs;
|
||||
@ -834,12 +836,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* Plugin developers should not use this, use setSkin() and sendSkin() instead.
|
||||
*
|
||||
* @param Skin $skin
|
||||
* @param string $newSkinName
|
||||
* @param string $oldSkinName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function changeSkin(Skin $skin, string $newSkinName, string $oldSkinName) : bool{
|
||||
public function changeSkin(Skin $skin) : bool{
|
||||
if(!$skin->isValid()){
|
||||
return false;
|
||||
}
|
||||
@ -1112,9 +1112,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
protected function sendRespawnPacket(Vector3 $pos){
|
||||
protected function sendRespawnPacket(Vector3 $pos, int $respawnState = 1){
|
||||
$pk = new RespawnPacket();
|
||||
$pk->position = $pos->add(0, $this->baseOffset, 0);
|
||||
$pk->respawnState = $respawnState;
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
@ -1913,12 +1915,22 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->uuid = UUID::fromString($packet->clientUUID);
|
||||
$this->rawUUID = $this->uuid->toBinary();
|
||||
|
||||
$animations = [];
|
||||
foreach($packet->clientData["AnimatedImageData"] as $animatedData){
|
||||
$animations[] = new SkinAnimation(new SerializedImage($animatedData["ImageWidth"], $animatedData["ImageHeight"], base64_decode($animatedData["Image"])), $animatedData["Type"], $animatedData["Frames"]);
|
||||
}
|
||||
$skin = new Skin(
|
||||
$packet->clientData["SkinId"],
|
||||
base64_decode($packet->clientData["SkinData"] ?? ""),
|
||||
base64_decode($packet->clientData["CapeData"] ?? ""),
|
||||
$packet->clientData["SkinGeometryName"] ?? "",
|
||||
base64_decode($packet->clientData["SkinGeometry"] ?? "")
|
||||
base64_decode($packet->clientData["SkinResourcePatch"] ?? ""),
|
||||
new SerializedImage($packet->clientData["SkinImageHeight"], $packet->clientData["SkinImageWidth"], base64_decode($packet->clientData["SkinData" ?? ""])), //SerializedImage
|
||||
$animations,
|
||||
new SerializedImage($packet->clientData["CapeImageHeight"], $packet->clientData["CapeImageWidth"], base64_decode($packet->clientData["CapeData"] ?? "")),
|
||||
base64_decode($packet->clientData["SkinGeometryData"] ?? ""),
|
||||
base64_decode($packet->clientData["SkinAnimationData"] ?? ""),
|
||||
(bool) $packet->clientData["PremiumSkin"] ?? false,
|
||||
(bool) $packet->clientData["PersonaSkin"] ?? false,
|
||||
(bool) $packet->clientData["CapeOnClassicSkin"] ?? false,
|
||||
$packet->clientData["CapeId"] ?? ""
|
||||
);
|
||||
|
||||
if(!$skin->isValid()){
|
||||
|
@ -24,6 +24,8 @@ declare(strict_types=1);
|
||||
namespace pocketmine\entity;
|
||||
|
||||
use Ahc\Json\Comment as CommentedJsonDecoder;
|
||||
use pocketmine\utils\SerializedImage;
|
||||
use pocketmine\utils\SkinAnimation;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function json_encode;
|
||||
@ -39,20 +41,38 @@ class Skin{
|
||||
/** @var string */
|
||||
private $skinId;
|
||||
/** @var string */
|
||||
private $skinResourcePatch;
|
||||
/** @var SerializedImage */
|
||||
private $skinData;
|
||||
/** @var string */
|
||||
/** @var SkinAnimation[] */
|
||||
private $animations = [];
|
||||
/** @var SerializedImage */
|
||||
private $capeData;
|
||||
/** @var string */
|
||||
private $geometryName;
|
||||
/** @var string */
|
||||
private $geometryData;
|
||||
/** @var string */
|
||||
private $animationData;
|
||||
/** @var bool */
|
||||
private $premium;
|
||||
/** @var bool */
|
||||
private $persona;
|
||||
/** @var bool */
|
||||
private $capeOnClassic;
|
||||
/** @var string */
|
||||
private $capeId;
|
||||
|
||||
public function __construct(string $skinId, string $skinData, string $capeData = "", string $geometryName = "", string $geometryData = ""){
|
||||
public function __construct(string $skinId, string $skinResourcePatch, SerializedImage $skinData, array $animations = [], SerializedImage $capeData = null, string $geometryData = "", string $animationData = "", bool $premium = false, bool $persona = false, bool $capeOnClassic = false, string $capeId = ""){
|
||||
$this->skinId = $skinId;
|
||||
$this->skinResourcePatch = $skinResourcePatch;
|
||||
$this->skinData = $skinData;
|
||||
$this->animations = $animations;
|
||||
$this->capeData = $capeData;
|
||||
$this->geometryName = $geometryName;
|
||||
$this->geometryData = $geometryData;
|
||||
$this->animationData = $animationData;
|
||||
$this->premium = $premium;
|
||||
$this->persona = $persona;
|
||||
$this->capeOnClassic = $capeOnClassic;
|
||||
$this->capeId = $capeId;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,13 +95,14 @@ class Skin{
|
||||
if($this->skinId === ""){
|
||||
throw new \InvalidArgumentException("Skin ID must not be empty");
|
||||
}
|
||||
$len = strlen($this->skinData);
|
||||
//Broken with Persona skins
|
||||
/*$len = strlen($this->skinData->getData());
|
||||
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)");
|
||||
}
|
||||
if($this->capeData->getData() !== "" and strlen($this->capeData->getData()) !== 8192){
|
||||
throw new \InvalidArgumentException("Invalid cape data size " . strlen($this->capeData->getData()) . " bytes (must be exactly 8192 bytes)");
|
||||
}*/
|
||||
//TODO: validate geometry
|
||||
}
|
||||
|
||||
@ -95,22 +116,29 @@ class Skin{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSkinData() : string{
|
||||
public function getSkinResourcePatch() : string{
|
||||
return $this->skinResourcePatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SerializedImage
|
||||
*/
|
||||
public function getSkinData() : SerializedImage{
|
||||
return $this->skinData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @return SkinAnimation[]
|
||||
*/
|
||||
public function getCapeData() : string{
|
||||
return $this->capeData;
|
||||
public function getAnimations() : array{
|
||||
return $this->animations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @return SerializedImage
|
||||
*/
|
||||
public function getGeometryName() : string{
|
||||
return $this->geometryName;
|
||||
public function getCapeData() : SerializedImage{
|
||||
return $this->capeData;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,6 +148,48 @@ class Skin{
|
||||
return $this->geometryData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAnimationData() : string{
|
||||
return $this->animationData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getPremium() : bool{
|
||||
return $this->premium;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getPersona() : bool{
|
||||
return $this->persona;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getCapeOnClassic() : bool{
|
||||
return $this->capeOnClassic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCapeId() : string{
|
||||
return $this->capeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFullSkinId() : string{
|
||||
return $this->skinId . "_" . $this->capeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack to cut down on network overhead due to skins, by un-pretty-printing geometry JSON.
|
||||
*
|
||||
|
@ -38,7 +38,6 @@ use pocketmine\level\particle\HugeExplodeSeedParticle;
|
||||
use pocketmine\level\utils\SubChunkIteratorManager;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\ExplodePacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use pocketmine\tile\Chest;
|
||||
use pocketmine\tile\Container;
|
||||
@ -260,12 +259,6 @@ class Explosion{
|
||||
$send[] = new Vector3($block->x - $source->x, $block->y - $source->y, $block->z - $source->z);
|
||||
}
|
||||
|
||||
$pk = new ExplodePacket();
|
||||
$pk->position = $this->source->asVector3();
|
||||
$pk->radius = $this->size;
|
||||
$pk->records = $send;
|
||||
$this->level->broadcastPacketToViewers($source, $pk);
|
||||
|
||||
$this->level->addParticle(new HugeExplodeSeedParticle($source));
|
||||
$this->level->broadcastLevelSoundEvent($source, LevelSoundEventPacket::SOUND_EXPLODE);
|
||||
|
||||
|
@ -39,6 +39,7 @@ use pocketmine\network\mcpe\protocol\types\CommandOriginData;
|
||||
use pocketmine\network\mcpe\protocol\types\EntityLink;
|
||||
use pocketmine\network\mcpe\protocol\types\StructureSettings;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use pocketmine\utils\SerializedImage;
|
||||
use pocketmine\utils\UUID;
|
||||
use function count;
|
||||
use function strlen;
|
||||
@ -74,6 +75,19 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$this->putLInt($uuid->getPart(2));
|
||||
}
|
||||
|
||||
public function putImage(SerializedImage $image) : void{
|
||||
$this->putLInt($image->getWidth());
|
||||
$this->putLInt($image->getHeight());
|
||||
$this->putString($image->getData());
|
||||
}
|
||||
|
||||
public function getImage() : SerializedImage{
|
||||
$width = $this->getLInt();
|
||||
$height = $this->getLInt();
|
||||
$data = $this->getString();
|
||||
return new SerializedImage($height, $width, $data);
|
||||
}
|
||||
|
||||
public function getSlot() : Item{
|
||||
$id = $this->getVarInt();
|
||||
if($id === 0){
|
||||
|
@ -247,10 +247,6 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleExplode(ExplodePacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleLevelSoundEventPacketV1(LevelSoundEventPacketV1 $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
|
||||
}
|
||||
|
||||
public function handlePlayerSkin(PlayerSkinPacket $packet) : bool{
|
||||
return $this->player->changeSkin($packet->skin, $packet->newSkinName, $packet->oldSkinName);
|
||||
return $this->player->changeSkin($packet->skin);
|
||||
}
|
||||
|
||||
public function handleBookEdit(BookEditPacket $packet) : bool{
|
||||
|
@ -1,73 +0,0 @@
|
||||
<?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;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use function count;
|
||||
|
||||
class ExplodePacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::EXPLODE_PACKET;
|
||||
|
||||
/** @var Vector3 */
|
||||
public $position;
|
||||
/** @var float */
|
||||
public $radius;
|
||||
/** @var Vector3[] */
|
||||
public $records = [];
|
||||
|
||||
public function clean(){
|
||||
$this->records = [];
|
||||
return parent::clean();
|
||||
}
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->position = $this->getVector3();
|
||||
$this->radius = (float) ($this->getVarInt() / 32);
|
||||
$count = $this->getUnsignedVarInt();
|
||||
for($i = 0; $i < $count; ++$i){
|
||||
$x = $y = $z = null;
|
||||
$this->getSignedBlockPosition($x, $y, $z);
|
||||
$this->records[$i] = new Vector3($x, $y, $z);
|
||||
}
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putVector3($this->position);
|
||||
$this->putVarInt((int) ($this->radius * 32));
|
||||
$this->putUnsignedVarInt(count($this->records));
|
||||
if(count($this->records) > 0){
|
||||
foreach($this->records as $record){
|
||||
$this->putSignedBlockPosition((int) $record->x, (int) $record->y, (int) $record->z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleExplode($this);
|
||||
}
|
||||
}
|
@ -54,7 +54,6 @@ class PacketPool{
|
||||
static::registerPacket(new RiderJumpPacket());
|
||||
static::registerPacket(new UpdateBlockPacket());
|
||||
static::registerPacket(new AddPaintingPacket());
|
||||
static::registerPacket(new ExplodePacket());
|
||||
static::registerPacket(new LevelSoundEventPacketV1());
|
||||
static::registerPacket(new LevelEventPacket());
|
||||
static::registerPacket(new BlockEventPacket());
|
||||
|
@ -29,6 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
use pocketmine\entity\Skin;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||
use pocketmine\utils\SerializedImage;
|
||||
use pocketmine\utils\SkinAnimation;
|
||||
use function count;
|
||||
|
||||
class PlayerListPacket extends DataPacket{
|
||||
@ -57,22 +59,32 @@ class PlayerListPacket extends DataPacket{
|
||||
$entry->uuid = $this->getUUID();
|
||||
$entry->entityUniqueId = $this->getEntityUniqueId();
|
||||
$entry->username = $this->getString();
|
||||
|
||||
$skinId = $this->getString();
|
||||
$skinData = $this->getString();
|
||||
$capeData = $this->getString();
|
||||
$geometryName = $this->getString();
|
||||
$geometryData = $this->getString();
|
||||
|
||||
$entry->skin = new Skin(
|
||||
$skinId,
|
||||
$skinData,
|
||||
$capeData,
|
||||
$geometryName,
|
||||
$geometryData
|
||||
);
|
||||
$entry->xboxUserId = $this->getString();
|
||||
$entry->platformChatId = $this->getString();
|
||||
$entry->buildPlatform = $this->getLInt();
|
||||
|
||||
$skinId = $this->getString();
|
||||
$skinResourcePatch = $this->getString();
|
||||
$skinData = $this->getImage();
|
||||
$animations = [];
|
||||
for($i = 0; $i < $this->getLInt(); ++$i){
|
||||
$animations[] = new SkinAnimation($this->getImage(), $this->getLInt(), $this->getLFloat());
|
||||
}
|
||||
$capeData = $this->getImage();
|
||||
$geometryData = $this->getString();
|
||||
$animationData = $this->getString();
|
||||
$premium = $this->getBool();
|
||||
$persona = $this->getBool();
|
||||
$capeOnClassic = $this->getBool();
|
||||
$capeId = $this->getString();
|
||||
$fullSkinId = $this->getString();
|
||||
|
||||
$entry->skin = new Skin(
|
||||
$skinId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $animationData, $premium, $persona, $capeOnClassic, $capeId
|
||||
);
|
||||
|
||||
$entry->isTeacher = $this->getBool();
|
||||
$entry->isHost = $this->getBool();
|
||||
}else{
|
||||
$entry->uuid = $this->getUUID();
|
||||
}
|
||||
@ -89,13 +101,30 @@ class PlayerListPacket extends DataPacket{
|
||||
$this->putUUID($entry->uuid);
|
||||
$this->putEntityUniqueId($entry->entityUniqueId);
|
||||
$this->putString($entry->username);
|
||||
$this->putString($entry->skin->getSkinId());
|
||||
$this->putString($entry->skin->getSkinData());
|
||||
$this->putString($entry->skin->getCapeData());
|
||||
$this->putString($entry->skin->getGeometryName());
|
||||
$this->putString($entry->skin->getGeometryData());
|
||||
$this->putString($entry->xboxUserId);
|
||||
$this->putString($entry->platformChatId);
|
||||
$this->putLInt($entry->buildPlatform);
|
||||
|
||||
$this->putString($entry->skin->getSkinId());
|
||||
$this->putString($entry->skin->getSkinResourcePatch());
|
||||
$this->putImage($entry->skin->getSkinData());
|
||||
$this->putLInt(count($entry->skin->getAnimations()));
|
||||
foreach($entry->skin->getAnimations() as $animation){
|
||||
$this->putImage($animation->getImage());
|
||||
$this->putLInt($animation->getType());
|
||||
$this->putLFloat($animation->getFrames());
|
||||
}
|
||||
$this->putImage($entry->skin->getCapeData());
|
||||
$this->putString($entry->skin->getGeometryData());
|
||||
$this->putString($entry->skin->getAnimationData());
|
||||
$this->putBool($entry->skin->getPremium());
|
||||
$this->putBool($entry->skin->getPersona());
|
||||
$this->putBool($entry->skin->getCapeOnClassic());
|
||||
$this->putString($entry->skin->getCapeId());
|
||||
$this->putString($entry->skin->getFullSkinId());
|
||||
|
||||
$this->putBool($entry->isTeacher);
|
||||
$this->putBool($entry->isHost);
|
||||
}else{
|
||||
$this->putUUID($entry->uuid);
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\entity\Skin;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\utils\SerializedImage;
|
||||
use pocketmine\utils\SkinAnimation;
|
||||
use pocketmine\utils\UUID;
|
||||
|
||||
class PlayerSkinPacket extends DataPacket{
|
||||
@ -34,43 +36,53 @@ class PlayerSkinPacket extends DataPacket{
|
||||
|
||||
/** @var UUID */
|
||||
public $uuid;
|
||||
/** @var string */
|
||||
public $oldSkinName = "";
|
||||
/** @var string */
|
||||
public $newSkinName = "";
|
||||
/** @var Skin */
|
||||
public $skin;
|
||||
/** @var bool */
|
||||
public $premiumSkin = false;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->uuid = $this->getUUID();
|
||||
|
||||
$skinId = $this->getString();
|
||||
$this->newSkinName = $this->getString();
|
||||
$this->oldSkinName = $this->getString();
|
||||
$skinData = $this->getString();
|
||||
$capeData = $this->getString();
|
||||
$geometryModel = $this->getString();
|
||||
$skinResourcePatch = $this->getString();
|
||||
$skinData = $this->getImage();
|
||||
$animations = [];
|
||||
for($i = 0; $i < $this->getLInt(); ++$i){
|
||||
$animations[] = new SkinAnimation($this->getImage(), $this->getLInt(), $this->getLFloat());
|
||||
}
|
||||
$capeData = $this->getImage();
|
||||
$geometryData = $this->getString();
|
||||
$animationData = $this->getString();
|
||||
$premium = $this->getBool();
|
||||
$persona = $this->getBool();
|
||||
$capeOnClassic = $this->getBool();
|
||||
$capeId = $this->getString();
|
||||
$fullSkinId = $this->getString();
|
||||
|
||||
$this->skin = new Skin($skinId, $skinData, $capeData, $geometryModel, $geometryData);
|
||||
|
||||
$this->premiumSkin = $this->getBool();
|
||||
$this->skin = new Skin(
|
||||
$skinId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $animationData, $premium, $persona, $capeOnClassic, $capeId
|
||||
);
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putUUID($this->uuid);
|
||||
|
||||
$this->putString($this->skin->getSkinId());
|
||||
$this->putString($this->newSkinName);
|
||||
$this->putString($this->oldSkinName);
|
||||
$this->putString($this->skin->getSkinData());
|
||||
$this->putString($this->skin->getCapeData());
|
||||
$this->putString($this->skin->getGeometryName());
|
||||
$this->putString($this->skin->getSkinResourcePatch());
|
||||
$this->putImage($this->skin->getSkinData());
|
||||
$this->putLInt(count($this->skin->getAnimations()));
|
||||
foreach($this->skin->getAnimations() as $animation){
|
||||
$this->putImage($animation->getImage());
|
||||
$this->putLInt($animation->getType());
|
||||
$this->putLFloat($animation->getFrames());
|
||||
}
|
||||
$this->putImage($this->skin->getCapeData());
|
||||
$this->putString($this->skin->getGeometryData());
|
||||
|
||||
$this->putBool($this->premiumSkin);
|
||||
$this->putString($this->skin->getAnimationData());
|
||||
$this->putBool($this->skin->getPremium());
|
||||
$this->putBool($this->skin->getPersona());
|
||||
$this->putBool($this->skin->getCapeOnClassic());
|
||||
$this->putString($this->skin->getCapeId());
|
||||
$this->putString($this->skin->getFullSkinId());
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -39,15 +39,15 @@ interface ProtocolInfo{
|
||||
/**
|
||||
* Actual Minecraft: PE protocol version
|
||||
*/
|
||||
public const CURRENT_PROTOCOL = 361;
|
||||
public const CURRENT_PROTOCOL = 388;
|
||||
/**
|
||||
* Current Minecraft PE version reported by the server. This is usually the earliest currently supported version.
|
||||
*/
|
||||
public const MINECRAFT_VERSION = 'v1.12.0';
|
||||
public const MINECRAFT_VERSION = 'v1.13.0';
|
||||
/**
|
||||
* Version number sent to clients in ping responses.
|
||||
*/
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.12.0';
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.13.0';
|
||||
|
||||
public const LOGIN_PACKET = 0x01;
|
||||
public const PLAY_STATUS_PACKET = 0x02;
|
||||
@ -71,7 +71,7 @@ interface ProtocolInfo{
|
||||
public const RIDER_JUMP_PACKET = 0x14;
|
||||
public const UPDATE_BLOCK_PACKET = 0x15;
|
||||
public const ADD_PAINTING_PACKET = 0x16;
|
||||
public const EXPLODE_PACKET = 0x17;
|
||||
public const TICK_SYNC_PACKET = 0x17;
|
||||
public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18;
|
||||
public const LEVEL_EVENT_PACKET = 0x19;
|
||||
public const BLOCK_EVENT_PACKET = 0x1a;
|
||||
@ -185,5 +185,13 @@ interface ProtocolInfo{
|
||||
public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86;
|
||||
public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87;
|
||||
public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88;
|
||||
public const EDUCATION_SETTINGS_PACKET = 0x89;
|
||||
public const EMOTE_PACKET = 0x8a;
|
||||
public const MULTIPLAYER_SETTINGS_PACKET = 0x8b;
|
||||
public const SETTINGS_COMMAND_PACKET = 0x8c;
|
||||
public const ANVIL_DAMAGE_PACKET = 0x8d;
|
||||
public const COMPLETED_USING_ITEM_PACKET = 0x8e;
|
||||
public const NETWORK_SETTINGS_PACKET = 0x8f;
|
||||
public const PLAYER_AUTH_INPUT_PACKET = 0x90;
|
||||
|
||||
}
|
||||
|
@ -46,15 +46,14 @@ class ResourcePackChunkDataPacket extends DataPacket{
|
||||
$this->packId = $this->getString();
|
||||
$this->chunkIndex = $this->getLInt();
|
||||
$this->progress = $this->getLLong();
|
||||
$this->data = $this->get($this->getLInt());
|
||||
$this->data = $this->getString();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putString($this->packId);
|
||||
$this->putLInt($this->chunkIndex);
|
||||
$this->putLLong($this->progress);
|
||||
$this->putLInt(strlen($this->data));
|
||||
$this->put($this->data);
|
||||
$this->putString($this->data);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -34,13 +34,21 @@ class RespawnPacket extends DataPacket{
|
||||
|
||||
/** @var Vector3 */
|
||||
public $position;
|
||||
/** @var int */
|
||||
public $respawnState = 1; //TODO: Add
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->position = $this->getVector3();
|
||||
$this->respawnState = $this->getInt();
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putVector3($this->position);
|
||||
$this->putInt($this->respawnState);
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -27,6 +27,10 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||
@ -130,6 +134,8 @@ class StartGamePacket extends DataPacket{
|
||||
/** @var bool */
|
||||
public $onlySpawnV1Villagers = false;
|
||||
|
||||
/** @var string */
|
||||
public $vanillaVersion = ProtocolInfo::MINECRAFT_VERSION_NETWORK;
|
||||
/** @var string */
|
||||
public $levelId = ""; //base64 string, usually the same as world folder name in vanilla
|
||||
/** @var string */
|
||||
@ -138,6 +144,8 @@ class StartGamePacket extends DataPacket{
|
||||
public $premiumWorldTemplateId = "";
|
||||
/** @var bool */
|
||||
public $isTrial = false;
|
||||
/** @var bool */
|
||||
public $isMovementServerAuthoritative = false;
|
||||
/** @var int */
|
||||
public $currentTick = 0; //only used if isTrial is true
|
||||
/** @var int */
|
||||
@ -193,10 +201,12 @@ class StartGamePacket extends DataPacket{
|
||||
$this->isWorldTemplateOptionLocked = $this->getBool();
|
||||
$this->onlySpawnV1Villagers = $this->getBool();
|
||||
|
||||
$this->vanillaVersion = $this->getString();
|
||||
$this->levelId = $this->getString();
|
||||
$this->worldName = $this->getString();
|
||||
$this->premiumWorldTemplateId = $this->getString();
|
||||
$this->isTrial = $this->getBool();
|
||||
$this->isMovementServerAuthoritative = $this->getBool();
|
||||
$this->currentTick = $this->getLLong();
|
||||
|
||||
$this->enchantmentSeed = $this->getVarInt();
|
||||
@ -263,10 +273,12 @@ class StartGamePacket extends DataPacket{
|
||||
$this->putBool($this->isWorldTemplateOptionLocked);
|
||||
$this->putBool($this->onlySpawnV1Villagers);
|
||||
|
||||
$this->putString($this->vanillaVersion);
|
||||
$this->putString($this->levelId);
|
||||
$this->putString($this->worldName);
|
||||
$this->putString($this->premiumWorldTemplateId);
|
||||
$this->putBool($this->isTrial);
|
||||
$this->putBool($this->isMovementServerAuthoritative);
|
||||
$this->putLLong($this->currentTick);
|
||||
|
||||
$this->putVarInt($this->enchantmentSeed);
|
||||
@ -293,14 +305,27 @@ class StartGamePacket extends DataPacket{
|
||||
}
|
||||
|
||||
private static function serializeBlockTable(array $table) : string{
|
||||
$stream = new NetworkBinaryStream();
|
||||
$states = new ListTag();
|
||||
foreach($table as $v){
|
||||
$state = new CompoundTag();
|
||||
$state->setTag(new CompoundTag("block", [
|
||||
new StringTag("name", $v["name"]),
|
||||
$v["states"]
|
||||
]));
|
||||
$state->setShort("id", $v["legacy_id"]);
|
||||
$states->push($state);
|
||||
}
|
||||
($stream = new NetworkLittleEndianNBTStream())->writeTag($states);
|
||||
return $stream->buffer;
|
||||
|
||||
/*$stream = new NetworkBinaryStream();
|
||||
$stream->putUnsignedVarInt(count($table));
|
||||
foreach($table as $v){
|
||||
$stream->putString($v["name"]);
|
||||
$stream->putLShort($v["data"]);
|
||||
$stream->putLShort($v["legacy_id"]);
|
||||
}
|
||||
return $stream->getBuffer();
|
||||
return $stream->getBuffer();*/
|
||||
}
|
||||
|
||||
private static function serializeItemTable(array $table) : string{
|
||||
|
@ -34,12 +34,18 @@ class PlayerListEntry{
|
||||
public $entityUniqueId;
|
||||
/** @var string */
|
||||
public $username;
|
||||
/** @var Skin */
|
||||
public $skin;
|
||||
/** @var string */
|
||||
public $xboxUserId;
|
||||
/** @var string */
|
||||
public $platformChatId = "";
|
||||
/** @var int */
|
||||
public $buildPlatform = 0; //Unknown
|
||||
/** @var Skin */
|
||||
public $skin;
|
||||
/** @var bool */
|
||||
public $isTeacher = false;
|
||||
/** @var bool */
|
||||
public $isHost = false;
|
||||
|
||||
public static function createRemovalEntry(UUID $uuid) : PlayerListEntry{
|
||||
$entry = new PlayerListEntry();
|
||||
@ -48,7 +54,7 @@ class PlayerListEntry{
|
||||
return $entry;
|
||||
}
|
||||
|
||||
public static function createAdditionEntry(UUID $uuid, int $entityUniqueId, string $username, Skin $skin, string $xboxUserId = "", string $platformChatId = "") : PlayerListEntry{
|
||||
public static function createAdditionEntry(UUID $uuid, int $entityUniqueId, string $username, Skin $skin, string $xboxUserId = "", string $platformChatId = "", int $buildPlatform = 0, bool $isTeacher = false, bool $isHost = false) : PlayerListEntry{
|
||||
$entry = new PlayerListEntry();
|
||||
$entry->uuid = $uuid;
|
||||
$entry->entityUniqueId = $entityUniqueId;
|
||||
@ -56,6 +62,9 @@ class PlayerListEntry{
|
||||
$entry->skin = $skin;
|
||||
$entry->xboxUserId = $xboxUserId;
|
||||
$entry->platformChatId = $platformChatId;
|
||||
$entry->buildPlatform = $buildPlatform;
|
||||
$entry->isTeacher = $isTeacher;
|
||||
$entry->isHost = $isHost;
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ final class ResourcePackType{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
//Needs updated
|
||||
public const INVALID = 0;
|
||||
public const RESOURCES = 1;
|
||||
public const BEHAVIORS = 2;
|
||||
|
@ -24,6 +24,9 @@ declare(strict_types=1);
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
use pocketmine\block\BlockIds;
|
||||
use pocketmine\nbt\BigEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\utils\BinaryDataException;
|
||||
use function file_get_contents;
|
||||
use function getmypid;
|
||||
use function json_decode;
|
||||
@ -51,8 +54,29 @@ final class RuntimeBlockMapping{
|
||||
$legacyIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/block_id_map.json"), true);
|
||||
|
||||
$compressedTable = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/required_block_states.json"), true);
|
||||
|
||||
try{
|
||||
/** @var CompoundTag $tag */
|
||||
$tag = (new BigEndianNBTStream())->read(file_get_contents(\pocketmine\RESOURCE_PATH . "runtime_block_states.dat"));
|
||||
}catch(BinaryDataException $e){
|
||||
throw new \RuntimeException("", 0, $e);
|
||||
}
|
||||
|
||||
$decompressed = [];
|
||||
|
||||
$states = $tag->getListTag("Palette");
|
||||
foreach($states as $state){
|
||||
/** @var CompoundTag $state */
|
||||
$block = $state->getCompoundTag("block");
|
||||
$decompressed[] = [
|
||||
"name" => $block->getString("name"),
|
||||
"states" => $block->getCompoundTag("states"),
|
||||
"data" => $state->getShort("meta"),
|
||||
"legacy_id" => $state->getShort("id"),
|
||||
];
|
||||
}
|
||||
|
||||
/*
|
||||
foreach($compressedTable as $prefix => $entries){
|
||||
foreach($entries as $shortStringId => $states){
|
||||
foreach($states as $state){
|
||||
@ -63,8 +87,7 @@ final class RuntimeBlockMapping{
|
||||
"legacy_id" => $legacyIdMap[$name]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
self::$bedrockKnownStates = self::randomizeTable($decompressed);
|
||||
|
||||
foreach(self::$bedrockKnownStates as $k => $obj){
|
||||
|
BIN
src/pocketmine/resources/runtime_block_states.dat
Normal file
BIN
src/pocketmine/resources/runtime_block_states.dat
Normal file
Binary file not shown.
67
src/pocketmine/utils/SerializedImage.php
Normal file
67
src/pocketmine/utils/SerializedImage.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?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\utils;
|
||||
|
||||
class SerializedImage{
|
||||
|
||||
/** @var int */
|
||||
private $height;
|
||||
/** @var int */
|
||||
private $width;
|
||||
/** @var string */
|
||||
private $data;
|
||||
|
||||
public function __construct(int $height, int $width, string $data){
|
||||
$this->height = $height;
|
||||
$this->width = $width;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public static function fromLegacy(string $data) : SerializedImage{
|
||||
switch(strlen($data)){
|
||||
case 64 * 32 * 4:
|
||||
return new self(64, 32, $data);
|
||||
case 64 * 64 * 4:
|
||||
return new self(64, 64, $data);
|
||||
case 128 * 64 * 4:
|
||||
return new self(128, 64, $data);
|
||||
case 128 * 128 * 4:
|
||||
return new self(128, 128, $data);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Unknown size");
|
||||
}
|
||||
|
||||
public function getHeight() : int{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
public function getWidth() : int{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
public function getData() : string{
|
||||
return $this->data;
|
||||
}
|
||||
}
|
52
src/pocketmine/utils/SkinAnimation.php
Normal file
52
src/pocketmine/utils/SkinAnimation.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?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\utils;
|
||||
|
||||
class SkinAnimation{
|
||||
|
||||
/** @var SerializedImage */
|
||||
private $image;
|
||||
/** @var int */
|
||||
private $type;
|
||||
/** @var float */
|
||||
private $frames;
|
||||
|
||||
public function __construct(SerializedImage $image, int $type, float $frames){
|
||||
$this->image = $image;
|
||||
$this->type = $type;
|
||||
$this->frames = $frames;
|
||||
}
|
||||
|
||||
public function getImage() : SerializedImage{
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function getType() : int{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getFrames() : float{
|
||||
return $this->frames;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user