Skip to content

Commit

Permalink
Add legacy support for Forge 1.17 to 1.20.1
Browse files Browse the repository at this point in the history
Co-authored-by: Matyrobbrt <[email protected]>
  • Loading branch information
shartte and Matyrobbrt committed Oct 13, 2024
1 parent 951a5c8 commit 39bb3eb
Show file tree
Hide file tree
Showing 42 changed files with 1,564 additions and 60 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/build-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
project: [testproject, legacytest]
runs-on: ${{ matrix.os }}
name: Test on ${{ matrix.os }}
name: Test ${{ matrix.project }} on ${{ matrix.os }}
steps:
- name: Checkout project sources
uses: actions/checkout@v4
Expand All @@ -47,12 +48,12 @@ jobs:

- name: Run build
run: ./gradlew build neoForgeIdeSync
working-directory: ./testproject
working-directory: ./${{ matrix.project }}

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

- name: Ensure runData runs
run: ./gradlew runData
working-directory: ./testproject
working-directory: ./${{ matrix.project }}
100 changes: 100 additions & 0 deletions LEGACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# ModDevGradle Legacy Plugin
ModDevGradle has a secondary plugin (ID: `net.neoforged.moddevgradle.legacy`, released alongside the normal plugin with the same version)
that adds support for developing mods against MinecraftForge and Vanilla Minecraft versions 1.17 up to 1.20.1.

The legacy plugin is an "addon" plugin, meaning it operates on top of the normal plugin. This means that the APIs normally used
are also available when using the legacy plugin.

## Basic Usage for MinecraftForge Mods
An example `build.gradle` file for developing a mod against MinecraftForge for 1.20.1 is provided below:
```groovy
plugins {
// Apply the plugin. You can find the latest version at https://projects.neoforged.net/neoforged/ModDevGradle
id 'net.neoforged.moddev.legacy' version '2.0.28-beta'
}
neoForge {
// Develop against MinecraftForge version 47.3.0 for 1.20.1 (the versions can be found at https://files.minecraftforge.net/)
version = "1.20.1-47.3.0"
// Validate AT files and raise errors when they have invalid targets
// This option is false by default, but turning it on is recommended
validateAccessTransformers = true
runs {
client {
client()
}
data {
data()
}
server {
server()
}
}
mods {
testproject {
sourceSet sourceSets.main
}
}
}
```

## Reobfuscating artifacts
Forge used SRG mappings as intermediary mappings in 1.20.1 and below. While your mod is developed against the mappings provided
by Mojang (known as official mappings), you need to reobfuscate it to SRG mappings for it to work in production.
Reobfuscation will automatically be configured for the `jar` task; the non-obfuscated jar will have a `-dev` classifier
and will not be published in favour of the reobfuscated variant. You should upload the `reobfJar` task's output when using a
task to upload to a mod hosting platform, or otherwise the jar without a `-dev` classifier if you're uploading it manually.

You may reobfuscate other jar tasks using `obfuscation.reobfuscate(TaskProvider<AbstractArchiveTask>, SourceSet, Action<RemapJarTask>)`.
For instance, if you want to reobfuscate a `shadowJar` task:
```groovy
shadowJar {
// Change the classifier of the shadow jar to be -dev-all as it's not mapped in intermediary and not usable for production
archiveClassifier = 'dev-all'
}
obfuscation {
// Reobfuscate the shadowJar task, using the classpath of the main sourceset for properly remapping inherited members
reobfuscate(tasks.named('shadowJar'), sourceSets.main) {
// Make the reobfuscated shadowJar have the all classifier
// 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
archiveClassifier = 'all'
}
}
```

When reobfuscating a jar, it will be replaced in publications with the obfuscated version to avoid publishing jars that aren't mapped to SRG.

## Remapping mod dependencies
As published mods are using intermediary mappings, you must remap them to official mappings before being able to use them as a dependencies.
ModDevGradle creates configurations that will automatically remap dependencies added to them from SRG mappings to official mappings.
The following configurations are created automatically and are children of the configurations without the `mod` prefix:
- `modImplementation`
- `modRuntimeOnly`
- `modCompileOnly`
- `modApi` (only if the `java-library` plugin is applied)
- `modCompileOnlyApi` (only if the `java-library` plugin is applied)

You may create your own remapping configurations using `obfuscation.createRemappingConfiguration(Configuration)`:
```groovy
configurations {
// Create a custom configuration named "custom"
custom
}
obfuscation {
// Create a configuration named "modCustom" that remaps its dependencies and then adds them to the "custom" configuration
createRemappingConfiguration(configurations.custom)
}
```

## Effects of applying the legacy plugin
When applied, the legacy plugin will change the base NeoForm and NeoForge artifact coordinates of the `neoForge` extension to
`de.oceanlabs.mcp:mcp_config` and `net.minecraftforge:forge`.
It will also trigger the creation of various intermediary (SRG) to named (official) mapping files used by various parts of the toolchain, such as
mod reobfuscation and runtime naming services.
Reobfuscation to the intermediary mappings will automatically be configured for the `jar` task, the non-obfuscated jar will have a `-dev` classifier
and will not be published in favour of the reobfuscated variant.
31 changes: 16 additions & 15 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,15 @@ sourceSets {
compileClasspath += java8.output
runtimeClasspath += java8.output
}
legacy
}

configurations {
// Configuration for all dependencies that we want shaded.
shaded
// Place shaded dependencies into `compileOnly` so that they do not leak into our publications' dependencies.
compileOnly.extendsFrom shaded
legacyCompileOnly.extendsFrom shaded
testCompileOnly.extendsFrom shaded
testRuntimeOnly.extendsFrom shaded
shadowRuntimeElements {
Expand Down Expand Up @@ -123,6 +125,10 @@ dependencies {
testImplementation gradleTestKit()
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

legacyImplementation(sourceSets.main.output)
legacyImplementation(sourceSets.java8.output)
legacyImplementation gradleApi()
}

java {
Expand All @@ -135,12 +141,14 @@ java {
jar {
archiveClassifier = 'slim'
from sourceSets.java8.output
from sourceSets.legacy.output
}

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

from sourceSets.java8.output
from sourceSets.legacy.output

configurations = [project.configurations.shaded]
enableRelocation = true
Expand Down Expand Up @@ -188,6 +196,13 @@ gradlePlugin {
description = "This plugin helps you create Minecraft mods using the NeoForge platform"
tags = ["minecraft", "neoforge", "java", "mod"]
}
legacy {
id = 'net.neoforged.moddev.legacy'
implementationClass = 'net.neoforged.moddevgradle.boot.LegacyModDevPlugin'
displayName = "NeoForge Legacy Mod Development Plugin"
description = "This plugin helps you create Minecraft mods using the Forge platform, up to 1.20.1"
tags = ["minecraft", "neoforge", "forge", "java", "mod"]
}
repositories {
id = 'net.neoforged.moddev.repositories'
implementationClass = 'net.neoforged.moddevgradle.boot.RepositoriesPlugin'
Expand All @@ -212,21 +227,7 @@ artifacts {

publishing {
repositories {
maven {
name = 'NeoForge'
if (System.getenv('MAVEN_USER') && System.getenv('MAVEN_PASSWORD')) {
it.url = "https://maven.neoforged.net/releases/"
it.authentication {
it.create('basic', BasicAuthentication)
}
it.credentials { credentials ->
credentials.username = System.getenv('MAVEN_USER')
credentials.password = System.getenv('MAVEN_PASSWORD')
}
} else {
it.url = 'file://' + file("repo").getAbsolutePath()
}
}
maven(gradleutils.publishingMaven)
}
}

Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Empty file modified gradlew
100644 → 100755
Empty file.
3 changes: 3 additions & 0 deletions legacytest/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
run/
repo/
*.log
41 changes: 41 additions & 0 deletions legacytest/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
plugins {
id 'maven-publish'
id 'net.neoforged.moddev.legacy'
}

group = 'com.example.legacy'
version = '1.0.0'

repositories {
mavenLocal()
maven {
name 'cursemaven'
url 'https://cursemaven.com'
content {
includeGroup "curse.maven"
}
}
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

neoForge {
neoFormVersion = '1.19.2'
}

publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
repositories {
maven {
url file('local')
}
}
}
49 changes: 49 additions & 0 deletions legacytest/forge/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
plugins {
id 'net.neoforged.moddev.legacy'
}

repositories {
mavenLocal()
maven {
name = "Jared's maven"
url = "https://maven.blamejared.com/"
}
maven {
name 'cursemaven'
url 'https://cursemaven.com'
content {
includeGroup "curse.maven"
}
}
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

dependencies {
modCompileOnly('mezz.jei:jei-1.20.1-forge:15.17.0.76') {
transitive = false
}
modRuntimeOnly('curse.maven:mekanism-268560:5662583')
modImplementation('curse.maven:applied-energistics-2-223794:5641282')
}

neoForge {
version = '1.20.1-47.3.0'
runs {
client {
client()
}
data {
data()
}
}
mods {
myMod {
sourceSet(sourceSets.main)
}
}
}
20 changes: 20 additions & 0 deletions legacytest/forge/src/main/java/mymod/JeiCompat.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package mymod;

import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.registration.ISubtypeRegistration;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Items;

@JeiPlugin
public class JeiCompat implements IModPlugin {
@Override
public ResourceLocation getPluginUid() {
return new ResourceLocation("mymod:mymod");
}

@Override
public void registerItemSubtypes(ISubtypeRegistration registration) {
registration.registerSubtypeInterpreter(Items.ALLIUM, (ingredient, context) -> "allium");
}
}
9 changes: 9 additions & 0 deletions legacytest/forge/src/main/java/mymod/MyMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package mymod;

import net.minecraftforge.fml.common.Mod;

@Mod("mymod")
public class MyMod {
public void run() {
}
}
12 changes: 12 additions & 0 deletions legacytest/forge/src/main/resources/META-INF/mods.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
modLoader="javafml" #mandatory
loaderVersion="*" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
license="ARR"
[[mods]] #mandatory
# The modid of the mod
modId="mymod" #mandatory
# The version number of the mod
version="1.0" #mandatory
# A display name for the mod
displayName="My Mod" #mandatory
authors="MDG" #optional
description='''Hi.'''
1 change: 1 addition & 0 deletions legacytest/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.gradle.configuration-cache=true
Binary file added legacytest/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
7 changes: 7 additions & 0 deletions legacytest/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 39bb3eb

Please sign in to comment.