A lot of stuff, including project ATs as a jar processor

This commit is contained in:
Juuz
2022-01-19 14:11:05 +02:00
parent 63293b3417
commit 1bedce942e
16 changed files with 372 additions and 183 deletions

View File

@@ -24,7 +24,9 @@
package net.fabricmc.loom.configuration;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import org.gradle.api.NamedDomainObjectProvider;
import org.gradle.api.Project;
@@ -41,6 +43,7 @@ import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.mixin.JavaApInvoker;
import net.fabricmc.loom.build.mixin.KaptApInvoker;
import net.fabricmc.loom.build.mixin.ScalaApInvoker;
import net.fabricmc.loom.configuration.accesstransformer.AccessTransformerJarProcessor;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor;
import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor;
@@ -187,6 +190,11 @@ public final class CompileConfiguration {
project.getDependencies().add(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, Constants.Dependencies.DEV_LAUNCH_INJECTOR + Constants.Dependencies.Versions.DEV_LAUNCH_INJECTOR);
project.getDependencies().add(Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, Constants.Dependencies.TERMINAL_CONSOLE_APPENDER + Constants.Dependencies.Versions.TERMINAL_CONSOLE_APPENDER);
project.getDependencies().add(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS);
if (extension.isForge()) {
project.getDependencies().add(Constants.Dependencies.FORGE_RUNTIME + Constants.Dependencies.Versions.FORGE_RUNTIME, Constants.Configurations.FORGE_EXTRA);
project.getDependencies().add(Constants.Dependencies.JAVAX_ANNOTATIONS + Constants.Dependencies.Versions.JAVAX_ANNOTATIONS, JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME);
}
}
public static void configureCompile(Project p) {
@@ -319,6 +327,14 @@ public final class CompileConfiguration {
}
}
if (extension.isForge()) {
Set<File> atFiles = AccessTransformerJarProcessor.getAccessTransformerFiles(project);
if (!atFiles.isEmpty()) {
extension.getGameJarProcessors().add(new AccessTransformerJarProcessor(project, atFiles));
}
}
JarProcessorManager processorManager = new JarProcessorManager(extension.getGameJarProcessors().get());
extension.setJarProcessorManager(processorManager);
processorManager.setupProcessors();

View File

@@ -0,0 +1,164 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.configuration.accesstransformer;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteSource;
import org.apache.commons.io.output.NullOutputStream;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.configuration.ShowStacktrace;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.SourceSet;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
public final class AccessTransformerJarProcessor implements JarProcessor {
private final Project project;
private byte[] atHash;
private final Set<File> atFiles;
public AccessTransformerJarProcessor(Project project, Set<File> atFiles) {
this.project = project;
this.atFiles = atFiles;
}
public static Set<File> getAccessTransformerFiles(Project project) {
final Set<File> atFiles = new HashSet<>();
LoomGradleExtension extension = LoomGradleExtension.get(project);
ConfigurableFileCollection accessTransformers = extension.getForge().getAccessTransformers();
accessTransformers.finalizeValue();
atFiles.addAll(accessTransformers.getFiles());
if (atFiles.isEmpty()) {
SourceSet main = project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().getByName("main");
for (File srcDir : main.getResources().getSrcDirs()) {
File projectAt = new File(srcDir, Constants.Forge.ACCESS_TRANSFORMER_PATH);
if (projectAt.exists()) {
atFiles.add(projectAt);
break;
}
}
}
return atFiles;
}
@Override
public String getId() {
return "architectury:access_transformer:" + Checksum.toHex(atHash);
}
@Override
public void setup() {
atHash = getProjectAtsHash();
}
private byte[] getProjectAtsHash() {
try {
if (atFiles.isEmpty()) return ByteSource.empty().hash(Hashing.sha256()).asBytes();
List<ByteSource> currentBytes = new ArrayList<>();
for (File projectAt : atFiles) {
currentBytes.add(com.google.common.io.Files.asByteSource(projectAt));
}
return ByteSource.concat(currentBytes).hash(Hashing.sha256()).asBytes();
} catch (IOException e) {
throw new UncheckedIOException("Could not compute project AT hash", e);
}
}
@Override
public void process(File file) {
try {
Path tempInput = Files.createTempFile(null, "loom-at.jar");
Files.copy(file.toPath(), tempInput);
executeAt(project, tempInput, file.toPath(), args -> {
for (File atFile : atFiles) {
args.add("--atFile");
args.add(atFile.getAbsolutePath());
}
});
Files.delete(tempInput);
} catch (IOException e) {
throw new UncheckedIOException("Could not access transform " + file.getAbsolutePath(), e);
}
}
public static void executeAt(Project project, Path input, Path output, AccessTransformerConfiguration configuration) throws IOException {
boolean serverBundleMetadataPresent = LoomGradleExtension.get(project).getMinecraftProvider().getServerBundleMetadata() != null;
String atDependency = Constants.Dependencies.ACCESS_TRANSFORMERS + (serverBundleMetadataPresent ? Constants.Dependencies.Versions.ACCESS_TRANSFORMERS_NEW : Constants.Dependencies.Versions.ACCESS_TRANSFORMERS);
FileCollection classpath = DependencyDownloader.download(project, atDependency);
List<String> args = new ArrayList<>();
args.add("--inJar");
args.add(input.toAbsolutePath().toString());
args.add("--outJar");
args.add(output.toAbsolutePath().toString());
configuration.apply(args);
project.javaexec(spec -> {
spec.getMainClass().set("net.minecraftforge.accesstransformer.TransformerProcessor");
spec.setArgs(args);
spec.setClasspath(classpath);
// if running with INFO or DEBUG logging
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);
}
}).rethrowFailure().assertNormalExitValue();
}
@FunctionalInterface
public interface AccessTransformerConfiguration {
void apply(List<String> args) throws IOException;
}
}

View File

@@ -32,6 +32,7 @@ import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.ArchitecturyGenerateSourcesTask;
import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.util.Constants;
@@ -76,6 +77,24 @@ public class SingleJarDecompileConfiguration extends DecompileConfiguration<Mapp
});
});
LoomGradleExtension.get(project).getArchGameDecompilers().configureEach(decompiler -> {
String taskName = "genSourcesWith" + decompiler.name();
// Decompiler will be passed to the constructor of ArchitecturyGenerateSourcesTask
project.getTasks().register(taskName, ArchitecturyGenerateSourcesTask.class, decompiler).configure(task -> {
task.getInputJar().set(inputJar);
task.getRuntimeJar().set(namedJar);
task.dependsOn(project.getTasks().named("validateAccessWidener"));
task.setDescription("Decompile minecraft using %s.".formatted(decompiler.name()));
task.setGroup(Constants.TaskGroup.FABRIC);
if (mappingsProvider.hasUnpickDefinitions()) {
task.dependsOn(project.getTasks().named("unpickJar"));
}
});
});
project.getTasks().register("genSources", task -> {
task.setDescription("Decompile minecraft using the default decompiler.");
task.setGroup(Constants.TaskGroup.FABRIC);

View File

@@ -32,6 +32,8 @@ import org.gradle.api.Task;
import org.gradle.api.tasks.TaskProvider;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.ArchitecturyGenerateSourcesTask;
import net.fabricmc.loom.task.DecompilationTask;
import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.task.UnpickJarTask;
import net.fabricmc.loom.util.Constants;
@@ -93,7 +95,7 @@ public final class SplitDecompileConfiguration extends DecompileConfiguration<Ma
});
}
private TaskProvider<Task> createDecompileTasks(String name, Action<GenerateSourcesTask> configureAction) {
private TaskProvider<Task> createDecompileTasks(String name, Action<DecompilationTask> configureAction) {
extension.getDecompilerOptions().forEach(options -> {
final String decompilerName = options.getName().substring(0, 1).toUpperCase() + options.getName().substring(1);
final String taskName = "gen%sSourcesWith%s".formatted(name, decompilerName);
@@ -106,6 +108,18 @@ public final class SplitDecompileConfiguration extends DecompileConfiguration<Ma
});
});
extension.getArchGameDecompilers().configureEach(decompiler -> {
String taskName = "genSourcesWith" + decompiler.name();
// Decompiler will be passed to the constructor of ArchitecturyGenerateSourcesTask
project.getTasks().register(taskName, ArchitecturyGenerateSourcesTask.class, decompiler).configure(task -> {
configureAction.execute(task);
task.dependsOn(project.getTasks().named("validateAccessWidener"));
task.setDescription("Decompile minecraft using %s.".formatted(decompiler.name()));
task.setGroup(Constants.TaskGroup.FABRIC);
});
});
return project.getTasks().register("gen%sSources".formatted(name), task -> {
task.setDescription("Decompile minecraft (%s) using the default decompiler.".formatted(name));
task.setGroup(Constants.TaskGroup.FABRIC);

View File

@@ -3,7 +3,6 @@ package net.fabricmc.loom.configuration.providers.forge;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -19,7 +18,6 @@ import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -37,25 +35,15 @@ import com.google.common.base.Preconditions;
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 de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import dev.architectury.tinyremapper.InputTag;
import dev.architectury.tinyremapper.OutputConsumerPath;
import dev.architectury.tinyremapper.TinyRemapper;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.minecraftforge.binarypatcher.ConsoleTool;
import org.apache.commons.io.output.NullOutputStream;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
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.jetbrains.annotations.Nullable;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
@@ -66,11 +54,11 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.accesstransformer.AccessTransformerJarProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.FunnyTodoException;
import net.fabricmc.loom.util.MappingsProviderVerbose;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperHelper;
@@ -85,27 +73,23 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
private static final String CURRENT_LOOM_PATCH_VERSION = "5";
private static final String NAME_MAPPING_SERVICE_PATH = "/inject/META-INF/services/cpw.mods.modlauncher.api.INameMappingService";
// Step 1: Remap Minecraft to SRG (global)
// Step 1: Remap Minecraft to SRG
private File minecraftClientSrgJar;
private File minecraftServerSrgJar;
// Step 2: Binary Patch (global)
// Step 2: Binary Patch
private File minecraftClientPatchedSrgJar;
private File minecraftServerPatchedSrgJar;
// Step 3: Merge (global)
private File minecraftMergedPatchedSrgJar;
// Step 4: Access Transform (global or project)
// Step 4: Access Transform
private File minecraftMergedPatchedSrgAtJar;
// Step 5: Remap Patched AT & Forge to Official (global or project)
// Step 5: Remap Patched AT & Forge to Official
private File minecraftMergedPatchedJar;
@Nullable
private File forgeMergedJar;
private File minecraftClientExtra;
private boolean dirty;
private File projectAtHash;
private Set<File> projectAts = new HashSet<>();
private boolean atDirty = false;
private boolean filesDirty = false;
public static MergedMinecraftProvider createMergedMinecraftProvider(Project project) {
return LoomGradleExtension.get(project).isForge() ? new MinecraftPatchedProvider(project) : new MergedMinecraftProvider(project);
@@ -129,18 +113,11 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
protected void initFiles() {
super.initFiles();
PatchProvider patchProvider = getExtension().getPatchProvider();
String minecraftVersion = minecraftVersion();
String patchId = "forge-" + getExtension().getForgeProvider().getVersion().getCombined() + "-";
FunnyTodoException.yes("jar prefix");
//if (getExtension().isForgeAndOfficial()) {
// minecraftProvider.setJarPrefix(patchId);
//}
File globalCache = getExtension().getForgeProvider().getGlobalCache();
File projectDir = usesProjectCache() ? getExtension().getForgeProvider().getProjectCache() : globalCache;
projectDir.mkdirs();
if (getExtension().isForgeAndOfficial()) {
setJarPrefix(patchId);
}
minecraftClientSrgJar = file("minecraft-client-srg.jar");
minecraftServerSrgJar = file("minecraft-server-srg.jar");
@@ -153,23 +130,10 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
minecraftClientExtra = file("forge-client-extra.jar");
}
private byte[] getProjectAtsHash() throws IOException {
if (projectAts.isEmpty()) return ByteSource.empty().hash(Hashing.sha256()).asBytes();
List<ByteSource> currentBytes = new ArrayList<>();
for (File projectAt : projectAts) {
currentBytes.add(com.google.common.io.Files.asByteSource(projectAt));
}
return ByteSource.concat(currentBytes).hash(Hashing.sha256()).asBytes();
}
public void cleanAllCache() {
for (File file : getGlobalCaches()) {
file.delete();
}
cleanProjectCache();
}
private File[] getGlobalCaches() {
@@ -180,6 +144,8 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
minecraftServerPatchedSrgJar,
minecraftMergedPatchedSrgJar,
minecraftClientExtra,
minecraftMergedPatchedSrgAtJar,
minecraftMergedPatchedJar
};
if (forgeMergedJar != null) {
@@ -190,65 +156,17 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
return files;
}
public void cleanProjectCache() {
for (File file : getProjectCache()) {
file.delete();
}
}
private File[] getProjectCache() {
return new File[] {
minecraftMergedPatchedSrgAtJar,
minecraftMergedPatchedJar
};
}
private void checkAtAndCache() throws IOException {
filesDirty = false;
projectAtHash = new File(getExtension().getFiles().getProjectPersistentCache(), "at.sha256");
ConfigurableFileCollection accessTransformers = getExtension().getForge().getAccessTransformers();
accessTransformers.finalizeValue();
projectAts = accessTransformers.getFiles();
if (projectAts.isEmpty()) {
SourceSet main = getProject().getConvention().findPlugin(JavaPluginConvention.class).getSourceSets().getByName("main");
for (File srcDir : main.getResources().getSrcDirs()) {
File projectAt = new File(srcDir, Constants.Forge.ACCESS_TRANSFORMER_PATH);
if (projectAt.exists()) {
this.projectAts.add(projectAt);
break;
}
}
}
if (isRefreshDeps() || !projectAtHash.exists()) {
writeAtHash();
atDirty = !projectAts.isEmpty();
} else {
byte[] expected = com.google.common.io.Files.asByteSource(projectAtHash).read();
byte[] current = getProjectAtsHash();
boolean mismatched = !Arrays.equals(current, expected);
if (mismatched) {
writeAtHash();
}
atDirty = mismatched;
}
private void checkCache() throws IOException {
if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(((Predicate<File>) File::exists).negate())
|| !isPatchedJarUpToDate(minecraftMergedPatchedJar)) {
cleanAllCache();
} else if (atDirty || Stream.of(getProjectCache()).anyMatch(((Predicate<File>) File::exists).negate())) {
cleanProjectCache();
}
}
@Override
public void provide() throws Exception {
super.provide();
checkCache();
this.dirty = false;
@@ -267,7 +185,7 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
mergeJars(getProject().getLogger());
}
if (atDirty || !minecraftMergedPatchedSrgAtJar.exists()) {
if (!minecraftMergedPatchedSrgAtJar.exists()) {
this.dirty = true;
accessTransformForge(getProject().getLogger());
}
@@ -284,7 +202,6 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
}
}
this.filesDirty = dirty;
this.dirty = false;
if (getExtension().isForgeAndOfficial()) {
@@ -327,12 +244,6 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
return remapper;
}
private void writeAtHash() throws IOException {
try (FileOutputStream out = new FileOutputStream(projectAtHash)) {
out.write(getProjectAtsHash());
}
}
private void createSrgJars(Logger logger) throws Exception {
produceSrgJar(getExtension().isForgeAndOfficial(), super.getMinecraftClientJar().toPath(), MoreObjects.firstNonNull(super.getMinecraftExtractedServerJar(), super.getMinecraftServerJar()).toPath());
}
@@ -475,8 +386,6 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
private void accessTransformForge(Logger logger) throws Exception {
List<File> toDelete = new ArrayList<>();
String atDependency = Constants.Dependencies.ACCESS_TRANSFORMERS + (getServerBundleMetadata() != null ? Constants.Dependencies.Versions.ACCESS_TRANSFORMERS_NEW : Constants.Dependencies.Versions.ACCESS_TRANSFORMERS);
FileCollection classpath = DependencyDownloader.download(getProject(), atDependency);
Stopwatch stopwatch = Stopwatch.createStarted();
logger.lifecycle(":access transforming minecraft");
@@ -485,46 +394,19 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
File target = minecraftMergedPatchedSrgAtJar;
Files.deleteIfExists(target.toPath());
List<String> args = new ArrayList<>();
args.add("--inJar");
args.add(input.getAbsolutePath());
args.add("--outJar");
args.add(target.getAbsolutePath());
AccessTransformerJarProcessor.executeAt(getProject(), input.toPath(), target.toPath(), args -> {
for (File jar : ImmutableList.of(getForgeJar(), getForgeUserdevJar(), minecraftMergedPatchedSrgJar)) {
byte[] atBytes = ZipUtils.unpackNullable(jar.toPath(), Constants.Forge.ACCESS_TRANSFORMER_PATH);
for (File jar : ImmutableList.of(getForgeJar(), getForgeUserdevJar(), minecraftMergedPatchedSrgJar)) {
byte[] atBytes = ZipUtils.unpackNullable(jar.toPath(), Constants.Forge.ACCESS_TRANSFORMER_PATH);
if (atBytes != null) {
File tmpFile = File.createTempFile("at-conf", ".cfg");
toDelete.add(tmpFile);
Files.write(tmpFile.toPath(), atBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
args.add("--atFile");
args.add(tmpFile.getAbsolutePath());
if (atBytes != null) {
File tmpFile = File.createTempFile("at-conf", ".cfg");
toDelete.add(tmpFile);
Files.write(tmpFile.toPath(), atBytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
args.add("--atFile");
args.add(tmpFile.getAbsolutePath());
}
}
}
if (usesProjectCache()) {
for (File projectAt : projectAts) {
args.add("--atFile");
args.add(projectAt.getAbsolutePath());
}
}
getProject().javaexec(spec -> {
spec.getMainClass().set("net.minecraftforge.accesstransformer.TransformerProcessor");
spec.setArgs(args);
spec.setClasspath(classpath);
// if running with INFO or DEBUG logging
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);
}
}).rethrowFailure().assertNormalExitValue();
});
for (File file : toDelete) {
file.delete();
@@ -766,15 +648,6 @@ public class MinecraftPatchedProvider extends MergedMinecraftProvider {
return forgeMergedJar;
}
public boolean usesProjectCache() {
if (!projectAts.isEmpty()) FunnyTodoException.yes("project ATs");
return false;
}
public boolean isAtDirty() {
return atDirty || filesDirty;
}
@Override
public List<Path> getMinecraftJars() {
if (forgeMergedJar != null) {

View File

@@ -66,6 +66,7 @@ public abstract class MinecraftProvider {
private BundleMetadata serverBundleMetadata;
private File versionManifestJson;
private File experimentalVersionsJson;
private String jarPrefix = "";
private final Project project;
@@ -77,6 +78,10 @@ public abstract class MinecraftProvider {
final DependencyInfo dependency = DependencyInfo.create(getProject(), Constants.Configurations.MINECRAFT);
minecraftVersion = dependency.getDependency().getVersion();
if (getExtension().shouldGenerateSrgTiny() && !getExtension().isForge()) {
getProject().getDependencies().add("de.oceanlabs.mcp:mcp_config:" + minecraftVersion, Constants.Configurations.SRG);
}
boolean offline = getProject().getGradle().getStartParameter().isOffline();
initFiles();
@@ -295,6 +300,14 @@ public abstract class MinecraftProvider {
return libraryProvider;
}
public String getJarPrefix() {
return jarPrefix;
}
public void setJarPrefix(String jarSuffix) {
this.jarPrefix = jarSuffix;
}
public String getTargetConfig() {
return Constants.Configurations.MINECRAFT;
}

View File

@@ -93,7 +93,7 @@ public abstract class AbstractMappedMinecraftProvider<M extends MinecraftProvide
}
protected String getDependencyNotation(String name) {
return "net.minecraft:%s:%s/%s".formatted(getName(name), extension.getMinecraftProvider().minecraftVersion(), extension.getMappingsProvider().mappingsIdentifier());
return "net.minecraft:%s%s:%s/%s".formatted(getName(name), extension.getMinecraftProvider().getJarPrefix(), extension.getMinecraftProvider().minecraftVersion(), extension.getMappingsProvider().mappingsIdentifier());
}
private boolean areOutputsValid(List<RemappedJars> remappedJars) {

View File

@@ -50,7 +50,7 @@ public abstract class ProcessedNamedMinecraftProvider<M extends MinecraftProvide
this.parentMinecraftProvider = parentMinecraftProvide;
this.jarProcessorManager = jarProcessorManager;
this.projectMappedName = "minecraft-project-%s-".formatted(getProject().getPath().replace(':', '@'));
this.projectMappedName = parentMinecraftProvide.getMinecraftProvider().getJarPrefix() + "minecraft-project-%s-".formatted(getProject().getPath().replace(':', '@'));
final LoomGradleExtension extension = LoomGradleExtension.get(getProject());
this.projectMappedDir = extension.getFiles().getRootProjectPersistentCache().toPath()

View File

@@ -39,14 +39,26 @@ import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.api.decompilers.DecompilationMetadata;
import net.fabricmc.loom.api.decompilers.architectury.ArchitecturyLoomDecompiler;
import net.fabricmc.loom.util.FunnyTodoException;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.OperatingSystem;
public abstract class ArchitecturyGenerateSourcesTask extends AbstractLoomTask {
public abstract class ArchitecturyGenerateSourcesTask extends AbstractLoomTask implements DecompilationTask {
private final ArchitecturyLoomDecompiler decompiler;
/**
* The jar to decompile, can be the unpick jar.
*/
@Override
@InputFile
public abstract RegularFileProperty getInputJar();
/**
* The jar used at runtime.
*/
@Override
@InputFile
public abstract RegularFileProperty getRuntimeJar();
@Input
public abstract MapProperty<String, String> getOptions();
@@ -59,16 +71,14 @@ public abstract class ArchitecturyGenerateSourcesTask extends AbstractLoomTask {
@TaskAction
public void run() throws IOException {
FunnyTodoException.yes("Architectury decompiler API");
/*if (!OperatingSystem.is64Bit()) {
if (!OperatingSystem.is64Bit()) {
throw new UnsupportedOperationException("GenSources task requires a 64bit JVM to run due to the memory requirements.");
}
// TODO: Need a good way to not keep a duplicated code for this
Path compiledJar = getInputJar().get().getAsFile().toPath();
Path runtimeJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath();
Path sourcesDestination = GenerateSourcesTask.getMappedJarFileWithSuffix(getProject(), "-sources.jar").toPath();
Path linemapDestination = GenerateSourcesTask.getMappedJarFileWithSuffix(getProject(), "-sources.lmap").toPath();
Path sourcesDestination = GenerateSourcesTask.getMappedJarFileWithSuffix(getRuntimeJar(), "-sources.jar").toPath();
Path linemapDestination = GenerateSourcesTask.getMappedJarFileWithSuffix(getRuntimeJar(), "-sources.lmap").toPath();
DecompilationMetadata metadata = new DecompilationMetadata(
Runtime.getRuntime().availableProcessors(),
GenerateSourcesTask.getMappings(getProject(), getExtension()),
@@ -81,7 +91,8 @@ public abstract class ArchitecturyGenerateSourcesTask extends AbstractLoomTask {
// Apply linemap
if (Files.exists(linemapDestination)) {
Path linemapJar = GenerateSourcesTask.getMappedJarFileWithSuffix(getProject(), "-linemapped.jar").toPath();
Path linemapJar = GenerateSourcesTask.getMappedJarFileWithSuffix(getRuntimeJar(), "-linemapped.jar").toPath();
Path runtimeJar = getRuntimeJar().get().getAsFile().toPath();
try {
GenerateSourcesTask.DecompileAction.remapLineNumbers(getLogger()::info, runtimeJar, linemapDestination, linemapJar);
@@ -90,6 +101,6 @@ public abstract class ArchitecturyGenerateSourcesTask extends AbstractLoomTask {
} catch (Exception e) {
throw new RuntimeException("Could not remap line numbers", e);
}
}*/
}
}
}

View File

@@ -0,0 +1,11 @@
package net.fabricmc.loom.task;
import org.gradle.api.Task;
import org.gradle.api.file.RegularFileProperty;
// TODO: This should probably be replaced in favour of just using upstream Loom's decompiler options
@Deprecated
public interface DecompilationTask extends Task {
RegularFileProperty getInputJar();
RegularFileProperty getRuntimeJar();
}

View File

@@ -72,18 +72,20 @@ import net.fabricmc.loom.util.gradle.WorkerDaemonClientsManagerHelper;
import net.fabricmc.loom.util.ipc.IPCClient;
import net.fabricmc.loom.util.ipc.IPCServer;
public abstract class GenerateSourcesTask extends AbstractLoomTask {
public abstract class GenerateSourcesTask extends AbstractLoomTask implements DecompilationTask {
private final DecompilerOptions decompilerOptions;
/**
* The jar to decompile, can be the unpick jar.
*/
@Override
@InputFile
public abstract RegularFileProperty getInputJar();
/**
* The jar used at runtime.
*/
@Override
@InputFile
public abstract RegularFileProperty getRuntimeJar();
@@ -289,7 +291,11 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
}
private File getMappedJarFileWithSuffix(String suffix) {
String path = getRuntimeJar().get().getAsFile().getAbsolutePath();
return getMappedJarFileWithSuffix(getRuntimeJar(), suffix);
}
static File getMappedJarFileWithSuffix(RegularFileProperty runtimeJar, String suffix) {
String path = runtimeJar.get().getAsFile().getAbsolutePath();
if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) {
throw new RuntimeException("Invalid mapped JAR path: " + path);

View File

@@ -96,6 +96,7 @@ public final class LoomTasks {
registerIDETasks(tasks);
registerRunTasks(tasks, project);
registerLaunchSettings(project);
}
private static void registerIDETasks(TaskContainer tasks) {
@@ -149,6 +150,17 @@ public final class LoomTasks {
});
}
private static void registerLaunchSettings(Project project) {
LoomGradleExtension extension = LoomGradleExtension.get(project);
Preconditions.checkArgument(extension.getLaunchConfigs().size() == 0, "Launch configurations must not be registered before loom");
extension.getLaunchConfigs().create("client");
extension.getLaunchConfigs().create("server");
if (extension.isForge()) {
extension.getLaunchConfigs().create("data");
}
}
public static Provider<Task> getIDELaunchConfigureTaskName(Project project) {
return project.provider(() -> {
final MinecraftJarConfiguration jarConfiguration = LoomGradleExtension.get(project).getMinecraftJarConfiguration().get();

View File

@@ -171,9 +171,14 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
}
params.getForge().set(extension.isForge());
params.getMappingBuildServiceUuid().convention("this should be unavailable!");
if (extension.isForge()) {
params.getAtAccessWideners().set(getAtAccessWideners());
if (!getAtAccessWideners().get().isEmpty()) {
params.getMappingBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getProject(), MappingsService.createDefault(getProject(), getSourceNamespace().get(), getTargetNamespace().get())));
}
}
});
}
@@ -246,6 +251,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
Property<JarManifestService> getJarManifestService();
Property<String> getTinyRemapperBuildServiceUuid();
Property<String> getMappingBuildServiceUuid();
}
public abstract static class RemapAction extends AbstractRemapAction<RemapParams> {
@@ -269,6 +275,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
remapAccessWidener();
addRefmaps();
addNestedJars();
convertAwToAt();
if (!getParameters().getForge().get()) {
modifyJarManifest();
@@ -309,8 +316,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
}
private void convertAwToAt() throws IOException {
FunnyTodoException.yes("AW2AT");
/*if (!this.getParameters().getAtAccessWideners().isPresent()) {
if (!this.getParameters().getAtAccessWideners().isPresent()) {
return;
}
@@ -345,14 +351,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
Files.delete(awPath);
}
List<Provider<MappingsService>> providers = getParameters().getMappings().get();
// This is a bit of a hack, but we are going to get the first one, it should be the default one
if (providers.isEmpty()) {
throw new IllegalStateException("No mappings provider found for AW to AT conversion!");
}
MappingsService service = providers.get(0).get();
MappingsService service = UnsafeWorkQueueHelper.get(getParameters().getMappingBuildServiceUuid(), MappingsService.class);
try (TinyMappingsReader reader = new TinyMappingsReader(service.getMemoryMappingTree(), service.getFromNamespace(), service.getToNamespace())) {
MappingSet mappingSet = reader.read();
@@ -362,7 +361,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
try (Writer writer = new LfWriter(Files.newBufferedWriter(atPath))) {
AccessTransformFormats.FML.write(writer, at);
}
}*/
}
}
private byte[] remapAccessWidener(byte[] input) {

View File

@@ -32,6 +32,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
@@ -39,7 +40,9 @@ import org.apache.commons.io.FileUtils;
import org.gradle.api.logging.configuration.ConsoleOutput;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
import net.fabricmc.loom.task.AbstractLoomTask;
import net.fabricmc.loom.util.PropertyUtil;
public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
@TaskAction
@@ -53,12 +56,56 @@ public abstract class GenerateDLIConfigTask extends AbstractLoomTask {
.property("log4j2.formatMsgNoLookups", "true")
.property("client", "java.library.path", nativesPath)
.property("client", "org.lwjgl.librarypath", nativesPath)
.property("client", "org.lwjgl.librarypath", nativesPath);
.argument("client", "--assetIndex")
.argument("client", getExtension().getMinecraftProvider().getVersionInfo().assetIndex().fabricId(getExtension().getMinecraftProvider().minecraftVersion()))
.argument("client", "--assetsDir")
.argument("client", new File(getExtension().getFiles().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(getExtension().getFiles().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("data", "--all")
.argument("data", "--mod")
.argument("data", String.join(",", getExtension().getForge().getDataGenMods()))
.argument("data", "--output")
.argument("data", getProject().file("src/generated/resources").getAbsolutePath())
.property("mixin.env.remapRefMap", "true");
if (PropertyUtil.getAndFinalize(getExtension().getForge().getUseCustomMixin())) {
launchConfig.property("mixin.forgeloom.inject.mappings.srg-named", getExtension().getMappingsProvider().mixinTinyMappingsWithSrg.toAbsolutePath().toString());
} else {
launchConfig.property("net.minecraftforge.gradle.GradleStart.srg.srg-mcp", getExtension().getMappingsProvider().srgToNamedSrg.toAbsolutePath().toString());
}
Set<String> mixinConfigs = PropertyUtil.getAndFinalize(getExtension().getForge().getMixinConfigs());
if (!mixinConfigs.isEmpty()) {
for (String config : mixinConfigs) {
launchConfig.argument("-mixin.config");
launchConfig.argument(config);
}
}
}
for (LaunchProviderSettings settings : getExtension().getLaunchConfigs()) {
settings.evaluateNow();
for (String argument : settings.getArguments()) {
launchConfig.argument(settings.getName(), argument);
}
for (Map.Entry<String, String> property : settings.getProperties()) {
launchConfig.property(settings.getName(), property.getKey(), property.getValue());
}
}
final boolean plainConsole = getProject().getGradle().getStartParameter().getConsoleOutput() == ConsoleOutput.Plain;
final boolean ansiSupportedIDE = new File(getProject().getRootDir(), ".vscode").exists()

View File

@@ -56,6 +56,10 @@ public abstract class GenerateRemapClasspathTask extends AbstractLoomTask {
remapClasspath.add(minecraftJar.toFile());
}
if (getExtension().isForgeAndNotOfficial()) {
remapClasspath.add(getExtension().getMinecraftMappedProvider().getForgeIntermediaryJar());
}
String str = remapClasspath.stream()
.map(File::getAbsolutePath)
.collect(Collectors.joining(File.pathSeparator));

View File

@@ -56,7 +56,7 @@ public final class MappingsService implements SharedService {
final MappingsProviderImpl mappingsProvider = LoomGradleExtension.get(project).getMappingsProvider();
final String name = mappingsProvider.getBuildServiceName("mappingsProvider", from, to);
return MappingsService.create(project, name, (from.equals("srg") || to.equals("srg")) && LoomGradleExtension.get(project).shouldGenerateSrgTiny() ? mappingsProvider.tinyMappingsWithSrg.toFile() : mappingsProvider.tinyMappings, from, to, false);
return MappingsService.create(project, name, (from.equals("srg") || to.equals("srg")) && LoomGradleExtension.get(project).shouldGenerateSrgTiny() ? mappingsProvider.tinyMappingsWithSrg : mappingsProvider.tinyMappings, from, to, false);
}
private final Options options;