Introduction

Lotus At A Glance

Lotus is a menu framework for Bukkit-based plugins. You describe a menu in terms of title, capacity, content, and button behavior, then Lotus handles the boring runtime work for you: opening inventories, tracking live views, dispatching clicks, repainting buttons, and building paginated screens.

If you are coming from raw Bukkit Inventory code, Lotus removes the three big pain points:

  • slot math everywhere
  • listener boilerplate everywhere
  • state scattered across unrelated classes

Which module do you use?

Lotus is split into three modules:

Module Purpose Use it directly?
lotus-commons Shared core runtime and API No
lotus-paper Paper 1.21+ integration Yes, on Paper
lotus-spigot Spigot 1.8.8 integration Yes, on Spigot

You add exactly one platform module to your plugin: lotus-paper or lotus-spigot. lotus-commons comes in automatically.

These docs are written against the current Lotus 2.x source API from the Lotus repository, including the multi-module split and the platform-specific builders.

The Mental Model

You only need a few concepts to be productive:

  • Lotus<C> is the runtime you create once in onEnable().
  • Menu<C> is the template that describes one screen.
  • MenuView<C, M> is the live, per-player instance of that menu.
  • Content is the slot-to-button map inside a view.
  • Button is the clickable or decorative thing placed in a slot.
  • Pagination<T> is a reusable page definition that opens a fresh session per player.

The easiest way to think about Lotus is: a menu is a function of the current view state. When the state changes, Lotus can repaint what the player sees.

Quick Tour

Add the repository configuration that matches your build tool: {<repositories> <repository> <id>papermc-repo</id> <url>https://repo.papermc.io/repository/maven-public/</url> </repository> </repositories>} {repositories { maven { url = 'https://repo.papermc.io/repository/maven-public/' } mavenCentral() }} {repositories { maven("https://repo.papermc.io/repository/maven-public/") mavenCentral() }}

Then add the Paper artifact:

Minimal Paper setup:













public final class MyPlugin extends JavaPlugin {

    private Lotus<Component> lotus;

    @Override
    public void onEnable() {
        this.lotus = PaperLotus.create(this);
    }

    public void openWelcome(Player player) {
        lotus.openMenu(player, new WelcomeMenu());
    }
}

final class WelcomeMenu implements PaperMenu {

    @Override
    public Component title(MenuView<Component, ?> view) {
        return Component.text("Welcome");
    }

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

    @Override
    public Content content(MenuView<Component, ?> view) {
        return Content.builder(view.capacity())
            .fillBorder(Button.of(new ItemStack(Material.BLACK_STAINED_GLASS_PANE)))
            .set(1, 4, Button.clickable(
                new ItemStack(Material.PAPER),
                (menuView, event) ->
                    menuView.viewer().sendMessage(Component.text("Hello from Lotus!"))
            ))
            .build();
    }
}

Add the repository configuration that matches your build tool: {<repositories> <repository> <id>spigotmc-repo</id> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> </repository> <repository> <id>sonatype-snapshots</id> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> </repository> </repositories>} {repositories { maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } maven { url = 'https://oss.sonatype.org/content/repositories/snapshots/' } mavenCentral() }} {repositories { maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") maven("https://oss.sonatype.org/content/repositories/snapshots/") mavenCentral() }}

Then add the Spigot artifact:

Minimal Spigot setup:













public final class MyPlugin extends JavaPlugin {

    private Lotus<String> lotus;

    @Override
    public void onEnable() {
        this.lotus = SpigotLotus.create(this);
    }

    public void openWelcome(Player player) {
        lotus.openMenu(player, new WelcomeMenu());
    }
}

final class WelcomeMenu implements Menu<String> {

    @Override
    public String title(MenuView<String, ?> view) {
        return ChatColor.GOLD + "Welcome";
    }

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

    @Override
    public Content content(MenuView<String, ?> view) {
        return Content.builder(view.capacity())
            .fillBorder(Button.of(new ItemStack(Material.STAINED_GLASS_PANE)))
            .set(1, 4, Button.clickable(
                new ItemStack(Material.PAPER),
                (menuView, event) ->
                    menuView.viewer().sendMessage(ChatColor.YELLOW + "Hello from Lotus!")
            ))
            .build();
    }
}

On Paper, menu titles are Adventure Components. On Spigot, menu titles are plain Strings, and Lotus uses that string as-is. If you want colors on Spigot, translate or build the string yourself.

Read The Docs In This Order

  1. Getting Started to install the right artifact, shade it, and boot Lotus once.
  2. Your First Menu to build something that opens immediately.
  3. Capacity, Slots & Slot Masks to understand the grid model.
  4. Content and Slot Iterator to learn how Lotus stores buttons and how to place several objects in order.
  5. Menus to learn templates, live views, and handler hooks.
  6. Buttons to learn the six built-in button types.
  7. Pagination once you are ready for scrollable lists.