1
0
mirror of https://e.coding.net/circlecloud/YumCore.git synced 2024-11-24 02:08:48 +00:00

refactor: 重构命令类库 支持自定义生成帮助页面

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-11-16 19:45:57 +08:00
parent 877ef5e0b5
commit 24846733e8
14 changed files with 416 additions and 235 deletions

View File

@ -2,10 +2,11 @@ package pw.yumc.YumCore.commands;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import pw.yumc.YumCore.bukkit.P; import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.commands.annotation.Help; import pw.yumc.YumCore.commands.annotation.Help;
import pw.yumc.YumCore.commands.info.CommandInfo; import pw.yumc.YumCore.commands.info.CommandInfo;
import pw.yumc.YumCore.commands.interfaces.CommandHelpParse; import pw.yumc.YumCore.commands.interfaces.HelpGenerator;
import pw.yumc.YumCore.commands.interfaces.HelpParse;
import java.util.*; import java.util.*;
@ -16,19 +17,7 @@ import java.util.*;
* @author * @author
*/ */
public class CommandHelp { public class CommandHelp {
/** private static String commandNotFound = "§c当前插件未注册默认命令以及子命令!";
* 消息配置
*/
private static String prefix = String.format("§6[§b%s§6] ", P.instance.getName());
private static String commandNotFound = prefix + "§c当前插件未注册默认命令以及子命令!";
private static String pageNotFound = prefix + "§c不存在的帮助页面 §b请输入 /%s help §e1-%s";
private static String helpTitle = String.format("§6========= %s §6帮助 §aBy §b喵♂呜 §6=========", prefix);
private static String helpBody = "§6/%1$s §a%2$s §e%3$s §6- §b%4$s";
private static String helpFooter = "§6查看更多的帮助页面 §b请输入 /%s help §e1-%s";
/**
* 帮助页面每页行数
*/
private static int LINES_PER_PAGE = 7;
/** /**
* 默认命令 * 默认命令
*/ */
@ -38,17 +27,21 @@ public class CommandHelp {
*/ */
private List<CommandInfo> cmdlist; private List<CommandInfo> cmdlist;
/** /**
* 命令解析 * 帮助页生成
*/ */
private CommandHelpParse helpParse; private HelpGenerator helpGenerator = new DefaultHelpGenerator();
/**
* 帮助页面数量
*/
private int HELPPAGECOUNT;
/** /**
* 帮助列表缓存 * 帮助列表缓存
*/ */
private Map<String, String[]> cacheHelp = new HashMap<>(); private Map<String, String[]> cacheHelp = new HashMap<>();
/**
* 帮助页面每页行数
*/
private static int LINES_PER_PAGE = 7;
/**
* 帮助页面数量
*/
private int HELPPAGECOUNT;
/** /**
* 命令帮助 * 命令帮助
@ -70,40 +63,12 @@ public class CommandHelp {
*/ */
public CommandHelp(CommandInfo defCmd, Collection<? extends CommandInfo> list) { public CommandHelp(CommandInfo defCmd, Collection<? extends CommandInfo> list) {
this.defCmd = defCmd; this.defCmd = defCmd;
cmdlist = new LinkedList<CommandInfo>(list); cmdlist = new LinkedList<>(list);
Collections.sort(cmdlist, new CommandNameComparator()); Collections.sort(cmdlist, new CommandNameComparator());
Collections.sort(cmdlist, new CommandComparator()); Collections.sort(cmdlist, new CommandComparator());
HELPPAGECOUNT = (int) Math.ceil((double) cmdlist.size() / LINES_PER_PAGE); HELPPAGECOUNT = (int) Math.ceil((double) cmdlist.size() / LINES_PER_PAGE);
} }
/**
* 格式化命令信息
*
* @param ci
* 命令信息
* @param label
* 命令
* @return 格式化后的字串
*/
public String formatCommand(CommandInfo ci, String label) {
String aliases = Arrays.toString(ci.getCommand().aliases());
String cmd = ci.getName() + (aliases.length() == 2 ? "" : "§7" + aliases);
Help help = ci.getHelp();
return String.format(helpBody, label, cmd, help.possibleArguments(), formatHelp(help.value()));
}
/**
* 解析帮助
*
* @param value
* 参数
* @return 解析后的帮助
*/
public String formatHelp(String value) {
if (helpParse != null) { return helpParse.parse(value); }
return value;
}
/** /**
* 发送帮助 * 发送帮助
* *
@ -115,56 +80,63 @@ public class CommandHelp {
* 标签 * 标签
* @param args * @param args
* 参数 * 参数
* @return 是否发送成功
*/ */
public boolean send(CommandSender sender, Command command, String label, String[] args) { public boolean send(CommandSender sender, Command command, String label, String[] args) {
if (this.HELPPAGECOUNT == 0) { if (this.HELPPAGECOUNT == 0) {
sender.sendMessage(commandNotFound); Log.toSender(sender, commandNotFound);
return true; return true;
} }
int page = 1; int page = 1;
try { try {
page = Integer.parseInt(args[1]); page = Integer.parseInt(args[1]);
page = page == 0 ? 1 : page; page = page == 0 ? 1 : page;
} catch (Exception e) { } catch (Exception ignored) {
// Ignore
} }
String helpkey = label + page; String helpkey = label + page;
if (!cacheHelp.containsKey(helpkey)) { if (!cacheHelp.containsKey(helpkey)) {
List<String> helpList = new LinkedList<>(); if (page > HELPPAGECOUNT || page < 1) {
if (page > this.HELPPAGECOUNT || page < 1) { // 帮助页面不存在
// 帮助页面不存在 cacheHelp.put(helpkey, new String[] { helpGenerator.notFound(label, HELPPAGECOUNT) });
helpList.add(String.format(pageNotFound, label, HELPPAGECOUNT));
} else { } else {
List<String> helpList = new LinkedList<>();
// 帮助标题 // 帮助标题
helpList.add(helpTitle); helpList.add(helpGenerator.title());
if (page == 1 && defCmd != null) { if (page == 1 && defCmd != null) {
helpList.add(formatCommand(defCmd, label)); helpList.add(helpGenerator.body(label, defCmd));
} }
int start = LINES_PER_PAGE * (page - 1); int start = LINES_PER_PAGE * (page - 1);
int end = start + LINES_PER_PAGE; int end = start + LINES_PER_PAGE;
for (int i = start; i < end; i++) { for (int i = start; i < end; i++) {
if (this.cmdlist.size() > i) { if (cmdlist.size() > i) {
// 帮助列表 // 帮助列表
helpList.add(formatCommand(cmdlist.get(i), label)); helpList.add(helpGenerator.body(label, cmdlist.get(i)));
} }
} }
// 帮助结尾 // 帮助结尾
helpList.add(String.format(helpFooter, label, HELPPAGECOUNT)); helpList.add(helpGenerator.foot(label, HELPPAGECOUNT));
cacheHelp.put(helpkey, helpList.toArray(new String[] {}));
} }
cacheHelp.put(helpkey, helpList.toArray(new String[0]));
} }
sender.sendMessage(cacheHelp.get(helpkey)); sender.sendMessage(cacheHelp.get(helpkey));
return true; return true;
} }
/** /**
* 设置解析 * 设置帮助生成
* *
* @param helpParse * @param helpGenerator
* 帮助解析 * 帮助生成
*/ */
public void setHelpParse(CommandHelpParse helpParse) { public void setHelpGenerator(HelpGenerator helpGenerator) {
this.helpParse = helpParse; this.helpGenerator = helpGenerator;
}
/**
* @return 命令帮助生成器
*/
public HelpGenerator getHelpGenerator() {
return helpGenerator;
} }
/** /**
@ -198,4 +170,63 @@ public class CommandHelp {
} }
} }
} }
static class DefaultHelpGenerator implements HelpGenerator {
/**
* 消息配置
*/
private static String helpTitle = String.format("§6========= %s §6帮助 §aBy §b喵♂呜 §6=========", Log.getPrefix());
private static String helpBody = "§6/%1$s §a%2$s §e%3$s §6- §b%4$s";
private static String helpFooter = "§6查看更多的帮助页面 §b请输入 /%s help §e1-%s";
private static String pageNotFound = "§c不存在的帮助页面 §b请输入 /%s help §e1-%s";
/**
* 帮助解析
*/
private HelpParse helpParse;
@Override
public String title() {
return helpTitle;
}
@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, label, cmd, help.possibleArguments(), parse(help.value()));
}
@Override
public String foot(String label, int HELPPAGECOUNT) {
return String.format(helpFooter, label, HELPPAGECOUNT);
}
@Override
public String notFound(String label, int HELPPAGECOUNT) {
return String.format(pageNotFound, label, HELPPAGECOUNT);
}
/**
* 解析帮助
*
* @param value
* 参数
* @return 解析后的帮助
*/
public String parse(String value) {
if (helpParse != null) { return helpParse.parse(value); }
return value;
}
/**
* 设置解析器
*
* @param helpParse
* 帮助解析器
*/
public void setHelpParse(HelpParse helpParse) {
this.helpParse = helpParse;
}
}
} }

View File

@ -10,10 +10,16 @@ import org.bukkit.util.StringUtil;
import pw.yumc.YumCore.bukkit.Log; import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P; import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.bukkit.compatible.C; import pw.yumc.YumCore.bukkit.compatible.C;
import pw.yumc.YumCore.commands.exception.ArgumentException;
import pw.yumc.YumCore.commands.exception.CommandException;
import pw.yumc.YumCore.commands.exception.PermissionException;
import pw.yumc.YumCore.commands.exception.SenderException;
import pw.yumc.YumCore.commands.info.CommandInfo; import pw.yumc.YumCore.commands.info.CommandInfo;
import pw.yumc.YumCore.commands.info.CommandTabInfo; import pw.yumc.YumCore.commands.info.CommandTabInfo;
import pw.yumc.YumCore.commands.interfaces.CommandExecutor; import pw.yumc.YumCore.commands.interfaces.ErrorHanlder;
import pw.yumc.YumCore.commands.interfaces.CommandHelpParse; import pw.yumc.YumCore.commands.interfaces.Executor;
import pw.yumc.YumCore.commands.interfaces.HelpGenerator;
import pw.yumc.YumCore.commands.interfaces.HelpParse;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -30,6 +36,11 @@ import java.util.*;
public class CommandManager implements TabExecutor { public class CommandManager implements TabExecutor {
private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!"; private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!";
private static String returnTypeError = "注解命令补全 %s 位于 %s 的返回值错误 应实现 List 接口!"; private static String returnTypeError = "注解命令补全 %s 位于 %s 的返回值错误 应实现 List 接口!";
private static String onlyExecutor = "§c当前命令仅允许 §b%s §c执行!";
private static String losePerm = "§c你需要有 %s 的权限才能执行此命令!";
private static String cmdErr = "§6错误原因: §4命令参数不正确!";
private static String cmdUse = "§6使用方法: §e/%s %s%s";
private static String cmdDes = "§6命令描述: §3%s";
private static Constructor<PluginCommand> PluginCommandConstructor; private static Constructor<PluginCommand> PluginCommandConstructor;
private static Map<String, Command> knownCommands; private static Map<String, Command> knownCommands;
private static Map<String, Plugin> lookupNames; private static Map<String, Plugin> lookupNames;
@ -57,6 +68,31 @@ public class CommandManager implements TabExecutor {
} }
} }
/**
* 命令帮助
*/
private CommandHelp help;
/**
* 插件命令
*/
private PluginCommand cmd;
/**
* 命令错误处理
*/
private ErrorHanlder commandErrorHanlder = new ErrorHanlder() {
@Override
public void error(CommandException e, CommandSender sender, CommandInfo info, CommandArgument args) {
if (e instanceof SenderException) {
Log.toSender(sender, onlyExecutor, info.getExecutorStr());
} else if (e instanceof PermissionException) {
Log.toSender(sender, losePerm, info.getCommand().permission());
} else if (e instanceof ArgumentException) {
Log.toSender(sender, cmdErr);
Log.toSender(sender, cmdUse, args.getAlias(), info.isDefault() ? "" : info.getName() + " ", info.getHelp().possibleArguments());
Log.toSender(sender, cmdDes, info.getHelp().value());
}
}
};
/** /**
* 插件实例类 * 插件实例类
*/ */
@ -81,14 +117,6 @@ public class CommandManager implements TabExecutor {
* 命令名称缓存 * 命令名称缓存
*/ */
private List<String> cmdNameCache = new ArrayList<>(); private List<String> cmdNameCache = new ArrayList<>();
/**
* 命令帮助
*/
private CommandHelp help;
/**
* 插件命令
*/
private PluginCommand cmd;
/** /**
* 命令管理器 * 命令管理器
@ -118,7 +146,7 @@ public class CommandManager implements TabExecutor {
* @param executor * @param executor
* 命令执行类 * 命令执行类
*/ */
public CommandManager(String name, CommandExecutor... executor) { public CommandManager(String name, Executor... executor) {
this(name); this(name);
register(executor); register(executor);
} }
@ -207,11 +235,19 @@ public class CommandManager implements TabExecutor {
String subcmd = args[0].toLowerCase(); String subcmd = args[0].toLowerCase();
if (subcmd.equalsIgnoreCase("help")) { return help.send(sender, command, label, args); } if (subcmd.equalsIgnoreCase("help")) { return help.send(sender, command, label, args); }
CommandInfo cmd = getByCache(subcmd); CommandInfo cmd = getByCache(subcmd);
CommandArgument arg;
if (cmd.equals(CommandInfo.Unknow) && defCmd != null) { if (cmd.equals(CommandInfo.Unknow) && defCmd != null) {
return defCmd.execute(new CommandArgument(sender, command, label, args)); cmd = defCmd;
arg = new CommandArgument(sender, command, label, args);
} else { } else {
return cmd.execute(new CommandArgument(sender, command, label, moveStrings(args, 1))); arg = new CommandArgument(sender, command, label, moveStrings(args, 1));
} }
try {
return cmd.execute(arg);
} catch (CommandException e) {
commandErrorHanlder.error(e, sender, cmd, arg);
}
return false;
} }
@Override @Override
@ -235,8 +271,8 @@ public class CommandManager implements TabExecutor {
* @param clazzs * @param clazzs
* 子命令处理类 * 子命令处理类
*/ */
public void register(CommandExecutor... clazzs) { public CommandManager register(Executor... clazzs) {
for (CommandExecutor clazz : clazzs) { for (Executor clazz : clazzs) {
Method[] methods = clazz.getClass().getDeclaredMethods(); Method[] methods = clazz.getClass().getDeclaredMethods();
for (Method method : methods) { for (Method method : methods) {
if (registerCommand(method, clazz)) { if (registerCommand(method, clazz)) {
@ -247,6 +283,7 @@ public class CommandManager implements TabExecutor {
} }
help = new CommandHelp(defCmd, cmds); help = new CommandHelp(defCmd, cmds);
buildCmdNameCache(); buildCmdNameCache();
return this;
} }
/** /**
@ -258,7 +295,7 @@ public class CommandManager implements TabExecutor {
* 调用对象 * 调用对象
* @return 是否成功 * @return 是否成功
*/ */
private boolean registerCommand(Method method, CommandExecutor clazz) { private boolean registerCommand(Method method, Executor clazz) {
CommandInfo ci = CommandInfo.parse(method, clazz); CommandInfo ci = CommandInfo.parse(method, clazz);
if (ci != null) { if (ci != null) {
Class[] params = method.getParameterTypes(); Class[] params = method.getParameterTypes();
@ -289,7 +326,7 @@ public class CommandManager implements TabExecutor {
* 调用对象 * 调用对象
* @return 是否成功 * @return 是否成功
*/ */
private boolean registerTab(Method method, CommandExecutor clazz) { private boolean registerTab(Method method, Executor clazz) {
CommandTabInfo ti = CommandTabInfo.parse(method, clazz); CommandTabInfo ti = CommandTabInfo.parse(method, clazz);
if (ti != null) { if (ti != null) {
if (method.getReturnType().equals(List.class)) { if (method.getReturnType().equals(List.class)) {
@ -301,13 +338,40 @@ public class CommandManager implements TabExecutor {
return false; return false;
} }
/**
* 设置命令错误处理器
*
* @param commandErrorHanlder
* 命令错误处理器
*/
public CommandManager setCommandErrorHanlder(ErrorHanlder commandErrorHanlder) {
this.commandErrorHanlder = commandErrorHanlder;
return this;
}
/**
* 设置帮助生成器
*
* @param helpGenerator
* 帮助生成器
*/
public CommandManager setHelpGenerator(HelpGenerator helpGenerator) {
help.setHelpGenerator(helpGenerator);
return this;
}
/** /**
* 设置帮助解析器 * 设置帮助解析器
* *
* @param helpParse * @param helpParse
* 帮助解析器 * 帮助解析器
*/ */
public void setHelpParse(CommandHelpParse helpParse) { public CommandManager setHelpParse(HelpParse helpParse) {
help.setHelpParse(helpParse); if (help.getHelpGenerator() instanceof CommandHelp.DefaultHelpGenerator) {
((CommandHelp.DefaultHelpGenerator) help.getHelpGenerator()).setHelpParse(helpParse);
} else {
Log.w("已设置自定义帮助生成器 解析器设置将不会生效!");
}
return this;
} }
} }

View File

@ -1,20 +1,19 @@
package pw.yumc.YumCore.commands; package pw.yumc.YumCore.commands;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import pw.yumc.YumCore.bukkit.Log; import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.commands.annotation.Default; import pw.yumc.YumCore.commands.annotation.Default;
import pw.yumc.YumCore.commands.annotation.KeyValue; import pw.yumc.YumCore.commands.annotation.KeyValue;
import pw.yumc.YumCore.commands.annotation.Limit; import pw.yumc.YumCore.commands.annotation.Limit;
import pw.yumc.YumCore.commands.exception.CommandParseException; import pw.yumc.YumCore.commands.exception.ParseException;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
/** /**
* 命令参数解析 * 命令参数解析
@ -47,7 +46,7 @@ public class CommandParse {
if (clazz.isEnum()) { if (clazz.isEnum()) {
parse = new EnumParse(clazz); parse = new EnumParse(clazz);
} }
if (parse == null) { throw new CommandParseException(String.format("存在无法解析的参数类型 %s", clazz.getName())); } if (parse == null) { throw new ParseException(String.format("存在无法解析的参数类型 %s", clazz.getName())); }
this.parse.add(parse.clone().parseAnnotation(annotations)); this.parse.add(parse.clone().parseAnnotation(annotations));
} }
} }
@ -92,7 +91,7 @@ public class CommandParse {
} }
pobjs.add(param == null ? null : p.parse(cmdArgs.getSender(), param)); pobjs.add(param == null ? null : p.parse(cmdArgs.getSender(), param));
} catch (Exception e) { } catch (Exception e) {
throw new CommandParseException(String.format("第 %s 个参数 ", isMain ? 1 : 2 + i) + e.getMessage()); throw new ParseException(String.format("第 %s 个参数 ", isMain ? 1 : 2 + i) + e.getMessage());
} }
} }
Log.d("解析参数: %s => %s", Arrays.toString(args), pobjs); Log.d("解析参数: %s => %s", Arrays.toString(args), pobjs);
@ -110,7 +109,7 @@ public class CommandParse {
try { try {
return Boolean.parseBoolean(arg); return Boolean.parseBoolean(arg);
} catch (Exception e) { } catch (Exception e) {
throw new CommandParseException("必须为True或者False!", e); throw new ParseException("必须为True或者False!", e);
} }
} }
} }
@ -129,7 +128,7 @@ public class CommandParse {
try { try {
return Enum.valueOf(etype, arg); return Enum.valueOf(etype, arg);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
throw new CommandParseException(String.format("不是 %s 有效值为 %s", etype.getSimpleName(), Arrays.toString(elist))); throw new ParseException(String.format("不是 %s 有效值为 %s", etype.getSimpleName(), Arrays.toString(elist)));
} }
} }
} }
@ -140,9 +139,9 @@ public class CommandParse {
} }
@Override @Override
public File parse(CommandSender sender, String arg) throws CommandParseException { public File parse(CommandSender sender, String arg) throws ParseException {
File file = new File(arg); File file = new File(arg);
if (attrs.containsKey("check") && !file.exists()) { throw new CommandParseException("文件 " + arg + " 不存在!"); } if (attrs.containsKey("check") && !file.exists()) { throw new ParseException("文件 " + arg + " 不存在!"); }
return file; return file;
} }
} }
@ -162,7 +161,7 @@ public class CommandParse {
} }
return result; return result;
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new CommandParseException("必须为数字!", e); throw new ParseException("必须为数字!", e);
} }
} }
} }
@ -182,7 +181,7 @@ public class CommandParse {
} }
return result; return result;
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new CommandParseException("必须为数字!", e); throw new ParseException("必须为数字!", e);
} }
} }
} }
@ -202,7 +201,7 @@ public class CommandParse {
} }
return result; return result;
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new CommandParseException("必须为数字!", e); throw new ParseException("必须为数字!", e);
} }
} }
} }
@ -217,7 +216,7 @@ public class CommandParse {
try { try {
return Material.valueOf(arg); return Material.valueOf(arg);
} catch (Exception e) { } catch (Exception e) {
throw new CommandParseException(String.format("%s 不是一个有效的Material枚举", arg), e); throw new ParseException(String.format("%s 不是一个有效的Material枚举", arg), e);
} }
} }
} }
@ -241,7 +240,7 @@ public class CommandParse {
return def; return def;
} }
public abstract RT parse(CommandSender sender, String arg) throws CommandParseException; public abstract RT parse(CommandSender sender, String arg) throws ParseException;
public Parse<RT> parseAnnotation(Annotation[] annotations) { public Parse<RT> parseAnnotation(Annotation[] annotations) {
for (Annotation annotation : annotations) { for (Annotation annotation : annotations) {
@ -259,7 +258,7 @@ public class CommandParse {
} }
public void throwException(String str, Object... objects) { public void throwException(String str, Object... objects) {
throw new CommandParseException(String.format(str, objects)); throw new ParseException(String.format(str, objects));
} }
public void throwRange() { public void throwRange() {
@ -267,7 +266,7 @@ public class CommandParse {
} }
public void throwRange(String str) { public void throwRange(String str) {
throw new CommandParseException(String.format(str == null ? "范围必须在 %s 到 %s 之间!" : str, min, max)); throw new ParseException(String.format(str == null ? "范围必须在 %s 到 %s 之间!" : str, min, max));
} }
} }
@ -281,7 +280,7 @@ public class CommandParse {
@Override @Override
public Player parse(CommandSender sender, String arg) { public Player parse(CommandSender sender, String arg) {
Player p = Bukkit.getPlayerExact(arg); Player p = Bukkit.getPlayerExact(arg);
if (check && p == null) { throw new CommandParseException("玩家 " + arg + " 不存在或不在线!"); } if (check && p == null) { throw new ParseException("玩家 " + arg + " 不存在或不在线!"); }
return p; return p;
} }

View File

@ -0,0 +1,22 @@
package pw.yumc.YumCore.commands.exception;
/**
* 命令参数解析异常
*
* @author
* @since 2016年10月5日 下午5:15:43
*/
public class ArgumentException extends CommandException {
public ArgumentException(Exception e) {
super(e);
}
public ArgumentException(String string) {
super(string);
}
public ArgumentException(String string, Exception e) {
super(string, e);
}
}

View File

@ -1,22 +0,0 @@
package pw.yumc.YumCore.commands.exception;
/**
* 命令参数解析异常
*
* @author
* @since 2016年10月5日 下午5:15:43
*/
public class CommandArgumentException extends CommandException {
public CommandArgumentException(Exception e) {
super(e);
}
public CommandArgumentException(String string) {
super(string);
}
public CommandArgumentException(String string, Exception e) {
super(string, e);
}
}

View File

@ -1,22 +0,0 @@
package pw.yumc.YumCore.commands.exception;
/**
* 命令参数解析异常
*
* @author
* @since 2016年10月5日 下午5:15:43
*/
public class CommandParseException extends CommandException {
public CommandParseException(Exception e) {
super(e);
}
public CommandParseException(String string) {
super(string);
}
public CommandParseException(String string, Exception e) {
super(string, e);
}
}

View File

@ -0,0 +1,22 @@
package pw.yumc.YumCore.commands.exception;
/**
* 命令参数解析异常
*
* @author
* @since 2016年10月5日 下午5:15:43
*/
public class ParseException extends CommandException {
public ParseException(Exception e) {
super(e);
}
public ParseException(String string) {
super(string);
}
public ParseException(String string, Exception e) {
super(string, e);
}
}

View File

@ -0,0 +1,22 @@
package pw.yumc.YumCore.commands.exception;
/**
* 命令参数解析异常
*
* @author
* @since 2016年10月5日 下午5:15:43
*/
public class PermissionException extends CommandException {
public PermissionException(Exception e) {
super(e);
}
public PermissionException(String string) {
super(string);
}
public PermissionException(String string, Exception e) {
super(string, e);
}
}

View File

@ -0,0 +1,22 @@
package pw.yumc.YumCore.commands.exception;
/**
* 命令参数解析异常
*
* @author
* @since 2016年10月5日 下午5:15:43
*/
public class SenderException extends CommandException {
public SenderException(Exception e) {
super(e);
}
public SenderException(String string) {
super(string);
}
public SenderException(String string, Exception e) {
super(string, e);
}
}

View File

@ -11,9 +11,7 @@ import pw.yumc.YumCore.commands.annotation.Cmd;
import pw.yumc.YumCore.commands.annotation.Cmd.Executor; import pw.yumc.YumCore.commands.annotation.Cmd.Executor;
import pw.yumc.YumCore.commands.annotation.Help; import pw.yumc.YumCore.commands.annotation.Help;
import pw.yumc.YumCore.commands.annotation.Sort; import pw.yumc.YumCore.commands.annotation.Sort;
import pw.yumc.YumCore.commands.exception.CommandArgumentException; import pw.yumc.YumCore.commands.exception.*;
import pw.yumc.YumCore.commands.exception.CommandException;
import pw.yumc.YumCore.commands.exception.CommandParseException;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -30,12 +28,7 @@ import java.util.Objects;
*/ */
public class CommandInfo { public class CommandInfo {
public static CommandInfo Unknow = new CommandInfo(); public static CommandInfo Unknow = new CommandInfo();
private static String onlyExecutor = "§c当前命令仅允许 §b%s §c执行!";
private static String losePerm = "§c你需要有 %s 的权限才能执行此命令!";
private static String argErr = "§c参数错误: §4%s"; private static String argErr = "§c参数错误: §4%s";
private static String cmdErr = "§6错误原因: §4命令参数不正确!";
private static String cmdUse = "§6使用方法: §e/%s %s %s";
private static String cmdDes = "§6命令描述: §3%s";
private static Help defHelp = new Help() { private static Help defHelp = new Help() {
@Override @Override
public Class<? extends Annotation> annotationType() { public Class<? extends Annotation> annotationType() {
@ -59,6 +52,7 @@ public class CommandInfo {
private List<Executor> executors; private List<Executor> executors;
private String executorStr; private String executorStr;
private boolean async; private boolean async;
private boolean def;
private Cmd command; private Cmd command;
private Help help; private Help help;
private int sort; private int sort;
@ -74,6 +68,7 @@ public class CommandInfo {
this.command = command; this.command = command;
this.help = help != null ? help : defHelp; this.help = help != null ? help : defHelp;
this.async = async; this.async = async;
this.def = method.getReturnType().equals(boolean.class);
this.sort = sort; this.sort = sort;
this.parse = parse; this.parse = parse;
} }
@ -88,6 +83,7 @@ public class CommandInfo {
this.command = null; this.command = null;
this.help = null; this.help = null;
this.async = false; this.async = false;
this.def = false;
this.sort = 0; this.sort = 0;
this.parse = null; this.parse = null;
} }
@ -122,24 +118,23 @@ public class CommandInfo {
*/ */
public boolean execute(final CommandArgument cmdArgs) { public boolean execute(final CommandArgument cmdArgs) {
if (method == null) { return false; } if (method == null) { return false; }
if (check(cmdArgs)) { check(cmdArgs);
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
method.invoke(origin, parse.parse(cmdArgs)); method.invoke(origin, parse.parse(cmdArgs));
} catch (CommandParseException | CommandArgumentException e) { } catch (ParseException | ArgumentException e) {
Log.toSender(cmdArgs.getSender(), argErr, e.getMessage()); Log.toSender(cmdArgs.getSender(), argErr, e.getMessage());
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new CommandException(e); throw new CommandException(e);
}
} }
};
if (async) {
Bukkit.getScheduler().runTaskAsynchronously(P.instance, runnable);
} else {
runnable.run();
} }
};
if (async) {
Bukkit.getScheduler().runTaskAsynchronously(P.instance, runnable);
} else {
runnable.run();
} }
return true; return true;
} }
@ -179,6 +174,20 @@ public class CommandInfo {
return async; return async;
} }
/**
* @return 是否为默认命令
*/
public boolean isDefault() {
return def;
}
/**
* @return 允许的命令发送者
*/
public String getExecutorStr() {
return executorStr;
}
/** /**
* 验证命令是否匹配 * 验证命令是否匹配
* *
@ -203,36 +212,11 @@ public class CommandInfo {
return Objects.hash(origin, method, name); return Objects.hash(origin, method, name);
} }
private boolean check(CommandArgument cmdArgs) { private void check(CommandArgument cmdArgs) {
CommandSender sender = cmdArgs.getSender(); CommandSender sender = cmdArgs.getSender();
return checkSender(sender) && checkArgs(sender, cmdArgs) && checkPerm(sender); if (!executors.contains(Executor.ALL) && !executors.contains(Executor.valueOf(sender))) { throw new SenderException(executorStr); }
} if (!"".equals(command.permission()) && !sender.hasPermission(command.permission())) { throw new PermissionException(command.permission()); }
if (cmdArgs.getArgs().length < command.minimumArguments()) { throw new ArgumentException(String.valueOf(command.minimumArguments())); }
private boolean checkArgs(CommandSender sender, CommandArgument cmdArgs) {
if (cmdArgs.getArgs().length < command.minimumArguments()) {
Log.toSender(sender, cmdErr);
Log.toSender(sender, cmdUse, cmdArgs.getAlias(), getName(), help.possibleArguments());
Log.toSender(sender, cmdDes, help.value());
return false;
}
return true;
}
private boolean checkPerm(CommandSender sender) {
String perm = command.permission();
if (!"".equals(perm) && !sender.hasPermission(perm)) {
Log.toSender(sender, losePerm, perm);
return false;
}
return true;
}
private boolean checkSender(CommandSender sender) {
if (!executors.contains(Executor.ALL) && !executors.contains(Executor.valueOf(sender))) {
Log.toSender(sender, onlyExecutor, executorStr);
return false;
}
return true;
} }
private String eS(List<Executor> executors) { private String eS(List<Executor> executors) {

View File

@ -0,0 +1,16 @@
package pw.yumc.YumCore.commands.interfaces;
import org.bukkit.command.CommandSender;
import pw.yumc.YumCore.commands.CommandArgument;
import pw.yumc.YumCore.commands.exception.CommandException;
import pw.yumc.YumCore.commands.info.CommandInfo;
/**
* 命令错误处理
*
* @since 2016年7月23日 上午9:55:51
* @author
*/
public interface ErrorHanlder {
void error(CommandException e, CommandSender sender, CommandInfo info, CommandArgument args);
}

View File

@ -1,11 +1,11 @@
package pw.yumc.YumCore.commands.interfaces; package pw.yumc.YumCore.commands.interfaces;
/** /**
* 命令执行类 * 命令执行类
* *
* @since 2016年7月23日 上午9:55:51 * @since 2016年7月23日 上午9:55:51
* @author * @author
*/ */
public interface CommandExecutor { public interface Executor {
} }

View File

@ -0,0 +1,43 @@
package pw.yumc.YumCore.commands.interfaces;
import pw.yumc.YumCore.commands.info.CommandInfo;
/**
* 帮助页生成器
*
* @author
* @since 2016年11月16日 上午12:39:26
*/
public interface HelpGenerator {
/**
* @return 帮助标题
*/
String title();
/**
* 格式化命令信息
*
* @param label 命令
* @param ci 命令信息
* @return 格式化后的字串
*/
String body(String label, CommandInfo ci);
/**
* 格式化帮助尾部
*
* @param label 命令标签
* @param HELPPAGECOUNT 帮助页数
* @return 帮助尾部
*/
String foot(String label, int HELPPAGECOUNT);
/**
* 格式化未找到
*
* @param label 命令标签
* @param HELPPAGECOUNT 帮助页数
* @return 未找到提示
*/
String notFound(String label, int HELPPAGECOUNT);
}

View File

@ -1,18 +1,18 @@
package pw.yumc.YumCore.commands.interfaces; package pw.yumc.YumCore.commands.interfaces;
/** /**
* 命令解析接口 * 命令解析接口
* *
* @author * @author
* @since 2016年9月14日 上午12:39:26 * @since 2016年9月14日 上午12:39:26
*/ */
public interface CommandHelpParse { public interface HelpParse {
/** /**
* 解析命令帮助 * 解析命令帮助
* *
* @param str * @param str
* 参数 * 参数
* @return 命令帮助 * @return 命令帮助
*/ */
String parse(String str); String parse(String str);
} }