From 57d274901d4a0ca65881f7199af85ee2e5d0820f Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 8 Jun 2021 19:40:28 +0100 Subject: [PATCH] Protocol changes for 1.17.0 --- src/pocketmine/Player.php | 2 + .../network/mcpe/NetworkBinaryStream.php | 12 ++-- .../network/mcpe/NetworkSession.php | 15 +++++ .../network/mcpe/convert/ItemTranslator.php | 9 ++- .../mcpe/protocol/AddVolumeEntityPacket.php | 64 +++++++++++++++++++ .../mcpe/protocol/GameRulesChangedPacket.php | 2 +- .../network/mcpe/protocol/PacketPool.php | 3 + .../network/mcpe/protocol/ProtocolInfo.php | 9 ++- .../protocol/RemoveVolumeEntityPacket.php | 55 ++++++++++++++++ .../network/mcpe/protocol/StartGamePacket.php | 8 ++- .../mcpe/protocol/SyncActorPropertyPacket.php | 57 +++++++++++++++++ src/pocketmine/resources/vanilla | 2 +- tests/phpstan/configs/l7-baseline.neon | 12 +++- 13 files changed, 235 insertions(+), 15 deletions(-) create mode 100644 src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/RemoveVolumeEntityPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/SyncActorPropertyPacket.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 43fe198dc..7c1cdf838 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -215,6 +215,7 @@ use function min; use function preg_match; use function round; use function spl_object_hash; +use function sprintf; use function sqrt; use function strlen; use function strpos; @@ -2279,6 +2280,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $pk->experiments = new Experiments([], false); $pk->itemTable = ItemTypeDictionary::getInstance()->getEntries(); $pk->playerMovementSettings = new PlayerMovementSettings(PlayerMovementType::LEGACY, 0, false); + $pk->serverSoftwareVersion = sprintf("%s %s", \pocketmine\NAME, \pocketmine\VERSION); $this->dataPacket($pk); $this->sendDataPacket(new AvailableActorIdentifiersPacket()); diff --git a/src/pocketmine/network/mcpe/NetworkBinaryStream.php b/src/pocketmine/network/mcpe/NetworkBinaryStream.php index c124c95b4..c1307369d 100644 --- a/src/pocketmine/network/mcpe/NetworkBinaryStream.php +++ b/src/pocketmine/network/mcpe/NetworkBinaryStream.php @@ -671,14 +671,15 @@ class NetworkBinaryStream extends BinaryStream{ * Reads gamerules * TODO: implement this properly * - * @return mixed[][], members are in the structure [name => [type, value]] - * @phpstan-return array + * @return mixed[][], members are in the structure [name => [type, value, isPlayerModifiable]] + * @phpstan-return array */ public function getGameRules() : array{ $count = $this->getUnsignedVarInt(); $rules = []; for($i = 0; $i < $count; ++$i){ $name = $this->getString(); + $isPlayerModifiable = $this->getBool(); $type = $this->getUnsignedVarInt(); $value = null; switch($type){ @@ -693,23 +694,24 @@ class NetworkBinaryStream extends BinaryStream{ break; } - $rules[$name] = [$type, $value]; + $rules[$name] = [$type, $value, $isPlayerModifiable]; } return $rules; } /** - * Writes a gamerule array, members should be in the structure [name => [type, value]] + * Writes a gamerule array, members should be in the structure [name => [type, value, isPlayerModifiable]] * TODO: implement this properly * * @param mixed[][] $rules - * @phpstan-param array $rules + * @phpstan-param array $rules */ public function putGameRules(array $rules) : void{ $this->putUnsignedVarInt(count($rules)); foreach($rules as $name => $rule){ $this->putString($name); + $this->putBool($rule[2]); $this->putUnsignedVarInt($rule[0]); switch($rule[0]){ case GameRuleType::BOOL: diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index f9b77f8fe..a3bfb13b7 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -31,6 +31,7 @@ use pocketmine\network\mcpe\protocol\AddEntityPacket; use pocketmine\network\mcpe\protocol\AddItemActorPacket; use pocketmine\network\mcpe\protocol\AddPaintingPacket; use pocketmine\network\mcpe\protocol\AddPlayerPacket; +use pocketmine\network\mcpe\protocol\AddVolumeEntityPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AnimateEntityPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; @@ -130,6 +131,7 @@ use pocketmine\network\mcpe\protocol\PurchaseReceiptPacket; use pocketmine\network\mcpe\protocol\RemoveActorPacket; use pocketmine\network\mcpe\protocol\RemoveEntityPacket; use pocketmine\network\mcpe\protocol\RemoveObjectivePacket; +use pocketmine\network\mcpe\protocol\RemoveVolumeEntityPacket; use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket; use pocketmine\network\mcpe\protocol\ResourcePackChunkDataPacket; use pocketmine\network\mcpe\protocol\ResourcePackChunkRequestPacket; @@ -172,6 +174,7 @@ use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket; use pocketmine\network\mcpe\protocol\StructureTemplateDataRequestPacket; use pocketmine\network\mcpe\protocol\StructureTemplateDataResponsePacket; use pocketmine\network\mcpe\protocol\SubClientLoginPacket; +use pocketmine\network\mcpe\protocol\SyncActorPropertyPacket; use pocketmine\network\mcpe\protocol\TakeItemActorPacket; use pocketmine\network\mcpe\protocol\TextPacket; use pocketmine\network\mcpe\protocol\TickSyncPacket; @@ -826,4 +829,16 @@ abstract class NetworkSession{ public function handleClientboundDebugRenderer(ClientboundDebugRendererPacket $packet) : bool{ return false; } + + public function handleSyncActorProperty(SyncActorPropertyPacket $packet) : bool{ + return false; + } + + public function handleAddVolumeEntity(AddVolumeEntityPacket $packet) : bool{ + return false; + } + + public function handleRemoveVolumeEntity(RemoveVolumeEntityPacket $packet) : bool{ + return false; + } } diff --git a/src/pocketmine/network/mcpe/convert/ItemTranslator.php b/src/pocketmine/network/mcpe/convert/ItemTranslator.php index 530f4af4c..7e68a46fb 100644 --- a/src/pocketmine/network/mcpe/convert/ItemTranslator.php +++ b/src/pocketmine/network/mcpe/convert/ItemTranslator.php @@ -85,6 +85,10 @@ final class ItemTranslator{ if(!is_string($oldId) || !is_string($newId)){ throw new AssumptionFailedError("Invalid item table format"); } + if(!isset($legacyStringToIntMap[$oldId])){ + //new item without a fixed legacy ID - we can't handle this right now + continue; + } $simpleMappings[$newId] = $legacyStringToIntMap[$oldId]; } foreach($legacyStringToIntMap as $stringId => $intId){ @@ -128,8 +132,9 @@ final class ItemTranslator{ }elseif(isset($simpleMappings[$stringId])){ $this->simpleCoreToNetMapping[$simpleMappings[$stringId]] = $netId; $this->simpleNetToCoreMapping[$netId] = $simpleMappings[$stringId]; - }elseif($stringId !== "minecraft:unknown"){ - throw new \InvalidArgumentException("Unmapped entry " . $stringId); + }else{ + //not all items have a legacy mapping - for now, we only support the ones that do + continue; } } } diff --git a/src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php b/src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php new file mode 100644 index 000000000..a95e54df0 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php @@ -0,0 +1,64 @@ + + +use pocketmine\nbt\NetworkLittleEndianNBTStream; +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\network\mcpe\NetworkSession; + +class AddVolumeEntityPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::ADD_VOLUME_ENTITY_PACKET; + + /** @var int */ + private $entityNetId; + /** @var CompoundTag */ + private $data; + + public static function create(int $entityNetId, CompoundTag $data) : self{ + $result = new self; + $result->entityNetId = $entityNetId; + $result->data = $data; + return $result; + } + + public function getEntityNetId() : int{ return $this->entityNetId; } + + public function getData() : CompoundTag{ return $this->data; } + + protected function decodePayload() : void{ + $this->entityNetId = $this->getUnsignedVarInt(); + $this->data = $this->getNbtCompoundRoot(); + } + + protected function encodePayload() : void{ + $this->putUnsignedVarInt($this->entityNetId); + $this->put((new NetworkLittleEndianNBTStream())->write($this->data)); + } + + public function handle(NetworkSession $handler) : bool{ + return $handler->handleAddVolumeEntity($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/GameRulesChangedPacket.php b/src/pocketmine/network/mcpe/protocol/GameRulesChangedPacket.php index 6c59c1672..c099dfbd8 100644 --- a/src/pocketmine/network/mcpe/protocol/GameRulesChangedPacket.php +++ b/src/pocketmine/network/mcpe/protocol/GameRulesChangedPacket.php @@ -32,7 +32,7 @@ class GameRulesChangedPacket extends DataPacket{ /** * @var mixed[][] - * @phpstan-var array + * @phpstan-var array */ public $gameRules = []; diff --git a/src/pocketmine/network/mcpe/protocol/PacketPool.php b/src/pocketmine/network/mcpe/protocol/PacketPool.php index d91cf2ae2..83e6531de 100644 --- a/src/pocketmine/network/mcpe/protocol/PacketPool.php +++ b/src/pocketmine/network/mcpe/protocol/PacketPool.php @@ -195,6 +195,9 @@ class PacketPool{ static::registerPacket(new ItemComponentPacket()); static::registerPacket(new FilterTextPacket()); static::registerPacket(new ClientboundDebugRendererPacket()); + static::registerPacket(new SyncActorPropertyPacket()); + static::registerPacket(new AddVolumeEntityPacket()); + static::registerPacket(new RemoveVolumeEntityPacket()); } /** diff --git a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php index 8e0494ddc..2793c0ab2 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 = 431; + public const CURRENT_PROTOCOL = 440; /** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */ - public const MINECRAFT_VERSION = 'v1.16.220'; + public const MINECRAFT_VERSION = 'v1.17.0'; /** Version number sent to clients in ping responses. */ - public const MINECRAFT_VERSION_NETWORK = '1.16.220'; + public const MINECRAFT_VERSION_NETWORK = '1.17.0'; public const LOGIN_PACKET = 0x01; public const PLAY_STATUS_PACKET = 0x02; @@ -207,5 +207,8 @@ interface ProtocolInfo{ public const ITEM_COMPONENT_PACKET = 0xa2; public const FILTER_TEXT_PACKET = 0xa3; public const CLIENTBOUND_DEBUG_RENDERER_PACKET = 0xa4; + public const SYNC_ACTOR_PROPERTY_PACKET = 0xa5; + public const ADD_VOLUME_ENTITY_PACKET = 0xa6; + public const REMOVE_VOLUME_ENTITY_PACKET = 0xa7; } diff --git a/src/pocketmine/network/mcpe/protocol/RemoveVolumeEntityPacket.php b/src/pocketmine/network/mcpe/protocol/RemoveVolumeEntityPacket.php new file mode 100644 index 000000000..3f50a3a92 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/RemoveVolumeEntityPacket.php @@ -0,0 +1,55 @@ + + +use pocketmine\network\mcpe\NetworkSession; + +class RemoveVolumeEntityPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::REMOVE_VOLUME_ENTITY_PACKET; + + /** @var int */ + private $entityNetId; + + public static function create(int $entityNetId) : self{ + $result = new self; + $result->entityNetId = $entityNetId; + return $result; + } + + public function getEntityNetId() : int{ return $this->entityNetId; } + + protected function decodePayload() : void{ + $this->entityNetId = $this->getUnsignedVarInt(); + } + + protected function encodePayload() : void{ + $this->putUnsignedVarInt($this->entityNetId); + } + + public function handle(NetworkSession $handler) : bool{ + return $handler->handleRemoveVolumeEntity($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php index 8c5961102..58d04a7cb 100644 --- a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php +++ b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php @@ -104,10 +104,10 @@ class StartGamePacket extends DataPacket{ public $isTexturePacksRequired = true; /** * @var mixed[][] - * @phpstan-var array + * @phpstan-var array */ public $gameRules = [ //TODO: implement this - "naturalregeneration" => [GameRuleType::BOOL, false] //Hack for client side regeneration + "naturalregeneration" => [GameRuleType::BOOL, false, false] //Hack for client side regeneration ]; /** @var Experiments */ public $experiments; @@ -176,6 +176,8 @@ class StartGamePacket extends DataPacket{ public $itemTable; /** @var bool */ public $enableNewInventorySystem = false; //TODO + /** @var string */ + public $serverSoftwareVersion; protected function decodePayload(){ $this->entityUniqueId = $this->getEntityUniqueId(); @@ -258,6 +260,7 @@ class StartGamePacket extends DataPacket{ $this->multiplayerCorrelationId = $this->getString(); $this->enableNewInventorySystem = $this->getBool(); + $this->serverSoftwareVersion = $this->getString(); } protected function encodePayload(){ @@ -337,6 +340,7 @@ class StartGamePacket extends DataPacket{ $this->putString($this->multiplayerCorrelationId); $this->putBool($this->enableNewInventorySystem); + $this->putString($this->serverSoftwareVersion); } public function handle(NetworkSession $session) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/SyncActorPropertyPacket.php b/src/pocketmine/network/mcpe/protocol/SyncActorPropertyPacket.php new file mode 100644 index 000000000..e95e50850 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/SyncActorPropertyPacket.php @@ -0,0 +1,57 @@ + + +use pocketmine\nbt\NetworkLittleEndianNBTStream; +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\network\mcpe\NetworkSession; + +class SyncActorPropertyPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::SYNC_ACTOR_PROPERTY_PACKET; + + /** @var CompoundTag */ + private $data; + + public static function create(CompoundTag $data) : self{ + $result = new self; + $result->data = $data; + return $result; + } + + public function getData() : CompoundTag{ return $this->data; } + + protected function decodePayload() : void{ + $this->data = $this->getNbtCompoundRoot(); + } + + protected function encodePayload() : void{ + $this->put((new NetworkLittleEndianNBTStream())->write($this->data)); + } + + public function handle(NetworkSession $handler) : bool{ + return $handler->handleSyncActorProperty($this); + } +} diff --git a/src/pocketmine/resources/vanilla b/src/pocketmine/resources/vanilla index 989e02a63..04c846c5f 160000 --- a/src/pocketmine/resources/vanilla +++ b/src/pocketmine/resources/vanilla @@ -1 +1 @@ -Subproject commit 989e02a6318b1278fda8526dd136749b9b7b34b4 +Subproject commit 04c846c5f95a7bb9ae111f699f2ba08c9ec838aa diff --git a/tests/phpstan/configs/l7-baseline.neon b/tests/phpstan/configs/l7-baseline.neon index 366618a18..593bcc369 100644 --- a/tests/phpstan/configs/l7-baseline.neon +++ b/tests/phpstan/configs/l7-baseline.neon @@ -581,7 +581,7 @@ parameters: path: ../../../src/pocketmine/level/generator/object/TallGrass.php - - message: "#^Method pocketmine\\\\network\\\\mcpe\\\\NetworkBinaryStream\\:\\:getGameRules\\(\\) should return array\\ but returns array\\\\.$#" + message: "#^Method pocketmine\\\\network\\\\mcpe\\\\NetworkBinaryStream\\:\\:getGameRules\\(\\) should return array\\ but returns array\\\\.$#" count: 1 path: ../../../src/pocketmine/network/mcpe/NetworkBinaryStream.php @@ -635,6 +635,11 @@ parameters: count: 1 path: ../../../src/pocketmine/network/mcpe/convert/RuntimeBlockMapping.php + - + message: "#^Parameter \\#1 \\$str of method pocketmine\\\\utils\\\\BinaryStream\\:\\:put\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: ../../../src/pocketmine/network/mcpe/protocol/AddVolumeEntityPacket.php + - message: "#^Parameter \\#1 \\$str of method pocketmine\\\\utils\\\\BinaryStream\\:\\:put\\(\\) expects string, string\\|false given\\.$#" count: 1 @@ -680,6 +685,11 @@ parameters: count: 1 path: ../../../src/pocketmine/network/mcpe/protocol/StartGamePacket.php + - + message: "#^Parameter \\#1 \\$str of method pocketmine\\\\utils\\\\BinaryStream\\:\\:put\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: ../../../src/pocketmine/network/mcpe/protocol/SyncActorPropertyPacket.php + - message: "#^Parameter \\#3 \\$resourcePatch of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinData constructor expects string, string\\|false given\\.$#" count: 1