diff --git a/pom.xml b/pom.xml index a5cb2d1..82576b3 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 Yum - 2.9.1 + 2.9.5 jar Minecraft 服务器插件管理系统 @@ -16,16 +16,18 @@ - §a补丁包 2.9.1 版本 + §a补丁包 2.9.5 版本 - §620-03-25 §cfix: paper HikariPool error; - §619-09-30 §cfix: tabComplete error; - §619-08-28 §cfix: knownCommands not compatible; -        §cfix: async event on primary thread; - §619-08-26 §cfix: 修复不兼容 1.14.4 的问题; - §619-02-23 §cfix: 修复不兼容 1.13 的问题; + §621-10-28 §afeat: 新增屏蔽插件报错功能; + §620-03-25 §afeat: 优化 当前插件获取逻辑; + §620-03-25 §c修复: Paper HikariPool 不兼容问题; + §619-09-30 §c修复: 自动补全报错的问题; + §619-08-28 §c修复: knownCommands 不兼容; +       §c修复: async event on primary thread; + §619-08-26 §c修复: 修复不兼容 1.14.4 的问题; + §619-02-23 §c修复: 修复不兼容 1.13 的问题; §617-07-29 §cfix: 修复不兼容 1.12 的问题; §6- §cfix: §7修复仓库数据读取错误的问题; §6- §cfix: §7修复一个tab补全产生的错误 diff --git a/src/main/java/pw/yumc/Yum/inject/CommandInjector.java b/src/main/java/pw/yumc/Yum/inject/CommandInjector.java index 558c2ee..965f95f 100644 --- a/src/main/java/pw/yumc/Yum/inject/CommandInjector.java +++ b/src/main/java/pw/yumc/Yum/inject/CommandInjector.java @@ -1,139 +1,132 @@ -package pw.yumc.Yum.inject; - -import java.util.Collections; -import java.util.List; - -import org.apache.commons.lang.Validate; -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 pw.yumc.Yum.commands.MonitorCommand; -import pw.yumc.Yum.managers.MonitorManager; -import pw.yumc.YumCore.kit.StrKit; -import pw.yumc.YumCore.reflect.Reflect; - -public class CommandInjector implements TabExecutor { - private static String prefix = "§6[§bYum §a命令监控§6] "; - private static String warn = "§c注意! §6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令 §c耗时 §4%sms §c平均耗时 §4%sms!"; - private static String err = prefix + "§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常!"; - private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!"; - private static String plugin_is_null = "插件不得为NULL!"; - private CommandExecutor originalExecutor; - private TabCompleter originalCompleter; - - private Plugin plugin; - - public long totalTime; - public int count; - - public CommandInjector(CommandExecutor originalCommandExecutor, TabCompleter originalTabCompleter, Plugin plugin) { - this.originalExecutor = originalCommandExecutor; - this.originalCompleter = originalTabCompleter; - this.plugin = plugin; - } - - public static void inject(Plugin plugin) { - Validate.notNull(plugin, plugin_is_null); - try { - PluginManager pluginManager = Bukkit.getPluginManager(); - SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); - for (Command command : commandMap.getCommands()) { - if (command instanceof PluginCommand) { - PluginCommand pluginCommand = (PluginCommand) command; - Plugin cp = pluginCommand.getPlugin(); - if (cp.equals(plugin)) { - CommandExecutor executor = Reflect.on(command).get("executor"); - if (executor instanceof CommandInjector) { return; } - TabCompleter completer = Reflect.on(command).get("completer"); - CommandInjector commandInjector = new CommandInjector(executor, completer, plugin); - Reflect.on(command).set("executor", commandInjector); - Reflect.on(command).set("completer", commandInjector); - } - } - } - } catch (Throwable e) { - MonitorManager.log(String.format(inject_error, plugin.getName())); - } - } - - public static void uninject(Plugin plugin) { - Validate.notNull(plugin, plugin_is_null); - try { - PluginManager pluginManager = Bukkit.getPluginManager(); - SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); - for (Command command : commandMap.getCommands()) { - if (command instanceof PluginCommand) { - PluginCommand pluginCommand = (PluginCommand) command; - Plugin cp = pluginCommand.getPlugin(); - if (cp.equals(plugin)) { - CommandExecutor executor = Reflect.on(command).get("executor"); - if (executor instanceof CommandInjector) { - CommandInjector injected = (CommandInjector) executor; - Reflect.on(command).set("executor", injected.getOriginalExecutor()); - } - TabCompleter completer = Reflect.on(command).get("completer"); - if (completer instanceof CommandInjector) { - CommandInjector injected = (CommandInjector) completer; - Reflect.on(command).set("completer", injected.getOriginalCompleter()); - } - } - } - } - } catch (Throwable ignored) { - } - } - - public TabCompleter getOriginalCompleter() { - return originalCompleter; - } - - public CommandExecutor getOriginalExecutor() { - return originalExecutor; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - try { - long start = System.nanoTime(); - boolean result = originalExecutor.onCommand(sender, command, label, args); - long end = System.nanoTime(); - long lag = end - start; - totalTime += lag; - count++; - long lagms = lag / MonitorManager.um; - long avglagms = totalTime / count / MonitorManager.um; - if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) { - MonitorManager.lagTip(String.format(warn, sender.getName(), plugin.getName(), label, StrKit.join(args, " "), lagms, avglagms)); - } - MonitorManager.addCmd(plugin.getName(), lag); - return result; - } catch (Throwable e) { - while (e.getCause() != null) { - e = e.getCause(); - } - MonitorCommand.lastError = e; - MonitorManager.sendError(sender, plugin, e); - MonitorManager.printThrowable(String.format(err, sender.getName(), plugin.getName(), label, StrKit.join(args, " ")), e); - } - return false; - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - if (originalCompleter == null) { return Collections.emptyList(); } - long start = System.nanoTime(); - List result = originalCompleter.onTabComplete(sender, command, alias, args); - long end = System.nanoTime(); - totalTime += end - start; - count++; - return result; - } -} +package pw.yumc.Yum.inject; + +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.command.*; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; +import pw.yumc.Yum.commands.MonitorCommand; +import pw.yumc.Yum.managers.MonitorManager; +import pw.yumc.YumCore.kit.StrKit; +import pw.yumc.YumCore.reflect.Reflect; + +import java.util.Collections; +import java.util.List; + +public class CommandInjector implements TabExecutor { + private static String prefix = "§6[§bYum §a命令监控§6] "; + private static String warn = "§c注意! §6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令 §c耗时 §4%sms §c平均耗时 §4%sms!"; + private static String err = prefix + "§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常!"; + private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!"; + private static String plugin_is_null = "插件不得为NULL!"; + private CommandExecutor originalExecutor; + private TabCompleter originalCompleter; + + private Plugin plugin; + + public long totalTime; + public int count; + + public CommandInjector(CommandExecutor originalCommandExecutor, TabCompleter originalTabCompleter, Plugin plugin) { + this.originalExecutor = originalCommandExecutor; + this.originalCompleter = originalTabCompleter; + this.plugin = plugin; + } + + public static void inject(Plugin plugin) { + Validate.notNull(plugin, plugin_is_null); + try { + PluginManager pluginManager = Bukkit.getPluginManager(); + SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); + for (Command command : commandMap.getCommands()) { + if (command instanceof PluginCommand) { + PluginCommand pluginCommand = (PluginCommand) command; + Plugin cp = pluginCommand.getPlugin(); + if (cp.equals(plugin)) { + CommandExecutor executor = Reflect.on(command).get("executor"); + if (executor instanceof CommandInjector) { return; } + TabCompleter completer = Reflect.on(command).get("completer"); + CommandInjector commandInjector = new CommandInjector(executor, completer, plugin); + Reflect.on(command).set("executor", commandInjector); + Reflect.on(command).set("completer", commandInjector); + } + } + } + } catch (Throwable e) { + MonitorManager.log(String.format(inject_error, plugin.getName())); + } + } + + public static void uninject(Plugin plugin) { + Validate.notNull(plugin, plugin_is_null); + try { + PluginManager pluginManager = Bukkit.getPluginManager(); + SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap"); + for (Command command : commandMap.getCommands()) { + if (command instanceof PluginCommand) { + PluginCommand pluginCommand = (PluginCommand) command; + Plugin cp = pluginCommand.getPlugin(); + if (cp.equals(plugin)) { + CommandExecutor executor = Reflect.on(command).get("executor"); + if (executor instanceof CommandInjector) { + CommandInjector injected = (CommandInjector) executor; + Reflect.on(command).set("executor", injected.getOriginalExecutor()); + } + TabCompleter completer = Reflect.on(command).get("completer"); + if (completer instanceof CommandInjector) { + CommandInjector injected = (CommandInjector) completer; + Reflect.on(command).set("completer", injected.getOriginalCompleter()); + } + } + } + } + } catch (Throwable ignored) { + } + } + + public TabCompleter getOriginalCompleter() { + return originalCompleter; + } + + public CommandExecutor getOriginalExecutor() { + return originalExecutor; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + try { + long start = System.nanoTime(); + boolean result = originalExecutor.onCommand(sender, command, label, args); + long end = System.nanoTime(); + long lag = end - start; + totalTime += lag; + count++; + long lagms = lag / MonitorManager.um; + long avglagms = totalTime / count / MonitorManager.um; + if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) { + MonitorManager.lagTip(String.format(warn, sender.getName(), plugin.getName(), label, StrKit.join(args, " "), lagms, avglagms)); + } + MonitorManager.addCmd(plugin.getName(), lag); + return result; + } catch (Throwable e) { + while (e.getCause() != null) { + e = e.getCause(); + } + MonitorCommand.lastError = e; + MonitorManager.sendError(sender, plugin, e); + MonitorManager.printThrowable(plugin, String.format(err, sender.getName(), plugin.getName(), label, StrKit.join(args, " ")), e); + } + return false; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + if (originalCompleter == null) { return Collections.emptyList(); } + long start = System.nanoTime(); + List result = originalCompleter.onTabComplete(sender, command, alias, args); + 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 a8221f8..5809633 100644 --- a/src/main/java/pw/yumc/Yum/inject/ListenerInjector.java +++ b/src/main/java/pw/yumc/Yum/inject/ListenerInjector.java @@ -1,120 +1,119 @@ -package pw.yumc.Yum.inject; - -import java.lang.reflect.Field; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.lang.Validate; -import org.bukkit.event.Event; -import org.bukkit.event.EventException; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.plugin.EventExecutor; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredListener; -import org.bukkit.plugin.TimedRegisteredListener; - -import pw.yumc.Yum.commands.MonitorCommand; -import pw.yumc.Yum.managers.ConfigManager; -import pw.yumc.Yum.managers.MonitorManager; -import pw.yumc.YumCore.reflect.Reflect; - -public class ListenerInjector implements EventExecutor { - private static String prefix = "§6[§bYum §a事件监控§6] "; - private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6事件 §c耗时 §4%sms §c平均耗时 §4%sms!"; - private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6事件时发生异常!"; - private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败 §6注入类: §3%s!"; - private static String plugin_is_null = "插件不得为NULL!"; - private EventExecutor originalExecutor; - - private Plugin plugin; - - public Map eventTotalTime = new ConcurrentHashMap<>(); - public Map eventCount = new ConcurrentHashMap<>(); - - public ListenerInjector(EventExecutor originalExecutor, Plugin plugin) { - this.originalExecutor = originalExecutor; - this.plugin = plugin; - } - - public static void inject(Plugin plugin) { - Validate.notNull(plugin, plugin_is_null); - List listeners = HandlerList.getRegisteredListeners(plugin); - for (RegisteredListener listener : listeners) { - try { - if (listener instanceof TimedRegisteredListener) { return; } - // 兼容PerWorldPlugin - if (listener.getClass().getName().contains("PWPRegisteredListener")) { - Field f = Reflect.getDeclaredField(RegisteredListener.class, "executor"); - f.setAccessible(true); - EventExecutor originalExecutor = (EventExecutor) f.get(listener); - if (originalExecutor instanceof ListenerInjector) { return; } - ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin); - f.set(listener, listenerInjector); - } else { - EventExecutor originalExecutor = Reflect.on(listener).get("executor"); - if (originalExecutor instanceof ListenerInjector) { return; } - ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin); - Reflect.on(listener).set("executor", listenerInjector); - } - } catch (Throwable e) { - MonitorManager.log(String.format(inject_error, plugin.getName(), listener.getClass().getName())); - e.printStackTrace(); - } - } - } - - public static void uninject(Plugin plugin) { - Validate.notNull(plugin, plugin_is_null); - try { - List listeners = HandlerList.getRegisteredListeners(plugin); - for (RegisteredListener listener : listeners) { - if (listener instanceof TimedRegisteredListener) { return; } - EventExecutor executor = Reflect.on(listener).get("executor"); - if (executor instanceof ListenerInjector) { - Reflect.on(listener).set("executor", ((ListenerInjector) executor).getOriginalExecutor()); - } - } - } catch (Throwable ignored) { - } - } - - @Override - public void execute(Listener listener, Event event) throws EventException { - try { - if (!event.isAsynchronous()) { - long start = System.nanoTime(); - originalExecutor.execute(listener, event); - long end = System.nanoTime(); - String en = event.getEventName(); - long lag = end - start; - if (eventTotalTime.containsKey(en)) { - eventTotalTime.put(en, eventTotalTime.get(en) + lag); - eventCount.put(en, eventCount.get(en) + 1); - } else { - eventTotalTime.put(en, end - start); - eventCount.put(en, 1); - } - long lagms = lag / MonitorManager.um; - long avglagms = eventTotalTime.get(en) / eventCount.get(en) / MonitorManager.um; - if (avglagms > MonitorManager.lagTime && lagms > MonitorManager.lagTime && !ConfigManager.i().getMonitorIgnoreList().contains(plugin.getName())) { - MonitorManager.lagTip(String.format(warn, plugin.getName(), event.getEventName(), lagms, avglagms)); - } - MonitorManager.addEvent(plugin.getName(), lag); - } else { - originalExecutor.execute(listener, event); - } - } catch (Throwable e) { - while (e.getCause() != null) { - e = e.getCause(); - } - MonitorCommand.lastError = e; - MonitorManager.printThrowable(String.format(err, plugin.getName(), event.getEventName()), e); - } - } - - public EventExecutor getOriginalExecutor() { - return originalExecutor; - } -} +package pw.yumc.Yum.inject; + +import org.apache.commons.lang.Validate; +import org.bukkit.event.Event; +import org.bukkit.event.EventException; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredListener; +import org.bukkit.plugin.TimedRegisteredListener; +import pw.yumc.Yum.commands.MonitorCommand; +import pw.yumc.Yum.managers.ConfigManager; +import pw.yumc.Yum.managers.MonitorManager; +import pw.yumc.YumCore.reflect.Reflect; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ListenerInjector implements EventExecutor { + private static String prefix = "§6[§bYum §a事件监控§6] "; + private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6事件 §c耗时 §4%sms §c平均耗时 §4%sms!"; + private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6事件时发生异常!"; + private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败 §6注入类: §3%s!"; + private static String plugin_is_null = "插件不得为NULL!"; + private EventExecutor originalExecutor; + + private Plugin plugin; + + public Map eventTotalTime = new ConcurrentHashMap<>(); + public Map eventCount = new ConcurrentHashMap<>(); + + public ListenerInjector(EventExecutor originalExecutor, Plugin plugin) { + this.originalExecutor = originalExecutor; + this.plugin = plugin; + } + + public static void inject(Plugin plugin) { + Validate.notNull(plugin, plugin_is_null); + List listeners = HandlerList.getRegisteredListeners(plugin); + for (RegisteredListener listener : listeners) { + try { + if (listener instanceof TimedRegisteredListener) { return; } + // 兼容PerWorldPlugin + if (listener.getClass().getName().contains("PWPRegisteredListener")) { + Field f = Reflect.getDeclaredField(RegisteredListener.class, "executor"); + f.setAccessible(true); + EventExecutor originalExecutor = (EventExecutor) f.get(listener); + if (originalExecutor instanceof ListenerInjector) { return; } + ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin); + f.set(listener, listenerInjector); + } else { + EventExecutor originalExecutor = Reflect.on(listener).get("executor"); + if (originalExecutor instanceof ListenerInjector) { return; } + ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin); + Reflect.on(listener).set("executor", listenerInjector); + } + } catch (Throwable e) { + MonitorManager.log(String.format(inject_error, plugin.getName(), listener.getClass().getName())); + e.printStackTrace(); + } + } + } + + public static void uninject(Plugin plugin) { + Validate.notNull(plugin, plugin_is_null); + try { + List listeners = HandlerList.getRegisteredListeners(plugin); + for (RegisteredListener listener : listeners) { + if (listener instanceof TimedRegisteredListener) { return; } + EventExecutor executor = Reflect.on(listener).get("executor"); + if (executor instanceof ListenerInjector) { + Reflect.on(listener).set("executor", ((ListenerInjector) executor).getOriginalExecutor()); + } + } + } catch (Throwable ignored) { + } + } + + @Override + public void execute(Listener listener, Event event) throws EventException { + try { + if (!event.isAsynchronous()) { + long start = System.nanoTime(); + originalExecutor.execute(listener, event); + long end = System.nanoTime(); + String en = event.getEventName(); + long lag = end - start; + if (eventTotalTime.containsKey(en)) { + eventTotalTime.put(en, eventTotalTime.get(en) + lag); + eventCount.put(en, eventCount.get(en) + 1); + } else { + eventTotalTime.put(en, end - start); + eventCount.put(en, 1); + } + long lagms = lag / MonitorManager.um; + long avglagms = eventTotalTime.get(en) / eventCount.get(en) / MonitorManager.um; + if (avglagms > MonitorManager.lagTime && lagms > MonitorManager.lagTime && !ConfigManager.i().getMonitorIgnoreList().contains(plugin.getName())) { + MonitorManager.lagTip(String.format(warn, plugin.getName(), event.getEventName(), lagms, avglagms)); + } + MonitorManager.addEvent(plugin.getName(), lag); + } else { + originalExecutor.execute(listener, event); + } + } catch (Throwable e) { + while (e.getCause() != null) { + e = e.getCause(); + } + MonitorCommand.lastError = e; + MonitorManager.printThrowable(plugin, String.format(err, plugin.getName(), event.getEventName()), e); + } + } + + public EventExecutor getOriginalExecutor() { + return originalExecutor; + } +} diff --git a/src/main/java/pw/yumc/Yum/inject/TaskInjector.java b/src/main/java/pw/yumc/Yum/inject/TaskInjector.java index b993df5..22c3877 100644 --- a/src/main/java/pw/yumc/Yum/inject/TaskInjector.java +++ b/src/main/java/pw/yumc/Yum/inject/TaskInjector.java @@ -1,120 +1,119 @@ -package pw.yumc.Yum.inject; - -import java.util.List; - -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitScheduler; -import org.bukkit.scheduler.BukkitTask; - -import pw.yumc.Yum.commands.MonitorCommand; -import pw.yumc.Yum.managers.MonitorManager; -import pw.yumc.YumCore.bukkit.P; -import pw.yumc.YumCore.kit.StrKit; -import pw.yumc.YumCore.reflect.Reflect; - -public class TaskInjector implements Runnable { - private static String prefix = "§6[§bYum §a任务监控§6] "; - private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6任务 §c耗时 §4%sms §c平均耗时 §4%sms!"; - private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6任务时发生异常!"; - private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!"; - private static String plugin_is_null = "插件不得为NULL!"; - private static String taskFieldName = "task"; - - static { - BukkitTask task = Bukkit.getServer().getScheduler().runTask(P.instance, new Runnable(){ - @Override - public void run() {} - }); - try { - Reflect.on(task).get("rTask"); - taskFieldName = "rTask"; - }catch (Throwable ex) { - } - } - - private Runnable originalTask; - private Plugin plugin; - - private String taskName; - - public long totalTime; - public int count; - - public TaskInjector(Runnable originalTask, Plugin plugin) { - this.originalTask = originalTask; - this.plugin = plugin; - Class taskClass = getOriginalTask().getClass(); - taskName = StrKit.isBlank(taskClass.getSimpleName()) ? taskClass.getName() : taskClass.getSimpleName(); - } - - // 当前注入只能对TimerTask有效 - // 对于单次执行的任务 我们需要注册一个动态的代理 - public static void inject(Plugin plugin) { - Validate.notNull(plugin, plugin_is_null); - try { - BukkitScheduler scheduler = Bukkit.getScheduler(); - List pendingTasks = scheduler.getPendingTasks(); - for (BukkitTask pendingTask : pendingTasks) { - // 忽略异步任务 - if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { - Runnable originalTask = Reflect.on(pendingTask).get(taskFieldName); - if (originalTask instanceof TaskInjector) { - return; - } - TaskInjector taskInjector = new TaskInjector(originalTask, plugin); - Reflect.on(pendingTask).set(taskFieldName, taskInjector); - } - } - } catch (Throwable e) { - MonitorManager.log(String.format(inject_error, plugin.getName())); - } - } - - public static void uninject(Plugin plugin) { - Validate.notNull(plugin, plugin_is_null); - try { - BukkitScheduler scheduler = Bukkit.getScheduler(); - List pendingTasks = scheduler.getPendingTasks(); - for (BukkitTask pendingTask : pendingTasks) { - // 忽略异步任务 - if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { - Runnable originalTask = Reflect.on(pendingTask).get("task"); - if (originalTask instanceof TaskInjector) { - Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask()); - } - } - } - } catch (Throwable ignored) { - } - } - - public Runnable getOriginalTask() { - return originalTask; - } - - @Override - public void run() { - try { - long start = System.nanoTime(); - originalTask.run(); - long end = System.nanoTime(); - long lag = end - start; - totalTime += lag; - count++; - long lagms = lag / MonitorManager.um; - long avglagms = totalTime / count / MonitorManager.um; - if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) { - MonitorManager.lagTip(String.format(warn, plugin.getName(), taskName, lagms, avglagms)); - } - MonitorManager.addTask(plugin.getName(), lag); - } catch (Throwable e) { - while (e.getCause() != null) { - e = e.getCause(); - } - MonitorCommand.lastError = e; - MonitorManager.printThrowable(String.format(err, plugin.getName(), taskName), e); - } - } -} +package pw.yumc.Yum.inject; + +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.scheduler.BukkitTask; +import pw.yumc.Yum.commands.MonitorCommand; +import pw.yumc.Yum.managers.MonitorManager; +import pw.yumc.YumCore.bukkit.P; +import pw.yumc.YumCore.kit.StrKit; +import pw.yumc.YumCore.reflect.Reflect; + +import java.util.List; + +public class TaskInjector implements Runnable { + private static String prefix = "§6[§bYum §a任务监控§6] "; + private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6任务 §c耗时 §4%sms §c平均耗时 §4%sms!"; + private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6任务时发生异常!"; + private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!"; + private static String plugin_is_null = "插件不得为NULL!"; + private static String taskFieldName = "task"; + + static { + BukkitTask task = Bukkit.getServer().getScheduler().runTask(P.instance, new Runnable() { + @Override + public void run() {} + }); + try { + Reflect.on(task).get("rTask"); + taskFieldName = "rTask"; + } catch (Throwable ex) { + } + } + + private Runnable originalTask; + private Plugin plugin; + + private String taskName; + + public long totalTime; + public int count; + + public TaskInjector(Runnable originalTask, Plugin plugin) { + this.originalTask = originalTask; + this.plugin = plugin; + Class taskClass = getOriginalTask().getClass(); + taskName = StrKit.isBlank(taskClass.getSimpleName()) ? taskClass.getName() : taskClass.getSimpleName(); + } + + // 当前注入只能对TimerTask有效 + // 对于单次执行的任务 我们需要注册一个动态的代理 + public static void inject(Plugin plugin) { + Validate.notNull(plugin, plugin_is_null); + try { + BukkitScheduler scheduler = Bukkit.getScheduler(); + List pendingTasks = scheduler.getPendingTasks(); + for (BukkitTask pendingTask : pendingTasks) { + // 忽略异步任务 + if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { + Runnable originalTask = Reflect.on(pendingTask).get(taskFieldName); + if (originalTask instanceof TaskInjector) { + return; + } + TaskInjector taskInjector = new TaskInjector(originalTask, plugin); + Reflect.on(pendingTask).set(taskFieldName, taskInjector); + } + } + } catch (Throwable e) { + MonitorManager.log(String.format(inject_error, plugin.getName())); + } + } + + public static void uninject(Plugin plugin) { + Validate.notNull(plugin, plugin_is_null); + try { + BukkitScheduler scheduler = Bukkit.getScheduler(); + List pendingTasks = scheduler.getPendingTasks(); + for (BukkitTask pendingTask : pendingTasks) { + // 忽略异步任务 + if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { + Runnable originalTask = Reflect.on(pendingTask).get("task"); + if (originalTask instanceof TaskInjector) { + Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask()); + } + } + } + } catch (Throwable ignored) { + } + } + + public Runnable getOriginalTask() { + return originalTask; + } + + @Override + public void run() { + try { + long start = System.nanoTime(); + originalTask.run(); + long end = System.nanoTime(); + long lag = end - start; + totalTime += lag; + count++; + long lagms = lag / MonitorManager.um; + long avglagms = totalTime / count / MonitorManager.um; + if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) { + MonitorManager.lagTip(String.format(warn, plugin.getName(), taskName, lagms, avglagms)); + } + MonitorManager.addTask(plugin.getName(), lag); + } catch (Throwable e) { + while (e.getCause() != null) { + e = e.getCause(); + } + MonitorCommand.lastError = e; + MonitorManager.printThrowable(plugin, String.format(err, plugin.getName(), taskName), e); + } + } +} diff --git a/src/main/java/pw/yumc/Yum/managers/ConfigManager.java b/src/main/java/pw/yumc/Yum/managers/ConfigManager.java index 4ecb2b9..7b3bd50 100644 --- a/src/main/java/pw/yumc/Yum/managers/ConfigManager.java +++ b/src/main/java/pw/yumc/Yum/managers/ConfigManager.java @@ -1,126 +1,129 @@ -package pw.yumc.Yum.managers; - -import java.util.List; - -import org.bukkit.plugin.java.JavaPlugin; - -import pw.yumc.YumCore.bukkit.P; -import pw.yumc.YumCore.config.FileConfig; -import pw.yumc.YumCore.sql.DataBase; - -public class ConfigManager { - public static String ENABLE = "Enable"; - public static String BLACK = "Black"; - public static String IGNORE = "Ignore"; - - private static ConfigManager i = new ConfigManager(P.instance); - - public FileConfig config; - public FileConfig setop; - public FileConfig network; - public FileConfig thread; - public FileConfig monitor; - - public ConfigManager(JavaPlugin plugin) { - config = new FileConfig(); - setop = new FileConfig("setop.yml"); - network = new FileConfig("network.yml"); - thread = new FileConfig("thread.yml"); - monitor = new FileConfig("monitor.yml"); - } - - public static ConfigManager i() { - return i; - } - - public List getBlackList() { - return config.getStringList("blacklist"); - } - - public DataBase getDataBase() { - return DataBase.create(P.instance, config.getConfigurationSection("")); - } - - public List getIgnoreList() { - return config.getStringList("ignorelist"); - } - - public List getMonitorIgnoreList() { - return monitor.getStringList(IGNORE); - } - - public List getNetworkBlackList() { - return network.getStringList(BLACK); - } - - public List getNetworkIgnoreList() { - return network.getStringList(IGNORE); - } - - public List getNetworkWhiteURL() { - return network.getStringList("WhiteURL"); - } - - public List getSetOpBlackList() { - return setop.getStringList(BLACK); - } - - public List getSetOpIgnoreList() { - return setop.getStringList(IGNORE); - } - - public boolean isAllowPrimaryThread() { - return network.getBoolean("AllowPrimaryThread", false); - } - - public boolean isLogToFile() { - return monitor.getBoolean("LogToFile"); - } - - public boolean isMainThreadCheck() { - return thread.getBoolean("MainThreadCheck", true); - } - - public boolean isMainThreadDebug() { - return thread.getBoolean("Debug"); - } - - public boolean isMonitorDebug() { - return monitor.getBoolean("Debug"); - } - - public boolean isMonitorEnable() { - return monitor.getBoolean(ENABLE, true); - } - - public boolean isNetworkDebug() { - return network.getBoolean("NetworkDebug", false); - } - - public boolean isNetworkEnable() { - return network.getBoolean(ENABLE, true); - } - - public boolean isNetworkShowInfo() { - return network.getBoolean("ShowInfo", true); - } - - public boolean isSetOpEnable() { - return setop.getBoolean(ENABLE, true); - } - - public boolean isThreadSafe() { - return thread.getBoolean("ThreadSafe", true); - } - - public List getNetWorkDebug() { - return network.getStringList("Debug"); - } - - public void reload() { - setop.reload(); - network.reload(); - thread.reload(); - monitor.reload(); - } -} +package pw.yumc.Yum.managers; + +import org.bukkit.plugin.java.JavaPlugin; +import pw.yumc.YumCore.bukkit.P; +import pw.yumc.YumCore.config.FileConfig; +import pw.yumc.YumCore.sql.DataBase; + +import java.util.List; + +public class ConfigManager { + public static String ENABLE = "Enable"; + public static String BLACK = "Black"; + public static String IGNORE = "Ignore"; + + private static ConfigManager i = new ConfigManager(P.instance); + + public FileConfig config; + public FileConfig setop; + public FileConfig network; + public FileConfig thread; + public FileConfig monitor; + + public ConfigManager(JavaPlugin plugin) { + config = new FileConfig(); + setop = new FileConfig("setop.yml"); + network = new FileConfig("network.yml"); + thread = new FileConfig("thread.yml"); + monitor = new FileConfig("monitor.yml"); + } + + public static ConfigManager i() { + return i; + } + + public List getBlackList() { + return config.getStringList("blacklist"); + } + + public DataBase getDataBase() { + return DataBase.create(P.instance, config.getConfigurationSection("")); + } + + public List getIgnoreList() { + return config.getStringList("ignorelist"); + } + + public List getMonitorIgnoreList() { + return monitor.getStringList(IGNORE); + } + + public List getMonitorIgnoreErrorList() { + return monitor.getStringList("IgnoreError"); + } + + public List getNetworkBlackList() { + return network.getStringList(BLACK); + } + + public List getNetworkIgnoreList() { + return network.getStringList(IGNORE); + } + + public List getNetworkWhiteURL() { + return network.getStringList("WhiteURL"); + } + + public List getSetOpBlackList() { + return setop.getStringList(BLACK); + } + + public List getSetOpIgnoreList() { + return setop.getStringList(IGNORE); + } + + public boolean isAllowPrimaryThread() { + return network.getBoolean("AllowPrimaryThread", false); + } + + public boolean isLogToFile() { + return monitor.getBoolean("LogToFile"); + } + + public boolean isMainThreadCheck() { + return thread.getBoolean("MainThreadCheck", true); + } + + public boolean isMainThreadDebug() { + return thread.getBoolean("Debug"); + } + + public boolean isMonitorDebug() { + return monitor.getBoolean("Debug"); + } + + public boolean isMonitorEnable() { + return monitor.getBoolean(ENABLE, true); + } + + public boolean isNetworkDebug() { + return network.getBoolean("NetworkDebug", false); + } + + public boolean isNetworkEnable() { + return network.getBoolean(ENABLE, true); + } + + public boolean isNetworkShowInfo() { + return network.getBoolean("ShowInfo", true); + } + + public boolean isSetOpEnable() { + return setop.getBoolean(ENABLE, true); + } + + public boolean isThreadSafe() { + return thread.getBoolean("ThreadSafe", true); + } + + public List getNetWorkDebug() { + return network.getStringList("Debug"); + } + + public void reload() { + setop.reload(); + network.reload(); + thread.reload(); + monitor.reload(); + } +} diff --git a/src/main/java/pw/yumc/Yum/managers/MonitorManager.java b/src/main/java/pw/yumc/Yum/managers/MonitorManager.java index 8cc9c5f..1a3cbf9 100644 --- a/src/main/java/pw/yumc/Yum/managers/MonitorManager.java +++ b/src/main/java/pw/yumc/Yum/managers/MonitorManager.java @@ -1,185 +1,180 @@ -package pw.yumc.Yum.managers; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; - -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; - -import pw.yumc.YumCore.bukkit.Log; -import pw.yumc.YumCore.kit.LogKit; - -/** - * 能耗监控管理 - * - * @since 2016年7月19日 下午3:55:54 - * @author 喵♂呜 - */ -public class MonitorManager { - public static String prefix = "§6[§bYum §a能耗监控§6] "; - private static String errMsg = prefix + "§c命令执行异常 请反馈下列信息给腐竹!"; - private static String errP = "§6插件名称: §b%s"; - private static String errN = "§6异常名称: §c%s"; - private static String errM = "§6异常说明: §3%s"; - private static String errInfo = "§6简易错误信息如下:"; - private static String errStackTrace = " §e位于 §c%s.%s(§4%s:%s§c)"; - private static String devInfo = "§c开发人员调试信息如下:"; - - public static int lagTime = 20; - public static int um = 1000000; - public static boolean debug = ConfigManager.i().isMonitorDebug(); - public static boolean log_to_file = ConfigManager.i().isLogToFile(); - - private static double totalTime = 0; - - private static Map monitor = new ConcurrentHashMap<>(); - private static Map task = new ConcurrentHashMap<>(); - private static Map event = new ConcurrentHashMap<>(); - private static Map cmd = new ConcurrentHashMap<>(); - - private static LogKit mlog = new LogKit("monitor.log"); - private static LogKit elog = new LogKit("error.log"); - - public static void addCmd(String pname, long time) { - add(pname, time, monitor, cmd); - } - - public static void addEvent(String pname, long time) { - add(pname, time, monitor, event); - } - - public static void addTask(String pname, long time) { - add(pname, time, monitor, task); - } - - public static void elog(String message) { - if (log_to_file) { - elog.console(message); - } else { - Log.console(message); - } - } - - public static Map getMonitor() { - return sortMapByValue(monitor); - } - - public static MonitorInfo getMonitorInfo(String pname) { - double per = 100.00; - return new MonitorInfo(monitor.get(pname) / totalTime * per, cmd.get(pname) / totalTime * per, event.get(pname) / totalTime * per, task.get(pname) / totalTime * per); - } - - public static void init() { - for (Plugin p : Bukkit.getPluginManager().getPlugins()) { - reset(p.getName()); - } - } - - public static void lagTip(String message) { - log(prefix + message); - } - - public static void log(String message) { - if (log_to_file) { - mlog.console(message); - } else { - Log.console(message); - } - } - - public static void printThrowable(String title, Throwable e) { - elog(title); - elog(String.format(errN, e.getClass().getName())); - elog(String.format(errM, e.getMessage())); - elog(errInfo); - int l = e.getStackTrace().length > 5 ? 5 : e.getStackTrace().length; - for (int i = 0; i < l; i++) { - StackTraceElement ste = e.getStackTrace()[i]; - elog(String.format(errStackTrace, ste.getClassName(), ste.getMethodName(), ste.getFileName() == null ? "未知" : ste.getFileName(), ste.getLineNumber())); - } - if (debug) { - Log.console(devInfo); - e.printStackTrace(); - } - } - - public static void reset(String pname) { - monitor.put(pname, 0L); - task.put(pname, 0L); - event.put(pname, 0L); - cmd.put(pname, 0L); - } - - public static void sendError(CommandSender sender, Plugin plugin, Throwable e) { - sender.sendMessage(errMsg); - sender.sendMessage(String.format(errP, plugin.getName())); - sender.sendMessage(String.format(errN, e.getClass().getName())); - sender.sendMessage(String.format(errM, e.getMessage())); - } - - /** - * 使用 Map按value进行排序 - * - * @param oriMap - * @return - */ - public static Map sortMapByValue(Map oriMap) { - if (oriMap == null || oriMap.isEmpty()) { return oriMap; } - Map sortedMap = new LinkedHashMap<>(); - List> entryList = new ArrayList<>(oriMap.entrySet()); - Collections.sort(entryList, new MonitorComparator()); - Iterator> iter = entryList.iterator(); - Entry tmpEntry; - while (iter.hasNext()) { - tmpEntry = iter.next(); - sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue()); - } - return sortedMap; - } - - @SafeVarargs - private static void add(String pname, long time, Map... maps) { - totalTime += time; - for (Map map : maps) { - map.put(pname, map.get(pname) + time); - } - } - - private static long sum(Collection numbers) { - int result = 0; - for (Long num : numbers) { - result += num; - } - return result; - } - - public static class MonitorInfo { - public double monitor; - public double cmd; - public double event; - public double task; - - public MonitorInfo(double monitor, double cmd, double event, double task) { - this.monitor = monitor; - this.cmd = cmd; - this.event = event; - this.task = task; - } - } - - static class MonitorComparator implements Comparator> { - @Override - public int compare(Entry o1, Entry o2) { - return o2.getValue().compareTo(o1.getValue()); - } - } -} +package pw.yumc.Yum.managers; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; +import pw.yumc.YumCore.bukkit.Log; +import pw.yumc.YumCore.kit.LogKit; + +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 能耗监控管理 + * + * @author 喵♂呜 + * @since 2016年7月19日 下午3:55:54 + */ +public class MonitorManager { + public static String prefix = "§6[§bYum §a能耗监控§6] "; + private static String errMsg = prefix + "§c命令执行异常 请反馈下列信息给腐竹!"; + private static String errP = "§6插件名称: §b%s"; + private static String errN = "§6异常名称: §c%s"; + private static String errM = "§6异常说明: §3%s"; + private static String errInfo = "§6简易错误信息如下:"; + private static String errStackTrace = " §e位于 §c%s.%s(§4%s:%s§c)"; + private static String devInfo = "§c开发人员调试信息如下:"; + + public static int lagTime = 20; + public static int um = 1000000; + public static boolean debug = ConfigManager.i().isMonitorDebug(); + public static boolean log_to_file = ConfigManager.i().isLogToFile(); + + private static double totalTime = 0; + + private static Map monitor = new ConcurrentHashMap<>(); + private static Map task = new ConcurrentHashMap<>(); + private static Map event = new ConcurrentHashMap<>(); + private static Map cmd = new ConcurrentHashMap<>(); + + private static LogKit mlog = new LogKit("monitor.log"); + private static LogKit elog = new LogKit("error.log"); + + public static void addCmd(String pname, long time) { + add(pname, time, monitor, cmd); + } + + public static void addEvent(String pname, long time) { + add(pname, time, monitor, event); + } + + public static void addTask(String pname, long time) { + add(pname, time, monitor, task); + } + + public static void elog(String message) { + if (log_to_file) { + elog.console(message); + } else { + Log.console(message); + } + } + + public static Map getMonitor() { + return sortMapByValue(monitor); + } + + public static MonitorInfo getMonitorInfo(String pname) { + double per = 100.00; + return new MonitorInfo(monitor.get(pname) / totalTime * per, cmd.get(pname) / totalTime * per, event.get(pname) / totalTime * per, task.get(pname) / totalTime * per); + } + + public static void init() { + for (Plugin p : Bukkit.getPluginManager().getPlugins()) { + reset(p.getName()); + } + } + + public static void lagTip(String message) { + log(prefix + message); + } + + public static void log(String message) { + if (log_to_file) { + mlog.console(message); + } else { + Log.console(message); + } + } + + public static void printThrowable(Plugin plugin, String title, Throwable e) { + if (ConfigManager.i().getMonitorIgnoreErrorList().contains(plugin.getName())) { + return; + } + elog(title); + elog(String.format(errN, e.getClass().getName())); + elog(String.format(errM, e.getMessage())); + elog(errInfo); + int l = Math.min(e.getStackTrace().length, 5); + for (int i = 0; i < l; i++) { + StackTraceElement ste = e.getStackTrace()[i]; + elog(String.format(errStackTrace, ste.getClassName(), ste.getMethodName(), ste.getFileName() == null ? "未知" : ste.getFileName(), ste.getLineNumber())); + } + if (debug) { + Log.console(devInfo); + e.printStackTrace(); + } + } + + public static void reset(String pname) { + monitor.put(pname, 0L); + task.put(pname, 0L); + event.put(pname, 0L); + cmd.put(pname, 0L); + } + + public static void sendError(CommandSender sender, Plugin plugin, Throwable e) { + sender.sendMessage(errMsg); + sender.sendMessage(String.format(errP, plugin.getName())); + sender.sendMessage(String.format(errN, e.getClass().getName())); + sender.sendMessage(String.format(errM, e.getMessage())); + } + + /** + * 使用 Map按value进行排序 + * + * @param oriMap + * @return + */ + public static Map sortMapByValue(Map oriMap) { + if (oriMap == null || oriMap.isEmpty()) { return oriMap; } + Map sortedMap = new LinkedHashMap<>(); + List> entryList = new ArrayList<>(oriMap.entrySet()); + entryList.sort(new MonitorComparator()); + Iterator> iter = entryList.iterator(); + Entry tmpEntry; + while (iter.hasNext()) { + tmpEntry = iter.next(); + sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue()); + } + return sortedMap; + } + + @SafeVarargs + private static void add(String pname, long time, Map... maps) { + totalTime += time; + for (Map map : maps) { + map.put(pname, map.get(pname) + time); + } + } + + private static long sum(Collection numbers) { + int result = 0; + for (Long num : numbers) { + result += num; + } + return result; + } + + public static class MonitorInfo { + public double monitor; + public double cmd; + public double event; + public double task; + + public MonitorInfo(double monitor, double cmd, double event, double task) { + this.monitor = monitor; + this.cmd = cmd; + this.event = event; + this.task = task; + } + } + + static class MonitorComparator implements Comparator> { + @Override + public int compare(Entry o1, Entry o2) { + return o2.getValue().compareTo(o1.getValue()); + } + } +} diff --git a/src/main/resources/monitor.yml b/src/main/resources/monitor.yml index 930f851..e520510 100644 --- a/src/main/resources/monitor.yml +++ b/src/main/resources/monitor.yml @@ -1,16 +1,19 @@ -############################ -### 能耗监控系统配置文件 -############################ - -#配置版本号 请勿修改!!! -Version: 1.3 - -#是否开启 -Enable: true -#是否显示开发人员信息 -Debug: false -#是否保存Lag日志到文件 -LogToFile: true -#忽略检测列表 -Ignore: -- PluginHelper \ No newline at end of file +############################ +### 能耗监控系统配置文件 +############################ + +#配置版本号 请勿修改!!! +Version: 1.4 + +#是否开启 +Enable: true +#是否显示开发人员信息 +Debug: false +#是否保存Lag日志到文件 +LogToFile: true +#忽略检测列表 +Ignore: + - PluginHelper +#忽略报错的插件列表 +IgnoreError: + - PluginHelper