--- front: hard: 入门 time: 30分钟 --- # 命令执行器 ## 认识命令机制 MC中的命令是一个字符串, 用来实现游戏内高级功能. 在MC客户端中, 玩家将在聊天框内输入命令. **当且仅当在“聊天”内, 命令与普通的聊天内容的区别在于其内容的第一个字符是一个斜杠`/`**. 该字符串中的空格表示一个分隔, 开头的一节为命令的名称. 除去命令的名称, 剩下的部分从空格处断开可以分成一个数组. 例如, `a b c`是一个命令, 其命令名称为`a`, 其参数可用一个数组`args`表示为: ``` args[0]: "b" args[1]: "c" ``` ## 定义新命令 如果我们需要定义一个新的命令, 首先我们需要在`plugin.yml`文件中增加相关信息: ```yml name: HelloWorld main: tdiant.helloworld.HelloWorld version: 1 author: tdiant commands: rua: description: RUA!RUA!RUA! ``` 在`plugin.yml`文件里, 我们增加了`commands.rua`键, 这就可以代表注册了一个`rua`命令. 我们给他增加了一个`description`子键表示对该命令的描述, 描述信息会出现在`/help`菜单里. 请注意, 请不要在plugin.yml文件里出现中文! 这可能会出现问题! `commands.命令名`键可以有很多个子键, 这些都不是必须添加的, 甚至它可以没有子键. 具体子键如下: | 键 | 用途 | 例子 | | ----- | ----- | ---- | | description | 描述作用. 将会在/help中显示 | description: "I am a cute command." | | aliases | 设置别名. 比如登录插件login命令也可以用/l命令代替. | aliases: [l, log] | | permission | 设置命令需要的权限 | permission: rua.use | | permission-message | 没权限时的提示语 | permission-message: "YOU HAVE NO PERMISSION!" | | usage | 命令的用法. | usage: `/ YOUR_NAME` | 注意: 1. ``在usage里可以代表你的命令名. 2. 你的命令设置了aliases后命令名不能按照aliases称呼. 比如你给login命令设置了`aliases: [l]`你不能也叫他`l`命令, 它还是`login`命令. 3. 不推荐使用`permission`和`permission-message`, 因为plugin.yml里出现中文爱出问题. 事实上, 我们可以用`Player.hasPermission`方法在监听命令的时候自己亲自判断有没有权限. 4. 如果一个名称被别的插件注册了或设置为了某个命令的别称, 会出现冲突问题, 尽量避免. 5. 别弄中文的命令, 如果想搞, 去试试监听`PlayerCommandPreprocessEvent`. ## onCommand 我们可以类似`Listener`, 做一个`CommandExecutor`监听命令. ```java public class DemoCommand implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { sender.sendMessage("HI!"); return true; //true代表命令执行没问题, 返回false的话Bukkit会给命令输入方一个错误提示语 } } ``` 然后也同理, 在onEnable里加入注册: ```java Bukkit.getPluginCommand("rua").setExecutor(new DemoCommand()); ``` 但是如果onCommand方法放在了主类里, 那就不需要注册了. `onCommand`方法有四个参数, 分别为: 1. `CommandSender sender` —— 命令输入方, 实际传入的有可能是Console, 有可能是Player或者其他情况. 2. `Command cmd` —— 所执行的命令对象. 3. `String label` —— 如果该指令被设置了别名(`aliases`), 此值将为玩家使用哪一个别名执行了该指令. 4. `String[] args` —— 参数. 例如/rua a b的话, args[0]为"a", args[1]为"b". > 警告: 字符串的比较, 请不要使用`==`, 因为其比对的是内存地址, 可能造成一些没有预料到的结果! 建议使用`equals`方法, 例如`args[0].equals(string)` 如果你的命令希望只被玩家使用, 通常这样判断: ```java if(!(sender instanceof Player)){ sender.sendMessage("你不是玩家!不能用!"); return true; //不返回true, Bukkit还会显示出来一串错误提示, 你可以试试看. } ``` 判断完为玩家后, 若希望判断其有没有权限执行命令, 可以: ```java Player p=(Player)sender; //sender可以直接强转为Player if(p.hasPermission("rua.use")){ p.sendMessage("你有权限!"); } ``` 玩家将会在聊天区域内看到输出: ``` 你有权限! ``` Bukkit内可以用ChatColor表示颜色前缀, 例如: ```java p.sendMessage(ChatColor.RED+"你输错了!"); //输出红色的 "你输错了" p.sendMessage(ChatColor.RED+"还可以"+ChatColor.YELLOW+"两种颜色混着用!"); p.sendMessage(ChatColor.BOLD+"猜猜我会显示成什么效果"); p.sendMessage(ChatColor.RED+""+ChatColor.BOLD+"猜猜我会显示成什么效果"); p.sendMessage(ChatColor.BOLD+""+ChatColor.RED+"猜猜我会显示成什么效果"); String str = "&4哈哈"; //假如你从配置文件里读出来了一串 "&4哈哈". p.sendMessage(str); //这样会显示出 "&4哈哈", 不带颜色 p.sendMessage(ChatColor.translateAlternateColorCodes('&',str)); //这样就带颜色了 ``` 还有其他的好玩的东西, 把下面的代码放在onEnable方法里试试看: ```java System.out.println(ChatColor.RED+"猜猜我是什么效果"); this.getLogger().info(ChatColor.RED+"你再猜猜我是什么效果"); ``` 以后推荐您用`getLogger().info`方法代替`System.out.println(也就是sout、sysout方法)`! 在实际应用的时候, 还要小心`args.length`! 玩家只输入`/rua`没有参数的时候, 小心因为自己的疏忽造成`ArrayIndexOutOfBoundsException`!