Start work on porting 0.7.4 over

Signed-off-by: shedaniel <daniel@shedaniel.me>
This commit is contained in:
shedaniel
2021-08-30 14:10:32 +08:00
parent d819b1cc47
commit 9366d42baa
42 changed files with 1221 additions and 818 deletions

View File

@@ -122,6 +122,16 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
return getDependencyManager().getProvider(McpConfigProvider.class);
}
@Override
default boolean isForgeAndOfficial() {
return isForge() && getMcpConfigProvider().isOfficial();
}
@Override
default boolean isForgeAndNotOfficial() {
return isForge() && !getMcpConfigProvider().isOfficial();
}
default SrgProvider getSrgProvider() {
return getDependencyManager().getProvider(SrgProvider.class);
}

View File

@@ -195,6 +195,10 @@ public interface LoomGradleExtensionAPI {
return getPlatform().get() == ModPlatform.FORGE;
}
boolean isForgeAndOfficial();
boolean isForgeAndNotOfficial();
boolean supportsInclude();
void setGenerateSrgTiny(Boolean generateSrgTiny);

View File

@@ -83,8 +83,9 @@ public final class CompileConfiguration {
extension.createLazyConfiguration(Constants.Configurations.FORGE_USERDEV).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_INSTALLER).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_UNIVERSAL).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_DEPENDENCIES).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_DEPENDENCIES);
extension.createLazyConfiguration(Constants.Configurations.FORGE_NAMED).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.FORGE_EXTRA).configure(configuration -> configuration.setTransitive(false));
extension.createLazyConfiguration(Constants.Configurations.MCP_CONFIG).configure(configuration -> configuration.setTransitive(false));
extendsFrom(Constants.Configurations.MINECRAFT_DEPENDENCIES, Constants.Configurations.FORGE_DEPENDENCIES, project);
@@ -93,6 +94,10 @@ public final class CompileConfiguration {
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_NAMED, project);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.FORGE_EXTRA, project);
}
if (extension.supportsInclude()) {

View File

@@ -24,21 +24,15 @@
package net.fabricmc.loom.configuration.ide;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
@@ -132,23 +126,6 @@ public class RunConfig {
runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main";
runConfig.vmArgs = "-Dfabric.dli.config=" + encodeEscaped(extension.getFiles().getDevLauncherConfig().getAbsolutePath()) + " -Dfabric.dli.env=" + environment.toLowerCase();
if (extension.isForge()) {
List<String> modClasses = new ArrayList<>();
for (Supplier<SourceSet> sourceSetSupplier : extension.getForgeLocalMods()) {
SourceSet sourceSet = sourceSetSupplier.get();
String sourceSetName = sourceSet.getName() + "_" + UUID.randomUUID().toString().replace("-", "").substring(0, 7);
Stream.concat(
Stream.of(sourceSet.getOutput().getResourcesDir().getAbsolutePath()),
StreamSupport.stream(sourceSet.getOutput().getClassesDirs().spliterator(), false)
.map(File::getAbsolutePath)
).map(s -> sourceSetName + "%%" + s).collect(Collectors.toCollection(() -> modClasses));
}
runConfig.envVariables.put("MOD_CLASSES", String.join(File.pathSeparator, modClasses));
}
}
// Turns camelCase/PascalCase into Capital Case
@@ -162,6 +139,7 @@ public class RunConfig {
}
public static RunConfig runConfig(Project project, RunConfigSettings settings) {
settings.evaluateNow();
LoomGradleExtension extension = LoomGradleExtension.get(project);
String name = settings.getName();
@@ -195,6 +173,7 @@ public class RunConfig {
}
RunConfig runConfig = new RunConfig();
runConfig.envVariables.putAll(settings.envVariables);
runConfig.configName = configName;
populate(project, extension, runConfig, environment);
runConfig.ideaModuleName = getIdeaModuleName(project, sourceSet);

View File

@@ -28,6 +28,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -36,6 +37,7 @@ import org.gradle.api.Named;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants;
@@ -96,6 +98,8 @@ public final class RunConfigSettings implements Named {
private final Project project;
private final LoomGradleExtension extension;
public final Map<String, String> envVariables = new HashMap<>();
private List<Runnable> evaluateLater = new ArrayList<>();
public RunConfigSettings(Project project, String baseName) {
this.baseName = baseName;
@@ -107,6 +111,20 @@ public final class RunConfigSettings implements Named {
runDir("run");
}
@ApiStatus.Internal
public void evaluateLater(Runnable runnable) {
this.evaluateLater.add(runnable);
}
@ApiStatus.Internal
public void evaluateNow() {
for (Runnable runnable : this.evaluateLater) {
runnable.run();
}
this.evaluateLater.clear();
}
public Project getProject() {
return project;
}

View File

@@ -46,13 +46,13 @@ public class SetupIntelijRunConfigs {
}
try {
generate(project);
generate(project, false);
} catch (IOException e) {
throw new RuntimeException("Failed to generate run configs", e);
}
}
private static void generate(Project project) throws IOException {
public static void generate(Project project, boolean override) throws IOException {
Project rootProject = project.getRootProject();
LoomGradleExtension extension = LoomGradleExtension.get(project);
@@ -82,6 +82,10 @@ public class SetupIntelijRunConfigs {
File runConfigs = new File(runConfigsDir, name + projectPath + ".xml");
String runConfigXml = config.fromDummy("idea_run_config_template.xml");
if (runConfigs.exists() && override) {
runConfigs.delete();
}
if (!runConfigs.exists()) {
FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8);
}

View File

@@ -33,11 +33,13 @@ import java.util.Map;
import org.gradle.api.Named;
import org.gradle.api.Project;
import org.jetbrains.annotations.ApiStatus;
public class LaunchProviderSettings implements Named {
private final String name;
private List<Map.Entry<String, String>> properties = new ArrayList<>();
private List<String> arguments = new ArrayList<>();
private List<Runnable> evaluateLater = new ArrayList<>();
public LaunchProviderSettings(Project project, String name) {
this.name = name;
@@ -48,6 +50,20 @@ public class LaunchProviderSettings implements Named {
return name;
}
@ApiStatus.Internal
public void evaluateLater(Runnable runnable) {
this.evaluateLater.add(runnable);
}
@ApiStatus.Internal
public void evaluateNow() {
for (Runnable runnable : this.evaluateLater) {
runnable.run();
}
this.evaluateLater.clear();
}
public void arg(String argument) {
this.arguments.add(argument);
}

View File

@@ -164,7 +164,7 @@ public class ModProcessor {
remapper.readClassPathAsync(mc);
if (extension.isForge()) {
if (extension.isForgeAndNotOfficial()) {
remapper.readClassPathAsync(mappedProvider.getForgeSrgJar().toPath());
}

View File

@@ -60,31 +60,21 @@ public class LaunchProvider extends DependencyProvider {
.property("log4j.configurationFile", getAllLog4JConfigFiles())
.property("client", "java.library.path", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath())
.property("client", "org.lwjgl.librarypath", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath())
.property("client", "org.lwjgl.librarypath", getExtension().getMinecraftProvider().nativesDir().getAbsolutePath());
.argument("client", "--assetIndex")
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
.argument("client", "--assetsDir")
.argument("client", new File(getDirectories().getUserCache(), "assets").getAbsolutePath());
if (!getExtension().isForge()) {
launchConfig
.argument("client", "--assetIndex")
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
.argument("client", "--assetsDir")
.argument("client", new File(getDirectories().getUserCache(), "assets").getAbsolutePath());
}
if (getExtension().isForge()) {
launchConfig
// Should match YarnNamingService.PATH_TO_MAPPINGS in forge-runtime
.property("fabric.yarnWithSrg.path", getExtension().getMappingsProvider().tinyMappingsWithSrg.toAbsolutePath().toString())
.argument("--fml.mcVersion")
.argument(getExtension().getMinecraftProvider().minecraftVersion())
.argument("--fml.forgeVersion")
.argument(getExtension().getForgeProvider().getVersion().getForgeVersion())
.argument("client", "--launchTarget")
.argument("client", "fmluserdevclient")
.argument("server", "--launchTarget")
.argument("server", "fmluserdevserver")
.argument("data", "--launchTarget")
.argument("data", "fmluserdevdata")
.argument("data", "--all")
.argument("data", "--mod")
.argument("data", String.join(",", getExtension().getDataGenMods()))
@@ -109,7 +99,18 @@ public class LaunchProvider extends DependencyProvider {
}
}
addDependency(Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
addDependency(Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
addDependency(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
if (getExtension().isForge()) {
addDependency(Constants.Dependencies.FORGE_RUNTIME + Constants.Dependencies.Versions.FORGE_RUNTIME, Constants.Configurations.FORGE_EXTRA);
addDependency(Constants.Dependencies.JAVAX_ANNOTATIONS + Constants.Dependencies.Versions.JAVAX_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
}
for (LaunchProviderSettings settings : getExtension().getLaunchConfigs()) {
settings.evaluateNow();
for (String argument : settings.getArguments()) {
launchConfig.argument(settings.getName(), argument);
}
@@ -129,16 +130,6 @@ public class LaunchProvider extends DependencyProvider {
writeLog4jConfig();
FileUtils.writeStringToFile(getDirectories().getDevLauncherConfig(), launchConfig.asString(), StandardCharsets.UTF_8);
addDependency(Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
addDependency(Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES);
addDependency(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
if (getExtension().isForge()) {
addDependency(Constants.Dependencies.FORGE_RUNTIME + Constants.Dependencies.Versions.FORGE_RUNTIME, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
addDependency(Constants.Dependencies.FORGE_RUNTIME + Constants.Dependencies.Versions.FORGE_RUNTIME, JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME);
addDependency(Constants.Dependencies.JAVAX_ANNOTATIONS + Constants.Dependencies.Versions.JAVAX_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
}
postPopulationScheduler.accept(this::writeRemapClassPath);
}
@@ -178,7 +169,7 @@ public class LaunchProvider extends DependencyProvider {
remapClasspath.add(getExtension().getMinecraftMappedProvider().getIntermediaryJar());
if (getExtension().isForge()) {
if (getExtension().isForgeAndNotOfficial()) {
remapClasspath.add(getExtension().getMinecraftMappedProvider().getForgeIntermediaryJar());
}

View File

@@ -103,7 +103,7 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl {
@Override
protected String createMappingsIdentifier(String mappingsName, String version, String classifier) {
return super.createMappingsIdentifier(mappingsName, version, classifier) + "-forge-" + getExtension().getPatchProvider().forgeVersion;
return super.createMappingsIdentifier(mappingsName, version, classifier) + "-forge-" + getExtension().getForgeProvider().getVersion().getCombined();
}
@Override
@@ -116,7 +116,7 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl {
if (getExtension().shouldGenerateSrgTiny()) {
if (Files.notExists(rawTinyMappingsWithSrg) || isRefreshDeps()) {
// Merge tiny mappings with srg
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), rawTinyMappings, rawTinyMappingsWithSrg, true);
SrgMerger.mergeSrg(this::getMojmapSrgFileIfPossible, getRawSrgFile(), rawTinyMappings, rawTinyMappingsWithSrg, true);
}
}

View File

@@ -55,10 +55,13 @@ public class ForgeProvider extends DependencyProvider {
}
public static final class ForgeVersion {
private final String combined;
private final String minecraftVersion;
private final String forgeVersion;
public ForgeVersion(String combined) {
this.combined = combined;
if (combined == null) {
this.minecraftVersion = "NO_VERSION";
this.forgeVersion = "NO_VERSION";
@@ -76,6 +79,10 @@ public class ForgeProvider extends DependencyProvider {
}
}
public String getCombined() {
return combined;
}
public String getMinecraftVersion() {
return minecraftVersion;
}

View File

@@ -25,6 +25,7 @@
package net.fabricmc.loom.configuration.providers.forge;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.nio.file.FileSystem;
@@ -32,19 +33,46 @@ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.artifacts.transform.InputArtifact;
import org.gradle.api.artifacts.transform.TransformAction;
import org.gradle.api.artifacts.transform.TransformOutputs;
import org.gradle.api.artifacts.transform.TransformParameters;
import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
import org.gradle.api.attributes.Attribute;
import org.gradle.api.file.FileSystemLocation;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
public class ForgeUserdevProvider extends DependencyProvider {
private File userdevJar;
private JsonObject json;
private Consumer<Runnable> postPopulationScheduler;
public ForgeUserdevProvider(Project project) {
super(project);
@@ -52,6 +80,18 @@ public class ForgeUserdevProvider extends DependencyProvider {
@Override
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
this.postPopulationScheduler = postPopulationScheduler;
Attribute<Boolean> transformed = Attribute.of("architectury-loom-forge-dependencies-transformed", Boolean.class);
getProject().getDependencies().registerTransform(RemoveNameProvider.class, spec -> {
spec.getFrom().attribute(transformed, false);
spec.getTo().attribute(transformed, true);
});
for (ArtifactTypeDefinition type : getProject().getDependencies().getArtifactTypes()) {
type.getAttributes().attribute(transformed, false);
}
userdevJar = new File(getDirectories().getProjectPersistentCache(), "forge-" + dependency.getDependency().getVersion() + "-userdev.jar");
Path configJson = getDirectories()
@@ -68,8 +108,6 @@ public class ForgeUserdevProvider extends DependencyProvider {
}
}
JsonObject json;
try (Reader reader = Files.newBufferedReader(configJson)) {
json = new Gson().fromJson(reader, JsonObject.class);
}
@@ -79,19 +117,199 @@ public class ForgeUserdevProvider extends DependencyProvider {
addDependency(json.get("universal").getAsString(), Constants.Configurations.FORGE_UNIVERSAL);
for (JsonElement lib : json.get("libraries").getAsJsonArray()) {
Dependency dep = null;
if (lib.getAsString().startsWith("org.spongepowered:mixin:")) {
if (getExtension().isUseFabricMixin()) {
addDependency("net.fabricmc:sponge-mixin:0.8.2+build.24", Constants.Configurations.FORGE_DEPENDENCIES);
continue;
dep = addDependency("net.fabricmc:sponge-mixin:0.8.2+build.24", Constants.Configurations.FORGE_DEPENDENCIES);
}
}
addDependency(lib.getAsString(), Constants.Configurations.FORGE_DEPENDENCIES);
if (dep == null) {
dep = addDependency(lib.getAsString(), Constants.Configurations.FORGE_DEPENDENCIES);
}
if (lib.getAsString().split(":").length < 4) {
((ModuleDependency) dep).attributes(attributes -> {
attributes.attribute(transformed, true);
});
}
}
// TODO: Read launch configs from the JSON too
// TODO: Should I copy the patches from here as well?
// That'd require me to run the "MCP environment" fully up to merging.
for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject("runs").entrySet()) {
LaunchProviderSettings launchSettings = getExtension().getLaunchConfigs().findByName(entry.getKey());
RunConfigSettings settings = getExtension().getRunConfigs().findByName(entry.getKey());
JsonObject value = entry.getValue().getAsJsonObject();
if (launchSettings != null) {
launchSettings.evaluateLater(() -> {
if (value.has("args")) {
launchSettings.arg(StreamSupport.stream(value.getAsJsonArray("args").spliterator(), false)
.map(JsonElement::getAsString)
.map(this::processTemplates)
.collect(Collectors.toList()));
}
if (value.has("props")) {
for (Map.Entry<String, JsonElement> props : value.getAsJsonObject("props").entrySet()) {
String string = processTemplates(props.getValue().getAsString());
launchSettings.property(props.getKey(), string);
}
}
});
}
if (settings != null) {
settings.evaluateLater(() -> {
settings.defaultMainClass(value.getAsJsonPrimitive("main").getAsString());
settings.vmArgs(StreamSupport.stream(value.getAsJsonArray("jvmArgs").spliterator(), false)
.map(JsonElement::getAsString)
.map(this::processTemplates)
.collect(Collectors.toList()));
for (Map.Entry<String, JsonElement> env : value.getAsJsonObject("env").entrySet()) {
String string = processTemplates(env.getValue().getAsString());
settings.envVariables.put(env.getKey(), string);
}
});
}
}
}
public abstract static class RemoveNameProvider implements TransformAction<TransformParameters.None> {
@InputArtifact
public abstract Provider<FileSystemLocation> getInput();
@Override
public void transform(TransformOutputs outputs) {
try {
File input = getInput().get().getAsFile();
//architectury-loom-forge-dependencies-transformed
File output = outputs.file(input.getName() + "-alfd-transformed.jar");
Files.copy(input.toPath(), output.toPath(), StandardCopyOption.REPLACE_EXISTING);
try (FileSystemUtil.FileSystemDelegate fs = FileSystemUtil.getJarFileSystem(output, false)) {
Path path = fs.get().getPath("META-INF/services/cpw.mods.modlauncher.api.INameMappingService");
Files.deleteIfExists(path);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public String processTemplates(String string) {
if (string.startsWith("{")) {
String key = string.substring(1, string.length() - 1);
// TODO: Look into ways to not hardcode
if (key.equals("runtime_classpath")) {
string = runtimeClasspath().stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining(File.pathSeparator));
} else if (key.equals("minecraft_classpath")) {
string = minecraftClasspath().stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining(File.pathSeparator));
} else if (key.equals("runtime_classpath_file")) {
Path path = getDirectories().getProjectPersistentCache().toPath().resolve("forge_runtime_classpath.txt");
postPopulationScheduler.accept(() -> {
try {
Files.writeString(path, runtimeClasspath().stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining("\n")),
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
string = path.toAbsolutePath().toString();
} else if (key.equals("minecraft_classpath_file")) {
Path path = getDirectories().getProjectPersistentCache().toPath().resolve("forge_minecraft_classpath.txt");
postPopulationScheduler.accept(() -> {
try {
Files.writeString(path, minecraftClasspath().stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining("\n")),
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
string = path.toAbsolutePath().toString();
} else if (key.equals("asset_index")) {
string = getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion());
} else if (key.equals("assets_root")) {
string = new File(getDirectories().getUserCache(), "assets").getAbsolutePath();
} else if (key.equals("natives")) {
string = getMinecraftProvider().nativesDir().getAbsolutePath();
} else if (key.equals("source_roots")) {
List<String> modClasses = new ArrayList<>();
for (Supplier<SourceSet> sourceSetSupplier : getExtension().getForgeLocalMods()) {
SourceSet sourceSet = sourceSetSupplier.get();
String sourceSetName = sourceSet.getName() + "_" + UUID.randomUUID().toString().replace("-", "").substring(0, 7);
Stream.concat(
Stream.of(sourceSet.getOutput().getResourcesDir().getAbsolutePath()),
StreamSupport.stream(sourceSet.getOutput().getClassesDirs().spliterator(), false)
.map(File::getAbsolutePath)
).map(s -> sourceSetName + "%%" + s).collect(Collectors.toCollection(() -> modClasses));
}
string = String.join(File.pathSeparator, modClasses);
} else if (json.has(key)) {
JsonElement element = json.get(key);
if (element.isJsonArray()) {
string = StreamSupport.stream(element.getAsJsonArray().spliterator(), false)
.map(JsonElement::getAsString)
.flatMap(str -> {
if (str.contains(":")) {
return DependencyDownloader.download(getProject(), str, false, false).getFiles().stream()
.map(File::getAbsolutePath)
.filter(dep -> !dep.contains("bootstraplauncher")); // TODO: Hack
}
return Stream.of(str);
})
.collect(Collectors.joining(File.pathSeparator));
} else {
string = element.toString();
}
} else {
getProject().getLogger().warn("Unrecognized template! " + string);
}
}
return string;
}
private Set<File> runtimeClasspath() {
// Should we actually include the runtime classpath here? Forge doesn't seem to be using this property anyways
Set<File> mcLibs = DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_DEPENDENCIES), true);
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES), false));
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_EXTRA), false));
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_NAMED), false));
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_NAMED), false));
return mcLibs;
}
private Set<File> minecraftClasspath() {
Set<File> mcLibs = DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_DEPENDENCIES), true);
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES), false));
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_EXTRA), false));
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_NAMED), false));
mcLibs.addAll(DependencyDownloader.resolveFiles(getProject().getConfigurations().getByName(Constants.Configurations.FORGE_NAMED), false));
return mcLibs;
}
public File getUserdevJar() {

View File

@@ -24,19 +24,33 @@
package net.fabricmc.loom.configuration.providers.forge;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.function.Consumer;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.FileSystemUtil;
public class McpConfigProvider extends DependencyProvider {
private File mcp;
private Path configJson;
private Path mappings;
private Boolean official;
private String mappingsPath;
public McpConfigProvider(Project project) {
super(project);
@@ -46,25 +60,63 @@ public class McpConfigProvider extends DependencyProvider {
public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception {
init(dependency.getDependency().getVersion());
if (mcp.exists() && !isRefreshDeps()) {
return; // No work for us to do here
}
Path mcpZip = dependency.resolveFile().orElseThrow(() -> new RuntimeException("Could not resolve MCPConfig")).toPath();
if (!mcp.exists() || isRefreshDeps()) {
if (!mcp.exists() || !Files.exists(configJson) || isRefreshDeps()) {
Files.copy(mcpZip, mcp.toPath(), StandardCopyOption.REPLACE_EXISTING);
try (FileSystemUtil.FileSystemDelegate fs = FileSystemUtil.getJarFileSystem(mcp, false)) {
Files.copy(fs.get().getPath("config.json"), configJson, StandardCopyOption.REPLACE_EXISTING);
}
}
JsonObject json;
try (Reader reader = Files.newBufferedReader(configJson)) {
json = new Gson().fromJson(reader, JsonObject.class);
}
official = json.has("official") && json.getAsJsonPrimitive("official").getAsBoolean();
mappingsPath = json.get("data").getAsJsonObject().get("mappings").getAsString();
}
private void init(String version) throws IOException {
File dir = getMinecraftProvider().dir("mcp/" + version);
mcp = new File(dir, "mcp.zip");
configJson = dir.toPath().resolve("mcp-config.json");
mappings = dir.toPath().resolve("mcp-config-mappings.txt");
if (isRefreshDeps()) {
Files.deleteIfExists(mappings);
}
}
private void init(String version) {
mcp = new File(getDirectories().getUserCache(), "mcp-" + version + ".zip");
public Path getMappings() {
if (Files.notExists(mappings)) {
if (!ZipUtil.handle(getMcp(), getMappingsPath(), (in, zipEntry) -> {
try (BufferedWriter writer = Files.newBufferedWriter(mappings, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
IOUtils.copy(in, writer, StandardCharsets.UTF_8);
}
})) {
throw new IllegalStateException("Failed to find mappings '" + getMappingsPath() + "' in " + getMcp().getAbsolutePath() + "!");
}
}
return mappings;
}
public File getMcp() {
return mcp;
}
public boolean isOfficial() {
return official;
}
public String getMappingsPath() {
return mappingsPath;
}
@Override
public String getTargetConfig() {
return Constants.Configurations.MCP_CONFIG;

View File

@@ -29,7 +29,6 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UncheckedIOException;
@@ -55,47 +54,63 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteSource;
import com.google.gson.JsonParser;
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import net.minecraftforge.binarypatcher.ConsoleTool;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.configuration.ShowStacktrace;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingLayer;
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.MappingsProviderVerbose;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.function.FsPathConsumer;
import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
import net.fabricmc.loom.util.srg.Tsrg2Utils;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappingio.MappingVisitor;
public class MinecraftPatchedProvider extends DependencyProvider {
private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version";
@@ -115,11 +130,14 @@ public class MinecraftPatchedProvider extends DependencyProvider {
// Step 5: Remap Patched AT & Forge to Official (global or project)
private File minecraftMergedPatchedJar;
private File forgeMergedJar;
private File minecraftClientExtra;
private File projectAtHash;
private Set<File> projectAts = new HashSet<>();
private boolean atDirty = false;
private boolean filesDirty = false;
private Path mcpConfigMappings;
private Path[] mergedMojangTsrg2Files;
public MinecraftPatchedProvider(Project project) {
super(project);
@@ -161,34 +179,29 @@ public class MinecraftPatchedProvider extends DependencyProvider {
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
PatchProvider patchProvider = getExtension().getPatchProvider();
String minecraftVersion = minecraftProvider.minecraftVersion();
String patchId = "forge-" + patchProvider.forgeVersion;
if (getExtension().isUseFabricMixin()) {
patchId += "-fabric-mixin";
}
String patchId = "forge-" + getExtension().getForgeProvider().getVersion().getCombined();
minecraftProvider.setJarSuffix(patchId);
File globalCache = getDirectories().getUserCache();
File globalCache = getMinecraftProvider().dir("forge/" + getExtension().getForgeProvider().getVersion().getCombined());
File cache = usesProjectCache() ? getDirectories().getProjectPersistentCache() : globalCache;
File globalDir = new File(globalCache, patchId);
File projectDir = new File(cache, patchId);
globalDir.mkdirs();
File projectDir = new File(cache, "forge/" + getExtension().getForgeProvider().getVersion().getCombined());
projectDir.mkdirs();
minecraftClientSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-client-srg.jar");
minecraftServerSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-srg.jar");
minecraftClientPatchedSrgJar = new File(globalDir, "client-srg-patched.jar");
minecraftServerPatchedSrgJar = new File(globalDir, "server-srg-patched.jar");
minecraftMergedPatchedSrgJar = new File(globalDir, "merged-srg-patched.jar");
forgeMergedJar = new File(globalDir, "forge-official.jar");
minecraftClientSrgJar = new File(globalCache, "minecraft-client-srg.jar");
minecraftServerSrgJar = new File(globalCache, "minecraft-server-srg.jar");
minecraftClientPatchedSrgJar = new File(globalCache, "client-srg-patched.jar");
minecraftServerPatchedSrgJar = new File(globalCache, "server-srg-patched.jar");
minecraftMergedPatchedSrgJar = new File(globalCache, "merged-srg-patched.jar");
forgeMergedJar = getExtension().isForgeAndOfficial() ? null : new File(globalCache, "forge-official.jar");
minecraftMergedPatchedSrgAtJar = new File(projectDir, "merged-srg-at-patched.jar");
minecraftMergedPatchedJar = new File(projectDir, "merged-patched.jar");
minecraftClientExtra = new File(globalCache, "forge-client-extra.jar");
if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(Predicates.not(File::exists))
if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(((Predicate<File>) File::exists).negate())
|| !isPatchedJarUpToDate(minecraftMergedPatchedJar)) {
cleanAllCache();
} else if (atDirty || Stream.of(getProjectCache()).anyMatch(Predicates.not(File::exists))) {
} else if (atDirty || Stream.of(getProjectCache()).anyMatch(((Predicate<File>) File::exists).negate())) {
cleanProjectCache();
}
}
@@ -213,14 +226,21 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private File[] getGlobalCaches() {
return new File[] {
File[] files = {
minecraftClientSrgJar,
minecraftServerSrgJar,
minecraftClientPatchedSrgJar,
minecraftServerPatchedSrgJar,
minecraftMergedPatchedSrgJar,
forgeMergedJar,
minecraftClientExtra,
};
if (forgeMergedJar != null) {
Arrays.copyOf(files, files.length + 1);
files[files.length - 1] = forgeMergedJar;
}
return files;
}
public void cleanProjectCache() {
@@ -270,7 +290,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
accessTransformForge(getProject().getLogger());
}
if (!forgeMergedJar.exists()) {
if (forgeMergedJar != null && !forgeMergedJar.exists()) {
this.dirty = true;
}
@@ -278,10 +298,25 @@ public class MinecraftPatchedProvider extends DependencyProvider {
if (dirty) {
remapPatchedJar(input, getProject().getLogger());
if (getExtension().isForgeAndOfficial()) {
fillClientExtraJar();
}
}
this.filesDirty = dirty;
this.dirty = false;
if (getExtension().isForgeAndOfficial()) {
addDependency(minecraftClientExtra, Constants.Configurations.FORGE_EXTRA);
}
}
private void fillClientExtraJar() throws IOException {
Files.deleteIfExists(minecraftClientExtra.toPath());
FileSystemUtil.getJarFileSystem(minecraftClientExtra, true).close();
copyNonClassFiles(getExtension().getMinecraftProvider().minecraftClientJar, minecraftClientExtra);
}
private TinyRemapper buildRemapper(Path input) throws IOException {
@@ -291,12 +326,16 @@ public class MinecraftPatchedProvider extends DependencyProvider {
.logger(getProject().getLogger()::lifecycle)
.logUnknownInvokeDynamic(false)
.withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true))
.withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official"))
.withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappingsWithSrg, "srg", "official"))
.renameInvalidLocals(true)
.rebuildSourceFilenames(true)
.fixPackageAccess(true)
.build();
if (getProject().getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
MappingsProviderVerbose.saveFile(remapper);
}
remapper.readClassPath(libraries);
remapper.prepareClasses();
return remapper;
@@ -309,41 +348,107 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private void createSrgJars(Logger logger) throws Exception {
McpConfigProvider mcpProvider = getExtension().getMcpConfigProvider();
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
String dep = getExtension().isForgeAndOfficial() ? Constants.Dependencies.VIGNETTE + Constants.Dependencies.Versions.VIGNETTE
: Constants.Dependencies.SPECIAL_SOURCE + Constants.Dependencies.Versions.SPECIAL_SOURCE + ":shaded";
FileCollection classpath = DependencyDownloader.download(getProject(), dep, true, true);
produceSrgJar(getExtension().isForgeAndOfficial(), minecraftProvider.minecraftClientJar.toPath(), minecraftProvider.minecraftServerJar.toPath(), classpath);
}
String[] mappingsPath = {null};
if (!ZipUtil.handle(mcpProvider.getMcp(), "config.json", (in, zipEntry) -> {
mappingsPath[0] = JsonParser.parseReader(new InputStreamReader(in)).getAsJsonObject().get("data").getAsJsonObject().get("mappings").getAsString();
})) {
throw new IllegalStateException("Failed to find 'config.json' in " + mcpProvider.getMcp().getAbsolutePath() + "!");
}
Path[] tmpSrg = {null};
if (!ZipUtil.handle(mcpProvider.getMcp(), mappingsPath[0], (in, zipEntry) -> {
tmpSrg[0] = Files.createTempFile(null, null);
try (BufferedWriter writer = Files.newBufferedWriter(tmpSrg[0])) {
IOUtils.copy(in, writer, StandardCharsets.UTF_8);
}
})) {
throw new IllegalStateException("Failed to find mappings '" + mappingsPath[0] + "' in " + mcpProvider.getMcp().getAbsolutePath() + "!");
}
String atDependency = Constants.Dependencies.SPECIAL_SOURCE + Constants.Dependencies.Versions.SPECIAL_SOURCE + ":shaded";
// Do getFiles() to resolve it before multithreading it
FileCollection classpath = getProject().files(DependencyDownloader.download(getProject(), atDependency).getFiles());
private void produceSrgJar(boolean official, Path clientJar, Path serverJar, FileCollection classpath) throws IOException {
Path tmpSrg = getToSrgMappings();
Set<File> mcLibs = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).resolve();
ThreadingUtils.run(() -> {
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "client", classpath, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath());
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "client", classpath, clientJar, tmpSrg), minecraftClientSrgJar.toPath());
}, () -> {
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "server", classpath, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath());
Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "server", classpath, serverJar, tmpSrg), minecraftServerSrgJar.toPath());
});
}
private Path getToSrgMappings() throws IOException {
if (getExtension().isForgeAndOfficial()) {
return getMergedMojangTsrg2(true);
} else {
return getExtension().getMcpConfigProvider().getMappings();
}
}
private static void visitMojmap(MappingVisitor visitor, LoomGradleExtension extension) {
GradleMappingContext context = new GradleMappingContext(extension.getForgeProvider().getProject(), "tmp-mojmap");
try {
FileUtils.deleteDirectory(context.workingDirectory("/"));
MojangMappingLayer layer = new MojangMappingsSpec(() -> true).createLayer(context);
layer.visit(visitor);
} catch (IOException e) {
throw new UncheckedIOException(e);
} finally {
try {
FileUtils.deleteDirectory(context.workingDirectory("/"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static Path getMojmapTsrg(LoomGradleExtension extension) throws IOException {
Path path = extension.getMinecraftProvider().dir("forge").toPath().resolve("mojmap.tsrg");
if (Files.notExists(path)) {
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
Tsrg2Utils.writeTsrg(visitor -> visitMojmap(visitor, extension),
MappingNamespace.NAMED.stringValue(), false, writer);
}
}
return path;
}
public static Path getMojmapTsrg2(LoomGradleExtension extension) throws IOException {
Path path = extension.getMinecraftProvider().dir("forge").toPath().resolve("mojmap.tsrg");
if (Files.notExists(path)) {
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
Tsrg2Utils.writeTsrg2(visitor -> visitMojmap(visitor, extension), writer);
}
}
return path;
}
public Path getMergedMojangTsrg2(boolean hasParameters) throws IOException {
if (mergedMojangTsrg2Files == null) {
Path out = Files.createTempFile("merged-mojang-tsrg2", null);
Path outTrimmed = Files.createTempFile("merged-mojang-tsrg2-trimmed", null);
net.minecraftforge.installertools.ConsoleTool.main(new String[]{
"--task",
"MERGE_MAPPING",
"--left",
getExtension().getMcpConfigProvider().getMappings().toAbsolutePath().toString(),
"--right",
getMojmapTsrg(getExtension()).toAbsolutePath().toString(),
"--classes",
"--output",
out.toAbsolutePath().toString()
});
MutableTinyTree mappings = MappingsUtils.deserializeFromTsrg2(FileUtils.readFileToString(out.toFile(), StandardCharsets.UTF_8));
for (MutableClassDef classDef : mappings.getClassesMutable()) {
for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
methodDef.getParametersMutable().clear();
}
}
Files.writeString(outTrimmed, MappingsUtils.serializeToTsrg2(mappings), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
mergedMojangTsrg2Files = new Path[]{out, outTrimmed};
}
return mergedMojangTsrg2Files[hasParameters ? 0 : 1];
}
private void fixParameterAnnotation(File jarFile) throws Exception {
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.getAbsolutePath());
Stopwatch stopwatch = Stopwatch.createStarted();
@@ -378,6 +483,60 @@ public class MinecraftPatchedProvider extends DependencyProvider {
getProject().getLogger().info(":fixing parameter annotations for " + jarFile.getAbsolutePath() + " in " + stopwatch);
}
private void deleteParameterNames(File jarFile) throws Exception {
getProject().getLogger().info(":deleting parameter names for " + jarFile.getAbsolutePath());
Stopwatch stopwatch = Stopwatch.createStarted();
try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + jarFile.toURI()), ImmutableMap.of("create", false))) {
ThreadingUtils.TaskCompleter completer = ThreadingUtils.taskCompleter();
Pattern vignetteParameters = Pattern.compile("p_\\d+_");
for (Path file : (Iterable<? extends Path>) Files.walk(fs.getPath("/"))::iterator) {
if (!file.toString().endsWith(".class")) continue;
completer.add(() -> {
byte[] bytes = Files.readAllBytes(file);
ClassReader reader = new ClassReader(bytes);
ClassWriter writer = new ClassWriter(0);
reader.accept(new ClassVisitor(Opcodes.ASM9, writer) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
return new MethodVisitor(Opcodes.ASM9, super.visitMethod(access, name, descriptor, signature, exceptions)) {
@Override
public void visitParameter(String name, int access) {
if (vignetteParameters.matcher(name).matches()) {
super.visitParameter(null, access);
} else {
super.visitParameter(name, access);
}
}
@Override
public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
if (!vignetteParameters.matcher(name).matches()) {
super.visitLocalVariable(name, descriptor, signature, start, end, index);
}
}
};
}
}, 0);
byte[] out = writer.toByteArray();
if (!Arrays.equals(bytes, out)) {
Files.delete(file);
Files.write(file, out);
}
});
}
completer.complete();
}
getProject().getLogger().info(":deleting parameter names for " + jarFile.getAbsolutePath() + " in " + stopwatch);
}
private File getForgeJar() {
return getExtension().getForgeUniversalProvider().getForge();
}
@@ -453,8 +612,10 @@ public class MinecraftPatchedProvider extends DependencyProvider {
spec.setClasspath(classpath);
// if running with INFO or DEBUG logging
if (getProject().getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
if (getProject().getGradle().getStartParameter().getShowStacktrace() != ShowStacktrace.INTERNAL_EXCEPTIONS
|| getProject().getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
spec.setStandardOutput(System.out);
spec.setErrorOutput(System.err);
} else {
spec.setStandardOutput(NullOutputStream.NULL_OUTPUT_STREAM);
spec.setErrorOutput(NullOutputStream.NULL_OUTPUT_STREAM);
@@ -529,7 +690,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
ThreadingUtils.run(Environment.values(), environment -> {
copyMissingClasses(environment.srgJar.apply(this), environment.patchedSrgJar.apply(this));
fixParameterAnnotation(environment.patchedSrgJar.apply(this));
if (getExtension().isForgeAndNotOfficial()) {
fixParameterAnnotation(environment.patchedSrgJar.apply(this));
} else {
deleteParameterNames(environment.patchedSrgJar.apply(this));
}
});
logger.lifecycle(":patched jars in " + stopwatch.stop());
@@ -565,9 +731,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
logger.lifecycle(":copying resources");
// Copy resources
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
copyNonClassFiles(minecraftProvider.minecraftClientJar, minecraftMergedPatchedSrgJar);
copyNonClassFiles(minecraftProvider.minecraftServerJar, minecraftMergedPatchedSrgJar);
if (getExtension().isForgeAndNotOfficial()) {
// Copy resources
MinecraftProviderImpl minecraftProvider = getExtension().getMinecraftProvider();
copyNonClassFiles(minecraftProvider.minecraftClientJar, minecraftMergedPatchedSrgJar);
copyNonClassFiles(minecraftProvider.minecraftServerJar, minecraftMergedPatchedSrgJar);
}
}
private void walkFileSystems(File source, File target, Predicate<Path> filter, Function<FileSystem, Iterable<Path>> toWalk, FsPathConsumer action)
@@ -576,6 +745,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) {
for (Path sourceDir : toWalk.apply(sourceFs.get())) {
Path dir = sourceDir.toAbsolutePath();
if (!Files.exists(dir)) continue;
Files.walk(dir)
.filter(Files::isRegularFile)
.filter(filter)
@@ -616,9 +786,12 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
private void copyNonClassFiles(File source, File target) throws IOException {
Predicate<Path> filter = file -> {
Predicate<Path> filter = getExtension().isForgeAndOfficial() ? file -> {
String s = file.toString();
return !s.endsWith(".class");
} : file -> {
String s = file.toString();
return !s.endsWith(".class") || (s.startsWith("META-INF") && !s.startsWith("META-INF/services"));
};
walkFileSystems(source, target, filter, this::copyReplacing);

View File

@@ -43,7 +43,6 @@ import net.fabricmc.loom.util.Constants;
public class PatchProvider extends DependencyProvider {
public Path clientPatches;
public Path serverPatches;
public String forgeVersion;
public Path projectCacheFolder;
public PatchProvider(Project project) {
@@ -67,8 +66,7 @@ public class PatchProvider extends DependencyProvider {
}
private void init(String forgeVersion) {
this.forgeVersion = forgeVersion;
projectCacheFolder = getDirectories().getProjectPersistentCache().toPath().resolve(forgeVersion);
projectCacheFolder = getMinecraftProvider().dir("forge/" + forgeVersion).toPath();
clientPatches = projectCacheFolder.resolve("patches-client.lzma");
serverPatches = projectCacheFolder.resolve("patches-server.lzma");

View File

@@ -25,9 +25,7 @@
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.logging.Logger;

View File

@@ -35,8 +35,19 @@ import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import org.gradle.api.Action;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExternalDependency;
import org.gradle.api.artifacts.ExternalModuleDependency;
import org.gradle.api.artifacts.ModuleIdentifier;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.MutableVersionConstraint;
import org.gradle.api.artifacts.SelfResolvingDependency;
import org.gradle.api.artifacts.VersionConstraint;
import org.gradle.api.internal.artifacts.DefaultModuleIdentifier;
import org.gradle.api.internal.artifacts.ModuleVersionSelectorStrictSpec;
import org.gradle.api.internal.artifacts.dependencies.AbstractModuleDependency;
import org.gradle.api.internal.artifacts.dependencies.DefaultMutableVersionConstraint;
import org.gradle.api.tasks.TaskDependency;
import org.zeroturnaround.zip.ByteSource;
import org.zeroturnaround.zip.ZipEntrySource;
@@ -48,7 +59,7 @@ import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.format.Tiny2Writer;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
public class LayeredMappingsDependency implements SelfResolvingDependency {
public class LayeredMappingsDependency extends AbstractModuleDependency implements SelfResolvingDependency, ExternalModuleDependency {
private static final String GROUP = "loom";
private static final String MODULE = "mappings";
@@ -57,6 +68,7 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
private final String version;
public LayeredMappingsDependency(MappingContext mappingContext, LayeredMappingSpec layeredMappingSpec, String version) {
super(null);
this.mappingContext = mappingContext;
this.layeredMappingSpec = layeredMappingSpec;
this.version = version;
@@ -118,6 +130,21 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
return version;
}
@Override
public VersionConstraint getVersionConstraint() {
return new DefaultMutableVersionConstraint(getVersion());
}
@Override
public boolean matchesStrictly(ModuleVersionIdentifier identifier) {
return new ModuleVersionSelectorStrictSpec(this).isSatisfiedBy(identifier);
}
@Override
public ModuleIdentifier getModule() {
return DefaultModuleIdentifier.newId(GROUP, MODULE);
}
@Override
public boolean contentEquals(Dependency dependency) {
if (dependency instanceof LayeredMappingsDependency layeredMappingsDependency) {
@@ -128,10 +155,34 @@ public class LayeredMappingsDependency implements SelfResolvingDependency {
}
@Override
public Dependency copy() {
public boolean isChanging() {
return false;
}
@Override
public ExternalModuleDependency setChanging(boolean b) {
return this;
}
@Override
public boolean isForce() {
return false;
}
@Override
public ExternalDependency setForce(boolean b) {
return this;
}
@Override
public ExternalModuleDependency copy() {
return new LayeredMappingsDependency(mappingContext, layeredMappingSpec, version);
}
@Override
public void version(Action<? super MutableVersionConstraint> action) {
}
@Override
public String getReason() {
return null;

View File

@@ -27,6 +27,7 @@ package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
@@ -151,7 +152,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
if (getExtension().shouldGenerateSrgTiny()) {
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
// Merge tiny mappings with srg
SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings, tinyMappingsWithSrg, true);
SrgMerger.mergeSrg(this::getMojmapSrgFileIfPossible, getRawSrgFile(), tinyMappings, tinyMappingsWithSrg, true);
}
}
@@ -216,7 +217,27 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
mappedProvider.provide(dependency, postPopulationScheduler);
}
public void manipulateMappings(Path mappingsJar) throws IOException { }
protected Path getRawSrgFile() throws IOException {
LoomGradleExtension extension = getExtension();
if (extension.isForgeAndOfficial()) {
return patchedProvider.getMergedMojangTsrg2(false);
}
return extension.getSrgProvider().getSrg().toPath();
}
protected Path getMojmapSrgFileIfPossible() {
try {
LoomGradleExtension extension = getExtension();
return MinecraftPatchedProvider.getMojmapTsrg2(extension);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void manipulateMappings(Path mappingsJar) throws IOException {
}
private String getMappingsClassifier(DependencyInfo dependency, boolean isV2) {
String[] depStringSplit = dependency.getDepString().split(":");
@@ -248,7 +269,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
}
}
private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler) throws IOException {
private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler)
throws IOException {
project.getLogger().info(":extracting " + yarnJar.getFileName());
if (isMCP(yarnJar)) {
@@ -298,7 +320,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
provider.provide(DependencyInfo.create(getProject(), configuration.getDependencies().iterator().next(), configuration), postPopulationScheduler);
}
Path srgPath = provider.getSrg().toPath();
Path srgPath = getRawSrgFile();
TinyFile file = new MCPReader(intermediaryTinyPath, srgPath).read(mcpJar);
TinyV2Writer.write(file, tinyMappings);
}
@@ -426,20 +448,20 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
try {
Command command = new CommandMergeTinyV2();
runCommand(command, intermediaryMappings.toAbsolutePath().toString(),
yarnMappings.toAbsolutePath().toString(),
newMergedMappings.toAbsolutePath().toString(),
"intermediary", "official");
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);
+ " with mappings from " + yarnMappings, e);
}
}
private void suggestFieldNames(MinecraftProviderImpl minecraftProvider, Path oldMappings, Path newMappings) {
Command command = new CommandProposeFieldNames();
runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(),
oldMappings.toAbsolutePath().toString(),
newMappings.toAbsolutePath().toString());
oldMappings.toAbsolutePath().toString(),
newMappings.toAbsolutePath().toString());
}
private void runCommand(Command command, String... args) {

View File

@@ -101,7 +101,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
needToRemap = true;
}
if (getExtension().isForge() && (!getForgeMappedJar().exists() || !getForgeIntermediaryJar().exists() || !getForgeSrgJar().exists() || isRefreshDeps() || isForgeAtDirty)) {
if (getExtension().isForgeAndNotOfficial() && (!getForgeMappedJar().exists() || !getForgeIntermediaryJar().exists() || !getForgeSrgJar().exists() || isRefreshDeps() || isForgeAtDirty)) {
needToRemap = true;
}
@@ -120,7 +120,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
minecraftSrgJar.delete();
}
if (getExtension().isForge()) {
if (getExtension().isForgeAndNotOfficial()) {
if (getForgeMappedJar().exists()) {
getForgeMappedJar().delete();
}
@@ -158,16 +158,18 @@ public class MinecraftMappedProvider extends DependencyProvider {
addDependencies(dependency, postPopulationScheduler);
if (getExtension().isForge()) {
if (getExtension().isForgeAndNotOfficial()) {
getProject().getRepositories().flatDir(repository -> repository.dir(new File(getJarDirectory(getDirectories().getUserCache(), "mapped"), "forge")));
getProject().getDependencies().add(Constants.Configurations.FORGE_NAMED,
getProject().getDependencies().module("net.minecraftforge-loom:forge:" + getJarVersionString("mapped")));
getProject().getDependencies().module("net.minecraftforge-loom:forge-mapped:" + getMinecraftProvider().minecraftVersion() + "/" + getExtension().getMappingsProvider().mappingsIdentifier() + "/forge"));
}
if (getExtension().isForge()) {
getProject().afterEvaluate(project -> {
if (!OperatingSystem.isCIBuild()) {
try {
ForgeSourcesRemapper.addBaseForgeSources(project);
ForgeSourcesRemapper.addBaseForgeSources(project, getExtension().isForgeAndOfficial());
} catch (IOException e) {
e.printStackTrace();
}
@@ -241,13 +243,13 @@ public class MinecraftMappedProvider extends DependencyProvider {
forgeAssets.toFile().deleteOnExit();
Info vanilla = new Info(vanillaAssets, input, outputMapped, outputIntermediary, outputSrg);
Info forge = getExtension().isForge() ? new Info(forgeAssets, inputForge, forgeOutputMapped, forgeOutputIntermediary, forgeOutputSrg) : null;
Info forge = getExtension().isForgeAndNotOfficial() ? new Info(forgeAssets, inputForge, forgeOutputMapped, forgeOutputIntermediary, forgeOutputSrg) : null;
TinyRemapper remapper = remapperArray[0] = buildRemapper();
assetsOut(input, vanillaAssets);
if (getExtension().isForge()) {
if (getExtension().isForgeAndNotOfficial()) {
assetsOut(inputForge, forgeAssets);
}
@@ -271,6 +273,8 @@ public class MinecraftMappedProvider extends DependencyProvider {
}
public void remap(TinyRemapper remapper, Info vanilla, @Nullable Info forge, String fromM) throws IOException {
Set<String> classNames = getExtension().isForge() ? InnerClassRemapper.readClassNames(vanilla.input) : null;
for (String toM : getExtension().isForge() ? Arrays.asList("intermediary", "srg", "named") : Arrays.asList("intermediary", "named")) {
Path output = "named".equals(toM) ? vanilla.outputMapped : "srg".equals(toM) ? vanilla.outputSrg : vanilla.outputIntermediary;
Path outputForge = forge == null ? null : "named".equals(toM) ? forge.outputMapped : "srg".equals(toM) ? forge.outputSrg : forge.outputIntermediary;
@@ -285,7 +289,7 @@ public class MinecraftMappedProvider extends DependencyProvider {
remapper.readInputs(forgeTag, forge.input);
}
remapper.replaceMappings(getMappings(vanilla.input, fromM, toM));
remapper.replaceMappings(getMappings(classNames, fromM, toM));
OutputRemappingHandler.remap(remapper, vanilla.assets, output, null, vanillaTag);
if (forge != null) {
@@ -325,13 +329,13 @@ public class MinecraftMappedProvider extends DependencyProvider {
return builder.build();
}
public Set<IMappingProvider> getMappings(@Nullable Path fromJar, String fromM, String toM) throws IOException {
public Set<IMappingProvider> getMappings(@Nullable Set<String> fromClassNames, String fromM, String toM) throws IOException {
Set<IMappingProvider> providers = new HashSet<>();
providers.add(TinyRemapperMappingsHelper.create(getExtension().isForge() ? getExtension().getMappingsProvider().getMappingsWithSrg() : getExtension().getMappingsProvider().getMappings(), fromM, toM, true));
if (getExtension().isForge()) {
if (fromJar != null) {
providers.add(InnerClassRemapper.of(fromJar, getExtension().getMappingsProvider().getMappingsWithSrg(), fromM, toM));
if (fromClassNames != null) {
providers.add(InnerClassRemapper.of(fromClassNames, getExtension().getMappingsProvider().getMappingsWithSrg(), fromM, toM));
}
} else {
providers.add(out -> JSR_TO_JETBRAINS.forEach(out::acceptClass));
@@ -357,11 +361,16 @@ public class MinecraftMappedProvider extends DependencyProvider {
minecraftMappedJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-mapped.jar");
inputJar = getExtension().isForge() ? mappingsProvider.patchedProvider.getMergedJar() : minecraftProvider.getMergedJar();
if (getExtension().isForge()) {
if (getExtension().isForgeAndNotOfficial()) {
inputForgeJar = mappingsProvider.patchedProvider.getForgeMergedJar();
forgeIntermediaryJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge-intermediary.jar");
forgeSrgJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge-srg.jar");
forgeIntermediaryJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge/forge-intermediary.jar");
forgeSrgJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge/forge-srg.jar");
forgeMappedJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge/forge-mapped.jar");
} else {
inputForgeJar = null;
forgeIntermediaryJar = null;
forgeSrgJar = null;
forgeMappedJar = null;
}
}

View File

@@ -58,8 +58,8 @@ import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.lorenztiny.TinyMappingsReader;
public class ForgeSourcesRemapper {
public static void addBaseForgeSources(Project project) throws IOException {
Path sourcesJar = GenerateSourcesTask.getMappedJarFileWithSuffix(project, "-sources.jar", true).toPath();
public static void addBaseForgeSources(Project project, boolean isOfficial) throws IOException {
Path sourcesJar = GenerateSourcesTask.getMappedJarFileWithSuffix(project, "-sources.jar", !isOfficial).toPath();
if (!Files.exists(sourcesJar)) {
addForgeSources(project, sourcesJar);
@@ -185,7 +185,11 @@ public class ForgeSourcesRemapper {
// Distinct and add the srg jar at the top, so it gets prioritized
mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getSrgJar().toPath());
mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getForgeSrgJar().toPath());
if (extension.isForgeAndNotOfficial()) {
mercury.getClassPath().add(0, extension.getMinecraftMappedProvider().getForgeSrgJar().toPath());
}
List<Path> newClassPath = mercury.getClassPath().stream()
.distinct()
.filter(Files::isRegularFile)

View File

@@ -366,6 +366,16 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
throw new RuntimeException("Yeah... something is really wrong");
}
@Override
public boolean isForgeAndOfficial() {
throw new RuntimeException("Yeah... something is really wrong");
}
@Override
public boolean isForgeAndNotOfficial() {
throw new RuntimeException("Yeah... something is really wrong");
}
@Override
protected String getMinecraftVersion() {
throw new RuntimeException("Yeah... something is really wrong");

View File

@@ -160,6 +160,18 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
return parent.getPlatform();
}
@Override
public boolean isForgeAndOfficial() {
reportDeprecation();
return parent.isForgeAndOfficial();
}
@Override
public boolean isForgeAndNotOfficial() {
reportDeprecation();
return parent.isForgeAndNotOfficial();
}
@Override
public boolean supportsInclude() {
reportDeprecation();

View File

@@ -25,6 +25,8 @@
package net.fabricmc.loom.task;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import com.google.common.base.Preconditions;
import org.gradle.api.Project;
@@ -33,6 +35,7 @@ import org.gradle.api.tasks.TaskContainer;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;
import net.fabricmc.loom.util.Constants;
@@ -86,6 +89,19 @@ public final class LoomTasks {
t.dependsOn("downloadAssets");
t.setGroup(Constants.TaskGroup.IDE);
});
tasks.register("genIntelliJRuns", AbstractLoomTask.class, t -> {
t.setDescription("Generates IntelliJ IDEA launch configurations.");
t.dependsOn("downloadAssets");
t.setGroup("ide");
t.doLast(task -> {
try {
SetupIntelijRunConfigs.generate(task.getProject(), true);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
});
}
private static void registerRunTasks(TaskContainer tasks, Project project) {

View File

@@ -187,9 +187,12 @@ public class MigrateMappingsTask extends AbstractLoomTask {
if (extension.isForge()) {
mercury.getClassPath().add(minecraftMappedProvider.getSrgJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeMappedJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeIntermediaryJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeSrgJar().toPath());
if (extension.isForgeAndNotOfficial()) {
mercury.getClassPath().add(minecraftMappedProvider.getForgeMappedJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeIntermediaryJar().toPath());
mercury.getClassPath().add(minecraftMappedProvider.getForgeSrgJar().toPath());
}
}
mercury.getProcessors().add(MercuryRemapper.create(mappingSet));

View File

@@ -79,6 +79,7 @@ public class Constants {
public static final String FORGE_UNIVERSAL = "forgeUniversal";
public static final String FORGE_DEPENDENCIES = "forgeDependencies";
public static final String FORGE_NAMED = "forgeNamed";
public static final String FORGE_EXTRA = "forgeExtra";
public static final String MAPPING_CONSTANTS = "mappingsConstants";
public static final String UNPICK_CLASSPATH = "unpick";
@@ -95,9 +96,10 @@ public class Constants {
public static final String TERMINAL_CONSOLE_APPENDER = "net.minecrell:terminalconsoleappender:";
public static final String JETBRAINS_ANNOTATIONS = "org.jetbrains:annotations:";
public static final String JAVAX_ANNOTATIONS = "com.google.code.findbugs:jsr305:"; // I hate that I have to add these.
public static final String FORGE_RUNTIME = "dev.architectury:architectury-loom-forge-runtime:";
public static final String FORGE_RUNTIME = "dev.architectury:architectury-loom-runtime:";
public static final String ACCESS_TRANSFORMERS = "net.minecraftforge:accesstransformers:";
public static final String SPECIAL_SOURCE = "net.md-5:SpecialSource:";
public static final String VIGNETTE = "net.minecraftforge.lex:vignette:";
private Dependencies() {
}
@@ -111,9 +113,10 @@ public class Constants {
public static final String TERMINAL_CONSOLE_APPENDER = "1.2.0";
public static final String JETBRAINS_ANNOTATIONS = "19.0.0";
public static final String JAVAX_ANNOTATIONS = "3.0.2";
public static final String FORGE_RUNTIME = "$LOOM_VERSION"; // replaced with current version at build time
public static final String ACCESS_TRANSFORMERS = "2.2.0";
public static final String FORGE_RUNTIME = "1.0.1";
public static final String ACCESS_TRANSFORMERS = "3.0.1";
public static final String SPECIAL_SOURCE = "1.8.3";
public static final String VIGNETTE = "0.2.0.10";
private Versions() {
}

View File

@@ -24,7 +24,14 @@
package net.fabricmc.loom.util;
import java.io.File;
import java.util.LinkedHashSet;
import java.util.Set;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.file.FileCollection;
/**
@@ -41,8 +48,40 @@ public final class DependencyDownloader {
* @return the resolved files
*/
public static FileCollection download(Project project, String dependencyNotation) {
var dependency = project.getDependencies().create(dependencyNotation);
var config = project.getConfigurations().detachedConfiguration(dependency);
return config.fileCollection(dep -> true);
return download(project, dependencyNotation, true, false);
}
public static FileCollection download(Project project, String dependencyNotation, boolean transitive, boolean resolve) {
Dependency dependency = project.getDependencies().create(dependencyNotation);
if (dependency instanceof ModuleDependency) {
((ModuleDependency) dependency).setTransitive(transitive);
}
Configuration config = project.getConfigurations().detachedConfiguration(dependency);
config.setTransitive(transitive);
FileCollection files = config.fileCollection(dep -> true);
if (resolve) {
files = project.files(files.getFiles());
}
return files;
}
private static Set<File> resolve(Configuration configuration, boolean transitive) {
Configuration copy = configuration.copy();
copy.setTransitive(transitive);
Set<File> files = new LinkedHashSet<>(copy.resolve());
for (Configuration extendsForm : configuration.getExtendsFrom()) {
files.addAll(resolve(extendsForm, transitive));
}
return files;
}
public static Set<File> resolveFiles(Configuration configuration, boolean transitive) {
return resolve(configuration, transitive);
}
}

View File

@@ -0,0 +1,71 @@
package net.fabricmc.loom.util;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import dev.architectury.mappingslayers.api.mutable.MutableTinyMetadata;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
import dev.architectury.tinyremapper.IMappingProvider;
import dev.architectury.tinyremapper.TinyRemapper;
public class MappingsProviderVerbose {
public static void saveFile(TinyRemapper providers) throws IOException {
try {
Field field = TinyRemapper.class.getDeclaredField("mappingProviders");
field.setAccessible(true);
Set<IMappingProvider> mappingProviders = (Set<IMappingProvider>) field.get(providers);
saveFile(mappingProviders);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
public static void saveFile(Iterable<IMappingProvider> providers) throws IOException {
MutableTinyTree tree = MappingsUtils.create(MutableTinyMetadata.create(2, 0, Arrays.asList("from", "to"), new HashMap<>()));
for (IMappingProvider provider : providers) {
provider.load(new IMappingProvider.MappingAcceptor() {
@Override
public void acceptClass(String from, String to) {
tree.getOrCreateClass(from).setName(1, to);
}
@Override
public void acceptMethod(IMappingProvider.Member from, String to) {
tree.getOrCreateClass(from.owner).getOrCreateMethod(from.name, from.desc)
.setName(1, to);
}
@Override
public void acceptMethodArg(IMappingProvider.Member from, int lvIndex, String to) {
tree.getOrCreateClass(from.owner).getOrCreateMethod(from.name, from.desc)
.getOrCreateParameter(lvIndex, "")
.setName(1, to);
}
@Override
public void acceptMethodVar(IMappingProvider.Member from, int i, int i1, int i2, String s) {
// NO-OP
}
@Override
public void acceptField(IMappingProvider.Member from, String to) {
tree.getOrCreateClass(from.owner).getOrCreateField(from.name, from.desc)
.setName(1, to);
}
});
}
Path check = Files.createTempFile("CHECK", null);
Files.writeString(check, MappingsUtils.serializeToString(tree), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
System.out.println("Saved debug check mappings to " + check);
}
}

View File

@@ -27,11 +27,14 @@ package net.fabricmc.loom.util.srg;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import dev.architectury.tinyremapper.IMappingProvider;
import net.fabricmc.loom.util.FileSystemUtil;
@@ -40,22 +43,16 @@ import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.TinyTree;
public class InnerClassRemapper {
public static IMappingProvider of(Path fromJar, TinyTree mappingsWithSrg, String from, String to) throws IOException {
public static IMappingProvider of(Set<String> fromClassNames, TinyTree mappingsWithSrg, String from, String to) throws IOException {
return sink -> {
remapInnerClass(fromJar, mappingsWithSrg, from, to, sink::acceptClass);
remapInnerClass(fromClassNames, mappingsWithSrg, from, to, sink::acceptClass);
};
}
private static void remapInnerClass(Path fromJar, TinyTree mappingsWithSrg, String from, String to, BiConsumer<String, String> action) {
try (FileSystemDelegate system = FileSystemUtil.getJarFileSystem(fromJar, false)) {
Map<String, String> availableClasses = mappingsWithSrg.getClasses().stream()
.collect(Collectors.groupingBy(classDef -> classDef.getName(from),
Collectors.<ClassDef, String>reducing(
null,
classDef -> classDef.getName(to),
(first, last) -> last
))
);
public static Set<String> readClassNames(Path jar) {
Set<String> set = new HashSet<>();
try (FileSystemDelegate system = FileSystemUtil.getJarFileSystem(jar, false)) {
Iterator<Path> iterator = Files.walk(system.get().getPath("/")).iterator();
while (iterator.hasNext()) {
@@ -65,21 +62,42 @@ public class InnerClassRemapper {
if (!Files.isDirectory(path) && name.contains("$") && name.endsWith(".class")) {
String className = name.substring(0, name.length() - 6);
if (!availableClasses.containsKey(className)) {
String parentName = className.substring(0, className.indexOf('$'));
String childName = className.substring(className.indexOf('$') + 1);
String remappedParentName = availableClasses.getOrDefault(parentName, parentName);
String remappedName = remappedParentName + "$" + childName;
if (!className.equals(remappedName)) {
action.accept(className, remappedName);
}
}
set.add(className);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return set;
}
private static void remapInnerClass(Set<String> classNames, TinyTree mappingsWithSrg, String from, String to, BiConsumer<String, String> action) {
BiMap<String, String> availableClasses = HashBiMap.create(mappingsWithSrg.getClasses().stream()
.collect(Collectors.groupingBy(classDef -> classDef.getName(from),
Collectors.<ClassDef, String>reducing(
null,
classDef -> classDef.getName(to),
(first, last) -> last
))
));
for (String className : classNames) {
if (!availableClasses.containsKey(className)) {
String parentName = className.substring(0, className.indexOf('$'));
String childName = className.substring(className.indexOf('$') + 1);
String remappedParentName = availableClasses.getOrDefault(parentName, parentName);
String remappedName = remappedParentName + "$" + childName;
if (!className.equals(remappedName)) {
if (availableClasses.containsValue(remappedName)) {
// https://github.com/MinecraftForge/MinecraftForge/blob/b027a92dd287d6810a9fdae4d4b1e1432d7dc9cc/patches/minecraft/net/minecraft/Util.java.patch#L8
action.accept(className, remappedName + "_UNBREAK");
} else {
action.accept(className, remappedName);
}
}
}
}
}
}

View File

@@ -39,6 +39,7 @@ import org.apache.commons.io.output.NullOutputStream;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.configuration.ShowStacktrace;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
@@ -87,8 +88,10 @@ public class SpecialSourceExecutor {
spec.setMain("net.md_5.specialsource.SpecialSource");
// if running with INFO or DEBUG logging
if (project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
if (project.getGradle().getStartParameter().getShowStacktrace() != ShowStacktrace.INTERNAL_EXCEPTIONS
|| project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
spec.setStandardOutput(System.out);
spec.setErrorOutput(System.err);
} else {
spec.setStandardOutput(NullOutputStream.NULL_OUTPUT_STREAM);
spec.setErrorOutput(NullOutputStream.NULL_OUTPUT_STREAM);

View File

@@ -27,15 +27,20 @@ package net.fabricmc.loom.util.srg;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
import com.google.common.base.MoreObjects;
import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
import dev.architectury.mappingslayers.api.mutable.MutableDescriptored;
import dev.architectury.mappingslayers.api.mutable.MutableFieldDef;
import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
@@ -56,6 +61,7 @@ import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.MethodDef;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappingio.format.TsrgReader;
import net.fabricmc.stitch.commands.tinyv2.TinyClass;
import net.fabricmc.stitch.commands.tinyv2.TinyField;
import net.fabricmc.stitch.commands.tinyv2.TinyFile;
@@ -80,8 +86,9 @@ public final class SrgMerger {
* @throws MappingException if the input tiny tree's default namespace is not 'official'
* or if an element mentioned in the SRG file does not have tiny mappings
*/
public static void mergeSrg(Path srg, Path tiny, Path out, boolean lenient) throws IOException, MappingException {
MappingSet arr = readSrg(srg);
public static void mergeSrg(Supplier<Path> mojmap, Path srg, Path tiny, Path out, boolean lenient) throws IOException, MappingException {
Map<String, List<MutableDescriptored>> addRegardlessSrgs = new HashMap<>();
MappingSet arr = readSrg(srg, mojmap, addRegardlessSrgs);
TinyTree foss;
try (BufferedReader reader = Files.newBufferedReader(tiny)) {
@@ -100,19 +107,19 @@ public final class SrgMerger {
List<TinyClass> classes = new ArrayList<>();
for (TopLevelClassMapping klass : arr.getTopLevelClassMappings()) {
classToTiny(foss, namespaces, klass, classes::add, lenient);
classToTiny(addRegardlessSrgs, foss, namespaces, klass, classes::add, lenient);
}
TinyFile file = new TinyFile(header, classes);
TinyV2Writer.write(file, out);
}
private static MappingSet readSrg(Path srg) throws IOException {
private static MappingSet readSrg(Path srg, Supplier<Path> mojmap, Map<String, List<MutableDescriptored>> addRegardlessSrgs) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(srg)) {
String content = IOUtils.toString(reader);
if (content.startsWith("tsrg2")) {
return readTsrg2(content);
return readTsrg2(content, mojmap, addRegardlessSrgs);
} else {
try (TSrgReader srgReader = new TSrgReader(new StringReader(content))) {
return srgReader.read();
@@ -121,31 +128,45 @@ public final class SrgMerger {
}
}
private static MappingSet readTsrg2(String content) {
MappingSet set = MappingSet.create();
MutableTinyTree tree = MappingsUtils.deserializeFromTsrg2(content);
int obfIndex = tree.getMetadata().index("obf");
int srgIndex = tree.getMetadata().index("srg");
private static MappingSet readTsrg2(String content, Supplier<Path> mojmap, Map<String, List<MutableDescriptored>> addRegardlessSrgs) throws IOException {
MappingSet set;
for (MutableClassDef classDef : tree.getClassesMutable()) {
ClassMapping<?, ?> classMapping = set.getOrCreateClassMapping(classDef.getName(obfIndex));
classMapping.setDeobfuscatedName(classDef.getName(srgIndex));
try (Tsrg2Utils.MappingsIO2LorenzWriter lorenzWriter = new Tsrg2Utils.MappingsIO2LorenzWriter(0, false)) {
TsrgReader.read(new StringReader(content), lorenzWriter);
set = lorenzWriter.read();
MutableTinyTree mojmapTree = readTsrg2ToTinyTree(mojmap.get());
for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
FieldMapping fieldMapping = classMapping.getOrCreateFieldMapping(fieldDef.getName(obfIndex));
fieldMapping.setDeobfuscatedName(fieldDef.getName(srgIndex));
}
for (MutableClassDef classDef : mojmapTree.getClassesMutable()) {
for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
String name = methodDef.getName(0);
for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
MethodMapping methodMapping = classMapping.getOrCreateMethodMapping(methodDef.getName(obfIndex), methodDef.getDescriptor(obfIndex));
methodMapping.setDeobfuscatedName(methodDef.getName(srgIndex));
if (name.indexOf('<') != 0 && name.equals(methodDef.getName(1))) {
addRegardlessSrgs.computeIfAbsent(classDef.getName(0), $ -> new ArrayList<>()).add(methodDef);
}
}
for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
if (fieldDef.getName(0).equals(fieldDef.getName(1))) {
addRegardlessSrgs.computeIfAbsent(classDef.getName(0), $ -> new ArrayList<>()).add(fieldDef);
}
}
}
}
return set;
}
private static void classToTiny(TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer, boolean lenient) {
private static MutableTinyTree readTsrg2ToTinyTree(Path path) throws IOException {
MutableTinyTree tree;
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
tree = MappingsUtils.deserializeFromTsrg2(IOUtils.toString(reader));
}
return tree;
}
private static void classToTiny(Map<String, List<MutableDescriptored>> addRegardlessSrgs, TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer, boolean lenient) {
String obf = klass.getFullObfuscatedName();
String srg = klass.getFullDeobfuscatedName();
ClassDef classDef = foss.getDefaultNamespaceClassMap().get(obf);
@@ -170,9 +191,17 @@ public final class SrgMerger {
MethodDef def = CollectionUtil.find(
classDef.getMethods(),
m -> m.getName("official").equals(method.getObfuscatedName()) && m.getDescriptor("official").equals(method.getObfuscatedDescriptor())
).orElse(nullOrThrow(lenient, () -> new MappingException("Missing method: " + method.getFullObfuscatedName() + " (srg: " + method.getFullDeobfuscatedName() + ")")));
).orElse(null);
if (def == null) continue;
if (def == null) {
if (tryMatchRegardlessSrgs(addRegardlessSrgs, namespaces, obf, methods, method)) continue;
if (!lenient) {
throw new MappingException("Missing method: " + method.getFullObfuscatedName() + " (srg: " + method.getFullDeobfuscatedName() + ")");
}
continue;
}
List<String> methodNames = CollectionUtil.map(
namespaces,
@@ -207,10 +236,36 @@ public final class SrgMerger {
classConsumer.accept(tinyClass);
for (InnerClassMapping innerKlass : klass.getInnerClassMappings()) {
classToTiny(foss, namespaces, innerKlass, classConsumer, lenient);
classToTiny(addRegardlessSrgs, foss, namespaces, innerKlass, classConsumer, lenient);
}
}
private static boolean tryMatchRegardlessSrgs(Map<String, List<MutableDescriptored>> addRegardlessSrgs, List<String> namespaces, String obf,
List<TinyMethod> methods, MethodMapping method) {
List<MutableDescriptored> mutableDescriptoredList = addRegardlessSrgs.get(obf);
if (!method.getDeobfuscatedName().equals(method.getObfuscatedName())) {
for (MutableDescriptored descriptored : MoreObjects.firstNonNull(mutableDescriptoredList, Collections.<MutableDescriptored>emptyList())) {
if (descriptored.isMethod() && descriptored.getName(0).equals(method.getObfuscatedName()) && descriptored.getDescriptor(0).equals(method.getObfuscatedDescriptor())) {
List<String> methodNames = CollectionUtil.map(
namespaces,
namespace -> "srg".equals(namespace) ? method.getDeobfuscatedName() : method.getObfuscatedName()
);
methods.add(new TinyMethod(
method.getObfuscatedDescriptor(), methodNames,
/* parameters */ Collections.emptyList(),
/* locals */ Collections.emptyList(),
/* comments */ Collections.emptyList()
));
return true;
}
}
}
return false;
}
@Nullable
private static <T, X extends Exception> T nullOrThrow(boolean lenient, Supplier<X> exception) throws X {
if (lenient) {

View File

@@ -0,0 +1,209 @@
package net.fabricmc.loom.util.srg;
import java.io.IOException;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
import dev.architectury.mappingslayers.api.mutable.MutableFieldDef;
import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
import dev.architectury.mappingslayers.api.mutable.MutableParameterDef;
import dev.architectury.mappingslayers.api.mutable.MutableTinyMetadata;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.lorenz.io.srg.tsrg.TSrgWriter;
import org.cadixdev.lorenz.model.ClassMapping;
import org.cadixdev.lorenz.model.MethodMapping;
import net.fabricmc.mappingio.MappingVisitor;
import net.fabricmc.mappingio.MappingWriter;
import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor;
import net.fabricmc.mappingio.format.TsrgReader;
import net.fabricmc.mappingio.tree.MappingTree;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
public class Tsrg2Utils {
public static void convert(Reader reader, Writer writer) throws IOException {
writeTsrg(visitor -> {
try {
TsrgReader.read(reader, visitor);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}, "srg", false, writer);
}
public static void writeTsrg(Consumer<MappingVisitor> visitorConsumer, String dstNamespace, boolean applyParameterMappings, Writer writer)
throws IOException {
MappingSet set;
try (MappingsIO2LorenzWriter lorenzWriter = new MappingsIO2LorenzWriter(dstNamespace, applyParameterMappings)) {
visitorConsumer.accept(lorenzWriter);
set = lorenzWriter.read();
}
try (TSrgWriter w = new TSrgWriter(writer)) {
w.write(set);
}
}
public static void writeTsrg2(Consumer<MappingVisitor> visitorConsumer, Writer writer)
throws IOException {
MutableTinyTree tree;
try (MappingsIO2MappingsUtils w = new MappingsIO2MappingsUtils()) {
visitorConsumer.accept(w);
tree = w.read();
}
writer.write(MappingsUtils.serializeToTsrg2(tree));
}
// TODO Move this elsewhere
public abstract static class MappingsIO2Others extends ForwardingMappingVisitor implements MappingWriter {
public MappingsIO2Others() {
super(new MemoryMappingTree());
}
public MappingTree tree() {
return (MappingTree) next;
}
@Override
public void close() throws IOException {
MappingTree tree = tree();
List<String> names = new ArrayList<>();
for (MappingTree.ClassMapping aClass : tree.getClasses()) {
names.add(aClass.getSrcName());
}
for (String name : names) {
tree.removeClass(name);
}
}
}
public static class MappingsIO2LorenzWriter extends MappingsIO2Others {
private final Object dstNamespaceUnresolved;
private int dstNamespace;
private boolean applyParameterMappings;
public MappingsIO2LorenzWriter(int dstNamespace, boolean applyParameterMappings) {
this.dstNamespaceUnresolved = dstNamespace;
this.applyParameterMappings = applyParameterMappings;
}
public MappingsIO2LorenzWriter(String dstNamespace, boolean applyParameterMappings) {
this.dstNamespaceUnresolved = dstNamespace;
this.applyParameterMappings = applyParameterMappings;
}
@Override
public void visitNamespaces(String srcNamespace, List<String> dstNamespaces) throws IOException {
super.visitNamespaces(srcNamespace, dstNamespaces);
this.dstNamespace = dstNamespaceUnresolved instanceof Integer ? (Integer) dstNamespaceUnresolved : dstNamespaces.indexOf((String) dstNamespaceUnresolved);
}
public MappingSet read() throws IOException {
return this.read(MappingSet.create());
}
public MappingSet read(final MappingSet mappings) throws IOException {
MappingTree tree = tree();
for (MappingTree.ClassMapping aClass : tree.getClasses()) {
ClassMapping<?, ?> lClass = mappings.getOrCreateClassMapping(aClass.getSrcName())
.setDeobfuscatedName(aClass.getDstName(dstNamespace));
for (MappingTree.FieldMapping aField : aClass.getFields()) {
String srcDesc = aField.getSrcDesc();
if (srcDesc == null || srcDesc.isEmpty()) {
lClass.getOrCreateFieldMapping(aField.getSrcName())
.setDeobfuscatedName(aField.getDstName(dstNamespace));
} else {
lClass.getOrCreateFieldMapping(aField.getSrcName(), srcDesc)
.setDeobfuscatedName(aField.getDstName(dstNamespace));
}
}
for (MappingTree.MethodMapping aMethod : aClass.getMethods()) {
MethodMapping lMethod = lClass.getOrCreateMethodMapping(aMethod.getSrcName(), aMethod.getSrcDesc())
.setDeobfuscatedName(aMethod.getDstName(dstNamespace));
if (applyParameterMappings) {
for (MappingTree.MethodArgMapping aArg : aMethod.getArgs()) {
lMethod.getOrCreateParameterMapping(aArg.getLvIndex())
.setDeobfuscatedName(aArg.getDstName(dstNamespace));
}
}
}
}
return mappings;
}
}
public static class MappingsIO2MappingsUtils extends MappingsIO2Others {
public MutableTinyTree read() {
MappingTree tree = tree();
int dstNamesSize = tree.getDstNamespaces().size();
List<String> namespaces = new ArrayList<>();
namespaces.add(tree.getSrcNamespace());
namespaces.addAll(tree.getDstNamespaces());
Map<String, String> properties = new HashMap<>();
for (Map.Entry<String, String> entry : tree.getMetadata()) {
properties.put(entry.getKey(), entry.getValue());
}
MutableTinyTree out = MappingsUtils.create(MutableTinyMetadata.create(2, 0, namespaces, properties));
for (MappingTree.ClassMapping aClass : tree.getClasses()) {
MutableClassDef classDef = out.getOrCreateClass(aClass.getSrcName());
classDef.setComment(aClass.getComment());
for (int i = 0; i < dstNamesSize; i++) {
classDef.setName(i + 1, aClass.getDstName(i));
}
for (MappingTree.MethodMapping aMethod : aClass.getMethods()) {
MutableMethodDef methodDef = classDef.getOrCreateMethod(aMethod.getSrcName(), aMethod.getSrcDesc());
methodDef.setComment(aMethod.getComment());
for (int i = 0; i < dstNamesSize; i++) {
methodDef.setName(i + 1, aMethod.getDstName(i));
}
for (MappingTree.MethodArgMapping aMethodArg : aMethod.getArgs()) {
MutableParameterDef parameterDef = methodDef.getOrCreateParameter(aMethodArg.getLvIndex(), aMethodArg.getSrcName());
parameterDef.setComment(aMethodArg.getComment());
for (int i = 0; i < dstNamesSize; i++) {
parameterDef.setName(i + 1, aMethodArg.getDstName(i));
}
}
}
for (MappingTree.FieldMapping aField : aClass.getFields()) {
MutableFieldDef fieldDef = classDef.getOrCreateField(aField.getSrcName(), aField.getSrcDesc());
fieldDef.setComment(aField.getComment());
for (int i = 0; i < dstNamesSize; i++) {
fieldDef.setName(i + 1, aField.getDstName(i));
}
}
}
return out;
}
}
}