From 986077e03cc2d0caf43fee3e2566009d2089e0c2 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 15 Jun 2018 19:24:23 +0100 Subject: [PATCH 1/5] Protocol changes for 1.6.0.1 --- src/pocketmine/Player.php | 6 -- src/pocketmine/block/BlockFactory.php | 4 +- .../network/mcpe/NetworkSession.php | 15 ++++ .../network/mcpe/RakLibInterface.php | 2 +- .../network/mcpe/protocol/DataPacket.php | 7 -- .../network/mcpe/protocol/LoginPacket.php | 7 -- .../protocol/NetworkStackLatencyPacket.php | 47 +++++++++++++ .../network/mcpe/protocol/PacketPool.php | 3 + .../mcpe/protocol/PlayStatusPacket.php | 14 ---- .../network/mcpe/protocol/ProtocolInfo.php | 11 +-- .../protocol/SetScoreboardIdentityPacket.php | 69 +++++++++++++++++++ .../network/mcpe/protocol/StartGamePacket.php | 23 +++++++ .../mcpe/protocol/UpdateSoftEnumPacket.php | 64 +++++++++++++++++ .../types/ScoreboardIdentityPacketEntry.php | 34 +++++++++ src/pocketmine/resources/runtimeid_table.json | 2 +- 15 files changed, 266 insertions(+), 42 deletions(-) create mode 100644 src/pocketmine/network/mcpe/protocol/NetworkStackLatencyPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/SetScoreboardIdentityPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/UpdateSoftEnumPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/types/ScoreboardIdentityPacketEntry.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index b6ba9dd98..695ddf907 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -193,9 +193,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ */ protected $sessionAdapter; - /** @var int */ - protected $protocol = -1; - /** @var string */ protected $ip; /** @var int */ @@ -1839,8 +1836,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ return false; } - $this->protocol = $packet->protocol; - if($packet->protocol !== ProtocolInfo::CURRENT_PROTOCOL){ if($packet->protocol < ProtocolInfo::CURRENT_PROTOCOL){ $this->sendPlayStatus(PlayStatusPacket::LOGIN_FAILED_CLIENT, true); @@ -1923,7 +1918,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ public function sendPlayStatus(int $status, bool $immediate = false){ $pk = new PlayStatusPacket(); $pk->status = $status; - $pk->protocol = $this->protocol; $this->sendDataPacket($pk, false, $immediate); } diff --git a/src/pocketmine/block/BlockFactory.php b/src/pocketmine/block/BlockFactory.php index 4774b4c58..b5dee4f42 100644 --- a/src/pocketmine/block/BlockFactory.php +++ b/src/pocketmine/block/BlockFactory.php @@ -421,8 +421,8 @@ class BlockFactory{ public static function registerStaticRuntimeIdMappings() : void{ /** @var mixed[] $runtimeIdMap */ $runtimeIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "runtimeid_table.json"), true); - foreach($runtimeIdMap as $obj){ - self::registerMapping($obj["runtimeID"], $obj["id"], $obj["data"]); + foreach($runtimeIdMap as $k => $obj){ + self::registerMapping($k, $obj["id"], $obj["data"]); } } diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index 67265e947..33fa61d90 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -79,6 +79,7 @@ use pocketmine\network\mcpe\protocol\ModalFormResponsePacket; use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket; use pocketmine\network\mcpe\protocol\MoveEntityDeltaPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket; +use pocketmine\network\mcpe\protocol\NetworkStackLatencyPacket; use pocketmine\network\mcpe\protocol\NpcRequestPacket; use pocketmine\network\mcpe\protocol\PhotoTransferPacket; use pocketmine\network\mcpe\protocol\PlaySoundPacket; @@ -115,6 +116,7 @@ use pocketmine\network\mcpe\protocol\SetLastHurtByPacket; use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket; use pocketmine\network\mcpe\protocol\SetPlayerGameTypePacket; use pocketmine\network\mcpe\protocol\SetScorePacket; +use pocketmine\network\mcpe\protocol\SetScoreboardIdentityPacket; use pocketmine\network\mcpe\protocol\SetSpawnPositionPacket; use pocketmine\network\mcpe\protocol\SetTimePacket; use pocketmine\network\mcpe\protocol\SetTitlePacket; @@ -134,6 +136,7 @@ use pocketmine\network\mcpe\protocol\UpdateAttributesPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket; use pocketmine\network\mcpe\protocol\UpdateEquipPacket; +use pocketmine\network\mcpe\protocol\UpdateSoftEnumPacket; use pocketmine\network\mcpe\protocol\UpdateTradePacket; use pocketmine\network\mcpe\protocol\WSConnectPacket; @@ -585,7 +588,19 @@ abstract class NetworkSession{ return false; } + public function handleSetScoreboardIdentity(SetScoreboardIdentityPacket $packet) : bool{ + return false; + } + public function handleSetLocalPlayerAsInitialized(SetLocalPlayerAsInitializedPacket $packet) : bool{ return false; } + + public function handleUpdateSoftEnum(UpdateSoftEnumPacket $packet) : bool{ + return false; + } + + public function handleNetworkStackLatency(NetworkStackLatencyPacket $packet) : bool{ + return false; + } } diff --git a/src/pocketmine/network/mcpe/RakLibInterface.php b/src/pocketmine/network/mcpe/RakLibInterface.php index 797d015c8..db7537726 100644 --- a/src/pocketmine/network/mcpe/RakLibInterface.php +++ b/src/pocketmine/network/mcpe/RakLibInterface.php @@ -46,7 +46,7 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{ * Sometimes this gets changed when the MCPE-layer protocol gets broken to the point where old and new can't * communicate. It's important that we check this to avoid catastrophes. */ - private const MCPE_RAKNET_PROTOCOL_VERSION = 8; + private const MCPE_RAKNET_PROTOCOL_VERSION = 9; /** @var Server */ private $server; diff --git a/src/pocketmine/network/mcpe/protocol/DataPacket.php b/src/pocketmine/network/mcpe/protocol/DataPacket.php index c1b983177..87c715296 100644 --- a/src/pocketmine/network/mcpe/protocol/DataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/DataPacket.php @@ -74,10 +74,6 @@ abstract class DataPacket extends NetworkBinaryStream{ protected function decodeHeader(){ $pid = $this->getUnsignedVarInt(); assert($pid === static::NETWORK_ID); - - $this->senderSubId = $this->getByte(); - $this->recipientSubId = $this->getByte(); - assert($this->senderSubId === 0 and $this->recipientSubId === 0, "Got unexpected non-zero split-screen bytes (byte1: $this->senderSubId, byte2: $this->recipientSubId"); } /** @@ -96,9 +92,6 @@ abstract class DataPacket extends NetworkBinaryStream{ protected function encodeHeader(){ $this->putUnsignedVarInt(static::NETWORK_ID); - - $this->putByte($this->senderSubId); - $this->putByte($this->recipientSubId); } /** diff --git a/src/pocketmine/network/mcpe/protocol/LoginPacket.php b/src/pocketmine/network/mcpe/protocol/LoginPacket.php index 67c70fc12..04746709f 100644 --- a/src/pocketmine/network/mcpe/protocol/LoginPacket.php +++ b/src/pocketmine/network/mcpe/protocol/LoginPacket.php @@ -79,13 +79,6 @@ class LoginPacket extends DataPacket{ protected function decodePayload(){ $this->protocol = $this->getInt(); - if($this->protocol !== ProtocolInfo::CURRENT_PROTOCOL){ - if($this->protocol > 0xffff){ //guess MCPE <= 1.1 - $this->offset -= 6; - $this->protocol = $this->getInt(); - } - } - try{ $this->decodeConnectionRequest(); }catch(\Throwable $e){ diff --git a/src/pocketmine/network/mcpe/protocol/NetworkStackLatencyPacket.php b/src/pocketmine/network/mcpe/protocol/NetworkStackLatencyPacket.php new file mode 100644 index 000000000..ace6a90d7 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/NetworkStackLatencyPacket.php @@ -0,0 +1,47 @@ + + +use pocketmine\network\mcpe\NetworkSession; + +class NetworkStackLatencyPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::NETWORK_STACK_LATENCY_PACKET; + + /** @var int */ + public $timestamp; + + protected function decodePayload(){ + $this->timestamp = $this->getLLong(); + } + + protected function encodePayload(){ + $this->putLLong($this->timestamp); + } + + public function handle(NetworkSession $session) : bool{ + return $session->handleNetworkStackLatency($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/PacketPool.php b/src/pocketmine/network/mcpe/protocol/PacketPool.php index ac550f720..814d082a6 100644 --- a/src/pocketmine/network/mcpe/protocol/PacketPool.php +++ b/src/pocketmine/network/mcpe/protocol/PacketPool.php @@ -142,7 +142,10 @@ class PacketPool{ static::registerPacket(new LabTablePacket()); static::registerPacket(new UpdateBlockSyncedPacket()); static::registerPacket(new MoveEntityDeltaPacket()); + static::registerPacket(new SetScoreboardIdentityPacket()); static::registerPacket(new SetLocalPlayerAsInitializedPacket()); + static::registerPacket(new UpdateSoftEnumPacket()); + static::registerPacket(new NetworkStackLatencyPacket()); static::registerPacket(new BatchPacket()); } diff --git a/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php b/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php index 0dd128cbf..97e65ffb3 100644 --- a/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php +++ b/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php @@ -43,12 +43,6 @@ class PlayStatusPacket extends DataPacket{ /** @var int */ public $status; - /** - * @var int - * Used to determine how to write the packet when we disconnect incompatible clients. - */ - public $protocol = ProtocolInfo::CURRENT_PROTOCOL; - protected function decodePayload(){ $this->status = $this->getInt(); } @@ -57,14 +51,6 @@ class PlayStatusPacket extends DataPacket{ return true; } - protected function encodeHeader(){ - if($this->protocol < 130){ //MCPE <= 1.1 - $this->putByte(static::NETWORK_ID); - }else{ - parent::encodeHeader(); - } - } - protected function encodePayload(){ $this->putInt($this->status); } diff --git a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php index 6aa8957b2..8b3f3fa89 100644 --- a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php +++ b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php @@ -39,15 +39,15 @@ interface ProtocolInfo{ /** * Actual Minecraft: PE protocol version */ - public const CURRENT_PROTOCOL = 274; + public const CURRENT_PROTOCOL = 280; /** * Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */ - public const MINECRAFT_VERSION = 'v1.5.0'; + public const MINECRAFT_VERSION = 'v1.6.0.1 beta'; /** * Version number sent to clients in ping responses. */ - public const MINECRAFT_VERSION_NETWORK = '1.5.0'; + public const MINECRAFT_VERSION_NETWORK = '1.6.0.1'; public const LOGIN_PACKET = 0x01; public const PLAY_STATUS_PACKET = 0x02; @@ -160,6 +160,9 @@ interface ProtocolInfo{ public const LAB_TABLE_PACKET = 0x6d; public const UPDATE_BLOCK_SYNCED_PACKET = 0x6e; public const MOVE_ENTITY_DELTA_PACKET = 0x6f; - public const SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET = 0x70; + public const SET_SCOREBOARD_IDENTITY_PACKET = 0x70; + public const SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET = 0x71; + public const UPDATE_SOFT_ENUM_PACKET = 0x72; + public const NETWORK_STACK_LATENCY_PACKET = 0x73; } diff --git a/src/pocketmine/network/mcpe/protocol/SetScoreboardIdentityPacket.php b/src/pocketmine/network/mcpe/protocol/SetScoreboardIdentityPacket.php new file mode 100644 index 000000000..91cd54612 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/SetScoreboardIdentityPacket.php @@ -0,0 +1,69 @@ + + +use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\ScoreboardIdentityPacketEntry; + +class SetScoreboardIdentityPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::SET_SCOREBOARD_IDENTITY_PACKET; + + public const TYPE_REGISTER_IDENTITY = 0; + public const TYPE_CLEAR_IDENTITY = 1; + + /** @var int */ + public $type; + /** @var ScoreboardIdentityPacketEntry[] */ + public $entries = []; + + protected function decodePayload(){ + $this->type = $this->getByte(); + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $entry = new ScoreboardIdentityPacketEntry(); + $entry->scoreboardId = $this->getVarLong(); + if($this->type === self::TYPE_REGISTER_IDENTITY){ + $entry->uuid = $this->getUUID(); + } + + $this->entries[] = $entry; + } + } + + protected function encodePayload(){ + $this->putByte($this->type); + $this->putUnsignedVarInt(count($this->entries)); + foreach($this->entries as $entry){ + $this->putVarLong($entry->scoreboardId); + if($this->type === self::TYPE_REGISTER_IDENTITY){ + $this->putUUID($entry->uuid); + } + } + } + + public function handle(NetworkSession $session) : bool{ + return $session->handleSetScoreboardIdentity($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php index 0cea9e24e..43a7614c7 100644 --- a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php +++ b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php @@ -27,12 +27,16 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\math\Vector3; +use pocketmine\network\mcpe\NetworkBinaryStream; use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\protocol\types\PlayerPermissions; class StartGamePacket extends DataPacket{ public const NETWORK_ID = ProtocolInfo::START_GAME_PACKET; + /** @var string|null */ + private static $runtimeIdTable; + /** @var int */ public $entityUniqueId; /** @var int */ @@ -175,6 +179,12 @@ class StartGamePacket extends DataPacket{ $this->currentTick = $this->getLLong(); $this->enchantmentSeed = $this->getVarInt(); + + $count = $this->getUnsignedVarInt(); + for($i = 0; $i < $count; ++$i){ + $this->getString(); + $this->getLShort(); + } } protected function encodePayload(){ @@ -226,6 +236,19 @@ class StartGamePacket extends DataPacket{ $this->putLLong($this->currentTick); $this->putVarInt($this->enchantmentSeed); + + if(self::$runtimeIdTable === null){ + //this is a really nasty hack, but it'll do for now + $stream = new NetworkBinaryStream(); + $data = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "runtimeid_table.json"), true); + $stream->putUnsignedVarInt(count($data)); + foreach($data as $v){ + $stream->putString($v["name"]); + $stream->putLShort($v["data"]); + } + self::$runtimeIdTable = $stream->buffer; + } + $this->put(self::$runtimeIdTable); } public function handle(NetworkSession $session) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/UpdateSoftEnumPacket.php b/src/pocketmine/network/mcpe/protocol/UpdateSoftEnumPacket.php new file mode 100644 index 000000000..8fffe55d6 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/UpdateSoftEnumPacket.php @@ -0,0 +1,64 @@ + + +use pocketmine\network\mcpe\NetworkSession; + +class UpdateSoftEnumPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::UPDATE_SOFT_ENUM_PACKET; + + public const TYPE_ADD = 0; + public const TYPE_REMOVE = 1; + public const TYPE_SET = 2; + + /** @var string */ + public $enumName; + /** @var string[] */ + public $values = []; + /** @var int */ + public $type; + + protected function decodePayload(){ + $this->enumName = $this->getString(); + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $this->values[] = $this->getString(); + } + $this->type = $this->getByte(); + } + + protected function encodePayload(){ + $this->putString($this->enumName); + $this->putUnsignedVarInt(count($this->values)); + foreach($this->values as $v){ + $this->putString($v); + } + $this->putByte($this->type); + } + + public function handle(NetworkSession $session) : bool{ + return $session->handleUpdateSoftEnum($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/ScoreboardIdentityPacketEntry.php b/src/pocketmine/network/mcpe/protocol/types/ScoreboardIdentityPacketEntry.php new file mode 100644 index 000000000..416e2434d --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/ScoreboardIdentityPacketEntry.php @@ -0,0 +1,34 @@ + Date: Wed, 20 Jun 2018 17:40:36 +0100 Subject: [PATCH 2/5] AvailableCommandsPacket: deal with dynamic enums somehow I missed this, thanks @NiclasOlofsson for pointing it out --- .../mcpe/protocol/AvailableCommandsPacket.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php index 6592afe67..a885a32b3 100644 --- a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php @@ -103,6 +103,13 @@ class AvailableCommandsPacket extends DataPacket{ */ public $commandData = []; + /** + * @var CommandEnum[] + * List of dynamic command enums, also referred to as "soft" enums. These can by dynamically updated mid-game + * without resending this packet. + */ + public $softEnums = []; + protected function decodePayload(){ for($i = 0, $this->enumValuesCount = $this->getUnsignedVarInt(); $i < $this->enumValuesCount; ++$i){ $this->enumValues[] = $this->getString(); @@ -119,6 +126,10 @@ class AvailableCommandsPacket extends DataPacket{ for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ $this->commandData[] = $this->getCommandData(); } + + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $this->softEnums[] = $this->getSoftEnum(); + } } protected function getEnum() : CommandEnum{ @@ -133,6 +144,18 @@ class AvailableCommandsPacket extends DataPacket{ return $retval; } + protected function getSoftEnum() : CommandEnum{ + $retval = new CommandEnum(); + $retval->enumName = $this->getString(); + + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + //Get the enum value from the initial pile of mess + $retval->enumValues[] = $this->getString(); + } + + return $retval; + } + protected function putEnum(CommandEnum $enum){ $this->putString($enum->enumName); @@ -147,6 +170,15 @@ class AvailableCommandsPacket extends DataPacket{ } } + protected function putSoftEnum(CommandEnum $enum) : void{ + $this->putString($enum->enumName); + + $this->putUnsignedVarInt(count($enum->enumValues)); + foreach($enum->enumValues as $value){ + $this->putString($value); + } + } + protected function getEnumValueIndex() : int{ if($this->enumValuesCount < 256){ return $this->getByte(); @@ -334,6 +366,11 @@ class AvailableCommandsPacket extends DataPacket{ foreach($this->commandData as $data){ $this->putCommandData($data); } + + $this->putUnsignedVarInt(count($this->softEnums)); + foreach($this->softEnums as $enum){ + $this->putSoftEnum($enum); + } } public function handle(NetworkSession $session) : bool{ From 566f3c6262ecfc8e31e5420aaa213a21282203ff Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 20 Jun 2018 17:41:39 +0100 Subject: [PATCH 3/5] AvailableCommandsPacket: stricter decode and handling --- .../mcpe/protocol/AvailableCommandsPacket.php | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php index a885a32b3..e5e425c64 100644 --- a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php @@ -217,13 +217,17 @@ class AvailableCommandsPacket extends DataPacket{ if($parameter->paramType & self::ARG_FLAG_ENUM){ $index = ($parameter->paramType & 0xffff); $parameter->enum = $this->enums[$index] ?? null; - - assert($parameter->enum !== null, "expected enum at $index, but got none"); - }elseif(($parameter->paramType & self::ARG_FLAG_VALID) === 0){ //postfix (guessing) + if($parameter->enum === null){ + throw new \UnexpectedValueException("expected enum at $index, but got none"); + } + }elseif($parameter->paramType & self::ARG_FLAG_POSTFIX){ $index = ($parameter->paramType & 0xffff); $parameter->postfix = $this->postfixes[$index] ?? null; - - assert($parameter->postfix !== null, "expected postfix at $index, but got none"); + if($parameter->postfix === null){ + throw new \UnexpectedValueException("expected postfix at $index, but got none"); + } + }elseif(($parameter->paramType & self::ARG_FLAG_VALID) === 0){ + throw new \UnexpectedValueException("Invalid parameter type 0x" . dechex($parameter->paramType)); } $retval->overloads[$overloadIndex][$paramIndex] = $parameter; @@ -259,7 +263,7 @@ class AvailableCommandsPacket extends DataPacket{ if($key === false){ throw new \InvalidStateException("Postfix '$parameter->postfix' not in postfixes array"); } - $type = $parameter->paramType << 24 | $key; + $type = self::ARG_FLAG_POSTFIX | $key; }else{ $type = $parameter->paramType; } @@ -298,13 +302,12 @@ class AvailableCommandsPacket extends DataPacket{ case self::ARG_TYPE_COMMAND: return "command"; } - }elseif($argtype !== 0){ - //guessed - $baseType = $argtype >> 24; - $typeName = $this->argTypeToString(self::ARG_FLAG_VALID | $baseType); + }elseif($argtype & self::ARG_FLAG_POSTFIX){ $postfix = $this->postfixes[$argtype & 0xffff]; - return $typeName . " (postfix $postfix)"; + return "int (postfix $postfix)"; + }else{ + throw new \UnexpectedValueException("Unknown arg type 0x" . dechex($argtype)); } return "unknown ($argtype)"; From 424c50e1e9e405ebf0aa0733ce80497c22273212 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 21 Aug 2018 17:36:29 +0100 Subject: [PATCH 4/5] Protocol changes for 1.6.0.5, minus Entity->Actor rename --- src/pocketmine/network/mcpe/protocol/ProtocolInfo.php | 6 +++--- .../network/mcpe/protocol/ResourcePacksInfoPacket.php | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php index 8b3f3fa89..27b4e3eb6 100644 --- a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php +++ b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php @@ -39,15 +39,15 @@ interface ProtocolInfo{ /** * Actual Minecraft: PE protocol version */ - public const CURRENT_PROTOCOL = 280; + public const CURRENT_PROTOCOL = 281; /** * Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */ - public const MINECRAFT_VERSION = 'v1.6.0.1 beta'; + public const MINECRAFT_VERSION = 'v1.6.0.5 beta'; /** * Version number sent to clients in ping responses. */ - public const MINECRAFT_VERSION_NETWORK = '1.6.0.1'; + public const MINECRAFT_VERSION_NETWORK = '1.6.0.5'; public const LOGIN_PACKET = 0x01; public const PLAY_STATUS_PACKET = 0x02; diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php index a01cb6384..61286e6ba 100644 --- a/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php @@ -70,6 +70,7 @@ class ResourcePacksInfoPacket extends DataPacket{ $this->putLLong($entry->getPackSize()); $this->putString(""); //TODO: encryption key $this->putString(""); //TODO: subpack name + $this->putString(""); //TODO: content identity } $this->putLShort(count($this->resourcePackEntries)); foreach($this->resourcePackEntries as $entry){ @@ -78,6 +79,7 @@ class ResourcePacksInfoPacket extends DataPacket{ $this->putLLong($entry->getPackSize()); $this->putString(""); //TODO: encryption key $this->putString(""); //TODO: subpack name + $this->putString(""); //TODO: content identity } } From 9ca38ba868cde677a939ccea827e7d13ee44c10c Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 27 Jul 2018 16:42:11 +0100 Subject: [PATCH 5/5] Protocol changes for 1.6.0.8 + resource packs "fix" --- src/pocketmine/Player.php | 2 +- src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php | 7 +++++++ src/pocketmine/network/mcpe/protocol/ProtocolInfo.php | 6 +++--- src/pocketmine/network/mcpe/protocol/StartGamePacket.php | 6 ++++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 695ddf907..7cc5b1dc4 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2025,7 +2025,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ case ResourcePackClientResponsePacket::STATUS_SEND_PACKS: $manager = $this->server->getResourcePackManager(); foreach($packet->packIds as $uuid){ - $pack = $manager->getPackById($uuid); + $pack = $manager->getPackById(substr($uuid, 0, strpos($uuid, "_"))); //dirty hack for mojang's dirty hack for versions if(!($pack instanceof ResourcePack)){ //Client requested a resource pack but we don't have it available on the server $this->close("", "disconnectionScreen.resourcePack", true); diff --git a/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php b/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php index 2394bbd6b..537e1d543 100644 --- a/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddPlayerPacket.php @@ -75,6 +75,9 @@ class AddPlayerPacket extends DataPacket{ /** @var EntityLink[] */ public $links = []; + /** @var string */ + public $deviceId = ""; //TODO: fill player's device ID (???) + protected function decodePayload(){ $this->uuid = $this->getUUID(); $this->username = $this->getString(); @@ -103,6 +106,8 @@ class AddPlayerPacket extends DataPacket{ for($i = 0; $i < $linkCount; ++$i){ $this->links[$i] = $this->getEntityLink(); } + + $this->deviceId = $this->getString(); } protected function encodePayload(){ @@ -133,6 +138,8 @@ class AddPlayerPacket extends DataPacket{ foreach($this->links as $link){ $this->putEntityLink($link); } + + $this->putString($this->deviceId); } 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 27b4e3eb6..d7cc21f51 100644 --- a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php +++ b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php @@ -39,15 +39,15 @@ interface ProtocolInfo{ /** * Actual Minecraft: PE protocol version */ - public const CURRENT_PROTOCOL = 281; + public const CURRENT_PROTOCOL = 282; /** * Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */ - public const MINECRAFT_VERSION = 'v1.6.0.5 beta'; + public const MINECRAFT_VERSION = 'v1.6.0.8 beta'; /** * Version number sent to clients in ping responses. */ - public const MINECRAFT_VERSION_NETWORK = '1.6.0.5'; + public const MINECRAFT_VERSION_NETWORK = '1.6.0.8'; public const LOGIN_PACKET = 0x01; public const PLAY_STATUS_PACKET = 0x02; diff --git a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php index 43a7614c7..1c016a2c2 100644 --- a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php +++ b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php @@ -129,6 +129,8 @@ class StartGamePacket extends DataPacket{ public $currentTick = 0; //only used if isTrial is true /** @var int */ public $enchantmentSeed = 0; + /** @var string */ + public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort protected function decodePayload(){ $this->entityUniqueId = $this->getEntityUniqueId(); @@ -185,6 +187,8 @@ class StartGamePacket extends DataPacket{ $this->getString(); $this->getLShort(); } + + $this->multiplayerCorrelationId = $this->getString(); } protected function encodePayload(){ @@ -249,6 +253,8 @@ class StartGamePacket extends DataPacket{ self::$runtimeIdTable = $stream->buffer; } $this->put(self::$runtimeIdTable); + + $this->putString($this->multiplayerCorrelationId); } public function handle(NetworkSession $session) : bool{