1
0
mirror of https://e.coding.net/circlecloud/YumCore.git synced 2024-11-21 01:38:51 +00:00

feat: 移动配置处理类 重构命令框架

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-10-08 00:11:27 +08:00
parent 8d29a90c04
commit ea1ddd6385
9 changed files with 228 additions and 15 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>pw.yumc</groupId>
<artifactId>YumCore</artifactId>
<version>1.0</version>
<version>1.1</version>
<name>YumCore</name>
<build>
<finalName>${project.name}</finalName>

View File

@ -15,12 +15,14 @@ public class CommandArgument {
private final Command command;
private final String alias;
private final String[] args;
private final CommandParse parses;
public CommandArgument(final CommandSender sender, final Command command, final String alias, final String[] args) {
this.sender = sender;
this.command = command;
this.alias = alias;
this.args = args;
parses = null;
}
/**

View File

@ -43,8 +43,9 @@ public class CommandInfo {
private final Cmd command;
private final Help help;
private final int sort;
private final CommandParse parse;
public CommandInfo(final Method method, final Object origin, final Cmd command, final Help help, final boolean async, final int sort) {
public CommandInfo(final Method method, final Object origin, final Cmd command, final Help help, final boolean async, final int sort, final CommandParse parse) {
this.method = method;
this.origin = origin;
this.name = "".equals(command.value()) ? method.getName().toLowerCase() : command.value();
@ -55,6 +56,7 @@ public class CommandInfo {
this.help = help;
this.async = async;
this.sort = sort;
this.parse = parse;
}
private CommandInfo() {
@ -68,6 +70,7 @@ public class CommandInfo {
this.help = null;
this.async = false;
this.sort = 0;
this.parse = null;
}
/**
@ -85,7 +88,8 @@ public class CommandInfo {
final Help help = method.getAnnotation(Help.class);
final Async async = method.getAnnotation(Async.class);
final Sort sort = method.getAnnotation(Sort.class);
return new CommandInfo(method, origin, command, help != null ? help : Help.DEFAULT, async != null, sort != null ? sort.value() : 50);
final CommandParse cp = CommandParse.get(method);
return new CommandInfo(method, origin, command, help != null ? help : Help.DEFAULT, async != null, sort != null ? sort.value() : 50, cp);
}
return null;
}
@ -117,7 +121,7 @@ public class CommandInfo {
@Override
public void run() {
try {
method.invoke(origin, cmdArgs);
method.invoke(origin, cmdArgs.getSender(), parse.parse(cmdArgs));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new CommandException(e);
}

View File

@ -1,5 +1,8 @@
package pw.yumc.YumCore.commands;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
@ -10,11 +13,15 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.StringUtil;
@ -29,8 +36,33 @@ import pw.yumc.YumCore.bukkit.compatible.C;
* @author
*/
public class CommandManager implements TabExecutor {
private final static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 应只有 CommandArgument 参数!";
private final static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!";
private final static String returnTypeError = "注解命令补全 %s 位于 %s 的返回值错误 应实现 List 接口!";
private static Constructor<PluginCommand> PluginCommandConstructor;
private static Map<String, Command> knownCommands;
private static Map<String, Plugin> lookupNames;
static {
try {
final PluginManager pluginManager = Bukkit.getPluginManager();
final Field lookupNamesField = pluginManager.getClass().getDeclaredField("lookupNames");
lookupNamesField.setAccessible(true);
lookupNames = (Map<String, Plugin>) lookupNamesField.get(pluginManager);
final Field commandMapField = pluginManager.getClass().getDeclaredField("commandMap");
commandMapField.setAccessible(true);
final SimpleCommandMap commandMap = (SimpleCommandMap) commandMapField.get(pluginManager);
final Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands");
knownCommandsField.setAccessible(true);
knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
PluginCommandConstructor = PluginCommand.class.getConstructor(String.class, Plugin.class);
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
Log.d("初始化命令管理器失败!");
Log.debug(e);
}
}
/**
* 插件实例类
*/
@ -62,7 +94,7 @@ public class CommandManager implements TabExecutor {
/**
* 插件命令
*/
private final PluginCommand cmd;
private PluginCommand cmd;
/**
* 命令管理器
@ -73,7 +105,14 @@ public class CommandManager implements TabExecutor {
public CommandManager(final String name) {
cmd = plugin.getCommand(name);
if (cmd == null) {
throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + name + " 命令!");
try {
knownCommands.put(name, PluginCommandConstructor.newInstance(name, plugin));
lookupNames.put(name, plugin);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
}
if ((cmd = plugin.getCommand(name)) == null) {
throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + name + " 命令!");
}
}
cmd.setExecutor(this);
cmd.setTabCompleter(this);
@ -106,9 +145,8 @@ public class CommandManager implements TabExecutor {
help.send(sender, command, label, args);
return true;
}
final CommandArgument cmdArgs = new CommandArgument(sender, command, label, moveStrings(args, 1));
final CommandInfo ci = checkCache(subcmd);
return ci.execute(cmdArgs);
return ci.execute(new CommandArgument(sender, command, label, moveStrings(args, 1)));
}
@Override
@ -245,7 +283,7 @@ public class CommandManager implements TabExecutor {
final CommandInfo ci = CommandInfo.parse(method, clazz);
if (ci != null) {
final Class<?>[] params = method.getParameterTypes();
if (params.length == 1 && params[0].equals(CommandArgument.class)) {
if (params.length > 0 && params[0].equals(CommandArgument.class)) {
if (method.getReturnType() == boolean.class) {
defCmd = ci;
return true;

View File

@ -0,0 +1,143 @@
package pw.yumc.YumCore.commands;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import pw.yumc.YumCore.commands.exception.CommandException;
import pw.yumc.YumCore.commands.exception.CommandParseException;
/**
* 命令参数解析
*
* @author
* @since 2016年10月5日 下午4:02:04
*/
public class CommandParse {
private static Map<Class, Parse> allparses;
static {
new IntegerParse();
new LongParse();
new BooleanParse();
new PlayerParse();
new StringParse();
}
public List<Parse> parse = new LinkedList<>();
public List<Object> parsed = new LinkedList<>();
public CommandParse(final Class[] classes, final Annotation[][] annons) {
for (final Class classe : classes) {
final Class clazz = classe;
if (!allparses.containsKey(clazz)) {
throw new CommandParseException(String.format("无法解析的参数类型 %s !", clazz.getName()));
}
parse.add(allparses.get(clazz));
}
}
public static CommandParse get(final Method method) {
return new CommandParse(method.getParameterTypes(), method.getParameterAnnotations());
}
public static void registerParse(final Class clazz, final Parse parse) {
allparses.put(clazz, parse);
}
public Object[] parse(final CommandArgument cmdArgs) {
final String args[] = cmdArgs.getArgs();
if (args.length == 0) {
return null;
}
final List<Object> pobjs = new LinkedList<>();
pobjs.add(cmdArgs.getSender());
for (int i = 0; i < args.length; i++) {
try {
if (i < parse.size()) {
pobjs.add(parse.get(i).parse(args[i]));
}
} catch (final Exception e) {
throw new CommandException(String.format(e.getMessage(), i + 1));
}
}
return pobjs.toArray();
}
public static class BooleanParse implements Parse<Boolean> {
public BooleanParse() {
allparses.put(Boolean.class, this);
allparses.put(boolean.class, this);
}
@Override
public Boolean parse(final String arg) {
try {
return Boolean.parseBoolean(arg);
} catch (final Exception e) {
throw new CommandParseException("第 %s 个参数必须为True或者False!");
}
}
}
public static class IntegerParse implements Parse<Integer> {
public IntegerParse() {
allparses.put(Integer.class, this);
allparses.put(int.class, this);
}
@Override
public Integer parse(final String arg) {
try {
return Integer.parseInt(arg);
} catch (final Exception e) {
throw new CommandParseException("第 %s 个参数必须为数字!");
}
}
}
public static class LongParse implements Parse<Long> {
public LongParse() {
allparses.put(Long.class, this);
allparses.put(long.class, this);
}
@Override
public Long parse(final String arg) {
try {
return Long.parseLong(arg);
} catch (final Exception e) {
throw new CommandParseException("第 %s 个参数必须为数字!");
}
}
}
public static interface Parse<RT> {
public RT parse(String arg) throws CommandParseException;
}
public static class PlayerParse implements Parse<Player> {
public PlayerParse() {
allparses.put(Player.class, this);
}
@Override
public Player parse(final String arg) {
return Bukkit.getPlayerExact(arg);
}
}
public static class StringParse implements Parse<String> {
public StringParse() {
allparses.put(String.class, this);
}
@Override
public String parse(final String arg) {
return arg;
}
}
}

View File

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

View File

@ -1,4 +1,4 @@
package pw.yumc.YumCore.config;
package pw.yumc.YumCore.config.inject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@ -12,6 +12,9 @@ import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.config.ConfigNode;
import pw.yumc.YumCore.config.Default;
import pw.yumc.YumCore.config.Nullable;
/**
* 抽象注入配置
@ -177,7 +180,6 @@ public abstract class AbstractInjectConfig {
* @throws IllegalAccessException
*/
private void hanldeValue(final String path, final Field field, Object value) throws IllegalAccessException, IllegalArgumentException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException, ParseException {
final Object origin = field.get(this);
final Class<?> type = field.getType();
if (!type.equals(value.getClass())) {
value = convertType(type, path, value);
@ -186,7 +188,7 @@ public abstract class AbstractInjectConfig {
value = ChatColor.translateAlternateColorCodes('&', (String) value);
}
field.set(this, value);
Log.d("设置字段 %s 由 %s 为 %s ", field.getName(), origin, value);
Log.d("设置字段 %s 为 %s ", field.getName(), value);
}
/**

View File

@ -1,7 +1,9 @@
package pw.yumc.YumCore.config;
package pw.yumc.YumCore.config.inject;
import java.io.File;
import pw.yumc.YumCore.config.FileConfig;
/**
* 配置自动载入类
*

View File

@ -1,4 +1,4 @@
package pw.yumc.YumCore.config;
package pw.yumc.YumCore.config.inject;
import org.bukkit.configuration.ConfigurationSection;