> For the complete documentation index, see [llms.txt](https://docs.marioded.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.marioded.com/api-how-to-guides/examples/replay-notifications.md).

# Handling notifications

Observe save completion and playback termination while respecting event threading.

**Runtime:** recorder/player APIs · **Use it for:** save and playback notifications

Follow the [event guide](/api-how-to-guides/events.md) to choose the correct notification and completion thread.

The save event may be asynchronous. Copy the values you need and schedule Bukkit-facing work onto the main thread. A stop event is a post-cleanup playback notification, not a cancellation hook.

This teaching example imports both role APIs. Split it into role-specific listeners for independently deployed recorder and player integrations; do not eagerly resolve an absent role's event classes.

{% code title="ReplayNotifications.java" %}

```java
package example;

import com.marioded.reverse.api.player.event.PlaybackStopEvent;
import com.marioded.reverse.api.recorder.event.RecordingSavedEvent;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;

/** Install this dual-role example only where both event API modules are available. */
public final class ReplayNotifications extends JavaPlugin implements Listener {
  @Override
  public void onEnable() {
    Bukkit.getPluginManager().registerEvents(this, this);
  }

  @EventHandler
  public void onSaved(RecordingSavedEvent event) {
    UUID replayId = event.getReplayId();
    boolean degraded = event.isDegraded();
    if (!isEnabled()) return;
    Bukkit.getScheduler().runTask(this, () -> {
      // Replace this logging hook with your application's main-thread notification.
      getLogger().info("Saved " + replayId + (degraded ? " (terrain unavailable)" : ""));
    });
  }

  @EventHandler
  public void onPlaybackStopped(PlaybackStopEvent event) {
    getLogger().info("Playback ended: " + event.getSession().getSessionId()
        + "; reached final tick: " + event.getSession().isFinished());
  }
}
```

{% endcode %}

Copy the handlers needed by your integration and declare the corresponding runtime dependency.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.marioded.com/api-how-to-guides/examples/replay-notifications.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
