Solved Tab completion through CommandMap

Discussion in 'Spigot Plugin Development' started by notjacob1, Feb 27, 2020.

  1. I'm trying to create tab completions for my commands, which are registered through the command map
    here is what I have so far (example command class)
    Code (Java):

    public class CmdArenatp extends NotCommand {
       public CmdArenatp() {
          super("arenatp", "atp");
       }

       @Override
       public boolean execute(CommandSender sender, String commandLabel, String[] args) {
          if(!(sender instanceof Player)) {
             ChatUtilities.noconsole();
             return false;
          }
          Player p = (Player) sender;
          if (p.hasPermission("notduels.arena.tp")) {
             if (args.length == 1) {
                if (HandlerUtil.arenaFromString(args[0]) != null) {
                   if (HandlerUtil.getPool().getAvailable().contains(HandlerUtil.arenaFromString(args[0]))) {
                      if (Objects.requireNonNull(HandlerUtil.arenaFromString(args[0])).getSpawn1() != null) {
                         TeleportHandler.Teleport(p, Objects.requireNonNull(HandlerUtil.arenaFromString(args[0])).getSpawn1());
                         p.sendMessage(HandlerUtil.textGet("spawnTpComplete"));
                      } else {
                         p.sendMessage(HandlerUtil.textGet("noSpawnTp"));
                      }
                   } else {
                      p.sendMessage(HandlerUtil.textGet("InUseArenaTp"));
                   }
                } else {
                   p.sendMessage(HandlerUtil.textGet("ArenaNoExist"));
                }
             } else {
                p.sendMessage(ChatUtilities.usage("/arenatp (arena)"));
             }
          } else {
             p.sendMessage(ChatUtilities.noperm());
          }
       
          return true;
       }
       @Override
       public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
          List<String> temp = new ArrayList<String>();
          if (args.length == 0) {
             for (int i = 0; i < HandlerUtil.getPool().getAvailable().size(); i++) {
                if (i < 6) {
                   temp.add(((DuelArena) HandlerUtil.getPool().getAvailable().get(i)).getName());
                }
             }
          } else {
             temp = Collections.emptyList();
          }
          return temp;
       }
    }
     
    but when I enter "/atp" there are no tab completions (not even player names)
    EDIT: there are objects in .getAvailable()
    Code (Java):

    private synchronized void registerCommands() {
       if (!isPaperMc()) {
          Field bukkitCommandMap;
          try {
             bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap");
             bukkitCommandMap.setAccessible(true);
             CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer());
             for (NotCommand notCommand : commandmap) {
                commandMap.register("NotDuels", notCommand);
             }
          } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
             e.printStackTrace();
          }
       } else {
          for (NotCommand cmd : commandmap) {
             Bukkit.getCommandMap().register("NotDuels", cmd);
          }
       }
    }
     
    Code (Java):

    public abstract class NotCommand extends Command {
       // static so it's not duplicated when a new command is created
       public static Collection<String> commands;
       static {
          commands = new ArrayList<>();
       }
       protected NotCommand(String name) {
          super(name);
          NotMain.getPlugin().commandmap.add(this);
          commands.add(name);
       }
       protected NotCommand(String name, String... aliases) {
          super(name);
          setAliases(Arrays.asList(aliases));
          NotMain.getPlugin().commandmap.add(this);
          commands.add(name);
          commands.addAll(CollectionUtil.asList(aliases));
       }
       // static so it's not duplicated when a new command is created
       public static boolean isDuelsCommand(String command) {
          for (String s : commands) {
             if (command.equalsIgnoreCase(s)) {
                return true;
             }
          }
          return false;
       }
    }
     
    EDIT: im stupid lol. Fixed by changing if (args.length == 0) to if (args.length == 1)
     
    #1 notjacob1, Feb 27, 2020
    Last edited: Feb 27, 2020
  2. In order to get player name you need to use return null;

    Btw, try it that way:
    Code (Java):
    List<String> options= new ArrayList<String>();
            for (int i = 0; i < HandlerUtil.getPool().getAvailable().size(); i++) //why not use the i < 6 here?
                if (i < 6) //Double verification?
                    options.add(((DuelArena) HandlerUtil.getPool().getAvailable().get(i)).getName());
                } else {
                    options= Collections.emptyList();
                }
           
                if (args.length == 1)
                    return options;
    May I ask, why are so many people using the command map instead of the API???
     
    #2 Maxx_Qc, Feb 27, 2020
    Last edited: Feb 27, 2020
  3. I like the command map because it's super easy to create commands, for instance instead of having to add it to the plugin.yml I can just do super(comandname, aliases...); and I don't have to mess with anything else.
    also thanks for the tip about double verification, didnt notice that
     
    • Like Like x 1
  4. Also using options= Collections.emptyList(); will make your list empty. So if the i is bigger or equals to 6, then the list will be empty.