diff --git a/src/main/java/pw/yumc/YumCore/commands/CommandHelp.java b/src/main/java/pw/yumc/YumCore/commands/CommandHelp.java index 7c70082..d592b37 100644 --- a/src/main/java/pw/yumc/YumCore/commands/CommandHelp.java +++ b/src/main/java/pw/yumc/YumCore/commands/CommandHelp.java @@ -125,10 +125,10 @@ public class CommandHelp { * @param args * 参数 */ - public void send(final CommandSender sender, final Command command, final String label, final String[] args) { + public boolean send(final CommandSender sender, final Command command, final String label, final String[] args) { if (this.HELPPAGECOUNT == 0) { sender.sendMessage(commandNotFound); - return; + return true; } int page = 1; try { @@ -163,6 +163,7 @@ public class CommandHelp { cacheHelp.put(helpkey, helpList.toArray(new String[0])); } sender.sendMessage(cacheHelp.get(helpkey)); + return true; } /** diff --git a/src/main/java/pw/yumc/YumCore/commands/CommandManager.java b/src/main/java/pw/yumc/YumCore/commands/CommandManager.java index 981e5a6..f8f1dcc 100644 --- a/src/main/java/pw/yumc/YumCore/commands/CommandManager.java +++ b/src/main/java/pw/yumc/YumCore/commands/CommandManager.java @@ -141,16 +141,13 @@ public class CommandManager implements TabExecutor { if (defCmd != null) { return defCmd.execute(new CommandArgument(sender, command, label, args)); } - help.send(sender, command, label, args); - return true; + return help.send(sender, command, label, args); } final String subcmd = args[0].toLowerCase(); if (subcmd.equalsIgnoreCase("help")) { - help.send(sender, command, label, args); - return true; + return help.send(sender, command, label, args); } - final CommandInfo ci = checkCache(subcmd); - return ci.execute(new CommandArgument(sender, command, label, moveStrings(args, 1))); + return getByCache(subcmd).execute(new CommandArgument(sender, command, label, moveStrings(args, 1))); } @Override @@ -218,7 +215,7 @@ public class CommandManager implements TabExecutor { * 子命令 * @return 命令信息 */ - private CommandInfo checkCache(final String subcmd) { + private CommandInfo getByCache(final String subcmd) { if (!cmdCache.containsKey(subcmd)) { for (final CommandInfo cmdinfo : cmds) { if (cmdinfo.isValid(subcmd)) { diff --git a/src/main/java/pw/yumc/YumCore/commands/CommandParse.java b/src/main/java/pw/yumc/YumCore/commands/CommandParse.java index 0ec8774..22f5d51 100644 --- a/src/main/java/pw/yumc/YumCore/commands/CommandParse.java +++ b/src/main/java/pw/yumc/YumCore/commands/CommandParse.java @@ -2,15 +2,18 @@ package pw.yumc.YumCore.commands; import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import pw.yumc.YumCore.bukkit.Log; import pw.yumc.YumCore.commands.annotation.Default; import pw.yumc.YumCore.commands.annotation.KeyValue; import pw.yumc.YumCore.commands.annotation.Limit; @@ -32,26 +35,31 @@ public class CommandParse { new PlayerParse(); new StringParse(); } - public List parse = new LinkedList<>(); - public List parsed = new LinkedList<>(); + private final List parse = new LinkedList<>(); - public CommandParse(final Class[] classes, final Annotation[][] annons) { + private final boolean isMain; + + public CommandParse(final Class[] classes, final Annotation[][] annons, final boolean isMain) { + this.isMain = isMain; for (int i = 0; i < classes.length; i++) { final Class clazz = classes[i]; final Annotation[] annotations = annons[i]; if (clazz.isAssignableFrom(CommandSender.class)) { continue; } - if (!allparses.containsKey(clazz)) { - throw new CommandParseException(String.format("无法解析的参数类型 %s !", clazz.getName())); + Parse parse = allparses.get(clazz); + if (parse == null) { + if (!clazz.isEnum()) { + throw new CommandParseException(String.format("存在无法解析的参数类型 %s", clazz.getName())); + } + parse = new EnumParse(clazz); } - final Parse parse = allparses.get(clazz).clone(); - this.parse.add(parse.parseAnnotation(annotations)); + this.parse.add(parse.clone().parseAnnotation(annotations)); } } public static CommandParse get(final Method method) { - return new CommandParse(method.getParameterTypes(), method.getParameterAnnotations()); + return new CommandParse(method.getParameterTypes(), method.getParameterAnnotations(), method.getReturnType().equals(boolean.class)); } public static void registerParse(final Class clazz, final Parse parse) { @@ -60,18 +68,16 @@ public class CommandParse { public Object[] parse(final CommandArgument cmdArgs) { final String args[] = cmdArgs.getArgs(); - if (args.length == 0) { - return null; - } final List pobjs = new LinkedList<>(); pobjs.add(cmdArgs.getSender()); - for (int i = 0; i < args.length; i++) { + for (int i = 0; i < parse.size(); i++) { try { - if (i < parse.size()) { - pobjs.add(parse.get(i).parse(args[i])); - } + final Parse p = parse.get(i); + final String param = i < args.length ? args[i] : p.def; + pobjs.add(param == null ? param : p.parse(param)); } catch (final Exception e) { - throw new CommandException(String.format("第 %s 个参数 ", i + 1) + e.getMessage()); + Log.debug(e); + throw new CommandParseException(String.format("第 %s 个参数 ", isMain ? 1 : 2 + i) + e.getMessage()); } } return pobjs.toArray(); @@ -88,7 +94,26 @@ public class CommandParse { try { return Boolean.parseBoolean(arg); } catch (final Exception e) { - throw new CommandParseException("必须为True或者False!"); + throw new CommandParseException("必须为True或者False!", e); + } + } + } + + public static class EnumParse extends Parse { + Class etype; + Enum[] elist; + + public EnumParse(final Class etype) { + this.etype = etype; + this.elist = etype.getEnumConstants(); + } + + @Override + public Enum parse(final String arg) { + try { + return Enum.valueOf(etype, arg); + } catch (final IllegalArgumentException ex) { + throw new CommandParseException(String.format("不是 %s 有效值为 %s", etype.getSimpleName(), Arrays.toString(elist))); } } } @@ -107,8 +132,8 @@ public class CommandParse { throwRange(); } return result; - } catch (final Exception e) { - throw new CommandParseException("必须为数字!"); + } catch (final NumberFormatException e) { + throw new CommandParseException("必须为数字!", e); } } } @@ -127,17 +152,32 @@ public class CommandParse { throwRange(); } return result; + } catch (final NumberFormatException e) { + throw new CommandParseException("必须为数字!", e); + } + } + } + + public static class MaterialParse extends Parse { + public MaterialParse() { + allparses.put(String.class, this); + } + + @Override + public Material parse(final String arg) { + try { + return Material.valueOf(arg); } catch (final Exception e) { - throw new CommandParseException("必须为数字!"); + throw new CommandParseException("玩家 " + arg + "不存在或不在线!"); } } } public static abstract class Parse implements Cloneable { - protected Object def; - protected Map attrs = new HashMap<>(); - protected int min; - protected int max; + protected String def; + protected Map attrs = new HashMap<>(); + protected int min = 0; + protected int max = Integer.MAX_VALUE; @Override public Parse clone() { @@ -148,43 +188,33 @@ public class CommandParse { } } - public Object getDefault() { + public String getDefault() { return def; } - public void load() { - def = attrs.get("default"); - min = (int) attrs.get("min"); - max = (int) attrs.get("max"); - } - public abstract RT parse(String arg) throws CommandParseException; public Parse parseAnnotation(final Annotation[] annotations) { for (final Annotation annotation : annotations) { if (annotation.annotationType() == Default.class) { - setAttr("default", ((Default) annotation).value()); + def = ((Default) annotation).value(); } else if (annotation.annotationType() == Limit.class) { - setAttr("min", ((Limit) annotation).min()); - setAttr("max", ((Limit) annotation).max()); + min = ((Limit) annotation).min(); + max = ((Limit) annotation).max(); } else if (annotation.annotationType() == KeyValue.class) { final KeyValue kv = (KeyValue) annotation; - setAttr(kv.key(), kv.value()); + attrs.put(kv.key(), kv.value()); } } return this; } - public void setAttr(final String name, final Object value) { - attrs.put(name, value); - } - public void throwRange() { throwRange(null); } public void throwRange(final String str) { - throw new CommandException(String.format(str == null ? "必须在 %s 到 %s之间!" : str, min, max)); + throw new CommandException(String.format(str == null ? "必须在 %s 到 %s 之间!" : str, min, max)); } } @@ -204,8 +234,13 @@ public class CommandParse { } public static class StringParse extends Parse { + List options; + public StringParse() { allparses.put(String.class, this); + if (attrs.containsKey("option")) { + + } } @Override diff --git a/src/main/java/pw/yumc/YumCore/commands/annotation/Limit.java b/src/main/java/pw/yumc/YumCore/commands/annotation/Limit.java index f03691f..bd58c48 100644 --- a/src/main/java/pw/yumc/YumCore/commands/annotation/Limit.java +++ b/src/main/java/pw/yumc/YumCore/commands/annotation/Limit.java @@ -1,26 +1,26 @@ -package pw.yumc.YumCore.commands.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 参数限制 - * - * @since 2016年7月23日 上午9:00:27 - * @author 喵♂呜 - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Limit { - /** - * @return 最大长度(最大值) - */ - int max() default 255; - - /** - * @return 最小长度(或最小值) - */ - int min(); +package pw.yumc.YumCore.commands.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 参数限制 + * + * @since 2016年7月23日 上午9:00:27 + * @author 喵♂呜 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface Limit { + /** + * @return 最大长度(最大值) + */ + int max() default 255; + + /** + * @return 最小长度(或最小值) + */ + int min(); } \ No newline at end of file diff --git a/src/main/java/pw/yumc/YumCore/commands/exception/CommandArgumentException.java b/src/main/java/pw/yumc/YumCore/commands/exception/CommandArgumentException.java new file mode 100644 index 0000000..ddcbace --- /dev/null +++ b/src/main/java/pw/yumc/YumCore/commands/exception/CommandArgumentException.java @@ -0,0 +1,22 @@ +package pw.yumc.YumCore.commands.exception; + +/** + * 命令参数解析异常 + * + * @author 喵♂呜 + * @since 2016年10月5日 下午5:15:43 + */ +public class CommandArgumentException extends CommandException { + + public CommandArgumentException(final Exception e) { + super(e); + } + + public CommandArgumentException(final String string) { + super(string); + } + + public CommandArgumentException(final String string, final Exception e) { + super(string, e); + } +} diff --git a/src/main/java/pw/yumc/YumCore/commands/info/CommandInfo.java b/src/main/java/pw/yumc/YumCore/commands/info/CommandInfo.java index 3cc5a0b..1dbbd00 100644 --- a/src/main/java/pw/yumc/YumCore/commands/info/CommandInfo.java +++ b/src/main/java/pw/yumc/YumCore/commands/info/CommandInfo.java @@ -17,7 +17,9 @@ import pw.yumc.YumCore.commands.annotation.Cmd; import pw.yumc.YumCore.commands.annotation.Cmd.Executor; import pw.yumc.YumCore.commands.annotation.Help; import pw.yumc.YumCore.commands.annotation.Sort; +import pw.yumc.YumCore.commands.exception.CommandArgumentException; import pw.yumc.YumCore.commands.exception.CommandException; +import pw.yumc.YumCore.commands.exception.CommandParseException; /** * 命令信息存储类 @@ -29,6 +31,7 @@ public class CommandInfo { public static final CommandInfo Unknow = new CommandInfo(); private static final String onlyExecutor = "§c当前命令仅允许 §b%s §c执行!"; private static final String losePerm = "§c你需要有 %s 的权限才能执行此命令!"; + private static final String argErr = "§c参数错误: §4%s"; private static final String cmdErr = "§6错误原因: §4命令参数不正确!"; private static final String cmdUse = "§6使用方法: §e/%s %s %s"; private static final String cmdDes = "§6命令描述: §3%s"; @@ -121,6 +124,8 @@ public class CommandInfo { public void run() { try { method.invoke(origin, parse.parse(cmdArgs)); + } catch (final CommandParseException | CommandArgumentException e) { + Log.toSender(cmdArgs.getSender(), argErr, e.getMessage()); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new CommandException(e); }