Easy Command Handler

Discussion in 'Resources' started by SoThatsIt, Nov 9, 2013.

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

    SoThatsIt

    Here is a simple command handling system that i am going to use in my latest release of pushball. Note, this is not tested so please post below the error or even better a fix if there is an error. Also if im doing something wrong tell me!

    Command.java
    Code:
    package me.sothatsit.pushball.cmd;
     
    import java.util.Arrays;
    import java.util.List;
    import java.util.ArrayList;
     
    import org.bukkit.ChatColor;
    import org.bukkit.command.CommandSender;
     
    public class Command{
       
        private String permission;
        private Handler noPermHandler;
        private Handler runHandler;
        private List<String> commandLabels;
        private List<Command> subCommands;
        private Command superCommand;
       
        public Command(String... commandLabels){
            this.commandLabels = new ArrayList<String>(Arrays.asList(commandLabels));
            this.subCommands = new ArrayList<Command>();
            this.permission = null;
            this.noPermHandler= null;
            this.runHandler = null;
            this.superCommand = null;
        }
       
        //Getters and Setters
        public void addSubCommand(Command command){this.subCommands.add(command);command.setSuperCommand(this);}
        public void setPermHanlder(Handler permHandler){this.noPermHandler=permHandler;}
        public void setRunHandler(Handler runHandler){this.runHandler=runHandler;}
        public void setPerm(String permission){this.permission=permission;}
        public void setSuperCommand(Command superCommand){this.superCommand=superCommand;}
       
        public Command getSuperCommand(){return superCommand;}
        public List<String> getLabels(){return commandLabels;}
        public String getLabel(){if(getLabels().size()>0)return getLabels().get(0);else return "";}
       
        public boolean isCommand(String label){
            for(String l : commandLabels){
                if(l.equalsIgnoreCase(label))return true;
            }
            return false;
        }
        public boolean checkPerms(CommandSender sender, String[] args){
            if(permission == null)return true;
            else{
                if(noPermHandler != null)noPermHandler.run(sender, args);
                return sender.hasPermission(permission);
            }
        }
       
        //Run Command method
        public void run(CommandSender sender, String[] args){
            if(checkPerms(sender, args)){
                boolean found = false;
                if(args.length > 0){
                    for(Command c : subCommands){
                        if(c.isCommand(args[0])){
                            c.run(sender, Arrays.copyOfRange(args, 1, args.length));
                            found = true;
                        }
                    }
                }
                if(runHandler != null)runHandler.run(sender, args);
                else if(!found && subCommands.size() > 0){
                    String message = this.getLabel()+" ";
                    Command cmd = this;
                    while(cmd.getSuperCommand() != null){
                        message = cmd.getSuperCommand().getLabel() + " " + message;
                        cmd = cmd.getSuperCommand();
                    }
                   
                    message = message + "[";
                    for(int i=0; i<subCommands.size(); i++){
                        Command command = subCommands.get(i);
                        message = message + (i!=0 ? ", " : "") + command.getLabel();
                    }
                    message = message + "]";
                   
                    sender.sendMessage(ChatColor.RED+message);
                }
            }else{
                if(noPermHandler != null)noPermHandler.run(sender, args);
                else{
                    sender.sendMessage(ChatColor.RED+"Sorry, you do not have permission to run this command");
                }
            }
        }
       
        public interface Handler{
            public void run(CommandSender sender, String[] args);
        }
    }
    How do i use it?
    This works by you creating an initial command object and then adding sub commands to it, you can add an infinite amount of sub commands.

    firstly, you must create a base command, this command does not need any command label as you call it yourself in your onCommand method.
    Code:
    Command cmd = new Command();
    you must then create your sub commands.
    Code:
    Command sub1 = new Command("sub1", "sub1aliase", "asManyAliasesAsYouNeed");
    Command sub2 = new Command("sub2", "sub2aliase", "asManyAliasesAsYouNeed");
    you now must add those sub commands to your main command, note this is the same way you would do it if you were adding another sub command to one of your current sub commands.
    Code:
    cmd.addSubCommand(sub1);
    cmd.addSubCommand(sub2);
    you now must go into your onCommand method and run the command.
    Code:
    public boolean onCommand(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args){
            if(label.equalsIgnoreCase("cmd") || label.equalsIgnoreCase("command"))cmd.run(sender, args);
            return true;
        }
    if you need to use permissions you can set the permissions for each command as well.
    Code:
    cmd.setPerm("myplugin.cmd");
    sub1.setPerm("myplugin.cmd.sub1");
    you can also set the run handler for when the command is run or the perm handler which runs when the permission is not met. if you do not set the perm handler it will simply send "you do not have permission to run this command" to the user.
    Code:
    //add perm handler
    cmd.addPermHandler(new Command.Handler() {
      public void run(CommandSender sender, String[] args){
          //do stuff
      }
    });
     
    //add run handler
    cmd.addRunHandler(new Command.Handler() {
      public void run(CommandSender sender, String[] args){
          //do stuff
      }
    });
    you can also create classes which implement Command.Handler and use them.
    Code:
    public class CommandSub1 implements Command.Handler{
        public void run(CommandSender sender, String[] args) {
            //do stuff
        }
    }
    Code:
    sub1.setRunHandler(new CommandSub1());
    if it cannot find the requested sub command, you run command "/cmd sub3" but there is no sub3, it will send you a message looking like this "cmd [sub1,sub2]"

    Example
    Coming Soon!

    i hope this helps with anyones command handling
    ~sothatsit
     
  2. Offline

    drtshock

    Why are you using labels instead of commands?
     
  3. Offline

    SoThatsIt

    what do you mean?
     
  4. Offline

    drtshock

    You are checking command labels instead of the command name. That isn't good in most cases :\ Makes it so if people define aliases they won't work.
     
    Aengo and Ivan like this.
  5. Offline

    SoThatsIt

    you must call the base command in the onCommand method and you check there whether the command is what you want... other than that its just checking the args so i cant see whats wrong

    just found some errors with this although i have updated the post above with a new version with a fix

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  6. Offline

    Ultimate_n00b

    What I like to do, is make good use of the Permission object.
    You can define the permission, who can use it by default, AND the usage.
    I also use a little hack which adds the command, without using the plugin.yml.
     
  7. Offline

    SoThatsIt

    so i should take a Permission object instead of a string? and registering the commands without a plugin.yml sounds interesting, how would you do that :D
     
  8. Offline

    Ultimate_n00b

    Google it, it involves using reflection to modify the object holding the commands.
     
  9. Offline

    mkremins

    To elaborate a little: Bukkit handles commands by generating a Command object for each command registered in a plugin's manifest file (plugin.yml) and storing these Command objects in a structure called a CommandMap. The CommandMap isn't exposed through the public Bukkit API, because it's treated as an "implementation detail" of the commands API that's subject to change at any time and for any reason; that said, it's perfectly safe to register your own objects in it if you make it accessible using reflection.

    One project that does something of the sort to enable dynamic command registration is the sk89q-command-framework, whose source code you can examine to get a feel for the internals of the command API that you need to "hack" if you want to dynamically register commands. I also have some experience messing with this stuff, so feel free to ask if you want to learn more.
     
    Ultimate_n00b likes this.
  10. Offline

    Ultimate_n00b

    Yep, the hard part is getting/setting bukkit's CommandMap.
     
  11. Offline

    xTrollxDudex

    SoThatsIt
    That's a really long class for handling commands, just saying. Mine is less that 50 lines, if you remove the white space.
     
  12. Offline

    SoThatsIt

    well it works :D
     
  13. Offline

    xTrollxDudex

    I never said t didn't
     
Thread Status:
Not open for further replies.

Share This Page