diff --git a/src/main/java/net/neoforged/neoform/runtime/actions/ApplySourceTransformAction.java b/src/main/java/net/neoforged/neoform/runtime/actions/ApplySourceTransformAction.java index 3a1b074..982c255 100644 --- a/src/main/java/net/neoforged/neoform/runtime/actions/ApplySourceTransformAction.java +++ b/src/main/java/net/neoforged/neoform/runtime/actions/ApplySourceTransformAction.java @@ -41,9 +41,16 @@ public class ApplySourceTransformAction extends ExternalJavaToolAction { /** * Additional paths to access transformers. + *

+ * A description of the format can be found in the NeoForge documentation. */ private List additionalAccessTransformers = new ArrayList<>(); + /** + * Additional paths to interface injection data files. + */ + private List injectedInterfaces = new ArrayList<>(); + /** * Path to a Parchment data archive. */ @@ -88,6 +95,16 @@ public void run(ProcessingEnvironment environment) throws IOException, Interrupt } } + if (!injectedInterfaces.isEmpty()) { + args.add("--enable-interface-injection"); + for (var path : injectedInterfaces) { + args.add("--interface-injection-data"); + args.add(environment.getPathArgument(path)); + } + args.add("--interface-injection-stub-location"); + args.add("{stubs}"); + } + if (parchmentData != null) { args.add("--enable-parchment"); args.add("--parchment-mappings=" + environment.getPathArgument(parchmentData.toAbsolutePath())); @@ -114,6 +131,7 @@ public void computeCacheKey(CacheKeyBuilder ck) { super.computeCacheKey(ck); ck.addStrings("access transformers data ids", accessTransformersData); ck.addPaths("additional access transformers", additionalAccessTransformers); + ck.addPaths("injected interfaces", injectedInterfaces); if (parchmentData != null) { ck.addPath("parchment data", parchmentData); } @@ -137,6 +155,10 @@ public void setAdditionalAccessTransformers(List additionalAccessTransform this.additionalAccessTransformers = List.copyOf(additionalAccessTransformers); } + public void setInjectedInterfaces(List injectedInterfaces) { + this.injectedInterfaces = List.copyOf(injectedInterfaces); + } + public @Nullable Path getParchmentData() { return parchmentData; } diff --git a/src/main/java/net/neoforged/neoform/runtime/actions/ExtensibleClasspath.java b/src/main/java/net/neoforged/neoform/runtime/actions/ExtensibleClasspath.java index 4aeb2f4..8082d40 100644 --- a/src/main/java/net/neoforged/neoform/runtime/actions/ExtensibleClasspath.java +++ b/src/main/java/net/neoforged/neoform/runtime/actions/ExtensibleClasspath.java @@ -2,6 +2,7 @@ import net.neoforged.neoform.runtime.artifacts.ClasspathItem; import net.neoforged.neoform.runtime.cache.CacheKeyBuilder; +import net.neoforged.neoform.runtime.graph.NodeOutput; import net.neoforged.neoform.runtime.manifests.MinecraftLibrary; import net.neoforged.neoform.runtime.utils.MavenCoordinate; import org.jetbrains.annotations.Nullable; @@ -109,6 +110,7 @@ public void computeCacheKey(String prefix, CacheKeyBuilder ck) { } } case ClasspathItem.PathItem(Path path) -> ck.addPath(component, path); + case ClasspathItem.NodeOutputItem(NodeOutput output) -> ck.addPath(component, output.getResultPath()); } } } diff --git a/src/main/java/net/neoforged/neoform/runtime/artifacts/ArtifactManager.java b/src/main/java/net/neoforged/neoform/runtime/artifacts/ArtifactManager.java index de8b3c2..095fc93 100644 --- a/src/main/java/net/neoforged/neoform/runtime/artifacts/ArtifactManager.java +++ b/src/main/java/net/neoforged/neoform/runtime/artifacts/ArtifactManager.java @@ -4,6 +4,7 @@ import net.neoforged.neoform.runtime.cli.LockManager; import net.neoforged.neoform.runtime.downloads.DownloadManager; import net.neoforged.neoform.runtime.downloads.DownloadSpec; +import net.neoforged.neoform.runtime.graph.NodeOutput; import net.neoforged.neoform.runtime.manifests.LauncherManifest; import net.neoforged.neoform.runtime.manifests.MinecraftLibrary; import net.neoforged.neoform.runtime.manifests.MinecraftVersionManifest; @@ -138,6 +139,7 @@ public List resolveClasspath(Collection classpathItems) thr } case ClasspathItem.MinecraftLibraryItem(MinecraftLibrary library) -> get(library).path(); case ClasspathItem.PathItem(Path path) -> path; + case ClasspathItem.NodeOutputItem(NodeOutput output) -> output.getResultPath(); }; result.add(pathToAdd); } diff --git a/src/main/java/net/neoforged/neoform/runtime/artifacts/ClasspathItem.java b/src/main/java/net/neoforged/neoform/runtime/artifacts/ClasspathItem.java index 7dd8a03..a384989 100644 --- a/src/main/java/net/neoforged/neoform/runtime/artifacts/ClasspathItem.java +++ b/src/main/java/net/neoforged/neoform/runtime/artifacts/ClasspathItem.java @@ -1,5 +1,6 @@ package net.neoforged.neoform.runtime.artifacts; +import net.neoforged.neoform.runtime.graph.NodeOutput; import net.neoforged.neoform.runtime.manifests.MinecraftLibrary; import net.neoforged.neoform.runtime.utils.MavenCoordinate; import org.jetbrains.annotations.Nullable; @@ -27,6 +28,10 @@ static ClasspathItem of(MavenCoordinate mavenLibrary, @Nullable URI repositoryBa return new MavenCoordinateItem(mavenLibrary, repositoryBaseUrl); } + static ClasspathItem of(NodeOutput output) { + return new NodeOutputItem(output); + } + record MavenCoordinateItem(MavenCoordinate coordinate, @Nullable URI repositoryBaseUrl) implements ClasspathItem { @Override public String toString() { @@ -51,4 +56,11 @@ public String toString() { return library.toString(); } } + + record NodeOutputItem(NodeOutput output) implements ClasspathItem { + @Override + public String toString() { + return output.getResultPath().toString(); + } + } } diff --git a/src/main/java/net/neoforged/neoform/runtime/cli/RunNeoFormCommand.java b/src/main/java/net/neoforged/neoform/runtime/cli/RunNeoFormCommand.java index 71e62a3..c998472 100644 --- a/src/main/java/net/neoforged/neoform/runtime/cli/RunNeoFormCommand.java +++ b/src/main/java/net/neoforged/neoform/runtime/cli/RunNeoFormCommand.java @@ -6,9 +6,11 @@ import net.neoforged.neoform.runtime.actions.MergeWithSourcesAction; import net.neoforged.neoform.runtime.actions.PatchActionFactory; import net.neoforged.neoform.runtime.actions.RecompileSourcesAction; +import net.neoforged.neoform.runtime.artifacts.ClasspathItem; import net.neoforged.neoform.runtime.config.neoforge.NeoForgeConfig; import net.neoforged.neoform.runtime.engine.NeoFormEngine; import net.neoforged.neoform.runtime.graph.ExecutionGraph; +import net.neoforged.neoform.runtime.graph.ExecutionNode; import net.neoforged.neoform.runtime.graph.NodeOutput; import net.neoforged.neoform.runtime.graph.NodeOutputType; import net.neoforged.neoform.runtime.graph.transforms.GraphTransform; @@ -25,6 +27,7 @@ import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; @@ -37,9 +40,6 @@ public class RunNeoFormCommand extends NeoFormEngineCommand { private static final Logger LOG = Logger.create(); - @CommandLine.ParentCommand - Main commonOptions; - @CommandLine.ArgGroup(exclusive = false, multiplicity = "1") SourceArtifacts sourceArtifacts; @@ -49,9 +49,12 @@ public class RunNeoFormCommand extends NeoFormEngineCommand { @CommandLine.Option(names = "--write-result", arity = "*") List writeResults = new ArrayList<>(); - @CommandLine.Option(names = "--access-transformer", arity = "*") + @CommandLine.Option(names = "--access-transformer", arity = "*", description = "path to an access transformer file, which widens the access modifiers of classes/methods/fields") List additionalAccessTransformers = new ArrayList<>(); + @CommandLine.Option(names = "--interface-injection-data", arity = "*", description = "path to an interface injection data file, which extends classes with implements/extends clauses") + List interfaceInjectionDataFiles = new ArrayList<>(); + @CommandLine.Option(names = "--validate-access-transformers", description = "Whether access transformers should be validated and fatal errors should arise if they target members that do not exist") boolean validateAccessTransformers; @@ -99,7 +102,8 @@ protected void runWithNeoFormEngine(NeoFormEngine engine, List cl engine.addManagedResource(neoforgeSourcesZip); engine.addManagedResource(neoforgeClassesZip); - var transformSources = getOrAddTransformSourcesNode(engine); + var transformSources = getOrAddTransformSourcesAction(engine); + transformSources.setAccessTransformersData(List.of("neoForgeAccessTransformers")); // Add NeoForge libraries to the list of libraries @@ -133,7 +137,7 @@ protected void runWithNeoFormEngine(NeoFormEngine engine, List cl } if (!additionalAccessTransformers.isEmpty()) { - var transformSources = getOrAddTransformSourcesNode(engine); + var transformSources = getOrAddTransformSourcesAction(engine); transformSources.setAdditionalAccessTransformers(additionalAccessTransformers.stream().map(Paths::get).toList()); if (validateAccessTransformers) { transformSources.addArg("--access-transformer-validation=error"); @@ -141,7 +145,7 @@ protected void runWithNeoFormEngine(NeoFormEngine engine, List cl } if (parchmentData != null) { - var transformSources = getOrAddTransformSourcesNode(engine); + var transformSources = getOrAddTransformSourcesAction(engine); var parchmentDataFile = artifactManager.get(parchmentData); transformSources.setParchmentData(parchmentDataFile.path()); @@ -150,6 +154,20 @@ protected void runWithNeoFormEngine(NeoFormEngine engine, List cl } } + if (!interfaceInjectionDataFiles.isEmpty()) { + var transformNode = getOrAddTransformSourcesNode(engine); + ((ApplySourceTransformAction) transformNode.action()).setInjectedInterfaces(interfaceInjectionDataFiles); + + // Add the stub source jar to the recomp classpath + engine.applyTransform(new ModifyAction<>( + "recompile", + RecompileSourcesAction.class, + action -> { + action.getClasspath().add(ClasspathItem.of(transformNode.getRequiredOutput("stubs"))); + } + )); + } + execute(engine); } @@ -197,7 +215,7 @@ private void execute(NeoFormEngine engine) throws InterruptedException, IOExcept LOG.println(stringWriter.toString()); } - var neededResults = writeResults.stream().map(encodedResult -> { + var neededResults = writeResults.stream().map(encodedResult -> { var parts = encodedResult.split(":", 2); if (parts.length != 2) { throw new IllegalArgumentException("Specify a result destination in the form: :"); @@ -235,12 +253,16 @@ private void execute(NeoFormEngine engine) throws InterruptedException, IOExcept } } - private static ApplySourceTransformAction getOrAddTransformSourcesNode(NeoFormEngine engine) { + private static ApplySourceTransformAction getOrAddTransformSourcesAction(NeoFormEngine engine) { + return (ApplySourceTransformAction) getOrAddTransformSourcesNode(engine).action(); + } + + private static ExecutionNode getOrAddTransformSourcesNode(NeoFormEngine engine) { var graph = engine.getGraph(); var transformNode = graph.getNode("transformSources"); if (transformNode != null) { - if (transformNode.action() instanceof ApplySourceTransformAction action) { - return action; + if (transformNode.action() instanceof ApplySourceTransformAction) { + return transformNode; } else { throw new IllegalStateException("Node transformSources has a different action type than expected. Expected: " + ApplySourceTransformAction.class + " but got " + transformNode.action().getClass()); @@ -256,7 +278,8 @@ private static ApplySourceTransformAction getOrAddTransformSourcesNode(NeoFormEn builder.inputFromNodeOutput("libraries", "listLibraries", "output"); var action = new ApplySourceTransformAction(); builder.action(action); - return builder.output("output", NodeOutputType.ZIP, "Sources with additional transforms (ATs, Parchment) applied"); + builder.output("stubs", NodeOutputType.JAR, "Additional stubs (resulted as part of interface injection) to add to the recompilation classpath"); + return builder.output("output", NodeOutputType.ZIP, "Sources with additional transforms (ATs, Parchment, Interface Injections) applied"); } ).apply(engine, graph); diff --git a/src/main/java/net/neoforged/neoform/runtime/engine/NeoFormEngine.java b/src/main/java/net/neoforged/neoform/runtime/engine/NeoFormEngine.java index fab7bc7..e35eaa9 100644 --- a/src/main/java/net/neoforged/neoform/runtime/engine/NeoFormEngine.java +++ b/src/main/java/net/neoforged/neoform/runtime/engine/NeoFormEngine.java @@ -497,6 +497,10 @@ public void applyTransforms(List transforms) { } } + public void applyTransform(GraphTransform transform) { + transform.apply(this, graph); + } + public ExecutionGraph getGraph() { return graph; } diff --git a/src/main/resources/tools.properties b/src/main/resources/tools.properties index f8dedce..0938ded 100644 --- a/src/main/resources/tools.properties +++ b/src/main/resources/tools.properties @@ -1,5 +1,5 @@ # https://projects.neoforged.net/neoforged/javasourcetransformer -JAVA_SOURCE_TRANSFORMER=net.neoforged.jst:jst-cli-bundle:1.0.50 +JAVA_SOURCE_TRANSFORMER=net.neoforged.jst:jst-cli-bundle:1.0.58 DIFF_PATCH=codechicken:DiffPatch:1.5.0.29:all