From 018897062cd52ad5ba20547ff5e90fe6ad8fc964 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 6 Oct 2016 11:21:48 +0100 Subject: [PATCH] Initial working slash commands on 0.16. TODO: new API --- src/pocketmine/Player.php | 26 +++++++++- src/pocketmine/command/Command.php | 48 +++++++++++++++++++ .../network/protocol/CommandStepPacket.php | 21 +++++++- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index b3278627f..bb1f321f7 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -102,6 +102,7 @@ use pocketmine\nbt\tag\ShortTag; use pocketmine\nbt\tag\StringTag; use pocketmine\network\protocol\AdventureSettingsPacket; use pocketmine\network\protocol\AnimatePacket; +use pocketmine\network\protocol\AvailableCommandsPacket; use pocketmine\network\protocol\BatchPacket; use pocketmine\network\protocol\ChunkRadiusUpdatedPacket; use pocketmine\network\protocol\ContainerClosePacket; @@ -1686,7 +1687,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $pk->eduMode = 0; $pk->rainLevel = 0; //TODO: implement these properly $pk->lightningLevel = 0; - $pk->commandsEnabled = 0; + $pk->commandsEnabled = 1; $pk->unknown = "UNKNOWN"; $pk->worldName = $this->server->getMotd(); $this->dataPacket($pk); @@ -1712,6 +1713,14 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade if($this->isOp()){ $this->setRemoveFormat(false); } + + $pk = new AvailableCommandsPacket(); + $data = []; + foreach($this->server->getCommandMap()->getCommands() as $command){ + $data[$command->getName()] = $command->generateJsonData($this); + } + $pk->commands = json_encode($data); + $this->dataPacket($pk); if($this->isCreative()){ $this->inventory->sendCreativeContents(); @@ -2483,6 +2492,21 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false); break; + case ProtocolInfo::COMMAND_STEP_PACKET: + if($this->spawned === false or !$this->isAlive()){ + break; + } + $this->craftingType = 0; + Timings::$playerCommandTimer->startTiming(); + $commandText = $packet->command; + if($packet->args !== null){ + foreach($packet->args as $arg){ //command ordering will be an issue + $commandText .= " " . $arg; + } + } + $this->server->dispatchCommand($this, $commandText); + Timings::$playerCommandTimer->stopTiming(); + break; case ProtocolInfo::TEXT_PACKET: if($this->spawned === false or !$this->isAlive()){ break; diff --git a/src/pocketmine/command/Command.php b/src/pocketmine/command/Command.php index 04d32d5d8..6bb66e828 100644 --- a/src/pocketmine/command/Command.php +++ b/src/pocketmine/command/Command.php @@ -27,6 +27,7 @@ namespace pocketmine\command; use pocketmine\event\TextContainer; use pocketmine\event\TimingsHandler; use pocketmine\event\TranslationContainer; +use pocketmine\Player; use pocketmine\Server; use pocketmine\utils\TextFormat; @@ -85,6 +86,25 @@ abstract class Command{ $this->timings = new TimingsHandler("** Command: " . $name); } + public function generateJsonData(Player $player) : array{ + /*if(!$this->testPermissionSilent($player)){ + return []; + }*/ + $data = [ + "versions" => [ + [ + "description" => $this->getDescription(), + "overloads" => $this->getOverloadData(), + "permission" => "any", //TODO: implement vanilla op API + ] + ] + ]; + if(count($aliases = $this->getAliases()) > 0){ + $data["versions"][0]["aliases"] = $aliases; + } + return $data; + } + /** * @param CommandSender $sender * @param string $commandLabel @@ -101,6 +121,34 @@ abstract class Command{ return $this->name; } + /** + * Returns an array of overload data for generating JSON data for AvailableCommandsPacket + * To show custom usages and command parameters, you MUST override this method and define + * your own parameters and overloads. Omitting this method will cause the generic default + * [args: string] message to be shown. + * + * @return array + */ + public function getOverloadData() : array{ + $data = [ + "default" => [ + "input" => [ + "parameters" => [ + 0 => [ //Default rawtext parameter for old plugins + "name" => "args", + "type" => "rawtext", + "optional" => true + ] + ] + ], + "output" => [ + "format_strings" => [] + ] + ] + ]; + return $data; + } + /** * @return string */ diff --git a/src/pocketmine/network/protocol/CommandStepPacket.php b/src/pocketmine/network/protocol/CommandStepPacket.php index 5467440d6..8d5025b4b 100644 --- a/src/pocketmine/network/protocol/CommandStepPacket.php +++ b/src/pocketmine/network/protocol/CommandStepPacket.php @@ -38,8 +38,27 @@ class CommandStepPacket extends DataPacket{ * https://gist.github.com/dktapps/8285b93af4ca38e0104bfeb9a6c87afd */ + public $command; + public $overload; + public $uvarint1; + public $uvarint2; + public $bool; + public $uvarint64; + public $args; //JSON formatted command arguments + public $string4; + public function decode(){ - //TODO + $this->command = $this->getString(); + $this->overload = $this->getString(); + $this->uvarint1 = $this->getUnsignedVarInt(); + $this->uvarint2 = $this->getUnsignedVarInt(); + $this->bool = (bool) $this->getByte(); + $this->uvarint64 = $this->getUnsignedVarInt(); //TODO: varint64 + $this->args = json_decode($this->getString()); + $this->string4 = $this->getString(); + while(!$this->feof()){ + $this->getByte(); //prevent assertion errors. TODO: find out why there are always 3 extra bytes at the end of this packet. + } } public function encode(){