Events
PlumDelivery fires custom Bukkit events that allow other plugins to react to delivery system actions. All events are in the net.plumstudio.plumdelivery.api package.
Listening to Events
Register your event listeners like any standard Bukkit event:
public class MyPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
}
@EventHandler
public void onPointChange(PointChangeEvent event) {
// Handle the event
}
}
Tips
Make sure PlumDelivery is listed in your plugin.yml under depend or softdepend so that it loads before your plugin and the event classes are available.
PointChangeEvent
Fired whenever a player's points are modified (added or removed). This event is cancellable.
Fields
| Field | Type | Description |
|---|---|---|
playerUuid | UUID | UUID of the affected player |
deliveryType | DeliveryType | The delivery period (DAILY, WEEKLY, MONTHLY) |
category | String | The category key (e.g. "mining") |
oldPoints | int | Point count before the change |
newPoints | int | Point count after the change |
amount | int | The amount being added or removed |
changeType | ChangeType | Either ADD or REMOVE |
cancelled | boolean | Whether the event is cancelled |
ChangeType Enum
| Value | Description |
|---|---|
ADD | Points are being added |
REMOVE | Points are being removed |
Example: Bonus Points for VIP Players
@EventHandler
public void onPointChange(PointChangeEvent event) {
Player player = Bukkit.getPlayer(event.getPlayerUuid());
if (player == null) return;
// Double points for players with VIP permission
if (event.getChangeType() == PointChangeEvent.ChangeType.ADD
&& player.hasPermission("myplugin.vip")) {
int bonus = event.getAmount();
// Schedule bonus points to be added after this event completes
Bukkit.getScheduler().runTaskLater(this, () -> {
PlumDeliveryAPI.getInstance().addPoints(
event.getPlayerUuid(),
event.getDeliveryType(),
event.getCategory(),
bonus
);
player.sendMessage("§a§lVIP Bonus! §7You received §e" + bonus + " §7extra points!");
}, 1L);
}
}
Example: Prevent Point Removal
@EventHandler
public void onPointChange(PointChangeEvent event) {
// Prevent any point removal during a special event
if (event.getChangeType() == PointChangeEvent.ChangeType.REMOVE) {
event.setCancelled(true);
Player player = Bukkit.getPlayer(event.getPlayerUuid());
if (player != null) {
player.sendMessage("§cPoints cannot be removed during the event!");
}
}
}
Use Cases
- Audit logging: Track all point changes for analytics
- Anti-cheat: Validate or cap point changes per tick
- Bonus systems: Award multiplied points based on permissions, time of day, or events
- Protection: Prevent point removal under certain conditions
GoalReachEvent
Fired when a player reaches their goal for a specific delivery type and category. This event is NOT cancellable.
Fields
| Field | Type | Description |
|---|---|---|
playerUuid | UUID | UUID of the player who reached the goal |
deliveryType | DeliveryType | The delivery period |
category | String | The category key |
goalValue | int | The goal value that was reached |
Example: Broadcast Goal Completion
@EventHandler
public void onGoalReach(GoalReachEvent event) {
Player player = Bukkit.getPlayer(event.getPlayerUuid());
if (player == null) return;
String message = String.format(
"§6§l★ §e%s §7completed the §b%s §7%s goal! (§f%d pts§7)",
player.getName(),
event.getCategory(),
event.getDeliveryType().getDisplayName(),
event.getGoalValue()
);
Bukkit.broadcastMessage(message);
}
Example: Chain Rewards
@EventHandler
public void onGoalReach(GoalReachEvent event) {
Player player = Bukkit.getPlayer(event.getPlayerUuid());
if (player == null) return;
// Check if the player has completed ALL categories for this delivery type
PlumDeliveryAPI api = PlumDeliveryAPI.getInstance();
ApiUser user = api.getUser(event.getPlayerUuid());
boolean allComplete = true;
for (String category : api.getCategories()) {
int points = user.getPoints(event.getDeliveryType(), category);
int goal = user.getCurrentGoal(event.getDeliveryType(), category);
if (points < goal) {
allComplete = false;
break;
}
}
if (allComplete) {
player.sendMessage("§6§l★ §eYou completed ALL " +
event.getDeliveryType().getDisplayName() + " goals! Bonus reward incoming!");
// Grant bonus reward via your own logic
}
}
Use Cases
- Broadcasts: Announce goal completions to the server
- Chain rewards: Grant bonus rewards when all categories are completed
- Statistics: Track completion rates and player achievement timelines
- Integrations: Trigger actions in other plugins (economy, ranks, etc.)
DeliveryStartEvent
Fired when a delivery cycle starts. This event is cancellable.
Fields
| Field | Type | Description |
|---|---|---|
deliveryType | DeliveryType | The delivery type that is starting |
cancelled | boolean | Whether the event is cancelled |
Example: Announce Delivery Start
@EventHandler
public void onDeliveryStart(DeliveryStartEvent event) {
String typeName = event.getDeliveryType().getDisplayName();
Bukkit.broadcastMessage("§a§l⬆ §7A new §e" + typeName + " §7delivery has started!");
// Play a sound for all online players
for (Player player : Bukkit.getOnlinePlayers()) {
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f);
}
}
Example: Conditionally Prevent Delivery Start
@EventHandler
public void onDeliveryStart(DeliveryStartEvent event) {
// Only allow deliveries to start if there are at least 5 players online
if (Bukkit.getOnlinePlayers().size() < 5) {
event.setCancelled(true);
getLogger().info("Delivery start cancelled: not enough players online.");
}
}
Use Cases
- Announcements: Notify players when a new delivery cycle begins
- Conditional start: Prevent deliveries from starting based on server conditions
- Integrations: Trigger scoreboard updates, boss bar displays, or Discord webhooks
- Scheduling: Coordinate delivery cycles with other timed events on your server
DeliveryEndEvent
Fired when a delivery cycle ends. This event is cancellable.
Fields
| Field | Type | Description |
|---|---|---|
deliveryType | DeliveryType | The delivery type that is ending |
cancelled | boolean | Whether the event is cancelled |
Warning
Cancelling this event will prevent the delivery from ending. Use with caution — this may keep a delivery running indefinitely until the event is no longer cancelled.
Example: End-of-Cycle Summary
@EventHandler
public void onDeliveryEnd(DeliveryEndEvent event) {
PlumDeliveryAPI api = PlumDeliveryAPI.getInstance();
String typeName = event.getDeliveryType().getDisplayName();
Bukkit.broadcastMessage("§c§l⬇ §7The §e" + typeName + " §7delivery has ended!");
// Show summary to all online players
for (Player player : Bukkit.getOnlinePlayers()) {
ApiUser user = api.getUser(player.getUniqueId());
int totalPoints = 0;
int completedGoals = 0;
int totalGoals = 0;
for (String category : api.getCategories()) {
int points = user.getPoints(event.getDeliveryType(), category);
int goal = user.getCurrentGoal(event.getDeliveryType(), category);
totalPoints += points;
totalGoals++;
if (points >= goal) completedGoals++;
}
player.sendMessage(String.format(
"§7Your %s summary: §f%d §7points | §f%d§7/§f%d §7goals completed",
typeName, totalPoints, completedGoals, totalGoals
));
}
}
Example: Extend Delivery Under Conditions
@EventHandler
public void onDeliveryEnd(DeliveryEndEvent event) {
// Extend daily deliveries by 1 hour on weekends
if (event.getDeliveryType() == DeliveryType.DAILY) {
DayOfWeek day = LocalDate.now().getDayOfWeek();
if (day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY) {
event.setCancelled(true);
// Schedule the actual end for 1 hour later
Bukkit.getScheduler().runTaskLater(this, () -> {
// Let the delivery end naturally on next cycle
Bukkit.broadcastMessage("§7The weekend delivery extension has ended!");
}, 20L * 60 * 60); // 1 hour in ticks
}
}
}
Use Cases
- Summaries: Show players their performance when a cycle ends
- Extensions: Keep deliveries running longer under special conditions
- Cleanup: Perform post-delivery logic (reset custom scoreboards, update leaderboards)
- Integrations: Send end-of-cycle reports to Discord or a web panel
Event Priority
All PlumDelivery events support Bukkit's standard EventPriority system. Use it to control the order in which your listeners execute:
@EventHandler(priority = EventPriority.HIGH)
public void onPointChange(PointChangeEvent event) {
// This runs after NORMAL priority listeners
}
| Priority | Use Case |
|---|---|
LOWEST | Pre-processing and validation |
LOW | Early modifications |
NORMAL | Standard handling (default) |
HIGH | Post-processing and reactions |
HIGHEST | Final overrides |
MONITOR | Read-only observation (do not modify the event) |
Caution
Do not cancel events at MONITOR priority. This priority is reserved for read-only observation of the final event state.
Summary Table
| Event | Cancellable | When It Fires |
|---|---|---|
PointChangeEvent | ✅ Yes | A player's points are added or removed |
GoalReachEvent | ❌ No | A player reaches their goal in a category |
DeliveryStartEvent | ✅ Yes | A delivery cycle is about to start |
DeliveryEndEvent | ✅ Yes | A delivery cycle is about to end |
