Search code examples
pluginsminecraftbukkitspigot

How to make commands with subcommands in spigot plugins?


So I'm trying to make a command with subcommands
command examples:

/its heal (player)
/its feed (player)
/its help

Here is my main plugin file code if needed:

    package com.itsmateo20;
    
    import com.itsmateo20.events.JoinQuit;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class ItsPlugin20 extends JavaPlugin {
        private static ItsPlugin20 instance;
    
    
        @Override
        public void onEnable() {
            instance = this;
            FileConfiguration config = getConfig();
            config.addDefault("Prefix", "[ItsPlugin20]:");
            config.addDefault("JoinQuit", true);
            config.options().copyDefaults(true);
            saveConfig();

            if (config.getBoolean("JoinQuit")) {
                Bukkit.getPluginManager().registerEvents(new JoinQuit(), this);
            }
            Bukkit.getLogger().info(config.getString("Prefix") + ChatColor.GREEN + " Enabled successfully!");
        }
    
        @Override
        public void onDisable() {
            FileConfiguration config = getConfig();
            Bukkit.getLogger().info(config.getString("Prefix") + ChatColor.RED + " Disabled successfully!");
        }
    
        public static ItsPlugin20 getInstance() {
            return instance;
        }
    }

Solution

  • Firstly, you have to register your command in your plugin.yml file :

    commands:
       its:
          description: "Made things"
    

    Then, to use it in your plugin, in the onEnable() method :

    getCommand("its").setExecutor(new ItsCommand());
    

    After this, you should create the class ItsCommand and make the complete command, with all sub commands. Spigot don't have a very good API for this. The class should look like that :

    public class ItsCommand implements CommandExecutor {
    
        @Override
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            return false;
        }
    }
    

    The method will be called each time the command will be runned.

    1. The sender can be the console, a command block or the player. We should check by using :
    if(!(sender instanceof Player)) {
       sender.sendMessage("Only players can run this command !");
       return false;
    }
    
    1. The command is globally never used.
    2. The label correspond to the exact command that the player runned (to know if it's "/plugin:its", "/its" ...)
    3. The args are what you are looking for.

    You should check if it's empty with args.length == 0, and so the player just use "/its". You can show the help.

    Then, you should check what is the argument, like args[0].equalsIgnoreCase("feed").

    Complete example of the method :

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if(!(sender instanceof Player)) {
            sender.sendMessage("Only players can run this command !");
            return false;
        }
        Player p = (Player) sender;
        if(args.length == 0 || args[0].equalsIgnoreCase("help")) { // if no args or help
            showHelp(p);
        } else if(args[0].equalsIgnoreCase("feed")) { // if the first arg is what you want
            if(args.length == 1) { // only run "/its feed" without player
                p.sendMessage(ChatColor.RED + "You forget the player name !");
                return false;
            }
    
            Player cible = Bukkit.getPlayer(args[1]); // get the player given
            if(cible == null){ // player not online/invalid
                p.sendMessage(ChatColor.RED + "The given player doesn't exist !");
            } else {
                cible.setFoodLevel(20); // do what you want with the cible
                p.sendMessage(ChatColor.GREEN + "Player feeded !");
            }
        } else { // unknow sub command
            p.sendMessage(ChatColor.RED + "Unknow arguments !");
            showHelp(p);
        }
        return false;
    }