Skip to content

API and Integration

Third-party plugins reach EmakiMobs' mob definitions through emaki-mobs-api.

Maven coordinates

xml
<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>
kotlin
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:

yaml
dependencies:
  server:
    EmakiMobs:
      load: BEFORE
      required: false
      join-classpath: true

Facade

emaki.jiuwu.craft.mobs.api.EmakiMobsApi is a static facade:

MethodDescription
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.

MethodThreadReturnsDescription
definition(String mobId)any threadOptional<MobDefinition>Look up a mob definition by id.
registeredIds()any threadSet<String>List every registered mob id (immutable snapshot).

All methods return immutable snapshots and are thread-safe.

MobOperations operation layer

MethodReturnsDescription
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)voidRemove 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

MethodDescription
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.

java
EmakiMobsApi.extensions().registerCustomSpawner("my_spawner", () -> {
    // Runs on registration and after every reload
    reloadMySpawnConfig();
});

MobDefinition model

Exposed fields:

FieldTypeDescription
id()StringThe unique mob identifier used in YAML files and commands
entityType()EntityTypeThe underlying Minecraft entity type
displayName()@Nullable StringMiniMessage-formatted custom name; null when unset
experience()intExperience 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.

java
// Correct
EmakiMobsApi.catalog().definition("elite_zombie");

// Wrong: this reference points at the old bridge after a reload
private final MobCatalog cached = EmakiMobsApi.catalog();

Example

java
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.
  • MobDefinition exposes 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.