diff options
Diffstat (limited to 'src/main/java/net/fabricmc/loom/configuration')
13 files changed, 478 insertions, 351 deletions
diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index d315f75c..a8c52b5a 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -248,10 +248,8 @@ public final class CompileConfiguration { project1.getTasks().getByName("eclipse").finalizedBy(project1.getTasks().getByName("genEclipseRuns")); project1.getTasks().getByName("cleanEclipse").finalizedBy(project1.getTasks().getByName("cleanEclipseRuns")); - if (extension.autoGenIDERuns) { - SetupIntelijRunConfigs.setup(project1); - GenVsCodeProjectTask.generate(project1); - } + SetupIntelijRunConfigs.setup(project1); + GenVsCodeProjectTask.generate(project1); // Enables the default mod remapper if (extension.remapMod) { @@ -362,6 +360,7 @@ public final class CompileConfiguration { // Disable some things used by log4j via the mixin AP that prevent it from being garbage collected System.setProperty("log4j2.disable.jmx", "true"); System.setProperty("log4j.shutdownHookEnabled", "false"); + System.setProperty("log4j.skipJansi", "true"); project.getLogger().info("Configuring compiler arguments for Java"); new JavaApInvoker(project).configureMixin(); diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java index 41cda1b1..ec50c3a5 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java @@ -92,6 +92,13 @@ public final class RunConfigSettings implements Named { */ private final String baseName; + /** + * When true a run configuration file will be generated for IDE's. + * + * <p>By default only run configs on the root project will be generated. + */ + private boolean ideConfigGenerated; + private final Project project; private final LoomGradleExtension extension; @@ -99,6 +106,7 @@ public final class RunConfigSettings implements Named { this.baseName = baseName; this.project = project; this.extension = project.getExtensions().getByType(LoomGradleExtension.class); + this.ideConfigGenerated = extension.isRootProject(); source("main"); runDir("run"); @@ -232,6 +240,10 @@ public final class RunConfigSettings implements Named { }); } + public void ideConfigGenerated(boolean ideConfigGenerated) { + this.ideConfigGenerated = ideConfigGenerated; + } + /** * Add the {@code -XstartOnFirstThread} JVM argument when on OSX. */ @@ -295,4 +307,12 @@ public final class RunConfigSettings implements Named { file.mkdir(); } } + + public boolean isIdeConfigGenerated() { + return ideConfigGenerated; + } + + public void setIdeConfigGenerated(boolean ideConfigGenerated) { + this.ideConfigGenerated = ideConfigGenerated; + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java index c531cee8..d3911d18 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java @@ -59,7 +59,7 @@ public class SetupIntelijRunConfigs { if (extension.ideSync()) { //Ensures the assets are downloaded when idea is syncing a project MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); - MinecraftNativesProvider.provide(extension.getMinecraftProvider(), project); + MinecraftNativesProvider.provide(project); } String projectPath = project == rootProject ? "" : project.getPath().replace(':', '_'); @@ -71,7 +71,11 @@ public class SetupIntelijRunConfigs { runConfigsDir.mkdirs(); } - for (RunConfigSettings settings : extension.getRuns()) { + for (RunConfigSettings settings : extension.getRunConfigs()) { + if (!settings.isIdeConfigGenerated()) { + continue; + } + RunConfig config = RunConfig.runConfig(project, settings); String name = config.configName.replaceAll("[^a-zA-Z0-9$_]", "_"); diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java index 9c366225..9673a9a4 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java @@ -53,7 +53,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider { boolean isForgeAtDirty = getExtension().isForge() && getExtension().getMappingsProvider().patchedProvider.isAtDirty(); if (jarProcessorManager.isInvalid(projectMappedJar) || isRefreshDeps() || isForgeAtDirty) { - getProject().getLogger().lifecycle(":processing mapped jar"); + getProject().getLogger().info(":processing mapped jar"); invalidateJars(); try { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java index 4ecb34fb..9e11cb3a 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java @@ -41,6 +41,7 @@ import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; import org.gradle.api.Project; import org.gradle.api.artifacts.Dependency; +import org.gradle.api.plugins.JavaPlugin; import net.fabricmc.loom.configuration.DependencyProvider; import net.fabricmc.loom.configuration.RemappedConfigurationEntry; @@ -64,7 +65,7 @@ public class LaunchProvider extends DependencyProvider { .property("client", "org.lwjgl.librarypath", getExtension().getNativesDirectory().getAbsolutePath()) .argument("client", "--assetIndex") - .argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex.getFabricId(getExtension().getMinecraftProvider().getMinecraftVersion())) + .argument("client", getExtension().getMinecraftProvider().getVersionInfo().getAssetIndex().getFabricId(getExtension().getMinecraftProvider().getMinecraftVersion())) .argument("client", "--assetsDir") .argument("client", new File(getExtension().getUserCache(), "assets").getAbsolutePath()); @@ -125,8 +126,8 @@ public class LaunchProvider extends DependencyProvider { writeLog4jConfig(); FileUtils.writeStringToFile(getExtension().getDevLauncherConfig(), launchConfig.asString(), StandardCharsets.UTF_8); - addDependency(Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR, "runtimeOnly"); - addDependency(Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER, "runtimeOnly"); + addDependency(Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR, JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); + addDependency(Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER, JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); annotationDependency = addDependency(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS, "compileOnly"); if (getExtension().isForge()) { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java index 8d0a8d5e..2d0ac48b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java @@ -44,7 +44,7 @@ import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.DependencyProvider; import net.fabricmc.loom.configuration.providers.minecraft.ManifestVersion; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftLibraryProvider; -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.DownloadUtil; import net.fabricmc.loom.util.HashedDownloadUtil; @@ -53,7 +53,7 @@ import net.fabricmc.stitch.merge.JarMerger; public class MinecraftProvider extends DependencyProvider { private String minecraftVersion; - private MinecraftVersionInfo versionInfo; + private MinecraftVersionMeta versionInfo; private MinecraftLibraryProvider libraryProvider; private File minecraftJson; @@ -84,7 +84,7 @@ public class MinecraftProvider extends DependencyProvider { downloadMcJson(offline); try (FileReader reader = new FileReader(minecraftJson)) { - versionInfo = LoomGradlePlugin.GSON.fromJson(reader, MinecraftVersionInfo.class); + versionInfo = LoomGradlePlugin.GSON.fromJson(reader, MinecraftVersionMeta.class); } // Add Loom as an annotation processor @@ -217,15 +217,15 @@ public class MinecraftProvider extends DependencyProvider { return; } - MinecraftVersionInfo.Downloads client = versionInfo.downloads.get("client"); - MinecraftVersionInfo.Downloads server = versionInfo.downloads.get("server"); + MinecraftVersionMeta.Download client = versionInfo.getDownload("client"); + MinecraftVersionMeta.Download server = versionInfo.getDownload("server"); - HashedDownloadUtil.downloadIfInvalid(new URL(client.url), minecraftClientJar, client.sha1, logger, false); - HashedDownloadUtil.downloadIfInvalid(new URL(server.url), minecraftServerJar, server.sha1, logger, false); + HashedDownloadUtil.downloadIfInvalid(new URL(client.getUrl()), minecraftClientJar, client.getSha1(), logger, false); + HashedDownloadUtil.downloadIfInvalid(new URL(server.getUrl()), minecraftServerJar, server.getSha1(), logger, false); } private void mergeJars(Logger logger) throws IOException { - logger.lifecycle(":merging jars"); + logger.info(":merging jars"); try (JarMerger jarMerger = new JarMerger(minecraftClientJar, minecraftServerJar, minecraftMergedJar)) { jarMerger.enableSyntheticParamsOffset(); @@ -241,7 +241,7 @@ public class MinecraftProvider extends DependencyProvider { return minecraftVersion; } - public MinecraftVersionInfo getVersionInfo() { + public MinecraftVersionMeta getVersionInfo() { return versionInfo; } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java index cf9fab37..df5aa108 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java @@ -239,7 +239,7 @@ public class MappingsProvider extends DependencyProvider { private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler) throws Exception { - project.getLogger().lifecycle(":extracting " + yarnJar.getFileName()); + project.getLogger().info(":extracting " + yarnJar.getFileName()); if (isMCP(yarnJar)) { readAndMergeMCP(yarnJar, postPopulationScheduler); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java index 7ec517c0..af9dcbdb 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MojangMappingsDependency.java @@ -65,7 +65,7 @@ import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; import net.fabricmc.loom.util.DownloadUtil; import net.fabricmc.lorenztiny.TinyMappingsReader; import net.fabricmc.mapping.tree.TinyMappingFactory; @@ -172,14 +172,14 @@ public class MojangMappingsDependency extends AbstractModuleDependency implement } private MappingSet getMappingsSet(Path clientMappings, Path serverMappings) throws IOException { - MinecraftVersionInfo versionInfo = extension.getMinecraftProvider().getVersionInfo(); + MinecraftVersionMeta versionInfo = extension.getMinecraftProvider().getVersionInfo(); - if (versionInfo.downloads.get(MANIFEST_CLIENT_MAPPINGS) == null) { + if (versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS) == null) { throw new RuntimeException("Failed to find official mojang mappings for " + getVersion()); } - String clientMappingsUrl = versionInfo.downloads.get(MANIFEST_CLIENT_MAPPINGS).url; - String serverMappingsUrl = versionInfo.downloads.get(MANIFEST_SERVER_MAPPINGS).url; + String clientMappingsUrl = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS).getUrl(); + String serverMappingsUrl = versionInfo.getDownload(MANIFEST_CLIENT_MAPPINGS).getUrl(); DownloadUtil.downloadIfChanged(new URL(clientMappingsUrl), clientMappings.toFile(), project.getLogger()); DownloadUtil.downloadIfChanged(new URL(serverMappingsUrl), serverMappings.toFile(), project.getLogger()); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java index 8822140c..dcf846e8 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java @@ -36,22 +36,13 @@ public class MinecraftLibraryProvider { public File MINECRAFT_LIBS; public void provide(MinecraftProvider minecraftProvider, Project project) { - MinecraftVersionInfo versionInfo = minecraftProvider.getVersionInfo(); + MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); initFiles(project, minecraftProvider); - for (MinecraftVersionInfo.Library library : versionInfo.libraries) { - if (library.allowed() && !library.isNative() && library.getFile(MINECRAFT_LIBS) != null) { - // TODO: Add custom library locations - - // By default, they are all available on all sides - /* boolean isClientOnly = false; - - if (library.name.contains("java3d") || library.name.contains("paulscode") || library.name.contains("lwjgl") || library.name.contains("twitch") || library.name.contains("jinput") || library.name.contains("text2speech") || library.name.contains("objc")) { - isClientOnly = true; - } */ - - project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, project.getDependencies().module(library.getArtifactName())); + for (MinecraftVersionMeta.Library library : versionInfo.getLibraries()) { + if (library.isValidForOS() && !library.hasNatives() && library.getArtifact() != null) { + project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, project.getDependencies().module(library.getName())); } } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftNativesProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftNativesProvider.java index 7a8b05cc..59c626d8 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftNativesProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftNativesProvider.java @@ -27,26 +27,40 @@ package net.fabricmc.loom.configuration.providers.minecraft; import java.io.File; import java.io.IOException; import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; -import com.google.common.base.Stopwatch; +import org.apache.commons.io.FileUtils; import org.gradle.api.GradleException; import org.gradle.api.Project; import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.configuration.providers.MinecraftProvider; -import net.fabricmc.loom.util.DownloadUtil; +import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.util.HashedDownloadUtil; import net.fabricmc.loom.util.ThreadingUtils; public class MinecraftNativesProvider { - public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { - LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); - MinecraftVersionInfo versionInfo = minecraftProvider.getVersionInfo(); - boolean offline = project.getGradle().getStartParameter().isOffline(); + private final Project project; + private final LoomGradleExtension extension; + private final File nativesDir; + private final File jarStore; + + public MinecraftNativesProvider(Project project) { + this.project = project; + extension = project.getExtensions().getByType(LoomGradleExtension.class); - File nativesDir = extension.getNativesDirectory(); - File jarStore = extension.getNativesJarStore(); + nativesDir = extension.getNativesDirectory(); + jarStore = extension.getNativesJarStore(); + } + + public static void provide(Project project) throws IOException { + new MinecraftNativesProvider(project).provide(); + } + private void provide() throws IOException { if (extension.hasCustomNatives()) { if (!nativesDir.exists()) { throw new RuntimeException("Could no find custom natives directory at " + nativesDir.getAbsolutePath()); @@ -55,25 +69,82 @@ public class MinecraftNativesProvider { return; } - Stopwatch stopwatch = Stopwatch.createStarted(); + if (!LoomGradlePlugin.refreshDeps && !requiresExtract()) { + project.getLogger().info("Natives do no need extracting, skipping"); + return; + } - ThreadingUtils.run(versionInfo.libraries, library -> { - File libJarFile = library.getFile(jarStore); + extractNatives(); + } - if (library.allowed() && library.isNative() && libJarFile != null) { - if (!offline) { - DownloadUtil.downloadIfChanged(new URL(library.getURL()), libJarFile, project.getLogger()); - } + private void extractNatives() throws IOException { + boolean offline = project.getGradle().getStartParameter().isOffline(); - if (!libJarFile.exists()) { - throw new GradleException("Native jar not found at " + libJarFile.getAbsolutePath()); - } + if (nativesDir.exists()) { + try { + FileUtils.deleteDirectory(nativesDir); + } catch (IOException e) { + throw new IOException("Failed to delete the natives directory, is the game running?", e); + } + } + + nativesDir.mkdirs(); + + for (MinecraftVersionMeta.Classifier library : getNatives()) { + File libJarFile = library.getRelativeFile(jarStore); + + if (!offline) { + HashedDownloadUtil.downloadIfInvalid(new URL(library.getUrl()), libJarFile, library.getSha1(), project.getLogger(), false); + } - // TODO possibly find a way to prevent needing to re-extract after each run, doesnt seem too slow - ZipUtil.unpack(libJarFile, nativesDir); + if (!libJarFile.exists()) { + throw new GradleException("Native jar not found at " + libJarFile.getAbsolutePath()); } - }); - project.getLogger().info("Took " + stopwatch.stop() + " to provide " + versionInfo.libraries.size() + " natives."); + ZipUtil.unpack(libJarFile, nativesDir); + + // Store a file containing the hash of the extracted natives, used on subsequent runs to skip extracting all the natives if they haven't changed + File libSha1File = new File(nativesDir, libJarFile.getName() + ".sha1"); + FileUtils.writeStringToFile(libSha1File, library.getSha1(), StandardCharsets.UTF_8); + } + } + + private boolean requiresExtract() { + List<MinecraftVersionMeta.Classifier> natives = getNatives(); + + if (natives.isEmpty()) { + throw new IllegalStateException("No natives found for the current system"); + } + + for (MinecraftVersionMeta.Classifier library : natives) { + File libJarFile = library.getRelativeFile(jarStore); + File libSha1File = new File(nativesDir, libJarFile.getName() + ".sha1"); + + if (!libSha1File.exists()) { + return true; + } + + try { + String sha1 = FileUtils.readFileToString(libSha1File, StandardCharsets.UTF_8); + + if (!sha1.equalsIgnoreCase(library.getSha1())) { + return true; + } + } catch (IOException e) { + project.getLogger().error("Failed to read " + libSha1File.getAbsolutePath(), e); + return true; + } + } + + // All looks good, no need to re-extract + return false; + } + + private List<MinecraftVersionMeta.Classifier> getNatives() { + return extension.getMinecraftProvider().getVersionInfo().getLibraries().stream() + .filter((MinecraftVersionMeta.Library::hasNativesForOS)) + .map(MinecraftVersionMeta.Library::getClassifierForOS) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionInfo.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionInfo.java deleted file mode 100644 index 0994b4cc..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionInfo.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2016, 2017, 2018 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.File; -import java.util.List; -import java.util.Map; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -import net.fabricmc.loom.util.Constants; -import net.fabricmc.loom.util.OperatingSystem; - -public class MinecraftVersionInfo { - public List<Library> libraries; - public Map<String, Downloads> downloads; - public AssetIndex assetIndex; - - public class Downloads { - public String url; - public String sha1; - } - - public class AssetIndex { - private String id; - public String sha1; - public String url; - - public String getId() { - return id; - } - - public String getFabricId(String version) { - return id.equals(version) ? version : version + "-" + id; - } - } - - public class Library { - public String name; - public JsonObject natives; - public JsonObject downloads; - private Artifact artifact; - public Rule[] rules; - - public String getURL() { - String path; - String[] parts = this.name.split(":", 3); - path = parts[0].replace(".", "/") + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + getClassifier() + ".jar"; - return Constants.LIBRARIES_BASE + path; - } - - public File getFile(File baseDir) { - String[] parts = this.name.split(":", 3); - return new File(baseDir, parts[0].replace(".", File.separator) + File.separator + parts[1] + File.separator + parts[2] + File.separator + parts[1] + "-" + parts[2] + getClassifier() + ".jar"); - } - - public String getSha1() { - if (this.downloads == null) { - return ""; - } else if (this.downloads.getAsJsonObject("artifact") == null) { - return ""; - } else if (this.downloads.getAsJsonObject("artifact").get("sha1") == null) { - return ""; - } else { - return this.downloads.getAsJsonObject("artifact").get("sha1").getAsString(); - } - } - - public String getClassifier() { - if (natives == null) { - return ""; - } else { - JsonElement element = natives.get(OperatingSystem.getOS().replace("${arch}", OperatingSystem.getArch())); - - if (element == null) { - return ""; - } - - return "-" + element.getAsString().replace("\"", "").replace("${arch}", OperatingSystem.getArch()); - } - } - - public boolean isNative() { - return getClassifier().contains("natives"); - } - - public boolean allowed() { - if (this.rules == null || this.rules.length <= 0) { - return true; - } - - boolean success = false; - - for (Rule rule : this.rules) { - if (rule.os != null && rule.os.name != null) { - if (rule.os.name.equalsIgnoreCase(OperatingSystem.getOS())) { - return rule.action.equalsIgnoreCase("allow"); - } - } else { - success = rule.action.equalsIgnoreCase("allow"); - } - } - - return success; - } - - public String getArtifactName() { - if (artifact == null) { - artifact = new Artifact(name); - } - - if (natives != null) { - JsonElement jsonElement = natives.get(OperatingSystem.getOS()); - - if (jsonElement != null) { - return artifact.getArtifact(jsonElement.getAsString()); - } - } - - return artifact.getArtifact(artifact.classifier); - } - - private class Artifact { - private final String domain, name, version, classifier, ext; - - Artifact(String name) { - String[] splitedArtifact = name.split(":"); - int idx = splitedArtifact[splitedArtifact.length - 1].indexOf('@'); - - if (idx != -1) { - ext = splitedArtifact[splitedArtifact.length - 1].substring(idx + 1); - splitedArtifact[splitedArtifact.length - 1] = splitedArtifact[splitedArtifact.length - 1].substring(0, idx); - } else { - ext = "jar"; - } - - this.domain = splitedArtifact[0]; - this.name = splitedArtifact[1]; - this.version = splitedArtifact[2]; - this.classifier = splitedArtifact.length > 3 ? splitedArtifact[3] : null; - } - - public String getArtifact(String classifier) { - String ret = domain + ":" + name + ":" + version; - - if (classifier != null && classifier.indexOf('$') > -1) { - classifier = classifier.replace("${arch}", Constants.SYSTEM_ARCH); - } - - if (classifier != null) { - ret += ":" + classifier; - } - - if (!"jar".equals(ext)) { - ret += "@" + ext; - } - - return ret; - } - - public String getClassifier() { - return classifier; - } - } - } - - private class Rule { - public String action; - public OS os; - - private class OS { - String name; - } - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionMeta.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionMeta.java new file mode 100644 index 00000000..f6676283 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftVersionMeta.java @@ -0,0 +1,277 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.File; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import com.google.gson.JsonObject; + +import net.fabricmc.loom.util.OperatingSystem; + +@SuppressWarnings("unused") +public final class MinecraftVersionMeta { + private JsonObject arguments; + private AssetIndex assetIndex; + private String assets; + private int complianceLevel; + private Map<String, Download> downloads; + private String id; + private List<Library> libraries; + private JsonObject logging; + private String mainClass; + private int minimumLauncherVersion; + private String releaseTime; + private String time; + private String type; + + public Download getDownload(String key) { + return getDownloads().get(key); + } + + public JsonObject getArguments() { + return arguments; + } + + public AssetIndex getAssetIndex() { + return assetIndex; + } + + public String getAssets() { + return assets; + } + + public int getComplianceLevel() { + return complianceLevel; + } + + public Map<String, Download> getDownloads() { + return downloads; + } + + public String getId() { + return id; + } + + public List<Library> getLibraries() { + return libraries; + } + + public JsonObject getLogging() { + return logging; + } + + public String getMainClass() { + return mainClass; + } + + public int getMinimumLauncherVersion() { + return minimumLauncherVersion; + } + + public String getReleaseTime() { + return releaseTime; + } + + public String getTime() { + return time; + } + + public String getType() { + return type; + } + + public final class AssetIndex extends Downloadable { + private String id; + private long totalSize; + + public String getFabricId(String version) { + return id.equals(version) ? version : version + "-" + id; + } + + public String getId() { + return id; + } + + public long getTotalSize() { + return totalSize; + } + } + + public final class Download extends Downloadable { + } + + public final class Library { + private Downloads downloads; + private String name; + private Map<String, String> natives; + private List<Rule> rules; + + public boolean isValidForOS() { + if (rules == null || rules.isEmpty()) { + return true; + } + + for (Rule rule : rules) { + if (rule.appliesToOS() && !rule.isAllowed()) { + return false; + } + } + + return true; + } + + public boolean hasNatives() { + return this.natives != null; + } + + public boolean hasNativesForOS() { + if (!hasNatives()) { + return false; + } + + if (natives.get(OperatingSystem.getOS()) == null) { + return false; + } + + return isValidForOS(); + } + + public Classifier getClassifierForOS() { + return getDownloads().getClassifier(natives.get(OperatingSystem.getOS())); + } + + public Downloads getDownloads() { + return downloads; + } + + public Artifact getArtifact() { + if (getDownloads() == null) { + return null; + } + + return getDownloads().getArtifact(); + } + + public String getName() { + return name; + } + + public Map<String, String> getNatives() { + return natives; + } + + public List<Rule> getRules() { + return rules; + } + } + + public final class Downloads { + private Artifact artifact; + private Map<String, Classifier> classifiers; + + public Classifier getClassifier(String os) { + return classifiers.get(os); + } + + public Artifact getArtifact() { + return artifact; + } + + public Map<String, Classifier> getClassifiers() { + return classifiers; + } + } + + public final class Artifact extends Downloadable { + } + + public final class Classifier extends Downloadable { + } + + public final class Rule { + private String action; + private OS os; + + public boolean appliesToOS() { + return getOS() == null || getOS().isValidForOS(); + } + + public boolean isAllowed() { + return getAction().equals("allow"); + } + + public String getAction() { + return action; + } + + public OS getOS() { + return os; + } + } + + public final class OS { + private String name; + + public boolean isValidForOS() { + return getName() == null || getName().equalsIgnoreCase(OperatingSystem.getOS()); + } + + public String getName() { + return name; + } + } + + // A base class for everything that can be downloaded + public abstract class Downloadable { + private String path; + private String sha1; + private long size; + private String url; + + public File getRelativeFile(File baseDirectory) { + Objects.requireNonNull(getPath(), "Cannot get relative file from a null path"); + return new File(baseDirectory, getPath()); + } + + public String getPath() { + return path; + } + + public String getSha1() { + return sha1; + } + + public long getSize() { + return size; + } + + public String getUrl() { + return url; + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java index cdf0c618..e185d06d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java @@ -26,20 +26,14 @@ package net.fabricmc.loom.configuration.providers.minecraft.assets; import java.io.File; import java.io.FileReader; -import java.io.FileWriter; import java.io.IOException; import java.net.URL; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import com.google.common.base.Stopwatch; -import com.google.common.hash.Hashing; -import com.google.common.io.Files; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; import me.tongfei.progressbar.DelegatingProgressBarConsumer; import me.tongfei.progressbar.ProgressBar; import me.tongfei.progressbar.ProgressBarBuilder; @@ -50,18 +44,17 @@ import org.gradle.api.Project; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.providers.MinecraftProvider; -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo; -import net.fabricmc.loom.util.Checksum; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; import net.fabricmc.loom.util.Constants; -import net.fabricmc.loom.util.DownloadUtil; +import net.fabricmc.loom.util.HashedDownloadUtil; public class MinecraftAssetsProvider { public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); boolean offline = project.getGradle().getStartParameter().isOffline(); - MinecraftVersionInfo versionInfo = minecraftProvider.getVersionInfo(); - MinecraftVersionInfo.AssetIndex assetIndex = versionInfo.assetIndex; + MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); + MinecraftVersionMeta.AssetIndex assetIndex = versionInfo.getAssetIndex(); // get existing cache files File assets = new File(extension.getUserCache(), "assets"); @@ -71,32 +64,19 @@ public class MinecraftAssetsProvider { } File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.getMinecraftVersion()) + ".json"); - File checksumInfo = new File(assets, "checksum" + File.separator + minecraftProvider.getMinecraftVersion() + ".json"); - if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) { - project.getLogger().lifecycle(":downloading asset index"); + project.getLogger().info(":downloading asset index"); - if (offline) { - if (assetsInfo.exists()) { - //We know it's outdated but can't do anything about it, oh well - project.getLogger().warn("Asset index outdated"); - } else { - //We don't know what assets we need, just that we don't have any - throw new GradleException("Asset index not found at " + assetsInfo.getAbsolutePath()); - } + if (offline) { + if (assetsInfo.exists()) { + //We know it's outdated but can't do anything about it, oh well + project.getLogger().warn("Asset index outdated"); } else { - DownloadUtil.downloadIfChanged(new URL(assetIndex.url), assetsInfo, project.getLogger()); - } - } - - Gson gson = new Gson(); - Map<String, String> checksumInfos = new ConcurrentHashMap<>(); - - if (checksumInfo.exists()) { - try (FileReader reader = new FileReader(checksumInfo)) { - checksumInfos.putAll(gson.fromJson(reader, new TypeToken<Map<String, String>>() { - }.getType())); + //We don't know what assets we need, just that we don't have any + throw new GradleException("Asset index not found at " + assetsInfo.getAbsolutePath()); } + } else { + HashedDownloadUtil.downloadIfInvalid(new URL(assetIndex.getUrl()), assetsInfo, assetIndex.getSha1(), project.getLogger(), false); } ExecutorService executor = Executors.newFixedThreadPool(Math.min(16, Math.max(Runtime.getRuntime().availableProcessors() * 2, 1))); @@ -105,7 +85,7 @@ public class MinecraftAssetsProvider { AssetIndex index; try (FileReader fileReader = new FileReader(assetsInfo)) { - index = gson.fromJson(fileReader, AssetIndex.class); + index = LoomGradlePlugin.GSON.fromJson(fileReader, AssetIndex.class); } Stopwatch stopwatch = Stopwatch.createStarted(); @@ -121,77 +101,59 @@ public class MinecraftAssetsProvider { String filename = "objects" + File.separator + sha1.substring(0, 2) + File.separator + sha1; File file = new File(assets, filename); - String localFileChecksum = !file.exists() ? null : checksumInfos.computeIfAbsent(entry.getKey(), path -> { - try { - return Files.asByteSource(file).hash(Hashing.sha1()).toString(); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - }); - - if (LoomGradlePlugin.refreshDeps || localFileChecksum == null || !localFileChecksum.equals(sha1)) { - if (offline) { - if (file.exists()) { - project.getLogger().warn("Outdated asset " + entry.getKey()); - } else { - throw new GradleException("Asset " + entry.getKey() + " not found at " + file.getAbsolutePath()); - } + + if (offline) { + if (file.exists()) { + project.getLogger().warn("Outdated asset " + entry.getKey()); } else { - toDownload++; - - if (progressBar[0] == null) { - progressBar[0] = new ProgressBarBuilder() - .setConsumer(new DelegatingProgressBarConsumer(project.getLogger()::lifecycle)) - .setInitialMax(toDownload) - .setUpdateIntervalMillis(2000) - .setTaskName(":downloading assets") - .setStyle(ProgressBarStyle.ASCII) - .showSpeed() - .build(); - } + throw new GradleException("Asset " + entry.getKey() + " not found at " + file.getAbsolutePath()); + } + } else { + toDownload++; + + if (progressBar[0] == null) { + progressBar[0] = new ProgressBarBuilder() + .setConsumer(new DelegatingProgressBarConsumer(project.getLogger()::lifecycle)) + .setInitialMax(toDownload) + .setUpdateIntervalMillis(2000) + .setTaskName(":downloading assets") + .setStyle(ProgressBarStyle.ASCII) + .showSpeed() + .build(); + } - progressBar[0].maxHint(toDownload); + progressBar[0].maxHint(toDownload); - executor.execute(() -> { - String assetName = entry.getKey(); - int end = assetName.lastIndexOf("/") + 1; + executor.execute(() -> { + String assetName = entry.getKey(); + int end = assetName.lastIndexOf("/") + 1; - if (end > 0) { - assetName = assetName.substring(end); - } + if (end > 0) { + assetName = assetName.substring(end); + } - project.getLogger().debug(":downloading asset " + assetName); + project.getLogger().debug(":downloading asset " + assetName); - try { - DownloadUtil.downloadIfChanged(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, project.getLogger(), true); - } catch (IOException e) { - throw new RuntimeException("Failed to download: " + assetName, e); - } + try { + HashedDownloadUtil.downloadIfInvalid(new URL(Constants.RESOURCES_BASE + sha1.substring(0, 2) + "/" + sha1), file, sha1, project.getLogger(), true); + } catch (IOException e) { + throw new RuntimeException("Failed to download: " + assetName, e); + } - if (localFileChecksum == null) { - checksumInfos.put(entry.getKey(), sha1); - } + //Give this logger back + if (localFileChecksum == null) { + checksumInfos.put(entry.getKey(), sha1); + } - synchronized (progressBar[0]) { - progressBar[0].step(); - } - }); - } + synchronized (progressBar[0]) { + progressBar[0].step(); + } + }); } } project.getLogger().info("Took " + stopwatch.stop() + " to iterate " + parent.size() + " asset index."); - if (toDownload > 0) { - project.getLogger().lifecycle(":downloading " + toDownload + " asset" + (toDownload == 1 ? "" : "s") + "..."); - } - - checksumInfo.getParentFile().mkdirs(); - - try (FileWriter writer = new FileWriter(checksumInfo)) { - gson.toJson(checksumInfos, writer); - } //Wait for the assets to all download executor.shutdown(); |
