📣 Bukkit Events
EventForge exposes Bukkit events so addons can react to EventForge activity without touching internal runtime classes.
Use these events for:
Discord announcements
external dashboards
custom scoreboards
admin logs
analytics
custom rewards
addon-side state tracking
The v1.0.3 events follow the same rule as the rest of the public API: addons receive safe public objects and snapshots, not internal managers or mutable runtime maps.
Register a listener
Register your listener like any other Bukkit listener.
public final class MyAddonPlugin extends JavaPlugin {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(new MyEventForgeListener(), this);
}
}
Example listener class:
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public final class MyEventForgeListener implements Listener {
@EventHandler
public void onEventStart(EventForgeEventStartEvent event) {
System.out.println("Event started: " + event.getEventId());
}
}
Event lifecycle events
EventForgeEventStartEvent
EventForgeEventStopEvent
EventForgeEventFinishEvent
EventForgeReloadEvent
These are the main lifecycle events for normal EventForge events and reloads.
Event start
Called when an EventForge event starts.
@EventHandler
public void onEventStart(EventForgeEventStartEvent event) {
String eventId = event.getEventId();
String displayName = event.getEventDisplayName();
int duration = event.getDurationSeconds();
Bukkit.getLogger().info("Event started: " + displayName + " for " + duration + "s");
}
Useful methods:
event.getEventInfo();
event.getSession();
event.getEventId();
event.getEventDisplayName();
event.getDurationSeconds();
Event stop
Called when an EventForge event is stopped before normal completion.
@EventHandler
public void onEventStop(EventForgeEventStopEvent event) {
Bukkit.getLogger().info("Event stopped: " + event.getEventId());
}
This can happen when:
an admin stops the event
EventForge reloads
the server shuts down
another system stops the event
Useful methods:
event.getEventInfo();
event.getSession();
event.getEventId();
event.getEventDisplayName();
event.getDurationSeconds();
Event finish
Called when an EventForge event finishes normally.
@EventHandler
public void onEventFinish(EventForgeEventFinishEvent event) {
Bukkit.getLogger().info("Event finished: " + event.getEventId());
}
Use this for logic that should run after an event completes naturally.
Useful methods:
event.getEventInfo();
event.getSession();
event.getEventId();
event.getEventDisplayName();
event.getDurationSeconds();
Reload event
Called when EventForge reloads.
@EventHandler
public void onReload(EventForgeReloadEvent event) {
Bukkit.getLogger().info("EventForge reloaded by " + event.getSender().getName());
}
Useful methods:
event.getSender();
event.getLoadedEvents();
event.getValidationWarnings();
event.getValidationErrors();
event.getScheduledEvents();
event.getRegisteredObjectives();
Use this to refresh addon-side caches after EventForge reloads configs, templates, schedules and runtime services.
Score and reward events
EventForgePlayerScoreChangeEvent
EventForgePlayerMilestoneEvent
EventForgeRewardExecuteEvent
These events are useful for addons that track scores, block certain score changes, react to milestones or adjust reward commands before they run.
Player score change
Called when a player's score changes during an active EventForge event.
@EventHandler
public void onScoreChange(EventForgePlayerScoreChangeEvent event) {
Player player = event.getPlayer();
int oldScore = event.getOldScore();
int newScore = event.getNewScore();
int difference = event.getDifference();
player.sendMessage("Score changed from " + oldScore + " to " + newScore + " (" + difference + ")");
}
Useful methods:
event.getEventInfo();
event.getSession();
event.getPlayer();
event.getEventId();
event.getEventDisplayName();
event.getOldScore();
event.getNewScore();
event.setNewScore(newScore);
event.getDifference();
event.isCancelled();
event.setCancelled(true);
EventForgePlayerScoreChangeEvent is cancellable.
If cancelled, the score change is blocked.
@EventHandler
public void onScoreChange(EventForgePlayerScoreChangeEvent event) {
if (event.getNewScore() < 0) {
event.setCancelled(true);
}
}
Player milestone
Called when a player crosses a configured EventForge milestone.
@EventHandler
public void onMilestone(EventForgePlayerMilestoneEvent event) {
Player player = event.getPlayer();
player.sendMessage("Milestone reached: " + event.getMilestone().getDisplayName());
}
Useful methods:
event.getEventInfo();
event.getPlayer();
event.getMilestone();
event.getEventId();
event.getEventDisplayName();
event.getOldScore();
event.getNewScore();
event.getScoreChange();
event.isCancelled();
event.setCancelled(true);
Milestone information:
event.getMilestone().getId();
event.getMilestone().getDisplayName();
event.getMilestone().getThreshold();
event.getMilestone().isOncePerPlayer();
event.getMilestone().getActions();
EventForgePlayerMilestoneEvent is cancellable.
If cancelled, the milestone actions will not run and the milestone will not be marked as triggered for that player.
@EventHandler
public void onMilestone(EventForgePlayerMilestoneEvent event) {
if (event.getMilestone().getThreshold() >= 1000) {
event.setCancelled(true);
}
}
Reward execute
Called before EventForge executes a configured reward command.
@EventHandler
public void onReward(EventForgeRewardExecuteEvent event) {
if (event.getRewardType() == EventForgeRewardType.LEADERBOARD) {
Bukkit.getLogger().info("Leaderboard reward for " + event.getPlayerName());
}
}
Useful methods:
event.getEventInfo();
event.getSession();
event.getPlayer();
event.getPlayerUuid();
event.getPlayerName();
event.getEventId();
event.getEventDisplayName();
event.getScore();
event.getPosition();
event.getRewardType();
event.getOriginalCommand();
event.getCommand();
event.setCommand(command);
event.isCancelled();
event.setCancelled(true);
Reward types:
EventForgeRewardType.PARTICIPATION
EventForgeRewardType.LEADERBOARD
EventForgeRewardType.MILESTONE
Use this event when an addon needs to block, log or adjust reward commands before they run.
Voting events
v1.0.3 adds public Bukkit events for manual event voting.
EventForgeVoteStartEvent
EventForgeVoteCastEvent
EventForgeVoteEndEvent
EventForgeVoteCancelEvent
Voting events expose EventVoteInfo snapshots only. Addons do not receive access to ActiveEventVote, vote maps, tasks or manager internals.
Vote start
Called when a manual or scheduled vote starts.
@EventHandler
public void onVoteStart(EventForgeVoteStartEvent event) {
EventVoteInfo vote = event.getVoteInfo();
Bukkit.broadcastMessage("A vote started with " + vote.getOptions().size() + " options.");
}
Useful methods:
event.getVoteInfo();
event.getSender();
Vote cast
Called when a player successfully votes.
@EventHandler
public void onVoteCast(EventForgeVoteCastEvent event) {
Player player = event.getPlayer();
String eventId = event.getEventId();
player.sendMessage("You voted for " + eventId + ".");
}
Useful methods:
event.getVoteInfo();
event.getPlayer();
event.getEventId();
event.getPreviousEventId();
event.isChangedVote();
getPreviousEventId() is useful when vote changing is enabled.
Vote end
Called when a vote finishes and the result is calculated.
@EventHandler
public void onVoteEnd(EventForgeVoteEndEvent event) {
String winner = event.getWinnerId();
if (winner == null || winner.isBlank()) {
Bukkit.getLogger().info("Vote ended with no winner.");
return;
}
Bukkit.getLogger().info("Vote winner: " + winner);
}
Useful methods:
event.getVoteInfo();
event.getWinnerId();
event.isTied();
If the winning event uses manual participation, EventForge can open a manual queue after the vote result instead of starting the event instantly.
Vote cancel
Called when an active vote is cancelled.
@EventHandler
public void onVoteCancel(EventForgeVoteCancelEvent event) {
if (event.isReload()) {
Bukkit.getLogger().info("Vote was cancelled because EventForge reloaded.");
}
}
Useful methods:
event.getVoteInfo();
event.getSender();
event.isReload();
Scheduled vote events
v1.0.3 adds public Bukkit events for scheduled hybrid voting.
EventForgeScheduledVoteStartEvent
EventForgeScheduledVoteSkipEvent
Scheduled vote events expose ScheduledVoteInfo snapshots only.
Scheduled vote start
Called when a configured scheduled vote starts.
@EventHandler
public void onScheduledVoteStart(EventForgeScheduledVoteStartEvent event) {
ScheduledVoteInfo info = event.getScheduledVoteInfo();
Bukkit.getLogger().info("Scheduled vote started: " + info.getId());
}
Useful methods:
event.getScheduledVoteInfo();
event.getSelectedOptionIds();
getSelectedOptionIds() is especially useful when the scheduled vote uses randomized options.
Scheduled vote skip
Called when a scheduled vote is skipped safely.
@EventHandler
public void onScheduledVoteSkip(EventForgeScheduledVoteSkipEvent event) {
Bukkit.getLogger().info(
"Scheduled vote skipped: " + event.getReason() + " - " + event.getMessage()
);
}
Useful methods:
event.getScheduledVoteInfo();
event.getReason();
event.getMessage();
Skip reasons:
ScheduledVoteSkipReason.ACTIVE_EVENT
ScheduledVoteSkipReason.ACTIVE_VOTE
ScheduledVoteSkipReason.NOT_ENOUGH_OPTIONS
ScheduledVoteSkipReason.VOTE_MANAGER_UNAVAILABLE
ScheduledVoteSkipReason.VOTE_START_FAILED
ScheduledVoteSkipReason.INVALID_CONFIG
Manual queue events
v1.0.3 adds public Bukkit events for the manual event queue / hype phase system.
EventForgeQueueOpenEvent
EventForgeQueueJoinEvent
EventForgeQueueLeaveEvent
EventForgeQueueStartEvent
EventForgeQueueCancelEvent
Queue events expose EventQueueInfo snapshots only. Addons do not receive the internal QueuedEvent object or mutable queue player collections.
Queue open
Called when a manual event queue opens.
@EventHandler
public void onQueueOpen(EventForgeQueueOpenEvent event) {
EventQueueInfo queue = event.getQueueInfo();
Bukkit.broadcastMessage("Queue opened for " + queue.getEventDisplayName());
}
Useful methods:
event.getQueueInfo();
event.getSender();
Queue join
Called when a player successfully joins a queue.
@EventHandler
public void onQueueJoin(EventForgeQueueJoinEvent event) {
Player player = event.getPlayer();
EventQueueInfo queue = event.getQueueInfo();
player.sendMessage("Joined queue: " + queue.getEventDisplayName());
}
Useful methods:
event.getQueueInfo();
event.getPlayer();
Queue leave
Called when a player successfully leaves a queue.
@EventHandler
public void onQueueLeave(EventForgeQueueLeaveEvent event) {
event.getPlayer().sendMessage("Left queue: " + event.getQueueInfo().getEventDisplayName());
}
Useful methods:
event.getQueueInfo();
event.getPlayer();
Queue start
Called when a queue successfully starts its event.
@EventHandler
public void onQueueStart(EventForgeQueueStartEvent event) {
EventQueueInfo queue = event.getQueueInfo();
Bukkit.getLogger().info("Queue started event: " + queue.getEventId());
}
Useful methods:
event.getQueueInfo();
EventForgeQueueStartEvent only fires after EventForge confirms that the event actually started.
Queue cancel
Called when a queue is cancelled instead of starting its event.
@EventHandler
public void onQueueCancel(EventForgeQueueCancelEvent event) {
EventQueueInfo queue = event.getQueueInfo();
Bukkit.getLogger().info("Queue cancelled for " + queue.getEventId() + ": " + event.getReason());
}
Useful methods:
event.getQueueInfo();
event.getReason();
Current queue cancel reasons include:
NOT_ENOUGH_PLAYERS
START_FAILED
EventQueueInfo snapshot
Queue events use EventQueueInfo.
EventQueueInfo queue = event.getQueueInfo();
String eventId = queue.getEventId();
String displayName = queue.getEventDisplayName();
long secondsLeft = queue.getSecondsLeft();
int players = queue.getJoinedCount();
int minPlayers = queue.getMinPlayers();
boolean hasEnough = queue.hasEnoughPlayers();
Useful methods:
queue.getEventId();
queue.getEventDisplayName();
queue.getOpenedAtEpochSecond();
queue.getClosesAtEpochSecond();
queue.getSecondsLeft();
queue.getJoinedCount();
queue.getMinPlayers();
queue.getMaxPlayers();
queue.hasMaxPlayers();
queue.isLeaveBeforeStartAllowed();
queue.isLobbyEnabled();
queue.isClosed();
queue.hasExpired();
queue.hasEnoughPlayers();
queue.getJoinedPlayerIds();
queue.isJoined(playerId);
getJoinedPlayerIds() returns an immutable set.
Dialogue events
EventForge also exposes dialogue lifecycle events.
EventForgeDialogueCompleteEvent
EventForgeDialogueCancelEvent
These are useful for addons that want to react when an EventForge dialogue finishes or is cancelled.
@EventHandler
public void onDialogueComplete(EventForgeDialogueCompleteEvent event) {
Bukkit.getLogger().info("Dialogue complete: " + event.getDialogueId());
}
Useful methods:
event.getSessionInfo();
event.getPlayerName();
event.getEventId();
event.getDialogueId();
Full event list
EventForgeEventStartEvent
EventForgeEventStopEvent
EventForgeEventFinishEvent
EventForgePlayerScoreChangeEvent
EventForgePlayerMilestoneEvent
EventForgeRewardExecuteEvent
EventForgeReloadEvent
EventForgeDialogueCompleteEvent
EventForgeDialogueCancelEvent
EventForgeVoteStartEvent
EventForgeVoteCastEvent
EventForgeVoteEndEvent
EventForgeVoteCancelEvent
EventForgeScheduledVoteStartEvent
EventForgeScheduledVoteSkipEvent
EventForgeQueueOpenEvent
EventForgeQueueJoinEvent
EventForgeQueueLeaveEvent
EventForgeQueueStartEvent
EventForgeQueueCancelEvent
Snapshot safety
v1.0.3 voting, scheduled voting and queue events expose immutable public snapshots:
EventVoteInfo
ScheduledVoteInfo
EventQueueInfo
Addons should treat these as read-only state views.
Do not try to store them forever as live runtime objects. If you need fresh state later, use the matching API service:
EventForgeAPI.getEventVoteService();
EventForgeAPI.getScheduledVoteService();
EventForgeAPI.getEventQueueService();
Example listener
package com.example.eventforgeaddon;
import dev.hxze.eventforge.api.EventQueueInfo;
import dev.hxze.eventforge.api.event.EventForgeEventStartEvent;
import dev.hxze.eventforge.api.event.EventForgePlayerMilestoneEvent;
import dev.hxze.eventforge.api.event.EventForgeQueueJoinEvent;
import dev.hxze.eventforge.api.event.EventForgeVoteEndEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public final class MyEventForgeListener implements Listener {
@EventHandler
public void onEventStart(EventForgeEventStartEvent event) {
Bukkit.getLogger().info("Started: " + event.getEventId());
}
@EventHandler
public void onMilestone(EventForgePlayerMilestoneEvent event) {
event.getPlayer().sendMessage("Milestone: " + event.getMilestone().getDisplayName());
}
@EventHandler
public void onVoteEnd(EventForgeVoteEndEvent event) {
if (event.getWinnerId() != null && !event.getWinnerId().isBlank()) {
Bukkit.getLogger().info("Vote winner: " + event.getWinnerId());
}
}
@EventHandler
public void onQueueJoin(EventForgeQueueJoinEvent event) {
EventQueueInfo queue = event.getQueueInfo();
event.getPlayer().sendMessage("Joined queue: " + queue.getEventDisplayName());
}
}
Summary
Use Bukkit events when your addon needs to react to EventForge activity as it happens.
Use API services when your addon needs to read current state on demand.
For v1.0.3 systems, voting, scheduled voting and queue events expose safe snapshots only, keeping EventForge internals protected while still giving addons useful integration points.