From 27324a3aebe36d99b03ae2f3114a135c96a49892 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 22 Sep 2021 00:22:58 +0100 Subject: [PATCH 1/3] Protocol changes for 1.17.30 --- src/pocketmine/Player.php | 10 +- .../network/mcpe/NetworkBinaryStream.php | 18 ++-- .../network/mcpe/NetworkSession.php | 20 ++++ .../mcpe/protocol/ActorPickRequestPacket.php | 4 + .../mcpe/protocol/AddVolumeEntityPacket.php | 9 +- .../mcpe/protocol/AnimateEntityPacket.php | 9 +- .../mcpe/protocol/CraftingDataPacket.php | 24 +++++ .../mcpe/protocol/CreatePhotoPacket.php | 69 +++++++++++++ .../mcpe/protocol/EduUriResourcePacket.php | 55 +++++++++++ .../mcpe/protocol/EducationSettingsPacket.php | 60 +++++++++++- .../network/mcpe/protocol/HurtArmorPacket.php | 4 + .../network/mcpe/protocol/PacketPool.php | 4 + .../mcpe/protocol/PhotoInfoRequestPacket.php | 52 ++++++++++ .../mcpe/protocol/PhotoTransferPacket.php | 16 +++ .../network/mcpe/protocol/ProtocolInfo.php | 10 +- .../network/mcpe/protocol/StartGamePacket.php | 5 + .../protocol/UpdateSubChunkBlocksPacket.php | 97 +++++++++++++++++++ .../EducationSettingsAgentCapabilities.php | 51 ++++++++++ .../EducationSettingsExternalLinkSettings.php | 52 ++++++++++ .../protocol/types/EducationUriResource.php | 51 ++++++++++ .../protocol/types/MaterialReducerRecipe.php | 52 ++++++++++ .../types/MaterialReducerRecipeOutput.php | 39 ++++++++ .../network/mcpe/protocol/types/SkinData.php | 54 ++++++----- .../types/UpdateSubChunkBlocksPacketEntry.php | 88 +++++++++++++++++ src/pocketmine/resources/vanilla | 2 +- 25 files changed, 815 insertions(+), 40 deletions(-) create mode 100644 src/pocketmine/network/mcpe/protocol/CreatePhotoPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/EduUriResourcePacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/PhotoInfoRequestPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/UpdateSubChunkBlocksPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/types/EducationSettingsAgentCapabilities.php create mode 100644 src/pocketmine/network/mcpe/protocol/types/EducationSettingsExternalLinkSettings.php create mode 100644 src/pocketmine/network/mcpe/protocol/types/EducationUriResource.php create mode 100644 src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipe.php create mode 100644 src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipeOutput.php create mode 100644 src/pocketmine/network/mcpe/protocol/types/UpdateSubChunkBlocksPacketEntry.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 24ca53d3d..f08f704ae 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -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{ diff --git a/src/pocketmine/network/mcpe/NetworkBinaryStream.php b/src/pocketmine/network/mcpe/NetworkBinaryStream.php index c1307369d..9fa3506c1 100644 --- a/src/pocketmine/network/mcpe/NetworkBinaryStream.php +++ b/src/pocketmine/network/mcpe/NetworkBinaryStream.php @@ -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{ diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index f79df6c77..c0584ddb4 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -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; + } } diff --git a/src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php b/src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php index ed9a913c0..ecb07296f 100644 --- a/src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php @@ -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{ diff --git a/src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php b/src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php index a95e54df0..033c3c1e5 100644 --- a/src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php @@ -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{ diff --git a/src/pocketmine/network/mcpe/protocol/AnimateEntityPacket.php b/src/pocketmine/network/mcpe/protocol/AnimateEntityPacket.php index 18874081b..453437665 100644 --- a/src/pocketmine/network/mcpe/protocol/AnimateEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AnimateEntityPacket.php @@ -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 $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)); diff --git a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php index 84c795a2c..8714616c4 100644 --- a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php @@ -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); } diff --git a/src/pocketmine/network/mcpe/protocol/CreatePhotoPacket.php b/src/pocketmine/network/mcpe/protocol/CreatePhotoPacket.php new file mode 100644 index 000000000..ab9fb9205 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/CreatePhotoPacket.php @@ -0,0 +1,69 @@ + + +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); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/EduUriResourcePacket.php b/src/pocketmine/network/mcpe/protocol/EduUriResourcePacket.php new file mode 100644 index 000000000..a4ee92f8b --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/EduUriResourcePacket.php @@ -0,0 +1,55 @@ + + +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); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/EducationSettingsPacket.php b/src/pocketmine/network/mcpe/protocol/EducationSettingsPacket.php index 3ca1bbf93..a53f687ed 100644 --- a/src/pocketmine/network/mcpe/protocol/EducationSettingsPacket.php +++ b/src/pocketmine/network/mcpe/protocol/EducationSettingsPacket.php @@ -26,6 +26,8 @@ namespace pocketmine\network\mcpe\protocol; #include 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{ diff --git a/src/pocketmine/network/mcpe/protocol/HurtArmorPacket.php b/src/pocketmine/network/mcpe/protocol/HurtArmorPacket.php index e098cf22a..51078ce81 100644 --- a/src/pocketmine/network/mcpe/protocol/HurtArmorPacket.php +++ b/src/pocketmine/network/mcpe/protocol/HurtArmorPacket.php @@ -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{ diff --git a/src/pocketmine/network/mcpe/protocol/PacketPool.php b/src/pocketmine/network/mcpe/protocol/PacketPool.php index 3d6db709d..531db9052 100644 --- a/src/pocketmine/network/mcpe/protocol/PacketPool.php +++ b/src/pocketmine/network/mcpe/protocol/PacketPool.php @@ -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()); } /** diff --git a/src/pocketmine/network/mcpe/protocol/PhotoInfoRequestPacket.php b/src/pocketmine/network/mcpe/protocol/PhotoInfoRequestPacket.php new file mode 100644 index 000000000..a13783172 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/PhotoInfoRequestPacket.php @@ -0,0 +1,52 @@ + + +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); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/PhotoTransferPacket.php b/src/pocketmine/network/mcpe/protocol/PhotoTransferPacket.php index 8d42c3837..1d3194b9e 100644 --- a/src/pocketmine/network/mcpe/protocol/PhotoTransferPacket.php +++ b/src/pocketmine/network/mcpe/protocol/PhotoTransferPacket.php @@ -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{ diff --git a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php index c582f874f..7d1cbc077 100644 --- a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php +++ b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php @@ -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; } diff --git a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php index 58d04a7cb..df3de9e1e 100644 --- a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php +++ b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php @@ -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); diff --git a/src/pocketmine/network/mcpe/protocol/UpdateSubChunkBlocksPacket.php b/src/pocketmine/network/mcpe/protocol/UpdateSubChunkBlocksPacket.php new file mode 100644 index 000000000..3512e0d61 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/UpdateSubChunkBlocksPacket.php @@ -0,0 +1,97 @@ + + +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); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/EducationSettingsAgentCapabilities.php b/src/pocketmine/network/mcpe/protocol/types/EducationSettingsAgentCapabilities.php new file mode 100644 index 000000000..bb1aaef0f --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/EducationSettingsAgentCapabilities.php @@ -0,0 +1,51 @@ +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); + } + } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/EducationSettingsExternalLinkSettings.php b/src/pocketmine/network/mcpe/protocol/types/EducationSettingsExternalLinkSettings.php new file mode 100644 index 000000000..56cca2360 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/EducationSettingsExternalLinkSettings.php @@ -0,0 +1,52 @@ +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); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/EducationUriResource.php b/src/pocketmine/network/mcpe/protocol/types/EducationUriResource.php new file mode 100644 index 000000000..9633a7842 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/EducationUriResource.php @@ -0,0 +1,51 @@ +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); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipe.php b/src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipe.php new file mode 100644 index 000000000..057c2124c --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipe.php @@ -0,0 +1,52 @@ + + */ + private array $outputs; + + /** + * @param MaterialReducerRecipeOutput[] $outputs + * @phpstan-param list $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; } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipeOutput.php b/src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipeOutput.php new file mode 100644 index 000000000..4d06366c0 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/MaterialReducerRecipeOutput.php @@ -0,0 +1,39 @@ +itemId = $itemId; + $this->count = $count; + } + + public function getItemId() : int{ return $this->itemId; } + + public function getCount() : int{ return $this->count; } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/SkinData.php b/src/pocketmine/network/mcpe/protocol/types/SkinData.php index 1ef9c43f9..2291646be 100644 --- a/src/pocketmine/network/mcpe/protocol/types/SkinData.php +++ b/src/pocketmine/network/mcpe/protocol/types/SkinData.php @@ -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; } diff --git a/src/pocketmine/network/mcpe/protocol/types/UpdateSubChunkBlocksPacketEntry.php b/src/pocketmine/network/mcpe/protocol/types/UpdateSubChunkBlocksPacketEntry.php new file mode 100644 index 000000000..01c5915f2 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/UpdateSubChunkBlocksPacketEntry.php @@ -0,0 +1,88 @@ +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); + } +} diff --git a/src/pocketmine/resources/vanilla b/src/pocketmine/resources/vanilla index 21ec07f14..19569dd72 160000 --- a/src/pocketmine/resources/vanilla +++ b/src/pocketmine/resources/vanilla @@ -1 +1 @@ -Subproject commit 21ec07f14e258d10475a714d77cbdcb7284745ec +Subproject commit 19569dd729970e161a24b574b41c06a5e064ab81 From 7f1b2a0ee57457f523b4647abe6b279765ff8980 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 22 Sep 2021 00:29:24 +0100 Subject: [PATCH 2/3] Release 3.23.0 --- changelogs/3.23.md | 11 +++++++++++ src/pocketmine/VersionInfo.php | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 changelogs/3.23.md diff --git a/changelogs/3.23.md b/changelogs/3.23.md new file mode 100644 index 000000000..216ac2f95 --- /dev/null +++ b/changelogs/3.23.md @@ -0,0 +1,11 @@ +**For Minecraft: Bedrock Edition 1.17.30** + +### 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.23.0 +- Added support for Minecraft: Bedrock Edition 1.17.30. +- Removed compatibility with earlier versions. diff --git a/src/pocketmine/VersionInfo.php b/src/pocketmine/VersionInfo.php index 1bd8f91f4..d5c60d156 100644 --- a/src/pocketmine/VersionInfo.php +++ b/src/pocketmine/VersionInfo.php @@ -33,7 +33,7 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){ const _VERSION_INFO_INCLUDED = true; const NAME = "PocketMine-MP"; -const BASE_VERSION = "3.22.6"; -const IS_DEVELOPMENT_BUILD = true; +const BASE_VERSION = "3.23.0"; +const IS_DEVELOPMENT_BUILD = false; const BUILD_NUMBER = 0; -const BUILD_CHANNEL = ""; +const BUILD_CHANNEL = "stable"; From ceeef7c72997dd806c22241fae66c83224cc1b06 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 22 Sep 2021 00:29:24 +0100 Subject: [PATCH 3/3] 3.23.1 is next --- src/pocketmine/VersionInfo.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pocketmine/VersionInfo.php b/src/pocketmine/VersionInfo.php index d5c60d156..7b8ea6fe0 100644 --- a/src/pocketmine/VersionInfo.php +++ b/src/pocketmine/VersionInfo.php @@ -33,7 +33,7 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){ const _VERSION_INFO_INCLUDED = true; const NAME = "PocketMine-MP"; -const BASE_VERSION = "3.23.0"; -const IS_DEVELOPMENT_BUILD = false; +const BASE_VERSION = "3.23.1"; +const IS_DEVELOPMENT_BUILD = true; const BUILD_NUMBER = 0; -const BUILD_CHANNEL = "stable"; +const BUILD_CHANNEL = "";