Skip to content

API

EmakiCodexApi is EmakiCodex's static public API facade for third-party plugins. Depend on emaki-codex-api at compile time; the installed EmakiCodex plugin provides the runtime implementation.

Server owners install only EmakiCodex-*.jar. Do not put emaki-codex-api-*.jar into the server plugins/ directory.

Maven dependency

xml
<dependency>
    <groupId>emaki.jiuwu.craft</groupId>
    <artifactId>emaki-codex-api</artifactId>
    <version>1.0.0</version>
    <scope>provided</scope>
</dependency>

If your plugin is built with Maven, make sure the runtime server has the same or a newer EmakiCodex plugin installed.

Gradle dependency

kotlin
dependencies {
    compileOnly("emaki.jiuwu.craft:emaki-codex-api:1.0.0")
}

Availability checks

java
import emaki.jiuwu.craft.codex.api.EmakiCodexApi;

if (!EmakiCodexApi.available() || !EmakiCodexApi.isReady()) {
    return;
}

available() means the Codex API bridge is installed. isReady() means the plugin is enabled and initialized.

You can also use the migration helper:

java
import emaki.jiuwu.craft.codex.api.EmakiCodexApiProvider;

if (EmakiCodexApiProvider.available()) {
    EmakiCodexApiProvider.requireAvailable();
}

EmakiCodexApiProvider is only an availability helper; it is not an instance service entry point.

Grant a node

java
import java.util.UUID;
import emaki.jiuwu.craft.codex.api.EmakiCodexApi;

UUID playerId = player.getUniqueId();
boolean changed = EmakiCodexApi.grantAdvancement(playerId, "example/first_step");

if (!changed) {
    // The player is offline, the calling thread does not own the player, the node is not registered, or the player already completed it.
}

The synchronous methods require the calling thread to already own the target player. When it does not, they return false immediately. Use the asynchronous overloads below when ownership is unclear.

advancementId supports two forms:

FormExample
Short formexample/first_step
Full keyemakicodex:example/first_step

Granting a node awards the internal codex criterion. On first completion, the vanilla completion flow runs and the node's actions.complete list executes.

Revoke a node

java
import java.util.UUID;
import emaki.jiuwu.craft.codex.api.EmakiCodexApi;

UUID playerId = player.getUniqueId();
boolean changed = EmakiCodexApi.revokeAdvancement(playerId, "example/first_step");

if (!changed) {
    // The player is offline, the calling thread does not own the player, the node is not registered, or the player has not completed it.
}

Revoke only affects registered Codex nodes. It does not delete configuration files and does not remove advancement definitions from the server registry.

Asynchronous writes

When you are not sure whether the current thread owns the target player, use the asynchronous overloads and let EmakiCodex dispatch to the correct owner thread:

java
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import emaki.jiuwu.craft.codex.api.EmakiCodexApi;

CompletableFuture<Boolean> future =
        EmakiCodexApi.grantAdvancementAsync(playerId, "example/first_step");

future.thenAccept(changed -> {
    // The callback thread is not guaranteed to be the main thread.
});
MethodReturnsDescription
grantAdvancementAsync(UUID, String)CompletableFuture<Boolean>Grants a node asynchronously. Returns a completed false when the API is unavailable.
revokeAdvancementAsync(UUID, String)CompletableFuture<Boolean>Revokes a node asynchronously. Returns a completed false when the API is unavailable.

These methods do not promise a thread switch: the returned future may already be complete when the player is offline, the API is unavailable, or scheduling fails. Callbacks that touch Bukkit/Paper/Folia state must dispatch to the correct owner thread themselves.

Version and plugin name

java
String version = EmakiCodexApi.apiVersion();
String pluginName = EmakiCodexApi.pluginName();

When the API is unavailable, both methods return an empty string.

Integration boundaries

  • The API exposes only a static facade. It does not expose AdvancementService, loaders, listeners, or configuration parsers.
  • API methods target online player UUIDs. Offline players are not loaded or modified.
  • If you want to grant nodes from configured action chains, prefer CoreLib Actions. Use EmakiCodexApi for third-party plugin code integration.
  • The current public API does not expose a resync method for refreshing the player's client advancement tree. Use the codex_resync_advancement CoreLib action when you need that behavior.