Skip to main content

Entrypoints

Overview

In order for your mod to be loaded, you must create a mod-loader specific entrypoint inside each corresponding mod-loader subproject, and register your mod with Balm inside.

If you use the balm-mod template repository, this setup should already be done for you.

If you use Jared's MultiLoader template, you need to add the calls to Balm.initializeMod() so that your mod is registered with Balm.

NeoForge

neoforge.mods.toml

Your mod must come with a neoforge.mods.toml file that defines the metadata, dependencies and mixin configurations to load.

Refer to the NeoForge documentation to learn more.

Common Entrypoint

@Mod(Waystones.MOD_ID)
public class NeoForgeWaystones {
public NeoForgeWaystones(IEventBus modEventBus) {
final var context = new NeoForgeLoadContext(modEventBus);
// Using a BalmModule
Balm.initializeMod(Waystones.MOD_ID, context, new Waystones());
// or using a static initializer method
// Balm.initializeMod(Waystones.MOD_ID, EmptyLoadContext.INSTANCE, Waystones::initialize);
}
}

Client Entrypoint

@Mod(value = Waystones.MOD_ID, dist = Dist.CLIENT)
public class NeoForgeWaystonesClient {

public NeoForgeWaystonesClient(IEventBus modEventBus) {
final var context = new NeoForgeLoadContext(modEventBus);
// Using a BalmClientModule
BalmClient.initializeMod(Waystones.MOD_ID, context, new WaystonesClient());
// or using a static initializer method
// BalmClient.initializeMod(Waystones.MOD_ID, EmptyLoadContext.INSTANCE, WaystonesClient::initialize);
}
}

Fabric

fabric.mod.json

Your mod must come with a fabric.mod.json file that defines the main and client entrypoints to your entrypoint classes as well as all other metadata.

Refer to the Fabric documentation to learn more.

tip

Balm provides a default Mod Menu entrypoint to automatically expose your mod's configuration through supported config screens.

You should only need to define a custom modmenu entrypoint if you want to provide your own configuration screen or make other changes.

Common Entrypoint

public class FabricWaystones implements ModInitializer {
@Override
public void onInitialize() {
// Using a BalmModule
Balm.initializeMod(Waystones.MOD_ID, EmptyLoadContext.INSTANCE, new Waystones());
// or using a static initializer method
// Balm.initializeMod(Waystones.MOD_ID, EmptyLoadContext.INSTANCE, Waystones::initialize);
}
}

Client Entrypoint

public class FabricWaystonesClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
// Using a BalmClientModule
BalmClient.initializeMod(Waystones.MOD_ID, EmptyLoadContext.INSTANCE, new WaystonesClient());
// or using a static initializer method
// BalmClient.initializeMod(Waystones.MOD_ID, EmptyLoadContext.INSTANCE, WaystonesClient::initialize);
}
}

Forge

mods.toml

Your mod must come with a mods.toml file that defines the metadata and dependencies to load.

Refer to the Forge documentation to learn more.

Also note that Forge uses the MixinConfigs manifest attribute to define mixin configurations. On the template projects this is already taken care of, but otherwise you may have to adjust your gradle files to set the attribute accordingly.

Common & Client Entrypoint

@Mod(Waystones.MOD_ID)
public class ForgeWaystones {
final var loadContext = new ForgeLoadContext(context.getModEventBus());
// Using a BalmClientModule
Balm.initializeMod(Waystones.MOD_ID, EmptyLoadContext.INSTANCE, new Waystones());
// or using a static initializer method
// Balm.initialize(Waystones.MOD_ID, loadContext, Waystones::initialize);
if (FMLEnvironment.dist.isClient()) {
// To use BalmClientModule, create a static initializer method on Forge where you register the module manually.
BalmClient.initialize(Waystones.MOD_ID, loadContext, ForgeWaystonesClient::initialize);
// or using a static initializer method
// BalmClient.initialize(Waystones.MOD_ID, loadContext, WaystonesClient::initialize);
}
}

If you're using BalmClientModule:

public class ForgeWaystonesClient {
public static void initialize() {
Balm.registerModule(new WaystonesClient());
}
}
info

This looks scary because it's accessing client-only code from a common context, but it's actually safe in modern Java as long as the methods involved are all static.

However, creating a new instance of WaystonesClient like in the other examples would load the class, so unfortunately you have to wrap the module registration into a helper class on Forge.

Third Party Mod Compatibility

The mod-loader specific entrypoints are also a good place to initialize addon compatibility classes that are only present in your mod-loader subprojects.

You can use Balm.initializeIfLoaded to only load the given class if the mod is present, avoiding a hard dependency on the third party mod.

Balm.initializeIfLoaded("exnihilosequentia", "net.blay09.mods.excompressum.compat.ExNihiloSequentiaIntegration");
warning

Don't use ExNihiloSequentiaIntegration.class.getName() as that will cause the class to be loaded even if the third party mod isn't present, which will lead to a crash if that class happens to access any classes from the third party mod.