Skip to content

Commit 8748076

Browse files
shartteMatyrobbrt
andauthored
Legacy plugin for 1.17 to 1.20.1 (neoforged#118)
Co-authored-by: Matyrobbrt <[email protected]>
1 parent 5017446 commit 8748076

46 files changed

Lines changed: 1673 additions & 98 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-prs.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ jobs:
2828
strategy:
2929
matrix:
3030
os: [ubuntu-latest, windows-latest]
31+
project: [testproject, legacytest]
3132
runs-on: ${{ matrix.os }}
32-
name: Test on ${{ matrix.os }}
33+
name: Test ${{ matrix.project }} on ${{ matrix.os }}
3334
steps:
3435
- name: Checkout project sources
3536
uses: actions/checkout@v4
@@ -46,13 +47,13 @@ jobs:
4647
uses: gradle/actions/setup-gradle@v3
4748

4849
- name: Run build
49-
run: ./gradlew build neoForgeIdeSync
50-
working-directory: ./testproject
50+
run: ./gradlew build neoForgeIdeSync publish
51+
working-directory: ./${{ matrix.project }}
5152

5253
- name: Ensure clean, build and test work in the same run
5354
run: ./gradlew clean build check
54-
working-directory: ./testproject
55+
working-directory: ./${{ matrix.project }}
5556

5657
- name: Ensure runData runs
5758
run: ./gradlew runData
58-
working-directory: ./testproject
59+
working-directory: ./${{ matrix.project }}

LEGACY.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# ModDevGradle Legacy Forge Plugin
2+
ModDevGradle has a secondary plugin (ID: `net.neoforged.moddev.legacyforge`, released alongside the normal plugin with the same version)
3+
that adds support for developing mods against MinecraftForge and Vanilla Minecraft versions 1.17 up to 1.20.1.
4+
5+
The legacy plugin is an "addon" plugin, meaning it operates on top of the normal plugin. This means that the APIs normally used
6+
are also available when using the legacy plugin.
7+
8+
## Basic Usage for MinecraftForge Mods
9+
An example `build.gradle` file for developing a mod against MinecraftForge for 1.20.1 is provided below:
10+
```groovy
11+
plugins {
12+
// Apply the plugin. You can find the latest version at https://projects.neoforged.net/neoforged/ModDevGradle
13+
id 'net.neoforged.moddev.legacyforge' version '2.0.28-beta'
14+
}
15+
16+
neoForge {
17+
// Develop against MinecraftForge version 47.3.0 for 1.20.1 (the versions can be found at https://files.minecraftforge.net/)
18+
version = "1.20.1-47.3.0"
19+
20+
// Validate AT files and raise errors when they have invalid targets
21+
// This option is false by default, but turning it on is recommended
22+
validateAccessTransformers = true
23+
24+
runs {
25+
client {
26+
client()
27+
}
28+
data {
29+
data()
30+
}
31+
server {
32+
server()
33+
}
34+
}
35+
36+
mods {
37+
testproject {
38+
sourceSet sourceSets.main
39+
}
40+
}
41+
}
42+
```
43+
44+
## Reobfuscating artifacts
45+
Forge used SRG mappings as intermediary mappings in 1.20.1 and below. While your mod is developed against the mappings provided
46+
by Mojang (known as official mappings), you need to reobfuscate it to SRG mappings for it to work in production.
47+
Reobfuscation will automatically be configured for the `jar` task; the non-obfuscated jar will have a `-dev` classifier
48+
and will not be published in favour of the reobfuscated variant. You should upload the `reobfJar` task's output when using a
49+
task to upload to a mod hosting platform, or otherwise the jar without a `-dev` classifier if you're uploading it manually.
50+
51+
You may reobfuscate other jar tasks using `obfuscation.reobfuscate(TaskProvider<AbstractArchiveTask>, SourceSet, Action<RemapJarTask>)`.
52+
For instance, if you want to reobfuscate a `shadowJar` task:
53+
```groovy
54+
shadowJar {
55+
// Change the classifier of the shadow jar to be -dev-all as it's not mapped in intermediary and not usable for production
56+
archiveClassifier = 'dev-all'
57+
}
58+
59+
obfuscation {
60+
// Reobfuscate the shadowJar task, using the classpath of the main sourceset for properly remapping inherited members
61+
reobfuscate(tasks.named('shadowJar'), sourceSets.main) {
62+
// Make the reobfuscated shadowJar have the all classifier
63+
// You could also change it to an empty string if you want it to not have a classifier (in that case, you will also need to change the classifier of the slim `reobfJar` task
64+
archiveClassifier = 'all'
65+
}
66+
}
67+
```
68+
69+
When reobfuscating a jar, it will be replaced in publications with the obfuscated version to avoid publishing jars that aren't mapped to SRG.
70+
71+
## Remapping mod dependencies
72+
As published mods are using intermediary mappings, you must remap them to official mappings before being able to use them as a dependencies.
73+
ModDevGradle creates configurations that will automatically remap dependencies added to them from SRG mappings to official mappings.
74+
The following configurations are created automatically and are children of the configurations without the `mod` prefix:
75+
- `modImplementation`
76+
- `modRuntimeOnly`
77+
- `modCompileOnly`
78+
- `modApi` (only if the `java-library` plugin is applied)
79+
- `modCompileOnlyApi` (only if the `java-library` plugin is applied)
80+
81+
You may create your own remapping configurations using `obfuscation.createRemappingConfiguration(Configuration)`:
82+
```groovy
83+
configurations {
84+
// Create a custom configuration named "custom"
85+
custom
86+
}
87+
88+
obfuscation {
89+
// Create a configuration named "modCustom" that remaps its dependencies and then adds them to the "custom" configuration
90+
createRemappingConfiguration(configurations.custom)
91+
}
92+
```
93+
94+
## Effects of applying the legacy plugin
95+
When applied, the legacy plugin will change the base NeoForm and NeoForge artifact coordinates of the `neoForge` extension to
96+
`de.oceanlabs.mcp:mcp_config` and `net.minecraftforge:forge`.
97+
It will also trigger the creation of various intermediary (SRG) to named (official) mapping files used by various parts of the toolchain, such as
98+
mod reobfuscation and runtime naming services.
99+
Reobfuscation to the intermediary mappings will automatically be configured for the `jar` task, the non-obfuscated jar will have a `-dev` classifier
100+
and will not be published in favour of the reobfuscated variant.

build.gradle

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ sourceSets {
7070
compileClasspath += java8.output
7171
runtimeClasspath += java8.output
7272
}
73+
legacy
7374
}
7475

7576
configurations {
7677
// Configuration for all dependencies that we want shaded.
7778
shaded
7879
// Place shaded dependencies into `compileOnly` so that they do not leak into our publications' dependencies.
7980
compileOnly.extendsFrom shaded
81+
legacyCompileOnly.extendsFrom shaded
8082
testCompileOnly.extendsFrom shaded
8183
testRuntimeOnly.extendsFrom shaded
8284
shadowRuntimeElements {
@@ -123,6 +125,10 @@ dependencies {
123125
testImplementation gradleTestKit()
124126
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
125127
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
128+
129+
legacyImplementation(sourceSets.main.output)
130+
legacyImplementation(sourceSets.java8.output)
131+
legacyImplementation gradleApi()
126132
}
127133

128134
java {
@@ -135,12 +141,14 @@ java {
135141
jar {
136142
archiveClassifier = 'slim'
137143
from sourceSets.java8.output
144+
from sourceSets.legacy.output
138145
}
139146

140147
shadowJar {
141148
archiveClassifier = "" // Required for the Plugin Publish Plugin to publish this jar
142149

143150
from sourceSets.java8.output
151+
from sourceSets.legacy.output
144152

145153
configurations = [project.configurations.shaded]
146154
enableRelocation = true
@@ -188,6 +196,13 @@ gradlePlugin {
188196
description = "This plugin helps you create Minecraft mods using the NeoForge platform"
189197
tags = ["minecraft", "neoforge", "java", "mod"]
190198
}
199+
legacyforge {
200+
id = 'net.neoforged.moddev.legacyforge'
201+
implementationClass = 'net.neoforged.moddevgradle.boot.LegacyForgeModDevPlugin'
202+
displayName = "Mod Development Plugin for Legacy Forge"
203+
description = "This plugin helps you create Minecraft mods using the Forge platform, up to 1.20.1"
204+
tags = ["minecraft", "neoforge", "forge", "java", "mod"]
205+
}
191206
repositories {
192207
id = 'net.neoforged.moddev.repositories'
193208
implementationClass = 'net.neoforged.moddevgradle.boot.RepositoriesPlugin'
@@ -212,21 +227,7 @@ artifacts {
212227

213228
publishing {
214229
repositories {
215-
maven {
216-
name = 'NeoForge'
217-
if (System.getenv('MAVEN_USER') && System.getenv('MAVEN_PASSWORD')) {
218-
it.url = "https://maven.neoforged.net/releases/"
219-
it.authentication {
220-
it.create('basic', BasicAuthentication)
221-
}
222-
it.credentials { credentials ->
223-
credentials.username = System.getenv('MAVEN_USER')
224-
credentials.password = System.getenv('MAVEN_PASSWORD')
225-
}
226-
} else {
227-
it.url = 'file://' + file("repo").getAbsolutePath()
228-
}
229-
}
230+
maven(gradleutils.publishingMaven)
230231
}
231232
}
232233

gradlew

100644100755
File mode changed.

legacytest/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
run/
2+
repo/
3+
*.log

legacytest/build.gradle

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
plugins {
2+
id 'maven-publish'
3+
id 'net.neoforged.moddev.legacyforge'
4+
}
5+
6+
group = 'com.example.legacy'
7+
version = '1.0.0'
8+
9+
java {
10+
toolchain {
11+
languageVersion = JavaLanguageVersion.of(17)
12+
}
13+
}
14+
15+
neoForge {
16+
neoFormVersion = '1.19.2'
17+
}
18+
19+
publishing {
20+
publications {
21+
maven(MavenPublication) {
22+
from components.java
23+
}
24+
}
25+
repositories {
26+
maven {
27+
url file('local')
28+
}
29+
}
30+
}

legacytest/forge/build.gradle

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
plugins {
2+
id 'net.neoforged.moddev.legacyforge'
3+
id 'maven-publish'
4+
}
5+
6+
repositories {
7+
mavenLocal()
8+
maven {
9+
name = "Jared's maven"
10+
url = "https://maven.blamejared.com/"
11+
}
12+
maven {
13+
name 'cursemaven'
14+
url 'https://cursemaven.com'
15+
content {
16+
includeGroup "curse.maven"
17+
}
18+
}
19+
}
20+
21+
java {
22+
toolchain {
23+
languageVersion = JavaLanguageVersion.of(17)
24+
}
25+
}
26+
27+
dependencies {
28+
modCompileOnly('mezz.jei:jei-1.20.1-forge:15.17.0.76') {
29+
transitive = false // JEI publishes dependencies on its subprojects that are already included in this Jar
30+
}
31+
modRuntimeOnly('curse.maven:mekanism-268560:5662583')
32+
modImplementation('curse.maven:applied-energistics-2-223794:5641282')
33+
// This is an example for a mod that does NOT work with FG or MDG since its JiJ dependencies are
34+
// packages into /META-INF/jars while installertools will only remap /META-INF/jarjar/*.jar
35+
// modImplementation('curse.maven:gregtechceu-modern-890405:5641637')
36+
}
37+
38+
neoForge {
39+
version = '1.20.1-47.3.0'
40+
runs {
41+
client {
42+
client()
43+
}
44+
data {
45+
data()
46+
}
47+
}
48+
mods {
49+
myMod {
50+
sourceSet(sourceSets.main)
51+
}
52+
}
53+
}
54+
55+
publishing {
56+
publications {
57+
maven(MavenPublication) {
58+
from components.java
59+
}
60+
}
61+
repositories {
62+
maven {
63+
url rootProject.file('repo')
64+
}
65+
}
66+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package mymod;
2+
3+
import mezz.jei.api.IModPlugin;
4+
import mezz.jei.api.JeiPlugin;
5+
import mezz.jei.api.registration.ISubtypeRegistration;
6+
import net.minecraft.resources.ResourceLocation;
7+
import net.minecraft.world.item.Items;
8+
9+
@JeiPlugin
10+
public class JeiCompat implements IModPlugin {
11+
@Override
12+
public ResourceLocation getPluginUid() {
13+
return new ResourceLocation("mymod:mymod");
14+
}
15+
16+
@Override
17+
public void registerItemSubtypes(ISubtypeRegistration registration) {
18+
// Calling this method tests that JEI was remapped correctly, since the method has an "ItemStack" argument
19+
registration.registerSubtypeInterpreter(Items.ALLIUM, (ingredient, context) -> "allium");
20+
}
21+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package mymod;
2+
3+
import net.minecraftforge.fml.common.Mod;
4+
5+
@Mod("mymod")
6+
public class MyMod {
7+
public void run() {
8+
}
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
modLoader="javafml" #mandatory
2+
loaderVersion="*" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
3+
license="ARR"
4+
[[mods]] #mandatory
5+
# The modid of the mod
6+
modId="mymod" #mandatory
7+
# The version number of the mod
8+
version="1.0" #mandatory
9+
# A display name for the mod
10+
displayName="My Mod" #mandatory
11+
authors="MDG" #optional
12+
description='''Hi.'''

0 commit comments

Comments
 (0)