1
0
mirror of https://e.coding.net/circlecloud/YumCore.git synced 2024-11-22 01:48:50 +00:00

feat: 新的命令处理类

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-11-21 20:31:04 +08:00
parent ba080a6584
commit 5ded69df9e
16 changed files with 526 additions and 565 deletions

View File

@ -243,7 +243,7 @@ public class Log {
* @param sender 命令发送者 * @param sender 命令发送者
* @param msg 消息 * @param msg 消息
*/ */
public static void toSender(CommandSender sender, String msg) { public static void sender(CommandSender sender, String msg) {
sender.sendMessage(prefix + msg); sender.sendMessage(prefix + msg);
} }
@ -254,7 +254,7 @@ public class Log {
* @param msg 消息 * @param msg 消息
* @param objs 参数 * @param objs 参数
*/ */
public static void toSender(CommandSender sender, String msg, Object... objs) { public static void sender(CommandSender sender, String msg, Object... objs) {
sender.sendMessage(prefix + String.format(msg, objs)); sender.sendMessage(prefix + String.format(msg, objs));
} }
@ -264,9 +264,9 @@ public class Log {
* @param sender 命令发送者 * @param sender 命令发送者
* @param msg 消息 * @param msg 消息
*/ */
public static void toSender(CommandSender sender, String[] msg) { public static void sender(CommandSender sender, String[] msg) {
for (String str : msg) { for (String str : msg) {
toSender(sender, str); sender(sender, str);
} }
} }

View File

@ -1,52 +0,0 @@
package pw.yumc.YumCore.commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
/**
* 子命令参数类
*
* @since 2015年8月22日上午8:29:44
* @author
*/
public class CommandArgument {
private CommandSender sender;
private Command command;
private String alias;
private String[] args;
public CommandArgument(CommandSender sender, Command command, String alias, String[] args) {
this.sender = sender;
this.command = command;
this.alias = alias;
this.args = args;
}
/**
* @return 命令别名
*/
public String getAlias() {
return alias;
}
/**
* @return 命令参数
*/
public String[] getArgs() {
return args;
}
/**
* @return 命令实体
*/
public Command getCommand() {
return command;
}
/**
* @return 命令发送者
*/
public CommandSender getSender() {
return sender;
}
}

View File

@ -84,7 +84,7 @@ public class CommandHelp {
*/ */
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) {
Log.toSender(sender, commandNotFound); Log.sender(sender, commandNotFound);
return true; return true;
} }
int page = 1; int page = 1;
@ -175,7 +175,7 @@ public class CommandHelp {
/** /**
* 消息配置 * 消息配置
*/ */
private static String helpTitle = String.format("§6========= %s §6帮助 §aBy §b喵♂呜 §6=========", Log.getPrefix()); 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 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 helpFooter = "§6查看更多的帮助页面 §b请输入 /%s help §e1-%s";
private static String pageNotFound = "§c不存在的帮助页面 §b请输入 /%s help §e1-%s"; private static String pageNotFound = "§c不存在的帮助页面 §b请输入 /%s help §e1-%s";

View File

@ -0,0 +1,63 @@
package pw.yumc.YumCore.commands;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
/**
* 命令工具类
*
* @author 蒋天蓓
* @since 2016/11/21 0021.
*/
public class CommandKit {
private static Constructor<PluginCommand> PluginCommandConstructor;
private static Map<String, Command> knownCommands;
private static Map<String, Plugin> lookupNames;
static {
try {
PluginManager pluginManager = Bukkit.getPluginManager();
Field lookupNamesField = pluginManager.getClass().getDeclaredField("lookupNames");
lookupNamesField.setAccessible(true);
lookupNames = (Map<String, Plugin>) lookupNamesField.get(pluginManager);
Field commandMapField = pluginManager.getClass().getDeclaredField("commandMap");
commandMapField.setAccessible(true);
SimpleCommandMap commandMap = (SimpleCommandMap) commandMapField.get(pluginManager);
Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands");
knownCommandsField.setAccessible(true);
knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
PluginCommandConstructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
Log.d("初始化命令管理器失败!");
Log.debug(e);
}
}
public static PluginCommand create(String name) {
return create(name, P.instance);
}
public static PluginCommand create(String name, JavaPlugin plugin) {
try {
knownCommands.put(name, PluginCommandConstructor.newInstance(name, plugin));
lookupNames.put(name, plugin);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ignored) {
}
return plugin.getCommand(name);
}
}

View File

@ -1,22 +1,24 @@
package pw.yumc.YumCore.commands; 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.info.CommandInfo;
import pw.yumc.YumCore.commands.interfaces.Executor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.commands.info.CommandInfo;
import pw.yumc.YumCore.commands.interfaces.Executor;
/** /**
* 主类命令管理 * 主类命令管理
* *
* @author * @author
* @since 2016/11/18 0018 * @since 2016/11/18 0018
*/ */
public class CommandMain { public class CommandMain implements CommandExecutor {
private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!"; private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!";
/** /**
* 命令列表 * 命令列表
@ -54,14 +56,10 @@ public class CommandMain {
return this; return this;
} }
public boolean execute(CommandSender sender, Command command, String label, String[] args) {
CommandInfo manager = getByCache(label);
return manager != null && manager.execute(new CommandArgument(sender, command, label, args));
}
private boolean registerCommand(Method method, Executor 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) {
injectPluginCommand(ci);
Class[] params = method.getParameterTypes(); Class[] params = method.getParameterTypes();
Log.d("命令 %s 参数类型: %s", ci.getName(), Arrays.toString(params)); Log.d("命令 %s 参数类型: %s", ci.getName(), Arrays.toString(params));
try { try {
@ -76,6 +74,15 @@ public class CommandMain {
return false; return false;
} }
private void injectPluginCommand(CommandInfo ci) {
PluginCommand cmd = P.getCommand(ci.getName());
if (cmd == null) {
if ((cmd = CommandKit.create(ci.getName(), P.instance)) == null) { throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + ci.getName() + " 命令!"); }
}
cmd.setAliases(ci.getAliases());
cmd.setExecutor(this);
}
/** /**
* 检查缓存并获得命令 * 检查缓存并获得命令
* *
@ -95,4 +102,10 @@ public class CommandMain {
} }
return cmdCache.get(cmd); return cmdCache.get(cmd);
} }
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
CommandInfo manager = getByCache(label);
return manager != null && manager.execute(sender, label, args);
}
} }

View File

@ -5,9 +5,7 @@ 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.Option;
import pw.yumc.YumCore.commands.annotation.KeyValue;
import pw.yumc.YumCore.commands.annotation.Limit;
import pw.yumc.YumCore.commands.exception.ParseException; import pw.yumc.YumCore.commands.exception.ParseException;
import java.io.File; import java.io.File;
@ -47,7 +45,7 @@ public class CommandParse {
parse = new EnumParse(clazz); parse = new EnumParse(clazz);
} }
if (parse == null) { throw new ParseException(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).handleAttrs());
} }
} }
@ -77,10 +75,9 @@ public class CommandParse {
allparses.put(clazz, parse); allparses.put(clazz, parse);
} }
public Object[] parse(CommandArgument cmdArgs) { public Object[] parse(CommandSender sender, String label, String[] args) {
String args[] = cmdArgs.getArgs();
List<Object> pobjs = new LinkedList<>(); List<Object> pobjs = new LinkedList<>();
pobjs.add(cmdArgs.getSender()); pobjs.add(sender);
for (int i = 0; i < parse.size(); i++) { for (int i = 0; i < parse.size(); i++) {
try { try {
Parse p = parse.get(i); Parse p = parse.get(i);
@ -89,7 +86,7 @@ public class CommandParse {
if (i + 1 == parse.size() && args.length >= parse.size()) { if (i + 1 == parse.size() && args.length >= parse.size()) {
param = join(Arrays.copyOfRange(args, i, args.length), " "); param = join(Arrays.copyOfRange(args, i, args.length), " ");
} }
pobjs.add(param == null ? null : p.parse(cmdArgs.getSender(), param)); pobjs.add(param == null ? null : p.parse(sender, param));
} catch (Exception e) { } catch (Exception e) {
throw new ParseException(String.format("第 %s 个参数 ", isMain ? 1 : 2 + i) + e.getMessage()); throw new ParseException(String.format("第 %s 个参数 ", isMain ? 1 : 2 + i) + e.getMessage());
} }
@ -244,19 +241,35 @@ public class CommandParse {
public Parse<RT> parseAnnotation(Annotation[] annotations) { public Parse<RT> parseAnnotation(Annotation[] annotations) {
for (Annotation annotation : annotations) { for (Annotation annotation : annotations) {
if (annotation.annotationType() == Default.class) { if (annotation.annotationType() == Option.class) {
def = ((Default) annotation).value(); String value = ((Option) annotation).value();
} else if (annotation.annotationType() == Limit.class) { for (String str : value.split(" ")) {
min = ((Limit) annotation).min(); if (str.isEmpty()) {
max = ((Limit) annotation).max(); continue;
} else if (annotation.annotationType() == KeyValue.class) { }
KeyValue kv = (KeyValue) annotation; if (str.contains(":")) {
attrs.put(kv.key(), kv.value()); String[] args = str.split(":");
attrs.put(args[0], args[1]);
} else {
attrs.put(str, null);
}
}
} }
} }
return this; return this;
} }
public Parse<RT> handleAttrs() {
if (attrs.containsKey("def")) {
def = String.valueOf(attrs.get("def"));
} else if (attrs.containsKey("min")) {
min = Integer.parseInt(String.valueOf(attrs.get("min")));
} else if (attrs.containsKey("max")) {
max = Integer.parseInt(String.valueOf(attrs.get("max")));
}
return this;
}
public void throwException(String str, Object... objects) { public void throwException(String str, Object... objects) {
throw new ParseException(String.format(str, objects)); throw new ParseException(String.format(str, objects));
} }
@ -285,8 +298,7 @@ public class CommandParse {
} }
@Override @Override
public Parse<Player> parseAnnotation(Annotation[] annotations) { public Parse<Player> handleAttrs() {
super.parseAnnotation(annotations);
check = attrs.containsKey("check"); check = attrs.containsKey("check");
return this; return this;
} }
@ -311,8 +323,7 @@ public class CommandParse {
} }
@Override @Override
public Parse<String> parseAnnotation(Annotation[] annotations) { public Parse<String> handleAttrs() {
super.parseAnnotation(annotations);
if (attrs.containsKey("option")) { if (attrs.containsKey("option")) {
options = Arrays.asList(attrs.get("option").split(",")); options = Arrays.asList(attrs.get("option").split(","));
} }

View File

@ -1,392 +1,356 @@
package pw.yumc.YumCore.commands; package pw.yumc.YumCore.commands;
import java.lang.reflect.Constructor; import org.bukkit.command.Command;
import java.lang.reflect.Field; import org.bukkit.command.CommandSender;
import java.lang.reflect.InvocationTargetException; import org.bukkit.command.PluginCommand;
import java.lang.reflect.Method; import org.bukkit.command.TabExecutor;
import java.util.*; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.Bukkit; import org.bukkit.util.StringUtil;
import org.bukkit.command.*; import pw.yumc.YumCore.bukkit.Log;
import org.bukkit.entity.Player; import pw.yumc.YumCore.bukkit.P;
import org.bukkit.plugin.Plugin; import pw.yumc.YumCore.bukkit.compatible.C;
import org.bukkit.plugin.PluginManager; import pw.yumc.YumCore.commands.exception.ArgumentException;
import org.bukkit.plugin.java.JavaPlugin; import pw.yumc.YumCore.commands.exception.CommandException;
import org.bukkit.util.StringUtil; import pw.yumc.YumCore.commands.exception.PermissionException;
import pw.yumc.YumCore.commands.exception.SenderException;
import pw.yumc.YumCore.bukkit.Log; import pw.yumc.YumCore.commands.info.CommandInfo;
import pw.yumc.YumCore.bukkit.P; import pw.yumc.YumCore.commands.info.CommandTabInfo;
import pw.yumc.YumCore.bukkit.compatible.C; import pw.yumc.YumCore.commands.interfaces.ErrorHanlder;
import pw.yumc.YumCore.commands.exception.ArgumentException; import pw.yumc.YumCore.commands.interfaces.Executor;
import pw.yumc.YumCore.commands.exception.CommandException; import pw.yumc.YumCore.commands.interfaces.HelpGenerator;
import pw.yumc.YumCore.commands.exception.PermissionException; import pw.yumc.YumCore.commands.interfaces.HelpParse;
import pw.yumc.YumCore.commands.exception.SenderException;
import pw.yumc.YumCore.commands.info.CommandInfo; import java.lang.reflect.Method;
import pw.yumc.YumCore.commands.info.CommandTabInfo; import java.util.*;
import pw.yumc.YumCore.commands.interfaces.ErrorHanlder;
import pw.yumc.YumCore.commands.interfaces.Executor; /**
import pw.yumc.YumCore.commands.interfaces.HelpGenerator; * 命令管理类
import pw.yumc.YumCore.commands.interfaces.HelpParse; *
* @author
/** * @since 2016年7月23日 上午9:06:03
* 命令管理类 */
* public class CommandSub implements TabExecutor {
* @author private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!";
* @since 2016年7月23日 上午9:06:03 private static String returnTypeError = "注解命令补全 %s 位于 %s 的返回值错误 应实现 List 接口!";
*/ private static String onlyExecutor = "§c当前命令仅允许 §b%s §c执行!";
public class CommandManager implements TabExecutor { private static String losePerm = "§c你需要有 %s 的权限才能执行此命令!";
private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!"; private static String cmdErr = "§6错误原因: §4命令参数不正确!";
private static String returnTypeError = "注解命令补全 %s 位于 %s 的返回值错误 应实现 List 接口!"; private static String cmdUse = "§6使用方法: §e/%s %s%s";
private static String onlyExecutor = "§c当前命令仅允许 §b%s §c执行!"; private static String cmdDes = "§6命令描述: §3%s";
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 CommandHelp help;
private static Map<String, Command> knownCommands; /**
private static Map<String, Plugin> lookupNames; * 插件命令
*/
static { private PluginCommand cmd;
try { /**
PluginManager pluginManager = Bukkit.getPluginManager(); * 命令错误处理
*/
Field lookupNamesField = pluginManager.getClass().getDeclaredField("lookupNames"); private ErrorHanlder commandErrorHanlder = new ErrorHanlder() {
lookupNamesField.setAccessible(true); @Override
lookupNames = (Map<String, Plugin>) lookupNamesField.get(pluginManager); public void error(CommandException e, CommandSender sender, CommandInfo info, String label, String[] args) {
if (e instanceof SenderException) {
Field commandMapField = pluginManager.getClass().getDeclaredField("commandMap"); Log.sender(sender, onlyExecutor, info.getExecutorStr());
commandMapField.setAccessible(true); } else if (e instanceof PermissionException) {
SimpleCommandMap commandMap = (SimpleCommandMap) commandMapField.get(pluginManager); Log.sender(sender, losePerm, info.getCommand().permission());
} else if (e instanceof ArgumentException) {
Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands"); Log.sender(sender, cmdErr);
knownCommandsField.setAccessible(true); Log.sender(sender, cmdUse, label, info.isDefault() ? "" : info.getName() + " ", info.getHelp().possibleArguments());
knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap); Log.sender(sender, cmdDes, info.getHelp().value());
}
PluginCommandConstructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); }
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { };
Log.d("初始化命令管理器失败!"); /**
Log.debug(e); * 插件实例类
} */
} private static JavaPlugin plugin = P.instance;
/**
/** * 默认命令
* 命令帮助 */
*/ private CommandInfo defCmd = null;
private CommandHelp help; /**
/** * 命令列表
* 插件命令 */
*/ private Set<CommandInfo> cmds = new HashSet<>();
private PluginCommand cmd; /**
/** * Tab列表
* 命令错误处理 */
*/ private Set<CommandTabInfo> tabs = new HashSet<>();
private ErrorHanlder commandErrorHanlder = new ErrorHanlder() { /**
@Override * 命令缓存列表
public void error(CommandException e, CommandSender sender, CommandInfo info, CommandArgument args) { */
if (e instanceof SenderException) { private Map<String, CommandInfo> cmdCache = new HashMap<>();
Log.toSender(sender, onlyExecutor, info.getExecutorStr()); /**
} else if (e instanceof PermissionException) { * 命令名称缓存
Log.toSender(sender, losePerm, info.getCommand().permission()); */
} else if (e instanceof ArgumentException) { private List<String> cmdNameCache = new ArrayList<>();
Log.toSender(sender, cmdErr);
Log.toSender(sender, cmdUse, args.getAlias(), info.isDefault() ? "" : info.getName() + " ", info.getHelp().possibleArguments()); /**
Log.toSender(sender, cmdDes, info.getHelp().value()); * 命令管理器 用于主类
} *
} * @param executor
}; * 命令执行类
/** */
* 插件实例类 public CommandSub(Executor... executor) {
*/ register(executor);
private static JavaPlugin plugin = P.instance; }
/**
* 默认命令 /**
*/ * 命令管理器
private CommandInfo defCmd = null; *
/** * @param name
* 命令列表 * 注册的命令
*/ */
private Set<CommandInfo> cmds = new HashSet<>(); public CommandSub(String name) {
/** cmd = plugin.getCommand(name);
* Tab列表 if (cmd == null) {
*/ if ((cmd = CommandKit.create(name, plugin)) == null) { throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + name + " 命令!"); }
private Set<CommandTabInfo> tabs = new HashSet<>(); }
/** cmd.setExecutor(this);
* 命令缓存列表 cmd.setTabCompleter(this);
*/ }
private Map<String, CommandInfo> cmdCache = new HashMap<>();
/** /**
* 命令名称缓存 * 命令管理器
*/ *
private List<String> cmdNameCache = new ArrayList<>(); * @param name
* 注册的命令
/** * @param executor
* 命令管理器 用于主类 * 命令执行类
* */
* @param executor public CommandSub(String name, Executor... executor) {
* 命令执行类 this(name);
*/ register(executor);
public CommandManager(Executor... executor) { }
register(executor);
} /**
* 构建命令列表缓存
/** */
* 命令管理器 private void buildCmdNameCache() {
* cmdNameCache.clear();
* @param name for (CommandInfo cmd : cmds) {
* 注册的命令 cmdNameCache.add(cmd.getName());
*/ cmdNameCache.addAll(Arrays.asList(cmd.getCommand().aliases()));
public CommandManager(String name) { }
cmd = plugin.getCommand(name); cmdNameCache.add("help");
if (cmd == null) { }
try {
knownCommands.put(name, PluginCommandConstructor.newInstance(name, plugin)); /**
lookupNames.put(name, plugin); * 检查缓存并获得命令
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ignored) { *
} * @param subcmd
if ((cmd = plugin.getCommand(name)) == null) { throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + name + " 命令!"); } * 子命令
} * @return 命令信息
cmd.setExecutor(this); */
cmd.setTabCompleter(this); private CommandInfo getByCache(String subcmd) {
} if (!cmdCache.containsKey(subcmd)) {
for (CommandInfo cmdinfo : cmds) {
/** if (cmdinfo.isValid(subcmd)) {
* 命令管理器 cmdCache.put(subcmd, cmdinfo);
* break;
* @param name }
* 注册的命令 }
* @param executor if (!cmdCache.containsKey(subcmd)) {
* 命令执行类 cmdCache.put(subcmd, CommandInfo.Unknow);
*/ }
public CommandManager(String name, Executor... executor) { }
this(name); return cmdCache.get(subcmd);
register(executor); }
}
/**
/** * 获取玩家命令补全
* 构建命令列表缓存 *
*/ * @param sender
private void buildCmdNameCache() { * 命令发送者
cmdNameCache.clear(); * @param command
for (CommandInfo cmd : cmds) { * 命令
cmdNameCache.add(cmd.getName()); * @param alias
cmdNameCache.addAll(Arrays.asList(cmd.getCommand().aliases())); * 别名
} * @param args
cmdNameCache.add("help"); * 数组
} * @return 在线玩家数组
*/
/** private List<String> getPlayerTabComplete(CommandSender sender, Command command, String alias, String[] args) {
* 检查缓存并获得命令 String lastWord = args[args.length - 1];
* Player senderPlayer = sender instanceof Player ? (Player) sender : null;
* @param subcmd List<String> matchedPlayers = new ArrayList<>();
* 子命令 for (Player player : C.Player.getOnlinePlayers()) {
* @return 命令信息 String name = player.getName();
*/ if ((senderPlayer == null || senderPlayer.canSee(player)) && StringUtil.startsWithIgnoreCase(name, lastWord)) {
private CommandInfo getByCache(String subcmd) { matchedPlayers.add(name);
if (!cmdCache.containsKey(subcmd)) { }
for (CommandInfo cmdinfo : cmds) { }
if (cmdinfo.isValid(subcmd)) { return matchedPlayers;
cmdCache.put(subcmd, cmdinfo); }
break;
} /**
} * 转移数组
if (!cmdCache.containsKey(subcmd)) { *
cmdCache.put(subcmd, CommandInfo.Unknow); * @param args
} * 原数组
} * @param start
return cmdCache.get(subcmd); * 数组开始位置
} * @return 转移后的数组字符串
*/
/** private String[] moveStrings(String[] args, int start) {
* 获取玩家命令补全 String[] ret = new String[args.length - start];
* System.arraycopy(args, start, ret, 0, ret.length);
* @param sender return ret;
* 命令发送者 }
* @param command
* 命令 @Override
* @param alias public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
* 别名 if (args.length == 0) {
* @param args if (defCmd != null) { return defCmd.execute(sender, label, args); }
* 数组 return help.send(sender, command, label, args);
* @return 在线玩家数组 }
*/ String subcmd = args[0].toLowerCase();
private List<String> getPlayerTabComplete(CommandSender sender, Command command, String alias, String[] args) { if (subcmd.equalsIgnoreCase("help")) { return help.send(sender, command, label, args); }
String lastWord = args[args.length - 1]; CommandInfo cmd = getByCache(subcmd);
Player senderPlayer = sender instanceof Player ? (Player) sender : null; String[] subargs = args;
List<String> matchedPlayers = new ArrayList<>(); if (cmd.equals(CommandInfo.Unknow) && defCmd != null) {
for (Player player : C.Player.getOnlinePlayers()) { cmd = defCmd;
String name = player.getName(); } else {
if ((senderPlayer == null || senderPlayer.canSee(player)) && StringUtil.startsWithIgnoreCase(name, lastWord)) { subargs = moveStrings(args, 1);
matchedPlayers.add(name); }
} try {
} return cmd.execute(sender, label, subargs);
return matchedPlayers; } catch (CommandException e) {
} commandErrorHanlder.error(e, sender, cmd, label, subargs);
}
/** return false;
* 转移数组 }
*
* @param args @Override
* 原数组 public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
* @param start List<String> completions = new ArrayList<>();
* 数组开始位置 String token = args[args.length - 1];
* @return 转移后的数组字符串 if (args.length == 1) {
*/ StringUtil.copyPartialMatches(token, cmdNameCache, completions);
private String[] moveStrings(String[] args, int start) { }
String[] ret = new String[args.length - start]; for (CommandTabInfo tab : tabs) {
System.arraycopy(args, start, ret, 0, ret.length); StringUtil.copyPartialMatches(token, tab.execute(sender, token, args), completions);
return ret; }
} StringUtil.copyPartialMatches(token, getPlayerTabComplete(sender, command, alias, args), completions);
Collections.sort(completions, String.CASE_INSENSITIVE_ORDER);
@Override return completions;
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { }
if (args.length == 0) {
if (defCmd != null) { return defCmd.execute(new CommandArgument(sender, command, label, args)); } /**
return help.send(sender, command, label, args); * 通过注解读取命令并注册
} *
String subcmd = args[0].toLowerCase(); * @param clazzs
if (subcmd.equalsIgnoreCase("help")) { return help.send(sender, command, label, args); } * 子命令处理类
CommandInfo cmd = getByCache(subcmd); * @return {@link CommandSub}
CommandArgument arg; */
if (cmd.equals(CommandInfo.Unknow) && defCmd != null) { public CommandSub register(Executor... clazzs) {
cmd = defCmd; for (Executor clazz : clazzs) {
arg = new CommandArgument(sender, command, label, args); Method[] methods = clazz.getClass().getDeclaredMethods();
} else { for (Method method : methods) {
arg = new CommandArgument(sender, command, label, moveStrings(args, 1)); if (registerCommand(method, clazz)) {
} continue;
try { }
return cmd.execute(arg); registerTab(method, clazz);
} catch (CommandException e) { }
commandErrorHanlder.error(e, sender, cmd, arg); }
} help = new CommandHelp(defCmd, cmds);
return false; buildCmdNameCache();
} return this;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { /**
List<String> completions = new ArrayList<>(); * 注册命令
String token = args[args.length - 1]; *
if (args.length == 1) { * @param method
StringUtil.copyPartialMatches(token, cmdNameCache, completions); * 方法
} * @param clazz
for (CommandTabInfo tab : tabs) { * 调用对象
StringUtil.copyPartialMatches(token, tab.execute(sender, command, token, args), completions); * @return 是否成功
} */
StringUtil.copyPartialMatches(token, getPlayerTabComplete(sender, command, alias, args), completions); private boolean registerCommand(Method method, Executor clazz) {
Collections.sort(completions, String.CASE_INSENSITIVE_ORDER); CommandInfo ci = CommandInfo.parse(method, clazz);
return completions; if (ci != null) {
} Class[] params = method.getParameterTypes();
Log.d("命令 %s 参数类型: %s", ci.getName(), Arrays.toString(params));
/** try {
* 通过注解读取命令并注册 Class<? extends CommandSender> sender = params[0];
* // 用于消除unuse警告
* @param clazzs if (!sender.getName().isEmpty() && method.getReturnType() == boolean.class) {
* 子命令处理类 defCmd = ci;
* @return {@link CommandManager} } else {
*/ cmds.add(ci);
public CommandManager register(Executor... clazzs) { cmdCache.put(ci.getName(), ci);
for (Executor clazz : clazzs) { }
Method[] methods = clazz.getClass().getDeclaredMethods(); return true;
for (Method method : methods) { } catch (ArrayIndexOutOfBoundsException | ClassCastException ignored) {
if (registerCommand(method, clazz)) { }
continue; Log.warning(String.format(argumentTypeError, method.getName(), clazz.getClass().getName()));
} }
registerTab(method, clazz); return false;
} }
}
help = new CommandHelp(defCmd, cmds); /**
buildCmdNameCache(); * 注册Tab补全
return this; *
} * @param method
* 方法
/** * @param clazz
* 注册命令 * 调用对象
* * @return 是否成功
* @param method */
* 方法 private boolean registerTab(Method method, Executor clazz) {
* @param clazz CommandTabInfo ti = CommandTabInfo.parse(method, clazz);
* 调用对象 if (ti != null) {
* @return 是否成功 if (method.getReturnType().equals(List.class)) {
*/ tabs.add(ti);
private boolean registerCommand(Method method, Executor clazz) { return true;
CommandInfo ci = CommandInfo.parse(method, clazz); }
if (ci != null) { Log.warning(String.format(returnTypeError, method.getName(), clazz.getClass().getName()));
Class[] params = method.getParameterTypes(); }
Log.d("命令 %s 参数类型: %s", ci.getName(), Arrays.toString(params)); return false;
try { }
Class<? extends CommandSender> sender = params[0];
// 用于消除unuse警告 /**
if (!sender.getName().isEmpty() && method.getReturnType() == boolean.class) { * 设置命令错误处理器
defCmd = ci; *
} else { * @param commandErrorHanlder
cmds.add(ci); * 命令错误处理器
cmdCache.put(ci.getName(), ci); * @return {@link CommandSub}
} */
return true; public CommandSub setCommandErrorHanlder(ErrorHanlder commandErrorHanlder) {
} catch (ArrayIndexOutOfBoundsException | ClassCastException ignored) { this.commandErrorHanlder = commandErrorHanlder;
} return this;
Log.warning(String.format(argumentTypeError, method.getName(), clazz.getClass().getName())); }
}
return false; /**
} * 设置帮助生成器
*
/** * @param helpGenerator
* 注册Tab补全 * 帮助生成器
* * @return {@link CommandSub}
* @param method */
* 方法 public CommandSub setHelpGenerator(HelpGenerator helpGenerator) {
* @param clazz help.setHelpGenerator(helpGenerator);
* 调用对象 return this;
* @return 是否成功 }
*/
private boolean registerTab(Method method, Executor clazz) { /**
CommandTabInfo ti = CommandTabInfo.parse(method, clazz); * 设置帮助解析器
if (ti != null) { *
if (method.getReturnType().equals(List.class)) { * @param helpParse
tabs.add(ti); * 帮助解析器
return true; * @return {@link CommandSub}
} */
Log.warning(String.format(returnTypeError, method.getName(), clazz.getClass().getName())); public CommandSub setHelpParse(HelpParse helpParse) {
} if (help.getHelpGenerator() instanceof CommandHelp.DefaultHelpGenerator) {
return false; ((CommandHelp.DefaultHelpGenerator) help.getHelpGenerator()).setHelpParse(helpParse);
} } else {
Log.w("已设置自定义帮助生成器 解析器设置将不会生效!");
/** }
* 设置命令错误处理器 return this;
* }
* @param commandErrorHanlder }
* 命令错误处理器
* @return {@link CommandManager}
*/
public CommandManager setCommandErrorHanlder(ErrorHanlder commandErrorHanlder) {
this.commandErrorHanlder = commandErrorHanlder;
return this;
}
/**
* 设置帮助生成器
*
* @param helpGenerator
* 帮助生成器
* @return {@link CommandManager}
*/
public CommandManager setHelpGenerator(HelpGenerator helpGenerator) {
help.setHelpGenerator(helpGenerator);
return this;
}
/**
* 设置帮助解析器
*
* @param helpParse
* 帮助解析器
* @return {@link CommandManager}
*/
public CommandManager setHelpParse(HelpParse helpParse) {
if (help.getHelpGenerator() instanceof CommandHelp.DefaultHelpGenerator) {
((CommandHelp.DefaultHelpGenerator) help.getHelpGenerator()).setHelpParse(helpParse);
} else {
Log.w("已设置自定义帮助生成器 解析器设置将不会生效!");
}
return this;
}
}

View File

@ -1,26 +0,0 @@
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 KeyValue {
/**
* @return
*/
String key();
/**
* @return
*/
String value() default "";
}

View File

@ -1,26 +0,0 @@
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 Integer.MAX_VALUE;
/**
* @return 最小长度(或最小值)
*/
int min();
}

View File

@ -6,13 +6,13 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* 默认参数 * 扩展选项注解
* *
* @since 2016年7月23日 上午9:00:27 * @since 2016年7月23日 上午9:00:07
* @author * @author
*/ */
@Target(ElementType.PARAMETER) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Default { public @interface Option {
String value(); String value();
} }

View File

@ -4,7 +4,6 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
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.commands.CommandArgument;
import pw.yumc.YumCore.commands.CommandParse; import pw.yumc.YumCore.commands.CommandParse;
import pw.yumc.YumCore.commands.annotation.Async; import pw.yumc.YumCore.commands.annotation.Async;
import pw.yumc.YumCore.commands.annotation.Cmd; import pw.yumc.YumCore.commands.annotation.Cmd;
@ -112,20 +111,24 @@ public class CommandInfo {
/** /**
* 执行命令 * 执行命令
* *
* @param cmdArgs * @param sender
* 命令参数 * 命令发送者
* @param label
* 命令标签
* @param args
* 参数
* @return 是否执行成功 * @return 是否执行成功
*/ */
public boolean execute(final CommandArgument cmdArgs) { public boolean execute(final CommandSender sender, final String label, final String[] args) {
if (method == null) { return false; } if (method == null) { return false; }
check(cmdArgs); check(sender, label, args);
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(sender, label, args));
} catch (ParseException | ArgumentException e) { } catch (ParseException | ArgumentException e) {
Log.toSender(cmdArgs.getSender(), argErr, e.getMessage()); Log.sender(sender, argErr, e.getMessage());
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new CommandException(e); throw new CommandException(e);
} }
@ -160,6 +163,13 @@ public class CommandInfo {
return name; return name;
} }
/**
* @return 命令别名
*/
public List<String> getAliases() {
return aliases;
}
/** /**
* @return 命令排序 * @return 命令排序
*/ */
@ -212,11 +222,10 @@ public class CommandInfo {
return Objects.hash(origin, method, name); return Objects.hash(origin, method, name);
} }
private void check(CommandArgument cmdArgs) { private void check(CommandSender sender, String label, String[] args) {
CommandSender sender = cmdArgs.getSender();
if (!executors.contains(Executor.ALL) && !executors.contains(Executor.valueOf(sender))) { throw new SenderException(executorStr); } 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 (!"".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())); } if (args.length < command.minimumArguments()) { throw new ArgumentException(String.valueOf(command.minimumArguments())); }
} }
private String eS(List<Executor> executors) { private String eS(List<Executor> executors) {

View File

@ -2,7 +2,6 @@ package pw.yumc.YumCore.commands.info;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import pw.yumc.YumCore.bukkit.P; import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.commands.CommandArgument;
import pw.yumc.YumCore.commands.annotation.Tab; import pw.yumc.YumCore.commands.annotation.Tab;
import pw.yumc.YumCore.commands.exception.CommandException; import pw.yumc.YumCore.commands.exception.CommandException;
@ -47,8 +46,6 @@ public class CommandTabInfo {
* *
* @param sender * @param sender
* 发送者 * 发送者
* @param command
* 命令
* @param label * @param label
* 命令 * 命令
* @param args * @param args
@ -56,10 +53,9 @@ public class CommandTabInfo {
* @return Tab补全信息 * @return Tab补全信息
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<String> execute(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) { public List<String> execute(CommandSender sender, String label, String[] args) {
CommandArgument cmdArgs = new CommandArgument(sender, command, label, args);
try { try {
return (List<String>) method.invoke(origin, cmdArgs); return (List<String>) method.invoke(origin, sender, label, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new CommandException("调用Tab自动补全发生错误 请反馈给开发者 " + Arrays.toString(P.getDescription().getAuthors().toArray()) + " !", e); throw new CommandException("调用Tab自动补全发生错误 请反馈给开发者 " + Arrays.toString(P.getDescription().getAuthors().toArray()) + " !", e);
} }

View File

@ -1,7 +1,6 @@
package pw.yumc.YumCore.commands.interfaces; package pw.yumc.YumCore.commands.interfaces;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import pw.yumc.YumCore.commands.CommandArgument;
import pw.yumc.YumCore.commands.exception.CommandException; import pw.yumc.YumCore.commands.exception.CommandException;
import pw.yumc.YumCore.commands.info.CommandInfo; import pw.yumc.YumCore.commands.info.CommandInfo;
@ -12,5 +11,5 @@ import pw.yumc.YumCore.commands.info.CommandInfo;
* @author * @author
*/ */
public interface ErrorHanlder { public interface ErrorHanlder {
void error(CommandException e, CommandSender sender, CommandInfo info, CommandArgument args); void error(CommandException e, CommandSender sender, CommandInfo info, String label, String[] args);
} }

View File

@ -1,5 +1,9 @@
package pw.yumc.YumCore.config.inject; package pw.yumc.YumCore.config.inject;
import org.bukkit.configuration.ConfigurationSection;
import pw.yumc.YumCore.config.exception.ConfigParseException;
import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
@ -7,10 +11,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.bukkit.configuration.ConfigurationSection;
import pw.yumc.YumCore.config.exception.ConfigParseException;
/** /**
* 注入配置类解析 * 注入配置类解析
* *
@ -20,7 +20,7 @@ import pw.yumc.YumCore.config.exception.ConfigParseException;
public class InjectParse { public class InjectParse {
private static String DATE_PARSE_ERROR = "配置节点 {0} 日期解析失败 格式应该为: {1} 但输入值为: {2}!"; private static String DATE_PARSE_ERROR = "配置节点 {0} 日期解析失败 格式应该为: {1} 但输入值为: {2}!";
private static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); private static DateFormat df = new SimpleDateFormat(DATE_FORMAT);
private static Map<Class, Parse> allparse = new HashMap<>(); private static Map<Class, Parse> allparse = new HashMap<>();
static { static {
@ -62,6 +62,16 @@ public class InjectParse {
} }
} }
public static class DateFormatParse implements Parse<DateFormat> {
public DateFormatParse() {
allparse.put(DateFormat.class, this);
}
@Override
public DateFormat parse(ConfigurationSection config, String path) {
return new SimpleDateFormat(config.getString(path));
}
}
public static class ListParse implements Parse<List> { public static class ListParse implements Parse<List> {
public ListParse() { public ListParse() {
allparse.put(List.class, this); allparse.put(List.class, this);

View File

@ -45,7 +45,7 @@ public class I18N {
} }
public static void send(CommandSender sender, String message, String def, Object... objs) { public static void send(CommandSender sender, String message, String def, Object... objs) {
Log.toSender(sender, $(message, def), objs); Log.sender(sender, $(message, def), objs);
} }
/** /**

View File

@ -79,7 +79,7 @@ public class LogKit implements Runnable {
* 日志 * 日志
*/ */
public void send(final CommandSender sender, final String s) { public void send(final CommandSender sender, final String s) {
Log.toSender(sender, s); Log.sender(sender, s);
log(ChatColor.stripColor(s)); log(ChatColor.stripColor(s));
} }