Using the bukkit CommandMap

Discussion in 'Plugin Development' started by WesJD, Jan 25, 2015.

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

    WesJD

    Hey.

    Recently I've been working on this class so you don't need to input your commands into the plugin.yml. I've been attempting different approaches all day to get this working, thought no luck. Mind pointing me in the right direction?

    RetronCommand:

    Code:
    /**
    * ****************************************************************************************
    * All code contained within this document is sole property of WesJD. All rights reserved.*
    * Do NOT distribute/reproduce any of this code without permission from WesJD.            *
    * Not following this statement will result in a void of all agreements made.             *
    * Enjoy.                                                                                 *
    * ****************************************************************************************
    */
    public abstract class RetronCommand extends Command {
    
        public RetronCommand(String name) {
            super(name);
            Main.registerCommand(this);
        }
    
        @Override
        public boolean execute(CommandSender sender, String string, String[] args) {
            if (sender instanceof Player) {
                RetronPlayer p = new RetronPlayer((Player) sender);
    
                if (p.isGhosted()) {
                    p.message(Main.getPrefix() + ChatColor.RED + "Error: You are currenty ghosted. Please relog to fix this.");
                    return false;
                }
    
                onCmd(p, string, args);
    
            } else {
                sender.sendMessage(ChatColor.RED + "Only players can use commands.");
            }
            return false;
        }
    
        public abstract void onCmd(RetronPlayer p, String string, String[] args);
    
    }
    The register command method & how I get the bukkit CommandMap:

    Code:
    public static void registerCommand(Command cmd) {
            cmap.register("", cmd);
        }
    Code:
    //cmap is just a CommandMap instance
    
    try {
                Field f = Bukkit.getServer().getClass().getDeclaredField("commandMap");
                f.setAccessible(true);
                cmap = (CommandMap) f.get(Bukkit.getServer());
                f.setAccessible(false);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    (no errors.)
     
  2. Offline

    ESSHD

    @WesJD I'm not sure if this is possible, I was trying this the other day and was trying everything under the sun.

    I wouldn't say give up trying, maybe there is. But it's not likely..
     
  3. Offline

    TheMrGong

    create your own command registration
     
  4. Offline

    WesJD

  5. Offline

    mine-care

    That might be wrong but mabe use reflection to override the unknown command message and process commands on preprocesscommand event :-3 but yes command map will be the ideal way
     
  6. Offline

    1Rogue

    It's certainly possible, but I don't know why you would bother when the plugin yml is only a couple lines to add.
     
  7. Offline

    TheMrGong

    API's.. API's..
     
  8. Offline

    WesJD

    @1Rogue So I can create a command in 5 seconds with no hassle of setting it up.
     
  9. Offline

    1Rogue

    Code:
    commands:
      mycommand:
        description: such hassle very ptsd
     
  10. Offline

    WesJD

    @1Rogue Don't forget to set the executor class.
     
  11. Offline

    1Rogue

    Well you certainly can do that, but that's up to you for java. There are very simple ways of abstracting your own command system to handle commands from bukkit, such as defining your own Command class and having a CommandHandler or something of the sort.
     
  12. Offline

    WesJD

    Changed the code up to this, but still no luck.
    Code:
    /**
    * ****************************************************************************************
    * All code contained within this document is sole property of WesJD. All rights reserved.*
    * Do NOT distribute/reproduce any of this code without permission from WesJD.            *
    * Not following this statement will result in a void of all agreements made.             *
    * Enjoy.                                                                                 *
    * ****************************************************************************************
    */
    public abstract class RetronCommand implements CommandExecutor {
    
        private final class HandleCommand extends Command {
    
            private RetronCommand rcmd = null;
    
            public HandleCommand(String name) {
                super(name);
            }
    
            public void setExecutor(RetronCommand rcmd) {
                rcmd = rcmd;
            }
    
            @Override
            public boolean execute(CommandSender sender, String s, String[] args) {
                return rcmd.onCommand(sender, this, s, args);
            }
    
        }
    
        private CommandMap cmap = null;
        private String name;
    
        public RetronCommand(String name) {
            this.name = name;
            registerCommand();
        }
    
        private void registerCommand() {
            HandleCommand hcmd = new HandleCommand(name);
            if(cmap == null) {
                try {
                    final Field f = Bukkit.getServer().getClass().getDeclaredField("commandMap");
                    f.setAccessible(true);
                    cmap = (CommandMap) f.get(Bukkit.getServer());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            cmap.register("", hcmd);
            hcmd.setExecutor(this);
        }
    
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String s, String[] args) {
            if (sender instanceof Player) {
                RetronPlayer p = new RetronPlayer((Player) sender);
    
                if (p.isGhosted()) {
                    p.message(Main.getPrefix() + ChatColor.RED + "Error: You are currenty ghosted. Please relog to fix this.");
                    return false;
                }
    
                onCmd(p, s, args);
    
            } else {
                sender.sendMessage(ChatColor.RED + "Only players can use commands.");
            }
            return false;
        }
    
        public abstract void onCmd(RetronPlayer p, String string, String[] args);
    
    }
     
  13. Offline

    1Rogue

    Well not quite, you don't use bukkit's command class, you implement your own. For instance the one I use for subcommands:

    Code:java
    1. /*
    2.  * Copyright (C) 2015 Codelanx, All Rights Reserved
    3.  *
    4.  * This work is licensed under a Creative Commons
    5.  * Attribution-NonCommercial-NoDerivs 3.0 Unported License.
    6.  *
    7.  * This program is protected software: You are free to distrubute your
    8.  * own use of this software under the terms of the Creative Commons BY-NC-ND
    9.  * license as published by Creative Commons in the year 2015 or as published
    10.  * by a later date. You may not provide the source files or provide a means
    11.  * of running the software outside of those licensed to use it.
    12.  *
    13.  * This program is distributed in the hope that it will be useful,
    14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    16.  *
    17.  * You should have received a copy of the Creative Commons BY-NC-ND license
    18.  * long with this program. If not, see <[url]https://creativecommons.org/licenses/>[/url].
    19.  */
    20. package com.codelanx.codelanxlib.command;
    21.  
    22. import com.codelanx.codelanxlib.config.lang.Lang;
    23. import com.codelanx.codelanxlib.implementers.Commandable;
    24. import java.util.Arrays;
    25. import java.util.LinkedList;
    26. import java.util.List;
    27. import org.bukkit.command.CommandSender;
    28. import org.bukkit.plugin.Plugin;
    29.  
    30. /**
    31. * Skeleton class representing the structure of a sub-command for
    32. * {@link CommandHandler}
    33. *
    34. * @since 0.0.1
    35. * @author 1Rogue
    36. * @version 0.0.1
    37. *
    38. * @param <T> Represents a {@link Plugin} that implements the
    39. * {@link Commandable} interface
    40. */
    41. public abstract class SubCommand<T extends Plugin & Commandable<T>> {
    42.  
    43. /** The main {@link Plugin} instance */
    44. protected final T plugin;
    45.  
    46. /**
    47.   * {@link SubCommand} constructor
    48.   *
    49.   * @since 0.0.1
    50.   * @version 0.0.1
    51.   *
    52.   * @param plugin The {@link Plugin} associated with this command
    53.   */
    54. public SubCommand(T plugin) {
    55. this.plugin = plugin;
    56. }
    57.  
    58. /**
    59.   * Executes a relevant command grabbed from the {@link CommandHandler}.
    60.   *
    61.   * @since 0.0.1
    62.   * @version 0.0.1
    63.   *
    64.   * @param sender The command executor
    65.   * @param args The command arguments, starting after the command name
    66.   *
    67.   * @return The {@link CommandStatus} representing the result of the command
    68.   */
    69. public abstract CommandStatus execute(CommandSender sender, String... args);
    70.  
    71. /**
    72.   * Returns the name of the command, used for storing a
    73.   * {@link java.util.HashMap} of the commands as well as the subcommand
    74.   * argument
    75.   *
    76.   * @since 0.0.1
    77.   * @version 0.0.1
    78.   *
    79.   * @return The command's name
    80.   */
    81. public abstract String getName();
    82.  
    83. /**
    84.   * Returns the command usage
    85.   *
    86.   * @since 0.0.1
    87.   * @version 0.0.1
    88.   *
    89.   * @return Usage for this {@link SubCommand}
    90.   */
    91. public String getUsage() {
    92. return "/" + this.plugin.getCommandHandler().getMainCommand() + " " + this.getName();
    93. }
    94.  
    95. /**
    96.   * Information about this specific command. Should be kept concise
    97.   *
    98.   * @since 0.0.1
    99.   * @version 0.0.1
    100.   *
    101.   * @return A small string about the command
    102.   */
    103. public abstract Lang info();
    104.  
    105. /**
    106.   * Returns a permissions check for
    107.   * {@code <plugin-name>.cmd.<subcommand-name>}, can be nested into further
    108.   * permissions by passing tokens to append to the end of the permission
    109.   * string
    110.   *
    111.   * @since 0.0.1
    112.   * @version 0.0.1
    113.   *
    114.   * @param sender The {@link CommandSender} executing this command
    115.   * @param tokens Any additional tokens to append to the end of the string
    116.   * @return {@code true} if they have permission, {@code false} otherwise
    117.   */
    118. public boolean hasPermission(CommandSender sender, String... tokens) {
    119. List<String> lis = new LinkedList<>();
    120. lis.add(this.plugin.getName().toLowerCase());
    121. lis.add("cmd");
    122. lis.add(this.getName());
    123. lis.addAll(Arrays.asList(tokens));
    124. return sender.hasPermission(String.join(".", lis));
    125. }
    126.  
    127. }


    If you want, since you'd be extending your class, rather than even have a command manager you can simply have the command objects register themselves:

    Code:java
    1.  
    2. public abstract class SubCommand<T extends Plugin & Commandable<T>> {
    3.  
    4. /** The main {@link Plugin} instance */
    5. protected final T plugin;
    6.  
    7. /**
    8.   * {@link SubCommand} constructor
    9.   *
    10.   * @since 0.0.1
    11.   * @version 0.0.1
    12.   *
    13.   * @param plugin The {@link Plugin} associated with this command
    14.   */
    15. public SubCommand(T plugin) {
    16. this.plugin = plugin;
    17. this.plugin.getCommand(this.getName()).setExecutor(this); //register the command upon construction
    18. }
    19.  
    20. }
     
  14. Offline

    WesJD

    @1Rogue I've just decided to use the plugin.yml, as I just wasted a day for where I am now. Maybe I'll work on it again when everything else is done. Thanks for the help though!
     
Thread Status:
Not open for further replies.

Share This Page