From 15b61fa8803ab55236120259e9e2df99eac32e2f Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 26 Jun 2026 22:33:05 +0100 Subject: [PATCH 1/5] [CHANGE] Use try-with-resource in GameVersions --- .../curseupload/requests/GameVersions.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java index c394a4b..067b000 100644 --- a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java +++ b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java @@ -64,9 +64,10 @@ private void fetchValidVersionTypes() { try { TLongSet validVersionTypes = new TLongHashSet(); - Reader versionReader = HTTPUtils.fetch(gameType.versionTypesEndpoint()); - VersionType[] types = HTTPUtils.gson.fromJson(versionReader, VersionType[].class); - versionReader.close(); + VersionType[] types; + try (Reader versionReader = HTTPUtils.fetch(gameType.versionTypesEndpoint())) { + types = HTTPUtils.gson.fromJson(versionReader, VersionType[].class); + } for (VersionType type : types) { if (type.slug().startsWith("minecraft") || type.slug().equals("java") || type.slug().equals("environment") || type.slug().equals("modloader") || type.slug().equals("game")) { @@ -74,9 +75,10 @@ private void fetchValidVersionTypes() { } } - Reader gameVersionJson = HTTPUtils.fetch(gameType.versionsEndpoint()); - Version[] versions = HTTPUtils.gson.fromJson(gameVersionJson, Version[].class); - gameVersionJson.close(); + Version[] versions; + try (Reader gameVersionJson = HTTPUtils.fetch(gameType.versionsEndpoint())) { + versions = HTTPUtils.gson.fromJson(gameVersionJson, Version[].class); + } for (Version version : versions) { if (validVersionTypes.contains(version.type())) { From fc0314bb5b1b27647ac83362d546b8e7a2dae954 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Wed, 1 Jul 2026 14:32:51 +0100 Subject: [PATCH 2/5] [CHANGE] Process GameVersions in a stream --- .../hypherionmc/curseupload/requests/GameVersions.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java index 067b000..f3791aa 100644 --- a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java +++ b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java @@ -34,6 +34,7 @@ import me.hypherionmc.curseupload.util.HTTPUtils; import java.io.Reader; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -80,11 +81,10 @@ private void fetchValidVersionTypes() { versions = HTTPUtils.gson.fromJson(gameVersionJson, Version[].class); } - for (Version version : versions) { - if (validVersionTypes.contains(version.type())) { - version.versions().forEach(ver -> gameVersions.put(ver.name().toLowerCase(), ver.id())); - } - } + Arrays.stream(versions) + .filter(version -> validVersionTypes.contains(version.type())) + .flatMap(version -> version.versions().stream()) + .forEach(data -> gameVersions.put(data.name().toLowerCase(), data.id())); } catch (Exception e) { CurseUploadApi.INSTANCE.log("Failed to fetch CurseForge Versions", e); } From 49d5201a649ca355a96e0517c549e839f33f56cd Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 26 Jun 2026 22:24:57 +0100 Subject: [PATCH 3/5] [CHANGE] Sort GameVersions before throwing This makes it easier to scan through valid versions. --- .../me/hypherionmc/curseupload/requests/GameVersions.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java index f3791aa..baa6bd5 100644 --- a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java +++ b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java @@ -37,6 +37,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import java.util.stream.Collectors; /** * @author HypherionSA @@ -102,7 +103,8 @@ public Set resolveGameVersion(Set objects) { objects.forEach(obj -> { long id = gameVersions.get(obj.toLowerCase()); if (id == 0) { - throw new IllegalArgumentException(obj + " is not a valid game version. Valid versions are: " + gameVersions.keySet()); + String versions = gameVersions.keySet().stream().sorted().collect(Collectors.joining(", ")); + throw new IllegalArgumentException(obj + " is not a valid game version. Valid versions are: " + versions); } set.add(id); }); From 49002e17167621a359136bc2432855e8be821808 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sun, 5 Jul 2026 14:01:30 +0100 Subject: [PATCH 4/5] [CHANGE] Throw InvalidCurseVersionException for invalid GameVersions This allows clients to catch and recover from unsupported game versions, which is useful as CurseForge are not consistent with which versions are supported. --- .../errors/InvalidCurseVersionException.java | 78 +++++++++++++++++++ .../curseupload/requests/GameVersions.java | 19 ++--- 2 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 src/main/java/me/hypherionmc/curseupload/errors/InvalidCurseVersionException.java diff --git a/src/main/java/me/hypherionmc/curseupload/errors/InvalidCurseVersionException.java b/src/main/java/me/hypherionmc/curseupload/errors/InvalidCurseVersionException.java new file mode 100644 index 0000000..753c25e --- /dev/null +++ b/src/main/java/me/hypherionmc/curseupload/errors/InvalidCurseVersionException.java @@ -0,0 +1,78 @@ +/* + * This file is part of CurseUpload4J, licensed under the MIT License (MIT). + * + * Copyright (c) 2023 HypherionSA and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package me.hypherionmc.curseupload.errors; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.Collections.unmodifiableList; + +/** + * @author MattSturgeon + * Thrown when using Minecraft Versions that are not supported by Curseforge + */ +public class InvalidCurseVersionException extends IllegalArgumentException { + private final List invalidVersions; + private final List validVersions; + + public static InvalidCurseVersionException of(Collection invalidVersions, Collection validVersions) { + List invalid = invalidVersions.stream().sorted().collect(Collectors.toList()); + List valid = validVersions.stream().sorted().collect(Collectors.toList()); + return new InvalidCurseVersionException(invalid, valid); + } + + private static String message(List invalid, List valid) { + StringBuilder msg = new StringBuilder(); + switch (invalid.size()) { + case 0: break; + case 1: + String v = invalid.stream().findFirst().orElse(null); + msg.append(v).append(" is not a valid game version. "); + break; + default: + msg.append("Invalid game versions: "); + msg.append(String.join(", ", invalid)); + msg.append(". "); + break; + } + msg.append("Valid versions are: "); + msg.append(String.join(", ", valid)); + return msg.toString(); + } + + private InvalidCurseVersionException(List invalidVersions, List validVersions) { + super(message(invalidVersions, validVersions)); + this.invalidVersions = unmodifiableList(invalidVersions); + this.validVersions = unmodifiableList(validVersions); + } + + public final List getInvalidVersions() { + return invalidVersions; + } + + public final List getValidVersions() { + return validVersions; + } +} diff --git a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java index baa6bd5..2346752 100644 --- a/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java +++ b/src/main/java/me/hypherionmc/curseupload/requests/GameVersions.java @@ -29,6 +29,7 @@ import gnu.trove.set.hash.TLongHashSet; import me.hypherionmc.curseupload.CurseUploadApi; import me.hypherionmc.curseupload.constants.GameType; +import me.hypherionmc.curseupload.errors.InvalidCurseVersionException; import me.hypherionmc.curseupload.schema.versions.Version; import me.hypherionmc.curseupload.schema.versions.VersionType; import me.hypherionmc.curseupload.util.HTTPUtils; @@ -37,7 +38,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; -import java.util.stream.Collectors; /** * @author HypherionSA @@ -96,19 +96,20 @@ private void fetchValidVersionTypes() { * Used when sending a request to the API * @param objects The list of game versions to check * @return The list of game versions ID's if no error occurred + * @throws InvalidCurseVersionException If any game versions are not supported by CurseForge */ public Set resolveGameVersion(Set objects) { - Set set = new HashSet<>(); + Set ids = new HashSet<>(); + Set invalid = new HashSet<>(); objects.forEach(obj -> { - long id = gameVersions.get(obj.toLowerCase()); - if (id == 0) { - String versions = gameVersions.keySet().stream().sorted().collect(Collectors.joining(", ")); - throw new IllegalArgumentException(obj + " is not a valid game version. Valid versions are: " + versions); - } - set.add(id); + String version = obj.toLowerCase(); + long id = gameVersions.get(version); + if (id == 0) invalid.add(version); + else ids.add(id); }); - return set; + if (invalid.isEmpty()) return ids; + else throw InvalidCurseVersionException.of(invalid, gameVersions.keySet()); } } From 78f345901fb6bf1149e4d9a2471ecdf9d809b6f3 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Fri, 26 Jun 2026 22:24:57 +0100 Subject: [PATCH 5/5] [CHORE] Bump version to 1.1.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c31a9d1..a2eb64f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Plugin Information version_major=1 version_minor=1 -version_patch=0 +version_patch=1 maven_group=me.hypherionmc.modutils # Dependencies