Fix #4647: 修复总是将同时兼容 Forge 和 NeoForge 的模组识别为 Forge 模组的问题 (#4648)

This commit is contained in:
Glavo
2025-10-10 21:35:11 +08:00
committed by GitHub
parent 8a166266d8
commit 7dad43570e
2 changed files with 54 additions and 48 deletions

View File

@@ -41,21 +41,22 @@ public final class ModManager {
LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException;
}
private static final Map<String, List<Pair<ModMetadataReader, Set<ModLoaderType>>>> READERS;
private static final Map<String, List<Pair<ModMetadataReader, ModLoaderType>>> READERS;
static {
var map = new HashMap<String, List<Pair<ModMetadataReader, Set<ModLoaderType>>>>();
var zipReaders = List.<Pair<ModMetadataReader, Set<ModLoaderType>>>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<String, List<Pair<ModMetadataReader, ModLoaderType>>>();
var zipReaders = List.<Pair<ModMetadataReader, ModLoaderType>>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<Pair<ModMetadataReader, Set<ModLoaderType>>> readersMap = READERS.get(extension);
List<Pair<ModMetadataReader, ModLoaderType>> 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<ModMetadataReader>();
var unsupportedReaders = new ArrayList<ModMetadataReader>();
for (Pair<ModMetadataReader, Set<ModLoaderType>> reader : readersMap) {
boolean supported = false;
for (ModLoaderType type : reader.getValue()) {
if (modLoaderTypes.contains(type)) {
supported = true;
break;
}
}
if (supported) {
for (Pair<ModMetadataReader, ModLoaderType> reader : readersMap) {
if (modLoaderTypes.contains(reader.getValue())) {
supportedReaders.add(reader.getKey());
} else {
unsupportedReaders.add(reader.getKey());

View File

@@ -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);
}
public static LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException {
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/mods.toml", ACC_FORGE | ACC_NEO_FORGED, ModLoaderType.FORGE, modManager, modFile, fs);
return fromFile0("META-INF/neoforge.mods.toml", modLoaderType, modManager, modFile, fs);
} catch (Exception ignored) {
}
}
try {
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<HashMap<String, Object>> 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<String, Object> 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;
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;
}
}
private static ModLoaderType checkLoaderACC(int current, int target, ModLoaderType res) throws IOException {
if ((target & current) != 0) {
return res;
} else {
throw new IOException("Mismatched loader.");
}
}
}