> ## Documentation Index
> Fetch the complete documentation index at: https://docs.marioded.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Recording a milestone

> Serialize a custom transient event on the recorder and render it on the player.

# Recording a milestone

**Runtime:** shared payload with role-specific bindings · **Use it for:** a transient game announcement

Follow the [custom recordables guide](https://docs.marioded.com/api/recordables.md) for codec registration and seek behavior.

This event announces a milestone during ordinary playback. It is transient, not durable state reconstructed while seeking. Keep the payload/codec contract synchronized across recording and playback machines.

Codec ID `1000` is illustrative, not a reserved extension allocation. Coordinate a free ID with every installed extension and register it before recording or loading data that uses it. Bind each role-specific helper only on a runtime that supplies that role.

```java theme={null}
package example;

import com.marioded.reverse.api.RecordSession;
import com.marioded.reverse.api.codec.RecordableCodec;
import com.marioded.reverse.api.player.ReversePlayer;
import com.marioded.reverse.api.recorder.ReverseRecorder;
import com.marioded.reverse.api.recordable.Recordable;
import com.marioded.reverse.api.service.RecordableService;

/** Shared transient payload. Coordinate the example codec ID with every installed extension. */
public record Milestone(String text) implements Recordable {
  // Illustrative allocation, not a reserved extension range.
  private static final int CODEC_ID = 1000;
  private static final RecordableCodec<Milestone> CODEC = RecordableCodec.of(
      input -> new Milestone(input.readString()),
      (output, value) -> output.writeString(value.text()));

  public static void registerCodec(RecordableService codecs) {
    codecs.register(CODEC_ID, Milestone.class, CODEC);
  }

  public static void onRecorderEnable(ReverseRecorder recorder) {
    registerCodec(recorder.getRecordableService());
  }

  public static void onPlayerEnable(ReversePlayer player) {
    registerCodec(player.getRecordableService());
    player.getRendererService().register(Milestone.class, (event, context) -> {
      for (org.bukkit.entity.Player viewer : context.getViewers()) {
        viewer.sendMessage(event.text());
      }
    });
  }

  public static void record(ReverseRecorder recorder, RecordSession session, String text) {
    recorder.getRecorderService().insertIntoSession(session.getUniqueId(), new Milestone(text));
  }
}
```

Use this payload and its role-specific bindings in your own integration. For persistent entity/block effects, read the durable-state and resynchronization requirements before extending this pattern.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.