Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,9 @@ public Image getVersionIconImage(String id) {

if (LibraryAnalyzer.isModded(this, version)) {
LibraryAnalyzer libraryAnalyzer = LibraryAnalyzer.analyze(version, null);
if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.FABRIC))
if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.LEGACY_FABRIC))
return VersionIconType.LEGACY_FABRIC.getIcon();
else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.FABRIC))
return VersionIconType.FABRIC.getIcon();
else if (libraryAnalyzer.has(LibraryAnalyzer.LibraryType.QUILT))
return VersionIconType.QUILT.getIcon();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
59 changes: 21 additions & 38 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,35 +128,16 @@ public InstallerItem(String id, Style style) {
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;
case "game" -> iconType = VersionIconType.GRASS;
case "fabric", "fabric-api" -> iconType = VersionIconType.FABRIC;
case "legacyfabric", "legacyfabric-api" -> iconType = VersionIconType.LEGACY_FABRIC;
case "forge" -> iconType = VersionIconType.FORGE;
case "cleanroom" -> iconType = VersionIconType.CLEANROOM;
case "liteloader" -> iconType = VersionIconType.CHICKEN;
case "optifine" -> iconType = VersionIconType.OPTIFINE;
case "quilt", "quilt-api" -> iconType = VersionIconType.QUILT;
case "neoforge" -> iconType = VersionIconType.NEO_FORGE;
default -> iconType = null;
}
}

Expand Down Expand Up @@ -236,18 +217,20 @@ 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);
InstallerItem quilt = new InstallerItem(QUILT, style);
InstallerItem quiltApi = new InstallerItem(QUILT_API, style);

Map<InstallerItem, Set<InstallerItem>> 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);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fabricApi incompatibility list has 'legacyfabricApi' duplicated. The second occurrence should be 'legacyfabric' instead, so that fabricApi is marked as incompatible with both the Legacy Fabric loader and Legacy Fabric API.

Suggested change
addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabricApi, legacyfabricApi);
addIncompatibles(incompatibleMap, fabricApi, forge, quiltApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabricApi, legacyfabric);

Copilot uses AI. Check for mistakes.
addIncompatibles(incompatibleMap, quiltApi, forge, fabric, fabricApi, neoForge, liteLoader, optiFine, cleanroom, legacyfabric, legacyfabricApi);

for (Map.Entry<InstallerItem, Set<InstallerItem>> entry : incompatibleMap.entrySet()) {
InstallerItem item = entry.getKey();
Expand Down Expand Up @@ -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()) {
Expand All @@ -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};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -428,21 +431,23 @@ 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;
case "hmcl.modpack" -> message = i18n("install.modpack");
case "hmcl.modpack.download" -> message = i18n("launch.state.modpack");
case "hmcl.install.assets" -> message = i18n("assets.download");
case "hmcl.install.libraries" -> message = i18n("libraries.download");
case "hmcl.install.game" -> message = i18n("install.installer.install", i18n("install.installer.game") + " " + stageValue);
case "hmcl.install.forge" -> message = i18n("install.installer.install", i18n("install.installer.forge") + " " + stageValue);
case "hmcl.install.cleanroom" -> message = i18n("install.installer.install", i18n("install.installer.cleanroom") + " " + stageValue);
case "hmcl.install.neoforge" -> message = i18n("install.installer.install", i18n("install.installer.neoforge") + " " + stageValue);
case "hmcl.install.liteloader" -> message = i18n("install.installer.install", i18n("install.installer.liteloader") + " " + stageValue);
case "hmcl.install.optifine" -> message = i18n("install.installer.install", i18n("install.installer.optifine") + " " + stageValue);
case "hmcl.install.fabric" -> message = i18n("install.installer.install", i18n("install.installer.fabric") + " " + stageValue);
case "hmcl.install.fabric-api" -> message = i18n("install.installer.install", i18n("install.installer.fabric-api") + " " + stageValue);
case "hmcl.install.legacyfabric" -> message = i18n("install.installer.install", i18n("install.installer.legacyfabric") + " " + stageValue);
case "hmcl.install.legacyfabric-api" -> message = i18n("install.installer.install", i18n("install.installer.legacyfabric-api") + " " + stageValue);
case "hmcl.install.quilt" -> message = i18n("install.installer.install", i18n("install.installer.quilt") + " " + stageValue);
case "hmcl.install.quilt-api" -> message = i18n("install.installer.install", i18n("install.installer.quilt-api") + " " + stageValue);
default -> message = i18n(stageKey);
}
// @formatter:on
// CHECKSTYLE:ON
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,29 +123,17 @@ private void setTxtNameWithLoaders() {
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:
case FORGE -> loaderName = i18n("install.installer.forge");
case NEO_FORGE -> loaderName = i18n("install.installer.neoforge");
case CLEANROOM -> loaderName = i18n("install.installer.cleanroom");
case LEGACY_FABRIC -> loaderName = i18n("install.installer.legacyfabric").replace(" ", "_");
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The replacement of spaces with underscores only for Legacy Fabric seems inconsistent with how other loaders are named. This special handling should be documented or the naming convention should be consistent across all loaders.

Copilot uses AI. Check for mistakes.
case FABRIC -> loaderName = i18n("install.installer.fabric");
case LITELOADER -> loaderName = i18n("install.installer.liteloader");
case QUILT -> loaderName = i18n("install.installer.quilt");
case OPTIFINE -> loaderName = i18n("install.installer.optifine");
default -> {
continue;
}
}

nameBuilder.append("-").append(loaderName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading