Fix: NeoForge Support (#2632)

* Fix

* Fix: NeoForge may successfully made HMCL think it's Forge.

* Fix #2649

* Fix #2654 partly because MultiMC hasn't support NeoForge yet.

* Get ready for HMCL to support export and read MultiMC Modpacks with NeoForge.
This commit is contained in:
Burning_TNT 2024-01-24 00:19:49 +08:00 committed by GitHub
parent 5db3c123a0
commit f53aed9a08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 47 additions and 9 deletions

View File

@ -87,6 +87,7 @@ class AdditionalInstallersPage extends InstallersPage {
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(repository)); LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(repository));
String game = analyzer.getVersion(MINECRAFT).orElse(null); String game = analyzer.getVersion(MINECRAFT).orElse(null);
String forge = analyzer.getVersion(FORGE).orElse(null); String forge = analyzer.getVersion(FORGE).orElse(null);
String neoForge = analyzer.getVersion(NEO_FORGE).orElse(null);
String liteLoader = analyzer.getVersion(LITELOADER).orElse(null); String liteLoader = analyzer.getVersion(LITELOADER).orElse(null);
String optiFine = analyzer.getVersion(OPTIFINE).orElse(null); String optiFine = analyzer.getVersion(OPTIFINE).orElse(null);
String fabric = analyzer.getVersion(FABRIC).orElse(null); String fabric = analyzer.getVersion(FABRIC).orElse(null);
@ -95,7 +96,7 @@ class AdditionalInstallersPage extends InstallersPage {
String quiltApi = analyzer.getVersion(QUILT_API).orElse(null); String quiltApi = analyzer.getVersion(QUILT_API).orElse(null);
InstallerItem[] libraries = group.getLibraries(); InstallerItem[] libraries = group.getLibraries();
String[] versions = new String[]{game, forge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi}; String[] versions = new String[]{game, forge, neoForge, liteLoader, optiFine, fabric, fabricApi, quilt, quiltApi};
String currentGameVersion = Lang.nonNull(getVersion("game"), game); String currentGameVersion = Lang.nonNull(getVersion("game"), game);

View File

@ -99,8 +99,9 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
if (type == null) return version; if (type == null) return version;
List<Library> libraries = new ArrayList<>(); List<Library> libraries = new ArrayList<>();
for (Library library : version.getLibraries()) { List<Library> rawLibraries = version.getLibraries();
if (type.matchLibrary(library)) { for (Library library : rawLibraries) {
if (type.matchLibrary(library, rawLibraries)) {
// skip // skip
} else { } else {
libraries.add(library); libraries.add(library);
@ -135,9 +136,10 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
Map<String, Pair<Library, String>> libraries = new HashMap<>(); Map<String, Pair<Library, String>> libraries = new HashMap<>();
for (Library library : version.resolve(null).getLibraries()) { List<Library> rawLibraries = version.resolve(null).getLibraries();
for (Library library : rawLibraries) {
for (LibraryType type : LibraryType.values()) { for (LibraryType type : LibraryType.values()) {
if (type.matchLibrary(library)) { if (type.matchLibrary(library, rawLibraries)) {
libraries.put(type.getPatchId(), pair(library, type.patchVersion(version, library.getVersion()))); libraries.put(type.getPatchId(), pair(library, type.patchVersion(version, library.getVersion())));
break; break;
} }
@ -185,10 +187,27 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
} }
return super.patchVersion(gameVersion, libraryVersion); return super.patchVersion(gameVersion, libraryVersion);
} }
@Override
public boolean matchLibrary(Library library, List<Library> libraries) {
for (Library l : libraries) {
if (NEO_FORGE.matchLibrary(l, libraries)) {
return false;
}
}
return super.matchLibrary(library, libraries);
}
}, },
NEO_FORGE(true, "neoforge", Pattern.compile("net\\.neoforged\\.fancymodloader"), Pattern.compile("(core|loader)"), ModLoaderType.NEO_FORGED) { NEO_FORGE(true, "neoforge", Pattern.compile("net\\.neoforged\\.fancymodloader"), Pattern.compile("(core|loader)"), ModLoaderType.NEO_FORGED) {
private final Pattern NEO_FORGE_VERSION_MATCHER = Pattern.compile("^([0-9.]+)-(?<forge>[0-9.]+)(-([0-9.]+))?$");
@Override @Override
public String patchVersion(Version gameVersion, String libraryVersion) { public String patchVersion(Version gameVersion, String libraryVersion) {
Matcher matcher = NEO_FORGE_VERSION_MATCHER.matcher(libraryVersion);
if (matcher.find()) {
return matcher.group("forge");
}
String res = scanVersion(gameVersion); String res = scanVersion(gameVersion);
if (res != null) { if (res != null) {
return res; return res;
@ -266,7 +285,7 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
return null; return null;
} }
public boolean matchLibrary(Library library) { public boolean matchLibrary(Library library, List<Library> libraries) {
return group.matcher(library.getGroupId()).matches() && artifact.matcher(library.getArtifactId()).matches(); return group.matcher(library.getGroupId()).matches() && artifact.matcher(library.getArtifactId()).matches();
} }

View File

@ -89,7 +89,7 @@ public final class NeoForgeInstallTask extends Task<Version> {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
String installProfileText = FileUtils.readText(fs.getPath("install_profile.json")); String installProfileText = FileUtils.readText(fs.getPath("install_profile.json"));
Map<?, ?> installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class); Map<?, ?> installProfile = JsonUtils.fromNonNullJson(installProfileText, Map.class);
if (LibraryAnalyzer.LibraryType.FORGE.getPatchId().equals(installProfile.get("profile")) && Files.exists(fs.getPath("META-INF/NEOFORGE.RSA"))) { if (LibraryAnalyzer.LibraryType.FORGE.getPatchId().equals(installProfile.get("profile")) && (Files.exists(fs.getPath("META-INF/NEOFORGE.RSA")) || installProfileText.contains("neoforge"))) {
ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class); ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class);
if (!gameVersion.get().equals(profile.getMinecraft())) if (!gameVersion.get().equals(profile.getMinecraft()))
throw new VersionMismatchException(profile.getMinecraft(), gameVersion.get()); throw new VersionMismatchException(profile.getMinecraft(), gameVersion.get());
@ -97,9 +97,12 @@ public final class NeoForgeInstallTask extends Task<Version> {
if (!neoForgeVersion.getId().equals(LibraryAnalyzer.LibraryType.FORGE.getPatchId()) || neoForgeVersion.getVersion() == null) { if (!neoForgeVersion.getId().equals(LibraryAnalyzer.LibraryType.FORGE.getPatchId()) || neoForgeVersion.getVersion() == null) {
throw new IOException("Invalid neoforge version."); throw new IOException("Invalid neoforge version.");
} }
return neoForgeVersion.setId(LibraryAnalyzer.LibraryType.NEO_FORGE.getPatchId()).setVersion(neoForgeVersion.getVersion().replace(LibraryAnalyzer.LibraryType.FORGE.getPatchId(), LibraryAnalyzer.LibraryType.NEO_FORGE.getPatchId())); return neoForgeVersion.setId(LibraryAnalyzer.LibraryType.NEO_FORGE.getPatchId())
.setVersion(
removePrefix(neoForgeVersion.getVersion().replace(LibraryAnalyzer.LibraryType.FORGE.getPatchId(), ""), "-")
);
}); });
} else if (LibraryAnalyzer.LibraryType.NEO_FORGE.getPatchId().equals(installProfile.get("profile"))) { } else if (LibraryAnalyzer.LibraryType.NEO_FORGE.getPatchId().equals(installProfile.get("profile")) || "NeoForge".equals(installProfile.get("profile"))) {
ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class); ForgeNewInstallProfile profile = JsonUtils.fromNonNullJson(installProfileText, ForgeNewInstallProfile.class);
if (!gameVersion.get().equals(profile.getMinecraft())) if (!gameVersion.get().equals(profile.getMinecraft()))
throw new VersionMismatchException(profile.getMinecraft(), gameVersion.get()); throw new VersionMismatchException(profile.getMinecraft(), gameVersion.get());

View File

@ -91,6 +91,8 @@ public class McbbsModpackExportTask extends Task<Void> {
addons.add(new McbbsModpackManifest.Addon(MINECRAFT.getPatchId(), gameVersion)); addons.add(new McbbsModpackManifest.Addon(MINECRAFT.getPatchId(), gameVersion));
analyzer.getVersion(FORGE).ifPresent(forgeVersion -> analyzer.getVersion(FORGE).ifPresent(forgeVersion ->
addons.add(new McbbsModpackManifest.Addon(FORGE.getPatchId(), forgeVersion))); addons.add(new McbbsModpackManifest.Addon(FORGE.getPatchId(), forgeVersion)));
analyzer.getVersion(NEO_FORGE).ifPresent(neoForgeVersion ->
addons.add(new McbbsModpackManifest.Addon(NEO_FORGE.getPatchId(), neoForgeVersion)));
analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion -> analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion ->
addons.add(new McbbsModpackManifest.Addon(LITELOADER.getPatchId(), liteLoaderVersion))); addons.add(new McbbsModpackManifest.Addon(LITELOADER.getPatchId(), liteLoaderVersion)));
analyzer.getVersion(OPTIFINE).ifPresent(optifineVersion -> analyzer.getVersion(OPTIFINE).ifPresent(optifineVersion ->
@ -115,6 +117,7 @@ public class McbbsModpackExportTask extends Task<Void> {
// CurseForge manifest // CurseForge manifest
List<CurseManifestModLoader> modLoaders = new ArrayList<>(); List<CurseManifestModLoader> modLoaders = new ArrayList<>();
analyzer.getVersion(FORGE).ifPresent(forgeVersion -> modLoaders.add(new CurseManifestModLoader("forge-" + forgeVersion, true))); analyzer.getVersion(FORGE).ifPresent(forgeVersion -> modLoaders.add(new CurseManifestModLoader("forge-" + forgeVersion, true)));
analyzer.getVersion(NEO_FORGE).ifPresent(forgeVersion -> modLoaders.add(new CurseManifestModLoader("neoforge-" + forgeVersion, true)));
analyzer.getVersion(FABRIC).ifPresent(fabricVersion -> modLoaders.add(new CurseManifestModLoader("fabric-" + fabricVersion, true))); analyzer.getVersion(FABRIC).ifPresent(fabricVersion -> modLoaders.add(new CurseManifestModLoader("fabric-" + fabricVersion, true)));
// OptiFine and LiteLoader are not supported by CurseForge modpack. // OptiFine and LiteLoader are not supported by CurseForge modpack.
CurseManifest curseManifest = new CurseManifest(CurseManifest.MINECRAFT_MODPACK, 1, info.getName(), info.getVersion(), info.getAuthor(), "overrides", new CurseManifestMinecraft(gameVersion, modLoaders), Collections.emptyList()); CurseManifest curseManifest = new CurseManifest(CurseManifest.MINECRAFT_MODPACK, 1, info.getName(), info.getVersion(), info.getAuthor(), "overrides", new CurseManifestMinecraft(gameVersion, modLoaders), Collections.emptyList());

View File

@ -77,6 +77,9 @@ public class MultiMCModpackExportTask extends Task<Void> {
components.add(new MultiMCManifest.MultiMCManifestComponent(true, false, "net.minecraft", gameVersion)); components.add(new MultiMCManifest.MultiMCManifestComponent(true, false, "net.minecraft", gameVersion));
analyzer.getVersion(FORGE).ifPresent(forgeVersion -> analyzer.getVersion(FORGE).ifPresent(forgeVersion ->
components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "net.minecraftforge", forgeVersion))); components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "net.minecraftforge", forgeVersion)));
// MultiMC hasn't supported NeoForge yet.
// analyzer.getVersion(NEO_FORGE).ifPresent(neoForgeVersion ->
// components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "net.neoforged", neoForgeVersion)));
analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion -> analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion ->
components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "com.mumfrey.liteloader", liteLoaderVersion))); components.add(new MultiMCManifest.MultiMCManifestComponent(false, false, "com.mumfrey.liteloader", liteLoaderVersion)));
analyzer.getVersion(FABRIC).ifPresent(fabricVersion -> analyzer.getVersion(FABRIC).ifPresent(fabricVersion ->

View File

@ -78,6 +78,13 @@ public final class MultiMCModpackInstallTask extends Task<Void> {
builder.version("forge", c.getVersion()); builder.version("forge", c.getVersion());
}); });
// MultiMC hasn't supported NeoForge yet.
// Optional<MultiMCManifest.MultiMCManifestComponent> neoForge = manifest.getMmcPack().getComponents().stream().filter(e -> e.getUid().equals("net.neoforged")).findAny();
// neoForge.ifPresent(c -> {
// if (c.getVersion() != null)
// builder.version("neoforge", c.getVersion());
// });
Optional<MultiMCManifest.MultiMCManifestComponent> liteLoader = manifest.getMmcPack().getComponents().stream().filter(e -> e.getUid().equals("com.mumfrey.liteloader")).findAny(); Optional<MultiMCManifest.MultiMCManifestComponent> liteLoader = manifest.getMmcPack().getComponents().stream().filter(e -> e.getUid().equals("com.mumfrey.liteloader")).findAny();
liteLoader.ifPresent(c -> { liteLoader.ifPresent(c -> {
if (c.getVersion() != null) if (c.getVersion() != null)

View File

@ -85,6 +85,8 @@ public class ServerModpackExportTask extends Task<Void> {
addons.add(new ServerModpackManifest.Addon(MINECRAFT.getPatchId(), gameVersion)); addons.add(new ServerModpackManifest.Addon(MINECRAFT.getPatchId(), gameVersion));
analyzer.getVersion(FORGE).ifPresent(forgeVersion -> analyzer.getVersion(FORGE).ifPresent(forgeVersion ->
addons.add(new ServerModpackManifest.Addon(FORGE.getPatchId(), forgeVersion))); addons.add(new ServerModpackManifest.Addon(FORGE.getPatchId(), forgeVersion)));
analyzer.getVersion(NEO_FORGE).ifPresent(neoForgeVersion ->
addons.add(new ServerModpackManifest.Addon(NEO_FORGE.getPatchId(), neoForgeVersion)));
analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion -> analyzer.getVersion(LITELOADER).ifPresent(liteLoaderVersion ->
addons.add(new ServerModpackManifest.Addon(LITELOADER.getPatchId(), liteLoaderVersion))); addons.add(new ServerModpackManifest.Addon(LITELOADER.getPatchId(), liteLoaderVersion)));
analyzer.getVersion(OPTIFINE).ifPresent(optifineVersion -> analyzer.getVersion(OPTIFINE).ifPresent(optifineVersion ->