Skip to content

Instantly share code, notes, and snippets.

@SizableShrimp
Last active March 23, 2024 20:29
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save SizableShrimp/949e7c219bfc94487a45226b64ac7749 to your computer and use it in GitHub Desktop.
Save SizableShrimp/949e7c219bfc94487a45226b64ac7749 to your computer and use it in GitHub Desktop.
How to setup shading with Minecraft Forge

How to setup shading with Minecraft Forge

Shading is the concept of packing external dependencies inside your jar so that they exist in production. Without this, using external libraries would produce ClassNotFoundExceptions when you run your mod jar outside of an IDE. This guide explains how to setup shading through Gradle.

Assumptions

This guide assumes that:

  • You are on ForgeGradle 5 or higher
  • You are on Gradle 7.0 or higher

Gradle Configuration

Shading in Gradle is typically done through the use of the Gradle Shadow plugin.

First, set up the Shadow plugin by adding it to the plugins {} block in your build.gradle. If this block does not exist, add it above the apply plugin: 'net.minecraftforge.gradle' line near the top of the file. It should look something like this:

plugins {
    // ... potentially other plugins ...
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

At the time of writing, 7.1.2 is the latest version of the Shadow plugin for Gradle 7. See the latest releases here. You should always try to stay up-to-date with releases of the Shadow plugin, so double check for yourself!

Next, add this block of code above the dependencies {} block:

configurations {
    shade
    implementation.extendsFrom shade
}

dependencies {
    // Dependencies here
}

This declares a new shade configuration while also telling Gradle that dependencies under shade should still be treated like normal in a development environment.

You must also configure the Shadow plugin to output the shaded jar correctly. To prevent issues, you must ensure that the jar {} block contains the line archiveClassifier = 'slim'. You should also configure the Shadow plugin after this jar {} block:

jar {
    archiveClassifier = 'slim'
    manifest {
        attributes([
                // Attributes here
        ])
    }
}

shadowJar {
    archiveClassifier = ''
    configurations = [project.configurations.shade]
    finalizedBy 'reobfShadowJar'
}

assemble.dependsOn shadowJar

reobf {
    shadowJar {}
}

With this setup, running gradlew build will now produce two jars: a slim variant and one without a classifier. The no-classifier jar is now your shadowJar, which includes any dependencies you put into the shade configuration.

Adding Dependencies

Having a shaded jar isn't much use if you don't declare dependencies to be shaded. To do this, add any repositories like normal to the repositories {} block. Then, you must make sure to add the external dependency to the shade configuration.

Example:

dependencies {
    minecraft 'net.minecraftforge:forge:<forge version>'

    // ... Other dependencies ...

    shade 'com.example:example-thing:1.0.0'
}

Additionally, you must also make sure to relocate any external packages to be under your own package. This minimizes conflicts with other mods that may include the same dependencies as you! This is an extra line that you must put inside of the shadowJar {} block from earlier.

Example:

shadowJar {
    archiveClassifier = ''
    configurations = [project.configurations.shade]
    relocate 'com.example.example-thing', "${project.group}.relocated.example-thing"
    finalizedBy 'reobfShadowJar'
}

You should replace "com.example.example-thing" and "example-thing" with the package and name of the libraries you use.

Extra steps on Forge 1.17+

Forge 1.17+ uses the module system, requiring a little more setup. See this guide on how to ensure that external libraries load in your IDE.

@PanSzelescik
Copy link

Great guide! It's a pity that you have to look for them for a long time, they should be in the Forge documentation

@Subilan
Copy link

Subilan commented Jun 30, 2023

At

configurations {
    shade
    implementation.extendsFrom shade
}

The order of the extending is reversed unexpectedly (why does the extendee implementation extend newly-defined shade?). It should be 'shade.extendsFrom implementation', or it could lead to a puzzling error.

Cannot mutate content repository descriptor 'BUNDELED_XXXXXXXXX(path/to/.gradle/caches/forge_gradle/bundled_deobf_repo)' after repository has been used

I'm not 100% sure about this tho, so please let me know if I got things wrong.

Also thanks for the tutorial. This is of great help to me!!!

@Reycko
Copy link

Reycko commented Mar 23, 2024

HOLY SHIT TYSMMMMMMMM I NEEDED THIS TO FIX MY 1.12 MOD FOR MY SERVER

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment