YumCore/src/main/java/pw/yumc/YumCore/commands/CommandMain.java

151 lines
4.9 KiB
Java

package pw.yumc.YumCore.commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.commands.annotation.Help;
import pw.yumc.YumCore.commands.exception.CommandException;
import pw.yumc.YumCore.commands.info.CommandInfo;
import pw.yumc.YumCore.commands.interfaces.ErrorHanlder;
import pw.yumc.YumCore.commands.interfaces.Executor;
import pw.yumc.YumCore.commands.interfaces.HelpGenerator;
import java.lang.reflect.Method;
import java.util.*;
/**
* 主类命令管理
*
* @author 喵♂呜
* @since 2016/11/18 0018
*/
public class CommandMain implements CommandExecutor {
private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!";
/**
* 命令列表
*/
private Set<CommandInfo> cmds = new HashSet<>();
/**
* 命令缓存列表
*/
private Map<String, CommandInfo> cmdCache = new HashMap<>();
/**
* 命令帮助处理
*/
private CommandHelp help;
/**
* 命令错误处理
*/
private ErrorHanlder commandErrorHanlder = new CommandError();
/**
* 帮助页生成
*/
private HelpGenerator helpGenerator = new MainHelpGenerator();
/**
* 主类命令管理类
*
* @param clazzs
* 命令类
*/
public CommandMain(Executor... clazzs) {
register(clazzs);
}
/**
* 注册命令
*
* @param clazzs
* 命令类
* @return {@link CommandMain}
*/
public CommandMain register(Executor... clazzs) {
for (Executor clazz : clazzs) {
Method[] methods = clazz.getClass().getDeclaredMethods();
for (Method method : methods) {
registerCommand(method, clazz);
}
}
help = new CommandHelp(cmds);
help.setHelpGenerator(helpGenerator);
return this;
}
private boolean registerCommand(Method method, Executor clazz) {
CommandInfo ci = CommandInfo.parse(method, clazz);
if (ci != null) {
injectPluginCommand(ci);
Class[] params = method.getParameterTypes();
Log.d("命令 %s 参数类型: %s", ci.getName(), Arrays.toString(params));
try {
Class<? extends CommandSender> sender = params[0];
cmds.add(ci);
return true;
} catch (ArrayIndexOutOfBoundsException | ClassCastException ignored) {
}
Log.warning(String.format(argumentTypeError, method.getName(), clazz.getClass().getName()));
}
return false;
}
private void injectPluginCommand(CommandInfo ci) {
PluginCommand cmd = P.getCommand(ci.getName());
if (cmd == null) {
if ((cmd = CommandKit.create(ci.getName(), ci.getAliases().toArray(new String[] {}))) == null) { throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + ci.getName() + " 命令!"); }
}
cmd.setExecutor(this);
}
/**
* 检查缓存并获得命令
*
* @param cmd
* 子命令
* @return 命令信息
*/
private CommandInfo getByCache(String cmd) {
if (!cmdCache.containsKey(cmd)) {
for (CommandInfo cmdinfo : cmds) {
if (cmdinfo.isValid(cmd)) {
Log.d("匹配命令: %s => %s 已缓存...", cmd, cmdinfo);
cmdCache.put(cmd, cmdinfo);
return cmdinfo;
}
}
cmdCache.put(cmd, null);
}
return cmdCache.get(cmd);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
Log.d("执行者: %s 触发主命令: %s 参数: %s", sender.getName(), label, Arrays.toString(args));
if (args.length > 0 && args[0].equalsIgnoreCase("?")) {
help.send(sender, label, args);
return true;
}
CommandInfo manager = getByCache(label);
try {
return manager != null && manager.execute(sender, label, args);
} catch (CommandException e) {
commandErrorHanlder.error(e, sender, manager, label, args);
}
return false;
}
private class MainHelpGenerator extends CommandHelp.DefaultHelpGenerator {
private String helpBody = "§6/%1$s §e%2$s §6- §b%3$s";
@Override
public String body(String label, CommandInfo ci) {
String aliases = Arrays.toString(ci.getCommand().aliases());
String cmd = ci.getName() + (aliases.length() == 2 ? "" : "§7" + aliases);
Help help = ci.getHelp();
return String.format(helpBody, cmd, help.possibleArguments(), parse(help.value()));
}
}
}