> 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/menu-actions.md).

# Custom menu actions

Register an action, bind a catalog item to it, and use the menu interaction context.

Let's add a button that shows a recording's ID. We will register a callback in the real menu registry, then reference it from `gui.details.items`.

## Get the menu registry

On a lobby server:

```java
ReverseLobby lobby = ReverseLobby.get().orElseThrow();
MenuActionRegistry registry = lobby.getActionRegistry();
```

On a standalone player server:

```java
ReversePlayer player = ReversePlayer.get().orElseThrow();
MenuActionRegistry registry = player.getActionRegistry();
if (registry == null) {
    return; // The standalone GUI is not initialized, for example in network-worker mode.
}
```

These snippets belong in your main-thread integration setup. Keep the registry reference if you will unregister your action when disabling.

## Register the callback

```java
registry.register("example:show_id", (context, parameters) -> {
    if (!context.isActive() || !context.hasReplay()) return;

    String label = parameters.getOrDefault("label", "Replay");
    context.player().sendMessage(label + ": " + context.requireReplay().getUniqueId());
});
```

Here is what each piece does:

* `example:show_id` is the action's namespaced ID.
* `context` describes the current menu interaction and selected replay, if one exists.
* `parameters` contains the string parameters configured on the clicked item.
* `hasReplay()` protects `requireReplay()` from being called on an item without a replay selection.

This example only shows data. If an action edits or deletes a replay, perform a fresh catalog operation with a trusted actor rather than trusting an old selection.

## Put the action on a button

Merge this item into the lobby or standalone player's `config.yml`:

{% code title="config.yml — gui.details.items" %}

```yaml
gui:
  details:
    items:
      show_id:
        slot: 15
        entry: false
        visible-in: [ready]
        material: PAPER
        amount: 1
        data: 0
        name: '<aqua>Show replay ID'
        lore: ['<gray>Print the selected recording ID in chat.']
        flags: []
        action: example:show_id
        parameters:
          label: 'Recording'
```

{% endcode %}

Choose a slot that is free in that menu and reload the owning role. Menu slots are **zero-based**. Open a replay's details and click the button; our callback will read `label` and send the selected UUID.

## Use navigation from the context

The context also provides menu navigation:

```java
registry.register("example:return_to_catalog", (context, parameters) -> {
    if (context.isActive()) context.openCatalog();
});
```

Other context operations include `openDetails(replayId)`, `back()`, `close()`, `refresh()`, and page navigation. Use them instead of reaching into Inventory Framework objects. `replay()` can be null; not every catalog background item belongs to a recording.

## Unregister when disabling

```java
registry.unregister("example:show_id");
registry.unregister("example:return_to_catalog");
```

The registry is shared. If another integration intentionally replaced one of your IDs, coordinate cleanup instead of removing its callback accidentally. The namespace is not an automatic ownership token.

For asynchronous actions, see [Threading and failure handling](/api-how-to-guides/threading-and-failures.md). For the complete player setup and cleanup example, see [Extending the UI](/api-how-to-guides/examples/ui-extensions.md).


---

# 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/menu-actions.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.
