### Maven Dependency Setup
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Add the XenonDevs Maven repository and the InvUI artifact as a dependency in your Maven project.
```xml
xenondevs
https://repo.xenondevs.xyz/releases
xyz.xenondevs.invui
invui
2.1.0
provided
```
--------------------------------
### Gradle Dependency Setup
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Add the XenonDevs Maven repository and the InvUI artifact as a dependency in your Gradle project using Kotlin DSL.
```gradle
repositories {
maven { url = uri("https://repo.xenondevs.xyz/releases") }
}
dependencies {
implementation("xyz.xenondevs.invui:invui:2.1.0")
}
```
--------------------------------
### Window Management
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Demonstrates how to create and manage GUI windows, including standard split windows and specialized types like AnvilWindow. It covers setting titles, defining GUIs, handling player interactions, and dynamic title updates.
```APIDOC
## `Window` — Displaying GUIs and Handling Open/Close Events
`Window` is the link between a `Gui` and a Bukkit inventory shown to a specific player. Use `Window.builder()` for a standard split window (upper GUI + player inventory) or `Window.mergedBuilder()` for a single merged GUI. Special window types (Anvil, Furnace, Stonecutter, etc.) have their own factories.
```java
import net.kyori.adventure.text.Component;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.window.Window;
import xyz.xenondevs.invui.window.AnvilWindow;
// Standard split window (chest-style, upper GUI + player hotbar below)
Window window = Window.builder()
.setTitle("Treasure Chest")
.setGui(gui)
.setViewer(player)
.addOpenHandler(() -> System.out.println(player.getName() + " opened the menu"))
.addCloseHandler(() -> System.out.println(player.getName() + " closed the menu"))
.build();
window.open();
// Change the title dynamically after opening
window.setTitle(Component.text("Updated Title"));
// Anvil window — upper GUI is a 3-slot (left, right, output); captures rename input
AnvilWindow anvilWindow = AnvilWindow.builder()
.setTitle("Search…")
.setUpperGui(Gui.empty(3, 1))
.setLowerGui(gui)
.setViewer(player)
.addRenameHandler(text -> System.out.println("Player typed: " + text))
.build();
anvilWindow.open();
```
```
--------------------------------
### Normal GUI with Structure
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Build a bordered 9x4 chest GUI using Gui.builder() and a structure string. Unrecognized characters in the structure are left empty.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemBuilder;
import xyz.xenondevs.invui.window.Window;
// Build a bordered 9x4 chest GUI
Item borderItem = Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "));
Gui gui = Gui.builder()
.setStructure(
"# # # # # # # # #",
"# . . . . . . . #",
"# . . . . . . . #",
"# # # # # # # # #"
)
.addIngredient('#', borderItem)
.build();
// Show to a player with a chest window
Window.builder()
.setTitle("My Menu")
.setGui(gui)
.setViewer(player)
.build()
.open();
```
--------------------------------
### Create a Normal GUI with GUIBuilder
Source: https://github.com/nichtstudiocode/invui/wiki/Normal-GUI
Use GUIBuilder to construct a normal GUI with a specified size and structure. Define item placements using a string-based layout.
```java
Item border = new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))
GUI gui = new GUIBuilder<>(GUIType.NORMAL, 9, 4)
.setStructure("" +
"# # # # # # # # #" +
"# . . . . . . . #" +
"# . . . . . . . #" +
"# # # # # # # # #")
.addIngredient('#', border)
.build();
```
--------------------------------
### ItemBuilder with Placeholders and Localization
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Demonstrates using `ItemBuilder` with MiniMessage placeholders that are resolved at build time. It shows how to build an item with a player's specific locale.
```java
ItemBuilder localized = new ItemBuilder(Material.BOOK)
.setName("'s Journal")
.addLoreLines("Last login: ")
.setPlaceholder("player_name", player.getName())
.setPlaceholder("player_color", "")
.setPlaceholder("last_login", "2024-01-15");
ItemStack result = localized.build(); // builds with Locale.US
ItemStack forLocale = localized.build(player.locale()); // builds with player's locale
```
--------------------------------
### GUI Animations
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Explains how to use the `Animation` class to create pop-in effects for GUI slots. It details configuring animation speed, slot selection patterns, intermediary items, sound effects, and completion callbacks.
```APIDOC
## `Animation` — Slot Pop-In Effects
`Animation` lets slots in a GUI "pop in" in a defined order with a configurable tick delay between frames. While an animation runs, the GUI is frozen (no player interaction). Animations support custom slot filters, intermediary item providers, sound effects, and finish callbacks.
```java
import org.bukkit.Material;
import org.bukkit.Sound;
import xyz.xenondevs.invui.gui.Animation;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.item.ItemBuilder;
Gui gui = Gui.builder()
.setStructure(
"a a a a a a a a a",
"a a a a a a a a a",
"a a a a a a a a a"
)
.addIngredient('a', Item.simple(new ItemBuilder(Material.DIAMOND)))
.build();
// Horizontal snake animation with a sound effect on each frame
Animation animation = Animation.builder()
.setTickDelay(2)
.setSlotSelector(() -> Animation.horizontalSnakeSlotSelector())
.setIntermediary(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "))
.addSoundEffect(Sound.BLOCK_NOTE_BLOCK_PLING, 1.0f, 1.5f)
.addFinishHandler(state -> System.out.println("Animation complete!"))
.build();
gui.playAnimation(animation);
// Cancel a running animation if needed
// gui.cancelAnimation();
```
```
--------------------------------
### Create and Apply a Structure
Source: https://github.com/nichtstudiocode/invui/wiki/Structure
Define a GUI layout using characters and ingredients, then apply it to a GUI builder or an existing GUI. Ingredients like Marker.ITEM_LIST_SLOT, BackItem, and ForwardItem can be used.
```java
Structure structure = new Structure("\n # # # # # # # # #\n # x x x x x x x #\n # x x x x x x x #\n # # # < # > # # #")
.addIngredient('x', Marker.ITEM_LIST_SLOT) // where paged items should be put
.addIngredient('#', new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setDisplayName("§r")) // this will just create a SimpleItem with the given ItemBuilder
.addIngredient('<', new BackItem())
.addIngredient('>', new ForwardItem());
// use it in a GUI Builder
new GUIBuilder(GUIType.PAGED_ITEMS, 9, 4).setStructure(structure);
// or use it on an existing GUI
gui.applyStructure(structure);
```
--------------------------------
### Build a Paged GUI with a list of items
Source: https://github.com/nichtstudiocode/invui/wiki/Paged-GUI
Constructs a paged GUI using 'GUIBuilder' to display a list of items. It defines the GUI structure, assigns slots for paged items, borders, and navigation controls, and sets the items to be displayed.
```java
Item border = new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setDisplayName("§r"));
// an example list of items to display
List- items = Arrays.stream(Material.values())
.filter(material -> !material.isAir() && material.isItem())
.map(material -> new SimpleItem(new ItemBuilder(material)))
.collect(Collectors.toList());
// create the gui
GUI gui = new GUIBuilder<>(GUIType.PAGED_ITEMS, 9, 4)
.setStructure("" +
"# # # # # # # # #" +
"# x x x x x x x #" +
"# x x x x x x x #" +
"# # # < # > # # #")
.addIngredient('x', Markers.ITEM_LIST_SLOT) // where paged items should be put
.addIngredient('#', border)
.addIngredient('<', new BackItem())
.addIngredient('>', new ForwardItem())
.setItems(items)
.build();
// show the window
new SimpleWindow(player, "InvUI", gui).show();
```
--------------------------------
### Plugin Initialization
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Initialize InvUI in your plugin's onEnable method by supplying the plugin instance to the InvUI singleton before creating any GUIs.
```java
import xyz.xenondevs.invui.InvUI;
import org.bukkit.plugin.java.JavaPlugin;
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
InvUI.getInstance().setPlugin(this);
}
}
```
--------------------------------
### Gui.fill
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Fills the entire GUI with a specified item.
```APIDOC
## `Gui.fill`
### Description
Fills the entire GUI with the provided item.
### Method
`void fill(Item item)`
### Parameters
- **item** (Item) - The item to fill the GUI with.
### Request Example
```java
Gui gui = Gui.empty(9, 6);
Item glass = Item.simple(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE).setName(" "));
gui.fill(glass);
```
```
--------------------------------
### Build a Paged GUI with other GUIs as pages
Source: https://github.com/nichtstudiocode/invui/wiki/Paged-GUI
Constructs a paged GUI where each page is another GUI. It defines the structure, navigation controls, and sets a list of GUIs to be displayed as pages.
```java
GUI gui = new GUIBuilder<>(GUIType.PAGED_GUIs, 9, 5)
.setStructure("" +
"x x x x x x x x x" +
"x x x x x x x x x" +
"x x x x x x x x x" +
"x x x x x x x x x" +
". . < . . . > . .")
.addIngredient('x', Markers.ITEM_LIST_SLOT) // where paged items should be put (in this case: the parts of the nested GUI)
.addIngredient('<', new BackItem())
.addIngredient('>', new ForwardItem())
.setGUIs(Arrays.asList(page1GUI, page2GUI))
.build();
// show the window
new SimpleWindow(player, "InvUI", gui).show();
```
--------------------------------
### Set Up Server-Side Localization
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Register translation maps for each Locale using Languages.getInstance().addLanguage(). ItemBuilder automatically resolves translatable keys based on the viewer's locale when building items.
```java
import xyz.xenondevs.invui.i18n.Languages;
import xyz.xenondevs.invui.item.ItemBuilder;
import org.bukkit.Material;
import java.util.Locale;
import java.util.Map;
// Register translations in onEnable
Languages languages = Languages.getInstance();
languages.addLanguage(Locale.ENGLISH, Map.of(
"menu.title", "Main Menu",
"item.sword.name", "Firesword",
"item.sword.lore", "Burns enemies on hit"
));
languages.addLanguage(Locale.GERMAN, Map.of(
"menu.title", "Hauptmenü",
"item.sword.name", "Feuerschwert",
"item.sword.lore", "Setzt Feinde beim Treffen in Brand"
));
// ItemBuilder resolves keys automatically for the viewer's locale
ItemBuilder swordBuilder = new ItemBuilder(Material.DIAMOND_SWORD)
.setName("item.sword.name") // treated as a translation key (MiniMessage format)
.addLoreLines("item.sword.lore");
// When the window is opened, InvUI calls getItemProvider(player)
// which calls swordBuilder.get(player.locale()), resolving the correct translation
```
--------------------------------
### Fill GUI with Items
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Fills the entire GUI with a specified item. Useful for creating backgrounds or placeholder elements.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemBuilder;
Gui gui = Gui.empty(9, 6);
// Fill the entire GUI with a placeholder
Item glass = Item.simple(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE).setName(" "));
gui.fill(glass);
```
--------------------------------
### Custom Click Handling Item with Item.builder()
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Creates an item that counts clicks and updates its display. `updateOnClick()` automatically calls `notifyWindows()` on each click, so manual calls are not needed in the handler.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemBuilder;
// An item that counts clicks and updates its display accordingly
int[] clickCount = {0};
Item counterItem = Item.builder()
.setItemProvider(player -> new ItemBuilder(Material.DIAMOND)
.setName("Clicks: " + clickCount[0]))
.updateOnClick() // calls notifyWindows() automatically on each click
.addClickHandler(click -> {
if (click.clickType().isLeftClick()) {
clickCount[0]++;
} else {
clickCount[0] = 0;
}
// notifyWindows() is called by updateOnClick(); no manual call needed here
})
.build();
```
--------------------------------
### Create a Tabbed GUI with Switchable Sub-GUIs using TabGui
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Use TabGui to manage multiple nested GUIs as tabs. Individual tabs can be null for conditional disabling. Markers.ITEM_LIST_SLOT defines the content rendering area.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.gui.*;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemBuilder;
import xyz.xenondevs.invui.window.Window;
import java.util.List;
// Build two sub-GUIs used as tab content
Gui tab1Content = Gui.builder()
.setStructure("d d d d d d d d d")
.addIngredient('d', Item.simple(new ItemBuilder(Material.DIAMOND).setName("Diamonds")))
.build();
Gui tab2Content = Gui.builder()
.setStructure("g g g g g g g g g")
.addIngredient('g', Item.simple(new ItemBuilder(Material.GOLD_INGOT).setName("Gold")))
.build();
// Tab selector buttons
Item tab1Btn = Item.builder()
.setItemProvider(p -> new ItemBuilder(Material.DIAMOND).setName("Diamonds Tab"))
.addClickHandler((item, click) -> ((TabGui) click.gui()).setTab(0))
.build();
Item tab2Btn = Item.builder()
.setItemProvider(p -> new ItemBuilder(Material.GOLD_INGOT).setName("Gold Tab"))
.addClickHandler((item, click) -> ((TabGui) click.gui()).setTab(1))
.build();
Structure structure = new Structure(
"1 2 # # # # # # #",
"x x x x x x x x x",
"x x x x x x x x x",
"x x x x x x x x x"
)
.addIngredient('#', Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" ")))
.addIngredient('x', Markers.ITEM_LIST_SLOT)
.addIngredient('1', tab1Btn)
.addIngredient('2', tab2Btn);
TabGui gui = TabGui.builder()
.setStructure(structure)
.setTabs(List.of(tab1Content, tab2Content))
.addTabChangeHandler((from, to) -> System.out.println("Tab: " + from + " → " + to))
.build();
Window.builder()
.setTitle("Tabbed Menu")
.setGui(gui)
.setViewer(player)
.build()
.open();
```
--------------------------------
### Structure with Global and Per-Structure Ingredients
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Defines a reusable GUI structure using characters mapped to ingredients. Global ingredients are registered once with `Structure.addGlobalIngredient`, while per-structure ingredients are added using `addIngredient`.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.gui.Structure;
import xyz.xenondevs.invui.gui.Markers;
import xyz.xenondevs.invui.item.ItemBuilder;
// Register global ingredients once (e.g. in onEnable)
Structure.addGlobalIngredient('#', new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "));
Structure.addGlobalIngredient('x', Markers.ITEM_LIST_SLOT); // paged/scroll content slot
// Per-structure ingredients (page navigation buttons)
Structure structure = new Structure(
"# # # # # # # # #",
"# x x x x x x x #",
"# x x x x x x x #",
"# # # < # > # # #"
)
.addIngredient('<', () -> Item.builder() // supplier creates a new instance per slot
.setItemProvider(p -> new ItemBuilder(Material.RED_STAINED_GLASS_PANE).setName("◀ Back"))
.build())
.addIngredient('>', () -> Item.builder()
.setItemProvider(p -> new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE).setName("Forward ▶"))
.build());
```
--------------------------------
### Create GUI Manually
Source: https://github.com/nichtstudiocode/invui/wiki/InvUI-Basics
Manually create a SimpleGUI and set items using coordinates or slot indices. Structures can also be applied to manually created GUIs.
```java
// create the GUI
GUI gui = new SimpleGUI(9, 4);
// set items using x and y coordinates
gui.setItem(0, 0, item);
// set an item using the slot index
gui.setItem(10, item);
// use a Structure to add items (like in the GUI Builder)
Structure structure = new Structure("" +
"# # # # # # # # #" +
"# . . . . . . . #" +
"# . . . . . . . #" +
"# # # # # # # # #")
.addIngredient('#', item);
gui.applyStructure(structure);
```
--------------------------------
### Implement ScrollGui for Line-based Scrolling
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Use ScrollGui to arrange content in lines and allow player scrolling. Define scroll navigation items and use Markers.ITEM_LIST_SLOT for content placement. Requires setting up a Structure and binding it to content.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.gui.ScrollGui;
import xyz.xenondevs.invui.gui.Markers;
import xyz.xenondevs.invui.gui.Structure;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemBuilder;
import xyz.xenondevs.invui.window.Window;
import java.util.List;
List
- rows = List.of(
Item.simple(new ItemBuilder(Material.DIAMOND).setName("Row 1")),
Item.simple(new ItemBuilder(Material.GOLD_INGOT).setName("Row 2")),
Item.simple(new ItemBuilder(Material.EMERALD).setName("Row 3")),
Item.simple(new ItemBuilder(Material.REDSTONE).setName("Row 4")),
Item.simple(new ItemBuilder(Material.LAPIS_LAZULI).setName("Row 5"))
);
Item scrollUp = Item.builder()
.setItemProvider(p -> new ItemBuilder(Material.ARROW).setName("▲ Scroll Up"))
.addClickHandler((item, click) -> {
ScrollGui> scrollGui = (ScrollGui>) click.gui();
scrollGui.setLine(Math.max(0, scrollGui.getLine() - 1));
})
.build();
Item scrollDown = Item.builder()
.setItemProvider(p -> new ItemBuilder(Material.ARROW).setName("▼ Scroll Down"))
.addClickHandler((item, click) -> {
ScrollGui> scrollGui = (ScrollGui>) click.gui();
scrollGui.setLine(Math.min(scrollGui.getMaxLine(), scrollGui.getLine() + 1));
})
.build();
Structure structure = new Structure(
"^ x x x x x x x x",
"v x x x x x x x x"
)
.addIngredient('x', Markers.ITEM_LIST_SLOT)
.addIngredient('^', scrollUp)
.addIngredient('v', scrollDown);
ScrollGui
- gui = ScrollGui.itemsBuilder()
.setStructure(structure)
.setContent(rows)
.addScrollHandler((from, to) -> System.out.println("Scrolled: " + from + " → " + to))
.build();
Window.builder()
.setTitle("Scroll Menu")
.setGui(gui)
.setViewer(player)
.build()
.open();
```
--------------------------------
### Create GUI with GUIBuilder
Source: https://github.com/nichtstudiocode/invui/wiki/InvUI-Basics
Use GUIBuilder to define a GUI's type, dimensions, structure, and fill it with items. The structure string uses characters to represent different item types.
```java
GUI gui = new GUIBuilder<>(GUIType.NORMAL, 9, 4)
.setStructure("" +
"# # # # # # # # #" +
"# . . . . . . . #" +
"# . . . . . . . #" +
"# # # # # # # # #")
.addIngredient('#', new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE)))
.build();
```
--------------------------------
### Create an Embeddable, Event-Driven Inventory with VirtualInventory
Source: https://context7.com/nichtstudiocode/invui/llms.txt
VirtualInventory allows embedding inventories into GUIs with custom stack sizes and event handling. It supports serialization for persistence.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.gui.Structure;
import xyz.xenondevs.invui.inventory.VirtualInventory;
import xyz.xenondevs.invui.inventory.event.ItemPreUpdateEvent;
import xyz.xenondevs.invui.item.ItemBuilder;
import xyz.xenondevs.invui.window.Window;
// 9-slot virtual inventory with custom per-slot max stack sizes
int[] maxStackSizes = new int[9];
java.util.Arrays.fill(maxStackSizes, 16); // max 16 per slot
VirtualInventory inv = new VirtualInventory(maxStackSizes);
// Only allow players to place DIAMOND or EMERALD items
inv.addPreUpdateHandler((ItemPreUpdateEvent event) -> {
var newItem = event.getNewItem();
if (newItem != null
&& newItem.getType() != Material.DIAMOND
&& newItem.getType() != Material.EMERALD) {
event.setCancelled(true);
}
});
// Notify when the inventory changes
inv.addPostUpdateHandler(event ->
System.out.println("Slot " + event.getSlot() + " updated"));
// Embed into a GUI
Gui gui = Gui.builder()
.setStructure(
"# # # # # # # # #",
"# i i i i i i i i", // 'i' maps to the virtual inventory
"# # # # # # # # #"
)
.addIngredient('#', new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))
.build();
gui.setInventory('i', inv);
Window.builder()
.setTitle("Storage")
.setGui(gui)
.setViewer(player)
.build()
.open();
// Serialize / deserialize for persistence (e.g. to a database or file)
byte[] data = inv.serialize();
VirtualInventory loaded = VirtualInventory.deserialize(data);
```
--------------------------------
### Implement Slot Pop-In Animations
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Animations freeze the GUI while playing. Configure tick delay, slot selection patterns (e.g., horizontal snake), intermediary items, sound effects, and finish callbacks. Animations can be cancelled if needed.
```java
import org.bukkit.Material;
import org.bukkit.Sound;
import xyz.xenondevs.invui.gui.Animation;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.item.ItemBuilder;
Gui gui = Gui.builder()
.setStructure(
"a a a a a a a a a",
"a a a a a a a a a",
"a a a a a a a a a"
)
.addIngredient('a', Item.simple(new ItemBuilder(Material.DIAMOND)))
.build();
// Horizontal snake animation with a sound effect on each frame
Animation animation = Animation.builder()
.setTickDelay(2)
.setSlotSelector(() -> Animation.horizontalSnakeSlotSelector())
.setIntermediary(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "))
.addSoundEffect(Sound.BLOCK_NOTE_BLOCK_PLING, 1.0f, 1.5f)
.addFinishHandler(state -> System.out.println("Animation complete!"))
.build();
gui.playAnimation(animation);
// Cancel a running animation if needed
// gui.cancelAnimation();
```
--------------------------------
### Implement PagedGui for Paginated Item Display
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Use PagedGui to split content across multiple pages. Define navigation items and use Markers.ITEM_LIST_SLOT for content placement. Requires setting up a Structure and binding it to content.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.gui.PagedGui;
import xyz.xenondevs.invui.gui.Markers;
import xyz.xenondevs.invui.gui.Structure;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemBuilder;
import xyz.xenondevs.invui.window.Window;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Arrays;
// Build a list of items — one SimpleItem per non-air material
List
- items = Arrays.stream(Material.values())
.filter(m -> !m.isAir() && m.isItem())
.map(m -> Item.simple(new ItemBuilder(m)))
.collect(Collectors.toList());
// Page-navigation items that are aware of the paged GUI they are placed in
Item backItem = Item.builder()
.setItemProvider(p -> new ItemBuilder(Material.RED_STAINED_GLASS_PANE)
.setName("◀ Previous page"))
.addClickHandler((item, click) -> {
// obtain the bound paged gui from the click context
PagedGui> pagedGui = (PagedGui>) click.gui();
if (pagedGui.getPage() > 0) pagedGui.setPage(pagedGui.getPage() - 1);
})
.build();
Item forwardItem = Item.builder()
.setItemProvider(p -> new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE)
.setName("Next page ▶"))
.addClickHandler((item, click) -> {
PagedGui> pagedGui = (PagedGui>) click.gui();
if (pagedGui.getPage() < pagedGui.getPageCount() - 1)
pagedGui.setPage(pagedGui.getPage() + 1);
})
.build();
Structure structure = new Structure(
"# # # # # # # # #",
"# x x x x x x x #",
"# x x x x x x x #",
"# # # < # > # # #"
)
.addIngredient('#', Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" ")))
.addIngredient('x', Markers.ITEM_LIST_SLOT)
.addIngredient('<', backItem)
.addIngredient('>', forwardItem);
PagedGui
- gui = PagedGui.itemsBuilder()
.setStructure(structure)
.setContent(items)
.addPageChangeHandler((oldPage, newPage) ->
System.out.println("Page changed: " + oldPage + " → " + newPage))
.build();
Window.builder()
.setTitle("Item Browser — Page ")
.setGui(gui)
.setViewer(player)
.build()
.open();
```
--------------------------------
### Create and Manage GUI Windows
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Use Window.builder() for standard split GUIs or Window.mergedBuilder() for merged GUIs. Special window types like AnvilWindow have their own factories. You can dynamically update the window title after opening.
```java
import net.kyori.adventure.text.Component;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.window.Window;
import xyz.xenondevs.invui.window.AnvilWindow;
// Standard split window (chest-style, upper GUI + player hotbar below)
Window window = Window.builder()
.setTitle("Treasure Chest")
.setGui(gui)
.setViewer(player)
.addOpenHandler(() -> System.out.println(player.getName() + " opened the menu"))
.addCloseHandler(() -> System.out.println(player.getName() + " closed the menu"))
.build();
window.open();
// Change the title dynamically after opening
window.setTitle(Component.text("Updated Title"));
// Anvil window — upper GUI is a 3-slot (left, right, output); captures rename input
AnvilWindow anvilWindow = AnvilWindow.builder()
.setTitle("Search…")
.setUpperGui(Gui.empty(3, 1))
.setLowerGui(gui)
.setViewer(player)
.addRenameHandler(text -> System.out.println("Player typed: " + text))
.build();
anvilWindow.open();
```
--------------------------------
### Asynchronous Item Loading with Item.builder()
Source: https://context7.com/nichtstudiocode/invui/llms.txt
An item that displays a placeholder while its actual content is computed asynchronously in the background. This prevents the GUI from freezing during long computations.
```java
Item asyncItem = Item.builder()
.async(
new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE).setName("Loading…"),
() -> {
Thread.sleep(2000); // simulate heavy computation
return new ItemBuilder(Material.EMERALD).setName("Ready!");
})
.build();
```
--------------------------------
### Custom Clickable Item
Source: https://github.com/nichtstudiocode/invui/wiki/InvUI-Basics
Create a custom item by extending BaseItem. Implement getItemProvider for appearance and handleClick for interaction logic. Call notifyWindows() to update the displayed item.
```java
public class CountItem extends BaseItem {
private int count;
@Override
public ItemProvider getItemProvider() {
return new ItemBuilder(Material.DIAMOND).setDisplayName("Count: " + count);
}
@Override
public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) {
if (clickType.isLeftClick()) {
count++; // increment if left click
} else {
count--; // else decrement
}
notifyWindows(); // this will update the ItemStack that is displayed to the player
}
}
```
--------------------------------
### Maven Repository Configuration
Source: https://github.com/nichtstudiocode/invui/blob/main/README.md
Add this repository to your Maven project to access InvUI artifacts.
```xml
xenondevs
https://repo.xenondevs.xyz/releases
```
--------------------------------
### Localization with Languages
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Details the `Languages` singleton for server-side translation of item names and lore. It explains how to register translation maps for different locales and how `ItemBuilder` automatically resolves translatable keys based on the viewer's locale.
```APIDOC
## `Languages` — Built-in Localization
`Languages` is a singleton that enables server-side translation of `ItemBuilder` names and lore. Register translation maps (key → MiniMessage string) per `Locale`. `ItemBuilder` then resolves translatable keys at build time using the viewer's locale.
```java
import xyz.xenondevs.invui.i18n.Languages;
import xyz.xenondevs.invui.item.ItemBuilder;
import org.bukkit.Material;
import java.util.Locale;
import java.util.Map;
// Register translations in onEnable
Languages languages = Languages.getInstance();
languages.addLanguage(Locale.ENGLISH, Map.of(
"menu.title", "Main Menu",
"item.sword.name", "Firesword",
"item.sword.lore", "Burns enemies on hit"
));
languages.addLanguage(Locale.GERMAN, Map.of(
"menu.title", "Hauptmenü",
"item.sword.name", "Feuerschwert",
"item.sword.lore", "Setzt Feinde beim Treffen in Brand"
));
// ItemBuilder resolves keys automatically for the viewer's locale
ItemBuilder swordBuilder = new ItemBuilder(Material.DIAMOND_SWORD)
.setName("item.sword.name") // treated as a translation key (MiniMessage format)
.addLoreLines("item.sword.lore");
// When the window is opened, InvUI calls getItemProvider(player)
// which calls swordBuilder.get(player.locale()), resolving the correct translation
```
```
--------------------------------
### InvUI GUI Filling Methods
Source: https://github.com/nichtstudiocode/invui/wiki/GUIs
Utility methods for filling GUIs with items, other GUIs, or virtual inventories. The `replace` parameter determines if existing items are overwritten.
```java
gui.fill(item, replace);
// fills everything
```
```java
gui.fill(start, end, item, replace);
// fills from the start index to the end index
```
```java
gui.fillColumn(column, item, replace);
// fills a column
```
```java
gui.fillRow(row, item, replace);
// fills a row
```
```java
gui.fillBorders(item, replace);
// fill the borders
```
```java
gui.fillRectangle(x, y, width, height, item, replace);
// fills a rectangle with the an Item
```
```java
gui.fillRectangle(x, y, gui, replace);
// fills a rectangle with another GUI
```
```java
gui.fillRectangle(x, y, width, virtualInventory, replace);
// fills a rectangle with a VirtualInventory
```
--------------------------------
### Create a 'Forward' navigation item for PagedGUI
Source: https://github.com/nichtstudiocode/invui/wiki/Paged-GUI
Extends 'PageItem' to create a custom control for navigating to the next page. It uses a green stained glass pane and displays navigation information based on the current GUI state.
```java
public class ForwardItem extends PageItem {
public ForwardItem() {
super(true);
}
@Override
public ItemBuilder getItemProvider(PagedGUI gui) {
ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
builder.setDisplayName("§7Next page")
.addLoreLines(gui.hasNextPage()
? "§7Go to page §e" + (gui.getCurrentPageIndex() + 2) + "§7/§e" + gui.getPageAmount()
: "§cThere are no more pages");
return builder;
}
}
```
--------------------------------
### Create a 'Back' navigation item for PagedGUI
Source: https://github.com/nichtstudiocode/invui/wiki/Paged-GUI
Extends 'PageItem' to create a custom control for navigating to the previous page. It uses a red stained glass pane and displays navigation information based on the current GUI state.
```java
public class BackItem extends PageItem {
public BackItem() {
super(false);
}
@Override
public ItemBuilder getItemProvider(PagedGUI gui) {
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
builder.setDisplayName("§7Previous page")
.addLoreLines(gui.hasPageBefore()
? "§7Go to page §e" + gui.getCurrentPageIndex() + "§7/§e" + gui.getPageAmount()
: "§cYou can't go further back");
return builder;
}
}
```
--------------------------------
### Register Global Ingredients
Source: https://github.com/nichtstudiocode/invui/wiki/Structure
Register ingredients globally to reuse them across multiple structures. This is useful for common elements like background panes or navigation items.
```java
Structure.addGlobalIngredient('#', new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setDisplayName("§r"));
// These items need a supplier
Structure.addGlobalIngredient('<', BackItem::new);
Structure.addGlobalIngredient('>', ForwardItem::new);
// adding the Marker.ITEM_LIST_SLOT as a global ingredient is also a good idea
Structure.addGlobalIngredient('x', Marker.ITEM_LIST_SLOT);
```
--------------------------------
### Add InvUI Gradle Dependency
Source: https://github.com/nichtstudiocode/invui/wiki/Home
Configure your Gradle project with the XenonDevs repository and InvUI dependency.
```gradle
repositories {
maven { url = uri("https://repo.xenondevs.xyz/releases") }
}
dependencies {
implementation "de.studiocode.invui:InvUI:VERSION"
}
```
--------------------------------
### Gui.fillColumn
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Fills a specific column of the GUI with a specified item.
```APIDOC
## `Gui.fillColumn`
### Description
Fills an entire column of the GUI with the provided item.
### Method
`void fillColumn(int column, Object content)`
### Parameters
- **column** (int) - The index of the column to fill.
- **content** (Object) - The item or VirtualInventory to fill the column with.
### Request Example
```java
Gui gui = Gui.empty(9, 6);
Item border = Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "));
gui.fillColumn(0, border);
```
```
--------------------------------
### ItemBuilder with MiniMessage and Lore
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Constructs an item using `ItemBuilder`, supporting MiniMessage formatting for names and lore, enchantment glints, and custom data.
```java
import org.bukkit.Material;
import xyz.xenondevs.invui.item.ItemBuilder;
// Basic MiniMessage name + lore
ItemBuilder builder = new ItemBuilder(Material.NETHER_STAR)
.setName("Ultimate Sword")
.addLoreLines(
"Damage: +50",
"Speed: +10",
"",
"Click to equip"
)
.setGlint(true);
```
--------------------------------
### Add InvUI Maven Dependency
Source: https://github.com/nichtstudiocode/invui/wiki/Home
Include this repository and dependency in your Maven project to use InvUI.
```xml
xenondevs
https://repo.xenondevs.xyz/releases
de.studiocode.invui
InvUI
VERSION
```
--------------------------------
### InvUI GUI Background Item
Source: https://github.com/nichtstudiocode/invui/wiki/GUIs
Sets a background ItemProvider for a GUI. This background is displayed in slots that are otherwise empty, useful for paged GUIs.
```java
gui.setBackground(itemProvider);
```
--------------------------------
### Auto-cycling Item with Item.builder()
Source: https://context7.com/nichtstudiocode/invui/llms.txt
An item that automatically cycles between two states every 20 ticks (1 second).
```java
Item cyclingItem = Item.builder()
.setCyclingItemProvider(20,
new ItemBuilder(Material.RED_WOOL).setName("OFF"),
new ItemBuilder(Material.LIME_WOOL).setName("ON"))
.build();
```
--------------------------------
### Fill Row and Column
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Populates an entire row or column of the GUI with a specified item. Useful for creating structural elements or separators.
```java
gui.fillRow(0, border);
gui.fillColumn(0, border);
```
--------------------------------
### Implement ControlItem for PagedGUI
Source: https://github.com/nichtstudiocode/invui/wiki/Items
This ControlItem allows navigation through a PagedGUI. It handles left-clicks to go forward and right-clicks to go back. The displayed item updates automatically when the page changes.
```java
public class ChangePageItem extends ControlItem {
@Override
public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) {
if (clickType == ClickType.LEFT) {
getGui().goForward(); // go one page forward on left-click
} else if (clickType == ClickType.RIGHT) {
getGui().goBack(); // go one page back on right-click
}
}
@Override
public ItemProvider getItemProvider(PagedGUI gui) {
return new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE)
.setDisplayName("§7Current page: " + (gui.getCurrentPageIndex() + 1)) // + 1 because we don't want to have "Current page: 0"
.addLoreLines("§8Left-click to go forward", "§8Right-click to go back");
}
}
```
--------------------------------
### Fill GUI Borders
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Populates only the outer border slots of the GUI with a specified item. The `replaceExisting` parameter controls whether existing items in the border slots are overwritten.
```java
Item border = Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "));
gui.fillBorders(border, true);
```
--------------------------------
### Gui.fillRectangle
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Fills a specific rectangular region within the GUI.
```APIDOC
## `Gui.fillRectangle`
### Description
Fills a specified rectangular region within the GUI with a given item or inventory. The `replaceExisting` parameter determines if existing items in the region should be overwritten.
### Method
`void fillRectangle(int x, int y, int width, int height, Object content, boolean replaceExisting)`
### Parameters
- **x** (int) - The starting x-coordinate of the rectangle.
- **y** (int) - The starting y-coordinate of the rectangle.
- **width** (int) - The width of the rectangle.
- **height** (int) - The height of the rectangle.
- **content** (Object) - The item, VirtualInventory, or nested Gui to fill the region with.
- **replaceExisting** (boolean) - If true, existing items in the region will be replaced. If false, only empty slots will be filled.
### Request Example
```java
Gui gui = Gui.empty(9, 6);
Item highlight = Item.simple(new ItemBuilder(Material.YELLOW_STAINED_GLASS_PANE));
gui.fillRectangle(2, 1, 5, 4, highlight, false); // only fill empty slots
VirtualInventory inv = new VirtualInventory(5 * 4);
gui.fillRectangle(2, 1, 5, inv);
Gui innerGui = Gui.empty(3, 3);
gui.fillRectangle(3, 1, innerGui);
```
```
--------------------------------
### Gui.fillBorders
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Fills the borders of the GUI with a specified item, optionally preserving inner slots.
```APIDOC
## `Gui.fillBorders`
### Description
Fills the borders of the GUI with the provided item. The `replaceExisting` parameter controls whether existing items in the border slots are replaced.
### Method
`void fillBorders(Item item, boolean replaceExisting)`
### Parameters
- **item** (Item) - The item to fill the borders with.
- **replaceExisting** (boolean) - If true, existing items in border slots will be replaced. If false, only empty slots will be filled.
### Request Example
```java
Gui gui = Gui.empty(9, 6);
Item border = Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "));
gui.fillBorders(border, true);
```
```
--------------------------------
### Gui.fillRow
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Fills a specific row of the GUI with a specified item.
```APIDOC
## `Gui.fillRow`
### Description
Fills an entire row of the GUI with the provided item.
### Method
`void fillRow(int row, Object content)`
### Parameters
- **row** (int) - The index of the row to fill.
- **content** (Object) - The item or VirtualInventory to fill the row with.
### Request Example
```java
Gui gui = Gui.empty(9, 6);
Item border = Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setName(" "));
gui.fillRow(0, border);
```
```
--------------------------------
### InvUI Maven Dependency
Source: https://github.com/nichtstudiocode/invui/blob/main/README.md
Include this dependency in your project to use the InvUI library. Replace VERSION with the desired version.
```xml
xyz.xenondevs.invui
invui
VERSION
```
--------------------------------
### Embed Nested GUI
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Places a nested GUI within a specified rectangular region of the parent GUI. This allows for complex, hierarchical menu structures.
```java
Gui innerGui = Gui.empty(3, 3);
gui.fillRectangle(3, 1, innerGui);
```
--------------------------------
### Fill Rectangular Region
Source: https://context7.com/nichtstudiocode/invui/llms.txt
Fills a specified rectangular area within the GUI. The `replaceExisting` parameter determines if only empty slots are filled or if existing items are overwritten. This can be used with items or VirtualInventories.
```java
Item highlight = Item.simple(new ItemBuilder(Material.YELLOW_STAINED_GLASS_PANE));
gui.fillRectangle(2, 1, 5, 4, highlight, false); // only fill empty slots
```
```java
VirtualInventory inv = new VirtualInventory(5 * 4);
gui.fillRectangle(2, 1, 5, inv);
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.