Paper events¶
MythicRod publishes five Paper events. All live under
io.xcutiboo.mythicrod.paper.events.
| Event | Cancellable | Thread |
|---|---|---|
MythicRodBiteEvent |
yes | player-owner |
MythicRodRewardRollEvent |
no | player-owner |
MythicRodFishCatchEvent |
yes | player-owner |
MythicRodStatsUpdateEvent |
no | stats writer |
MythicRodReloadEvent |
no | reload-caller |
MythicRodBiteEvent¶
Fires when a fish bites a MythicRod rod (PlayerFishEvent.State.BITE).
Only fires for rods MythicRod recognises - vanilla rods never trigger
it. Use this for skill-check minigames, custom bite cues, or to
short-circuit the catch when the player is missing a buff item.
@EventHandler(ignoreCancelled = true)
public void onBite(MythicRodBiteEvent event) {
Player player = event.getPlayer();
Location at = event.getHook().getLocation();
player.spawnParticle(Particle.BUBBLE_POP, at, 8, 0.3, 0.1, 0.3, 0);
skillCheck.start(player, () -> event.setCancelled(true));
}
Cancelling the event cancels the underlying PlayerFishEvent, so the
catch never resolves.
MythicRodRewardRollEvent¶
Fires once MythicRod has identified eligible drops but before it has built the reward item. Bias selection here.
@EventHandler
public void onRoll(MythicRodRewardRollEvent event) {
if (event.getPlayer().hasPermission("myplugin.lucky")) {
event.setLuckMultiplier(event.getLuckMultiplier() * 1.5D);
}
}
Mutators: setLuckMultiplier(double), forceDrop(CustomDrop). The
forced-drop path is the advanced lane and bypasses weight selection;
prefer the multiplier when you can.
MythicRodFishCatchEvent¶
Fires after selection. Cancellable. The reward ItemStack is mutable.
Cancelling leaves the vanilla catch in place.
@EventHandler(ignoreCancelled = true)
public void onCatch(MythicRodFishCatchEvent event) {
if ("legendary".equalsIgnoreCase(event.getDropView().getTier())) {
event.getPlayer().getWorld().strikeLightningEffect(
event.getPlayer().getLocation());
}
}
setRewardItem(ItemStack) rejects null and AIR. Cancel the event
instead.
MythicRodStatsUpdateEvent¶
Read-only. Useful for analytics, webhooks, or sign refreshes.
@EventHandler
public void onStats(MythicRodStatsUpdateEvent event) {
var snap = event.getSnapshot();
metrics.record("mythicrod.catch", Map.of(
"uuid", snap.playerUuid().toString(),
"tier", event.getTier(),
"total", String.valueOf(snap.totalCaught())
));
}
MythicRodReloadEvent¶
Fires after MythicRod#reload() completes. Carries an isSuccess()
flag so listeners can refresh their caches only after a real swap.
@EventHandler
public void onReload(MythicRodReloadEvent event) {
if (event.isSuccess()) {
myDropProviderCache.invalidate();
}
}
Threading and Folia¶
All four events fire on the same thread that owns the data they carry:
- Reward roll, fish catch: the player's owner thread on Folia, the main thread on vanilla Paper.
- Stats update: MythicRod's stats writer thread. Do not call Bukkit world or entity APIs inline.
- Reload: the thread that called
MythicRod#reload(). For/mythicrod reloadissued from the server console on Paper, that is the main thread. On Folia it is the global region scheduler.
A misbehaving listener cannot break the reload. Exceptions are caught and logged by MythicRod.
What not to do¶
- Do not mutate
event.getDrop()directly. It is the internal type. Useevent.getDropView()for inspection. - Do not block, sleep, or wait on a future inside any event handler.
- Do not call
Bukkit.getScheduler()to move entity-bound work back to the main thread on Folia. Use the Folia entity or region scheduler.