Basic layered mappings with @ParchmentMC support (#413)
This commit is contained in:
		
							parent
							
								
									e179cccf64
								
							
						
					
					
						commit
						1f9f48052b
					
				
					 47 changed files with 2435 additions and 925 deletions
				
			
		|  | @ -45,6 +45,7 @@ configurations { | |||
| 	} | ||||
| 	compileClasspath.extendsFrom bootstrap | ||||
| 	runtimeClasspath.extendsFrom bootstrap | ||||
| 	testRuntimeClasspath.extendsFrom bootstrap | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
|  | @ -74,6 +75,7 @@ dependencies { | |||
| 	implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17') | ||||
| 
 | ||||
| 	implementation 'net.fabricmc:access-widener:1.0.0' | ||||
| 	implementation 'net.fabricmc:mapping-io:0.1.3' | ||||
| 
 | ||||
| 	implementation ('net.fabricmc:lorenz-tiny:3.0.0') { | ||||
| 		transitive = false | ||||
|  | @ -92,7 +94,7 @@ dependencies { | |||
| 
 | ||||
| 	// Testing | ||||
| 	testImplementation(gradleTestKit()) | ||||
| 	testImplementation('org.spockframework:spock-core:2.0-M5-groovy-3.0') { | ||||
| 	testImplementation('org.spockframework:spock-core:2.0-groovy-3.0') { | ||||
| 		exclude module: 'groovy-all' | ||||
| 	} | ||||
| 	testImplementation 'io.javalin:javalin:3.13.7' | ||||
|  |  | |||
|  | @ -52,10 +52,13 @@ import net.fabricmc.loom.configuration.LoomProjectData; | |||
| import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||
| import net.fabricmc.loom.configuration.processors.JarProcessor; | ||||
| import net.fabricmc.loom.configuration.processors.JarProcessorManager; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| 
 | ||||
| public class LoomGradleExtension { | ||||
| 	public String refmapName; | ||||
|  | @ -114,7 +117,14 @@ public class LoomGradleExtension { | |||
| 	} | ||||
| 
 | ||||
| 	public Dependency officialMojangMappings() { | ||||
| 		return new MojangMappingsDependency(project, this); | ||||
| 		return layered(LayeredMappingSpecBuilder::officalMojangMappings); | ||||
| 	} | ||||
| 
 | ||||
| 	public Dependency layered(Action<LayeredMappingSpecBuilder> action) { | ||||
| 		LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(); | ||||
| 		action.execute(builder); | ||||
| 		LayeredMappingSpec builtSpec = builder.build(); | ||||
| 		return new LayeredMappingsDependency(new GradleMappingContext(project, "layers_" + builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion()); | ||||
| 	} | ||||
| 
 | ||||
| 	public LoomGradleExtension(Project project) { | ||||
|  | @ -246,7 +256,7 @@ public class LoomGradleExtension { | |||
| 			return new File((String) project.property("fabric.loom.natives.dir")); | ||||
| 		} | ||||
| 
 | ||||
| 		File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().getMinecraftVersion()); | ||||
| 		File natives = new File(getUserCache(), "natives/" + getMinecraftProvider().minecraftVersion()); | ||||
| 
 | ||||
| 		if (!natives.exists()) { | ||||
| 			natives.mkdirs(); | ||||
|  | @ -271,16 +281,16 @@ public class LoomGradleExtension { | |||
| 		return dependencyManager; | ||||
| 	} | ||||
| 
 | ||||
| 	public MinecraftProvider getMinecraftProvider() { | ||||
| 		return getDependencyManager().getProvider(MinecraftProvider.class); | ||||
| 	public MinecraftProviderImpl getMinecraftProvider() { | ||||
| 		return getDependencyManager().getProvider(MinecraftProviderImpl.class); | ||||
| 	} | ||||
| 
 | ||||
| 	public MinecraftMappedProvider getMinecraftMappedProvider() { | ||||
| 		return getMappingsProvider().mappedProvider; | ||||
| 	} | ||||
| 
 | ||||
| 	public MappingsProvider getMappingsProvider() { | ||||
| 		return getDependencyManager().getProvider(MappingsProvider.class); | ||||
| 	public MappingsProviderImpl getMappingsProvider() { | ||||
| 		return getDependencyManager().getProvider(MappingsProviderImpl.class); | ||||
| 	} | ||||
| 
 | ||||
| 	public void setDependencyManager(LoomDependencyManager dependencyManager) { | ||||
|  | @ -342,7 +352,7 @@ public class LoomGradleExtension { | |||
| 	// Creates a new file each time its called, this is then held onto later when remapping the output jar | ||||
| 	// Required as now when using parallel builds the old single file could be written by another sourceset compile task | ||||
| 	public synchronized File getNextMixinMappings() { | ||||
| 		File mixinMapping = new File(getProjectBuildCache(), "mixin-map-" + getMinecraftProvider().getMinecraftVersion() + "-" + getMappingsProvider().mappingsVersion + "." + mixinMappings.size() + ".tiny"); | ||||
| 		File mixinMapping = new File(getProjectBuildCache(), "mixin-map-" + getMinecraftProvider().minecraftVersion() + "-" + getMappingsProvider().mappingsVersion + "." + mixinMappings.size() + ".tiny"); | ||||
| 		mixinMappings.add(mixinMapping); | ||||
| 		return mixinMapping; | ||||
| 	} | ||||
|  |  | |||
|  | @ -39,8 +39,8 @@ import net.fabricmc.loom.build.mixin.KaptApInvoker; | |||
| import net.fabricmc.loom.build.mixin.ScalaApInvoker; | ||||
| import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs; | ||||
| import net.fabricmc.loom.configuration.providers.LaunchProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| 
 | ||||
| public final class CompileConfiguration { | ||||
|  | @ -116,8 +116,8 @@ public final class CompileConfiguration { | |||
| 			LoomDependencyManager dependencyManager = new LoomDependencyManager(); | ||||
| 			extension.setDependencyManager(dependencyManager); | ||||
| 
 | ||||
| 			dependencyManager.addProvider(new MinecraftProvider(project)); | ||||
| 			dependencyManager.addProvider(new MappingsProvider(project)); | ||||
| 			dependencyManager.addProvider(new MinecraftProviderImpl(project)); | ||||
| 			dependencyManager.addProvider(new MappingsProviderImpl(project)); | ||||
| 			dependencyManager.addProvider(new LaunchProvider(project)); | ||||
| 
 | ||||
| 			dependencyManager.handleDependencies(project); | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ import net.fabricmc.loom.LoomGradleExtension; | |||
| import net.fabricmc.loom.build.ModCompileRemapper; | ||||
| import net.fabricmc.loom.configuration.DependencyProvider.DependencyInfo; | ||||
| import net.fabricmc.loom.configuration.mods.ModProcessor; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.SourceRemapper; | ||||
| import net.fabricmc.loom.LoomRepositoryPlugin; | ||||
|  | @ -86,7 +86,7 @@ public class LoomDependencyManager { | |||
| 	public void handleDependencies(Project project) { | ||||
| 		List<Runnable> afterTasks = new ArrayList<>(); | ||||
| 
 | ||||
| 		MappingsProvider mappingsProvider = null; | ||||
| 		MappingsProviderImpl mappingsProvider = null; | ||||
| 
 | ||||
| 		project.getLogger().info(":setting up loom dependencies"); | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
|  | @ -100,8 +100,8 @@ public class LoomDependencyManager { | |||
| 				return list; | ||||
| 			}).providers.add(provider); | ||||
| 
 | ||||
| 			if (provider instanceof MappingsProvider) { | ||||
| 				mappingsProvider = (MappingsProvider) provider; | ||||
| 			if (provider instanceof MappingsProviderImpl) { | ||||
| 				mappingsProvider = (MappingsProviderImpl) provider; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ import net.fabricmc.loom.LoomGradleExtension; | |||
| import net.fabricmc.loom.LoomGradlePlugin; | ||||
| import net.fabricmc.loom.configuration.RemappedConfigurationEntry; | ||||
| import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | ||||
|  | @ -132,7 +132,7 @@ public class ModProcessor { | |||
| 		String toM = "named"; | ||||
| 
 | ||||
| 		MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider(); | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
| 		Path mc = mappedProvider.getIntermediaryJar().toPath(); | ||||
| 		Path[] mcDeps = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles() | ||||
|  |  | |||
|  | @ -31,8 +31,8 @@ import java.util.function.Consumer; | |||
| import org.apache.commons.io.FileUtils; | ||||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| 
 | ||||
|  | @ -84,7 +84,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider { | |||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void initFiles(MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { | ||||
| 	public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) { | ||||
| 		super.initFiles(minecraftProvider, mappingsProvider); | ||||
| 
 | ||||
| 		projectMappedJar = new File(getJarDirectory(getExtension().getRootProjectPersistentCache(), projectMappedClassifier), "minecraft-" + getJarVersionString(projectMappedClassifier) + ".jar"); | ||||
|  |  | |||
|  | @ -65,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().fabricId(getExtension().getMinecraftProvider().getMinecraftVersion())) | ||||
| 				.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion())) | ||||
| 				.argument("client", "--assetsDir") | ||||
| 				.argument("client", new File(getExtension().getUserCache(), "assets").getAbsolutePath()); | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,224 +24,10 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.configuration.providers; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.Optional; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import com.google.common.io.Files; | ||||
| import org.gradle.api.GradleException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| 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.MinecraftVersionMeta; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.loom.util.HashedDownloadUtil; | ||||
| import net.fabricmc.stitch.merge.JarMerger; | ||||
| 
 | ||||
| public class MinecraftProvider extends DependencyProvider { | ||||
| 	private String minecraftVersion; | ||||
| public interface MinecraftProvider { | ||||
| 	String minecraftVersion(); | ||||
| 
 | ||||
| 	private MinecraftVersionMeta versionInfo; | ||||
| 	private MinecraftLibraryProvider libraryProvider; | ||||
| 
 | ||||
| 	private File minecraftJson; | ||||
| 	private File minecraftClientJar; | ||||
| 	private File minecraftServerJar; | ||||
| 	private File minecraftMergedJar; | ||||
| 	private File versionManifestJson; | ||||
| 
 | ||||
| 	public MinecraftProvider(Project project) { | ||||
| 		super(project); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||
| 		minecraftVersion = dependency.getDependency().getVersion(); | ||||
| 
 | ||||
| 		boolean offline = getProject().getGradle().getStartParameter().isOffline(); | ||||
| 
 | ||||
| 		initFiles(); | ||||
| 
 | ||||
| 		downloadMcJson(offline); | ||||
| 
 | ||||
| 		try (FileReader reader = new FileReader(minecraftJson)) { | ||||
| 			versionInfo = LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, MinecraftVersionMeta.class); | ||||
| 		} | ||||
| 
 | ||||
| 		// Add Loom as an annotation processor | ||||
| 		addDependency(getProject().files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), "compileOnly"); | ||||
| 
 | ||||
| 		if (offline) { | ||||
| 			if (minecraftClientJar.exists() && minecraftServerJar.exists()) { | ||||
| 				getProject().getLogger().debug("Found client and server jars, presuming up-to-date"); | ||||
| 			} else if (minecraftMergedJar.exists()) { | ||||
| 				//Strictly we don't need the split jars if the merged one exists, let's try go on | ||||
| 				getProject().getLogger().warn("Missing game jar but merged jar present, things might end badly"); | ||||
| 			} else { | ||||
| 				throw new GradleException("Missing jar(s); Client: " + minecraftClientJar.exists() + ", Server: " + minecraftServerJar.exists()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			downloadJars(getProject().getLogger()); | ||||
| 		} | ||||
| 
 | ||||
| 		libraryProvider = new MinecraftLibraryProvider(); | ||||
| 		libraryProvider.provide(this, getProject()); | ||||
| 
 | ||||
| 		if (!minecraftMergedJar.exists() || isRefreshDeps()) { | ||||
| 			try { | ||||
| 				mergeJars(getProject().getLogger()); | ||||
| 			} catch (Throwable e) { | ||||
| 				HashedDownloadUtil.delete(minecraftClientJar); | ||||
| 				HashedDownloadUtil.delete(minecraftServerJar); | ||||
| 				minecraftMergedJar.delete(); | ||||
| 
 | ||||
| 				getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e); | ||||
| 				throw e; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void initFiles() { | ||||
| 		minecraftJson = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-info.json"); | ||||
| 		minecraftClientJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-client.jar"); | ||||
| 		minecraftServerJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-server.jar"); | ||||
| 		minecraftMergedJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); | ||||
| 		versionManifestJson = new File(getExtension().getUserCache(), "version_manifest.json"); | ||||
| 	} | ||||
| 
 | ||||
| 	private void downloadMcJson(boolean offline) throws IOException { | ||||
| 		if (getExtension().isShareCaches() && !getExtension().isRootProject() && versionManifestJson.exists() && !isRefreshDeps()) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!offline && !isRefreshDeps() && hasRecentValidManifest()) { | ||||
| 			// We have a recent valid manifest file, so do nothing | ||||
| 		} else if (offline) { | ||||
| 			if (versionManifestJson.exists()) { | ||||
| 				// If there is the manifests already we'll presume that's good enough | ||||
| 				getProject().getLogger().debug("Found version manifests, presuming up-to-date"); | ||||
| 			} else { | ||||
| 				// If we don't have the manifests then there's nothing more we can do | ||||
| 				throw new GradleException("Version manifests not found at " + versionManifestJson.getAbsolutePath()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			getProject().getLogger().debug("Downloading version manifests"); | ||||
| 			DownloadUtil.downloadIfChanged(new URL(Constants.VERSION_MANIFESTS), versionManifestJson, getProject().getLogger()); | ||||
| 		} | ||||
| 
 | ||||
| 		String versionManifest = Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read(); | ||||
| 		ManifestVersion mcManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(versionManifest, ManifestVersion.class); | ||||
| 
 | ||||
| 		Optional<ManifestVersion.Versions> optionalVersion = Optional.empty(); | ||||
| 
 | ||||
| 		if (getExtension().customManifest != null) { | ||||
| 			ManifestVersion.Versions customVersion = new ManifestVersion.Versions(); | ||||
| 			customVersion.id = minecraftVersion; | ||||
| 			customVersion.url = getExtension().customManifest; | ||||
| 			optionalVersion = Optional.of(customVersion); | ||||
| 			getProject().getLogger().lifecycle("Using custom minecraft manifest"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!optionalVersion.isPresent()) { | ||||
| 			optionalVersion = mcManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (optionalVersion.isPresent()) { | ||||
| 			if (offline) { | ||||
| 				if (minecraftJson.exists()) { | ||||
| 					//If there is the manifest already we'll presume that's good enough | ||||
| 					getProject().getLogger().debug("Found Minecraft {} manifest, presuming up-to-date", minecraftVersion); | ||||
| 				} else { | ||||
| 					//If we don't have the manifests then there's nothing more we can do | ||||
| 					throw new GradleException("Minecraft " + minecraftVersion + " manifest not found at " + minecraftJson.getAbsolutePath()); | ||||
| 				} | ||||
| 			} else { | ||||
| 				getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion); | ||||
| 
 | ||||
| 				ManifestVersion.Versions version = optionalVersion.get(); | ||||
| 				String url = version.url; | ||||
| 
 | ||||
| 				if (version.sha1 != null) { | ||||
| 					HashedDownloadUtil.downloadIfInvalid(new URL(url), minecraftJson, version.sha1, getProject().getLogger(), true); | ||||
| 				} else { | ||||
| 					// Use the etag if no hash found from url | ||||
| 					DownloadUtil.downloadIfChanged(new URL(url), minecraftJson, getProject().getLogger()); | ||||
| 				} | ||||
| 			} | ||||
| 		} else { | ||||
| 			throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean hasRecentValidManifest() throws IOException { | ||||
| 		if (getExtension().customManifest != null) { | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!versionManifestJson.exists() || !minecraftJson.exists()) { | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		if (versionManifestJson.lastModified() > System.currentTimeMillis() - 24 * 3_600_000) { | ||||
| 			// Version manifest hasn't been modified in 24 hours, time to get a new one. | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		ManifestVersion manifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read(), ManifestVersion.class); | ||||
| 		Optional<ManifestVersion.Versions> version = manifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); | ||||
| 
 | ||||
| 		// fail if the expected mc version was not found, will download the file again. | ||||
| 		return version.isPresent(); | ||||
| 	} | ||||
| 
 | ||||
| 	private void downloadJars(Logger logger) throws IOException { | ||||
| 		if (getExtension().isShareCaches() && !getExtension().isRootProject() && minecraftClientJar.exists() && minecraftServerJar.exists() && !isRefreshDeps()) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		MinecraftVersionMeta.Download client = versionInfo.download("client"); | ||||
| 		MinecraftVersionMeta.Download server = versionInfo.download("server"); | ||||
| 
 | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(client.url()), minecraftClientJar, client.sha1(), logger, false); | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(server.url()), minecraftServerJar, server.sha1(), logger, false); | ||||
| 	} | ||||
| 
 | ||||
| 	private void mergeJars(Logger logger) throws IOException { | ||||
| 		logger.info(":merging jars"); | ||||
| 
 | ||||
| 		try (JarMerger jarMerger = new JarMerger(minecraftClientJar, minecraftServerJar, minecraftMergedJar)) { | ||||
| 			jarMerger.enableSyntheticParamsOffset(); | ||||
| 			jarMerger.merge(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public File getMergedJar() { | ||||
| 		return minecraftMergedJar; | ||||
| 	} | ||||
| 
 | ||||
| 	public String getMinecraftVersion() { | ||||
| 		return minecraftVersion; | ||||
| 	} | ||||
| 
 | ||||
| 	public MinecraftVersionMeta getVersionInfo() { | ||||
| 		return versionInfo; | ||||
| 	} | ||||
| 
 | ||||
| 	public MinecraftLibraryProvider getLibraryProvider() { | ||||
| 		return libraryProvider; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getTargetConfig() { | ||||
| 		return Constants.Configurations.MINECRAFT; | ||||
| 	} | ||||
| 	MinecraftVersionMeta getVersionInfo(); | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,249 @@ | |||
| /* | ||||
|  * 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; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.Optional; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import com.google.common.io.Files; | ||||
| import org.gradle.api.GradleException; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| 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.MinecraftVersionMeta; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.loom.util.HashedDownloadUtil; | ||||
| import net.fabricmc.stitch.merge.JarMerger; | ||||
| 
 | ||||
| public class MinecraftProviderImpl extends DependencyProvider implements MinecraftProvider { | ||||
| 	private String minecraftVersion; | ||||
| 
 | ||||
| 	private MinecraftVersionMeta versionInfo; | ||||
| 	private MinecraftLibraryProvider libraryProvider; | ||||
| 
 | ||||
| 	private File minecraftJson; | ||||
| 	private File minecraftClientJar; | ||||
| 	private File minecraftServerJar; | ||||
| 	private File minecraftMergedJar; | ||||
| 	private File versionManifestJson; | ||||
| 
 | ||||
| 	public MinecraftProviderImpl(Project project) { | ||||
| 		super(project); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||
| 		minecraftVersion = dependency.getDependency().getVersion(); | ||||
| 
 | ||||
| 		boolean offline = getProject().getGradle().getStartParameter().isOffline(); | ||||
| 
 | ||||
| 		initFiles(); | ||||
| 
 | ||||
| 		downloadMcJson(offline); | ||||
| 
 | ||||
| 		try (FileReader reader = new FileReader(minecraftJson)) { | ||||
| 			versionInfo = LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, MinecraftVersionMeta.class); | ||||
| 		} | ||||
| 
 | ||||
| 		// Add Loom as an annotation processor | ||||
| 		addDependency(getProject().files(this.getClass().getProtectionDomain().getCodeSource().getLocation()), "compileOnly"); | ||||
| 
 | ||||
| 		if (offline) { | ||||
| 			if (minecraftClientJar.exists() && minecraftServerJar.exists()) { | ||||
| 				getProject().getLogger().debug("Found client and server jars, presuming up-to-date"); | ||||
| 			} else if (minecraftMergedJar.exists()) { | ||||
| 				//Strictly we don't need the split jars if the merged one exists, let's try go on | ||||
| 				getProject().getLogger().warn("Missing game jar but merged jar present, things might end badly"); | ||||
| 			} else { | ||||
| 				throw new GradleException("Missing jar(s); Client: " + minecraftClientJar.exists() + ", Server: " + minecraftServerJar.exists()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			downloadJars(getProject().getLogger()); | ||||
| 		} | ||||
| 
 | ||||
| 		libraryProvider = new MinecraftLibraryProvider(); | ||||
| 		libraryProvider.provide(this, getProject()); | ||||
| 
 | ||||
| 		if (!minecraftMergedJar.exists() || isRefreshDeps()) { | ||||
| 			try { | ||||
| 				mergeJars(getProject().getLogger()); | ||||
| 			} catch (Throwable e) { | ||||
| 				HashedDownloadUtil.delete(minecraftClientJar); | ||||
| 				HashedDownloadUtil.delete(minecraftServerJar); | ||||
| 				minecraftMergedJar.delete(); | ||||
| 
 | ||||
| 				getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e); | ||||
| 				throw e; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void initFiles() { | ||||
| 		minecraftJson = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-info.json"); | ||||
| 		minecraftClientJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-client.jar"); | ||||
| 		minecraftServerJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-server.jar"); | ||||
| 		minecraftMergedJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); | ||||
| 		versionManifestJson = new File(getExtension().getUserCache(), "version_manifest.json"); | ||||
| 	} | ||||
| 
 | ||||
| 	private void downloadMcJson(boolean offline) throws IOException { | ||||
| 		if (getExtension().isShareCaches() && !getExtension().isRootProject() && versionManifestJson.exists() && !isRefreshDeps()) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!offline && !isRefreshDeps() && hasRecentValidManifest()) { | ||||
| 			// We have a recent valid manifest file, so do nothing | ||||
| 		} else if (offline) { | ||||
| 			if (versionManifestJson.exists()) { | ||||
| 				// If there is the manifests already we'll presume that's good enough | ||||
| 				getProject().getLogger().debug("Found version manifests, presuming up-to-date"); | ||||
| 			} else { | ||||
| 				// If we don't have the manifests then there's nothing more we can do | ||||
| 				throw new GradleException("Version manifests not found at " + versionManifestJson.getAbsolutePath()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			getProject().getLogger().debug("Downloading version manifests"); | ||||
| 			DownloadUtil.downloadIfChanged(new URL(Constants.VERSION_MANIFESTS), versionManifestJson, getProject().getLogger()); | ||||
| 		} | ||||
| 
 | ||||
| 		String versionManifest = Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read(); | ||||
| 		ManifestVersion mcManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(versionManifest, ManifestVersion.class); | ||||
| 
 | ||||
| 		Optional<ManifestVersion.Versions> optionalVersion = Optional.empty(); | ||||
| 
 | ||||
| 		if (getExtension().customManifest != null) { | ||||
| 			ManifestVersion.Versions customVersion = new ManifestVersion.Versions(); | ||||
| 			customVersion.id = minecraftVersion; | ||||
| 			customVersion.url = getExtension().customManifest; | ||||
| 			optionalVersion = Optional.of(customVersion); | ||||
| 			getProject().getLogger().lifecycle("Using custom minecraft manifest"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!optionalVersion.isPresent()) { | ||||
| 			optionalVersion = mcManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (optionalVersion.isPresent()) { | ||||
| 			if (offline) { | ||||
| 				if (minecraftJson.exists()) { | ||||
| 					//If there is the manifest already we'll presume that's good enough | ||||
| 					getProject().getLogger().debug("Found Minecraft {} manifest, presuming up-to-date", minecraftVersion); | ||||
| 				} else { | ||||
| 					//If we don't have the manifests then there's nothing more we can do | ||||
| 					throw new GradleException("Minecraft " + minecraftVersion + " manifest not found at " + minecraftJson.getAbsolutePath()); | ||||
| 				} | ||||
| 			} else { | ||||
| 				getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion); | ||||
| 
 | ||||
| 				ManifestVersion.Versions version = optionalVersion.get(); | ||||
| 				String url = version.url; | ||||
| 
 | ||||
| 				if (version.sha1 != null) { | ||||
| 					HashedDownloadUtil.downloadIfInvalid(new URL(url), minecraftJson, version.sha1, getProject().getLogger(), true); | ||||
| 				} else { | ||||
| 					// Use the etag if no hash found from url | ||||
| 					DownloadUtil.downloadIfChanged(new URL(url), minecraftJson, getProject().getLogger()); | ||||
| 				} | ||||
| 			} | ||||
| 		} else { | ||||
| 			throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean hasRecentValidManifest() throws IOException { | ||||
| 		if (getExtension().customManifest != null) { | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!versionManifestJson.exists() || !minecraftJson.exists()) { | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		if (versionManifestJson.lastModified() > System.currentTimeMillis() - 24 * 3_600_000) { | ||||
| 			// Version manifest hasn't been modified in 24 hours, time to get a new one. | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		ManifestVersion manifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(Files.asCharSource(versionManifestJson, StandardCharsets.UTF_8).read(), ManifestVersion.class); | ||||
| 		Optional<ManifestVersion.Versions> version = manifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); | ||||
| 
 | ||||
| 		// fail if the expected mc version was not found, will download the file again. | ||||
| 		return version.isPresent(); | ||||
| 	} | ||||
| 
 | ||||
| 	private void downloadJars(Logger logger) throws IOException { | ||||
| 		if (getExtension().isShareCaches() && !getExtension().isRootProject() && minecraftClientJar.exists() && minecraftServerJar.exists() && !isRefreshDeps()) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		MinecraftVersionMeta.Download client = versionInfo.download("client"); | ||||
| 		MinecraftVersionMeta.Download server = versionInfo.download("server"); | ||||
| 
 | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(client.url()), minecraftClientJar, client.sha1(), logger, false); | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(server.url()), minecraftServerJar, server.sha1(), logger, false); | ||||
| 	} | ||||
| 
 | ||||
| 	private void mergeJars(Logger logger) throws IOException { | ||||
| 		logger.info(":merging jars"); | ||||
| 
 | ||||
| 		try (JarMerger jarMerger = new JarMerger(minecraftClientJar, minecraftServerJar, minecraftMergedJar)) { | ||||
| 			jarMerger.enableSyntheticParamsOffset(); | ||||
| 			jarMerger.merge(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public File getMergedJar() { | ||||
| 		return minecraftMergedJar; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String minecraftVersion() { | ||||
| 		return minecraftVersion; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public MinecraftVersionMeta getVersionInfo() { | ||||
| 		return versionInfo; | ||||
| 	} | ||||
| 
 | ||||
| 	public MinecraftLibraryProvider getLibraryProvider() { | ||||
| 		return libraryProvider; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getTargetConfig() { | ||||
| 		return Constants.Configurations.MINECRAFT; | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,74 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.io.File; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Configuration; | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| 
 | ||||
| public class GradleMappingContext implements MappingContext { | ||||
| 	private final Project project; | ||||
| 	private final LoomGradleExtension extension; | ||||
| 	private final String workingDirName; | ||||
| 
 | ||||
| 	public GradleMappingContext(Project project, String workingDirName) { | ||||
| 		this.project = project; | ||||
| 		this.extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		this.workingDirName = workingDirName; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public File mavenFile(String mavenNotation) { | ||||
| 		Configuration configuration = project.getConfigurations().detachedConfiguration(project.getDependencies().create(mavenNotation)); | ||||
| 		return configuration.getSingleFile(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public MappingsProvider mappingsProvider() { | ||||
| 		return extension.getMappingsProvider(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public MinecraftProvider minecraftProvider() { | ||||
| 		return extension.getMinecraftProvider(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public File workingDirectory(String name) { | ||||
| 		File tempDir = new File(mappingsProvider().getMappingsDir().toFile(), workingDirName); | ||||
| 		tempDir.mkdirs(); | ||||
| 		return new File(tempDir, name); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Logger getLogger() { | ||||
| 		return project.getLogger(); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,34 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| public record LayeredMappingSpec(List<MappingsSpec<?>> layers) { | ||||
| 	public String getVersion() { | ||||
| 		// TODO something better? | ||||
| 		return "layered+hash.%d".formatted(Math.abs(hashCode())); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,65 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.gradle.api.Action; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpecBuilder; | ||||
| 
 | ||||
| public class LayeredMappingSpecBuilder { | ||||
| 	private final List<MappingsSpec<?>> layers = new LinkedList<>(); | ||||
| 
 | ||||
| 	public LayeredMappingSpecBuilder officalMojangMappings() { | ||||
| 		layers.add(new MojangMappingsSpec()); | ||||
| 		return this; | ||||
| 	} | ||||
| 
 | ||||
| 	public LayeredMappingSpecBuilder parchment(String mavenNotation) { | ||||
| 		parchment(mavenNotation, parchmentMappingsSpecBuilder -> parchmentMappingsSpecBuilder.setRemovePrefix(true)); | ||||
| 		return this; | ||||
| 	} | ||||
| 
 | ||||
| 	public LayeredMappingSpecBuilder parchment(String mavenNotation, Action<ParchmentMappingsSpecBuilder> action) { | ||||
| 		var builder = ParchmentMappingsSpecBuilder.builder(mavenNotation); | ||||
| 		action.execute(builder); | ||||
| 		layers.add(builder.build()); | ||||
| 		return this; | ||||
| 	} | ||||
| 
 | ||||
| 	public LayeredMappingSpec build() { | ||||
| 		List<MappingsSpec<?>> builtLayers = new LinkedList<>(); | ||||
| 		// Intermediary is always the base layer | ||||
| 		builtLayers.add(new IntermediaryMappingsSpec()); | ||||
| 		builtLayers.addAll(layers); | ||||
| 
 | ||||
| 		return new LayeredMappingSpec(Collections.unmodifiableList(builtLayers)); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,143 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.StringWriter; | ||||
| import java.io.Writer; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Collections; | ||||
| import java.util.Objects; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.SelfResolvingDependency; | ||||
| import org.gradle.api.tasks.TaskDependency; | ||||
| import org.zeroturnaround.zip.ByteSource; | ||||
| import org.zeroturnaround.zip.ZipEntrySource; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradlePlugin; | ||||
| import net.fabricmc.mappingio.adapter.MappingDstNsReorder; | ||||
| import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; | ||||
| import net.fabricmc.mappingio.format.Tiny2Writer; | ||||
| import net.fabricmc.mappingio.tree.MemoryMappingTree; | ||||
| 
 | ||||
| public class LayeredMappingsDependency implements SelfResolvingDependency { | ||||
| 	private static final String GROUP = "loom"; | ||||
| 	private static final String MODULE = "mappings"; | ||||
| 
 | ||||
| 	private final MappingContext mappingContext; | ||||
| 	private final LayeredMappingSpec layeredMappingSpec; | ||||
| 	private final String version; | ||||
| 
 | ||||
| 	public LayeredMappingsDependency(MappingContext mappingContext, LayeredMappingSpec layeredMappingSpec, String version) { | ||||
| 		this.mappingContext = mappingContext; | ||||
| 		this.layeredMappingSpec = layeredMappingSpec; | ||||
| 		this.version = version; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Set<File> resolve() { | ||||
| 		Path mappingsDir = mappingContext.mappingsProvider().getMappingsDir(); | ||||
| 		Path mappingsFile = mappingsDir.resolve(String.format("%s.%s-%s.tiny", GROUP, MODULE, getVersion())); | ||||
| 
 | ||||
| 		if (!Files.exists(mappingsFile) || LoomGradlePlugin.refreshDeps) { | ||||
| 			try { | ||||
| 				var processor = new LayeredMappingsProcessor(layeredMappingSpec); | ||||
| 				MemoryMappingTree mappings = processor.getMappings(mappingContext); | ||||
| 
 | ||||
| 				try (Writer writer = new StringWriter()) { | ||||
| 					Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false); | ||||
| 
 | ||||
| 					MappingDstNsReorder nsReorder = new MappingDstNsReorder(tiny2Writer, Collections.singletonList(MappingNamespace.NAMED.stringValue())); | ||||
| 					MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingNamespace.INTERMEDIARY.stringValue()); | ||||
| 					mappings.accept(nsSwitch); | ||||
| 
 | ||||
| 					Files.deleteIfExists(mappingsFile); | ||||
| 
 | ||||
| 					ZipUtil.pack(new ZipEntrySource[] { | ||||
| 							new ByteSource("mappings/mappings.tiny", writer.toString().getBytes(StandardCharsets.UTF_8)) | ||||
| 					}, mappingsFile.toFile()); | ||||
| 				} | ||||
| 			} catch (IOException e) { | ||||
| 				throw new RuntimeException("Failed to resolve Mojang mappings", e); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return Collections.singleton(mappingsFile.toFile()); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Set<File> resolve(boolean transitive) { | ||||
| 		return resolve(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public TaskDependency getBuildDependencies() { | ||||
| 		return task -> Collections.emptySet(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getGroup() { | ||||
| 		return GROUP; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getName() { | ||||
| 		return MODULE; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getVersion() { | ||||
| 		return version; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public boolean contentEquals(Dependency dependency) { | ||||
| 		if (dependency instanceof LayeredMappingsDependency layeredMappingsDependency) { | ||||
| 			return Objects.equals(layeredMappingsDependency.getVersion(), this.getVersion()); | ||||
| 		} | ||||
| 
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Dependency copy() { | ||||
| 		return new LayeredMappingsDependency(mappingContext, layeredMappingSpec, version); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getReason() { | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void because(String s) { | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,89 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; | ||||
| import net.fabricmc.mappingio.tree.MemoryMappingTree; | ||||
| 
 | ||||
| public class LayeredMappingsProcessor { | ||||
| 	private final LayeredMappingSpec layeredMappingSpec; | ||||
| 
 | ||||
| 	public LayeredMappingsProcessor(LayeredMappingSpec spec) { | ||||
| 		this.layeredMappingSpec = spec; | ||||
| 	} | ||||
| 
 | ||||
| 	public MemoryMappingTree getMappings(MappingContext context) throws IOException { | ||||
| 		MemoryMappingTree mappingTree = new MemoryMappingTree(); | ||||
| 
 | ||||
| 		List<Class<? extends MappingLayer>> visitedLayers = new ArrayList<>(); | ||||
| 
 | ||||
| 		for (MappingsSpec<?> spec : layeredMappingSpec.layers()) { | ||||
| 			MappingLayer layer = spec.createLayer(context); | ||||
| 
 | ||||
| 			for (Class<? extends MappingLayer> dependentLayer : layer.dependsOn()) { | ||||
| 				if (!visitedLayers.contains(dependentLayer)) { | ||||
| 					throw new RuntimeException("Layer %s depends on %s".formatted(layer.getClass().getName(), dependentLayer.getName())); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			visitedLayers.add(layer.getClass()); | ||||
| 
 | ||||
| 			// We have to rebuild a new tree to work on when a layer doesnt merge into layered | ||||
| 			boolean rebuild = layer.getSourceNamespace() != MappingNamespace.NAMED; | ||||
| 			MemoryMappingTree workingTree; | ||||
| 
 | ||||
| 			if (rebuild) { | ||||
| 				var tempTree = new MemoryMappingTree(); | ||||
| 
 | ||||
| 				// This can be null on the first layer | ||||
| 				if (mappingTree.getSrcNamespace() != null) { | ||||
| 					var sourceNsSwitch = new MappingSourceNsSwitch(tempTree, layer.getSourceNamespace().stringValue()); | ||||
| 					mappingTree.accept(sourceNsSwitch); | ||||
| 				} | ||||
| 
 | ||||
| 				workingTree = tempTree; | ||||
| 			} else { | ||||
| 				workingTree = mappingTree; | ||||
| 			} | ||||
| 
 | ||||
| 			try { | ||||
| 				layer.visit(workingTree); | ||||
| 			} catch (IOException e) { | ||||
| 				throw new IOException("Failed to visit: " + layer.getClass(), e); | ||||
| 			} | ||||
| 
 | ||||
| 			if (rebuild) { | ||||
| 				mappingTree = new MemoryMappingTree(); | ||||
| 				workingTree.accept(new MappingSourceNsSwitch(mappingTree, MappingNamespace.NAMED.stringValue())); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return mappingTree; | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,50 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.io.File; | ||||
| 
 | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| 
 | ||||
| public interface MappingContext { | ||||
| 	File mavenFile(String mavenNotation); | ||||
| 
 | ||||
| 	MappingsProvider mappingsProvider(); | ||||
| 
 | ||||
| 	MinecraftProvider minecraftProvider(); | ||||
| 
 | ||||
| 	default String minecraftVersion() { | ||||
| 		return minecraftProvider().minecraftVersion(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Creates a temporary working dir to be used to store working files. | ||||
| 	 */ | ||||
| 	File workingDirectory(String name); | ||||
| 
 | ||||
| 	Logger getLogger(); | ||||
| } | ||||
|  | @ -0,0 +1,43 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import net.fabricmc.mappingio.MappingVisitor; | ||||
| 
 | ||||
| public interface MappingLayer { | ||||
| 	void visit(MappingVisitor mappingVisitor) throws IOException; | ||||
| 
 | ||||
| 	default MappingNamespace getSourceNamespace() { | ||||
| 		return MappingNamespace.NAMED; | ||||
| 	} | ||||
| 
 | ||||
| 	default List<Class<? extends MappingLayer>> dependsOn() { | ||||
| 		return Collections.emptyList(); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,37 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.util.Locale; | ||||
| 
 | ||||
| public enum MappingNamespace { | ||||
| 	OFFICIAL, | ||||
| 	INTERMEDIARY, | ||||
| 	NAMED; | ||||
| 
 | ||||
| 	public String stringValue() { | ||||
| 		return name().toLowerCase(Locale.ROOT); | ||||
| 	} | ||||
| } | ||||
|  | @ -24,390 +24,11 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.configuration.providers.mappings; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.nio.file.FileSystem; | ||||
| import java.nio.file.FileSystems; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.nio.file.StandardCopyOption; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import com.google.common.base.Preconditions; | ||||
| import com.google.common.net.UrlEscapers; | ||||
| import com.google.gson.JsonObject; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.apache.tools.ant.util.StringUtils; | ||||
| import org.gradle.api.Project; | ||||
| import org.zeroturnaround.zip.FileSource; | ||||
| import org.zeroturnaround.zip.ZipEntrySource; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| public interface MappingsProvider { | ||||
| 	Path getMappingsDir(); | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.LoomGradlePlugin; | ||||
| import net.fabricmc.loom.configuration.DependencyProvider; | ||||
| import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; | ||||
| import net.fabricmc.loom.configuration.processors.JarProcessorManager; | ||||
| import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DeletingFileVisitor; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.mapping.reader.v2.TinyV2Factory; | ||||
| import net.fabricmc.mapping.tree.TinyTree; | ||||
| import net.fabricmc.stitch.Command; | ||||
| import net.fabricmc.stitch.commands.CommandProposeFieldNames; | ||||
| import net.fabricmc.stitch.commands.tinyv2.CommandMergeTinyV2; | ||||
| import net.fabricmc.stitch.commands.tinyv2.CommandReorderTinyV2; | ||||
| 
 | ||||
| public class MappingsProvider extends DependencyProvider { | ||||
| 	public MinecraftMappedProvider mappedProvider; | ||||
| 
 | ||||
| 	public String mappingsName; | ||||
| 	public String minecraftVersion; | ||||
| 	public String mappingsVersion; | ||||
| 
 | ||||
| 	private final Path mappingsDir; | ||||
| 	private final Path mappingsStepsDir; | ||||
| 	private Path intermediaryTiny; | ||||
| 	private boolean hasRefreshed = false; | ||||
| 	// The mappings that gradle gives us | ||||
| 	private Path baseTinyMappings; | ||||
| 	// The mappings we use in practice | ||||
| 	public File tinyMappings; | ||||
| 	public File tinyMappingsJar; | ||||
| 	private File unpickDefinitionsFile; | ||||
| 	private boolean hasUnpickDefinitions; | ||||
| 	private UnpickMetadata unpickMetadata; | ||||
| 
 | ||||
| 	public MappingsProvider(Project project) { | ||||
| 		super(project); | ||||
| 		mappingsDir = getExtension().getUserCache().toPath().resolve("mappings"); | ||||
| 		mappingsStepsDir = mappingsDir.resolve("steps"); | ||||
| 	} | ||||
| 
 | ||||
| 	public void clean() throws IOException { | ||||
| 		FileUtils.deleteDirectory(mappingsDir.toFile()); | ||||
| 	} | ||||
| 
 | ||||
| 	public TinyTree getMappings() throws IOException { | ||||
| 		return MappingsCache.INSTANCE.get(tinyMappings.toPath()); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||
| 		MinecraftProvider minecraftProvider = getDependencyManager().getProvider(MinecraftProvider.class); | ||||
| 
 | ||||
| 		getProject().getLogger().info(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")"); | ||||
| 
 | ||||
| 		String version = dependency.getResolvedVersion(); | ||||
| 		File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find yarn mappings: " + dependency)); | ||||
| 
 | ||||
| 		this.mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged"); | ||||
| 		this.minecraftVersion = minecraftProvider.getMinecraftVersion(); | ||||
| 
 | ||||
| 		boolean isV2; | ||||
| 
 | ||||
| 		// Only do this for official yarn, there isn't really a way we can get the mc version for all mappings | ||||
| 		if (dependency.getDependency().getGroup() != null && dependency.getDependency().getGroup().equals("net.fabricmc") && dependency.getDependency().getName().equals("yarn") && dependency.getDependency().getVersion() != null) { | ||||
| 			String yarnVersion = dependency.getDependency().getVersion(); | ||||
| 			char separator = yarnVersion.contains("+build.") ? '+' : yarnVersion.contains("-") ? '-' : '.'; | ||||
| 			String yarnMinecraftVersion = yarnVersion.substring(0, yarnVersion.lastIndexOf(separator)); | ||||
| 
 | ||||
| 			if (!yarnMinecraftVersion.equalsIgnoreCase(minecraftVersion)) { | ||||
| 				throw new RuntimeException(String.format("Minecraft Version (%s) does not match yarn's minecraft version (%s)", minecraftVersion, yarnMinecraftVersion)); | ||||
| 			} | ||||
| 
 | ||||
| 			// We can save reading the zip file + header by checking the file name | ||||
| 			isV2 = mappingsJar.getName().endsWith("-v2.jar"); | ||||
| 		} else { | ||||
| 			isV2 = doesJarContainV2Mappings(mappingsJar.toPath()); | ||||
| 		} | ||||
| 
 | ||||
| 		this.mappingsVersion = version + (isV2 ? "-v2" : ""); | ||||
| 
 | ||||
| 		initFiles(); | ||||
| 
 | ||||
| 		if (isRefreshDeps()) { | ||||
| 			cleanFiles(); | ||||
| 		} | ||||
| 
 | ||||
| 		Files.createDirectories(mappingsDir); | ||||
| 		Files.createDirectories(mappingsStepsDir); | ||||
| 
 | ||||
| 		String[] depStringSplit = dependency.getDepString().split(":"); | ||||
| 		String jarClassifier = "final"; | ||||
| 
 | ||||
| 		if (depStringSplit.length >= 4) { | ||||
| 			jarClassifier = jarClassifier + depStringSplit[3]; | ||||
| 		} | ||||
| 
 | ||||
| 		tinyMappings = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".tiny").toFile(); | ||||
| 		unpickDefinitionsFile = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".unpick").toFile(); | ||||
| 		tinyMappingsJar = new File(getExtension().getUserCache(), mappingsJar.getName().replace(".jar", "-" + jarClassifier + ".jar")); | ||||
| 
 | ||||
| 		if (!tinyMappings.exists() || isRefreshDeps()) { | ||||
| 			storeMappings(getProject(), minecraftProvider, mappingsJar.toPath()); | ||||
| 		} else { | ||||
| 			try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), (ClassLoader) null)) { | ||||
| 				extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath()); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (!tinyMappingsJar.exists() || isRefreshDeps()) { | ||||
| 			ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar); | ||||
| 		} | ||||
| 
 | ||||
| 		if (hasUnpickDefinitions()) { | ||||
| 			String notation = String.format("%s:%s:%s:constants", | ||||
| 					dependency.getDependency().getGroup(), | ||||
| 					dependency.getDependency().getName(), | ||||
| 					dependency.getDependency().getVersion() | ||||
| 			); | ||||
| 
 | ||||
| 			getProject().getDependencies().add(Constants.Configurations.MAPPING_CONSTANTS, notation); | ||||
| 			populateUnpickClasspath(); | ||||
| 		} | ||||
| 
 | ||||
| 		addDependency(tinyMappingsJar, Constants.Configurations.MAPPINGS_FINAL); | ||||
| 
 | ||||
| 		LoomGradleExtension extension = getExtension(); | ||||
| 
 | ||||
| 		if (extension.accessWidener != null) { | ||||
| 			extension.addJarProcessor(new AccessWidenerJarProcessor(getProject())); | ||||
| 		} | ||||
| 
 | ||||
| 		JarProcessorManager processorManager = new JarProcessorManager(extension.getJarProcessors()); | ||||
| 		extension.setJarProcessorManager(processorManager); | ||||
| 		processorManager.setupProcessors(); | ||||
| 
 | ||||
| 		if (processorManager.active()) { | ||||
| 			mappedProvider = new MinecraftProcessedProvider(getProject(), processorManager); | ||||
| 			getProject().getLogger().lifecycle("Using project based jar storage"); | ||||
| 		} else { | ||||
| 			mappedProvider = new MinecraftMappedProvider(getProject()); | ||||
| 		} | ||||
| 
 | ||||
| 		mappedProvider.initFiles(minecraftProvider, this); | ||||
| 		mappedProvider.provide(dependency, postPopulationScheduler); | ||||
| 	} | ||||
| 
 | ||||
| 	private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar) throws IOException { | ||||
| 		project.getLogger().info(":extracting " + yarnJar.getFileName()); | ||||
| 
 | ||||
| 		try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, (ClassLoader) null)) { | ||||
| 			extractMappings(fileSystem, baseTinyMappings); | ||||
| 			extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath()); | ||||
| 		} | ||||
| 
 | ||||
| 		if (baseMappingsAreV2()) { | ||||
| 			// These are unmerged v2 mappings | ||||
| 			mergeAndSaveMappings(project, yarnJar); | ||||
| 		} else { | ||||
| 			// These are merged v1 mappings | ||||
| 			if (tinyMappings.exists()) { | ||||
| 				tinyMappings.delete(); | ||||
| 			} | ||||
| 
 | ||||
| 			project.getLogger().lifecycle(":populating field names"); | ||||
| 			suggestFieldNames(minecraftProvider, baseTinyMappings, tinyMappings.toPath()); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean baseMappingsAreV2() throws IOException { | ||||
| 		try (BufferedReader reader = Files.newBufferedReader(baseTinyMappings)) { | ||||
| 			TinyV2Factory.readMetadata(reader); | ||||
| 			return true; | ||||
| 		} catch (IllegalArgumentException e) { | ||||
| 			// TODO: just check the mappings version when Parser supports V1 in readMetadata() | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean doesJarContainV2Mappings(Path path) throws IOException { | ||||
| 		try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) { | ||||
| 			try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) { | ||||
| 				TinyV2Factory.readMetadata(reader); | ||||
| 				return true; | ||||
| 			} catch (IllegalArgumentException e) { | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public static void extractMappings(FileSystem jar, Path extractTo) throws IOException { | ||||
| 		Files.copy(jar.getPath("mappings/mappings.tiny"), extractTo, StandardCopyOption.REPLACE_EXISTING); | ||||
| 	} | ||||
| 
 | ||||
| 	private void extractUnpickDefinitions(FileSystem jar, Path extractTo) throws IOException { | ||||
| 		Path unpickPath = jar.getPath("extras/definitions.unpick"); | ||||
| 		Path unpickMetadataPath = jar.getPath("extras/unpick.json"); | ||||
| 
 | ||||
| 		if (!Files.exists(unpickPath) || !Files.exists(unpickMetadataPath)) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		Files.copy(unpickPath, extractTo, StandardCopyOption.REPLACE_EXISTING); | ||||
| 
 | ||||
| 		unpickMetadata = parseUnpickMetadata(unpickMetadataPath); | ||||
| 		hasUnpickDefinitions = true; | ||||
| 	} | ||||
| 
 | ||||
| 	private UnpickMetadata parseUnpickMetadata(Path input) throws IOException { | ||||
| 		JsonObject jsonObject = LoomGradlePlugin.GSON.fromJson(Files.readString(input), JsonObject.class); | ||||
| 
 | ||||
| 		if (!jsonObject.has("version") || jsonObject.get("version").getAsInt() != 1) { | ||||
| 			throw new UnsupportedOperationException("Unsupported unpick version"); | ||||
| 		} | ||||
| 
 | ||||
| 		return new UnpickMetadata( | ||||
| 				jsonObject.get("unpickGroup").getAsString(), | ||||
| 				jsonObject.get("unpickVersion").getAsString() | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	private void populateUnpickClasspath() { | ||||
| 		String unpickCliName = "unpick-cli"; | ||||
| 		getProject().getDependencies().add(Constants.Configurations.UNPICK_CLASSPATH, | ||||
| 				String.format("%s:%s:%s", unpickMetadata.unpickGroup, unpickCliName, unpickMetadata.unpickVersion) | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	private void extractIntermediary(Path intermediaryJar, Path intermediaryTiny) throws IOException { | ||||
| 		getProject().getLogger().info(":extracting " + intermediaryJar.getFileName()); | ||||
| 
 | ||||
| 		try (FileSystem unmergedIntermediaryFs = FileSystems.newFileSystem(intermediaryJar, (ClassLoader) null)) { | ||||
| 			extractMappings(unmergedIntermediaryFs, intermediaryTiny); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void mergeAndSaveMappings(Project project, Path unmergedYarnJar) throws IOException { | ||||
| 		Path unmergedYarn = Paths.get(mappingsStepsDir.toString(), "unmerged-yarn.tiny"); | ||||
| 		project.getLogger().info(":extracting " + unmergedYarnJar.getFileName()); | ||||
| 
 | ||||
| 		try (FileSystem unmergedYarnJarFs = FileSystems.newFileSystem(unmergedYarnJar, (ClassLoader) null)) { | ||||
| 			extractMappings(unmergedYarnJarFs, unmergedYarn); | ||||
| 		} | ||||
| 
 | ||||
| 		Path invertedIntermediary = Paths.get(mappingsStepsDir.toString(), "inverted-intermediary.tiny"); | ||||
| 		reorderMappings(getIntermediaryTiny(), invertedIntermediary, "intermediary", "official"); | ||||
| 		Path unorderedMergedMappings = Paths.get(mappingsStepsDir.toString(), "unordered-merged.tiny"); | ||||
| 		project.getLogger().info(":merging"); | ||||
| 		mergeMappings(invertedIntermediary, unmergedYarn, unorderedMergedMappings); | ||||
| 		reorderMappings(unorderedMergedMappings, tinyMappings.toPath(), "official", "intermediary", "named"); | ||||
| 	} | ||||
| 
 | ||||
| 	private void reorderMappings(Path oldMappings, Path newMappings, String... newOrder) { | ||||
| 		Command command = new CommandReorderTinyV2(); | ||||
| 		String[] args = new String[2 + newOrder.length]; | ||||
| 		args[0] = oldMappings.toAbsolutePath().toString(); | ||||
| 		args[1] = newMappings.toAbsolutePath().toString(); | ||||
| 		System.arraycopy(newOrder, 0, args, 2, newOrder.length); | ||||
| 		runCommand(command, args); | ||||
| 	} | ||||
| 
 | ||||
| 	private void mergeMappings(Path intermediaryMappings, Path yarnMappings, Path newMergedMappings) { | ||||
| 		try { | ||||
| 			Command command = new CommandMergeTinyV2(); | ||||
| 			runCommand(command, intermediaryMappings.toAbsolutePath().toString(), | ||||
| 							yarnMappings.toAbsolutePath().toString(), | ||||
| 							newMergedMappings.toAbsolutePath().toString(), | ||||
| 							"intermediary", "official"); | ||||
| 		} catch (Exception e) { | ||||
| 			throw new RuntimeException("Could not merge mappings from " + intermediaryMappings.toString() | ||||
| 							+ " with mappings from " + yarnMappings, e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void suggestFieldNames(MinecraftProvider minecraftProvider, Path oldMappings, Path newMappings) { | ||||
| 		Command command = new CommandProposeFieldNames(); | ||||
| 		runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(), | ||||
| 						oldMappings.toAbsolutePath().toString(), | ||||
| 						newMappings.toAbsolutePath().toString()); | ||||
| 	} | ||||
| 
 | ||||
| 	private void runCommand(Command command, String... args) { | ||||
| 		try { | ||||
| 			command.run(args); | ||||
| 		} catch (Exception e) { | ||||
| 			throw new RuntimeException(e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void initFiles() { | ||||
| 		baseTinyMappings = mappingsDir.resolve(mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion + "-base"); | ||||
| 	} | ||||
| 
 | ||||
| 	public void cleanFiles() { | ||||
| 		try { | ||||
| 			if (Files.exists(mappingsStepsDir)) { | ||||
| 				Files.walkFileTree(mappingsStepsDir, new DeletingFileVisitor()); | ||||
| 			} | ||||
| 
 | ||||
| 			if (Files.exists(baseTinyMappings)) { | ||||
| 				Files.deleteIfExists(baseTinyMappings); | ||||
| 			} | ||||
| 
 | ||||
| 			if (tinyMappings != null) { | ||||
| 				tinyMappings.delete(); | ||||
| 			} | ||||
| 
 | ||||
| 			if (tinyMappingsJar != null) { | ||||
| 				tinyMappingsJar.delete(); | ||||
| 			} | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getTargetConfig() { | ||||
| 		return Constants.Configurations.MAPPINGS; | ||||
| 	} | ||||
| 
 | ||||
| 	public Path getMappingsDir() { | ||||
| 		return mappingsDir; | ||||
| 	} | ||||
| 
 | ||||
| 	public Path getIntermediaryTiny() throws IOException { | ||||
| 		if (intermediaryTiny == null) { | ||||
| 			minecraftVersion = getExtension().getMinecraftProvider().getMinecraftVersion(); | ||||
| 			Preconditions.checkNotNull(minecraftVersion, "Minecraft version cannot be null"); | ||||
| 
 | ||||
| 			intermediaryTiny = mappingsDir.resolve(String.format("intermediary-%s-v2.tiny", minecraftVersion)); | ||||
| 
 | ||||
| 			if (!Files.exists(intermediaryTiny) || (isRefreshDeps() && !hasRefreshed)) { | ||||
| 				hasRefreshed = true; | ||||
| 
 | ||||
| 				// Download and extract intermediary | ||||
| 				String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftVersion); | ||||
| 				String intermediaryArtifactUrl = getExtension().getIntermediaryUrl().apply(encodedMinecraftVersion); | ||||
| 				Path intermediaryJar = mappingsDir.resolve("v2-intermediary-" + minecraftVersion + ".jar"); | ||||
| 				DownloadUtil.downloadIfChanged(new URL(intermediaryArtifactUrl), intermediaryJar.toFile(), getProject().getLogger()); | ||||
| 
 | ||||
| 				extractIntermediary(intermediaryJar, intermediaryTiny); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return intermediaryTiny; | ||||
| 	} | ||||
| 
 | ||||
| 	public String getMappingsKey() { | ||||
| 		return mappingsName + "." + minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsVersion; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getUnpickDefinitionsFile() { | ||||
| 		return unpickDefinitionsFile; | ||||
| 	} | ||||
| 
 | ||||
| 	public boolean hasUnpickDefinitions() { | ||||
| 		return hasUnpickDefinitions; | ||||
| 	} | ||||
| 
 | ||||
| 	public record UnpickMetadata(String unpickGroup, String unpickVersion) { | ||||
| 	} | ||||
| 	File intermediaryTinyFile(); | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,423 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.nio.file.FileSystem; | ||||
| import java.nio.file.FileSystems; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.nio.file.StandardCopyOption; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import com.google.common.base.Preconditions; | ||||
| import com.google.common.net.UrlEscapers; | ||||
| import com.google.gson.JsonObject; | ||||
| import org.apache.commons.io.FileUtils; | ||||
| import org.apache.tools.ant.util.StringUtils; | ||||
| import org.gradle.api.Project; | ||||
| import org.zeroturnaround.zip.FileSource; | ||||
| import org.zeroturnaround.zip.ZipEntrySource; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.LoomGradlePlugin; | ||||
| import net.fabricmc.loom.configuration.DependencyProvider; | ||||
| import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; | ||||
| import net.fabricmc.loom.configuration.processors.JarProcessorManager; | ||||
| import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.DeletingFileVisitor; | ||||
| import net.fabricmc.loom.util.DownloadUtil; | ||||
| import net.fabricmc.mapping.reader.v2.TinyV2Factory; | ||||
| import net.fabricmc.mapping.tree.TinyTree; | ||||
| import net.fabricmc.stitch.Command; | ||||
| import net.fabricmc.stitch.commands.CommandProposeFieldNames; | ||||
| import net.fabricmc.stitch.commands.tinyv2.CommandMergeTinyV2; | ||||
| import net.fabricmc.stitch.commands.tinyv2.CommandReorderTinyV2; | ||||
| 
 | ||||
| public class MappingsProviderImpl extends DependencyProvider implements MappingsProvider { | ||||
| 	public MinecraftMappedProvider mappedProvider; | ||||
| 
 | ||||
| 	public String mappingsName; | ||||
| 	public String minecraftVersion; | ||||
| 	public String mappingsVersion; | ||||
| 
 | ||||
| 	private final Path mappingsDir; | ||||
| 	private final Path mappingsStepsDir; | ||||
| 	private Path intermediaryTiny; | ||||
| 	private boolean hasRefreshed = false; | ||||
| 	// The mappings that gradle gives us | ||||
| 	private Path baseTinyMappings; | ||||
| 	// The mappings we use in practice | ||||
| 	public File tinyMappings; | ||||
| 	public File tinyMappingsJar; | ||||
| 	private File unpickDefinitionsFile; | ||||
| 	private boolean hasUnpickDefinitions; | ||||
| 	private UnpickMetadata unpickMetadata; | ||||
| 
 | ||||
| 	public MappingsProviderImpl(Project project) { | ||||
| 		super(project); | ||||
| 		mappingsDir = getExtension().getUserCache().toPath().resolve("mappings"); | ||||
| 		mappingsStepsDir = mappingsDir.resolve("steps"); | ||||
| 	} | ||||
| 
 | ||||
| 	public void clean() throws IOException { | ||||
| 		FileUtils.deleteDirectory(mappingsDir.toFile()); | ||||
| 	} | ||||
| 
 | ||||
| 	public TinyTree getMappings() throws IOException { | ||||
| 		return MappingsCache.INSTANCE.get(tinyMappings.toPath()); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception { | ||||
| 		MinecraftProviderImpl minecraftProvider = getDependencyManager().getProvider(MinecraftProviderImpl.class); | ||||
| 
 | ||||
| 		getProject().getLogger().info(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")"); | ||||
| 
 | ||||
| 		String version = dependency.getResolvedVersion(); | ||||
| 		File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find yarn mappings: " + dependency)); | ||||
| 
 | ||||
| 		this.mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged"); | ||||
| 		this.minecraftVersion = minecraftProvider.minecraftVersion(); | ||||
| 
 | ||||
| 		boolean isV2; | ||||
| 
 | ||||
| 		// Only do this for official yarn, there isn't really a way we can get the mc version for all mappings | ||||
| 		if (dependency.getDependency().getGroup() != null && dependency.getDependency().getGroup().equals("net.fabricmc") && dependency.getDependency().getName().equals("yarn") && dependency.getDependency().getVersion() != null) { | ||||
| 			String yarnVersion = dependency.getDependency().getVersion(); | ||||
| 			char separator = yarnVersion.contains("+build.") ? '+' : yarnVersion.contains("-") ? '-' : '.'; | ||||
| 			String yarnMinecraftVersion = yarnVersion.substring(0, yarnVersion.lastIndexOf(separator)); | ||||
| 
 | ||||
| 			if (!yarnMinecraftVersion.equalsIgnoreCase(minecraftVersion)) { | ||||
| 				throw new RuntimeException(String.format("Minecraft Version (%s) does not match yarn's minecraft version (%s)", minecraftVersion, yarnMinecraftVersion)); | ||||
| 			} | ||||
| 
 | ||||
| 			// We can save reading the zip file + header by checking the file name | ||||
| 			isV2 = mappingsJar.getName().endsWith("-v2.jar"); | ||||
| 		} else { | ||||
| 			isV2 = doesJarContainV2Mappings(mappingsJar.toPath()); | ||||
| 		} | ||||
| 
 | ||||
| 		this.mappingsVersion = version + (isV2 ? "-v2" : ""); | ||||
| 
 | ||||
| 		initFiles(); | ||||
| 
 | ||||
| 		if (isRefreshDeps()) { | ||||
| 			cleanFiles(); | ||||
| 		} | ||||
| 
 | ||||
| 		Files.createDirectories(mappingsDir); | ||||
| 		Files.createDirectories(mappingsStepsDir); | ||||
| 
 | ||||
| 		String[] depStringSplit = dependency.getDepString().split(":"); | ||||
| 		String jarClassifier = "final"; | ||||
| 
 | ||||
| 		if (depStringSplit.length >= 4) { | ||||
| 			jarClassifier = jarClassifier + depStringSplit[3]; | ||||
| 		} | ||||
| 
 | ||||
| 		tinyMappings = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".tiny").toFile(); | ||||
| 		unpickDefinitionsFile = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".unpick").toFile(); | ||||
| 		tinyMappingsJar = new File(getExtension().getUserCache(), mappingsJar.getName().replace(".jar", "-" + jarClassifier + ".jar")); | ||||
| 
 | ||||
| 		if (!tinyMappings.exists() || isRefreshDeps()) { | ||||
| 			storeMappings(getProject(), minecraftProvider, mappingsJar.toPath()); | ||||
| 		} else { | ||||
| 			try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), (ClassLoader) null)) { | ||||
| 				extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath()); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (!tinyMappingsJar.exists() || isRefreshDeps()) { | ||||
| 			ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar); | ||||
| 		} | ||||
| 
 | ||||
| 		if (hasUnpickDefinitions()) { | ||||
| 			String notation = String.format("%s:%s:%s:constants", | ||||
| 					dependency.getDependency().getGroup(), | ||||
| 					dependency.getDependency().getName(), | ||||
| 					dependency.getDependency().getVersion() | ||||
| 			); | ||||
| 
 | ||||
| 			getProject().getDependencies().add(Constants.Configurations.MAPPING_CONSTANTS, notation); | ||||
| 			populateUnpickClasspath(); | ||||
| 		} | ||||
| 
 | ||||
| 		addDependency(tinyMappingsJar, Constants.Configurations.MAPPINGS_FINAL); | ||||
| 
 | ||||
| 		LoomGradleExtension extension = getExtension(); | ||||
| 
 | ||||
| 		if (extension.accessWidener != null) { | ||||
| 			extension.addJarProcessor(new AccessWidenerJarProcessor(getProject())); | ||||
| 		} | ||||
| 
 | ||||
| 		JarProcessorManager processorManager = new JarProcessorManager(extension.getJarProcessors()); | ||||
| 		extension.setJarProcessorManager(processorManager); | ||||
| 		processorManager.setupProcessors(); | ||||
| 
 | ||||
| 		if (processorManager.active()) { | ||||
| 			mappedProvider = new MinecraftProcessedProvider(getProject(), processorManager); | ||||
| 			getProject().getLogger().lifecycle("Using project based jar storage"); | ||||
| 		} else { | ||||
| 			mappedProvider = new MinecraftMappedProvider(getProject()); | ||||
| 		} | ||||
| 
 | ||||
| 		mappedProvider.initFiles(minecraftProvider, this); | ||||
| 		mappedProvider.provide(dependency, postPopulationScheduler); | ||||
| 	} | ||||
| 
 | ||||
| 	private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar) throws IOException { | ||||
| 		project.getLogger().info(":extracting " + yarnJar.getFileName()); | ||||
| 
 | ||||
| 		try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, (ClassLoader) null)) { | ||||
| 			extractMappings(fileSystem, baseTinyMappings); | ||||
| 			extractUnpickDefinitions(fileSystem, unpickDefinitionsFile.toPath()); | ||||
| 		} | ||||
| 
 | ||||
| 		if (baseMappingsAreV2()) { | ||||
| 			// These are unmerged v2 mappings | ||||
| 			mergeAndSaveMappings(project, yarnJar); | ||||
| 		} else { | ||||
| 			// These are merged v1 mappings | ||||
| 			if (tinyMappings.exists()) { | ||||
| 				tinyMappings.delete(); | ||||
| 			} | ||||
| 
 | ||||
| 			project.getLogger().lifecycle(":populating field names"); | ||||
| 			suggestFieldNames(minecraftProvider, baseTinyMappings, tinyMappings.toPath()); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean baseMappingsAreV2() throws IOException { | ||||
| 		try (BufferedReader reader = Files.newBufferedReader(baseTinyMappings)) { | ||||
| 			TinyV2Factory.readMetadata(reader); | ||||
| 			return true; | ||||
| 		} catch (IllegalArgumentException e) { | ||||
| 			// TODO: just check the mappings version when Parser supports V1 in readMetadata() | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean doesJarContainV2Mappings(Path path) throws IOException { | ||||
| 		try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) { | ||||
| 			try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) { | ||||
| 				TinyV2Factory.readMetadata(reader); | ||||
| 				return true; | ||||
| 			} catch (IllegalArgumentException e) { | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public static void extractMappings(FileSystem jar, Path extractTo) throws IOException { | ||||
| 		Files.copy(jar.getPath("mappings/mappings.tiny"), extractTo, StandardCopyOption.REPLACE_EXISTING); | ||||
| 	} | ||||
| 
 | ||||
| 	private void extractUnpickDefinitions(FileSystem jar, Path extractTo) throws IOException { | ||||
| 		Path unpickPath = jar.getPath("extras/definitions.unpick"); | ||||
| 		Path unpickMetadataPath = jar.getPath("extras/unpick.json"); | ||||
| 
 | ||||
| 		if (!Files.exists(unpickPath) || !Files.exists(unpickMetadataPath)) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		Files.copy(unpickPath, extractTo, StandardCopyOption.REPLACE_EXISTING); | ||||
| 
 | ||||
| 		unpickMetadata = parseUnpickMetadata(unpickMetadataPath); | ||||
| 		hasUnpickDefinitions = true; | ||||
| 	} | ||||
| 
 | ||||
| 	private UnpickMetadata parseUnpickMetadata(Path input) throws IOException { | ||||
| 		JsonObject jsonObject = LoomGradlePlugin.GSON.fromJson(Files.readString(input), JsonObject.class); | ||||
| 
 | ||||
| 		if (!jsonObject.has("version") || jsonObject.get("version").getAsInt() != 1) { | ||||
| 			throw new UnsupportedOperationException("Unsupported unpick version"); | ||||
| 		} | ||||
| 
 | ||||
| 		return new UnpickMetadata( | ||||
| 				jsonObject.get("unpickGroup").getAsString(), | ||||
| 				jsonObject.get("unpickVersion").getAsString() | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	private void populateUnpickClasspath() { | ||||
| 		String unpickCliName = "unpick-cli"; | ||||
| 		getProject().getDependencies().add(Constants.Configurations.UNPICK_CLASSPATH, | ||||
| 				String.format("%s:%s:%s", unpickMetadata.unpickGroup, unpickCliName, unpickMetadata.unpickVersion) | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	private void extractIntermediary(Path intermediaryJar, Path intermediaryTiny) throws IOException { | ||||
| 		getProject().getLogger().info(":extracting " + intermediaryJar.getFileName()); | ||||
| 
 | ||||
| 		try (FileSystem unmergedIntermediaryFs = FileSystems.newFileSystem(intermediaryJar, (ClassLoader) null)) { | ||||
| 			extractMappings(unmergedIntermediaryFs, intermediaryTiny); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void mergeAndSaveMappings(Project project, Path unmergedYarnJar) throws IOException { | ||||
| 		Path unmergedYarn = Paths.get(mappingsStepsDir.toString(), "unmerged-yarn.tiny"); | ||||
| 		project.getLogger().info(":extracting " + unmergedYarnJar.getFileName()); | ||||
| 
 | ||||
| 		try (FileSystem unmergedYarnJarFs = FileSystems.newFileSystem(unmergedYarnJar, (ClassLoader) null)) { | ||||
| 			extractMappings(unmergedYarnJarFs, unmergedYarn); | ||||
| 		} | ||||
| 
 | ||||
| 		Path invertedIntermediary = Paths.get(mappingsStepsDir.toString(), "inverted-intermediary.tiny"); | ||||
| 		reorderMappings(getIntermediaryTiny(), invertedIntermediary, "intermediary", "official"); | ||||
| 		Path unorderedMergedMappings = Paths.get(mappingsStepsDir.toString(), "unordered-merged.tiny"); | ||||
| 		project.getLogger().info(":merging"); | ||||
| 		mergeMappings(invertedIntermediary, unmergedYarn, unorderedMergedMappings); | ||||
| 		reorderMappings(unorderedMergedMappings, tinyMappings.toPath(), "official", "intermediary", "named"); | ||||
| 	} | ||||
| 
 | ||||
| 	private void reorderMappings(Path oldMappings, Path newMappings, String... newOrder) { | ||||
| 		Command command = new CommandReorderTinyV2(); | ||||
| 		String[] args = new String[2 + newOrder.length]; | ||||
| 		args[0] = oldMappings.toAbsolutePath().toString(); | ||||
| 		args[1] = newMappings.toAbsolutePath().toString(); | ||||
| 		System.arraycopy(newOrder, 0, args, 2, newOrder.length); | ||||
| 		runCommand(command, args); | ||||
| 	} | ||||
| 
 | ||||
| 	private void mergeMappings(Path intermediaryMappings, Path yarnMappings, Path newMergedMappings) { | ||||
| 		try { | ||||
| 			Command command = new CommandMergeTinyV2(); | ||||
| 			runCommand(command, intermediaryMappings.toAbsolutePath().toString(), | ||||
| 							yarnMappings.toAbsolutePath().toString(), | ||||
| 							newMergedMappings.toAbsolutePath().toString(), | ||||
| 							"intermediary", "official"); | ||||
| 		} catch (Exception e) { | ||||
| 			throw new RuntimeException("Could not merge mappings from " + intermediaryMappings.toString() | ||||
| 							+ " with mappings from " + yarnMappings, e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void suggestFieldNames(MinecraftProviderImpl minecraftProvider, Path oldMappings, Path newMappings) { | ||||
| 		Command command = new CommandProposeFieldNames(); | ||||
| 		runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(), | ||||
| 						oldMappings.toAbsolutePath().toString(), | ||||
| 						newMappings.toAbsolutePath().toString()); | ||||
| 	} | ||||
| 
 | ||||
| 	private void runCommand(Command command, String... args) { | ||||
| 		try { | ||||
| 			command.run(args); | ||||
| 		} catch (Exception e) { | ||||
| 			throw new RuntimeException(e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void initFiles() { | ||||
| 		baseTinyMappings = mappingsDir.resolve(mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion + "-base"); | ||||
| 	} | ||||
| 
 | ||||
| 	public void cleanFiles() { | ||||
| 		try { | ||||
| 			if (Files.exists(mappingsStepsDir)) { | ||||
| 				Files.walkFileTree(mappingsStepsDir, new DeletingFileVisitor()); | ||||
| 			} | ||||
| 
 | ||||
| 			if (Files.exists(baseTinyMappings)) { | ||||
| 				Files.deleteIfExists(baseTinyMappings); | ||||
| 			} | ||||
| 
 | ||||
| 			if (tinyMappings != null) { | ||||
| 				tinyMappings.delete(); | ||||
| 			} | ||||
| 
 | ||||
| 			if (tinyMappingsJar != null) { | ||||
| 				tinyMappingsJar.delete(); | ||||
| 			} | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getTargetConfig() { | ||||
| 		return Constants.Configurations.MAPPINGS; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Path getMappingsDir() { | ||||
| 		return mappingsDir; | ||||
| 	} | ||||
| 
 | ||||
| 	public Path getIntermediaryTiny() throws IOException { | ||||
| 		if (intermediaryTiny == null) { | ||||
| 			minecraftVersion = getExtension().getMinecraftProvider().minecraftVersion(); | ||||
| 			Preconditions.checkNotNull(minecraftVersion, "Minecraft version cannot be null"); | ||||
| 
 | ||||
| 			intermediaryTiny = mappingsDir.resolve(String.format("intermediary-%s-v2.tiny", minecraftVersion)); | ||||
| 
 | ||||
| 			if (!Files.exists(intermediaryTiny) || (isRefreshDeps() && !hasRefreshed)) { | ||||
| 				hasRefreshed = true; | ||||
| 
 | ||||
| 				// Download and extract intermediary | ||||
| 				String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftVersion); | ||||
| 				String intermediaryArtifactUrl = getExtension().getIntermediaryUrl().apply(encodedMinecraftVersion); | ||||
| 				Path intermediaryJar = mappingsDir.resolve("v2-intermediary-" + minecraftVersion + ".jar"); | ||||
| 				DownloadUtil.downloadIfChanged(new URL(intermediaryArtifactUrl), intermediaryJar.toFile(), getProject().getLogger()); | ||||
| 
 | ||||
| 				extractIntermediary(intermediaryJar, intermediaryTiny); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return intermediaryTiny; | ||||
| 	} | ||||
| 
 | ||||
| 	public String getMappingsKey() { | ||||
| 		return mappingsName + "." + minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsVersion; | ||||
| 	} | ||||
| 
 | ||||
| 	public File getUnpickDefinitionsFile() { | ||||
| 		return unpickDefinitionsFile; | ||||
| 	} | ||||
| 
 | ||||
| 	public boolean hasUnpickDefinitions() { | ||||
| 		return hasUnpickDefinitions; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public File intermediaryTinyFile() { | ||||
| 		try { | ||||
| 			return getIntermediaryTiny().toFile(); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException("Failed to get intermediary", e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public record UnpickMetadata(String unpickGroup, String unpickVersion) { | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,29 @@ | |||
| /* | ||||
|  * 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.mappings; | ||||
| 
 | ||||
| public interface MappingsSpec<L extends MappingLayer> { | ||||
| 	L createLayer(MappingContext context); | ||||
| } | ||||
|  | @ -1,275 +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.mappings; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.StringWriter; | ||||
| import java.io.Writer; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Collections; | ||||
| import java.util.Set; | ||||
| import java.util.function.Consumer; | ||||
| 
 | ||||
| import org.cadixdev.lorenz.MappingSet; | ||||
| import org.cadixdev.lorenz.io.TextMappingsWriter; | ||||
| import org.cadixdev.lorenz.io.proguard.ProGuardReader; | ||||
| import org.cadixdev.lorenz.model.ClassMapping; | ||||
| import org.cadixdev.lorenz.model.FieldMapping; | ||||
| import org.cadixdev.lorenz.model.InnerClassMapping; | ||||
| import org.cadixdev.lorenz.model.MethodMapping; | ||||
| import org.cadixdev.lorenz.model.TopLevelClassMapping; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.artifacts.SelfResolvingDependency; | ||||
| import org.gradle.api.tasks.TaskDependency; | ||||
| import org.zeroturnaround.zip.ByteSource; | ||||
| import org.zeroturnaround.zip.ZipEntrySource; | ||||
| import org.zeroturnaround.zip.ZipUtil; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.LoomGradlePlugin; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; | ||||
| import net.fabricmc.loom.util.HashedDownloadUtil; | ||||
| import net.fabricmc.lorenztiny.TinyMappingsReader; | ||||
| import net.fabricmc.mapping.tree.TinyMappingFactory; | ||||
| 
 | ||||
| public class MojangMappingsDependency implements SelfResolvingDependency { | ||||
| 	public static final String GROUP = "net.minecraft"; | ||||
| 	public static final String MODULE = "mappings"; | ||||
| 	// Keys in dependency manifest | ||||
| 	private static final String MANIFEST_CLIENT_MAPPINGS = "client_mappings"; | ||||
| 	private static final String MANIFEST_SERVER_MAPPINGS = "server_mappings"; | ||||
| 
 | ||||
| 	private final Project project; | ||||
| 	private final LoomGradleExtension extension; | ||||
| 
 | ||||
| 	public MojangMappingsDependency(Project project, LoomGradleExtension extension) { | ||||
| 		this.project = project; | ||||
| 		this.extension = extension; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Set<File> resolve() { | ||||
| 		Path mappingsDir = extension.getMappingsProvider().getMappingsDir(); | ||||
| 		Path mappingsFile = mappingsDir.resolve(String.format("%s.%s-%s.tiny", GROUP, MODULE, getVersion())); | ||||
| 		Path clientMappings = mappingsDir.resolve(String.format("%s.%s-%s-client.map", GROUP, MODULE, getVersion())); | ||||
| 		Path serverMappings = mappingsDir.resolve(String.format("%s.%s-%s-server.map", GROUP, MODULE, getVersion())); | ||||
| 
 | ||||
| 		if (!Files.exists(mappingsFile) || LoomGradlePlugin.refreshDeps) { | ||||
| 			MappingSet mappingSet; | ||||
| 
 | ||||
| 			try { | ||||
| 				mappingSet = getMappingsSet(clientMappings, serverMappings); | ||||
| 
 | ||||
| 				try (Writer writer = new StringWriter()) { | ||||
| 					new TinyWriter(writer, "intermediary", "named").write(mappingSet); | ||||
| 					Files.deleteIfExists(mappingsFile); | ||||
| 
 | ||||
| 					ZipUtil.pack(new ZipEntrySource[] { | ||||
| 							new ByteSource("mappings/mappings.tiny", writer.toString().getBytes(StandardCharsets.UTF_8)) | ||||
| 					}, mappingsFile.toFile()); | ||||
| 				} | ||||
| 			} catch (IOException e) { | ||||
| 				throw new RuntimeException("Failed to resolve Mojang mappings", e); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8)) { | ||||
| 			project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); | ||||
| 			project.getLogger().warn("Using of the official minecraft mappings is at your own risk!"); | ||||
| 			project.getLogger().warn("Please make sure to read and understand the following license:"); | ||||
| 			project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); | ||||
| 			String line; | ||||
| 
 | ||||
| 			while ((line = clientBufferedReader.readLine()).startsWith("#")) { | ||||
| 				project.getLogger().warn(line); | ||||
| 			} | ||||
| 
 | ||||
| 			project.getLogger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException("Failed to read client mappings", e); | ||||
| 		} | ||||
| 
 | ||||
| 		return Collections.singleton(mappingsFile.toFile()); | ||||
| 	} | ||||
| 
 | ||||
| 	private MappingSet getMappingsSet(Path clientMappings, Path serverMappings) throws IOException { | ||||
| 		MinecraftVersionMeta versionInfo = extension.getMinecraftProvider().getVersionInfo(); | ||||
| 
 | ||||
| 		if (versionInfo.download(MANIFEST_CLIENT_MAPPINGS) == null) { | ||||
| 			throw new RuntimeException("Failed to find official mojang mappings for " + getVersion()); | ||||
| 		} | ||||
| 
 | ||||
| 		MinecraftVersionMeta.Download clientMappingsDownload = versionInfo.download(MANIFEST_CLIENT_MAPPINGS); | ||||
| 		MinecraftVersionMeta.Download serverMappingsDownload = versionInfo.download(MANIFEST_CLIENT_MAPPINGS); | ||||
| 
 | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(clientMappingsDownload.url()), clientMappings.toFile(), clientMappingsDownload.sha1(), project.getLogger(), false); | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(serverMappingsDownload.url()), serverMappings.toFile(), clientMappingsDownload.sha1(), project.getLogger(), false); | ||||
| 
 | ||||
| 		MappingSet mappings = MappingSet.create(); | ||||
| 
 | ||||
| 		try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8); | ||||
| 				BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings, StandardCharsets.UTF_8)) { | ||||
| 			try (ProGuardReader proGuardReaderClient = new ProGuardReader(clientBufferedReader); | ||||
| 					ProGuardReader proGuardReaderServer = new ProGuardReader(serverBufferedReader)) { | ||||
| 				proGuardReaderClient.read(mappings); | ||||
| 				proGuardReaderServer.read(mappings); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		MappingSet officialToNamed = mappings.reverse(); | ||||
| 		MappingSet intermediaryToOfficial; | ||||
| 
 | ||||
| 		try (BufferedReader reader = Files.newBufferedReader(extension.getMappingsProvider().getIntermediaryTiny(), StandardCharsets.UTF_8)) { | ||||
| 			intermediaryToOfficial = new TinyMappingsReader(TinyMappingFactory.loadWithDetection(reader), "intermediary", "official").read(); | ||||
| 		} | ||||
| 
 | ||||
| 		MappingSet intermediaryToMojang = MappingSet.create(); | ||||
| 
 | ||||
| 		// Merging. Don't use MappingSet#merge | ||||
| 		iterateClasses(intermediaryToOfficial, inputMappings -> { | ||||
| 			officialToNamed.getClassMapping(inputMappings.getFullDeobfuscatedName()) | ||||
| 					.ifPresent(namedClass -> { | ||||
| 						ClassMapping<?, ?> mojangClassMapping = intermediaryToMojang.getOrCreateClassMapping(inputMappings.getFullObfuscatedName()) | ||||
| 								.setDeobfuscatedName(namedClass.getFullDeobfuscatedName()); | ||||
| 
 | ||||
| 						for (FieldMapping fieldMapping : inputMappings .getFieldMappings()) { | ||||
| 							namedClass.getFieldMapping(fieldMapping.getDeobfuscatedName()) | ||||
| 									.ifPresent(namedField -> { | ||||
| 										mojangClassMapping.getOrCreateFieldMapping(fieldMapping.getSignature()) | ||||
| 												.setDeobfuscatedName(namedField.getDeobfuscatedName()); | ||||
| 									}); | ||||
| 						} | ||||
| 
 | ||||
| 						for (MethodMapping methodMapping : inputMappings .getMethodMappings()) { | ||||
| 							namedClass.getMethodMapping(methodMapping.getDeobfuscatedSignature()) | ||||
| 									.ifPresent(namedMethod -> { | ||||
| 										mojangClassMapping.getOrCreateMethodMapping(methodMapping.getSignature()) | ||||
| 												.setDeobfuscatedName(namedMethod.getDeobfuscatedName()); | ||||
| 									}); | ||||
| 						} | ||||
| 					}); | ||||
| 		}); | ||||
| 
 | ||||
| 		return intermediaryToMojang; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Set<File> resolve(boolean transitive) { | ||||
| 		return resolve(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public TaskDependency getBuildDependencies() { | ||||
| 		return task -> Collections.emptySet(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getGroup() { | ||||
| 		return GROUP; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getName() { | ||||
| 		return MODULE; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getVersion() { | ||||
| 		return extension.getMinecraftProvider().getMinecraftVersion(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public boolean contentEquals(Dependency dependency) { | ||||
| 		if (dependency instanceof MojangMappingsDependency mojangMappingsDependency) { | ||||
| 			return mojangMappingsDependency.extension.getMinecraftProvider().getMinecraftVersion().equals(getVersion()); | ||||
| 		} | ||||
| 
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public Dependency copy() { | ||||
| 		return new MojangMappingsDependency(project, extension); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public String getReason() { | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void because(String s) { | ||||
| 	} | ||||
| 
 | ||||
| 	private static void iterateClasses(MappingSet mappings, Consumer<ClassMapping<?, ?>> consumer) { | ||||
| 		for (TopLevelClassMapping classMapping : mappings.getTopLevelClassMappings()) { | ||||
| 			iterateClass(classMapping, consumer); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private static void iterateClass(ClassMapping<?, ?> classMapping, Consumer<ClassMapping<?, ?>> consumer) { | ||||
| 		consumer.accept(classMapping); | ||||
| 
 | ||||
| 		for (InnerClassMapping innerClassMapping : classMapping.getInnerClassMappings()) { | ||||
| 			iterateClass(innerClassMapping, consumer); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private static class TinyWriter extends TextMappingsWriter { | ||||
| 		private final String namespaceFrom; | ||||
| 		private final String namespaceTo; | ||||
| 
 | ||||
| 		protected TinyWriter(Writer writer, String namespaceFrom, String namespaceTo) { | ||||
| 			super(writer); | ||||
| 			this.namespaceFrom = namespaceFrom; | ||||
| 			this.namespaceTo = namespaceTo; | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		public void write(MappingSet mappings) { | ||||
| 			writer.println("tiny\t2\t0\t" + namespaceFrom + "\t" + namespaceTo); | ||||
| 
 | ||||
| 			iterateClasses(mappings, classMapping -> { | ||||
| 				writer.println("c\t" + classMapping.getFullObfuscatedName() + "\t" + classMapping.getFullDeobfuscatedName()); | ||||
| 
 | ||||
| 				for (FieldMapping fieldMapping : classMapping.getFieldMappings()) { | ||||
| 					fieldMapping.getType().ifPresent(fieldType -> { | ||||
| 						writer.println("\tf\t" + fieldType + "\t" + fieldMapping.getObfuscatedName() + "\t" + fieldMapping.getDeobfuscatedName()); | ||||
| 					}); | ||||
| 				} | ||||
| 
 | ||||
| 				for (MethodMapping methodMapping : classMapping.getMethodMappings()) { | ||||
| 					writer.println("\tm\t" + methodMapping.getSignature().getDescriptor() + "\t" + methodMapping.getObfuscatedName() + "\t" + methodMapping.getDeobfuscatedName()); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,55 @@ | |||
| /* | ||||
|  * 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.mappings.intermediary; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.nio.file.Files; | ||||
| import java.util.Collections; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; | ||||
| import net.fabricmc.mappingio.MappingVisitor; | ||||
| import net.fabricmc.mappingio.adapter.MappingNsCompleter; | ||||
| import net.fabricmc.mappingio.format.Tiny2Reader; | ||||
| 
 | ||||
| public record IntermediaryMappingLayer(File tinyFile) implements MappingLayer { | ||||
| 	@Override | ||||
| 	public MappingNamespace getSourceNamespace() { | ||||
| 		return MappingNamespace.OFFICIAL; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void visit(MappingVisitor mappingVisitor) throws IOException { | ||||
| 		// Populate named with intermediary and add Add a "named" namespace | ||||
| 		MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true); | ||||
| 
 | ||||
| 		try (BufferedReader reader = Files.newBufferedReader(tinyFile().toPath(), StandardCharsets.UTF_8)) { | ||||
| 			Tiny2Reader.read(reader, nsCompleter); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,35 @@ | |||
| /* | ||||
|  * 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.mappings.intermediary; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingContext; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; | ||||
| 
 | ||||
| public record IntermediaryMappingsSpec() implements MappingsSpec<IntermediaryMappingLayer> { | ||||
| 	@Override | ||||
| 	public IntermediaryMappingLayer createLayer(MappingContext context) { | ||||
| 		return new IntermediaryMappingLayer(context.mappingsProvider().intermediaryTinyFile()); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,102 @@ | |||
| /* | ||||
|  * 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.mappings.mojmap; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.gradle.api.logging.Logger; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer; | ||||
| import net.fabricmc.loom.util.HashedDownloadUtil; | ||||
| import net.fabricmc.mappingio.MappingVisitor; | ||||
| import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; | ||||
| import net.fabricmc.mappingio.format.ProGuardReader; | ||||
| 
 | ||||
| public record MojangMappingLayer(MinecraftVersionMeta.Download clientDownload, | ||||
| 									MinecraftVersionMeta.Download serverDownload, | ||||
| 									File workingDir, | ||||
| 									Logger logger) implements MappingLayer { | ||||
| 	@Override | ||||
| 	public void visit(MappingVisitor mappingVisitor) throws IOException { | ||||
| 		var clientMappings = new File(workingDir(), "client.txt"); | ||||
| 		var serverMappings = new File(workingDir(), "server.txt"); | ||||
| 
 | ||||
| 		download(clientMappings, serverMappings); | ||||
| 
 | ||||
| 		printMappingsLicense(clientMappings.toPath()); | ||||
| 
 | ||||
| 		// Make official the source namespace | ||||
| 		MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, MappingNamespace.OFFICIAL.stringValue()); | ||||
| 
 | ||||
| 		try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings.toPath(), StandardCharsets.UTF_8); | ||||
| 				BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings.toPath(), StandardCharsets.UTF_8)) { | ||||
| 			ProGuardReader.read(clientBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch); | ||||
| 			ProGuardReader.read(serverBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void download(File clientMappings, File serverMappings) throws IOException { | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(clientDownload().url()), clientMappings, clientDownload().sha1(), logger(), false); | ||||
| 		HashedDownloadUtil.downloadIfInvalid(new URL(serverDownload().url()), serverMappings, serverDownload().sha1(), logger(), false); | ||||
| 	} | ||||
| 
 | ||||
| 	private void printMappingsLicense(Path clientMappings) { | ||||
| 		try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8)) { | ||||
| 			logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); | ||||
| 			logger().warn("Using of the official minecraft mappings is at your own risk!"); | ||||
| 			logger().warn("Please make sure to read and understand the following license:"); | ||||
| 			logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); | ||||
| 			String line; | ||||
| 
 | ||||
| 			while ((line = clientBufferedReader.readLine()).startsWith("#")) { | ||||
| 				logger().warn(line); | ||||
| 			} | ||||
| 
 | ||||
| 			logger().warn("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); | ||||
| 		} catch (IOException e) { | ||||
| 			throw new RuntimeException("Failed to read client mappings", e); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public MappingNamespace getSourceNamespace() { | ||||
| 		return MappingNamespace.OFFICIAL; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public List<Class<? extends MappingLayer>> dependsOn() { | ||||
| 		return List.of(IntermediaryMappingLayer.class); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,51 @@ | |||
| /* | ||||
|  * 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.mappings.mojmap; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingContext; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; | ||||
| 
 | ||||
| public record MojangMappingsSpec() implements MappingsSpec<MojangMappingLayer> { | ||||
| 	// Keys in dependency manifest | ||||
| 	private static final String MANIFEST_CLIENT_MAPPINGS = "client_mappings"; | ||||
| 	private static final String MANIFEST_SERVER_MAPPINGS = "server_mappings"; | ||||
| 
 | ||||
| 	@Override | ||||
| 	public MojangMappingLayer createLayer(MappingContext context) { | ||||
| 		MinecraftVersionMeta versionInfo = context.minecraftProvider().getVersionInfo(); | ||||
| 
 | ||||
| 		if (versionInfo.download(MANIFEST_CLIENT_MAPPINGS) == null) { | ||||
| 			throw new RuntimeException("Failed to find official mojang mappings for " + context.minecraftVersion()); | ||||
| 		} | ||||
| 
 | ||||
| 		return new MojangMappingLayer( | ||||
| 				versionInfo.download(MANIFEST_CLIENT_MAPPINGS), | ||||
| 				versionInfo.download(MANIFEST_SERVER_MAPPINGS), | ||||
| 				context.workingDirectory("mojang"), | ||||
| 				context.getLogger() | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,63 @@ | |||
| /* | ||||
|  * 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.mappings.parchment; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStreamReader; | ||||
| import java.util.Objects; | ||||
| import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipFile; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradlePlugin; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; | ||||
| import net.fabricmc.mappingio.MappingVisitor; | ||||
| 
 | ||||
| public record ParchmentMappingLayer(File parchmentFile, boolean removePrefix) implements MappingLayer { | ||||
| 	private static final String PARCHMENT_DATA_FILE_NAME = "parchment.json"; | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void visit(MappingVisitor mappingVisitor) throws IOException { | ||||
| 		ParchmentTreeV1 parchmentData = getParchmentData(); | ||||
| 
 | ||||
| 		if (removePrefix()) { | ||||
| 			mappingVisitor = new ParchmentPrefixStripingMappingVisitor(mappingVisitor); | ||||
| 		} | ||||
| 
 | ||||
| 		parchmentData.visit(mappingVisitor, MappingNamespace.NAMED.stringValue()); | ||||
| 	} | ||||
| 
 | ||||
| 	private ParchmentTreeV1 getParchmentData() throws IOException { | ||||
| 		try (var zipFile = new ZipFile(parchmentFile())) { | ||||
| 			ZipEntry zipFileEntry = zipFile.getEntry(PARCHMENT_DATA_FILE_NAME); | ||||
| 			Objects.requireNonNull(zipFileEntry, "Could not find %s in parchment data file".formatted(PARCHMENT_DATA_FILE_NAME)); | ||||
| 
 | ||||
| 			try (var reader = new InputStreamReader(zipFile.getInputStream(zipFileEntry))) { | ||||
| 				return LoomGradlePlugin.OBJECT_MAPPER.readValue(reader, ParchmentTreeV1.class); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,35 @@ | |||
| /* | ||||
|  * 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.mappings.parchment; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingContext; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; | ||||
| 
 | ||||
| public record ParchmentMappingsSpec(String mavenNotation, boolean removePrefix) implements MappingsSpec<ParchmentMappingLayer> { | ||||
| 	@Override | ||||
| 	public ParchmentMappingLayer createLayer(MappingContext context) { | ||||
| 		return new ParchmentMappingLayer(context.mavenFile(mavenNotation()), removePrefix()); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,48 @@ | |||
| /* | ||||
|  * 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.mappings.parchment; | ||||
| 
 | ||||
| public class ParchmentMappingsSpecBuilder { | ||||
| 	private final String mavenNotation; | ||||
| 
 | ||||
| 	private boolean removePrefix; | ||||
| 
 | ||||
| 	private ParchmentMappingsSpecBuilder(String mavenNotation) { | ||||
| 		this.mavenNotation = mavenNotation; | ||||
| 	} | ||||
| 
 | ||||
| 	public static ParchmentMappingsSpecBuilder builder(String depNotation) { | ||||
| 		return new ParchmentMappingsSpecBuilder(depNotation); | ||||
| 	} | ||||
| 
 | ||||
| 	public ParchmentMappingsSpecBuilder setRemovePrefix(boolean removePrefix) { | ||||
| 		this.removePrefix = removePrefix; | ||||
| 		return this; | ||||
| 	} | ||||
| 
 | ||||
| 	public ParchmentMappingsSpec build() { | ||||
| 		return new ParchmentMappingsSpec(mavenNotation, removePrefix); | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,50 @@ | |||
| /* | ||||
|  * 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.mappings.parchment; | ||||
| 
 | ||||
| import java.util.Locale; | ||||
| 
 | ||||
| import net.fabricmc.mappingio.MappingVisitor; | ||||
| import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor; | ||||
| 
 | ||||
| public final class ParchmentPrefixStripingMappingVisitor extends ForwardingMappingVisitor { | ||||
| 	protected ParchmentPrefixStripingMappingVisitor(MappingVisitor next) { | ||||
| 		super(next); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public boolean visitMethodArg(int argPosition, int lvIndex, String srcName) { | ||||
| 		return super.visitMethodArg(argPosition, lvIndex, stripMethodArg(srcName)); | ||||
| 	} | ||||
| 
 | ||||
| 	public static String stripMethodArg(String arg) { | ||||
| 		if (arg.length() > 1 && arg.startsWith("p") && Character.isUpperCase(arg.charAt(1))) { | ||||
| 			String a2 = arg.substring(1); // Remove p | ||||
| 			return a2.substring(0, 1).toLowerCase(Locale.ROOT) + a2.substring(1); // Make first char lowercase | ||||
| 		} | ||||
| 
 | ||||
| 		return arg; | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,165 @@ | |||
| /* | ||||
|  * 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.mappings.parchment; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| 
 | ||||
| import net.fabricmc.mappingio.MappedElementKind; | ||||
| import net.fabricmc.mappingio.MappingVisitor; | ||||
| 
 | ||||
| public record ParchmentTreeV1( | ||||
| 		String version, | ||||
| 		@Nullable | ||||
| 		List<Class> classes, | ||||
| 		@Nullable | ||||
| 		List<Package> packages | ||||
| ) { | ||||
| 	public void visit(MappingVisitor visitor, String srcNamespace) { | ||||
| 		while (true) { | ||||
| 			if (visitor.visitHeader()) { | ||||
| 				visitor.visitNamespaces(srcNamespace, Collections.emptyList()); | ||||
| 			} | ||||
| 
 | ||||
| 			if (visitor.visitContent()) { | ||||
| 				if (classes() != null) { | ||||
| 					for (Class c : classes()) { | ||||
| 						c.visit(visitor); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (visitor.visitEnd()) { | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public record Class( | ||||
| 			String name, | ||||
| 			@Nullable | ||||
| 			List<Field> fields, | ||||
| 			@Nullable | ||||
| 			List<Method> methods, | ||||
| 			@Nullable | ||||
| 			List<String> javadoc | ||||
| 	) { | ||||
| 		public void visit(MappingVisitor visitor) { | ||||
| 			if (visitor.visitClass(name())) { | ||||
| 				if (!visitor.visitElementContent(MappedElementKind.CLASS)) { | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
| 				if (fields() != null) { | ||||
| 					for (Field field : fields()) { | ||||
| 						field.visit(visitor); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				if (methods() != null) { | ||||
| 					for (Method method : methods()) { | ||||
| 						method.visit(visitor); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				if (javadoc() != null) { | ||||
| 					visitor.visitComment(MappedElementKind.CLASS, String.join("\n", javadoc())); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public record Field( | ||||
| 			String name, | ||||
| 			String descriptor, | ||||
| 			@Nullable | ||||
| 			List<String> javadoc | ||||
| 	) { | ||||
| 		public void visit(MappingVisitor visitor) { | ||||
| 			if (visitor.visitField(name, descriptor)) { | ||||
| 				if (!visitor.visitElementContent(MappedElementKind.FIELD)) { | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
| 				if (javadoc() != null) { | ||||
| 					visitor.visitComment(MappedElementKind.FIELD, String.join("\n", javadoc())); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public record Method( | ||||
| 			String name, | ||||
| 			String descriptor, | ||||
| 			@Nullable | ||||
| 			List<Parameter> parameters, | ||||
| 			@Nullable | ||||
| 			List<String> javadoc | ||||
| 	) { | ||||
| 		public void visit(MappingVisitor visitor) { | ||||
| 			if (visitor.visitMethod(name, descriptor)) { | ||||
| 				if (!visitor.visitElementContent(MappedElementKind.METHOD)) { | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
| 				if (parameters() != null) { | ||||
| 					for (Parameter parameter : parameters()) { | ||||
| 						parameter.visit(visitor); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				if (javadoc() != null) { | ||||
| 					visitor.visitComment(MappedElementKind.METHOD, String.join("\n", javadoc())); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public record Parameter( | ||||
| 			int index, | ||||
| 			String name, | ||||
| 			@Nullable | ||||
| 			String javadoc | ||||
| 	) { | ||||
| 		public void visit(MappingVisitor visitor) { | ||||
| 			if (visitor.visitMethodArg(index, index, name)) { | ||||
| 				if (!visitor.visitElementContent(MappedElementKind.METHOD_ARG)) { | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
| 				if (javadoc() != null) { | ||||
| 					visitor.visitComment(MappedElementKind.METHOD_ARG, javadoc); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public record Package( | ||||
| 			String name, | ||||
| 			List<String> javadoc | ||||
| 	) { } | ||||
| } | ||||
|  | @ -29,13 +29,13 @@ import java.io.File; | |||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| 
 | ||||
| public class MinecraftLibraryProvider { | ||||
| 	public File MINECRAFT_LIBS; | ||||
| 
 | ||||
| 	public void provide(MinecraftProvider minecraftProvider, Project project) { | ||||
| 	public void provide(MinecraftProviderImpl minecraftProvider, Project project) { | ||||
| 		MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); | ||||
| 
 | ||||
| 		initFiles(project, minecraftProvider); | ||||
|  | @ -47,7 +47,7 @@ public class MinecraftLibraryProvider { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void initFiles(Project project, MinecraftProvider minecraftProvider) { | ||||
| 	private void initFiles(Project project, MinecraftProviderImpl minecraftProvider) { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); | ||||
| 	} | ||||
|  |  | |||
|  | @ -36,8 +36,8 @@ import com.google.common.collect.ImmutableMap; | |||
| import org.gradle.api.Project; | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.DependencyProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | ||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||
|  | @ -53,7 +53,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | |||
| 	private File minecraftMappedJar; | ||||
| 	private File minecraftIntermediaryJar; | ||||
| 
 | ||||
| 	private MinecraftProvider minecraftProvider; | ||||
| 	private MinecraftProviderImpl minecraftProvider; | ||||
| 
 | ||||
| 	public MinecraftMappedProvider(Project project) { | ||||
| 		super(project); | ||||
|  | @ -101,7 +101,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | |||
| 	private void mapMinecraftJar() throws IOException { | ||||
| 		String fromM = "official"; | ||||
| 
 | ||||
| 		MappingsProvider mappingsProvider = getExtension().getMappingsProvider(); | ||||
| 		MappingsProviderImpl mappingsProvider = getExtension().getMappingsProvider(); | ||||
| 
 | ||||
| 		Path input = minecraftProvider.getMergedJar().toPath(); | ||||
| 		Path outputMapped = minecraftMappedJar.toPath(); | ||||
|  | @ -148,7 +148,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | |||
| 				getProject().getDependencies().module("net.minecraft:minecraft:" + getJarVersionString("mapped"))); | ||||
| 	} | ||||
| 
 | ||||
| 	public void initFiles(MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { | ||||
| 	public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) { | ||||
| 		this.minecraftProvider = minecraftProvider; | ||||
| 		minecraftIntermediaryJar = new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("intermediary") + ".jar"); | ||||
| 		minecraftMappedJar = new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("mapped") + ".jar"); | ||||
|  | @ -159,7 +159,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | |||
| 	} | ||||
| 
 | ||||
| 	protected String getJarVersionString(String type) { | ||||
| 		return String.format("%s-%s-%s-%s", minecraftProvider.getMinecraftVersion(), type, getExtension().getMappingsProvider().mappingsName, getExtension().getMappingsProvider().mappingsVersion); | ||||
| 		return String.format("%s-%s-%s-%s", minecraftProvider.minecraftVersion(), type, getExtension().getMappingsProvider().mappingsName, getExtension().getMappingsProvider().mappingsVersion); | ||||
| 	} | ||||
| 
 | ||||
| 	public File getIntermediaryJar() { | ||||
|  |  | |||
|  | @ -41,14 +41,14 @@ 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.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.HashedDownloadUtil; | ||||
| import net.fabricmc.loom.util.gradle.ProgressLogger; | ||||
| 
 | ||||
| public class MinecraftAssetsProvider { | ||||
| 	public static void provide(MinecraftProvider minecraftProvider, Project project) throws IOException { | ||||
| 	public static void provide(MinecraftProviderImpl minecraftProvider, Project project) throws IOException { | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		boolean offline = project.getGradle().getStartParameter().isOffline(); | ||||
| 
 | ||||
|  | @ -62,7 +62,7 @@ public class MinecraftAssetsProvider { | |||
| 			assets.mkdirs(); | ||||
| 		} | ||||
| 
 | ||||
| 		File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.fabricId(minecraftProvider.getMinecraftVersion()) + ".json"); | ||||
| 		File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.fabricId(minecraftProvider.minecraftVersion()) + ".json"); | ||||
| 
 | ||||
| 		project.getLogger().info(":downloading asset index"); | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ import org.gradle.api.tasks.TaskAction; | |||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.api.decompilers.DecompilationMetadata; | ||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.decompilers.LineNumberRemapper; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.gradle.ProgressLogger; | ||||
|  | @ -102,7 +102,7 @@ public class GenerateSourcesTask extends AbstractLoomTask { | |||
| 
 | ||||
| 	private File getMappedJarFileWithSuffix(String suffix) { | ||||
| 		LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 		File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||
| 		String path = mappedJar.getAbsolutePath(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ import org.gradle.api.tasks.TaskContainer; | |||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||
| import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler; | ||||
| 
 | ||||
| public final class LoomTasks { | ||||
|  | @ -113,7 +113,7 @@ public final class LoomTasks { | |||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 
 | ||||
| 		project.afterEvaluate(p -> { | ||||
| 			MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 			MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 			File inputJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||
| 
 | ||||
| 			if (mappingsProvider.hasUnpickDefinitions()) { | ||||
|  |  | |||
|  | @ -49,9 +49,10 @@ import org.gradle.api.tasks.TaskAction; | |||
| import org.gradle.api.tasks.options.Option; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; | ||||
| import net.fabricmc.loom.util.SourceRemapper; | ||||
| import net.fabricmc.lorenztiny.TinyMappingsJoiner; | ||||
| import net.fabricmc.mapping.tree.TinyMappingFactory; | ||||
|  | @ -96,7 +97,7 @@ public class MigrateMappingsTask extends AbstractLoomTask { | |||
| 		Files.createDirectories(outputDir); | ||||
| 
 | ||||
| 		File mappings = loadMappings(); | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
| 		try { | ||||
| 			TinyTree currentMappings = mappingsProvider.getMappings(); | ||||
|  | @ -118,12 +119,13 @@ public class MigrateMappingsTask extends AbstractLoomTask { | |||
| 		Set<File> files; | ||||
| 
 | ||||
| 		try { | ||||
| 			if (mappings.startsWith(MojangMappingsDependency.GROUP + ':' + MojangMappingsDependency.MODULE + ':') || mappings.startsWith("net.mojang.minecraft:mappings:")) { | ||||
| 				if (!mappings.endsWith(":" + project.getExtensions().getByType(LoomGradleExtension.class).getMinecraftProvider().getMinecraftVersion())) { | ||||
| 			if (mappings.startsWith("net.minecraft:mappings:") || mappings.startsWith("net.mojang.minecraft:mappings:")) { | ||||
| 				if (!mappings.endsWith(":" + project.getExtensions().getByType(LoomGradleExtension.class).getMinecraftProvider().minecraftVersion())) { | ||||
| 					throw new UnsupportedOperationException("Migrating Mojang mappings is currently only supported for the specified minecraft version"); | ||||
| 				} | ||||
| 
 | ||||
| 				files = new MojangMappingsDependency(project, getExtension()).resolve(); | ||||
| 				LayeredMappingsDependency dep = (LayeredMappingsDependency) getExtension().layered(LayeredMappingSpecBuilder::officalMojangMappings); | ||||
| 				files = dep.resolve(); | ||||
| 			} else { | ||||
| 				Dependency dependency = project.getDependencies().create(mappings); | ||||
| 				files = project.getConfigurations().detachedConfiguration(dependency).resolve(); | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ import net.fabricmc.loom.build.nesting.MergedNestedJarProvider; | |||
| import net.fabricmc.loom.build.nesting.NestedDependencyProvider; | ||||
| import net.fabricmc.loom.build.nesting.NestedJarProvider; | ||||
| import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | ||||
| import net.fabricmc.loom.util.ZipReprocessorUtil; | ||||
|  | @ -113,7 +113,7 @@ public class RemapJarTask extends Jar { | |||
| 			throw new FileNotFoundException(input.toString()); | ||||
| 		} | ||||
| 
 | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
| 		String fromM = "named"; | ||||
| 		String toM = "intermediary"; | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ import org.zeroturnaround.zip.ZipUtil; | |||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.configuration.RemappedConfigurationEntry; | ||||
| import net.fabricmc.loom.configuration.providers.LaunchProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.util.gradle.ProgressLogger; | ||||
| import net.fabricmc.lorenztiny.TinyMappingsReader; | ||||
| import net.fabricmc.mapping.tree.TinyTree; | ||||
|  | @ -163,7 +163,7 @@ public class SourceRemapper { | |||
| 		} | ||||
| 
 | ||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | ||||
| 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
| 		MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> { | ||||
| 			try { | ||||
|  |  | |||
|  | @ -0,0 +1,52 @@ | |||
| /* | ||||
|  * 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.test.integration | ||||
| 
 | ||||
| import net.fabricmc.loom.test.util.ProjectTestTrait | ||||
| import spock.lang.Specification | ||||
| import spock.lang.Unroll | ||||
| 
 | ||||
| import static org.gradle.testkit.runner.TaskOutcome.SUCCESS | ||||
| 
 | ||||
| class ParchmentTest extends Specification implements ProjectTestTrait { | ||||
| 	@Override | ||||
| 	String name() { | ||||
| 		"parchment" | ||||
| 	} | ||||
| 
 | ||||
| 	@Unroll | ||||
| 	def "parchment #gradle"() { | ||||
| 		when: | ||||
| 			def result = create("build", gradle) | ||||
| 
 | ||||
| 		then: | ||||
| 			result.task(":build").outcome == SUCCESS | ||||
| 
 | ||||
| 		where: | ||||
| 			gradle              | _ | ||||
| 			DEFAULT_GRADLE      | _ | ||||
| 			PRE_RELEASE_GRADLE  | _ | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,43 @@ | |||
| /* | ||||
|  * 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.test.unit.layeredmappings | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec | ||||
| 
 | ||||
| class IntermediaryMappingLayerTest extends LayeredMappingsSpecification { | ||||
|     def "Read intermediary mappings" () { | ||||
|         setup: | ||||
|             mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_17_URL, "intermediary.jar"), "mappings/mappings.tiny") | ||||
|         when: | ||||
|             def mappings = getSingleMapping(new IntermediaryMappingsSpec()) | ||||
|             def tiny = getTiny(mappings) | ||||
|         then: | ||||
|             mappings.srcNamespace == "official" | ||||
|             mappings.dstNamespaces == ["intermediary", "named"] | ||||
|             mappings.classes.size() == 6107 | ||||
|             mappings.getClass("abc").getDstName(0) == "net/minecraft/class_3191" | ||||
|             mappings.getClass("abc").getDstName(1) == "net/minecraft/class_3191" | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,118 @@ | |||
| /* | ||||
|  * 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.test.unit.layeredmappings | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder | ||||
| import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec | ||||
| import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec | ||||
| import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec | ||||
| import org.gradle.api.Action | ||||
| import org.gradle.util.ConfigureUtil | ||||
| import spock.lang.Specification | ||||
| 
 | ||||
| class LayeredMappingSpecBuilderTest extends Specification { | ||||
|     def "simple mojmap" () { | ||||
|         when: | ||||
|             def spec = layered() { | ||||
|                 officalMojangMappings() | ||||
|             } | ||||
|             def layers = spec.layers() | ||||
|         then: | ||||
|             spec.version == "layered+hash.961" | ||||
|             layers.size() == 2 | ||||
|             layers[0].class == IntermediaryMappingsSpec | ||||
|             layers[1].class == MojangMappingsSpec | ||||
|     } | ||||
| 
 | ||||
|     def "simple mojmap with parchment" () { | ||||
|         when: | ||||
|             def spec = layered() { | ||||
|                 officalMojangMappings() | ||||
|                 parchment("I like cake") | ||||
|             } | ||||
|             def layers = spec.layers() | ||||
|             def parchment = layers[2] as ParchmentMappingsSpec | ||||
|         then: | ||||
|             spec.version == "layered+hash.863714404" | ||||
|             layers.size() == 3 | ||||
|             layers[0].class == IntermediaryMappingsSpec | ||||
|             layers[1].class == MojangMappingsSpec | ||||
|             layers[2].class == ParchmentMappingsSpec | ||||
|             parchment.mavenNotation() == "I like cake" | ||||
|             parchment.removePrefix() == true | ||||
|     } | ||||
| 
 | ||||
|     def "simple mojmap with parchment keep prefix" () { | ||||
|         when: | ||||
|             def spec = layered() { | ||||
|                 officalMojangMappings() | ||||
|                 parchment("I like cake") { | ||||
|                     it.removePrefix = false | ||||
|                 } | ||||
|             } | ||||
|             def layers = spec.layers() | ||||
|             def parchment = layers[2] as ParchmentMappingsSpec | ||||
|         then: | ||||
|             spec.version == "layered+hash.863714410" | ||||
|             layers.size() == 3 | ||||
|             layers[0].class == IntermediaryMappingsSpec | ||||
|             layers[1].class == MojangMappingsSpec | ||||
|             layers[2].class == ParchmentMappingsSpec | ||||
|             parchment.mavenNotation() == "I like cake" | ||||
|             parchment.removePrefix() == false | ||||
|     } | ||||
| 
 | ||||
|     def "simple mojmap with parchment keep prefix alternate hash" () { | ||||
|         when: | ||||
|             def spec = layered() { | ||||
|                 officalMojangMappings() | ||||
|                 parchment("I really like cake") { | ||||
|                     it.removePrefix = false | ||||
|                 } | ||||
|             } | ||||
|             def layers = spec.layers() | ||||
|             def parchment = layers[2] as ParchmentMappingsSpec | ||||
|         then: | ||||
|             spec.version == "layered+hash.1144465487" | ||||
|             layers.size() == 3 | ||||
|             layers[0].class == IntermediaryMappingsSpec | ||||
|             layers[1].class == MojangMappingsSpec | ||||
|             layers[2].class == ParchmentMappingsSpec | ||||
|             parchment.mavenNotation() == "I really like cake" | ||||
|             parchment.removePrefix() == false | ||||
|     } | ||||
| 
 | ||||
|     // Gradle does this big of magic behind the scenes | ||||
|     LayeredMappingSpec layered(@DelegatesTo(LayeredMappingSpecBuilder) Closure cl) { | ||||
|         return layeredAction(ConfigureUtil.configureUsing(cl)) | ||||
|     } | ||||
| 
 | ||||
|     LayeredMappingSpec layeredAction(Action<LayeredMappingSpecBuilder> action) { | ||||
|         LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder() | ||||
|         action.execute(builder) | ||||
|         return builder.build() | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,121 @@ | |||
| /* | ||||
|  * 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.test.unit.layeredmappings | ||||
| 
 | ||||
| import groovy.transform.CompileStatic | ||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec | ||||
| import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsProcessor | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingContext | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingLayer | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec | ||||
| import net.fabricmc.mappingio.format.Tiny2Writer | ||||
| import net.fabricmc.mappingio.tree.MappingTree | ||||
| import net.fabricmc.mappingio.tree.MemoryMappingTree | ||||
| import org.gradle.api.logging.Logger | ||||
| import spock.lang.Specification | ||||
| 
 | ||||
| import java.util.zip.ZipFile | ||||
| 
 | ||||
| abstract class LayeredMappingsSpecification extends Specification implements LayeredMappingsTestConstants { | ||||
|     Logger mockLogger = Mock(Logger) | ||||
|     MappingsProvider mockMappingsProvider = Mock(MappingsProvider) | ||||
|     MinecraftProvider mockMinecraftProvider = Mock(MinecraftProvider) | ||||
| 
 | ||||
|     MappingContext mappingContext = new TestMappingContext() | ||||
| 
 | ||||
|     File tempDir = File.createTempDir() | ||||
| 
 | ||||
|     Map<String, File> mavenFiles = [:] | ||||
| 
 | ||||
|     def withMavenFile(String mavenNotation, File file) { | ||||
|         mavenFiles.put(mavenNotation, file) | ||||
|     } | ||||
| 
 | ||||
|     File downloadFile(String url, String name) { | ||||
|         File dst = new File(tempDir, name) | ||||
|         dst.parentFile.mkdirs() | ||||
|         dst << new URL(url).newInputStream() | ||||
|         return dst | ||||
|     } | ||||
| 
 | ||||
|     File extractFileFromZip(File zipFile, String name) { | ||||
|         File dst = new File(tempDir, name) | ||||
|         dst.parentFile.mkdirs() | ||||
| 
 | ||||
|         new ZipFile(zipFile).withCloseable { | ||||
|             dst << it.getInputStream(it.getEntry(name)) | ||||
|         } | ||||
|         return dst | ||||
|     } | ||||
| 
 | ||||
|     MemoryMappingTree getSingleMapping(MappingsSpec<? extends MappingLayer> spec) { | ||||
|         MemoryMappingTree mappingTree = new MemoryMappingTree() | ||||
|         spec.createLayer(mappingContext).visit(mappingTree) | ||||
|         return mappingTree | ||||
|     } | ||||
| 
 | ||||
|     MemoryMappingTree getLayeredMappings(MappingsSpec<? extends MappingLayer>... specs) { | ||||
|         LayeredMappingSpec spec = new LayeredMappingSpec(specs.toList()) | ||||
|         LayeredMappingsProcessor processor = new LayeredMappingsProcessor(spec) | ||||
|         return processor.getMappings(mappingContext) | ||||
|     } | ||||
| 
 | ||||
|     String getTiny(MemoryMappingTree mappingTree) { | ||||
|         def sw = new StringWriter() | ||||
|         mappingTree.accept(new Tiny2Writer(sw, false)) | ||||
|         return sw.toString() | ||||
|     } | ||||
| 
 | ||||
|     @CompileStatic | ||||
|     class TestMappingContext implements MappingContext { | ||||
|         @Override | ||||
|         File mavenFile(String mavenNotation) { | ||||
|             assert mavenFiles.containsKey(mavenNotation) | ||||
|             return mavenFiles.get(mavenNotation) | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         MappingsProvider mappingsProvider() { | ||||
|             return mockMappingsProvider | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         MinecraftProvider minecraftProvider() { | ||||
|             return mockMinecraftProvider | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         File workingDirectory(String name) { | ||||
|             return new File(tempDir, name) | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         Logger getLogger() { | ||||
|             return mockLogger | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,47 @@ | |||
| /* | ||||
|  * 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.test.unit.layeredmappings | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta | ||||
| 
 | ||||
| interface LayeredMappingsTestConstants { | ||||
|     public static final String INTERMEDIARY_1_17_URL = "https://maven.fabricmc.net/net/fabricmc/intermediary/1.17/intermediary-1.17-v2.jar" | ||||
|     public static final String INTERMEDIARY_1_16_5_URL = "https://maven.fabricmc.net/net/fabricmc/intermediary/1.16.5/intermediary-1.16.5-v2.jar" | ||||
| 
 | ||||
|     public static final Map<String, MinecraftVersionMeta.Download> DOWNLOADS_1_17 = [ | ||||
|             client_mappings:new MinecraftVersionMeta.Download(null, "227d16f520848747a59bef6f490ae19dc290a804", 6431705, "https://launcher.mojang.com/v1/objects/227d16f520848747a59bef6f490ae19dc290a804/client.txt"), | ||||
|             server_mappings:new MinecraftVersionMeta.Download(null, "84d80036e14bc5c7894a4fad9dd9f367d3000334", 4948536, "https://launcher.mojang.com/v1/objects/84d80036e14bc5c7894a4fad9dd9f367d3000334/server.txt") | ||||
|     ] | ||||
|     public static final MinecraftVersionMeta VERSION_META_1_17 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_17, null, null, null, null, 0, null, null, null) | ||||
| 
 | ||||
|     public static final Map<String, MinecraftVersionMeta.Download> DOWNLOADS_1_16_5 = [ | ||||
|             client_mappings:new MinecraftVersionMeta.Download(null, "e3dfb0001e1079a1af72ee21517330edf52e6192", 5746047, "https://launcher.mojang.com/v1/objects/e3dfb0001e1079a1af72ee21517330edf52e6192/client.txt"), | ||||
|             server_mappings:new MinecraftVersionMeta.Download(null, "81d5c793695d8cde63afddb40dde88e3a88132ac", 4400926, "https://launcher.mojang.com/v1/objects/81d5c793695d8cde63afddb40dde88e3a88132ac/server.txt") | ||||
|     ] | ||||
|     public static final MinecraftVersionMeta VERSION_META_1_16_5 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_16_5, null, null, null, null, 0, null, null, null) | ||||
| 
 | ||||
|     public static final String PARCHMENT_NOTATION = "org.parchmentmc.data:parchment-1.16.5:20210608-SNAPSHOT@zip" | ||||
|     public static final String PARCHMENT_URL = "https://ldtteam.jfrog.io/artifactory/parchmentmc-snapshots/org/parchmentmc/data/parchment-1.16.5/20210608-SNAPSHOT/parchment-1.16.5-20210608-SNAPSHOT.zip" | ||||
| } | ||||
|  | @ -0,0 +1,49 @@ | |||
| /* | ||||
|  * 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.test.unit.layeredmappings | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec | ||||
| import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec | ||||
| 
 | ||||
| class MojangMappingLayerTest extends LayeredMappingsSpecification { | ||||
|     def "Read mojang mappings" () { | ||||
|         setup: | ||||
|             mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_17_URL, "intermediary.jar"), "mappings/mappings.tiny") | ||||
|             mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17 | ||||
|         when: | ||||
|             def mappings = getLayeredMappings( | ||||
|                     new IntermediaryMappingsSpec(), | ||||
|                     new MojangMappingsSpec() | ||||
|             ) | ||||
|             def tiny = getTiny(mappings) | ||||
|         then: | ||||
|             mappings.srcNamespace == "named" | ||||
|             mappings.dstNamespaces == ["intermediary", "official"] | ||||
|             mappings.classes.size() == 6113 | ||||
|             mappings.classes[0].srcName.hashCode() == 1869546970 // MojMap name, just check the hash | ||||
|             mappings.classes[0].getDstName(0) == "net/minecraft/class_2354" | ||||
|             mappings.classes[0].methods[0].args.size() == 0 // No Args | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,74 @@ | |||
| /* | ||||
|  * 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.test.unit.layeredmappings | ||||
| 
 | ||||
| import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec | ||||
| import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec | ||||
| import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec | ||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta | ||||
| 
 | ||||
| class ParchmentMappingLayerTest extends LayeredMappingsSpecification { | ||||
|     def "Read parchment mappings" () { | ||||
|         setup: | ||||
|             mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_16_5_URL, "intermediary.jar"), "mappings/mappings.tiny") | ||||
|             mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5 | ||||
|         when: | ||||
|             withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip")) | ||||
|             def mappings = getLayeredMappings( | ||||
|                     new IntermediaryMappingsSpec(), | ||||
|                     new MojangMappingsSpec(), | ||||
|                     new ParchmentMappingsSpec(PARCHMENT_NOTATION, false) | ||||
|             ) | ||||
|             def tiny = getTiny(mappings) | ||||
|         then: | ||||
|             mappings.srcNamespace == "named" | ||||
|             mappings.dstNamespaces == ["intermediary", "official"] | ||||
|             mappings.classes.size() == 5747 | ||||
|             mappings.classes[0].srcName.hashCode() == -1112444138 // MojMap name, just check the hash | ||||
|             mappings.classes[0].getDstName(0) == "net/minecraft/class_2573" | ||||
|             mappings.classes[0].methods[0].args[0].srcName == "pStack" | ||||
|     } | ||||
| 
 | ||||
|     def "Read parchment mappings remove prefix" () { | ||||
|         setup: | ||||
|             mockMappingsProvider.intermediaryTinyFile() >> extractFileFromZip(downloadFile(INTERMEDIARY_1_16_5_URL, "intermediary.jar"), "mappings/mappings.tiny") | ||||
|             mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_16_5 | ||||
|         when: | ||||
|             withMavenFile(PARCHMENT_NOTATION, downloadFile(PARCHMENT_URL, "parchment.zip")) | ||||
|             def mappings = getLayeredMappings( | ||||
|                     new IntermediaryMappingsSpec(), | ||||
|                     new MojangMappingsSpec(), | ||||
|                     new ParchmentMappingsSpec(PARCHMENT_NOTATION, true) | ||||
|             ) | ||||
|             def tiny = getTiny(mappings) | ||||
|         then: | ||||
|             mappings.srcNamespace == "named" | ||||
|             mappings.dstNamespaces == ["intermediary", "official"] | ||||
|             mappings.classes.size() == 5747 | ||||
|             mappings.classes[0].srcName.hashCode() == -1112444138 // MojMap name, just check the hash | ||||
|             mappings.classes[0].getDstName(0) == "net/minecraft/class_2573" | ||||
|             mappings.classes[0].methods[0].args[0].srcName == "stack" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								src/test/resources/projects/parchment/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/test/resources/projects/parchment/build.gradle
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| plugins { | ||||
| 	id 'fabric-loom' | ||||
| } | ||||
| 
 | ||||
| repositories { | ||||
| 	maven { | ||||
| 		name = "ldtteam" | ||||
| 		url = "https://ldtteam.jfrog.io/artifactory/parchmentmc-snapshots/" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
| 	minecraft "com.mojang:minecraft:1.16.5" | ||||
| 	mappings loom.layered() { | ||||
| 		officalMojangMappings() | ||||
| 		parchment("org.parchmentmc.data:parchment-1.16.5:20210608-SNAPSHOT@zip") | ||||
| 	} | ||||
| 
 | ||||
| 	modImplementation "net.fabricmc:fabric-loader:0.11.3" | ||||
| } | ||||
		Loading…
	
		Reference in a new issue