Cultivation API
Cultivation ships a public integration surface for other Hytale mods: plugin.siren.API.CultivationAPI plus fifty-one *Events classes in the same package. It is the intended stable shape of the mod - prefer it over reaching into CultivationManager, Cultivation or the ECS components directly, since those are free to change between versions.
There are four things you can do with it:
- Read a player's cultivation state - realm, stage, global level, banked Qi, race, meditation state, skill points, unlocked nodes, and the state of every subsystem from sects to Lifespan. See the API Reference.
- Register new content that behaves exactly like the built-in content - a race, a technique, a Qi absorption item modifier, a title, a sect banner, a palette, a menu page, a Codex article, an update or compatibility check. Thirty
register*methods in all. See API Registries. - Listen to (and re-tune, or veto) 370 events across every subsystem in the mod. See API Events.
- Replace a whole layer of the mod - the progression ladder itself, its entire vocabulary, or both - while every other subsystem keeps running on top. New in 0.5.0; see API Addons.
This page documents the API as of Cultivation 0.11.0, the current release. Where a method or event arrived after 0.5.0, the page that describes it says which version.
The sources are published. Every public API class, with its javadoc, lives at github.com/SirenHytale/Cultivation-API — alongside a generated reference for every event, a worked example add-on, and a brief written for AI coding assistants. The javadoc in those sources is the authoritative contract; this wiki is the guided tour.
Adding Cultivation to your project
Cultivation 0.11.0 is built for Hytale Update 7 (Server API 0.7.0-pre.5.1, ServerVersion: >=0.7.0-pre.0 <0.8.0) and Java 25, so an addon compiling against it needs the same. Cultivation is not on a public Maven repository: install the released jar into your local one first, then depend on it with provided scope and never shade it into your own jar. The server loads the real Cultivation jar, and two copies of plugin.siren.Cultivation on the classpath would each get their own static plugin instance - so every registry call would go into the copy nobody reads, silently.
mvn install:install-file -Dfile=Cultivation-0.11.0.jar -DgroupId=plugin.siren -DartifactId=Cultivation -Dversion=0.11.0 -Dpackaging=jar
Maven pom.xml:
<repositories>
<repository>
<id>hytale-release</id>
<url>https://maven.hytale.com/release</url>
</repository>
<repository>
<id>hytale-pre-release</id>
<url>https://maven.hytale.com/pre-release</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.hypixel.hytale</groupId>
<artifactId>Server</artifactId>
<version>0.7.0-pre.5.1</version>
</dependency>
<dependency>
<groupId>plugin.siren</groupId>
<artifactId>Cultivation</artifactId>
<version>0.11.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Then declare it in your Hytale manifest.json. Cultivation's own manifest publishes itself as group Siren, name Cultivation, so the dependency id is Siren:Cultivation. Every first-party add-on released with 0.11.0 declares a floor of 0.11.0:
"Dependencies": {
"Siren:Cultivation": ">=0.11.0"
}
A manifest range accepts a full semver range rather than only a floor - ">=0.11.0 <0.12.0" makes the engine refuse to load your addon against any Cultivation outside that band, before a line of your code runs. If you would rather integrate only when Cultivation happens to be installed, put the same entry under "OptionalDependencies" instead, and keep every reference to a plugin.siren class behind a guard so the classes never load without it. See Compatibility for the published compatibility list that corrects a pairing after both jars have shipped.
The entry point
Everything is static. CultivationAPI has a private constructor and is never instantiated - you call it straight off the class:
import plugin.siren.API.CultivationAPI;
import plugin.siren.ECS.Realms.CultivationRealm;
CultivationRealm realm = CultivationAPI.getRealm(accessor, ref);
float qi = CultivationAPI.getQi(accessor, ref);
The read methods all take a ComponentAccessor<EntityStore> and a Ref<EntityStore> - the same pair every Hytale ECS system already has in hand. Anything that reads a component returns null (or 0, or Human) when the player does not have that component yet, so a fresh player never throws.
Listener and registry calls are safe from your own plugin's setup() in any load order relative to Cultivation's own setup(). The registries are plain static maps and the listener lists are CopyOnWriteArrayLists; nothing reads either until a player actually interacts with the mod, which is long after every plugin has finished loading.
Your first listener
The pattern is CultivationEvents.onPreX(...) to change or veto something before it happens, and CultivationEvents.onX(...) to be told once it is committed. Both take a java.util.function.Consumer of the event type, so a lambda is all you need:
import com.hypixel.hytale.server.core.universe.PlayerRef;
import plugin.siren.API.CultivationEvents;
import plugin.siren.ECS.Realms.CultivationRealm;
public final class MyCultivationHooks {
public static void register(){
// Make the jump into Golden Core Formation cost twice as much banked Qi.
CultivationEvents.onPreBreakthrough(event -> {
if(event.toRealm() == CultivationRealm.GOLDEN_CORE_FORMATION){
event.setQiCost(event.qiCost() * 2.0F);
}
});
// Refuse the very last realm outright.
CultivationEvents.onPreBreakthrough(event -> {
if(event.toRealm() == CultivationRealm.VOID_REFINEMENT){
event.setCancelled(true);
}
});
// React once it has actually happened - the component already shows the new realm.
CultivationEvents.onBreakthrough(event -> {
if(event.player() != null){
recordAscension(event.player(), event.newRealm());
}
});
}
private static void recordAscension(PlayerRef player, CultivationRealm realm){
// your own bookkeeping here
}
}
Call MyCultivationHooks.register() from your plugin's setup(). There is deliberately no unregister - a listener's lifetime is the server's lifetime, matching how plugins load once and stay.
Pages
| Page | Covers |
|---|---|
| API Events | All 370 events in the 51 *Events classes, grouped by subsystem: when each fires, whether it can be cancelled, what it exposes, and the locking and threading rules that apply. |
| API Registries | All 30 register* methods - races, techniques and their gates, menu pages, Codex entries, update, build and compat checks, palettes, auras, titles, banners, standing modifiers, store benefits, the caps - and the public types they use. |
| API Reference | Every one of the 261 CultivationAPI methods by family, and the 50 CultivationConfigs accessors. |
| API Addons | ProgressionProvider (every method you implement, with a complete example), CultivationTheme and AdminConfigSection - replacing the ladder, the wording, and adding your own admin settings. |
Player-facing documentation for the systems these hooks sit on top of lives on the main wiki: Cultivation Realms, Qi Gathering, The Dao, Techniques, Sects, Sect Wars, Formations, Cave Abodes, Duels and Spirit Beasts. Every number an event lets you re-tune also has a server-owner-facing equivalent on the Config page, and most of them mirror something on the Commands page.