<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://forge.gemwire.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AterAnimAvis</id>
	<title>Forge Community Wiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://forge.gemwire.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AterAnimAvis"/>
	<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/wiki/Special:Contributions/AterAnimAvis"/>
	<updated>2026-06-02T05:37:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Jar-in-Jar&amp;diff=3359</id>
		<title>Jar-in-Jar</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Jar-in-Jar&amp;diff=3359"/>
		<updated>2022-10-15T14:53:45Z</updated>

		<summary type="html">&lt;p&gt;AterAnimAvis: Update link to sources&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Jar-in-Jar is a way to handle the dependencies of your mod.&lt;br /&gt;
Sometimes these are libraries pulled from a central maven repository, sometimes these are libraries specially designed for Minecraft and sometimes these are completely other mods.&lt;br /&gt;
Whatever the reason for using a library during the development of your mods, you will need to ensure that the end user has them available when he runs your mod in his environment.&lt;br /&gt;
&lt;br /&gt;
Although there are several options available to achieve this, including for example the Shading plugin, this does not work all the time and can even cause problems along the way when for example two mods need the same dependency.&lt;br /&gt;
Introducing the all-new, all-shiny: Jar-In-Jar.&lt;br /&gt;
====Central function====&lt;br /&gt;
Jar-In-Jar is first and foremost a way to load dependencies for mods, from the jars of the mods.&lt;br /&gt;
To achieve this it looks for a file called: ''META-INF/jarjar/metadata.json''. If you are interested in the format of this file, see the following section of the JarJar library which we expose: [https://github.com/MinecraftForge/JarJar/tree/main/metadata/src/main/java/net/minecraftforge/jarjar/metadata JarJar Library - Metadata Source] &lt;br /&gt;
&lt;br /&gt;
In short, this metadata file lists a set of dependencies to include, what their maven coordinate is, the accepted version range that your mod supports, the version of the dependency that is included in your mods jar as well as a path to the jar in your mods jar file.&lt;br /&gt;
&lt;br /&gt;
During the startup of the game, FML will first collect all mods and then collect all their dependencies to load. Jar-In-Jar hooks into this second phase and reads all the dependency files (recursively) and then determines what versions of the dependencies to load. &lt;br /&gt;
====Dependency negotiation====&lt;br /&gt;
Because different mods might need different versions of the same dependency (and have those included) Jar-In-Jar is first and foremost a negotiation system (hence you having to supply a version range your mod supports). From all dependencies that need to be loaded their supported version range is narrowed down to the agreeable range that all mods support. Then there are in principle three outcomes that can occur:&lt;br /&gt;
# No agreeable version range is found: Loading can not continue and the user will see an error message that mods require different dependency versions which are not compatible.&lt;br /&gt;
# An agreeable version range is found, but no jar was included in any of the dependencies which have a version that fits in the agreed range: Loading can not continue and the user will see an error message that the mods have agreed upon a supported range, but no file was found with the required version.&lt;br /&gt;
# An agreeable version range is found, and a matching jar could be located: That dependency will be loaded.&lt;br /&gt;
&lt;br /&gt;
====Dependency loading====&lt;br /&gt;
Once negotiation ends, the selected jars are loaded into the game.&lt;br /&gt;
The class loading layer is determined in two ways:&lt;br /&gt;
# The default way: If a mod, plugin, or language loader is detected then it is loaded in the appropriate layer and processed as such.&lt;br /&gt;
# The override way: If a library is supposed to be loaded which is not aware of Minecraft (for example JGraphT) then it will be loaded as a game library only. Meaning that your mod has access to it, but not plugins or language loaders. Those as such can only use libraries that are Minecraft aware or Shaded instead of Jar-In-Jarred into their respective jar.&lt;br /&gt;
&lt;br /&gt;
=== Using ForgeGradle to generate a Jar-In-Jar ===&lt;br /&gt;
Jar-In-Jar is a completely optional system.&lt;br /&gt;
To enable it, you need to call `jarJar.enable()` anywhere in your buildscript.&lt;br /&gt;
By default, this will include all the dependencies in the `jarjar` configuration into the task output of the `jarJar` task.&lt;br /&gt;
''Note: The task jarJar is not accessible via the `jarJar` statement, since this references the project extension to manage Jar-In-Jar. If you need to modify the task use: `tasks.jarJar.configure { ... } `''&lt;br /&gt;
&lt;br /&gt;
==== Using the runtime dependencies ====&lt;br /&gt;
To include the runtime dependencies as well, you can invoke `jarJar.fromRuntimeConfiguration()` which will include the dependencies which are found at the runtime. If you use this, it is highly suggested to include a dependency filter, since else every single dependency, including Minecraft, forge, and their dependencies are included as well.&lt;br /&gt;
&lt;br /&gt;
==== Using dependency filters ====&lt;br /&gt;
While you can filter the dependencies by including them in the `jarJar` configuration or not, this is not always as flexible as you need it to be. To achieve fine grain filtering the dependency configuration endpoint has been added to the `jarJar` extension as well as to the `jarJar` task. &lt;br /&gt;
Using this endpoint you can configure dependency patterns (including using regular expressions) which you can include and exclude from the configuration:&lt;br /&gt;
&lt;br /&gt;
===== Exclude gson example =====&lt;br /&gt;
 dependencies {&lt;br /&gt;
     exclude(dependency('com.google.gson.*')) &lt;br /&gt;
 }&lt;br /&gt;
This example excludes any dependency which has `com.google.gson.` as a prefix of the group name of that artifact.&lt;br /&gt;
&lt;br /&gt;
===== Include filters with runtime configuration usage =====&lt;br /&gt;
It is generally recommended to set at least one `include` filter when using the `fromRuntimeConfiguration` option.&lt;br /&gt;
&lt;br /&gt;
==== Dependency version pinning ====&lt;br /&gt;
Since Jar-In-Jar is first and foremost a negotiation system it is required that you provide a way to supply it with a supported range, by default this is done via the version property of your dependency:&lt;br /&gt;
 dependencies {&lt;br /&gt;
    jarJar(group: 'com.google.code.gson', name: 'gson', version: '[2.0,3.0)')&lt;br /&gt;
 }&lt;br /&gt;
However, this might not produce the required result or even the required artifact you wish to include (by default the highest supported version is included based on Gradle dependency resolution rules).&lt;br /&gt;
Using dependency version pinning you can specify which version of the dependency Jar-In-Jar should include when the jar is made. To achieve this configure the dependency and invoke: `jarJar.pin(&amp;lt;dependency instance&amp;gt;, &amp;quot;version_string&amp;quot;)` as follows:&lt;br /&gt;
 dependencies {&lt;br /&gt;
    implementation(group: 'com.google.code.gson', name: 'gson', version: '[2.0,3.0)') {&lt;br /&gt;
        jarJar.pin(it, &amp;quot;2.8.0&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
The example above will include version 2.8.0 of the GSON library into the Jar-In-Jar jar built by the `jarJar` task.&lt;br /&gt;
&lt;br /&gt;
==== Dependency range pinning ====&lt;br /&gt;
Next to dependency version pinning Jar-In-Jar also supports pinning the version range which your mod supports, outside of the compile dependency range that you specify in the dependency statement:&lt;br /&gt;
 dependencies {&lt;br /&gt;
    implementation(group: 'com.google.code.gson', name: 'gson', version: '2.8.0') {&lt;br /&gt;
        jarJar.ranged(it, &amp;quot;[2.0,3.0)&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
As you can see this function is very useful when you combine it with runtime configuration-based dependency selection since it allows you to use a single statement to add the dependency to your project, as well as include it with a properly supported version range within your Jar-In-Jar jar.&lt;br /&gt;
&lt;br /&gt;
==== Publishing a Jar-in-Jar jar to maven ====&lt;br /&gt;
Although in practice this is not really useful to do, for archival reasons FG supports publishing Jar-In-Jar artifacts to a maven of choice. The setup is similar to how the Shadow plugin handles this:&lt;br /&gt;
 publications {&lt;br /&gt;
     mavenJava(MavenPublication) {&lt;br /&gt;
         from components.java&lt;br /&gt;
         jarJar.component(it)&lt;br /&gt;
  &lt;br /&gt;
         //Other statements related to configuring the POM go here&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Using this technique will add all Jar-In-Jar you build in the project to the publication at once and publish them with the other artifacts.&lt;br /&gt;
If you want to only publish a specific Jar-In-Jar artifact to this publication use the following statement, which accepts a task instance to achieve this:&lt;br /&gt;
 publications {&lt;br /&gt;
     mavenJava(MavenPublication) {&lt;br /&gt;
         from components.java&lt;br /&gt;
         jarJar.component(it, tasks.jarJarOther)&lt;br /&gt;
  &lt;br /&gt;
         //Other statements related to configuring the POM go here&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>AterAnimAvis</name></author>
	</entry>
	<entry>
		<id>https://forge.gemwire.uk/index.php?title=Dependencies&amp;diff=2592</id>
		<title>Dependencies</title>
		<link rel="alternate" type="text/html" href="https://forge.gemwire.uk/index.php?title=Dependencies&amp;diff=2592"/>
		<updated>2021-05-09T19:46:08Z</updated>

		<summary type="html">&lt;p&gt;AterAnimAvis: Basic CurseMaven description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;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.&lt;br /&gt;
&lt;br /&gt;
Dependencies are declared in three ways:&lt;br /&gt;
* The &amp;lt;code&amp;gt;dependencies&amp;lt;/code&amp;gt; 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.&lt;br /&gt;
* 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).&lt;br /&gt;
* [[Proper_Mod_Structuring#Dependency_Configurations|Dependency configurations]] are declared in the &amp;lt;tt&amp;gt;mods.toml&amp;lt;/tt&amp;gt; metafile, which is then checked by Forge on runtime on whether they are satisfied.&lt;br /&gt;
&lt;br /&gt;
== Hard and Soft Dependencies ==&lt;br /&gt;
There are two types of mod dependencies: hard dependencies, and soft dependencies.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Declaring Dependencies ==&lt;br /&gt;
A mod declares a dependency on a mod or library through Gradle, through the &amp;lt;code&amp;gt;dependencies&amp;lt;/code&amp;gt; block.&amp;lt;ref&amp;gt;[https://docs.gradle.org/6.8.1/userguide/declaring_dependencies.html Gradle User Guide for 6.8.1: ''Declaring dependencies'']&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, to declare a dependency on the &amp;lt;code&amp;gt;net:minecraftforge:eventbus:4.0.0&amp;lt;/code&amp;gt; library from the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; source set:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
dependencies {&lt;br /&gt;
    // 'implementation' is for the main source set&lt;br /&gt;
    implementation &amp;quot;net.minecraftforge:eventbus:4.0.0&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{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 &amp;lt;code&amp;gt;repositories&amp;lt;/code&amp;gt; block of the Gradle buildscript.&amp;lt;ref&amp;gt;[https://docs.gradle.org/6.8.1/userguide/declaring_repositories.html Gradle User Guide for 6.8.1: ''Declaring repositories'']&amp;lt;/ref&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=== Deobfuscating Dependencies ===&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
These mods/libraries must be deobfuscated to the development environment's mappings first. This is done using the &amp;lt;code&amp;gt;fg.deobf&amp;lt;/code&amp;gt; function, which creates a dependency which is dynamically remapped to the local environment's mappings.&lt;br /&gt;
&lt;br /&gt;
For example, to declare a dependency on the &amp;lt;code&amp;gt;mezz.jei:jei-1.16.5:7.6.1.75&amp;lt;/code&amp;gt; library (which is obfuscated):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
dependencies {&lt;br /&gt;
    implementation fg.deobf(&amp;quot;mezz.jei:jei-1.16.5:7.6.1.75&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Flat Directory Repositories ===&lt;br /&gt;
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.&amp;lt;ref&amp;gt;[https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver Gradle User Guide for 6.8.1: ''Flat directory repository'']&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A flat directory repository is declared using a &amp;lt;code&amp;gt;flatDir&amp;lt;/code&amp;gt; block within the &amp;lt;code&amp;gt;repositories&amp;lt;/code&amp;gt; block, and specifying directories using &amp;lt;code&amp;gt;dirs&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
repositories {&lt;br /&gt;
    flatDir {&lt;br /&gt;
        dirs 'lib'&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a dependency artifact is searched for in a flat directory repository, it will look for the following files in order (&amp;lt;code&amp;gt;''ext''&amp;lt;/code&amp;gt; defaults to &amp;lt;code&amp;gt;jar&amp;lt;/code&amp;gt;)&amp;lt;ref&amp;gt;[https://github.com/gradle/gradle/blob/v6.8.1/subprojects/core-api/src/main/java/org/gradle/api/artifacts/repositories/FlatDirectoryArtifactRepository.java gradle/gradle; tag v6.8.1; org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository]&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''-''&amp;lt;version&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''-''&amp;lt;version&amp;gt;''-''&amp;lt;classifier&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;''&amp;lt;artifact&amp;gt;''-''&amp;lt;classifier&amp;gt;''.''&amp;lt;ext&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, for the dependency &amp;lt;code&amp;gt;junit:junit:4.8.1&amp;lt;/code&amp;gt;, it will first search for &amp;lt;code&amp;gt;junit-4.8.1.jar&amp;lt;/code&amp;gt; then &amp;lt;code&amp;gt;junit.jar&amp;lt;/code&amp;gt;. 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.&lt;br /&gt;
&lt;br /&gt;
{{Tip/Warning&lt;br /&gt;
|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.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== CurseMaven ===&lt;br /&gt;
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].&lt;br /&gt;
&lt;br /&gt;
First add the CurseMaven Repository within the &amp;lt;code&amp;gt;repositories&amp;lt;/code&amp;gt; block:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gradle&amp;quot;&amp;gt;&lt;br /&gt;
repositories {&lt;br /&gt;
    maven {&lt;br /&gt;
        url 'https://www.cursemaven.com'&lt;br /&gt;
        // FG4: It's recommended to uncomment the following block&lt;br /&gt;
        // content {&lt;br /&gt;
        //     includeGroup &amp;quot;curse.maven&amp;quot;&lt;br /&gt;
        // }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then declare a dependency using the following format:&lt;br /&gt;
* &amp;lt;code&amp;gt;''curse.maven'':''&amp;lt;description&amp;gt;-&amp;lt;project-id&amp;gt;'':''&amp;lt;file-id&amp;gt;''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As an example, the dependency &amp;lt;code&amp;gt;curse.maven:jei-238222:3295418 &amp;lt;/code&amp;gt;, would resolve to [https://www.curseforge.com/minecraft/mc-mods/jei/files/3295418 this file] on CurseForge.&lt;br /&gt;
&lt;br /&gt;
For more information on usage, visit [https://www.cursemaven.com/ CurseMaven]&lt;/div&gt;</summary>
		<author><name>AterAnimAvis</name></author>
	</entry>
</feed>