diff --git a/build.gradle b/build.gradle index d3669aa8e..e7befa80d 100644 --- a/build.gradle +++ b/build.gradle @@ -60,9 +60,6 @@ dependencies { // GradleUtils Shared Base implementation libs.gradleutils.shared - // AccessTransformers - compileOnlyApi libs.accesstransformers.gradle - // Utils implementation libs.maven.artifact implementation libs.bundles.utils @@ -100,8 +97,8 @@ tasks.named('shadowJar', ShadowJar) { } } -tasks.withType(Javadoc).configureEach { - javadocTool = javaToolchains.javadocToolFor { languageVersion = JavaLanguageVersion.of(24) } +tasks.named('javadoc', Javadoc) { + javadocTool = javaToolchains.javadocToolFor { languageVersion = JavaLanguageVersion.of(25) } } changelog { diff --git a/runtime-environment-check/src/main/java/net/minecraftforge/gradle/internal/ForgeGradlePluginEntry.java b/runtime-environment-check/src/main/java/net/minecraftforge/gradle/internal/ForgeGradlePluginEntry.java index 8a60a5864..a427573b8 100644 --- a/runtime-environment-check/src/main/java/net/minecraftforge/gradle/internal/ForgeGradlePluginEntry.java +++ b/runtime-environment-check/src/main/java/net/minecraftforge/gradle/internal/ForgeGradlePluginEntry.java @@ -21,6 +21,10 @@ abstract class ForgeGradlePluginEntry implements Plugin { private static final GradleVersion CURRENT_GRADLE = GradleVersion.current(); private static final GradleVersion MINIMUM_GRADLE = GradleVersion.version("9.3.0-rc-1"); + private static final String PLUGIN_DISPLAY_NAME = "ForgeGradle"; + private static final String PLUGIN_VERSION = "7"; + private static final String PLUGIN_CLASS = "net.minecraftforge.gradle.internal.ForgeGradlePlugin"; + @Inject public ForgeGradlePluginEntry() { } @@ -28,7 +32,9 @@ public ForgeGradlePluginEntry() { } public void apply(PluginAware target) { if (CURRENT_GRADLE.compareTo(MINIMUM_GRADLE) < 0) { String message = String.format( - "ForgeGradle 7 requires %s or later to run. You are currently using %s.", + "%s %s requires %s or later to run. You are currently using %s.", + PLUGIN_DISPLAY_NAME, + PLUGIN_VERSION, MINIMUM_GRADLE, CURRENT_GRADLE ); @@ -37,9 +43,9 @@ public void apply(PluginAware target) { } try { - target.getPluginManager().apply(Class.forName("net.minecraftforge.gradle.internal.ForgeGradlePlugin")); + target.getPluginManager().apply(Class.forName(PLUGIN_CLASS)); } catch (ClassNotFoundException e) { - throw new RuntimeException("Failed to find the ForgeGradle entry-point.", e); + throw new RuntimeException(String.format("Failed to find the %s entry-point.", PLUGIN_DISPLAY_NAME), e); } } } diff --git a/settings.gradle b/settings.gradle index f53b817e0..8ba109688 100644 --- a/settings.gradle +++ b/settings.gradle @@ -24,7 +24,7 @@ gradle.beforeProject { Project project -> //@formatter:off dependencyResolutionManagement.versionCatalogs.register('libs') { - version 'gradleutils', '3.3.40' + version 'gradleutils', '3.3.42' plugin 'licenser', 'net.minecraftforge.licenser' version '1.2.0' // https://plugins.gradle.org/plugin/net.minecraftforge.licenser plugin 'gradleutils', 'net.minecraftforge.gradleutils' versionRef 'gradleutils' @@ -45,10 +45,6 @@ dependencyResolutionManagement.versionCatalogs.register('libs') { // GradleUtils Shared Base library 'gradleutils-shared', 'net.minecraftforge', 'gradleutils-shared' versionRef 'gradleutils' - // AccessTransformers Gradle Plugin - // https://plugins.gradle.org/plugin/net.minecraftforge.accesstransformers - library 'accesstransformers-gradle', 'net.minecraftforge.accesstransformers', 'net.minecraftforge.accesstransformers.gradle.plugin' version '5.0.1' - // Artifact Versioning library 'maven-artifact', 'org.apache.maven', 'maven-artifact' version '3.9.11' diff --git a/src/main/java/net/minecraftforge/gradle/ClosureOwner.java b/src/main/java/net/minecraftforge/gradle/ClosureOwner.java index 4994edddc..a547d8a48 100644 --- a/src/main/java/net/minecraftforge/gradle/ClosureOwner.java +++ b/src/main/java/net/minecraftforge/gradle/ClosureOwner.java @@ -18,10 +18,4 @@ public interface ClosureOwner { /// /// @see ClosureOwner interface MinecraftDependency extends ClosureOwner, net.minecraftforge.gradle.MinecraftDependency, ExternalModuleDependency { } - - /// A closure owner that delegates to [net.minecraftforge.gradle.MinecraftDependencyWithAccessTransformers] and - /// [ExternalModuleDependency]. - /// - /// @see ClosureOwner - interface MinecraftDependencyWithAccessTransformers extends ClosureOwner, net.minecraftforge.gradle.MinecraftDependencyWithAccessTransformers, ExternalModuleDependency { } } diff --git a/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java b/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java index fccfb8e13..60639de2c 100644 --- a/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java +++ b/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java @@ -7,6 +7,7 @@ import groovy.lang.Closure; import org.gradle.api.Action; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; +import org.gradle.api.attributes.Attribute; /// The ForgeGradle extension contains a handful of helpers that are not directly related to development involving /// Minecraft. @@ -44,4 +45,48 @@ public interface ForgeGradleExtension { * @return The closure */ Action getMinecraftLibsMaven(); + + /** + * The attributes object for easy reference. + *

+     * dependencies {
+     *     implementation 'com.example:example:1.0' {
+     *         attributes.attribute(fg.attributes.os, 'windows')
+     *     }
+     * }
+     * 
+ * + * @return The attributes object + * @see Attributes + */ + Attributes getAttributes(); + + /// This interface contains the attributes used by the [Minecraft][MinecraftExtension] extension for resolving the + /// Minecraft and deobfuscated dependencies. + /// + /// @see ForgeGradleExtension#getAttributes() + interface Attributes { + /// The operating system of the project's host. + /// + /// This is used to filter natives from the Minecraft repo. + /// + /// @return The operating system attribute + Attribute getOs(); + + /// The requested mappings channel of the project. + /// + /// This is determined using [MinecraftMappings#getChannel()] via [MinecraftMappingsContainer#getMappings()] + /// + /// @return The mappings channel attribute + /// @see #getMappingsVersion() + Attribute getMappingsChannel(); + + /// The requested mappings version of the project. + /// + /// This is determined using [MinecraftMappings#getVersion()] via [MinecraftMappingsContainer#getMappings()] + /// + /// @return The mappings channel version + /// @see #getMappingsChannel() + Attribute getMappingsVersion(); + } } diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftDependencyWithAccessTransformers.java b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java similarity index 81% rename from src/main/java/net/minecraftforge/gradle/MinecraftDependencyWithAccessTransformers.java rename to src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java index 868df9c0d..33825ce10 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftDependencyWithAccessTransformers.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java @@ -4,13 +4,10 @@ */ package net.minecraftforge.gradle; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.RegularFileProperty; -/// An extension of [MinecraftDependency] that contains additional convenience methods for working with -/// AccessTransformers. -/// -/// @see MinecraftDependency -public interface MinecraftDependencyWithAccessTransformers extends MinecraftDependency { +public interface MinecraftAccessTransformersContainer { /// The default path, from the source set's [resources][org.gradle.api.tasks.SourceSet#getResources()], for the /// AccessTransformers config to be located in. String DEFAULT_PATH = "META-INF/accesstransformer.cfg"; @@ -18,7 +15,7 @@ public interface MinecraftDependencyWithAccessTransformers extends MinecraftDepe /// Gets the AccessTransformer configuration to use. /// /// @return The property for the configuration file to use - RegularFileProperty getAccessTransformer(); + ConfigurableFileCollection getAccessTransformer(); /// Sets the path, relative to this dependency's [org.gradle.api.tasks.SourceSet#getResources()], to the /// AccessTransformers config file to use. @@ -35,8 +32,7 @@ public interface MinecraftDependencyWithAccessTransformers extends MinecraftDepe /// file is in a strict location. void setAccessTransformer(String accessTransformer); - /// Sets if this dependency should use AccessTransformers. The default value depends on the state of - /// [MinecraftExtensionForProjectWithAccessTransformers#getAccessTransformers()]. + /// Sets if this dependency should use AccessTransformers. /// /// If `true`, this calls [#setAccessTransformer(String)] using [#DEFAULT_PATH] as the path. If `false`, this will /// force this dependency to *not use* AccessTransformers, even if the convention is set to do so from the Minecraft diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftDependency.java b/src/main/java/net/minecraftforge/gradle/MinecraftDependency.java index f970bf466..357d7f2bd 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftDependency.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftDependency.java @@ -14,7 +14,7 @@ /// The Minecraft dependency contains information essential for how the /// {@linkplain MinecraftExtensionForProject minecraft extension} processes Minecraft dependencies. -public interface MinecraftDependency extends MinecraftMappingsContainer { +public interface MinecraftDependency extends MinecraftMappingsContainer, MinecraftAccessTransformersContainer { /// The collection of Slime Launcher options with which to create the launcher tasks. /// /// @return The collection of run task options diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftExtension.java b/src/main/java/net/minecraftforge/gradle/MinecraftExtension.java index 6914be208..4c158df13 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftExtension.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftExtension.java @@ -8,7 +8,6 @@ import org.gradle.api.Action; import org.gradle.api.artifacts.dsl.RepositoryHandler; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; -import org.gradle.api.attributes.Attribute; /// The main extension for ForgeGradle, where the Minecraft dependency resolution takes place. /// @@ -56,48 +55,4 @@ default MavenArtifactRepository mavenizer(RepositoryHandler repositories) { repositories.addFirst(mavenizer); return mavenizer; } - - /** - * The attributes object for easy reference. - *

-     * dependencies {
-     *     implementation 'com.example:example:1.0' {
-     *         attributes.attribute(minecraft.attributes.os, 'windows')
-     *     }
-     * }
-     * 
- * - * @return The attributes object - * @see Attributes - */ - Attributes getAttributes(); - - /// This interface contains the attributes used by the [Minecraft][MinecraftExtension] extension for resolving the - /// Minecraft and deobfuscated dependencies. - /// - /// @see MinecraftExtension#getAttributes() - interface Attributes { - /// The operating system of the project's host. - /// - /// This is used to filter natives from the Minecraft repo. - /// - /// @return The operating system attribute - Attribute getOs(); - - /// The requested mappings channel of the project. - /// - /// This is determined using [MinecraftMappings#getChannel()] via [#getMappings()] - /// - /// @return The mappings channel attribute - /// @see #getMappingsVersion() - Attribute getMappingsChannel(); - - /// The requested mappings version of the project. - /// - /// This is determined using [MinecraftMappings#getVersion()] via [#getMappings()] - /// - /// @return The mappings channel version - /// @see #getMappingsChannel() - Attribute getMappingsVersion(); - } } diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java b/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java index 830a1d7ed..ae942d764 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java @@ -8,6 +8,7 @@ import groovy.lang.DelegatesTo; import groovy.transform.stc.ClosureParams; import groovy.transform.stc.FromString; +import groovy.transform.stc.SimpleType; import net.minecraftforge.gradleutils.shared.Closures; import org.gradle.api.Action; import org.gradle.api.NamedDomainObjectContainer; @@ -16,32 +17,8 @@ /// [Project][org.gradle.api.Project]-specific additions for the Minecraft extension. These will be accessible from the /// `minecraft` DSL object within your project's buildscript. /// -/// @param The type of closure owner used for [#dependency] /// @see MinecraftExtension -public interface MinecraftExtensionForProject extends MinecraftExtension { - /// The collection of Slime Launcher options with which to create the launcher tasks. - /// - /// @return The collection of run task options - NamedDomainObjectContainer getRuns(); - - /// Configures the Slime Launcher options for this project, which will be used to create the launcher tasks. - /// - /// @param closure The configuring closure - default void runs( - @DelegatesTo(NamedDomainObjectContainer.class) - @ClosureParams(value = FromString.class, options = "org.gradle.api.NamedDomainObjectContainer") - Closure closure - ) { - this.getRuns().configure(closure); - } - - /// Configures the Slime Launcher options for this project, which will be used to create the launcher tasks. - /// - /// @param action The configuring action - default void runs(Action> action) { - this.runs(Closures.action(this, action)); - } - +public interface MinecraftExtensionForProject extends MinecraftExtension, MinecraftDependency { /// Creates (or marks if existing) the given dependency as a Minecraft dependency and configures it with the given /// closure. /// @@ -53,7 +30,7 @@ default void runs(Action closure ); @@ -65,7 +42,7 @@ ExternalModuleDependency dependency( /// @return The dependency /// @see Declaring Dependencies /// in Gradle - default ExternalModuleDependency dependency(Object value, Action action) { + default ExternalModuleDependency dependency(Object value, Action action) { return this.dependency(value, Closures.action(this, action)); } diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProjectWithAccessTransformers.java b/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProjectWithAccessTransformers.java deleted file mode 100644 index 3941cb76c..000000000 --- a/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProjectWithAccessTransformers.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ -package net.minecraftforge.gradle; - -import org.gradle.api.provider.Property; - -/// An additional extension of [MinecraftExtensionForProject] that allows for working with AccessTransformers as long as -/// the `net.minecraftforge.accesstransformers` plugin has been applied before ForgeGradle. -/// -/// @see MinecraftExtensionForProject -public interface MinecraftExtensionForProjectWithAccessTransformers extends MinecraftExtensionForProject { - /// The path, relative to the related Minecraft dependency's [org.gradle.api.tasks.SourceSet#getResources()], to the - /// AccessTransformers config file to use. If set, this will recursively enable access transformers for all - /// Minecraft dependencies in the project. - /// - /// The default location for the AccessTransformer config file will be in - /// [org.gradle.api.tasks.SourceSet#getResources()] -> first directory of - /// [org.gradle.api.file.SourceDirectorySet#getSrcDirs()] -> `META-INF/accesstransformer.cfg`. If the source set, - /// for whatever reason, does not have any resources directories set, ForgeGradle will make the best guess of - /// {@code src/}{@link org.gradle.api.tasks.SourceSet#getName() name}{@code - /// /resources/META-INF/accesstransformer.cfg}. - /// - /// @return The property for the default AccessTransformers path from the source set's resources. - /// @apiNote Setting this property will apply to **all Minecraft dependencies** regardless of source set. A single - /// Minecraft dependency can manually be opted into using AccessTransformers by setting the value of - /// [MinecraftDependencyWithAccessTransformers#getAccessTransformer()], or by using - /// [MinecraftDependencyWithAccessTransformers#setAccessTransformer]. - Property getAccessTransformers(); - - /// Sets if all Minecraft dependencies in this project should use AccessTransformers. - /// - /// @param accessTransformers If all Minecraft dependencies should use AccessTransformers. - /// @see #getAccessTransformers() - default void setAccessTransformers(boolean accessTransformers) { - if (accessTransformers) - this.getAccessTransformers().convention(MinecraftDependencyWithAccessTransformers.DEFAULT_PATH); - else - this.getAccessTransformers().unsetConvention(); - } -} diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftMappings.java b/src/main/java/net/minecraftforge/gradle/MinecraftMappings.java index 463b4edf4..8cf28de51 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftMappings.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftMappings.java @@ -15,7 +15,7 @@ public interface MinecraftMappings extends Serializable { /// @return The channel String getChannel(); - /// Gets the version for these mappings (i.e. `1.21.10`) + /// Gets the version for these mappings (i.e. `1.21.11`) /// /// @return The version String getVersion(); diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftMappingsContainer.java b/src/main/java/net/minecraftforge/gradle/MinecraftMappingsContainer.java index 75bb2fc66..fc49f47d8 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftMappingsContainer.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftMappingsContainer.java @@ -28,7 +28,7 @@ public interface MinecraftMappingsContainer { *

This method includes a generated named variant that can make declaration in your buildscript easier.

*

      * minecraft {
-     *     mappings channel: 'official', version: '1.21.5'
+     *     mappings channel: 'official', version: '1.21.11'
      * }
      * 
* diff --git a/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerImpl.java b/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerImpl.java index d5cae9003..19c83d5bc 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerImpl.java @@ -68,10 +68,4 @@ static class MinecraftDependencyImpl extends ClosureOwnerImpl implements ClosureOwnerInternal.MinecraftDependencyWithAccessTransformers { - MinecraftDependencyWithAccessTransformersImpl(Object originalOwner, net.minecraftforge.gradle.MinecraftDependencyWithAccessTransformers ownerDelegate) { - super(originalOwner, ownerDelegate); - } - } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java b/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java index 7f4ce6f33..b483b6ae5 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java @@ -9,6 +9,7 @@ import groovy.transform.NamedParam; import groovy.transform.NamedParams; import net.minecraftforge.gradle.ClosureOwner; +import net.minecraftforge.gradle.MinecraftDependency; import net.minecraftforge.gradle.MinecraftMappings; import net.minecraftforge.gradle.SlimeLauncherOptions; import org.gradle.api.Action; @@ -25,6 +26,7 @@ import org.gradle.api.artifacts.capability.CapabilitySelector; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.capabilities.Capability; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.reflect.HasPublicType; import org.gradle.api.reflect.TypeOf; @@ -90,170 +92,17 @@ default NamedDomainObjectContainer getRuns() { } @Override - default boolean isChanging() { - throw stub(); - } - - @Override - default ExternalModuleDependency setChanging(boolean changing) { - throw stub(); - } - - @Override - default ExternalModuleDependency copy() { - throw stub(); - } - - @Override - default boolean isForce() { - throw stub(); - } - - @Override - default void version(Action configureAction) { - throw stub(); - } - - @Override - default VersionConstraint getVersionConstraint() { - throw stub(); - } - - @Override - default ModuleDependency exclude(Map excludeProperties) { - throw stub(); - } - - @Override - default Set getExcludeRules() { - throw stub(); - } - - @Override - default Set getArtifacts() { - throw stub(); - } - - @Override - default ModuleDependency addArtifact(DependencyArtifact artifact) { - throw stub(); - } - - @Override - default DependencyArtifact artifact(Closure configureClosure) { - throw stub(); - } - - @Override - default DependencyArtifact artifact(Action configureAction) { - throw stub(); - } - - @Override - default boolean isTransitive() { - throw stub(); - } - - @Override - default ModuleDependency setTransitive(boolean transitive) { - throw stub(); - } - - @Override - default @Nullable String getTargetConfiguration() { - throw stub(); - } - - @Override - default void setTargetConfiguration(@Nullable String name) { - throw stub(); - } - - @Override - default AttributeContainer getAttributes() { - throw stub(); - } - - @Override - default ModuleDependency attributes(Action configureAction) { - throw stub(); - } - - @Override - default ModuleDependency capabilities(Action configureAction) { - throw stub(); - } - - @Override - default List getRequestedCapabilities() { - throw stub(); - } - - @Override - default Set getCapabilitySelectors() { - throw stub(); - } - - @Override - default void endorseStrictVersions() { - throw stub(); + default void runs(Closure closure) { + this.getOwnerDelegate().runs(closure); } @Override - default void doNotEndorseStrictVersions() { - throw stub(); + default void runs(Action> action) { + this.getOwnerDelegate().runs(action); } @Override - default boolean isEndorsingStrictVersions() { - throw stub(); - } - - @Override default @Nullable String getGroup() { - throw stub(); - } - - @Override - default String getName() { - throw stub(); - } - - @Override - default @Nullable String getVersion() { - throw stub(); - } - - @Override - default @Nullable String getReason() { - throw stub(); - } - - @Override - default void because(@Nullable String reason) { - throw stub(); - } - - @Override - default boolean matchesStrictly(ModuleVersionIdentifier identifier) { - throw stub(); - } - - @Override - default ModuleIdentifier getModule() { - throw stub(); - } - } - - interface MinecraftDependencyWithAccessTransformers extends ClosureOwnerInternal, ClosureOwner.MinecraftDependencyWithAccessTransformers, HasPublicType { - @Override - default TypeOf getPublicType() { - return TypeOf.typeOf(ClosureOwner.MinecraftDependencyWithAccessTransformers.class); - } - - net.minecraftforge.gradle.MinecraftDependencyWithAccessTransformers getOwnerDelegate(); - - @Override - default RegularFileProperty getAccessTransformer() { + default ConfigurableFileCollection getAccessTransformer() { return this.getOwnerDelegate().getAccessTransformer(); } @@ -267,39 +116,6 @@ default void setAccessTransformer(boolean accessTransformer) { this.getOwnerDelegate().setAccessTransformer(accessTransformer); } - @Override - default @Nullable MinecraftMappings getMappings() { - return this.getOwnerDelegate().getMappings(); - } - - @Override - default void mappings(String channel, String version) { - this.getOwnerDelegate().mappings(channel, version); - } - - @Override - default void mappings( - @NamedParams({ - @NamedParam( - type = String.class, - value = "channel", - required = true - ), - @NamedParam( - type = String.class, - value = "version", - required = true - ) - }) Map namedArgs - ) { - this.getOwnerDelegate().mappings(namedArgs); - } - - @Override - default NamedDomainObjectContainer getRuns() { - return this.getOwnerDelegate().getRuns(); - } - @Override default boolean isChanging() { throw stub(); diff --git a/src/main/java/net/minecraftforge/gradle/internal/Constants.java b/src/main/java/net/minecraftforge/gradle/internal/Constants.java index 2c6bc1183..736cec03d 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/Constants.java +++ b/src/main/java/net/minecraftforge/gradle/internal/Constants.java @@ -4,11 +4,11 @@ */ package net.minecraftforge.gradle.internal; -import net.minecraftforge.gradle.MinecraftExtension; +import net.minecraftforge.gradle.ForgeGradleExtension; /// The package-private constants used throughout ForgeGradle. /// -/// Looking for attributes? They are in [MinecraftExtension.Attributes]. +/// Looking for attributes? They are in [ForgeGradleExtension.Attributes]. final class Constants { static final String FORGE_MAVEN = "https://maven.minecraftforge.net/"; static final String MC_LIBS_MAVEN = "https://libraries.minecraft.net/"; @@ -20,7 +20,7 @@ final class Constants { static final String SLIMELAUNCHER_MAIN = "net.minecraftforge.launcher.Main"; static final String MAVENIZER_NAME = "mavenizer"; - static final String MAVENIZER_VERSION = "0.4.15"; + static final String MAVENIZER_VERSION = "0.4.18"; static final String MAVENIZER_DL_URL = "https://maven.minecraftforge.net/net/minecraftforge/minecraft-mavenizer/" + MAVENIZER_VERSION + "/minecraft-mavenizer-" + MAVENIZER_VERSION + ".jar"; static final int MAVENIZER_JAVA_VERSION = 25; static final String MAVENIZER_MAIN = "net.minecraftforge.mcmaven.cli.Main"; @@ -50,9 +50,9 @@ fixes. We will (gently) encourage developers to move away from them and use please let us know! - Many things that ForgeGradle 6 and older used to do are now decentralized away from the plugin. This means that your project will need to apply - 'net.minecraftforge.accesstransformers' if you wish to use AccessTransformers. + 'net.minecraftforge.jarjar' if you wish to use Forge's Jar-in-Jar system. If you are on an older version (1.20.4 and older), you will need the - 'net.minecraftforge.obfuscation' plugin. Many of these come with our provided + 'net.minecraftforge.renamer' plugin. Many of these come with our provided MDK, so this should not be an issue for you. For more details on this release, see https://docs.minecraftforge.net/en/fg-7.0/"""; diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeAttributes.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeAttributes.java index 1be8e04e5..e7a8e288d 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeAttributes.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeAttributes.java @@ -1,3 +1,7 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ package net.minecraftforge.gradle.internal; import net.minecraftforge.util.os.OS; @@ -98,6 +102,6 @@ public void execute(MultipleCandidatesDetails details) { static final class MappingsVersion { static final Attribute ATTRIBUTE = Attribute.of("net.minecraftforge.mappings.version", String.class); - static final Comparator COMPARATOR = Comparator.comparing(DefaultArtifactVersion::new); + static final Comparator COMPARATOR = Util.versionComparator(); } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java new file mode 100644 index 000000000..14bb4d3a7 --- /dev/null +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ +package net.minecraftforge.gradle.internal; + +import org.gradle.api.artifacts.CacheableRule; +import org.gradle.api.artifacts.ComponentMetadataContext; +import org.gradle.api.artifacts.ComponentMetadataRule; + +import javax.inject.Inject; +import java.util.List; + +final class ForgeGradleComponentMetadataRules { + @CacheableRule + abstract static class AlwaysUseMatureStatus implements ComponentMetadataRule { + private final List modules; + + @Inject + public AlwaysUseMatureStatus(List modules) { + this.modules = modules; + } + + @Override + public void execute(ComponentMetadataContext context) { + var details = context.getDetails(); + if (!modules.isEmpty() && !modules.contains(details.getId().getModule().toString())) return; + + var statusScheme = details.getStatusScheme(); + var status = statusScheme.contains("release") ? "release" : statusScheme.get(statusScheme.size() - 1); + details.setStatus(status); + } + } +} diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionImpl.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionImpl.java index f11c7f8e2..5e1baa1c3 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionImpl.java @@ -6,17 +6,16 @@ import net.minecraftforge.gradle.ForgeGradleExtension; import org.gradle.api.plugins.ExtensionAware; -import org.gradle.api.reflect.HasPublicType; import javax.inject.Inject; -abstract class ForgeGradleExtensionImpl implements ForgeGradleExtensionInternal, HasPublicType { +abstract class ForgeGradleExtensionImpl implements ForgeGradleExtensionInternal { static void register( ForgeGradlePlugin plugin, ExtensionAware target ) { var extensions = target.getExtensions(); - extensions.create(ForgeGradleExtension.NAME, ForgeGradleExtensionImpl.class); + extensions.create(ForgeGradleExtension.class, ForgeGradleExtension.NAME, ForgeGradleExtensionImpl.class); } @Inject diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java index 189f5abac..be82a58c5 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java @@ -7,15 +7,9 @@ import net.minecraftforge.gradle.ForgeGradleExtension; import org.gradle.api.Action; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; -import org.gradle.api.reflect.HasPublicType; -import org.gradle.api.reflect.TypeOf; - -interface ForgeGradleExtensionInternal extends ForgeGradleExtension, HasPublicType { - @Override - default TypeOf getPublicType() { - return TypeOf.typeOf(ForgeGradleExtension.class); - } +import org.gradle.api.attributes.Attribute; +interface ForgeGradleExtensionInternal extends ForgeGradleExtension { Action forgeMaven = repo -> { repo.setName("MinecraftForge"); repo.setUrl(Constants.FORGE_MAVEN); @@ -35,4 +29,28 @@ default Action getForgeMaven() { default Action getMinecraftLibsMaven() { return minecraftLibsMaven; } + + @Override + default Attributes getAttributes() { + return AttributesInternal.INSTANCE; + } + + record AttributesInternal() implements Attributes { + static AttributesInternal INSTANCE = new AttributesInternal(); + + @Override + public Attribute getOs() { + return ForgeAttributes.OperatingSystem.ATTRIBUTE; + } + + @Override + public Attribute getMappingsChannel() { + return ForgeAttributes.MappingsChannel.ATTRIBUTE; + } + + @Override + public Attribute getMappingsVersion() { + return ForgeAttributes.MappingsVersion.ATTRIBUTE; + } + } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java index a3f11ac27..c0f6b98b6 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java @@ -1,12 +1,13 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ package net.minecraftforge.gradle.internal; -import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.jspecify.annotations.Nullable; -import java.util.List; - record ForgeGradleSharedData( - @Nullable MinecraftMappingsImpl mappings + @Nullable MinecraftMappingsInternal mappings ) { static final String NAME = "__fg_shared_data"; } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java new file mode 100644 index 000000000..b60b57be1 --- /dev/null +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ +package net.minecraftforge.gradle.internal; + +import net.minecraftforge.gradle.MinecraftAccessTransformersContainer; +import org.gradle.api.provider.Property; + +interface MinecraftAccessTransformersContainerInternal extends MinecraftAccessTransformersContainer { + boolean hasAccessTransformersPlugin(); + + Property getAccessTransformerPath(); + + @Override + default void setAccessTransformer(String accessTransformer) { + this.getAccessTransformerPath().set(accessTransformer); + } + + @Override + default void setAccessTransformer(boolean accessTransformer) { + if (accessTransformer) + this.getAccessTransformerPath().set(DEFAULT_PATH); + else + this.getAccessTransformerPath().unset(); + } +} diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java index 9b71d8cd8..08ebab257 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java @@ -6,11 +6,7 @@ import groovy.lang.Closure; import groovy.transform.NamedVariant; -import net.minecraftforge.accesstransformers.gradle.ArtifactAccessTransformer; -import net.minecraftforge.gradle.MinecraftDependencyWithAccessTransformers; -import net.minecraftforge.gradle.MinecraftExtension; import net.minecraftforge.gradle.MinecraftExtensionForProject; -import net.minecraftforge.gradle.MinecraftExtensionForProjectWithAccessTransformers; import net.minecraftforge.gradle.MinecraftMappings; import net.minecraftforge.gradle.SlimeLauncherOptions; import net.minecraftforge.gradleutils.shared.Closures; @@ -26,9 +22,7 @@ import org.gradle.api.artifacts.type.ArtifactTypeDefinition; import org.gradle.api.attributes.Attribute; import org.gradle.api.attributes.AttributeContainer; -import org.gradle.api.attributes.AttributeDisambiguationRule; -import org.gradle.api.attributes.Category; -import org.gradle.api.attributes.MultipleCandidatesDetails; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.Directory; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.ProjectLayout; @@ -37,19 +31,15 @@ import org.gradle.api.flow.FlowScope; import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.ExtensionAware; -import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; -import org.gradle.api.provider.ProviderFactory; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskProvider; -import org.gradle.plugins.ide.eclipse.model.EclipseModel; import org.jspecify.annotations.Nullable; import javax.inject.Inject; import java.io.File; import java.util.Objects; -import java.util.Set; abstract class MinecraftDependencyImpl implements MinecraftDependencyInternal { // These can be nullable due to configuration caching. @@ -57,15 +47,21 @@ abstract class MinecraftDependencyImpl implements MinecraftDependencyInternal { private transient @Nullable TaskProvider mavenizer; private transient @Nullable NamedDomainObjectContainer runs; - private final MinecraftExtensionImpl.ForProjectImpl minecraft; + // Minecraft extension + private final MinecraftExtensionInternal.ForProject minecraft = ((MinecraftExtensionInternal.ForProject) getProject().getExtensions().getByType(MinecraftExtensionForProject.class)); - final Property asString = getObjects().property(String.class); - final Property asPath = getObjects().property(String.class); - final Property module = getObjects().property(ModuleIdentifier.class); - final Property version = getObjects().property(String.class); + // Access Transformers + private final ConfigurableFileCollection accessTransformer = this.getObjects().fileCollection(); + private final Property accessTransformerPath = this.getObjects().property(String.class); + + // Dependency Information + private final Property asString = getObjects().property(String.class); + private final Property asPath = getObjects().property(String.class); + private final Property module = getObjects().property(ModuleIdentifier.class); + private final Property version = getObjects().property(String.class); private final DirectoryProperty mavenizerOutput = getObjects().directoryProperty(); - private final Property mappings = this.getObjects().property(MinecraftMappingsImpl.class); + private final Property mappings = this.getObjects().property(MinecraftMappingsInternal.class); private @Nullable String sourceSetName; private final ForgeGradleProblems problems = this.getObjects().newInstance(ForgeGradleProblems.class); @@ -80,14 +76,10 @@ abstract class MinecraftDependencyImpl implements MinecraftDependencyInternal { protected abstract @Inject ProjectLayout getProjectLayout(); - protected abstract @Inject ProviderFactory getProviders(); - @Inject public MinecraftDependencyImpl(Provider mavenizerOutput) { - this.minecraft = ((MinecraftExtensionImpl.ForProjectImpl) getProject().getExtensions().getByType(MinecraftExtensionForProject.class)); - this.mavenizerOutput.set(mavenizerOutput); - this.mappings.convention(minecraft.mappings); + this.mappings.convention(minecraft.getMappingsProperty()); } // Can be nullable due to configuration caching. @@ -96,6 +88,41 @@ public MinecraftDependencyImpl(Provider mavenizerOutput) { return this.runs; } + @Override + public MinecraftMappings getMappings() { + try { + return this.mappings.get(); + } catch (IllegalStateException e) { + throw this.problems.missingMappings(e); + } + } + + @Override + @NamedVariant + public void mappings(String channel, String version) { + this.mappings.set(this.getObjects().newInstance(MinecraftMappingsImpl.class, channel, version)); + } + + @Override public boolean hasAccessTransformersPlugin() { + return minecraft.hasAccessTransformersPlugin(); + } + + @Override + public ConfigurableFileCollection getAccessTransformer() { + return this.accessTransformer; + } + + @Override + public Property getAccessTransformerPath() { + return this.accessTransformerPath; + } + + /* INTERNAL */ + + private boolean hasAccessTransformers() { + return !this.accessTransformer.isEmpty() || this.accessTransformerPath.isPresent(); + } + // Can be nullable due to configuration caching. @Override public @Nullable ExternalModuleDependency asDependency() { @@ -126,7 +153,7 @@ public ExternalModuleDependency init(Object dependencyNotation, Closure closu return module; })); - this.mavenizer = SyncMavenizer.register(getProject(), dependency, this.mappings, mavenizerOutput); + this.mavenizer = SyncMavenizer.register(getProject(), dependency, this.mappings, this.accessTransformer, mavenizerOutput); this.asString.set(dependency.toString()); this.asPath.set(Util.pathify(dependency)); @@ -137,13 +164,30 @@ public ExternalModuleDependency init(Object dependencyNotation, Closure closu } @Override - public Action addAttributes() { - return attributes -> { }; + public void handle(Configuration configuration) { + if (configuration.isCanBeResolved()) { + var moduleSelector = "%s:%s".formatted(this.module.get(), this.version.get()); + var resolutionStrategy = configuration.getResolutionStrategy(); + var dependencySubstitution = resolutionStrategy.getDependencySubstitution(); + + // Apply the dependency substitution for mappings attributes. + if (this.mappings.isPresent()) { + var module = dependencySubstitution.module(moduleSelector); + try { + dependencySubstitution + .substitute(module) + .using(dependencySubstitution.variant(module, variant -> variant.attributes(attributes -> { + attributes.attributeProvider(ForgeAttributes.MappingsChannel.ATTRIBUTE, this.mappings.map(MinecraftMappings::getChannel)); + attributes.attributeProvider(ForgeAttributes.MappingsVersion.ATTRIBUTE, this.mappings.map(MinecraftMappings::getVersion)); + }))) + .because("Accounts for declared mappings."); + } catch (InvalidUserCodeException e) { + throw new IllegalStateException("Resolvable configuration '%s' was resolved too early!".formatted(configuration.getName()), e); + } + } + } } - @Override - public void handle(Configuration configuration) { } - @Override public void handle(NamedDomainObjectSet sourceSets, NamedDomainObjectSet allSourceSets) { allSourceSets.all(sourceSet -> @@ -163,7 +207,7 @@ public void handle(NamedDomainObjectSet sourceSets, NamedDomainObject if (!sourceSets.isEmpty() && this.sourceSetName == null) this.sourceSetName = sourceSets.iterator().next().getName(); - var runs = Objects.requireNonNullElseGet(getRuns(), () -> getObjects().domainObjectContainer(SlimeLauncherOptionsImpl.class)); + var runs = Objects.requireNonNullElseGet(this.getRuns(), () -> getObjects().domainObjectContainer(SlimeLauncherOptionsImpl.class)); ((NamedDomainObjectContainer) runs).addAll((NamedDomainObjectContainer) minecraft.getRuns()); allSourceSets.configureEach(sourceSet -> { var single = getProject() @@ -176,140 +220,25 @@ public void handle(NamedDomainObjectSet sourceSets, NamedDomainObject var task = SlimeLauncherExec.register(getProject(), sourceSet, (SlimeLauncherOptionsImpl) options, module.get(), version.get(), asPath.get(), asString, single, minecraft.getEclipseOutputDir()); }); }); - } - - @Override - public MinecraftMappings getMappings() { - try { - return this.mappings.get(); - } catch (IllegalStateException e) { - throw this.problems.missingMappings(e); - } - } - @Override - @NamedVariant - public void mappings(String channel, String version) { - this.mappings.set(this.getObjects().newInstance(MinecraftMappingsImpl.class, channel, version)); - } - - static abstract class WithAccessTransformersImpl extends MinecraftDependencyImpl implements WithAccessTransformers { - private final RegularFileProperty atFile = this.getObjects().fileProperty(); - private final Property atPath = this - .getObjects().property(String.class) - .convention(getProject().getExtensions().getByType(MinecraftExtensionForProjectWithAccessTransformers.class).getAccessTransformers()); - - private final Attribute attribute = this.registerTransform(); - - @Inject - public WithAccessTransformersImpl(Provider mavenizerOutput) { - super(mavenizerOutput); - } - - @Override - public Action addAttributes() { - return attributes -> { - super.addAttributes().execute(attributes); - attributes.attribute(this.attribute, true); - }; + if (this.accessTransformer.isEmpty() && !this.accessTransformerPath.isPresent()) { + this.accessTransformer.convention(minecraft.getAccessTransformer()); + this.accessTransformerPath.convention(minecraft.getAccessTransformerPath()); } - @Override - public void handle(Configuration configuration) { - super.handle(configuration); - - if (configuration.isCanBeResolved()) { - configuration.getResolutionStrategy().dependencySubstitution(s -> { - var moduleSelector = "%s:%s".formatted(this.module.get(), this.version.get()); - var module = s.module(moduleSelector); - try { - s.substitute(module) - .using(s.variant(module, variant -> variant.attributes(this.addAttributes()))) - .because("Applies AccessTransformers"); - } catch (InvalidUserCodeException e) { - throw new IllegalStateException("Resolvable configuration '%s' was resolved too early!".formatted(configuration.getName()), e); - } - }); - } - } - - @Override - public void handle(NamedDomainObjectSet sourceSets, NamedDomainObjectSet allSourceSets) { - super.handle(sourceSets, allSourceSets); - - if (!this.atPath.isPresent() || sourceSets.isEmpty()) return; + if (this.accessTransformer.isEmpty() && this.accessTransformerPath.isPresent() && !sourceSets.isEmpty()) { var sourceSet = sourceSets.iterator().next(); var itor = sourceSet.getResources().getSrcDirs().iterator(); if (itor.hasNext()) { var file = itor.next(); - this.atFile.convention(this.getProjectLayout().file(this.atPath.map(atPath -> new File(file, atPath)))); + this.accessTransformer.setFrom(this.getProjectLayout().file(this.accessTransformerPath.map(atPath -> new File(file, atPath)))); } else { // weird edge case where a source set might not have any resources??? // in which case, just best guess the location for accesstransformer.cfg var sourceSetName = sourceSet.getName(); - this.atFile.convention(this.getProjectLayout().getProjectDirectory().file(this.atPath.map(atPath -> "src/" + sourceSetName + "/resources/" + atPath))); + this.accessTransformer.setFrom(this.getProjectLayout().getProjectDirectory().file(this.accessTransformerPath.map(atPath -> "src/" + sourceSetName + "/resources/" + atPath))); } - - ArtifactAccessTransformer.validateConfig(getProject(), asDependency(), this.atFile); - } - - private Attribute registerTransform() { - var dependencies = getProject().getDependencies(); - - var attribute = Attribute.of("net.minecraftforge.gradle.accesstransformers.automatic." + this.getIndex(), Boolean.class); - - dependencies.getAttributesSchema().attribute(attribute); - dependencies.getArtifactTypes().named( - ArtifactTypeDefinition.JAR_TYPE, - type -> type.getAttributes().attribute(attribute, false) - ); - - dependencies.registerTransform(ArtifactAccessTransformer.class, spec -> { - spec.parameters(ArtifactAccessTransformer.Parameters.defaults(getProject(), parameters -> { - parameters.getConfig().set(this.atFile); - })); - - spec.getFrom() - .attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE) - .attribute(Category.CATEGORY_ATTRIBUTE, spec.getFrom().named(Category.class, Category.LIBRARY)) - .attribute(attribute, false); - - spec.getTo() - .attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE) - .attribute(Category.CATEGORY_ATTRIBUTE, spec.getTo().named(Category.class, Category.LIBRARY)) - .attribute(attribute, true); - }); - - return attribute; - } - - private int getIndex() { - var ext = getProject().getGradle().getExtensions().getExtraProperties(); - - int index = ext.has(AT_COUNT_NAME) - ? (int) Objects.requireNonNull(ext.get(AT_COUNT_NAME), "Internal extra property can never be null!") + 1 - : 0; - ext.set(AT_COUNT_NAME, index); - return index; - } - - @Override - public RegularFileProperty getAccessTransformer() { - return this.atFile; - } - - @Override - public void setAccessTransformer(String accessTransformer) { - this.atPath.set(accessTransformer); - } - - @Override - public void setAccessTransformer(boolean accessTransformer) { - if (accessTransformer) - this.setAccessTransformer(MinecraftDependencyWithAccessTransformers.DEFAULT_PATH); - else - this.atPath.unsetConvention().unset(); } } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java index f3e0a7d92..bc664c0e1 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java @@ -6,7 +6,6 @@ import groovy.lang.Closure; import net.minecraftforge.gradle.MinecraftDependency; -import net.minecraftforge.gradle.MinecraftDependencyWithAccessTransformers; import net.minecraftforge.gradle.SlimeLauncherOptions; import org.gradle.api.Action; import org.gradle.api.NamedDomainObjectContainer; @@ -23,11 +22,8 @@ import org.jspecify.annotations.NullUnmarked; import org.jspecify.annotations.Nullable; -import java.util.Set; - -interface MinecraftDependencyInternal extends MinecraftDependency, HasPublicType, MinecraftMappingsContainerInternal { +interface MinecraftDependencyInternal extends MinecraftDependency, HasPublicType, MinecraftMappingsContainerInternal, MinecraftAccessTransformersContainerInternal { String MC_EXT_NAME = "__fg_minecraft_dependency"; - String AT_COUNT_NAME = "__fg_minecraft_atcontainers"; @Override default TypeOf getPublicType() { @@ -62,8 +58,6 @@ static boolean is(Dependency dependency) { // Can be nullable due to configuration caching. @Nullable TaskProvider asTask(); - Action addAttributes(); - default Closure closure(Closure closure) { return closure.rehydrate(closure.getDelegate(), new ClosureOwnerImpl.MinecraftDependencyImpl(closure.getOwner(), this), closure.getThisObject()); } @@ -71,15 +65,4 @@ default Closure closure(Closure closure) { void handle(Configuration configuration); void handle(NamedDomainObjectSet sourceSets, NamedDomainObjectSet allSourceSets); - - interface WithAccessTransformers extends MinecraftDependencyWithAccessTransformers, MinecraftDependencyInternal { - @Override - default TypeOf getPublicType() { - return TypeOf.typeOf(MinecraftDependencyWithAccessTransformers.class); - } - - default Closure closure(Closure closure) { - return closure.rehydrate(closure.getDelegate(), new ClosureOwnerImpl.MinecraftDependencyWithAccessTransformersImpl(closure.getOwner(), this), closure.getThisObject()); - } - } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java index 425b46539..83ed05247 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java @@ -9,8 +9,6 @@ import groovy.transform.NamedVariant; import groovy.transform.stc.ClosureParams; import groovy.transform.stc.SimpleType; -import net.minecraftforge.gradle.ClosureOwner; -import net.minecraftforge.gradle.MinecraftDependency; import net.minecraftforge.gradle.MinecraftExtension; import net.minecraftforge.gradle.MinecraftExtensionForProject; import net.minecraftforge.gradle.MinecraftMappings; @@ -24,14 +22,19 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ExternalModuleDependency; import org.gradle.api.artifacts.ExternalModuleDependencyBundle; +import org.gradle.api.artifacts.dsl.ComponentMetadataHandler; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.attributes.Category; import org.gradle.api.attributes.DocsType; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.ProjectLayout; +import org.gradle.api.file.RegularFileProperty; import org.gradle.api.flow.FlowProviders; import org.gradle.api.flow.FlowScope; import org.gradle.api.initialization.Settings; +import org.gradle.api.initialization.resolve.DependencyResolutionManagement; +import org.gradle.api.initialization.resolve.RepositoriesMode; import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.JavaPluginExtension; @@ -40,10 +43,12 @@ import org.gradle.api.reflect.TypeOf; import org.gradle.api.tasks.TaskProvider; import org.gradle.plugins.ide.eclipse.model.EclipseModel; +import org.jetbrains.annotations.UnmodifiableView; import org.jspecify.annotations.Nullable; import javax.inject.Inject; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Predicate; @@ -52,34 +57,29 @@ abstract class MinecraftExtensionImpl implements MinecraftExtensionInternal { private final DirectoryProperty mavenizerOutput = getObjects().directoryProperty(); - final Property mappings = getObjects().property(MinecraftMappingsImpl.class); + private final Property mappings = getObjects().property(MinecraftMappingsInternal.class); - final ForgeGradleProblems problems = getObjects().newInstance(ForgeGradleProblems.class); + private final ForgeGradleProblems problems = getObjects().newInstance(ForgeGradleProblems.class); protected abstract @Inject ObjectFactory getObjects(); protected abstract @Inject ProviderFactory getProviders(); + // TODO [ForgeGradle] KnownPlugins system. See https://github.com/LexManos/ForgeGradle/commit/7c59cf3c8d54a89e01cd14a0c5ab75ea51918360 + // Specifically, the ability to hide external plugin types from method signatures and lambdas using a dummy MissingExtension + // Thankfully, this will very likely not affect the base DSL at all, making it only additive. + // But for now, MinecraftExtensionForProject and MinecraftDependency both implement MinecraftAccessTransformersContainer static void register( ForgeGradlePlugin plugin, ExtensionAware target ) { var extensions = target.getExtensions(); - if (target instanceof Project project) { - if (project.getPluginManager().hasPlugin("net.minecraftforge.accesstransformers")) { - try { - extensions.create(MinecraftExtension.NAME, ForProjectImpl.WithAccessTransformersImpl.class, plugin); - } catch (Exception e) { - var problems = project.getObjects().newInstance(ForgeGradleProblems.class); - throw problems.accessTransformersNotOnClasspath(e); - } - } else { - extensions.create(MinecraftExtension.NAME, ForProjectImpl.class, plugin); - } + if (target instanceof Project) { + extensions.create(MinecraftExtensionForProject.class, MinecraftExtension.NAME, ForProjectImpl.class, plugin); } else if (target instanceof Settings) { - extensions.create(MinecraftExtension.NAME, ForSettingsImpl.class, plugin, target); + extensions.create(MinecraftExtension.class, MinecraftExtension.NAME, ForSettingsImpl.class, plugin, target); } else { - extensions.create(MinecraftExtension.NAME, MinecraftExtensionImpl.class, plugin); + extensions.create(MinecraftExtension.class, MinecraftExtension.NAME, MinecraftExtensionImpl.class, plugin); } } @@ -89,8 +89,8 @@ public MinecraftExtensionImpl(ForgeGradlePlugin plugin) { } @Override - public TypeOf getPublicType() { - return MinecraftExtensionInternal.super.getPublicType(); + public Property getMappingsProperty() { + return this.mappings; } @Override @@ -125,6 +125,13 @@ public void mappings(String channel, String version) { this.mappings.set(replacement); } + // TODO [ForgeGradle] Do this better (most likely by getting a list of possible artifacts from Mavenizer) + static void applyComponentRules(ComponentMetadataHandler components) { + components.all(ForgeGradleComponentMetadataRules.AlwaysUseMatureStatus.class, ctor -> + ctor.params(List.of("net.minecraftforge:forge", "net.minecraftforge:fmlonly")) + ); + } + static abstract class ForSettingsImpl extends MinecraftExtensionImpl { @Inject public ForSettingsImpl(ForgeGradlePlugin plugin, Settings settings) { @@ -133,16 +140,21 @@ public ForSettingsImpl(ForgeGradlePlugin plugin, Settings settings) { } private void finish(Settings settings) { + // Attach shared data to Gradle instance (accessible to project) settings.getGradle().getExtensions().add( ForgeGradleSharedData.NAME, new ForgeGradleSharedData( - this.mappings.getOrNull() + this.getMappingsProperty().getOrNull() ) ); + + // Add component rules, even if they aren't used + // RulesMode.PREFER_PROJECT && !projectRules.isEmpty() -> use projectRules + applyComponentRules(settings.getDependencyResolutionManagement().getComponents()); } } - static abstract class ForProjectImpl extends MinecraftExtensionImpl implements ForProject { + static abstract class ForProjectImpl extends MinecraftExtensionImpl implements ForProject { private @Nullable TaskProvider genEclipseRuns; final DirectoryProperty eclipseOutputDir = getObjects().directoryProperty().convention(getProjectLayout().getProjectDirectory().dir("bin")); @@ -152,8 +164,17 @@ static abstract class ForProjectImpl minecraftDependencies = new ArrayList<>(); + // Access Transformers + private final boolean hasAccessTransformersPlugin; + private final ConfigurableFileCollection accessTransformer = getObjects().fileCollection(); + private final Property accessTransformerPath = getObjects().property(String.class); + + private final ForgeGradleProblems problems = getObjects().newInstance(ForgeGradleProblems.class); + protected abstract @Inject Project getProject(); + protected abstract @Inject DependencyResolutionManagement getDependencyResolutionManagement(); + protected abstract @Inject FlowScope getFlowScope(); protected abstract @Inject FlowProviders getFlowProviders(); @@ -164,35 +185,50 @@ static abstract class ForProjectImpl { + // TODO Report AccessTransformers applied in wrong order + }); + } + var sharedData = getProject().getGradle().getExtensions().findByType(ForgeGradleSharedData.class); if (sharedData != null) { - this.mappings.set(sharedData.mappings()); + this.getMappingsProperty().value(sharedData.mappings()); } plugin.queueMessage(ForgeGradleMessage.WELCOME); plugin.queueMessage(ForgeGradleMessage.MAGIC); - this.getFlowScope().always(ForgeGradleFlowAction.AccessTransformersMissing.class, spec -> spec.parameters(parameters -> { - parameters.getFailure().set(this.getFlowProviders().getBuildWorkResult().map(p -> p.getFailure().orElse(null))); - parameters.appliedPlugin.set(getProject().getPluginManager().hasPlugin("net.minecraftforge.accesstransformers")); + getFlowScope().always(ForgeGradleFlowAction.AccessTransformersMissing.class, spec -> spec.parameters(parameters -> { + parameters.getFailure().set(getFlowProviders().getBuildWorkResult().map(p -> p.getFailure().orElse(null))); + parameters.appliedPlugin.set(hasAccessTransformersPlugin); })); getProject().getConfigurations().configureEach(c -> c.withDependencies(d -> this.apply(c))); - getProject().getDependencies().attributesSchema(schema -> { - schema.attribute(ForgeAttributes.OperatingSystem.ATTRIBUTE, strategy -> { + // Dependencies + { + var dependencies = getProject().getDependencies(); + + try { + applyComponentRules(dependencies.getComponents()); + } catch (Exception ignored) { } + + var attributesSchema = dependencies.getAttributesSchema(); + attributesSchema.attribute(ForgeAttributes.OperatingSystem.ATTRIBUTE, strategy -> { var currentOS = getProviders().of(ForgeAttributes.OperatingSystem.CurrentValue.class, ForgeAttributes.OperatingSystem.CurrentValue.Parameters.DEFAULT).get(); strategy.getDisambiguationRules().add(ForgeAttributes.OperatingSystem.DisambiguationRule.class, ctor -> ctor.params(currentOS)); }); - - schema.attribute(ForgeAttributes.MappingsChannel.ATTRIBUTE, strategy -> + attributesSchema.attribute(ForgeAttributes.MappingsChannel.ATTRIBUTE, strategy -> strategy.getDisambiguationRules().add(ForgeAttributes.MappingsChannel.DisambiguationRule.class) ); - - schema.attribute(ForgeAttributes.MappingsVersion.ATTRIBUTE, strategy -> + attributesSchema.attribute(ForgeAttributes.MappingsVersion.ATTRIBUTE, strategy -> strategy.ordered(ForgeAttributes.MappingsVersion.COMPARATOR) ); - }); + } getProject().getPluginManager().withPlugin("eclipse", appliedEclipsePlugin -> { var eclipse = getProject().getExtensions().getByType(EclipseModel.class); @@ -211,22 +247,33 @@ public ForProjectImpl(ForgeGradlePlugin plugin) { } @Override - public TypeOf getPublicType() { - return new TypeOf>() { }; + public boolean hasAccessTransformersPlugin() { + return this.hasAccessTransformersPlugin; } @Override - public List getRepositories() { - var repositories = getObjects().namedDomainObjectList(MavenArtifactRepository.class); - repositories.addAll(getProject().getRepositories().withType(MavenArtifactRepository.class)); - try { - Settings settings = (Settings) InvokerHelper.getProperty(getProject().getGradle(), "settings"); - repositories.addAll(settings.getDependencyResolutionManagement().getRepositories().withType(MavenArtifactRepository.class)); - } catch (Exception e) { - problems.reportCannotAccessSettingsRepos(e); - } + public ConfigurableFileCollection getAccessTransformer() { + return this.accessTransformer; + } - return repositories; + @Override + public Property getAccessTransformerPath() { + return this.accessTransformerPath; + } + + @Override + public List getRepositories() { + var repositoriesMode = getDependencyResolutionManagement().getRepositoriesMode().getOrElse(RepositoriesMode.PREFER_PROJECT); + var projectRepositories = getProject().getRepositories().withType(MavenArtifactRepository.class); + var settingsRepositories = getDependencyResolutionManagement().getRepositories().withType(MavenArtifactRepository.class); + + return switch (repositoriesMode) { + case FAIL_ON_PROJECT_REPOS -> Collections.unmodifiableList(settingsRepositories); + case PREFER_SETTINGS -> + Collections.unmodifiableList(!projectRepositories.isEmpty() && settingsRepositories.isEmpty() ? projectRepositories : settingsRepositories); + case PREFER_PROJECT -> + Collections.unmodifiableList(!settingsRepositories.isEmpty() && projectRepositories.isEmpty() ? settingsRepositories : projectRepositories); + }; } @Override @@ -328,10 +375,6 @@ public NamedDomainObjectContainer getRuns() { return this.runs; } - Class getMinecraftDependencyClass() { - return MinecraftDependencyImpl.class; - } - @Override public ExternalModuleDependency dependency( Object value, @@ -344,7 +387,7 @@ public ExternalModuleDependency dependency( if (value instanceof ExternalModuleDependencyBundle) throw new IllegalArgumentException("Minecraft dependency cannot be a bundle"); - var minecraftDependency = (MinecraftDependencyInternal) this.getObjects().newInstance(this.getMinecraftDependencyClass(), this.getMavenizerOutput()); + var minecraftDependency = this.getObjects().newInstance(MinecraftDependencyImpl.class, this.getMavenizerOutput()); this.minecraftDependencies.add(minecraftDependency); return minecraftDependency.init(value, closure); } @@ -383,29 +426,5 @@ private void checkRepos(List repos) { problems.reportMcLibsMavenNotDeclared(); } } - - static abstract class WithAccessTransformersImpl extends ForProjectImpl implements WithAccessTransformers { - private final Property accessTransformers = this.getObjects().property(String.class); - - @Inject - public WithAccessTransformersImpl(ForgeGradlePlugin plugin) { - super(plugin); - } - - @Override - public TypeOf getPublicType() { - return WithAccessTransformers.super.getPublicType(); - } - - @Override - public Property getAccessTransformers() { - return this.accessTransformers; - } - - @Override - final Class getMinecraftDependencyClass() { - return MinecraftDependencyImpl.WithAccessTransformersImpl.class; - } - } } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java index c10f03538..b92ced259 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java @@ -4,65 +4,25 @@ */ package net.minecraftforge.gradle.internal; -import net.minecraftforge.gradle.ClosureOwner; import net.minecraftforge.gradle.MinecraftExtension; import net.minecraftforge.gradle.MinecraftExtensionForProject; -import net.minecraftforge.gradle.MinecraftExtensionForProjectWithAccessTransformers; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; -import org.gradle.api.attributes.Attribute; import org.gradle.api.file.DirectoryProperty; -import org.gradle.api.reflect.HasPublicType; -import org.gradle.api.reflect.TypeOf; +import org.gradle.api.provider.Property; +import org.jetbrains.annotations.UnmodifiableView; import java.util.List; -interface MinecraftExtensionInternal extends MinecraftExtension, HasPublicType, MinecraftMappingsContainerInternal { - @Override - default TypeOf getPublicType() { - return TypeOf.typeOf(MinecraftExtension.class); - } - - @Override - default Attributes getAttributes() { - return AttributesInternal.INSTANCE; - } +interface MinecraftExtensionInternal extends MinecraftExtension, MinecraftMappingsContainerInternal { + Property getMappingsProperty(); DirectoryProperty getMavenizerOutput(); - record AttributesInternal() implements Attributes { - static AttributesInternal INSTANCE = new AttributesInternal(); - - @Override - public Attribute getOs() { - return ForgeAttributes.OperatingSystem.ATTRIBUTE; - } - - @Override - public Attribute getMappingsChannel() { - return ForgeAttributes.MappingsChannel.ATTRIBUTE; - } - - @Override - public Attribute getMappingsVersion() { - return ForgeAttributes.MappingsVersion.ATTRIBUTE; - } - } - - interface ForProject extends MinecraftExtensionForProject, MinecraftExtensionInternal, HasPublicType { - @Override - default TypeOf getPublicType() { - return new TypeOf>() { }; - } - - List getRepositories(); + // NOTE: This internal interface does NOT implement MinecraftDependencyInternal as it is not actually a dependency! + // The top-level interface implements MinecraftDependency since it acts as a default for all Minecraft dependencies. + interface ForProject extends MinecraftExtensionForProject, MinecraftExtensionInternal, MinecraftAccessTransformersContainerInternal { + @UnmodifiableView List getRepositories(); DirectoryProperty getEclipseOutputDir(); - - interface WithAccessTransformers extends MinecraftExtensionForProjectWithAccessTransformers, MinecraftExtensionInternal.ForProject, HasPublicType { - @Override - default TypeOf getPublicType() { - return TypeOf.typeOf(MinecraftExtensionForProjectWithAccessTransformers.class); - } - } } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftMappingsContainerInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftMappingsContainerInternal.java index 77ffa7c8d..c6d4bcc94 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftMappingsContainerInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftMappingsContainerInternal.java @@ -12,7 +12,7 @@ import java.util.Map; interface MinecraftMappingsContainerInternal extends MinecraftMappingsContainer { - // NOTE: Overridden with @UnknownNullability, null is checked in MinecraftMappingsImpl + // NOTE: Overridden with @NullUnmarked, null is checked in MinecraftMappingsImpl @Override @NullUnmarked void mappings(String channel, String version); diff --git a/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java b/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java index 0c82853a1..0decd8d94 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java +++ b/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java @@ -12,12 +12,17 @@ import org.gradle.api.artifacts.ExternalModuleDependency; import org.gradle.api.artifacts.ModuleIdentifier; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.Directory; import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.RegularFile; +import org.gradle.api.file.RegularFileProperty; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.TaskProvider; @@ -30,23 +35,22 @@ @DisableCachingByDefault(because = "Mavenizer uses its own in-house caching") abstract class SyncMavenizer extends ToolExec { - static TaskProvider register(Project project, ExternalModuleDependency dependency, Provider mappings, Provider output) { + static TaskProvider register(Project project, ExternalModuleDependency dependency, Provider mappings, ConfigurableFileCollection accessTransformer, Provider output) { var version = dependency.getVersion(); var taskName = "syncMavenizerFor" + StringGroovyMethods.capitalize(dependency.getName()) + (version == null ? "" : version.replace(".", "").replace('-', '_')); var tasks = project.getTasks(); - try { - return tasks.named(taskName, SyncMavenizer.class); - } catch (UnknownDomainObjectException e) { - return project.getTasks().register(taskName, SyncMavenizer.class, task -> { - task.getOutput().set(output); - task.getModule().set(dependency.getModule()); - task.getVersion().set(dependency.getVersion()); - task.getMappings().set(mappings); - }); - } + return tasks.getNames().contains(taskName) + ? tasks.named(taskName, SyncMavenizer.class) + : tasks.register(taskName, SyncMavenizer.class, task -> { + task.getOutput().set(output); + task.getModule().set(dependency.getModule()); + task.getVersion().set(dependency.getVersion()); + task.getMappings().set(mappings); + task.getAccessTransformer().setFrom(accessTransformer); + }); } protected abstract @Internal DirectoryProperty getCaches(); @@ -59,6 +63,8 @@ static TaskProvider register(Project project, ExternalModuleDepen protected abstract @Input Property getMappings(); + protected abstract @InputFiles @Optional ConfigurableFileCollection getAccessTransformer(); + protected abstract @Input @Optional ListProperty getRepositories(); private void addRepositories(Iterable repositories) { @@ -84,7 +90,7 @@ public SyncMavenizer() { this.getCaches().convention(this.defaultToolDir.dir("caches")); - var minecraft = ((MinecraftExtensionInternal.ForProject) getProject().getExtensions().getByType(MinecraftExtensionForProject.class)); + var minecraft = ((MinecraftExtensionInternal.ForProject) getProject().getExtensions().getByType(MinecraftExtensionForProject.class)); this.addRepositories(minecraft.getRepositories()); } @@ -103,6 +109,7 @@ protected void addArguments() { this.args("--jdk-cache", this.getCaches()); this.args("--artifact", this.getModule()); this.args("--version", this.getVersion()); + this.args("--access-transformer", this.getAccessTransformer()); this.args("--global-auxiliary-variants"); if ("parchment".equals(this.getMappings().get().getChannel())) { diff --git a/src/main/java/net/minecraftforge/gradle/internal/Util.java b/src/main/java/net/minecraftforge/gradle/internal/Util.java index 9001cb167..a9a026488 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/Util.java +++ b/src/main/java/net/minecraftforge/gradle/internal/Util.java @@ -10,12 +10,16 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.Version; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSetContainer; import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; +import java.util.Locale; +import java.util.Map; final class Util extends SharedUtil { static String checkMappingsParam(ForgeGradleProblems problems, @Nullable Object param, String name) {