feat: 去除加载器注入 异步获取主线程

Signed-off-by: 502647092 <admin@yumc.pw>
dev
502647092 2016-09-08 07:52:02 +08:00
parent 887919552d
commit 340d457e41
12 changed files with 109 additions and 234 deletions

View File

@ -67,8 +67,8 @@
<update.changes>
§c注意 §6- §aYum更新需要§d重启服务器!§c重启服务器!§4重启服务器!;
§b2.7.7 §6- §c修复部分插件重载时提示Plugin already initialized的问题!;
§6- §c修复§eBukkitDev§c下载地址跳转问题...;
§6- §c修复§eBukkitDev§c下载为空时的异常...;
§6- §c修复§eBukkitDev§c下载地址跳转问题...;
§6- §c修复§eBukkitDev§c下载为空时的异常...;
</update.changes>
<env.GIT_COMMIT>DEBUG</env.GIT_COMMIT>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

View File

@ -11,13 +11,13 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import cn.citycraft.CommonData.UpdatePlugin;
import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit;
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.inject.YumPluginLoader;
import pw.yumc.Yum.listeners.PluginListener;
import pw.yumc.Yum.listeners.PluginNetworkListener;
import pw.yumc.Yum.listeners.SecurityListener;
@ -39,8 +39,6 @@ public class Yum extends JavaPlugin {
public static Thread mainThread = null;
public static Timer task = new Timer();
public static TimerTask tt;
private static boolean isLoad = false;
private static boolean isEnable = false;
@Override
public FileConfiguration getConfig() {
@ -54,35 +52,38 @@ public class Yum extends JavaPlugin {
@Override
public void onEnable() {
if (!isEnable) {
if (Bukkit.isPrimaryThread()) {
mainThread = Thread.currentThread();
}
new YumAPI();
initCommands();
initListeners();
initRunnable();
MonitorManager.init();
new Statistics();
new SubscribeTask();
YumAPI.updateRepo(Bukkit.getConsoleSender());
YumAPI.updateCheck(Bukkit.getConsoleSender());
if (Bukkit.isPrimaryThread()) {
mainThread = Thread.currentThread();
} else {
mainThread = getMainThread();
}
new YumAPI();
initCommands();
initListeners();
initRunnable();
MonitorManager.init();
new Statistics();
new SubscribeTask();
YumAPI.updateRepo(Bukkit.getConsoleSender());
YumAPI.updateCheck(Bukkit.getConsoleSender());
}
@Override
public void onLoad() {
if (!isLoad) {
// 初始化配置
ConfigManager.i();
// 注入插件加载器
YumPluginLoader.inject();
// 初始化更新列
UpdatePlugin.getUpdateList();
// 启用网络注入
NetworkManager.register(this);
isLoad = true;
}
// 初始化配置
ConfigManager.i();
// 初始化更新列
UpdatePlugin.getUpdateList();
// 启用网络注入
NetworkManager.register(this);
}
/**
* @return 线
*/
private Thread getMainThread() {
final Object console = Reflect.on(Bukkit.getServer()).get("console");
return Reflect.on(console).get("primaryThread");
}
/**

View File

@ -236,6 +236,13 @@ public class MonitorCommand implements CommandExecutor {
sender.sendMessage(reinject);
}
@Cmd
@Help("重置能耗监控器")
@Async
public void reset(final CommandArgument e) {
MonitorManager.init();
}
@Cmd(aliases = "t", minimumArguments = 1)
@Help(value = "查看插件任务能耗", possibleArguments = "[插件名称]")
@Async

View File

@ -21,6 +21,7 @@ import org.bukkit.plugin.java.JavaPlugin;
import cn.citycraft.PluginHelper.callback.CallBack.One;
import cn.citycraft.PluginHelper.kit.PluginKit;
import cn.citycraft.PluginHelper.kit.ZipKit;
import cn.citycraft.PluginHelper.utils.FileUtil;
import cn.citycraft.PluginHelper.utils.IOUtil;
import cn.citycraft.PluginHelper.utils.StrKit;
import pw.yumc.Yum.Yum;
@ -30,7 +31,6 @@ import pw.yumc.Yum.models.BukkitDev;
import pw.yumc.Yum.models.BukkitDev.Files;
import pw.yumc.Yum.models.BukkitDev.Projects;
import pw.yumc.Yum.models.RepoSerialization.Repositories;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.commands.CommandArgument;
import pw.yumc.YumCore.commands.CommandExecutor;
import pw.yumc.YumCore.commands.CommandManager;
@ -66,6 +66,7 @@ public class YumCommand implements Listener, CommandExecutor {
private final String look = "§6查看";
private final String install = "§a安装";
private final String install_tip = "§a点击安装";
private final String update = "§a更新";
private final String unload = "§d卸载";
private final String reload = "§6重载";
@ -105,6 +106,7 @@ public class YumCommand implements Listener, CommandExecutor {
tr.text(String.format(filelist, f.name, f.gameVersion, f.releaseType));
tr.then(" ");
tr.then(install).command(String.format("/yum br ai %s %s", f.name, f.downloadUrl));
tr.tip(install_tip);
tr.send(sender);
}
break;
@ -184,6 +186,20 @@ public class YumCommand implements Listener, CommandExecutor {
}
}
@Cmd(aliases = "ddel", minimumArguments = 1)
@Help(value = "删除插件数据文件夹", possibleArguments = "<插件名称>")
@Sort(7)
public void dirdelete(final CommandArgument e) {
final String pluginname = e.getArgs()[0];
final CommandSender sender = e.getSender();
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) {
FileUtil.deleteDir(sender, plugin.getDataFolder());
} else {
sender.sendMessage(pnf(pluginname));
}
}
@Cmd(aliases = "f", minimumArguments = 1)
@Help(value = "通过类名查找插件", possibleArguments = "<插件类名>")
@Sort(10)
@ -298,13 +314,13 @@ public class YumCommand implements Listener, CommandExecutor {
final Tellraw fm = Tellraw.create();
fm.text(String.format("§6- %-32s", YumAPI.getPlugman().getFormattedName(plugin, true)));
fm.then(" ");
fm.then(update).command("/yum u " + pname);
fm.then(update).cmd_tip("/yum u " + pname, update);
fm.then(" ");
fm.then(unload).command("/yum unload " + pname);
fm.then(unload).cmd_tip("/yum unload " + pname, unload);
fm.then(" ");
fm.then(reload).command("/yum re " + pname);
fm.then(reload).cmd_tip("/yum re " + pname, reload);
fm.then(" ");
fm.then(delete).command("/yum del " + pname);
fm.then(delete).cmd_tip("/yum del " + pname, delete);
fm.send(sender);
}
}
@ -433,17 +449,11 @@ public class YumCommand implements Listener, CommandExecutor {
final Tellraw fm = Tellraw.create();
fm.text(String.format(bukkitlist, p.id, p.name, p.stage));
fm.then(" ");
fm.then(look).command("/yum br look " + p.id);
fm.then(look).cmd_tip("/yum br look " + p.id, look);
fm.send(sender);
}
}
@Cmd
public void test(final CommandArgument e) {
Log.toSender(e.getSender(), "Test");
Log.toSender(e.getSender(), new String[] { "Test1", "Test2", "Test3" });
}
@Cmd(minimumArguments = 1)
@Help(value = "卸载插件", possibleArguments = "<插件名称>")
@Sort(4)

View File

@ -1,146 +0,0 @@
/**
* Created on 17 May 2014 by _MylesC
* Copyright 2014
*/
package pw.yumc.Yum.inject;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.event.Event;
import org.bukkit.event.Listener;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.InvalidPluginException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredListener;
import org.bukkit.plugin.UnknownDependencyException;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
public class YumPluginLoader implements PluginLoader {
private static boolean isInit = false;
private static final String needRestart = "§6[§bYum§6] §c由于修改了服务器内部文件 §bYum §c无法直接重载 §4请重启服务器!";
private static final YumPluginLoader yumPluginLoader = new YumPluginLoader(Bukkit.getServer());
public final JavaPluginLoader internal_loader;
private final Server server;
@SuppressWarnings("deprecation")
public YumPluginLoader(final Server instance) {
server = instance;
internal_loader = new JavaPluginLoader(instance);
}
public static void inject() {
injectExistingPlugins(yumPluginLoader);
replaceJavaPluginLoaders(yumPluginLoader);
}
public static void inject(final String pname) {
injectExistingPlugin(Bukkit.getPluginManager().getPlugin(pname), yumPluginLoader);
replaceJavaPluginLoaders(yumPluginLoader);
}
private static void injectExistingPlugin(final Plugin p, final YumPluginLoader yumPluginLoader) {
if (p != null && p instanceof JavaPlugin) {
final JavaPlugin jp = (JavaPlugin) p;
try {
final Field f = JavaPlugin.class.getDeclaredField("loader");
f.setAccessible(true);
f.set(jp, yumPluginLoader);
} catch (final Exception e) {
Bukkit.getServer().getLogger().log(Level.SEVERE, "Yum failed injecting " + jp.getDescription().getFullName() + " with the new PluginLoader, contact the developers on YUMC!", e);
}
}
}
private static void injectExistingPlugins(final YumPluginLoader yumPluginLoader) {
for (final org.bukkit.plugin.Plugin p : Bukkit.getPluginManager().getPlugins()) {
injectExistingPlugin(p, yumPluginLoader);
}
}
private static void replaceJavaPluginLoaders(final YumPluginLoader yumPluginLoader) {
final PluginManager spm = Bukkit.getPluginManager();
try {
final Field field = spm.getClass().getDeclaredField("fileAssociations");
field.setAccessible(true);
final Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
@SuppressWarnings("unchecked")
final Map<Pattern, PluginLoader> map = (Map<Pattern, PluginLoader>) field.get(spm);
final Iterator<Map.Entry<Pattern, PluginLoader>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
final Entry<Pattern, PluginLoader> entry = iter.next();
entry.setValue(yumPluginLoader);
}
field.set(spm, map);
} catch (final Exception e) {
Bukkit.getServer().getLogger().log(Level.SEVERE, "Yum failed replacing the existing PluginLoader, contact the developers on YUMC!", e);
}
}
@Override
public Map<Class<? extends Event>, Set<RegisteredListener>> createRegisteredListeners(final Listener listener, final Plugin plugin) {
return internal_loader.createRegisteredListeners(listener, plugin);
}
@Override
public void disablePlugin(final Plugin plugin) {
if (plugin.getName().equalsIgnoreCase("Yum")) {
Bukkit.getConsoleSender().sendMessage(needRestart);
} else {
internal_loader.disablePlugin(plugin);
}
}
@Override
public void enablePlugin(final Plugin plugin) {
if (plugin.getName().equalsIgnoreCase("Yum")) {
if (isInit) {
Bukkit.getConsoleSender().sendMessage(needRestart);
} else {
internal_loader.enablePlugin(plugin);
isInit = true;
}
} else {
internal_loader.enablePlugin(plugin);
}
}
@Override
public PluginDescriptionFile getPluginDescription(final File arg0) throws InvalidDescriptionException {
return internal_loader.getPluginDescription(arg0);
}
@Override
public Pattern[] getPluginFileFilters() {
return internal_loader.getPluginFileFilters();
}
@Override
public Plugin loadPlugin(final File file) throws InvalidPluginException, UnknownDependencyException {
try {
final PluginDescriptionFile description = getPluginDescription(file);
if (description.getName().equalsIgnoreCase("Yum")) {
Bukkit.getConsoleSender().sendMessage(needRestart);
return null;
}
} catch (final InvalidDescriptionException ex) {
}
return internal_loader.loadPlugin(file);
}
}

View File

@ -40,6 +40,6 @@ public class PluginListener implements Listener {
public void run() {
YumAPI.inject(e.getPlugin());
}
}, 60);
}, 2);
}
}

View File

@ -65,7 +65,6 @@ public class ThreadSafetyListener implements Listener {
checkSafety(quitEvent);
}
@EventHandler
public void onPlayerTeleport(final PlayerTeleportEvent teleportEvent) {
checkSafety(teleportEvent);
}

View File

@ -161,12 +161,13 @@ public class DownloadManager {
}
}
final int fileLength = uc.getContentLength();
if (fileLength < 0) {
final boolean dyml = "chunked".equalsIgnoreCase(uc.getHeaderField("Transfer-Encoding"));
if (fileLength < 0 && !dyml) {
sender.sendMessage("§6下载: §c文件 " + file.getName() + " 获取长度错误(可能是网络问题)!");
sender.sendMessage("§6文件: §c" + file.getName() + " 下载失败!");
return false;
}
sender.sendMessage("§6文件长度: §3" + fileLength);
sender.sendMessage("§6文件长度: §3" + (dyml ? "动态长度" : fileLength));
in = new BufferedInputStream(uc.getInputStream());
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
@ -185,12 +186,19 @@ public class DownloadManager {
while ((count = in.read(data)) != -1) {
downloaded += count;
fout.write(data, 0, count);
final int percent = (int) (downloaded * 100L / fileLength);
if (percent % 10 == 0) {
if (System.currentTimeMillis() - time > 500) {
sender.sendMessage(String.format("§6已下载: §a" + getPer(percent / 10) + " %s%%", percent));
if (dyml) {
if (System.currentTimeMillis() - time > 1000) {
sender.sendMessage(String.format("§6已下载: §a%sk", downloaded / 1024));
time = System.currentTimeMillis();
}
} else {
final int percent = (int) (downloaded * 100L / fileLength);
if (percent % 10 == 0) {
if (System.currentTimeMillis() - time > 500) {
sender.sendMessage(String.format("§6已下载: §a" + getPer(percent / 10) + " %s%%", percent));
time = System.currentTimeMillis();
}
}
}
}
String pVer = null;

View File

@ -19,7 +19,8 @@ import cn.citycraft.PluginHelper.kit.LogKit;
import cn.citycraft.PluginHelper.kit.PluginKit;
/**
*
*
*
* @since 2016719 3:55:54
* @author
*/

View File

@ -15,8 +15,6 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
@ -32,14 +30,11 @@ import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.UnknownDependencyException;
import org.bukkit.plugin.java.JavaPluginLoader;
import com.google.common.base.Joiner;
import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.utils.FileUtil;
import cn.citycraft.PluginHelper.utils.StringUtil;
import pw.yumc.Yum.inject.YumPluginLoader;
/**
*
@ -547,14 +542,11 @@ public class PluginsManager {
sender = Bukkit.getConsoleSender();
}
final PluginManager pluginManager = Bukkit.getPluginManager();
if ("Yum".equalsIgnoreCase(name)) {
return true;
}
SimpleCommandMap commandMap = null;
List<Plugin> plugins = null;
Map<String, Plugin> lookupNames = null;
Map<String, Command> knownCommands = null;
Map<Pattern, JavaPluginLoader> fileAssociations = null;
// final Map<Pattern, JavaPluginLoader> fileAssociations = null;
if (pluginManager == null) {
sender.sendMessage("§4异常: §c插件管理类反射获取失败!");
return false;
@ -576,9 +568,9 @@ public class PluginsManager {
knownCommandsField.setAccessible(true);
knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
final Field fileAssociationsField = pluginManager.getClass().getDeclaredField("fileAssociations");
fileAssociationsField.setAccessible(true);
fileAssociations = (Map<Pattern, JavaPluginLoader>) fileAssociationsField.get(pluginManager);
// final Field fileAssociationsField = pluginManager.getClass().getDeclaredField("fileAssociations");
// fileAssociationsField.setAccessible(true);
// fileAssociations = (Map<Pattern, JavaPluginLoader>) fileAssociationsField.get(pluginManager);
} catch (final Exception e) {
sender.sendMessage("§4异常: §c" + e.getMessage() + " 插件 §b" + name + " §c卸载失败!");
@ -609,28 +601,28 @@ public class PluginsManager {
}
}
}
try {
if (fileAssociations != null) {
for (final Entry<Pattern, JavaPluginLoader> entry : fileAssociations.entrySet()) {
final Matcher match = entry.getKey().matcher(getPluginFile(next).getName());
if (match.find()) {
PluginLoader pluginLoader = entry.getValue();
if (pluginLoader instanceof YumPluginLoader) {
pluginLoader = ((YumPluginLoader) pluginLoader).internal_loader;
}
final Field loadersField = pluginLoader.getClass().getDeclaredField("loaders");
loadersField.setAccessible(true);
final Map<String, URLClassLoader> loaders = (Map<String, URLClassLoader>) loadersField.get(pluginLoader);
for (final Entry<String, URLClassLoader> entry2 : loaders.entrySet()) {
Reflect.on(entry2.getValue()).set("pluginInit", null).set("plugin", null);
}
sender.sendMessage("§6卸载: §a移除插件 §b" + name + " §a的类实例缓存!");
}
}
}
} catch (final Exception e) {
e.printStackTrace();
}
// try {
// if (fileAssociations != null) {
// for (final Entry<Pattern, JavaPluginLoader> entry : fileAssociations.entrySet()) {
// final Matcher match = entry.getKey().matcher(getPluginFile(next).getName());
// if (match.find()) {
// PluginLoader pluginLoader = entry.getValue();
// if (pluginLoader instanceof YumPluginLoader) {
// pluginLoader = ((YumPluginLoader) pluginLoader).internal_loader;
// }
// final Field loadersField = pluginLoader.getClass().getDeclaredField("loaders");
// loadersField.setAccessible(true);
// final Map<String, URLClassLoader> loaders = (Map<String, URLClassLoader>) loadersField.get(pluginLoader);
// for (final Entry<String, URLClassLoader> entry2 : loaders.entrySet()) {
// Reflect.on(entry2.getValue()).set("pluginInit", null).set("plugin", null);
// }
// sender.sendMessage("§6卸载: §a移除插件 §b" + name + " §a的类实例缓存!");
// }
// }
// }
// } catch (final Exception e) {
// e.printStackTrace();
// }
sender.sendMessage("§6卸载: §a注销插件 §b" + name + " §a的所有命令!");
final ClassLoader cl = next.getClass().getClassLoader();
try {
@ -690,6 +682,9 @@ public class PluginsManager {
sender.sendMessage("§4异常: §c文件夹 §d服务器更新文件夹 §c未找到或IO错误!");
return false;
}
if (!updateDirectory.exists()) {
updateDirectory.mkdirs();
}
try {
sender.sendMessage("§6升级: §b从 §d" + updateDirectory.getCanonicalPath() + " §b文件夹检索插件插件!");
} catch (SecurityException | IOException e1) {

View File

@ -198,7 +198,7 @@ public class RepositoryManager {
sender = Bukkit.getConsoleSender();
}
if (repocenter == null || repocenter.repos.isEmpty()) {
sender.sendMessage("源地址为Null或源列表为空!");
sender.sendMessage(String.format("§6[§bYum§6] 源 %s 数据为空或列表为空!", repocenter.name));
return false;
}
for (final Repository repo : repocenter.repos) {

View File

@ -49,12 +49,12 @@ public class RepoCache implements Serializable {
public Repositories getRepo(final String repo) {
final String json = IOUtil.getData(repo);
if (json == null || json.isEmpty()) {
PluginKit.sc(c源地址获取数据为空 §b" + repo);
PluginKit.sc(6[§bYum§6] §c源地址获取数据为空 §b" + repo);
return null;
}
final Repositories reposes = new Repositories((JSONObject) JSONValue.parse(json));
if (reposes == null || reposes.repos.isEmpty()) {
PluginKit.sc(c源地址解析Json为空 §b" + repo);
if (reposes.repos.isEmpty()) {
PluginKit.sc(6[§bYum§6] §c源地址解析Json为空 §b" + repo);
return null;
}
return reposes;