一般情况下,大多数插件在Bukkit注册指令中选择的是通过plugin.yml文件配置来注册指令。例如:
- name: xxx
- main: xxx.xxx.xxx
- version: xxx
- author: xxx
- commands:
- xxx:
这是存在于Bukkit org.bukkit.command.defaults下的一个Kill指令。在构造函数中它
- super("kill");
- this.description = "Commits suicide, only usable as a player";
- this.usageMessage = "/kill";
而KillCommand的构造函数是被
这个调用的。不难看出它是调用了某一个类的自身register方法。而这个类就是org.bukkit.command.SimpleCommandMap。而SimpleCommandMap是被Bukkit一开始调用过的。要获得SimpleCommandMap只能在CraftServer下的方法getCommandMap()获得
但是在Server下并没有getCommandMap这个方法。所以我们需要通过反射来获得CommandMap进行进一步操作。
- private void getCommandMap() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
- final Class<?> c = Bukkit.getServer().getClass();
- for (final Method method : c.getDeclaredMethods())
- if (method.getName().equals("getCommandMap"))
- this.commandMap = (CommandMap) method.invoke(Bukkit.getServer(), new Object[0]);
- }
获得了commandMap那我们要怎样继续操作呢?
还是这里,它调用了SimpleCommandMap的register方法。
它首先调用了第一个register,再由第一个regiser调用第二个。
不难看出调用register这个方法的两个参数的类型分别为String和Command。
那我们首先先从Command下手。
因为Command是一个抽象类,不建议通过直接new的方式来获取Command对象,这样不太方便管理。代码也显得冗长。所以我建议新建一个类来继承它。
继承这个抽象类后,在系统的引导下它会让你生成两个构造函数中的一个和一个必要的execute方法。
下面我来介绍一下构造函数:
第一个构造函数只有一个参数。这个参数就如同它本身的名字一样就是这个指令的名字,也就是说要使用这个指令需要输入的指令。如:/kill kill就是它的name。
第二个构造函数有四个参数。第一个参数同样是它的名字;第二个参数就是他的描述,也就是在使用 /help 你的指令名字 系统会显示出来的字符串;第三个参数就是在execute方法返回值为false的时候系统会显示这个字符串;第四个参数就是该指令的简称。如:假设你设置了k为kill的简称,那么当你输入/k 的时候是等同于输入/kill。
execute方法也就是和平常通过plugin.yml注册的调用onCommand方法的参数一样。分别为sender,输入的指令(如果是简称则显示简称),参数。
知道了Command的对象如何获取,那应该如何写入第一个参数string呢?
(PS:因为本人比较严谨(其实就是强迫症啦),所以我不想乱入几个字符串)
然后我去查找了加载plugin.yml时的源码。通过JavaPluginLoader下的loadPlugin(File file)方法中一步一步查找到了加载plugin.yml中的command节点的源码。也就是在org.bukkit.plugin.PluginDescriptionFile类下的loadMap(Map<?, ?> map)方法中。
再通过PluginDescriptionFile下的commands这个Field查到它被调用的地方,最后在org.bukkit.plugin.SimplePluginManager下的enablePlugin(Plugin plugin)方法中找到。
它调用了SimpleCommandMap的registerAll方法。
所以不难看出那个string类型的对象应该是plugin.getDescription().getName()。而plugin则是一个JavaPlugin对象,所以获得commandMap后可以通过register(this.getDescroption().getName()(PS:当然这是在继承JavaPlugin类中调用,用其他类调用则要获得JavaPlugin的对象),Command对象)来注册指令。 然后我又去看了plugin.getDescription().getName()到底是什么。
不难看出,plugin.getDescription().getName()这个方法返回值应该是plugin.yml的name的那一项,并且如果name中含有空格则会被替换为“_”。
最后我在列举一下使用commandMap来注册指令比通过plugin.yml来注册指令的好处。
1.你不用再担心会在plugin.yml中写错格式,写中文担心乱码的问题了。
2.使用Command类下面独有的execute,在多个指令同时存在时你不用在想使用plugin.yml而通过onCommand方法判断是不是其中某一个指令,而是直接独立使用execute来实现。
最后,谢谢大家阅读这篇帖子。希望帖子内容会对你们有用哦~
[groupid=1181]Unknown Domain[/groupid]