Gradle Tips for Minecraft Fabric Mod

In the past few months, I am having fun with my first Minecraft Fabric mod for posting item info to Discord text channels. Intuitively, I use some third-party library for handling the Discord and testing stuff which surprisingly was a challenge to me. That's because I am familiar with Maven but Fabric mods use another build tool, Gradle. Here I am noting down some tips for using it.

Adding Dependency

Testcases

I am using Junit and Mockito for my test cases. To add them to the project, add the following into build.gradle:

// include the library for test-only
dependencies {
    testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"
    testImplementation "org.mockito:mockito-core:5.2.0"
}

// avoid the error `Execution failed for task ':test'. No tests found for given includes: [somePackage.SomeClassTest.formatTest](--tests filter)` when running the test cases
test {
    useJUnitPlatform()
}

Simple Dependency

// the `include` make the built Jar include the library jar 
// Fabric treat it as a dummy mod
dependencies {
    implementation include('org.yaml:snakeyaml:1.33')
}

Transitive Dependency by Shadow Jar

This is the case that I struggled with. The include only include the library itself but not the library used by it. In other words, a transitive dependency is not supported. In order to include all the .class we need to run the mod, a shadow plugin is required.

plugins {
    id 'fabric-loom' version '1.1.10'
    id 'maven-publish'
    // add the shadow plugin
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

dependencies {
    // add the library that include transitive dependency
    // `include` is not needed here
    implementation "com.discord4j:discord4j-core:3.2.3"
    shadow "com.discord4j:discord4j-core:3.2.3"
}

shadowJar {
    configurations = [project.configurations.shadow]
    exclude("META-INF")
}

remapJar {
    // wait until the shadowJar is done
    dependsOn(shadowJar)
    mustRunAfter(shadowJar)
    // Set the input jar for the task. Here use the shadow Jar that include the .class of the transitive dependency
    inputFile = file(shadowJar.archivePath)
}

For more, see the Fabric Loom Documentation.