Skip to main content

Prerequisites

  • Oracle JDK 21 installed and on your PATH
  • The Gradle wrapper (gradlew) is included in the repository — you do not need to install Gradle separately
Always use ./gradlew (the wrapper) instead of a system-installed gradle command. The wrapper ensures everyone uses the same Gradle version.

Key properties

The following properties in gradle.properties control the build output and dependency versions:
PropertyValueDescription
mod_version1.0.0Version embedded in the output JAR name
minecraft_version1.21.1Target Minecraft version
neo_version21.1.209NeoForge loader version

Build and run

1

Build the mod JAR

Run the following command to compile the mod and produce the output JAR:
./gradlew build
The output is written to:
build/libs/gm-<version>.jar
For example, with mod_version=1.0.0 the output file is build/libs/gm-1.0.0.jar.
2

Run the Minecraft client

Launch a Minecraft client with the mod loaded for manual testing:
./gradlew runClient
3

Run the Minecraft server

Launch a headless Minecraft server (the --nogui flag is applied automatically):
./gradlew runServer
4

Run game tests

Run all registered game tests. The server exits automatically after tests complete:
./gradlew runGameTestServer
By default the game test server crashes if no game tests are registered. Make sure at least one test exists before running this task.
5

Run data generation

Generate mod resources (recipes, loot tables, tags, etc.). Output is written to src/generated/resources/ and is automatically included in subsequent builds:
./gradlew runData
This task passes --mod gm --all along with the output and existing-resources paths to the data generator.

JVM compiler flags

The build applies --add-exports and --add-opens flags to the Java compiler’s JVM process. These are required for Lombok’s annotation processor to access internal javac APIs:
tasks.withType(JavaCompile).configureEach {
    options.encoding = 'UTF-8'
    options.fork = true
    def addExportsOpens = [
            '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
            '--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
            // ... matching --add-opens flags
    ]
    options.forkOptions.jvmArgs += addExportsOpens
}
You do not need to configure these manually — they are applied automatically by Gradle.

Maven publishing

The project includes a maven-publish configuration that publishes to a local Maven repository inside the project directory:
publishing {
    publications {
        register('mavenJava', MavenPublication) {
            from components.java
        }
    }
    repositories {
        maven {
            url "file://${project.projectDir}/repo"
        }
    }
}
To publish to the local repo:
./gradlew publishMavenJavaPublicationToMavenRepository
The artifact is written to repo/ in the project root.

Gradle optimizations

The following options are enabled in gradle.properties to speed up builds:
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
These are active by default and require no additional setup.

Build docs developers (and LLMs) love