diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 86c27372c1..f7032a1b3e 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -615,6 +615,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ } public function sendCommandData(){ + //TODO: this needs fixing + /* $data = []; foreach($this->server->getCommandMap()->getCommands() as $command){ if(count($cmdData = $command->generateCustomCommandData($this)) > 0){ @@ -627,7 +629,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $pk = new AvailableCommandsPacket(); $pk->commands = json_encode($data); $this->dataPacket($pk); - } + }*/ + } /** diff --git a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php index 3e4f1be842..3a8de02f0c 100644 --- a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php @@ -30,17 +30,164 @@ use pocketmine\network\mcpe\NetworkSession; class AvailableCommandsPacket extends DataPacket{ const NETWORK_ID = ProtocolInfo::AVAILABLE_COMMANDS_PACKET; - public $commands; //JSON-encoded command data - public $unknown = ""; + + /** + * This flag is set on all types EXCEPT the TEMPLATE type. Not completely sure what this is for, but it is required + * for the argtype to work correctly. VALID seems as good a name as any. + */ + const ARG_FLAG_VALID = 0x100000; + + /** + * Basic parameter types. These must be combined with the ARG_FLAG_VALID constant. + * ARG_FLAG_VALID | (type const) + */ + const ARG_TYPE_INT = 0x01; + const ARG_TYPE_FLOAT = 0x02; + const ARG_TYPE_VALUE = 0x03; + const ARG_TYPE_TARGET = 0x04; + + const ARG_TYPE_STRING = 0x0c; + const ARG_TYPE_POSITION = 0x0d; + + const ARG_TYPE_RAWTEXT = 0x10; + + const ARG_TYPE_TEXT = 0x12; + + const ARG_TYPE_JSON = 0x15; + + const ARG_TYPE_COMMAND = 0x1c; + + /** + * Enums are a little different: they are composed as follows: + * ARG_FLAG_ENUM | ARG_FLAG_VALID | (enum index) + */ + const ARG_FLAG_ENUM = 0x200000; + + /** + * This type is used for for /xp L. This value should be used on its own without bitflags. + */ + const ARG_FLAG_TEMPLATE = 0x01000000; + + /** + * @var string[] + * A list of every single enum value for every single command in the packet, including alias names. + */ + public $enumValues = []; + /** + * @var string[] + * No idea what this is. Leaving it empty works. + */ + public $idk = []; + /** + * @var array + * List of enum names, along with a list of ints indicating the enum's possible values from the enumValues array. + */ + public $enums = []; + /** + * @var array + * List of command data, including name, description, alias indexes and parameters. + */ + public $commandData = []; protected function decodePayload(){ - $this->commands = $this->getString(); - $this->unknown = $this->getString(); + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $this->enumValues[] = $this->getString(); + } + + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $this->idk[] = $this->getString(); + } + + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $this->enums[] = $this->getEnum(); + } + + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $this->commandData[] = $this->getCommandData(); + } + } + + protected function getEnum(){ + $retval = []; + $retval["enumName"] = $this->getString(); + + $enumValues = []; + + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + //Get the enum value from the initial pile of mess + $enumValues[] = $this->enumValues[$this->getLShort()]; + } + + $retval["enumValues"] = $enumValues; + + return $retval; + } + + protected function getCommandData(){ + $retval = []; + $retval["commandName"] = $commandName = $this->getString(); + $retval["commandDescription"] = $this->getString(); + $retval["byte1"] = $this->getByte(); + $retval["byte2"] = $this->getByte(); + $retval["aliasesEnum"] = $this->enums[$this->getLInt()] ?? null; + + for($i = 0, $overloadCount = $this->getUnsignedVarInt(); $i < $overloadCount; ++$i){ + for($j = 0, $paramCount = $this->getUnsignedVarInt(); $j < $paramCount; ++$j){ + $retval["overloads"][$i]["params"][$j]["paramName"] = $this->getString(); + $retval["overloads"][$i]["params"][$j]["paramType"] = $type = $this->getLInt(); + $retval["overloads"][$i]["params"][$j]["optional"] = $this->getBool(); + if($type & self::ARG_FLAG_ENUM){ + $index = ($type & 0xffff); + if(isset($this->enums[$index])){ + $retval["overloads"][$i]["params"][$j]["enum"] = $this->enums[$index]; + }else{ + $retval["overloads"][$i]["params"][$j]["enum"] = null; + } + } + $retval["overloads"][$i]["params"][$j]["paramTypeString"] = self::argTypeToString($type); + } + } + + return $retval; + } + + private static function argTypeToString(int $argtype) : string{ + if($argtype & self::ARG_FLAG_VALID){ + if($argtype & self::ARG_FLAG_ENUM){ + return "stringenum (" . ($argtype & 0xffff) . ")"; + } + + switch($argtype & 0xffff){ + case self::ARG_TYPE_INT: + return "int"; + case self::ARG_TYPE_FLOAT: + return "float"; + case self::ARG_TYPE_VALUE: + return "mixed"; + case self::ARG_TYPE_TARGET: + return "target"; + case self::ARG_TYPE_STRING: + return "string"; + case self::ARG_TYPE_POSITION: + return "xyz"; + case self::ARG_TYPE_RAWTEXT: + return "rawtext"; + case self::ARG_TYPE_TEXT: + return "text"; + case self::ARG_TYPE_JSON: + return "json"; + case self::ARG_TYPE_COMMAND: + return "command"; + } + }elseif($argtype === self::ARG_FLAG_TEMPLATE){ + return "special int"; + } + + return "unknown ($argtype)"; } protected function encodePayload(){ - $this->putString($this->commands); - $this->putString($this->unknown); + //TODO } public function handle(NetworkSession $session) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/ShowProfilePacket.php b/src/pocketmine/network/mcpe/protocol/ShowProfilePacket.php index 15935a29c5..7f708ff7e8 100644 --- a/src/pocketmine/network/mcpe/protocol/ShowProfilePacket.php +++ b/src/pocketmine/network/mcpe/protocol/ShowProfilePacket.php @@ -30,12 +30,15 @@ use pocketmine\network\mcpe\NetworkSession; class ShowProfilePacket extends DataPacket{ const NETWORK_ID = ProtocolInfo::SHOW_PROFILE_PACKET; + /** @var string */ + public $string1; + protected function decodePayload(){ - //TODO + $this->string1 = $this->getString(); } protected function encodePayload(){ - //TODO + $this->putString($this->string1); } public function handle(NetworkSession $session) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/SubClientLoginPacket.php b/src/pocketmine/network/mcpe/protocol/SubClientLoginPacket.php index f5461a08a2..4b048eec30 100644 --- a/src/pocketmine/network/mcpe/protocol/SubClientLoginPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SubClientLoginPacket.php @@ -30,12 +30,15 @@ use pocketmine\network\mcpe\NetworkSession; class SubClientLoginPacket extends DataPacket{ const NETWORK_ID = ProtocolInfo::SUB_CLIENT_LOGIN_PACKET; + /** @var string */ + public $connectionRequestData; + protected function decodePayload(){ - //TODO + $this->connectionRequestData = $this->getString(); } protected function encodePayload(){ - //TODO + $this->putString($this->connectionRequestData); } public function handle(NetworkSession $session) : bool{