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 | 	compileClasspath.extendsFrom bootstrap | ||||||
| 	runtimeClasspath.extendsFrom bootstrap | 	runtimeClasspath.extendsFrom bootstrap | ||||||
|  | 	testRuntimeClasspath.extendsFrom bootstrap | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| dependencies { | dependencies { | ||||||
|  | @ -74,6 +75,7 @@ dependencies { | ||||||
| 	implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17') | 	implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17') | ||||||
| 
 | 
 | ||||||
| 	implementation 'net.fabricmc:access-widener:1.0.0' | 	implementation 'net.fabricmc:access-widener:1.0.0' | ||||||
|  | 	implementation 'net.fabricmc:mapping-io:0.1.3' | ||||||
| 
 | 
 | ||||||
| 	implementation ('net.fabricmc:lorenz-tiny:3.0.0') { | 	implementation ('net.fabricmc:lorenz-tiny:3.0.0') { | ||||||
| 		transitive = false | 		transitive = false | ||||||
|  | @ -92,7 +94,7 @@ dependencies { | ||||||
| 
 | 
 | ||||||
| 	// Testing | 	// Testing | ||||||
| 	testImplementation(gradleTestKit()) | 	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' | 		exclude module: 'groovy-all' | ||||||
| 	} | 	} | ||||||
| 	testImplementation 'io.javalin:javalin:3.13.7' | 	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.ide.RunConfigSettings; | ||||||
| import net.fabricmc.loom.configuration.processors.JarProcessor; | import net.fabricmc.loom.configuration.processors.JarProcessor; | ||||||
| import net.fabricmc.loom.configuration.processors.JarProcessorManager; | import net.fabricmc.loom.configuration.processors.JarProcessorManager; | ||||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; |  | ||||||
| import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency; |  | ||||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | 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 class LoomGradleExtension { | ||||||
| 	public String refmapName; | 	public String refmapName; | ||||||
|  | @ -114,7 +117,14 @@ public class LoomGradleExtension { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public Dependency officialMojangMappings() { | 	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) { | 	public LoomGradleExtension(Project project) { | ||||||
|  | @ -246,7 +256,7 @@ public class LoomGradleExtension { | ||||||
| 			return new File((String) project.property("fabric.loom.natives.dir")); | 			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()) { | 		if (!natives.exists()) { | ||||||
| 			natives.mkdirs(); | 			natives.mkdirs(); | ||||||
|  | @ -271,16 +281,16 @@ public class LoomGradleExtension { | ||||||
| 		return dependencyManager; | 		return dependencyManager; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public MinecraftProvider getMinecraftProvider() { | 	public MinecraftProviderImpl getMinecraftProvider() { | ||||||
| 		return getDependencyManager().getProvider(MinecraftProvider.class); | 		return getDependencyManager().getProvider(MinecraftProviderImpl.class); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public MinecraftMappedProvider getMinecraftMappedProvider() { | 	public MinecraftMappedProvider getMinecraftMappedProvider() { | ||||||
| 		return getMappingsProvider().mappedProvider; | 		return getMappingsProvider().mappedProvider; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public MappingsProvider getMappingsProvider() { | 	public MappingsProviderImpl getMappingsProvider() { | ||||||
| 		return getDependencyManager().getProvider(MappingsProvider.class); | 		return getDependencyManager().getProvider(MappingsProviderImpl.class); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void setDependencyManager(LoomDependencyManager dependencyManager) { | 	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 | 	// 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 | 	// Required as now when using parallel builds the old single file could be written by another sourceset compile task | ||||||
| 	public synchronized File getNextMixinMappings() { | 	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); | 		mixinMappings.add(mixinMapping); | ||||||
| 		return 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.build.mixin.ScalaApInvoker; | ||||||
| import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs; | import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs; | ||||||
| import net.fabricmc.loom.configuration.providers.LaunchProvider; | import net.fabricmc.loom.configuration.providers.LaunchProvider; | ||||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||||
| 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.Constants; | ||||||
| 
 | 
 | ||||||
| public final class CompileConfiguration { | public final class CompileConfiguration { | ||||||
|  | @ -116,8 +116,8 @@ public final class CompileConfiguration { | ||||||
| 			LoomDependencyManager dependencyManager = new LoomDependencyManager(); | 			LoomDependencyManager dependencyManager = new LoomDependencyManager(); | ||||||
| 			extension.setDependencyManager(dependencyManager); | 			extension.setDependencyManager(dependencyManager); | ||||||
| 
 | 
 | ||||||
| 			dependencyManager.addProvider(new MinecraftProvider(project)); | 			dependencyManager.addProvider(new MinecraftProviderImpl(project)); | ||||||
| 			dependencyManager.addProvider(new MappingsProvider(project)); | 			dependencyManager.addProvider(new MappingsProviderImpl(project)); | ||||||
| 			dependencyManager.addProvider(new LaunchProvider(project)); | 			dependencyManager.addProvider(new LaunchProvider(project)); | ||||||
| 
 | 
 | ||||||
| 			dependencyManager.handleDependencies(project); | 			dependencyManager.handleDependencies(project); | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.build.ModCompileRemapper; | import net.fabricmc.loom.build.ModCompileRemapper; | ||||||
| import net.fabricmc.loom.configuration.DependencyProvider.DependencyInfo; | import net.fabricmc.loom.configuration.DependencyProvider.DependencyInfo; | ||||||
| import net.fabricmc.loom.configuration.mods.ModProcessor; | 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.Constants; | ||||||
| import net.fabricmc.loom.util.SourceRemapper; | import net.fabricmc.loom.util.SourceRemapper; | ||||||
| import net.fabricmc.loom.LoomRepositoryPlugin; | import net.fabricmc.loom.LoomRepositoryPlugin; | ||||||
|  | @ -86,7 +86,7 @@ public class LoomDependencyManager { | ||||||
| 	public void handleDependencies(Project project) { | 	public void handleDependencies(Project project) { | ||||||
| 		List<Runnable> afterTasks = new ArrayList<>(); | 		List<Runnable> afterTasks = new ArrayList<>(); | ||||||
| 
 | 
 | ||||||
| 		MappingsProvider mappingsProvider = null; | 		MappingsProviderImpl mappingsProvider = null; | ||||||
| 
 | 
 | ||||||
| 		project.getLogger().info(":setting up loom dependencies"); | 		project.getLogger().info(":setting up loom dependencies"); | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | @ -100,8 +100,8 @@ public class LoomDependencyManager { | ||||||
| 				return list; | 				return list; | ||||||
| 			}).providers.add(provider); | 			}).providers.add(provider); | ||||||
| 
 | 
 | ||||||
| 			if (provider instanceof MappingsProvider) { | 			if (provider instanceof MappingsProviderImpl) { | ||||||
| 				mappingsProvider = (MappingsProvider) provider; | 				mappingsProvider = (MappingsProviderImpl) provider; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.LoomGradlePlugin; | import net.fabricmc.loom.LoomGradlePlugin; | ||||||
| import net.fabricmc.loom.configuration.RemappedConfigurationEntry; | import net.fabricmc.loom.configuration.RemappedConfigurationEntry; | ||||||
| import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo; | 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.configuration.providers.minecraft.MinecraftMappedProvider; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
| import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | ||||||
|  | @ -132,7 +132,7 @@ public class ModProcessor { | ||||||
| 		String toM = "named"; | 		String toM = "named"; | ||||||
| 
 | 
 | ||||||
| 		MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider(); | 		MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider(); | ||||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||||
| 
 | 
 | ||||||
| 		Path mc = mappedProvider.getIntermediaryJar().toPath(); | 		Path mc = mappedProvider.getIntermediaryJar().toPath(); | ||||||
| 		Path[] mcDeps = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles() | 		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.apache.commons.io.FileUtils; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||||
| 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.configuration.providers.minecraft.MinecraftMappedProvider; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
| 
 | 
 | ||||||
|  | @ -84,7 +84,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public void initFiles(MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) { | 	public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) { | ||||||
| 		super.initFiles(minecraftProvider, mappingsProvider); | 		super.initFiles(minecraftProvider, mappingsProvider); | ||||||
| 
 | 
 | ||||||
| 		projectMappedJar = new File(getJarDirectory(getExtension().getRootProjectPersistentCache(), projectMappedClassifier), "minecraft-" + getJarVersionString(projectMappedClassifier) + ".jar"); | 		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()) | 				.property("client", "org.lwjgl.librarypath", getExtension().getNativesDirectory().getAbsolutePath()) | ||||||
| 
 | 
 | ||||||
| 				.argument("client", "--assetIndex") | 				.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", "--assetsDir") | ||||||
| 				.argument("client", new File(getExtension().getUserCache(), "assets").getAbsolutePath()); | 				.argument("client", new File(getExtension().getUserCache(), "assets").getAbsolutePath()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,224 +24,10 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.configuration.providers; | 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.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 { | public interface MinecraftProvider { | ||||||
| 	private String minecraftVersion; | 	String minecraftVersion(); | ||||||
| 
 | 
 | ||||||
| 	private MinecraftVersionMeta versionInfo; | 	MinecraftVersionMeta getVersionInfo(); | ||||||
| 	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; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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; | package net.fabricmc.loom.configuration.providers.mappings; | ||||||
| 
 | 
 | ||||||
| import java.io.BufferedReader; |  | ||||||
| import java.io.File; | 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.Path; | ||||||
| import java.nio.file.Paths; |  | ||||||
| import java.nio.file.StandardCopyOption; |  | ||||||
| import java.util.function.Consumer; |  | ||||||
| 
 | 
 | ||||||
| import com.google.common.base.Preconditions; | public interface MappingsProvider { | ||||||
| import com.google.common.net.UrlEscapers; | 	Path getMappingsDir(); | ||||||
| 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; | 	File intermediaryTinyFile(); | ||||||
| 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) { |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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 org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | 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; | import net.fabricmc.loom.util.Constants; | ||||||
| 
 | 
 | ||||||
| public class MinecraftLibraryProvider { | public class MinecraftLibraryProvider { | ||||||
| 	public File MINECRAFT_LIBS; | 	public File MINECRAFT_LIBS; | ||||||
| 
 | 
 | ||||||
| 	public void provide(MinecraftProvider minecraftProvider, Project project) { | 	public void provide(MinecraftProviderImpl minecraftProvider, Project project) { | ||||||
| 		MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); | 		MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); | ||||||
| 
 | 
 | ||||||
| 		initFiles(project, minecraftProvider); | 		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); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); | 		MINECRAFT_LIBS = new File(extension.getUserCache(), "libraries"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -36,8 +36,8 @@ import com.google.common.collect.ImmutableMap; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.configuration.DependencyProvider; | import net.fabricmc.loom.configuration.DependencyProvider; | ||||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||||
| 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.Constants; | ||||||
| import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | ||||||
| import net.fabricmc.tinyremapper.OutputConsumerPath; | import net.fabricmc.tinyremapper.OutputConsumerPath; | ||||||
|  | @ -53,7 +53,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | ||||||
| 	private File minecraftMappedJar; | 	private File minecraftMappedJar; | ||||||
| 	private File minecraftIntermediaryJar; | 	private File minecraftIntermediaryJar; | ||||||
| 
 | 
 | ||||||
| 	private MinecraftProvider minecraftProvider; | 	private MinecraftProviderImpl minecraftProvider; | ||||||
| 
 | 
 | ||||||
| 	public MinecraftMappedProvider(Project project) { | 	public MinecraftMappedProvider(Project project) { | ||||||
| 		super(project); | 		super(project); | ||||||
|  | @ -101,7 +101,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | ||||||
| 	private void mapMinecraftJar() throws IOException { | 	private void mapMinecraftJar() throws IOException { | ||||||
| 		String fromM = "official"; | 		String fromM = "official"; | ||||||
| 
 | 
 | ||||||
| 		MappingsProvider mappingsProvider = getExtension().getMappingsProvider(); | 		MappingsProviderImpl mappingsProvider = getExtension().getMappingsProvider(); | ||||||
| 
 | 
 | ||||||
| 		Path input = minecraftProvider.getMergedJar().toPath(); | 		Path input = minecraftProvider.getMergedJar().toPath(); | ||||||
| 		Path outputMapped = minecraftMappedJar.toPath(); | 		Path outputMapped = minecraftMappedJar.toPath(); | ||||||
|  | @ -148,7 +148,7 @@ public class MinecraftMappedProvider extends DependencyProvider { | ||||||
| 				getProject().getDependencies().module("net.minecraft:minecraft:" + getJarVersionString("mapped"))); | 				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; | 		this.minecraftProvider = minecraftProvider; | ||||||
| 		minecraftIntermediaryJar = new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("intermediary") + ".jar"); | 		minecraftIntermediaryJar = new File(getExtension().getUserCache(), "minecraft-" + getJarVersionString("intermediary") + ".jar"); | ||||||
| 		minecraftMappedJar = new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("mapped") + ".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) { | 	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() { | 	public File getIntermediaryJar() { | ||||||
|  |  | ||||||
|  | @ -41,14 +41,14 @@ import org.gradle.api.Project; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.LoomGradlePlugin; | 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.configuration.providers.minecraft.MinecraftVersionMeta; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
| import net.fabricmc.loom.util.HashedDownloadUtil; | import net.fabricmc.loom.util.HashedDownloadUtil; | ||||||
| import net.fabricmc.loom.util.gradle.ProgressLogger; | import net.fabricmc.loom.util.gradle.ProgressLogger; | ||||||
| 
 | 
 | ||||||
| public class MinecraftAssetsProvider { | 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); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		boolean offline = project.getGradle().getStartParameter().isOffline(); | 		boolean offline = project.getGradle().getStartParameter().isOffline(); | ||||||
| 
 | 
 | ||||||
|  | @ -62,7 +62,7 @@ public class MinecraftAssetsProvider { | ||||||
| 			assets.mkdirs(); | 			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"); | 		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.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.api.decompilers.DecompilationMetadata; | import net.fabricmc.loom.api.decompilers.DecompilationMetadata; | ||||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | 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.decompilers.LineNumberRemapper; | ||||||
| import net.fabricmc.loom.util.Constants; | import net.fabricmc.loom.util.Constants; | ||||||
| import net.fabricmc.loom.util.gradle.ProgressLogger; | import net.fabricmc.loom.util.gradle.ProgressLogger; | ||||||
|  | @ -102,7 +102,7 @@ public class GenerateSourcesTask extends AbstractLoomTask { | ||||||
| 
 | 
 | ||||||
| 	private File getMappedJarFileWithSuffix(String suffix) { | 	private File getMappedJarFileWithSuffix(String suffix) { | ||||||
| 		LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||||
| 		File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | 		File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||||
| 		String path = mappedJar.getAbsolutePath(); | 		String path = mappedJar.getAbsolutePath(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ import org.gradle.api.tasks.TaskContainer; | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||||
| import net.fabricmc.loom.configuration.ide.RunConfigSettings; | 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; | import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler; | ||||||
| 
 | 
 | ||||||
| public final class LoomTasks { | public final class LoomTasks { | ||||||
|  | @ -113,7 +113,7 @@ public final class LoomTasks { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 
 | 
 | ||||||
| 		project.afterEvaluate(p -> { | 		project.afterEvaluate(p -> { | ||||||
| 			MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 			MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||||
| 			File inputJar = mappingsProvider.mappedProvider.getMappedJar(); | 			File inputJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||||
| 
 | 
 | ||||||
| 			if (mappingsProvider.hasUnpickDefinitions()) { | 			if (mappingsProvider.hasUnpickDefinitions()) { | ||||||
|  |  | ||||||
|  | @ -49,9 +49,10 @@ import org.gradle.api.tasks.TaskAction; | ||||||
| import org.gradle.api.tasks.options.Option; | import org.gradle.api.tasks.options.Option; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; | import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||||
| import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependency; |  | ||||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | 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.loom.util.SourceRemapper; | ||||||
| import net.fabricmc.lorenztiny.TinyMappingsJoiner; | import net.fabricmc.lorenztiny.TinyMappingsJoiner; | ||||||
| import net.fabricmc.mapping.tree.TinyMappingFactory; | import net.fabricmc.mapping.tree.TinyMappingFactory; | ||||||
|  | @ -96,7 +97,7 @@ public class MigrateMappingsTask extends AbstractLoomTask { | ||||||
| 		Files.createDirectories(outputDir); | 		Files.createDirectories(outputDir); | ||||||
| 
 | 
 | ||||||
| 		File mappings = loadMappings(); | 		File mappings = loadMappings(); | ||||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||||
| 
 | 
 | ||||||
| 		try { | 		try { | ||||||
| 			TinyTree currentMappings = mappingsProvider.getMappings(); | 			TinyTree currentMappings = mappingsProvider.getMappings(); | ||||||
|  | @ -118,12 +119,13 @@ public class MigrateMappingsTask extends AbstractLoomTask { | ||||||
| 		Set<File> files; | 		Set<File> files; | ||||||
| 
 | 
 | ||||||
| 		try { | 		try { | ||||||
| 			if (mappings.startsWith(MojangMappingsDependency.GROUP + ':' + MojangMappingsDependency.MODULE + ':') || mappings.startsWith("net.mojang.minecraft:mappings:")) { | 			if (mappings.startsWith("net.minecraft:mappings:") || mappings.startsWith("net.mojang.minecraft:mappings:")) { | ||||||
| 				if (!mappings.endsWith(":" + project.getExtensions().getByType(LoomGradleExtension.class).getMinecraftProvider().getMinecraftVersion())) { | 				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"); | 					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 { | 			} else { | ||||||
| 				Dependency dependency = project.getDependencies().create(mappings); | 				Dependency dependency = project.getDependencies().create(mappings); | ||||||
| 				files = project.getConfigurations().detachedConfiguration(dependency).resolve(); | 				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.NestedDependencyProvider; | ||||||
| import net.fabricmc.loom.build.nesting.NestedJarProvider; | import net.fabricmc.loom.build.nesting.NestedJarProvider; | ||||||
| import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; | 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.Constants; | ||||||
| import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | import net.fabricmc.loom.util.TinyRemapperMappingsHelper; | ||||||
| import net.fabricmc.loom.util.ZipReprocessorUtil; | import net.fabricmc.loom.util.ZipReprocessorUtil; | ||||||
|  | @ -113,7 +113,7 @@ public class RemapJarTask extends Jar { | ||||||
| 			throw new FileNotFoundException(input.toString()); | 			throw new FileNotFoundException(input.toString()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||||
| 
 | 
 | ||||||
| 		String fromM = "named"; | 		String fromM = "named"; | ||||||
| 		String toM = "intermediary"; | 		String toM = "intermediary"; | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ import org.zeroturnaround.zip.ZipUtil; | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.configuration.RemappedConfigurationEntry; | import net.fabricmc.loom.configuration.RemappedConfigurationEntry; | ||||||
| import net.fabricmc.loom.configuration.providers.LaunchProvider; | 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.loom.util.gradle.ProgressLogger; | ||||||
| import net.fabricmc.lorenztiny.TinyMappingsReader; | import net.fabricmc.lorenztiny.TinyMappingsReader; | ||||||
| import net.fabricmc.mapping.tree.TinyTree; | import net.fabricmc.mapping.tree.TinyTree; | ||||||
|  | @ -163,7 +163,7 @@ public class SourceRemapper { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 		MappingsProvider mappingsProvider = extension.getMappingsProvider(); | 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||||
| 
 | 
 | ||||||
| 		MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> { | 		MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> { | ||||||
| 			try { | 			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