diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 773d83c8..25a55b51 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,74 +1,110 @@ -name: Bug Feedback +name: Bug Feedback / 错误反馈 description: - Report a bug. + Report a bug. 报告错误。 labels: bug body: - type: markdown attributes: value: | Please ensure you are using the **latest bata version** before you submit, you can get the latest beta version by checking update in launcher setting page. - + 请确认在你提交之前你使用的是最新版本,你可以在启动器的设置页内通过检测更新获取最新版本。 + Please confirm that the question you are asking is not related to modpacks.If you ask about modpacks, we will directly delete it. + 请确认你询问的不是整合包相关的问题。如果你询问整合包相关问题,我们会直接删除。 To improve communication efficiency, we suggest you join our community to report bugs. + 为了提高交流效率,我们建议你加入我们的社区报告错误。 You can find our community in community page of the launcher. + 你可以在启动器的社区页内找到我们的社区。 + - type: checkboxes + id: checks + attributes: + label: Before making issue / 在发布提问之前... + options: + - label: I have read the content above.我已经阅读了上方的内容。 + required: true + - label: I understand what I'm asking is not about modpack.我明白我询问的不是整合包相关的问题。 + required: true + - label: I have searched for existing issues.我已经搜索了现有的 issues。 + required: true + - label: I have tried switching renderer.我已经尝试过切换渲染器。 - type: input id: fcl-version attributes: - label: Launcher Version - description: Please enter the Fold Craft Launcher version you are using. - placeholder: e.g. 1.0.1 + label: Launcher Version / 启动器版本 + description: | + Please enter the Fold Craft Launcher version you are using. + 请输入你正在使用的Fold Craft Launcher版本。 + placeholder: e.g. 1.0.1 / 例如1.0.1 validations: required: true - type: input id: device attributes: - label: Device Information - description: Please enter the information of the device on which you encountered the bug. + label: Device Information / 设备信息 + description: | + Please enter the information of the device on which you encountered the bug. + 请输入你遇到错误的设备的信息。 placeholder: e.g. OPPO Find X3 Pro, Android 13, arm64 validations: required: true - type: textarea id: bug-report attributes: - label: Problem Description - description: Please describe the problem in as much detail as possible, especially how you encountered this bug. + label: Problem Description / 问题描述 + description: | + Please describe the problem in as much detail as possible, especially how you encountered this bug. + 请尽可能详细地描述问题,特别是你是如何遇到这个bug的。 validations: required: true - type: input id: java-version attributes: label: Java - description: Please enter the version of Java you are using. + description: | + Please enter the version of Java you are using. + 请输入你正在使用的Java版本。 placeholder: e.g. Java 17 - type: input id: renderer attributes: - label: Renderer - description: Please enter the renderer you are using. + label: Renderer / 渲染器 + description: | + Please enter the renderer you are using. + 请输入你正在使用的渲染器。 placeholder: e.g. Holy-GL4ES - type: input id: game-version attributes: - label: Game Version - description: If you are having trouble launching a game that was automatically downloaded through the Fold Craft Launcher, please enter the version of the game you are launching. + label: Game Version / 游戏版本 + description: | + If you are having trouble launching a game that was automatically downloaded through the Fold Craft Launcher, please enter the version of the game you are launching. + 如果你在启动通过Fold Craft Launcher自动下载的游戏时遇到问题,请输入你要启动的游戏版本。 placeholder: e.g. 1.19 - type: input id: game-modify attributes: - label: Modifications Made to the Game - description: If you have OptiFine, Forge, or other mods installed for the game, please enter your modifications below. + label: Modifications Made to the Game / 对游戏所做的修改 + description: | + If you have OptiFine, Forge, or other mods installed for the game, please enter your modifications below. + 如果你为游戏安装了OptiFine、Forge或其他模组,请在下面输入你的修改。 placeholder: e.g. OptiFine HD_U_G9, Rift - type: textarea id: game-crash-report attributes: - label: Game Crash Report - description: If there is a game crash report, please upload it below. + label: Game Crash Report / 游戏崩溃报告 + description: | + If there is a game crash report, please upload it(file) below. + 如果有游戏崩溃报告,请在下面上传(文件)。 - type: textarea id: fcl-crash-report attributes: - label: Launcher Crash Report - description: If there is a launcher crash report, please upload it below. + label: Launcher Crash Report / 启动器崩溃报告 + description: | + If there is a launcher crash report, please upload it(file) below. + 如果有启动器崩溃报告,请在下面上传(文件)。 - type: textarea id: fcl-logs attributes: - label: Launcher Log File - description: After encountering a problem, please click "Export Launcher Log" in the launcher setting page, and upload the exported log to the input field below. \ No newline at end of file + label: Launcher Log File / 启动器日志文件 + description: | + After encountering a problem, please click "Export Launcher Log" in the launcher setting page, and upload the exported log to the input field below. + 遇到问题后,请在启动器设置页面中单击“导出启动器日志”,并将导出的日志上传到下面的输入字段。 diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index 003ab33e..795141e1 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -1,21 +1,36 @@ -name: "Feature Request" -description: "Propose new features for Fold Craft Launcher" +name: Feature Request / 功能请求 +description: | + Propose new features for Fold Craft Launcher. + 为Fold Craft Launcher提出新功能。 labels: feature request body: - type: markdown attributes: - value: "Make sure to check the issues list for duplicates before submitting!" + value: | + Make sure to check the issues list for duplicates before submitting! + 提交前,请务必检查问题列表中的重复项! +- type: checkboxes + id: checks + attributes: + label: Before making issue / 在发布提问之前... + options: + - label: I understand this is a request, not a wish.我明白这是在提出请求而不是在许愿。 + required: true - type: textarea id: "feature" attributes: - label: Description - description: "Describe in detail the new features you would like to add." + label: Description / 描述 + description: | + Describe in detail the new features you would like to add. + 详细描述你要添加的新功能。 validations: required: true - type: textarea id: "reason" attributes: - label: Why - description: "Describe the benefits of this feature and why." + label: Why / 原因 + description: | + Describe the benefits of this feature and why. + 描述此功能的好处及其原因。 validations: required: true diff --git a/FCL/build.gradle b/FCL/build.gradle index e51e893a..f5776d1e 100644 --- a/FCL/build.gradle +++ b/FCL/build.gradle @@ -44,8 +44,8 @@ android { applicationId "com.tungsten.fcl" minSdk 26 targetSdk 34 - versionCode 1175 - versionName "1.1.7.5" + versionCode 1176 + versionName "1.1.7.6" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/FCL/src/main/assets/options.txt b/FCL/src/main/assets/options.txt index ec659a66..b87c1b6c 100644 --- a/FCL/src/main/assets/options.txt +++ b/FCL/src/main/assets/options.txt @@ -4,7 +4,7 @@ fov:0.0 gamma:0.5070422 saturation:0.0 renderDistance:2 -guiScale:0 +guiScale:4 particles:1 bobView:false anaglyph3d:false diff --git a/FCL/src/main/java/com/tungsten/fcl/game/JarExecutorHelper.java b/FCL/src/main/java/com/tungsten/fcl/game/JarExecutorHelper.java index 1955a11b..9c7ce8c8 100644 --- a/FCL/src/main/java/com/tungsten/fcl/game/JarExecutorHelper.java +++ b/FCL/src/main/java/com/tungsten/fcl/game/JarExecutorHelper.java @@ -11,6 +11,8 @@ import android.util.Log; import com.tungsten.fcl.activity.JVMActivity; import com.tungsten.fcl.control.MenuType; +import com.tungsten.fcl.setting.Profile; +import com.tungsten.fcl.setting.Profiles; import com.tungsten.fcl.util.AndroidUtils; import com.tungsten.fcl.util.RequestCodes; import com.tungsten.fclauncher.FCLConfig; @@ -59,6 +61,13 @@ public class JarExecutorHelper { private static void launchJarExecutor(Context context, File file) { int version = getJavaVersion(file); int javaVersion = getNearestJavaVersion(version); + Profile profile = Profiles.getSelectedProfile(); + if (profile != null) { + String java = profile.getGlobal().getJava(); + if (!java.equals(JavaVersion.JAVA_AUTO.getVersionName())) { + javaVersion = JavaVersion.getJavaFromVersionName(java).getVersion(); + } + } exec(context, file, javaVersion, null); } diff --git a/FCL/src/main/java/com/tungsten/fcl/game/LauncherHelper.java b/FCL/src/main/java/com/tungsten/fcl/game/LauncherHelper.java index 06e72e78..733e72fd 100644 --- a/FCL/src/main/java/com/tungsten/fcl/game/LauncherHelper.java +++ b/FCL/src/main/java/com/tungsten/fcl/game/LauncherHelper.java @@ -207,7 +207,7 @@ public final class LauncherHelper { launchingStepsPane.dismiss(); if (!success) { Exception ex = executor.getException(); - if (!(ex instanceof CancellationException)) { + if (ex != null && !(ex instanceof CancellationException)) { Schedulers.androidUIThread().execute(() -> { String message; if (ex instanceof ModpackCompletionException) { diff --git a/FCL/src/main/java/com/tungsten/fcl/game/ManuallyCreatedModpackInstallTask.java b/FCL/src/main/java/com/tungsten/fcl/game/ManuallyCreatedModpackInstallTask.java index 1ded36c9..fc5a4d15 100644 --- a/FCL/src/main/java/com/tungsten/fcl/game/ManuallyCreatedModpackInstallTask.java +++ b/FCL/src/main/java/com/tungsten/fcl/game/ManuallyCreatedModpackInstallTask.java @@ -17,6 +17,8 @@ */ package com.tungsten.fcl.game; +import android.os.Environment; + import com.tungsten.fcl.setting.Profile; import com.tungsten.fclcore.task.Task; import com.tungsten.fclcore.util.io.CompressingUtils; @@ -48,7 +50,7 @@ public class ManuallyCreatedModpackInstallTask extends Task { subdirectory = ModpackHelper.findMinecraftDirectoryInManuallyCreatedModpack(zipFile.toString(), fs); } - Path dest = Paths.get("externalgames").resolve(name); + Path dest = Paths.get(Environment.getExternalStorageDirectory().getAbsolutePath() + "/FCL").resolve(name); setResult(dest); diff --git a/FCL/src/main/java/com/tungsten/fcl/game/ModpackHelper.java b/FCL/src/main/java/com/tungsten/fcl/game/ModpackHelper.java index 7d50a235..83d8799d 100644 --- a/FCL/src/main/java/com/tungsten/fcl/game/ModpackHelper.java +++ b/FCL/src/main/java/com/tungsten/fcl/game/ModpackHelper.java @@ -21,12 +21,13 @@ import static com.tungsten.fclcore.util.Lang.mapOf; import static com.tungsten.fclcore.util.Lang.toIterable; import static com.tungsten.fclcore.util.Pair.pair; +import android.os.Environment; + import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; import com.tungsten.fcl.setting.Profile; import com.tungsten.fcl.setting.Profiles; import com.tungsten.fcl.setting.VersionSetting; -import com.tungsten.fclcore.game.GameDirectoryType; import com.tungsten.fclcore.mod.MismatchedModpackTypeException; import com.tungsten.fclcore.mod.Modpack; import com.tungsten.fclcore.mod.ModpackCompletionException; @@ -181,7 +182,7 @@ public final class ModpackHelper { } public static boolean isExternalGameNameConflicts(String name) { - return Files.exists(Paths.get("externalgames").resolve(name)); + return Files.exists(Paths.get(Environment.getExternalStorageDirectory().getAbsolutePath() + "/FCL").resolve(name)); } public static Task getInstallManuallyCreatedModpackTask(Profile profile, File zipFile, String name, Charset charset) { diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/GameOption.java b/FCL/src/main/java/com/tungsten/fcl/setting/GameOption.java index 50eed126..1fd4a427 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/GameOption.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/GameOption.java @@ -143,9 +143,9 @@ public class GameOption { String str = get("guiScale"); int guiScale; try { - guiScale = (str == null ? 0 : Integer.parseInt(str)); + guiScale = (str == null ? 4 : Integer.parseInt(str)); } catch (NumberFormatException ignore) { - guiScale = 0; + guiScale = 4; } int scale = Math.max(Math.min(width / 320, height / 240), 1); if (scale < guiScale || guiScale == 0) { diff --git a/FCL/src/main/res/drawable/ic_launcher_background.xml b/FCL/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..424ccb10 --- /dev/null +++ b/FCL/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index c5c9e8f5..c4a603d4 100644 --- a/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index c5c9e8f5..c4a603d4 100644 --- a/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/FCL/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/FCL/src/main/res/mipmap-hdpi/ic_launcher.png b/FCL/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index e7232767..00000000 Binary files a/FCL/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/FCL/src/main/res/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 74efc213..00000000 Binary files a/FCL/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/FCL/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 00000000..c4b6364d Binary files /dev/null and b/FCL/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/FCL/src/main/res/mipmap-mdpi/ic_launcher.png b/FCL/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 762f488a..00000000 Binary files a/FCL/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/FCL/src/main/res/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 3a2d5629..00000000 Binary files a/FCL/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/FCL/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 00000000..4a0ce27d Binary files /dev/null and b/FCL/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/FCL/src/main/res/mipmap-xhdpi/ic_launcher.png b/FCL/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 2a2a34ae..00000000 Binary files a/FCL/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/FCL/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index c3a88e52..00000000 Binary files a/FCL/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/FCL/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 00000000..37677444 Binary files /dev/null and b/FCL/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/FCL/src/main/res/mipmap-xxhdpi/ic_launcher.png b/FCL/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 9eee6b36..00000000 Binary files a/FCL/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/FCL/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 7f4ff9ce..00000000 Binary files a/FCL/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/FCL/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 00000000..16efdef0 Binary files /dev/null and b/FCL/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index e0cccf24..00000000 Binary files a/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 61417a9d..00000000 Binary files a/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 00000000..09f20640 Binary files /dev/null and b/FCL/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/FCL/src/main/res/values-v31/themes.xml b/FCL/src/main/res/values-v31/themes.xml new file mode 100644 index 00000000..a5683bcb --- /dev/null +++ b/FCL/src/main/res/values-v31/themes.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/FCL/src/main/res/values-zh/strings.xml b/FCL/src/main/res/values-zh/strings.xml index b11011b1..c5d8bddc 100644 --- a/FCL/src/main/res/values-zh/strings.xml +++ b/FCL/src/main/res/values-zh/strings.xml @@ -270,7 +270,7 @@ 我的世界中文论坛 (https://www.mcbbs.net/) BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) - 官方 (OptiFine 自动安装使用 BMCLAPI 下载源) + 官方 (OptiFine 自动安装使用 OF-302 下载源) 尽量使用官方源 选择加载速度快的下载源 尽量使用镜像源 diff --git a/FCL/src/main/res/values/strings.xml b/FCL/src/main/res/values/strings.xml index f55972dc..7b0ede99 100644 --- a/FCL/src/main/res/values/strings.xml +++ b/FCL/src/main/res/values/strings.xml @@ -293,7 +293,7 @@ MCBBS (https://www.mcbbs.net/) BMCLAPI (bangbang93, https://bmclapi2.bangbang93.com/) - Mojang (OptiFine is provided by BMCLAPI) + Mojang (OptiFine is provided by OF-302) From Official Sources From Fastest Available From Mirror diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/auth/offline/OfflineAccount.java b/FCLCore/src/main/java/com/tungsten/fclcore/auth/offline/OfflineAccount.java index 979d967f..d8b9f01c 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/auth/offline/OfflineAccount.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/auth/offline/OfflineAccount.java @@ -38,7 +38,6 @@ import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorArtifactInfo; import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorArtifactProvider; import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorDownloadException; import com.tungsten.fclcore.auth.yggdrasil.Texture; -import com.tungsten.fclcore.auth.yggdrasil.TextureModel; import com.tungsten.fclcore.auth.yggdrasil.TextureType; import com.tungsten.fclcore.fakefx.beans.binding.Bindings; import com.tungsten.fclcore.fakefx.beans.binding.ObjectBinding; @@ -100,14 +99,7 @@ public class OfflineAccount extends Account { } protected boolean loadAuthlibInjector(Skin skin) { - if (skin == null) return false; - if (skin.getType() == Skin.Type.DEFAULT) return false; - TextureModel defaultModel = TextureModel.detectUUID(getUUID()); - if (skin.getType() == Skin.Type.ALEX && defaultModel == TextureModel.ALEX || - skin.getType() == Skin.Type.STEVE && defaultModel == TextureModel.STEVE) { - return false; - } - return true; + return skin != null && skin.getType() != Skin.Type.DEFAULT; } @Override diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/MojangDownloadProvider.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/MojangDownloadProvider.java index a163b17d..61a9b189 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/MojangDownloadProvider.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/MojangDownloadProvider.java @@ -19,11 +19,11 @@ package com.tungsten.fclcore.download; import com.tungsten.fclcore.download.fabric.FabricAPIVersionList; import com.tungsten.fclcore.download.fabric.FabricVersionList; -import com.tungsten.fclcore.download.forge.ForgeBMCLVersionList; +import com.tungsten.fclcore.download.forge.ForgeVersionList; import com.tungsten.fclcore.download.game.GameVersionList; import com.tungsten.fclcore.download.liteloader.LiteLoaderVersionList; import com.tungsten.fclcore.download.neoforge.NeoForgeOfficialVersionList; -import com.tungsten.fclcore.download.optifine.OptiFineBMCLVersionList; +import com.tungsten.fclcore.download.optifine.OptiFine302VersionList; import com.tungsten.fclcore.download.quilt.QuiltAPIVersionList; import com.tungsten.fclcore.download.quilt.QuiltVersionList; @@ -34,10 +34,10 @@ public class MojangDownloadProvider implements DownloadProvider { private final GameVersionList game; private final FabricVersionList fabric; private final FabricAPIVersionList fabricApi; - private final ForgeBMCLVersionList forge; + private final ForgeVersionList forge; private final NeoForgeOfficialVersionList neoforge; private final LiteLoaderVersionList liteLoader; - private final OptiFineBMCLVersionList optifine; + private final OptiFine302VersionList optifine; private final QuiltVersionList quilt; private final QuiltAPIVersionList quiltApi; @@ -47,10 +47,10 @@ public class MojangDownloadProvider implements DownloadProvider { this.game = new GameVersionList(this); this.fabric = new FabricVersionList(this); this.fabricApi = new FabricAPIVersionList(this); - this.forge = new ForgeBMCLVersionList(apiRoot); + this.forge = new ForgeVersionList(this); this.neoforge = new NeoForgeOfficialVersionList(this); this.liteLoader = new LiteLoaderVersionList(this); - this.optifine = new OptiFineBMCLVersionList(apiRoot); + this.optifine = new OptiFine302VersionList("https://zkitefly.github.io/optifine-download-list/index.json"); this.quilt = new QuiltVersionList(this); this.quiltApi = new QuiltAPIVersionList(this); } diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/VersionList.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/VersionList.java index 1b15fb5f..686a9334 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/VersionList.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/VersionList.java @@ -129,9 +129,14 @@ public abstract class VersionList { lock.readLock().lock(); try { T result = null; - for (T it : versions.get(gameVersion)) + TreeSet remoteVersions = versions.get(gameVersion); + for (T it : remoteVersions) if (remoteVersion.equals(it.getSelfVersion())) result = it; + if (result == null) + for (T it : remoteVersions) + if (remoteVersion.equals(it.getFullVersion())) + result = it; return Optional.ofNullable(result); } finally { lock.readLock().unlock(); diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeBMCLVersionList.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeBMCLVersionList.java index ce005fca..86dd7fd0 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeBMCLVersionList.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeBMCLVersionList.java @@ -25,6 +25,7 @@ import static com.tungsten.fclcore.util.Pair.pair; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; import com.tungsten.fclcore.download.VersionList; +import com.tungsten.fclcore.util.Lang; import com.tungsten.fclcore.util.StringUtils; import com.tungsten.fclcore.util.gson.Validation; import com.tungsten.fclcore.util.io.HttpRequest; @@ -35,7 +36,10 @@ import org.jetbrains.annotations.Nullable; import java.time.Instant; import java.time.format.DateTimeParseException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.logging.Level; @@ -64,10 +68,27 @@ public final class ForgeBMCLVersionList extends VersionList throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list."); } + private static String toLookupVersion(String gameVersion) { + return "1.7.10-pre4".equals(gameVersion) ? "1.7.10_pre4" : gameVersion; + } + + private static String fromLookupVersion(String lookupVersion) { + return "1.7.10_pre4".equals(lookupVersion) ? "1.7.10-pre4" : lookupVersion; + } + + private static String toLookupBranch(String gameVersion, String branch) { + if ("1.7.10-pre4".equals(gameVersion)) { + return "prerelease"; + } + return Lang.requireNonNullElse(branch, ""); + } + @Override public CompletableFuture refreshAsync(String gameVersion) { + String lookupVersion = toLookupVersion(gameVersion); + return CompletableFuture.completedFuture(null) - .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + gameVersion).>getJson(new TypeToken>() { + .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).>getJson(new TypeToken>() { }.getType()))) .thenAcceptAsync(forgeVersions -> { lock.writeLock().lock(); @@ -81,16 +102,17 @@ public final class ForgeBMCLVersionList extends VersionList List urls = new ArrayList<>(); for (ForgeVersion.File file : version.getFiles()) if ("installer".equals(file.getCategory()) && "jar".equals(file.getFormat())) { - String classifier = gameVersion + "-" + version.getVersion() - + (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : ""); + String branch = toLookupBranch(gameVersion, version.getBranch()); + + String classifier = lookupVersion + "-" + version.getVersion() + (branch.isEmpty() ? "" : '-' + branch); String fileName1 = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat(); - String fileName2 = "forge-" + classifier + "-" + gameVersion + "-" + file.getCategory() + "." + file.getFormat(); + String fileName2 = "forge-" + classifier + "-" + lookupVersion + "-" + file.getCategory() + "." + file.getFormat(); urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "/" + fileName1); - urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "-" + gameVersion + "/" + fileName2); + urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "-" + lookupVersion + "/" + fileName2); urls.add(NetworkUtils.withQuery("https://bmclapi2.bangbang93.com/forge/download", mapOf( pair("mcversion", version.getGameVersion()), pair("version", version.getVersion()), - pair("branch", version.getBranch()), + pair("branch", branch), pair("category", file.getCategory()), pair("format", file.getFormat()) ))); @@ -109,7 +131,7 @@ public final class ForgeBMCLVersionList extends VersionList } versions.put(gameVersion, new ForgeRemoteVersion( - version.getGameVersion(), version.getVersion(), releaseDate, urls)); + fromLookupVersion(version.getGameVersion()), version.getVersion(), releaseDate, urls)); } } finally { lock.writeLock().unlock(); diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersion.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersion.java index a8a83fb4..a77009ea 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersion.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersion.java @@ -27,7 +27,7 @@ public final class ForgeVersion implements Validation { private final String jobver; private final String version; private final int build; - private final double modified; + private final String modified; private final String[][] files; /** @@ -35,10 +35,10 @@ public final class ForgeVersion implements Validation { */ @SuppressWarnings("unused") public ForgeVersion() { - this(null, null, null, null, 0, 0, null); + this(null, null, null, null, 0, null, null); } - public ForgeVersion(String branch, String mcversion, String jobver, String version, int build, double modified, String[][] files) { + public ForgeVersion(String branch, String mcversion, String jobver, String version, int build, String modified, String[][] files) { this.branch = branch; this.mcversion = mcversion; this.jobver = jobver; @@ -68,7 +68,7 @@ public final class ForgeVersion implements Validation { return build; } - public double getModified() { + public String getModified() { return modified; } diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersionList.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersionList.java index 238f42d1..9866ea41 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersionList.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/forge/ForgeVersionList.java @@ -23,9 +23,13 @@ import com.tungsten.fclcore.util.StringUtils; import com.tungsten.fclcore.util.io.HttpRequest; import com.tungsten.fclcore.util.versioning.VersionNumber; +import java.time.Instant; import java.util.Collections; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.logging.Level; + +import static com.tungsten.fclcore.util.Logging.LOG; public final class ForgeVersionList extends VersionList { private final DownloadProvider downloadProvider; @@ -39,9 +43,17 @@ public final class ForgeVersionList extends VersionList { return false; } + private static String toLookupVersion(String gameVersion) { + return "1.7.10-pre4".equals(gameVersion) ? "1.7.10_pre4" : gameVersion; + } + + private static String fromLookupVersion(String lookupVersion) { + return "1.7.10_pre4".equals(lookupVersion) ? "1.7.10-pre4" : lookupVersion; + } + @Override public CompletableFuture refreshAsync() { - return HttpRequest.GET(downloadProvider.injectURL(FORGE_LIST)).getJsonAsync(ForgeVersionRoot.class) + return HttpRequest.GET(FORGE_LIST).getJsonAsync(ForgeVersionRoot.class) .thenAcceptAsync(root -> { lock.writeLock().lock(); @@ -51,7 +63,7 @@ public final class ForgeVersionList extends VersionList { versions.clear(); for (Map.Entry entry : root.getGameVersions().entrySet()) { - String gameVersion = VersionNumber.normalize(entry.getKey()); + String gameVersion = fromLookupVersion(VersionNumber.normalize(entry.getKey())); for (int v : entry.getValue()) { ForgeVersion version = root.getNumber().get(v); if (version == null) @@ -67,8 +79,19 @@ public final class ForgeVersionList extends VersionList { if (jar == null) continue; + + Instant releaseDate = null; + if (version.getModified() != null) { + try { + long timestamp = Long.parseLong(version.getModified()); + releaseDate = Instant.ofEpochSecond(timestamp); + } catch (NumberFormatException e) { + LOG.log(Level.WARNING, "Failed to parse instant " + version.getModified(), e); + } + } + versions.put(gameVersion, new ForgeRemoteVersion( - version.getGameVersion(), version.getVersion(), null, Collections.singletonList(jar) + toLookupVersion(version.getGameVersion()), version.getVersion(), releaseDate, Collections.singletonList(jar) )); } } @@ -78,5 +101,5 @@ public final class ForgeVersionList extends VersionList { }); } - public static final String FORGE_LIST = "https://files.minecraftforge.net/maven/net/minecraftforge/forge/json"; -} + public static final String FORGE_LIST = "https://zkitefly.github.io/forge-maven-metadata/list.json"; +} \ No newline at end of file diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFine302VersionList.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFine302VersionList.java new file mode 100644 index 00000000..7ddfbf5a --- /dev/null +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFine302VersionList.java @@ -0,0 +1,94 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2020 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.tungsten.fclcore.download.optifine; + +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.tungsten.fclcore.download.VersionList; +import com.tungsten.fclcore.util.io.HttpRequest; +import com.tungsten.fclcore.util.versioning.VersionNumber; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +/** + * @author huangyuhui + */ +public final class OptiFine302VersionList extends VersionList { + private final String versionListURL; + + public OptiFine302VersionList(String versionListURL) { + this.versionListURL = versionListURL; + } + + @Override + public boolean hasType() { + return true; + } + + @Override + public CompletableFuture refreshAsync() { + return HttpRequest.GET(versionListURL).getJsonAsync(new TypeToken() { + }.getType()).thenAcceptAsync(root -> { + lock.writeLock().lock(); + + try { + versions.clear(); + for (OptiFineVersion element : root.versions) { + String gameVersion = VersionNumber.normalize(element.gameVersion); + versions.put(gameVersion, new OptiFineRemoteVersion( + gameVersion, element.version, + root.downloadBases.stream().map(u -> u + element.fileName).collect(Collectors.toList()), + element.fileName.startsWith("pre") + )); + } + } finally { + lock.writeLock().unlock(); + } + }); + } + + private static final class VersionList { + @SerializedName("file") + private final List versions; + + @SerializedName("download") + private final List downloadBases; + + public VersionList(List versions, List downloadBases) { + this.versions = versions; + this.downloadBases = downloadBases; + } + } + + private static final class OptiFineVersion { + @SerializedName("name") + private final String version; + @SerializedName("filename") + private final String fileName; + @SerializedName("mcversion") + private final String gameVersion; + + public OptiFineVersion(String version, String fileName, String gameVersion) { + this.version = version; + this.fileName = fileName; + this.gameVersion = gameVersion; + } + } +} \ No newline at end of file diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineBMCLVersionList.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineBMCLVersionList.java index 08515d1a..5b1f3f33 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineBMCLVersionList.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineBMCLVersionList.java @@ -17,6 +17,7 @@ */ package com.tungsten.fclcore.download.optifine; +import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; import com.tungsten.fclcore.download.VersionList; import com.tungsten.fclcore.util.StringUtils; @@ -47,31 +48,46 @@ public final class OptiFineBMCLVersionList extends VersionList refreshAsync() { return HttpRequest.GET(apiRoot + "/optifine/versionlist").>getJsonAsync(new TypeToken>() { - }.getType()) - .thenAcceptAsync(root -> { - lock.writeLock().lock(); + }.getType()).thenAcceptAsync(root -> { + lock.writeLock().lock(); - try { - versions.clear(); - Set duplicates = new HashSet<>(); - for (OptiFineVersion element : root) { - String version = element.getType() + "_" + element.getPatch(); - String mirror = "https://bmclapi2.bangbang93.com/optifine/" + element.getGameVersion() + "/" + element.getType() + "/" + element.getPatch(); - if (!duplicates.add(mirror)) - continue; + try { + versions.clear(); + Set duplicates = new HashSet<>(); + for (OptiFineVersion element : root) { + String version = element.type + "_" + element.patch; + String mirror = apiRoot + "/optifine/" + element.gameVersion + "/" + element.type + "/" + element.patch; + if (!duplicates.add(mirror)) + continue; - boolean isPre = element.getPatch() != null && (element.getPatch().startsWith("pre") || element.getPatch().startsWith("alpha")); + boolean isPre = element.patch != null && (element.patch.startsWith("pre") || element.patch.startsWith("alpha")); - if (StringUtils.isBlank(element.getGameVersion())) - continue; + if (StringUtils.isBlank(element.gameVersion)) + continue; - String gameVersion = VersionNumber.normalize(element.getGameVersion()); - versions.put(gameVersion, new OptiFineRemoteVersion(gameVersion, version, Collections.singletonList(mirror), isPre)); - } - } finally { - lock.writeLock().unlock(); - } - }); + String gameVersion = VersionNumber.normalize(element.gameVersion); + versions.put(gameVersion, new OptiFineRemoteVersion(gameVersion, version, Collections.singletonList(mirror), isPre)); + } + } finally { + lock.writeLock().unlock(); + } + }); } -} + private static final class OptiFineVersion { + @SerializedName("type") + private final String type; + + @SerializedName("patch") + private final String patch; + + @SerializedName("mcversion") + private final String gameVersion; + + public OptiFineVersion(String type, String patch, String gameVersion) { + this.type = type; + this.patch = patch; + this.gameVersion = gameVersion; + } + } +} \ No newline at end of file diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineRemoteVersion.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineRemoteVersion.java index c29688cc..ddac5ebe 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineRemoteVersion.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineRemoteVersion.java @@ -31,6 +31,11 @@ public class OptiFineRemoteVersion extends RemoteVersion { super(LibraryAnalyzer.LibraryType.OPTIFINE.getPatchId(), gameVersion, selfVersion, null, snapshot ? Type.SNAPSHOT : Type.RELEASE, urls); } + @Override + public String getFullVersion() { + return getGameVersion() + "_" + getSelfVersion(); + } + @Override public Task getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) { return new OptiFineInstallTask(dependencyManager, baseVersion, this); diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineVersion.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineVersion.java deleted file mode 100644 index 03c3817e..00000000 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/optifine/OptiFineVersion.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.tungsten.fclcore.download.optifine; - -import com.google.gson.annotations.SerializedName; - -public final class OptiFineVersion { - - @SerializedName("dl") - private final String downloadLink; - - @SerializedName("ver") - private final String version; - - @SerializedName("date") - private final String date; - - @SerializedName("type") - private final String type; - - @SerializedName("patch") - private final String patch; - - @SerializedName("mirror") - private final String mirror; - - @SerializedName("mcversion") - private final String gameVersion; - - public OptiFineVersion() { - this(null, null, null, null, null, null, null); - } - - public OptiFineVersion(String downloadLink, String version, String date, String type, String patch, String mirror, String gameVersion) { - this.downloadLink = downloadLink; - this.version = version; - this.date = date; - this.type = type; - this.patch = patch; - this.mirror = mirror; - this.gameVersion = gameVersion; - } - - public String getDownloadLink() { - return downloadLink; - } - - public String getVersion() { - return version; - } - - public String getDate() { - return date; - } - - public String getType() { - return type; - } - - public String getPatch() { - return patch; - } - - public String getMirror() { - return mirror; - } - - public String getGameVersion() { - return gameVersion; - } -} diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/game/AssetIndex.java b/FCLCore/src/main/java/com/tungsten/fclcore/game/AssetIndex.java index c7728e5d..c6f8c691 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/game/AssetIndex.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/game/AssetIndex.java @@ -48,6 +48,10 @@ public final class AssetIndex { return virtual || mapToResources; } + public boolean needMapToResources() { + return mapToResources; + } + public Map getObjects() { return Collections.unmodifiableMap(objects); } diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/game/DefaultGameRepository.java b/FCLCore/src/main/java/com/tungsten/fclcore/game/DefaultGameRepository.java index ab069a19..ea686812 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/game/DefaultGameRepository.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/game/DefaultGameRepository.java @@ -23,14 +23,7 @@ import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; import com.tungsten.fclcore.download.MaintainTask; import com.tungsten.fclcore.download.game.VersionJsonSaveTask; -import com.tungsten.fclcore.event.Event; -import com.tungsten.fclcore.event.EventBus; -import com.tungsten.fclcore.event.GameJsonParseFailedEvent; -import com.tungsten.fclcore.event.LoadedOneVersionEvent; -import com.tungsten.fclcore.event.RefreshedVersionsEvent; -import com.tungsten.fclcore.event.RefreshingVersionsEvent; -import com.tungsten.fclcore.event.RemoveVersionEvent; -import com.tungsten.fclcore.event.RenameVersionEvent; +import com.tungsten.fclcore.event.*; import com.tungsten.fclcore.game.tlauncher.TLauncherVersion; import com.tungsten.fclcore.mod.ModManager; import com.tungsten.fclcore.mod.ModpackConfiguration; @@ -47,13 +40,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.TreeMap; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.stream.Stream; @@ -125,9 +112,12 @@ public class DefaultGameRepository implements GameRepository { @Override public File getRunDirectory(String id) { switch (getGameDirectoryType(id)) { - case VERSION_FOLDER: return getVersionRoot(id); - case ROOT_FOLDER: return getBaseDirectory(); - default: throw new IllegalStateException(); + case VERSION_FOLDER: + return getVersionRoot(id); + case ROOT_FOLDER: + return getBaseDirectory(); + default: + throw new IllegalStateException(); } } @@ -448,6 +438,8 @@ public class DefaultGameRepository implements GameRepository { return assetsDir; if (index.isVirtual()) { + Path resourcesDir = getRunDirectory(version).toPath().resolve("resources"); + int cnt = 0; int tot = index.getObjects().entrySet().size(); for (Map.Entry entry : index.getObjects().entrySet()) { @@ -457,6 +449,12 @@ public class DefaultGameRepository implements GameRepository { cnt++; if (!Files.isRegularFile(target)) FileUtils.copyFile(original, target); + + if (index.needMapToResources()) { + target = resourcesDir.resolve(entry.getKey()); + if (!Files.isRegularFile(target)) + FileUtils.copyFile(original, target); + } } } @@ -489,18 +487,20 @@ public class DefaultGameRepository implements GameRepository { /** * read modpack configuration for a version. + * * @param version version installed as modpack - * @param manifest type of ModpackConfiguration + * @param manifest type of ModpackConfiguration * @return modpack configuration object, or null if this version is not a modpack. * @throws VersionNotFoundException if version does not exist. - * @throws IOException if an i/o error occurs. + * @throws IOException if an i/o error occurs. */ @Nullable public ModpackConfiguration readModpackConfiguration(String version) throws IOException, VersionNotFoundException { if (!hasVersion(version)) throw new VersionNotFoundException(version); File file = getModpackConfiguration(version); if (!file.exists()) return null; - return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken>(){}.getType()); + return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken>() { + }.getType()); } public boolean isModpack(String version) { diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/game/GameVersion.java b/FCLCore/src/main/java/com/tungsten/fclcore/game/GameVersion.java index faa3e4f2..94106125 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/game/GameVersion.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/game/GameVersion.java @@ -17,7 +17,6 @@ */ package com.tungsten.fclcore.game; -import static com.tungsten.fclcore.util.Lang.tryCast; import static com.tungsten.fclcore.util.Logging.LOG; import com.google.gson.JsonParseException; @@ -47,8 +46,11 @@ public final class GameVersion { private static Optional getVersionFromJson(InputStream versionJson) { try { Map version = JsonUtils.fromNonNullJsonFully(versionJson, Map.class); - return tryCast(version.get("id"), String.class); - } catch (IOException | JsonParseException e) { + String id = (String) version.get("id"); + if (id != null && id.contains(" / ")) + id = id.substring(0, id.indexOf(" / ")); + return Optional.ofNullable(id); + } catch (IOException | JsonParseException | ClassCastException e) { LOG.log(Level.WARNING, "Failed to parse version.json", e); return Optional.empty(); } diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/task/FetchTask.java b/FCLCore/src/main/java/com/tungsten/fclcore/task/FetchTask.java index 366f363f..3abed86e 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/task/FetchTask.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/task/FetchTask.java @@ -94,6 +94,7 @@ public abstract class FetchTask extends Task { break download; } + List redirects = null; try { beforeDownload(url); @@ -103,7 +104,9 @@ public abstract class FetchTask extends Task { if (checkETag) repository.injectConnection(conn); if (conn instanceof HttpURLConnection) { - conn = NetworkUtils.resolveConnection((HttpURLConnection) conn); + redirects = new ArrayList<>(); + + conn = NetworkUtils.resolveConnection((HttpURLConnection) conn, redirects); int responseCode = ((HttpURLConnection) conn).getResponseCode(); if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) { @@ -164,13 +167,13 @@ public abstract class FetchTask extends Task { } catch (FileNotFoundException ex) { failedURL = url; exception = ex; - Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", not found", ex); + Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", not found" + ((redirects == null || redirects.isEmpty()) ? "" : ", redirects: " + redirects), ex); break; // we will not try this URL again } catch (IOException ex) { failedURL = url; exception = ex; - Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", repeat times: " + (++repeat), ex); + Logging.LOG.log(Level.WARNING, "Failed to download " + url + ", repeat times: " + (++repeat) + ((redirects == null || redirects.isEmpty()) ? "" : ", redirects: " + redirects), ex); } } } diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/util/CacheRepository.java b/FCLCore/src/main/java/com/tungsten/fclcore/util/CacheRepository.java index 3d8494b2..50ce3c41 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/util/CacheRepository.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/util/CacheRepository.java @@ -294,8 +294,12 @@ public class CacheRepository { ETagIndex indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class); Map newIndex = joinETagIndexes(indexOnDisk == null ? null : indexOnDisk.eTag, index.values()); channel.truncate(0); - ETagIndex writeTo = new ETagIndex(newIndex.values()); - channel.write(ByteBuffer.wrap(JsonUtils.GSON.toJson(writeTo).getBytes(UTF_8))); + ByteBuffer writeTo = ByteBuffer.wrap(JsonUtils.GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8)); + while (writeTo.hasRemaining()) { + if (channel.write(writeTo) == 0) { + throw new IOException("No value is written"); + } + } this.index = newIndex; } finally { lock.release(); diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java b/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java index 850f40d8..9ba2cd53 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java @@ -144,6 +144,10 @@ public final class NetworkUtils { return sb.toString(); } + public static HttpURLConnection resolveConnection(HttpURLConnection conn) throws IOException { + return resolveConnection(conn, null); + } + /** * This method is a work-around that aims to solve problem when "Location" in * stupid server's response is not encoded. @@ -153,7 +157,7 @@ public final class NetworkUtils { * @return manually redirected http connection. * @throws IOException if an I/O error occurs. */ - public static HttpURLConnection resolveConnection(HttpURLConnection conn) throws IOException { + public static HttpURLConnection resolveConnection(HttpURLConnection conn, List redirects) throws IOException { int redirect = 0; while (true) { @@ -168,6 +172,9 @@ public final class NetworkUtils { String newURL = conn.getHeaderField("Location"); conn.disconnect(); + if (redirects != null) { + redirects.add(newURL); + } if (redirect > 20) { throw new IOException("Too much redirects"); } diff --git a/version_map.json b/version_map.json index 4958f596..6a083614 100644 --- a/version_map.json +++ b/version_map.json @@ -1,9 +1,9 @@ [ { "type": "release", - "versionCode": 1175, - "versionName": "1.1.7.5", - "date": "2024.08.16", + "versionCode": 1176, + "versionName": "1.1.7.6", + "date": "2024.08.23", "description": [ { "lang": "en", @@ -11,10 +11,10 @@ }, { "lang": "zh_CN", - "text": "FCL 1.1.7.5更新内容(若启动器内下载缓慢请使用网盘下载,64位的请下载arm64,不知道该下哪个的请下载all)\n1.更新赞助链接\n2.更新turnip驱动\n3.允许使用外部应用选择文件\n4.移除xhook改为bytehook\n5.修复少量bug" + "text": "FCL 1.1.7.6更新内容(若启动器内下载缓慢请使用网盘下载,64位的请下载arm64,不知道该下哪个的请下载all)\n1.修复微软登录时的错误提示\n2.修复neoforge整合包版本错误\n3.修复手动选择整合包时的整合包为非正常格式时无法安装的bug\n4.可手动选择执行jar文件使用的java\n5.同步部分HMCL Core,修复些许bug" } ], - "netdiskUrl": "https://pan.quark.cn/s/b65dd99d5555", - "url": "https://github.com/FCL-Team/FoldCraftLauncher/releases/download/1.1.7.5/FCL-release-1.1.7.5-all.apk" + "netdiskUrl": "https://pan.quark.cn/s/04bc07022a7d", + "url": "https://github.com/FCL-Team/FoldCraftLauncher/releases/download/1.1.7.6/FCL-release-1.1.7.6-all.apk" } ]