1. The forums will be archived and moved to a read only mode in about 2 weeks (mid march).

Tutorial Temporary: MCPE Command Syntax checking

Discussion in 'Resources' started by Sandertv, May 17, 2017.

  1. Sandertv

    Sandertv Zombie Pigman Poggit Reviewer

    Messages:
    786
    GitHub:
    Sandertv
    Hello everyone,

    Due to the lacking API in the PocketMine core I've decided to make this quick tutorial for developers to see how they can make use of the command syntax checking from MCPE with what the current API offers. This will get rendundant when a proper API gets implemented for this, but for now, this tutorial shows you exactly how to do it.

    This tutorial aims to show how to add command syntax checking for classes inside of a class that extends Command. (or PluginCommand) Using this in any other class will not have any effect.

    The method that can currently be used, or actually overwritten from the Command class is the 'generateCustomCommandData' method, which looks like this:
    PHP:
    public function generateCustomCommandData(pocketmine\Player $player) { }
    First off, we're making sure to call the parent function, or the function that we are overwriting, by adding:
    PHP:
    $commandData parent::generateCustomCommandData($player);
    In order to add our custom syntax checking instead of string:args, we'll have go through the following array 'structure':
    PHP:
    $commandData["overloads"]["default"]["input"]["parameters"] = [];
    There we go! We can now change the array to whatever we want our argument structure to look like. Say we want one integer type argument and one player argument and an argument with the autocompletion options called hi and hello. This is what we would do:
    PHP:
    $commandData["overloads"]["default"]["input"]["parameters"] = [
          [
             
    "type" => "int",
             
    "name" => "amount",
             
    "optional" => false,
          ],
          [
             
    "type" => "rawtext",
             
    "name" => "player",
             
    "optional" => false
          
    ],
          [
             
    "type" => "stringenum",
             
    "name" => "parameter",
             
    "optional" => true
             
    "enum_values" => ["hi""hello"]
          ]
      ]
    ];
    There we go. We have our argument structure finished. If we put this inside of our command class, it will have the desired effect. A useful list of available argument types and more can be found on this gist by @gurun:

    But can't we do this easier? I don't want to have this method in everyone of my command classes, it's too much duplicated code! Yes, there are some ways to make it semi-automatic. This part is my personal preference, and you may or may not like it too.

    If you decide to use my way, create a new class and put the following code in it. (MAKE SURE TO ADJUST THE NAMESPACE AND CLASS NAME)

    PHP:
    <?php

    namespace My\Namespace;

    class 
    CommandOverloads {

        private static 
    $commandOverloads = [
              
    "mycommand" => [
                   [
                     
    "type" => "int",
                     
    "name" => "amount",
                     
    "optional" => false,
                  ],
                  [
                     
    "type" => "rawtext",
                     
    "name" => "player",
                     
    "optional" => false
                   
    ],
                   [
                     
    "type" => "stringenum",
                     
    "name" => "parameter",
                     
    "optional" => true
                     
    "enum_values" => ["hi""hello"]
                   ]
                ],
           ];

        
    /**
        * @param string $command
        *
        * @return array
        */
        
    public static function getOverloads(string $command): array {
            return 
    self::$commandOverloads[$command];
        }
    }
    You could of course use json for this as well. I was just too lazy for that, and this works fine as well. In order to get this all working, you will need a superclass for the command classes you made, and make your commands extend that superclass. In your superclass, for example BaseCommand, you can then add the following code:
    PHP:
    public function generateCustomCommandData(Player $player) {
        
    $commandData parent::generateCustomCommandData($player);
        
    $commandData["overloads"]["default"]["input"]["parameters"] = CommandOverloads::getOverloads($this->getName());
        return 
    $commandData;
    }
    Just make sure to have the key in the array from CommandOverloads be exactly the same name as your command name, and there you go! You can now simply add new arguments to the array and add new commands without any additional code.

    I hope this helped for you. Looking forward to seeing more plugins with MCPE argument syntax checking! ;)
    Remember, once a proper API gets added in PMMP this tutorial will be obsolete. Examples of the usage of this can be found in some of the plugins I work on. I'm not going to mention them here as I'm not a supporter of advertisement.
     
    Last edited: Jul 21, 2017
  2. Sandertv

    Sandertv Zombie Pigman Poggit Reviewer

    Messages:
    786
    GitHub:
    Sandertv
    Note that for the arrays from the parameters you don't necessarily need to add the number (key) of the parameter. It automatically gets rendered that way in PHP so you could leave it out, but it does provide some more readability.
     
  3. jasonwynn10

    jasonwynn10 Moderator Poggit Reviewer

    Messages:
    1,489
    GitHub:
    jasonwynn10
    Do the methods provided override any already existing arguments and commands? Could any of this be used to block certain command access on the client?
     
  4. Sandertv

    Sandertv Zombie Pigman Poggit Reviewer

    Messages:
    786
    GitHub:
    Sandertv
    The actual command registering is still the same, so that won't actually make a difference. You can only change the arguments without hacking around too much inside of commands you registered inside your plugin. You might be able to change the command access by setting the $commandData["permission"] (?) I'm not entirely sure about that, as I didn't test it yet.
     
    jasonwynn10 likes this.
  5. Sandertv

    Sandertv Zombie Pigman Poggit Reviewer

    Messages:
    786
    GitHub:
    Sandertv
    @jasonwynn10 I really wonder if it's possible to make the command only show up to the one player and not to the other player. If you do anything wrong with this you'll either end up disconnecting the client immediately on join, and in most occasions all commands will dissapear from the client. Perhaps there is an interesting way to achieve your idea.
     
    jasonwynn10 likes this.
  6. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    As far as I remember, PocketMine doesn't send commands that the player doesn't have permission to use.
     
    jasonwynn10 likes this.
  7. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    It should've been that way but it sends all commands to the player, including the ones they don't have permissions to. That hasn't yet been implemented.
    Source
     
    jasonwynn10, Sandertv and SOFe like this.
  8. mal0ne_23

    mal0ne_23 Spider Jockey

    Messages:
    30
    GitHub:
    mal0ne-23
    Question.. Why is testPermissionSilent commented out..? Wouldn't that work fine to filter commands?
     
  9. mal0ne_23

    mal0ne_23 Spider Jockey

    Messages:
    30
    GitHub:
    mal0ne-23
    And how can I do a list of players? One that updates
     
  10. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    Yeah it would work. Check Player::sendCommandData() to see how it's done.
     
  11. mal0ne_23

    mal0ne_23 Spider Jockey

    Messages:
    30
    GitHub:
    mal0ne-23
    Another questionnnn, how do I make the last argument able to be more than one word?
     
  12. Sandertv

    Sandertv Zombie Pigman Poggit Reviewer

    Messages:
    786
    GitHub:
    Sandertv
    MCPE Syntax checking does not check for too many parameters, and simply allows it. You can simply implode those last arguments.
     
    mal0ne_23 likes this.
  13. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    Or use a rawtext.
    See /tell.
     
  14. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    Avoid using the `0 => ` indices for the parameters. The "parameters" property should be an array, not an object. If you accidentally order the indices wrongly, json_encode() will interpret your array as an object, which might lead to an MCPE crash. So, why potential trouble while you didn't need such indices at all?
     
    Sandertv likes this.
  15. jasonwynn10

    jasonwynn10 Moderator Poggit Reviewer

    Messages:
    1,489
    GitHub:
    jasonwynn10
    @Sandertv can you provide me with some info on how to use the output overload? I'm looking to use these in my permission management plugin
     
  16. Sandertv

    Sandertv Zombie Pigman Poggit Reviewer

    Messages:
    786
    GitHub:
    Sandertv
    As far as I know the output is unused by plugins, unless it's a vanilla command. In 1.2 everything will change anyway, so I'll update this tutorial then once I find out how it works.
     
  17. jasonwynn10

    jasonwynn10 Moderator Poggit Reviewer

    Messages:
    1,489
    GitHub:
    jasonwynn10
    @Sandertv is there a way to make the arguments of the command change based on previous arguments' filled in data? The reason I am asking is because MyPlot utilizes a single command, but the subcommand arguments change with each sub command.
     
  18. Sandertv

    Sandertv Zombie Pigman Poggit Reviewer

    Messages:
    786
    GitHub:
    Sandertv
    The only way to sort of achieve this result is by adding the same command data with different parameters multiple times, which I know is really messy and ugly. That's why in 1.2 json is no longer used. I have yet to find out how the stuff works in 1.2.
     
    jasonwynn10 likes this.
  19. jasonwynn10

    jasonwynn10 Moderator Poggit Reviewer

    Messages:
    1,489
    GitHub:
    jasonwynn10
    When you figure it out, can you tell me how it works :D
     
  20. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    FYI: Last time I checked the packet isn't even completed on PocketMine.
     
    Sandertv and jasonwynn10 like this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.