mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-30 21:05:58 -05:00
Fix + test minecraft metadata downloading (#905)
This commit is contained in:
@@ -27,8 +27,18 @@ package net.fabricmc.loom.configuration.providers.minecraft;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public record ManifestVersion(List<Versions> versions, Map<String, String> latest) {
|
||||
public static class Versions {
|
||||
public String id, url, sha1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Versions getVersion(String id) {
|
||||
return versions.stream()
|
||||
.filter(versions -> versions.id.equalsIgnoreCase(id))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2023 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.loom.configuration.providers.minecraft;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.util.MirrorUtil;
|
||||
import net.fabricmc.loom.util.download.DownloadBuilder;
|
||||
|
||||
public final class MinecraftMetadataProvider {
|
||||
private final Options options;
|
||||
private final Function<String, DownloadBuilder> download;
|
||||
|
||||
private ManifestVersion.Versions versionEntry;
|
||||
private MinecraftVersionMeta versionMeta;
|
||||
|
||||
public MinecraftMetadataProvider(Options options, Function<String, DownloadBuilder> download) {
|
||||
this.options = options;
|
||||
this.download = download;
|
||||
}
|
||||
|
||||
public MinecraftVersionMeta getVersionMeta() {
|
||||
try {
|
||||
if (versionEntry == null) {
|
||||
versionEntry = getVersionEntry();
|
||||
}
|
||||
|
||||
if (versionMeta == null) {
|
||||
versionMeta = readVersionMeta();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return versionMeta;
|
||||
}
|
||||
|
||||
private ManifestVersion.Versions getVersionEntry() throws IOException {
|
||||
// Custom URL always takes priority
|
||||
if (options.customManifestUrl() != null) {
|
||||
ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
|
||||
customVersion.id = options.minecraftVersion();
|
||||
customVersion.url = options.customManifestUrl();
|
||||
return customVersion;
|
||||
}
|
||||
|
||||
final List<ManifestVersionSupplier> suppliers = List.of(
|
||||
// First try finding the version with caching
|
||||
() -> getVersions(false),
|
||||
// Then try finding the experimental version with caching
|
||||
() -> getExperimentalVersions(false),
|
||||
// Then force download Mojang's metadata to find the version
|
||||
() -> getVersions(true),
|
||||
// Finally try a force downloaded experimental metadata.
|
||||
() -> getExperimentalVersions(true)
|
||||
);
|
||||
|
||||
for (ManifestVersionSupplier supplier : suppliers) {
|
||||
final ManifestVersion.Versions version = supplier.get().getVersion(options.minecraftVersion());
|
||||
|
||||
if (version != null) {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Failed to find minecraft version: " + options.minecraftVersion());
|
||||
}
|
||||
|
||||
private ManifestVersion getVersions(boolean forceDownload) throws IOException {
|
||||
return getVersions(options.versionManifestUrl(), options.versionManifestPath(), forceDownload);
|
||||
}
|
||||
|
||||
private ManifestVersion getExperimentalVersions(boolean forceDownload) throws IOException {
|
||||
return getVersions(options.experimentalVersionManifestUrl(), options.experimentalVersionManifestPath(), forceDownload);
|
||||
}
|
||||
|
||||
private ManifestVersion getVersions(String url, Path cacheFile, boolean forceDownload) throws IOException {
|
||||
DownloadBuilder builder = download.apply(url);
|
||||
|
||||
if (forceDownload) {
|
||||
builder = builder.forceDownload();
|
||||
} else {
|
||||
builder = builder.defaultCache();
|
||||
}
|
||||
|
||||
final String versionManifest = builder.downloadString(cacheFile);
|
||||
return LoomGradlePlugin.OBJECT_MAPPER.readValue(versionManifest, ManifestVersion.class);
|
||||
}
|
||||
|
||||
private MinecraftVersionMeta readVersionMeta() throws IOException {
|
||||
final DownloadBuilder builder = download.apply(versionEntry.url);
|
||||
|
||||
if (versionEntry.sha1 != null) {
|
||||
builder.sha1(versionEntry.sha1);
|
||||
} else {
|
||||
builder.defaultCache();
|
||||
}
|
||||
|
||||
final String json = builder.downloadString(options.minecraftMetadataPath());
|
||||
return LoomGradlePlugin.OBJECT_MAPPER.readValue(json, MinecraftVersionMeta.class);
|
||||
}
|
||||
|
||||
public record Options(String minecraftVersion,
|
||||
String versionManifestUrl,
|
||||
String experimentalVersionManifestUrl,
|
||||
@Nullable String customManifestUrl,
|
||||
Path versionManifestPath,
|
||||
Path experimentalVersionManifestPath,
|
||||
Path minecraftMetadataPath) {
|
||||
public static Options create(String minecraftVersion, Project project, Path minecraftMetadataPath) {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
final Path userCache = extension.getFiles().getUserCache().toPath();
|
||||
|
||||
return new Options(
|
||||
minecraftVersion,
|
||||
MirrorUtil.getVersionManifests(project),
|
||||
MirrorUtil.getExperimentalVersions(project),
|
||||
extension.getCustomMinecraftManifest().getOrNull(),
|
||||
userCache.resolve("version_manifest.json"),
|
||||
userCache.resolve("experimental_version_manifest.json"),
|
||||
minecraftMetadataPath
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface ManifestVersionSupplier {
|
||||
ManifestVersion get() throws IOException;
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
package net.fabricmc.loom.configuration.providers.minecraft;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
@@ -37,25 +36,19 @@ import org.gradle.api.logging.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
import net.fabricmc.loom.configuration.ConfigContext;
|
||||
import net.fabricmc.loom.configuration.DependencyInfo;
|
||||
import net.fabricmc.loom.configuration.providers.BundleMetadata;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.MirrorUtil;
|
||||
import net.fabricmc.loom.util.download.DownloadBuilder;
|
||||
import net.fabricmc.loom.util.download.DownloadExecutor;
|
||||
import net.fabricmc.loom.util.download.GradleDownloadProgressListener;
|
||||
import net.fabricmc.loom.util.gradle.ProgressGroup;
|
||||
|
||||
public abstract class MinecraftProvider {
|
||||
private String minecraftVersion;
|
||||
|
||||
private MinecraftVersionMeta versionInfo;
|
||||
private MinecraftLibraryProvider libraryProvider;
|
||||
private MinecraftMetadataProvider metadataProvider;
|
||||
|
||||
private File workingDir;
|
||||
private File minecraftJson;
|
||||
private File minecraftClientJar;
|
||||
// Note this will be the boostrap jar starting with 21w39a
|
||||
private File minecraftServerJar;
|
||||
@@ -63,8 +56,6 @@ public abstract class MinecraftProvider {
|
||||
private File minecraftExtractedServerJar;
|
||||
@Nullable
|
||||
private BundleMetadata serverBundleMetadata;
|
||||
private File versionManifestJson;
|
||||
private File experimentalVersionsJson;
|
||||
|
||||
private final Project project;
|
||||
|
||||
@@ -86,11 +77,14 @@ public abstract class MinecraftProvider {
|
||||
|
||||
initFiles();
|
||||
|
||||
downloadMcJson();
|
||||
|
||||
try (FileReader reader = new FileReader(minecraftJson)) {
|
||||
versionInfo = LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, MinecraftVersionMeta.class);
|
||||
}
|
||||
metadataProvider = new MinecraftMetadataProvider(
|
||||
MinecraftMetadataProvider.Options.create(
|
||||
minecraftVersion,
|
||||
getProject(),
|
||||
file("minecraft-info.json").toPath()
|
||||
),
|
||||
getExtension()::download
|
||||
);
|
||||
|
||||
downloadJars();
|
||||
|
||||
@@ -98,16 +92,13 @@ public abstract class MinecraftProvider {
|
||||
serverBundleMetadata = BundleMetadata.fromJar(minecraftServerJar.toPath());
|
||||
}
|
||||
|
||||
libraryProvider = new MinecraftLibraryProvider(this, project);
|
||||
final MinecraftLibraryProvider libraryProvider = new MinecraftLibraryProvider(this, project);
|
||||
libraryProvider.provide();
|
||||
}
|
||||
|
||||
protected void initFiles() {
|
||||
workingDir = new File(getExtension().getFiles().getUserCache(), minecraftVersion);
|
||||
workingDir.mkdirs();
|
||||
minecraftJson = file("minecraft-info.json");
|
||||
versionManifestJson = new File(getExtension().getFiles().getUserCache(), "version_manifest.json");
|
||||
experimentalVersionsJson = new File(getExtension().getFiles().getUserCache(), "experimental_version_manifest.json");
|
||||
|
||||
if (provideClient()) {
|
||||
minecraftClientJar = file("minecraft-client.jar");
|
||||
@@ -119,73 +110,11 @@ public abstract class MinecraftProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadMcJson() throws IOException {
|
||||
final String versionManifestUrl = MirrorUtil.getVersionManifests(getProject());
|
||||
final String versionManifest = getExtension().download(versionManifestUrl)
|
||||
.defaultCache()
|
||||
.downloadString(versionManifestJson.toPath());
|
||||
|
||||
final ManifestVersion mcManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(versionManifest, ManifestVersion.class);
|
||||
ManifestVersion.Versions version = null;
|
||||
|
||||
if (getExtension().getCustomMinecraftManifest().isPresent()) {
|
||||
ManifestVersion.Versions customVersion = new ManifestVersion.Versions();
|
||||
customVersion.id = minecraftVersion;
|
||||
customVersion.url = getExtension().getCustomMinecraftManifest().get();
|
||||
version = customVersion;
|
||||
getProject().getLogger().lifecycle("Using custom minecraft manifest");
|
||||
}
|
||||
|
||||
if (version == null) {
|
||||
version = mcManifest.versions().stream()
|
||||
.filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
if (version == null) {
|
||||
version = findExperimentalVersion();
|
||||
}
|
||||
|
||||
if (version == null) {
|
||||
throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion);
|
||||
}
|
||||
|
||||
getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion);
|
||||
final DownloadBuilder download = getExtension().download(version.url);
|
||||
|
||||
if (version.sha1 != null) {
|
||||
download.sha1(version.sha1);
|
||||
} else {
|
||||
download.defaultCache();
|
||||
}
|
||||
|
||||
download.downloadPath(minecraftJson.toPath());
|
||||
}
|
||||
|
||||
// This attempts to find the version from fabric's own fallback version manifest json.
|
||||
private ManifestVersion.Versions findExperimentalVersion() throws IOException {
|
||||
final String expVersionManifest = getExtension().download(MirrorUtil.getExperimentalVersions(getProject()))
|
||||
.defaultCache()
|
||||
.downloadString(experimentalVersionsJson.toPath());
|
||||
|
||||
final ManifestVersion expManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(expVersionManifest, ManifestVersion.class);
|
||||
final ManifestVersion.Versions result = expManifest.versions().stream()
|
||||
.filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (result != null) {
|
||||
getProject().getLogger().lifecycle("Using fallback experimental version {}", minecraftVersion);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void downloadJars() throws IOException {
|
||||
try (ProgressGroup progressGroup = new ProgressGroup(getProject(), "Download Minecraft jars");
|
||||
DownloadExecutor executor = new DownloadExecutor(2)) {
|
||||
if (provideClient()) {
|
||||
final MinecraftVersionMeta.Download client = versionInfo.download("client");
|
||||
final MinecraftVersionMeta.Download client = getVersionInfo().download("client");
|
||||
getExtension().download(client.url())
|
||||
.sha1(client.sha1())
|
||||
.progress(new GradleDownloadProgressListener("Minecraft client", progressGroup::createProgressLogger))
|
||||
@@ -193,7 +122,7 @@ public abstract class MinecraftProvider {
|
||||
}
|
||||
|
||||
if (provideServer()) {
|
||||
final MinecraftVersionMeta.Download server = versionInfo.download("server");
|
||||
final MinecraftVersionMeta.Download server = getVersionInfo().download("server");
|
||||
getExtension().download(server.url())
|
||||
.sha1(server.sha1())
|
||||
.progress(new GradleDownloadProgressListener("Minecraft server", progressGroup::createProgressLogger))
|
||||
@@ -256,7 +185,7 @@ public abstract class MinecraftProvider {
|
||||
}
|
||||
|
||||
public MinecraftVersionMeta getVersionInfo() {
|
||||
return versionInfo;
|
||||
return Objects.requireNonNull(metadataProvider, "Metadata provider not setup").getVersionMeta();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user