mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 16:51:42 +00:00
Added encode for AvailableCommandsPacket, bring back command lists (no arguments yet)
This commit is contained in:
parent
a4e955c0a4
commit
41f363d0c1
@ -103,6 +103,7 @@ use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||
use pocketmine\network\mcpe\protocol\BatchPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||
@ -139,6 +140,9 @@ use pocketmine\network\mcpe\protocol\StartGamePacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\TextPacket;
|
||||
use pocketmine\network\mcpe\protocol\TransferPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandData;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandEnum;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandParameter;
|
||||
use pocketmine\network\mcpe\protocol\types\ContainerIds;
|
||||
use pocketmine\network\mcpe\protocol\types\DimensionIds;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||
@ -655,20 +659,36 @@ 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){
|
||||
$data[$command->getName()]["versions"][0] = $cmdData;
|
||||
|
||||
$pk = new AvailableCommandsPacket();
|
||||
foreach($this->server->getCommandMap()->getCommands() as $name => $command){
|
||||
if(isset($pk->commandData[$command->getName()]) or $command->getName() === "help"){
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = new CommandData();
|
||||
$data->commandName = $command->getName();
|
||||
$data->commandDescription = $this->server->getLanguage()->translateString($command->getDescription());
|
||||
$data->flags = 0;
|
||||
$data->permission = 0;
|
||||
|
||||
$parameter = new CommandParameter();
|
||||
$parameter->paramName = "args";
|
||||
$parameter->paramType = AvailableCommandsPacket::ARG_FLAG_VALID | AvailableCommandsPacket::ARG_TYPE_RAWTEXT;
|
||||
$parameter->isOptional = true;
|
||||
$data->overloads[0][0] = $parameter;
|
||||
|
||||
$aliases = $command->getAliases();
|
||||
if(!empty($aliases)){
|
||||
$data->aliases = new CommandEnum();
|
||||
$data->aliases->enumName = ucfirst($command->getName()) . "Aliases";
|
||||
$data->aliases->enumValues = $aliases;
|
||||
}
|
||||
|
||||
$pk->commandData[$command->getName()] = $data;
|
||||
}
|
||||
|
||||
if(count($data) > 0){
|
||||
//TODO: structure checking
|
||||
$pk = new AvailableCommandsPacket();
|
||||
$pk->commands = json_encode($data);
|
||||
$this->dataPacket($pk);
|
||||
}*/
|
||||
$this->dataPacket($pk);
|
||||
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,9 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandData;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandEnum;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandParameter;
|
||||
|
||||
class AvailableCommandsPacket extends DataPacket{
|
||||
const NETWORK_ID = ProtocolInfo::AVAILABLE_COMMANDS_PACKET;
|
||||
@ -83,13 +86,17 @@ class AvailableCommandsPacket extends DataPacket{
|
||||
public $postfixes = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* List of enum names, along with a list of ints indicating the enum's possible values from the enumValues array.
|
||||
* @var CommandEnum[]
|
||||
* List of command enums, from command aliases to argument enums.
|
||||
*/
|
||||
public $enums = [];
|
||||
/**
|
||||
* @var int[] string => int map of enum name to index
|
||||
*/
|
||||
private $enumMap = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var CommandData[]
|
||||
* List of command data, including name, description, alias indexes and parameters.
|
||||
*/
|
||||
public $commandData = [];
|
||||
@ -115,22 +122,32 @@ class AvailableCommandsPacket extends DataPacket{
|
||||
}
|
||||
}
|
||||
|
||||
protected function getEnum(){
|
||||
$retval = [];
|
||||
$retval["enumName"] = $this->getString();
|
||||
|
||||
$enumValues = [];
|
||||
protected function getEnum() : 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
|
||||
$enumValues[] = $this->enumValues[$this->getEnumValueIndex()];
|
||||
$retval->enumValues[] = $this->enumValues[$this->getEnumValueIndex()];
|
||||
}
|
||||
|
||||
$retval["enumValues"] = $enumValues;
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
protected function putEnum(CommandEnum $enum){
|
||||
$this->putString($enum->enumName);
|
||||
|
||||
$this->putUnsignedVarInt(count($enum->enumValues));
|
||||
foreach($enum->enumValues as $value){
|
||||
//Dumb bruteforce search. I hate this packet.
|
||||
$index = array_search($value, $this->enumValues, true);
|
||||
if($index === false){
|
||||
throw new \InvalidStateException("Enum value '$value' not found");
|
||||
}
|
||||
$this->putEnumValueIndex($index);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getEnumValueIndex() : int{
|
||||
if($this->enumValuesCount < 256){
|
||||
return $this->getByte();
|
||||
@ -141,34 +158,87 @@ class AvailableCommandsPacket extends DataPacket{
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
protected function putEnumValueIndex(int $index){
|
||||
if($this->enumValuesCount < 256){
|
||||
$this->putByte($index);
|
||||
}elseif($this->enumValuesCount < 65536){
|
||||
$this->putLShort($index);
|
||||
}else{
|
||||
$this->putLInt($index);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
protected function getCommandData() : CommandData{
|
||||
$retval = new CommandData();
|
||||
$retval->commandName = $this->getString();
|
||||
$retval->commandDescription = $this->getString();
|
||||
$retval->flags = $this->getByte();
|
||||
$retval->permission = $this->getByte();
|
||||
$retval->aliases = $this->enums[$this->getLInt()] ?? null;
|
||||
|
||||
for($overloadIndex = 0, $overloadCount = $this->getUnsignedVarInt(); $overloadIndex < $overloadCount; ++$overloadIndex){
|
||||
for($paramIndex = 0, $paramCount = $this->getUnsignedVarInt(); $paramIndex < $paramCount; ++$paramIndex){
|
||||
$parameter = new CommandParameter();
|
||||
$parameter->paramName = $this->getString();
|
||||
$parameter->paramType = $this->getLInt();
|
||||
$parameter->isOptional = $this->getBool();
|
||||
|
||||
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)
|
||||
$index = ($parameter->paramType & 0xffff);
|
||||
$parameter->postfix = $this->postfixes[$index] ?? null;
|
||||
|
||||
assert($parameter->postfix !== null, "expected postfix at $index, but got none");
|
||||
}
|
||||
$retval["overloads"][$i]["params"][$j]["paramTypeString"] = $this->argTypeToString($type);
|
||||
|
||||
$retval->overloads[$overloadIndex][$paramIndex] = $parameter;
|
||||
}
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
protected function putCommandData(CommandData $data){
|
||||
$this->putString($data->commandName);
|
||||
$this->putString($data->commandDescription);
|
||||
$this->putByte($data->flags);
|
||||
$this->putByte($data->permission);
|
||||
|
||||
if($data->aliases !== null){
|
||||
$this->putLInt($this->enumMap[$data->aliases->enumName] ?? -1);
|
||||
}else{
|
||||
$this->putLInt(-1);
|
||||
}
|
||||
|
||||
$this->putUnsignedVarInt(count($data->overloads));
|
||||
foreach($data->overloads as $overload){
|
||||
/** @var CommandParameter[] $overload */
|
||||
$this->putUnsignedVarInt(count($overload));
|
||||
foreach($overload as $parameter){
|
||||
$this->putString($parameter->paramName);
|
||||
|
||||
if($parameter->enum !== null){
|
||||
$type = self::ARG_FLAG_ENUM | self::ARG_FLAG_VALID | ($this->enumMap[$parameter->enum->enumName] ?? -1);
|
||||
}elseif($parameter->postfix !== null){
|
||||
$key = array_search($parameter->postfix, $this->postfixes, true);
|
||||
if($key === false){
|
||||
throw new \InvalidStateException("Postfix '$parameter->postfix' not in postfixes array");
|
||||
}
|
||||
$type = $parameter->paramType << 24 | $key;
|
||||
}else{
|
||||
$type = $parameter->paramType;
|
||||
}
|
||||
|
||||
$this->putLInt($type);
|
||||
$this->putBool($parameter->isOptional);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function argTypeToString(int $argtype) : string{
|
||||
if($argtype & self::ARG_FLAG_VALID){
|
||||
if($argtype & self::ARG_FLAG_ENUM){
|
||||
@ -210,7 +280,61 @@ class AvailableCommandsPacket extends DataPacket{
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
//TODO
|
||||
$enumValuesMap = [];
|
||||
$postfixesMap = [];
|
||||
$enumMap = [];
|
||||
foreach($this->commandData as $commandData){
|
||||
if($commandData->aliases !== null){
|
||||
$enumMap[$commandData->aliases->enumName] = $commandData->aliases;
|
||||
|
||||
foreach($commandData->aliases->enumValues as $str){
|
||||
$enumValuesMap[$str] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($commandData->overloads as $overload){
|
||||
/**
|
||||
* @var CommandParameter[] $overload
|
||||
* @var CommandParameter $parameter
|
||||
*/
|
||||
foreach($overload as $parameter){
|
||||
if($parameter->enum !== null){
|
||||
$enumMap[$parameter->enum->enumName] = $parameter->enum;
|
||||
foreach($parameter->enum->enumValues as $str){
|
||||
$enumValuesMap[$str] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($parameter->postfix !== null){
|
||||
$postfixesMap[$parameter->postfix] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->enumValues = array_map('strval', array_keys($enumValuesMap)); //stupid PHP key casting D:
|
||||
$this->putUnsignedVarInt($this->enumValuesCount = count($this->enumValues));
|
||||
foreach($this->enumValues as $enumValue){
|
||||
$this->putString($enumValue);
|
||||
}
|
||||
|
||||
$this->postfixes = array_map('strval', array_keys($postfixesMap));
|
||||
$this->putUnsignedVarInt(count($this->postfixes));
|
||||
foreach($this->postfixes as $postfix){
|
||||
$this->putString($postfix);
|
||||
}
|
||||
|
||||
$this->enums = array_values($enumMap);
|
||||
$this->enumMap = array_flip(array_keys($enumMap));
|
||||
$this->putUnsignedVarInt(count($this->enums));
|
||||
foreach($this->enums as $enum){
|
||||
$this->putEnum($enum);
|
||||
}
|
||||
|
||||
$this->putUnsignedVarInt(count($this->commandData));
|
||||
foreach($this->commandData as $data){
|
||||
$this->putCommandData($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
40
src/pocketmine/network/mcpe/protocol/types/CommandData.php
Normal file
40
src/pocketmine/network/mcpe/protocol/types/CommandData.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
class CommandData{
|
||||
/** @var string */
|
||||
public $commandName;
|
||||
/** @var string */
|
||||
public $commandDescription;
|
||||
/** @var int */
|
||||
public $flags;
|
||||
/** @var int */
|
||||
public $permission;
|
||||
/** @var CommandEnum|null */
|
||||
public $aliases;
|
||||
/** @var CommandParameter[][] */
|
||||
public $overloads = [];
|
||||
|
||||
}
|
32
src/pocketmine/network/mcpe/protocol/types/CommandEnum.php
Normal file
32
src/pocketmine/network/mcpe/protocol/types/CommandEnum.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
class CommandEnum{
|
||||
/** @var string */
|
||||
public $enumName;
|
||||
/** @var string[] */
|
||||
public $enumValues = [];
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
class CommandParameter{
|
||||
/** @var string */
|
||||
public $paramName;
|
||||
/** @var int */
|
||||
public $paramType;
|
||||
/** @var bool */
|
||||
public $isOptional;
|
||||
/** @var CommandEnum|null */
|
||||
public $enum;
|
||||
/** @var string|null */
|
||||
public $postfix;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user