Technical reference for plugin developers and advanced users. Includes the public API for external plugin integration.
External plugins can interact with the Quest System through a stable public API.
import com.kyuubisoft.quests.api.QuestAPI;
QuestAPI api = QuestAPI.getInstance();
// Quest plugin not loaded
// Or with availability check
if (QuestAPI.isAvailable()) {
QuestAPI api = QuestAPI.getInstance();
| Method | Description |
|---|
getActiveQuests(UUID) | Map of active quest IDs to QuestProgress |
getCompletedQuests(UUID) | Set of completed quest IDs |
hasActiveQuest(UUID, String) | Check if quest is active |
hasCompletedQuest(UUID, String) | Check if quest is completed |
getQuestProgress(UUID, String) | Get QuestProgress for a quest |
getQuestDefinition(String) | Get quest definition by ID |
getAllQuestIds() | List of all available quest IDs |
getQuestsByType(String) | Get quests by type (daily/weekly/story/side/hub) |
| Method | Description |
|---|
getCurrentDailyQuests(UUID) | Current daily quest IDs for player |
getCurrentWeeklyQuests(UUID) | Current weekly quest IDs for player |
getTimeUntilDailyReset() | Duration until next daily reset |
getTimeUntilWeeklyReset() | Duration until next weekly reset |
| Method | Description |
|---|
getCurrentStreak(UUID) | Player’s current completion streak |
getLongestStreak(UUID) | Player’s longest streak ever |
| Method | Description |
|---|
startQuest(Player, String) | Start a quest (returns success) |
abandonQuest(Player, String) | Abandon an active quest |
updateProgress(Player, String, String, int) | Update objective progress (questId, objectiveId, amount) |
processTrigger(Player, String, String, int) | Process trigger for all active quests (type, target, amount) |
| Method | Description |
|---|
getQuestTokens(UUID) | Get token balance |
addQuestTokens(UUID, int) | Add tokens |
spendQuestTokens(UUID, int) | Spend tokens (returns false if insufficient) |
| Method | Description |
|---|
onQuestStarted(BiConsumer<Player, String>) | Listen for quest start events |
onQuestCompleted(BiConsumer<Player, String>) | Listen for quest completion events |
onQuestAbandoned(BiConsumer<Player, String>) | Listen for quest abandon events |
removeStartListener(BiConsumer) | Remove start listener |
removeCompleteListener(BiConsumer) | Remove complete listener |
removeAbandonListener(BiConsumer) | Remove abandon listener |
| Method | Description |
|---|
getPlayerFact(UUID, String) | Get a story fact value |
setPlayerFact(UUID, String, Object) | Set a story fact value |
checkFactConditions(UUID, List<String>) | Check fact conditions |
QuestAPI api = QuestAPI.getInstance();
// Does the player have an active quest?
if (api.hasActiveQuest(player.getUUID(), "merchant_delivery")) {
player.sendMessage("You still have a delivery to complete!");
if (api.hasCompletedQuest(player.getUUID(), "main_story_01")) {
player.sendMessage("Chapter 1 complete!");
QuestProgress progress = api.getQuestProgress(player.getUUID(), "kill_spiders");
player.sendMessage("Quest progress: " + progress.getCurrentProgress() + "/" + progress.getRequiredProgress());
QuestAPI api = QuestAPI.getInstance();
api.onQuestCompleted((player, questId) -> {
// Firework effect or similar
spawnFirework(player.getLocation());
LOGGER.info(player.getDisplayName() + " completed quest " + questId + "!");
if (questId.equals("main_story_01")) {
api.startQuest(player, "main_story_02");
api.onQuestAbandoned((player, questId) -> {
LOGGER.info(player.getDisplayName() + " abandoned quest " + questId);
QuestAPI api = QuestAPI.getInstance();
// Start quest on special event
if (specialEventTriggered) {
boolean started = api.startQuest(player, "special_event_quest");
player.sendMessage("New quest started!");
// Player already has quest, quest doesn't exist, or prerequisites not met
player.sendMessage("Could not start quest.");
// Update progress manually
api.updateProgress(player, "gather_resources", "collect_wood", 5);
// Process a trigger across all active quests
api.processTrigger(player, "kills", "Spider", 1);
QuestAPI api = QuestAPI.getInstance();
int tokens = api.getQuestTokens(player.getUUID());
player.sendMessage("Quest Tokens: " + tokens);
// Spend tokens for a reward
if (api.spendQuestTokens(player.getUUID(), 50)) {
player.sendMessage("Not enough tokens! Need 50, have " + tokens);
api.addQuestTokens(player.getUUID(), 25);
QuestAPI api = QuestAPI.getInstance();
api.setPlayerFact(player.getUUID(), "rescued_villager", true);
api.setPlayerFact(player.getUUID(), "chosen_faction", "rebels");
Object faction = api.getPlayerFact(player.getUUID(), "chosen_faction");
if ("rebels".equals(faction)) {
player.sendMessage("The rebels welcome you back!");
// Check multiple conditions at once
List<String> conditions = List.of("rescued_villager=true", "chosen_faction=rebels");
if (api.checkFactConditions(player.getUUID(), conditions)) {
// All conditions met - unlock special dialogue
api.startQuest(player, "rebel_secret_mission");
- The API is thread-safe using
CopyOnWriteArrayList for listeners
- All query methods can be called from any thread
- Modification methods should ideally be called from the main thread
- Facts database access is synchronized
The QuestAPI provides cross-mod integration for the quest system. Other mods can listen for quest events and query quest data.
Register callbacks that fire when quest state changes:
| Method | Parameters | Description |
|---|
onQuestStarted(listener) | BiConsumer<Player, String> | Fires when a player starts a quest |
onQuestCompleted(listener) | BiConsumer<Player, String> | Fires when a player completes a quest |
onQuestAbandoned(listener) | BiConsumer<Player, String> | Fires when a player abandons a quest |
QuestAPI.onQuestCompleted((player, questId) -> {
logger.info(player.getDisplayName() + " completed " + questId);
| Method | Returns | Description |
|---|
getAllQuestIds() | Set<String> | All registered quest IDs |
getQuestsByType(type) | List<QuestDefinition> | Quests filtered by type (story, daily, weekly, side) |
Facts are per-player key-value pairs used for story state tracking:
| Method | Returns | Description |
|---|
getPlayerFact(player, key) | String | Get a fact value for a player |
setPlayerFact(player, key, value) | void | Set a fact value |
checkFactConditions(player, conditions) | boolean | Check if all fact conditions are met |
├── config.json - Main configuration
├── configs/ - Standard configs
├── quest_npc_profiles/ - NPC personality profiles
├── localization/ - Language files
└── playerdata/ - Player quest data
Common/UI/Custom/Pages/QuestBook/
├── QuestPlugin.java - Main plugin class
│ └── QuestAPI.java - Public API for external plugins
│ ├── QuestCommand.java - /ksquest command
│ ├── QuestAdminCommand.java - /ksquestadmin command
│ └── QuestSettingsCommand.java - /ksquestsettings command
│ ├── QuestConfig.java - Config model
│ └── QuestDefinition.java - Quest definition model
│ ├── PlayerQuestData.java - Player quest data
│ └── QuestProgress.java - Quest progress tracking
│ └── QuestTrackerHud.java - Quest tracker HUD overlay
│ └── QuestService.java - Core quest logic
└── QuestBookPage.java - Quest book UI page
quests.name.<id> - Quest display name
quests.desc.<id> - Quest description
quests.objective.<id>.<obj> - Objective display text
quests.dialog.<npc>.<key> - NPC dialog text
quests.ui.book_title - Quest book window title
quests.ui.active - "Active" tab
quests.ui.completed - "Completed" tab
quests.ui.available - "Available" tab
quests.ui.daily - "Daily" label
quests.ui.weekly - "Weekly" label
quests.ui.story - "Story" label
quests.ui.side - "Side" label
quests.ui.progress - "Progress" label
quests.ui.abandon - "Abandon" button
quests.ui.accept - "Accept" button
quests.ui.rewards - "Rewards" label
quests.ui.objectives - "Objectives" label
quests.ui.streak - "Streak" label
quests.ui.tokens - "Tokens" label
quests.cmd.start.success - Quest start success message
quests.cmd.start.already - Already active message
quests.cmd.abandon.success - Abandon success message
quests.cmd.abandon.not_active - Not active message
quests.cmd.complete.success - Admin complete success message
quests.cmd.reset.success - Admin reset success message