From 30d0a18dbdaba7046d377d75e82dfb1659d98b42 Mon Sep 17 00:00:00 2001 From: LT_Name <572413378@qq.com> Date: Sun, 25 Dec 2022 15:52:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86GameCore=E4=B8=8B=E8=BD=BD=E6=95=B4?= =?UTF-8?q?=E5=90=88=E5=88=B0GameCoreDownload=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 1 + src/main/java/com/smallaswater/npc/RsNPC.java | 38 +-- .../com/smallaswater/npc/utils/Download.java | 146 ---------- .../npc/utils/GameCoreDownload.java | 261 ++++++++++++++++++ .../com/smallaswater/npc/utils/Utils.java | 86 +----- 5 files changed, 269 insertions(+), 263 deletions(-) delete mode 100644 src/main/java/com/smallaswater/npc/utils/Download.java create mode 100644 src/main/java/com/smallaswater/npc/utils/GameCoreDownload.java diff --git a/pom.xml b/pom.xml index d884fd3..d10de93 100644 --- a/pom.xml +++ b/pom.xml @@ -141,6 +141,7 @@ ${project.basedir}/src/main/resources/plugin.yml ${project.basedir}/src/main/java/com/smallaswater/npc/RsNPC.java + ${project.basedir}/src/main/java/com/smallaswater/npc/utils/GameCoreDownload.java diff --git a/src/main/java/com/smallaswater/npc/RsNPC.java b/src/main/java/com/smallaswater/npc/RsNPC.java index da65bbc..e4a086a 100644 --- a/src/main/java/com/smallaswater/npc/RsNPC.java +++ b/src/main/java/com/smallaswater/npc/RsNPC.java @@ -14,6 +14,7 @@ import com.smallaswater.npc.dialog.DialogManager; import com.smallaswater.npc.entitys.EntityRsNPC; import com.smallaswater.npc.tasks.CheckNpcEntityTask; +import com.smallaswater.npc.utils.GameCoreDownload; import com.smallaswater.npc.utils.MetricsLite; import com.smallaswater.npc.utils.Utils; import com.smallaswater.npc.utils.update.ConfigUpdateUtils; @@ -59,13 +60,6 @@ public class RsNPC extends PluginBase { private static final Skin DEFAULT_SKIN; - public static final String MINIMUM_GAME_CORE_VERSION = "1.6.8"; - - private static final String MAVEN_URL_CENTRAL = "https://repo1.maven.org/maven2/"; - private static final String MAVEN_URL_LANINK = "https://repo.lanink.cn/"; - - private static final String GAME_CORE_URL = "cn/lanink/MemoriesOfTime-GameCore/" + MINIMUM_GAME_CORE_VERSION + "/MemoriesOfTime-GameCore-" + MINIMUM_GAME_CORE_VERSION + ".jar"; - static { Skin skin = new Skin(); skin.setTrusted(true); @@ -82,8 +76,6 @@ public static RsNPC getInstance() { public void onLoad() { rsNPC = this; - this.loadLanguage(); - VariableManage.addVariable("%npcName%", (player, rsNpcConfig) -> rsNpcConfig.getName()); VariableManage.addVariable("@p", (player, rsNpcConfig) -> player.getName()); @@ -101,9 +93,7 @@ public void onLoad() { @Override public void onEnable() { - this.getLogger().info(this.getLanguage().translateString("plugin.load.startLoad")); - - switch (Utils.checkAndDownloadDepend()) { + switch (GameCoreDownload.checkAndDownload()) { case 1: Server.getInstance().getPluginManager().disablePlugin(this); return; @@ -114,6 +104,10 @@ public void onEnable() { break; } + this.loadLanguage(); + + this.getLogger().info(this.getLanguage().translateString("plugin.load.startLoad")); + NukkitTypeUtils.NukkitType nukkitType = NukkitTypeUtils.getNukkitType(); if (nukkitType != NukkitTypeUtils.NukkitType.NUKKITX && nukkitType != NukkitTypeUtils.NukkitType.POWER_NUKKIT) { this.getLogger().error("警告!您所使用的插件版本不支持此Nukkit分支!"); @@ -357,26 +351,6 @@ public Config getNpcConfigDescription() { return this.npcConfigDescription; } - /** - * @return 最低GameCore版本 - */ - public String getMinimumGameCoreVersion() { - return MINIMUM_GAME_CORE_VERSION; - } - - /** - * @return GameCore下载链接 - */ - public String getGameCoreUrl(int i) { - String maven; - if (i > 0) { - maven = MAVEN_URL_LANINK; - }else { - maven = MAVEN_URL_CENTRAL; - } - return maven + GAME_CORE_URL; - } - public String getVersion() { Config config = new Config(Config.PROPERTIES); config.load(this.getResource("git.properties")); diff --git a/src/main/java/com/smallaswater/npc/utils/Download.java b/src/main/java/com/smallaswater/npc/utils/Download.java deleted file mode 100644 index 9e13df2..0000000 --- a/src/main/java/com/smallaswater/npc/utils/Download.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.smallaswater.npc.utils; - -import lombok.NonNull; -import lombok.SneakyThrows; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.RecursiveAction; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -/** - * @author iGxnon - * 多线程下载 - */ -public class Download { - - private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36"; - - // 每个任务下载 128 kb数据 - private static final int THRESHOLD = 128 * 1024; - - - /** - * 下载 - * - * @param strUrl 目标url - * @param saveFile 保存到文件 - * @param callback 下载完的回调 - */ - public static void download(String strUrl, File saveFile, BiConsumer callback) throws Exception { - URL url = new URL(strUrl); - HttpURLConnection connection = ((HttpURLConnection) url.openConnection()); - connection.setRequestMethod("GET"); - connection.setRequestProperty("Connection", "keep-alive"); - connection.setRequestProperty("Accept", "*/*"); - connection.setRequestProperty("User-Agent", USER_AGENT); - connection.setReadTimeout(5000); - - - long len = connection.getContentLength(); - if ("chunked".equals(connection.getHeaderField("Transfer-Encoding"))) { // chunked transfer 采用单线程下载 - RandomAccessFile out = new RandomAccessFile(saveFile, "rw"); - out.seek(0); - byte[] b = new byte[1024]; - InputStream in = connection.getInputStream(); - int read; - long count = 0; - while ((read = in.read(b)) >= 0) { - out.write(b, 0, read); - count += read; - if (callback != null) { - callback.accept(count, len); - } - } - in.close(); - out.close(); - return; - } - ForkJoinPool pool = new ForkJoinPool(); - AtomicLong atomicLong = new AtomicLong(); - pool.submit(new DownloadTask(strUrl,0, len, saveFile, (l) -> { - atomicLong.addAndGet(l); - callback.accept(atomicLong.get(), len); - })); - pool.shutdown(); - // 同步 - while (!pool.awaitTermination(1, TimeUnit.SECONDS)) { - } - if (len < 1 || saveFile.length() < 1) { - throw new Exception("下载失败"); - } - } - - static class DownloadTask extends RecursiveAction { - - private final String strUrl; - private final File file; - private final long start; - private final long end; - - private final Consumer callback; - - public DownloadTask(@NonNull String strUrl, long start, long end, File file, Consumer callback) { - this.strUrl = strUrl; - this.start = start; - this.end = end; - this.file = file; - this.callback = callback; - } - - @SneakyThrows - @Override - protected void compute() { - long l = end - start; - if (l < THRESHOLD) { - HttpURLConnection connection = getConnection(); - connection.setRequestProperty("Range", "bytes=" + start + "-" + end); - - RandomAccessFile out = new RandomAccessFile(file, "rw"); - out.seek(start); - InputStream in = connection.getInputStream(); - byte[] b = new byte[1024]; - int len; - while ((len = in.read(b)) >= 0) { - out.write(b, 0, len); - callback.accept(len); - } - in.close(); - out.close(); - }else { - long mid = (start + end) / 2; - new SubDownloadTask(strUrl, start, mid, file, callback).fork(); - new SubDownloadTask(strUrl, mid, end, file, callback).fork(); - } - } - - public HttpURLConnection getConnection() throws IOException { - HttpURLConnection connection = (HttpURLConnection) new URL(strUrl).openConnection(); - connection.setReadTimeout(5000); - connection.setRequestMethod("GET"); - connection.setRequestProperty("Connection", "keep-alive"); - connection.setRequestProperty("Accept", "*/*"); - connection.setRequestProperty("User-Agent", USER_AGENT); - - return connection; - } - } - - static class SubDownloadTask extends DownloadTask { - - public SubDownloadTask(@NonNull String strUrl, long start, long end, File file, Consumer callback) { - super(strUrl, start, end, file, callback); - } - - } - -} - diff --git a/src/main/java/com/smallaswater/npc/utils/GameCoreDownload.java b/src/main/java/com/smallaswater/npc/utils/GameCoreDownload.java new file mode 100644 index 0000000..17eb977 --- /dev/null +++ b/src/main/java/com/smallaswater/npc/utils/GameCoreDownload.java @@ -0,0 +1,261 @@ +package com.smallaswater.npc.utils; + +import cn.lanink.gamecore.utils.VersionUtils; +import cn.nukkit.Server; +import cn.nukkit.math.NukkitMath; +import cn.nukkit.plugin.Plugin; +import com.google.common.util.concurrent.AtomicDouble; +import com.smallaswater.npc.RsNPC; +import lombok.NonNull; +import lombok.SneakyThrows; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLDecoder; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +/** + * 自动下载GameCore依赖工具类 + */ +public class GameCoreDownload { + + private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36"; + + // 每个任务下载 128 kb数据 + private static final int THRESHOLD = 128 * 1024; + + public static final String MINIMUM_GAME_CORE_VERSION = "1.6.8"; + + private static final String MAVEN_URL_CENTRAL = "https://repo1.maven.org/maven2/"; + private static final String MAVEN_URL_LANINK = "https://repo.lanink.cn/"; + + private static final String GAME_CORE_URL_SUFFIX = "cn/lanink/MemoriesOfTime-GameCore/" + MINIMUM_GAME_CORE_VERSION + "/MemoriesOfTime-GameCore-" + MINIMUM_GAME_CORE_VERSION + ".jar"; + + private static final List GAME_CORE_URL_LIST; + + static { + GAME_CORE_URL_LIST = Collections.unmodifiableList(Arrays.asList( + MAVEN_URL_CENTRAL + GAME_CORE_URL_SUFFIX, + MAVEN_URL_LANINK + GAME_CORE_URL_SUFFIX + )); + } + + private GameCoreDownload() { + throw new RuntimeException("error"); + } + + /** + * 检查并下载GameCore依赖 + * + * @return 0 - GameCore已加载且是最新版本 1 - 无法下载GameCore 2 下载成功 + */ + public static int checkAndDownload() { + return checkAndDownload(0); + } + + /** + * 检查并下载GameCore依赖 + * + * @param retry 重试次数(下载链接序号) + * @return 0 - GameCore已加载且是最新版本 1 - 无法下载GameCore 2 下载成功 + */ + private static int checkAndDownload(int retry) { + if (retry >= GAME_CORE_URL_LIST.size()) { + return 1; + } + String url = GAME_CORE_URL_LIST.get(retry); + if (retry > 0) { + RsNPC.getInstance().getLogger().info("尝试从 " + url + " 下载 GameCore"); + } + Plugin plugin = Server.getInstance().getPluginManager().getPlugin("MemoriesOfTime-GameCore"); + + if (plugin != null) { + if (!VersionUtils.checkMinimumVersion(plugin, MINIMUM_GAME_CORE_VERSION)) { + RsNPC.getInstance().getLogger().warning("MemoriesOfTime-GameCore依赖版本太低!正在尝试更新版本..."); + File file = getPluginFile(plugin); + if (file != null) { + Server.getInstance().getPluginManager().disablePlugin(plugin); + ClassLoader classLoader = plugin.getClass().getClassLoader(); + try { + if (classLoader instanceof URLClassLoader) { + ((URLClassLoader) classLoader).close(); + } + } catch (IOException ignored) { + + } + if (file != null) { + file.delete(); + } + }else { + RsNPC.getInstance().getLogger().error("删除旧版本失败!请手动删除!"); + } + } + } + + if (plugin == null || plugin.isDisabled()) { + RsNPC.getInstance().getLogger().info("下载MemoriesOfTime-GameCore依赖中..."); + + File file = new File(Server.getInstance().getFilePath() + "/plugins/MemoriesOfTime-GameCore-" + MINIMUM_GAME_CORE_VERSION + ".jar"); + + try { + AtomicDouble last = new AtomicDouble(-10); + download(url, file, (l, len) -> { + double d = NukkitMath.round(l * 1.0 / len * 100, 2); + if (d - last.get() > 10) { // 每10%提示一次 + RsNPC.getInstance().getLogger().info("已下载:" + d + "%"); + last.set(d); + } + }); + } catch (Exception e) { + RsNPC.getInstance().getLogger().error("MemoriesOfTime-GameCore依赖下载失败!"); + return checkAndDownload(++retry); + } + + RsNPC.getInstance().getLogger().info("MemoriesOfTime-GameCore依赖下载成功!"); + Server.getInstance().getPluginManager().loadPlugin(file); + return 2; + } + return 0; + } + + public static File getPluginFile(Plugin plugin) { + File file = null; + ClassLoader PluginClass = plugin.getClass().getClassLoader(); + try { + if (PluginClass instanceof URLClassLoader) { + URLClassLoader pluginClass = (URLClassLoader) PluginClass; + URL url = pluginClass.getURLs()[0]; + file = new File(URLDecoder.decode(url.getFile(), "UTF-8")); + } + } catch (UnsupportedEncodingException ignored) { + + } + return file; + } + + /** + * 下载 + * + * @param strUrl 目标url + * @param saveFile 保存到文件 + * @param callback 下载完的回调 + */ + private static void download(String strUrl, File saveFile, BiConsumer callback) throws Exception { + URL url = new URL(strUrl); + HttpURLConnection connection = ((HttpURLConnection) url.openConnection()); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Connection", "keep-alive"); + connection.setRequestProperty("Accept", "*/*"); + connection.setRequestProperty("User-Agent", USER_AGENT); + connection.setReadTimeout(5000); + + + long len = connection.getContentLength(); + if ("chunked".equals(connection.getHeaderField("Transfer-Encoding"))) { // chunked transfer 采用单线程下载 + RandomAccessFile out = new RandomAccessFile(saveFile, "rw"); + out.seek(0); + byte[] b = new byte[1024]; + InputStream in = connection.getInputStream(); + int read; + long count = 0; + while ((read = in.read(b)) >= 0) { + out.write(b, 0, read); + count += read; + if (callback != null) { + callback.accept(count, len); + } + } + in.close(); + out.close(); + return; + } + ForkJoinPool pool = new ForkJoinPool(); + AtomicLong atomicLong = new AtomicLong(); + pool.submit(new DownloadTask(strUrl,0, len, saveFile, (l) -> { + atomicLong.addAndGet(l); + callback.accept(atomicLong.get(), len); + })); + pool.shutdown(); + // 同步 + while (!pool.awaitTermination(1, TimeUnit.SECONDS)) { + } + if (len < 1 || saveFile.length() < 1) { + throw new Exception("下载失败"); + } + } + + private static class DownloadTask extends RecursiveAction { + + private final String strUrl; + private final File file; + private final long start; + private final long end; + + private final Consumer callback; + + public DownloadTask(@NonNull String strUrl, long start, long end, File file, Consumer callback) { + this.strUrl = strUrl; + this.start = start; + this.end = end; + this.file = file; + this.callback = callback; + } + + @SneakyThrows + @Override + protected void compute() { + long l = end - start; + if (l < THRESHOLD) { + HttpURLConnection connection = getConnection(); + connection.setRequestProperty("Range", "bytes=" + start + "-" + end); + + RandomAccessFile out = new RandomAccessFile(file, "rw"); + out.seek(start); + InputStream in = connection.getInputStream(); + byte[] b = new byte[1024]; + int len; + while ((len = in.read(b)) >= 0) { + out.write(b, 0, len); + callback.accept(len); + } + in.close(); + out.close(); + }else { + long mid = (start + end) / 2; + new SubDownloadTask(strUrl, start, mid, file, callback).fork(); + new SubDownloadTask(strUrl, mid, end, file, callback).fork(); + } + } + + public HttpURLConnection getConnection() throws IOException { + HttpURLConnection connection = (HttpURLConnection) new URL(strUrl).openConnection(); + connection.setReadTimeout(5000); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Connection", "keep-alive"); + connection.setRequestProperty("Accept", "*/*"); + connection.setRequestProperty("User-Agent", USER_AGENT); + + return connection; + } + } + + private static class SubDownloadTask extends DownloadTask { + + public SubDownloadTask(@NonNull String strUrl, long start, long end, File file, Consumer callback) { + super(strUrl, start, end, file, callback); + } + + } + +} + diff --git a/src/main/java/com/smallaswater/npc/utils/Utils.java b/src/main/java/com/smallaswater/npc/utils/Utils.java index 8f877a1..679f8fe 100644 --- a/src/main/java/com/smallaswater/npc/utils/Utils.java +++ b/src/main/java/com/smallaswater/npc/utils/Utils.java @@ -1,13 +1,10 @@ package com.smallaswater.npc.utils; -import cn.lanink.gamecore.utils.VersionUtils; import cn.nukkit.Player; import cn.nukkit.Server; import cn.nukkit.item.Item; import cn.nukkit.level.Location; -import cn.nukkit.math.NukkitMath; import cn.nukkit.plugin.Plugin; -import com.google.common.util.concurrent.AtomicDouble; import com.smallaswater.npc.RsNPC; import com.smallaswater.npc.data.RsNpcConfig; import com.smallaswater.npc.tasks.PlayerPermissionCheckTask; @@ -16,11 +13,7 @@ import java.io.File; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.math.BigDecimal; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLDecoder; import java.util.List; public class Utils { @@ -131,84 +124,7 @@ public static double getYaw(@NotNull Location location) { } public static File getPluginFile(Plugin plugin) { - File file = null; - ClassLoader PluginClass = plugin.getClass().getClassLoader(); - try { - if (PluginClass instanceof URLClassLoader) { - URLClassLoader pluginClass = (URLClassLoader) PluginClass; - URL url = pluginClass.getURLs()[0]; - file = new File(URLDecoder.decode(url.getFile(), "UTF-8")); - } - } catch (UnsupportedEncodingException ignored) { - - } - return file; - } - - public static int checkAndDownloadDepend() { - return checkAndDownloadDepend(0); - } - - public static int checkAndDownloadDepend(int retry) { - if (retry > 0) { - RsNPC.getInstance().getLogger().info("尝试更换下载链接为 " + RsNPC.getInstance().getGameCoreUrl(retry)); - } - String version = RsNPC.getInstance().getMinimumGameCoreVersion(); - Plugin plugin = Server.getInstance().getPluginManager().getPlugin("MemoriesOfTime-GameCore"); - - if (plugin != null) { - if (!VersionUtils.checkMinimumVersion(plugin, version)) { - RsNPC.getInstance().getLogger().warning("MemoriesOfTime-GameCore依赖版本太低!正在尝试更新版本..."); - File file = getPluginFile(plugin); - Server.getInstance().getPluginManager().disablePlugin(plugin); - ClassLoader classLoader = plugin.getClass().getClassLoader(); - try { - if (classLoader instanceof URLClassLoader) { - ((URLClassLoader) classLoader).close(); - } - } catch (IOException ignored) { - - } - if (file != null) { - file.delete(); - } - } - } - - if (plugin == null || plugin.isDisabled()) { - RsNPC.getInstance().getLogger().info("下载MemoriesOfTime-GameCore依赖中..."); - - String gamecore = Server.getInstance().getFilePath() + "/plugins/MemoriesOfTime-GameCore-" + version + ".jar"; - - try { - AtomicDouble last = new AtomicDouble(-10); - Download.download(RsNPC.getInstance().getGameCoreUrl(retry), new File(gamecore), (l, len) -> { - double d = NukkitMath.round(l * 1.0 / len * 100, 2); - if (d - last.get() > 10) { - RsNPC.getInstance().getLogger().info("已下载:" + d + "%"); - last.set(d); - } - }); - /*FileOutputStream fos = new FileOutputStream(gamecore); - URL url = new URL(RsNPC.getInstance().getGameCoreUrl()); - fos.getChannel().transferFrom(Channels.newChannel(url.openStream()), 0, Long.MAX_VALUE); - fos.close();*/ - } catch (Exception e) { - RsNPC.getInstance().getLogger().error(RsNPC.getInstance().getGameCoreUrl(retry) + " 下载失败!"); - if (retry >= 1) { - RsNPC.getInstance().getLogger().error("无法下载MemoriesOfTime-GameCore依赖!", e); - RsNPC.getInstance().getLogger().error("请尝试手动下载依赖!"); - RsNPC.getInstance().getLogger().error(RsNPC.getInstance().getGameCoreUrl(retry)); - return 1; - } - return checkAndDownloadDepend(++retry); - } - - RsNPC.getInstance().getLogger().info("MemoriesOfTime-GameCore依赖下载成功!"); - Server.getInstance().getPluginManager().loadPlugin(gamecore); - return 2; - } - return 0; + return GameCoreDownload.getPluginFile(plugin); } }