diff --git a/src/main/java/i18nupdatemod/core/I18nConfig.java b/src/main/java/i18nupdatemod/core/I18nConfig.java
index fab2c2e..b0169c7 100644
--- a/src/main/java/i18nupdatemod/core/I18nConfig.java
+++ b/src/main/java/i18nupdatemod/core/I18nConfig.java
@@ -12,8 +12,12 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
+import static i18nupdatemod.util.AssetUtil.getFastestUrl;
+import static i18nupdatemod.util.AssetUtil.getGitIndex;
+
public class I18nConfig {
/**
* CFPAOrg/Minecraft-Mod-Language-Package
@@ -58,17 +62,60 @@ public static GameAssetDetail getAssetDetail(String minecraftVersion, String loa
GameMetaData convert = getGameMetaData(minecraftVersion);
GameAssetDetail ret = new GameAssetDetail();
- ret.downloads = convert.convertFrom.stream().map(it -> getAssetMetaData(it, loader)).map(it -> {
+ String assetRoot = getFastestUrl();
+ Log.debug("Using asset root: " + assetRoot);
+
+ if (assetRoot.equals("https://raw.githubusercontent.com/")) {
+ ret.downloads = createDownloadDetailsFromGit(convert, loader);
+ } else {
+ ret.downloads = createDownloadDetails(convert, loader, assetRoot);
+ }
+
+ ret.covertPackFormat = convert.packFormat;
+ ret.covertFileName =
+ String.format("Minecraft-Mod-Language-Modpack-Converted-%s.zip", minecraftVersion);
+ return ret;
+ }
+
+ private static List createDownloadDetails(GameMetaData convert, String loader, String assetRoot) {
+ return convert.convertFrom.stream().map(it -> getAssetMetaData(it, loader)).map(it -> {
GameAssetDetail.AssetDownloadDetail adi = new GameAssetDetail.AssetDownloadDetail();
adi.fileName = it.filename;
- adi.fileUrl = CFPA_ASSET_ROOT + it.filename;
- adi.md5Url = CFPA_ASSET_ROOT + it.md5Filename;
+ adi.fileUrl = assetRoot + it.filename;
+ adi.md5Url = assetRoot + it.md5Filename;
adi.targetVersion = it.targetVersion;
return adi;
}).collect(Collectors.toList());
- ret.covertPackFormat = convert.packFormat;
- ret.covertFileName =
- String.format("Minecraft-Mod-Language-Modpack-Converted-%s.zip", minecraftVersion);
- return ret;
+ }
+
+ private static List createDownloadDetailsFromGit(GameMetaData convert, String loader) {
+ try {
+ Map index = getGitIndex();
+ String releaseTag;
+ String version = convert.convertFrom.get(0);
+
+ if (loader.toLowerCase().contains("fabric")) {
+ releaseTag = index.get(version + "-fabric");
+ } else {
+ releaseTag = index.get(version);
+ }
+ if (releaseTag == null) {
+ Log.debug("Error getting index: " + version + "-" + loader);
+ Log.debug(index.toString());
+ throw new Exception();
+ }
+ String assetRoot = "https://github.com/CFPAOrg/Minecraft-Mod-Language-Package/releases/download/" + releaseTag + "/";
+
+ return convert.convertFrom.stream().map(it -> getAssetMetaData(it, loader)).map(it -> {
+ GameAssetDetail.AssetDownloadDetail adi = new GameAssetDetail.AssetDownloadDetail();
+ adi.fileName = it.filename;
+ adi.fileUrl = assetRoot + it.filename;
+ adi.md5Url = assetRoot + it.md5Filename;
+ adi.targetVersion = it.targetVersion;
+ return adi;
+ }).collect(Collectors.toList());
+ } catch (Exception ignore) {
+ return createDownloadDetails(convert, loader, CFPA_ASSET_ROOT);
+ }
}
}
diff --git a/src/main/java/i18nupdatemod/util/AssetUtil.java b/src/main/java/i18nupdatemod/util/AssetUtil.java
index 713ea10..d75c840 100644
--- a/src/main/java/i18nupdatemod/util/AssetUtil.java
+++ b/src/main/java/i18nupdatemod/util/AssetUtil.java
@@ -1,16 +1,38 @@
package i18nupdatemod.util;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import org.jetbrains.annotations.NotNull;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
-import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
public class AssetUtil {
+ private static final String CFPA_ASSET_ROOT = "http://downloader1.meitangdehulu.com:22943/";
+ private static final List MIRRORS;
+
+ static {
+ // 镜像地址可以改成服务器下发
+ MIRRORS = new ArrayList<>();
+ MIRRORS.add("https://raw.githubusercontent.com/");
+ // 此镜像源维护者:502y
+ MIRRORS.add("http://8.137.167.65:64684/");
+ }
+
public static void download(String url, Path localFile) throws IOException, URISyntaxException {
Log.info("Downloading: %s -> %s", url, localFile);
FileUtils.copyURLToFile(new URI(url).toURL(), localFile.toFile(),
@@ -21,4 +43,85 @@ public static void download(String url, Path localFile) throws IOException, URIS
public static String getString(String url) throws IOException, URISyntaxException {
return IOUtils.toString(new URI(url).toURL(), StandardCharsets.UTF_8);
}
+
+ public static String getFastestUrl() {
+ List urls = new ArrayList<>(MIRRORS);
+ urls.add(CFPA_ASSET_ROOT);
+
+ ExecutorService executor = Executors.newFixedThreadPool(Math.max(urls.size(), 10));
+ try {
+ List> futures = new ArrayList<>();
+ for (String url : urls) {
+ CompletableFuture future = CompletableFuture.supplyAsync(() -> {
+ try {
+ return testUrlConnection(url);
+ } catch (IOException e) {
+ return null; // 表示失败
+ }
+ }, executor);
+ futures.add(future);
+ }
+
+ // 阻塞等待最快完成且成功的任务
+ String fastest = null;
+ while (!futures.isEmpty()) {
+ CompletableFuture