Skip to content

Commit 8cbdb66

Browse files
committed
Configure binary patch mode ready for production.
1 parent e713b9b commit 8cbdb66

17 files changed

Lines changed: 447 additions & 103 deletions

File tree

userdev/src/functionalTest/groovy/net/neoforged/gradle/userdev/AdvancedFmlTests.groovy

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@ class AdvancedFmlTests extends BuilderBasedTestSpecification {
5858
implementation 'net.neoforged:neoforge:+'
5959
}
6060
""")
61+
it.file("src/main/java/net/neoforged/gradle/userdev/FunctionalTests.java", """
62+
package net.neoforged.gradle.userdev;
63+
64+
import net.minecraft.client.Minecraft;
65+
66+
public class FunctionalTests {
67+
public static void main(String[] args) {
68+
System.out.println(Minecraft.getInstance().getClass().toString());
69+
}
70+
}
71+
""")
6172
it.withToolchains()
6273
it.withGlobalCacheDirectory(tempDir)
6374
it.withEnvironmentVariable("CI", "true")
@@ -70,13 +81,13 @@ class AdvancedFmlTests extends BuilderBasedTestSpecification {
7081
}
7182

7283
then:
73-
run.task(':compileJava').outcome == TaskOutcome.NO_SOURCE
84+
run.task(':compileJava').outcome == TaskOutcome.SUCCESS
7485
run.task(":neoFormDecompile") == null
7586
}
7687

7788
def "a mod with userdev as dependency can run the compile task for that dependency with the decompiler disabled"() {
7889
given:
79-
def project = create("running_compile_in_ci", {
90+
def project = create("running_compile_with_compiler_disabled", {
8091
it.build("""
8192
java {
8293
toolchain {
@@ -88,6 +99,17 @@ class AdvancedFmlTests extends BuilderBasedTestSpecification {
8899
implementation 'net.neoforged:neoforge:+'
89100
}
90101
""")
102+
it.file("src/main/java/net/neoforged/gradle/userdev/FunctionalTests.java", """
103+
package net.neoforged.gradle.userdev;
104+
105+
import net.minecraft.client.Minecraft;
106+
107+
public class FunctionalTests {
108+
public static void main(String[] args) {
109+
System.out.println(Minecraft.getInstance().getClass().toString());
110+
}
111+
}
112+
""")
91113
it.withToolchains()
92114
it.withGlobalCacheDirectory(tempDir)
93115
it.property("neogradle.subsystems.decompiler.enabled", "false")
@@ -100,23 +122,13 @@ class AdvancedFmlTests extends BuilderBasedTestSpecification {
100122
}
101123

102124
then:
103-
run.task(':compileJava').outcome == TaskOutcome.NO_SOURCE
125+
run.task(':compileJava').outcome == TaskOutcome.SUCCESS
104126
run.task(":neoFormDecompile") == null
105127
}
106128

107129
def "a mod using a disabled decompiler should be able to run the game"() {
108130
given:
109-
def project = create("version_libs_runnable", {
110-
it.file("gradle/libs.versions.toml",
111-
"""
112-
[versions]
113-
# Neoforge Settings
114-
neoforge = "+"
115-
116-
[libraries]
117-
neoforge = { group = "net.neoforged", name = "neoforge", version.ref = "neoforge" }
118-
""".trim())
119-
131+
def project = create("disabled_decompiler_runs_game", {
120132
it.build("""
121133
java {
122134
toolchain {
@@ -129,9 +141,32 @@ class AdvancedFmlTests extends BuilderBasedTestSpecification {
129141
}
130142
131143
dependencies {
132-
implementation(libs.neoforge)
144+
implementation 'net.neoforged:neoforge:+'
133145
}
134146
""")
147+
148+
it.file("src/main/resources/META-INF/neoforge.mods.toml", """
149+
license="MIT"
150+
[[mods]]
151+
modId="neogradle_test"
152+
version="1.0"
153+
displayName="NeoGradle Test"
154+
description='''Test Mod for NeoGradle'''
155+
""".stripMargin())
156+
157+
it.file("src/main/java/net/neoforged/gradle/userdev/FunctionalTests.java", """
158+
package net.neoforged.gradle.userdev;
159+
160+
import net.minecraft.client.Minecraft;
161+
import net.neoforged.fml.common.Mod;
162+
163+
@Mod("neogradle_test")
164+
public class FunctionalTests {
165+
public FunctionalTests() {
166+
System.out.println(Minecraft.class.toString());
167+
}
168+
}
169+
""".stripMargin())
135170
it.withToolchains()
136171
it.withGlobalCacheDirectory(tempDir)
137172
it.property("neogradle.subsystems.decompiler.enabled", "false")
@@ -140,14 +175,12 @@ class AdvancedFmlTests extends BuilderBasedTestSpecification {
140175
when:
141176
def run = project.run {
142177
it.tasks(':runClientData')
143-
//We are expecting this test to fail, since there is a mod without any files included so it is fine.
144-
it.shouldFail()
145178
it.stacktrace()
146179
}
147180

148181
then:
149182
true
150-
run.output.contains("is not a valid mod file")
183+
run.output.contains("class net.minecraft.client.Minecraft")
151184
run.task(":neoFormDecompile") == null
152185
}
153186
}

userdev/src/main/java/net/neoforged/gradle/userdev/runtime/extension/UserDevRuntimeExtension.java

Lines changed: 33 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import net.neoforged.gradle.dsl.common.runs.run.RunManager;
1212
import net.neoforged.gradle.dsl.common.runs.type.RunTypeManager;
1313
import net.neoforged.gradle.dsl.common.runtime.tasks.Runtime;
14-
import net.neoforged.gradle.dsl.common.runtime.tasks.RuntimeArguments;
1514
import net.neoforged.gradle.dsl.common.runtime.tasks.tree.TaskTreeAdapter;
1615
import net.neoforged.gradle.dsl.common.tasks.WithOutput;
1716
import net.neoforged.gradle.dsl.common.util.CommonRuntimeUtils;
@@ -62,7 +61,8 @@ public UserDevRuntimeExtension(Project project)
6261
"AdditionalDependenciesFor" + spec.getIdentifier()
6362
);
6463

65-
if (!useCombinedJarWithNeoForgeOnRecompile(spec)) {
64+
if (!useCombinedJarWithNeoForgeOnRecompile(spec))
65+
{
6666
//Create the client-extra jar dependency.
6767
final Dependency clientExtraJar = spec.getProject().getDependencies().create(
6868
ExtraJarDependencyManager.generateClientCoordinateFor(spec.getMinecraftVersion())
@@ -72,7 +72,9 @@ public UserDevRuntimeExtension(Project project)
7272
userDevAdditionalDependenciesConfiguration.getDependencies().add(
7373
clientExtraJar
7474
);
75-
} else {
75+
}
76+
else
77+
{
7678
userDevAdditionalDependenciesConfiguration.getDependencies().addLater(
7779
userDevProfile.getUniversalJarArtifactCoordinate().map(spec.getProject().getDependencies()::create)
7880
);
@@ -92,7 +94,7 @@ public UserDevRuntimeExtension(Project project)
9294
builder.withNeoFormDependency(userDevProfile.getNeoForm().get())
9395
.withDistributionType(DistributionType.JOINED)
9496
.withAdditionalDependencies(getProject().files(userDevAdditionalDependenciesConfiguration))
95-
.withStepsMutator(this.adaptNeoFormRuntime(spec));
97+
.withStepsMutator(this.adaptNeoFormRuntime(spec, userDevProfile, userDevJar));
9698

9799
final FileTree accessTransformerFiles =
98100
userDevJar.matching(filter -> filter.include(userDevProfile.getAccessTransformerDirectory().get() + "/**"));
@@ -102,6 +104,7 @@ public UserDevRuntimeExtension(Project project)
102104
builder.withPostTaskAdapter("patch", createPatchAdapter(userDevJar, userDevProfile.getSourcePatchesDirectory().get()));
103105

104106
if (!useCombinedJarWithNeoForgeOnRecompile(spec))
107+
{
105108
builder.withTaskCustomizer("inject", InjectZipContent.class, task -> {
106109
FileTree injectionDirectoryTree;
107110
if (userDevProfile.getInjectedFilesDirectory().isPresent())
@@ -120,6 +123,7 @@ public UserDevRuntimeExtension(Project project)
120123
ConfigurationUtils.getArtifactProvider(getProject(), "NeoForgeRawLookupFor" + spec.getIdentifier(), userDevProfile.getUniversalJarArtifactCoordinate())
121124
);
122125
});
126+
}
123127
});
124128

125129
spec.setMinecraftVersion(neoFormRuntimeDefinition.getSpecification().getMinecraftVersion());
@@ -133,7 +137,10 @@ public UserDevRuntimeExtension(Project project)
133137
);
134138
}
135139

136-
private @NotNull BiConsumer<List<NeoFormConfigConfigurationSpecV1.Step>, Map<String, NeoFormConfigConfigurationSpecV1.Function>> adaptNeoFormRuntime(final UserDevRuntimeSpecification spec)
140+
private @NotNull BiConsumer<List<NeoFormConfigConfigurationSpecV1.Step>, Map<String, NeoFormConfigConfigurationSpecV1.Function>> adaptNeoFormRuntime(
141+
final UserDevRuntimeSpecification spec,
142+
final UserdevProfile userDevProfile,
143+
final FileTree userDevJar)
137144
{
138145
return (steps, functions) -> {
139146
if (!useCombinedJarWithNeoForgeOnRecompile(spec))
@@ -166,7 +173,11 @@ public UserDevRuntimeExtension(Project project)
166173
);
167174

168175
final Subsystems parchment = spec.getProject().getExtensions().getByType(Subsystems.class);
169-
final SetupConfiguration configuration = buildSetupConfiguration();
176+
final SetupConfiguration configuration = buildSetupConfiguration(
177+
spec,
178+
userDevProfile,
179+
userDevJar
180+
);
170181

171182
//Register the setup function:
172183
functions.put(
@@ -188,13 +199,15 @@ public UserDevRuntimeExtension(Project project)
188199
};
189200
}
190201

191-
private record SetupConfiguration(List<String> arguments, Map<String, String> values) {
192-
193-
}
202+
private record SetupConfiguration(
203+
List<String> arguments,
204+
Map<String, String> values) {}
194205

195-
private SetupConfiguration buildSetupConfiguration(UserDevRuntimeDefinition definition) {
206+
private SetupConfiguration buildSetupConfiguration(UserDevRuntimeSpecification spec, final UserdevProfile userDevProfile, final FileTree userDevJar)
207+
{
196208
final Decompiler decompilerSubsystemConfiguration = getProject().getExtensions().getByType(Subsystems.class).getDecompiler();
197-
if (decompilerSubsystemConfiguration.getIsDisabled().get() && useCombinedJarWithNeoForgeOnRecompile(definition.getSpecification())) {
209+
if (decompilerSubsystemConfiguration.getIsDisabled().get() && useCombinedJarWithNeoForgeOnRecompile(spec))
210+
{
198211
return new SetupConfiguration(
199212
List.of(
200213
"--task", "PROCESS_MINECRAFT_JAR",
@@ -210,7 +223,10 @@ private SetupConfiguration buildSetupConfiguration(UserDevRuntimeDefinition defi
210223
"clientMappings", "{downloadClientMappingsOutput}",
211224
"server", "{downloadServerOutput}",
212225
"neoform", "{neoform}",
213-
"patches", "{patches}"
226+
"patches", userDevProfile.getBinaryPatchFile()
227+
.map(patchFilePath -> userDevJar
228+
.matching(matcher -> matcher.include(patchFilePath))
229+
.getSingleFile()).get().getAbsolutePath()
214230
)
215231
);
216232
}
@@ -277,84 +293,17 @@ protected void afterRegistration(UserDevRuntimeDefinition runtime)
277293
);
278294
}
279295

280-
private void bakeDefinition(UserDevRuntimeDefinition definition) {
296+
private void bakeDefinition(UserDevRuntimeDefinition definition)
297+
{
281298
final Decompiler decompilerSubsystemConfiguration = this.getProject().getExtensions().getByType(Subsystems.class).getDecompiler();
282-
if (decompilerSubsystemConfiguration.getIsDisabled().get() && useCombinedJarWithNeoForgeOnRecompile(definition.getSpecification())) {
283-
final TaskProvider<? extends Runtime> binaryPatchedOutput = configureBinaryPatchMode(
284-
definition,
285-
definition.getNeoFormRuntimeDefinition().getTaskInputsByStepName(),
286-
definition.getNeoFormRuntimeDefinition().getBakedSteps()
287-
);
288-
289-
binaryPatchedOutput.configure(task -> {
290-
NeoFormRuntimeExtension.configureMcpRuntimeTaskWithDefaults(
291-
definition.getNeoFormRuntimeDefinition(),
292-
task,
293-
new NeoFormConfigConfigurationSpecV1.Step("binPatch", "binPatch", Map.of())
294-
);
295-
});
296-
299+
if (decompilerSubsystemConfiguration.getIsDisabled().get() && useCombinedJarWithNeoForgeOnRecompile(definition.getSpecification()))
300+
{
297301
definition.getNeoFormRuntimeDefinition().getRawJarTask().configure(task -> {
298-
task.getInput().set(binaryPatchedOutput.flatMap(WithOutput::getOutput));
302+
task.getInput().set(definition.getNeoFormRuntimeDefinition().getTask("setup").flatMap(WithOutput::getOutput));
299303
});
300304
}
301305
}
302306

303-
private TaskProvider<? extends Runtime> configureBinaryPatchMode(
304-
final UserDevRuntimeDefinition definition,
305-
final Map<String, Optional<TaskProvider<? extends WithOutput>>> taskInputsByStepName,
306-
final List<NeoFormConfigConfigurationSpecV1.Step> steps) {
307-
final NeoFormConfigConfigurationSpecV1.Step step = ListUtils.find(
308-
steps, s -> s.getType().equals("decompile")
309-
);
310-
if (step == null)
311-
throw new IllegalArgumentException("Could not find the decompile step!");
312-
final Provider<File> cleanFileProvider;
313-
Optional<TaskProvider<? extends WithOutput>> decompilerInputOptional = taskInputsByStepName.get("decompile");
314-
TaskProvider<? extends Runtime> decompileTask = definition.getSpecification().getProject().getTasks().named(
315-
CommonRuntimeUtils.buildTaskName(definition.getNeoFormRuntimeDefinition(), "decompile"),
316-
Runtime.class
317-
);
318-
if (decompilerInputOptional != null && decompilerInputOptional.isPresent()) {
319-
cleanFileProvider = decompilerInputOptional.get().flatMap(WithOutput::getOutput)
320-
.map(RegularFile::getAsFile);
321-
} else {
322-
cleanFileProvider = decompileTask.map(Runtime::getArguments)
323-
.flatMap(arguments -> arguments.get("input"))
324-
.map(File::new);
325-
}
326-
327-
return definition.getSpecification().getProject().getTasks().register(CommonRuntimeUtils.buildTaskName(definition.getSpecification(), "binaryPatch"), DefaultExecute.class, task -> {
328-
task.getExecutingJar().fileProvider(ToolUtilities.resolveTool(
329-
task.getProject(),
330-
definition.getUserdevConfiguration().getBinaryPatcher()
331-
.flatMap(UserdevProfile.ToolExecution::getTool)
332-
));
333-
task.getJvmArguments().addAll(
334-
definition.getUserdevConfiguration().getBinaryPatcher()
335-
.flatMap(UserdevProfile.ToolExecution::getJvmArguments)
336-
);
337-
task.getProgramArguments().addAll(
338-
definition.getUserdevConfiguration().getBinaryPatcher()
339-
.flatMap(UserdevProfile.ToolExecution::getArguments)
340-
);
341-
342-
task.getArguments().putFile(
343-
"clean",
344-
cleanFileProvider
345-
);
346-
task.getArguments().putFile(
347-
"patch",
348-
definition.getUserdevConfiguration().getBinaryPatchFile()
349-
.map(patchFilePath -> definition.getUnpackedUserDevJarDirectory()
350-
.matching(matcher -> matcher.include(patchFilePath))
351-
.getSingleFile())
352-
);
353-
});
354-
355-
}
356-
357-
358307
@Override
359308
protected UserDevRuntimeSpecification.Builder createBuilder()
360309
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
plugins {
2+
id 'net.neoforged.gradle.userdev'
3+
}
4+
5+
6+
java {
7+
toolchain {
8+
languageVersion = JavaLanguageVersion.of(21)
9+
}
10+
}
11+
12+
repositories {
13+
mavenCentral()
14+
}
15+
16+
dependencies {
17+
implementation 'net.neoforged:neoforge:+'
18+
}
19+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
neogradle.subsystems.decompiler.enabled=false
2+
net.neoforged.gradle.caching.cacheDirectory=/tmp/spock_a_mod_using_a_disab_0_tempDir6841875930781773787/.ng-cache
3+
org.gradle.console=rich
4+
org.gradle.jvmargs=-Xmx8000m
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#Disables File Watcher. Used to automatically update config if its file has been modified.
2+
disableConfigWatcher = false
3+
#Shows an early loading screen for mod loading which improves the user experience with early feedback about mod loading.
4+
earlyWindowControl = true
5+
#Max threads for early initialization parallelism, -1 is based on processor count
6+
maxThreads = -1
7+
#Enable NeoForge global version checking
8+
versionCheck = true
9+
#Enable synchronous OpenGL debug output and object labeling
10+
debugOpenGl = false
11+
#Default config path for servers
12+
defaultConfigPath = "defaultconfigs"
13+
#Disables Optimized DFU client-side - already disabled on servers
14+
disableOptimizedDFU = true
15+
#Early window provider
16+
earlyWindowProvider = "fmlearlywindow"
17+
#Early window width
18+
earlyWindowWidth = 854
19+
#Early window height
20+
earlyWindowHeight = 480
21+
#Early window starts maximized
22+
earlyWindowMaximized = false
23+
#Force a given theme-id to be used for the early loading screen
24+
earlyLoadingScreenTheme = ""
25+
#Define dependency overrides below
26+
#Dependency overrides can be used to forcibly remove a dependency constraint from a mod or to force a mod to load AFTER another mod
27+
#Using dependency overrides can cause issues. Use at your own risk.
28+
#Example dependency override for the mod with the id 'targetMod': dependency constraints (incompatibility clauses or restrictive version ranges) against mod 'dep1' are removed, and the mod will now load after the mod 'dep2'
29+
#dependencyOverrides.targetMod = ["-dep1", "+dep2"]
30+
dependencyOverrides = {}

0 commit comments

Comments
 (0)