Skip to content

Commit

Permalink
Implement support for split datagen (MC 1.21.4+) (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
Technici4n authored Nov 26, 2024
1 parent 703cf83 commit c32dc0b
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 20 deletions.
23 changes: 23 additions & 0 deletions src/main/java/net/neoforged/moddevgradle/dsl/RunModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,21 @@ public void client() {
getType().set("client");
}

/**
* Equivalent to setting {@code type = "clientData"}.
*
* <p>Should only be used for Minecraft versions starting from 1.21.4.
* (The first snapshot that supports this is 24w45a).
*/
public void clientData() {
getType().set("clientData");
}

/**
* Equivalent to setting {@code type = "data"}.
*
* <p>Should only be used for Minecraft versions up to 1.21.3 included.
* (The last snapshot that supports this is 24w44a).
*/
public void data() {
getType().set("data");
Expand All @@ -170,6 +183,16 @@ public void server() {
getType().set("server");
}

/**
* Equivalent to setting {@code type = "serverData"}.
*
* <p>Should only be used for Minecraft versions starting from 1.21.4.
* (The first snapshot that supports this is 24w45a).
*/
public void serverData() {
getType().set("serverData");
}

/**
* Equivalent to setting {@code ideName = ""}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ public void apply(Project project) {
userDevConfigOnly,
modulePath -> modulePath.getDependencies().addLater(modulePathDependency),
legacyClassPath -> legacyClassPath.extendsFrom(additionalClasspath),
downloadAssets.flatMap(DownloadAssets::getAssetPropertiesFile)
downloadAssets.flatMap(DownloadAssets::getAssetPropertiesFile),
extension.getNeoFormVersion()
);

setupJarJar(project);
Expand Down Expand Up @@ -478,7 +479,8 @@ static void setupRuns(Project project,
Object runTemplatesSourceFile,
Consumer<Configuration> configureModulePath,
Consumer<Configuration> configureLegacyClasspath,
Provider<RegularFile> assetPropertiesFile
Provider<RegularFile> assetPropertiesFile,
Provider<String> neoFormVersion
) {
var ideIntegration = IdeIntegration.of(project, branding);

Expand All @@ -499,7 +501,8 @@ static void setupRuns(Project project,
configureModulePath,
configureLegacyClasspath,
assetPropertiesFile,
devLaunchConfig
devLaunchConfig,
neoFormVersion
);
prepareRunTasks.put(run, prepareRunTask);
});
Expand All @@ -521,7 +524,8 @@ private static TaskProvider<PrepareRun> setupRunInGradle(
Consumer<Configuration> configureModulePath,
Consumer<Configuration> configureLegacyClasspath, // TODO: can be removed in favor of directly passing a configuration for the moddev libraries
Provider<RegularFile> assetPropertiesFile,
Configuration devLaunchConfig
Configuration devLaunchConfig,
Provider<String> neoFormVersion
) {
var ideIntegration = IdeIntegration.of(project, branding);
var configurations = project.getConfigurations();
Expand Down Expand Up @@ -553,7 +557,7 @@ private static TaskProvider<PrepareRun> setupRunInGradle(
spec.shouldResolveConsistentlyWith(runtimeClasspathConfig.get());
spec.attributes(attributes -> {
attributes.attributeProvider(MinecraftDistribution.ATTRIBUTE, type.map(t -> {
var name = t.equals("client") || t.equals("data") ? MinecraftDistribution.CLIENT : MinecraftDistribution.SERVER;
var name = t.equals("client") || t.equals("data") || t.equals("clientData") ? MinecraftDistribution.CLIENT : MinecraftDistribution.SERVER;
return project.getObjects().named(MinecraftDistribution.class, name);
}));
setNamedAttribute(project, attributes, Usage.USAGE_ATTRIBUTE, Usage.JAVA_RUNTIME);
Expand Down Expand Up @@ -590,6 +594,7 @@ private static TaskProvider<PrepareRun> setupRunInGradle(
task.getProgramArguments().set(run.getProgramArguments());
task.getJvmArguments().set(run.getJvmArguments());
task.getGameLogLevel().set(run.getLogLevel());
task.getNeoFormVersion().set(neoFormVersion);
});
ideIntegration.runTaskOnProjectSync(prepareRunTask);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,30 @@ public static void setupRuns(Project project,
runTemplatesSourceFile,
configureModulePath,
configureAdditionalClasspath,
assetPropertiesFile
assetPropertiesFile,
project.getObjects().property(String.class) // empty provider
);
}

public static void setupRuns(Project project,
Provider<Directory> argFileDir,
DomainObjectCollection<RunModel> runs,
Object runTemplatesSourceFile,
Consumer<Configuration> configureModulePath,
Consumer<Configuration> configureAdditionalClasspath,
Provider<RegularFile> assetPropertiesFile,
Provider<String> neoFormVersion
) {
ModDevPlugin.setupRuns(
project,
Branding.NEODEV,
argFileDir,
runs,
runTemplatesSourceFile,
configureModulePath,
configureAdditionalClasspath,
assetPropertiesFile,
neoFormVersion
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.neoforged.moddevgradle.internal.utils.FileUtils;
import net.neoforged.moddevgradle.internal.utils.OperatingSystem;
import net.neoforged.moddevgradle.internal.utils.StringUtils;
import net.neoforged.moddevgradle.internal.utils.VersionUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.DirectoryProperty;
Expand All @@ -28,6 +29,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -91,6 +93,14 @@ abstract class PrepareRunOrTest extends DefaultTask {
@Input
public abstract Property<Level> getGameLogLevel();

/**
* Only used when {@link #getRunTypeTemplatesSource()} is empty,
* to know whether the associated Minecraft version requires one or two data runs.
*/
@Optional
@Input
public abstract Property<String> getNeoFormVersion();

private final ProgramArgsFormat programArgsFormat;

protected PrepareRunOrTest(ProgramArgsFormat programArgsFormat) {
Expand Down Expand Up @@ -147,17 +157,32 @@ private UserDevConfig getSimulatedUserDevConfigForVanilla() {
var clientArgs = List.of("--gameDir", ".", "--assetIndex", "{asset_index}", "--assetsDir", "{assets_root}", "--accessToken", "NotValid", "--version", "ModDevGradle");
var commonArgs = List.<String>of();

return new UserDevConfig("", "", "", List.of(), List.of(), Map.of(
"client", new UserDevRunType(
true, "net.minecraft.client.main.Main", clientArgs, List.of(), true, false, false, false, Map.of(), Map.of()
),
"server", new UserDevRunType(
true, "net.minecraft.server.Main", commonArgs, List.of(), false, true, false, false, Map.of(), Map.of()
),
"data", new UserDevRunType(
true, "net.minecraft.data.Main", commonArgs, List.of(), false, false, true, false, Map.of(), Map.of()
)
var runTypes = new LinkedHashMap<String, UserDevRunType>();
runTypes.put("client", new UserDevRunType(
true, "net.minecraft.client.main.Main", clientArgs, List.of(), Map.of(), Map.of()
));
runTypes.put("server", new UserDevRunType(
true, "net.minecraft.server.Main", commonArgs, List.of(), Map.of(), Map.of()
));

var splitData = getNeoFormVersion()
.map(VersionUtils::hasSplitDataRuns)
.orElse(false) // Default to single run for backwards compatibility
.get();
if (splitData) {
runTypes.put("clientData", new UserDevRunType(
true, "net.minecraft.client.data.Main", commonArgs, List.of(), Map.of(), Map.of()
));
runTypes.put("serverData", new UserDevRunType(
true, "net.minecraft.data.Main", commonArgs, List.of(), Map.of(), Map.of()
));
} else {
runTypes.put("data", new UserDevRunType(
true, "net.minecraft.data.Main", commonArgs, List.of(), Map.of(), Map.of()
));
}

return new UserDevConfig(runTypes);
}

private void writeJvmArguments(UserDevRunType runConfig) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
import java.io.File;
import java.io.Serializable;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

public record UserDevConfig(String mcp, String sources, String universal, List<String> libraries, List<String> modules,
Map<String, UserDevRunType> runs) implements Serializable {
/**
* Sourced from the userdev config json. The run templates are the only thing that we use.
*/
public record UserDevConfig(Map<String, UserDevRunType> runs) implements Serializable {
public static UserDevConfig from(File userDevFile) {
try (var reader = Files.newBufferedReader(userDevFile.toPath())) {
return new Gson().fromJson(reader, UserDevConfig.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@
import java.util.Map;

public record UserDevRunType(boolean singleInstance, String main, List<String> args, List<String> jvmArgs,
boolean client, boolean server, boolean dataGenerator, boolean gameTest,
Map<String, String> env, Map<String, String> props) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.neoforged.moddevgradle.internal.utils;

import java.util.Objects;
import java.util.regex.Pattern;

public final class VersionUtils {
private VersionUtils() {}

private static final Pattern RELEASE_PATTERN = Pattern.compile("1\\.(\\d+)(?:.(\\d+))?(?:-.*)?$");

/**
* Checks whether the provided NeoForm version should have split client and server data runs.
*/
public static boolean hasSplitDataRuns(String neoFormVersion) {
// Snapshots starting from 24w45a
if (neoFormVersion.length() >= 5 && neoFormVersion.charAt(2) == 'w') {
try {
var year = Integer.parseInt(neoFormVersion.substring(0, 2));
var week = Integer.parseInt(neoFormVersion.substring(3, 5));

return year > 24 || (year == 24 && week >= 45);
} catch (NumberFormatException ignored) {}
}
// Releases starting from 1.21.4
var matcher = RELEASE_PATTERN.matcher(neoFormVersion);
if (matcher.find()) {
try {
int minor = Integer.parseInt(matcher.group(1));
// If there is no patch version, the second group has a null value
int patch = Integer.parseInt(Objects.requireNonNullElse(matcher.group(2), "0"));

return minor > 21 || (minor == 21 && patch >= 4);
} catch (NumberFormatException ignored) {}
}
// Assume other version patterns are newer and therefore split
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package net.neoforged.moddevgradle.internal;

import net.neoforged.moddevgradle.internal.utils.VersionUtils;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.assertj.core.api.Assertions.assertThat;

public class VersionUtilsTest {
@ParameterizedTest()
@CsvSource({
"1.21.4,true",
"1.21.4-pre1-20241120.190508,true",
"1.21.3,false",
"24w45a,true",
"24w44a,false",
"1.21.3-pre1,false",
"25w01a,true",
"23w07a,false",
"1.20,false",
"1.20-pre1,false",
"1.21,false",
"1.21-pre1-20240529.150918,false",
"1.21-pre1,false",
"1.22,true",
"1.22-pre1,true"
})
public void testSplitDataRunsCorrectness(String neoFormVersion, boolean splitDataRuns) {
assertThat(VersionUtils.hasSplitDataRuns(neoFormVersion))
.isEqualTo(splitDataRuns);
}

@ParameterizedTest
@CsvSource({
"1",
"1.",
"1.21.",
"test",
"24w",
"24w5",
"24w50",
"2aw50",
"24242",
})
public void testSplitDataRunsDoesNotCrash(String neoFormVersion) {
assertThat(VersionUtils.hasSplitDataRuns(neoFormVersion))
.isTrue();
}
}

0 comments on commit c32dc0b

Please sign in to comment.