Support using TinyV2 mappings (#132)
This commit is contained in:
		
							parent
							
								
									baf976d3f3
								
							
						
					
					
						commit
						8e916f8fb0
					
				
					 16 changed files with 451 additions and 214 deletions
				
			
		
							
								
								
									
										13
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								build.gradle
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -39,15 +39,17 @@ dependencies {
 | 
			
		|||
	implementation ('com.google.guava:guava:28.0-jre')
 | 
			
		||||
 | 
			
		||||
	// game handling utils
 | 
			
		||||
	implementation ('net.fabricmc:stitch:0.2.1.60') {
 | 
			
		||||
	implementation ('net.fabricmc:stitch:0.3.0.66') {
 | 
			
		||||
		exclude module: 'enigma'
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// tinyfile management
 | 
			
		||||
	implementation ('net.fabricmc:tiny-remapper:0.1.0.38') {
 | 
			
		||||
	implementation ('net.fabricmc:tiny-remapper:0.2.0.52') {
 | 
			
		||||
		transitive = false
 | 
			
		||||
	}
 | 
			
		||||
	implementation ('net.fabricmc:fabric-mixin-compile-extensions:0.1.0.+')
 | 
			
		||||
	implementation ('net.fabricmc:fabric-mixin-compile-extensions:0.2.0.3'){
 | 
			
		||||
		exclude group :"net.fabricmc"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// decompilers
 | 
			
		||||
	implementation ('net.fabricmc:procyon-fabric-compilertools:0.5.35.+')
 | 
			
		||||
| 
						 | 
				
			
			@ -132,3 +134,8 @@ publishing {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
configurations.all {
 | 
			
		||||
    resolutionStrategy {
 | 
			
		||||
        force 'org.codehaus.groovy:groovy-all:2.4.12'
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,6 +114,7 @@ public class AbstractPlugin implements Plugin<Project> {
 | 
			
		|||
		includeConfig.setTransitive(false); // Dont get transitive deps
 | 
			
		||||
 | 
			
		||||
		project.getConfigurations().maybeCreate(Constants.MAPPINGS);
 | 
			
		||||
		project.getConfigurations().maybeCreate(Constants.MAPPINGS_FINAL);
 | 
			
		||||
 | 
			
		||||
		for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
 | 
			
		||||
			Configuration compileModsConfig = project.getConfigurations().maybeCreate(entry.getSourceConfiguration());
 | 
			
		||||
| 
						 | 
				
			
			@ -136,8 +137,8 @@ public class AbstractPlugin implements Plugin<Project> {
 | 
			
		|||
		extendsFrom(Constants.MINECRAFT_NAMED, Constants.MINECRAFT_DEPENDENCIES);
 | 
			
		||||
		extendsFrom(Constants.MINECRAFT_INTERMEDIARY, Constants.MINECRAFT_DEPENDENCIES);
 | 
			
		||||
 | 
			
		||||
		extendsFrom("compile", Constants.MAPPINGS);
 | 
			
		||||
		extendsFrom("annotationProcessor", Constants.MAPPINGS);
 | 
			
		||||
		extendsFrom("compile", Constants.MAPPINGS_FINAL);
 | 
			
		||||
		extendsFrom("annotationProcessor", Constants.MAPPINGS_FINAL);
 | 
			
		||||
 | 
			
		||||
		configureIDEs();
 | 
			
		||||
		configureCompile();
 | 
			
		||||
| 
						 | 
				
			
			@ -156,8 +157,8 @@ public class AbstractPlugin implements Plugin<Project> {
 | 
			
		|||
						project.getLogger().lifecycle(":setting java compiler args");
 | 
			
		||||
 | 
			
		||||
						try {
 | 
			
		||||
							javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath());
 | 
			
		||||
							javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath());
 | 
			
		||||
							javaCompileTask.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().tinyMappings.getCanonicalPath());
 | 
			
		||||
							javaCompileTask.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().mappingsMixinExport.getCanonicalPath());
 | 
			
		||||
							javaCompileTask.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(javaCompileTask.getDestinationDir(), extension.getRefmapName()).getCanonicalPath());
 | 
			
		||||
							javaCompileTask.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary");
 | 
			
		||||
						} catch (IOException e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -183,8 +184,8 @@ public class AbstractPlugin implements Plugin<Project> {
 | 
			
		|||
				project.getLogger().warn(":configuring scala compilation processing");
 | 
			
		||||
 | 
			
		||||
				try {
 | 
			
		||||
					task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_TINY.getCanonicalPath());
 | 
			
		||||
					task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().MAPPINGS_MIXIN_EXPORT.getCanonicalPath());
 | 
			
		||||
					task.getOptions().getCompilerArgs().add("-AinMapFileNamedIntermediary=" + extension.getMappingsProvider().tinyMappings.getCanonicalPath());
 | 
			
		||||
					task.getOptions().getCompilerArgs().add("-AoutMapFileNamedIntermediary=" + extension.getMappingsProvider().mappingsMixinExport.getCanonicalPath());
 | 
			
		||||
					task.getOptions().getCompilerArgs().add("-AoutRefMapFile=" + new File(task.getDestinationDir(), extension.getRefmapName()).getCanonicalPath());
 | 
			
		||||
					task.getOptions().getCompilerArgs().add("-AdefaultObfuscationEnv=named:intermediary");
 | 
			
		||||
				} catch (IOException e) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,8 @@
 | 
			
		|||
 | 
			
		||||
package net.fabricmc.loom.providers;
 | 
			
		||||
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.lang.ref.SoftReference;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
| 
						 | 
				
			
			@ -33,32 +33,32 @@ import java.util.HashMap;
 | 
			
		|||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.loom.util.StaticPathWatcher;
 | 
			
		||||
import net.fabricmc.mappings.Mappings;
 | 
			
		||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
 | 
			
		||||
import net.fabricmc.mapping.tree.TinyTree;
 | 
			
		||||
 | 
			
		||||
public final class MappingsCache {
 | 
			
		||||
	public static final MappingsCache INSTANCE = new MappingsCache();
 | 
			
		||||
 | 
			
		||||
	private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>();
 | 
			
		||||
	private final Map<Path, SoftReference<TinyTree>> mappingsCache = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
	public Mappings get(Path mappingsPath) {
 | 
			
		||||
	//TODO: loom doesn't actually use new mappings when the mappings change until the gradle daemons are stopped
 | 
			
		||||
	public TinyTree get(Path mappingsPath) throws IOException {
 | 
			
		||||
		mappingsPath = mappingsPath.toAbsolutePath();
 | 
			
		||||
 | 
			
		||||
		if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) {
 | 
			
		||||
			mappingsCache.remove(mappingsPath);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		SoftReference<Mappings> ref = mappingsCache.get(mappingsPath);
 | 
			
		||||
		SoftReference<TinyTree> ref = mappingsCache.get(mappingsPath);
 | 
			
		||||
 | 
			
		||||
		if (ref != null && ref.get() != null) {
 | 
			
		||||
			return ref.get();
 | 
			
		||||
		} else {
 | 
			
		||||
			try (InputStream stream = Files.newInputStream(mappingsPath)) {
 | 
			
		||||
				Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false);
 | 
			
		||||
			try (BufferedReader reader = Files.newBufferedReader(mappingsPath)) {
 | 
			
		||||
				TinyTree mappings = TinyMappingFactory.loadWithDetection(reader);
 | 
			
		||||
				ref = new SoftReference<>(mappings);
 | 
			
		||||
				mappingsCache.put(mappingsPath, ref);
 | 
			
		||||
				return mappings;
 | 
			
		||||
			} catch (IOException e) {
 | 
			
		||||
				throw new RuntimeException(e);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,25 +24,38 @@
 | 
			
		|||
 | 
			
		||||
package net.fabricmc.loom.providers;
 | 
			
		||||
 | 
			
		||||
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.net.UrlEscapers;
 | 
			
		||||
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.util.Constants;
 | 
			
		||||
import net.fabricmc.loom.util.DependencyProvider;
 | 
			
		||||
import net.fabricmc.loom.util.DownloadUtil;
 | 
			
		||||
import net.fabricmc.loom.util.Version;
 | 
			
		||||
import net.fabricmc.mappings.Mappings;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
//TODO fix local mappings
 | 
			
		||||
//TODO possibly use maven for mappings, can fix above at the same time
 | 
			
		||||
public class MappingsProvider extends DependencyProvider {
 | 
			
		||||
	public MinecraftMappedProvider mappedProvider;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,13 +63,21 @@ public class MappingsProvider extends DependencyProvider {
 | 
			
		|||
	public String minecraftVersion;
 | 
			
		||||
	public String mappingsVersion;
 | 
			
		||||
 | 
			
		||||
	public File MAPPINGS_DIR;
 | 
			
		||||
	public File MAPPINGS_TINY_BASE;
 | 
			
		||||
	public File MAPPINGS_TINY;
 | 
			
		||||
	public File MAPPINGS_MIXIN_EXPORT;
 | 
			
		||||
	private Path mappingsDir;
 | 
			
		||||
	private Path mappingsStepsDir;
 | 
			
		||||
	// The mappings that gradle gives us
 | 
			
		||||
	private Path baseTinyMappings;
 | 
			
		||||
	// The mappings we use in practice
 | 
			
		||||
	public File tinyMappings;
 | 
			
		||||
	public File tinyMappingsJar;
 | 
			
		||||
	public File mappingsMixinExport;
 | 
			
		||||
 | 
			
		||||
	public Mappings getMappings() throws IOException {
 | 
			
		||||
		return MappingsCache.INSTANCE.get(MAPPINGS_TINY.toPath());
 | 
			
		||||
	public void clean() throws IOException {
 | 
			
		||||
		FileUtils.deleteDirectory(mappingsDir.toFile());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public TinyTree getMappings() throws IOException {
 | 
			
		||||
		return MappingsCache.INSTANCE.get(tinyMappings.toPath());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			@ -66,50 +87,166 @@ public class MappingsProvider extends DependencyProvider {
 | 
			
		|||
		project.getLogger().lifecycle(":setting up mappings (" + dependency.getDependency().getName() + " " + dependency.getResolvedVersion() + ")");
 | 
			
		||||
 | 
			
		||||
		String version = dependency.getResolvedVersion();
 | 
			
		||||
		File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find dependency " + dependency));
 | 
			
		||||
		File mappingsJar = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not find yarn mappings: " + dependency));
 | 
			
		||||
 | 
			
		||||
		this.mappingsName = dependency.getDependency().getGroup() + "." + dependency.getDependency().getName();
 | 
			
		||||
		this.mappingsName = StringUtils.removeSuffix(dependency.getDependency().getGroup() + "." + dependency.getDependency().getName(), "-unmerged");
 | 
			
		||||
 | 
			
		||||
		boolean isV2 = doesJarContainV2Mappings(mappingsJar.toPath());
 | 
			
		||||
 | 
			
		||||
		Version mappingsVersion = new Version(version);
 | 
			
		||||
		this.minecraftVersion = mappingsVersion.getMinecraftVersion();
 | 
			
		||||
		this.mappingsVersion = mappingsVersion.getMappingsVersion();
 | 
			
		||||
		this.mappingsVersion = mappingsVersion.getMappingsVersion() + (isV2 ? "-v2" : "");
 | 
			
		||||
 | 
			
		||||
		initFiles(project);
 | 
			
		||||
 | 
			
		||||
		if (!MAPPINGS_DIR.exists()) {
 | 
			
		||||
			MAPPINGS_DIR.mkdir();
 | 
			
		||||
		Files.createDirectories(mappingsDir);
 | 
			
		||||
		Files.createDirectories(mappingsStepsDir);
 | 
			
		||||
 | 
			
		||||
		String[] depStringSplit = dependency.getDepString().split(":");
 | 
			
		||||
		String jarClassifier = "final";
 | 
			
		||||
 | 
			
		||||
		if (depStringSplit.length >= 4) {
 | 
			
		||||
			jarClassifier = jarClassifier + depStringSplit[3];
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!MAPPINGS_TINY_BASE.exists() || !MAPPINGS_TINY.exists()) {
 | 
			
		||||
			if (!MAPPINGS_TINY_BASE.exists()) {
 | 
			
		||||
				project.getLogger().lifecycle(":extracting " + mappingsJar.getName());
 | 
			
		||||
		tinyMappings = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".tiny").toFile();
 | 
			
		||||
		tinyMappingsJar = new File(extension.getUserCache(), mappingsJar.getName().replace(".jar", "-" + jarClassifier + ".jar"));
 | 
			
		||||
 | 
			
		||||
				try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), null)) {
 | 
			
		||||
					Path fileToExtract = fileSystem.getPath("mappings/mappings.tiny");
 | 
			
		||||
					Files.copy(fileToExtract, MAPPINGS_TINY_BASE.toPath());
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (MAPPINGS_TINY.exists()) {
 | 
			
		||||
				MAPPINGS_TINY.delete();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			project.getLogger().lifecycle(":populating field names");
 | 
			
		||||
			new CommandProposeFieldNames().run(new String[]{minecraftProvider.MINECRAFT_MERGED_JAR.getAbsolutePath(), MAPPINGS_TINY_BASE.getAbsolutePath(), MAPPINGS_TINY.getAbsolutePath()});
 | 
			
		||||
		if (!tinyMappings.exists()) {
 | 
			
		||||
			storeMappings(project, minecraftProvider, mappingsJar.toPath());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!tinyMappingsJar.exists()) {
 | 
			
		||||
			ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		addDependency(tinyMappingsJar, project, Constants.MAPPINGS_FINAL);
 | 
			
		||||
 | 
			
		||||
		mappedProvider = new MinecraftMappedProvider();
 | 
			
		||||
		mappedProvider.initFiles(project, minecraftProvider, this);
 | 
			
		||||
		mappedProvider.provide(dependency, project, extension, postPopulationScheduler);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void initFiles(Project project) {
 | 
			
		||||
		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
 | 
			
		||||
		MAPPINGS_DIR = new File(extension.getUserCache(), "mappings");
 | 
			
		||||
	private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar) throws IOException {
 | 
			
		||||
		project.getLogger().lifecycle(":extracting " + yarnJar.getFileName());
 | 
			
		||||
 | 
			
		||||
		MAPPINGS_TINY_BASE = new File(MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion + "-base");
 | 
			
		||||
		MAPPINGS_TINY = new File(MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion);
 | 
			
		||||
		MAPPINGS_MIXIN_EXPORT = new File(extension.getProjectBuildCache(), "mixin-map-" + minecraftVersion + "-" + mappingsVersion + ".tiny");
 | 
			
		||||
		try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, null)) {
 | 
			
		||||
			extractMappings(fileSystem, baseTinyMappings);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (baseMappingsAreV2()) {
 | 
			
		||||
			// These are unmerged v2 mappings
 | 
			
		||||
 | 
			
		||||
			// Download and extract intermediary
 | 
			
		||||
			String encodedMinecraftVersion = UrlEscapers.urlFragmentEscaper().escape(minecraftVersion);
 | 
			
		||||
			String intermediaryArtifactUrl = "https://maven.fabricmc.net/net/fabricmc/intermediary/" + encodedMinecraftVersion + "/intermediary-" + encodedMinecraftVersion + "-v2.jar";
 | 
			
		||||
			Path intermediaryJar = mappingsStepsDir.resolve("v2-intermediary-" + minecraftVersion + ".jar");
 | 
			
		||||
			DownloadUtil.downloadIfChanged(new URL(intermediaryArtifactUrl), intermediaryJar.toFile(), project.getLogger());
 | 
			
		||||
 | 
			
		||||
			mergeAndSaveMappings(project, intermediaryJar, 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, 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 mergeAndSaveMappings(Project project, Path unmergedIntermediaryJar, Path unmergedYarnJar) throws IOException {
 | 
			
		||||
		Path unmergedIntermediary = Paths.get(mappingsStepsDir.toString(), "unmerged-intermediary.tiny");
 | 
			
		||||
		project.getLogger().info(":extracting " + unmergedIntermediaryJar.getFileName());
 | 
			
		||||
 | 
			
		||||
		try (FileSystem unmergedIntermediaryFs = FileSystems.newFileSystem(unmergedIntermediaryJar, null)) {
 | 
			
		||||
			extractMappings(unmergedIntermediaryFs, unmergedIntermediary);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Path unmergedYarn = Paths.get(mappingsStepsDir.toString(), "unmerged-yarn.tiny");
 | 
			
		||||
		project.getLogger().info(":extracting " + unmergedYarnJar.getFileName());
 | 
			
		||||
 | 
			
		||||
		try (FileSystem unmergedYarnJarFs = FileSystems.newFileSystem(unmergedYarnJar, null)) {
 | 
			
		||||
			extractMappings(unmergedYarnJarFs, unmergedYarn);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Path invertedIntermediary = Paths.get(mappingsStepsDir.toString(), "inverted-intermediary.tiny");
 | 
			
		||||
		reorderMappings(unmergedIntermediary, 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.MINECRAFT_MERGED_JAR.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(Project project) {
 | 
			
		||||
		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
 | 
			
		||||
		mappingsDir = extension.getUserCache().toPath().resolve("mappings");
 | 
			
		||||
		mappingsStepsDir = mappingsDir.resolve("steps");
 | 
			
		||||
 | 
			
		||||
		baseTinyMappings = mappingsDir.resolve(mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion + "-base");
 | 
			
		||||
		mappingsMixinExport = new File(extension.getProjectBuildCache(), "mixin-map-" + minecraftVersion + "-" + mappingsVersion + ".tiny");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,11 +39,14 @@ public class MinecraftMappedProvider extends DependencyProvider {
 | 
			
		|||
	public File MINECRAFT_MAPPED_JAR;
 | 
			
		||||
	public File MINECRAFT_INTERMEDIARY_JAR;
 | 
			
		||||
 | 
			
		||||
	public MinecraftMappedProvider() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private MinecraftProvider minecraftProvider;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void provide(DependencyInfo dependency, Project project, LoomGradleExtension extension, Consumer<Runnable> postPopulationScheduler) throws Exception {
 | 
			
		||||
		if (!extension.getMappingsProvider().MAPPINGS_TINY.exists()) {
 | 
			
		||||
		if (!extension.getMappingsProvider().tinyMappings.exists()) {
 | 
			
		||||
			throw new RuntimeException("mappings file not found");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,17 +70,28 @@ public class MinecraftMappedProvider extends DependencyProvider {
 | 
			
		|||
			throw new RuntimeException("mapped jar not found");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		String version = minecraftProvider.minecraftVersion + "-mapped-" + extension.getMappingsProvider().mappingsName + "-" + extension.getMappingsProvider().mappingsVersion;
 | 
			
		||||
		project.getDependencies().add(Constants.MINECRAFT_NAMED, project.getDependencies().module("net.minecraft:minecraft:" + version));
 | 
			
		||||
		version = minecraftProvider.minecraftVersion + "-intermediary-" + extension.getMappingsProvider().mappingsName;
 | 
			
		||||
		project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY, project.getDependencies().module("net.minecraft:minecraft:" + version));
 | 
			
		||||
		MappingsProvider mappingsProvider = extension.getMappingsProvider();
 | 
			
		||||
		project.getDependencies().add(Constants.MINECRAFT_NAMED,
 | 
			
		||||
						project.getDependencies().module("net.minecraft:minecraft:" + getNamedJarVersionString(mappingsProvider.mappingsName, mappingsProvider.mappingsVersion)));
 | 
			
		||||
		project.getDependencies().add(Constants.MINECRAFT_INTERMEDIARY,
 | 
			
		||||
						project.getDependencies().module("net.minecraft:minecraft:" + getIntermediaryJarVersionString(mappingsProvider.mappingsName, mappingsProvider.mappingsVersion)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void initFiles(Project project, MinecraftProvider minecraftProvider, MappingsProvider mappingsProvider) {
 | 
			
		||||
		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
 | 
			
		||||
		this.minecraftProvider = minecraftProvider;
 | 
			
		||||
		MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-intermediary-" + mappingsProvider.mappingsName + ".jar");
 | 
			
		||||
		MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(), "minecraft-" + minecraftProvider.minecraftVersion + "-mapped-" + mappingsProvider.mappingsName + "-" + mappingsProvider.mappingsVersion + ".jar");
 | 
			
		||||
		MINECRAFT_INTERMEDIARY_JAR = new File(extension.getUserCache(),
 | 
			
		||||
						"minecraft-" + getIntermediaryJarVersionString(mappingsProvider.mappingsName, mappingsProvider.mappingsVersion) + ".jar");
 | 
			
		||||
		MINECRAFT_MAPPED_JAR = new File(extension.getUserCache(),
 | 
			
		||||
						"minecraft-" + getNamedJarVersionString(mappingsProvider.mappingsName, mappingsProvider.mappingsVersion) + ".jar");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private String getNamedJarVersionString(String mappingsName, String mappingsVersion) {
 | 
			
		||||
		return minecraftProvider.minecraftVersion + "-mapped-" + mappingsName + "-" + mappingsVersion;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private String getIntermediaryJarVersionString(String mappingsName, String mappingsVersion) {
 | 
			
		||||
		return minecraftProvider.minecraftVersion + "-intermediary-" + mappingsName + "-" + mappingsVersion;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Collection<File> getMapperPaths() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,14 +36,12 @@ import net.fabricmc.loom.util.DeletingFileVisitor;
 | 
			
		|||
public class CleanLoomMappings extends AbstractLoomTask {
 | 
			
		||||
	@TaskAction
 | 
			
		||||
	public void run() {
 | 
			
		||||
		Project project = this.getProject();
 | 
			
		||||
		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
 | 
			
		||||
		extension.getMappingsProvider().MAPPINGS_TINY.delete();
 | 
			
		||||
		extension.getMappingsProvider().MAPPINGS_TINY_BASE.delete();
 | 
			
		||||
		extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
 | 
			
		||||
		extension.getMinecraftMappedProvider().getMappedJar().delete();
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			Project project = this.getProject();
 | 
			
		||||
			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
 | 
			
		||||
			extension.getMappingsProvider().clean();
 | 
			
		||||
			extension.getMinecraftMappedProvider().getIntermediaryJar().delete();
 | 
			
		||||
			extension.getMinecraftMappedProvider().getMappedJar().delete();
 | 
			
		||||
			Files.walkFileTree(extension.getRootProjectBuildCache().toPath(), new DeletingFileVisitor());
 | 
			
		||||
		} catch (IOException e) {
 | 
			
		||||
			throw new RuntimeException(e);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,27 +24,41 @@
 | 
			
		|||
 | 
			
		||||
package net.fabricmc.loom.task;
 | 
			
		||||
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
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.util.Collection;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.function.BiFunction;
 | 
			
		||||
 | 
			
		||||
import com.google.common.net.UrlEscapers;
 | 
			
		||||
import org.apache.commons.io.FileUtils;
 | 
			
		||||
import org.cadixdev.lorenz.MappingSet;
 | 
			
		||||
import org.cadixdev.lorenz.io.MappingsReader;
 | 
			
		||||
import org.cadixdev.lorenz.model.ClassMapping;
 | 
			
		||||
import org.cadixdev.lorenz.model.Mapping;
 | 
			
		||||
import org.cadixdev.mercury.Mercury;
 | 
			
		||||
import org.cadixdev.mercury.remapper.MercuryRemapper;
 | 
			
		||||
import org.gradle.api.Project;
 | 
			
		||||
import org.gradle.api.tasks.TaskAction;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.loom.LoomGradleExtension;
 | 
			
		||||
import net.fabricmc.loom.util.Constants;
 | 
			
		||||
import net.fabricmc.loom.util.Version;
 | 
			
		||||
import net.fabricmc.mappings.ClassEntry;
 | 
			
		||||
import net.fabricmc.mappings.EntryTriple;
 | 
			
		||||
import net.fabricmc.mappings.FieldEntry;
 | 
			
		||||
import net.fabricmc.mappings.Mappings;
 | 
			
		||||
import net.fabricmc.mappings.MethodEntry;
 | 
			
		||||
import net.fabricmc.loom.providers.MappingsProvider;
 | 
			
		||||
import net.fabricmc.loom.providers.MinecraftMappedProvider;
 | 
			
		||||
import net.fabricmc.loom.util.SourceRemapper;
 | 
			
		||||
import net.fabricmc.mapping.tree.ClassDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.Descriptored;
 | 
			
		||||
import net.fabricmc.mapping.tree.FieldDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.MethodDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.TinyMappingFactory;
 | 
			
		||||
import net.fabricmc.mapping.tree.TinyTree;
 | 
			
		||||
 | 
			
		||||
public class MigrateMappingsTask extends AbstractLoomTask {
 | 
			
		||||
	@TaskAction
 | 
			
		||||
| 
						 | 
				
			
			@ -55,75 +69,95 @@ public class MigrateMappingsTask extends AbstractLoomTask {
 | 
			
		|||
 | 
			
		||||
		project.getLogger().lifecycle(":loading mappings");
 | 
			
		||||
 | 
			
		||||
		File mappingsFile = null;
 | 
			
		||||
		String inputDir = (String) properties.get("inputDir");
 | 
			
		||||
		if (inputDir == null) inputDir = "src/main/java";
 | 
			
		||||
		String outputDir = (String) properties.get("outputDir");
 | 
			
		||||
		if (outputDir == null) outputDir = "remappedSrc";
 | 
			
		||||
		String officialMappingsVersion = (String) properties.get("targetMappings");
 | 
			
		||||
		String localMappingsPath = (String) properties.get("targetLocalMappings");
 | 
			
		||||
 | 
			
		||||
		if (properties.containsKey("targetMappingsFile")) {
 | 
			
		||||
			mappingsFile = new File((String) properties.get("targetMappingsFile"));
 | 
			
		||||
		} else if (properties.containsKey("targetMappingsArtifact")) {
 | 
			
		||||
			String[] artifactName = ((String) properties.get("targetMappingsArtifact")).split(":");
 | 
			
		||||
 | 
			
		||||
			if (artifactName.length != 3) {
 | 
			
		||||
				throw new RuntimeException("Invalid artifact name: " + properties.get("targetMappingsArtifact"));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			String mappingsName = artifactName[0] + "." + artifactName[1];
 | 
			
		||||
 | 
			
		||||
			Version v = new Version(artifactName[2]);
 | 
			
		||||
			String minecraftVersion = v.getMinecraftVersion();
 | 
			
		||||
			String mappingsVersion = v.getMappingsVersion();
 | 
			
		||||
 | 
			
		||||
			mappingsFile = new File(extension.getMappingsProvider().MAPPINGS_DIR, mappingsName + "-tiny-" + minecraftVersion + "-" + mappingsVersion);
 | 
			
		||||
		if (officialMappingsVersion != null && localMappingsPath != null) {
 | 
			
		||||
			throw new IllegalArgumentException("targetMappings and targetLocalMappings are mutually exclusive;"
 | 
			
		||||
							+ " you either specify an official yarn mappings version with targetMappings, "
 | 
			
		||||
							+ "or a local one with targetLocalMappings.");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (mappingsFile == null || !mappingsFile.exists()) {
 | 
			
		||||
			throw new RuntimeException("Could not find mappings file: " + (mappingsFile != null ? mappingsFile : "null"));
 | 
			
		||||
		if (officialMappingsVersion == null && localMappingsPath == null) {
 | 
			
		||||
			throw new IllegalArgumentException("You must specify a new mappings version with -PtargetMappings (or local mappings with -PtargetLocalMappings).");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!properties.containsKey("inputDir") || !properties.containsKey("outputDir")) {
 | 
			
		||||
			throw new RuntimeException("Must specify input and output dir!");
 | 
			
		||||
		boolean useLocalMappings = localMappingsPath != null;
 | 
			
		||||
 | 
			
		||||
		if (useLocalMappings && !Files.exists(Paths.get(localMappingsPath))) {
 | 
			
		||||
			throw new IllegalArgumentException("Can't find local mappings in specified location: " + localMappingsPath);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		File inputDir = new File((String) properties.get("inputDir"));
 | 
			
		||||
		File outputDir = new File((String) properties.get("outputDir"));
 | 
			
		||||
		String targetMappingsName = useLocalMappings ? localMappingsPath : officialMappingsVersion;
 | 
			
		||||
 | 
			
		||||
		if (!inputDir.exists() || !inputDir.isDirectory()) {
 | 
			
		||||
			throw new RuntimeException("Could not find input directory: " + inputDir);
 | 
			
		||||
		Path inputDirPath = Paths.get(System.getProperty("user.dir"), inputDir);
 | 
			
		||||
		Path outputDirPath = Paths.get(System.getProperty("user.dir"), outputDir);
 | 
			
		||||
 | 
			
		||||
		if (!Files.exists(inputDirPath) || !Files.isDirectory(inputDirPath)) {
 | 
			
		||||
			throw new IllegalArgumentException("Could not find input directory: " + inputDirPath.toAbsolutePath());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!outputDir.exists()) {
 | 
			
		||||
			if (!outputDir.mkdirs()) {
 | 
			
		||||
				throw new RuntimeException("Could not create output directory:" + outputDir);
 | 
			
		||||
		Files.createDirectories(outputDirPath);
 | 
			
		||||
 | 
			
		||||
		MappingsProvider mappingsProvider = extension.getMappingsProvider();
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			TinyTree currentMappings = mappingsProvider.getMappings();
 | 
			
		||||
			TinyTree targetMappings = getMappings(project, targetMappingsName, useLocalMappings);
 | 
			
		||||
			migrateMappings(project, extension.getMinecraftMappedProvider(), inputDirPath, outputDirPath, currentMappings, targetMappings, extension);
 | 
			
		||||
			project.getLogger().lifecycle(":remapped project written to " + outputDirPath.toAbsolutePath());
 | 
			
		||||
		} catch (IOException e) {
 | 
			
		||||
			throw new IllegalArgumentException("Could not find mappings for version " + officialMappingsVersion, e);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private TinyTree getMappings(Project project, String mappingsVersionOrPath, boolean useLocalMappings) throws IOException {
 | 
			
		||||
		Path migrateMappingsDir = Files.createTempDirectory("migrate");
 | 
			
		||||
		Path localMappingsOfVersion = migrateMappingsDir.resolve(mappingsVersionOrPath + ".tiny");
 | 
			
		||||
 | 
			
		||||
		if (!Files.exists(localMappingsOfVersion)) {
 | 
			
		||||
			if (useLocalMappings) {
 | 
			
		||||
				Files.copy(Paths.get(mappingsVersionOrPath), localMappingsOfVersion);
 | 
			
		||||
			} else {
 | 
			
		||||
				String versionRelativePath = UrlEscapers.urlFragmentEscaper().escape(mappingsVersionOrPath);
 | 
			
		||||
				String artifactUrl = "https://maven.fabricmc.net/net/fabricmc/yarn/" + versionRelativePath + "/yarn-" + versionRelativePath + ".jar";
 | 
			
		||||
				File mappingsJar = File.createTempFile("migrateMappingsJar", ".jar");
 | 
			
		||||
				project.getLogger().lifecycle(":downloading new mappings from " + artifactUrl);
 | 
			
		||||
				FileUtils.copyURLToFile(new URL(artifactUrl), mappingsJar);
 | 
			
		||||
 | 
			
		||||
				try (FileSystem jar = FileSystems.newFileSystem(mappingsJar.toPath(), null)) {
 | 
			
		||||
					if (!Files.exists(migrateMappingsDir)) Files.createDirectory(migrateMappingsDir);
 | 
			
		||||
					MappingsProvider.extractMappings(jar, localMappingsOfVersion);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Mappings sourceMappings = extension.getMappingsProvider().getMappings();
 | 
			
		||||
		Mappings targetMappings;
 | 
			
		||||
 | 
			
		||||
		try (FileInputStream stream = new FileInputStream(mappingsFile)) {
 | 
			
		||||
			targetMappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false);
 | 
			
		||||
		try (BufferedReader reader = Files.newBufferedReader(localMappingsOfVersion)) {
 | 
			
		||||
			return TinyMappingFactory.loadWithDetection(reader);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void migrateMappings(Project project, MinecraftMappedProvider minecraftMappedProvider,
 | 
			
		||||
										Path inputDir, Path outputDir, TinyTree currentMappings, TinyTree targetMappings, LoomGradleExtension extension
 | 
			
		||||
	) throws IOException {
 | 
			
		||||
		project.getLogger().lifecycle(":joining mappings");
 | 
			
		||||
		MappingSet mappingSet = new MappingsJoiner(sourceMappings, targetMappings, "intermediary", "named").read();
 | 
			
		||||
		MappingSet mappingSet = new MappingsJoiner(currentMappings, targetMappings,
 | 
			
		||||
						"intermediary", "named").read();
 | 
			
		||||
 | 
			
		||||
		project.getLogger().lifecycle(":remapping");
 | 
			
		||||
		Mercury mercury = new Mercury();
 | 
			
		||||
		Mercury mercury = SourceRemapper.createMercuryWithClassPath(project, false);
 | 
			
		||||
 | 
			
		||||
		for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) {
 | 
			
		||||
			mercury.getClassPath().add(file.toPath());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
 | 
			
		||||
			mercury.getClassPath().add(file.toPath());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_MAPPED_JAR.toPath());
 | 
			
		||||
		mercury.getClassPath().add(extension.getMinecraftMappedProvider().MINECRAFT_INTERMEDIARY_JAR.toPath());
 | 
			
		||||
		mercury.getClassPath().add(minecraftMappedProvider.MINECRAFT_MAPPED_JAR.toPath());
 | 
			
		||||
		mercury.getClassPath().add(minecraftMappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath());
 | 
			
		||||
 | 
			
		||||
		mercury.getProcessors().add(MercuryRemapper.create(mappingSet));
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			mercury.rewrite(inputDir.toPath(), outputDir.toPath());
 | 
			
		||||
			mercury.rewrite(inputDir, outputDir);
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			project.getLogger().warn("Could not remap fully!", e);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -133,10 +167,19 @@ public class MigrateMappingsTask extends AbstractLoomTask {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	public static class MappingsJoiner extends MappingsReader {
 | 
			
		||||
		private final Mappings sourceMappings, targetMappings;
 | 
			
		||||
		private final TinyTree sourceMappings, targetMappings;
 | 
			
		||||
		private final String fromNamespace, toNamespace;
 | 
			
		||||
 | 
			
		||||
		public MappingsJoiner(Mappings sourceMappings, Mappings targetMappings, String fromNamespace, String toNamespace) {
 | 
			
		||||
		/**
 | 
			
		||||
		 * Say A is the source mappings and B is the target mappings.
 | 
			
		||||
		 * It does not map from intermediary to named but rather maps from named-A to named-B, by matching intermediary names.
 | 
			
		||||
		 * It goes through all of the intermediary names of A, and for every such intermediary name, call it I,
 | 
			
		||||
		 * matches the named mapping of I in A, with the named mapping of I in B.
 | 
			
		||||
		 * As you might imagine, this requires intermediary mappings to be stable across all versions.
 | 
			
		||||
		 * Since we only use intermediary names (and not descriptors) to match, and intermediary names are unique,
 | 
			
		||||
		 * this will migrate methods that have had their signature changed too.
 | 
			
		||||
		 */
 | 
			
		||||
		public MappingsJoiner(TinyTree sourceMappings, TinyTree targetMappings, String fromNamespace, String toNamespace) {
 | 
			
		||||
			this.sourceMappings = sourceMappings;
 | 
			
		||||
			this.targetMappings = targetMappings;
 | 
			
		||||
			this.fromNamespace = fromNamespace;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,40 +187,51 @@ public class MigrateMappingsTask extends AbstractLoomTask {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public MappingSet read(MappingSet mappings) throws IOException {
 | 
			
		||||
			Map<String, ClassEntry> targetClasses = new HashMap<>();
 | 
			
		||||
			Map<EntryTriple, FieldEntry> targetFields = new HashMap<>();
 | 
			
		||||
			Map<EntryTriple, MethodEntry> targetMethods = new HashMap<>();
 | 
			
		||||
		public MappingSet read(MappingSet mappings) {
 | 
			
		||||
			Map<String, ClassDef> targetClasses = new HashMap<>();
 | 
			
		||||
			Map<String, FieldDef> targetFields = new HashMap<>();
 | 
			
		||||
			Map<String, MethodDef> targetMethods = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
			targetMappings.getClassEntries().forEach((c) -> targetClasses.put(c.get(fromNamespace), c));
 | 
			
		||||
			targetMappings.getFieldEntries().forEach((c) -> targetFields.put(c.get(fromNamespace), c));
 | 
			
		||||
			targetMappings.getMethodEntries().forEach((c) -> targetMethods.put(c.get(fromNamespace), c));
 | 
			
		||||
			for (ClassDef newClass : targetMappings.getClasses()) {
 | 
			
		||||
				targetClasses.put(newClass.getName(fromNamespace), newClass);
 | 
			
		||||
 | 
			
		||||
			for (ClassEntry entry : sourceMappings.getClassEntries()) {
 | 
			
		||||
				String from = entry.get(toNamespace);
 | 
			
		||||
				String to = targetClasses.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
 | 
			
		||||
				for (FieldDef field : newClass.getFields()) {
 | 
			
		||||
					targetFields.put(field.getName(fromNamespace), field);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				mappings.getOrCreateClassMapping(from).setDeobfuscatedName(to);
 | 
			
		||||
				for (MethodDef method : newClass.getMethods()) {
 | 
			
		||||
					targetMethods.put(method.getName(fromNamespace), method);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (FieldEntry entry : sourceMappings.getFieldEntries()) {
 | 
			
		||||
				EntryTriple fromEntry = entry.get(toNamespace);
 | 
			
		||||
				EntryTriple toEntry = targetFields.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
 | 
			
		||||
			for (ClassDef oldClass : sourceMappings.getClasses()) {
 | 
			
		||||
				String namedMappingOfSourceMapping = oldClass.getName(toNamespace);
 | 
			
		||||
				String namedMappingOfTargetMapping = targetClasses.getOrDefault(oldClass.getName(fromNamespace), oldClass).getName(toNamespace);
 | 
			
		||||
 | 
			
		||||
				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
 | 
			
		||||
			}
 | 
			
		||||
				ClassMapping classMapping = mappings.getOrCreateClassMapping(namedMappingOfSourceMapping).setDeobfuscatedName(namedMappingOfTargetMapping);
 | 
			
		||||
 | 
			
		||||
			for (MethodEntry entry : sourceMappings.getMethodEntries()) {
 | 
			
		||||
				EntryTriple fromEntry = entry.get(toNamespace);
 | 
			
		||||
				EntryTriple toEntry = targetMethods.getOrDefault(entry.get(fromNamespace), entry).get(toNamespace);
 | 
			
		||||
 | 
			
		||||
				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
 | 
			
		||||
				mapMembers(oldClass.getFields(), targetFields, classMapping::getOrCreateFieldMapping);
 | 
			
		||||
				mapMembers(oldClass.getMethods(), targetMethods, classMapping::getOrCreateMethodMapping);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return mappings;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private <T extends Descriptored> void mapMembers(Collection<T> oldMembers, Map<String, T> newMembers,
 | 
			
		||||
														BiFunction<String, String, Mapping> mapper) {
 | 
			
		||||
			for (T oldMember : oldMembers) {
 | 
			
		||||
				String oldName = oldMember.getName(toNamespace);
 | 
			
		||||
				String oldDescriptor = oldMember.getDescriptor(toNamespace);
 | 
			
		||||
				// We only use the intermediary name (and not the descriptor) because every method has a unique intermediary name
 | 
			
		||||
				String newName = newMembers.getOrDefault(oldMember.getName(fromNamespace), oldMember).getName(toNamespace);
 | 
			
		||||
 | 
			
		||||
				mapper.apply(oldName, oldDescriptor).setDeobfuscatedName(newName);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void close() throws IOException { }
 | 
			
		||||
		public void close() {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,16 +76,16 @@ public class RemapJarTask extends Jar {
 | 
			
		|||
		String toM = "intermediary";
 | 
			
		||||
 | 
			
		||||
		Set<File> classpathFiles = new LinkedHashSet<>(
 | 
			
		||||
				project.getConfigurations().getByName("compileClasspath").getFiles()
 | 
			
		||||
						project.getConfigurations().getByName("compileClasspath").getFiles()
 | 
			
		||||
		);
 | 
			
		||||
		Path[] classpath = classpathFiles.stream().map(File::toPath).filter((p) -> !input.equals(p) && Files.exists(p)).toArray(Path[]::new);
 | 
			
		||||
 | 
			
		||||
		File mixinMapFile = mappingsProvider.MAPPINGS_MIXIN_EXPORT;
 | 
			
		||||
		File mixinMapFile = mappingsProvider.mappingsMixinExport;
 | 
			
		||||
		Path mixinMapPath = mixinMapFile.toPath();
 | 
			
		||||
 | 
			
		||||
		TinyRemapper.Builder remapperBuilder = TinyRemapper.newRemapper();
 | 
			
		||||
 | 
			
		||||
		remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM));
 | 
			
		||||
		remapperBuilder = remapperBuilder.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM, false));
 | 
			
		||||
 | 
			
		||||
		if (mixinMapFile.exists()) {
 | 
			
		||||
			remapperBuilder = remapperBuilder.withMappings(TinyUtils.createTinyMappingProvider(mixinMapPath, fromM, toM));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,4 +50,5 @@ public class Constants {
 | 
			
		|||
	public static final String MINECRAFT_NAMED = "minecraftNamed";
 | 
			
		||||
	public static final String MINECRAFT_LINEMAPPED = "minecraftLinemapped";
 | 
			
		||||
	public static final String MAPPINGS = "mappings";
 | 
			
		||||
	public static final String MAPPINGS_FINAL = "mappingsFinal";
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,11 @@ public class MapJarsTiny {
 | 
			
		|||
 | 
			
		||||
			project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
 | 
			
		||||
 | 
			
		||||
			TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).renameInvalidLocals(true).rebuildSourceFilenames(true).build();
 | 
			
		||||
			TinyRemapper remapper = TinyRemapper.newRemapper()
 | 
			
		||||
							.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM, true))
 | 
			
		||||
							.renameInvalidLocals(true)
 | 
			
		||||
							.rebuildSourceFilenames(true)
 | 
			
		||||
							.build();
 | 
			
		||||
 | 
			
		||||
			try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
 | 
			
		||||
				outputConsumer.addNonClassFiles(input);
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +68,7 @@ public class MapJarsTiny {
 | 
			
		|||
				remapper.readInputs(input);
 | 
			
		||||
				remapper.apply(outputConsumer);
 | 
			
		||||
			} catch (Exception e) {
 | 
			
		||||
				throw new RuntimeException("Failed to remap JAR", e);
 | 
			
		||||
				throw new RuntimeException("Failed to remap JAR " + input + " with mappings from " + mappingsProvider.tinyMappings, e);
 | 
			
		||||
			} finally {
 | 
			
		||||
				remapper.finish();
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,13 +41,12 @@ import com.google.gson.Gson;
 | 
			
		|||
import com.google.gson.JsonArray;
 | 
			
		||||
import com.google.gson.JsonObject;
 | 
			
		||||
import org.apache.commons.io.IOUtils;
 | 
			
		||||
import org.gradle.api.Project;
 | 
			
		||||
import org.gradle.api.artifacts.Configuration;
 | 
			
		||||
import org.zeroturnaround.zip.ZipUtil;
 | 
			
		||||
import org.zeroturnaround.zip.commons.FileUtils;
 | 
			
		||||
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
 | 
			
		||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
 | 
			
		||||
import org.gradle.api.Project;
 | 
			
		||||
import org.gradle.api.artifacts.Configuration;
 | 
			
		||||
import org.gradle.internal.impldep.aQute.lib.strings.Strings;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.loom.LoomGradleExtension;
 | 
			
		||||
import net.fabricmc.loom.providers.MappingsProvider;
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +109,7 @@ public class ModProcessor {
 | 
			
		|||
		JarEntry entry = parentJar.getJarEntry(fileName);
 | 
			
		||||
 | 
			
		||||
		if (entry == null) {
 | 
			
		||||
			throw new RuntimeException(Strings.format("%s was not found in %s", fileName, parentJar.getName()));
 | 
			
		||||
			throw new RuntimeException(String.format("%s was not found in %s", fileName, parentJar.getName()));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		File nestedFile = new File(extension.getNestedModCache(), fileName.substring(fileName.lastIndexOf("/")));
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +132,7 @@ public class ModProcessor {
 | 
			
		|||
 | 
			
		||||
	private static void stripNestedJars(File file) {
 | 
			
		||||
		//Strip out all contained jar info as we dont want loader to try and load the jars contained in dev.
 | 
			
		||||
		ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
 | 
			
		||||
		ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[] {(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() {
 | 
			
		||||
			@Override
 | 
			
		||||
			protected String transform(ZipEntry zipEntry, String input) throws IOException {
 | 
			
		||||
				JsonObject json = GSON.fromJson(input, JsonObject.class);
 | 
			
		||||
| 
						 | 
				
			
			@ -151,8 +150,6 @@ public class ModProcessor {
 | 
			
		|||
		MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider();
 | 
			
		||||
		MappingsProvider mappingsProvider = extension.getMappingsProvider();
 | 
			
		||||
 | 
			
		||||
		File mappingsFile = mappingsProvider.MAPPINGS_TINY;
 | 
			
		||||
		Path mappings = mappingsFile.toPath();
 | 
			
		||||
		Path inputPath = input.getAbsoluteFile().toPath();
 | 
			
		||||
		Path mc = mappedProvider.MINECRAFT_INTERMEDIARY_JAR.toPath();
 | 
			
		||||
		Path[] mcDeps = mappedProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
 | 
			
		||||
| 
						 | 
				
			
			@ -170,7 +167,9 @@ public class ModProcessor {
 | 
			
		|||
 | 
			
		||||
		project.getLogger().lifecycle(":remapping " + input.getName() + " (TinyRemapper, " + fromM + " -> " + toM + ")");
 | 
			
		||||
 | 
			
		||||
		TinyRemapper remapper = TinyRemapper.newRemapper().withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM)).build();
 | 
			
		||||
		TinyRemapper remapper = TinyRemapper.newRemapper()
 | 
			
		||||
						.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM, false))
 | 
			
		||||
						.build();
 | 
			
		||||
 | 
			
		||||
		try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) {
 | 
			
		||||
			outputConsumer.addNonClassFiles(inputPath);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,18 +31,18 @@ import java.nio.file.Path;
 | 
			
		|||
 | 
			
		||||
import org.cadixdev.lorenz.MappingSet;
 | 
			
		||||
import org.cadixdev.lorenz.io.MappingsReader;
 | 
			
		||||
import org.cadixdev.lorenz.model.ClassMapping;
 | 
			
		||||
import org.cadixdev.mercury.Mercury;
 | 
			
		||||
import org.cadixdev.mercury.remapper.MercuryRemapper;
 | 
			
		||||
import org.zeroturnaround.zip.ZipUtil;
 | 
			
		||||
import org.gradle.api.Project;
 | 
			
		||||
import org.zeroturnaround.zip.ZipUtil;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.loom.LoomGradleExtension;
 | 
			
		||||
import net.fabricmc.loom.providers.MappingsProvider;
 | 
			
		||||
import net.fabricmc.mappings.ClassEntry;
 | 
			
		||||
import net.fabricmc.mappings.EntryTriple;
 | 
			
		||||
import net.fabricmc.mappings.FieldEntry;
 | 
			
		||||
import net.fabricmc.mappings.Mappings;
 | 
			
		||||
import net.fabricmc.mappings.MethodEntry;
 | 
			
		||||
import net.fabricmc.mapping.tree.ClassDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.FieldDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.MethodDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.TinyTree;
 | 
			
		||||
import net.fabricmc.stitch.util.StitchUtil;
 | 
			
		||||
 | 
			
		||||
public class SourceRemapper {
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ public class SourceRemapper {
 | 
			
		|||
 | 
			
		||||
		MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> {
 | 
			
		||||
			try {
 | 
			
		||||
				Mappings m = mappingsProvider.getMappings();
 | 
			
		||||
				TinyTree m = mappingsProvider.getMappings();
 | 
			
		||||
				project.getLogger().lifecycle(":loading " + (toNamed ? "intermediary -> named" : "named -> intermediary") + " source mappings");
 | 
			
		||||
				return new TinyReader(m, toNamed ? "intermediary" : "named", toNamed ? "named" : "intermediary").read();
 | 
			
		||||
			} catch (Exception e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,17 +69,7 @@ public class SourceRemapper {
 | 
			
		|||
		project.getLogger().info(":remapping source jar");
 | 
			
		||||
 | 
			
		||||
		Mercury mercury = extension.getOrCreateSrcMercuryCache(toNamed ? 1 : 0, () -> {
 | 
			
		||||
			Mercury m = new Mercury();
 | 
			
		||||
 | 
			
		||||
			for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) {
 | 
			
		||||
				m.getClassPath().add(file.toPath());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!toNamed) {
 | 
			
		||||
				for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
 | 
			
		||||
					m.getClassPath().add(file.toPath());
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			Mercury m = createMercuryWithClassPath(project, toNamed);
 | 
			
		||||
 | 
			
		||||
			for (Path file : extension.getUnmappedMods()) {
 | 
			
		||||
				if (Files.isRegularFile(file)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +149,22 @@ public class SourceRemapper {
 | 
			
		|||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static Mercury createMercuryWithClassPath(Project project, boolean toNamed) {
 | 
			
		||||
		Mercury m = new Mercury();
 | 
			
		||||
 | 
			
		||||
		for (File file : project.getConfigurations().getByName(Constants.MINECRAFT_DEPENDENCIES).getFiles()) {
 | 
			
		||||
			m.getClassPath().add(file.toPath());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!toNamed) {
 | 
			
		||||
			for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
 | 
			
		||||
				m.getClassPath().add(file.toPath());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return m;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static boolean isJavaFile(Path path) {
 | 
			
		||||
		String name = path.getFileName().toString();
 | 
			
		||||
		// ".java" is not a valid java file
 | 
			
		||||
| 
						 | 
				
			
			@ -166,39 +172,36 @@ public class SourceRemapper {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	public static class TinyReader extends MappingsReader {
 | 
			
		||||
		private final Mappings m;
 | 
			
		||||
		private final TinyTree mappings;
 | 
			
		||||
		private final String from, to;
 | 
			
		||||
 | 
			
		||||
		public TinyReader(Mappings m, String from, String to) {
 | 
			
		||||
			this.m = m;
 | 
			
		||||
		public TinyReader(TinyTree m, String from, String to) {
 | 
			
		||||
			this.mappings = m;
 | 
			
		||||
			this.from = from;
 | 
			
		||||
			this.to = to;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public MappingSet read(final MappingSet mappings) {
 | 
			
		||||
			for (ClassEntry entry : m.getClassEntries()) {
 | 
			
		||||
				mappings.getOrCreateClassMapping(entry.get(from)).setDeobfuscatedName(entry.get(to));
 | 
			
		||||
			}
 | 
			
		||||
			for (ClassDef classDef : this.mappings.getClasses()) {
 | 
			
		||||
				ClassMapping classMapping = mappings.getOrCreateClassMapping(classDef.getName(from))
 | 
			
		||||
								.setDeobfuscatedName(classDef.getName(to));
 | 
			
		||||
 | 
			
		||||
			for (FieldEntry entry : m.getFieldEntries()) {
 | 
			
		||||
				EntryTriple fromEntry = entry.get(from);
 | 
			
		||||
				EntryTriple toEntry = entry.get(to);
 | 
			
		||||
				for (FieldDef field : classDef.getFields()) {
 | 
			
		||||
					classMapping.getOrCreateFieldMapping(field.getName(from), field.getDescriptor(from))
 | 
			
		||||
									.setDeobfuscatedName(field.getName(to));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateFieldMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (MethodEntry entry : m.getMethodEntries()) {
 | 
			
		||||
				EntryTriple fromEntry = entry.get(from);
 | 
			
		||||
				EntryTriple toEntry = entry.get(to);
 | 
			
		||||
 | 
			
		||||
				mappings.getOrCreateClassMapping(fromEntry.getOwner()).getOrCreateMethodMapping(fromEntry.getName(), fromEntry.getDesc()).setDeobfuscatedName(toEntry.getName());
 | 
			
		||||
				for (MethodDef method : classDef.getMethods()) {
 | 
			
		||||
					classMapping.getOrCreateMethodMapping(method.getName(from), method.getDescriptor(from))
 | 
			
		||||
									.setDeobfuscatedName(method.getName(to));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return mappings;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void close() throws IOException { }
 | 
			
		||||
		public void close() { }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,31 +24,47 @@
 | 
			
		|||
 | 
			
		||||
package net.fabricmc.loom.util;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.mappings.ClassEntry;
 | 
			
		||||
import net.fabricmc.mappings.EntryTriple;
 | 
			
		||||
import net.fabricmc.mappings.FieldEntry;
 | 
			
		||||
import net.fabricmc.mappings.Mappings;
 | 
			
		||||
import net.fabricmc.mappings.MethodEntry;
 | 
			
		||||
import net.fabricmc.mapping.tree.ClassDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.FieldDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.LocalVariableDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.MethodDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.ParameterDef;
 | 
			
		||||
import net.fabricmc.mapping.tree.TinyTree;
 | 
			
		||||
import net.fabricmc.tinyremapper.IMappingProvider;
 | 
			
		||||
import net.fabricmc.tinyremapper.MemberInstance;
 | 
			
		||||
 | 
			
		||||
public class TinyRemapperMappingsHelper {
 | 
			
		||||
	private TinyRemapperMappingsHelper() { }
 | 
			
		||||
 | 
			
		||||
	public static IMappingProvider create(Mappings mappings, String from, String to) {
 | 
			
		||||
		return (classMap, fieldMap, methodMap) -> {
 | 
			
		||||
			for (ClassEntry entry : mappings.getClassEntries()) {
 | 
			
		||||
				classMap.put(entry.get(from), entry.get(to));
 | 
			
		||||
			}
 | 
			
		||||
	private static IMappingProvider.Member memberOf(String className, String memberName, String descriptor) {
 | 
			
		||||
		return new IMappingProvider.Member(className, memberName, descriptor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
			for (FieldEntry entry : mappings.getFieldEntries()) {
 | 
			
		||||
				EntryTriple fromTriple = entry.get(from);
 | 
			
		||||
				fieldMap.put(fromTriple.getOwner() + "/" + MemberInstance.getFieldId(fromTriple.getName(), fromTriple.getDesc()), entry.get(to).getName());
 | 
			
		||||
			}
 | 
			
		||||
	public static IMappingProvider create(TinyTree mappings, String from, String to, boolean remapLocalVariables) {
 | 
			
		||||
		return (acceptor) -> {
 | 
			
		||||
			for (ClassDef classDef : mappings.getClasses()) {
 | 
			
		||||
				String className = classDef.getName(from);
 | 
			
		||||
				acceptor.acceptClass(className, classDef.getName(to));
 | 
			
		||||
 | 
			
		||||
			for (MethodEntry entry : mappings.getMethodEntries()) {
 | 
			
		||||
				EntryTriple fromTriple = entry.get(from);
 | 
			
		||||
				methodMap.put(fromTriple.getOwner() + "/" + MemberInstance.getMethodId(fromTriple.getName(), fromTriple.getDesc()), entry.get(to).getName());
 | 
			
		||||
				for (FieldDef field : classDef.getFields()) {
 | 
			
		||||
					acceptor.acceptField(memberOf(className, field.getName(from), field.getDescriptor(from)), field.getName(to));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				for (MethodDef method : classDef.getMethods()) {
 | 
			
		||||
					IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDescriptor(from));
 | 
			
		||||
					acceptor.acceptMethod(methodIdentifier, method.getName(to));
 | 
			
		||||
 | 
			
		||||
					if (remapLocalVariables) {
 | 
			
		||||
						for (ParameterDef parameter : method.getParameters()) {
 | 
			
		||||
							acceptor.acceptMethodArg(methodIdentifier, parameter.getLocalVariableIndex(), parameter.getName(to));
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						for (LocalVariableDef localVariable : method.getLocalVariables()) {
 | 
			
		||||
							acceptor.acceptMethodVar(methodIdentifier, localVariable.getLocalVariableIndex(),
 | 
			
		||||
											localVariable.getLocalVariableStartOffset(), localVariable.getLocalVariableTableIndex(),
 | 
			
		||||
											localVariable.getName(to));
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ archivesBaseName = project.archives_base_name
 | 
			
		|||
version = project.mod_version
 | 
			
		||||
group = project.maven_group
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
minecraft {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ class EmptyBuildFunctionalTest extends Specification {
 | 
			
		|||
		when:
 | 
			
		||||
		def result = GradleRunner.create()
 | 
			
		||||
				.withProjectDir(testProjectDir.root)
 | 
			
		||||
				.withArguments('build')
 | 
			
		||||
				.withArguments('build',"--stacktrace")
 | 
			
		||||
				.withPluginClasspath()
 | 
			
		||||
				.withGradleVersion("4.9")
 | 
			
		||||
				.build()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,9 +45,10 @@ class SimpleBuildFunctionalTest extends Specification {
 | 
			
		|||
		when:
 | 
			
		||||
		def result = GradleRunner.create()
 | 
			
		||||
				.withProjectDir(testProjectDir.root)
 | 
			
		||||
				.withArguments('build')
 | 
			
		||||
				.withArguments('build',"--stacktrace")
 | 
			
		||||
				.withPluginClasspath()
 | 
			
		||||
				.withGradleVersion("4.9")
 | 
			
		||||
				.withDebug(true)
 | 
			
		||||
				.build()
 | 
			
		||||
 | 
			
		||||
		then:
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +56,7 @@ class SimpleBuildFunctionalTest extends Specification {
 | 
			
		|||
 | 
			
		||||
		where:
 | 
			
		||||
		mcVersion | yarnVersion       | loaderVersion     | fabricVersion
 | 
			
		||||
		'19w45a'  | '19w45a+build.2:v2'   | '0.6.2+build.166' | '0.4.9+build.258-1.15'
 | 
			
		||||
		'1.14'    | '1.14+build.21'   | '0.4.8+build.155' | '0.3.0+build.184'
 | 
			
		||||
		'1.14.1'  | '1.14.1+build.10' | '0.4.8+build.155' | '0.3.0+build.184'
 | 
			
		||||
		'1.14.2'  | '1.14.2+build.7'  | '0.4.8+build.155' | '0.3.0+build.184'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue