diff --git a/HMCLCore/build.gradle.kts b/HMCLCore/build.gradle.kts index 284e3d7d7e..f962419170 100644 --- a/HMCLCore/build.gradle.kts +++ b/HMCLCore/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { api(libs.kala.compress.tar) api(libs.simple.png.javafx) api(libs.gson) - api(libs.toml) + api(libs.tomlj) api(libs.xz) api(libs.lz4) api(libs.fx.gson) 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 5e14f90262..c321e3d3a2 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 @@ -24,7 +24,6 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; import com.google.gson.annotations.JsonAdapter; -import com.moandjiezana.toml.Toml; import kala.compress.archivers.zip.ZipArchiveEntry; import org.jackhuang.hmcl.mod.LocalModFile; import org.jackhuang.hmcl.mod.ModLoaderType; @@ -35,6 +34,10 @@ import org.jackhuang.hmcl.util.gson.Validation; import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.tree.ZipFileTree; +import org.tomlj.Toml; +import org.tomlj.TomlArray; +import org.tomlj.TomlParseResult; +import org.tomlj.TomlTable; import java.io.IOException; import java.io.InputStream; @@ -42,8 +45,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.StringJoiner; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -208,10 +211,15 @@ private static LocalModFile fromFile0( ZipArchiveEntry modToml = tree.getEntry(tomlPath); if (modToml == null) throw new IOException("File " + modFile + " is not a Forge 1.13+ or NeoForge mod."); - Toml toml = new Toml().read(tree.readTextEntry(modToml)); - ForgeNewModMetadata metadata = toml.to(ForgeNewModMetadata.class); + TomlParseResult tomlParseResult = Toml.parse(tree.readTextEntry(modToml)); + if (tomlParseResult.hasErrors()) { + var ioException = new IOException("Mod " + modFile + " `%s` is malformed..".formatted(modToml.getName())); + tomlParseResult.errors().forEach(ioException::addSuppressed); + throw ioException; + } + ForgeNewModMetadata metadata = JsonUtils.GSON.fromJson(tomlParseResult.toJson(), ForgeNewModMetadata.class); if (metadata == null || metadata.getMods().isEmpty()) - throw new IOException("Mod " + modFile + " `mods.toml` is malformed.."); + throw new IOException("Mod " + modFile + " `%s` is malformed..".formatted(modToml.getName())); Mod mod = metadata.getMods().get(0); ZipArchiveEntry manifestMF = tree.getEntry("META-INF/MANIFEST.MF"); String jarVersion = ""; @@ -224,7 +232,7 @@ private static LocalModFile fromFile0( } } - ModLoaderType type = analyzeLoader(toml, mod.getModId(), modLoaderType); + ModLoaderType type = analyzeLoader(tomlParseResult, 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), "", @@ -293,23 +301,32 @@ private static LocalModFile fromEmbeddedMod(ModManager modManager, Path modFile, throw new IOException(); } - private static ModLoaderType analyzeLoader(Toml toml, String modID, ModLoaderType loader) throws IOException { - List> dependencies = null; + private static ModLoaderType analyzeLoader(TomlParseResult toml, String modID, ModLoaderType loader) throws IOException { + List> dependencies = null; try { - dependencies = toml.getList("dependencies." + modID); + TomlArray tomlArray = toml.getArray("dependencies." + modID); + if (tomlArray != null) { + dependencies = tomlArray.toList().stream().map( o -> ((TomlTable) o).toMap()).toList(); + } } catch (ClassCastException ignored) { // https://github.com/HMCL-dev/HMCL/issues/5068 } if (dependencies == null) { try { - dependencies = toml.getList("dependencies"); // ??? I have no idea why some of the Forge mods use [[dependencies]] + TomlArray tomlArray = toml.getArray("dependencies"); // ??? I have no idea why some of the Forge mods use [[dependencies]] + if (tomlArray != null) { + dependencies = tomlArray.toList().stream().map( o -> ((TomlTable) o).toMap()).toList(); + } } catch (ClassCastException e) { try { - Toml table = toml.getTable("dependencies"); + TomlTable table = toml.getTable("dependencies"); if (table == null) return loader; - dependencies = table.getList(modID); + TomlArray tomlArray = table.getArray(modID); + if (tomlArray != null) { + dependencies = tomlArray.toList().stream().map( o -> ((TomlTable) o).toMap()).toList(); + } } catch (Throwable ignored) { } } @@ -321,7 +338,7 @@ private static ModLoaderType analyzeLoader(Toml toml, String modID, ModLoaderTyp ModLoaderType result = null; loop: - for (HashMap dependency : dependencies) { + for (Map dependency : dependencies) { switch ((String) dependency.get("modId")) { case "forge": result = ModLoaderType.FORGE; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1ca4ce29f0..427efa9266 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ jetbrains-annotations = "26.1.0" kala-compress = "1.27.1-3" simple-png-javafx = "0.3.0" gson = "2.13.2" -toml4j = "0.7.2" +tomlj = "1.1.1" xz = "1.11" lz4 = "1.10.4.1" fx-gson = "5.0.0" @@ -36,7 +36,7 @@ kala-compress-zip = { module = "org.glavo.kala:kala-compress-archivers-zip", ver kala-compress-tar = { module = "org.glavo.kala:kala-compress-archivers-tar", version.ref = "kala-compress" } simple-png-javafx = { module = "org.glavo:simple-png-javafx", version.ref = "simple-png-javafx" } gson = { module = "com.google.code.gson:gson", version.ref = "gson" } -toml = { module = "com.moandjiezana.toml:toml4j", version.ref = "toml4j" } +tomlj = { module = "org.tomlj:tomlj", version.ref = "tomlj" } xz = { module = "org.tukaani:xz", version.ref = "xz" } lz4 = { module = "org.glavo:lz4-java", version.ref = "lz4" } fx-gson = { module = "org.hildan.fxgson:fx-gson", version.ref = "fx-gson" }