Skip to main content

Dependencies

Built-in dependencies​

Prism automatically adds the following to each version's common subproject:

  • org.spongepowered:mixin:0.8.5 (compileOnly, always)
  • io.github.llamalad7:mixinextras-common:0.3.5 (compileOnly + annotation processor, only when Forge is not a loader for that version)

MixinExtras is bundled by Fabric Loader and NeoForge, but not by Forge. If your version targets Forge, MixinExtras is not added to common. You can add it per-loader if needed.

For Fabric, Minecraft, Fabric Loader, and optionally Fabric API are added automatically.

For NeoForge and Forge, the loader handles Minecraft and loader dependencies through the extension.

Common dependencies​

Dependencies shared across all loaders for a version:

version("1.21.1") {
common {
implementation("some:shared-library:1.0")
compileOnly("some:api:2.0")
}

fabric { loaderVersion = "0.16.2" }
neoforge { loaderVersion = "21.1.26" }
}

Common dependencies are added to the common subproject's configurations and are available to all loader subprojects through the source wiring.

Per-loader dependencies​

Each loader has its own dependencies block:

fabric {
loaderVersion = "0.16.2"
fabricApi("0.102.1")

dependencies {
modImplementation("curse.maven:jei-238222:4613379")
modCompileOnly("modrinth:sodium:0.5.3")
implementation("com.google.code.gson:gson:2.10.1")
jarJar("some:library:[1.0,2.0)")
}
}

forge {
loaderVersion = "47.4.16"

dependencies {
modImplementation("curse.maven:jei-238222:7391695")
modCompileOnly("curse.maven:polymorph-388800:6450982")
implementation("com.google.code.gson:gson:2.10.1")
}
}

neoforge {
loaderVersion = "21.1.26"

dependencies {
implementation("curse.maven:jei-238222:4613379")
jarJar("some:library:[1.0,2.0)")
}
}

Available configurations​

MethodDescription
api(dep)Exported API dependency
implementation(dep)Compile and runtime dependency (no remapping)
modApi(dep)Exported mod dependency, remapped when supported
compileOnlyApi(dep)Exported compile-only API dependency
modImplementation(dep)Mod dependency, remapped to dev mappings
compileOnly(dep)Compile-time only (no remapping)
modCompileOnlyApi(dep)Exported compile-only mod dependency, remapped when supported
modCompileOnly(dep)Mod compile-time only, remapped to dev mappings
runtimeOnly(dep)Runtime only (no remapping)
modRuntimeOnly(dep)Mod runtime only, remapped to dev mappings
jarJar(dep)Embed dependency in output JAR
shadow(dep)Shade dependency into output JAR (merges classes, avoids split packages)
localJar(path)Local JAR file (defaults to compileOnly)
localJar(path, config)Local JAR file with custom configuration
configuration(name, dep)Add a dependency to a custom Gradle configuration
modConfiguration(name, dep)Add a dependency to mod{Name} when present

Use mod* variants for Minecraft mod JARs (from CurseMaven, Modrinth Maven, or mod maven repos). These remap the dependency from production mappings (SRG/intermediary) to dev mappings so you don't get NoSuchMethodError / NoSuchFieldError crashes.

Use plain implementation / compileOnly / runtimeOnly for regular Java libraries that don't reference Minecraft classes (e.g. Gson, Apache Commons). These don't need remapping.

On Fabric, mod* maps to Loom's remapping configurations. On Forge, mod* maps to MDG Legacy's remapping transform. On NeoForge, no remapping is needed so mod* behaves the same as the plain variants.

Custom configurations​

Create an extra configuration in the loader block, then add dependencies to it:

forge {
loaderVersion = "47.4.16"
configuration("localRuntime")
remapConfiguration("optionalMods")

dependencies {
configuration("localRuntime", "com.example:helper:1.0")
modConfiguration("optionalMods", "curse.maven:jei-238222:7391695")
}
}

Notes:

  • configuration("name") creates a plain custom Gradle configuration for that loader project.
  • remapConfiguration("name") is currently Forge-only and creates both name and mod{Name} through MDG Legacy.
  • modConfiguration(name, dep) falls back to the plain configuration with a warning if mod{Name} does not exist.

Shared common dependencies​

Dependencies in the sharedCommon block are propagated to all loader subprojects:

prism {
sharedCommon {
dependencies {
implementation("com.example:my-library:1.0")
}
}
}

For Forge and NeoForge loaders, shared common implementation, api, and runtimeOnly dependencies are automatically:

  • Added as compileOnly so they don't end up on Forge's module path (avoids SecureJarHandler crashes)
  • Added to additionalRuntimeClasspath so they are visible during dev runs (runClient/runServer)

On Fabric, shared common dependencies are added normally (Fabric's classloading handles them without issues).

Shading with Shadow​

Use shadow(dep) to shade a dependency into the output JAR. This merges the dependency's classes directly into your mod JAR, avoiding split-package errors that jarJar() can cause when multiple JARs share the same Java package.

prism {
sharedCommon {
dependencies {
shadow("com.example:my-library:1.0") // shaded into output JAR
shadow("com.example:my-other-lib:2.0") // also shaded
implementation("com.google.code.gson:gson:2.10.1") // NOT shaded, just a normal dep
}
}
}

// Also works in per-loader dependency blocks:
forge {
dependencies {
shadow("some:library:1.0")
}
}

On Forge/NeoForge, shadow(dep) dependencies are:

  • Added to the shadow configuration (merged into the output JAR)
  • Added to additionalRuntimeClasspath while the Minecraft version has a legacy classpath, i.e. before 1.21.9 (so Forge dev runs can see them without putting them on the module path)
  • Added to runtimeOnly on Minecraft 1.21.9 and newer, where ModDevGradle no longer accepts dependencies on additionalRuntimeClasspath
  • Merged into a single module in dev runs (through the mergeModules system property) while the Minecraft version has a legacy classpath, mirroring how they are merged into one JAR in production. Without this, JARs sharing a Java package lose classes to each other on the module path, and libraries cannot read resources of their sibling JARs. JARs that declare their own module-info are never merged

On Fabric, shadow(dep) maps to implementation + include (Loom's Jar-in-Jar).

Prism automatically applies the Shadow Gradle plugin when any shadow() dependency is declared.

On Legacy Forge/MDG builds, Prism also wires the shaded artifact into reobfShadowJar, and publishing prefers reobfShadowJar when it exists.

Use shadow() instead of jarJar() when your dependencies share Java packages across multiple JARs, since Forge's jar-in-jar keeps those JARs separate and can still hit module split-package errors at runtime.

Shadow configuration​

The shadow {} block (or shadow(dep) { } overload) exposes full control over the Shadow task:

dependencies {
shadow("com.example:my-library:1.0") {
// Auto-relocation: Prism relocates all packages to a default prefix by default.
// Disable with:
relocation(false)
// Or set a custom prefix (default: derived from mod group):
relocationPrefix("com.example.mymod.libs")
// Restrict which packages are relocated:
includeRelocation("com.example.somelibrary")
excludeRelocation("com.example.sharedapi")

// Explicit per-package relocation rules:
relocate("org.apache.commons", "com.example.mymod.libs.commons") {
include("org.apache.commons.lang3.*")
exclude("org.apache.commons.lang3.builder.*")
skipStringConstants(true)
}

// Exclude files from the shadow JAR:
exclude("META-INF/MANIFEST.MF", "*.SF")

// Strip file entries matching Ant patterns (removes the entry entirely):
strip("META-INF/services/some.ServiceInterface")

// Remove manifest attributes (Class-Path and Multi-Release are removed by default):
removeManifestAttribute("Implementation-Version")

// Merge service files:
mergeServiceFiles() // merges all META-INF/services/
mergeServiceFiles("META-INF/services/some.Service") // specific file only

// Direct access to the ShadowJar task for anything not covered above:
raw { shadowJar -> }
}
}

Top-level shorthands are also available directly on the dependencies {} block for quick overrides:

dependencies {
shadow("com.example:my-library:1.0")
shadowRelocation(false) // disable auto-relocation
shadowRelocationPrefix("com.example.mymod.shadow") // set prefix
}

Jar-in-Jar​

The jarJar() method embeds a dependency inside your output JAR:

fabric {
dependencies {
jarJar("some:library:1.0")
}
}

On Fabric, this maps to Loom's include configuration and also adds the dependency to implementation, so it is on the classpath of dev runs. On NeoForge/Forge, this maps to MDG's jarJar configuration.

jarJar() is best for normal jar-in-jar embedding. If a library is split across multiple JARs that share packages, prefer shadow() instead.

Excluding entries​

jarJar(dep) { } accepts a block to strip entries from the embedded JAR before it is bundled. This is useful for dropping native libraries for platforms you do not ship:

dependencies {
jarJar("org.rocksdb:rocksdbjni:10.2.1") {
excludeNatives("osx", "linux32", "musl", "s390x", "riscv64", "ppc64le", "aarch64")
exclude("some/unwanted/file.txt")
}
}

excludeNatives(tokens...) removes native library entries (.so, .dll, .dylib, .jnilib) whose path contains any of the given tokens. exclude(paths...) removes entries by exact path or suffix match. When either is set, Prism resolves the dependency, repackages it without the excluded entries, and embeds the repackaged JAR.

Local JARs​

Use localJar() to depend on a JAR file from disk:

neoforge {
loaderVersion = "21.1.26"

dependencies {
localJar("libs/some-mod.jar") // compileOnly (default)
localJar("libs/some-lib.jar", "implementation") // implementation
}
}

Paths are relative to the root project directory. Absolute paths are also supported.

Maven repositories​

Prism provides shortcuts for common Minecraft mod repositories:

prism {
curseMaven() // https://cursemaven.com
modrinthMaven() // https://api.modrinth.com/maven
maven("BlameJared", "https://maven.blamejared.com")
}

For artifacts hosted outside a Maven layout (such as GitHub release downloads), use ivy() with an artifact pattern:

prism {
ivy("github", "https://github.com/", "/[organisation]/[module]/releases/download/[revision]/[module]-[revision]-[classifier].[ext]")
}

Then depend on it with the matching coordinates, e.g. compileOnly("owner:repo:1.0:classifier@jar").

These repositories are added to all subprojects.

CurseMaven dependency format​

curse.maven:{slug}-{projectId}:{fileId}

Example: curse.maven:jei-238222:4613379

Modrinth Maven dependency format​

maven.modrinth:{slug}:{version}

Example: maven.modrinth:sodium:mc1.21-0.5.11