Util Register Commands Without Plugin.yml!

Discussion in 'Resources' started by mine-care, Mar 19, 2015.

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

    mine-care

    I am making a plugin that requires users to register commands themselvs. To do that i had to go into Bukkit CraftServer and use command map to register the command. So i decided to share it with you =D
    I know it has been out there and there are great tutorials to do this (i hope) so if i came second/third/fourth... please dont take that into consideration;

    The method:
    Code:
        public static void registerFakeCommand(Command whatCommand,Plugin plugin)
                throws ReflectiveOperationException {
                //Getting command map from CraftServer
                Method commandMap = plugin.getServer().getClass().getMethod("getCommandMap", null);
                //Invoking the method and getting the returned object (SimpleCommandMap)
                Object cmdmap = commandMap.invoke(plugin.getServer(), null);
                //getting register method with parameters String and Command from SimpleCommandMap
                Method register = cmdmap.getClass().getMethod("register", String.class,Command.class);
                //Registering the command provided above
                register.invoke(cmdmap, whatCommand.getName(),whatCommand);
                //All the exceptions thrown above are due to reflection, They will be thrown if any of the above methods
                //and objects used above change location or turn private. IF they do, let me know to update the thread!
        }
    
    How to use:
    In order to use it, you need to make a class that extends either Command or BukkitCommand (preferably BukkitCommand) and then provide it to the above method ^
    Sample code:
    SampleCode (open)


    The command class:
    Code:
    public class FakeCommandRegistry extends BukkitCommand {
        public FakeCommandRegistry(String permission,String name, String description,
                String usageMessage, List<String> aliases) {
            super(name, description, usageMessage, aliases);
            this.setPermission(permission);
          
        }
        @Override
        public boolean execute(CommandSender sender, String arg1, String[] arg2) {
            if (!sender.hasPermission(this.getPermission())) {
                sender.sendMessage(ChatColor.RED + "You dont have permission to do this!");
                return true;
            }
            if(!(sender instanceof Player)){
                sender.sendMessage(ChatColor.RED+"Only players can do this!");
                return false;
            }
            Player p = (Player)sender;
           // Handle the command as you normally would in any CommandExecutor class.
            return false;
        }
    }
    In your onEnable method (or anywhere you want your commands to be registered;):
    Code:
        public void onEnable(){
        try {
                FakeCommandRegister.registerFakeCommand(new FakeCommandRegistry(this, "permission.to.command", "cmdname", "Command Description", "Usage Message", Arrays.asList("List","Of","Aliases")), this);
            } catch (NoSuchMethodException | SecurityException
                    | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException e) {
                e.printStackTrace();
            }
        }



    Please leave feedback =D i would love to hear any other ideas you have on such utils i can make.

    TODO:

    Add sample code :$ thanks @ChipDev for the reminder

    Think i deserve it? throw me a "Like" =)
     
    Last edited: Apr 14, 2015
  2. Offline

    ChipDev

    Thats amazing! 10/10 love it. Its so simple, and that it uses NMS, it gets even better.
    Oh the things you can do!
    P.S: Nice job on the comments, It helps new people learn what you are doing, like Method#invoke!
     
  3. Offline

    mine-care

    @ChipDev Firsty commenty! =-D
    ty! Anything else i can add?
     
    ChipDev likes this.
  4. Offline

    ChipDev

    Maybe just a clarification on if you have to register on the enable?
     
  5. Offline

    mine-care

    @ChipDev True! i will provide a sample code :$ i completely forgot it! TY!
     
    ChipDev likes this.
  6. Offline

    MexMaster

    Wouldn't it be possible just by using the PlayerCommandPreProcess and do something?

    But nice thing ;)!
     
  7. Offline

    mrCookieSlime Retired Staff

    @MexMaster
    It would.
    However it would not be added to the /help page nor would it allow the usage of TAB-completion.
     
    mine-care and MexMaster like this.
  8. Offline

    mine-care

    @MexMaster Thanks! =), upon what @mrCookieSlime said, No... if you do a command that is not registered, it will still show the "Unknown command type /help for help" after you do something with tha command :p
     
  9. Offline

    mrCookieSlime Retired Staff

    @mine-care
    It will not, if you cancel the Event.
     
  10. Offline

    mine-care

  11. Offline

    xTrollxDudex

    It doesn't use NMS

    @mine-care
    Please make your command map a field. The object returned by the command map is a direct reference to original field, there is no need to call it every time.
     
    ChipDev likes this.
  12. Offline

    mine-care

    @xTrollxDudex i think he ment "that messes with NMS" refering to the package net#minecraft#server :3
    But good point :p
     
    ChipDev likes this.
  13. Offline

    ChipDev

    Really?
    Yuss! I figured it out!
     
  14. Offline

    AdamQpzm

    nverdier likes this.
  15. Offline

    mine-care

    @AdamQpzm I know.. I know... ReflectiveOperationException :3
    Other than that i need to fix the inefficiencies as sugested above.
     
  16. Offline

    AdamQpzm

    @mine-care The problem was actually more along the lines of "this simple method is throwing too many damn Exceptions!" Also I wonder at the value in it being a public static method. It's not like you'll repeatedly be registering your commands... right?
     
    mine-care likes this.
  17. Offline

    mine-care

    @AdamQpzm well it is simple to use, Reflection comes with a price :3 And yes it should be mentioned that it is commingwith those "side effects" :) but to be fairly honest i have abanoded this thread a litle.
     
  18. Offline

    AdamQpzm

    @mine-care You know exceptions can be caught and handled... right?
     
  19. Offline

    mine-care

    @AdamQpzm Really? XD jk.
    Yes i do but i wanted to leave that to the possible user of this method. Because what i would do is print the stack trace, Someone might want to do something else with it so i wanted to provide this ability.
     
  20. Offline

    Rixterz

    Argument type mismatch :/
     
  21. Offline

    timtower Moderator Moderator

    @Rixterz On what? What code do you have?
     
  22. Offline

    FisheyLP

    Maybe instead of "List<String> aliases" you could use "String... aliases" and convert it to a List<String> when calling the super constructor? Just more pleasant to add aliases.

    Also, why do you call:
    Code:
    registerFakeCommand(new FakeCommandRegistry(this, 
    But the first argument of the constructor of FakeCommandRegistry is actually a string... :confused:

    And now make a util to unregister commands :p

    I have already done this if you're interested:
    Show Spoiler
    I used a util class for reflections but the method names are self explanatory if you want to convert it to regular reflections.
    Code:
    public void unregisterCommands(String... cmds) {
            for (String cmd : cmds) {
        try {
            PluginCommand command = (PluginCommand) main.getCommand(cmd);
            CommandMap map = (CommandMap) Reflections.getDeclaredField(Bukkit.getPluginManager(),
                    "commandMap");
            HashMap<String, Command> knownCommands = (HashMap<String, Command>)
                    Reflections.getDeclaredField(map, "knownCommands");
            knownCommands.remove(command.getName());
            for (String alias : command.getAliases())
               if (knownCommands.containsKey(alias) &&
                      knownCommands.get(alias).toString().contains(main.getName()))
                    knownCommands.remove(alias);
        } catch (Exception e) {
            Bukkit.getConsoleSender().sendMessage(l+"§4The command §c"+cmd+""
                    + " §4couldn't be removed!");
                }
            }
        }
     
    Last edited: Jun 22, 2016
Thread Status:
Not open for further replies.

Share This Page