YML file - registing sub-commands

Discussion in 'Plugin Development' started by Sammy, Feb 28, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    Sammy

    Is there a way to register sub commands on the yml file?
    My idea is to make a sufix that will always be used and the "real" cmds are after, like this:

    /s <command>
    /s help
    /s kit
    /s info
     
  2. Offline

    Plague

    I don't think that is possible, but you can use underscore if you need it that much...
     
  3. Offline

    Sammy

    Yeah, but that would defeat my purpose, and would quickly start to get messy =/
     
  4. Offline

    Nohup

    s is truly your command where the rest is the parameter being passed to the command. You catch when your command is called, determine what parameter it was called with in your code and then take the appropriate action
     
  5. Offline

    Sammy

    But that's the normal way , call them parameters call them sub-commands, the problem is not doing it is making it more legible (out of the compiled src code)

    A yml with only one cmd registered is not that useful, look at the bigbrother src code, they have the same problem they only register /bb but the rest are the "real" commands.
    --- merged: Mar 1, 2011 12:58 AM ---
    So I found a way around it
    I made another yaml file and a handler for it

    Code:
    package com.SySammy.SyBot.UI;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import org.yaml.snakeyaml.Yaml;
    
    /**
     *
     * @author Sammy
     */
    public class yamlHandler {
    
        private String cmd;
        private Object objd;
        private Object obju;
        BufferedReader input;
    
        public yamlHandler(String command) {
            this.cmd = command;
            try {
    
                input = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("commands.yml")));
    
    
            } catch (Exception ex) {
                Logger.getLogger(yamlHandler.class.getName()).log(Level.SEVERE, null, ex);
            }
            Yaml yaml = new Yaml();
            Map<String, Map<String, Map<String, Object>>> data = (Map<String, Map<String, Map<String, Object>>>) yaml.load(input);
    
            if (command.equals(command)) {
                objd = data.get("commands").get(cmd).get("description");
                obju = data.get("commands").get(cmd).get("usage");
            }
        }
    
        public String getdescription() {
            return objd.toString();
        }
    
        public String getusage() {
            return obju.toString();
        }
    }
    My yml file is only for commands:

    Code:
    commands:
      help:
        description: Help menu
        usage: |
               /<command> - help menu.
    If someone wants a better explication of this tell me and I will make a thread =)
     
  6. Offline

    Zeroth

    I would be very interested in a new thread on the topic! But I'm more interested in how to read yaml's, not specifically making commands out of them.
     
  7. Offline

    Sammy

    This part is used to read the file
    Code:
        public String getdescription() {
            return objd.toString();
        }
    
        public String getusage() {
            return obju.toString().replace("<command>", cmd);
        }
    the general idea is that you make a hashmap from the object that is given to you by the yaml file

    The Object you get is something like this
    Code:
    {commands={clear={description=Clears your own or a player's inventory., usage=/<command> [player]
    Example: /<command> - clears your own inventory.
    Example: /<command> Bukkit - clears Bukkit's inventory.}}}
    commands,clear,description,usage will be the key's of the map

    PS: I'll try and make a new thread tomorrow cherrs
     
  8. Offline

    NathanWolf

    Hi!

    If you're interested in a plugin framework for this, Persistence has a very nice command dispatch interface that handles sub-comands. Here's some example code from my sample plugin:


    Code:
    SampleDefaults d = new SampleDefaults();
    utilities = persistence.getUtilities(this);
    
    // Register Commands
    setCommand = utilities.getGeneralCommand(d.setCommand[0], d.setCommand[1], d.setCommand[2], PermissionType.ADMINS_ONLY);
    setNickNameCommand = setCommand.getSubCommand(d.setNickNameCommand[0], d.setNickNameCommand[1], d.setNickNameCommand[2], PermissionType.ADMINS_ONLY);
    
    showCommand = utilities.getGeneralCommand(d.showCommand[0], d.showCommand[1], d.showCommand[2]);
    showNickNameCommand = showCommand.getSubCommand(d.showNickNameCommand[0], d.showNickNameCommand[1], d.showNickNameCommand[2]);
    
     // Bind commands to handler methods
    showNickNameCommand.bind("onShowNickname");
    setNickNameCommand.bind("onSetNickname");
    You set this up in onEnable. You can see that you can build complex trees of sub-commands, and you only need to register the base command(s) in your YML file.

    For clarify, here is SampleDefaults- you don't have to keep your default text in a separate file, that's just something I do:

    Code:
    class SampleDefaults
    {
        public final String[] setCommand = {"set", "Base set command - use 'set nickname'", null};
        public final String[] setNickNameCommand = {"nickname", "Set a player's nickname", "<player> <nickname>"};
        public final String[] showCommand = {"show", "Base show command - use 'show nickname'", null};
        public final String[] showNickNameCommand = {"nickname", "Display a player's nickname", "<player>"};
    
        public final String changedNicknameMessage = "Set nickname for %s to %s";
        public final String showNicknameMessage = "%s's nickname is %s";
        public final String unknownPlayerMessage = "Player %s is unknown";
        public final String noNicknameMessage = "Player %s has no nickname";
    }
    There is also an interface for data-driven messaging, which is nice:

    Code:
    // Messages
     changedNicknameMessage = utilities.getMessage("changedNickname", d.changedNicknameMessage);
    showNicknameMessage = utilities.getMessage("showNickname", d.showNicknameMessage);
    unknownPlayerMessage = utilities.getMessage("unknownPlayer", d.unknownPlayerMessage);
    noNicknameMessage = utilities.getMessage("noNickname", d.noNicknameMessage);
    This lets you easily support customization and internationalization for your in-game messages.

    Anyway, for command dispatch, all you need to do at this point is set up handlers, like so:

    Code:
    public boolean onShowNickname(CommandSender sender, String[] parameters)
    {
    ...
    }
    Note that if I had used getPlayerCommand instead of getGeneralCommand in onEnable- I could write onShowNickname to accept a Player instead of a CommandSender, and avoid casting. But, do try to support server console commands when appropriate! In this case (nickname display and setting), it makes sense.

    Also, the parameters that get passed to your handler are the actual parameters, starting after the sub-command name.

    Anyway, that's pretty much it- jump into the Persistence thread if you're interested and have more questions.
     
  9. Offline

    Sammy

    thank u very much Nathan, that seems to be a great way to accomplish my goal,
    I'll try to implement this in my base plugin and in doubt I'll nag you a bit on the thread ^^
     
Thread Status:
Not open for further replies.

Share This Page