API Reference
API Reference
Section titled “API Reference”Technical reference for plugin developers. Provides programmatic access to the Citizen and Dialog systems through the unified CoreAPI facade.
:::info Module
The CoreAPI is provided by kyuubisoft-core.jar. Ensure the Core mod is loaded before calling any API methods.
:::
Getting the API Instance
Section titled “Getting the API Instance”import com.kyuubisoft.core.api.CoreAPI;
// Availability check (recommended)if (CoreAPI.isAvailable()) { CoreAPI api = CoreAPI.getInstance(); // ...}
// Or direct (returns null if Core is not loaded)CoreAPI api = CoreAPI.getInstance();if (api == null) { // Core plugin not loaded return;}Citizen Methods
Section titled “Citizen Methods”| Method | Return Type | Description |
|---|---|---|
getCitizen(String id) | CitizenData | Get CitizenData by ID, or null if not found |
getAllCitizens() | Collection<CitizenData> | Get all registered citizens (never null) |
getCitizensByGroup(String group) | List<CitizenData> | Get citizens matching a group (never null) |
addCitizenListener(CitizenListener) | void | Add a citizen lifecycle listener |
removeCitizenListener(CitizenListener) | void | Remove a citizen lifecycle listener |
addDialogInterceptor(CitizenDialogInterceptor) | void | Add a dialog interceptor (checked before default dialogs) |
removeDialogInterceptor(CitizenDialogInterceptor) | void | Remove a dialog interceptor |
dispatchCitizenInteract(Player, String citizenId) | void | Trigger a citizen interaction event programmatically |
pauseCitizenMovement(CitizenData, Player) | void | Pause NPC movement (e.g., during dialog) |
resumeCitizenMovement(String citizenId) | void | Resume NPC movement after interaction |
isCitizenPaused(String citizenId) | boolean | Check if an NPC is currently paused |
Dialog Methods
Section titled “Dialog Methods”| Method | Return Type | Description |
|---|---|---|
openDialog(Player, PlayerRef, Ref, Store, String dialogId, String citizenId) | void | Open a dialog by its ID |
openDialogFromTree(Player, PlayerRef, Ref, Store, DialogTree, String citizenId) | void | Open a dialog from a pre-built DialogTree object |
addDialogConditionProvider(DialogConditionProvider) | void | Register a custom condition provider for dialog branching |
removeDialogConditionProvider(DialogConditionProvider) | void | Remove a condition provider |
Interfaces
Section titled “Interfaces”CitizenListener
Section titled “CitizenListener”Implement this interface to receive citizen lifecycle events. All methods have default no-op implementations, so you only need to override what you need.
import com.kyuubisoft.core.citizen.CitizenListener;
public interface CitizenListener { /** Player interacts with an NPC (before dialog opens) */ default void onCitizenInteract(Player player, String citizenId) {}
/** Player selects a dialog choice */ default void onDialogChoice(Player player, String dialogId, int choiceIndex, String choiceText) {}
/** Dialog chain is fully completed */ default void onDialogComplete(Player player, String dialogId) {}
/** Player enters text input during a dialog */ default void onDialogInput(Player player, String dialogId, String input) {}}CitizenDialogInterceptor
Section titled “CitizenDialogInterceptor”Implement this interface to intercept NPC interactions before the default dialog system runs. If your interceptor returns true, no further dialog processing occurs.
import com.kyuubisoft.core.citizen.CitizenDialogInterceptor;
public interface CitizenDialogInterceptor { /** * Attempt to intercept the dialog for a citizen. * * @return true if this interceptor handled the interaction (no further dialog will open) */ boolean interceptDialog(Player player, PlayerRef playerRef, Ref<EntityStore> ref, Store<EntityStore> store, String citizenId);}DialogConditionProvider
Section titled “DialogConditionProvider”Implement this interface to provide custom conditions for dialog branching. Used by the Quest mod, Achievement mod, and others to enable conditional dialog flows.
import com.kyuubisoft.core.dialog.DialogConditionProvider;
public interface DialogConditionProvider { /** Whether this provider handles the given condition type. */ boolean handles(String conditionType);
/** Evaluate the condition for a player. */ boolean evaluate(Player player, String conditionType, String value, boolean negate);}Usage Examples
Section titled “Usage Examples”Get Citizen Data
Section titled “Get Citizen Data”CoreAPI api = CoreAPI.getInstance();
CitizenData citizen = api.getCitizen("blacksmith_npc");if (citizen != null) { String name = citizen.getDisplayName(); boolean hasShop = citizen.shopId != null; LOGGER.info("Citizen: " + name + ", shop: " + hasShop);}
// Get all citizens in a groupList<CitizenData> guards = api.getCitizensByGroup("town_guards");LOGGER.info("Found " + guards.size() + " town guards");React to Citizen Interactions (Interceptor)
Section titled “React to Citizen Interactions (Interceptor)”CoreAPI api = CoreAPI.getInstance();
api.addDialogInterceptor((player, playerRef, ref, store, citizenId) -> { if ("quest_giver".equals(citizenId)) { // Open custom quest UI instead of default dialog openQuestUI(player, playerRef, ref, store); return true; // Intercepted — no default dialog } return false; // Let default dialog system handle it});Open a Dialog Programmatically
Section titled “Open a Dialog Programmatically”CoreAPI api = CoreAPI.getInstance();
// Open a specific dialog for a citizen// (typically called from within a command or event handler that has access to PlayerRef/Ref/Store)api.openDialog(player, playerRef, ref, store, "greeting_dialog", "merchant_npc");Pause and Resume NPC Movement
Section titled “Pause and Resume NPC Movement”CoreAPI api = CoreAPI.getInstance();
CitizenData npc = api.getCitizen("patrol_guard");if (npc != null && !api.isCitizenPaused("patrol_guard")) { // Pause the NPC while player interacts api.pauseCitizenMovement(npc, player);
// ... do interaction ...
// Resume movement when done api.resumeCitizenMovement("patrol_guard");}Register a Dialog Condition Provider
Section titled “Register a Dialog Condition Provider”CoreAPI api = CoreAPI.getInstance();
api.addDialogConditionProvider(new DialogConditionProvider() { @Override public boolean handles(String type) { return "quest_active".equals(type) || "quest_completed".equals(type); }
@Override public boolean evaluate(Player player, String type, String value, boolean negate) { boolean result = switch (type) { case "quest_active" -> questService.isQuestActive(player, value); case "quest_completed" -> questService.isQuestCompleted(player, value); default -> false; }; return negate ? !result : result; }});Thread Safety
Section titled “Thread Safety”- The API uses
CopyOnWriteArrayListfor all listener and interceptor lists (thread-safe registration/removal) - All query methods (
getCitizen,getAllCitizens,getCitizensByGroup,isCitizenPaused) can be called from any thread pauseCitizenMovementandresumeCitizenMovementinvolve entity operations and should be called withinworld.execute()when possible- Dialog opening methods (
openDialog,openDialogFromTree) involve UI operations and should be called from the main thread or withinworld.execute()
Java Package Structure
Section titled “Java Package Structure”com.kyuubisoft.core.citizen/├── CitizenData.java - NPC data model├── CitizenService.java - Citizen lifecycle management├── CitizenListener.java - Lifecycle event interface├── CitizenDialogInterceptor.java - Dialog intercept interface
com.kyuubisoft.core.dialog/├── DialogService.java - Dialog management├── DialogTree.java - Dialog tree model├── DialogNode.java - Dialog node model├── DialogConditionProvider.java - Condition provider interface