diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index b99d5ed62e..ed1f3d0561 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -321,6 +321,8 @@ public Image getVersionIconImage(String id) { return VersionIconType.FABRIC.getIcon(); else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.QUILT)) return VersionIconType.QUILT.getIcon(); + else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.LEGACY_FABRIC)) + return VersionIconType.LEGACY_FABRIC.getIcon(); else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.NEO_FORGE)) return VersionIconType.NEO_FORGE.getIcon(); else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.FORGE)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java index 09675738c3..dd19336b8c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionIconType.java @@ -36,7 +36,9 @@ public enum VersionIconType { FURNACE("/assets/img/furnace.png"), QUILT("/assets/img/quilt.png"), APRIL_FOOLS("/assets/img/april_fools.png"), - CLEANROOM("/assets/img/cleanroom.png"); + CLEANROOM("/assets/img/cleanroom.png"), + LEGACY_FABRIC("/assets/img/legacyfabric.png") + ; // Please append new items at last diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java index 9c237a7bd8..486d769b82 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -127,37 +127,18 @@ public InstallerItem(String id, Style style) { this.id = id; this.style = style; - switch (id) { - case "game": - iconType = VersionIconType.GRASS; - break; - case "fabric": - case "fabric-api": - iconType = VersionIconType.FABRIC; - break; - case "forge": - iconType = VersionIconType.FORGE; - break; - case "cleanroom": - iconType = VersionIconType.CLEANROOM; - break; - case "liteloader": - iconType = VersionIconType.CHICKEN; - break; - case "optifine": - iconType = VersionIconType.OPTIFINE; - break; - case "quilt": - case "quilt-api": - iconType = VersionIconType.QUILT; - break; - case "neoforge": - iconType = VersionIconType.NEO_FORGE; - break; - default: - iconType = null; - break; - } + iconType = switch (id) { + case "game" -> VersionIconType.GRASS; + case "fabric", "fabric-api" -> VersionIconType.FABRIC; + case "legacyfabric", "legacyfabric-api" -> VersionIconType.LEGACY_FABRIC; + case "forge" -> VersionIconType.FORGE; + case "cleanroom" -> VersionIconType.CLEANROOM; + case "liteloader" -> VersionIconType.CHICKEN; + case "optifine" -> VersionIconType.OPTIFINE; + case "quilt", "quilt-api" -> VersionIconType.QUILT; + case "neoforge" -> VersionIconType.NEO_FORGE; + default -> null; + }; } public String getLibraryId() { @@ -236,6 +217,8 @@ public InstallerItemGroup(String gameVersion, Style style) { InstallerItem fabricApi = new InstallerItem(FABRIC_API, style); InstallerItem forge = new InstallerItem(FORGE, style); InstallerItem cleanroom = new InstallerItem(CLEANROOM, style); + InstallerItem legacyfabric = new InstallerItem(LEGACY_FABRIC, style); + InstallerItem legacyfabricApi = new InstallerItem(LEGACY_FABRIC_API, style); InstallerItem neoForge = new InstallerItem(NEO_FORGE, style); InstallerItem liteLoader = new InstallerItem(LITELOADER, style); InstallerItem optiFine = new InstallerItem(OPTIFINE, style); @@ -243,11 +226,11 @@ public InstallerItemGroup(String gameVersion, Style style) { InstallerItem quiltApi = new InstallerItem(QUILT_API, style); Map> incompatibleMap = new HashMap<>(); - mutualIncompatible(incompatibleMap, forge, fabric, quilt, neoForge, cleanroom); - addIncompatibles(incompatibleMap, liteLoader, fabric, quilt, neoForge, cleanroom); - addIncompatibles(incompatibleMap, optiFine, fabric, quilt, neoForge, cleanroom); - addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine, cleanroom); - addIncompatibles(incompatibleMap, quiltApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom); + mutualIncompatible(incompatibleMap, forge, fabric, quilt, neoForge, cleanroom, legacyfabric); + addIncompatibles(incompatibleMap, liteLoader, fabric, quilt, neoForge, cleanroom, legacyfabric); + addIncompatibles(incompatibleMap, optiFine, fabric, quilt, neoForge, cleanroom, liteLoader, legacyfabric); + addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabricApi, legacyfabricApi); + addIncompatibles(incompatibleMap, quiltApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabric, legacyfabricApi); for (Map.Entry> entry : incompatibleMap.entrySet()) { InstallerItem item = entry.getKey(); @@ -281,7 +264,7 @@ public InstallerItemGroup(String gameVersion, Style style) { game.versionProperty.set(new InstalledState(gameVersion, false, false)); } - InstallerItem[] all = {game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi, cleanroom}; + InstallerItem[] all = {game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi, legacyfabric, legacyfabricApi, cleanroom}; for (InstallerItem item : all) { if (!item.resolvedStateProperty.isBound()) { @@ -298,9 +281,9 @@ public InstallerItemGroup(String gameVersion, Style style) { if (gameVersion == null) { this.libraries = all; } else if (gameVersion.equals("1.12.2")) { - this.libraries = new InstallerItem[]{game, forge, cleanroom, liteLoader, optiFine}; - } else if (GameVersionNumber.compare(gameVersion, "1.13") < 0) { - this.libraries = new InstallerItem[]{game, forge, liteLoader, optiFine}; + this.libraries = new InstallerItem[]{game, forge, cleanroom, liteLoader, legacyfabric, legacyfabricApi, optiFine}; + } else if (GameVersionNumber.compare(gameVersion, "1.13.2") <= 0) { + this.libraries = new InstallerItem[]{game, forge, liteLoader, optiFine, legacyfabric, legacyfabricApi}; } else { this.libraries = new InstallerItem[]{game, forge, neoForge, optiFine, fabric, fabricApi, quilt, quiltApi}; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java index 06153282b2..0eb62cbed8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java @@ -41,6 +41,7 @@ import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; import org.jackhuang.hmcl.download.game.GameInstallTask; import org.jackhuang.hmcl.download.java.mojang.MojangJavaDownloadTask; +import org.jackhuang.hmcl.download.legacyfabric.LegacyFabricInstallTask; import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask; import org.jackhuang.hmcl.download.neoforge.NeoForgeInstallTask; import org.jackhuang.hmcl.download.neoforge.NeoForgeOldInstallTask; @@ -164,6 +165,8 @@ public void onRunning(Task task) { task.setName(i18n("install.installer.install", i18n("install.installer.game"))); } else if (task instanceof CleanroomInstallTask) { task.setName(i18n("install.installer.install", i18n("install.installer.cleanroom"))); + } else if (task instanceof LegacyFabricInstallTask) { + task.setName(i18n("install.installer.install", i18n("install.installer.legacyfabric"))); } else if (task instanceof ForgeNewInstallTask || task instanceof ForgeOldInstallTask) { task.setName(i18n("install.installer.install", i18n("install.installer.forge"))); } else if (task instanceof NeoForgeInstallTask || task instanceof NeoForgeOldInstallTask) { @@ -427,23 +430,25 @@ private StageNode(String stage) { // CHECKSTYLE:OFF // @formatter:off - switch (stageKey) { - case "hmcl.modpack": message = i18n("install.modpack"); break; - case "hmcl.modpack.download": message = i18n("launch.state.modpack"); break; - case "hmcl.install.assets": message = i18n("assets.download"); break; - case "hmcl.install.libraries": message = i18n("libraries.download"); break; - case "hmcl.install.game": message = i18n("install.installer.install", i18n("install.installer.game") + " " + stageValue); break; - case "hmcl.install.forge": message = i18n("install.installer.install", i18n("install.installer.forge") + " " + stageValue); break; - case "hmcl.install.cleanroom": message = i18n("install.installer.install", i18n("install.installer.cleanroom") + " " + stageValue); break; - case "hmcl.install.neoforge": message = i18n("install.installer.install", i18n("install.installer.neoforge") + " " + stageValue); break; - case "hmcl.install.liteloader": message = i18n("install.installer.install", i18n("install.installer.liteloader") + " " + stageValue); break; - case "hmcl.install.optifine": message = i18n("install.installer.install", i18n("install.installer.optifine") + " " + stageValue); break; - case "hmcl.install.fabric": message = i18n("install.installer.install", i18n("install.installer.fabric") + " " + stageValue); break; - case "hmcl.install.fabric-api": message = i18n("install.installer.install", i18n("install.installer.fabric-api") + " " + stageValue); break; - case "hmcl.install.quilt": message = i18n("install.installer.install", i18n("install.installer.quilt") + " " + stageValue); break; - case "hmcl.install.quilt-api": message = i18n("install.installer.install", i18n("install.installer.quilt-api") + " " + stageValue); break; - default: message = i18n(stageKey); break; - } + message = switch (stageKey) { + case "hmcl.modpack" -> i18n("install.modpack"); + case "hmcl.modpack.download" -> i18n("launch.state.modpack"); + case "hmcl.install.assets" -> i18n("assets.download"); + case "hmcl.install.libraries" -> i18n("libraries.download"); + case "hmcl.install.game" -> i18n("install.installer.install", i18n("install.installer.game") + " " + stageValue); + case "hmcl.install.forge" -> i18n("install.installer.install", i18n("install.installer.forge") + " " + stageValue); + case "hmcl.install.cleanroom" -> i18n("install.installer.install", i18n("install.installer.cleanroom") + " " + stageValue); + case "hmcl.install.neoforge" -> i18n("install.installer.install", i18n("install.installer.neoforge") + " " + stageValue); + case "hmcl.install.liteloader" -> i18n("install.installer.install", i18n("install.installer.liteloader") + " " + stageValue); + case "hmcl.install.optifine" -> i18n("install.installer.install", i18n("install.installer.optifine") + " " + stageValue); + case "hmcl.install.fabric" -> i18n("install.installer.install", i18n("install.installer.fabric") + " " + stageValue); + case "hmcl.install.fabric-api" -> i18n("install.installer.install", i18n("install.installer.fabric-api") + " " + stageValue); + case "hmcl.install.legacyfabric" -> i18n("install.installer.install", i18n("install.installer.legacyfabric") + " " + stageValue); + case "hmcl.install.legacyfabric-api" -> i18n("install.installer.install", i18n("install.installer.legacyfabric-api") + " " + stageValue); + case "hmcl.install.quilt" -> i18n("install.installer.install", i18n("install.installer.quilt") + " " + stageValue); + case "hmcl.install.quilt-api" -> i18n("install.installer.install", i18n("install.installer.quilt-api") + " " + stageValue); + default -> i18n(stageKey); + }; // @formatter:on // CHECKSTYLE:ON diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index 346c4a0dfa..efc8b25c07 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -121,32 +121,20 @@ private void setTxtNameWithLoaders() { LibraryAnalyzer.LibraryType libraryType = LibraryAnalyzer.LibraryType.fromPatchId(libraryId); if (libraryType != null) { - String loaderName; - switch (libraryType) { - case FORGE: - loaderName = i18n("install.installer.forge"); - break; - case NEO_FORGE: - loaderName = i18n("install.installer.neoforge"); - break; - case CLEANROOM: - loaderName = i18n("install.installer.cleanroom"); - break; - case FABRIC: - loaderName = i18n("install.installer.fabric"); - break; - case LITELOADER: - loaderName = i18n("install.installer.liteloader"); - break; - case QUILT: - loaderName = i18n("install.installer.quilt"); - break; - case OPTIFINE: - loaderName = i18n("install.installer.optifine"); - break; - default: - continue; - } + String loaderName = switch (libraryType) { + case FORGE -> i18n("install.installer.forge"); + case NEO_FORGE -> i18n("install.installer.neoforge"); + case CLEANROOM -> i18n("install.installer.cleanroom"); + case LEGACY_FABRIC -> i18n("install.installer.legacyfabric").replace(" ", "_"); + case FABRIC -> i18n("install.installer.fabric"); + case LITELOADER -> i18n("install.installer.liteloader"); + case QUILT -> i18n("install.installer.quilt"); + case OPTIFINE -> i18n("install.installer.optifine"); + default -> null; + }; + + if (loaderName == null) + continue; nameBuilder.append("-").append(loaderName); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index daa341ee8a..1e88870b61 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -38,6 +38,8 @@ import org.jackhuang.hmcl.download.fabric.FabricRemoteVersion; import org.jackhuang.hmcl.download.forge.ForgeRemoteVersion; import org.jackhuang.hmcl.download.game.GameRemoteVersion; +import org.jackhuang.hmcl.download.legacyfabric.LegacyFabricAPIRemoteVersion; +import org.jackhuang.hmcl.download.legacyfabric.LegacyFabricRemoteVersion; import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersion; import org.jackhuang.hmcl.download.neoforge.NeoForgeRemoteVersion; import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion; @@ -273,6 +275,8 @@ else if (remoteVersion instanceof CleanroomRemoteVersion) iconType = VersionIconType.CLEANROOM; else if (remoteVersion instanceof NeoForgeRemoteVersion) iconType = VersionIconType.NEO_FORGE; + else if (remoteVersion instanceof LegacyFabricRemoteVersion || remoteVersion instanceof LegacyFabricAPIRemoteVersion) + iconType = VersionIconType.LEGACY_FABRIC; else if (remoteVersion instanceof FabricRemoteVersion || remoteVersion instanceof FabricAPIRemoteVersion) iconType = VersionIconType.FABRIC; else if (remoteVersion instanceof QuiltRemoteVersion || remoteVersion instanceof QuiltAPIRemoteVersion) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index 2f487ff1d8..5d7aa7fbe1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -76,12 +76,12 @@ public void loadVersion(Profile profile, String versionId) { InstallerItem.InstallerItemGroup group = new InstallerItem.InstallerItemGroup(gameVersion, InstallerItem.Style.LIST_ITEM); - // Conventional libraries: game, fabric, forge, cleanroom, neoforge, liteloader, optifine + // Conventional libraries: game, fabric, legacyfabric, forge, cleanroom, neoforge, liteloader, optifine for (InstallerItem item : group.getLibraries()) { String libraryId = item.getLibraryId(); - // Skip fabric-api and quilt-api - if (libraryId.contains("fabric-api") || libraryId.contains("quilt-api")) { + // Skip fabric-api and quilt-api and legacyfabric-api + if (libraryId.endsWith("-api")) { continue; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index e91f1b3da9..5b937682a1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -152,6 +152,10 @@ private void updateSupportedLoaders(ModManager modManager) { supportedLoaders.add(ModLoaderType.FABRIC); } + if (analyzer.has(LibraryAnalyzer.LibraryType.LEGACY_FABRIC)) { + supportedLoaders.add(ModLoaderType.FABRIC); + } + if (analyzer.has(LibraryAnalyzer.LibraryType.FABRIC) && modManager.hasMod("kilt", ModLoaderType.FABRIC)) { supportedLoaders.add(ModLoaderType.FORGE); supportedLoaders.add(ModLoaderType.NEO_FORGED); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java index dd60f01301..7b018768d5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java @@ -457,29 +457,18 @@ final class ModInfoDialog extends JFXDialogLayout { RemoteMod remoteMod = repository.getModById(versionOptional.get().getModid()); FXUtils.runInFX(() -> { for (ModLoaderType modLoaderType : versionOptional.get().getLoaders()) { - String loaderName; - switch (modLoaderType) { - case FORGE: - loaderName = i18n("install.installer.forge"); - break; - case CLEANROOM: - loaderName = i18n("install.installer.cleanroom"); - break; - case NEO_FORGED: - loaderName = i18n("install.installer.neoforge"); - break; - case FABRIC: - loaderName = i18n("install.installer.fabric"); - break; - case LITE_LOADER: - loaderName = i18n("install.installer.liteloader"); - break; - case QUILT: - loaderName = i18n("install.installer.quilt"); - break; - default: - continue; - } + String loaderName = switch (modLoaderType) { + case FORGE -> i18n("install.installer.forge"); + case CLEANROOM -> i18n("install.installer.cleanroom"); + case LEGACY_FABRIC -> i18n("install.installer.legacyfabric"); + case NEO_FORGED -> i18n("install.installer.neoforge"); + case FABRIC -> i18n("install.installer.fabric"); + case LITE_LOADER -> i18n("install.installer.liteloader"); + case QUILT -> i18n("install.installer.quilt"); + default -> null; + }; + if (loaderName == null) + continue; if (title.getTags() .stream() .noneMatch(it -> it.getText().equals(loaderName))) { @@ -651,24 +640,13 @@ protected void updateControl(ModInfoObject dataItem, boolean empty) { } else if (!ModListPageSkin.this.getSkinnable().supportedLoaders.contains(modLoaderType)) { warning.add(i18n("mods.warning.loader_mismatch")); switch (dataItem.getModInfo().getModLoaderType()) { - case FORGE: - content.addTagWarning(i18n("install.installer.forge")); - break; - case CLEANROOM: - content.addTagWarning(i18n("install.installer.cleanroom")); - break; - case NEO_FORGED: - content.addTagWarning(i18n("install.installer.neoforge")); - break; - case FABRIC: - content.addTagWarning(i18n("install.installer.fabric")); - break; - case LITE_LOADER: - content.addTagWarning(i18n("install.installer.liteloader")); - break; - case QUILT: - content.addTagWarning(i18n("install.installer.quilt")); - break; + case FORGE -> content.addTagWarning(i18n("install.installer.forge")); + case LEGACY_FABRIC -> content.addTagWarning(i18n("install.installer.legacyfabric")); + case CLEANROOM -> content.addTagWarning(i18n("install.installer.cleanroom")); + case NEO_FORGED -> content.addTagWarning(i18n("install.installer.neoforge")); + case FABRIC -> content.addTagWarning(i18n("install.installer.fabric")); + case LITE_LOADER -> content.addTagWarning(i18n("install.installer.liteloader")); + case QUILT -> content.addTagWarning(i18n("install.installer.quilt")); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java index 3c35219364..a48fc63a09 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionIconDialog.java @@ -64,6 +64,7 @@ public VersionIconDialog(Profile profile, String versionId, Runnable onFinish) { createIcon(VersionIconType.OPTIFINE), createIcon(VersionIconType.CRAFT_TABLE), createIcon(VersionIconType.FABRIC), + createIcon(VersionIconType.LEGACY_FABRIC), createIcon(VersionIconType.FORGE), createIcon(VersionIconType.CLEANROOM), createIcon(VersionIconType.NEO_FORGE), diff --git a/HMCL/src/main/resources/assets/img/legacyfabric.png b/HMCL/src/main/resources/assets/img/legacyfabric.png new file mode 100644 index 0000000000..6dc7d3a661 Binary files /dev/null and b/HMCL/src/main/resources/assets/img/legacyfabric.png differ diff --git a/HMCL/src/main/resources/assets/img/legacyfabric@2x.png b/HMCL/src/main/resources/assets/img/legacyfabric@2x.png new file mode 100644 index 0000000000..dcc9bfcf71 Binary files /dev/null and b/HMCL/src/main/resources/assets/img/legacyfabric@2x.png differ diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index dbed63c568..4f3b1f9533 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -715,6 +715,8 @@ install.installer.depend=Requires %s install.installer.do_not_install=Do not install install.installer.fabric=Fabric install.installer.fabric-api=Fabric API +install.installer.legacyfabric=Legacy Fabric +install.installer.legacyfabric-api=Legacy Fabric API install.installer.fabric-api.warning=Warning: Fabric API is a mod and will be installed into the mod directory of the game instance. Please do not change the working directory of the game, or the Fabric API will not function. If you do want to change the directory, you should reinstall it. install.installer.forge=Forge install.installer.neoforge=NeoForge @@ -1273,6 +1275,7 @@ settings.advanced.custom_commands.hint=The following environment variables are p \ · $INST_LITELOADER: set if LiteLoader is installed.\n\ \ · $INST_OPTIFINE: set if OptiFine is installed.\n\ \ · $INST_FABRIC: set if Fabric is installed.\n\ + \ · $INST_LEGACYFABRIC: set if Legacy Fabric is installed.\n\ \ · $INST_QUILT: set if Quilt is installed. settings.advanced.dont_check_game_completeness=Do not check game integrity settings.advanced.dont_check_jvm_validity=Do not check JVM compatibility diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index e3a50aab7d..7d1632a5ec 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -522,6 +522,8 @@ install.installer.depend=需要先安裝 %s install.installer.do_not_install=不安裝 install.installer.fabric=Fabric install.installer.fabric-api=Fabric API +install.installer.legacyfabric=Legacy Fabric +install.installer.legacyfabric-api=Legacy Fabric API install.installer.fabric-api.warning=警告:Fabric API 是一個模組,將會被安裝到新遊戲的模組目錄。請你在安裝遊戲後不要修改目前遊戲的「執行路徑」設定。如果你在之後修改了相關設定,則需要重新安裝 Fabric API。 install.installer.forge=Forge install.installer.neoforge=NeoForge @@ -1066,6 +1068,7 @@ settings.advanced.custom_commands.hint=自訂指令被呼叫時將包含如下 \ · $INST_LITELOADER: 若安裝了 LiteLoader,將會存在本環境變數;\n\ \ · $INST_OPTIFINE: 若安裝了 OptiFine,將會存在本環境變數;\n\ \ · $INST_FABRIC: 若安裝了 Fabric,將會存在本環境變數;\n\ + \ · $INST_LEGACYFABRIC: 若安裝了 Legacy Fabric,將會存在本環境變數;\n\ \ · $INST_QUILT: 若安裝了 Quilt,將會存在本環境變數。 settings.advanced.dont_check_game_completeness=不檢查遊戲完整性 settings.advanced.dont_check_jvm_validity=不檢查 Java 虛擬機與遊戲的相容性 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 09aff45729..b3f3004c5a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -531,6 +531,8 @@ install.installer.cleanroom=Cleanroom install.installer.depend=需要先安装 %s install.installer.do_not_install=不安装 install.installer.fabric=Fabric +install.installer.legacyfabric=Legacy Fabric +install.installer.legacyfabric-api=Legacy Fabric API install.installer.fabric-api=Fabric API install.installer.fabric-api.warning=警告:Fabric API 是一个模组,将会被安装到新游戏的模组文件夹。请你在安装游戏后不要修改当前游戏的“运行路径”设置。如果你在之后修改了相关设置,则需要重新安装 Fabric API。 install.installer.forge=Forge @@ -1076,6 +1078,7 @@ settings.advanced.custom_commands.hint=自定义命令被调用时将包含如 \ · $INST_LITELOADER: 若安装了 LiteLoader,将会存在本环境变量;\n\ \ · $INST_OPTIFINE: 若安装了 OptiFine,将会存在本环境变量;\n\ \ · $INST_FABRIC: 若安装了 Fabric,将会存在本环境变量;\n\ + \ · $INST_LEGACYFABRIC: 若安装了 Legacy Fabric,将会存在本环境变量;\n\ \ · $INST_QUILT: 若安装了 Quilt,将会存在本环境变量。 settings.advanced.dont_check_game_completeness=不检查游戏完整性 settings.advanced.dont_check_jvm_validity=不检查 Java 虚拟机与游戏的兼容性 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java index 22b85cbf9d..7042d32279 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java @@ -22,6 +22,8 @@ import org.jackhuang.hmcl.download.fabric.FabricVersionList; import org.jackhuang.hmcl.download.forge.ForgeBMCLVersionList; import org.jackhuang.hmcl.download.game.GameVersionList; +import org.jackhuang.hmcl.download.legacyfabric.LegacyFabricAPIVersionList; +import org.jackhuang.hmcl.download.legacyfabric.LegacyFabricVersionList; import org.jackhuang.hmcl.download.liteloader.LiteLoaderBMCLVersionList; import org.jackhuang.hmcl.download.neoforge.NeoForgeBMCLVersionList; import org.jackhuang.hmcl.download.optifine.OptiFineBMCLVersionList; @@ -47,6 +49,8 @@ public final class BMCLAPIDownloadProvider implements DownloadProvider { private final FabricAPIVersionList fabricApi; private final ForgeBMCLVersionList forge; private final CleanroomVersionList cleanroom; + private final LegacyFabricVersionList legacyFabric; + private final LegacyFabricAPIVersionList legacyFabricApi; private final NeoForgeBMCLVersionList neoforge; private final LiteLoaderBMCLVersionList liteLoader; private final OptiFineBMCLVersionList optifine; @@ -66,6 +70,9 @@ public BMCLAPIDownloadProvider(String apiRoot) { this.optifine = new OptiFineBMCLVersionList(apiRoot); this.quilt = new QuiltVersionList(this); this.quiltApi = new QuiltAPIVersionList(this); + this.legacyFabric = new LegacyFabricVersionList(this); + this.legacyFabricApi = new LegacyFabricAPIVersionList(this); + this.replacement = Arrays.asList( pair("https://bmclapi2.bangbang93.com", apiRoot), pair("https://launchermeta.mojang.com", apiRoot), @@ -112,30 +119,21 @@ public List getAssetObjectCandidates(String assetObjectLocation) { @Override public VersionList getVersionListById(String id) { - switch (id) { - case "game": - return game; - case "fabric": - return fabric; - case "fabric-api": - return fabricApi; - case "forge": - return forge; - case "cleanroom": - return cleanroom; - case "neoforge": - return neoforge; - case "liteloader": - return liteLoader; - case "optifine": - return optifine; - case "quilt": - return quilt; - case "quilt-api": - return quiltApi; - default: - throw new IllegalArgumentException("Unrecognized version list id: " + id); - } + return switch (id) { + case "game" -> game; + case "fabric" -> fabric; + case "fabric-api" -> fabricApi; + case "forge" -> forge; + case "cleanroom" -> cleanroom; + case "neoforge" -> neoforge; + case "liteloader" -> liteLoader; + case "optifine" -> optifine; + case "quilt" -> quilt; + case "quilt-api" -> quiltApi; + case "legacyfabric" -> legacyFabric; + case "legacyfabric-api" -> legacyFabricApi; + default -> throw new IllegalArgumentException("Unrecognized version list id: " + id); + }; } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java index edbb735efa..bfbac5d9b2 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/LibraryAnalyzer.java @@ -189,7 +189,35 @@ public Set getModLoaders() { public enum LibraryType { MINECRAFT(true, "game", "^$", "^$", null), - FABRIC(true, "fabric", "net\\.fabricmc", "fabric-loader", ModLoaderType.FABRIC), + LEGACY_FABRIC(true, "legacyfabric", "net\\.fabricmc", "fabric-loader", ModLoaderType.LEGACY_FABRIC) { + @Override + protected boolean matchLibrary(Library library, List libraries) { + if (!super.matchLibrary(library, libraries)) { + return false; + } + for (Library l : libraries) { + if ("net.legacyfabric".equals(l.getGroupId())) { + return true; + } + } + return false; + } + }, + LEGACY_FABRIC_API(false, "legacyfabric-api", "net.legacyfabric", "legacyfabric-api", null), + FABRIC(true, "fabric", "net\\.fabricmc", "fabric-loader", ModLoaderType.FABRIC) { + @Override + protected boolean matchLibrary(Library library, List libraries) { + if (!super.matchLibrary(library, libraries)) { + return false; + } + for (Library l : libraries) { + if ("net.legacyfabric".equals(l.getGroupId())) { + return false; + } + } + return true; + } + }, FABRIC_API(true, "fabric-api", "net\\.fabricmc", "fabric-api", null), FORGE(true, "forge", "net\\.minecraftforge", "(forge|fmlloader)", ModLoaderType.FORGE) { private final Pattern FORGE_VERSION_MATCHER = Pattern.compile("^([0-9.]+)-(?[0-9.]+)(-([0-9.]+))?$"); @@ -278,6 +306,7 @@ private String scanVersion(Version version) { private final ModLoaderType modLoaderType; private static final Map PATCH_ID_MAP = new HashMap<>(); + static { for (LibraryType type : values()) { PATCH_ID_MAP.put(type.getPatchId(), type); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java index df8424c1ec..716acbcc39 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java @@ -22,6 +22,8 @@ import org.jackhuang.hmcl.download.fabric.FabricVersionList; import org.jackhuang.hmcl.download.forge.ForgeVersionList; import org.jackhuang.hmcl.download.game.GameVersionList; +import org.jackhuang.hmcl.download.legacyfabric.LegacyFabricAPIVersionList; +import org.jackhuang.hmcl.download.legacyfabric.LegacyFabricVersionList; import org.jackhuang.hmcl.download.liteloader.LiteLoaderVersionList; import org.jackhuang.hmcl.download.neoforge.NeoForgeOfficialVersionList; import org.jackhuang.hmcl.download.optifine.OptiFineBMCLVersionList; @@ -47,6 +49,8 @@ public class MojangDownloadProvider implements DownloadProvider { private final OptiFineBMCLVersionList optifine; private final QuiltVersionList quilt; private final QuiltAPIVersionList quiltApi; + private final LegacyFabricVersionList legacyFabric; + private final LegacyFabricAPIVersionList legacyFabricApi; public MojangDownloadProvider() { // If there is no official download channel available, fallback to BMCLAPI. @@ -62,6 +66,8 @@ public MojangDownloadProvider() { this.optifine = new OptiFineBMCLVersionList(apiRoot); this.quilt = new QuiltVersionList(this); this.quiltApi = new QuiltAPIVersionList(this); + this.legacyFabric = new LegacyFabricVersionList(this); + this.legacyFabricApi = new LegacyFabricAPIVersionList(this); } @Override @@ -76,30 +82,21 @@ public List getAssetObjectCandidates(String assetObjectLocation) { @Override public VersionList getVersionListById(String id) { - switch (id) { - case "game": - return game; - case "fabric": - return fabric; - case "fabric-api": - return fabricApi; - case "forge": - return forge; - case "cleanroom": - return cleanroom; - case "neoforge": - return neoforge; - case "liteloader": - return liteLoader; - case "optifine": - return optifine; - case "quilt": - return quilt; - case "quilt-api": - return quiltApi; - default: - throw new IllegalArgumentException("Unrecognized version list id: " + id); - } + return switch (id) { + case "game" -> game; + case "fabric" -> fabric; + case "fabric-api" -> fabricApi; + case "forge" -> forge; + case "cleanroom" -> cleanroom; + case "neoforge" -> neoforge; + case "liteloader" -> liteLoader; + case "optifine" -> optifine; + case "quilt" -> quilt; + case "quilt-api" -> quiltApi; + case "legacyfabric" -> legacyFabric; + case "legacyfabric-api" -> legacyFabricApi; + default -> throw new IllegalArgumentException("Unrecognized version list id: " + id); + }; } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIInstallTask.java index 90c5f388a3..e74c8bf621 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIInstallTask.java @@ -59,7 +59,7 @@ public boolean isRelyingOnDependencies() { public void execute() throws IOException { dependencies.add(new FileDownloadTask( remote.getVersion().getFile().getUrl(), - dependencyManager.getGameRepository().getRunDirectory(version.getId()).resolve("mods").resolve("fabric-api-" + remote.getVersion().getVersion() + ".jar"), + dependencyManager.getGameRepository().getModsDirectory(version.getId()).resolve("fabric-api-" + remote.getVersion().getVersion() + ".jar"), remote.getVersion().getFile().getIntegrityCheck()) ); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java index 458d8dd9b4..b21586201a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricInstallTask.java @@ -28,6 +28,7 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonSerializable; import org.jackhuang.hmcl.util.gson.JsonUtils; import java.io.IOException; @@ -127,6 +128,7 @@ private Version getPatch(FabricInfo fabricInfo, String gameVersion, String loade return new Version(LibraryAnalyzer.LibraryType.FABRIC.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries); } + @JsonSerializable public static class FabricInfo { private final LoaderInfo loader; private final IntermediaryInfo intermediary; @@ -151,6 +153,7 @@ public JsonObject getLauncherMeta() { } } + @JsonSerializable public static class LoaderInfo { private final String separator; private final int build; @@ -187,6 +190,7 @@ public boolean isStable() { } } + @JsonSerializable public static class IntermediaryInfo { private final String maven; private final String version; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIInstallTask.java new file mode 100644 index 0000000000..1a9c2de6a0 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIInstallTask.java @@ -0,0 +1,61 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 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 org.jackhuang.hmcl.download.legacyfabric; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.task.Task; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public final class LegacyFabricAPIInstallTask extends Task { + + private final DefaultDependencyManager dependencyManager; + private final Version version; + private final LegacyFabricAPIRemoteVersion remote; + private final List> dependencies = new ArrayList<>(1); + + public LegacyFabricAPIInstallTask(DefaultDependencyManager dependencyManager, Version version, LegacyFabricAPIRemoteVersion remoteVersion) { + this.dependencyManager = dependencyManager; + this.version = version; + this.remote = remoteVersion; + } + + @Override + public Collection> getDependencies() { + return dependencies; + } + + @Override + public boolean isRelyingOnDependencies() { + return false; + } + + @Override + public void execute() throws IOException { + dependencies.add(new FileDownloadTask( + remote.getVersion().getFile().getUrl(), + dependencyManager.getGameRepository().getModsDirectory(version.getId()).resolve("legacy-fabric-api-" + remote.getVersion().getVersion() + ".jar"), + remote.getVersion().getFile().getIntegrityCheck()) + ); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIRemoteVersion.java new file mode 100644 index 0000000000..eb21c07aab --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIRemoteVersion.java @@ -0,0 +1,67 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2022 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 org.jackhuang.hmcl.download.legacyfabric; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.mod.RemoteMod; +import org.jackhuang.hmcl.task.Task; + +import java.time.Instant; +import java.util.List; + +public class LegacyFabricAPIRemoteVersion extends RemoteVersion { + private final String fullVersion; + private final RemoteMod.Version version; + + /** + * Constructor. + * + * @param gameVersion the Minecraft version that this remote version suits. + * @param selfVersion the version string of the remote version. + * @param urls the installer or universal jar original URL. + */ + LegacyFabricAPIRemoteVersion(String gameVersion, String selfVersion, String fullVersion, Instant datePublished, RemoteMod.Version version, List urls) { + super(LibraryAnalyzer.LibraryType.LEGACY_FABRIC_API.getPatchId(), gameVersion, selfVersion, datePublished, urls); + + this.fullVersion = fullVersion; + this.version = version; + } + + @Override + public String getFullVersion() { + return fullVersion; + } + + public RemoteMod.Version getVersion() { + return version; + } + + @Override + public Task getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) { + return new LegacyFabricAPIInstallTask(dependencyManager, baseVersion, this); + } + + @Override + public int compareTo(RemoteVersion o) { + if (!(o instanceof LegacyFabricAPIRemoteVersion)) return 0; + return -this.getReleaseDate().compareTo(o.getReleaseDate()); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIVersionList.java new file mode 100644 index 0000000000..da21df24a5 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricAPIVersionList.java @@ -0,0 +1,53 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2022 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 org.jackhuang.hmcl.download.legacyfabric; + +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.mod.RemoteMod; +import org.jackhuang.hmcl.mod.modrinth.ModrinthRemoteModRepository; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Lang; + +import java.util.Collections; + +public class LegacyFabricAPIVersionList extends VersionList { + + private final DownloadProvider downloadProvider; + + public LegacyFabricAPIVersionList(DownloadProvider downloadProvider) { + this.downloadProvider = downloadProvider; + } + + @Override + public boolean hasType() { + return false; + } + + @Override + public Task refreshAsync() { + return Task.runAsync(() -> { + for (RemoteMod.Version modVersion : Lang.toIterable(ModrinthRemoteModRepository.MODS.getRemoteVersionsById("legacy-fabric-api"))) { + for (String gameVersion : modVersion.getGameVersions()) { + versions.put(gameVersion, new LegacyFabricAPIRemoteVersion(gameVersion, modVersion.getVersion(), modVersion.getName(), modVersion.getDatePublished(), modVersion, + Collections.singletonList(modVersion.getFile().getUrl()))); + } + } + }); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricInstallTask.java new file mode 100644 index 0000000000..7ef8cd1227 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricInstallTask.java @@ -0,0 +1,130 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2022 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 org.jackhuang.hmcl.download.legacyfabric; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.download.UnsupportedInstallationException; +import org.jackhuang.hmcl.download.fabric.FabricInstallTask; +import org.jackhuang.hmcl.game.Arguments; +import org.jackhuang.hmcl.game.Artifact; +import org.jackhuang.hmcl.game.Library; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonUtils; + +import java.util.*; + +import static org.jackhuang.hmcl.download.UnsupportedInstallationException.FABRIC_NOT_COMPATIBLE_WITH_FORGE; + +public final class LegacyFabricInstallTask extends Task { + + private final DefaultDependencyManager dependencyManager; + private final Version version; + private final LegacyFabricRemoteVersion remote; + private final GetTask launchMetaTask; + private final List> dependencies = new ArrayList<>(1); + + public LegacyFabricInstallTask(DefaultDependencyManager dependencyManager, Version version, LegacyFabricRemoteVersion remoteVersion) { + this.dependencyManager = dependencyManager; + this.version = version; + this.remote = remoteVersion; + + launchMetaTask = new GetTask(dependencyManager.getDownloadProvider().injectURLsWithCandidates(remoteVersion.getUrls())); + launchMetaTask.setCacheRepository(dependencyManager.getCacheRepository()); + } + + @Override + public boolean doPreExecute() { + return true; + } + + @Override + public void preExecute() throws Exception { + if (!Objects.equals("net.minecraft.client.main.Main", version.resolve(dependencyManager.getGameRepository()).getMainClass())) + throw new UnsupportedInstallationException(FABRIC_NOT_COMPATIBLE_WITH_FORGE); + } + + @Override + public Collection> getDependents() { + return Collections.singleton(launchMetaTask); + } + + @Override + public Collection> getDependencies() { + return dependencies; + } + + @Override + public boolean isRelyingOnDependencies() { + return false; + } + + @Override + public void execute() { + setResult(getPatch(JsonUtils.GSON.fromJson(launchMetaTask.getResult(), FabricInstallTask.FabricInfo.class), remote.getGameVersion(), remote.getSelfVersion())); + + dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult(), true)); + } + + private Version getPatch(FabricInstallTask.FabricInfo legacyFabricInfo, String gameVersion, String loaderVersion) { + JsonObject launcherMeta = legacyFabricInfo.getLauncherMeta(); + Arguments arguments = new Arguments(); + + String mainClass; + if (!launcherMeta.get("mainClass").isJsonObject()) { + mainClass = launcherMeta.get("mainClass").getAsString(); + } else { + mainClass = launcherMeta.get("mainClass").getAsJsonObject().get("client").getAsString(); + } + + if (launcherMeta.has("launchwrapper")) { + String clientTweaker = launcherMeta.get("launchwrapper").getAsJsonObject().get("tweakers").getAsJsonObject().get("client").getAsJsonArray().get(0).getAsString(); + arguments = arguments.addGameArguments("--tweakClass", clientTweaker); + } + + JsonObject librariesObject = launcherMeta.getAsJsonObject("libraries"); + List libraries = new ArrayList<>(); + + // "common, server" is hard coded in fabric installer. + // Don't know the purpose of ignoring client libraries. + for (String side : new String[]{"common", "server"}) { + for (JsonElement element : librariesObject.getAsJsonArray(side)) { + libraries.add(JsonUtils.GSON.fromJson(element, Library.class)); + } + } + + // libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.hashed.maven), getMavenRepositoryByGroup(legacyFabricInfo.hashed.maven), null)); + libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.getIntermediary().getMaven()), getMavenRepositoryByGroup(legacyFabricInfo.getIntermediary().getMaven()), null)); + libraries.add(new Library(Artifact.fromDescriptor(legacyFabricInfo.getLoader().getMaven()), getMavenRepositoryByGroup(legacyFabricInfo.getLoader().getMaven()), null)); + + return new Version(LibraryAnalyzer.LibraryType.LEGACY_FABRIC.getPatchId(), loaderVersion, Version.PRIORITY_LOADER, arguments, mainClass, libraries); + } + + private static String getMavenRepositoryByGroup(String maven) { + Artifact artifact = Artifact.fromDescriptor(maven); + return switch (artifact.getGroup()) { + case "net.fabricmc" -> "https://maven.fabricmc.net/"; + case "net.legacyfabric" -> "https://maven.legacyfabric.net/"; + default -> "https://maven.fabricmc.net/"; + }; + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricRemoteVersion.java new file mode 100644 index 0000000000..cd29f0fddd --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricRemoteVersion.java @@ -0,0 +1,44 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2022 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 org.jackhuang.hmcl.download.legacyfabric; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.Task; + +import java.util.List; + +public class LegacyFabricRemoteVersion extends RemoteVersion { + /** + * Constructor. + * + * @param gameVersion the Minecraft version that this remote version suits. + * @param selfVersion the version string of the remote version. + * @param urls the installer or universal jar original URL. + */ + LegacyFabricRemoteVersion(String gameVersion, String selfVersion, List urls) { + super(LibraryAnalyzer.LibraryType.LEGACY_FABRIC.getPatchId(), gameVersion, selfVersion, null, urls); + } + + @Override + public Task getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) { + return new LegacyFabricInstallTask(dependencyManager, baseVersion, this); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricVersionList.java new file mode 100644 index 0000000000..5533e9e5ff --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/legacyfabric/LegacyFabricVersionList.java @@ -0,0 +1,106 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2022 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 org.jackhuang.hmcl.download.legacyfabric; + +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.io.NetworkUtils; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; + +public final class LegacyFabricVersionList extends VersionList { + private final DownloadProvider downloadProvider; + + public LegacyFabricVersionList(DownloadProvider downloadProvider) { + this.downloadProvider = downloadProvider; + } + + @Override + public boolean hasType() { + return false; + } + + @Override + public Task refreshAsync() { + return Task.runAsync(() -> { + List gameVersions = getGameVersions(GAME_META_URL); + List loaderVersions = getGameVersions(LOADER_META_URL); + + lock.writeLock().lock(); + + try { + for (String gameVersion : gameVersions) + for (String loaderVersion : loaderVersions) + versions.put(gameVersion, new LegacyFabricRemoteVersion(gameVersion, loaderVersion, + Collections.singletonList(getLaunchMetaUrl(gameVersion, loaderVersion)))); + } finally { + lock.writeLock().unlock(); + } + }); + } + + private static final String LOADER_META_URL = "https://meta.legacyfabric.net/v2/versions/loader"; + private static final String GAME_META_URL = "https://meta.legacyfabric.net/v2/versions/game"; + + private List getGameVersions(String metaUrl) throws IOException { + String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl)); + return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class)) + .stream().map(GameVersion::getVersion).collect(Collectors.toList()); + } + + private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) { + return String.format("https://meta.legacyfabric.net/v2/versions/loader/%s/%s", gameVersion, loaderVersion); + } + + private static class GameVersion { + private final String version; + private final String maven; + private final boolean stable; + + public GameVersion() { + this("", null, false); + } + + public GameVersion(String version, String maven, boolean stable) { + this.version = version; + this.maven = maven; + this.stable = stable; + } + + public String getVersion() { + return version; + } + + @Nullable + public String getMaven() { + return maven; + } + + public boolean isStable() { + return stable; + } + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIInstallTask.java index b0d9eb2bf9..5f06cccba5 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIInstallTask.java @@ -59,7 +59,7 @@ public boolean isRelyingOnDependencies() { public void execute() throws IOException { dependencies.add(new FileDownloadTask( remote.getVersion().getFile().getUrl(), - dependencyManager.getGameRepository().getRunDirectory(version.getId()).resolve("mods").resolve("quilt-api-" + remote.getVersion().getVersion() + ".jar"), + dependencyManager.getGameRepository().getModsDirectory(version.getId()).resolve("quilt-api-" + remote.getVersion().getVersion() + ".jar"), remote.getVersion().getFile().getIntegrityCheck()) ); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltInstallTask.java index c0bd512907..01642cecf0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltInstallTask.java @@ -28,6 +28,7 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonSerializable; import org.jackhuang.hmcl.util.gson.JsonUtils; import java.util.*; @@ -135,6 +136,7 @@ private static String getMavenRepositoryByGroup(String maven) { } } + @JsonSerializable public static class QuiltInfo { private final LoaderInfo loader; private final IntermediaryInfo hashed; @@ -165,6 +167,7 @@ public JsonObject getLauncherMeta() { } } + @JsonSerializable public static class LoaderInfo { private final String separator; private final int build; @@ -201,6 +204,7 @@ public boolean isStable() { } } + @JsonSerializable public static class IntermediaryInfo { private final String maven; private final String version; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index 3f4ba0098c..67244ff99a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -597,6 +597,9 @@ private Map getEnvVars() { if (analyzer.has(LibraryAnalyzer.LibraryType.QUILT)) { env.put("INST_QUILT", "1"); } + if (analyzer.has(LibraryAnalyzer.LibraryType.LEGACY_FABRIC)) { + env.put("INST_LEGACYFABRIC", "1"); + } env.putAll(options.getEnvironmentVariables()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java index f4b8feacd8..c1205803a6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModLoaderType.java @@ -25,5 +25,6 @@ public enum ModLoaderType { FABRIC, QUILT, LITE_LOADER, - PACK; + LEGACY_FABRIC, + PACK } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java index 2429b10737..3386951788 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/mcbbs/McbbsModpackExportTask.java @@ -109,6 +109,8 @@ public void execute() throws Exception { addons.add(new McbbsModpackManifest.Addon(FABRIC.getPatchId(), fabricVersion))); analyzer.getVersion(QUILT).ifPresent(quiltVersion -> addons.add(new McbbsModpackManifest.Addon(QUILT.getPatchId(), quiltVersion))); + analyzer.getVersion(LEGACY_FABRIC).ifPresent(legacyfabricVersion -> + addons.add(new McbbsModpackManifest.Addon(LEGACY_FABRIC.getPatchId(), legacyfabricVersion))); List libraries = new ArrayList<>(); // TODO libraries