API and Integration
Third-party plugins reach EmakiMobs' mob definitions through emaki-mobs-api.
Maven coordinates
<repositories>
<repository>
<id>jiuwu-releases</id>
<url>https://repo.crypticlib.com/repository/maven-public/</url>
</repository>
</repositories>
<dependency>
<groupId>emaki.jiuwu.craft</groupId>
<artifactId>emaki-mobs-api</artifactId>
<version>1.0.6</version>
<scope>provided</scope>
</dependency>repositories { maven("https://repo.crypticlib.com/repository/maven-public/") }
dependencies { compileOnly("emaki.jiuwu.craft:emaki-mobs-api:1.0.6") }Compile-time dependency only
The runtime jar already embeds its API classes without relocation. Never install, bundle, shade, or relocate the API jar: a duplicate ClassLoader type breaks events and bridges.
Declare EmakiMobs as a dependency in your paper-plugin.yml:
dependencies:
server:
EmakiMobs:
load: BEFORE
required: false
join-classpath: trueFacade
emaki.jiuwu.craft.mobs.api.EmakiMobsApi is a static facade:
| Method | Description |
|---|---|
status() | Availability and identity metadata; returns CoreLib's ApiStatus. |
catalog() | Query layer, see MobCatalog below. |
operations() | Operation layer, see MobOperations below. |
extensions() | Extension layer, see MobExtensions below. |
Accessors never return null. When EmakiMobs is absent the catalog answers empty, so callers must not treat a NullPointerException as an availability signal.
MobCatalog query layer
Annotated @ApiStatus.NonExtendable.
| Method | Thread | Returns | Description |
|---|---|---|---|
definition(String mobId) | any thread | Optional<MobDefinition> | Look up a mob definition by id. |
registeredIds() | any thread | Set<String> | List every registered mob id (immutable snapshot). |
All methods return immutable snapshots and are thread-safe.
MobOperations operation layer
| Method | Returns | Description |
|---|---|---|
spawn(Location location, String mobId) | Optional<LivingEntity> | Spawn a registered custom mob at the given location. location must have a non-null world and mobId is case-sensitive; returns an empty Optional when the id is unknown or spawning fails. |
remove(LivingEntity entity) | void | Remove a managed entity. The interface default is a no-op; the active runtime bridge supplies the real implementation. |
While EmakiMobs is absent or not yet ready, operations() returns a safe no-op implementation whose spawn always yields Optional.empty().
Spawning an entity mutates Bukkit state: on Folia, switch to the owner thread for that location before calling it.
MobExtensions extension layer
| Method | Description |
|---|---|
registerCustomSpawner(String id, CustomSpawner spawner) | Register a custom spawner; id is used for deduplication. |
MobExtensions.CustomSpawner is a functional interface nested inside MobExtensions, with a single onReload() callback: it is invoked once immediately on registration, then again after every EmakiMobs config reload. Use it to read updated config values and (re)schedule your own spawn tasks.
EmakiMobsApi.extensions().registerCustomSpawner("my_spawner", () -> {
// Runs on registration and after every reload
reloadMySpawnConfig();
});MobDefinition model
Exposed fields:
| Field | Type | Description |
|---|---|---|
id() | String | The unique mob identifier used in YAML files and commands |
entityType() | EntityType | The underlying Minecraft entity type |
displayName() | @Nullable String | MiniMessage-formatted custom name; null when unset |
experience() | int | Experience override on kill; 0 means use the vanilla default |
Internal implementation that is not exposed: components, attributes, skills, threat, and boss_bar are not part of the public API. They are internal configuration and cannot be queried by third-party plugins.
Do not cache layer objects
Resolve catalog() at the point of use instead of storing it in a field: the backing bridge is replaced on reload.
// Correct
EmakiMobsApi.catalog().definition("elite_zombie");
// Wrong: this reference points at the old bridge after a reload
private final MobCatalog cached = EmakiMobsApi.catalog();Example
import emaki.jiuwu.craft.mobs.api.EmakiMobsApi;
import emaki.jiuwu.craft.mobs.api.MobCatalog;
import emaki.jiuwu.craft.mobs.api.model.MobDefinition;
import org.bukkit.entity.EntityType;
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
if (!EmakiMobsApi.status().usable()) {
getLogger().warning("EmakiMobs API is unavailable");
return;
}
MobCatalog catalog = EmakiMobsApi.catalog();
// Look up a single mob definition
catalog.definition("elite_zombie").ifPresent(mob -> {
getLogger().info("Found mob: " + mob.displayName()
+ " (type: " + mob.entityType()
+ ", exp: " + mob.experience() + ")");
});
// List every registered mob
getLogger().info("Registered " + catalog.registeredIds().size() + " mob types");
for (String mobId : catalog.registeredIds()) {
catalog.definition(mobId).ifPresent(mob -> {
if (mob.entityType() == EntityType.ZOMBIE) {
getLogger().info(" - " + mobId + " (zombie variant)");
}
});
}
}
}Integration notes
- Use
definition()to check whether an id belongs to an EmakiMobs-managed custom mob when a mob spawns or is interacted with. registeredIds()is useful for tab completion and configuration validation.MobDefinitionexposes a small field set intended for basic information display. When you need more detail (components, attributes, and so on), read EmakiMobs' configuration files directly or use entity PDC markers.