feat: 添加能耗监控系统

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-07-06 20:51:25 +08:00
parent 4e1304d912
commit 7985ff3433
13 changed files with 497 additions and 54 deletions

View File

@ -8,6 +8,7 @@ import java.util.TimerTask;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import cn.citycraft.CommonData.UpdatePlugin;
@ -15,6 +16,7 @@ import cn.citycraft.PluginHelper.kit.PluginKit;
import cn.citycraft.PluginHelper.utils.VersionChecker;
import pw.yumc.Yum.api.YumAPI;
import pw.yumc.Yum.commands.FileCommand;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.commands.NetCommand;
import pw.yumc.Yum.commands.YumCommand;
import pw.yumc.Yum.listeners.PluginNetworkListener;
@ -43,6 +45,9 @@ public class Yum extends JavaPlugin {
@Override
public void onDisable() {
NetworkManager.unregister();
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
YumAPI.uninject(plugin);
}
}
@Override
@ -54,6 +59,7 @@ public class Yum extends JavaPlugin {
initCommands();
initListeners();
initRunnable();
initInject();
new VersionChecker(this);
YumAPI.updaterepo(Bukkit.getConsoleSender());
YumAPI.updatecheck(Bukkit.getConsoleSender());
@ -76,6 +82,14 @@ public class Yum extends JavaPlugin {
new YumCommand(this);
new NetCommand(this);
new FileCommand(this);
new MonitorCommand(this);
}
private void initInject() {
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
YumAPI.inject(plugin);
}
PluginKit.scp("§a性能监控系统已启用...");
}
/**

View File

@ -12,6 +12,7 @@ import org.bukkit.plugin.Plugin;
import cn.citycraft.CommonData.UpdatePlugin;
import cn.citycraft.PluginHelper.kit.PKit;
import pw.yumc.Yum.inject.CommandInjector;
import pw.yumc.Yum.managers.ConfigManager;
import pw.yumc.Yum.managers.DownloadManager;
import pw.yumc.Yum.managers.PluginsManager;
@ -31,6 +32,20 @@ public class YumAPI {
private static RepositoryManager repo;
private static boolean runlock = false;
/**
* 初始化Yum管理中心
*
* @param plugin
* 插件实体
*/
public YumAPI() {
YumAPI.main = PKit.instance;
plugman = new PluginsManager(main);
download = new DownloadManager(main);
repo = new RepositoryManager(main);
plugman.addIgnore(ConfigManager.i().getIgnoreList());
}
/**
* 删除插件
*
@ -81,6 +96,18 @@ public class YumAPI {
return ulist;
}
/**
* 注入性能监控器
*
* @param plugin
* 插件
*/
public static void inject(final Plugin plugin) {
CommandInjector.inject(plugin);
// ListenerInjector.inject(plugin);
// TaskInjector.inject(plugin);
}
/**
* 安装新插件
*
@ -175,6 +202,18 @@ public class YumAPI {
plugman.reload(plugin);
}
/**
* 取消注入
*
* @param plugin
* 插件
*/
public static void uninject(final Plugin plugin) {
CommandInjector.uninject(plugin);
// ListenerInjector.uninject(plugin);
// TaskInjector.uninject(plugin);
}
/**
* 卸载插件
*
@ -239,9 +278,10 @@ public class YumAPI {
sender.sendMessage("§d开始更新服务器可更新插件");
for (final Plugin updateplugin : ulist) {
sender.sendMessage("§d一键更新: §a开始更新" + updateplugin.getName() + "!");
if (!updatefromyum(sender, updateplugin, null, true))
if (!updatefromyum(sender, updateplugin, null, true)) {
failed++;
}
}
if (failed != 0) {
sender.sendMessage("§d一键更新: §c升级过程中 §4" + failed + " §c个插件更新失败!");
}
@ -354,18 +394,4 @@ public class YumAPI {
public static void upgrade(final CommandSender sender, final Plugin plugin) {
plugman.upgrade(sender, plugin);
}
/**
* 初始化Yum管理中心
*
* @param plugin
* 插件实体
*/
public YumAPI() {
YumAPI.main = PKit.instance;
plugman = new PluginsManager(main);
download = new DownloadManager(main);
repo = new RepositoryManager(main);
plugman.addIgnore(ConfigManager.i().getIgnoreList());
}
}

View File

@ -12,7 +12,6 @@ import cn.citycraft.PluginHelper.commands.InvokeSubCommand;
import cn.citycraft.PluginHelper.utils.FileUtil;
import pw.yumc.Yum.Yum;
import pw.yumc.Yum.api.YumAPI;
import pw.yumc.Yum.managers.DownloadManager;
/**
* File命令基类
@ -22,11 +21,9 @@ import pw.yumc.Yum.managers.DownloadManager;
*/
public class FileCommand implements HandlerCommands {
Yum plugin;
DownloadManager dl;
public FileCommand(final Yum yum) {
plugin = yum;
dl = YumAPI.getDownload();
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "file");
cmdhandler.setAllCommandOnlyConsole(yum.getConfig().getBoolean("onlyFileCommandConsole", true));
cmdhandler.registerCommands(this);
@ -64,9 +61,9 @@ public class FileCommand implements HandlerCommands {
if (args.length == 2) {
file = new File(args[1]);
} else {
file = new File(Bukkit.getUpdateFolderFile(), dl.getFileName(urlstr));
file = new File(Bukkit.getUpdateFolderFile(), YumAPI.getDownload().getFileName(urlstr));
}
dl.run(e.getSender(), urlstr, file);
YumAPI.getDownload().run(e.getSender(), urlstr, file);
}
@HandlerCommand(name = "ls", aliases = { "l" }, description = "列出当前目录(服务器JAR为根目录)", possibleArguments = "<相对目录>")

View File

@ -0,0 +1,129 @@
package pw.yumc.Yum.commands;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
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.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitTask;
import cn.citycraft.PluginHelper.commands.HandlerCommand;
import cn.citycraft.PluginHelper.commands.HandlerCommands;
import cn.citycraft.PluginHelper.commands.HandlerTabComplete;
import cn.citycraft.PluginHelper.commands.InvokeCommandEvent;
import cn.citycraft.PluginHelper.commands.InvokeSubCommand;
import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.utils.StrKit;
import pw.yumc.Yum.Yum;
import pw.yumc.Yum.api.YumAPI;
import pw.yumc.Yum.inject.CommandInjector;
import pw.yumc.Yum.inject.TaskInjector;
/**
*
* @since 2016年7月6日 下午5:13:32
* @author
*/
public class MonitorCommand implements HandlerCommands {
Yum main;
public MonitorCommand(final Yum yum) {
main = yum;
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "monitor");
cmdhandler.setAllCommandOnlyConsole(yum.getConfig().getBoolean("onlyFileCommandConsole", true));
cmdhandler.registerCommands(this);
}
@HandlerCommand(name = "a")
public void a(final InvokeCommandEvent e) {
}
@HandlerCommand(name = "cmd", minimumArguments = 1, possibleArguments = "插件名称")
public void cmd(final InvokeCommandEvent e) {
final String pname = e.getArgs()[0];
final CommandSender sender = e.getSender();
if (Bukkit.getPluginManager().getPlugin(pname) == null) {
sender.sendMessage("§c插件不存在!");
return;
}
final PluginManager pluginManager = Bukkit.getPluginManager();
final SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap");
sender.sendMessage("§6插件 §b" + pname + " §6的命令能耗如下!");
final Map<String, Command> temp = new HashMap<>();
for (final Command command : commandMap.getCommands()) {
if (command instanceof PluginCommand) {
final PluginCommand pluginCommand = (PluginCommand) command;
final Plugin plugin = pluginCommand.getPlugin();
if (plugin.getName().equalsIgnoreCase(pname)) {
temp.put(command.getName(), command);
}
}
}
for (final Entry<String, Command> command : temp.entrySet()) {
final CommandExecutor executor = Reflect.on(command.getValue()).get("executor");
if (executor instanceof CommandInjector) {
final CommandInjector injected = (CommandInjector) executor;
final StringBuffer str = new StringBuffer();
str.append("§6- §e" + command.getValue().getName() + " ");
str.append(String.format("§6总耗时: §a%.2f秒 ", injected.totalTime / 1000000.0));
str.append("§6执行次数: §b" + injected.count + "");
if (injected.count != 0) {
str.append(String.format("§6平均耗时: §d%.2f秒!", injected.totalTime / 1000000.0 / injected.count));
}
e.getSender().sendMessage(str.toString());
} else {
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);
}
}
}
@HandlerTabComplete()
public List<String> listtab(final InvokeCommandEvent e) {
final String[] args = e.getArgs();
return StrKit.copyPartialMatches(args[1], YumAPI.getPlugman().getPluginNames(false), new ArrayList<String>());
}
@HandlerCommand(name = "task")
public void task(final InvokeCommandEvent e) {
final String pname = e.getArgs()[0];
final CommandSender sender = e.getSender();
final Plugin plugin = Bukkit.getPluginManager().getPlugin(pname);
if (plugin == null) {
sender.sendMessage("§c插件不存在!");
return;
}
final List<BukkitTask> pendingTasks = Bukkit.getScheduler().getPendingTasks();
sender.sendMessage("§6插件 §b" + pname + " §6的任务能耗如下!");
for (final BukkitTask pendingTask : pendingTasks) {
final Runnable task = Reflect.on(pendingTask).get("task");
if (task instanceof TaskInjector) {
final TaskInjector executor = (TaskInjector) task;
final StringBuffer str = new StringBuffer();
str.append("§6- §e" + task.getClass().getSimpleName() + " ");
str.append(String.format("§6总耗时: §a%.2f秒 ", executor.totalTime / 1000000.0));
str.append("§6执行次数: §b" + executor.count + "");
if (executor.count != 0) {
str.append(String.format("§6平均耗时: §d%.2f秒!", executor.totalTime / 1000000.0 / executor.count));
}
e.getSender().sendMessage(str.toString());
} else {
final TaskInjector taskInjector = new TaskInjector(task);
Reflect.on(pendingTask).set("task", taskInjector);
}
}
}
}

View File

@ -27,8 +27,6 @@ import cn.citycraft.PluginHelper.utils.StrKit;
import pw.yumc.Yum.Yum;
import pw.yumc.Yum.api.YumAPI;
import pw.yumc.Yum.managers.ConfigManager;
import pw.yumc.Yum.managers.PluginsManager;
import pw.yumc.Yum.managers.RepositoryManager;
import pw.yumc.Yum.models.RepoSerialization.Repositories;
/**
@ -39,13 +37,9 @@ import pw.yumc.Yum.models.RepoSerialization.Repositories;
*/
public class YumCommand implements HandlerCommands, Listener {
Yum main;
RepositoryManager repo;
PluginsManager plugman;
public YumCommand(final Yum yum) {
main = yum;
repo = YumAPI.getRepo();
plugman = YumAPI.getPlugman();
Bukkit.getPluginManager().registerEvents(this, yum);
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "yum");
cmdhandler.setAllCommandOnlyConsole(yum.getConfig().getBoolean("onlyCommandConsole", false));
@ -59,7 +53,7 @@ public class YumCommand implements HandlerCommands, Listener {
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) {
final String version = StringUtils.substring(plugin.getDescription().getVersion(), 0, 15);
if (plugman.deletePlugin(sender, plugin)) {
if (YumAPI.getPlugman().deletePlugin(sender, plugin)) {
sender.sendMessage("§c删除: §a插件 §b" + pluginname + " §a版本 §d" + version + " §a已从服务器卸载并删除!");
} else {
sender.sendMessage("§c删除: §a插件 §b" + pluginname + " §c卸载或删除时发生错误 删除失败!");
@ -91,7 +85,7 @@ public class YumCommand implements HandlerCommands, Listener {
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) {
final String version = StringUtils.substring(plugin.getDescription().getVersion(), 0, 15);
if (plugman.fullDeletePlugin(sender, plugin)) {
if (YumAPI.getPlugman().fullDeletePlugin(sender, plugin)) {
sender.sendMessage("§c删除: §a插件 §b" + pluginname + " §a版本 §d" + version + " §a已从服务器卸载并删除!");
} else {
sender.sendMessage("§c删除: §c插件 §b" + pluginname + " §c卸载或删除时发生错误 删除失败!");
@ -134,7 +128,7 @@ public class YumCommand implements HandlerCommands, Listener {
sender.sendMessage("§6 - §a" + perm.getName() + "§6 - §e" + (perm.getDescription().isEmpty() ? "无描述" : perm.getDescription()));
}
}
sender.sendMessage("§6插件物理路径: §3" + plugman.getPluginFile(plugin).getAbsolutePath());
sender.sendMessage("§6插件物理路径: §3" + YumAPI.getPlugman().getPluginFile(plugin).getAbsolutePath());
} else {
sender.sendMessage(pnf(pluginname));
}
@ -167,7 +161,7 @@ public class YumCommand implements HandlerCommands, Listener {
final CommandSender sender = e.getSender();
sender.sendMessage("§6[Yum仓库]§3服务器已安装插件: ");
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
sender.sendMessage("§6- " + plugman.getFormattedName(plugin, true));
sender.sendMessage("§6- " + YumAPI.getPlugman().getFormattedName(plugin, true));
}
}
@ -175,16 +169,16 @@ public class YumCommand implements HandlerCommands, Listener {
public List<String> listtab(final InvokeCommandEvent e) {
final String[] args = e.getArgs();
if (args[0].equalsIgnoreCase("install") || args[0].equalsIgnoreCase("i")) {
return StrKit.copyPartialMatches(args[1], repo.getAllPluginName(), new ArrayList<String>());
return StrKit.copyPartialMatches(args[1], YumAPI.getRepo().getAllPluginName(), new ArrayList<String>());
} else if (args[0].equalsIgnoreCase("repo")) {
if (args.length == 2) {
return StrKit.copyPartialMatches(args[1], Arrays.asList(new String[] { "add", "all", "list", "delall", "clean", "update", "del" }), new ArrayList<String>());
}
if (args.length == 3 && (args[1] == "add" || args[1] == "del")) {
return StrKit.copyPartialMatches(args[2], repo.getRepos().keySet(), new ArrayList<String>());
return StrKit.copyPartialMatches(args[2], YumAPI.getRepo().getRepos().keySet(), new ArrayList<String>());
}
} else {
return StrKit.copyPartialMatches(args[1], plugman.getPluginNames(false), new ArrayList<String>());
return StrKit.copyPartialMatches(args[1], YumAPI.getPlugman().getPluginNames(false), new ArrayList<String>());
}
return null;
}
@ -195,7 +189,7 @@ public class YumCommand implements HandlerCommands, Listener {
final String pluginname = e.getArgs()[0];
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin == null) {
plugman.load(sender, pluginname);
YumAPI.getPlugman().load(sender, pluginname);
} else {
sender.sendMessage("§c错误: §a插件 §b" + pluginname + " §c已加载到服务器!");
}
@ -218,12 +212,12 @@ public class YumCommand implements HandlerCommands, Listener {
}
final String pluginname = e.getArgs()[0];
if (pluginname.equalsIgnoreCase("all") || pluginname.equalsIgnoreCase("*")) {
plugman.reloadAll(sender);
YumAPI.getPlugman().reloadAll(sender);
return;
}
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) {
plugman.reload(sender, plugin);
YumAPI.getPlugman().reload(sender, plugin);
} else {
sender.sendMessage(pnf(pluginname));
}
@ -240,8 +234,8 @@ public class YumCommand implements HandlerCommands, Listener {
switch (cmd) {
case "add":
if (args.length == 2) {
if (repo.addRepositories(sender, args[1])) {
final String reponame = repo.getRepoCache(args[1]).name;
if (YumAPI.getRepo().addRepositories(sender, args[1])) {
final String reponame = YumAPI.getRepo().getRepoCache(args[1]).name;
sender.sendMessage("§6仓库: §a源仓库 §e" + reponame + " §a的插件信息已缓存!");
} else {
sender.sendMessage("§6仓库: §c源地址未找到仓库信息或当前地址已缓存!");
@ -252,9 +246,9 @@ public class YumCommand implements HandlerCommands, Listener {
break;
case "del":
if (args.length == 2) {
final Repositories delrepo = repo.getRepoCache(args[1]);
final Repositories delrepo = YumAPI.getRepo().getRepoCache(args[1]);
if (delrepo != null) {
repo.delRepositories(sender, args[1]);
YumAPI.getRepo().delRepositories(sender, args[1]);
sender.sendMessage("§6仓库: §a源仓库 §e" + delrepo.name + " §c已删除 §a请使用 §b/yum repo update §a更新缓存!");
} else {
sender.sendMessage("§6仓库: §c源地址未找到!");
@ -264,23 +258,23 @@ public class YumCommand implements HandlerCommands, Listener {
}
break;
case "delall":
repo.getRepoCache().getRepos().clear();
YumAPI.getRepo().getRepoCache().getRepos().clear();
sender.sendMessage("§6仓库: §a缓存的仓库信息已清理!");
break;
case "list":
sender.sendMessage("§6仓库: §b缓存的插件信息如下 ");
StrKit.sendStringArray(sender, repo.getAllPluginsInfo());
StrKit.sendStringArray(sender, YumAPI.getRepo().getAllPluginsInfo());
break;
case "all":
sender.sendMessage("§6仓库: §b缓存的仓库信息如下 ");
StrKit.sendStringArray(sender, repo.getRepoCache().getAllRepoInfo());
StrKit.sendStringArray(sender, YumAPI.getRepo().getRepoCache().getAllRepoInfo());
break;
case "clean":
repo.clean();
YumAPI.getRepo().clean();
sender.sendMessage("§6仓库: §a缓存的插件信息已清理!");
break;
case "update":
repo.updateRepositories(sender);
YumAPI.getRepo().updateRepositories(sender);
sender.sendMessage("§6仓库: §a仓库缓存数据已更新!");
break;
}
@ -335,7 +329,7 @@ public class YumCommand implements HandlerCommands, Listener {
final CommandSender sender = e.getSender();
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) {
plugman.unload(sender, plugin);
YumAPI.getPlugman().unload(sender, plugin);
} else {
sender.sendMessage(pnf(pluginname));
}
@ -347,7 +341,7 @@ public class YumCommand implements HandlerCommands, Listener {
final CommandSender sender = e.getSender();
switch (args.length) {
case 0:
repo.updateRepositories(sender);
YumAPI.getRepo().updateRepositories(sender);
sender.sendMessage("§6仓库: §a仓库缓存数据已更新!");
break;
case 1:
@ -393,7 +387,7 @@ public class YumCommand implements HandlerCommands, Listener {
@Override
public void run() {
if (args.length == 0) {
plugman.upgrade(sender);
YumAPI.getPlugman().upgrade(sender);
} else {
final String pluginname = args[0];
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);

View File

@ -0,0 +1,108 @@
package pw.yumc.Yum.inject;
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;
public class CommandInjector implements TabExecutor {
private final CommandExecutor originalExecutor;
private final TabCompleter originalCompleter;
public long totalTime;
public long 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);
}
}
}
PluginKit.scp("§a注入命令性能监控到 " + toInjectPlugin.getName());
}
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 add a more aggressive 10 ms cpu sample
final boolean result = originalExecutor.onCommand(sender, command, label, args);
final long end = System.nanoTime();
totalTime += end - start;
count++;
return result;
}
@Override
public List<String> onTabComplete(final CommandSender sender, final Command command, final String alias, final String[] args) {
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

@ -0,0 +1,61 @@
package pw.yumc.Yum.inject;
import java.util.List;
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 cn.citycraft.PluginHelper.ext.kit.Reflect;
public class ListenerInjector implements EventExecutor {
private final EventExecutor originalExecutor;
public long totalTime;
public long count;
public ListenerInjector(final EventExecutor originalExecutor) {
this.originalExecutor = originalExecutor;
}
public static void inject(final Plugin plugin) {
final List<RegisteredListener> listeners = HandlerList.getRegisteredListeners(plugin);
for (final RegisteredListener listener : listeners) {
final EventExecutor originalExecutor = Reflect.on(listener).get("executor");
final ListenerInjector listenerInjector = new ListenerInjector(originalExecutor);
Reflect.on(listener).set("executor", listenerInjector);
}
}
public static void uninject(final Plugin plugin) {
final List<RegisteredListener> listeners = HandlerList.getRegisteredListeners(plugin);
for (final RegisteredListener listener : listeners) {
final ListenerInjector executor = Reflect.on(listener).get("executor");
Reflect.on(listener).set("executor", executor.getOriginalExecutor());
}
}
@Override
public void execute(final Listener listener, final Event event) throws EventException {
if (!event.isAsynchronous()) {
final long start = System.nanoTime();
// todo add a more aggressive 10 ms cpu sample
originalExecutor.execute(listener, event);
final long end = System.nanoTime();
totalTime += end - start;
count++;
} else {
originalExecutor.execute(listener, event);
}
}
public EventExecutor getOriginalExecutor() {
return originalExecutor;
}
}

View File

@ -0,0 +1,64 @@
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 long count;
public TaskInjector(final Runnable originalTask) {
this.originalTask = originalTask;
}
// sadly it works only with interval tasks
// for single runs we would have to register a dynamic proxy
public static void inject(final Plugin plugin) {
final BukkitScheduler scheduler = Bukkit.getScheduler();
final List<BukkitTask> pendingTasks = scheduler.getPendingTasks();
for (final BukkitTask pendingTask : pendingTasks) {
// we could ignore async tasks for now
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
final Runnable originalTask = Reflect.on(pendingTask).get("task");
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<BukkitTask> pendingTasks = scheduler.getPendingTasks();
for (final BukkitTask pendingTask : pendingTasks) {
// we could ignore async tasks for now
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
final TaskInjector originalTask = Reflect.on(pendingTask).get("task");
Reflect.on(pendingTask).set("task", originalTask.getOriginalTask());
}
}
}
public Runnable getOriginalTask() {
return originalTask;
}
@Override
public void run() {
final long start = System.nanoTime();
// todo add a more aggressive 10 ms cpu sample
originalTask.run();
final long end = System.nanoTime();
totalTime += end - start;
count++;
}
}

View File

@ -0,0 +1,32 @@
package pw.yumc.Yum.listeners;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import cn.citycraft.PluginHelper.kit.PKit;
import pw.yumc.Yum.api.YumAPI;
/**
*
* @since 2016年7月6日 下午6:44:16
* @author
*/
public class PluginListener implements Listener {
public PluginListener() {
Bukkit.getPluginManager().registerEvents(this, PKit.i());
}
@EventHandler
public void onPluginDisable(final PluginDisableEvent e) {
YumAPI.uninject(e.getPlugin());
}
@EventHandler
public void onPluginEnable(final PluginEnableEvent e) {
YumAPI.inject(e.getPlugin());
}
}

View File

@ -15,7 +15,9 @@ import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldSaveEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.plugin.Plugin;
import cn.citycraft.PluginHelper.kit.PluginKit;
import pw.yumc.Yum.Yum;
/**
@ -87,7 +89,10 @@ public class ThreadSafetyListener implements Listener {
private void checkSafety(final Event eventType) {
if (Yum.mainThread != null && Thread.currentThread() != Yum.mainThread && !eventType.isAsynchronous()) {
final String eventName = eventType.getEventName();
throw new IllegalAccessError("[Yum 线程安全]: 请勿异步调用一个同步事件 " + eventName);
final Plugin plugin = PluginKit.getOperatePlugin();
if (plugin != null) {
throw new IllegalAccessError("[Yum 线程安全]: 请勿异步调用一个同步事件 " + eventName + " 操作插件: " + plugin.getName());
}
}
}
}

View File

@ -6,13 +6,23 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import cn.citycraft.PluginHelper.PluginHelperLogger;
import cn.citycraft.PluginHelper.kit.PKit;
import cn.citycraft.PluginHelper.utils.IOUtil;
import pw.yumc.Yum.models.RepoSerialization.Plugin;
import pw.yumc.Yum.models.RepoSerialization.TagInfo;
import pw.yumc.Yum.models.RepoSerialization.URLType;
public class PluginInfo implements Serializable {
public static final String NMSVersion = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
public static String NMSVersion;
static {
try {
NMSVersion = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
} catch (final Exception e) {
PKit.i().getLogger().warning("服务器NMS解析失败: " + Bukkit.getServer().getClass().getPackage().getName());
NMSVersion = "NONMS";
}
}
public String branch;
public String name;
@ -78,10 +88,7 @@ public class PluginInfo implements Serializable {
* @return 更新地址
*/
public String getMavenUrl(final String ver) {
return String.format(url + (url.endsWith("/") ? "" : "/") + "%1$s/%2$s/%3$s/%2$s-%3$s.jar",
plugin.groupId.replace(".", "/"),
plugin.artifactId,
(ver == null || ver.isEmpty()) ? plugin.version : ver);
return String.format(url + (url.endsWith("/") ? "" : "/") + "%1$s/%2$s/%3$s/%2$s-%3$s.jar", plugin.groupId.replace(".", "/"), plugin.artifactId, (ver == null || ver.isEmpty()) ? plugin.version : ver);
}
public String getUrl(final CommandSender sender, final String version) {

View File

View File

@ -30,6 +30,12 @@ commands:
usage: §6使用§a/security help§6查看帮助!
permission: security.use
permission-message: §c你没有 <permission> 的权限来执行此命令!
monitor:
description: MC系统监控命令
aliases: [m]
usage: §6使用§a/monitor help§6查看帮助!
permission: monitor.use
permission-message: §c你没有 <permission> 的权限来执行此命令!
permissions:
yum.use:
description: 插件管理系统使用权限!