From a3bf692fb47614c1ca8cc8c17b6d1d087619ec1f Mon Sep 17 00:00:00 2001 From: Jonathing Date: Sun, 21 Dec 2025 16:34:53 -0500 Subject: [PATCH 1/6] Remove top-level WithAccessTransformers subtypes --- settings.gradle | 2 +- .../minecraftforge/gradle/ClosureOwner.java | 6 - ...MinecraftAccessTransformersContainer.java} | 10 +- .../gradle/MinecraftDependency.java | 2 +- .../gradle/MinecraftExtensionForProject.java | 7 +- ...nsionForProjectWithAccessTransformers.java | 42 ---- .../gradle/internal/ClosureOwnerImpl.java | 6 - .../gradle/internal/ClosureOwnerInternal.java | 195 +-------------- .../gradle/internal/ForgeAttributes.java | 2 +- .../ForgeGradleComponentMetadataRules.java | 19 ++ .../internal/ForgeGradleSharedData.java | 5 +- ...ftAccessTransformersContainerInternal.java | 23 ++ .../internal/MinecraftDependencyImpl.java | 235 ++++++++---------- .../internal/MinecraftDependencyInternal.java | 16 +- .../internal/MinecraftExtensionImpl.java | 125 +++++----- .../internal/MinecraftExtensionInternal.java | 15 +- .../MinecraftMappingsContainerInternal.java | 2 +- .../gradle/internal/SyncMavenizer.java | 2 +- .../minecraftforge/gradle/internal/Util.java | 4 + 19 files changed, 239 insertions(+), 479 deletions(-) rename src/main/java/net/minecraftforge/gradle/{MinecraftDependencyWithAccessTransformers.java => MinecraftAccessTransformersContainer.java} (86%) delete mode 100644 src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProjectWithAccessTransformers.java create mode 100644 src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java create mode 100644 src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java diff --git a/settings.gradle b/settings.gradle index f53b817e0..63b1a725b 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' 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/MinecraftDependencyWithAccessTransformers.java b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java similarity index 86% rename from src/main/java/net/minecraftforge/gradle/MinecraftDependencyWithAccessTransformers.java rename to src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java index 868df9c0d..4ac0f8c71 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftDependencyWithAccessTransformers.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java @@ -1,16 +1,8 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ package net.minecraftforge.gradle; 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"; 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/MinecraftExtensionForProject.java b/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java index 830a1d7ed..aaab308e6 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; @@ -18,7 +19,7 @@ /// /// @param The type of closure owner used for [#dependency] /// @see MinecraftExtension -public interface MinecraftExtensionForProject extends MinecraftExtension { +public interface MinecraftExtensionForProject extends MinecraftExtension, MinecraftAccessTransformersContainer { /// The collection of Slime Launcher options with which to create the launcher tasks. /// /// @return The collection of run task options @@ -53,7 +54,7 @@ default void runs(Action closure ); @@ -65,7 +66,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/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..6e9e57f2b 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; @@ -90,168 +91,15 @@ 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() { return this.getOwnerDelegate().getAccessTransformer(); @@ -267,39 +115,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/ForgeAttributes.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeAttributes.java index 1be8e04e5..be8876919 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeAttributes.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeAttributes.java @@ -98,6 +98,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..505663254 --- /dev/null +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java @@ -0,0 +1,19 @@ +package net.minecraftforge.gradle.internal; + +import org.gradle.api.artifacts.CacheableRule; +import org.gradle.api.artifacts.ComponentMetadataContext; +import org.gradle.api.artifacts.ComponentMetadataRule; + +final class ForgeGradleComponentMetadataRules { + @CacheableRule + abstract static class AlwaysUseMatureStatus implements ComponentMetadataRule { + @Override + public void execute(ComponentMetadataContext context) { + var details = context.getDetails(); + + 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/ForgeGradleSharedData.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java index a3f11ac27..e018163be 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java @@ -1,12 +1,9 @@ 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..785c67b83 --- /dev/null +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java @@ -0,0 +1,23 @@ +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..ba621dbc1 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java @@ -7,10 +7,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 +23,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.Directory; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.ProjectLayout; @@ -37,19 +32,16 @@ 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 +49,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)); + // Access Transformers + private final RegularFileProperty accessTransformer = this.getObjects().fileProperty().convention(minecraft.getAccessTransformer()); + private final Property accessTransformerPath = this.getObjects().property(String.class).convention(minecraft.getAccessTransformerPath()); + + // Dependency Information 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); 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 +78,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 +90,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 RegularFileProperty getAccessTransformer() { + return this.accessTransformer; + } + + @Override + public Property getAccessTransformerPath() { + return this.accessTransformerPath; + } + + /* INTERNAL */ + + private boolean hasAccessTransformers() { + return this.accessTransformer.isPresent() || this.accessTransformerPath.isPresent(); + } + // Can be nullable due to configuration caching. @Override public @Nullable ExternalModuleDependency asDependency() { @@ -142,7 +171,31 @@ public Action addAttributes() { } @Override - public void handle(Configuration configuration) { } + 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(); + + // Force the version we have in our configuration. + resolutionStrategy.force(moduleSelector); + + // Apply the dependency substitution for Access Transformers. + if (this.hasAccessTransformers()) { + var module = dependencySubstitution.module(moduleSelector); + try { + dependencySubstitution + .substitute(module) + .using(dependencySubstitution.variant(module, variant -> variant.attributes(attributes -> + attributes.attribute(this.registerAccessTransformer(), Boolean.TRUE))) + ) + .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) { @@ -163,7 +216,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 +229,62 @@ 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); - }; - } - - @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.isPresent() && 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.convention(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.convention(this.getProjectLayout().getProjectDirectory().file(this.accessTransformerPath.map(atPath -> "src/" + sourceSetName + "/resources/" + atPath))); } - ArtifactAccessTransformer.validateConfig(getProject(), asDependency(), this.atFile); + ArtifactAccessTransformer.validateConfig(getProject(), asDependency(), this.accessTransformer); } + } - 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); - })); + private Attribute registerAccessTransformer() { + var dependencies = getProject().getDependencies(); - spec.getFrom() - .attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE) - .attribute(Category.CATEGORY_ATTRIBUTE, spec.getFrom().named(Category.class, Category.LIBRARY)) - .attribute(attribute, false); + var attribute = Attribute.of("net.minecraftforge.gradle.accesstransformers.automatic." + this.getATIndex(), Boolean.class); - spec.getTo() - .attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE) - .attribute(Category.CATEGORY_ATTRIBUTE, spec.getTo().named(Category.class, Category.LIBRARY)) - .attribute(attribute, true); - }); + dependencies.getAttributesSchema().attribute(attribute); + dependencies.getArtifactTypes().named( + ArtifactTypeDefinition.JAR_TYPE, + type -> type.getAttributes().attribute(attribute, false) + ); - return attribute; - } + dependencies.registerTransform(ArtifactAccessTransformer.class, spec -> { + spec.parameters(ArtifactAccessTransformer.Parameters.defaults(getProject(), parameters -> { + parameters.getConfig().set(this.accessTransformer); + })); - private int getIndex() { - var ext = getProject().getGradle().getExtensions().getExtraProperties(); + spec.getFrom() + .attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE) + .attribute(Category.CATEGORY_ATTRIBUTE, spec.getFrom().named(Category.class, Category.LIBRARY)) + .attribute(attribute, false); - 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; - } + spec.getTo() + .attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE) + .attribute(Category.CATEGORY_ATTRIBUTE, spec.getTo().named(Category.class, Category.LIBRARY)) + .attribute(attribute, true); + }); - @Override - public RegularFileProperty getAccessTransformer() { - return this.atFile; - } + return attribute; + } - @Override - public void setAccessTransformer(String accessTransformer) { - this.atPath.set(accessTransformer); - } + private int getATIndex() { + var ext = getProject().getGradle().getExtensions().getExtraProperties(); - @Override - public void setAccessTransformer(boolean accessTransformer) { - if (accessTransformer) - this.setAccessTransformer(MinecraftDependencyWithAccessTransformers.DEFAULT_PATH); - else - this.atPath.unsetConvention().unset(); - } + 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; } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java index f3e0a7d92..1cae31a68 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,9 +22,7 @@ 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"; @@ -71,15 +68,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..91f4eef7d 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; @@ -29,6 +27,7 @@ import org.gradle.api.attributes.DocsType; 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; @@ -52,9 +51,9 @@ 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(); @@ -65,17 +64,8 @@ static void register( 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(MinecraftExtension.NAME, ForProjectImpl.class, plugin); } else if (target instanceof Settings) { extensions.create(MinecraftExtension.NAME, ForSettingsImpl.class, plugin, target); } else { @@ -93,6 +83,11 @@ public TypeOf getPublicType() { return MinecraftExtensionInternal.super.getPublicType(); } + @Override + public Property getMappingsProperty() { + return this.mappings; + } + @Override public DirectoryProperty getMavenizerOutput() { return this.mavenizerOutput; @@ -136,13 +131,13 @@ private void finish(Settings settings) { settings.getGradle().getExtensions().add( ForgeGradleSharedData.NAME, new ForgeGradleSharedData( - this.mappings.getOrNull() + this.getMappingsProperty().getOrNull() ) ); } } - 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,6 +147,13 @@ static abstract class ForProjectImpl minecraftDependencies = new ArrayList<>(); + // Access Transformers + private final boolean hasAccessTransformersPlugin; + private final RegularFileProperty accessTransformer = getObjects().fileProperty(); + private final Property accessTransformerPath = getObjects().property(String.class); + + private final ForgeGradleProblems problems = getObjects().newInstance(ForgeGradleProblems.class); + protected abstract @Inject Project getProject(); protected abstract @Inject FlowScope getFlowScope(); @@ -164,35 +166,53 @@ 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(); + var components = dependencies.getComponents(); + var attributesSchema = dependencies.getAttributesSchema(); + + try { + components.withModule("net.minecraftforge:forge", ForgeGradleComponentMetadataRules.AlwaysUseMatureStatus.class); + } catch (Exception e) { + // TODO Handle settings only rules + } + + 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); @@ -212,7 +232,22 @@ public ForProjectImpl(ForgeGradlePlugin plugin) { @Override public TypeOf getPublicType() { - return new TypeOf>() { }; + return TypeOf.typeOf(MinecraftExtensionForProject.class); + } + + @Override + public boolean hasAccessTransformersPlugin() { + return this.hasAccessTransformersPlugin; + } + + @Override + public RegularFileProperty getAccessTransformer() { + return this.accessTransformer; + } + + @Override + public Property getAccessTransformerPath() { + return this.accessTransformerPath; } @Override @@ -220,7 +255,7 @@ 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"); + var settings = (Settings) InvokerHelper.getProperty(getProject().getGradle(), "settings"); repositories.addAll(settings.getDependencyResolutionManagement().getRepositories().withType(MavenArtifactRepository.class)); } catch (Exception e) { problems.reportCannotAccessSettingsRepos(e); @@ -328,10 +363,6 @@ public NamedDomainObjectContainer getRuns() { return this.runs; } - Class getMinecraftDependencyClass() { - return MinecraftDependencyImpl.class; - } - @Override public ExternalModuleDependency dependency( Object value, @@ -344,7 +375,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 +414,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..e8c78d149 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java @@ -7,10 +7,10 @@ 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.provider.Property; import org.gradle.api.reflect.HasPublicType; import org.gradle.api.reflect.TypeOf; @@ -27,6 +27,8 @@ default Attributes getAttributes() { return AttributesInternal.INSTANCE; } + Property getMappingsProperty(); + DirectoryProperty getMavenizerOutput(); record AttributesInternal() implements Attributes { @@ -48,21 +50,14 @@ public Attribute getMappingsVersion() { } } - interface ForProject extends MinecraftExtensionForProject, MinecraftExtensionInternal, HasPublicType { + interface ForProject extends MinecraftExtensionForProject, MinecraftExtensionInternal, HasPublicType, MinecraftAccessTransformersContainerInternal { @Override default TypeOf getPublicType() { - return new TypeOf>() { }; + return TypeOf.typeOf(MinecraftExtensionForProject.class); } 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..7aca8235f 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java +++ b/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java @@ -84,7 +84,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()); } 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) { From 40a3163f65ca02ef0f3be3a9454e4a8977c24e18 Mon Sep 17 00:00:00 2001 From: Jonathing Date: Sun, 21 Dec 2025 17:22:59 -0500 Subject: [PATCH 2/6] Generalize impl of the plugin entry This will likely be a class generated by ASM in a future Gradle plugin that allows us to re-use this for all of our Gradle plugins. --- .../gradle/internal/ForgeGradlePluginEntry.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) 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); } } } From 8aa99236c134fc6f171db63a57f8ebe735aa251b Mon Sep 17 00:00:00 2001 From: Jonathing Date: Sun, 21 Dec 2025 17:23:29 -0500 Subject: [PATCH 3/6] Move Attributes to ForgeGradleExtension --- build.gradle | 4 +- .../gradle/ForgeGradleExtension.java | 45 +++++++++++++++++++ .../MinecraftAccessTransformersContainer.java | 3 +- .../gradle/MinecraftExtension.java | 45 ------------------- .../gradle/MinecraftExtensionForProject.java | 25 +---------- .../gradle/MinecraftMappings.java | 2 +- .../gradle/MinecraftMappingsContainer.java | 2 +- .../gradle/internal/Constants.java | 4 +- .../ForgeGradleExtensionInternal.java | 25 +++++++++++ .../internal/MinecraftExtensionInternal.java | 29 ++---------- 10 files changed, 81 insertions(+), 103 deletions(-) diff --git a/build.gradle b/build.gradle index d3669aa8e..1d9b46878 100644 --- a/build.gradle +++ b/build.gradle @@ -100,8 +100,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/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java b/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java index fccfb8e13..8e29aa25d 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 [#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/MinecraftAccessTransformersContainer.java b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java index 4ac0f8c71..135761fac 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java @@ -27,8 +27,7 @@ public interface MinecraftAccessTransformersContainer { /// 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/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 aaab308e6..e785df690 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java @@ -19,30 +19,7 @@ /// /// @param The type of closure owner used for [#dependency] /// @see MinecraftExtension -public interface MinecraftExtensionForProject extends MinecraftExtension, MinecraftAccessTransformersContainer { - /// 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. /// 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/Constants.java b/src/main/java/net/minecraftforge/gradle/internal/Constants.java index 2c6bc1183..1f154a93a 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/"; diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java index 189f5abac..098389b32 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java @@ -7,6 +7,7 @@ import net.minecraftforge.gradle.ForgeGradleExtension; import org.gradle.api.Action; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; +import org.gradle.api.attributes.Attribute; import org.gradle.api.reflect.HasPublicType; import org.gradle.api.reflect.TypeOf; @@ -35,4 +36,28 @@ default Action getForgeMaven() { default Action getMinecraftLibsMaven() { return minecraftLibsMaven; } + + @Override + default Attributes getAttributes() { + return ForgeGradleExtensionInternal.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/MinecraftExtensionInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java index e8c78d149..afd197395 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java @@ -4,11 +4,10 @@ */ package net.minecraftforge.gradle.internal; -import net.minecraftforge.gradle.ClosureOwner; +import net.minecraftforge.gradle.ForgeGradleExtension; import net.minecraftforge.gradle.MinecraftExtension; import net.minecraftforge.gradle.MinecraftExtensionForProject; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; -import org.gradle.api.attributes.Attribute; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.provider.Property; import org.gradle.api.reflect.HasPublicType; @@ -22,34 +21,12 @@ default TypeOf getPublicType() { return TypeOf.typeOf(MinecraftExtension.class); } - @Override - default Attributes getAttributes() { - return AttributesInternal.INSTANCE; - } - 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; - } - } - + // 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, HasPublicType, MinecraftAccessTransformersContainerInternal { @Override default TypeOf getPublicType() { From 3d0289fd42db361526872858e42373f4300c04bf Mon Sep 17 00:00:00 2001 From: Jonathing Date: Sun, 21 Dec 2025 17:54:28 -0500 Subject: [PATCH 4/6] Declare extensions' public type on creation, not via interface --- .../internal/ForgeGradleExtensionImpl.java | 5 ++--- .../ForgeGradleExtensionInternal.java | 11 ++-------- .../internal/MinecraftExtensionImpl.java | 20 +++++++------------ .../internal/MinecraftExtensionInternal.java | 17 ++-------------- 4 files changed, 13 insertions(+), 40 deletions(-) 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 098389b32..be82a58c5 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleExtensionInternal.java @@ -8,15 +8,8 @@ import org.gradle.api.Action; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.attributes.Attribute; -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); - } +interface ForgeGradleExtensionInternal extends ForgeGradleExtension { Action forgeMaven = repo -> { repo.setName("MinecraftForge"); repo.setUrl(Constants.FORGE_MAVEN); @@ -39,7 +32,7 @@ default Action getMinecraftLibsMaven() { @Override default Attributes getAttributes() { - return ForgeGradleExtensionInternal.AttributesInternal.INSTANCE; + return AttributesInternal.INSTANCE; } record AttributesInternal() implements Attributes { diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java index 91f4eef7d..cf888dd1a 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java @@ -59,17 +59,21 @@ abstract class MinecraftExtensionImpl implements MinecraftExtensionInternal { 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) { - extensions.create(MinecraftExtension.NAME, ForProjectImpl.class, plugin); + 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); } } @@ -78,11 +82,6 @@ public MinecraftExtensionImpl(ForgeGradlePlugin plugin) { this.mavenizerOutput.convention(plugin.localCaches().dir("mavenizer/output").map(this.problems.ensureFileLocation())); } - @Override - public TypeOf getPublicType() { - return MinecraftExtensionInternal.super.getPublicType(); - } - @Override public Property getMappingsProperty() { return this.mappings; @@ -230,11 +229,6 @@ public ForProjectImpl(ForgeGradlePlugin plugin) { getProject().afterEvaluate(this::finish); } - @Override - public TypeOf getPublicType() { - return TypeOf.typeOf(MinecraftExtensionForProject.class); - } - @Override public boolean hasAccessTransformersPlugin() { return this.hasAccessTransformersPlugin; diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java index afd197395..ddae2e978 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java @@ -4,35 +4,22 @@ */ package net.minecraftforge.gradle.internal; -import net.minecraftforge.gradle.ForgeGradleExtension; import net.minecraftforge.gradle.MinecraftExtension; import net.minecraftforge.gradle.MinecraftExtensionForProject; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.provider.Property; -import org.gradle.api.reflect.HasPublicType; -import org.gradle.api.reflect.TypeOf; import java.util.List; -interface MinecraftExtensionInternal extends MinecraftExtension, HasPublicType, MinecraftMappingsContainerInternal { - @Override - default TypeOf getPublicType() { - return TypeOf.typeOf(MinecraftExtension.class); - } - +interface MinecraftExtensionInternal extends MinecraftExtension, MinecraftMappingsContainerInternal { Property getMappingsProperty(); DirectoryProperty getMavenizerOutput(); // 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, HasPublicType, MinecraftAccessTransformersContainerInternal { - @Override - default TypeOf getPublicType() { - return TypeOf.typeOf(MinecraftExtensionForProject.class); - } - + interface ForProject extends MinecraftExtensionForProject, MinecraftExtensionInternal, MinecraftAccessTransformersContainerInternal { List getRepositories(); DirectoryProperty getEclipseOutputDir(); From 782eb366d8a4af9814c9bd708f62994651be7b61 Mon Sep 17 00:00:00 2001 From: Jonathing Date: Sun, 21 Dec 2025 20:24:43 -0500 Subject: [PATCH 5/6] Pivot to completely gutting out at-gradle --- build.gradle | 3 - settings.gradle | 4 - .../gradle/ForgeGradleExtension.java | 4 +- .../MinecraftAccessTransformersContainer.java | 4 + .../gradle/MinecraftExtensionForProject.java | 1 - .../gradle/internal/Constants.java | 6 +- .../gradle/internal/ForgeAttributes.java | 4 + .../ForgeGradleComponentMetadataRules.java | 15 +++ .../internal/ForgeGradleSharedData.java | 4 + ...ftAccessTransformersContainerInternal.java | 4 + .../internal/MinecraftDependencyImpl.java | 91 +++++-------------- .../internal/MinecraftDependencyInternal.java | 3 - .../internal/MinecraftExtensionImpl.java | 49 ++++++---- .../internal/MinecraftExtensionInternal.java | 3 +- .../gradle/internal/SyncMavenizer.java | 30 +++--- 15 files changed, 112 insertions(+), 113 deletions(-) diff --git a/build.gradle b/build.gradle index 1d9b46878..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 diff --git a/settings.gradle b/settings.gradle index 63b1a725b..8ba109688 100644 --- a/settings.gradle +++ b/settings.gradle @@ -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/ForgeGradleExtension.java b/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java index 8e29aa25d..60639de2c 100644 --- a/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java +++ b/src/main/java/net/minecraftforge/gradle/ForgeGradleExtension.java @@ -75,7 +75,7 @@ interface Attributes { /// The requested mappings channel of the project. /// - /// This is determined using [MinecraftMappings#getChannel()] via [#getMappings()] + /// This is determined using [MinecraftMappings#getChannel()] via [MinecraftMappingsContainer#getMappings()] /// /// @return The mappings channel attribute /// @see #getMappingsVersion() @@ -83,7 +83,7 @@ interface Attributes { /// The requested mappings version of the project. /// - /// This is determined using [MinecraftMappings#getVersion()] via [#getMappings()] + /// This is determined using [MinecraftMappings#getVersion()] via [MinecraftMappingsContainer#getMappings()] /// /// @return The mappings channel version /// @see #getMappingsChannel() diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java index 135761fac..f96d159d4 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java @@ -1,3 +1,7 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ package net.minecraftforge.gradle; import org.gradle.api.file.RegularFileProperty; diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java b/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java index e785df690..ae942d764 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftExtensionForProject.java @@ -17,7 +17,6 @@ /// [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, MinecraftDependency { /// Creates (or marks if existing) the given dependency as a Minecraft dependency and configures it with the given diff --git a/src/main/java/net/minecraftforge/gradle/internal/Constants.java b/src/main/java/net/minecraftforge/gradle/internal/Constants.java index 1f154a93a..736cec03d 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/Constants.java +++ b/src/main/java/net/minecraftforge/gradle/internal/Constants.java @@ -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 be8876919..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; diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java index 505663254..14bb4d3a7 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleComponentMetadataRules.java @@ -1,15 +1,30 @@ +/* + * 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); diff --git a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java index e018163be..c0f6b98b6 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ForgeGradleSharedData.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 org.jspecify.annotations.Nullable; diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java index 785c67b83..b60b57be1 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftAccessTransformersContainerInternal.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.gradle.MinecraftAccessTransformersContainer; diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java index ba621dbc1..91cc3687e 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyImpl.java @@ -6,7 +6,6 @@ import groovy.lang.Closure; import groovy.transform.NamedVariant; -import net.minecraftforge.accesstransformers.gradle.ArtifactAccessTransformer; import net.minecraftforge.gradle.MinecraftExtensionForProject; import net.minecraftforge.gradle.MinecraftMappings; import net.minecraftforge.gradle.SlimeLauncherOptions; @@ -23,7 +22,6 @@ import org.gradle.api.artifacts.type.ArtifactTypeDefinition; import org.gradle.api.attributes.Attribute; import org.gradle.api.attributes.AttributeContainer; -import org.gradle.api.attributes.Category; import org.gradle.api.file.Directory; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.ProjectLayout; @@ -34,7 +32,6 @@ import org.gradle.api.plugins.ExtensionAware; 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.jspecify.annotations.Nullable; @@ -53,14 +50,14 @@ abstract class MinecraftDependencyImpl implements MinecraftDependencyInternal { private final MinecraftExtensionInternal.ForProject minecraft = ((MinecraftExtensionInternal.ForProject) getProject().getExtensions().getByType(MinecraftExtensionForProject.class)); // Access Transformers - private final RegularFileProperty accessTransformer = this.getObjects().fileProperty().convention(minecraft.getAccessTransformer()); - private final Property accessTransformerPath = this.getObjects().property(String.class).convention(minecraft.getAccessTransformerPath()); + private final RegularFileProperty accessTransformer = this.getObjects().fileProperty(); + private final Property accessTransformerPath = this.getObjects().property(String.class); // Dependency Information - 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); + 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(MinecraftMappingsInternal.class); @@ -155,7 +152,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)); @@ -165,11 +162,6 @@ public ExternalModuleDependency init(Object dependencyNotation, Closure closu return this.delegate = dependency; } - @Override - public Action addAttributes() { - return attributes -> { }; - } - @Override public void handle(Configuration configuration) { if (configuration.isCanBeResolved()) { @@ -177,19 +169,17 @@ public void handle(Configuration configuration) { var resolutionStrategy = configuration.getResolutionStrategy(); var dependencySubstitution = resolutionStrategy.getDependencySubstitution(); - // Force the version we have in our configuration. - resolutionStrategy.force(moduleSelector); - - // Apply the dependency substitution for Access Transformers. - if (this.hasAccessTransformers()) { + // 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.attribute(this.registerAccessTransformer(), Boolean.TRUE))) - ) - .because("Applies AccessTransformers"); + .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); } @@ -230,61 +220,24 @@ public void handle(NamedDomainObjectSet sourceSets, NamedDomainObject }); }); - if (this.accessTransformer.isPresent() && this.accessTransformerPath.isPresent() && !sourceSets.isEmpty()) { + if (!this.accessTransformer.isPresent() && !this.accessTransformerPath.isPresent()) { + this.accessTransformer.convention(minecraft.getAccessTransformer()); + this.accessTransformerPath.convention(minecraft.getAccessTransformerPath()); + } + + if (!this.accessTransformer.isPresent() && this.accessTransformerPath.isPresent() && !sourceSets.isEmpty()) { var sourceSet = sourceSets.iterator().next(); var itor = sourceSet.getResources().getSrcDirs().iterator(); if (itor.hasNext()) { var file = itor.next(); - this.accessTransformer.convention(this.getProjectLayout().file(this.accessTransformerPath.map(atPath -> new File(file, atPath)))); + this.accessTransformer.value(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.accessTransformer.convention(this.getProjectLayout().getProjectDirectory().file(this.accessTransformerPath.map(atPath -> "src/" + sourceSetName + "/resources/" + atPath))); + this.accessTransformer.value(this.getProjectLayout().getProjectDirectory().file(this.accessTransformerPath.map(atPath -> "src/" + sourceSetName + "/resources/" + atPath))); } - - ArtifactAccessTransformer.validateConfig(getProject(), asDependency(), this.accessTransformer); } } - - private Attribute registerAccessTransformer() { - var dependencies = getProject().getDependencies(); - - var attribute = Attribute.of("net.minecraftforge.gradle.accesstransformers.automatic." + this.getATIndex(), 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.accessTransformer); - })); - - 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 getATIndex() { - 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; - } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java index 1cae31a68..bc664c0e1 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftDependencyInternal.java @@ -24,7 +24,6 @@ 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() { @@ -59,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()); } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java index cf888dd1a..500b01739 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java @@ -22,6 +22,7 @@ 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; @@ -31,6 +32,8 @@ 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; @@ -39,10 +42,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; @@ -119,6 +124,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) { @@ -127,12 +139,17 @@ 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.getMappingsProperty().getOrNull() ) ); + + // Add component rules, even if they aren't used + // RulesMode.PREFER_PROJECT && !projectRules.isEmpty() -> use projectRules + applyComponentRules(settings.getDependencyResolutionManagement().getComponents()); } } @@ -155,6 +172,8 @@ static abstract class ForProjectImpl extends MinecraftExtensionImpl implements F protected abstract @Inject Project getProject(); + protected abstract @Inject DependencyResolutionManagement getDependencyResolutionManagement(); + protected abstract @Inject FlowScope getFlowScope(); protected abstract @Inject FlowProviders getFlowProviders(); @@ -192,15 +211,12 @@ public ForProjectImpl(ForgeGradlePlugin plugin) { // Dependencies { var dependencies = getProject().getDependencies(); - var components = dependencies.getComponents(); - var attributesSchema = dependencies.getAttributesSchema(); try { - components.withModule("net.minecraftforge:forge", ForgeGradleComponentMetadataRules.AlwaysUseMatureStatus.class); - } catch (Exception e) { - // TODO Handle settings only rules - } + 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)); @@ -246,16 +262,17 @@ public Property getAccessTransformerPath() { @Override public List getRepositories() { - var repositories = getObjects().namedDomainObjectList(MavenArtifactRepository.class); - repositories.addAll(getProject().getRepositories().withType(MavenArtifactRepository.class)); - try { - var settings = (Settings) InvokerHelper.getProperty(getProject().getGradle(), "settings"); - repositories.addAll(settings.getDependencyResolutionManagement().getRepositories().withType(MavenArtifactRepository.class)); - } catch (Exception e) { - problems.reportCannotAccessSettingsRepos(e); - } - - return repositories; + 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 diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java index ddae2e978..b92ced259 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionInternal.java @@ -9,6 +9,7 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.provider.Property; +import org.jetbrains.annotations.UnmodifiableView; import java.util.List; @@ -20,7 +21,7 @@ interface MinecraftExtensionInternal extends MinecraftExtension, MinecraftMappin // 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 { - List getRepositories(); + @UnmodifiableView List getRepositories(); DirectoryProperty getEclipseOutputDir(); } diff --git a/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java b/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java index 7aca8235f..efbf4b561 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,23 @@ @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, Provider 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); + if (accessTransformer.isPresent()) + task.getAccessTransformer().setFrom(accessTransformer); + }); } protected abstract @Internal DirectoryProperty getCaches(); @@ -59,6 +64,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) { @@ -103,6 +110,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())) { From f5a8e48038b85ad355c5c5152b6cefe454e67390 Mon Sep 17 00:00:00 2001 From: Jonathing Date: Sun, 21 Dec 2025 21:35:44 -0500 Subject: [PATCH 6/6] Bake in support for multiple AT configs --- .../MinecraftAccessTransformersContainer.java | 3 ++- .../gradle/internal/ClosureOwnerInternal.java | 3 ++- .../gradle/internal/MinecraftDependencyImpl.java | 15 ++++++++------- .../gradle/internal/MinecraftExtensionImpl.java | 5 +++-- .../gradle/internal/SyncMavenizer.java | 5 ++--- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java index f96d159d4..33825ce10 100644 --- a/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java +++ b/src/main/java/net/minecraftforge/gradle/MinecraftAccessTransformersContainer.java @@ -4,6 +4,7 @@ */ package net.minecraftforge.gradle; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.RegularFileProperty; public interface MinecraftAccessTransformersContainer { @@ -14,7 +15,7 @@ public interface MinecraftAccessTransformersContainer { /// 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. diff --git a/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java b/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java index 6e9e57f2b..b483b6ae5 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java +++ b/src/main/java/net/minecraftforge/gradle/internal/ClosureOwnerInternal.java @@ -26,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; @@ -101,7 +102,7 @@ default void runs(Action accessTransformerPath = this.getObjects().property(String.class); // Dependency Information @@ -107,7 +108,7 @@ public void mappings(String channel, String version) { } @Override - public RegularFileProperty getAccessTransformer() { + public ConfigurableFileCollection getAccessTransformer() { return this.accessTransformer; } @@ -119,7 +120,7 @@ public Property getAccessTransformerPath() { /* INTERNAL */ private boolean hasAccessTransformers() { - return this.accessTransformer.isPresent() || this.accessTransformerPath.isPresent(); + return !this.accessTransformer.isEmpty() || this.accessTransformerPath.isPresent(); } // Can be nullable due to configuration caching. @@ -220,23 +221,23 @@ public void handle(NamedDomainObjectSet sourceSets, NamedDomainObject }); }); - if (!this.accessTransformer.isPresent() && !this.accessTransformerPath.isPresent()) { + if (this.accessTransformer.isEmpty() && !this.accessTransformerPath.isPresent()) { this.accessTransformer.convention(minecraft.getAccessTransformer()); this.accessTransformerPath.convention(minecraft.getAccessTransformerPath()); } - if (!this.accessTransformer.isPresent() && this.accessTransformerPath.isPresent() && !sourceSets.isEmpty()) { + 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.accessTransformer.value(this.getProjectLayout().file(this.accessTransformerPath.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.accessTransformer.value(this.getProjectLayout().getProjectDirectory().file(this.accessTransformerPath.map(atPath -> "src/" + sourceSetName + "/resources/" + atPath))); + this.accessTransformer.setFrom(this.getProjectLayout().getProjectDirectory().file(this.accessTransformerPath.map(atPath -> "src/" + sourceSetName + "/resources/" + atPath))); } } } diff --git a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java index 500b01739..83ed05247 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java +++ b/src/main/java/net/minecraftforge/gradle/internal/MinecraftExtensionImpl.java @@ -26,6 +26,7 @@ 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; @@ -165,7 +166,7 @@ static abstract class ForProjectImpl extends MinecraftExtensionImpl implements F // Access Transformers private final boolean hasAccessTransformersPlugin; - private final RegularFileProperty accessTransformer = getObjects().fileProperty(); + private final ConfigurableFileCollection accessTransformer = getObjects().fileCollection(); private final Property accessTransformerPath = getObjects().property(String.class); private final ForgeGradleProblems problems = getObjects().newInstance(ForgeGradleProblems.class); @@ -251,7 +252,7 @@ public boolean hasAccessTransformersPlugin() { } @Override - public RegularFileProperty getAccessTransformer() { + public ConfigurableFileCollection getAccessTransformer() { return this.accessTransformer; } diff --git a/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java b/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java index efbf4b561..0decd8d94 100644 --- a/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java +++ b/src/main/java/net/minecraftforge/gradle/internal/SyncMavenizer.java @@ -35,7 +35,7 @@ @DisableCachingByDefault(because = "Mavenizer uses its own in-house caching") abstract class SyncMavenizer extends ToolExec { - static TaskProvider register(Project project, ExternalModuleDependency dependency, Provider mappings, Provider accessTransformer, 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()) @@ -49,8 +49,7 @@ static TaskProvider register(Project project, ExternalModuleDepen task.getModule().set(dependency.getModule()); task.getVersion().set(dependency.getVersion()); task.getMappings().set(mappings); - if (accessTransformer.isPresent()) - task.getAccessTransformer().setFrom(accessTransformer); + task.getAccessTransformer().setFrom(accessTransformer); }); }