From e954b10e8264f833e51f39126c0cd56986d14afb Mon Sep 17 00:00:00 2001 From: 502647092 Date: Mon, 18 Jul 2016 20:36:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E6=8B=A6=E6=88=AA=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 502647092 --- .../pw/yumc/Yum/commands/MonitorCommand.java | 31 ++- .../pw/yumc/Yum/inject/CommandInjector.java | 249 ++++++++++-------- .../pw/yumc/Yum/inject/ListenerInjector.java | 14 +- .../java/pw/yumc/Yum/inject/TaskInjector.java | 172 +++++++----- src/main/resources/config.yml | 5 +- src/main/resources/monitor.yml | 6 +- 6 files changed, 290 insertions(+), 187 deletions(-) diff --git a/src/main/java/pw/yumc/Yum/commands/MonitorCommand.java b/src/main/java/pw/yumc/Yum/commands/MonitorCommand.java index 7aed136..a828778 100644 --- a/src/main/java/pw/yumc/Yum/commands/MonitorCommand.java +++ b/src/main/java/pw/yumc/Yum/commands/MonitorCommand.java @@ -24,12 +24,14 @@ import cn.citycraft.PluginHelper.commands.HandlerCommands; import cn.citycraft.PluginHelper.commands.InvokeCommandEvent; import cn.citycraft.PluginHelper.commands.InvokeSubCommand; import cn.citycraft.PluginHelper.ext.kit.Reflect; +import cn.citycraft.PluginHelper.kit.PluginKit; import cn.citycraft.PluginHelper.kit.StrKit; import pw.yumc.Yum.Yum; import pw.yumc.Yum.api.YumAPI; import pw.yumc.Yum.inject.CommandInjector; import pw.yumc.Yum.inject.ListenerInjector; import pw.yumc.Yum.inject.TaskInjector; +import pw.yumc.Yum.managers.ConfigManager; /** * @@ -37,26 +39,35 @@ import pw.yumc.Yum.inject.TaskInjector; * @author 喵♂呜 */ public class MonitorCommand implements HandlerCommands { + public static boolean debug = false; + public static Throwable lastError = null; + private final String prefix = "§6[§bYum §a能耗监控§6] "; + private final String total = "§6总耗时: §a%.2f毫秒 "; private final String count = "§6执行次数: §b%s次 "; private final String avg = "§6平均耗时: §d%.5f毫秒!"; private final String avg_warn = "§6平均耗时: §c%.5f毫秒!"; - private final String p_n_f = prefix + "§c插件 §b%s §c不存在!"; private final String injected = "§a插件 §b%s §a成功注入能耗监控器!"; private final String uninjected = "§a插件 §b%s §a成功撤销能耗监控器!"; private final String notEnable = "§c插件 §b%s §c未成功加载 无法执行注入!"; + private final String no_error = prefix + "§a自服务器启动以来尚未发现报错!"; + private final String last_error = prefix + "§c最后一次错误异常由 §b%s §c造成 详细如下:"; + + private final String p_n_f = prefix + "§c插件 §b%s §c不存在!"; + private final double um = 1000000.0; public MonitorCommand(final Yum yum) { final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "monitor"); cmdhandler.registerCommands(this); cmdhandler.registerCommands(PluginTabComplete.instence); + debug = ConfigManager.i().isMonitorDebug(); } - @HandlerCommand(name = "cmd", description = "查看插件命令能耗", minimumArguments = 1, possibleArguments = "[插件名称]") + @HandlerCommand(name = "cmd", aliases = "c", description = "查看插件命令能耗", minimumArguments = 1, possibleArguments = "[插件名称]") public void cmd(final InvokeCommandEvent e) { final String pname = e.getArgs()[0]; final CommandSender sender = e.getSender(); @@ -93,7 +104,7 @@ public class MonitorCommand implements HandlerCommands { } } - @HandlerCommand(name = "event", description = "查看插件事件能耗", minimumArguments = 1, possibleArguments = "[插件名称]") + @HandlerCommand(name = "event", aliases = "e", description = "查看插件事件能耗", minimumArguments = 1, possibleArguments = "[插件名称]") public void event(final InvokeCommandEvent e) throws InstantiationException, IllegalAccessException { final String pname = e.getArgs()[0]; final CommandSender sender = e.getSender(); @@ -157,6 +168,20 @@ public class MonitorCommand implements HandlerCommands { } } + @HandlerCommand(name = "lasterror", aliases = "la", description = "查看最后一次报错") + public void lasterror(final InvokeCommandEvent e) { + final CommandSender sender = e.getSender(); + if (lastError == null) { + sender.sendMessage(no_error); + return; + } + final Plugin plugin = PluginKit.getOperatePlugin(lastError.getStackTrace()); + if (plugin != null) { + sender.sendMessage(String.format(last_error, plugin.getName())); + lastError.printStackTrace(); + } + } + @HandlerCommand(name = "task", description = "查看插件任务能耗", minimumArguments = 1, possibleArguments = "[插件名称]") public void task(final InvokeCommandEvent e) { final String pname = e.getArgs()[0]; diff --git a/src/main/java/pw/yumc/Yum/inject/CommandInjector.java b/src/main/java/pw/yumc/Yum/inject/CommandInjector.java index 82ce6d8..4c13c05 100644 --- a/src/main/java/pw/yumc/Yum/inject/CommandInjector.java +++ b/src/main/java/pw/yumc/Yum/inject/CommandInjector.java @@ -1,109 +1,140 @@ -package pw.yumc.Yum.inject; - -import java.util.Collections; -import java.util.List; - -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.PluginCommand; -import org.bukkit.command.SimpleCommandMap; -import org.bukkit.command.TabCompleter; -import org.bukkit.command.TabExecutor; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginManager; - -import cn.citycraft.PluginHelper.ext.kit.Reflect; - -public class CommandInjector implements TabExecutor { - - private final CommandExecutor originalExecutor; - private final TabCompleter originalCompleter; - - public long totalTime; - public int count; - - public CommandInjector(final CommandExecutor originalCommandExecutor, final TabCompleter originalTabCompleter) { - this.originalExecutor = originalCommandExecutor; - this.originalCompleter = originalTabCompleter; - } - - public static void inject(final Plugin toInjectPlugin) { - final PluginManager pluginManager = Bukkit.getPluginManager(); - final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); - for (final Command command : commandMap.getCommands()) { - if (command instanceof PluginCommand) { - final PluginCommand pluginCommand = (PluginCommand) command; - final Plugin plugin = pluginCommand.getPlugin(); - if (plugin.equals(toInjectPlugin)) { - final CommandExecutor executor = Reflect.on(command).get("executor"); - if (executor instanceof CommandInjector) { - return; - } - final TabCompleter completer = Reflect.on(command).get("completer"); - final CommandInjector commandInjector = new CommandInjector(executor, completer); - Reflect.on(command).set("executor", commandInjector); - Reflect.on(command).set("completer", commandInjector); - } - } - } - } - - public static void uninject(final Plugin toUninject) { - final PluginManager pluginManager = Bukkit.getPluginManager(); - final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); - for (final Command command : commandMap.getCommands()) { - if (command instanceof PluginCommand) { - final PluginCommand pluginCommand = (PluginCommand) command; - final Plugin plugin = pluginCommand.getPlugin(); - if (plugin.equals(toUninject)) { - final CommandExecutor executor = Reflect.on(command).get("executor"); - if (executor instanceof CommandInjector) { - final CommandInjector injected = (CommandInjector) executor; - Reflect.on(command).set("executor", injected.getOriginalExecutor()); - } - final TabCompleter completer = Reflect.on(command).get("completer"); - if (completer instanceof CommandInjector) { - final CommandInjector injected = (CommandInjector) completer; - Reflect.on(command).set("completer", injected.getOriginalCompleter()); - } - } - } - } - } - - public TabCompleter getOriginalCompleter() { - return originalCompleter; - } - - public CommandExecutor getOriginalExecutor() { - return originalExecutor; - } - - @Override - public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) { - final long start = System.nanoTime(); - // TODO 当操作大于10ms的时候添加一个Lag提示 - final boolean result = originalExecutor.onCommand(sender, command, label, args); - final long end = System.nanoTime(); - totalTime += end - start; - count++; - return result; - } - - @Override - public List onTabComplete(final CommandSender sender, final Command command, final String alias, final String[] args) { - if (originalCompleter == null) { - return Collections.emptyList(); - } - final long start = System.nanoTime(); - // TODO add a more aggressive 10 ms cpu sample - final List result = originalCompleter.onTabComplete(sender, command, alias, args); - final long end = System.nanoTime(); - - totalTime += end - start; - count++; - return result; - } -} +package pw.yumc.Yum.inject; + +import java.util.Collections; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.SimpleCommandMap; +import org.bukkit.command.TabCompleter; +import org.bukkit.command.TabExecutor; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; + +import cn.citycraft.PluginHelper.ext.kit.Reflect; +import cn.citycraft.PluginHelper.kit.PluginKit; +import cn.citycraft.PluginHelper.kit.StrKit; +import pw.yumc.Yum.commands.MonitorCommand; + +public class CommandInjector implements TabExecutor { + private final String prefix = "§6[§bYum §a命令监控§6] "; + private final CommandExecutor originalExecutor; + private final TabCompleter originalCompleter; + + private final Plugin plugin; + + public long totalTime; + public int count; + + public CommandInjector(final CommandExecutor originalCommandExecutor, final TabCompleter originalTabCompleter, final Plugin plugin) { + this.originalExecutor = originalCommandExecutor; + this.originalCompleter = originalTabCompleter; + this.plugin = plugin; + } + + public static void inject(final Plugin toInjectPlugin) { + final PluginManager pluginManager = Bukkit.getPluginManager(); + final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); + for (final Command command : commandMap.getCommands()) { + if (command instanceof PluginCommand) { + final PluginCommand pluginCommand = (PluginCommand) command; + final Plugin plugin = pluginCommand.getPlugin(); + if (plugin.equals(toInjectPlugin)) { + final CommandExecutor executor = Reflect.on(command).get("executor"); + if (executor instanceof CommandInjector) { + return; + } + final TabCompleter completer = Reflect.on(command).get("completer"); + final CommandInjector commandInjector = new CommandInjector(executor, completer, toInjectPlugin); + Reflect.on(command).set("executor", commandInjector); + Reflect.on(command).set("completer", commandInjector); + } + } + } + } + + public static void uninject(final Plugin toUninject) { + final PluginManager pluginManager = Bukkit.getPluginManager(); + final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); + for (final Command command : commandMap.getCommands()) { + if (command instanceof PluginCommand) { + final PluginCommand pluginCommand = (PluginCommand) command; + final Plugin plugin = pluginCommand.getPlugin(); + if (plugin.equals(toUninject)) { + final CommandExecutor executor = Reflect.on(command).get("executor"); + if (executor instanceof CommandInjector) { + final CommandInjector injected = (CommandInjector) executor; + Reflect.on(command).set("executor", injected.getOriginalExecutor()); + } + final TabCompleter completer = Reflect.on(command).get("completer"); + if (completer instanceof CommandInjector) { + final CommandInjector injected = (CommandInjector) completer; + Reflect.on(command).set("completer", injected.getOriginalCompleter()); + } + } + } + } + } + + public TabCompleter getOriginalCompleter() { + return originalCompleter; + } + + public CommandExecutor getOriginalExecutor() { + return originalExecutor; + } + + @Override + public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) { + try { + final long start = System.nanoTime(); + // TODO 当操作大于10ms的时候添加一个Lag提示 + final boolean result = originalExecutor.onCommand(sender, command, label, args); + final long end = System.nanoTime(); + final long lag = end - start; + if (Bukkit.isPrimaryThread() && lag / 1000000 > 10) { + PluginKit.sc("§6[§bYum §a能耗监控§6] §c注意! §6插件 §b" + plugin.getName() + " §6执行 §d" + label + " " + StrKit.join(args, " ") + " §6命令 §c耗时 §4" + lag / 1000000 + "ms!"); + } + totalTime += lag; + count++; + return result; + } catch (Throwable e) { + while (e.getCause() != null) { + e = e.getCause(); + } + MonitorCommand.lastError = e; + PluginKit.sc(prefix + "§6插件 §b" + plugin.getName() + " §6执行 §d" + label + " §6命令时发生异常!"); + PluginKit.sc("§6异常名称: §c" + e.getClass().getName()); + PluginKit.sc("§6异常说明: §3" + e.getMessage()); + PluginKit.sc("§6简易错误信息如下:"); + final int l = e.getStackTrace().length > 5 ? 5 : e.getStackTrace().length; + for (int i = 0; i < l; i++) { + final StackTraceElement ste = e.getStackTrace()[i]; + PluginKit.sc(" §e位于 §c" + ste.getClassName() + "." + ste.getMethodName() + "(§4" + ste.getFileName() + ":" + ste.getLineNumber() + "§c)"); + } + if (MonitorCommand.debug) { + PluginKit.sc("§c开发人员调试信息如下:"); + e.printStackTrace(); + } + } + return false; + } + + @Override + public List onTabComplete(final CommandSender sender, final Command command, final String alias, final String[] args) { + if (originalCompleter == null) { + return Collections.emptyList(); + } + final long start = System.nanoTime(); + // TODO add a more aggressive 10 ms cpu sample + final List result = originalCompleter.onTabComplete(sender, command, alias, args); + final long end = System.nanoTime(); + + totalTime += end - start; + count++; + return result; + } +} diff --git a/src/main/java/pw/yumc/Yum/inject/ListenerInjector.java b/src/main/java/pw/yumc/Yum/inject/ListenerInjector.java index 3b5ed78..206f847 100644 --- a/src/main/java/pw/yumc/Yum/inject/ListenerInjector.java +++ b/src/main/java/pw/yumc/Yum/inject/ListenerInjector.java @@ -15,6 +15,7 @@ import org.bukkit.plugin.TimedRegisteredListener; import cn.citycraft.PluginHelper.ext.kit.Reflect; import cn.citycraft.PluginHelper.kit.PluginKit; +import pw.yumc.Yum.commands.MonitorCommand; import pw.yumc.Yum.managers.ConfigManager; public class ListenerInjector implements EventExecutor { @@ -72,7 +73,7 @@ public class ListenerInjector implements EventExecutor { final String en = event.getEventName(); final long lag = end - start; if (lag / 1000000 > 10 && !ConfigManager.i().getMonitorIgnoreList().contains(plugin.getName())) { - PluginKit.sc("§6[§bYum §a能耗监控§6] §c注意! §6插件 §b" + plugin.getName() + " §6处理 §d" + event.getEventName() + " §6事件时§c耗时 §4" + lag / 1000000 + "ms!"); + PluginKit.sc("§6[§bYum §a能耗监控§6] §c注意! §6插件 §b" + plugin.getName() + " §6处理 §d" + event.getEventName() + " §6事件 §c耗时 §4" + lag / 1000000 + "ms!"); } if (eventTotalTime.containsKey(en)) { eventTotalTime.put(en, eventTotalTime.get(en) + lag); @@ -88,13 +89,20 @@ public class ListenerInjector implements EventExecutor { while (e.getCause() != null) { e = e.getCause(); } - PluginKit.sc(prefix + "§6插件 §b" + plugin.getName() + " §6处理 §d" + event.getEventName() + " §6事件时发生异常 §c" + e.getClass().getName() + ": " + e.getMessage()); - PluginKit.sc("§c错误信息如下:"); + MonitorCommand.lastError = e; + PluginKit.sc(prefix + "§6插件 §b" + plugin.getName() + " §6处理 §d" + event.getEventName() + " §6事件时发生异常!"); + PluginKit.sc("§6异常名称: §c" + e.getClass().getName()); + PluginKit.sc("§6异常说明: §3" + e.getMessage()); + PluginKit.sc("§6简易错误信息如下:"); final int l = e.getStackTrace().length > 5 ? 5 : e.getStackTrace().length; for (int i = 0; i < l; i++) { final StackTraceElement ste = e.getStackTrace()[i]; PluginKit.sc(" §e位于 §c" + ste.getClassName() + "." + ste.getMethodName() + "(§4" + ste.getFileName() + ":" + ste.getLineNumber() + "§c)"); } + if (MonitorCommand.debug) { + PluginKit.sc("§c开发人员调试信息如下:"); + e.printStackTrace(); + } } } diff --git a/src/main/java/pw/yumc/Yum/inject/TaskInjector.java b/src/main/java/pw/yumc/Yum/inject/TaskInjector.java index 229ef9c..cfc13d4 100644 --- a/src/main/java/pw/yumc/Yum/inject/TaskInjector.java +++ b/src/main/java/pw/yumc/Yum/inject/TaskInjector.java @@ -1,68 +1,104 @@ -package pw.yumc.Yum.inject; - -import java.util.List; - -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitScheduler; -import org.bukkit.scheduler.BukkitTask; - -import cn.citycraft.PluginHelper.ext.kit.Reflect; - -public class TaskInjector implements Runnable { - - private final Runnable originalTask; - - public long totalTime; - public int count; - - public TaskInjector(final Runnable originalTask) { - this.originalTask = originalTask; - } - - // 当前注入只能对TimerTask有效 - // 对于单次执行的任务 我们需要注册一个动态的代理 - public static void inject(final Plugin plugin) { - final BukkitScheduler scheduler = Bukkit.getScheduler(); - final List pendingTasks = scheduler.getPendingTasks(); - for (final BukkitTask pendingTask : pendingTasks) { - // 忽略异步任务 - if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { - final Runnable originalTask = Reflect.on(pendingTask).get("task"); - if (originalTask instanceof TaskInjector) { - return; - } - final TaskInjector taskInjector = new TaskInjector(originalTask); - Reflect.on(pendingTask).set("task", taskInjector); - } - } - } - - public static void uninject(final Plugin plugin) { - final BukkitScheduler scheduler = Bukkit.getScheduler(); - final List pendingTasks = scheduler.getPendingTasks(); - for (final BukkitTask pendingTask : pendingTasks) { - // 忽略异步任务 - if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { - final Runnable originalTask = Reflect.on(pendingTask).get("task"); - if (originalTask instanceof TaskInjector) { - Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask()); - } - } - } - } - - public Runnable getOriginalTask() { - return originalTask; - } - - @Override - public void run() { - final long start = System.nanoTime(); - // TODO 当操作大于10ms的时候添加一个Lag提示 - originalTask.run(); - final long end = System.nanoTime(); - totalTime += end - start; - count++; - } -} +package pw.yumc.Yum.inject; + +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.scheduler.BukkitTask; + +import cn.citycraft.PluginHelper.ext.kit.Reflect; +import cn.citycraft.PluginHelper.kit.PluginKit; +import cn.citycraft.PluginHelper.kit.StrKit; +import pw.yumc.Yum.commands.MonitorCommand; + +public class TaskInjector implements Runnable { + private final String prefix = "§6[§bYum §a任务监控§6] "; + + private final Runnable originalTask; + private final Plugin plugin; + + private final String taskName; + + public long totalTime; + public int count; + + public TaskInjector(final Runnable originalTask, final Plugin plugin) { + this.originalTask = originalTask; + this.plugin = plugin; + final Class taskClass = getOriginalTask().getClass(); + taskName = StrKit.isBlank(taskClass.getSimpleName()) ? taskClass.getName() : taskClass.getSimpleName(); + } + + // 当前注入只能对TimerTask有效 + // 对于单次执行的任务 我们需要注册一个动态的代理 + public static void inject(final Plugin plugin) { + final BukkitScheduler scheduler = Bukkit.getScheduler(); + final List pendingTasks = scheduler.getPendingTasks(); + for (final BukkitTask pendingTask : pendingTasks) { + // 忽略异步任务 + if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { + final Runnable originalTask = Reflect.on(pendingTask).get("task"); + if (originalTask instanceof TaskInjector) { + return; + } + final TaskInjector taskInjector = new TaskInjector(originalTask, plugin); + Reflect.on(pendingTask).set("task", taskInjector); + } + } + } + + public static void uninject(final Plugin plugin) { + final BukkitScheduler scheduler = Bukkit.getScheduler(); + final List pendingTasks = scheduler.getPendingTasks(); + for (final BukkitTask pendingTask : pendingTasks) { + // 忽略异步任务 + if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { + final Runnable originalTask = Reflect.on(pendingTask).get("task"); + if (originalTask instanceof TaskInjector) { + Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask()); + } + } + } + } + + public Runnable getOriginalTask() { + return originalTask; + } + + @Override + public void run() { + + try { + final long start = System.nanoTime(); + // TODO 当操作大于10ms的时候添加一个Lag提示 + originalTask.run(); + final long end = System.nanoTime(); + final long lag = end - start; + if (Bukkit.isPrimaryThread() && lag / 1000000 > 10) { + PluginKit.sc("§6[§bYum §a能耗监控§6] §c注意! §6插件 §b" + plugin.getName() + " §6执行 §d" + taskName + " §6任务 §c耗时 §4" + lag / 1000000 + "ms!"); + } + totalTime += lag; + count++; + } catch (Throwable e) { + while (e.getCause() != null) { + e = e.getCause(); + } + MonitorCommand.lastError = e; + PluginKit.sc(prefix + "§6插件 §b" + plugin.getName() + " §6执行 §d" + taskName + " §6任务时发生异常!"); + PluginKit.sc("§6异常名称: §c" + e.getClass().getName()); + PluginKit.sc("§6异常说明: §3" + e.getMessage()); + PluginKit.sc("§6简易错误信息如下:"); + final int l = e.getStackTrace().length > 5 ? 5 : e.getStackTrace().length; + for (int i = 0; i < l; i++) { + final StackTraceElement ste = e.getStackTrace()[i]; + PluginKit.sc(" §e位于 §c" + ste.getClassName() + "." + ste.getMethodName() + "(§4" + ste.getFileName() + ":" + ste.getLineNumber() + "§c)"); + } + if (MonitorCommand.debug) { + PluginKit.sc("§c开发人员调试信息如下:"); + e.printStackTrace(); + } + } + + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 151cb95..f5cfef4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -3,14 +3,14 @@ ############################ #配置版本号 请勿修改!!! -Version: 2.2 +Version: 2.3 #是否只允许控制台执行插件仓库命令 onlyCommandConsole: false #是否只允许控制台执行插件网络管理命令 onlyNetCommandConsole: false #是否只允许控制台执行插件文件管理命令 -onlyFileCommandConsole: true +onlyFileCommandConsole: false #禁止rm -rf的文件夹列表 blacklist: - 'plugins' @@ -22,3 +22,4 @@ ignorelist: - 'iConomy' - 'GroupManager' - 'PermissionsEx' +- 'Essentials' \ No newline at end of file diff --git a/src/main/resources/monitor.yml b/src/main/resources/monitor.yml index f030dc9..ef784c3 100644 --- a/src/main/resources/monitor.yml +++ b/src/main/resources/monitor.yml @@ -3,10 +3,12 @@ ############################ #配置版本号 请勿修改!!! -Version: 1.1 +Version: 1.2 #是否开启 Enable: true +#是否显示开发人员信息 +Debug: false #忽略检测列表 Ignore: -- Essentials \ No newline at end of file +- PluginHelper \ No newline at end of file