Skip to main content

Overview

Most powers can be built in a data pack with no code at all. You only need the Java API when JSON can't do the job: a new kind of power, a new action or condition, or a hook into game internals that no existing type exposes.

This part of the docs is for mod authors writing an Apoli addon. Origins is the main example: a mod that depends on Apoli and registers its own types on top.

When to use Java

You wantUse
To combine existing behavioursA data pack
A new power type with custom logicA PowerType subclass
A new action or conditionAn ActionType or ConditionType implementation
A new data type usable from JSONA Codec and its registration
Compatibility with another modA gated compat module

If your idea rearranges things Apoli already does, stay in JSON. It is faster and needs no build.

How an addon is shaped

An Apoli addon is an ordinary Fabric or NeoForge mod that:

  1. depends on Apoli at build time and at runtime,
  2. registers its power types, actions and conditions during mod initialisation,
  3. optionally ships a data pack of its own powers.

The package layout follows Apoli's own convention, with everything under dev.<you>.<modid>. The entrypoint, MyMod.java, registers everything, and power types, actions and conditions each get a package of their own:

dev/example/mymod/
├── MyMod.java
├── power/
├── action/
└── condition/

Depending on Apoli

Apoli is published for each loader and Minecraft version, and the version string says which, as in 1.118.1+1.21.1-fabric, 1.118.1+1.21.1-neoforge or 1.118.1+1.20.1-fabric. The group is dev.overgrown.apoli and the artifact is apoli. To build against an Apoli you compiled yourself, run its publishToMavenLocal task and add it in build.gradle, with apoli_version set to the full version string in gradle.properties:

repositories {
    mavenLocal()
}

dependencies {
    modImplementation "dev.overgrown.apoli:apoli:${apoli_version}"
}

Released builds are also on the Modrinth Maven repository (https://api.modrinth.com/maven) as maven.modrinth:opoli:<version>. On NeoForge, use implementation instead of modImplementation.

Then declare it in fabric.mod.json, or the NeoForge equivalent, so the game enforces it:

{
  "depends": {
    "apoli": ">=1.5.0"
  }
}
warning

Building against an old local copy is the most common addon bug. If Apoli changes and your addon can't see the change, publish Apoli to mavenLocal again and rebuild with --refresh-dependencies.

Next

Reference map

TopicPage
Power typesRegistering power types
Actions and conditionsActions and conditions
ContextsContexts
Legacy JSONAliasing
Custom value typesCustom data types
Origins from JavaThe Origins API
Where powers liveThe power container
Detecting and granting powersReading powers
Saved stateAux and persistence
Client syncNetworking
Math fieldsExpressions
Rules for hot pathsPerformance
Support for other modsCompatibility
Loader and version differencesLoaders and versions

Worked recipes

ScenarioRecipe
Detect, grant, revoke or suppress a powerPowers on an entity
Get an origin's powers, or a player's originOrigins from Java
Write an action of any flavourWriting actions
Write a condition of any flavourWriting conditions
Mixin into vanilla without conflictsHooking the game