StarShadow

MC - Annotation-based Command System

Aug 2nd, 2016 (edited)
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.23 KB | None | 0 0
  1. import org.bukkit.ChatColor;
  2. import org.bukkit.Server;
  3. import org.bukkit.command.CommandSender;
  4. import org.bukkit.command.SimpleCommandMap;
  5. import org.bukkit.command.defaults.BukkitCommand;
  6. import org.bukkit.entity.Player;
  7. import org.bukkit.plugin.java.JavaPlugin;
  8.  
  9. import java.lang.annotation.ElementType;
  10. import java.lang.annotation.Retention;
  11. import java.lang.annotation.RetentionPolicy;
  12. import java.lang.annotation.Target;
  13. import java.lang.reflect.InvocationTargetException;
  14. import java.lang.reflect.Method;
  15. import java.lang.reflect.Type;
  16. import java.util.ArrayList;
  17. import java.util.Arrays;
  18. import java.util.List;
  19.  
  20. public class CmdWrapper {
  21.    
  22.     private final JavaPlugin plugin;
  23.    
  24.     public CmdWrapper(JavaPlugin plugin) {
  25.         this.plugin = plugin;
  26.     }
  27.    
  28.     @Retention(RetentionPolicy.RUNTIME)
  29.     @Target(ElementType.METHOD)
  30.     public @interface SCmd {
  31.         String name();
  32.         String description() default "";
  33.         String usage() default "";
  34.         String[] aliases() default {};
  35.         String[] require() default {};
  36.         String noPermMsg() default noPerm;
  37.         boolean playerOnly() default false;
  38.         String playerOnlyMsg() default playerOnly;
  39.         boolean consoleOnly() default false;
  40.         String consoleOnlyMsg() default consoleOnly;
  41.        
  42.         String noPerm = "&cYou don't have permission to use this command.";
  43.         String playerOnly = "The command is for players only.";
  44.         String consoleOnly = "The command can only be run from console.";
  45.     }
  46.    
  47.     @Retention(RetentionPolicy.RUNTIME)
  48.     @Target(ElementType.METHOD)
  49.     public @interface Cmd {
  50.         String value();
  51.     }
  52.    
  53.     @Retention(RetentionPolicy.RUNTIME)
  54.     @Target(ElementType.METHOD)
  55.     public @interface Description {
  56.         String value();
  57.     }
  58.    
  59.     @Retention(RetentionPolicy.RUNTIME)
  60.     @Target(ElementType.METHOD)
  61.     public @interface Usage {
  62.         String value();
  63.     }
  64.    
  65.     @Retention(RetentionPolicy.RUNTIME)
  66.     @Target(ElementType.METHOD)
  67.     public @interface Aliases {
  68.         String[] value();
  69.     }
  70.    
  71.     @Retention(RetentionPolicy.RUNTIME)
  72.     @Target(ElementType.METHOD)
  73.     public @interface Require {
  74.         String[] value();
  75.         String msg() default SCmd.noPerm;
  76.     }
  77.    
  78.     @Retention(RetentionPolicy.RUNTIME)
  79.     @Target(ElementType.METHOD)
  80.     public @interface PlayerOnly {
  81.         String msg() default SCmd.playerOnly;
  82.     }
  83.    
  84.     @Retention(RetentionPolicy.RUNTIME)
  85.     @Target(ElementType.METHOD)
  86.     public @interface ConsoleOnly {
  87.         String msg() default SCmd.consoleOnly;
  88.     }
  89.    
  90.     private static class CmdInfo extends BukkitCommand {
  91.         private Method method;
  92.         private Object object;
  93.         CmdInfo(String name, Object object, Method method) {
  94.             super(name, getDescription(method), getUsage(method), getAliases(method));
  95.             this.method = method;
  96.             this.object = object;
  97.         }
  98.         @Override
  99.         public boolean execute(CommandSender sender, String label, String[] args) {
  100.             if (!method.isAccessible()) method.setAccessible(true);
  101.             try {
  102.                 if (sender instanceof Player){
  103.                     if (isConsoleOnly(method)) {
  104.                         String msg = consoleOnlyMsg(method);
  105.                         if (!msg.isEmpty()) sender.sendMessage(ChatColor.translateAlternateColorCodes('&', msg));
  106.                         return true;
  107.                     }
  108.                     Player player = (Player) sender;
  109.                     for (String perm : getRequired(method)) {
  110.                         if (player.isOp() || player.hasPermission(perm)) continue;
  111.                         String msg = getMsg(method);
  112.                         if (!msg.isEmpty()) player.sendMessage(ChatColor.translateAlternateColorCodes('&', msg));
  113.                         return true;
  114.                     }
  115.                 }
  116.                 else {
  117.                     if (isPlayerOnly(method)) {
  118.                         String msg = playerOnlyMsg(method);
  119.                         if (!msg.isEmpty()) sender.sendMessage(ChatColor.translateAlternateColorCodes('&', msg));
  120.                         return true;
  121.                     }
  122.                 }
  123.                 return (boolean) method.invoke(object, sender, args);
  124.             } catch (IllegalAccessException | InvocationTargetException e) {
  125.                 e.printStackTrace();
  126.             }
  127.             return true;
  128.         }
  129.         static String getCommand(Method method) {
  130.             SCmd scmd = method.getAnnotation(SCmd.class);
  131.             if (scmd != null) return scmd.name();
  132.             return method.getAnnotation(Cmd.class).value();
  133.         }
  134.         static String getDescription(Method method) {
  135.             SCmd scmd = method.getAnnotation(SCmd.class);
  136.             if (scmd != null) return scmd.description();
  137.             Description desc = method.getAnnotation(Description.class);
  138.             return (desc == null ? "" : desc.value());
  139.         }
  140.         static String getUsage(Method method) {
  141.             SCmd scmd = method.getAnnotation(SCmd.class);
  142.             if (scmd != null) return scmd.usage();
  143.             Usage usage = method.getAnnotation(Usage.class);
  144.             return (usage == null ? "" : usage.value());
  145.         }
  146.         static List<String> getAliases(Method method) {
  147.             SCmd scmd = method.getAnnotation(SCmd.class);
  148.             if (scmd != null) return Arrays.asList(scmd.aliases());
  149.             Aliases aliases = method.getAnnotation(Aliases.class);
  150.             return (aliases == null ? new ArrayList<>() : Arrays.asList(aliases.value()));
  151.         }
  152.         static List<String> getRequired(Method method) {
  153.             SCmd scmd = method.getAnnotation(SCmd.class);
  154.             if (scmd != null) return Arrays.asList(scmd.require());
  155.             Require require = method.getAnnotation(Require.class);
  156.             return (require == null ? new ArrayList<>() : Arrays.asList(require.value()));
  157.         }
  158.         static String getMsg(Method method) {
  159.             SCmd scmd = method.getAnnotation(SCmd.class);
  160.             if (scmd != null) return scmd.noPermMsg();
  161.             Require require = method.getAnnotation(Require.class);
  162.             return (require == null ? SCmd.noPerm : require.msg());
  163.         }
  164.         static boolean isPlayerOnly(Method method) {
  165.             SCmd scmd = method.getAnnotation(SCmd.class);
  166.             if (scmd != null) return scmd.playerOnly();
  167.             PlayerOnly playerOnly = method.getAnnotation(PlayerOnly.class);
  168.             return (playerOnly != null);
  169.         }
  170.         static String playerOnlyMsg(Method method) {
  171.             SCmd scmd = method.getAnnotation(SCmd.class);
  172.             if (scmd != null) return scmd.playerOnlyMsg();
  173.             PlayerOnly playerOnly = method.getAnnotation(PlayerOnly.class);
  174.             return (playerOnly == null ? SCmd.playerOnly : playerOnly.msg());
  175.         }
  176.         static boolean isConsoleOnly(Method method) {
  177.             SCmd scmd = method.getAnnotation(SCmd.class);
  178.             if (scmd != null) return scmd.consoleOnly();
  179.             ConsoleOnly consoleOnly = method.getAnnotation(ConsoleOnly.class);
  180.             return (consoleOnly != null);
  181.         }
  182.         static String consoleOnlyMsg(Method method) {
  183.             SCmd scmd = method.getAnnotation(SCmd.class);
  184.             if (scmd != null) return scmd.consoleOnlyMsg();
  185.             ConsoleOnly consoleOnly = method.getAnnotation(ConsoleOnly.class);
  186.             return (consoleOnly == null ? SCmd.consoleOnly : consoleOnly.msg());
  187.         }
  188.     }
  189.    
  190.     public static void register(JavaPlugin plugin, Object object) {
  191.         SimpleCommandMap map = getCommandMap(plugin.getServer());
  192.         if (map == null) return;
  193.         Arrays.stream(object.getClass().getDeclaredMethods()).filter(CmdWrapper::hasAnnotation).filter(CmdWrapper::correctSignature).forEach(method -> {
  194.             String name = CmdInfo.getCommand(method);
  195.             map.register(name, new CmdInfo(name, object, method));
  196.         });
  197.     }
  198.    
  199.     public void addCommands(Object object) {
  200.         register(plugin, object);
  201.     }
  202.    
  203.     private static SimpleCommandMap getCommandMap(Server server) {
  204.         String version;
  205.         try {
  206.             version = server.getClass().getPackage().getName().split("\\.")[3];
  207.         } catch (ArrayIndexOutOfBoundsException e) {
  208.             return null;
  209.         }
  210.         if (version == null) return null;
  211.         try {
  212.             Class<?> clazz = Class.forName("org.bukkit.craftbukkit." + version + ".CraftServer");
  213.             Method method = clazz.getDeclaredMethod("getCommandMap");
  214.             return (SimpleCommandMap) method.invoke(clazz.cast(server));
  215.         } catch (ClassNotFoundException e) {
  216.             return null;
  217.         } catch (NoSuchMethodException e) {
  218.             return null;
  219.         } catch (InvocationTargetException | IllegalAccessException e) {
  220.             return null;
  221.         }
  222.     }
  223.    
  224.     private static boolean hasAnnotation(Method method) {
  225.         return (method.isAnnotationPresent(SCmd.class) || method.isAnnotationPresent(Cmd.class));
  226.     }
  227.    
  228.     private static boolean correctSignature(Method method) {
  229.         // boolean method(CommandSender, String[])
  230.         Type[] types = method.getGenericParameterTypes();
  231.         if (types.length != 2) return false;
  232.         if (!CommandSender.class.getCanonicalName().equalsIgnoreCase(types[0].getTypeName())) return false;
  233.         if (!String[].class.getCanonicalName().equalsIgnoreCase(types[1].getTypeName())) return false;
  234.         if (!boolean.class.getCanonicalName().equalsIgnoreCase(method.getGenericReturnType().getTypeName())) return false;
  235.         return true;
  236.     }
  237.    
  238. }
Add Comment
Please, Sign In to add comment