From 60da6d68564c3ed276317cbfa51f50ae732cf275 Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Sun, 5 Apr 2026 23:40:57 -0400 Subject: [PATCH 1/3] Add support for JST enum extension Will need a default NFRT bump once the relevant NFRT exists --- .../legacyforge/dsl/LegacyForgeExtension.java | 5 ++-- .../internal/LegacyForgeModDevPlugin.java | 4 ++- .../moddevgradle/dsl/ModDevExtension.java | 27 +++++++++++++++++- .../moddevgradle/dsl/NeoForgeExtension.java | 4 +-- .../internal/DataFileCollections.java | 13 +++++++-- .../internal/ModDevArtifactsWorkflow.java | 2 ++ .../moddevgradle/internal/ModDevPlugin.java | 4 ++- .../nfrtgradle/CreateMinecraftArtifacts.java | 11 ++++++++ .../DataFileCollectionFunctionalTest.java | 28 +++++++++++++++++++ 9 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/legacy/java/net/neoforged/moddevgradle/legacyforge/dsl/LegacyForgeExtension.java b/src/legacy/java/net/neoforged/moddevgradle/legacyforge/dsl/LegacyForgeExtension.java index bd207a27..43ae47c5 100644 --- a/src/legacy/java/net/neoforged/moddevgradle/legacyforge/dsl/LegacyForgeExtension.java +++ b/src/legacy/java/net/neoforged/moddevgradle/legacyforge/dsl/LegacyForgeExtension.java @@ -18,8 +18,9 @@ public abstract class LegacyForgeExtension extends ModDevExtension { @Inject public LegacyForgeExtension(Project project, DataFileCollection accessTransformers, - DataFileCollection interfaceInjectionData) { - super(project, accessTransformers, interfaceInjectionData); + DataFileCollection interfaceInjectionData, + DataFileCollection enumExtensionsData) { + super(project, accessTransformers, interfaceInjectionData, enumExtensionsData); this.project = project; } diff --git a/src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/LegacyForgeModDevPlugin.java b/src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/LegacyForgeModDevPlugin.java index a3f7ef17..c8ae98e3 100644 --- a/src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/LegacyForgeModDevPlugin.java +++ b/src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/LegacyForgeModDevPlugin.java @@ -104,7 +104,8 @@ public void apply(Project project) { LegacyForgeExtension.class, project, dataFileCollections.accessTransformers().extension(), - dataFileCollections.interfaceInjectionData().extension()); + dataFileCollections.interfaceInjectionData().extension(), + dataFileCollections.enumExtensionsData().extension()); } public void enable(Project project, LegacyForgeModdingSettings settings, LegacyForgeExtension extension) { @@ -153,6 +154,7 @@ public void enable(Project project, LegacyForgeModdingSettings settings, LegacyF artifactNamingStrategy, configurations.getByName(DataFileCollections.CONFIGURATION_ACCESS_TRANSFORMERS), configurations.getByName(DataFileCollections.CONFIGURATION_INTERFACE_INJECTION_DATA), + configurations.getByName(DataFileCollections.CONFIGURATION_ENUM_EXTENSIONS_DATA), versionCapabilities, settings.isDisableRecompilation()); diff --git a/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java b/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java index 021719a8..47831006 100644 --- a/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java +++ b/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java @@ -24,17 +24,20 @@ public abstract class ModDevExtension { private final Project project; private final DataFileCollection accessTransformers; private final DataFileCollection interfaceInjectionData; + private final DataFileCollection enumExtensionsData; @Inject public ModDevExtension(Project project, DataFileCollection accessTransformers, - DataFileCollection interfaceInjectionData) { + DataFileCollection interfaceInjectionData, + DataFileCollection enumExtensionsData) { mods = project.container(ModModel.class); runs = project.container(RunModel.class, name -> project.getObjects().newInstance(RunModel.class, name, project, mods)); parchment = project.getObjects().newInstance(Parchment.class); this.project = project; this.accessTransformers = accessTransformers; this.interfaceInjectionData = interfaceInjectionData; + this.enumExtensionsData = enumExtensionsData; getValidateAccessTransformers().convention(false); // Make sync tasks run @@ -88,6 +91,28 @@ public DataFileCollection getInterfaceInjectionData() { public void setInterfaceInjectionData(Object... paths) { getInterfaceInjectionData().getFiles().setFrom(paths); } + + /** + * The data-files describing additional enum extension declarations to be added to Minecraft enums. + *

+ * This is an advanced property: Extending enums in your development environment using this property will not actually extend the enums in your published mod. You must register your enum extensions in your mod metadata for that. + * + * @see Extensible Enums + */ + public void enumExtensionsData(Action action) { + action.execute(enumExtensionsData); + } + + public DataFileCollection getEnumExtensionsData() { + return enumExtensionsData; + } + + /** + * Replaces current enum extensions data files. + */ + public void setEnumExtensionsData(Object... paths) { + getEnumExtensionsData().getFiles().setFrom(paths); + } /** * Enable access transformer validation, raising fatal errors if an AT targets a member that doesn't exist. diff --git a/src/main/java/net/neoforged/moddevgradle/dsl/NeoForgeExtension.java b/src/main/java/net/neoforged/moddevgradle/dsl/NeoForgeExtension.java index c090517a..8b50abe5 100644 --- a/src/main/java/net/neoforged/moddevgradle/dsl/NeoForgeExtension.java +++ b/src/main/java/net/neoforged/moddevgradle/dsl/NeoForgeExtension.java @@ -17,8 +17,8 @@ public abstract class NeoForgeExtension extends ModDevExtension { private final UnitTest unitTest; @Inject - public NeoForgeExtension(Project project, DataFileCollection accessTransformers, DataFileCollection interfaceInjectionData) { - super(project, accessTransformers, interfaceInjectionData); + public NeoForgeExtension(Project project, DataFileCollection accessTransformers, DataFileCollection interfaceInjectionData, DataFileCollection enumExtensionsData) { + super(project, accessTransformers, interfaceInjectionData, enumExtensionsData); this.project = project; unitTest = project.getObjects().newInstance(UnitTest.class); unitTest.getLoadedMods().convention(getMods()); diff --git a/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java b/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java index 2079587e..fa8522e2 100644 --- a/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java +++ b/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java @@ -23,11 +23,14 @@ */ @ApiStatus.Internal public record DataFileCollections(CollectionWrapper accessTransformers, - CollectionWrapper interfaceInjectionData) { + CollectionWrapper interfaceInjectionData, + CollectionWrapper enumExtensionsData) { public static final String CONFIGURATION_ACCESS_TRANSFORMERS = "accessTransformers"; public static final String CONFIGURATION_INTERFACE_INJECTION_DATA = "interfaceInjectionData"; + + public static final String CONFIGURATION_ENUM_EXTENSIONS_DATA = "enumExtensionsData"; /** * Constructs the default data file collections for access transformers and intrface injection data @@ -61,8 +64,14 @@ public static DataFileCollections create(Project project) { CONFIGURATION_INTERFACE_INJECTION_DATA, "Interface injection data adds extend/implements clauses for interfaces to Minecraft code at development time", "interfaceinjection"); + + var enumExtensionsData = createCollection( + project, + CONFIGURATION_ENUM_EXTENSIONS_DATA, + "Enum extensions data adds new enum constants to Minecraft enums at development time", + "enumextensions"); - return new DataFileCollections(accessTransformers, interfaceInjectionData); + return new DataFileCollections(accessTransformers, interfaceInjectionData, enumExtensionsData); } public record CollectionWrapper(DataFileCollection extension, Configuration configuration) {} diff --git a/src/main/java/net/neoforged/moddevgradle/internal/ModDevArtifactsWorkflow.java b/src/main/java/net/neoforged/moddevgradle/internal/ModDevArtifactsWorkflow.java index 40b1723d..a81cf34e 100644 --- a/src/main/java/net/neoforged/moddevgradle/internal/ModDevArtifactsWorkflow.java +++ b/src/main/java/net/neoforged/moddevgradle/internal/ModDevArtifactsWorkflow.java @@ -67,6 +67,7 @@ public static ModDevArtifactsWorkflow create(Project project, ArtifactNamingStrategy artifactNamingStrategy, Configuration accessTransformers, Configuration interfaceInjectionData, + Configuration enumExtensionsData, VersionCapabilitiesInternal versionCapabilities, boolean disableRecompilation) { if (project.getExtensions().findByName(EXTENSION_NAME) != null) { @@ -147,6 +148,7 @@ public static ModDevArtifactsWorkflow create(Project project, } })); task.getInterfaceInjectionData().from(interfaceInjectionData); + task.getEnumExtensionsData().from(enumExtensionsData); task.getParchmentData().from(parchmentData); task.getParchmentEnabled().set(parchment.getEnabled()); task.getParchmentConflictResolutionPrefix().set(parchment.getConflictResolutionPrefix()); diff --git a/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java b/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java index 97f0e7f5..51272691 100644 --- a/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java +++ b/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java @@ -41,7 +41,8 @@ public void apply(Project project) { NeoForgeExtension.NAME, NeoForgeExtension.class, dataFileCollections.accessTransformers().extension(), - dataFileCollections.interfaceInjectionData().extension()); + dataFileCollections.interfaceInjectionData().extension(), + dataFileCollections.enumExtensionsData().extension()); } public void enable( @@ -97,6 +98,7 @@ public void enable( artifactNamingStrategy, configurations.getByName(DataFileCollections.CONFIGURATION_ACCESS_TRANSFORMERS), configurations.getByName(DataFileCollections.CONFIGURATION_INTERFACE_INJECTION_DATA), + configurations.getByName(DataFileCollections.CONFIGURATION_ENUM_EXTENSIONS_DATA), versionCapabilities, settings.isDisableRecompilation()); diff --git a/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java b/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java index d9f9eb54..e4c2d68d 100644 --- a/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java +++ b/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java @@ -80,6 +80,12 @@ public CreateMinecraftArtifacts() { @InputFiles public abstract ConfigurableFileCollection getInterfaceInjectionData(); + /** + * Files added to this collection will be passed to NFRT via the {@code --enum-extensions.data} command line option. + */ + @InputFiles + public abstract ConfigurableFileCollection getEnumExtensionsData(); + /** * If set to true, all files from {@link #getAccessTransformers()} are added as validated ATs and will fail the build * if they contain errors, or they target non-existent code elements. @@ -295,6 +301,11 @@ public void createArtifacts() { args.add("--interface-injection-data"); args.add(interfaceInjectionFile.getAbsolutePath()); } + + for (var enumExtensionsFile : getEnumExtensionsData().getFiles()) { + args.add("--enum-extensions-data"); + args.add(enumExtensionsFile.getAbsolutePath()); + } if (getParchmentEnabled().get()) { var parchmentData = getParchmentData().getFiles(); diff --git a/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java b/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java index e71d5e48..6d732951 100644 --- a/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java +++ b/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java @@ -111,6 +111,34 @@ public void testPublishInterfaceInjectionFile() throws IOException { entry("publish-if-1.0-interfaceinjection3.json", "{}")); } + @Test + public void testPublishEnumExtensionsFile() throws IOException { + writeProjectFile("enumextensions.json", "{}"); + writeProjectFile("enumextensions/enumextensions.json", "{}"); + Files.writeString(testProjectDir.toPath().resolve("enumextensions.json"), "{}"); + + publishDataFiles("test", "publish-if", "1.0", """ + def generatedDataFile = tasks.register("generateDataFile") { + outputs.file("build/generatedDataFile.json") + doFirst { + outputs.files.singleFile.text = '{}' + } + } + neoForge { + enumExtensionsData { + publish(file('enumextensions.json')) + publish(file('subfolder/enumextensions.json')) + publish(generatedDataFile) + } + } + """); + + assertThat(consumeDataFilePublication("enumExtensionsData", "test:publish-if:1.0")).containsOnly( + entry("publish-if-1.0-enumextensions1.json", "{}"), + entry("publish-if-1.0-enumextensions2.json", "{}"), + entry("publish-if-1.0-enumextensions3.json", "{}")); + } + @Test public void testNoEmptyVariantsArePublished() throws IOException { publishDataFiles("test", "publish-empty", "1.0", ""); From 8e03d2290d80f6ca33be2dd5cbcb08ad3fbbded5 Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Fri, 10 Apr 2026 20:45:05 -0400 Subject: [PATCH 2/3] Fix formatting --- .../net/neoforged/moddevgradle/dsl/ModDevExtension.java | 6 +++--- .../moddevgradle/internal/DataFileCollections.java | 4 ++-- .../net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java b/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java index 47831006..51bb11e3 100644 --- a/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java +++ b/src/main/java/net/neoforged/moddevgradle/dsl/ModDevExtension.java @@ -91,7 +91,7 @@ public DataFileCollection getInterfaceInjectionData() { public void setInterfaceInjectionData(Object... paths) { getInterfaceInjectionData().getFiles().setFrom(paths); } - + /** * The data-files describing additional enum extension declarations to be added to Minecraft enums. *

@@ -102,11 +102,11 @@ public void setInterfaceInjectionData(Object... paths) { public void enumExtensionsData(Action action) { action.execute(enumExtensionsData); } - + public DataFileCollection getEnumExtensionsData() { return enumExtensionsData; } - + /** * Replaces current enum extensions data files. */ diff --git a/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java b/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java index fa8522e2..ee0a5d8d 100644 --- a/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java +++ b/src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java @@ -29,7 +29,7 @@ public record DataFileCollections(CollectionWrapper accessTransformers, public static final String CONFIGURATION_ACCESS_TRANSFORMERS = "accessTransformers"; public static final String CONFIGURATION_INTERFACE_INJECTION_DATA = "interfaceInjectionData"; - + public static final String CONFIGURATION_ENUM_EXTENSIONS_DATA = "enumExtensionsData"; /** @@ -64,7 +64,7 @@ public static DataFileCollections create(Project project) { CONFIGURATION_INTERFACE_INJECTION_DATA, "Interface injection data adds extend/implements clauses for interfaces to Minecraft code at development time", "interfaceinjection"); - + var enumExtensionsData = createCollection( project, CONFIGURATION_ENUM_EXTENSIONS_DATA, diff --git a/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java b/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java index e4c2d68d..49f8867f 100644 --- a/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java +++ b/src/main/java/net/neoforged/nfrtgradle/CreateMinecraftArtifacts.java @@ -301,7 +301,7 @@ public void createArtifacts() { args.add("--interface-injection-data"); args.add(interfaceInjectionFile.getAbsolutePath()); } - + for (var enumExtensionsFile : getEnumExtensionsData().getFiles()) { args.add("--enum-extensions-data"); args.add(enumExtensionsFile.getAbsolutePath()); From 22b1b527277bcd1974e7ed9c8011f272da5c74a1 Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Fri, 10 Apr 2026 21:09:01 -0400 Subject: [PATCH 3/3] Fix failing test --- .../functional/DataFileCollectionFunctionalTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java b/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java index 6d732951..bdc23ba4 100644 --- a/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java +++ b/src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java @@ -114,7 +114,7 @@ public void testPublishInterfaceInjectionFile() throws IOException { @Test public void testPublishEnumExtensionsFile() throws IOException { writeProjectFile("enumextensions.json", "{}"); - writeProjectFile("enumextensions/enumextensions.json", "{}"); + writeProjectFile("subfolder/enumextensions.json", "{}"); Files.writeString(testProjectDir.toPath().resolve("enumextensions.json"), "{}"); publishDataFiles("test", "publish-if", "1.0", """