Balm allows you to write code once and build your mod for NeoForge, Fabric and Forge at the same time. For this, Balm provides abstractions to all common functionality such as registries and events.
Additionally, Balm comes with utilities to integrate popular mods like JEI, Jade or Curios all on a single common codebase.
In order to use Balm, you should have
Use this generator to download a blank mod with everything already set up.
You can extract the generated zip file, open the project in your IDE, and jump straight to the next page.
Alternatively, you can use the template repository on GitHub. However, you will have to follow the steps in the README and manually update the template with your own names and properties.
If you already have a project you're trying to port to Balm, the steps depend on whether you are currently on a multi-loader Gradle setup or not.
The following guides give a rough overview on how to migrate your setup to one that supports Balm
The templates offered by mod loaders are designed for single-loader projects.
To support multiple loaders at once, you will have to upgrade your Gradle setup to one that supports multi-loader projects.
You can reference the existing template in the balm-mod repository. It essentially comes down to replacing most of your build.gradle files, adding the build-logic folder from the template, and moving your source code from src/main/java to common/src/main/java.
You will still have a folder for each loader you target, but they will generally only contain your mod's entrypoint (e.g. the Fabric ModInitializer or NeoForge @Mod class).
Once you've got a working Gradle setup, you have to add Balm as a library (see below), and finally you have to initialize your mod with Balm in each loader-specific entrypoint. Learn how your loader-specific entrypoints should look like in the entrypoint section.
Add Balm as a library like you would any other dependency:
repositories {
maven {
url = 'https://maven.twelveiterations.com/repository/maven-public/'
content {
includeGroup 'net.blay09.mods'
}
}
}
dependencies {
implementation("net.blay09.mods:balm-common:${balm_version}") {
changing = balm_version.endsWith('SNAPSHOT')
}
}
repositories {
maven {
url = 'https://maven.twelveiterations.com/repository/maven-public/'
content {
includeGroup 'net.blay09.mods'
}
}
}
dependencies {
modImplementation("net.blay09.mods:balm-fabric:${balm_version}") {
changing = balm_version.contains('SNAPSHOT')
}
}
repositories {
maven {
url = 'https://maven.twelveiterations.com/repository/maven-public/'
content {
includeGroup 'net.blay09.mods'
}
}
}
dependencies {
implementation("net.blay09.mods:balm-neoforge:${balm_version}") {
changing = balm_version.contains('SNAPSHOT')
}
}
repositories {
maven {
url = 'https://maven.twelveiterations.com/repository/maven-public/'
content {
includeGroup 'net.blay09.mods'
}
}
}
dependencies {
implementation("net.blay09.mods:balm-forge:${balm_version}") {
changing = balm_version.contains('SNAPSHOT')
}
}
You will have to initialize your mod with Balm in each loader-specific entrypoint. Learn how your loader-specific entrypoints should look like in the entrypoint section.
That works too — just follow the setup guides and remove the loaders you don't want from the includes in your settings.gradle file. Everything else stays the same.