Improve setup speed. (#208)
* Improve access widener remapper, now uses tiny remapper * First pass on using the new tiny remapper * Optimise source remapping
This commit is contained in:
parent
bf6fb4a95e
commit
3eff7d0fdb
13 changed files with 420 additions and 362 deletions
|
@ -47,7 +47,7 @@ dependencies {
|
|||
}
|
||||
|
||||
// tinyfile management
|
||||
implementation ('net.fabricmc:tiny-remapper:0.2.2.66') {
|
||||
implementation ('net.fabricmc:tiny-remapper:0.3.0.70') {
|
||||
transitive = false
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ public class LoomGradleExtension {
|
|||
public String loaderLaunchMethod;
|
||||
public boolean remapMod = true;
|
||||
public boolean autoGenIDERuns = true;
|
||||
public boolean extractJars = false;
|
||||
public String customManifest = null;
|
||||
public File accessWidener = null;
|
||||
public Function<String, Object> intermediaryUrl = mcVer -> "https://maven.fabricmc.net/net/fabricmc/intermediary/" + mcVer + "/intermediary-" + mcVer + "-v2.jar";
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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.processors.dependency;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.fabricmc.loom.util.ModProcessor;
|
||||
|
||||
public class ModDependencyInfo {
|
||||
public final String group;
|
||||
public final String name;
|
||||
public final String version;
|
||||
public final String classifier;
|
||||
public final File inputFile;
|
||||
|
||||
public final RemapData remapData;
|
||||
|
||||
public ModDependencyInfo(String group, String name, String version, String classifier, File inputFile, RemapData remapData) {
|
||||
this.group = group;
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.classifier = classifier;
|
||||
this.inputFile = inputFile;
|
||||
this.remapData = remapData;
|
||||
}
|
||||
|
||||
public String getRemappedNotation() {
|
||||
return String.format("%s:%s:%s@%s%s", group, name, version, remapData.mappingsSuffix, classifier);
|
||||
}
|
||||
|
||||
public String getRemappedFilename() {
|
||||
return String.format("%s-%s@%s", name, version, remapData.mappingsSuffix + classifier.replace(':', '-'));
|
||||
}
|
||||
|
||||
public File getRemappedOutput() {
|
||||
return new File(remapData.modStore, getRemappedFilename() + ".jar");
|
||||
}
|
||||
|
||||
public File getInputFile() {
|
||||
return inputFile;
|
||||
}
|
||||
|
||||
public boolean requiresRemapping() {
|
||||
return !getRemappedOutput().exists() || inputFile.lastModified() <= 0 || inputFile.lastModified() > getRemappedOutput().lastModified();
|
||||
}
|
||||
|
||||
public void finaliseRemapping() {
|
||||
getRemappedOutput().setLastModified(inputFile.lastModified());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s:%s:%s:%s", group, name, version, classifier);
|
||||
}
|
||||
|
||||
public String getAccessWidener() throws IOException {
|
||||
try (JarFile jarFile = new JarFile(getInputFile())) {
|
||||
JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json");
|
||||
|
||||
if (modJsonEntry == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) {
|
||||
JsonObject json = ModProcessor.GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class);
|
||||
|
||||
if (!json.has("accessWidener")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return json.get("accessWidener").getAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.processors.dependency;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class RemapData {
|
||||
public final String mappingsSuffix;
|
||||
public final File modStore;
|
||||
|
||||
public RemapData(String mappingsSuffix, File modStore) {
|
||||
this.mappingsSuffix = mappingsSuffix;
|
||||
this.modStore = modStore;
|
||||
}
|
||||
}
|
|
@ -25,14 +25,19 @@
|
|||
package net.fabricmc.loom.providers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
|
||||
import net.fabricmc.tinyremapper.OutputConsumerPath;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.DependencyProvider;
|
||||
import net.fabricmc.loom.util.MapJarsTiny;
|
||||
|
||||
public class MinecraftMappedProvider extends DependencyProvider {
|
||||
private File minecraftMappedJar;
|
||||
|
@ -66,7 +71,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
|||
}
|
||||
|
||||
try {
|
||||
new MapJarsTiny().mapJars(minecraftProvider, this, this.minecraftMappedJar, this.minecraftIntermediaryJar, getProject());
|
||||
mapMinecraftJar();
|
||||
} catch (Throwable t) {
|
||||
//Cleanup some some things that may be in a bad state now
|
||||
minecraftMappedJar.delete();
|
||||
|
@ -83,6 +88,47 @@ public class MinecraftMappedProvider extends DependencyProvider {
|
|||
addDependencies(dependency, postPopulationScheduler);
|
||||
}
|
||||
|
||||
private void mapMinecraftJar() throws IOException {
|
||||
String fromM = "official";
|
||||
|
||||
MappingsProvider mappingsProvider = getExtension().getMappingsProvider();
|
||||
|
||||
Path input = minecraftProvider.getMergedJar().toPath();
|
||||
Path outputMapped = minecraftMappedJar.toPath();
|
||||
Path outputIntermediary = minecraftIntermediaryJar.toPath();
|
||||
|
||||
for (String toM : Arrays.asList("named", "intermediary")) {
|
||||
Path output = "named".equals(toM) ? outputMapped : outputIntermediary;
|
||||
|
||||
getProject().getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
|
||||
|
||||
TinyRemapper remapper = getTinyRemapper(fromM, toM);
|
||||
|
||||
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(output).build()) {
|
||||
outputConsumer.addNonClassFiles(input);
|
||||
remapper.readClassPath(getRemapClasspath());
|
||||
remapper.readInputs(input);
|
||||
remapper.apply(outputConsumer);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to remap JAR " + input + " with mappings from " + mappingsProvider.tinyMappings, e);
|
||||
} finally {
|
||||
remapper.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TinyRemapper getTinyRemapper(String fromM, String toM) throws IOException {
|
||||
return TinyRemapper.newRemapper()
|
||||
.withMappings(TinyRemapperMappingsHelper.create(getExtension().getMappingsProvider().getMappings(), fromM, toM, true))
|
||||
.renameInvalidLocals(true)
|
||||
.rebuildSourceFilenames(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Path[] getRemapClasspath() {
|
||||
return getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
|
||||
}
|
||||
|
||||
protected void addDependencies(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) {
|
||||
getProject().getRepositories().flatDir(repository -> repository.dir(getJarDirectory(getExtension().getUserCache(), "mapped")));
|
||||
|
||||
|
|
|
@ -110,11 +110,16 @@ public class RemapJarTask extends Jar {
|
|||
remapper.readInputs(input);
|
||||
remapper.apply(outputConsumer);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to remap " + input + " to " + output, e);
|
||||
} finally {
|
||||
remapper.finish();
|
||||
throw new RuntimeException("Failed to remap " + input + " to " + output, e);
|
||||
}
|
||||
|
||||
if (extension.accessWidener != null) {
|
||||
extension.getJarProcessorManager().getByType(AccessWidenerJarProcessor.class).remapAccessWidener(output, remapper.getRemapper());
|
||||
}
|
||||
|
||||
remapper.finish();
|
||||
|
||||
if (!Files.exists(output)) {
|
||||
throw new RuntimeException("Failed to remap " + input + " to " + output + " - file missing!");
|
||||
}
|
||||
|
@ -129,10 +134,6 @@ public class RemapJarTask extends Jar {
|
|||
}
|
||||
}
|
||||
|
||||
if (extension.accessWidener != null) {
|
||||
extension.getJarProcessorManager().getByType(AccessWidenerJarProcessor.class).remapAccessWidener(output);
|
||||
}
|
||||
|
||||
/*try {
|
||||
if (modJar.exists()) {
|
||||
Files.move(modJar, modJarUnmappedCopy);
|
||||
|
|
|
@ -116,11 +116,13 @@ public class LoomDependencyManager {
|
|||
});
|
||||
}
|
||||
|
||||
SourceRemapper sourceRemapper = new SourceRemapper(project, true);
|
||||
|
||||
{
|
||||
String mappingsKey = mappingsProvider.mappingsName + "." + mappingsProvider.minecraftVersion.replace(' ', '_').replace('.', '_').replace('-', '_') + "." + mappingsProvider.mappingsVersion;
|
||||
|
||||
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
|
||||
ModCompileRemapper.remapDependencies(project, mappingsKey, extension, project.getConfigurations().getByName(entry.getSourceConfiguration()), project.getConfigurations().getByName(entry.getRemappedConfiguration()), project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())), afterTasks::add);
|
||||
ModCompileRemapper.remapDependencies(project, mappingsKey, extension, project.getConfigurations().getByName(entry.getSourceConfiguration()), project.getConfigurations().getByName(entry.getRemappedConfiguration()), project.getConfigurations().getByName(entry.getTargetConfiguration(project.getConfigurations())), sourceRemapper);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,6 +152,8 @@ public class LoomDependencyManager {
|
|||
project.getLogger().warn("fabric-installer.json not found in classpath!");
|
||||
}
|
||||
|
||||
sourceRemapper.remapAll();
|
||||
|
||||
for (Runnable runnable : afterTasks) {
|
||||
runnable.run();
|
||||
}
|
||||
|
|
|
@ -1,77 +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.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.providers.MappingsProvider;
|
||||
import net.fabricmc.loom.providers.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.providers.MinecraftProvider;
|
||||
import net.fabricmc.tinyremapper.OutputConsumerPath;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public class MapJarsTiny {
|
||||
public void mapJars(MinecraftProvider jarProvider, MinecraftMappedProvider mapProvider, File mappedJar, File intermediaryJar, Project project) throws IOException {
|
||||
String fromM = "official";
|
||||
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
Path[] classpath = mapProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
|
||||
|
||||
Path input = jarProvider.getMergedJar().toPath();
|
||||
Path outputMapped = mappedJar.toPath();
|
||||
Path outputIntermediary = intermediaryJar.toPath();
|
||||
|
||||
for (String toM : Arrays.asList("named", "intermediary")) {
|
||||
Path output = "named".equals(toM) ? outputMapped : outputIntermediary;
|
||||
|
||||
project.getLogger().lifecycle(":remapping minecraft (TinyRemapper, " + fromM + " -> " + toM + ")");
|
||||
|
||||
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);
|
||||
remapper.readClassPath(classpath);
|
||||
remapper.readInputs(input);
|
||||
remapper.apply(outputConsumer);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to remap JAR " + input + " with mappings from " + mappingsProvider.tinyMappings, e);
|
||||
} finally {
|
||||
remapper.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,9 @@ package net.fabricmc.loom.util;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
|
@ -45,12 +47,19 @@ import org.gradle.jvm.JvmLibrary;
|
|||
import org.gradle.language.base.artifact.SourcesArtifact;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.processors.dependency.ModDependencyInfo;
|
||||
import net.fabricmc.loom.processors.dependency.RemapData;
|
||||
|
||||
public class ModCompileRemapper {
|
||||
public static void remapDependencies(Project project, String mappingsSuffix, LoomGradleExtension extension, Configuration modCompile, Configuration modCompileRemapped, Configuration regularCompile, Consumer<Runnable> postPopulationScheduler) {
|
||||
public static void remapDependencies(Project project, String mappingsSuffix, LoomGradleExtension extension, Configuration modCompile, Configuration modCompileRemapped, Configuration regularCompile, SourceRemapper sourceRemapper) {
|
||||
Logger logger = project.getLogger();
|
||||
DependencyHandler dependencies = project.getDependencies();
|
||||
|
||||
final File modStore = extension.getRemappedModCache();
|
||||
final RemapData remapData = new RemapData(mappingsSuffix, modStore);
|
||||
|
||||
final List<ModDependencyInfo> modDependencies = new ArrayList<>();
|
||||
|
||||
for (ResolvedArtifact artifact : modCompile.getResolvedConfiguration().getResolvedArtifacts()) {
|
||||
String group;
|
||||
String name;
|
||||
|
@ -76,21 +85,32 @@ public class ModCompileRemapper {
|
|||
|
||||
File sources = findSources(dependencies, artifact);
|
||||
|
||||
ModDependencyInfo info = new ModDependencyInfo(group, name, version, classifierSuffix, artifact.getFile(), remapData);
|
||||
modDependencies.add(info);
|
||||
|
||||
String remappedLog = group + ":" + name + ":" + version + classifierSuffix + " (" + mappingsSuffix + ")";
|
||||
String remappedNotation = String.format("%s:%s:%s@%s%s", group, name, version, mappingsSuffix, classifierSuffix);
|
||||
String remappedFilename = String.format("%s-%s@%s", name, version, mappingsSuffix + classifierSuffix.replace(':', '-'));
|
||||
project.getLogger().info(":providing " + remappedLog);
|
||||
|
||||
File modStore = extension.getRemappedModCache();
|
||||
|
||||
remapArtifact(project, modCompileRemapped, artifact, remappedFilename, modStore);
|
||||
|
||||
project.getDependencies().add(modCompileRemapped.getName(), project.getDependencies().module(remappedNotation));
|
||||
|
||||
if (sources != null) {
|
||||
scheduleSourcesRemapping(project, postPopulationScheduler, sources, remappedLog, remappedFilename, modStore);
|
||||
scheduleSourcesRemapping(project, sourceRemapper, sources, remappedLog, remappedFilename, modStore);
|
||||
}
|
||||
}
|
||||
|
||||
List<ModDependencyInfo> processList = modDependencies.stream()
|
||||
.filter(ModDependencyInfo::requiresRemapping)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
try {
|
||||
ModProcessor.processMods(project, processList);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to remap mods", e);
|
||||
}
|
||||
|
||||
// Add all of the remapped mods onto the config
|
||||
for (ModDependencyInfo modDependency : modDependencies) {
|
||||
project.getDependencies().add(modCompileRemapped.getName(), project.getDependencies().module(modDependency.getRemappedNotation()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,28 +143,6 @@ public class ModCompileRemapper {
|
|||
dependencies.add(regularCompile.getName(), dep);
|
||||
}
|
||||
|
||||
private static void remapArtifact(Project project, Configuration config, ResolvedArtifact artifact, String remappedFilename, File modStore) {
|
||||
File input = artifact.getFile();
|
||||
File output = new File(modStore, remappedFilename + ".jar");
|
||||
|
||||
if (!output.exists() || input.lastModified() <= 0 || input.lastModified() > output.lastModified()) {
|
||||
//If the output doesn't exist, or appears to be outdated compared to the input we'll remap it
|
||||
try {
|
||||
ModProcessor.processMod(input, output, project, config, artifact);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to remap mod", e);
|
||||
}
|
||||
|
||||
if (!output.exists()) {
|
||||
throw new RuntimeException("Failed to remap mod");
|
||||
}
|
||||
|
||||
output.setLastModified(input.lastModified());
|
||||
} else {
|
||||
project.getLogger().info(output.getName() + " is up to date with " + input.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static File findSources(DependencyHandler dependencies, ResolvedArtifact artifact) {
|
||||
@SuppressWarnings("unchecked") ArtifactResolutionQuery query = dependencies.createArtifactResolutionQuery()//
|
||||
.forComponents(artifact.getId().getComponentIdentifier())//
|
||||
|
@ -161,23 +159,21 @@ public class ModCompileRemapper {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static void scheduleSourcesRemapping(Project project, Consumer<Runnable> postPopulationScheduler, File sources, String remappedLog, String remappedFilename, File modStore) {
|
||||
postPopulationScheduler.accept(() -> {
|
||||
project.getLogger().info(":providing " + remappedLog + " sources");
|
||||
File remappedSources = new File(modStore, remappedFilename + "-sources.jar");
|
||||
private static void scheduleSourcesRemapping(Project project, SourceRemapper sourceRemapper, File sources, String remappedLog, String remappedFilename, File modStore) {
|
||||
project.getLogger().info(":providing " + remappedLog + " sources");
|
||||
File remappedSources = new File(modStore, remappedFilename + "-sources.jar");
|
||||
|
||||
if (!remappedSources.exists() || sources.lastModified() <= 0 || sources.lastModified() > remappedSources.lastModified()) {
|
||||
try {
|
||||
SourceRemapper.remapSources(project, sources, remappedSources, true);
|
||||
if (!remappedSources.exists() || sources.lastModified() <= 0 || sources.lastModified() > remappedSources.lastModified()) {
|
||||
try {
|
||||
sourceRemapper.scheduleRemapSources(sources, remappedSources);
|
||||
|
||||
//Set the remapped sources creation date to match the sources if we're likely succeeded in making it
|
||||
remappedSources.setLastModified(sources.lastModified());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
project.getLogger().info(remappedSources.getName() + " is up to date with " + sources.getName());
|
||||
//Set the remapped sources creation date to match the sources if we're likely succeeded in making it
|
||||
remappedSources.setLastModified(sources.lastModified());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
project.getLogger().info(remappedSources.getName() + " is up to date with " + sources.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,31 +25,28 @@
|
|||
package net.fabricmc.loom.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
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.gradle.api.artifacts.ResolvedArtifact;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
import org.zeroturnaround.zip.commons.FileUtils;
|
||||
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
|
||||
|
||||
|
@ -58,82 +55,34 @@ import net.fabricmc.loom.providers.MappingsProvider;
|
|||
import net.fabricmc.loom.providers.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.accesswidener.AccessWidener;
|
||||
import net.fabricmc.loom.util.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.tinyremapper.OutputConsumerPath;
|
||||
import net.fabricmc.loom.processors.dependency.ModDependencyInfo;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
import net.fabricmc.tinyremapper.InputTag;
|
||||
import net.fabricmc.tinyremapper.OutputConsumerPath;
|
||||
|
||||
public class ModProcessor {
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
public static void processMod(File input, File output, Project project, Configuration config, ResolvedArtifact artifact) throws IOException {
|
||||
if (output.exists()) {
|
||||
output.delete();
|
||||
public static void processMods(Project project, List<ModDependencyInfo> processList) throws IOException {
|
||||
if (processList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
remapJar(input, output, project, artifact);
|
||||
|
||||
//Enable this if you want your nested jars to be extracted, this will extract **all** jars
|
||||
if (project.getExtensions().getByType(LoomGradleExtension.class).extractJars) {
|
||||
handleNestedJars(input, project, config, artifact);
|
||||
}
|
||||
|
||||
remapaccessWidener(output, project);
|
||||
|
||||
//Always strip the nested jars
|
||||
stripNestedJars(output);
|
||||
}
|
||||
|
||||
private static void handleNestedJars(File input, Project project, Configuration config, ResolvedArtifact artifact) throws IOException {
|
||||
try (JarFile jarFile = new JarFile(input)) {
|
||||
JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json");
|
||||
|
||||
if (modJsonEntry == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) {
|
||||
JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class);
|
||||
|
||||
if (json == null || !json.has("jars")) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonArray jsonArray = json.getAsJsonArray("jars");
|
||||
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
|
||||
String fileName = jsonObject.get("file").getAsString();
|
||||
project.getLogger().lifecycle(String.format("Found %s nested in %s", fileName, input.getName()));
|
||||
processNestedJar(jarFile, fileName, project, config, artifact);
|
||||
}
|
||||
for (ModDependencyInfo info : processList) {
|
||||
if (info.getRemappedOutput().exists()) {
|
||||
info.getRemappedOutput().delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processNestedJar(JarFile parentJar, String fileName, Project project, Configuration config, ResolvedArtifact artifact) throws IOException {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
remapJars(project, processList);
|
||||
|
||||
JarEntry entry = parentJar.getJarEntry(fileName);
|
||||
for (ModDependencyInfo info : processList) {
|
||||
if (!info.getRemappedOutput().exists()) {
|
||||
throw new RuntimeException("Failed to remap mod" + info);
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
throw new RuntimeException(String.format("%s was not found in %s", fileName, parentJar.getName()));
|
||||
stripNestedJars(info.getRemappedOutput());
|
||||
}
|
||||
|
||||
File nestedFile = new File(extension.getNestedModCache(), fileName.substring(fileName.lastIndexOf("/")));
|
||||
|
||||
try (InputStream jarStream = parentJar.getInputStream(entry)) {
|
||||
FileUtils.copy(jarStream, nestedFile);
|
||||
}
|
||||
|
||||
File remappedFile = new File(extension.getRemappedModCache(), fileName.substring(fileName.lastIndexOf("/")));
|
||||
|
||||
processMod(nestedFile, remappedFile, project, config, artifact);
|
||||
|
||||
if (!remappedFile.exists()) {
|
||||
throw new RuntimeException("Failed to find processed nested jar");
|
||||
}
|
||||
|
||||
//Add the project right onto the remapped mods, hopefully this works
|
||||
project.getDependencies().add(config.getName(), project.files(remappedFile));
|
||||
}
|
||||
|
||||
private static void stripNestedJars(File file) {
|
||||
|
@ -148,57 +97,24 @@ public class ModProcessor {
|
|||
}))});
|
||||
}
|
||||
|
||||
private static void remapaccessWidener(File input, Project project) throws IOException {
|
||||
String accessWidenerPath;
|
||||
|
||||
try (JarFile jarFile = new JarFile(input)) {
|
||||
JarEntry modJsonEntry = jarFile.getJarEntry("fabric.mod.json");
|
||||
|
||||
if (modJsonEntry == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (InputStream inputStream = jarFile.getInputStream(modJsonEntry)) {
|
||||
JsonObject json = GSON.fromJson(new InputStreamReader(inputStream), JsonObject.class);
|
||||
|
||||
if (!json.has("accessWidener")) {
|
||||
return;
|
||||
}
|
||||
|
||||
accessWidenerPath = json.get("accessWidener").getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
if (accessWidenerPath == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZipUtil.transformEntry(input, accessWidenerPath, new StringZipEntryTransformer() {
|
||||
@Override
|
||||
protected String transform(ZipEntry zipEntry, String input) throws IOException {
|
||||
return remapaccessWidener(input, project);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String remapaccessWidener(String input, Project project) {
|
||||
try (BufferedReader bufferedReader = new BufferedReader(new StringReader(input))) {
|
||||
private static byte[] remapaccessWidener(byte[] input, Remapper remapper) {
|
||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(input), StandardCharsets.UTF_8))) {
|
||||
AccessWidener accessWidener = new AccessWidener();
|
||||
accessWidener.read(bufferedReader);
|
||||
|
||||
AccessWidenerRemapper accessWidenerRemapper = new AccessWidenerRemapper(accessWidener, project.getExtensions().getByType(LoomGradleExtension.class).getMappingsProvider().getMappings(), "named");
|
||||
AccessWidenerRemapper accessWidenerRemapper = new AccessWidenerRemapper(accessWidener, remapper, "named");
|
||||
AccessWidener remapped = accessWidenerRemapper.remap();
|
||||
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
remapped.write(writer);
|
||||
return writer.toString();
|
||||
return writer.toString().getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void remapJar(File input, File output, Project project, ResolvedArtifact artifact) throws IOException {
|
||||
private static void remapJars(Project project, List<ModDependencyInfo> processList) throws IOException {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
String fromM = "intermediary";
|
||||
String toM = "named";
|
||||
|
@ -206,47 +122,57 @@ public class ModProcessor {
|
|||
MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider();
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
Path inputPath = input.getAbsoluteFile().toPath();
|
||||
Path mc = mappedProvider.getIntermediaryJar().toPath();
|
||||
Path[] mcDeps = mappedProvider.getMapperPaths().stream().map(File::toPath).toArray(Path[]::new);
|
||||
Set<Path> modCompiles = new HashSet<>();
|
||||
|
||||
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
|
||||
project.getConfigurations().getByName(entry.getSourceConfiguration()).getFiles().stream().filter((f) -> !f.equals(input)).map(p -> {
|
||||
if (p.equals(input)) {
|
||||
return inputPath;
|
||||
} else {
|
||||
return p.toPath();
|
||||
}
|
||||
}).forEach(modCompiles::add);
|
||||
}
|
||||
|
||||
project.getLogger().lifecycle(":remapping " + input.getName() + " (TinyRemapper, " + fromM + " -> " + toM + ")");
|
||||
|
||||
// If the sources don't exist, we want remapper to give nicer names to the missing variable names.
|
||||
// However, if the sources do exist, if remapper gives names to the parameters that prevents IDEs (at least IDEA)
|
||||
// from replacing the parameters with the actual names from the sources.
|
||||
boolean sourcesExist = ModCompileRemapper.findSources(project.getDependencies(), artifact) != null;
|
||||
project.getLogger().lifecycle(":remapping " + processList.size() + " mods (TinyRemapper, " + fromM + " -> " + toM + ")");
|
||||
|
||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||
.withMappings(TinyRemapperMappingsHelper.create(mappingsProvider.getMappings(), fromM, toM, false))
|
||||
.renameInvalidLocals(!sourcesExist)
|
||||
.renameInvalidLocals(false)
|
||||
.build();
|
||||
|
||||
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(Paths.get(output.getAbsolutePath())).build()) {
|
||||
outputConsumer.addNonClassFiles(inputPath);
|
||||
remapper.readClassPath(modCompiles.toArray(new Path[0]));
|
||||
remapper.readClassPath(mc);
|
||||
remapper.readClassPath(mcDeps);
|
||||
remapper.readInputs(inputPath);
|
||||
remapper.apply(outputConsumer);
|
||||
} finally {
|
||||
remapper.finish();
|
||||
remapper.readClassPathAsync(mc);
|
||||
remapper.readClassPathAsync(mcDeps);
|
||||
|
||||
final Map<ModDependencyInfo, InputTag> tagMap = new HashMap<>();
|
||||
final Map<ModDependencyInfo, OutputConsumerPath> outputConsumerMap = new HashMap<>();
|
||||
|
||||
for (ModDependencyInfo info : processList) {
|
||||
InputTag tag = remapper.createInputTag();
|
||||
remapper.readInputsAsync(tag, info.getInputFile().toPath());
|
||||
tagMap.put(info, tag);
|
||||
}
|
||||
|
||||
if (!output.exists()) {
|
||||
throw new RuntimeException("Failed to remap JAR to " + toM + " file not found: " + output.getAbsolutePath());
|
||||
// Apply this in a second loop as we need to ensure all the inputs are on the classpath before remapping.
|
||||
for (ModDependencyInfo info : processList) {
|
||||
OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(info.getRemappedOutput().toPath()).build();
|
||||
outputConsumer.addNonClassFiles(info.getInputFile().toPath());
|
||||
outputConsumerMap.put(info, outputConsumer);
|
||||
String accessWidener = info.getAccessWidener();
|
||||
|
||||
if (accessWidener == null) {
|
||||
remapper.apply(outputConsumer, tagMap.get(info));
|
||||
} else {
|
||||
remapper.apply(remapAccessWidener(remapper.getRemapper(), accessWidener, outputConsumer), tagMap.get(info));
|
||||
}
|
||||
}
|
||||
|
||||
remapper.finish();
|
||||
|
||||
for (ModDependencyInfo info : processList) {
|
||||
outputConsumerMap.get(info).close();
|
||||
}
|
||||
}
|
||||
|
||||
static BiConsumer<String, byte[]> remapAccessWidener(Remapper remapper, String accessWidener, BiConsumer<String, byte[]> output) {
|
||||
return (s, bytes) -> {
|
||||
if (s.equals(accessWidener)) {
|
||||
output.accept(s, remapaccessWidener(bytes, remapper));
|
||||
} else {
|
||||
output.accept(s, bytes);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static JsonObject readInstallerJson(File file, Project project) {
|
||||
|
|
|
@ -28,6 +28,8 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.lorenz.io.MappingsReader;
|
||||
|
@ -46,44 +48,46 @@ import net.fabricmc.mapping.tree.TinyTree;
|
|||
import net.fabricmc.stitch.util.StitchUtil;
|
||||
|
||||
public class SourceRemapper {
|
||||
public static void remapSources(Project project, File source, File destination, boolean toNamed) throws Exception {
|
||||
remapSourcesInner(project, source, destination, toNamed);
|
||||
private final Project project;
|
||||
private final boolean toNamed;
|
||||
private final List<Runnable> remapTasks = new ArrayList<>();
|
||||
|
||||
private Mercury mercury;
|
||||
|
||||
public SourceRemapper(Project project, boolean toNamed) {
|
||||
this.project = project;
|
||||
this.toNamed = toNamed;
|
||||
}
|
||||
|
||||
public static void remapSources(Project project, File input, File output, boolean named) throws Exception {
|
||||
SourceRemapper sourceRemapper = new SourceRemapper(project, named);
|
||||
sourceRemapper.scheduleRemapSources(input, output);
|
||||
sourceRemapper.remapAll();
|
||||
}
|
||||
|
||||
public void scheduleRemapSources(File source, File destination) throws Exception {
|
||||
remapTasks.add(() -> {
|
||||
try {
|
||||
remapSourcesInner(source, destination);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to remap sources for " + source, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void remapAll() {
|
||||
if (!remapTasks.isEmpty()) {
|
||||
project.getLogger().lifecycle(":remapping sources");
|
||||
}
|
||||
|
||||
remapTasks.forEach(Runnable::run);
|
||||
// TODO: FIXME - WORKAROUND https://github.com/FabricMC/fabric-loom/issues/45
|
||||
System.gc();
|
||||
}
|
||||
|
||||
private static void remapSourcesInner(Project project, File source, File destination, boolean toNamed) throws Exception {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> {
|
||||
try {
|
||||
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) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
private void remapSourcesInner(File source, File destination) throws Exception {
|
||||
project.getLogger().info(":remapping source jar");
|
||||
|
||||
Mercury mercury = extension.getOrCreateSrcMercuryCache(toNamed ? 1 : 0, () -> {
|
||||
Mercury m = createMercuryWithClassPath(project, toNamed);
|
||||
|
||||
for (Path file : extension.getUnmappedMods()) {
|
||||
if (Files.isRegularFile(file)) {
|
||||
m.getClassPath().add(file);
|
||||
}
|
||||
}
|
||||
|
||||
m.getClassPath().add(extension.getMinecraftMappedProvider().getMappedJar().toPath());
|
||||
m.getClassPath().add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
|
||||
|
||||
m.getProcessors().add(MercuryRemapper.create(mappings));
|
||||
|
||||
return m;
|
||||
});
|
||||
Mercury mercury = getMercuryInstance();
|
||||
|
||||
if (source.equals(destination)) {
|
||||
if (source.isDirectory()) {
|
||||
|
@ -135,6 +139,45 @@ public class SourceRemapper {
|
|||
}
|
||||
}
|
||||
|
||||
private Mercury getMercuryInstance() {
|
||||
if (this.mercury != null) {
|
||||
return this.mercury;
|
||||
}
|
||||
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
MappingsProvider mappingsProvider = extension.getMappingsProvider();
|
||||
|
||||
MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> {
|
||||
try {
|
||||
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) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
Mercury mercury = extension.getOrCreateSrcMercuryCache(toNamed ? 1 : 0, () -> {
|
||||
Mercury m = createMercuryWithClassPath(project, toNamed);
|
||||
|
||||
for (Path file : extension.getUnmappedMods()) {
|
||||
if (Files.isRegularFile(file)) {
|
||||
m.getClassPath().add(file);
|
||||
}
|
||||
}
|
||||
|
||||
m.getClassPath().add(extension.getMinecraftMappedProvider().getMappedJar().toPath());
|
||||
m.getClassPath().add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
|
||||
|
||||
m.getProcessors().add(MercuryRemapper.create(mappings));
|
||||
|
||||
return m;
|
||||
});
|
||||
|
||||
this.mercury = mercury;
|
||||
return mercury;
|
||||
}
|
||||
|
||||
private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException {
|
||||
Files.walk(from).forEach(path -> {
|
||||
Path targetPath = to.resolve(from.relativize(path).toString());
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.objectweb.asm.ClassWriter;
|
|||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
import org.zeroturnaround.zip.transform.ByteArrayZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformer;
|
||||
|
@ -53,6 +54,7 @@ import net.fabricmc.mappings.EntryTriple;
|
|||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.loom.processors.JarProcessor;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public class AccessWidenerJarProcessor implements JarProcessor {
|
||||
private AccessWidener accessWidener = new AccessWidener();
|
||||
|
@ -79,8 +81,13 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
|||
//Remap accessWidener if its not named, allows for AE's to be written in intermediary
|
||||
if (!accessWidener.namespace.equals("named")) {
|
||||
try {
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, loomGradleExtension.getMappingsProvider().getMappings(), "named");
|
||||
TinyRemapper tinyRemapper = loomGradleExtension.getMinecraftMappedProvider().getTinyRemapper("official", "named");
|
||||
tinyRemapper.readClassPath(loomGradleExtension.getMinecraftMappedProvider().getRemapClasspath());
|
||||
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, tinyRemapper.getRemapper(), "named");
|
||||
accessWidener = remapper.remap();
|
||||
|
||||
tinyRemapper.finish();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to remap access widener", e);
|
||||
}
|
||||
|
@ -116,9 +123,8 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
|||
}
|
||||
|
||||
//Called when remapping the mod
|
||||
public void remapAccessWidener(Path modJarPath) throws IOException {
|
||||
LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class);
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, extension.getMappingsProvider().getMappings(), "intermediary");
|
||||
public void remapAccessWidener(Path modJarPath, Remapper asmRemapper) throws IOException {
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, asmRemapper, "intermediary");
|
||||
AccessWidener remapped = remapper.remap();
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
|
|
|
@ -24,54 +24,21 @@
|
|||
|
||||
package net.fabricmc.loom.util.accesswidener;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
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 org.objectweb.asm.commons.Remapper;
|
||||
|
||||
import net.fabricmc.mappings.EntryTriple;
|
||||
|
||||
public class AccessWidenerRemapper {
|
||||
private final AccessWidener input;
|
||||
private final String from, to;
|
||||
private final String to;
|
||||
private final Remapper remapper;
|
||||
|
||||
private Map<String, String> classNames = new HashMap<>();
|
||||
private Map<EntryTriple, EntryTriple> fieldNames = new HashMap<>();
|
||||
private Map<EntryTriple, EntryTriple> methodNames = new HashMap<>();
|
||||
|
||||
public AccessWidenerRemapper(AccessWidener input, TinyTree tinyTree, String to) {
|
||||
public AccessWidenerRemapper(AccessWidener input, Remapper remapper, String to) {
|
||||
this.input = input;
|
||||
this.from = input.namespace;
|
||||
this.to = to;
|
||||
populateMappings(tinyTree);
|
||||
}
|
||||
|
||||
private void populateMappings(TinyTree tinyTree) {
|
||||
if (!tinyTree.getMetadata().getNamespaces().contains(from)) {
|
||||
throw new UnsupportedOperationException("Unknown namespace: " + from);
|
||||
}
|
||||
|
||||
if (!tinyTree.getMetadata().getNamespaces().contains(to)) {
|
||||
throw new UnsupportedOperationException("Unknown namespace: " + to);
|
||||
}
|
||||
|
||||
for (ClassDef classDef : tinyTree.getClasses()) {
|
||||
classNames.put(classDef.getName(from), classDef.getName(to));
|
||||
|
||||
for (FieldDef fieldDef : classDef.getFields()) {
|
||||
EntryTriple fromEntry = new EntryTriple(classDef.getName(from), fieldDef.getName(from), fieldDef.getDescriptor(from));
|
||||
EntryTriple toEntry = new EntryTriple(classDef.getName(to), fieldDef.getName(to), fieldDef.getDescriptor(to));
|
||||
fieldNames.put(fromEntry, toEntry);
|
||||
}
|
||||
|
||||
for (MethodDef methodDef : classDef.getMethods()) {
|
||||
EntryTriple fromEntry = new EntryTriple(classDef.getName(from), methodDef.getName(from), methodDef.getDescriptor(from));
|
||||
EntryTriple toEntry = new EntryTriple(classDef.getName(to), methodDef.getName(to), methodDef.getDescriptor(to));
|
||||
methodNames.put(fromEntry, toEntry);
|
||||
}
|
||||
}
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
public AccessWidener remap() {
|
||||
|
@ -84,27 +51,33 @@ public class AccessWidenerRemapper {
|
|||
remapped.namespace = to;
|
||||
|
||||
for (Map.Entry<String, AccessWidener.Access> entry : input.classAccess.entrySet()) {
|
||||
remapped.classAccess.put(findMapping(classNames, entry.getKey()), entry.getValue());
|
||||
remapped.classAccess.put(remapper.map(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, AccessWidener.Access> entry : input.methodAccess.entrySet()) {
|
||||
remapped.addOrMerge(remapped.methodAccess, findMapping(methodNames, entry.getKey()), entry.getValue());
|
||||
remapped.addOrMerge(remapped.methodAccess, remapMethod(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, AccessWidener.Access> entry : input.fieldAccess.entrySet()) {
|
||||
remapped.addOrMerge(remapped.fieldAccess, findMapping(fieldNames, entry.getKey()), entry.getValue());
|
||||
remapped.addOrMerge(remapped.fieldAccess, remapField(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
return remapped;
|
||||
}
|
||||
|
||||
private static <K, V> V findMapping(Map<K, V> map, K key) {
|
||||
V value = map.get(key);
|
||||
private EntryTriple remapMethod(EntryTriple entryTriple) {
|
||||
return new EntryTriple(
|
||||
remapper.map(entryTriple.getName()),
|
||||
remapper.mapMethodName(entryTriple.getOwner(), entryTriple.getName(), entryTriple.getDesc()),
|
||||
remapper.mapDesc(entryTriple.getDesc())
|
||||
);
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
throw new RuntimeException("Failed to find mapping for " + key.toString());
|
||||
}
|
||||
|
||||
return value;
|
||||
private EntryTriple remapField(EntryTriple entryTriple) {
|
||||
return new EntryTriple(
|
||||
remapper.map(entryTriple.getName()),
|
||||
remapper.mapFieldName(entryTriple.getOwner(), entryTriple.getName(), entryTriple.getDesc()),
|
||||
remapper.mapDesc(entryTriple.getDesc())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue