Skip to content

Commit 206002b

Browse files
authored
Re-implement Mavenizer invocation as a task (#996)
- Add the first documentation page - All documentation pages will be moved to MinecraftForge/Documentation OR its own repo if necessary when the time comes - Create the ForgeGradle Magic plugin - Currently does nothing, but lays the groundwork for what it will need to do later on. - Re-implement Mavenizer invocation
1 parent e68f2a0 commit 206002b

21 files changed

+906
-573
lines changed

docs/Overview.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# ForgeGradle
2+
3+
[![Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/net.minecraftforge.gradle)](https://plugins.gradle.org/plugin/net.minecraftforge.gradle)
4+
5+
Welcome to ForgeGradle, Minecraft Forge's Gradle plugin. It is a small, simple,
6+
and effective plugin with the primary purpose of bootstrapping Minecraft Forge's
7+
toolchain to aid in the development of mods targeting Minecraft Forge.
8+
9+
## Basic Usage
10+
11+
### Applying the Plugin
12+
13+
ForgeGradle 7 can be applied to projects or settings by using the following:
14+
15+
```groovy
16+
plugins {
17+
id 'net.minecraftforge.gradle' version '<version>'
18+
}
19+
```
20+
21+
ForgeGradle 7 and later can now be found on the
22+
[Gradle Plugin Portal][Gradle Plugin Portal]. Adding the Forge maven to the
23+
plugin management repositories is no longer necessary.
24+
25+
### Depending on Minecraft
26+
27+
```groovy
28+
dependencies {
29+
implementation minecraft.dependency('net.minecraftforge:forge:1.21.10-60.0.0')
30+
}
31+
```
32+
33+
## API Design
34+
35+
ForgeGradle 7, the latest iteration of ForgeGradle, has a completely different
36+
approach to API design. If you plan on interfacing with the plugin in
37+
unconventional ways, there are a few things to keep in mind.
38+
39+
- ForgeGradle is **stateless by default.**
40+
- This means that if nothing is asked of it, it will not do anything.
41+
- The only exception to this rule is ForgeGradle Magic, which is covered in
42+
its own documentation entry.
43+
- ForgeGradle's **implementation and internal code is inaccessible.**
44+
- All implementations are package-private, so they cannot be accessed by other
45+
plugins or extended from. Everything that is public API has been
46+
deliberately made so.
47+
- ForgeGradle is **not the toolchain.**
48+
- Unlike ForgeGradle 6 and its predecessors, ForgeGradle 7 does not include
49+
the toolchain. It instead acts as the configuring interface and invocation
50+
of the toolchain. If you are interested in contributing to the toolchain,
51+
please see the [Minecraft Mavenizer][Mavenizer].
52+
53+
[Gradle Plugin Portal]: https://plugins.gradle.org
54+
[Mavenizer]: https://github.com/MinecraftForge/MinecraftMavenizer

settings.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ gradle.beforeProject { Project project ->
2020

2121
//@formatter:off
2222
dependencyResolutionManagement.versionCatalogs.register('libs') {
23-
version 'gradleutils', '3.3.18'
23+
version 'gradleutils', '3.3.20'
2424

2525
plugin 'licenser', 'net.minecraftforge.licenser' version '1.2.0' // https://plugins.gradle.org/plugin/net.minecraftforge.licenser
2626
plugin 'gradleutils', 'net.minecraftforge.gradleutils' versionRef 'gradleutils'
@@ -43,7 +43,7 @@ dependencyResolutionManagement.versionCatalogs.register('libs') {
4343

4444
// AccessTransformers Gradle Plugin
4545
// https://plugins.gradle.org/plugin/net.minecraftforge.accesstransformers
46-
library 'accesstransformers-gradle', 'net.minecraftforge.accesstransformers', 'net.minecraftforge.accesstransformers.gradle.plugin' version '5.0.0-beta.8'
46+
library 'accesstransformers-gradle', 'net.minecraftforge.accesstransformers', 'net.minecraftforge.accesstransformers.gradle.plugin' version '5.0.1'
4747

4848
library 'utils-data', 'net.minecraftforge', 'json-data-utils' version '0.3.0' // https://files.minecraftforge.net/net/minecraftforge/json-data-utils/index.html
4949
library 'utils-hash', 'net.minecraftforge', 'hash-utils' version '0.1.10' // https://files.minecraftforge.net/net/minecraftforge/hash-utils/index.html

src/main/java/net/minecraftforge/gradle/Constants.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ final class Constants {
1818
static final String SLIMELAUNCHER_MAIN = "net.minecraftforge.launcher.Main";
1919

2020
static final String MAVENIZER_NAME = "mavenizer";
21-
static final String MAVENIZER_VERSION = "0.3.17";
21+
static final String MAVENIZER_VERSION = "0.3.25";
2222
static final String MAVENIZER_DL_URL = "https://maven.minecraftforge.net/net/minecraftforge/minecraft-mavenizer/" + MAVENIZER_VERSION + "/minecraft-mavenizer-" + MAVENIZER_VERSION + ".jar";
2323
static final int MAVENIZER_JAVA_VERSION = 21;
2424
static final String MAVENIZER_MAIN = "net.minecraftforge.mcmaven.cli.Main";
@@ -58,5 +58,19 @@ If you are on an older version (1.20.4 and older), you will need the
5858
{}
5959
6060
For more details on this release, see https://docs.minecraftforge.net/en/fg-7.0/""";
61+
62+
static final String MAGIC = """
63+
This build is using ForgeGradle Magic. ForgeGradle Magic employs automatic
64+
behavior that is hidden from buildscript authors in order to implement and
65+
account for convenience features.
66+
67+
Magic is enabled by default. It can be disabled by using the following
68+
Gradle property:
69+
net.minecraftforge.gradle.magic=false
70+
71+
This message will not display again unless the below file is deleted:
72+
{}
73+
74+
For more information, see https://docs.minecraftforge.net/en/fg-7.0/magic/""";
6175
}
6276
}

src/main/java/net/minecraftforge/gradle/ForgeGradleFlowAction.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,46 @@ protected void run(Parameters parameters) throws IOException {
6363
}
6464
}
6565

66+
static abstract class MagicMessage extends ForgeGradleFlowAction<MagicMessage.Parameters> {
67+
enum DisplayOption {
68+
ONCE, NEVER, ALWAYS
69+
}
70+
71+
static abstract class Parameters extends ForgeGradleFlowAction.Parameters {
72+
final DirectoryProperty messagesDir;
73+
final Property<DisplayOption> displayOption;
74+
75+
protected abstract @Inject ProviderFactory getProviders();
76+
77+
@Inject
78+
public Parameters() {
79+
this.messagesDir = this.getObjects().directoryProperty();
80+
this.displayOption = this.getObjects().property(DisplayOption.class).convention(DisplayOption.ONCE).value(
81+
this.getProviders().gradleProperty("net.minecraftforge.gradle.messages.magic")
82+
.orElse(this.getProviders().systemProperty("net.minecraftforge.gradle.messages.magic"))
83+
.map(it -> DisplayOption.valueOf(it.toUpperCase(Locale.ROOT)))
84+
);
85+
}
86+
}
87+
88+
@Inject
89+
public MagicMessage() { }
90+
91+
@Override
92+
protected void run(Parameters parameters) throws IOException {
93+
// if build failed, don't bother
94+
if (parameters.getFailure().isPresent()) return;
95+
96+
// check for marker file
97+
var markerFile = parameters.messagesDir.file("7_0_BETA_MAGIC_1").get().getAsFile();
98+
if (markerFile.exists()) return;
99+
Files.createDirectories(markerFile.toPath().getParent());
100+
Files.createFile(markerFile.toPath());
101+
102+
LOGGER.lifecycle(Constants.Messages.MAGIC, markerFile.getAbsolutePath());
103+
}
104+
}
105+
66106
static abstract class AccessTransformersMissing extends ForgeGradleFlowAction<AccessTransformersMissing.Parameters> {
67107
static abstract class Parameters extends ForgeGradleFlowAction.Parameters {
68108
final Property<Boolean> appliedPlugin = this.getObjects().property(Boolean.class).convention(false);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) Forge Development LLC and contributors
3+
* SPDX-License-Identifier: LGPL-2.1-only
4+
*/
5+
package net.minecraftforge.gradle;
6+
7+
import net.minecraftforge.gradleutils.shared.EnhancedPlugin;
8+
import org.gradle.api.Project;
9+
import org.gradle.api.logging.Logger;
10+
import org.gradle.api.logging.Logging;
11+
12+
import javax.inject.Inject;
13+
14+
abstract class ForgeGradleMagicPlugin extends EnhancedPlugin<Project> {
15+
static final String NAME = "forgegradle-magic";
16+
static final String DISPLAY_NAME = "ForgeGradle Magic";
17+
18+
static final Logger LOGGER = Logging.getLogger(ForgeGradleMagicPlugin.class);
19+
20+
@Inject
21+
public ForgeGradleMagicPlugin() {
22+
super(NAME, DISPLAY_NAME);
23+
}
24+
25+
@Override
26+
public void setup(Project project) {
27+
28+
}
29+
}

src/main/java/net/minecraftforge/gradle/ForgeGradlePlugin.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package net.minecraftforge.gradle;
66

77
import net.minecraftforge.gradleutils.shared.EnhancedPlugin;
8+
import org.gradle.api.Project;
89
import org.gradle.api.logging.Logger;
910
import org.gradle.api.logging.Logging;
1011
import org.gradle.api.plugins.ExtensionAware;
@@ -17,13 +18,24 @@ abstract class ForgeGradlePlugin extends EnhancedPlugin<ExtensionAware> {
1718

1819
static final Logger LOGGER = Logging.getLogger(ForgeGradlePlugin.class);
1920

21+
private final ForgeGradleProblems problems = this.getObjects().newInstance(ForgeGradleProblems.class);
22+
23+
static {
24+
LOGGER.lifecycle("ForgeGradle 7 is an incubating plugin.");
25+
}
26+
2027
@Inject
2128
public ForgeGradlePlugin() {
2229
super(NAME, DISPLAY_NAME, "fgtools");
2330
}
2431

2532
@Override
2633
public void setup(ExtensionAware target) {
34+
if (target instanceof Project project && !problems.testFalse("net.minecraftforge.gradle.magic")) {
35+
LOGGER.info("Applying ForgeGradle Magic to {}", project);
36+
project.getPluginManager().apply(ForgeGradleMagicPlugin.class);
37+
}
38+
2739
ForgeGradleExtensionImpl.register(this, target);
2840
MinecraftExtensionImpl.register(this, target);
2941
}

src/main/java/net/minecraftforge/gradle/ForgeGradleProblems.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,21 @@ RuntimeException changingMinecraftDependency(Dependency dependency) {
124124
//endregion
125125

126126
//region Minecraft Maven
127+
RuntimeException mavenizerOutOfDateCompile(Dependency dependency) {
128+
return this.throwing(new IllegalStateException(), "mavenizer-out-of-date", "Minecraft Mavenizer is out-of-date", spec -> spec
129+
.details("""
130+
Gradle cannot compile your sources because the Minecraft Mavenizer is out-of-date.
131+
The Mavenizer must be re-run in order for the changes made to the Minecraft dependency to take effect.
132+
Affected dependency: '%s'"""
133+
.formatted(dependency))
134+
.severity(Severity.ERROR)
135+
.solution("Re-import your project in your IDE, as this will automatically synchronize the Mavenizer.")
136+
.solution("Run `gradlew` with no arguments, as this will automatically synchronize the Mavenizer.")
137+
.solution("Manually run the `syncMavenizer` task, located in the 'Build Setup' group.")
138+
.solution("Temporary revert any edits to the Minecraft dependency until the Mavenizer is re-run.")
139+
.solution(HELP_MESSAGE));
140+
}
141+
127142
void reportMcMavenNotDeclared() {
128143
if (!this.test("net.minecraftforge.gradle.warnings.repository.missing.mavenizer")) return;
129144

0 commit comments

Comments
 (0)