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