Difference between revisions of "Dependencies"

From Forge Community Wiki
(add WIP section on declaring dependencies)
(Update to 1.19)
 
(11 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Under construction}}
+
A '''dependency''' is the reliance of a piece of software on another piece of software. In the context of Minecraft Forge, it is a mod or library which another mod relies or ''depends'' on.
A '''dependency''' is the reliance of a piece of software on another piece of software. In the context of Minecraft Forge, it is a mod or library which another mod has a dependency on.
 
  
 
Dependencies are declared in three ways:
 
Dependencies are declared in three ways:
Line 19: Line 18:
  
 
== Declaring Dependencies ==
 
== Declaring Dependencies ==
A mod declares a dependency on a mod or library through Gradle, through the <code>dependencies</code> block.<ref>[https://docs.gradle.org/6.8.1/userguide/declaring_dependencies.html Gradle User Guide for 6.8.1: ''Declaring dependencies'']</ref>
+
A mod declares a dependency on a mod or library through Gradle, through the <code>dependencies</code> block.<ref>[https://docs.gradle.org/7.4.2/userguide/declaring_dependencies.html Gradle User Guide: ''Declaring dependencies'']</ref>
  
For example, to declare a dependency on the <code>net:minecraftforge:eventbus:4.0.0</code> library from the <code>main</code> source set:
+
For example, to declare a dependency on the <code>net:minecraftforge:eventbus:5.0.3</code> library from the <code>main</code> source set:
 
<syntaxhighlight lang="gradle">
 
<syntaxhighlight lang="gradle">
 
dependencies {
 
dependencies {
 
     // 'implementation' is for the main source set
 
     // 'implementation' is for the main source set
     implementation "net:minecraftforge:eventbus:4.0.0"
+
     implementation "net.minecraftforge:eventbus:5.0.3"
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
{{Tip|ForgeGradle automatically adds the [https://files.minecraftforge.net/maven/ Forge Maven] and [https://maven.apache.org/repository/ Maven Central] repositories to projects. If a dependency is not present in these (such as dependencies on other mods), the repository containing the dependency must be declared in the <code>repositories</code> block of the Gradle buildscript.<ref>[hhttps://docs.gradle.org/6.8.1/userguide/declaring_repositories.html Gradle User Guide for 6.8.1: ''Declaring repositories'']</ref>}}
+
{{Tip|ForgeGradle automatically adds the [https://files.minecraftforge.net/maven/ Forge Maven] and [https://maven.apache.org/repository/ Maven Central] repositories to projects. If a dependency is not present in these (such as dependencies on other mods), the repository containing the dependency must be declared in the <code>repositories</code> block of the Gradle buildscript.<ref>[https://docs.gradle.org/current/userguide/declaring_repositories.html Gradle User Guide: ''Declaring repositories'']</ref>}}
  
 
=== Deobfuscating Dependencies ===
 
=== Deobfuscating Dependencies ===
Line 42: Line 41:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=== Flat Directory Repositories ===
 +
There are occasions where it is needed to temporarily add a dependency on a JAR file that is not present in a Maven repository, such as to add a mod which adds some developer tools during runtime. Gradle allows declaring '''flat directory repositories''', which use a local directory as a simplified repository.<ref>[https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver Gradle User Guide: ''Flat directory repository'']</ref>
 +
 +
A flat directory repository is declared using a <code>flatDir</code> block within the <code>repositories</code> block, and specifying directories using <code>dirs</code>:
 +
<syntaxhighlight lang="gradle">
 +
repositories {
 +
    flatDir {
 +
        dirs 'lib'
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 +
When a dependency artifact is searched for in a flat directory repository, it will look for the following files in order (<code>''ext''</code> defaults to <code>jar</code>)<ref>[https://github.com/gradle/gradle/blob/v7.4.2/subprojects/core-api/src/main/java/org/gradle/api/artifacts/repositories/FlatDirectoryArtifactRepository.java gradle/gradle; tag v7.4.2; org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository]</ref>:
 +
* <code>''<artifact>''-''<version>''.''<ext>''</code>
 +
* <code>''<artifact>''-''<version>''-''<classifier>''.''<ext>''</code>
 +
* <code>''<artifact>''.''<ext>''</code>
 +
* <code>''<artifact>''-''<classifier>''.''<ext>''</code>
 +
 +
For example, for the dependency <code>org.junit.jupiter:junit-jupiter-api:5.7.2</code>, it will first search for <code>junit-jupiter-api-5.7.2.jar</code> then <code>junit-jupiter-api.jar</code>. The group ID in the dependency descriptor must be present (due to the presence of non-flat directory repositories as added by ForgeGradle), but it will always be ignored.
 +
 +
{{Tip/Warning
 +
|Flat directory repositories should ''only'' be used temporarily in a local environment, and not used to include a required dependency for your project. For a actual dependency used by your mod, use a remote Maven repository holding the artifact.
 +
}}
 +
 +
=== CurseMaven ===
 +
A commonly used alternative is [https://www.cursemaven.com/ CurseMaven](credits to Wyn Price) which allows you to depend on any file uploaded to [https://www.curseforge.com/minecraft/mc-mods/ CurseForge].
 +
 +
First add the CurseMaven Repository within the <code>repositories</code> block:
 +
<syntaxhighlight lang="gradle">
 +
repositories {
 +
    maven {
 +
        url 'https://www.cursemaven.com'
 +
        // FG4: It's recommended to uncomment the following block
 +
        // content {
 +
        //    includeGroup "curse.maven"
 +
        // }
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 +
Then declare a dependency using the following format:
 +
* <code>''curse.maven'':''<description>-<project-id>'':''<file-id>''</code>
 +
 +
As an example, the dependency <code>curse.maven:jei-238222:3295418 </code>, would resolve to [https://www.curseforge.com/minecraft/mc-mods/jei/files/3295418 this file] on CurseForge.
 +
 +
For more information on usage, visit [https://www.cursemaven.com/ CurseMaven]

Latest revision as of 14:32, 18 June 2022

A dependency is the reliance of a piece of software on another piece of software. In the context of Minecraft Forge, it is a mod or library which another mod relies or depends on.

Dependencies are declared in three ways:

  • The dependencies block in a Gradle buildscript defines compile-time and runtime dependencies, which are used by the build system and compiler when building or running the mod in the development environment.
  • The act of using classes, fields, and methods from a library creates a dependency on the library in the compiled binaries. The library may be an explicitly declared dependency, or a dependency of an explicitly declared dependency (such as the Guava libraries that Minecraft depends on).
  • Dependency configurations are declared in the mods.toml metafile, which is then checked by Forge on runtime on whether they are satisfied.

Hard and Soft Dependencies

There are two types of mod dependencies: hard dependencies, and soft dependencies.

A hard dependency is a dependency where the dependent mod requires that the dependency is present. This may be in the form of a code dependency, wherein the JVM will crash due to the missing class, field, or method from the dependency, or it may be in the form of a dependency configuration which mandates that the dependency is present.

Hard dependencies should be declared using a dependency configuration to allow the Forge Mod Loader to detect the missing dependency and gracefully handle it by showing an error screen to the user, rather than the JVM crashing with a non-user-friendly exception message.

A soft dependency is a dependency where the dependent mod does not require the dependency is present, but extra features or compatibility is added in the case of the dependency being present. This often takes the form of cross-mod compatibility features, where a mod soft-depends on another mod or the mod's API.

Soft dependencies usually take the form of isolated code dependencies, where the code that depends on the soft-dependency is isolated from the rest of the mod until the soft-dependency is detected as being present.

Declaring Dependencies

A mod declares a dependency on a mod or library through Gradle, through the dependencies block.[1]

For example, to declare a dependency on the net:minecraftforge:eventbus:5.0.3 library from the main source set:

dependencies {
    // 'implementation' is for the main source set
    implementation "net.minecraftforge:eventbus:5.0.3"
}
ForgeGradle automatically adds the Forge Maven and Maven Central repositories to projects. If a dependency is not present in these (such as dependencies on other mods), the repository containing the dependency must be declared in the repositories block of the Gradle buildscript.[2]

Deobfuscating Dependencies

Mods (and libraries which use Minecraft code) are usually released as an SRG-obfuscated JAR, which prevents their direct use in development environments due to mismatch between SRG names from the mod/library and the MCP/mapped names in the development environment.

These mods/libraries must be deobfuscated to the development environment's mappings first. This is done using the fg.deobf function, which creates a dependency which is dynamically remapped to the local environment's mappings.

For example, to declare a dependency on the mezz.jei:jei-1.16.5:7.6.1.75 library (which is obfuscated):

dependencies {
    implementation fg.deobf("mezz.jei:jei-1.16.5:7.6.1.75")
}

Flat Directory Repositories

There are occasions where it is needed to temporarily add a dependency on a JAR file that is not present in a Maven repository, such as to add a mod which adds some developer tools during runtime. Gradle allows declaring flat directory repositories, which use a local directory as a simplified repository.[3]

A flat directory repository is declared using a flatDir block within the repositories block, and specifying directories using dirs:

repositories {
    flatDir {
        dirs 'lib'
    }
}

When a dependency artifact is searched for in a flat directory repository, it will look for the following files in order (ext defaults to jar)[4]:

  • <artifact>-<version>.<ext>
  • <artifact>-<version>-<classifier>.<ext>
  • <artifact>.<ext>
  • <artifact>-<classifier>.<ext>

For example, for the dependency org.junit.jupiter:junit-jupiter-api:5.7.2, it will first search for junit-jupiter-api-5.7.2.jar then junit-jupiter-api.jar. The group ID in the dependency descriptor must be present (due to the presence of non-flat directory repositories as added by ForgeGradle), but it will always be ignored.

Warning

Flat directory repositories should only be used temporarily in a local environment, and not used to include a required dependency for your project. For a actual dependency used by your mod, use a remote Maven repository holding the artifact.

CurseMaven

A commonly used alternative is CurseMaven(credits to Wyn Price) which allows you to depend on any file uploaded to CurseForge.

First add the CurseMaven Repository within the repositories block:

repositories {
    maven {
        url 'https://www.cursemaven.com'
        // FG4: It's recommended to uncomment the following block
        // content {
        //     includeGroup "curse.maven"
        // }
    }
}

Then declare a dependency using the following format:

  • curse.maven:<description>-<project-id>:<file-id>

As an example, the dependency curse.maven:jei-238222:3295418 , would resolve to this file on CurseForge.

For more information on usage, visit CurseMaven