mirror of
				https://e.coding.net/circlecloud/YumCore.git
				synced 2025-11-03 23:06:02 +00:00 
			
		
		
		
	@@ -243,7 +243,7 @@ public class Log {
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param msg    消息
 | 
			
		||||
     */
 | 
			
		||||
    public static void toSender(CommandSender sender, String msg) {
 | 
			
		||||
    public static void sender(CommandSender sender, String msg) {
 | 
			
		||||
        sender.sendMessage(prefix + msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -254,7 +254,7 @@ public class Log {
 | 
			
		||||
     * @param msg    消息
 | 
			
		||||
     * @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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -264,9 +264,9 @@ public class Log {
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param msg    消息
 | 
			
		||||
     */
 | 
			
		||||
    public static void toSender(CommandSender sender, String[] msg) {
 | 
			
		||||
    public static void sender(CommandSender sender, String[] msg) {
 | 
			
		||||
        for (String str : msg) {
 | 
			
		||||
            toSender(sender, str);
 | 
			
		||||
            sender(sender, str);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -84,7 +84,7 @@ public class CommandHelp {
 | 
			
		||||
     */
 | 
			
		||||
    public boolean send(CommandSender sender, Command command, String label, String[] args) {
 | 
			
		||||
        if (this.HELPPAGECOUNT == 0) {
 | 
			
		||||
            Log.toSender(sender, commandNotFound);
 | 
			
		||||
            Log.sender(sender, commandNotFound);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        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 helpFooter = "§6查看更多的帮助页面 §b请输入 /%s help §e1-%s";
 | 
			
		||||
        private static String pageNotFound = "§c不存在的帮助页面 §b请输入 /%s help §e1-%s";
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								src/main/java/pw/yumc/YumCore/commands/CommandKit.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/main/java/pw/yumc/YumCore/commands/CommandKit.java
									
									
									
									
									
										Normal 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,22 +1,24 @@
 | 
			
		||||
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.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 喵♂呜
 | 
			
		||||
 * @since 2016/11/18 0018
 | 
			
		||||
 */
 | 
			
		||||
public class CommandMain {
 | 
			
		||||
public class CommandMain implements CommandExecutor {
 | 
			
		||||
    private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!";
 | 
			
		||||
    /**
 | 
			
		||||
     * 命令列表
 | 
			
		||||
@@ -54,14 +56,10 @@ public class CommandMain {
 | 
			
		||||
        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) {
 | 
			
		||||
        CommandInfo ci = CommandInfo.parse(method, clazz);
 | 
			
		||||
        if (ci != null) {
 | 
			
		||||
            injectPluginCommand(ci);
 | 
			
		||||
            Class[] params = method.getParameterTypes();
 | 
			
		||||
            Log.d("命令 %s 参数类型: %s", ci.getName(), Arrays.toString(params));
 | 
			
		||||
            try {
 | 
			
		||||
@@ -76,6 +74,15 @@ public class CommandMain {
 | 
			
		||||
        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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 | 
			
		||||
        CommandInfo manager = getByCache(label);
 | 
			
		||||
        return manager != null && manager.execute(sender, label, args);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,7 @@ 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;
 | 
			
		||||
import pw.yumc.YumCore.commands.annotation.Option;
 | 
			
		||||
import pw.yumc.YumCore.commands.exception.ParseException;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
@@ -47,7 +45,7 @@ public class CommandParse {
 | 
			
		||||
                parse = new EnumParse(clazz);
 | 
			
		||||
            }
 | 
			
		||||
            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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Object[] parse(CommandArgument cmdArgs) {
 | 
			
		||||
        String args[] = cmdArgs.getArgs();
 | 
			
		||||
    public Object[] parse(CommandSender sender, String label, String[] args) {
 | 
			
		||||
        List<Object> pobjs = new LinkedList<>();
 | 
			
		||||
        pobjs.add(cmdArgs.getSender());
 | 
			
		||||
        pobjs.add(sender);
 | 
			
		||||
        for (int i = 0; i < parse.size(); i++) {
 | 
			
		||||
            try {
 | 
			
		||||
                Parse p = parse.get(i);
 | 
			
		||||
@@ -89,7 +86,7 @@ public class CommandParse {
 | 
			
		||||
                if (i + 1 == parse.size() && args.length >= parse.size()) {
 | 
			
		||||
                    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) {
 | 
			
		||||
                throw new ParseException(String.format("第 %s 个参数 ", isMain ? 1 : 2 + i) + e.getMessage());
 | 
			
		||||
            }
 | 
			
		||||
@@ -244,15 +241,31 @@ public class CommandParse {
 | 
			
		||||
 | 
			
		||||
        public Parse<RT> parseAnnotation(Annotation[] annotations) {
 | 
			
		||||
            for (Annotation annotation : annotations) {
 | 
			
		||||
                if (annotation.annotationType() == Default.class) {
 | 
			
		||||
                    def = ((Default) annotation).value();
 | 
			
		||||
                } else if (annotation.annotationType() == Limit.class) {
 | 
			
		||||
                    min = ((Limit) annotation).min();
 | 
			
		||||
                    max = ((Limit) annotation).max();
 | 
			
		||||
                } else if (annotation.annotationType() == KeyValue.class) {
 | 
			
		||||
                    KeyValue kv = (KeyValue) annotation;
 | 
			
		||||
                    attrs.put(kv.key(), kv.value());
 | 
			
		||||
                if (annotation.annotationType() == Option.class) {
 | 
			
		||||
                    String value = ((Option) annotation).value();
 | 
			
		||||
                    for (String str : value.split(" ")) {
 | 
			
		||||
                        if (str.isEmpty()) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (str.contains(":")) {
 | 
			
		||||
                            String[] args = str.split(":");
 | 
			
		||||
                            attrs.put(args[0], args[1]);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            attrs.put(str, null);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
@@ -285,8 +298,7 @@ public class CommandParse {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public Parse<Player> parseAnnotation(Annotation[] annotations) {
 | 
			
		||||
            super.parseAnnotation(annotations);
 | 
			
		||||
        public Parse<Player> handleAttrs() {
 | 
			
		||||
            check = attrs.containsKey("check");
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
@@ -311,8 +323,7 @@ public class CommandParse {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public Parse<String> parseAnnotation(Annotation[] annotations) {
 | 
			
		||||
            super.parseAnnotation(annotations);
 | 
			
		||||
        public Parse<String> handleAttrs() {
 | 
			
		||||
            if (attrs.containsKey("option")) {
 | 
			
		||||
                options = Arrays.asList(attrs.get("option").split(","));
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,12 @@
 | 
			
		||||
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.*;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.command.*;
 | 
			
		||||
import org.bukkit.command.Command;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import org.bukkit.command.PluginCommand;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
import pw.yumc.YumCore.bukkit.Log;
 | 
			
		||||
import pw.yumc.YumCore.bukkit.P;
 | 
			
		||||
import pw.yumc.YumCore.bukkit.compatible.C;
 | 
			
		||||
@@ -28,13 +21,16 @@ 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.Method;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 命令管理类
 | 
			
		||||
 *
 | 
			
		||||
 * @author 喵♂呜
 | 
			
		||||
 * @since 2016年7月23日 上午9:06:03
 | 
			
		||||
 */
 | 
			
		||||
public class CommandManager implements TabExecutor {
 | 
			
		||||
public class CommandSub implements TabExecutor {
 | 
			
		||||
    private static String argumentTypeError = "注解命令方法 %s 位于 %s 的参数错误 第一个参数应实现 CommandSender 接口!";
 | 
			
		||||
    private static String returnTypeError = "注解命令补全 %s 位于 %s 的返回值错误 应实现 List 接口!";
 | 
			
		||||
    private static String onlyExecutor = "§c当前命令仅允许 §b%s §c执行!";
 | 
			
		||||
@@ -42,32 +38,6 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
    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 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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 命令帮助
 | 
			
		||||
@@ -82,15 +52,15 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     */
 | 
			
		||||
    private ErrorHanlder commandErrorHanlder = new ErrorHanlder() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void error(CommandException e, CommandSender sender, CommandInfo info, CommandArgument args) {
 | 
			
		||||
        public void error(CommandException e, CommandSender sender, CommandInfo info, String label, String[] args) {
 | 
			
		||||
            if (e instanceof SenderException) {
 | 
			
		||||
                Log.toSender(sender, onlyExecutor, info.getExecutorStr());
 | 
			
		||||
                Log.sender(sender, onlyExecutor, info.getExecutorStr());
 | 
			
		||||
            } else if (e instanceof PermissionException) {
 | 
			
		||||
                Log.toSender(sender, losePerm, info.getCommand().permission());
 | 
			
		||||
                Log.sender(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());
 | 
			
		||||
                Log.sender(sender, cmdErr);
 | 
			
		||||
                Log.sender(sender, cmdUse, label, info.isDefault() ? "" : info.getName() + " ", info.getHelp().possibleArguments());
 | 
			
		||||
                Log.sender(sender, cmdDes, info.getHelp().value());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
@@ -125,7 +95,7 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     * @param executor
 | 
			
		||||
     *            命令执行类
 | 
			
		||||
     */
 | 
			
		||||
    public CommandManager(Executor... executor) {
 | 
			
		||||
    public CommandSub(Executor... executor) {
 | 
			
		||||
        register(executor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -135,15 +105,10 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     * @param name
 | 
			
		||||
     *            注册的命令
 | 
			
		||||
     */
 | 
			
		||||
    public CommandManager(String name) {
 | 
			
		||||
    public CommandSub(String name) {
 | 
			
		||||
        cmd = plugin.getCommand(name);
 | 
			
		||||
        if (cmd == null) {
 | 
			
		||||
            try {
 | 
			
		||||
                knownCommands.put(name, PluginCommandConstructor.newInstance(name, plugin));
 | 
			
		||||
                lookupNames.put(name, plugin);
 | 
			
		||||
            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ignored) {
 | 
			
		||||
            }
 | 
			
		||||
            if ((cmd = plugin.getCommand(name)) == null) { throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + name + " 命令!"); }
 | 
			
		||||
            if ((cmd = CommandKit.create(name, plugin)) == null) { throw new IllegalStateException("未找到命令 必须在plugin.yml先注册 " + name + " 命令!"); }
 | 
			
		||||
        }
 | 
			
		||||
        cmd.setExecutor(this);
 | 
			
		||||
        cmd.setTabCompleter(this);
 | 
			
		||||
@@ -157,7 +122,7 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     * @param executor
 | 
			
		||||
     *            命令执行类
 | 
			
		||||
     */
 | 
			
		||||
    public CommandManager(String name, Executor... executor) {
 | 
			
		||||
    public CommandSub(String name, Executor... executor) {
 | 
			
		||||
        this(name);
 | 
			
		||||
        register(executor);
 | 
			
		||||
    }
 | 
			
		||||
@@ -240,23 +205,22 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
    @Override
 | 
			
		||||
    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)); }
 | 
			
		||||
            if (defCmd != null) { return defCmd.execute(sender, label, args); }
 | 
			
		||||
            return help.send(sender, command, label, args);
 | 
			
		||||
        }
 | 
			
		||||
        String subcmd = args[0].toLowerCase();
 | 
			
		||||
        if (subcmd.equalsIgnoreCase("help")) { return help.send(sender, command, label, args); }
 | 
			
		||||
        CommandInfo cmd = getByCache(subcmd);
 | 
			
		||||
        CommandArgument arg;
 | 
			
		||||
        String[] subargs = args;
 | 
			
		||||
        if (cmd.equals(CommandInfo.Unknow) && defCmd != null) {
 | 
			
		||||
            cmd = defCmd;
 | 
			
		||||
            arg = new CommandArgument(sender, command, label, args);
 | 
			
		||||
        } else {
 | 
			
		||||
            arg = new CommandArgument(sender, command, label, moveStrings(args, 1));
 | 
			
		||||
            subargs = moveStrings(args, 1);
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            return cmd.execute(arg);
 | 
			
		||||
            return cmd.execute(sender, label, subargs);
 | 
			
		||||
        } catch (CommandException e) {
 | 
			
		||||
            commandErrorHanlder.error(e, sender, cmd, arg);
 | 
			
		||||
            commandErrorHanlder.error(e, sender, cmd, label, subargs);
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
@@ -269,7 +233,7 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
            StringUtil.copyPartialMatches(token, cmdNameCache, completions);
 | 
			
		||||
        }
 | 
			
		||||
        for (CommandTabInfo tab : tabs) {
 | 
			
		||||
            StringUtil.copyPartialMatches(token, tab.execute(sender, command, token, args), completions);
 | 
			
		||||
            StringUtil.copyPartialMatches(token, tab.execute(sender, token, args), completions);
 | 
			
		||||
        }
 | 
			
		||||
        StringUtil.copyPartialMatches(token, getPlayerTabComplete(sender, command, alias, args), completions);
 | 
			
		||||
        Collections.sort(completions, String.CASE_INSENSITIVE_ORDER);
 | 
			
		||||
@@ -281,9 +245,9 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     *
 | 
			
		||||
     * @param clazzs
 | 
			
		||||
     *            子命令处理类
 | 
			
		||||
     * @return {@link CommandManager}
 | 
			
		||||
     * @return {@link CommandSub}
 | 
			
		||||
     */
 | 
			
		||||
    public CommandManager register(Executor... clazzs) {
 | 
			
		||||
    public CommandSub register(Executor... clazzs) {
 | 
			
		||||
        for (Executor clazz : clazzs) {
 | 
			
		||||
            Method[] methods = clazz.getClass().getDeclaredMethods();
 | 
			
		||||
            for (Method method : methods) {
 | 
			
		||||
@@ -355,9 +319,9 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     * 
 | 
			
		||||
     * @param commandErrorHanlder
 | 
			
		||||
     *            命令错误处理器
 | 
			
		||||
     * @return {@link CommandManager}
 | 
			
		||||
     * @return {@link CommandSub}
 | 
			
		||||
     */
 | 
			
		||||
    public CommandManager setCommandErrorHanlder(ErrorHanlder commandErrorHanlder) {
 | 
			
		||||
    public CommandSub setCommandErrorHanlder(ErrorHanlder commandErrorHanlder) {
 | 
			
		||||
        this.commandErrorHanlder = commandErrorHanlder;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
@@ -367,9 +331,9 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     *
 | 
			
		||||
     * @param helpGenerator
 | 
			
		||||
     *            帮助生成器
 | 
			
		||||
     * @return {@link CommandManager}
 | 
			
		||||
     * @return {@link CommandSub}
 | 
			
		||||
     */
 | 
			
		||||
    public CommandManager setHelpGenerator(HelpGenerator helpGenerator) {
 | 
			
		||||
    public CommandSub setHelpGenerator(HelpGenerator helpGenerator) {
 | 
			
		||||
        help.setHelpGenerator(helpGenerator);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
@@ -379,9 +343,9 @@ public class CommandManager implements TabExecutor {
 | 
			
		||||
     *
 | 
			
		||||
     * @param helpParse
 | 
			
		||||
     *            帮助解析器
 | 
			
		||||
     * @return {@link CommandManager}
 | 
			
		||||
     * @return {@link CommandSub}
 | 
			
		||||
     */
 | 
			
		||||
    public CommandManager setHelpParse(HelpParse helpParse) {
 | 
			
		||||
    public CommandSub setHelpParse(HelpParse helpParse) {
 | 
			
		||||
        if (help.getHelpGenerator() instanceof CommandHelp.DefaultHelpGenerator) {
 | 
			
		||||
            ((CommandHelp.DefaultHelpGenerator) help.getHelpGenerator()).setHelpParse(helpParse);
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -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 "";
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
@@ -6,13 +6,13 @@ import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 默认参数
 | 
			
		||||
 * 扩展选项注解
 | 
			
		||||
 *
 | 
			
		||||
 * @since 2016年7月23日 上午9:00:27
 | 
			
		||||
 * @since 2016年7月23日 上午9:00:07
 | 
			
		||||
 * @author 喵♂呜
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.PARAMETER)
 | 
			
		||||
@Target(ElementType.METHOD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
public @interface Default {
 | 
			
		||||
public @interface Option {
 | 
			
		||||
    String value();
 | 
			
		||||
}
 | 
			
		||||
@@ -4,7 +4,6 @@ import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import pw.yumc.YumCore.bukkit.Log;
 | 
			
		||||
import pw.yumc.YumCore.bukkit.P;
 | 
			
		||||
import pw.yumc.YumCore.commands.CommandArgument;
 | 
			
		||||
import pw.yumc.YumCore.commands.CommandParse;
 | 
			
		||||
import pw.yumc.YumCore.commands.annotation.Async;
 | 
			
		||||
import pw.yumc.YumCore.commands.annotation.Cmd;
 | 
			
		||||
@@ -112,20 +111,24 @@ public class CommandInfo {
 | 
			
		||||
    /**
 | 
			
		||||
     * 执行命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param cmdArgs
 | 
			
		||||
     *            命令参数
 | 
			
		||||
     * @param sender
 | 
			
		||||
     *            命令发送者
 | 
			
		||||
     * @param label
 | 
			
		||||
     *            命令标签
 | 
			
		||||
     * @param args
 | 
			
		||||
     *            参数
 | 
			
		||||
     * @return 是否执行成功
 | 
			
		||||
     */
 | 
			
		||||
    public boolean execute(final CommandArgument cmdArgs) {
 | 
			
		||||
    public boolean execute(final CommandSender sender, final String label, final String[] args) {
 | 
			
		||||
        if (method == null) { return false; }
 | 
			
		||||
        check(cmdArgs);
 | 
			
		||||
        check(sender, label, args);
 | 
			
		||||
        Runnable runnable = new Runnable() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void run() {
 | 
			
		||||
                try {
 | 
			
		||||
                    method.invoke(origin, parse.parse(cmdArgs));
 | 
			
		||||
                    method.invoke(origin, parse.parse(sender, label, args));
 | 
			
		||||
                } catch (ParseException | ArgumentException e) {
 | 
			
		||||
                    Log.toSender(cmdArgs.getSender(), argErr, e.getMessage());
 | 
			
		||||
                    Log.sender(sender, argErr, e.getMessage());
 | 
			
		||||
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
 | 
			
		||||
                    throw new CommandException(e);
 | 
			
		||||
                }
 | 
			
		||||
@@ -160,6 +163,13 @@ public class CommandInfo {
 | 
			
		||||
        return name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return 命令别名
 | 
			
		||||
     */
 | 
			
		||||
    public List<String> getAliases() {
 | 
			
		||||
        return aliases;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return 命令排序
 | 
			
		||||
     */
 | 
			
		||||
@@ -212,11 +222,10 @@ public class CommandInfo {
 | 
			
		||||
        return Objects.hash(origin, method, name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void check(CommandArgument cmdArgs) {
 | 
			
		||||
        CommandSender sender = cmdArgs.getSender();
 | 
			
		||||
    private void check(CommandSender sender, String label, String[] args) {
 | 
			
		||||
        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())); }
 | 
			
		||||
        if (args.length < command.minimumArguments()) { throw new ArgumentException(String.valueOf(command.minimumArguments())); }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String eS(List<Executor> executors) {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@ package pw.yumc.YumCore.commands.info;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import pw.yumc.YumCore.bukkit.P;
 | 
			
		||||
import pw.yumc.YumCore.commands.CommandArgument;
 | 
			
		||||
import pw.yumc.YumCore.commands.annotation.Tab;
 | 
			
		||||
import pw.yumc.YumCore.commands.exception.CommandException;
 | 
			
		||||
 | 
			
		||||
@@ -47,8 +46,6 @@ public class CommandTabInfo {
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender
 | 
			
		||||
     *            发送者
 | 
			
		||||
     * @param command
 | 
			
		||||
     *            命令
 | 
			
		||||
     * @param label
 | 
			
		||||
     *            命令
 | 
			
		||||
     * @param args
 | 
			
		||||
@@ -56,10 +53,9 @@ public class CommandTabInfo {
 | 
			
		||||
     * @return Tab补全信息
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressWarnings("unchecked")
 | 
			
		||||
    public List<String> execute(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) {
 | 
			
		||||
        CommandArgument cmdArgs = new CommandArgument(sender, command, label, args);
 | 
			
		||||
    public List<String> execute(CommandSender sender, String label, String[] args) {
 | 
			
		||||
        try {
 | 
			
		||||
            return (List<String>) method.invoke(origin, cmdArgs);
 | 
			
		||||
            return (List<String>) method.invoke(origin, sender, label, args);
 | 
			
		||||
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
 | 
			
		||||
            throw new CommandException("调用Tab自动补全发生错误 请反馈给开发者 " + Arrays.toString(P.getDescription().getAuthors().toArray()) + " !", e);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@@ -12,5 +11,5 @@ import pw.yumc.YumCore.commands.info.CommandInfo;
 | 
			
		||||
 * @author 喵♂呜
 | 
			
		||||
 */
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
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.SimpleDateFormat;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
@@ -7,10 +11,6 @@ import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
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 {
 | 
			
		||||
    private static String DATE_PARSE_ERROR = "配置节点 {0} 日期解析失败 格式应该为: {1} 但输入值为: {2}!";
 | 
			
		||||
    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<>();
 | 
			
		||||
 | 
			
		||||
    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 ListParse() {
 | 
			
		||||
            allparse.put(List.class, this);
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,7 @@ public class I18N {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void send(CommandSender sender, String message, String def, Object... objs) {
 | 
			
		||||
        Log.toSender(sender, $(message, def), objs);
 | 
			
		||||
        Log.sender(sender, $(message, def), objs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ public class LogKit implements Runnable {
 | 
			
		||||
     *            日志
 | 
			
		||||
     */
 | 
			
		||||
    public void send(final CommandSender sender, final String s) {
 | 
			
		||||
        Log.toSender(sender, s);
 | 
			
		||||
        Log.sender(sender, s);
 | 
			
		||||
        log(ChatColor.stripColor(s));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user