diff --git a/src/main/java/net/fabricmc/meta/data/VersionDatabase.java b/src/main/java/net/fabricmc/meta/data/VersionDatabase.java index f95e7bb..945757d 100644 --- a/src/main/java/net/fabricmc/meta/data/VersionDatabase.java +++ b/src/main/java/net/fabricmc/meta/data/VersionDatabase.java @@ -35,12 +35,14 @@ public class VersionDatabase { public static final PomParser INTERMEDIARY_PARSER = new PomParser(MAVEN_URL + "net/fabricmc/intermediary/maven-metadata.xml"); public static final PomParser LOADER_PARSER = new PomParser(MAVEN_URL + "net/fabricmc/fabric-loader/maven-metadata.xml"); public static final PomParser INSTALLER_PARSER = new PomParser(MAVEN_URL + "net/fabricmc/fabric-installer/maven-metadata.xml"); + public static final PomParser API_PARSER = new PomParser(MAVEN_URL + "net/fabricmc/fabric-api/fabric-api/maven-metadata.xml"); public List game; public List mappings; public List intermediary; public List loader; public List installer; + public List api; private VersionDatabase() { } @@ -52,6 +54,7 @@ public static VersionDatabase generate() throws IOException, XMLStreamException database.intermediary = INTERMEDIARY_PARSER.getMeta(MavenVersion::new, "net.fabricmc:intermediary:"); database.loader = LOADER_PARSER.getMeta(MavenBuildVersion::new, "net.fabricmc:fabric-loader:"); database.installer = INSTALLER_PARSER.getMeta(MavenUrlVersion::new, "net.fabricmc:fabric-installer:"); + database.api = API_PARSER.getMeta(MavenBuildApiGameVersion::new, "net.fabricmc:fabric-api:fabric-api:"); database.loadMcData(); System.out.println("DB update took " + (System.currentTimeMillis() - start) + "ms"); return database; @@ -68,6 +71,8 @@ private void loadMcData() throws IOException { intermediary.sort(Comparator.comparingInt(o -> launcherMeta.getIndex(o.getVersion()))); intermediary.forEach(version -> version.setStable(true)); + api.forEach(version -> version.setStable(true)); + List minecraftVersions = new ArrayList<>(); for (MavenVersion gameVersion : intermediary) { if (!minecraftVersions.contains(gameVersion.getVersion())) { diff --git a/src/main/java/net/fabricmc/meta/utils/ApiVersionParser.java b/src/main/java/net/fabricmc/meta/utils/ApiVersionParser.java new file mode 100644 index 0000000..cb32ec9 --- /dev/null +++ b/src/main/java/net/fabricmc/meta/utils/ApiVersionParser.java @@ -0,0 +1,101 @@ +package net.fabricmc.meta.utils; + +import net.fabricmc.meta.data.VersionDatabase; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; + +public class ApiVersionParser { + + private List hashes; + private String apiVersion; + private String majorMinecraftVersion; + private List minecraftVersions = new ArrayList<>(); + + private String version; + private int build; + + private URL versionMetaUrl; + + private static final String[] hashTypes = new String[]{"md5", "sha1", "sha256", "sha512"}; + private HashParser hashParser = new HashParser(VersionDatabase.MAVEN_URL, "net/fabricmc/fabric-api/fabric-api/"); + + public ApiVersionParser(String version) { + this.version = version; + + try { + // TODO use official url + versionMetaUrl = new URL("https://raw.githubusercontent.com/dexman545/fabric-api-version-map/main/apiVersions.properties"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + // Fix old API versions not having MC version + // Recreated from curseforge version index + if (version.contains("0.3.1") || version.contains("0.3.0")) { + version = version + "-1.14"; + } + + if (version.contains("+build.")) { + //TODO legacy remove when no longer needed + this.majorMinecraftVersion = version.substring(version.lastIndexOf('-')); + this.apiVersion = version.substring(0, version.lastIndexOf('+') - 1); + this.build = Integer.parseInt(version.substring(version.lastIndexOf("+build.")+7, version.lastIndexOf('-'))); + } else { + this.majorMinecraftVersion = version.substring(version.lastIndexOf('+')); + this.apiVersion = version.substring(0, version.lastIndexOf('+') - 1); + this.build = 999; // Build number is no longer appended to versions, use dummy version + } + + this.hashes = this.hashParser.getHashes(this.version, "/fabric-api-", ".jar", hashTypes); + + Properties mc2Api = new Properties(); + try { + mc2Api.load(versionMetaUrl.openStream()); + } catch (IOException e) { + e.printStackTrace(); + } + + String finalVersion = this.version; + + mc2Api.forEach((k, v) -> { + String[] apiVersions = v.toString().split(","); + Arrays.stream(apiVersions).map(String::trim).toArray(unused -> apiVersions); + + if (Arrays.asList(apiVersions).contains(finalVersion)) { + this.minecraftVersions.add((String) k); + } + }); + } + + public String getVersion() { + return this.version.substring(0, this.version.lastIndexOf(this.majorMinecraftVersion.charAt(0)) != -1 ? version.lastIndexOf(this.majorMinecraftVersion.charAt(0)) : this.version.length() - 1); + } + + public String getApiVersion() { + return apiVersion; + } + + public String getMajorMinecraftVersion() { + return majorMinecraftVersion; + } + + @Override + public String toString() { + return version; + } + + public int getBuild() { + return build; + } + + public List getMinecraftVersions() { + return minecraftVersions; + } + + public List getHashes() { + return hashes; + } +} diff --git a/src/main/java/net/fabricmc/meta/utils/HashParser.java b/src/main/java/net/fabricmc/meta/utils/HashParser.java new file mode 100644 index 0000000..cd7d498 --- /dev/null +++ b/src/main/java/net/fabricmc/meta/utils/HashParser.java @@ -0,0 +1,45 @@ +package net.fabricmc.meta.utils; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class HashParser { + + String path; + List hashes = new ArrayList<>(); + + public HashParser(String rootMavenUrl, String prefix) { + this.path = rootMavenUrl + prefix; + } + + public List getHashes(String version, String prefix, String fileExtension, String[] hashExtensions) { + this.hashes.clear(); + version = version.replaceAll("\\+", "%2B"); // Remove "+" + version = version + prefix + version; + for (String hashExtension : hashExtensions) { + URL url; + try { + url = new URL(this.path + version + fileExtension + "." + hashExtension); + + try { + Scanner s = new Scanner(url.openStream()); + String hash = s.next(); // Assumes only one line in hash file + this.hashes.add(new String[]{hashExtension, hash}); + } catch (IOException e) { // Hash-type doesn't exist (recent api has sha256, older ones don't) + this.hashes.add(new String[]{hashExtension, ""}); + } + + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + return this.hashes; + + } + +} diff --git a/src/main/java/net/fabricmc/meta/web/EndpointsV2.java b/src/main/java/net/fabricmc/meta/web/EndpointsV2.java index 24ac7f7..b4b3119 100644 --- a/src/main/java/net/fabricmc/meta/web/EndpointsV2.java +++ b/src/main/java/net/fabricmc/meta/web/EndpointsV2.java @@ -52,6 +52,9 @@ public static void setup() { WebServer.jsonGet("/v2/versions/loader/:game_version", context -> withLimitSkip(context, EndpointsV2.getLoaderInfoAll(context))); WebServer.jsonGet("/v2/versions/loader/:game_version/:loader_version", EndpointsV2::getLoaderInfo); + WebServer.jsonGet("/v2/versions/fabric-api", context -> withLimitSkip(context, FabricMeta.database.api)); + WebServer.jsonGet("/v2/versions/fabric-api/:game_version", context -> withLimitSkip(context, filter(context, FabricMeta.database.api))); + WebServer.jsonGet("/v2/versions/installer", context -> withLimitSkip(context, FabricMeta.database.installer)); ProfileHandler.setup(); diff --git a/src/main/java/net/fabricmc/meta/web/models/MavenBuildApiGameVersion.java b/src/main/java/net/fabricmc/meta/web/models/MavenBuildApiGameVersion.java new file mode 100644 index 0000000..8960c6e --- /dev/null +++ b/src/main/java/net/fabricmc/meta/web/models/MavenBuildApiGameVersion.java @@ -0,0 +1,41 @@ +package net.fabricmc.meta.web.models; + +import net.fabricmc.meta.utils.ApiVersionParser; + +import java.util.List; + +public class MavenBuildApiGameVersion extends MavenBuildVersion{ + + private List hashes; + String gameMajorVersion; + List gameVersions; + + public MavenBuildApiGameVersion(String maven) { + super(maven); + + String[] mavenP = maven.split(":"); + String version = mavenP[mavenP.length-1]; + ApiVersionParser parser = new ApiVersionParser(version); + gameMajorVersion = parser.getMajorMinecraftVersion(); + + this.hashes = parser.getHashes(); + + this.build = parser.getBuild(); + this.version = parser.getVersion(); + this.gameMajorVersion = gameMajorVersion.replaceAll("[+-]", ""); // Remove prefix character + this.gameVersions = parser.getMinecraftVersions(); + } + + public String getGameMajorVersion() { + return gameMajorVersion; + } + + @Override + public boolean test(String s) { + return this.gameVersions.contains(s); + } + + public List getHashes() { + return hashes; + } +} diff --git a/src/main/java/net/fabricmc/meta/web/models/MavenBuildVersion.java b/src/main/java/net/fabricmc/meta/web/models/MavenBuildVersion.java index a223ed0..d7acfc1 100644 --- a/src/main/java/net/fabricmc/meta/web/models/MavenBuildVersion.java +++ b/src/main/java/net/fabricmc/meta/web/models/MavenBuildVersion.java @@ -23,14 +23,20 @@ public class MavenBuildVersion extends MavenVersion { public MavenBuildVersion(String maven) { super(maven); - String version = maven.split(":")[2]; + String[] mavenP = maven.split(":"); + String version = mavenP[mavenP.length-1]; if (version.contains("+build.")) { separator = "+build."; } else { separator = "."; } - build = Integer.parseInt(version.substring(version.lastIndexOf(".") + 1)); + // Fix parser for oddball 20w14infinite api version (0.5.7+build.2-20w14infinite) + if (version.contains("+build.2-20w14infinite")) { + build = Integer.parseInt(version.substring(version.lastIndexOf(".") + 1, version.lastIndexOf('-'))); + } else { + build = Integer.parseInt(version.substring(version.lastIndexOf(".") + 1)); + } } diff --git a/src/main/java/net/fabricmc/meta/web/models/MavenVersion.java b/src/main/java/net/fabricmc/meta/web/models/MavenVersion.java index bb1309f..866a85d 100644 --- a/src/main/java/net/fabricmc/meta/web/models/MavenVersion.java +++ b/src/main/java/net/fabricmc/meta/web/models/MavenVersion.java @@ -21,7 +21,7 @@ public class MavenVersion extends BaseVersion { String maven; public MavenVersion(String maven, boolean stable) { - super(maven.split(":")[2], stable); + super(getMavenParsed(maven), stable); this.maven = maven; } @@ -29,6 +29,11 @@ public MavenVersion(String maven) { this(maven, false); } + private static String getMavenParsed(String maven) { + String[] mavenP = maven.split(":"); + return mavenP[mavenP.length-1]; + } + public String getMaven() { return maven; }