Protocol changes for 1.17.30

This commit is contained in:
Dylan K. Taylor 2021-09-22 00:22:58 +01:00
parent 33b5da3749
commit 27324a3aeb
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
25 changed files with 815 additions and 40 deletions

View File

@ -1976,17 +1976,19 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
base64_decode($packet->clientData["CapeData"] ?? "", true)
),
base64_decode($packet->clientData["SkinGeometryData"] ?? "", true),
base64_decode($packet->clientData["SkinGeometryDataEngineVersion"], true),
base64_decode($packet->clientData["SkinAnimationData"] ?? "", true),
$packet->clientData["PremiumSkin"] ?? false,
$packet->clientData["PersonaSkin"] ?? false,
$packet->clientData["CapeOnClassicSkin"] ?? false,
$packet->clientData["CapeId"] ?? "",
null,
$packet->clientData["ArmSize"] ?? SkinData::ARM_SIZE_WIDE,
$packet->clientData["SkinColor"] ?? "",
$personaPieces,
$pieceTintColors,
true
true,
$packet->clientData["PremiumSkin"] ?? false,
$packet->clientData["PersonaSkin"] ?? false,
$packet->clientData["CapeOnClassicSkin"] ?? false,
true, //assume this is true? there's no field for it ...
);
try{

View File

@ -105,10 +105,8 @@ class NetworkBinaryStream extends BinaryStream{
}
$capeData = $this->getSkinImage();
$geometryData = $this->getString();
$geometryDataVersion = $this->getString();
$animationData = $this->getString();
$premium = $this->getBool();
$persona = $this->getBool();
$capeOnClassic = $this->getBool();
$capeId = $this->getString();
$fullSkinId = $this->getString();
$armSize = $this->getString();
@ -137,8 +135,12 @@ class NetworkBinaryStream extends BinaryStream{
$colors
);
}
$premium = $this->getBool();
$persona = $this->getBool();
$capeOnClassic = $this->getBool();
$isPrimaryUser = $this->getBool();
return new SkinData($skinId, $skinPlayFabId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $animationData, $premium, $persona, $capeOnClassic, $capeId, $fullSkinId, $armSize, $skinColor, $personaPieces, $pieceTintColors);
return new SkinData($skinId, $skinPlayFabId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $geometryDataVersion, $animationData, $capeId, $fullSkinId, $armSize, $skinColor, $personaPieces, $pieceTintColors, true, $premium, $persona, $capeOnClassic, $isPrimaryUser);
}
/**
@ -158,10 +160,8 @@ class NetworkBinaryStream extends BinaryStream{
}
$this->putSkinImage($skin->getCapeImage());
$this->putString($skin->getGeometryData());
$this->putString($skin->getGeometryDataEngineVersion());
$this->putString($skin->getAnimationData());
$this->putBool($skin->isPremium());
$this->putBool($skin->isPersona());
$this->putBool($skin->isPersonaCapeOnClassic());
$this->putString($skin->getCapeId());
$this->putString($skin->getFullSkinId());
$this->putString($skin->getArmSize());
@ -182,6 +182,10 @@ class NetworkBinaryStream extends BinaryStream{
$this->putString($color);
}
}
$this->putBool($skin->isPremium());
$this->putBool($skin->isPersona());
$this->putBool($skin->isPersonaCapeOnClassic());
$this->putBool($skin->isPrimaryUser());
}
private function getSkinImage() : SkinImage{

View File

@ -66,11 +66,13 @@ use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
use pocketmine\network\mcpe\protocol\CorrectPlayerMovePredictionPacket;
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\CreatePhotoPacket;
use pocketmine\network\mcpe\protocol\CreativeContentPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DebugInfoPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\EducationSettingsPacket;
use pocketmine\network\mcpe\protocol\EduUriResourcePacket;
use pocketmine\network\mcpe\protocol\EmoteListPacket;
use pocketmine\network\mcpe\protocol\EmotePacket;
use pocketmine\network\mcpe\protocol\EventPacket;
@ -114,6 +116,7 @@ use pocketmine\network\mcpe\protocol\NpcDialoguePacket;
use pocketmine\network\mcpe\protocol\NpcRequestPacket;
use pocketmine\network\mcpe\protocol\OnScreenTextureAnimationPacket;
use pocketmine\network\mcpe\protocol\PacketViolationWarningPacket;
use pocketmine\network\mcpe\protocol\PhotoInfoRequestPacket;
use pocketmine\network\mcpe\protocol\PhotoTransferPacket;
use pocketmine\network\mcpe\protocol\PlayerActionPacket;
use pocketmine\network\mcpe\protocol\PlayerArmorDamagePacket;
@ -187,6 +190,7 @@ use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket;
use pocketmine\network\mcpe\protocol\UpdateEquipPacket;
use pocketmine\network\mcpe\protocol\UpdatePlayerGameTypePacket;
use pocketmine\network\mcpe\protocol\UpdateSoftEnumPacket;
use pocketmine\network\mcpe\protocol\UpdateSubChunkBlocksPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket;
abstract class NetworkSession{
@ -851,4 +855,20 @@ abstract class NetworkSession{
public function handleNpcDialogue(NpcDialoguePacket $packet) : bool{
return false;
}
public function handleEduUriResource(EduUriResourcePacket $packet) : bool{
return false;
}
public function handleCreatePhoto(CreatePhotoPacket $packet) : bool{
return false;
}
public function handleUpdateSubChunkBlocks(UpdateSubChunkBlocksPacket $packet) : bool{
return false;
}
public function handlePhotoInfoRequest(PhotoInfoRequestPacket $packet) : bool{
return false;
}
}

View File

@ -34,15 +34,19 @@ class ActorPickRequestPacket extends DataPacket{
public $entityUniqueId;
/** @var int */
public $hotbarSlot;
/** @var bool */
public $addUserData;
protected function decodePayload(){
$this->entityUniqueId = $this->getLLong();
$this->hotbarSlot = $this->getByte();
$this->addUserData = $this->getBool();
}
protected function encodePayload(){
$this->putLLong($this->entityUniqueId);
$this->putByte($this->hotbarSlot);
$this->putBool($this->addUserData);
}
public function handle(NetworkSession $session) : bool{

View File

@ -36,11 +36,14 @@ class AddVolumeEntityPacket extends DataPacket{
private $entityNetId;
/** @var CompoundTag */
private $data;
/** @var string */
private $engineVersion;
public static function create(int $entityNetId, CompoundTag $data) : self{
public static function create(int $entityNetId, CompoundTag $data, string $engineVersion) : self{
$result = new self;
$result->entityNetId = $entityNetId;
$result->data = $data;
$result->engineVersion = $engineVersion;
return $result;
}
@ -48,14 +51,18 @@ class AddVolumeEntityPacket extends DataPacket{
public function getData() : CompoundTag{ return $this->data; }
public function getEngineVersion() : string{ return $this->engineVersion; }
protected function decodePayload() : void{
$this->entityNetId = $this->getUnsignedVarInt();
$this->data = $this->getNbtCompoundRoot();
$this->engineVersion = $this->getString();
}
protected function encodePayload() : void{
$this->putUnsignedVarInt($this->entityNetId);
$this->put((new NetworkLittleEndianNBTStream())->write($this->data));
$this->putString($this->engineVersion);
}
public function handle(NetworkSession $handler) : bool{

View File

@ -37,6 +37,8 @@ class AnimateEntityPacket extends DataPacket/* implements ClientboundPacket*/{
private $nextState;
/** @var string */
private $stopExpression;
/** @var int */
private $stopExpressionVersion;
/** @var string */
private $controller;
/** @var float */
@ -51,11 +53,12 @@ class AnimateEntityPacket extends DataPacket/* implements ClientboundPacket*/{
* @param int[] $actorRuntimeIds
* @phpstan-param list<int> $actorRuntimeIds
*/
public static function create(string $animation, string $nextState, string $stopExpression, string $controller, float $blendOutTime, array $actorRuntimeIds) : self{
public static function create(string $animation, string $nextState, string $stopExpression, int $stopExpressionVersion, string $controller, float $blendOutTime, array $actorRuntimeIds) : self{
$result = new self;
$result->animation = $animation;
$result->nextState = $nextState;
$result->stopExpression = $stopExpression;
$result->stopExpressionVersion = $stopExpressionVersion;
$result->controller = $controller;
$result->blendOutTime = $blendOutTime;
$result->actorRuntimeIds = $actorRuntimeIds;
@ -68,6 +71,8 @@ class AnimateEntityPacket extends DataPacket/* implements ClientboundPacket*/{
public function getStopExpression() : string{ return $this->stopExpression; }
public function getStopExpressionVersion() : int{ return $this->stopExpressionVersion; }
public function getController() : string{ return $this->controller; }
public function getBlendOutTime() : float{ return $this->blendOutTime; }
@ -82,6 +87,7 @@ class AnimateEntityPacket extends DataPacket/* implements ClientboundPacket*/{
$this->animation = $this->getString();
$this->nextState = $this->getString();
$this->stopExpression = $this->getString();
$this->stopExpressionVersion = $this->getLInt();
$this->controller = $this->getString();
$this->blendOutTime = $this->getLFloat();
$this->actorRuntimeIds = [];
@ -94,6 +100,7 @@ class AnimateEntityPacket extends DataPacket/* implements ClientboundPacket*/{
$this->putString($this->animation);
$this->putString($this->nextState);
$this->putString($this->stopExpression);
$this->putLInt($this->stopExpressionVersion);
$this->putString($this->controller);
$this->putLFloat($this->blendOutTime);
$this->putUnsignedVarInt(count($this->actorRuntimeIds));

View File

@ -32,6 +32,8 @@ use pocketmine\item\ItemFactory;
use pocketmine\network\mcpe\convert\ItemTranslator;
use pocketmine\network\mcpe\NetworkBinaryStream;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\MaterialReducerRecipe;
use pocketmine\network\mcpe\protocol\types\MaterialReducerRecipeOutput;
use pocketmine\network\mcpe\protocol\types\PotionContainerChangeRecipe;
use pocketmine\network\mcpe\protocol\types\PotionTypeRecipe;
#ifndef COMPILE
@ -58,6 +60,8 @@ class CraftingDataPacket extends DataPacket{
public $potionTypeRecipes = [];
/** @var PotionContainerChangeRecipe[] */
public $potionContainerRecipes = [];
/** @var MaterialReducerRecipe[] */
public $materialReducerRecipes = [];
/** @var bool */
public $cleanRecipes = false;
@ -169,6 +173,17 @@ class CraftingDataPacket extends DataPacket{
[$output, ] = ItemTranslator::getInstance()->fromNetworkId($outputIdNet, 0);
$this->potionContainerRecipes[] = new PotionContainerChangeRecipe($input, $ingredient, $output);
}
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$inputIdAndData = $this->getVarInt();
[$inputId, $inputMeta] = [$inputIdAndData >> 16, $inputIdAndData & 0x7fff];
$outputs = [];
for($j = 0, $outputCount = $this->getUnsignedVarInt(); $j < $outputCount; ++$j){
$outputItemId = $this->getVarInt();
$outputItemCount = $this->getVarInt();
$outputs[] = new MaterialReducerRecipeOutput($outputItemId, $outputItemCount);
}
$this->materialReducerRecipes[] = new MaterialReducerRecipe($inputId, $inputMeta, $outputs);
}
$this->cleanRecipes = $this->getBool();
}
@ -301,6 +316,15 @@ class CraftingDataPacket extends DataPacket{
$this->putVarInt($recipe->getIngredientItemId());
$this->putVarInt($recipe->getOutputItemId());
}
$this->putUnsignedVarInt(count($this->materialReducerRecipes));
foreach($this->materialReducerRecipes as $recipe){
$this->putVarInt(($recipe->getInputItemId() << 16) | $recipe->getInputItemMeta());
$this->putUnsignedVarInt(count($recipe->getOutputs()));
foreach($recipe->getOutputs() as $output){
$this->putVarInt($output->getItemId());
$this->putVarInt($output->getCount());
}
}
$this->putBool($this->cleanRecipes);
}

View File

@ -0,0 +1,69 @@
<?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\network\mcpe\NetworkSession;
class CreatePhotoPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::CREATE_PHOTO_PACKET;
private int $entityUniqueId;
private string $photoName;
private string $photoItemName;
public static function create(int $actorUniqueId, string $photoName, string $photoItemName) : self{
$result = new self;
$result->entityUniqueId = $actorUniqueId;
$result->photoName = $photoName;
$result->photoItemName = $photoItemName;
return $result;
}
/**
* TODO: rename this to getEntityUniqueId() on PM4 (shit architecture, thanks shoghi)
*/
public function getEntityUniqueIdField() : int{ return $this->entityUniqueId; }
public function getPhotoName() : string{ return $this->photoName; }
public function getPhotoItemName() : string{ return $this->photoItemName; }
protected function decodePayload() : void{
$this->entityUniqueId = $this->getLLong(); //why be consistent mojang ?????
$this->photoName = $this->getString();
$this->photoItemName = $this->getString();
}
protected function encodePayload() : void{
$this->putLLong($this->entityUniqueId);
$this->putString($this->photoName);
$this->putString($this->photoItemName);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleCreatePhoto($this);
}
}

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;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\EducationUriResource;
class EduUriResourcePacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::EDU_URI_RESOURCE_PACKET;
private EducationUriResource $resource;
public static function create(EducationUriResource $resource) : self{
$result = new self;
$result->resource = $resource;
return $result;
}
public function getResource() : EducationUriResource{ return $this->resource; }
protected function decodePayload() : void{
$this->resource = EducationUriResource::read($this);
}
protected function encodePayload() : void{
$this->resource->write($this);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleEduUriResource($this);
}
}

View File

@ -26,6 +26,8 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\EducationSettingsAgentCapabilities;
use pocketmine\network\mcpe\protocol\types\EducationSettingsExternalLinkSettings;
class EducationSettingsPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::EDUCATION_SETTINGS_PACKET;
@ -36,18 +38,44 @@ class EducationSettingsPacket extends DataPacket{
private $codeBuilderTitle;
/** @var bool */
private $canResizeCodeBuilder;
/** @var bool */
private $disableLegacyTitleBar;
/** @var string */
private $postProcessFilter;
/** @var string */
private $screenshotBorderResourcePath;
/** @var EducationSettingsAgentCapabilities|null */
private $agentCapabilities;
/** @var string|null */
private $codeBuilderOverrideUri;
/** @var bool */
private $hasQuiz;
/** @var EducationSettingsExternalLinkSettings|null */
private $linkSettings;
public static function create(string $codeBuilderDefaultUri, string $codeBuilderTitle, bool $canResizeCodeBuilder, ?string $codeBuilderOverrideUri, bool $hasQuiz) : self{
public static function create(
string $codeBuilderDefaultUri,
string $codeBuilderTitle,
bool $canResizeCodeBuilder,
bool $disableLegacyTitleBar,
string $postProcessFilter,
string $screenshotBorderResourcePath,
?EducationSettingsAgentCapabilities $agentCapabilities,
?string $codeBuilderOverrideUri,
bool $hasQuiz,
?EducationSettingsExternalLinkSettings $linkSettings
) : self{
$result = new self;
$result->codeBuilderDefaultUri = $codeBuilderDefaultUri;
$result->codeBuilderTitle = $codeBuilderTitle;
$result->canResizeCodeBuilder = $canResizeCodeBuilder;
$result->disableLegacyTitleBar = $disableLegacyTitleBar;
$result->postProcessFilter = $postProcessFilter;
$result->screenshotBorderResourcePath = $screenshotBorderResourcePath;
$result->agentCapabilities = $agentCapabilities;
$result->codeBuilderOverrideUri = $codeBuilderOverrideUri;
$result->hasQuiz = $hasQuiz;
$result->linkSettings = $linkSettings;
return $result;
}
@ -63,6 +91,14 @@ class EducationSettingsPacket extends DataPacket{
return $this->canResizeCodeBuilder;
}
public function disableLegacyTitleBar() : bool{ return $this->disableLegacyTitleBar; }
public function getPostProcessFilter() : string{ return $this->postProcessFilter; }
public function getScreenshotBorderResourcePath() : string{ return $this->screenshotBorderResourcePath; }
public function getAgentCapabilities() : ?EducationSettingsAgentCapabilities{ return $this->agentCapabilities; }
public function getCodeBuilderOverrideUri() : ?string{
return $this->codeBuilderOverrideUri;
}
@ -71,27 +107,49 @@ class EducationSettingsPacket extends DataPacket{
return $this->hasQuiz;
}
public function getLinkSettings() : ?EducationSettingsExternalLinkSettings{ return $this->linkSettings; }
protected function decodePayload() : void{
$this->codeBuilderDefaultUri = $this->getString();
$this->codeBuilderTitle = $this->getString();
$this->canResizeCodeBuilder = $this->getBool();
$this->disableLegacyTitleBar = $this->getBool();
$this->postProcessFilter = $this->getString();
$this->screenshotBorderResourcePath = $this->getString();
$this->agentCapabilities = $this->getBool() ? EducationSettingsAgentCapabilities::read($this) : null;
if($this->getBool()){
$this->codeBuilderOverrideUri = $this->getString();
}else{
$this->codeBuilderOverrideUri = null;
}
$this->hasQuiz = $this->getBool();
$this->linkSettings = $this->getBool() ? EducationSettingsExternalLinkSettings::read($this) : null;
}
protected function encodePayload() : void{
$this->putString($this->codeBuilderDefaultUri);
$this->putString($this->codeBuilderTitle);
$this->putBool($this->canResizeCodeBuilder);
$this->putBool($this->disableLegacyTitleBar);
$this->putString($this->postProcessFilter);
$this->putString($this->screenshotBorderResourcePath);
if($this->agentCapabilities !== null){
$this->putBool(true);
$this->agentCapabilities->write($this);
}else{
$this->putBool(false);
}
$this->putBool($this->codeBuilderOverrideUri !== null);
if($this->codeBuilderOverrideUri !== null){
$this->putString($this->codeBuilderOverrideUri);
}
$this->putBool($this->hasQuiz);
if($this->linkSettings !== null){
$this->putBool(true);
$this->linkSettings->write($this);
}else{
$this->putBool(false);
}
}
public function handle(NetworkSession $handler) : bool{

View File

@ -34,15 +34,19 @@ class HurtArmorPacket extends DataPacket{
public $cause;
/** @var int */
public $health;
/** @var int */
public $armorSlotFlags;
protected function decodePayload(){
$this->cause = $this->getVarInt();
$this->health = $this->getVarInt();
$this->armorSlotFlags = $this->getUnsignedVarLong();
}
protected function encodePayload(){
$this->putVarInt($this->cause);
$this->putVarInt($this->health);
$this->putUnsignedVarLong($this->armorSlotFlags);
}
public function handle(NetworkSession $session) : bool{

View File

@ -200,6 +200,10 @@ class PacketPool{
static::registerPacket(new RemoveVolumeEntityPacket());
static::registerPacket(new SimulationTypePacket());
static::registerPacket(new NpcDialoguePacket());
static::registerPacket(new EduUriResourcePacket());
static::registerPacket(new CreatePhotoPacket());
static::registerPacket(new UpdateSubChunkBlocksPacket());
static::registerPacket(new PhotoInfoRequestPacket());
}
/**

View 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\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\NetworkSession;
class PhotoInfoRequestPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::PHOTO_INFO_REQUEST_PACKET;
private int $photoId;
public static function create(int $photoId) : self{
$result = new self;
$result->photoId = $photoId;
return $result;
}
protected function decodePayload() : void{
$this->photoId = $this->getEntityUniqueId();
}
protected function encodePayload() : void{
$this->putEntityUniqueId($this->photoId);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handlePhotoInfoRequest($this);
}
}

View File

@ -36,17 +36,33 @@ class PhotoTransferPacket extends DataPacket{
public $photoData;
/** @var string */
public $bookId; //photos are stored in a sibling directory to the games folder (screenshots/(some UUID)/bookID/example.png)
/** @var int */
public $type;
/** @var int */
public $sourceType;
/** @var int */
public $ownerEntityUniqueId;
/** @var string */
public $newPhotoName; //???
protected function decodePayload(){
$this->photoName = $this->getString();
$this->photoData = $this->getString();
$this->bookId = $this->getString();
$this->type = $this->getByte();
$this->sourceType = $this->getByte();
$this->ownerEntityUniqueId = $this->getLLong(); //...............
$this->newPhotoName = $this->getString();
}
protected function encodePayload(){
$this->putString($this->photoName);
$this->putString($this->photoData);
$this->putString($this->bookId);
$this->putByte($this->type);
$this->putByte($this->sourceType);
$this->putLLong($this->ownerEntityUniqueId);
$this->putString($this->newPhotoName);
}
public function handle(NetworkSession $session) : bool{

View File

@ -37,11 +37,11 @@ interface ProtocolInfo{
*/
/** Actual Minecraft: PE protocol version */
public const CURRENT_PROTOCOL = 448;
public const CURRENT_PROTOCOL = 465;
/** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */
public const MINECRAFT_VERSION = 'v1.17.10';
public const MINECRAFT_VERSION = 'v1.17.30';
/** Version number sent to clients in ping responses. */
public const MINECRAFT_VERSION_NETWORK = '1.17.10';
public const MINECRAFT_VERSION_NETWORK = '1.17.30';
public const LOGIN_PACKET = 0x01;
public const PLAY_STATUS_PACKET = 0x02;
@ -212,5 +212,9 @@ interface ProtocolInfo{
public const REMOVE_VOLUME_ENTITY_PACKET = 0xa7;
public const SIMULATION_TYPE_PACKET = 0xa8;
public const NPC_DIALOGUE_PACKET = 0xa9;
public const EDU_URI_RESOURCE_PACKET = 0xaa;
public const CREATE_PHOTO_PACKET = 0xab;
public const UPDATE_SUB_CHUNK_BLOCKS_PACKET = 0xac;
public const PHOTO_INFO_REQUEST_PACKET = 0xad;
}

View File

@ -30,6 +30,7 @@ use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\BlockPaletteEntry;
use pocketmine\network\mcpe\protocol\types\EducationEditionOffer;
use pocketmine\network\mcpe\protocol\types\EducationUriResource;
use pocketmine\network\mcpe\protocol\types\Experiments;
use pocketmine\network\mcpe\protocol\types\GameRuleType;
use pocketmine\network\mcpe\protocol\types\GeneratorType;
@ -143,6 +144,8 @@ class StartGamePacket extends DataPacket{
public $limitedWorldLength = 0;
/** @var bool */
public $isNewNether = true;
/** @var EducationUriResource|null */
public $eduSharedUriResource = null;
/** @var bool|null */
public $experimentalGameplayOverride = null;
@ -227,6 +230,7 @@ class StartGamePacket extends DataPacket{
$this->limitedWorldWidth = $this->getLInt();
$this->limitedWorldLength = $this->getLInt();
$this->isNewNether = $this->getBool();
$this->eduSharedUriResource = EducationUriResource::read($this);
if($this->getBool()){
$this->experimentalGameplayOverride = $this->getBool();
}else{
@ -311,6 +315,7 @@ class StartGamePacket extends DataPacket{
$this->putLInt($this->limitedWorldWidth);
$this->putLInt($this->limitedWorldLength);
$this->putBool($this->isNewNether);
($this->eduSharedUriResource ?? new EducationUriResource("", ""))->write($this);
$this->putBool($this->experimentalGameplayOverride !== null);
if($this->experimentalGameplayOverride !== null){
$this->putBool($this->experimentalGameplayOverride);

View 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\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\UpdateSubChunkBlocksPacketEntry;
use function count;
class UpdateSubChunkBlocksPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::UPDATE_SUB_CHUNK_BLOCKS_PACKET;
private int $subChunkX;
private int $subChunkY;
private int $subChunkZ;
/** @var UpdateSubChunkBlocksPacketEntry[] */
private array $layer0Updates;
/** @var UpdateSubChunkBlocksPacketEntry[] */
private array $layer1Updates;
/**
* @param UpdateSubChunkBlocksPacketEntry[] $layer0
* @param UpdateSubChunkBlocksPacketEntry[] $layer1
*/
public static function create(int $subChunkX, int $subChunkY, int $subChunkZ, array $layer0, array $layer1) : self{
$result = new self;
$result->subChunkX = $subChunkX;
$result->subChunkY = $subChunkY;
$result->subChunkZ = $subChunkZ;
$result->layer0Updates = $layer0;
$result->layer1Updates = $layer1;
return $result;
}
public function getSubChunkX() : int{ return $this->subChunkX; }
public function getSubChunkY() : int{ return $this->subChunkY; }
public function getSubChunkZ() : int{ return $this->subChunkZ; }
/** @return UpdateSubChunkBlocksPacketEntry[] */
public function getLayer0Updates() : array{ return $this->layer0Updates; }
/** @return UpdateSubChunkBlocksPacketEntry[] */
public function getLayer1Updates() : array{ return $this->layer1Updates; }
protected function decodePayload() : void{
$this->subChunkX = $this->subChunkY = $this->subChunkZ = 0;
$this->getBlockPosition($this->subChunkX, $this->subChunkY, $this->subChunkZ);
$this->layer0Updates = [];
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$this->layer0Updates[] = UpdateSubChunkBlocksPacketEntry::read($this);
}
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$this->layer1Updates[] = UpdateSubChunkBlocksPacketEntry::read($this);
}
}
protected function encodePayload() : void{
$this->putBlockPosition($this->subChunkX, $this->subChunkY, $this->subChunkZ);
$this->putUnsignedVarInt(count($this->layer0Updates));
foreach($this->layer0Updates as $update){
$update->write($this);
}
$this->putUnsignedVarInt(count($this->layer1Updates));
foreach($this->layer1Updates as $update){
$update->write($this);
}
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleUpdateSubChunkBlocks($this);
}
}

View File

@ -0,0 +1,51 @@
<?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;
use pocketmine\network\mcpe\NetworkBinaryStream;
final class EducationSettingsAgentCapabilities{
private ?bool $canModifyBlocks;
public function __construct(?bool $canModifyBlocks){
$this->canModifyBlocks = $canModifyBlocks;
}
public function getCanModifyBlocks() : ?bool{ return $this->canModifyBlocks; }
public static function read(NetworkBinaryStream $in) : self{
$canModifyBlocks = $in->getBool() ? $in->getBool() : null;
return new self($canModifyBlocks);
}
public function write(NetworkBinaryStream $out) : void{
if($this->canModifyBlocks !== null){
$out->putBool(true);
$out->putBool($this->canModifyBlocks);
}else{
$out->putBool(false);
}
}
}

View 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\network\mcpe\protocol\types;
use pocketmine\network\mcpe\NetworkBinaryStream;
final class EducationSettingsExternalLinkSettings{
private string $displayName;
private string $url;
public function __construct(string $url, string $displayName){
$this->displayName = $displayName;
$this->url = $url;
}
public function getUrl() : string{ return $this->url; }
public function getDisplayName() : string{ return $this->displayName; }
public static function read(NetworkBinaryStream $in) : self{
$url = $in->getString();
$displayName = $in->getString();
return new self($displayName, $url);
}
public function write(NetworkBinaryStream $out) : void{
$out->putString($this->url);
$out->putString($this->displayName);
}
}

View File

@ -0,0 +1,51 @@
<?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;
use pocketmine\network\mcpe\NetworkBinaryStream;
final class EducationUriResource{
private string $buttonName;
private string $linkUri;
public function __construct(string $buttonName, string $linkUri){
$this->buttonName = $buttonName;
$this->linkUri = $linkUri;
}
public function getButtonName() : string{ return $this->buttonName; }
public function getLinkUri() : string{ return $this->linkUri; }
public static function read(NetworkBinaryStream $in) : self{
$buttonName = $in->getString();
$linkUri = $in->getString();
return new self($buttonName, $linkUri);
}
public function write(NetworkBinaryStream $out) : void{
$out->putString($this->buttonName);
$out->putString($this->linkUri);
}
}

View 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\network\mcpe\protocol\types;
final class MaterialReducerRecipe{
private int $inputItemId;
private int $inputItemMeta;
/**
* @var MaterialReducerRecipeOutput[]
* @phpstan-var list<MaterialReducerRecipeOutput>
*/
private array $outputs;
/**
* @param MaterialReducerRecipeOutput[] $outputs
* @phpstan-param list<MaterialReducerRecipeOutput> $outputs
*/
public function __construct(int $inputItemId, int $inputItemMeta, array $outputs){
$this->inputItemId = $inputItemId;
$this->inputItemMeta = $inputItemMeta;
$this->outputs = $outputs;
}
public function getInputItemId() : int{ return $this->inputItemId; }
public function getInputItemMeta() : int{ return $this->inputItemMeta; }
/** @return MaterialReducerRecipeOutput[] */
public function getOutputs() : array{ return $this->outputs; }
}

View File

@ -0,0 +1,39 @@
<?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 MaterialReducerRecipeOutput{
private int $itemId;
private int $count;
public function __construct(int $itemId, int $count){
$this->itemId = $itemId;
$this->count = $count;
}
public function getItemId() : int{ return $this->itemId; }
public function getCount() : int{ return $this->count; }
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol\types;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\utils\UUID;
class SkinData{
@ -44,14 +45,9 @@ class SkinData{
private $capeImage;
/** @var string */
private $geometryData;
private string $geometryDataEngineVersion;
/** @var string */
private $animationData;
/** @var bool */
private $persona;
/** @var bool */
private $premium;
/** @var bool */
private $personaCapeOnClassic;
/** @var string */
private $capeId;
/** @var string */
@ -66,13 +62,21 @@ class SkinData{
private $pieceTintColors;
/** @var bool */
private $isVerified;
/** @var bool */
private $persona;
/** @var bool */
private $premium;
/** @var bool */
private $personaCapeOnClassic;
/** @var bool */
private $isPrimaryUser;
/**
* @param SkinAnimation[] $animations
* @param PersonaSkinPiece[] $personaPieces
* @param PersonaPieceTintColor[] $pieceTintColors
*/
public function __construct(string $skinId, string $playFabId, 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 = true){
public function __construct(string $skinId, string $playFabId, string $resourcePatch, SkinImage $skinImage, array $animations = [], SkinImage $capeImage = null, string $geometryData = "", string $geometryDataEngineVersion = ProtocolInfo::MINECRAFT_VERSION_NETWORK, string $animationData = "", string $capeId = "", ?string $fullSkinId = null, string $armSize = self::ARM_SIZE_WIDE, string $skinColor = "", array $personaPieces = [], array $pieceTintColors = [], bool $isVerified = true, bool $premium = false, bool $persona = false, bool $personaCapeOnClassic = false, bool $isPrimaryUser = true){
$this->skinId = $skinId;
$this->playFabId = $playFabId;
$this->resourcePatch = $resourcePatch;
@ -80,10 +84,8 @@ class SkinData{
$this->animations = $animations;
$this->capeImage = $capeImage ?? new SkinImage(0, 0, "");
$this->geometryData = $geometryData;
$this->geometryDataEngineVersion = $geometryDataEngineVersion;
$this->animationData = $animationData;
$this->premium = $premium;
$this->persona = $persona;
$this->personaCapeOnClassic = $personaCapeOnClassic;
$this->capeId = $capeId;
//this has to be unique or the client will do stupid things
$this->fullSkinId = $fullSkinId ?? UUID::fromRandom()->toString();
@ -92,6 +94,10 @@ class SkinData{
$this->personaPieces = $personaPieces;
$this->pieceTintColors = $pieceTintColors;
$this->isVerified = $isVerified;
$this->premium = $premium;
$this->persona = $persona;
$this->personaCapeOnClassic = $personaCapeOnClassic;
$this->isPrimaryUser = $isPrimaryUser;
}
public function getSkinId() : string{
@ -123,22 +129,12 @@ class SkinData{
return $this->geometryData;
}
public function getGeometryDataEngineVersion() : string{ return $this->geometryDataEngineVersion; }
public function getAnimationData() : string{
return $this->animationData;
}
public function isPersona() : bool{
return $this->persona;
}
public function isPremium() : bool{
return $this->premium;
}
public function isPersonaCapeOnClassic() : bool{
return $this->personaCapeOnClassic;
}
public function getCapeId() : string{
return $this->capeId;
}
@ -169,6 +165,20 @@ class SkinData{
return $this->pieceTintColors;
}
public function isPersona() : bool{
return $this->persona;
}
public function isPremium() : bool{
return $this->premium;
}
public function isPersonaCapeOnClassic() : bool{
return $this->personaCapeOnClassic;
}
public function isPrimaryUser() : bool{ return $this->isPrimaryUser; }
public function isVerified() : bool{
return $this->isVerified;
}

View File

@ -0,0 +1,88 @@
<?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;
use pocketmine\network\mcpe\NetworkBinaryStream;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
final class UpdateSubChunkBlocksPacketEntry{
private int $x;
private int $y;
private int $z;
private int $blockRuntimeId;
private int $flags;
//These two fields are useless 99.9% of the time; they are here to allow this packet to provide UpdateBlockSyncedPacket functionality.
private int $syncedUpdateEntityUniqueId;
private int $syncedUpdateType;
public function __construct(int $x, int $y, int $z, int $blockRuntimeId, int $flags, int $syncedUpdateEntityUniqueId, int $syncedUpdateType){
$this->x = $x;
$this->y = $y;
$this->z = $z;
$this->blockRuntimeId = $blockRuntimeId;
$this->flags = $flags;
$this->syncedUpdateEntityUniqueId = $syncedUpdateEntityUniqueId;
$this->syncedUpdateType = $syncedUpdateType;
}
public static function simple(int $x, int $y, int $z, int $blockRuntimeId) : self{
return new self($x, $y, $z, $blockRuntimeId, UpdateBlockPacket::FLAG_NETWORK, 0, 0);
}
public function getX() : int{ return $this->x; }
public function getY() : int{ return $this->y; }
public function getZ() : int{ return $this->z; }
public function getBlockRuntimeId() : int{ return $this->blockRuntimeId; }
public function getFlags() : int{ return $this->flags; }
public function getSyncedUpdateEntityUniqueId() : int{ return $this->syncedUpdateEntityUniqueId; }
public function getSyncedUpdateType() : int{ return $this->syncedUpdateType; }
public static function read(NetworkBinaryStream $in) : self{
$x = $y = $z = 0;
$in->getBlockPosition($x, $y, $z);
$blockRuntimeId = $in->getUnsignedVarInt();
$updateFlags = $in->getUnsignedVarInt();
$syncedUpdateEntityUniqueId = $in->getUnsignedVarLong(); //this can't use the standard method because it's unsigned as opposed to the usual signed... !!!!!!
$syncedUpdateType = $in->getUnsignedVarInt(); //this isn't even consistent with UpdateBlockSyncedPacket?!
return new self($x, $y, $z, $blockRuntimeId, $updateFlags, $syncedUpdateEntityUniqueId, $syncedUpdateType);
}
public function write(NetworkBinaryStream $out) : void{
$out->putBlockPosition($this->x, $this->y, $this->z);
$out->putUnsignedVarInt($this->blockRuntimeId);
$out->putUnsignedVarInt($this->flags);
$out->putUnsignedVarLong($this->syncedUpdateEntityUniqueId);
$out->putUnsignedVarInt($this->syncedUpdateType);
}
}

@ -1 +1 @@
Subproject commit 21ec07f14e258d10475a714d77cbdcb7284745ec
Subproject commit 19569dd729970e161a24b574b41c06a5e064ab81