> For the complete documentation index, see [llms.txt](https://docs-nightbeam.gitbook.io/infinity-rifts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-nightbeam.gitbook.io/infinity-rifts/docs/events.md).

# Public events

All public events are in `io.nightbeam.infinityrifts.api.event` and carry an immutable `GatewaySession` snapshot. They are notification events and are not cancellable.

| Event                       | Fired when                                                           | Additional value                                                          |
| --------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `GatewayStartedEvent`       | A new player-owned or ownerless session has started                  | `getSession()`                                                            |
| `GatewayWaveStartedEvent`   | A configured wave becomes active, before its mobs spawn              | `getWave()`                                                               |
| `GatewayWaveMobDeathEvent`  | A tracked wave mob dies naturally (once per mob)                     | entity, mob id, killer, damage cause, remaining count, wave-complete flag |
| `GatewayWaveMobRemoveEvent` | A tracked wave mob disappears without a natural death (once per mob) | remove reason, remaining count                                            |
| `GatewayWaveCompletedEvent` | All required mobs in a wave are gone and the wave completes          | spawn/kill/remove counts, duration, reason, next wave                     |
| `GatewayRestoredEvent`      | A persisted player session resumes after startup/join                | `getSession()`                                                            |
| `GatewayEndedEvent`         | Session cleanup has completed                                        | `getReason()`                                                             |

`GatewayWaveMobDeathEvent` and `GatewayWaveMobRemoveEvent` are mutually exclusive for the same mob. Natural deaths never also publish a remove event.

Example listener:

```java
public final class RiftListener implements Listener {
    @EventHandler
    public void onWave(GatewayWaveStartedEvent event) {
        getLogger().info(event.getSession().gatewayId()
                + " entered wave " + event.getWave());
    }

    @EventHandler
    public void onWaveMobDeath(GatewayWaveMobDeathEvent event) {
        getLogger().info("Mob " + event.getEntityId()
                + " died in wave " + event.getWave()
                + "; remaining=" + event.getRemainingMobCount());
    }

    @EventHandler
    public void onWaveComplete(GatewayWaveCompletedEvent event) {
        getLogger().info("Wave " + event.getWave()
                + " done: killed=" + event.getKilledMobCount());
    }

    @EventHandler
    public void onEnd(GatewayEndedEvent event) {
        getLogger().info(event.getSession().sessionId()
                + " ended: " + event.getReason());
    }
}
```

Register the listener normally with Bukkit. The snapshot on `GatewayEndedEvent` represents the session immediately before cleanup changed its internal state, while the event itself is published after cleanup.

Events are standard synchronous Bukkit events. On Folia, the callback runs in the owning region/entity execution context; it is not a promise that the callback is on the global server thread. Keep handlers short and schedule unrelated entity/world access on the correct owner.
