The Menu View
The Menu View
MenuView<C, M> is the live runtime object for one player and one open menu.
If Menu is the blueprint, MenuView is the actual house currently being lived in.
You will see a MenuView in:
title(...)capacity(...)content(...)- button click handlers
- menu handler callbacks
What You Can Read From A View
| Method | Meaning |
|---|---|
menu() |
The menu template behind this view |
viewer() |
The player looking at it |
title() |
The resolved title used when it was opened |
capacity() |
The resolved capacity used when it was opened |
content() |
The current live Content object |
data() |
The per-view DataRegistry |
type() |
The inventory type |
getInventory() |
The Bukkit inventory, or null before open / after close |
isOpen() |
Whether the view is still active |
refresh() |
Rebuild the content and repaint the inventory |
The Most Important Distinction
MenuView.refresh() rebuilds content, not the whole menu shell.
for (MenuView<?, ?> view : lotus.openViews()) {
if (view.menu() instanceof ShopMenu) {
view.refresh();
}
}
refresh() does not change the inventory title or capacity. Those were resolved when the view
was opened. If you need a new title or a different size, open a new menu.
Runtime Edits Inside A Click
Inside a button handler, you can mutate only the part that changed:
view.content().set(Slot.of(event.getSlot()), replacementButton);
view.content().update(Slot.of(event.getSlot()), current -> current.withItem(brighterIcon));
view.content().remove(Slot.of(event.getSlot()));
Lotus repaints automatically after button dispatch, so these changes show up right away.
If the change happens outside a click, such as a scheduler task or a service callback, call
view.refresh() yourself.
Tracking Open Views
Lotus keeps a live registry of open views:
Optional<MenuView<?, ?>> current = lotus.viewOf(player);
Collection<MenuView<?, ?>> allOpen = lotus.openViews();
This is useful for:
- refreshing every open shop menu after stock changes
- closing or inspecting a player's current menu
- syncing all viewers of a shared data source
A Practical Pattern
Use data() to keep the view-specific state close to the UI:
int page = view.data().get(Keys.PAGE).orElse(0);
UUID target = view.data().require(Keys.TARGET);
That keeps the view self-contained instead of scattering temporary menu state across your plugin.
Next: The Menu Handler for lifecycle hooks and click flow.