Getting started
Set up an Apoli addon and register your first power type in Java.
This page takes you from an empty mod to a working custom power type. You should already have a Fabric (or NeoForge) mod project building.
1. Depend on Apoli
In build.gradle, add Apoli. The coordinate is qualified by loader and Minecraft version:
repositories {
mavenLocal() // if you build Apoli yourself
}
dependencies {
modImplementation "dev.overgrown:apoli-fabric-1.21.1:${apoli_version}"
} And declare the dependency in fabric.mod.json so the game enforces it:
{ "depends": { "apoli": ">=1.5.0" } } 2. An id helper
Everything you register needs an id in your namespace. Mirror Apoli’s helper:
public final class MyMod {
public static final String MOD_ID = "mymod";
public static ResourceLocation id(String path) {
return ResourceLocation.fromNamespaceAndPath(MOD_ID, path);
}
} 3. Write a power type
A power type is a PowerType<C> where C is a config record. The codec is the JSON schema:
public final class GravityPower extends PowerType<GravityPower.Cfg> {
public record Cfg(double multiplier) {}
private static final MapCodec<Cfg> CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
Codec.DOUBLE.optionalFieldOf("multiplier", 1.0).forGetter(Cfg::multiplier)
).apply(i, Cfg::new));
@Override public MapCodec<Cfg> configCodec() { return CODEC; }
@Override public void onAdded(ResourceLocation id, Cfg cfg, PowerContainer holder, ResourceLocation source) {
// apply the effect to holder.owner()
}
} See Registering power types for the full lifecycle.
4. Register it
During mod initialisation (your entrypoint), hand it to the registry:
public class MyModInit implements ModInitializer {
@Override public void onInitialize() {
PowerTypeRegistry.register(MyMod.id("gravity"), new GravityPower());
}
} 5. Use it from JSON
Your type is now a first-class Apoli type — any data pack (including yours) can write:
{ "type": "mymod:gravity", "multiplier": 0.4 } Where things get registered
| You’re adding… | Register with |
|---|---|
| a power type | PowerTypeRegistry.register |
| an action | ActionTypes.ENTITY / .BI_ENTITY / … |
| a condition | ConditionTypes.ENTITY / … |
| a reusable JSON value type | a shared Codec |
Next
- Registering power types
- Actions & conditions
- Performance rules — read before shipping tick code.