Skip to main content
The Menu class is the foundation of the menu system in Foundation. It provides a framework for creating interactive inventory GUIs with automatic button registration, parent menu navigation, and event handling.

Creating a menu

To create a menu, extend the Menu class and customize it in your constructor:
public class MyMenu extends Menu {
    
    public MyMenu() {
        setTitle("&6My Custom Menu");
        setSize(9 * 3);
    }
    
    @Override
    public ItemStack getItemAt(int slot) {
        if (slot == 13) {
            return ItemCreator.of(CompMaterial.DIAMOND)
                .name("&bClick me!")
                .lore("This is a clickable item")
                .make();
        }
        return NO_ITEM;
    }
}

Constructors

Menu()
constructor
Create a new menu without a parent menu with default size of 9*3.
Menu(Menu parent)
constructor
Create a new menu with a parent menu.
Menu(Menu parent, boolean returnMakesNewInstance)
constructor
Create a new menu with a parent menu and control whether returning creates a new instance.

Core methods

Display methods

displayTo(Player player)
void
Display this menu to the specified player.
MyMenu menu = new MyMenu();
menu.displayTo(player);
restartMenu()
void
Redraws and refreshes all buttons in the current menu.
@Override
public void onButtonClick(Player player, int slot, InventoryAction action, ClickType click, Button button) {
    // Update some data
    updatePlayerData();
    
    // Refresh the menu
    restartMenu();
}
restartMenu(String animatedTitle)
void
Redraws and refreshes all buttons while showing an animated title.
restartMenu("&aItem purchased!");

Configuration methods

setTitle(String title)
void
Sets the title of the menu. Color codes with & are supported.
setTitle("&6&lMy Menu");
setSize(Integer size)
void
Sets the size of the menu. Must be a multiple of 9 (max 54).
setSize(9 * 6); // 6 rows
setSlotNumbersVisible()
void
Enable debug mode to show slot numbers in empty slots. Useful during development.
public MyMenu() {
    setSlotNumbersVisible();
}

Button registration

registerButton(Button button)
void
Manually register a button that is not a field. The button must have its slot set.
Do NOT use this for buttons that are fields - field buttons are automatically registered.
Button dynamicButton = new Button(10) {
    @Override
    public void onClickedInMenu(Player player, Menu menu, ClickType click) {
        player.sendMessage("Clicked!");
    }
    
    @Override
    public ItemStack getItem() {
        return ItemCreator.of(CompMaterial.STONE).make();
    }
};

registerButton(dynamicButton);
redrawButtons()
void
Redraws all registered buttons without restarting the entire menu.
// Update button appearance
redrawButtons();

Item management

getItemAt(int slot)
ItemStack
Returns the item to display at a specific slot. Override this method to populate your menu.
@Override
public ItemStack getItemAt(int slot) {
    if (slot == 0) {
        return ItemCreator.of(CompMaterial.DIAMOND_SWORD)
            .name("&6Weapon")
            .make();
    }
    return NO_ITEM;
}
setItem(int slot, ItemStack item)
void
Updates a specific slot with a new item.
If the slot contains a button and you want it to remain functional, use the @Position annotation or set the button’s slot.
setItem(10, ItemCreator.of(CompMaterial.GOLD_INGOT).make());

Event hooks

onMenuClick(Player player, int slot, ItemStack clicked)
void
Called when any slot in the menu is clicked.
@Override
protected void onMenuClick(Player player, int slot, ItemStack clicked) {
    player.sendMessage("You clicked slot " + slot);
}
onButtonClick(Player player, int slot, InventoryAction action, ClickType click, Button button)
void
Called when a registered button is clicked.
@Override
protected void onButtonClick(Player player, int slot, InventoryAction action, ClickType click, Button button) {
    if (click.isRightClick()) {
        player.sendMessage("Right clicked button!");
    }
}
onMenuClose(Player player, Inventory inventory)
void
Called when the menu is closed.
@Override
protected void onMenuClose(Player player, Inventory inventory) {
    savePlayerData(player);
}
onPreDisplay(InventoryDrawer drawer)
void
Called before the menu is displayed, after items have been drawn. Use for last-minute modifications.
@Override
protected void onPreDisplay(InventoryDrawer drawer) {
    drawer.setItem(0, ItemCreator.of(CompMaterial.BARRIER).make());
}
onRestart()
void
Called when the menu is restarted. Called after registerButtons() and before getItemAt().

Utility methods

Slot helpers

getCenterSlot()
int
Calculates and returns the center slot of the menu.
int center = getCenterSlot();
setItem(center, ItemCreator.of(CompMaterial.NETHER_STAR).make());
getBottomCenterSlot()
int
Returns the middle slot in the last row (hotbar area).

Messaging

tell(String... messages)
void
Send a message to the viewer.
tell("&aWelcome to the menu!");
tellInfo(String message)
void
Send an info message to the viewer.
tellSuccess(String message)
void
Send a success message to the viewer.
tellWarn(String message)
void
Send a warning message to the viewer.
tellError(String message)
void
Send an error message to the viewer.

Getters

getViewer()
Player
Get the player viewing this menu instance.
getTitle()
String
Get the current title of the menu.
getSize()
Integer
Get the size of the menu.
getParent()
Menu
Get the parent menu, or null if none exists.
getInventory()
Inventory
Return the currently opened inventory if viewer exists.

Animation

animateTitle(String title)
void
Animate the menu title temporarily, then revert to the original title.
animateTitle("&6Processing...");
animate(int periodTicks, MenuRunnable task)
void
Start a repeating task on the main thread that stops when the viewer closes the menu.
animate(20, () -> {
    // Update every second
    redrawButtons();
});

Static methods

getMenu(Player player)
Menu
Returns the current menu for a player, or null if none.
Menu currentMenu = Menu.getMenu(player);
getPreviousMenu(Player player)
Menu
Returns the previous menu for a player, or null if none.
setSound(SimpleSound sound)
void
Set the default sound played when opening menus. Set to null to disable.
Menu.setSound(new SimpleSound(CompSound.BLOCK_NOTE_BLOCK_PLING, 1.0F));

Complete example

public class ShopMenu extends Menu {
    
    private final Button buyButton;
    
    public ShopMenu() {
        setTitle("&6&lItem Shop");
        setSize(9 * 3);
        
        // Buttons as fields are automatically registered
        buyButton = new Button() {
            @Override
            public void onClickedInMenu(Player player, Menu menu, ClickType click) {
                player.sendMessage("Item purchased!");
                restartMenu("&aThank you!");
            }
            
            @Override
            public ItemStack getItem() {
                return ItemCreator.of(CompMaterial.DIAMOND)
                    .name("&6Buy Diamond")
                    .lore("&7Click to purchase")
                    .lore("&7Cost: $100")
                    .make();
            }
        };
    }
    
    @Override
    public ItemStack getItemAt(int slot) {
        if (slot == 13) {
            return buyButton.getItem();
        }
        return NO_ITEM;
    }
}

Build docs developers (and LLMs) love