SkillAgentSearch skills...

ModDevGradle

A Gradle plugin for developing Minecraft mods using NeoForge

Install / Use

/learn @neoforged/ModDevGradle
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Gradle Plugin for Developing Minecraft Mods on NeoForge

ModDevGradle Logo

Check the NeoForged Project Listing for latest releases.

If you are updating to a new major version of the plugin, refer to the list of breaking changes.

Features

  • Uses the latest Gradle best practices and is compatible with Gradle 8.8
  • Creates the necessary artifacts to compile Minecraft mods for NeoForge
  • Runs the game from Gradle or IntelliJ for debugging and testing
  • Automatically creates and uses a development-friendly logging configuration for the testing the mod
  • Supports the Gradle configuration cache to speed up repeated runs of Gradle tasks

Basic Usage for NeoForge Mods

In gradle.properties:

# Enable Gradle configuration cache if you'd like:
org.gradle.configuration-cache=true

In settings.gradle:

plugins {
    // This plugin allows Gradle to automatically download arbitrary versions of Java for you
    id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
}

In build.gradle:

plugins {
    // Apply the plugin. You can find the latest version at https://projects.neoforged.net/neoforged/ModDevGradle
    id 'net.neoforged.moddev' version '1.0.11'
}

neoForge {
    // We currently only support NeoForge versions later than 21.0.x
    // See https://projects.neoforged.net/neoforged/neoforge for the latest updates
    version = "21.0.103-beta"
    
    // 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
        }
    }
}

See the example code in the test project.

Vanilla-Mode

In multi-loader projects, you'll often need a subproject for your cross-loader code. This project will also need access to Minecraft classes, but without any loader-specific extensions.

This plugin solves that by offering a "Vanilla-mode" which you enable by specifying a NeoForm version instead of a NeoForge version. NeoForm contains the necessary configuration to produce Minecraft jar-files that you can compile against that contain no other modifications.

In Vanilla-mode, only the client, server and data run types are supported. Since the plugin includes no mod loader code in this mode, only basic resource- and data packs will be usable in-game.

In build.gradle:

Apply the plugin as usual and use a configuration block like this:

neoForge {
    // Look for versions on https://projects.neoforged.net/neoforged/neoform
    neoFormVersion = "1.21-20240613.152323"

    runs {
        client {
            client()
        }
        server {
            server()
        }
        data {
            data()
        }
    }
}

Disabling Decompilation and Recompilation

By default, MDG will use the NeoForm decompilation/recompilation pipeline to produce Minecraft sources and a matching compiled game jar. This leads to a great debugging experience, at the cost of longer setup times.

As of MDG 2.0.124, an alternative pipeline can be used, which will skip decompilation and recompilation entirely. As of MDG 2.0.136, this pipeline will be used by default in CI/CD pipelines, if the CI environment variable is true. This is true by default in many CI/CD systems such as GitHub Actions.

To control this setting manually, replace:

neoForge {
    version = "..." // or neoFormVersion = "..."
}

By:

neoForge {
    enable {
        version = "..." // or neoFormVersion = "..."
        disableRecompilation = true
    }
}

Common Issues

Clicking "Attach Sources" does nothing when viewing a Minecraft class (IntelliJ IDEA)

Sometimes IntelliJ gets into a state where clicking "Attach Sources" while viewing a decompiled Minecraft class will not work.

Reloading the Gradle Project and then clicking "Attach Sources" again will usually fix this problem.

Task idePostSync not found (IntelliJ IDEA)

This error typically happens when switching to ModDevGradle from another plugin with an idePostSync task. This can be fixed by unregistering the task in IntelliJ IDEA, as follows:

<details> <summary>Click to expand</summary>
  1. Open the Gradle tool window on the right, and right-click the Gradle project.

  1. Click on Tasks Activation.

  1. Select the idePostSync task and delete it using the - button.

  1. Sync the Gradle project again.
</details>

More Configuration

Runs

Any number of runs can be added in the neoForge { runs { ... } } block.

Every run must have a type. Currently, the supported types are client, data, gameTestServer, server. The run type can be set as follows:

neoForge {
    runs {
        <run name> {
            // This is the standard syntax:
            type = "gameTestServer"
            // Client, data and server runs can use a shorthand instead:
            // client()
            // data()
            // server()
        
            // Changes the working directory used for this run.
            // The default is the 'run' subdirectory of your project
            gameDirectory = project.file('runs/client')

            // Add arguments passed to the main method
            programArguments = ["--arg"]
            programArgument("--arg")

            // Add arguments passed to the JVM
            jvmArguments = ["-XX:+AllowEnhancedClassRedefinition"]
            jvmArgument("-XX:+AllowEnhancedClassRedefinition")

            // Add system properties
            systemProperties = [
                    "a.b.c": "xyz"
            ]
            systemProperty("a.b.c", "xyz")

            // Set or add environment variables
            environment = [
                    "FOO_BAR": "123"
            ]
            environment("FOO_BAR", "123")

            // Optionally set the log-level used by the game
            logLevel = org.slf4j.event.Level.DEBUG

            // You can change the name used for this run in your IDE
            ideName = "Run Game Tests"
            
            // You can disable a run configuration being generated for your IDE
            disableIdeRun()
            // ... alternatively you can set ideName = ""

            // Changes the source set whose runtime classpath is used for this run. This defaults to "main"
            // Eclipse does not support having multiple runtime classpaths per project (except for unit tests).
            sourceSet = sourceSets.main

            // Changes which local mods are loaded in this run.
            // This defaults to all mods declared in this project (inside of mods { ... } ).
            loadedMods = [mods.<mod name 1>, mods.<mod name 2>]

            // Allows advanced users to run additional Gradle tasks before each launch of this run
            // Please note that using this feature will significantly slow down launching the game
            taskBefore tasks.named("generateSomeCodeTask")
        }
    }
}

Please have a look at RunModel.java for the list of supported properties. Here is an example that sets a system property to change the log level to debug:

neoForge {
    runs {
        configureEach {
            systemProperty 'forge.logging.console.level', 'debug'
        }
    }
}

Jar-in-Jar

To embed external Jar-files into your mod file, you can use the jarJar configuration added by the plugin.

External Dependencies

When you want to bundle external dependencies, Jar-in-Jar has to be able to select a single copy of that dependency when it is bundled by multiple mods (possibly even in different versions). To support this scenario, you should set a supported version range to avoid mod incompatibilities.

dependencies {
    jarJar(implementation("org.commonmark:commonmark")) {
        version {
            // The version range your mod is actually compatible with. 
            // Note that you may receive a *lower* version than your preferred if another
            // Mod is only compatible up to 1.7.24, for example, your mod might get 1.7.24 at runtime.
            strictly '[0.1, 1.0)'
            prefer '0.21.0' // The version actually used in your dev workspace
        }
    }
}

Version ranges use the Maven version range format:

| Range | Meaning | |---------------|-------------------------------------------------------------------------------| | (,1.0] | x <= 1.0 | | 1.0 | Soft requirement on 1.0. It allows for any version. | | [1.0] | Hard requirement on 1.0 | | [1.2,1.3] | 1.2 <= x <= 1.3 | | [1.0,2.0) | 1.0 <= x < 2.0 | | [1.5,) | x >= 1.5 | | (,1.0],[1.2,) | x <= 1.0 or x >= 1.2. Multiple sets are comma-sepa

Related Skills

View on GitHub
GitHub Stars95
CategoryDevelopment
Updated23h ago
Forks28

Languages

Java

Security Score

100/100

Audited on Mar 30, 2026

No findings