本帖最后由 RecursiveG 于 2016-12-18 06:40 编辑
论坛竟然没有滑稽表情,差评!
大家平时写子命令都是都是用的switch或者if吧,但是这种方法在子命令多的情况下特别蛋疼,代码很乱,各种嵌套,影响阅读。
今天我讲给各位介绍利用
Annotation+反射实现更加方便清晰易用的子命令。
什么是Annotation? 百度去
什么是反射? 百度去
接下来,我将以一个/xxx命令为
梨子,来介绍利用Annotation写
子命令。
首先,你需要准备的是:
电脑
大脑
双手
滑稽
打开我们的IDE,我创建一个工程,并且完成包,类的,创建。并且在plugin.yml里注册xxx命令。
他看起来是这样的额
接下来,我们在onEnable方法里注册命令,并创建命令类。
一切看起来似乎很正常!
接下来才是正文!
我们创建一个Annotation类,就叫他SubCommand
@interface是定义Annotation类的关键字
@Target(ElementType.METHOD) 指的是用于方法的声明
@Retention(RetentionPolicy.RUNTIME) 指的是运行时加载Annotation到JVM中
default 表示这个成员的默认值。
不懂没关系,记住就行。
然后我们在里面定义了3个成员,后面会用到。
回到我们的命令方法,我们添加一个无参数的判断,输出所有子命令。
如图:
这里我们遍历了本类的方法,判断是否有SubCommand注释,如果有,获取这个方法的注释并拼接帮助并发送消息。
很多人问为什么要遍历本类方法?因为我们把子命令写在了这个类,下面看下去你就知道了。
然后,有帮助还不行,还有执行子命令啊,于是,如图:
我们同样遍历本类方法,判断SubCommand注释,并且判断注释中的cmd是否和输入的参数相等,相等就使用反射执行此方法,并return true退出方法。
然后我们再加个找不到子命令的提示
最后,完整的onCommand()方法是这样的:
- public boolean onCommand(CommandSender sender, Command arg1, String label, String[] args) {
- if(label.equalsIgnoreCase("xxx")){
- //判断是否是玩家
- if(!(sender instanceof Player)){
- sender.sendMessage("只能在游戏里执行此命令!");
- return true;
- }
- //判断是否有权限
- if(!sender.hasPermission("xxx.use")){
- sender.sendMessage("你没有权限。");
- return true;
- }
- //强转对象
- Player p=(Player) sender;
- //
- //无参数
- if(args.length==0){
- p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6==========[&b 帮助&6 ]=========="));
- for(Method method : this.getClass().getDeclaredMethods()){
- if(!method.isAnnotationPresent(SubCommand.class)){
- continue;
- }
- SubCommand sub=method.getAnnotation(SubCommand.class);
- p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6/xxx &b"+sub.cmd()+" &3"+sub.arg()+"&6-&a "+sub.des()));
- }
- return true;
- }
- for(Method method:this.getClass().getDeclaredMethods()){
- if(!method.isAnnotationPresent(SubCommand.class)){
- continue;
- }
- SubCommand sub=method.getAnnotation(SubCommand.class);
- if(!sub.cmd().equalsIgnoreCase(args[0])){
- continue;
- }
-
- try {
- method.invoke(this, p,args);
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- return true;
- }
- p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&a未找到此子命令:&c"+args[0]));
- return true;
- }
- return false;
- }
复制代码 |
好了,命令轮子造完了,现在我们几乎不需要再去动他了,我们只需要在下面添加命令就行了。@SubCommand(cmd="子命令内容",arg="参数介绍",des="命令介绍")
public void 方法名字随便写(Player p,String args[]){
//执行此子命令
}
为什么参数是Player p和String args[]呢?
因为,我们上面利用反射执行的时候传进来就是这两个参数,而我们也需要这2个参数啊,不然子命令怎么知道执行者和其他的参数?
方法名随意,因为靠的是上面的@SubCommand注释来判断的
然后我们添加2个字命令进行测试:
由于我们的命令帮助是靠遍历Annotation自动生成的,我们也不需要去改动onCommand方法
我们来测试下:
很棒是不是
而且代码清晰可读性高,添加子命令快速,自动生成帮助。
好了,教程就到这里
求人气求回复
禁止转载!禁止转载!