The Menu Template

The Menu Template

A Menu<C> is the blueprint of a screen. It is not the live inventory itself.

When you call lotus.openMenu(...), Lotus resolves that template for one player and creates a MenuView<C, M>.

What C Means

C is the title type:

  • Paper uses Component
  • Spigot uses String

That is why most plugin authors implement one of these:

  • PaperMenu on Paper
  • Menu<String> on Spigot

The Three Required Methods

Every menu answers the same three questions:

  1. What is the title?
  2. How big is the inventory?
  3. What content should be rendered?
{`

public final class ProfileMenu implements PaperMenu {

@Override
public Component title(MenuView<Component, ?> view) {
    return Component.text(view.viewer().getName() + "'s Profile");
}

@Override
public Capacity capacity(MenuView<Component, ?> view) {
    return Capacity.ofRows(3);
}

@Override
public Content content(MenuView<Component, ?> view) {
    return Content.builder(view.capacity())
        .set(1, 4, Button.of(new ItemStack(Material.PLAYER_HEAD)))
        .build();
}

} }</CodeTabItem> <CodeTabItem value="spigot" label="Spigot 1.8.8" language="java">{

public final class ProfileMenu implements Menu {

@Override
public String title(MenuView<String, ?> view) {
    return ChatColor.GOLD + view.viewer().getName() + "'s Profile";
}

@Override
public Capacity capacity(MenuView<String, ?> view) {
    return Capacity.ofRows(3);
}

@Override
public Content content(MenuView<String, ?> view) {
    return Content.builder(view.capacity())
        .set(1, 4, Button.of(new ItemStack(Material.SKULL_ITEM)))
        .build();
}

} `}

Treat title(...), capacity(...), and content(...) as pure functions of the current view. If data comes from elsewhere, read it from the view's DataRegistry or from your own service layer.

Optional Methods You Will Actually Use

Method Default Why override it
name() class simple name Open menus by string, such as commands or config
type() InventoryType.CHEST Use HOPPER, DISPENSER, WORKBENCH, and so on

name()

@Override
public String name() {
    return "profile";
}

type()

@Override
public InventoryType type() {
    return InventoryType.HOPPER;
}

Make sure type() and capacity() agree with each other. If you return InventoryType.HOPPER, use a hopper-sized capacity such as Capacity.of(InventoryType.HOPPER). For chest menus with 1-6 rows, keep type() as CHEST and use Capacity.ofRows(...).

Opening A Menu

lotus.openMenu(player, new ProfileMenu());

You can also seed the new view with data:

DataRegistry seed = DataRegistry.empty()
    .put(Keys.TARGET, target.getUniqueId());

lotus.openMenu(player, new ProfileMenu(), seed);

And if the menu was registered earlier:

lotus.openMenu(player, "profile");

Good Beginner Habit

Keep the menu class focused on presentation. Let your plugin services fetch or mutate the real data, and let the menu turn that data into buttons.

Next: The Menu View, the live object you receive everywhere else.