Data Registry
Data Registry
DataRegistry is Lotus's type-safe state bag for temporary menu data.
Use it when you need a view or a button to remember something like:
- the current page number
- the selected category
- the UUID of the model behind a clicked button
Key<T>
A Key<T> names one piece of data and declares the expected type:
public final class Keys {
public static final Key<Integer> PAGE = Key.of("page", Integer.class);
public static final Key<UUID> TARGET = Key.of("target", UUID.class);
public static final Key<String> CATEGORY = Key.of("category", String.class);
}
Declare keys once in a shared Keys class and reuse them. That keeps menu code consistent and
searchable.
One Crucial Rule About Keys
Key equality is based on the name, not the Java type.
Key<Integer> PAGE = Key.of("page", Integer.class);
Key<String> PAGE_TEXT = Key.of("page", String.class);
Those two keys conflict because they share the same name.
Do not reuse the same key name for different types. Pick one name per concept and stick to it.
DataRegistry
The registry API is intentionally small:
DataRegistry data = DataRegistry.empty();
data.put(Keys.PAGE, 2);
data.put(Keys.TARGET, player.getUniqueId());
int page = data.require(Keys.PAGE);
Optional<UUID> target = data.get(Keys.TARGET);
boolean hasPage = data.contains(Keys.PAGE);
data.remove(Keys.PAGE);
If the value is missing, require(...) throws. If the value exists but has the wrong type,
Lotus throws a ClassCastException.
That type-checking happens on write and on read, which is exactly what makes the API
safer than Map<String, Object>.
Where You Will Use It
1. Per-view state
Every MenuView has a registry:
DataRegistry seed = DataRegistry.empty()
.put(Keys.TARGET, target.getUniqueId());
lotus.openMenu(player, new ProfileMenu(), seed);
Later inside the menu:
UUID target = view.data().require(Keys.TARGET);
2. Per-button state
Every Button also has a registry:
Button entry = Button.clickable(icon, (view, event) -> {
view.content().get(Slot.of(event.getSlot()))
.flatMap(button -> button.data().get(Keys.TARGET))
.ifPresent(this::inspectTarget);
});
entry.data().put(Keys.TARGET, targetUuid);
This is a great fit for paginated item lists.
Good Retrieval Patterns
Use get(...).orElse(...) for defaults:
int page = view.data().get(Keys.PAGE).orElse(0);
Use require(...) for invariants:
UUID target = view.data().require(Keys.TARGET);
Use mutation when the view state changes:
view.data().put(Keys.PAGE, view.data().require(Keys.PAGE) + 1);
view.refresh();
What Not To Do
- Do not share one
DataRegistryacross several open views. - Do not use it for long-lived global plugin state.
- Do not invent lots of throwaway key names inline; centralize them.
The Simple Heuristic
If the data should live only as long as the menu or the button lives, DataRegistry is a
good fit.
Next: Pagination, where per-button data becomes especially useful.