Skip to content

Commit de7ec3c

Browse files
committed
Implement support for split datagen (MC 1.21.4+) (#187)
1 parent 6c63e9c commit de7ec3c

File tree

7 files changed

+151
-15
lines changed

7 files changed

+151
-15
lines changed

src/main/java/net/neoforged/moddevgradle/dsl/RunModel.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,21 @@ public void client() {
154154
getType().set("client");
155155
}
156156

157+
/**
158+
* Equivalent to setting {@code type = "clientData"}.
159+
*
160+
* <p>Should only be used for Minecraft versions starting from 1.21.4.
161+
* (The first snapshot that supports this is 24w45a).
162+
*/
163+
public void clientData() {
164+
getType().set("clientData");
165+
}
166+
157167
/**
158168
* Equivalent to setting {@code type = "data"}.
169+
*
170+
* <p>Should only be used for Minecraft versions up to 1.21.3 included.
171+
* (The last snapshot that supports this is 24w44a).
159172
*/
160173
public void data() {
161174
getType().set("data");
@@ -168,6 +181,16 @@ public void server() {
168181
getType().set("server");
169182
}
170183

184+
/**
185+
* Equivalent to setting {@code type = "serverData"}.
186+
*
187+
* <p>Should only be used for Minecraft versions starting from 1.21.4.
188+
* (The first snapshot that supports this is 24w45a).
189+
*/
190+
public void serverData() {
191+
getType().set("serverData");
192+
}
193+
171194
/**
172195
* Gets the Gradle tasks that should be run before running this run.
173196
*/

src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ public void apply(Project project) {
364364
spec.setCanBeConsumed(false);
365365
spec.shouldResolveConsistentlyWith(runtimeClasspathConfig.get());
366366
spec.attributes(attributes -> {
367-
attributes.attributeProvider(ATTRIBUTE_DISTRIBUTION, type.map(t -> t.equals("client") || t.equals("data") ? "client" : "server"));
367+
attributes.attributeProvider(ATTRIBUTE_DISTRIBUTION, type.map(t -> t.equals("client") || t.equals("data") || t.equals("clientData") ? "client" : "server"));
368368
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME));
369369
});
370370
spec.withDependencies(set -> {
@@ -402,6 +402,7 @@ public void apply(Project project) {
402402
task.getProgramArguments().set(run.getProgramArguments());
403403
task.getJvmArguments().set(run.getJvmArguments());
404404
task.getGameLogLevel().set(run.getLogLevel());
405+
task.getNeoFormVersion().set(extension.getNeoFormVersion());
405406
task.dependsOn(run.getTasksBefore());
406407
});
407408
prepareRunTasks.put(run, prepareRunTask);

src/main/java/net/neoforged/moddevgradle/internal/PrepareRunOrTest.java

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import net.neoforged.moddevgradle.internal.utils.FileUtils;
44
import net.neoforged.moddevgradle.internal.utils.OperatingSystem;
55
import net.neoforged.moddevgradle.internal.utils.StringUtils;
6+
import net.neoforged.moddevgradle.internal.utils.VersionUtils;
67
import org.gradle.api.DefaultTask;
78
import org.gradle.api.file.ConfigurableFileCollection;
89
import org.gradle.api.file.DirectoryProperty;
@@ -28,6 +29,7 @@
2829
import java.nio.charset.StandardCharsets;
2930
import java.nio.file.Files;
3031
import java.util.ArrayList;
32+
import java.util.LinkedHashMap;
3133
import java.util.List;
3234
import java.util.Map;
3335
import java.util.Objects;
@@ -82,6 +84,14 @@ abstract class PrepareRunOrTest extends DefaultTask {
8284
@Input
8385
public abstract Property<Level> getGameLogLevel();
8486

87+
/**
88+
* Only used when {@link #getRunTypeTemplatesSource()} is empty,
89+
* to know whether the associated Minecraft version requires one or two data runs.
90+
*/
91+
@Optional
92+
@Input
93+
public abstract Property<String> getNeoFormVersion();
94+
8595
private final ProgramArgsFormat programArgsFormat;
8696

8797
protected PrepareRunOrTest(ProgramArgsFormat programArgsFormat) {
@@ -138,17 +148,32 @@ private UserDevConfig getSimulatedUserDevConfigForVanilla() {
138148
var clientArgs = List.of("--gameDir", ".", "--assetIndex", "{asset_index}", "--assetsDir", "{assets_root}", "--accessToken", "NotValid", "--version", "ModDevGradle");
139149
var commonArgs = List.<String>of();
140150

141-
return new UserDevConfig("", "", "", List.of(), List.of(), Map.of(
142-
"client", new UserDevRunType(
143-
true, "net.minecraft.client.main.Main", clientArgs, List.of(), true, false, false, false, Map.of(), Map.of()
144-
),
145-
"server", new UserDevRunType(
146-
true, "net.minecraft.server.Main", commonArgs, List.of(), false, true, false, false, Map.of(), Map.of()
147-
),
148-
"data", new UserDevRunType(
149-
true, "net.minecraft.data.Main", commonArgs, List.of(), false, false, true, false, Map.of(), Map.of()
150-
)
151+
var runTypes = new LinkedHashMap<String, UserDevRunType>();
152+
runTypes.put("client", new UserDevRunType(
153+
true, "net.minecraft.client.main.Main", clientArgs, List.of(), Map.of(), Map.of()
151154
));
155+
runTypes.put("server", new UserDevRunType(
156+
true, "net.minecraft.server.Main", commonArgs, List.of(), Map.of(), Map.of()
157+
));
158+
159+
var splitData = getNeoFormVersion()
160+
.map(VersionUtils::hasSplitDataRuns)
161+
.orElse(false) // Default to single run for backwards compatibility
162+
.get();
163+
if (splitData) {
164+
runTypes.put("clientData", new UserDevRunType(
165+
true, "net.minecraft.client.data.Main", commonArgs, List.of(), Map.of(), Map.of()
166+
));
167+
runTypes.put("serverData", new UserDevRunType(
168+
true, "net.minecraft.data.Main", commonArgs, List.of(), Map.of(), Map.of()
169+
));
170+
} else {
171+
runTypes.put("data", new UserDevRunType(
172+
true, "net.minecraft.data.Main", commonArgs, List.of(), Map.of(), Map.of()
173+
));
174+
}
175+
176+
return new UserDevConfig(runTypes);
152177
}
153178

154179
private void writeJvmArguments(UserDevRunType runConfig) throws IOException {

src/main/java/net/neoforged/moddevgradle/internal/UserDevConfig.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
import java.io.File;
77
import java.io.Serializable;
88
import java.nio.file.Files;
9-
import java.util.List;
109
import java.util.Map;
1110

12-
public record UserDevConfig(String mcp, String sources, String universal, List<String> libraries, List<String> modules,
13-
Map<String, UserDevRunType> runs) implements Serializable {
11+
/**
12+
* Sourced from the userdev config json. The run templates are the only thing that we use.
13+
*/
14+
public record UserDevConfig(Map<String, UserDevRunType> runs) implements Serializable {
1415
public static UserDevConfig from(File userDevFile) {
1516
try (var reader = Files.newBufferedReader(userDevFile.toPath())) {
1617
return new Gson().fromJson(reader, UserDevConfig.class);

src/main/java/net/neoforged/moddevgradle/internal/UserDevRunType.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@
44
import java.util.Map;
55

66
public record UserDevRunType(boolean singleInstance, String main, List<String> args, List<String> jvmArgs,
7-
boolean client, boolean server, boolean dataGenerator, boolean gameTest,
87
Map<String, String> env, Map<String, String> props) {
98
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package net.neoforged.moddevgradle.internal.utils;
2+
3+
import java.util.Objects;
4+
import java.util.regex.Pattern;
5+
6+
public final class VersionUtils {
7+
private VersionUtils() {}
8+
9+
private static final Pattern RELEASE_PATTERN = Pattern.compile("1\\.(\\d+)(?:.(\\d+))?(?:-.*)?$");
10+
11+
/**
12+
* Checks whether the provided NeoForm version should have split client and server data runs.
13+
*/
14+
public static boolean hasSplitDataRuns(String neoFormVersion) {
15+
// Snapshots starting from 24w45a
16+
if (neoFormVersion.length() >= 5 && neoFormVersion.charAt(2) == 'w') {
17+
try {
18+
var year = Integer.parseInt(neoFormVersion.substring(0, 2));
19+
var week = Integer.parseInt(neoFormVersion.substring(3, 5));
20+
21+
return year > 24 || (year == 24 && week >= 45);
22+
} catch (NumberFormatException ignored) {}
23+
}
24+
// Releases starting from 1.21.4
25+
var matcher = RELEASE_PATTERN.matcher(neoFormVersion);
26+
if (matcher.find()) {
27+
try {
28+
int minor = Integer.parseInt(matcher.group(1));
29+
// If there is no patch version, the second group has a null value
30+
int patch = Integer.parseInt(Objects.requireNonNullElse(matcher.group(2), "0"));
31+
32+
return minor > 21 || (minor == 21 && patch >= 4);
33+
} catch (NumberFormatException ignored) {}
34+
}
35+
// Assume other version patterns are newer and therefore split
36+
return true;
37+
}
38+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package net.neoforged.moddevgradle.internal;
2+
3+
import net.neoforged.moddevgradle.internal.utils.VersionUtils;
4+
import org.junit.jupiter.params.ParameterizedTest;
5+
import org.junit.jupiter.params.provider.CsvSource;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
9+
public class VersionUtilsTest {
10+
@ParameterizedTest()
11+
@CsvSource({
12+
"1.21.4,true",
13+
"1.21.4-pre1-20241120.190508,true",
14+
"1.21.3,false",
15+
"24w45a,true",
16+
"24w44a,false",
17+
"1.21.3-pre1,false",
18+
"25w01a,true",
19+
"23w07a,false",
20+
"1.20,false",
21+
"1.20-pre1,false",
22+
"1.21,false",
23+
"1.21-pre1-20240529.150918,false",
24+
"1.21-pre1,false",
25+
"1.22,true",
26+
"1.22-pre1,true"
27+
})
28+
public void testSplitDataRunsCorrectness(String neoFormVersion, boolean splitDataRuns) {
29+
assertThat(VersionUtils.hasSplitDataRuns(neoFormVersion))
30+
.isEqualTo(splitDataRuns);
31+
}
32+
33+
@ParameterizedTest
34+
@CsvSource({
35+
"1",
36+
"1.",
37+
"1.21.",
38+
"test",
39+
"24w",
40+
"24w5",
41+
"24w50",
42+
"2aw50",
43+
"24242",
44+
})
45+
public void testSplitDataRunsDoesNotCrash(String neoFormVersion) {
46+
assertThat(VersionUtils.hasSplitDataRuns(neoFormVersion))
47+
.isTrue();
48+
}
49+
}

0 commit comments

Comments
 (0)