Skip to content

Commit 9163863

Browse files
authored
Fix 1.20.4 compatibility (#212)
1 parent 383ac6a commit 9163863

File tree

9 files changed

+70
-64
lines changed

9 files changed

+70
-64
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"pack": {
3+
"description": {
4+
"text": "My Mod resources"
5+
},
6+
"pack_format": 18
7+
}
8+
}

src/legacy/java/net/neoforged/moddevgradle/internal/LegacyForgeFacade.java

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/legacy/java/net/neoforged/moddevgradle/legacyforge/internal/LegacyForgeModDevPlugin.java

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66
import net.neoforged.moddevgradle.internal.DataFileCollections;
77
import net.neoforged.moddevgradle.internal.ModdingDependencies;
88
import net.neoforged.moddevgradle.internal.jarjar.JarJarPlugin;
9-
import net.neoforged.moddevgradle.internal.LegacyForgeFacade;
109
import net.neoforged.moddevgradle.internal.ModDevArtifactsWorkflow;
1110
import net.neoforged.moddevgradle.internal.ModDevRunWorkflow;
1211
import net.neoforged.moddevgradle.internal.RepositoriesPlugin;
13-
import net.neoforged.moddevgradle.internal.WorkflowArtifact;
1412
import net.neoforged.moddevgradle.internal.utils.ExtensionUtils;
1513
import net.neoforged.moddevgradle.internal.utils.VersionCapabilitiesInternal;
1614
import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension;
@@ -33,7 +31,6 @@
3331
import org.slf4j.LoggerFactory;
3432

3533
import java.net.URI;
36-
import java.util.Map;
3734
import java.util.stream.Stream;
3835

3936
@ApiStatus.Internal
@@ -125,26 +122,16 @@ public void enable(Project project, LegacyForgeModdingSettings settings, LegacyF
125122
throw new InvalidUserCodeException("Specifying a Forge version is mutually exclusive with NeoForge or MCP");
126123
}
127124

128-
var artifactPrefix = "forge-" + forgeVersion;
129-
// We have to ensure that client resources are named "client-extra" and *do not* contain forge-<version>
130-
// otherwise FML might pick up the client resources as the main Minecraft jar.
131-
artifactNamingStrategy = (artifact) -> {
132-
if (artifact == WorkflowArtifact.CLIENT_RESOURCES) {
133-
return "client-extra-" + forgeVersion + ".jar";
134-
} else {
135-
return artifactPrefix + artifact.defaultSuffix + ".jar";
136-
}
137-
};
138-
139125
versionCapabilities = VersionCapabilitiesInternal.ofForgeVersion(forgeVersion);
126+
artifactNamingStrategy = ArtifactNamingStrategy.createNeoForge(versionCapabilities, "forge", forgeVersion);
140127

141128
String groupId = forgeVersion != null ? "net.minecraftforge" : "net.neoforged";
142129
var neoForge = depFactory.create(groupId + ":forge:" + forgeVersion);
143130
var neoForgeNotation = groupId + ":forge:" + forgeVersion + ":userdev";
144131
dependencies = ModdingDependencies.create(neoForge, neoForgeNotation, null, null, versionCapabilities);
145132
} else if (mcpVersion != null) {
146-
artifactNamingStrategy = ArtifactNamingStrategy.createDefault("vanilla-" + mcpVersion);
147133
versionCapabilities = VersionCapabilitiesInternal.ofMinecraftVersion(mcpVersion);
134+
artifactNamingStrategy = ArtifactNamingStrategy.createVanilla(mcpVersion);
148135

149136
var neoForm = depFactory.create("de.oceanlabs.mcp:mcp_config:" + mcpVersion);
150137
var neoFormNotation = "de.oceanlabs.mcp:mcp_config:" + mcpVersion + "@zip";
@@ -186,7 +173,8 @@ public void enable(Project project, LegacyForgeModdingSettings settings, LegacyF
186173
obf.getSrgToNamedMappings().set(mappingsCsv);
187174

188175
extension.getRuns().configureEach(run -> {
189-
LegacyForgeFacade.configureRun(project, run);
176+
// Old BSL versions before 2022 (i.e. on 1.18.2) did not export any packages, causing DevLaunch to be unable to access the main method
177+
run.getJvmArguments().addAll("--add-exports", "cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED");
190178

191179
// Mixin needs the intermediate (SRG) -> named (Mojang, MCP) mapping file in SRG (TSRG is not supported) to be able to ignore the refmaps of dependencies
192180
run.getSystemProperties().put("mixin.env.remapRefMap", "true");
@@ -206,13 +194,6 @@ public void enable(Project project, LegacyForgeModdingSettings settings, LegacyF
206194
artifacts.runtimeDependencies()
207195
.getDependencies().add(project.getDependencyFactory().create(project.files(mappingsCsv)));
208196

209-
// Forge expects to find the Forge and client-extra jar on the legacy classpath
210-
// Newer FML versions also search for it on the java.class.path.
211-
// MDG already adds cilent-extra, but the forge jar is missing.
212-
runs.getAdditionalClasspath()
213-
.extendsFrom(artifacts.runtimeDependencies())
214-
.exclude(Map.of("group", "net.neoforged", "module", "DevLaunch"));
215-
216197
var remapDeps = project.getConfigurations().create("remappingDependencies", spec -> {
217198
spec.setDescription("An internal configuration that contains the Minecraft dependencies, used for remapping mods");
218199
spec.setCanBeConsumed(false);

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
package net.neoforged.moddevgradle.internal;
22

3+
import net.neoforged.moddevgradle.internal.utils.VersionCapabilitiesInternal;
34
import org.jetbrains.annotations.ApiStatus;
45

56
@FunctionalInterface
67
@ApiStatus.Internal
78
public interface ArtifactNamingStrategy {
8-
static ArtifactNamingStrategy createDefault(String artifactFilenamePrefix) {
9+
static ArtifactNamingStrategy createVanilla(String version) {
910
return (artifact) -> {
10-
// It's helpful to be able to differentiate the Vanilla jar and the NeoForge jar in classic multiloader setups.
11-
return artifactFilenamePrefix + artifact.defaultSuffix + ".jar";
11+
return "vanilla-%s%s.jar".formatted(version, artifact.defaultSuffix);
12+
};
13+
}
14+
15+
static ArtifactNamingStrategy createNeoForge(VersionCapabilitiesInternal versionCapabilities, String loader, String version) {
16+
return (artifact) -> {
17+
if (artifact != WorkflowArtifact.CLIENT_RESOURCES || versionCapabilities.modLocatorRework()) {
18+
return "%s-%s%s.jar".formatted(loader, version, artifact.defaultSuffix);
19+
} else {
20+
// We have to ensure that client resources are named "client-extra" and *do not* contain forge-<version>
21+
// otherwise FML might pick up the client resources as the main Minecraft jar.
22+
return "client-extra-" + version + ".jar";
23+
}
1224
};
1325
}
1426

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
import org.gradle.api.Named;
1212
import org.gradle.api.Project;
1313
import org.gradle.api.artifacts.Configuration;
14+
import org.gradle.api.artifacts.Dependency;
1415
import org.gradle.api.artifacts.ModuleDependency;
1516
import org.gradle.api.attributes.Attribute;
1617
import org.gradle.api.attributes.AttributeContainer;
1718
import org.gradle.api.attributes.Category;
1819
import org.gradle.api.attributes.DocsType;
1920
import org.gradle.api.attributes.Usage;
20-
import org.gradle.api.file.ConfigurableFileCollection;
2121
import org.gradle.api.file.Directory;
2222
import org.gradle.api.file.RegularFile;
2323
import org.gradle.api.plugins.JavaPluginExtension;
@@ -44,6 +44,7 @@ public record ModDevArtifactsWorkflow(
4444
ModdingDependencies dependencies,
4545
VersionCapabilitiesInternal versionCapabilities,
4646
TaskProvider<CreateMinecraftArtifacts> createArtifacts,
47+
Provider<? extends Dependency> minecraftClassesDependency,
4748
TaskProvider<DownloadAssets> downloadAssets,
4849
Configuration runtimeDependencies,
4950
Configuration compileDependencies,
@@ -164,11 +165,11 @@ public static ModDevArtifactsWorkflow create(Project project,
164165

165166
// For IntelliJ, we attach a combined sources+classes artifact which enables an "Attach Sources..." link for IJ users
166167
// Otherwise, attaching sources is a pain for IJ users.
167-
Provider<ConfigurableFileCollection> minecraftClassesArtifact;
168+
Provider<? extends Dependency> minecraftClassesDependency;
168169
if (ideIntegration.shouldUseCombinedSourcesAndClassesArtifact()) {
169-
minecraftClassesArtifact = createArtifacts.map(task -> project.files(task.getCompiledWithSourcesArtifact()));
170+
minecraftClassesDependency = createArtifacts.map(task -> project.files(task.getCompiledWithSourcesArtifact())).map(dependencyFactory::create);
170171
} else {
171-
minecraftClassesArtifact = createArtifacts.map(task -> project.files(task.getCompiledArtifact()));
172+
minecraftClassesDependency = createArtifacts.map(task -> project.files(task.getCompiledArtifact())).map(dependencyFactory::create);
172173
}
173174

174175
// Name of the configuration in which we place the required dependencies to develop mods for use in the runtime-classpath.
@@ -178,7 +179,7 @@ public static ModDevArtifactsWorkflow create(Project project,
178179
config.setCanBeResolved(false);
179180
config.setCanBeConsumed(false);
180181

181-
config.getDependencies().addLater(minecraftClassesArtifact.map(dependencyFactory::create));
182+
config.getDependencies().addLater(minecraftClassesDependency);
182183
config.getDependencies().addLater(createArtifacts.map(task -> project.files(task.getResourcesArtifact())).map(dependencyFactory::create));
183184
// Technically, the Minecraft dependencies do not strictly need to be on the classpath because they are pulled from the legacy class path.
184185
// However, we do it anyway because this matches production environments, and allows launch proxies such as DevLogin to use Minecraft's libraries.
@@ -191,7 +192,7 @@ public static ModDevArtifactsWorkflow create(Project project,
191192
config.setDescription("The compile-time dependencies to develop a mod, including Minecraft and modding platform classes.");
192193
config.setCanBeResolved(false);
193194
config.setCanBeConsumed(false);
194-
config.getDependencies().addLater(minecraftClassesArtifact.map(dependencyFactory::create));
195+
config.getDependencies().addLater(minecraftClassesDependency);
195196
config.getDependencies().add(moddingDependencies.gameLibrariesDependency());
196197
});
197198

@@ -210,6 +211,7 @@ public static ModDevArtifactsWorkflow create(Project project,
210211
moddingDependencies,
211212
versionCapabilities,
212213
createArtifacts,
214+
minecraftClassesDependency,
213215
downloadAssets,
214216
runtimeDependencies,
215217
compileDependencies,

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,19 @@ public void enable(
7272
neoFormNotation = "net.neoforged:neoform:" + neoFormVersion + "@zip";
7373
}
7474

75-
// When a NeoForge version is specified, we use the dependencies published by that, and otherwise
76-
// we fall back to a potentially specified NeoForm version, which allows us to run in "Vanilla" mode.
75+
var versionCapabilities = neoForgeVersion != null ? VersionCapabilitiesInternal.ofNeoForgeVersion(neoForgeVersion)
76+
: VersionCapabilitiesInternal.ofNeoFormVersion(neoFormVersion);
77+
7778
ArtifactNamingStrategy artifactNamingStrategy;
79+
// It's helpful to be able to differentiate the Vanilla jar and the NeoForge jar in classic multiloader setups.
7880
if (neoForge != null) {
79-
artifactNamingStrategy = ArtifactNamingStrategy.createDefault("neoforge-" + neoForgeVersion);
81+
artifactNamingStrategy = ArtifactNamingStrategy.createNeoForge(versionCapabilities, "neoforge", neoForgeVersion);
8082
} else {
81-
artifactNamingStrategy = ArtifactNamingStrategy.createDefault("vanilla-" + neoFormVersion);
83+
artifactNamingStrategy = ArtifactNamingStrategy.createVanilla(neoFormVersion);
8284
}
8385

8486
var configurations = project.getConfigurations();
8587

86-
var versionCapabilities = neoForgeVersion != null ? VersionCapabilitiesInternal.ofNeoForgeVersion(neoForgeVersion)
87-
: VersionCapabilitiesInternal.ofNeoFormVersion(neoFormVersion);
8888

8989
var dependencies = neoForge != null ? ModdingDependencies.create(neoForge, neoForgeNotation, neoForm, neoFormNotation, versionCapabilities)
9090
: ModdingDependencies.createVanillaOnly(neoForm, neoFormNotation);

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ private ModDevRunWorkflow(Project project,
105105

106106
spec.getDependencies().add(gameLibrariesDependency);
107107
addClientResources(project, spec, artifactsWorkflow.createArtifacts());
108+
if (!versionCapabilities.modLocatorRework()) {
109+
// Forge expects to find the Forge and client-extra jar on the legacy classpath
110+
// Newer FML versions also search for it on the java.class.path.
111+
spec.getDependencies().addLater(artifactsWorkflow.minecraftClassesDependency());
112+
}
108113
});
109114

110115
setupRuns(
@@ -242,6 +247,11 @@ public static void setupRuns(
242247

243248
Map<RunModel, TaskProvider<PrepareRun>> prepareRunTasks = new IdentityHashMap<>();
244249
runs.all(run -> {
250+
if (!versionCapabilities.modLocatorRework()) {
251+
// TODO: do this properly now that we have a flag in the version capabilities
252+
// This will explicitly be replaced in RunUtils to make this work for IDEs
253+
run.getEnvironment().put("MOD_CLASSES", RunUtils.getGradleModFoldersProvider(project, run.getLoadedMods(), null).getClassesArgument());
254+
}
245255
var prepareRunTask = setupRunInGradle(
246256
project,
247257
branding,

src/main/java/net/neoforged/moddevgradle/internal/utils/VersionCapabilitiesInternal.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,17 @@
1717
* @param testFixtures If the NeoForge version for this Minecraft version supports test fixtures.
1818
*/
1919
public record VersionCapabilitiesInternal(String minecraftVersion, int javaVersion, boolean splitDataRuns,
20-
boolean testFixtures) implements VersionCapabilities, Serializable {
20+
boolean testFixtures, boolean modLocatorRework) implements VersionCapabilities, Serializable {
2121
private static final Logger LOG = LoggerFactory.getLogger(VersionCapabilitiesInternal.class);
2222

23-
private static final VersionCapabilitiesInternal LATEST = new VersionCapabilitiesInternal(MinecraftVersionList.VERSIONS.get(0), 21, true, true);
23+
private static final VersionCapabilitiesInternal LATEST = ofVersionIndex(0);
2424

2525
private static final Pattern NEOFORGE_PATTERN = Pattern.compile("^(\\d+\\.\\d+)\\.\\d+(|-.*)$");
2626
// Strips NeoForm timestamp suffixes OR dynamic version markers
2727
private static final Pattern NEOFORM_PATTERN = Pattern.compile("^(.*)-(?:\\+|\\d{8}\\.\\d{6})$");
2828

2929
private static final int MC_24W45A_INDEX = getReferenceVersionIndex("24w45a");
30+
private static final int MC_1_20_5_INDEX = getReferenceVersionIndex("1.20.5");
3031
private static final int MC_24W14A_INDEX = getReferenceVersionIndex("24w14a");
3132
private static final int MC_1_20_4_INDEX = getReferenceVersionIndex("1.20.4");
3233
private static final int MC_1_18_PRE2_INDEX = getReferenceVersionIndex("1.18-pre2");
@@ -55,8 +56,9 @@ public static VersionCapabilitiesInternal ofVersionIndex(int versionIndex, Strin
5556
var javaVersion = getJavaVersion(versionIndex);
5657
var splitData = hasSplitDataEntrypoints(versionIndex);
5758
var testFixtures = hasTestFixtures(versionIndex);
59+
var modLocatorRework = hasModLocatorRework(versionIndex);
5860

59-
return new VersionCapabilitiesInternal(minecraftVersion, javaVersion, splitData, testFixtures);
61+
return new VersionCapabilitiesInternal(minecraftVersion, javaVersion, splitData, testFixtures, modLocatorRework);
6062
}
6163

6264
static int getJavaVersion(int versionIndex) {
@@ -79,6 +81,10 @@ static boolean hasTestFixtures(int versionIndex) {
7981
return versionIndex <= MC_1_20_4_INDEX;
8082
}
8183

84+
static boolean hasModLocatorRework(int versionIndex) {
85+
return versionIndex <= MC_1_20_5_INDEX;
86+
}
87+
8288
static int indexOfNeoForgeVersion(String version) {
8389
// NeoForge omits the "1." at the start of the Minecraft version and just adds an incrementing last digit
8490
var matcher = NEOFORGE_PATTERN.matcher(version);
@@ -162,7 +168,8 @@ public VersionCapabilitiesInternal withMinecraftVersion(String minecraftVersion)
162168
minecraftVersion,
163169
javaVersion,
164170
splitDataRuns,
165-
testFixtures
171+
testFixtures,
172+
modLocatorRework
166173
);
167174
}
168175
}

src/test/java/net/neoforged/moddevgradle/internal/ModDevPluginTest.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void testModdingCannotBeEnabledTwice() {
4949
@Test
5050
void testEnableForTestSourceSetOnly() {
5151
extension.enable(settings -> {
52-
settings.setVersion("2.3.0");
52+
settings.setVersion("100.3.0"); // Needs to be at least 20.5 to use paths for newer FML
5353
settings.setEnabledSourceSets(Set.of(testSourceSet));
5454
});
5555

@@ -58,25 +58,25 @@ void testEnableForTestSourceSetOnly() {
5858
assertThatDependencies(mainSourceSet.getRuntimeClasspathConfigurationName()).isEmpty();
5959

6060
// While the test classpath should have modding dependencies
61-
assertContainsModdingCompileDependencies("2.3.0", testSourceSet.getCompileClasspathConfigurationName());
62-
assertContainsModdingRuntimeDependencies("2.3.0", testSourceSet.getRuntimeClasspathConfigurationName());
61+
assertContainsModdingCompileDependencies("100.3.0", testSourceSet.getCompileClasspathConfigurationName());
62+
assertContainsModdingRuntimeDependencies("100.3.0", testSourceSet.getRuntimeClasspathConfigurationName());
6363
}
6464

6565
@Test
6666
void testAddModdingDependenciesTo() {
67-
extension.setVersion("2.3.0");
67+
extension.setVersion("100.3.0"); // Needs to be at least 20.5 to use paths for newer FML
6868

6969
// Initially, only the main source set should have the dependencies
70-
assertContainsModdingCompileDependencies("2.3.0", mainSourceSet.getCompileClasspathConfigurationName());
71-
assertContainsModdingRuntimeDependencies("2.3.0", mainSourceSet.getRuntimeClasspathConfigurationName());
70+
assertContainsModdingCompileDependencies("100.3.0", mainSourceSet.getCompileClasspathConfigurationName());
71+
assertContainsModdingRuntimeDependencies("100.3.0", mainSourceSet.getRuntimeClasspathConfigurationName());
7272
assertThatDependencies(testSourceSet.getCompileClasspathConfigurationName()).isEmpty();
7373
assertThatDependencies(testSourceSet.getRuntimeClasspathConfigurationName()).isEmpty();
7474

7575
// Now add it to the test source set too
7676
extension.addModdingDependenciesTo(testSourceSet);
7777

78-
assertContainsModdingCompileDependencies("2.3.0", testSourceSet.getCompileClasspathConfigurationName());
79-
assertContainsModdingRuntimeDependencies("2.3.0", testSourceSet.getRuntimeClasspathConfigurationName());
78+
assertContainsModdingCompileDependencies("100.3.0", testSourceSet.getCompileClasspathConfigurationName());
79+
assertContainsModdingRuntimeDependencies("100.3.0", testSourceSet.getRuntimeClasspathConfigurationName());
8080
}
8181

8282
@Test

0 commit comments

Comments
 (0)