๐ฌ Dialogue Service
DialogueService lets addons start, inspect, and cancel EventForge dialogue sequences.
Dialogues are configured in event files and can be triggered by addons, custom objectives, NPC plugins, or Skript.
EventForge provides the dialogue engine. Your addon decides when a dialogue should start.
When to use dialogues
Dialogues are useful for:
NPC tutorials
quest steps
relic hunts
story events
task chains
custom objective instructions
guided server events
Use dialogues when players need short, timed instructions or NPC-style messages during an event.
Getting the service
DialogueService dialogueService = EventForgeAPI.getDialogueService();
Always check the API first:
if (!EventForgeAPI.isAvailable()) {
return;
}
Event config
Dialogues are configured inside an event file.
dialogues:
guide_intro:
npc-id: "guide"
display-name: "Guide Introduction"
cancel-existing: true
lines:
- speaker: "&eGuide"
text: "&fHello {player}."
title: "&eGuide"
subtitle: "&fWelcome."
sound: ENTITY_VILLAGER_AMBIENT
delay: 3
The dialogue ID here is:
guide_intro
Simple dialogue format
Server owners can also use a simple line list:
dialogues:
guide_intro:
lines:
- "&eGuide: &fHello there!"
- "&eGuide: &fBring me 5 relics."
This is good for small events.
Start an event dialogue
Use:
EventForgeAPI.getDialogueService()
.startEventDialogue(player, "relic_hunt", "guide_intro");
This starts the guide_intro dialogue from the relic_hunt event for that player.
Handling completion
startEventDialogue(...) returns a future so you can continue your addon logic after the dialogue ends.
EventForgeAPI.getDialogueService()
.startEventDialogue(player, "relic_hunt", "guide_intro")
.thenAccept(session -> {
if (session.isCompleted()) {
player.sendMessage("Dialogue complete!");
}
});
Dialogue start/cancel operations are main-thread safe for addon developers.
Check whether a dialogue exists
boolean exists = EventForgeAPI.getDialogueService()
.hasDialogue("relic_hunt", "guide_intro");
Example:
DialogueService dialogueService = EventForgeAPI.getDialogueService();
if (!dialogueService.hasDialogue("relic_hunt", "guide_intro")) {
player.sendMessage("That dialogue is not configured.");
return;
}
dialogueService.startEventDialogue(player, "relic_hunt", "guide_intro");
Get dialogue IDs
Set<String> dialogueIds = EventForgeAPI.getDialogueService()
.getDialogueIds("relic_hunt");
Example:
for (String dialogueId : dialogueService.getDialogueIds("relic_hunt")) {
plugin.getLogger().info("Dialogue: " + dialogueId);
}
Get dialogue info
Optional<DialogueSequenceInfo> dialogue = EventForgeAPI.getDialogueService()
.getDialogue("relic_hunt", "guide_intro");
Example:
dialogue.ifPresent(sequence -> {
String id = sequence.getId();
String displayName = sequence.getDisplayName();
int lineCount = sequence.getLines().size();
});
Check if player is in dialogue
boolean inDialogue = EventForgeAPI.getDialogueService().isInDialogue(player);
Example:
if (dialogueService.isInDialogue(player)) {
player.sendMessage("You are already in a dialogue.");
return;
}
Get active session
Optional<DialogueSessionInfo> activeSession = EventForgeAPI
.getDialogueService()
.getActiveSession(player);
Example:
dialogueService.getActiveSession(player).ifPresent(session -> {
player.sendMessage("Current dialogue: " + session.getDialogueId());
});
Cancel dialogue
EventForgeAPI.getDialogueService().cancelDialogue(player);
Use this if your addon needs to stop an active dialogue.
Example:
if (dialogueService.isInDialogue(player)) {
dialogueService.cancelDialogue(player);
}
Start a custom sequence
Most addons should use startEventDialogue(...).
If you are building a completely custom dialogue sequence in code, you can use:
dialogueService.startDialogue(player, sequence);
For normal event-driven addons, prefer configured event dialogues so server owners can edit them in YAML.
Dialogue placeholders
Dialogues support placeholders such as:
{player}
{uuid}
{dialogue}
{dialogue_display}
{npc}
{event}
{event_display}
{var:key}
Example:
variables:
guide_name: "&eRelic Guide"
arena_name: "Spawn Ruins"
dialogues:
guide_intro:
npc-id: "relic_guide"
display-name: "{var:guide_name} Introduction"
lines:
- speaker: "{var:guide_name}"
text: "&fWelcome to {var:arena_name}, {player}."
Dialogue sequence info
DialogueSequenceInfo represents a configured dialogue.
Common methods include:
getId();
getNpcId();
getDisplayName();
shouldCancelExisting();
getLines();
getCompleteCommands();
Example:
DialogueSequenceInfo sequence = dialogue.get();
String id = sequence.getId();
String npcId = sequence.getNpcId();
String displayName = sequence.getDisplayName();
boolean cancelExisting = sequence.shouldCancelExisting();
int lineCount = sequence.getLines().size();
Dialogue line info
DialogueLineInfo represents one dialogue line.
Common methods include:
getSpeaker();
getText();
getTitle();
getSubtitle();
getSound();
getDelaySeconds();
Example:
for (DialogueLineInfo line : sequence.getLines()) {
String speaker = line.getSpeaker();
String text = line.getText();
int delay = line.getDelaySeconds();
}
Dialogue session info
DialogueSessionInfo represents an active or completed dialogue session.
Common methods include:
getEventId();
getDialogueId();
getPlayerUuid();
getPlayerName();
isCompleted();
isCancelled();
Example:
dialogueService.startEventDialogue(player, "relic_hunt", "guide_intro")
.thenAccept(session -> {
if (session.isCompleted()) {
plugin.getLogger().info(session.getPlayerName()
+ " completed "
+ session.getDialogueId());
}
});
Starting dialogue from a custom objective
A common use case is starting a dialogue when a player reaches a task step.
@Override
public void onPlayerMove(
EventObjectiveSession session,
RelicHuntObjectiveData data,
Player player,
PlayerMoveEvent event
) {
if (!playerReachedRelic(player)) {
return;
}
DialogueService dialogueService = EventForgeAPI.getDialogueService();
if (!dialogueService.hasDialogue(session.getEventId(), "guide_intro")) {
return;
}
dialogueService.startEventDialogue(player, session.getEventId(), "guide_intro");
}
Starting dialogue from an NPC plugin
Your addon can listen to an NPC interaction from another plugin, then start the configured dialogue.
Example idea:
public void handleNpcClick(Player player, String npcId) {
if (!npcId.equalsIgnoreCase("relic_guide")) {
return;
}
EventForgeAPI.getDialogueService()
.startEventDialogue(player, "relic_hunt", "guide_intro");
}
EventForge does not require a specific NPC plugin.
Bukkit dialogue events
EventForge fires Bukkit events for dialogue completion and cancellation.
@EventHandler
public void onDialogueComplete(EventForgeDialogueCompleteEvent event) {
String eventId = event.getEventId();
String dialogueId = event.getDialogueId();
String playerName = event.getPlayerName();
}
@EventHandler
public void onDialogueCancel(EventForgeDialogueCancelEvent event) {
String eventId = event.getEventId();
String dialogueId = event.getDialogueId();
String playerName = event.getPlayerName();
}
Use these for quest progression, logs, or cleanup.
Full event config example
id: relic_hunt
enabled: true
display-name: "{var:event_color}Relic Hunt"
duration: 5m
variables:
event_color: "&6"
guide_name: "&eRelic Guide"
arena_name: "Spawn Ruins"
dialogues:
guide_intro:
npc-id: "relic_guide"
display-name: "{var:guide_name} Introduction"
cancel-existing: true
lines:
- speaker: "{var:guide_name}"
text: "&fWelcome to {var:arena_name}, {player}. Ancient relics are hidden nearby."
title: "{var:event_color}Relic Hunt"
subtitle: "&fSearch the ruins for clues."
sound: ENTITY_VILLAGER_AMBIENT
delay: 3
- speaker: "{var:guide_name}"
text: "&fInteract with ancient blocks and recover fragments to earn points."
sound: ENTITY_EXPERIENCE_ORB_PICKUP
delay: 3
complete-commands:
- "say {player} completed the {dialogue_display} dialogue."
Example addon command
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage("Players only.");
return true;
}
if (args.length < 2) {
sender.sendMessage("/startdialogue <event> <dialogue>");
return true;
}
String eventId = args[0];
String dialogueId = args[1];
DialogueService dialogueService = EventForgeAPI.getDialogueService();
if (!dialogueService.hasDialogue(eventId, dialogueId)) {
player.sendMessage("Unknown dialogue.");
return true;
}
dialogueService.startEventDialogue(player, eventId, dialogueId)
.thenAccept(session -> {
if (session.isCompleted()) {
player.sendMessage("Dialogue complete.");
}
});
return true;
}
Recommended addon structure
src/main/java/com/example/dialogueaddon/
โโ DialogueAddonPlugin.java
โโ command/
โ โโ StartDialogueCommand.java
โโ listener/
โ โโ NpcClickListener.java
โโ util/
โโ TextUtil.java
Common mistakes
Starting a missing dialogueโ
Check first:
dialogueService.hasDialogue(eventId, dialogueId);
Assuming the player is not already in dialogueโ
Use:
dialogueService.isInDialogue(player);
or let the configured cancel-existing behaviour handle replacement.
Hardcoding all dialogue text in Javaโ
Prefer event config dialogues when possible.
That lets server owners edit text without recompiling the addon.
Forgetting that EventForge is not an NPC pluginโ
EventForge provides the dialogue engine.
Your addon, NPC plugin, Skript, or objective logic needs to decide when to start a dialogue.