Getting Started¶
This guide sets up a multi-loader mod on CoolCatLib: Core, and optionally Canvas. It assumes the usual layout: a common module plus one module per loader, as with Architectury Loom.
1. Add the dependency¶
CoolCatLib is published on the ModResources Maven. Artifacts are named net.ixdarklord.coolcatlib:coolcatlib-<mod>-<module>:<minecraft>-<build>, where <mod> is core or canvas.
repositories {
maven { url = "https://raw.githubusercontent.com/ixDarkLorD/ModResources/main/maven/" }
}
Remapped versions
On Minecraft versions that are still remapped (1.21.1 and 1.20.1), use Loom's modApi instead of api.
Then declare the dependency in your mod's metadata. Versions take the form <minecraft>-<build>:
2. Write your constructors¶
Everything starts from constructor classes in your common module: one per side, each optional. They live in net.ixdarklord.coolcatcore.api.core.
| Interface | Runs | Methods |
|---|---|---|
ModConstructor |
Both sides | onConstructMod(): create and register() your DeferredRegisters, and register payloads, events, configs and reload listeners. onCommonSetup(): after registries are filled. |
ClientModConstructor |
Client only, so it may use client classes | onConstructMod(): key mappings, menu screens, tooltip components, client events. onClientSetup(). |
ServerModConstructor |
Dedicated server only | onConstructMod(), onServerSetup(). |
DataGenerationConstructor |
Datagen runs only | onGatherData(DataGenerationContext context): add providers with context.addProvider(...). |
public class MyMod implements ModConstructor {
public static final String MOD_ID = "mymod";
@Override
public void onConstructMod() {
MyRegistries.BLOCKS.register();
MyRegistries.ITEMS.register();
MyConfigs.init();
MyPayloads.register();
ServerTickEvents.END.register(server -> { /* every server tick */ });
}
}
Register early
Payloads, key mappings, menu screens and tooltip components must be registered in onConstructMod(). NeoForge collects them through registration events that fire before common setup.
3. Hook them up per loader¶
No Java class is needed; list your constructors as entrypoints:
"entrypoints": {
"coolcatcore:common": ["com.example.mymod.MyMod"],
"coolcatcore:client": ["com.example.mymod.MyModClient"],
"coolcatcore:server": ["com.example.mymod.MyModServer"],
"coolcatcore:datagen": ["com.example.mymod.MyModData"],
"fabric-datagen": ["net.ixdarklord.coolcatcore.api.core.fabric.FabricDataGenerationEntrypoint"]
}
FabricDataGenerationEntrypoint runs every coolcatcore:datagen constructor of the mod being generated. You only need it for datagen.
Extend NeoForgeModEntrypoint with your @Mod class:
@Mod(MyMod.MOD_ID)
public final class MyModNeoForge extends NeoForgeModEntrypoint {
public MyModNeoForge(ModContainer container) {
super(container);
this.common(MyMod::new);
this.client(() -> MyModClient::new);
this.server(() -> MyModServer::new);
this.dataGeneration(MyModData::new);
}
}
Client and server constructors are given as a supplier of a factory, so their classes are never loaded on the other side. The entrypoint also exposes container, modEventBus and modId for any NeoForge-specific setup you still need.
4. Next steps¶
-
React to the game from common code.
-
Blocks, items, creative tabs and client registries.
-
Payloads without writing codecs.
-
Settings players can edit in game.
-
Data on players, entities and items.
-
Shader effects, skyboxes and animated text.