diff --git a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java index a6acd7f..7f49c7e 100644 --- a/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java +++ b/launcher/src/main/java/com/skcraft/launcher/model/minecraft/Library.java @@ -65,10 +65,32 @@ } } + /** + * BACKWARDS COMPATIBILITY: + * Some library definitions only come with a "name" key and don't trigger any other compatibility measures. + * Therefore, if a library has no artifacts when this is called, we call {@link #setServerreq)} to trigger + * artifact generation that assumes the source is the Minecraft libraries URL. + * There is also some special handling for natives in this function; if we have no extra artifacts (newer specs + * put this in "classifiers" in the download list) then we make up an artifact by adding a maven classifier to + * the library name and using that. + */ public Artifact getArtifact(Environment environment) { + if (getDownloads() == null) { + setServerreq(true); // BACKWARDS COMPATIBILITY + } + String nativeString = getNativeString(environment.getPlatform()); if (nativeString != null) { + if (getDownloads().getClassifiers() == null) { + // BACKWARDS COMPATIBILITY: make up a virtual artifact + Artifact virtualArtifact = new Artifact(); + virtualArtifact.setUrl(getDownloads().getArtifact().getUrl()); + virtualArtifact.setPath(mavenNameToPath(name + ":" + nativeString)); + + return virtualArtifact; + } + return getDownloads().getClassifiers().get(nativeString); } else { return getDownloads().getArtifact(); @@ -121,7 +143,13 @@ private Map classifiers; } - // Support for old Forge distributions with legacy library specs. + /** + * BACKWARDS COMPATIBILITY: + * Various sources use the old-style library specification, where there are two keys - "name" and "url", + * rather than the newer multiple-artifact style. This setter is called by Jackson when the "url" property + * is present, and uses it to create a "virtual" artifact using the URL given to us here plus the library + * name parsed out into a path. + */ public void setUrl(String url) { Artifact virtualArtifact = new Artifact(); @@ -134,9 +162,14 @@ setDownloads(downloads); } + /** + * BACKWARDS COMPATIBILITY: + * Some old Forge distributions use a parameter called "serverreq" to indicate that the dependency should + * be fetched from the Minecraft library source; this setter handles that. + */ public void setServerreq(boolean value) { if (value) { - setUrl("https://libraries.minecraft.net/"); // TODO do something better than this + setUrl("https://libraries.minecraft.net/"); // TODO get this from properties? } } diff --git a/launcher/src/main/java/com/skcraft/launcher/update/Updater.java b/launcher/src/main/java/com/skcraft/launcher/update/Updater.java index cf9c322..083dfde 100644 --- a/launcher/src/main/java/com/skcraft/launcher/update/Updater.java +++ b/launcher/src/main/java/com/skcraft/launcher/update/Updater.java @@ -102,30 +102,48 @@ return instance; } + /** + * Check whether the package manifest contains an embedded version manifest, + * otherwise we'll have to download the one for the given Minecraft version. + * + * BACKWARDS COMPATIBILITY: + * Old manifests have an embedded version manifest without the minecraft JARs list present. + * If we find a manifest without that jar list, fetch the newer copy from launchermeta and use the list from that. + * We can't just replace the manifest outright because library versions might differ and that screws up Runner. + */ private VersionManifest readVersionManifest(Manifest manifest) throws IOException, InterruptedException { - // Check whether the package manifest contains an embedded version manifest, - // otherwise we'll have to download the one for the given Minecraft version VersionManifest version = manifest.getVersionManifest(); - if (version != null) { - mapper.writeValue(instance.getVersionPath(), version); - return version; - } else { - URL url = url(launcher.getProperties().getProperty("versionManifestUrl")); + URL url = url(launcher.getProperties().getProperty("versionManifestUrl")); - ReleaseList releases = HttpRequest.get(url) - .execute() - .expectResponseCode(200) - .returnContent() - .asJson(ReleaseList.class); - - Version relVersion = releases.find(manifest.getGameVersion()); - return HttpRequest.get(url(relVersion.getUrl())) - .execute() - .expectResponseCode(200) - .returnContent() - .saveContent(instance.getVersionPath()) - .asJson(VersionManifest.class); + if (version == null) { + version = fetchVersionManifest(url, manifest); } + + if (version.getDownloads().isEmpty()) { + // Backwards compatibility hack + VersionManifest otherManifest = fetchVersionManifest(url, manifest); + + version.setDownloads(otherManifest.getDownloads()); + version.setAssetIndex(otherManifest.getAssetIndex()); + } + + mapper.writeValue(instance.getVersionPath(), version); + return version; + } + + private static VersionManifest fetchVersionManifest(URL url, Manifest manifest) throws IOException, InterruptedException { + ReleaseList releases = HttpRequest.get(url) + .execute() + .expectResponseCode(200) + .returnContent() + .asJson(ReleaseList.class); + + Version relVersion = releases.find(manifest.getGameVersion()); + return HttpRequest.get(url(relVersion.getUrl())) + .execute() + .expectResponseCode(200) + .returnContent() + .asJson(VersionManifest.class); } /**