@@ -59,7 +59,6 @@ public class ModDevRunWorkflow {
5959 @ Nullable
6060 private final ModuleDependency testFixturesDependency ;
6161 private final ModuleDependency gameLibrariesDependency ;
62- private final Configuration additionalClasspath ;
6362 private final Configuration userDevConfigOnly ;
6463
6564 /**
@@ -97,19 +96,32 @@ private ModDevRunWorkflow(Project project,
9796 }
9897 });
9998
100- additionalClasspath = configurations .create ("additionalRuntimeClasspath" , spec -> {
101- spec .setDescription ("Contains dependencies of every run, that should not be considered boot classpath modules." );
102- spec .setCanBeResolved (true );
103- spec .setCanBeConsumed (false );
104-
105- spec .getDependencies ().add (gameLibrariesDependency );
106- addClientResources (project , spec , artifactsWorkflow .createArtifacts ());
107- if (!versionCapabilities .modLocatorRework ()) {
108- // Forge expects to find the Forge and client-extra jar on the legacy classpath
109- // Newer FML versions also search for it on the java.class.path.
110- spec .getDependencies ().addLater (artifactsWorkflow .minecraftClassesDependency ());
111- }
112- });
99+ Consumer <Configuration > configureLegacyClasspath ;
100+ if (versionCapabilities .legacyClasspath ()) {
101+ var additionalClasspath = configurations .create ("additionalRuntimeClasspath" , spec -> {
102+ spec .setDescription ("Contains dependencies of every run, that should not be considered boot classpath modules." );
103+ spec .setCanBeResolved (true );
104+ spec .setCanBeConsumed (false );
105+
106+ spec .getDependencies ().add (gameLibrariesDependency );
107+ 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+ }
113+ });
114+ configureLegacyClasspath = legacyClassPath -> legacyClassPath .extendsFrom (additionalClasspath );
115+ } else {
116+ // Create the configuration but disallow adding anything to it, to notify users about potential mistakes.
117+ // We might decide to remove it entirely in the future
118+ var additionalClasspath = configurations .create ("additionalRuntimeClasspath" );
119+ forbidAdditionalRuntimeDependencies (additionalClasspath , versionCapabilities );
120+
121+ configureLegacyClasspath = legacyClassPath -> {
122+ throw new IllegalStateException ("There is no legacy classpath for Minecraft " + versionCapabilities .minecraftVersion ());
123+ };
124+ }
113125
114126 setupRuns (
115127 project ,
@@ -122,11 +134,24 @@ private ModDevRunWorkflow(Project project,
122134 modulePath .getDependencies ().add (modulePathDependency );
123135 }
124136 },
125- legacyClassPath -> legacyClassPath . extendsFrom ( additionalClasspath ) ,
137+ configureLegacyClasspath ,
126138 artifactsWorkflow .downloadAssets ().flatMap (DownloadAssets ::getAssetPropertiesFile ),
127139 versionCapabilities );
128140 }
129141
142+ private static void forbidAdditionalRuntimeDependencies (Configuration configuration , VersionCapabilitiesInternal versionCapabilities ) {
143+ // We cannot use withDependencies() since the configuration should never get resolved,
144+ // but we want to inform the user anyway.
145+ configuration .getDependencies ().all (dependency -> {
146+ throw new IllegalStateException (String .format (
147+ "Tried to add a dependency to configuration %s, but there is no additional classpath anymore for Minecraft %s. "
148+ + "Add the dependency to a standard configuration such as implementation or runtimeOnly. Dependency: %s" ,
149+ configuration ,
150+ versionCapabilities .minecraftVersion (),
151+ dependency ));
152+ });
153+ }
154+
130155 public static ModDevRunWorkflow get (Project project ) {
131156 var workflow = ExtensionUtils .findExtension (project , EXTENSION_NAME , ModDevRunWorkflow .class );
132157 if (workflow == null ) {
@@ -198,7 +223,8 @@ public void configureTesting(Provider<ModModel> testedMod, Provider<Set<ModModel
198223 legacyClassPath .getDependencies ().add (gameLibrariesDependency );
199224 addClientResources (project , legacyClassPath , artifactsWorkflow .createArtifacts ());
200225 },
201- artifactsWorkflow .downloadAssets ().flatMap (DownloadAssets ::getAssetPropertiesFile ));
226+ artifactsWorkflow .downloadAssets ().flatMap (DownloadAssets ::getAssetPropertiesFile ),
227+ artifactsWorkflow .versionCapabilities ());
202228 }
203229 }
204230
@@ -302,28 +328,36 @@ private static TaskProvider<PrepareRun> setupRunInGradle(
302328 configureModulePath .accept (spec );
303329 });
304330
305- var legacyClasspathConfiguration = configurations .create (InternalModelHelper .nameOfRun (run , "" , "legacyClasspath" ), spec -> {
306- spec .setDescription ("Contains all dependencies of the " + run .getName () + " run that should not be considered boot classpath modules." );
307- spec .setCanBeResolved (true );
308- spec .setCanBeConsumed (false );
309- spec .shouldResolveConsistentlyWith (runtimeClasspathConfig .get ());
310- spec .attributes (attributes -> {
311- attributes .attributeProvider (MinecraftDistribution .ATTRIBUTE , type .map (t -> {
312- var name = t .equals ("client" ) || t .equals ("data" ) || t .equals ("clientData" ) ? MinecraftDistribution .CLIENT : MinecraftDistribution .SERVER ;
313- return project .getObjects ().named (MinecraftDistribution .class , name );
314- }));
315- setNamedAttribute (project , attributes , Usage .USAGE_ATTRIBUTE , Usage .JAVA_RUNTIME );
331+ Provider <RegularFile > legacyClasspathFile ;
332+ if (versionCapabilities .legacyClasspath ()) {
333+ var legacyClasspathConfiguration = configurations .create (InternalModelHelper .nameOfRun (run , "" , "legacyClasspath" ), spec -> {
334+ spec .setDescription ("Contains all dependencies of the " + run .getName () + " run that should not be considered boot classpath modules." );
335+ spec .setCanBeResolved (true );
336+ spec .setCanBeConsumed (false );
337+ spec .shouldResolveConsistentlyWith (runtimeClasspathConfig .get ());
338+ spec .attributes (attributes -> {
339+ attributes .attributeProvider (MinecraftDistribution .ATTRIBUTE , type .map (t -> {
340+ var name = t .equals ("client" ) || t .equals ("data" ) || t .equals ("clientData" ) ? MinecraftDistribution .CLIENT : MinecraftDistribution .SERVER ;
341+ return project .getObjects ().named (MinecraftDistribution .class , name );
342+ }));
343+ setNamedAttribute (project , attributes , Usage .USAGE_ATTRIBUTE , Usage .JAVA_RUNTIME );
344+ });
345+ configureLegacyClasspath .accept (spec );
346+ spec .extendsFrom (run .getAdditionalRuntimeClasspathConfiguration ());
316347 });
317- configureLegacyClasspath .accept (spec );
318- spec .extendsFrom (run .getAdditionalRuntimeClasspathConfiguration ());
319- });
320348
321- var writeLcpTask = tasks .register (InternalModelHelper .nameOfRun (run , "write" , "legacyClasspath" ), WriteLegacyClasspath .class , writeLcp -> {
322- writeLcp .setGroup (branding .internalTaskGroup ());
323- writeLcp .setDescription ("Writes the legacyClasspath file for the " + run .getName () + " Minecraft run, containing all dependencies that shouldn't be considered boot modules." );
324- writeLcp .getLegacyClasspathFile ().set (argFileDir .map (dir -> dir .file (InternalModelHelper .nameOfRun (run , "" , "legacyClasspath" ) + ".txt" )));
325- writeLcp .addEntries (legacyClasspathConfiguration );
326- });
349+ var writeLcpTask = tasks .register (InternalModelHelper .nameOfRun (run , "write" , "legacyClasspath" ), WriteLegacyClasspath .class , writeLcp -> {
350+ writeLcp .setGroup (branding .internalTaskGroup ());
351+ writeLcp .setDescription ("Writes the legacyClasspath file for the " + run .getName () + " Minecraft run, containing all dependencies that shouldn't be considered boot modules." );
352+ writeLcp .getLegacyClasspathFile ().set (argFileDir .map (dir -> dir .file (InternalModelHelper .nameOfRun (run , "" , "legacyClasspath" ) + ".txt" )));
353+ writeLcp .addEntries (legacyClasspathConfiguration );
354+ });
355+ legacyClasspathFile = writeLcpTask .get ().getLegacyClasspathFile ();
356+ } else {
357+ // Disallow adding dependencies to the additional classpath configuration since it would have no effect.
358+ forbidAdditionalRuntimeDependencies (run .getAdditionalRuntimeClasspathConfiguration (), versionCapabilities );
359+ legacyClasspathFile = null ;
360+ }
327361
328362 var prepareRunTask = tasks .register (InternalModelHelper .nameOfRun (run , "prepare" , "run" ), PrepareRun .class , task -> {
329363 task .setGroup (branding .internalTaskGroup ());
@@ -337,7 +371,9 @@ private static TaskProvider<PrepareRun> setupRunInGradle(
337371 task .getRunType ().set (run .getType ());
338372 task .getRunTypeTemplatesSource ().from (runTemplatesFile );
339373 task .getModules ().from (modulePathConfiguration );
340- task .getLegacyClasspathFile ().set (writeLcpTask .get ().getLegacyClasspathFile ());
374+ if (legacyClasspathFile != null ) {
375+ task .getLegacyClasspathFile ().set (legacyClasspathFile );
376+ }
341377 task .getAssetProperties ().set (assetPropertiesFile );
342378 task .getSystemProperties ().set (run .getSystemProperties ().map (props -> {
343379 props = new HashMap <>(props );
@@ -405,7 +441,8 @@ static void setupTestTask(Project project,
405441 Provider <Directory > argFileDir ,
406442 Consumer <Configuration > configureModulePath ,
407443 Consumer <Configuration > configureLegacyClasspath ,
408- Provider <RegularFile > assetPropertiesFile ) {
444+ Provider <RegularFile > assetPropertiesFile ,
445+ VersionCapabilitiesInternal versionCapabilities ) {
409446 var gameDirectory = new File (project .getProjectDir (), JUNIT_GAME_DIR );
410447
411448 var ideIntegration = IdeIntegration .of (project , branding );
@@ -423,27 +460,33 @@ static void setupTestTask(Project project,
423460 configureModulePath .accept (spec );
424461 });
425462
426- var legacyClasspathConfiguration = configurations .create ("neoForgeTestLibraries" , spec -> {
427- spec .setDescription ("Contains the legacy classpath of unit tests." );
428- spec .setCanBeResolved (true );
429- spec .setCanBeConsumed (false );
430- spec .shouldResolveConsistentlyWith (testRuntimeClasspath );
431- spec .attributes (attributes -> {
432- setNamedAttribute (project , attributes , MinecraftDistribution .ATTRIBUTE , MinecraftDistribution .CLIENT );
433- setNamedAttribute (project , attributes , Usage .USAGE_ATTRIBUTE , Usage .JAVA_RUNTIME );
434- });
435- configureLegacyClasspath .accept (spec );
436- });
437-
438463 // Place files for junit runtime in a subdirectory to avoid conflicting with other runs
439464 var runArgsDir = argFileDir .map (dir -> dir .dir ("junit" ));
440465
441- var writeLcpTask = tasks .register ("writeNeoForgeTestClasspath" , WriteLegacyClasspath .class , writeLcp -> {
442- writeLcp .setGroup (branding .internalTaskGroup ());
443- writeLcp .setDescription ("Writes the legacyClasspath file for the test run, containing all dependencies that shouldn't be considered boot modules." );
444- writeLcp .getLegacyClasspathFile ().convention (runArgsDir .map (dir -> dir .file ("legacyClasspath.txt" )));
445- writeLcp .addEntries (legacyClasspathConfiguration );
446- });
466+ Provider <RegularFile > legacyClasspathFile ;
467+ if (versionCapabilities .legacyClasspath ()) {
468+ var legacyClasspathConfiguration = configurations .create ("neoForgeTestLibraries" , spec -> {
469+ spec .setDescription ("Contains the legacy classpath of unit tests." );
470+ spec .setCanBeResolved (true );
471+ spec .setCanBeConsumed (false );
472+ spec .shouldResolveConsistentlyWith (testRuntimeClasspath );
473+ spec .attributes (attributes -> {
474+ setNamedAttribute (project , attributes , MinecraftDistribution .ATTRIBUTE , MinecraftDistribution .CLIENT );
475+ setNamedAttribute (project , attributes , Usage .USAGE_ATTRIBUTE , Usage .JAVA_RUNTIME );
476+ });
477+ configureLegacyClasspath .accept (spec );
478+ });
479+
480+ var writeLcpTask = tasks .register ("writeNeoForgeTestClasspath" , WriteLegacyClasspath .class , writeLcp -> {
481+ writeLcp .setGroup (branding .internalTaskGroup ());
482+ writeLcp .setDescription ("Writes the legacyClasspath file for the test run, containing all dependencies that shouldn't be considered boot modules." );
483+ writeLcp .getLegacyClasspathFile ().convention (runArgsDir .map (dir -> dir .file ("legacyClasspath.txt" )));
484+ writeLcp .addEntries (legacyClasspathConfiguration );
485+ });
486+ legacyClasspathFile = writeLcpTask .get ().getLegacyClasspathFile ();
487+ } else {
488+ legacyClasspathFile = null ;
489+ }
447490
448491 var vmArgsFile = runArgsDir .map (dir -> dir .file ("vmArgs.txt" ));
449492 var programArgsFile = runArgsDir .map (dir -> dir .file ("programArgs.txt" ));
@@ -457,7 +500,9 @@ static void setupTestTask(Project project,
457500 task .getLog4jConfigFile ().set (log4j2ConfigFile );
458501 task .getRunTypeTemplatesSource ().from (runTemplatesSourceFile );
459502 task .getModules ().from (neoForgeModDevModules );
460- task .getLegacyClasspathFile ().set (writeLcpTask .get ().getLegacyClasspathFile ());
503+ if (legacyClasspathFile != null ) {
504+ task .getLegacyClasspathFile ().set (legacyClasspathFile );
505+ }
461506 task .getAssetProperties ().set (assetPropertiesFile );
462507 task .getGameLogLevel ().set (Level .INFO );
463508 });
@@ -485,10 +530,6 @@ static void setupTestTask(Project project,
485530 ideIntegration .configureTesting (loadedMods , testedMod , runArgsDir , gameDirectory , programArgsFile , vmArgsFile );
486531 }
487532
488- public Configuration getAdditionalClasspath () {
489- return additionalClasspath ;
490- }
491-
492533 private static <T extends Named > void setNamedAttribute (Project project , AttributeContainer attributes , Attribute <T > attribute , String value ) {
493534 attributes .attribute (attribute , project .getObjects ().named (attribute .getType (), value ));
494535 }
0 commit comments