1313import java .net .URLEncoder ;
1414import java .nio .charset .StandardCharsets ;
1515import java .util .*;
16+ import java .util .concurrent .TimeUnit ;
1617
1718public record CurseModpack (
1819 String title ,
@@ -32,14 +33,14 @@ public static Optional<CurseModpack> load(JsonElement json) throws IOException {
3233 JsonObject obj = json .getAsJsonObject ();
3334 String title = Objects .requireNonNull (obj .get ("name" ), "Missing property: name" ).getAsString ();
3435 String version = obj .has ("version" ) ? obj .get ("version" ).getAsString () : "unknown" ;
35-
36+
3637 JsonObject minecraft = Objects .requireNonNull (obj .get ("minecraft" ), "Missing property: minecraft" ).getAsJsonObject ();
3738 String mcVersion = Objects .requireNonNull (minecraft .get ("version" ), "Missing property: minecraft.version" ).getAsString ();
3839 JsonArray loaderArray = Objects .requireNonNull (minecraft .get ("modLoaders" ), "Missing property: minecraft.modLoaders" ).getAsJsonArray ();
3940 if (loaderArray .size () != 1 ) throw new JsonSyntaxException ("Modpack must define exactly one mod loader" );
4041 String loaderId = Objects .requireNonNull (loaderArray .get (0 ).getAsJsonObject ().get ("id" ), "Missing property: minecraft.modLoaders[0].id" ).getAsString ();
4142 if (!loaderId .contains ("-" )) throw new JsonSyntaxException ("Modpack loader id is invalid: " + loaderId );
42-
43+
4344 JsonArray filesArray = Objects .requireNonNull (obj .get ("files" ), "Missing property: files" ).getAsJsonArray ();
4445 Set <Integer > projectIds = new HashSet <>();
4546 Map <Integer , Integer > fileIds = new HashMap <>();
@@ -57,18 +58,19 @@ public static Optional<CurseModpack> load(JsonElement json) throws IOException {
5758 List <Modpack .File > files = fileIds .entrySet ().stream ()
5859 .<Modpack .File >map (entry -> new CurseFile (resolvedProjects .get (entry .getKey ()), entry .getValue ()))
5960 .toList ();
60-
61+
6162 return Optional .of (new CurseModpack (title , new Modpack .Minecraft (
6263 mcVersion , loaderId .substring (0 , loaderId .indexOf ('-' )), loaderId .substring (loaderId .indexOf ('-' ) + 1 )
6364 ), version , List .copyOf (files )));
6465 }
65-
66+
6667 // Don't resolve file name and URL if not needed
6768 private static class CurseFile implements Modpack .File {
6869
6970 private final ProjectInfo project ;
7071 private final int fileId ;
7172 private FileInfo file ;
73+ private int tries = 0 ;
7274
7375 private CurseFile (ProjectInfo project , int fileId ) {
7476 this .project = project ;
@@ -91,7 +93,16 @@ public String fileName() {
9193 if (this .file == null ) {
9294 try {
9395 this .file = API .getFile (this .project .projectId (), this .fileId );
96+ System .out .println ("Retrieved detailed information for \u001B [33m" + this .file .name () + "\u001B [0m" );
9497 } catch (IOException e ) {
98+ if (this .tries < 5 ) {
99+ System .out .println ("Failed to retrieve detailed information for project \u001B [33m" + this .project .name () + "\u001B [0m. Try again (" + ++this .tries + "/5)" );
100+ try {
101+ TimeUnit .SECONDS .sleep (3 );
102+ } catch (InterruptedException ignored ) {}
103+ return this .fileName ();
104+ }
105+
95106 throw new RuntimeException (e );
96107 }
97108 }
0 commit comments