2424import com .google .gson .JsonParseException ;
2525import com .google .gson .JsonPrimitive ;
2626import com .google .gson .annotations .JsonAdapter ;
27- import com .moandjiezana .toml .Toml ;
2827import kala .compress .archivers .zip .ZipArchiveEntry ;
2928import org .jackhuang .hmcl .mod .LocalModFile ;
3029import org .jackhuang .hmcl .mod .ModLoaderType ;
3534import org .jackhuang .hmcl .util .gson .Validation ;
3635import org .jackhuang .hmcl .util .io .CompressingUtils ;
3736import org .jackhuang .hmcl .util .tree .ZipFileTree ;
37+ import org .tomlj .Toml ;
38+ import org .tomlj .TomlArray ;
39+ import org .tomlj .TomlParseResult ;
40+ import org .tomlj .TomlTable ;
3841
3942import java .io .IOException ;
4043import java .io .InputStream ;
4144import java .lang .reflect .Type ;
4245import java .nio .file .Files ;
4346import java .nio .file .Path ;
4447import java .util .ArrayList ;
45- import java .util .HashMap ;
4648import java .util .List ;
49+ import java .util .Map ;
4750import java .util .StringJoiner ;
4851import java .util .jar .Attributes ;
4952import java .util .jar .Manifest ;
@@ -208,10 +211,15 @@ private static LocalModFile fromFile0(
208211 ZipArchiveEntry modToml = tree .getEntry (tomlPath );
209212 if (modToml == null )
210213 throw new IOException ("File " + modFile + " is not a Forge 1.13+ or NeoForge mod." );
211- Toml toml = new Toml ().read (tree .readTextEntry (modToml ));
212- ForgeNewModMetadata metadata = toml .to (ForgeNewModMetadata .class );
214+ TomlParseResult tomlParseResult = Toml .parse (tree .readTextEntry (modToml ));
215+ if (tomlParseResult .hasErrors ()) {
216+ var ioException = new IOException ("Mod " + modFile + " `%s` is malformed.." .formatted (modToml .getName ()));
217+ tomlParseResult .errors ().forEach (ioException ::addSuppressed );
218+ throw ioException ;
219+ }
220+ ForgeNewModMetadata metadata = JsonUtils .GSON .fromJson (tomlParseResult .toJson (), ForgeNewModMetadata .class );
213221 if (metadata == null || metadata .getMods ().isEmpty ())
214- throw new IOException ("Mod " + modFile + " `mods.toml ` is malformed.." );
222+ throw new IOException ("Mod " + modFile + " `%s ` is malformed.." . formatted ( modToml . getName ()) );
215223 Mod mod = metadata .getMods ().get (0 );
216224 ZipArchiveEntry manifestMF = tree .getEntry ("META-INF/MANIFEST.MF" );
217225 String jarVersion = "" ;
@@ -224,7 +232,7 @@ private static LocalModFile fromFile0(
224232 }
225233 }
226234
227- ModLoaderType type = analyzeLoader (toml , mod .getModId (), modLoaderType );
235+ ModLoaderType type = analyzeLoader (tomlParseResult , mod .getModId (), modLoaderType );
228236
229237 return new LocalModFile (modManager , modManager .getLocalMod (mod .getModId (), type ), modFile , mod .getDisplayName (), new LocalModFile .Description (mod .getDescription ()),
230238 mod .getAuthors (), jarVersion == null ? mod .getVersion () : mod .getVersion ().replace ("${file.jarVersion}" , jarVersion ), "" ,
@@ -293,23 +301,32 @@ private static LocalModFile fromEmbeddedMod(ModManager modManager, Path modFile,
293301 throw new IOException ();
294302 }
295303
296- private static ModLoaderType analyzeLoader (Toml toml , String modID , ModLoaderType loader ) {
297- List <HashMap <String , Object >> dependencies = null ;
304+ private static ModLoaderType analyzeLoader (TomlParseResult toml , String modID , ModLoaderType loader ) {
305+ List <Map <String , Object >> dependencies = null ;
298306 try {
299- dependencies = toml .getList ("dependencies." + modID );
307+ TomlArray tomlArray = toml .getArray ("dependencies." + modID );
308+ if (tomlArray != null ) {
309+ dependencies = tomlArray .toList ().stream ().map ( o -> ((TomlTable ) o ).toMap ()).toList ();
310+ }
300311 } catch (ClassCastException ignored ) { // https://github.com/HMCL-dev/HMCL/issues/5068
301312 }
302313
303314 if (dependencies == null ) {
304315 try {
305- dependencies = toml .getList ("dependencies" ); // ??? I have no idea why some of the Forge mods use [[dependencies]]
316+ TomlArray tomlArray = toml .getArray ("dependencies" ); // ??? I have no idea why some of the Forge mods use [[dependencies]]
317+ if (tomlArray != null ) {
318+ dependencies = tomlArray .toList ().stream ().map ( o -> ((TomlTable ) o ).toMap ()).toList ();
319+ }
306320 } catch (ClassCastException e ) {
307321 try {
308- Toml table = toml .getTable ("dependencies" );
322+ TomlTable table = toml .getTable ("dependencies" );
309323 if (table == null )
310324 return loader ;
311325
312- dependencies = table .getList (modID );
326+ TomlArray tomlArray = table .getArray (modID );
327+ if (tomlArray != null ) {
328+ dependencies = tomlArray .toList ().stream ().map ( o -> ((TomlTable ) o ).toMap ()).toList ();
329+ }
313330 } catch (Throwable ignored ) {
314331 }
315332 }
@@ -321,7 +338,7 @@ private static ModLoaderType analyzeLoader(Toml toml, String modID, ModLoaderTyp
321338
322339 ModLoaderType result = null ;
323340 loop :
324- for (HashMap <String , Object > dependency : dependencies ) {
341+ for (Map <String , Object > dependency : dependencies ) {
325342 switch ((String ) dependency .get ("modId" )) {
326343 case "forge" :
327344 result = ModLoaderType .FORGE ;
0 commit comments