### Play Animations for Page Switching Source: https://docs.xenondevs.xyz/invui/gui This example demonstrates setting up navigation buttons to play animations when switching pages in a PagedGui. Disabling freezing allows page changes before animations complete. ```Kotlin val animation = Animation.builder() .setSlotSelector(Animation::horizontalSnakeSlotSelector) .filterTaggedSlots('x') .setFreezing(false) .build() val back: BoundItem = BoundItem.pagedBuilder() .setItemProvider(ItemBuilder(Material.ARROW)) .addClickHandler { _, gui, _ -> gui.cancelAnimation() gui.page-- gui.playAnimation(animation) } .build() val forward: BoundItem = BoundItem.pagedBuilder() .setItemProvider(ItemBuilder(Material.ARROW)) .addClickHandler { _, gui, _ -> gui.cancelAnimation() gui.page++ gui.playAnimation(animation) } .build() val allTheItemTypes: List = Material.entries .filter { !it.isLegacy && it.isItem } .map { Item.simple(ItemBuilder(it)) } val gui: PagedGui = PagedGui.itemsBuilder() .setStructure( "# # # # # # # # #", "# x x x x x x x #", "# x x x x x x x #", "# x x x x x x x #", "# # # < # > # # #", ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('<', back) .addIngredient('>', forward) .setContent(allTheItemTypes) .build() ``` ```Java Animation animation = Animation.builder() .setSlotSelector(Animation::horizontalSnakeSlotSelector) .filterTaggedSlots('x') .setFreezing(false) .build(); BoundItem back = BoundItem.pagedBuilder() .setItemProvider(new ItemBuilder(Material.ARROW)) .addClickHandler((item, gui, click) -> { gui.cancelAnimation(); gui.setPage(gui.getPage() - 1); gui.playAnimation(animation); }) .build(); BoundItem forward = BoundItem.pagedBuilder() .setItemProvider(new ItemBuilder(Material.ARROW)) .addClickHandler((item, gui, click) -> { gui.cancelAnimation(); gui.setPage(gui.getPage() + 1); gui.playAnimation(animation); }) .build(); List allTheItemTypes = Arrays.stream(Material.values()) .filter(m -> !m.isLegacy() && m.isItem()) .map(m -> Item.simple(new ItemBuilder(m))) .toList(); PagedGui gui = PagedGui.itemsBuilder() .setStructure( "# # # # # # # # #", "# 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))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('<', back) .addIngredient('>', forward) .setContent(allTheItemTypes) .build(); ``` -------------------------------- ### Create and Apply Ingredient Preset in Kotlin Source: https://docs.xenondevs.xyz/invui/gui Define an ingredient preset with custom ingredients and apply it to a GUI builder. This example creates a preset for pagination arrows. ```kotlin val preset: IngredientPreset = IngredientPreset.builder() .addIngredient( '>', BoundItem.pagedBuilder() .setItemProvider(ItemBuilder(Material.ARROW)) .addClickHandler { _, gui, _ -> gui.page++ } ) .addIngredient( '<', BoundItem.pagedBuilder() .setItemProvider(ItemBuilder(Material.ARROW)) .addClickHandler { _, gui, _ -> gui.page-- } ) .build() val gui: Gui = Gui.builder() .setStructure(/* ... */) .applyPreset(preset) .build() ``` -------------------------------- ### Anvil Window with Java Implementation Source: https://docs.xenondevs.xyz/invui/window Constructs and opens an Anvil Window using Java, similar to the Kotlin example. It sets up a paginated GUI and adds a handler to update content based on search input. ```java PagedGui gui = PagedGui.itemsBuilder() .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.CONTENT_LIST_SLOT_HORIZONTAL) .setContent(getItems("")) .build(); AnvilWindow.builder() .addRenameHandler(search -> gui.setContent(getItems(search))) .setLowerGui(gui) .open(player); ``` -------------------------------- ### Anvil Window with Reactive Menus (Kotlin DSL) Source: https://docs.xenondevs.xyz/invui/window An experimental approach using reactive menus to create an Anvil Window with dynamic content based on text input. This DSL simplifies the setup for reactive GUI elements. ```kotlin anvilWindow(player) { lowerGui by pagedItemsGui( "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" ) { 'x' by Markers.CONTENT_LIST_SLOT_HORIZONTAL content by this@anvilWindow.text.map { search -> Material.entries .filter { !it.isLegacy && it.isItem } .filter { it.name.contains(search, true) } .map { Item.simple(ItemBuilder(it)) } } } }.open() ``` -------------------------------- ### Register Global Ingredients in Kotlin Source: https://docs.xenondevs.xyz/invui/gui Register ingredients globally so they are automatically used by all GUI builders. This example shows how to register a content list slot marker and pagination arrows. ```kotlin Structure.addGlobalIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) Structure.addGlobalIngredient( '>', BoundItem.pagedBuilder() .setItemProvider(ItemBuilder(Material.ARROW)) .addClickHandler { _, gui, _ -> gui.page++ } ) Structure.addGlobalIngredient( '<', BoundItem.pagedBuilder() .setItemProvider(ItemBuilder(Material.ARROW)) .addClickHandler { _, gui, _ -> gui.page-- } ) ``` -------------------------------- ### Menu with Dynamic Bundle Select Handler (Kotlin) Source: https://docs.xenondevs.xyz/invui/item An example of a menu using a bundle item where selecting an item from the bundle updates a display item in the GUI. This showcases dynamic UI updates based on bundle interactions. ```kotlin val wools: List = Tag.WOOL.values.map(ItemStack::of) var selectedWool: Int = -1 val display: Item = Item.builder() .setItemProvider { wools.getOrNull(selectedWool)?.let(::ItemBuilder) ?: ItemProvider.EMPTY } .build() val bundleItem: Item = Item.builder() .setItemProvider( ItemBuilder(Material.BUNDLE).set( DataComponentTypes.BUNDLE_CONTENTS, BundleContents.bundleContents().addAll(wools).build() ) ) .addBundleSelectHandler { selectedSlot -> selectedWool = selectedSlot display.notifyWindows() } .build() Window.builder() .setUpperGui(Gui.builder() .setStructure("b # # # # # # # #") .addIngredient('b', bundleItem) .addIngredient('#', display) ) .setLowerGui(Gui.of(9, 4, display)) .open(player) ``` -------------------------------- ### Implement Trash Can with ItemPostUpdateEvent Source: https://docs.xenondevs.xyz/invui/inventory Use ItemPostUpdateEvent to perform actions after an inventory update. This example implements a trash can by clearing the item from slot 0, using UpdateReason.SUPPRESSED to prevent infinite loops. ```kotlin inv.addPostUpdateHandler { event -> event.inventory.setItem(UpdateReason.SUPPRESSED, 0, null) } ``` -------------------------------- ### Reactive Search Menu with AnvilWindow Source: https://docs.xenondevs.xyz/invui/reactive-menus Shows a reactive menu where the search input updates a provider, which in turn dynamically filters and displays a list of items. This example uses `addRenameHandler` to bind text input to a provider and `PagedGui.itemsBuilder` for menu structure. ```kotlin val search = mutableProvider("") AnvilWindow.builder() .addRenameHandler(search) // automatically writes text into search provider .setLowerGui(PagedGui.itemsBuilder() .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.CONTENT_LIST_SLOT_HORIZONTAL) .setContent(search.map { search -> // content updates based on search provider Material.entries .filter { !it.isLegacy && it.isItem } .filter { it.name.contains(search, true) } .map { Item.simple(ItemBuilder(it)) } }) ) .open(player) ``` -------------------------------- ### Merchant Window with Tabbed Trades (Java) Source: https://docs.xenondevs.xyz/invui/window Implements a MerchantWindow where trades function as tab buttons for a TabGui. This Java example configures the TabGui with wool items and uses click handlers to switch tabs. ```java List woolItems = Tag.WOOL.getValues().stream().map(ItemStack::of).toList(); TabGui tabGui = TabGui.builder() .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.CONTENT_LIST_SLOT_HORIZONTAL) .setTabs(woolItems.stream().map(it -> Gui.of(9, 4, Item.simple(it))).toList()) .build(); List trades = IntStream.range(0, woolItems.size()) .mapToObj(i -> { Item tabItem = Item.builder() .setItemProvider(woolItems.get(i)) .addClickHandler(click -> tabGui.setTab(i)) .build(); return MerchantWindow.Trade.builder() .setFirstInput(tabItem) .build(); }) .toList(); MerchantWindow.builder() .setLowerGui(tabGui) .setTrades(trades) .open(player); ``` -------------------------------- ### Embedding Another Player's Inventory as Lower GUI (Kotlin) Source: https://docs.xenondevs.xyz/invui/window Embeds another player's inventory into the lower GUI slot. This example demonstrates custom configuration for shift-clicking and double-clicking behavior. ```kotlin val inv = ReferencingInventory.fromPlayerStorageContents(otherPlayer.inventory) inv.reverseIterationOrder(OperationCategory.ADD) // shift-clicking moves to bottom right instead of top left inv.setGuiPriority(OperationCategory.ADD, Int.MAX_VALUE) // shift-click always moves between upper and lower inv inv.setGuiPriority(OperationCategory.COLLECT, Int.MIN_VALUE) // double-click collects from lower inv last Window.builder() .setUpperGui(Gui.empty(5, 1)) .setLowerGui(Gui.of(9, 4, inv)) .open(player) ``` -------------------------------- ### Implement Trash Can with ItemPostUpdateEvent (Java) Source: https://docs.xenondevs.xyz/invui/inventory Use ItemPostUpdateEvent to perform actions after an inventory update. This example implements a trash can by clearing the item from slot 0, using UpdateReason.SUPPRESSED to prevent infinite loops. ```java inv.addPostUpdateHandler(event -> { event.getInventory().setItem(UpdateReason.SUPPRESSED, 0, null); }); ``` -------------------------------- ### Get or Create Virtual Inventory with Manager (Kotlin) Source: https://docs.xenondevs.xyz/invui/inventory Retrieves an existing VirtualInventory or creates a new one using the VirtualInventoryManager. This is useful for managing persistent inventories across application restarts. ```kotlin val inv: VirtualInventory = VirtualInventoryManager.getInstance().getOrCreate(uuid, size) ``` -------------------------------- ### Embedding Another Player's Inventory as Lower GUI (Java) Source: https://docs.xenondevs.xyz/invui/window Embeds another player's inventory into the lower GUI slot using Java. This example mirrors the Kotlin version, configuring inventory interaction priorities. ```java var inv = ReferencingInventory.fromPlayerStorageContents(otherPlayer.inventory); inv.reverseIterationOrder(OperationCategory.ADD); // shift-clicking moves to bottom right instead of top left inv.setGuiPriority(OperationCategory.ADD, Integer.MAX_VALUE); // shift-click always moves between upper and lower inv inv.setGuiPriority(OperationCategory.COLLECT, Integer.MIN_VALUE); // double-click collects from lower inv last Window.builder() .setUpperGui(Gui.empty(5, 1)) .setLowerGui(Gui.of(9, 4, inv)) .open(player); ``` -------------------------------- ### Create a 'Hello World' Menu in InvUI (Java) Source: https://docs.xenondevs.xyz/invui/overview This snippet demonstrates creating a clickable item, organizing it within a GUI, and presenting it in a player-facing window. Clicking the item logs 'Hello World!' to the console. ```java Item helloWorldItem = Item.builder() .setItemProvider(new ItemBuilder(Material.DIAMOND)) // the item is represented by a diamond (ItemBuilder acts as ItemProvider) .addClickHandler(click -> System.out.println("Hello World!")) // "Hello World" is printed to the console on click .build(); Gui gui = Gui.builder() .setStructure("x x x x x x x x x") // the gui is of dimensions 9x1 and uses the item 'x' everywhere .addIngredient('x', helloWorldItem) // by item 'x', we mean helloWorldItem .build(); Window window = Window.builder() .setTitle("Hello World!") .setUpperGui(gui) .setViewer(player) .build(); window.open(); ``` -------------------------------- ### Create a 'Hello World' Menu in InvUI (Kotlin) Source: https://docs.xenondevs.xyz/invui/overview This snippet shows how to create a clickable item, arrange it in a GUI, and display it in a window for the player. The item prints 'Hello World!' to the console when clicked. ```kotlin val helloWorldItem: Item = Item.builder() .setItemProvider(ItemBuilder(Material.DIAMOND)) // the item is represented by a diamond (ItemBuilder acts as ItemProvider) .addClickHandler { println("Hello World!") } // "Hello World" is printed to the console on click .build() val gui: Gui = Gui.builder() .setStructure("x x x x x x x x x") // the gui is of dimensions 9x1 and uses the item 'x' everywhere .addIngredient('x', helloWorldItem) // by item 'x', we mean helloWorldItem .build() val window: Window = Window.builder() .setTitle("Hello World!") .setUpperGui(gui) .setViewer(player) .build() window.open() ``` -------------------------------- ### Create and Build a Virtual Inventory GUI (Kotlin) Source: https://docs.xenondevs.xyz/invui/inventory Demonstrates how to create a VirtualInventory and integrate it into a GUI structure using the builder pattern. This is suitable for most use cases requiring interactive inventories. ```kotlin val inv = VirtualInventory(7 * 4) val gui = Gui.builder() .setStructure( "# # # # # # # # #", "# x x x x x x x #", "# x x x x x x x #", "# x x x x x x x #", "# # # # # # # # #", ) .addIngredient('x', inv) .build() ``` -------------------------------- ### Create and Build a Virtual Inventory GUI (Java) Source: https://docs.xenondevs.xyz/invui/inventory Demonstrates how to create a VirtualInventory and integrate it into a GUI structure using the builder pattern. This is suitable for most use cases requiring interactive inventories. ```java var inv = new VirtualInventory(7 * 4); var gui = Gui.builder() .setStructure( "# # # # # # # # #", "# x x x x x x x #", "# x x x x x x x #", "# x x x x x x x #", "# # # # # # # # #" ) .addIngredient('x', inv) .build(); ``` -------------------------------- ### Reverse Iteration Order for Adding Items Source: https://docs.xenondevs.xyz/invui/inventory Modify the default iteration order for specific operations. This example reverses the order for adding items, making it process slots from last to first. ```Kotlin val inv = VirtualInventory(7 * 4) inv.reverseIterationOrder(OperationCategory.ADD) val gui = Gui.builder() .setStructure( "# # # # # # # # #", "# x x x x x x x #", "# x x x x x x x #", "# x x x x x x x #", "# # # # # # # # #", ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).hideTooltip(true))) .addIngredient('x', inv) .build() ``` ```Java var inv = new VirtualInventory(7 * 4); inv.reverseIterationOrder(OperationCategory.ADD); var gui = Gui.builder() .setStructure( "# # # # # # # # #", "# 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).hideTooltip(true))) .addIngredient('x', inv) .build(); ``` -------------------------------- ### Create a Simple Gui Source: https://docs.xenondevs.xyz/invui/gui Use Gui.builder() to create a basic Gui with a defined structure and ingredients. This is suitable for static layouts. ```kotlin val gui: Gui = Gui.builder() .setStructure( "# # # # # # # # #", "# x x x x x x x #", "# x x x x x x x #", "# x x x x x x x #", "# # # # # # # # #", ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .build() ``` -------------------------------- ### Create Normal Window with 9x6 Upper GUI Source: https://docs.xenondevs.xyz/invui/window Demonstrates creating a normal InvUI window with a custom 9x6 upper GUI structure. The lower GUI defaults to the player's inventory. ```kotlin Window.builder() .setTitle("Example Window") .setUpperGui(Gui.builder() .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 #", "# # # # # # # # #" ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).hideTooltip(true))) ) .open(player) ``` -------------------------------- ### Restrict Item Placement with ItemPreUpdateEvent Source: https://docs.xenondevs.xyz/invui/inventory Cancel ItemPreUpdateEvent to restrict which items can be placed in specific inventory slots. This example allows only red wool in slot 10 and orange wool in other slots. ```kotlin inv.addPreUpdateHandler { event -> if (event.isAdd || event.isSwap) { if (event.slot == 10) { event.isCancelled = event.newItem?.type != Material.RED_WOOL } else { event.isCancelled = event.newItem?.type != Material.ORANGE_WOOL } } } ``` -------------------------------- ### Get or Create Virtual Inventory with Manager (Java) Source: https://docs.xenondevs.xyz/invui/inventory Retrieves an existing VirtualInventory or creates a new one using the VirtualInventoryManager. This is useful for managing persistent inventories across application restarts. ```java VirtualInventory inv = VirtualInventoryManager.getInstance().getOrCreate(uuid, size); ``` -------------------------------- ### Create a Simple Gui (Java) Source: https://docs.xenondevs.xyz/invui/gui Use Gui.builder() to create a basic Gui with a defined structure and ingredients. This is suitable for static layouts. ```java Gui gui = Gui.builder() .setStructure( "# # # # # # # # #", "# 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))) .build(); ``` -------------------------------- ### Build a TabGui with Tabs Source: https://docs.xenondevs.xyz/invui/gui Constructs a TabGui instance, defining its structure, ingredients, tab buttons, and the GUIs that will serve as tabs. Requires pre-defined tab buttons and tab GUIs. ```Kotlin val gui: TabGui = TabGui.builder() .setStructure( "# # # 0 # 1 # # #", "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('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('0', tab0Btn) .addIngredient('1', tab1Btn) .setTabs(listOf(tab0, tab1)) .build() ``` -------------------------------- ### Restrict Item Placement with ItemPreUpdateEvent (Java) Source: https://docs.xenondevs.xyz/invui/inventory Cancel ItemPreUpdateEvent to restrict which items can be placed in specific inventory slots. This example allows only red wool in slot 10 and orange wool in other slots. ```java inv.addPreUpdateHandler(event -> { if (event.isAdd() || event.isSwap()) { if (event.getSlot() == 10) { event.setCancelled(event.getNewItem().getType() != Material.RED_WOOL); } else { event.setCancelled(event.getNewItem().getType() != Material.ORANGE_WOOL); } } }); ``` -------------------------------- ### Reactive Menu with InvUI DSL Source: https://docs.xenondevs.xyz/invui/reactive-menus Illustrates creating a reactive menu using InvUI's DSL, which simplifies window and GUI creation. The `lowerGui` is defined using `pagedItemsGui`, and its content is reactively updated based on a `text` provider. ```kotlin anvilWindow(player) { lowerGui by pagedItemsGui( "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" ) { 'x' by Markers.CONTENT_LIST_SLOT_HORIZONTAL content by text.map { search -> Material.entries .filter { !it.isLegacy && it.isItem } .filter { it.name.contains(search, true) } .map { Item.simple(ItemBuilder(it)) } } } }.open() ``` -------------------------------- ### Build a TabGui with Tabs (Java) Source: https://docs.xenondevs.xyz/invui/gui Constructs a TabGui instance in Java, defining its structure, ingredients, tab buttons, and the GUIs that will serve as tabs. Requires pre-defined tab buttons and tab GUIs. ```Java TabGui gui = TabGui.builder() .setStructure( "# # # 0 # 1 # # #", "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('#', Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('0', tab0Btn) .addIngredient('1', tab1Btn) .setTabs(List.of(tab0, tab1)) .build(); ``` -------------------------------- ### Create and Apply Ingredient Preset in Java Source: https://docs.xenondevs.xyz/invui/gui Create an ingredient preset in Java and apply it to a GUI builder. This preset includes pagination arrows for navigation. ```java IngredientPreset preset = IngredientPreset.builder() .addIngredient( '>', BoundItem.pagedBuilder() .setItemProvider(new ItemBuilder(Material.ARROW)) .addClickHandler((item, gui, click) -> gui.setPage(gui.getPage() + 1)) ) .addIngredient( '<', BoundItem.pagedBuilder() .setItemProvider(new ItemBuilder(Material.ARROW)) .addClickHandler((item, gui, click) -> gui.setPage(gui.getPage() - 1)) ) .build(); Gui gui = Gui.builder() .setStructure(/* ... */) .applyPreset(preset) .build(); ``` -------------------------------- ### Prepare Content for GUI in Kotlin Source: https://docs.xenondevs.xyz/invui/gui Generates a list of simple items from all available material types that are valid items and not legacy. Requires `Material`, `Item`, and `ItemBuilder`. ```kotlin val allTheItemTypes: List = Material.entries .filter { !it.isLegacy && it.isItem } .map { Item.simple(ItemBuilder(it)) } ``` -------------------------------- ### Modify Hotbar Key Actions with InventoryClickEvent Source: https://docs.xenondevs.xyz/invui/inventory Intercept player clicks using InventoryClickEvent to customize behavior. This example changes number key presses to modify item amounts instead of moving items to hotbar slots. ```kotlin inv.addClickHandler { event -> if (event.clickType == ClickType.NUMBER_KEY) { event.isCancelled = true val newItem = event.inventory.getItem(event.slot)?.apply { amount = event.hotbarButton + 1 } event.inventory.setItem(null, event.slot, newItem) } } ``` -------------------------------- ### Build a ScrollGui with Content (Java) Source: https://docs.xenondevs.xyz/invui/gui Constructs a ScrollGui instance in Java, defining its structure, ingredients, and scrollable content. Requires pre-defined scroll buttons. ```Java List allTheItemTypes = Arrays.stream(Material.values()) .filter(m -> !m.isLegacy() && m.isItem()) .map(m -> Item.simple(new ItemBuilder(m))) .toList(); ScrollGui gui = ScrollGui.itemsBuilder() .setStructure( "# # x x x x x x #", "u # x x x x x x #", "# # x x x x x x #", "d # x x x x x x #", "# # x x x x x x #" ) .addIngredient('#', Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('u', up) .addIngredient('d', down) .setContent(allTheItemTypes) .build(); ``` -------------------------------- ### Build a ScrollGui with Content Source: https://docs.xenondevs.xyz/invui/gui Constructs a ScrollGui instance, defining its structure, ingredients, and scrollable content. Requires pre-defined scroll buttons. ```Kotlin val allTheItemTypes: List = Material.entries .filter { !it.isLegacy && it.isItem } .map { Item.simple(ItemBuilder(it)) } val gui: ScrollGui = ScrollGui.itemsBuilder() .setStructure( "# # x x x x x x #", "u # x x x x x x #", "# # x x x x x x #", "d # x x x x x x #", "# # x x x x x x #", ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('u', up) .addIngredient('d', down) .setContent(allTheItemTypes) .build() ``` -------------------------------- ### Modify Hotbar Key Actions with InventoryClickEvent (Java) Source: https://docs.xenondevs.xyz/invui/inventory Intercept player clicks using InventoryClickEvent to customize behavior. This example changes number key presses to modify item amounts instead of moving items to hotbar slots. ```java inv.addClickHandler(event -> { if (event.getClickType() == ClickType.NUMBER_KEY) { event.setCancelled(true); var newItem = event.getInventory().getItem(event.getSlot()); if (newItem != null) newItem.setAmount(event.getHotbarButton() + 1); event.getInventory().setItem(null, event.getSlot(), newItem); } }); ``` -------------------------------- ### Create a Paged Gui with Items Source: https://docs.xenondevs.xyz/invui/gui Build a PagedGui to display a list of items across multiple pages. Use Markers.CONTENT_LIST_SLOT_HORIZONTAL to define where page content should be placed. ```kotlin val allTheItemTypes: List = Material.entries .filter { !it.isLegacy && it.isItem } .map { Item.simple(ItemBuilder(it)) } val gui: PagedGui = PagedGui.itemsBuilder() .setStructure( "# # # # # # # # #", "# x x x x x x x #", "# x x x x x x x #", "# x x x x x x x #", "# # # < # > # # #", ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('<', back) .addIngredient('>', forward) .setContent(allTheItemTypes) .build() ``` -------------------------------- ### Create Normal Window with 9x6 Upper GUI (Java) Source: https://docs.xenondevs.xyz/invui/window Java version of creating a normal InvUI window with a custom 9x6 upper GUI structure. The lower GUI defaults to the player's inventory. ```java Window.builder() .setTitle("Example Window") .setUpperGui(Gui.builder() .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 #", "# # # # # # # # #" ) .addIngredient('#', Item.simple(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).hideTooltip(true))) ) .open(player); ``` -------------------------------- ### Re-using Bound Item Builders for Multiple Guis (Java) Source: https://docs.xenondevs.xyz/invui/item Illustrates the correct way to add bound items to global ingredients in Java. Always provide the BoundItem.Builder to ensure a new instance is created for each usage, rather than reusing a single built instance. ```Java BoundItem.Builder boundItemBuilder = BoundItem.builder() /* ... */ // DO NOT DO THIS // 'x' will always be the same BoundItem instance Structure.addGlobalIngredient('x', boundItemBuilder.build()); // DO THIS INSTEAD // 'x' will be a new BoundItem instance, built from boundItemBuilder, every time Structure.addGlobalIngredient('x', boundItemBuilder); ``` -------------------------------- ### Basic Provider Transformation Source: https://docs.xenondevs.xyz/invui/reactive-menus Demonstrates how to create a derived provider (`p1`) from a mutable provider (`p`) and observe its updates. The derived provider automatically reflects changes made to the original provider. ```kotlin val p = mutableProvider(1) val p1 = p.map { it + 1 } println(p1.get()) // 2 p1.set(2) println(p1.get()) // 3 ``` -------------------------------- ### Create a Paged Gui with Items (Java) Source: https://docs.xenondevs.xyz/invui/gui Build a PagedGui to display a list of items across multiple pages. Use Markers.CONTENT_LIST_SLOT_HORIZONTAL to define where page content should be placed. ```java List allTheItemTypes = Arrays.stream(Material.values()) .filter(m -> !m.isLegacy() && m.isItem()) .map(m -> Item.simple(new ItemBuilder(m))) .toList(); PagedGui gui = PagedGui.itemsBuilder() .setStructure( "# # # # # # # # #", "# 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))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('<', back) .addIngredient('>', forward) .setContent(allTheItemTypes) .build(); ``` -------------------------------- ### Crafting Window Suggesting Diamond Hoe Source: https://docs.xenondevs.xyz/invui/window Opens a CraftingWindow that ignores the recipe clicked in the recipe book and always suggests a diamond hoe. ```Kotlin CraftingWindow.builder() .setCraftingGui(Gui.of(3, 3, VirtualInventory(9))) .addModifier { w -> w.addRecipeClickHandler { w.sendGhostRecipe(Key.key("minecraft:diamond_hoe")) } } .open(player) ``` -------------------------------- ### Create Merged Window with Custom GUI Source: https://docs.xenondevs.xyz/invui/window Demonstrates creating a merged InvUI window where a single GUI definition is used for both upper and lower inventory sections. This is useful for unified inventory layouts. ```kotlin Window.mergedBuilder() .setTitle("Example Window") .setGui(Gui.builder() .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 x x x x x x #", "# x x x x x x x #", "# x x x x x x x #", "# # # # # # # # #" ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).hideTooltip(true))) ) .open(player) ``` -------------------------------- ### Create a Simple Clickable Item Source: https://docs.xenondevs.xyz/invui/item This snippet demonstrates how to create a basic item with a visual representation and a click handler that prints a message to the console. ```Kotlin val item = Item.builder() .setItemProvider(ItemBuilder(Material.DIAMOND)) // the item is represented by a diamond .addClickHandler { item, click -> println("Hello World!") } // "Hello World" is printed to the console on click .build() ``` -------------------------------- ### Creating a Bound Item with Bind and Click Handlers (Java) Source: https://docs.xenondevs.xyz/invui/item This snippet demonstrates how to create a BoundItem in Java, adding custom logic for when the item is bound to a GUI and when it is clicked. ```Java BoundItem boundItem = BoundItem.builder() .addBindHandler((item, gui) -> { /* ... */ }) .addClickHandler((item, gui, click) -> { /* ...*/}) .build(); ``` -------------------------------- ### Create a Simple Clickable Item (Java) Source: https://docs.xenondevs.xyz/invui/item This Java snippet demonstrates how to create a basic item with a visual representation and a click handler that prints a message to the console. ```Java Item item = Item.builder() .setItemProvider(new ItemBuilder(Material.DIAMOND)) // the item is represented by a diamond .addClickHandler(click -> System.out.println("Hello World!")) // "Hello World" is printed to the console on click .build(); ``` -------------------------------- ### Register Bundle Select Handler (Kotlin) Source: https://docs.xenondevs.xyz/invui/item Demonstrates how to create a bundle item and register a handler for when a slot within the bundle is selected. This is useful for custom inventory logic. ```kotlin val bundleItem: Item = Item.builder() .setItemProvider( ItemBuilder(Material.BUNDLE).set( DataComponentTypes.BUNDLE_CONTENTS, BundleContents.bundleContents().addAll(/* ... */).build() ) ) .addBundleSelectHandler { println("Slot selected: $it") } .build() ``` -------------------------------- ### Crafting Window Suggesting Diamond Hoe (Java) Source: https://docs.xenondevs.xyz/invui/window Opens a CraftingWindow that ignores the recipe clicked in the recipe book and always suggests a diamond hoe. ```Java CraftingWindow.builder() .setCraftingGui(Gui.of(3, 3, new VirtualInventory(9))) .addModifier(w -> w.addRecipeClickHandler(key -> w.sendGhostRecipe(Key.key("minecraft:diamond_hoe")))) .open(player); ``` -------------------------------- ### Anvil Window with Kotlin DSL Search Source: https://docs.xenondevs.xyz/invui/window Creates an Anvil Window that filters items based on user search input in real-time. Requires the 'getItems' function to be defined. ```kotlin fun getItems(search: String): List = Material.entries .filter { !it.isLegacy && it.isItem } .filter { it.name.contains(search, true) } .map { Item.simple(ItemBuilder(it)) } val gui: PagedGui = PagedGui.itemsBuilder() .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.CONTENT_LIST_SLOT_HORIZONTAL) .setContent(getItems("")) .build() AnvilWindow.builder() .addRenameHandler { search -> gui.setContent(getItems(search)) } .setLowerGui(gui) .open(player) ``` -------------------------------- ### Register Global Ingredients in Java Source: https://docs.xenondevs.xyz/invui/gui Register ingredients globally in Java for automatic use across GUI builders. Includes a content list slot marker and pagination arrows. ```java Structure.addGlobalIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL); Structure.addGlobalIngredient( '>', BoundItem.pagedBuilder() .setItemProvider(new ItemBuilder(Material.ARROW)) .addClickHandler((item, gui, click) -> gui.setPage(gui.getPage() + 1)) ); Structure.addGlobalIngredient( '<', BoundItem.pagedBuilder() .setItemProvider(new ItemBuilder(Material.ARROW)) .addClickHandler((item, gui, click) -> gui.setPage(gui.getPage() - 1)) ); ``` -------------------------------- ### Re-using Bound Item Builders for Multiple Guis (Kotlin) Source: https://docs.xenondevs.xyz/invui/item Illustrates the correct way to add bound items to global ingredients in Kotlin. Always provide the BoundItem.Builder to ensure a new instance is created for each usage, rather than reusing a single built instance. ```Kotlin val boundItemBuilder = BoundItem.builder() /* ... */ // DO NOT DO THIS // 'x' will always be the same BoundItem instance Structure.addGlobalIngredient('x', boundItemBuilder.build()) // DO THIS INSTEAD // 'x' will be a new BoundItem instance, built from boundItemBuilder, every time Structure.addGlobalIngredient('x', boundItemBuilder) ``` -------------------------------- ### Merchant Window with Tabbed Trades (Experimental Reactive Menus - Kotlin DSL) Source: https://docs.xenondevs.xyz/invui/window An experimental approach using reactive menus to create a MerchantWindow where trades act as tab buttons for a TabGui. A mutable provider `tab` is used to control the active tab index. ```kotlin merchantWindow(player) { val woolItems = Tag.WOOL.values.map(ItemStack::of) val tab = mutableProvider(0) lowerGui by tabGui( "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" ) { 'x' by Markers.CONTENT_LIST_SLOT_HORIZONTAL tabs by woolItems.map { Gui.of(9, 4, Item.simple(it)) } this.tab by tab } trades by woolItems.mapIndexed { i, wool -> trade { firstInput by item { itemProvider by ItemBuilder(wool) onClick { tab.set(i) } } } } }.open() ``` -------------------------------- ### Register Bundle Select Handler (Java) Source: https://docs.xenondevs.xyz/invui/item Shows the Java equivalent for creating a bundle item and attaching a listener to handle slot selections within the bundle. This enables custom interactions. ```java Item bundleItem = Item.builder() .setItemProvider( new ItemBuilder(Material.BUNDLE).set( DataComponentTypes.BUNDLE_CONTENTS, BundleContents.bundleContents().addAll(/* ... */).build() ) ) .addBundleSelectHandler(selectedSlot -> System.out.println("Slot selected: " + selectedSlot)) .build() ``` -------------------------------- ### Create Paged GUI with Structure and Content in Kotlin Source: https://docs.xenondevs.xyz/invui/gui Builds a paged GUI with a defined structure, including navigation buttons and content slots. Requires `PagedGui`, `Item`, `ItemBuilder`, `Material`, `BoundItem`, and `Markers`. ```kotlin val tab0: PagedGui = PagedGui.itemsBuilder() .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", "# # # < # > # # #", ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('<', back) .addIngredient('>', forward) .setContent(allTheItemTypes) .build() ``` -------------------------------- ### Paper Plugin Loader Configuration Source: https://docs.xenondevs.xyz/invui1 Configure a custom PluginLoader for Paper to manage InvUI's library loading, ensuring compatibility with Paper's Mojang-mapped runtime. ```java public class MyPluginLoader implements PluginLoader { @Override public void classloader(@NotNull PluginClasspathBuilder pluginClasspathBuilder) { MavenLibraryResolver resolver = new MavenLibraryResolver(); resolver.addRepository(new RemoteRepository.Builder("xenondevs", "default", "https://repo.xenondevs.xyz/releases/").build()); resolver.addDependency(new Dependency(new DefaultArtifact("xyz.xenondevs.invui:invui:pom:VERSION"), null)); pluginClasspathBuilder.addLibrary(resolver); } } ``` -------------------------------- ### Creating a Bound Item with Bind and Click Handlers Source: https://docs.xenondevs.xyz/invui/item This snippet demonstrates how to create a BoundItem in Kotlin, adding custom logic for when the item is bound to a GUI and when it is clicked. ```Kotlin val boundItem: BoundItem = BoundItem.builder() .addBindHandler { item, gui -> /* ... */ } .addClickHandler { item, gui, click -> /* ... */ } .build() ``` -------------------------------- ### Create Scrollable GUI with Structure and Content in Kotlin Source: https://docs.xenondevs.xyz/invui/gui Builds a scrollable GUI with a defined structure, including scroll buttons and content slots. Requires `ScrollGui`, `Item`, `ItemBuilder`, `Material`, `BoundItem`, and `Markers`. ```kotlin val tab1: ScrollGui = ScrollGui.itemsBuilder() .setStructure( "u # x x x x x x #", "# # x x x x x x #", "# # x x x x x x #", "d # x x x x x x #", ) .addIngredient('#', Item.simple(ItemBuilder(Material.BLACK_STAINED_GLASS_PANE))) .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) .addIngredient('u', up) .addIngredient('d', down) .setContent(allTheItemTypes) .build() ``` -------------------------------- ### Stonecutter Window with Inventory Buttons (Java) Source: https://docs.xenondevs.xyz/invui/window Java implementation using 'VirtualInventory' for the buttons GUI in a Stonecutter Window. This is experimental and may not be practical due to scroll bar resets. ```Java StonecutterWindow.builder() .setButtonsGui(Gui.of(4, 100, new VirtualInventory(400))) .addModifier(w -> w.addSelectedSlotChangeHandler((from, to) -> { if (to != -1) w.setSelectedSlot(-1); })) .open(player); ``` -------------------------------- ### Menu with Dynamic Bundle Select Handler (Java) Source: https://docs.xenondevs.xyz/invui/item The Java implementation of a menu featuring a bundle item. Selecting an item from the bundle dynamically updates a separate display item, demonstrating interactive GUI elements. ```java List wools = Tag.WOOL.getValues().stream().map(ItemStack::of).toList(); AtomicInteger selectedWool = new AtomicInteger(-1); Item display = Item.builder() .setItemProvider(p -> { if (selectedWool.get() >= 0 && selectedWool.get() < wools.size()) { return new ItemWrapper(wools.get(selectedWool.get())); } else { return ItemProvider.EMPTY; } }) .build(); Item bundleItem = Item.builder() .setItemProvider( new ItemBuilder(Material.BUNDLE).set( DataComponentTypes.BUNDLE_CONTENTS, BundleContents.bundleContents().addAll(wools).build() ) ) .addBundleSelectHandler(selectedSlot -> { selectedWool.set(selectedSlot); display.notifyWindows(); }) .build(); Window.builder() .setUpperGui(Gui.builder() .setStructure("b # # # # # # # #") .addIngredient('b', bundleItem) .addIngredient('#', display) ) .setLowerGui(Gui.of(9, 4, display)) .open(player); ``` -------------------------------- ### Stonecutter Window with Tabbed Buttons (Kotlin Reactive Menus) Source: https://docs.xenondevs.xyz/invui/window Experimental DSL for Stonecutter Window that combines tab and selected slot properties, automatically synchronizing them. Requires the 'Markers' component. ```Kotlin stonecutterWindow(player) { val woolTypes = Tag.ITEMS_WOOL.values.sortedBy { it.ordinal } lowerGui by tabGui( "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" ) { 'x' by Markers.CONTENT_LIST_SLOT_HORIZONTAL tabs by woolTypes.map { Gui.of(9, 4, Item.simple(ItemStack.of(it))) } tab by selectedSlot } buttonsGui by Gui.empty(4, Math.ceilDiv(woolTypes.size, 4)).also { gui -> for (i in woolTypes.indices) { gui[i] = Item.simple(ItemStack.of(woolTypes[i])) } } }.open() ``` -------------------------------- ### Create Item with Translatable Name and Placeholder Source: https://docs.xenondevs.xyz/invui/localization Builds an item with a translatable name and a placeholder that can be filled by the ItemBuilder. ```kotlin val itemBuilder = ItemBuilder(Material.DIAMOND) .setName(Component.translatable("invui.example_window.btn.name", Component.text("A"))) .setPlaceholder("placeholder", Component.text("B")) ```