feat: 添加监控异常拦截处理

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-07-18 20:36:56 +08:00
parent ce4e6650d7
commit e954b10e82
6 changed files with 290 additions and 187 deletions

View File

@ -24,12 +24,14 @@ import cn.citycraft.PluginHelper.commands.HandlerCommands;
import cn.citycraft.PluginHelper.commands.InvokeCommandEvent; import cn.citycraft.PluginHelper.commands.InvokeCommandEvent;
import cn.citycraft.PluginHelper.commands.InvokeSubCommand; import cn.citycraft.PluginHelper.commands.InvokeSubCommand;
import cn.citycraft.PluginHelper.ext.kit.Reflect; import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit;
import cn.citycraft.PluginHelper.kit.StrKit; import cn.citycraft.PluginHelper.kit.StrKit;
import pw.yumc.Yum.Yum; import pw.yumc.Yum.Yum;
import pw.yumc.Yum.api.YumAPI; import pw.yumc.Yum.api.YumAPI;
import pw.yumc.Yum.inject.CommandInjector; import pw.yumc.Yum.inject.CommandInjector;
import pw.yumc.Yum.inject.ListenerInjector; import pw.yumc.Yum.inject.ListenerInjector;
import pw.yumc.Yum.inject.TaskInjector; import pw.yumc.Yum.inject.TaskInjector;
import pw.yumc.Yum.managers.ConfigManager;
/** /**
* *
@ -37,26 +39,35 @@ import pw.yumc.Yum.inject.TaskInjector;
* @author * @author
*/ */
public class MonitorCommand implements HandlerCommands { 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 prefix = "§6[§bYum §a能耗监控§6] ";
private final String total = "§6总耗时: §a%.2f毫秒 "; private final String total = "§6总耗时: §a%.2f毫秒 ";
private final String count = "§6执行次数: §b%s次 "; private final String count = "§6执行次数: §b%s次 ";
private final String avg = "§6平均耗时: §d%.5f毫秒!"; private final String avg = "§6平均耗时: §d%.5f毫秒!";
private final String avg_warn = "§6平均耗时: §c%.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 injected = "§a插件 §b%s §a成功注入能耗监控器!";
private final String uninjected = "§a插件 §b%s §a成功撤销能耗监控器!"; private final String uninjected = "§a插件 §b%s §a成功撤销能耗监控器!";
private final String notEnable = "§c插件 §b%s §c未成功加载 无法执行注入!"; 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; private final double um = 1000000.0;
public MonitorCommand(final Yum yum) { public MonitorCommand(final Yum yum) {
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "monitor"); final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "monitor");
cmdhandler.registerCommands(this); cmdhandler.registerCommands(this);
cmdhandler.registerCommands(PluginTabComplete.instence); 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) { public void cmd(final InvokeCommandEvent e) {
final String pname = e.getArgs()[0]; final String pname = e.getArgs()[0];
final CommandSender sender = e.getSender(); 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 { public void event(final InvokeCommandEvent e) throws InstantiationException, IllegalAccessException {
final String pname = e.getArgs()[0]; final String pname = e.getArgs()[0];
final CommandSender sender = e.getSender(); 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 = "[插件名称]") @HandlerCommand(name = "task", description = "查看插件任务能耗", minimumArguments = 1, possibleArguments = "[插件名称]")
public void task(final InvokeCommandEvent e) { public void task(final InvokeCommandEvent e) {
final String pname = e.getArgs()[0]; final String pname = e.getArgs()[0];

View File

@ -1,109 +1,140 @@
package pw.yumc.Yum.inject; package pw.yumc.Yum.inject;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.command.SimpleCommandMap; import org.bukkit.command.SimpleCommandMap;
import org.bukkit.command.TabCompleter; import org.bukkit.command.TabCompleter;
import org.bukkit.command.TabExecutor; import org.bukkit.command.TabExecutor;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import cn.citycraft.PluginHelper.ext.kit.Reflect; import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit;
public class CommandInjector implements TabExecutor { import cn.citycraft.PluginHelper.kit.StrKit;
import pw.yumc.Yum.commands.MonitorCommand;
private final CommandExecutor originalExecutor;
private final TabCompleter originalCompleter; public class CommandInjector implements TabExecutor {
private final String prefix = "§6[§bYum §a命令监控§6] ";
public long totalTime; private final CommandExecutor originalExecutor;
public int count; private final TabCompleter originalCompleter;
public CommandInjector(final CommandExecutor originalCommandExecutor, final TabCompleter originalTabCompleter) { private final Plugin plugin;
this.originalExecutor = originalCommandExecutor;
this.originalCompleter = originalTabCompleter; public long totalTime;
} public int count;
public static void inject(final Plugin toInjectPlugin) { public CommandInjector(final CommandExecutor originalCommandExecutor, final TabCompleter originalTabCompleter, final Plugin plugin) {
final PluginManager pluginManager = Bukkit.getPluginManager(); this.originalExecutor = originalCommandExecutor;
final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); this.originalCompleter = originalTabCompleter;
for (final Command command : commandMap.getCommands()) { this.plugin = plugin;
if (command instanceof PluginCommand) { }
final PluginCommand pluginCommand = (PluginCommand) command;
final Plugin plugin = pluginCommand.getPlugin(); public static void inject(final Plugin toInjectPlugin) {
if (plugin.equals(toInjectPlugin)) { final PluginManager pluginManager = Bukkit.getPluginManager();
final CommandExecutor executor = Reflect.on(command).get("executor"); final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap");
if (executor instanceof CommandInjector) { for (final Command command : commandMap.getCommands()) {
return; if (command instanceof PluginCommand) {
} final PluginCommand pluginCommand = (PluginCommand) command;
final TabCompleter completer = Reflect.on(command).get("completer"); final Plugin plugin = pluginCommand.getPlugin();
final CommandInjector commandInjector = new CommandInjector(executor, completer); if (plugin.equals(toInjectPlugin)) {
Reflect.on(command).set("executor", commandInjector); final CommandExecutor executor = Reflect.on(command).get("executor");
Reflect.on(command).set("completer", commandInjector); 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);
public static void uninject(final Plugin toUninject) { Reflect.on(command).set("completer", commandInjector);
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(); public static void uninject(final Plugin toUninject) {
if (plugin.equals(toUninject)) { final PluginManager pluginManager = Bukkit.getPluginManager();
final CommandExecutor executor = Reflect.on(command).get("executor"); final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap");
if (executor instanceof CommandInjector) { for (final Command command : commandMap.getCommands()) {
final CommandInjector injected = (CommandInjector) executor; if (command instanceof PluginCommand) {
Reflect.on(command).set("executor", injected.getOriginalExecutor()); final PluginCommand pluginCommand = (PluginCommand) command;
} final Plugin plugin = pluginCommand.getPlugin();
final TabCompleter completer = Reflect.on(command).get("completer"); if (plugin.equals(toUninject)) {
if (completer instanceof CommandInjector) { final CommandExecutor executor = Reflect.on(command).get("executor");
final CommandInjector injected = (CommandInjector) completer; if (executor instanceof CommandInjector) {
Reflect.on(command).set("completer", injected.getOriginalCompleter()); 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;
} public TabCompleter getOriginalCompleter() {
return originalCompleter;
@Override }
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
final long start = System.nanoTime(); public CommandExecutor getOriginalExecutor() {
// TODO 当操作大于10ms的时候添加一个Lag提示 return originalExecutor;
final boolean result = originalExecutor.onCommand(sender, command, label, args); }
final long end = System.nanoTime();
totalTime += end - start; @Override
count++; public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
return result; try {
} final long start = System.nanoTime();
// TODO 当操作大于10ms的时候添加一个Lag提示
@Override final boolean result = originalExecutor.onCommand(sender, command, label, args);
public List<String> onTabComplete(final CommandSender sender, final Command command, final String alias, final String[] args) { final long end = System.nanoTime();
if (originalCompleter == null) { final long lag = end - start;
return Collections.emptyList(); 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!");
final long start = System.nanoTime(); }
// TODO add a more aggressive 10 ms cpu sample totalTime += lag;
final List<String> result = originalCompleter.onTabComplete(sender, command, alias, args); count++;
final long end = System.nanoTime(); return result;
} catch (Throwable e) {
totalTime += end - start; while (e.getCause() != null) {
count++; e = e.getCause();
return result; }
} 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<String> 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<String> result = originalCompleter.onTabComplete(sender, command, alias, args);
final long end = System.nanoTime();
totalTime += end - start;
count++;
return result;
}
}

View File

@ -15,6 +15,7 @@ import org.bukkit.plugin.TimedRegisteredListener;
import cn.citycraft.PluginHelper.ext.kit.Reflect; import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit; import cn.citycraft.PluginHelper.kit.PluginKit;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.ConfigManager; import pw.yumc.Yum.managers.ConfigManager;
public class ListenerInjector implements EventExecutor { public class ListenerInjector implements EventExecutor {
@ -72,7 +73,7 @@ public class ListenerInjector implements EventExecutor {
final String en = event.getEventName(); final String en = event.getEventName();
final long lag = end - start; final long lag = end - start;
if (lag / 1000000 > 10 && !ConfigManager.i().getMonitorIgnoreList().contains(plugin.getName())) { 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)) { if (eventTotalTime.containsKey(en)) {
eventTotalTime.put(en, eventTotalTime.get(en) + lag); eventTotalTime.put(en, eventTotalTime.get(en) + lag);
@ -88,13 +89,20 @@ public class ListenerInjector implements EventExecutor {
while (e.getCause() != null) { while (e.getCause() != null) {
e = e.getCause(); e = e.getCause();
} }
PluginKit.sc(prefix + "§6插件 §b" + plugin.getName() + " §6处理 §d" + event.getEventName() + " §6事件时发生异常 §c" + e.getClass().getName() + ": " + e.getMessage()); MonitorCommand.lastError = e;
PluginKit.sc("§c错误信息如下:"); 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; final int l = e.getStackTrace().length > 5 ? 5 : e.getStackTrace().length;
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
final StackTraceElement ste = e.getStackTrace()[i]; final StackTraceElement ste = e.getStackTrace()[i];
PluginKit.sc(" §e位于 §c" + ste.getClassName() + "." + ste.getMethodName() + "(§4" + ste.getFileName() + ":" + ste.getLineNumber() + "§c)"); PluginKit.sc(" §e位于 §c" + ste.getClassName() + "." + ste.getMethodName() + "(§4" + ste.getFileName() + ":" + ste.getLineNumber() + "§c)");
} }
if (MonitorCommand.debug) {
PluginKit.sc("§c开发人员调试信息如下:");
e.printStackTrace();
}
} }
} }

View File

@ -1,68 +1,104 @@
package pw.yumc.Yum.inject; package pw.yumc.Yum.inject;
import java.util.List; import java.util.List;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import cn.citycraft.PluginHelper.ext.kit.Reflect; import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit;
public class TaskInjector implements Runnable { import cn.citycraft.PluginHelper.kit.StrKit;
import pw.yumc.Yum.commands.MonitorCommand;
private final Runnable originalTask;
public class TaskInjector implements Runnable {
public long totalTime; private final String prefix = "§6[§bYum §a任务监控§6] ";
public int count;
private final Runnable originalTask;
public TaskInjector(final Runnable originalTask) { private final Plugin plugin;
this.originalTask = originalTask;
} private final String taskName;
// 当前注入只能对TimerTask有效 public long totalTime;
// 对于单次执行的任务 我们需要注册一个动态的代理 public int count;
public static void inject(final Plugin plugin) {
final BukkitScheduler scheduler = Bukkit.getScheduler(); public TaskInjector(final Runnable originalTask, final Plugin plugin) {
final List<BukkitTask> pendingTasks = scheduler.getPendingTasks(); this.originalTask = originalTask;
for (final BukkitTask pendingTask : pendingTasks) { this.plugin = plugin;
// 忽略异步任务 final Class<? extends Runnable> taskClass = getOriginalTask().getClass();
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { taskName = StrKit.isBlank(taskClass.getSimpleName()) ? taskClass.getName() : taskClass.getSimpleName();
final Runnable originalTask = Reflect.on(pendingTask).get("task"); }
if (originalTask instanceof TaskInjector) {
return; // 当前注入只能对TimerTask有效
} // 对于单次执行的任务 我们需要注册一个动态的代理
final TaskInjector taskInjector = new TaskInjector(originalTask); public static void inject(final Plugin plugin) {
Reflect.on(pendingTask).set("task", taskInjector); final BukkitScheduler scheduler = Bukkit.getScheduler();
} final List<BukkitTask> pendingTasks = scheduler.getPendingTasks();
} for (final BukkitTask pendingTask : pendingTasks) {
} // 忽略异步任务
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
public static void uninject(final Plugin plugin) { final Runnable originalTask = Reflect.on(pendingTask).get("task");
final BukkitScheduler scheduler = Bukkit.getScheduler(); if (originalTask instanceof TaskInjector) {
final List<BukkitTask> pendingTasks = scheduler.getPendingTasks(); return;
for (final BukkitTask pendingTask : pendingTasks) { }
// 忽略异步任务 final TaskInjector taskInjector = new TaskInjector(originalTask, plugin);
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { Reflect.on(pendingTask).set("task", taskInjector);
final Runnable originalTask = Reflect.on(pendingTask).get("task"); }
if (originalTask instanceof TaskInjector) { }
Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask()); }
}
} public static void uninject(final Plugin plugin) {
} final BukkitScheduler scheduler = Bukkit.getScheduler();
} final List<BukkitTask> pendingTasks = scheduler.getPendingTasks();
for (final BukkitTask pendingTask : pendingTasks) {
public Runnable getOriginalTask() { // 忽略异步任务
return originalTask; if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
} final Runnable originalTask = Reflect.on(pendingTask).get("task");
if (originalTask instanceof TaskInjector) {
@Override Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask());
public void run() { }
final long start = System.nanoTime(); }
// TODO 当操作大于10ms的时候添加一个Lag提示 }
originalTask.run(); }
final long end = System.nanoTime();
totalTime += end - start; public Runnable getOriginalTask() {
count++; 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();
}
}
}
}

View File

@ -3,14 +3,14 @@
############################ ############################
#配置版本号 请勿修改!!! #配置版本号 请勿修改!!!
Version: 2.2 Version: 2.3
#是否只允许控制台执行插件仓库命令 #是否只允许控制台执行插件仓库命令
onlyCommandConsole: false onlyCommandConsole: false
#是否只允许控制台执行插件网络管理命令 #是否只允许控制台执行插件网络管理命令
onlyNetCommandConsole: false onlyNetCommandConsole: false
#是否只允许控制台执行插件文件管理命令 #是否只允许控制台执行插件文件管理命令
onlyFileCommandConsole: true onlyFileCommandConsole: false
#禁止rm -rf的文件夹列表 #禁止rm -rf的文件夹列表
blacklist: blacklist:
- 'plugins' - 'plugins'
@ -22,3 +22,4 @@ ignorelist:
- 'iConomy' - 'iConomy'
- 'GroupManager' - 'GroupManager'
- 'PermissionsEx' - 'PermissionsEx'
- 'Essentials'

View File

@ -3,10 +3,12 @@
############################ ############################
#配置版本号 请勿修改!!! #配置版本号 请勿修改!!!
Version: 1.1 Version: 1.2
#是否开启 #是否开启
Enable: true Enable: true
#是否显示开发人员信息
Debug: false
#忽略检测列表 #忽略检测列表
Ignore: Ignore:
- Essentials - PluginHelper