From 7dad43570eb4413e8f3a7a723a0a250f908e7456 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 10 Oct 2025 21:35:11 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20#4647:=20=E4=BF=AE=E5=A4=8D=E6=80=BB?= =?UTF-8?q?=E6=98=AF=E5=B0=86=E5=90=8C=E6=97=B6=E5=85=BC=E5=AE=B9=20Forge?= =?UTF-8?q?=20=E5=92=8C=20NeoForge=20=E7=9A=84=E6=A8=A1=E7=BB=84=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E4=B8=BA=20Forge=20=E6=A8=A1=E7=BB=84=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20(#4648)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/mod/ModManager.java | 33 ++++----- .../hmcl/mod/modinfo/ForgeNewModMetadata.java | 69 +++++++++++-------- 2 files changed, 54 insertions(+), 48 deletions(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java index 21a8b5e95..d1a580f72 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/ModManager.java @@ -41,21 +41,22 @@ public final class ModManager { LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException; } - private static final Map>>> READERS; + private static final Map>> READERS; static { - var map = new HashMap>>>(); - var zipReaders = List.>>of( - pair(ForgeNewModMetadata::fromFile, EnumSet.of(ModLoaderType.FORGE, ModLoaderType.NEO_FORGED)), - pair(ForgeOldModMetadata::fromFile, EnumSet.of(ModLoaderType.FORGE)), - pair(FabricModMetadata::fromFile, EnumSet.of(ModLoaderType.FABRIC)), - pair(QuiltModMetadata::fromFile, EnumSet.of(ModLoaderType.QUILT)), - pair(PackMcMeta::fromFile, EnumSet.of(ModLoaderType.PACK)) + var map = new HashMap>>(); + var zipReaders = List.>of( + pair(ForgeNewModMetadata::fromForgeFile, ModLoaderType.FORGE), + pair(ForgeNewModMetadata::fromNeoForgeFile, ModLoaderType.NEO_FORGED), + pair(ForgeOldModMetadata::fromFile, ModLoaderType.FORGE), + pair(FabricModMetadata::fromFile, ModLoaderType.FABRIC), + pair(QuiltModMetadata::fromFile, ModLoaderType.QUILT), + pair(PackMcMeta::fromFile, ModLoaderType.PACK) ); map.put("zip", zipReaders); map.put("jar", zipReaders); - map.put("litemod", List.of(pair(LiteModMetadata::fromFile, EnumSet.of(ModLoaderType.LITE_LOADER)))); + map.put("litemod", List.of(pair(LiteModMetadata::fromFile, ModLoaderType.LITE_LOADER))); READERS = map; } @@ -102,7 +103,7 @@ public final class ModManager { String fileName = StringUtils.removeSuffix(FileUtils.getName(file), DISABLED_EXTENSION, OLD_EXTENSION); String extension = fileName.substring(fileName.lastIndexOf(".") + 1); - List>> readersMap = READERS.get(extension); + List> readersMap = READERS.get(extension); if (readersMap == null) { // Is not a mod file. return; @@ -113,16 +114,8 @@ public final class ModManager { var supportedReaders = new ArrayList(); var unsupportedReaders = new ArrayList(); - for (Pair> reader : readersMap) { - boolean supported = false; - for (ModLoaderType type : reader.getValue()) { - if (modLoaderTypes.contains(type)) { - supported = true; - break; - } - } - - if (supported) { + for (Pair reader : readersMap) { + if (modLoaderTypes.contains(reader.getValue())) { supportedReaders.add(reader.getKey()); } else { unsupportedReaders.add(reader.getKey()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java index ec7c811f8..6da608558 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modinfo/ForgeNewModMetadata.java @@ -110,23 +110,33 @@ public final class ForgeNewModMetadata { } } - private static final int ACC_FORGE = 0x01; + public static LocalModFile fromForgeFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException { + return fromFile(modManager, modFile, fs, ModLoaderType.FORGE); + } - private static final int ACC_NEO_FORGED = 0x02; + public static LocalModFile fromNeoForgeFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException { + return fromFile(modManager, modFile, fs, ModLoaderType.NEO_FORGED); + } + + private static LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs, ModLoaderType modLoaderType) throws IOException { + if (modLoaderType != ModLoaderType.FORGE && modLoaderType != ModLoaderType.NEO_FORGED) { + throw new IOException("Invalid mod loader: " + modLoaderType); + } + + if (modLoaderType == ModLoaderType.NEO_FORGED) { + try { + return fromFile0("META-INF/neoforge.mods.toml", modLoaderType, modManager, modFile, fs); + } catch (Exception ignored) { + } + } - public static LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException { try { - return fromFile0("META-INF/mods.toml", ACC_FORGE | ACC_NEO_FORGED, ModLoaderType.FORGE, modManager, modFile, fs); + return fromFile0("META-INF/mods.toml", modLoaderType, modManager, modFile, fs); } catch (Exception ignored) { } try { - return fromFile0("META-INF/neoforge.mods.toml", ACC_NEO_FORGED, ModLoaderType.NEO_FORGED, modManager, modFile, fs); - } catch (Exception ignored) { - } - - try { - return fromEmbeddedMod(modManager, modFile, fs); + return fromEmbeddedMod(modManager, modFile, fs, modLoaderType); } catch (Exception ignored) { } @@ -134,8 +144,8 @@ public final class ForgeNewModMetadata { } private static LocalModFile fromFile0( - String tomlPath, int loaderACC, - ModLoaderType defaultLoader, + String tomlPath, + ModLoaderType modLoaderType, ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException { @@ -158,7 +168,7 @@ public final class ForgeNewModMetadata { } } - ModLoaderType type = analyzeLoader(toml, mod.getModId(), loaderACC, defaultLoader); + ModLoaderType type = analyzeLoader(toml, mod.getModId(), modLoaderType); return new LocalModFile(modManager, modManager.getLocalMod(mod.getModId(), type), modFile, mod.getDisplayName(), new LocalModFile.Description(mod.getDescription()), mod.getAuthors(), jarVersion == null ? mod.getVersion() : mod.getVersion().replace("${file.jarVersion}", jarVersion), "", @@ -166,7 +176,7 @@ public final class ForgeNewModMetadata { metadata.getLogoFile()); } - private static LocalModFile fromEmbeddedMod(ModManager modManager, Path modFile, FileSystem fs) throws IOException { + private static LocalModFile fromEmbeddedMod(ModManager modManager, Path modFile, FileSystem fs, ModLoaderType modLoaderType) throws IOException { Path manifestFile = fs.getPath("META-INF/MANIFEST.MF"); if (!Files.isRegularFile(manifestFile)) throw new IOException("Missing MANIFEST.MF in file " + manifestFile); @@ -190,7 +200,7 @@ public final class ForgeNewModMetadata { try { Files.copy(embeddedModFile, tempFile, StandardCopyOption.REPLACE_EXISTING); try (FileSystem embeddedFs = CompressingUtils.createReadOnlyZipFileSystem(tempFile)) { - return fromFile(modManager, modFile, embeddedFs); + return fromFile(modManager, modFile, embeddedFs, modLoaderType); } } catch (IOException e) { LOG.warning("Failed to read embedded-dependencies-mod: " + embeddedModFile, e); @@ -200,33 +210,36 @@ public final class ForgeNewModMetadata { } } - private static ModLoaderType analyzeLoader(Toml toml, String modID, int loaderACC, ModLoaderType defaultLoader) throws IOException { + private static ModLoaderType analyzeLoader(Toml toml, String modID, ModLoaderType loader) throws IOException { List> dependencies = toml.getList("dependencies." + modID); if (dependencies == null) { dependencies = toml.getList("dependencies"); // ??? I have no idea why some of the Forge mods use [[dependencies]] if (dependencies == null) { - return defaultLoader; + return loader; } } + ModLoaderType result = null; + loop: for (HashMap dependency : dependencies) { switch ((String) dependency.get("modId")) { case "forge": - return checkLoaderACC(loaderACC, ACC_FORGE, ModLoaderType.FORGE); + result = ModLoaderType.FORGE; + break loop; case "neoforge": - return checkLoaderACC(loaderACC, ACC_NEO_FORGED, ModLoaderType.NEO_FORGED); + result = ModLoaderType.NEO_FORGED; + break loop; } } - // ??? I have no idea why some of the Forge mods doesn't provide this key. - return defaultLoader; - } - - private static ModLoaderType checkLoaderACC(int current, int target, ModLoaderType res) throws IOException { - if ((target & current) != 0) { - return res; - } else { - throw new IOException("Mismatched loader."); + if (result == loader) + return result; + else if (result != null) + throw new IOException("Loader mismatch"); + else { + LOG.warning("Cannot determine the mod loader for mod " + modID + ", expected " + loader); + return loader; } } + }