Delete Plugin.java
This commit is contained in:
parent
3d6bcac699
commit
f8c028e12d
445
Plugin.java
445
Plugin.java
@ -1,445 +0,0 @@
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.izzel.taboolib.PluginLoader;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* @Author 坏黑
|
||||
* @Since 2019-07-05 9:03
|
||||
*/
|
||||
public abstract class Plugin extends JavaPlugin {
|
||||
|
||||
/**
|
||||
* 版本信息获取地址
|
||||
* 优先采用国内地址
|
||||
* 防止部分机器封禁海外访问
|
||||
*/
|
||||
public static final String[][] URL = {
|
||||
{
|
||||
"https://skymc.oss-cn-shanghai.aliyuncs.com/plugins/latest.json",
|
||||
"https://skymc.oss-cn-shanghai.aliyuncs.com/plugins/TabooLib.jar"
|
||||
},
|
||||
{
|
||||
"https://api.github.com/repos/Bkm016/TabooLib/releases/latest",
|
||||
"https://github.com/Bkm016/TabooLib/releases/latest/download/TabooLib.jar",
|
||||
},
|
||||
};
|
||||
|
||||
protected static Plugin plugin;
|
||||
protected static File libFile = new File("TabooLib.jar");
|
||||
|
||||
/**
|
||||
* 插件在初始化过程中出现错误
|
||||
* 将在 onLoad 方法下关闭插件
|
||||
*/
|
||||
protected static boolean initFailed;
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onLoad() {
|
||||
if (initFailed) {
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
plugin = this;
|
||||
PluginLoader.addPlugin(this);
|
||||
PluginLoader.load(this);
|
||||
try {
|
||||
onLoading();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onEnable() {
|
||||
if (initFailed) {
|
||||
return;
|
||||
}
|
||||
PluginLoader.start(this);
|
||||
try {
|
||||
onStarting();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
Bukkit.getScheduler().runTask(this, () -> {
|
||||
PluginLoader.active(this);
|
||||
onActivated();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onDisable() {
|
||||
if (initFailed) {
|
||||
return;
|
||||
}
|
||||
PluginLoader.stop(this);
|
||||
try {
|
||||
onStopping();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 代替 JavaPlugin 本身的 onLoad 方法
|
||||
*/
|
||||
public void onLoading() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 代替 JavaPlugin 本身的 onEnable 方法
|
||||
*/
|
||||
public void onStarting() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 代替 JavaPlugin 本身的 onDisable 方法
|
||||
*/
|
||||
public void onStopping() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 当服务端完全启动时执行该方法
|
||||
* 完全启动指 "控制台可以输入命令且得到反馈时"
|
||||
* <p>
|
||||
* 使用 @TSchedule 同样可以代替该方法
|
||||
*/
|
||||
public void onActivated() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 TabooLib 是否已经被载入
|
||||
* 跳过 TabooLib 主类的初始化过程
|
||||
*/
|
||||
public static boolean isLoaded() {
|
||||
try {
|
||||
return Class.forName("io.izzel.taboolib.TabooLib", false, Bukkit.class.getClassLoader()) != null;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 TabooLib 当前运行版本
|
||||
*/
|
||||
public static double getVersion() {
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(libFile);
|
||||
return NumberConversions.toDouble(readFully(zipFile.getInputStream(zipFile.getEntry("version")), StandardCharsets.UTF_8));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 TabooLib 当前最新版本
|
||||
* 获取内容为版本号+访问地址+下载地址
|
||||
*/
|
||||
public static String[] getNewVersion() {
|
||||
for (String[] url : URL) {
|
||||
String read = readFromURL(url[0]);
|
||||
if (read == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
JsonObject jsonObject = (JsonObject) new JsonParser().parse(read);
|
||||
if (jsonObject.has("tag_name")) {
|
||||
return new String[] {jsonObject.get("tag_name").getAsString(), url[0], url[1]};
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件读取至内存中
|
||||
* 读取后不会随着插件的卸载而卸载
|
||||
* 请在执行前判断是否已经被读取
|
||||
* 防止出现未知错误
|
||||
*/
|
||||
private static void addToPath(File file) {
|
||||
try {
|
||||
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(Bukkit.class.getClassLoader(), file.toURI().toURL());
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean downloadFile(String in, File file) {
|
||||
try (InputStream inputStream = new URL(in).openStream(); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
|
||||
toFile(bufferedInputStream, file);
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static File toFile(String in, File file) {
|
||||
try (FileWriter fileWriter = new FileWriter(file); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) {
|
||||
bufferedWriter.write(in);
|
||||
bufferedWriter.flush();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private static File toFile(InputStream inputStream, File file) {
|
||||
try (FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = inputStream.read(buf)) > 0) {
|
||||
bos.write(buf, 0, len);
|
||||
}
|
||||
bos.flush();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private static String readFromURL(String in, String def) {
|
||||
return Optional.ofNullable(readFromURL(in)).orElse(def);
|
||||
}
|
||||
|
||||
private static String readFromURL(String in) {
|
||||
try (InputStream inputStream = new URL(in).openStream(); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
|
||||
return new String(readFully(bufferedInputStream));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String readFully(InputStream inputStream, Charset charset) throws IOException {
|
||||
return new String(readFully(inputStream), charset);
|
||||
}
|
||||
|
||||
private static byte[] readFully(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[1024];
|
||||
int len = 0;
|
||||
while ((len = inputStream.read(buf)) > 0) {
|
||||
stream.write(buf, 0, len);
|
||||
}
|
||||
return stream.toByteArray();
|
||||
}
|
||||
|
||||
private static Class<?> getMainClass() {
|
||||
File file = file(new File("plugins/TabooLib/temp/" + UUID.randomUUID()));
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(toFile(Plugin.class.getProtectionDomain().getCodeSource().getLocation().openStream(), file));
|
||||
return Class.forName(YamlConfiguration.loadConfiguration(new InputStreamReader(zipFile.getInputStream(zipFile.getEntry("plugin.yml")))).getString("main"));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class getCaller(Class<?> obj) {
|
||||
try {
|
||||
return Class.forName(Thread.currentThread().getStackTrace()[3].getClassName(), false, obj.getClassLoader());
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static File file(File file) {
|
||||
if (!file.exists()) {
|
||||
folder(file);
|
||||
try {
|
||||
file.createNewFile();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private static File folder(File file) {
|
||||
if (!file.exists()) {
|
||||
String filePath = file.getPath();
|
||||
int index = filePath.lastIndexOf(File.separator);
|
||||
String folderPath;
|
||||
File folder;
|
||||
if ((index >= 0) && (!(folder = new File(filePath.substring(0, index))).exists())) {
|
||||
folder.mkdirs();
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private static void deepDelete(File file) {
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
if (file.isFile()) {
|
||||
file.delete();
|
||||
return;
|
||||
}
|
||||
for (File file1 : Objects.requireNonNull(file.listFiles())) {
|
||||
deepDelete(file1);
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
private static void init() {
|
||||
// 检查 TabooLib 文件是否存在
|
||||
if (!libFile.exists()) {
|
||||
// 本地资源检测
|
||||
InputStream resourceAsStream = Plugin.class.getClassLoader().getResourceAsStream("TabooLib.jar");
|
||||
if (resourceAsStream != null) {
|
||||
// 写入文件
|
||||
toFile(resourceAsStream, libFile);
|
||||
}
|
||||
// 在线资源下载
|
||||
else if (!download()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 检查 TabooLib 运行版本是否正常
|
||||
else {
|
||||
double version = getVersion();
|
||||
// 本地版本获取失败
|
||||
if (version == -1) {
|
||||
// 重新下载文件,如果下载失败则停止加载
|
||||
if (!download()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Class<?> mainClass = getMainClass();
|
||||
if (mainClass != null && mainClass.isAnnotationPresent(Version.class)) {
|
||||
double requireVersion = mainClass.getAnnotation(Version.class).value();
|
||||
// 依赖版本高于当前运行版本
|
||||
if (requireVersion > version) {
|
||||
// 获取版本信息
|
||||
String[] newVersion = getNewVersion();
|
||||
if (newVersion == null) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
// 检查依赖版本是否合理
|
||||
// 如果插件使用不合理的版本则跳过下载防止死循环
|
||||
// 并跳过插件加载
|
||||
if (requireVersion > NumberConversions.toInt(newVersion[0])) {
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c版本 §4" + requireVersion + " §c无法获取.");
|
||||
initFailed = true;
|
||||
return;
|
||||
}
|
||||
Bukkit.getConsoleSender().sendMessage("§f[TabooLib] §7正在重新下载资源文件.");
|
||||
if (downloadFile(newVersion[2], libFile)) {
|
||||
// 如果资源下载成功则重启服务器
|
||||
restart();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 检查 TabooLib 是否已经被加载
|
||||
if (!isLoaded()) {
|
||||
// 将 TabooLib 通过 Bukkit.class 类加载器加载至内存中供其他插件使用
|
||||
// 并保证在热重载过程中不会被 Bukkit 卸载
|
||||
addToPath(libFile);
|
||||
// 初始化 TabooLib 主类
|
||||
try {
|
||||
Class.forName("io.izzel.taboolib.TabooLib");
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
// 清理临时文件
|
||||
deepDelete(new File("plugins/TabooLib/temp"));
|
||||
}
|
||||
|
||||
private static boolean download() {
|
||||
Bukkit.getConsoleSender().sendMessage("§f[TabooLib] §7正在下载资源文件.");
|
||||
String[] newVersion = getNewVersion();
|
||||
if (newVersion == null || !downloadFile(newVersion[2], libFile)) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void close() {
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c#################### 错误 ####################");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 初始化 §4TabooLib §c失败!");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 无法获取版本信息或下载时出现错误.");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 请检查网络连接.");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 服务端将在 5 秒后继续启动.");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c#################### 错误 ####################");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
try {
|
||||
Thread.sleep(5000L);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
initFailed = true;
|
||||
}
|
||||
|
||||
private static void restart() {
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c#################### 警告 ####################");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 初始化 §4TabooLib §c失败!");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 当前运行的版本低于插件所需版本.");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 已下载最新版.");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c 服务端将在 5 秒后重新启动.");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c#################### 警告 ####################");
|
||||
Bukkit.getConsoleSender().sendMessage("§4[TabooLib] §c");
|
||||
try {
|
||||
Thread.sleep(5000L);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
initFailed = true;
|
||||
Bukkit.shutdown();
|
||||
}
|
||||
|
||||
public static Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public static File getLibFile() {
|
||||
return libFile;
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Version {
|
||||
|
||||
double value();
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user