Advanced
Advanced
This page collects the less-common but still important knobs in Lotus: runtime options, helpers, custom openers, and extension boundaries.
Lotus.Options
Runtime options are configured when you create the Lotus instance:
Lotus<Component> lotus = PaperLotus.create(this, builder -> builder
.allowBottomInventoryClick(false)
.dynamicButtonAction(false)
.debug(true)
);
| Option | Default | What it means |
|---|---|---|
allowBottomInventoryClick |
true |
Allow clicks in the player's own inventory while a Lotus menu is open |
dynamicButtonAction |
false |
Let Lotus internally move buttons during pickup/place inventory actions |
debug |
false |
Enable [lotus] debug logging |
Read them back with lotus.options().
ItemBuilder
Both platform modules ship an ItemBuilder tuned to the platform's text API.
ItemStack sword = ItemBuilder.of(Material.DIAMOND_SWORD)
.displayName(Component.text("Legendary Blade").color(NamedTextColor.AQUA))
.lore(
Component.text("A very sharp blade").color(NamedTextColor.GRAY),
Component.text("Tier: Legendary").color(NamedTextColor.GOLD)
)
.amount(1)
.unbreakable(true)
.build();
}</CodeTabItem> <CodeTabItem value="spigot" label="Spigot 1.8.8" language="java">{
ItemStack sword = ItemBuilder.of(Material.DIAMOND_SWORD) .displayName("&bLegendary Blade") .lore("&7A very sharp blade", "&6Tier: Legendary") .amount(1) .unbreakable(true) .build(); `}
On Spigot, ItemBuilder translates & color codes for item names and lore.
Register Menus By Name
lotus.registerMenu(new ShopMenu());
lotus.openMenu(player, "shop");
lotus.registeredMenu("shop");
This is handy for command-driven or config-driven menus.
Inspect Open Views
lotus.viewOf(player);
lotus.openViews();
Common pattern:
for (MenuView<?, ?> view : lotus.openViews()) {
if (view.menu() instanceof ShopMenu) {
view.refresh();
}
}
Custom ViewOpener
If you need a special open path for a specific InventoryType, register a custom opener.
view.content().forEach((slot, button) -> inventory.setItem(slot.index(), button.item()));
view.viewer().openInventory(inventory);
return inventory;
});
}</CodeTabItem> <CodeTabItem value="spigot" label="Spigot 1.8.8" language="java">{
lotus.registerOpener(InventoryType.HOPPER, (framework, view) -> {
Inventory inventory = Bukkit.createInventory(view, InventoryType.HOPPER, "Quick Actions");
view.content().forEach((slot, button) -> inventory.setItem(slot.index(), button.item()));
view.viewer().openInventory(inventory);
return inventory;
}); `}
ViewOpener is part of the public spi package, so extending it is a supported customization path.
Pagination Sync Helpers
When a shared data source changes, you may want to refresh already-open pagination views without tracking every session yourself.
Use the pagination definition ID, which is the string passed to Pagination.builder("...").
The one-player overload refreshes a specific player's currently open pagination if it matches the ID. The two-argument overload scans all open views managed by that Lotus runtime and refreshes the matching ones.
Error Handling
If a button throws a RuntimeException, Lotus catches it, logs the problem, and keeps the menu
usable:
[lotus] button dispatch failed in menu <name>
You can also log your own messages through lotus.logger().
Public Surface vs Internal Surface
The stable extension points live in:
studio.mevera.lotus.api.*studio.mevera.lotus.spi.*
Avoid importing internal.* classes. They are implementation details and are not the public
compatibility surface.
High-Level Package Map
lotus-commons
studio.mevera.lotus
Lotus, LotusBuilder
api.button
api.content
api.data
api.item
api.menu
api.pagination
api.slot
spi
lotus-paper
studio.mevera.lotus.paper
PaperLotus
ItemBuilder
api.menu
api.pagination
lotus-spigot
studio.mevera.lotus.spigot
SpigotLotus
ItemBuilder
api.pagination
That is the practical import surface most plugin authors work with.