Open GUI
The Open GUI Action creates and displays an inventory-based GUI with layout pools, advanced interactions, animations, and persistent storage.
Core Parameters
guiType — GuiType
Type of GUI to display. Choose from 23 supported types.
title
"> Title displayed at the top of the GUI. Supports MiniMessage, PlaceholderAPI, and CraftEngine tags.
size — InventorySize
Size of the inventory (only for CUSTOM type). Values: 9, 18, 27, 36, 45, 54.
Layout System
The layout pool defines reusable layout components referenced by ID.
layoutPool
">
Available layout definitions. Each layout has an id field. Types: simple, flex, paginated, scrollable, frame, composite, book, merchant.
mainLayoutId — String
ID of the layout to display from the pool. If omitted, an EmptyLayout is used.
baseMenuId — String
Optional open_gui template to inherit. Its layout pool and views are merged first; local ids override inherited ids, while mainLayoutId and size fall back to the template when omitted.
autoRefreshTicks — Long
Re-render the menu every N ticks while it is open. 0 disables automatic refresh.
views — List<MenuViewData>
Addressable screens rendered by the same menu shell. See Addressable Views.
defaultViewId — String?
Initial view id. When empty, the first visible declared view is selected.
breadcrumbSeparator — String
MiniMessage separator used by the {breadcrumb} title token.
pushHistoryOnViewSwitch — Boolean
When enabled, switching views pushes the previous view onto the gui:back history stack.
Layout Types
SimpleLayout — items placed at explicit (x, y) coordinates on a virtual grid. Each item uses x, y, count, direction, gap, and repeatY for positioning.
FlexLayout — auto-positioning with justifyContent (START, CENTER, END, SPACE_BETWEEN), alignItems (START, CENTER, END), and wrap.
PaginatedLayout — discrete pages with configurable itemsPerPage and a compact navigationButtons list. Each button defines a role (NEXT, PREVIOUS, or BACK) and its item.
ScrollableLayout — wraps an innerId layout with scroll support. Configurable virtualWidth, virtualHeight, custom scroll buttons, and showDefaultButtons. Scroll navigation buttons (UP/DOWN/LEFT/RIGHT) are separate from content and can be positioned independently.
FrameLayout — divides the screen into named frames. Each frame: id, x, y, width, height, layoutId. Frames can overlap with fixed-position scroll buttons.
CompositeLayout — layers multiple children layouts (by their IDs) on top of each other.
Addressable views
Use a frame shell with layoutId: "@view", then map that frame to a layout from each declared view. A slot tagged with buttonPrefix: "view:" and buttonType: "home" becomes a tab for the home view. View criteria and permissions hide inaccessible tabs and reject inaccessible targets.
views:
- id: home
name: "Home"
frames: { content: home_content }
- id: details
name: "Details"
parentId: home
frames: { content: details_content }
layoutPool:
- type: frame
id: shell
frames:
- { id: tabs, x: 0, y: 0, width: 9, height: 1, layoutId: tabs }
- { id: content, x: 0, y: 1, width: 9, height: 5, layoutId: "@view" }
- type: simple
id: tabs
items:
- { x: 2, y: 0, buttonPrefix: "view:", buttonType: home, item: { material: BOOK } }
- { x: 3, y: 0, buttonPrefix: "view:", buttonType: details, item: { material: PAPER } }
Use gui:view <id> from a slot command to switch explicitly. The active view and its ancestors receive their configured activeStyle.
BookLayout — renders pages as a written book with MiniMessage formatting.
MerchantLayout — defines trades with result, costOne, optional costTwo, maxUses, experienceReward, villagerExperience, priceMultiplier, and criteria (conditions per trade — hidden if not met).
Item Configuration (GuiItemData)
All items use XY grid positioning — no legacy index-based slots field.
x — Int
X coordinate (0-8) in the virtual slot grid. Required for all slots.
y — Int
Y coordinate (0-5) for 6-row inventories. Required for all slots.
count — Int
Number of slots to generate starting from (x, y), repeating in the configured direction.
direction — Direction
Direction of repetition for multiple slots. Options: RIGHT, DOWN, LEFT, UP.
gap — Int
Gap in slots between repetitions when count > 1.
repeatY — Int
Number of rows to repeat in 2D grid. When set, slots repeat horizontally first (via direction/count), then repeat vertically by this many rows.
item
">
The item to display. Use Item.Empty for the player's held item.
displayName
?" default="null"> Custom display name. Supports placeholders and MiniMessage.
lore
" default="[]"> Custom lore lines.
criteria
" default="[]"> Conditions for this item to appear. Evaluated at menu build time.
interactionList
" default="[]">
Click actions per interaction type (LEFT_CLICK, RIGHT_CLICK, SWAP_OFFHAND, etc.). Each entry: type, commands, triggers, closeMenu, executeReturn.
allowPickup — Boolean
Allow the player to take the item from the GUI.
isGhost — Boolean
Click copies the item to the cursor without removing it from the slot.
fill — Boolean
Fill all empty slots with this item configuration.
cooldownTicks — Long
Cooldown in ticks (50ms each) before the slot can be clicked again. 0 = disabled.
animation — SlotAnimationData?
Smooth movement animation: targetX, targetY, duration (ms), easing (linear, ease_in, ease_out).
input — InputData?
Dialog input configuration: title, placeholder, targetVar, onInputCommands, onInputTriggers.
triggers
" default="[]"> Triggers executed when the slot is clicked.
modifiers
" default="[]"> Fact modifiers applied on click.
Storage Slots
Slots can persist items across sessions by referencing a GUI Storage artifact.
storagePool — List<StorageSlotData>
Reusable storage configurations owned by the open_gui entry. Each configuration has a unique id.
storageId — String?
ID of the storagePool configuration used by this GUI item. When set, click interactions are handled by the storage system instead of interactionList.
Properties
entry
">
Reference to a GUI Storage artifact entry.
maxAmount — Int
Maximum item stack size in this slot (1-64).
forceStorage — Boolean
If true, non-stackable items (swords, tools, armor) can be stored in this slot.
temporary — Boolean
If true, stored items are lost when the menu closes. group
?" default="null"> Group entry for shared storage (e.g., island group). Without a group, storage is per-player (UUID). placeholder
?" default="AIR"> Item displayed when the slot is empty. requiredItem
?" default="null">
If set, only items matching this type can be deposited.
requiredAmount — Int
Amount needed to trigger onReachRequired. Enables accumulation mode.
onReachRequired
" default="[]"> Triggers fired when
requiredAmountis reached. consumeOnReach —Boolean
If true, deposited items are consumed when the threshold is met. onFill
" default="[]"> Triggers when the slot becomes non-empty. onEmpty
" default="[]"> Triggers when the slot becomes empty.
Automatic schema migration
OmniGUI automatically migrates public pages created with the former inline storage and pagination formats:
- inline
GuiItemData.storagebecomes a reusablestoragePoolitem referenced bystorageId; nextPage,previousPage, andbackButtonbecome role-basednavigationButtons;- both published pages and staging pages are handled;
- changed files are backed up under
plugins/Typewriter/backup/omnigui-schema-v2/; - writes are atomic and the migration is idempotent.
No manual page editing is required. New pages and subsequent editor writes use only the compact schema.
This migration is designed for public extension users: legacy serialized pages are accepted, backed up, normalized once, then kept on the compact schema. The legacy fields are compatibility input only; generated blueprints and newly saved pages should use storagePool, storageId, and navigationButtons.
For QuestCodex menus, prefer the referenced-menu pattern: keep category_menu entries small and move the heavy GUI layout into an open_gui entry referenced by category_menu.menu. This is the most publication-friendly shape for large quest books and tracked-quest menus.
Storage Placeholders
In storage slot displayName and lore, use these placeholders that resolve at render time:
| Placeholder | Description | Example |
|---|---|---|
{stored_name} | Display name of the stored item | Diamond |
{stored_amount} | Current item count | 42 |
{stored_max} | Maximum slot capacity | 64 |
Click Configuration
Storage click behaviors are globally configurable via GUI Settings. Default mappings:
| Action | Default Click |
|---|---|
| Place one item | LEFT |
| Place all from cursor | SHIFT_LEFT |
| Take one item | RIGHT |
| Take all from slot | SHIFT_RIGHT |
| Take one stack (64) | SWAP_OFFHAND |
| Fill from inventory | DOUBLE_CLICK |
| Drop all on ground | DROP |
Interaction Configuration
globalInteractions
" default="[]">
Menu-wide keybind handlers. Each entry: type (InteractionType), commands, triggers, closeMenu, executeReturn.
Interaction Types
LEFT_CLICK, RIGHT_CLICK, SHIFT_LEFT_CLICK, SHIFT_RIGHT_CLICK, MIDDLE_CLICK, DOUBLE_CLICK, NUMBER_KEY_1..9, DROP, DROP_ALL, SWAP_OFFHAND, SCROLL_UP, SCROLL_DOWN
Internal Commands
| Command | Effect |
|---|---|
gui:close | Close current menu |
gui:back | Return to previous menu |
gui:scroll <dx> <dy> [targetId] | Scroll viewport |
gui:scroll_up | Scroll up 1 row (shorthand) |
gui:scroll_down | Scroll down 1 row (shorthand) |
gui:scroll_left | Scroll left 1 column (shorthand) |
gui:scroll_right | Scroll right 1 column (shorthand) |
gui:page <delta> [layoutId] | Change paginated page |
gui:slider_set <index> | Update slider position |
gui:input | Open input dialog |
gui:open <entryId> | Open another menu |
gui:action <entryId> | Trigger another entry |
Audio
audio — GuiAudioData
Lifecycle sounds: onOpen, onClose, onScroll, onClick — each accepts Typewriter Sound objects.
Example: Shop Menu
action:
type: open_gui
id: "shop_main"
guiType: CUSTOM
size: "54"
title: "<bold><gold>Server Shop</gold></bold>"
mainLayoutId: "shop_flex"
layoutPool:
- type: "flex"
id: "shop_flex"
justifyContent: "CENTER"
alignItems: "CENTER"
wrap: true
items:
- x: 2
y: 2
item: { material: DIAMOND_SWORD }
displayName: "<aqua>Weapons"
interactionList:
- type: LEFT_CLICK
commands: ["shop open weapons"]
- x: 6
y: 2
item: { material: IRON_CHESTPLATE }
displayName: "<aqua>Armor"
interactionList:
- type: LEFT_CLICK
commands: ["shop open armor"]
globalInteractions:
- type: DROP
closeMenu: true
audio:
onOpen: { sound: "block.chest.open", volume: 1.0 }
onClose: { sound: "block.chest.close", volume: 1.0 }
Example: Scrollable Crate Menu
action:
type: open_gui
id: "crate_rewards"
guiType: CUSTOM
size: "54"
title: "<gold>Crate Rewards"
mainLayoutId: "reward_scroll"
layoutPool:
- type: "scrollable"
id: "reward_scroll"
virtualWidth: 9
virtualHeight: 12
showDefaultButtons: true
innerId: "reward_items"
- type: "simple"
id: "reward_items"
items:
- x: 0
y: 0
count: 9
direction: RIGHT
item: { material: DIAMOND }
displayName: "<aqua>Reward {index}"
interactionList:
- type: LEFT_CLICK
commands: ["give %player% diamond 1"]
Example: FrameLayout with Sidebar
action:
type: open_gui
id: "panel"
guiType: CUSTOM
size: "54"
title: "<dark_gray>Control Panel"
mainLayoutId: "panel_root"
layoutPool:
- type: "frame"
id: "panel_root"
frames:
- id: sidebar
x: 0; y: 0; width: 4; height: 6
layoutId: sidebar_items
- id: content
x: 5; y: 0; width: 4; height: 6
layoutId: content_items
- type: "simple"
id: "sidebar_items"
items:
- x: 0
y: 0
count: 4
direction: DOWN
item: { material: COMPASS }
displayName: "<green>Tab {index}"
interactionList:
- type: LEFT_CLICK
commands: ["menu switch tab_{index}"]
- type: "paginated"
id: "content_items"
itemsPerPage: 20
items:
- item: { material: PAPER }
displayName: "<yellow>Item {index}"