diff options
| author | shedaniel <daniel@shedaniel.me> | 2021-02-14 15:42:50 +0800 | 
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2021-02-14 15:42:50 +0800 | 
| commit | 021773f263261673fbbe5d4be49b5b98ca64b4ca (patch) | |
| tree | e799d6028b0aea37ad42af2f35f768f805aaaf3e /src/main/java/net/fabricmc/loom/configuration/providers | |
| parent | 17d60503f15214e80b278d4e0ff89453d836e0bb (diff) | |
| parent | 2070aeb94aec2823e0941b71c9019424494cf792 (diff) | |
| download | architectury-loom-021773f263261673fbbe5d4be49b5b98ca64b4ca.tar.gz architectury-loom-021773f263261673fbbe5d4be49b5b98ca64b4ca.tar.bz2 architectury-loom-021773f263261673fbbe5d4be49b5b98ca64b4ca.zip | |
Merge remote-tracking branch 'FabricMC/dev/0.6' into dev/0.6-forge
# Conflicts:
#	build.gradle
#	src/main/java/net/fabricmc/loom/LoomGradleExtension.java
#	src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
#	src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java
#	src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java
#	src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftNativesProvider.java
#	src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java
#	src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java
#	src/main/java/net/fabricmc/loom/util/SourceRemapper.java
Diffstat (limited to 'src/main/java/net/fabricmc/loom/configuration/providers')
9 files changed, 448 insertions, 344 deletions
| 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(); | 
