Skip to main content

GUI

Inventory menus built in the web panel: layouts, items, click actions, storage and leaderboards.

Freev0.20Menus & visuals
RequiresTypeWriter0.9PacketEventsCraftEngineoptional

Overview​

GUI turns a single TypeWriter entry, Open GUI, into a complete inventory menu. You choose the container type (a chest, an anvil, a merchant window, a written book...), write a title in MiniMessage, then describe the content as a tree of layouts stored in the entry's layoutPool. Each layout places items: a material, a name, some lore, and what happens when a player clicks it.

Everything is edited in the web panel: there are no menu files to write by hand. A menu is opened like any other action, from a quest step, an NPC dialogue, a command event or another menu. Clicks run console commands, trigger other entries and modify facts, so a menu is just another way to drive your TypeWriter pages.

GUI is also the foundation of the other BTC menu extensions. Shops and Quest Codex do not ship their own window: they place marker items in an open_gui layout and the extension fills them with products or quests.

Features​

  • Ten layouts — simple, flex, paginated, scrollable, frame, composite, book, merchant, storage and leaderboard.
  • 24 container types — chest sizes from 9 to 54 slots, plus anvil, enchanting table, smithing table, stonecutter, grindstone, loom, cartography table, merchant, book, hopper, furnaces and more.
  • MiniMessage everywhere — colours, gradients and PlaceholderAPI placeholders in titles, item names and lore.
  • Click actions per click type — left, right, shift, middle, double click, number keys, drop and offhand swap, each with its own commands and triggers.
  • Slot permissions — hide a slot with viewPermission or leave it visible but inert with clickPermission.
  • Slot repetition — fill a row or a block with count, direction, gap and repeatY instead of copying items.
  • Views and tabs — one menu shell, several screens, with a breadcrumb title and tabs that light up.
  • Persistent storage — slots that keep their items per player or per group, with quotas, placeholders and optional drop on close.
  • Leaderboards — rank players, worlds or groups on one or more facts, including offline players, or show the rows another extension supplies through the source field (the statistics of Dungeon, for example).
  • Extended inventory — turn the player's own inventory into four extra menu rows for a ten-row canvas.

Installation​

  1. Install TypeWriter on a Paper or Folia server. PacketEvents, which TypeWriter already requires, must be present.
  2. Download the JAR from the GUI GitHub releases (the button in the summary panel above).
  3. Put it in plugins/Typewriter/extensions/ and restart the server.
  4. Optional: install CraftEngine if your titles use <image> or <shift> tags to draw custom backgrounds.

Install GUI before the extensions that rely on it, such as Shops and Quest Codex.

Web editor

The public GUI release does not include a standalone menu editor or its web server: menus are edited in the TypeWriter web panel. The release only ships a startup check that reads your published open_gui entries and reports broken menus in the console (see Troubleshooting).

Getting started​

Build a small three-button menu:

  1. In the web panel, open a sequence page and add an Open GUI entry. Name it main_menu.
  2. Set guiType to CUSTOM, size to SIZE_27 and title to <gold>Main menu.
  3. In layoutPool, add a layout of type simple, give it the id main, then type main in mainLayoutId.
  4. In the layout items, add an item at x 4, y 1. Pick a DIAMOND in item, set displayName to <aqua>Rewards and add a lore line <gray>Click to claim.
  5. In interactionList, add an interaction with type LEFT_CLICK. Add a console command such as give %player% diamond 1 to commands, or link an entry in triggers. Enable closeMenu to close the menu after the click.
  6. Add a second simple item with count 9, direction right and a gray stained glass pane to draw a border row. Set its displayName to a single space.
  7. Link the Open GUI entry to something that fires it, for example the trigger of a dialogue option or a command event, then Publish.
Start simple

Get a single simple layout working in game before you add frame, scrollable or paginated layers. Every layout is addressed by its id, so a mistyped mainLayoutId is the first thing to check when a menu opens empty.

How it works​

When the action fires, the extension builds the layout tree for that player (criteria and permissions are evaluated at this moment), registers a menu session and shows the inventory. Each click is resolved against the slot at that position, then runs the matching interaction. The session remembers previous menus, so gui:back returns to the menu the player came from.

Container types​

guiType selects the window. CUSTOM is a plain chest-like inventory whose height you choose with size. size only applies to CUSTOM and defaults to six rows; the other types use the vanilla size of their window.

guiTypeWindow
CUSTOM, CHEST, ENDER_CHEST, BARREL, SHULKER_BOXChest-style grids. For CUSTOM, size is SIZE_9, SIZE_18, SIZE_27, SIZE_36, SIZE_45 or SIZE_54.
HOPPER, DISPENSER, DROPPERSmall fixed-size containers.
FURNACE, BLAST_FURNACE, SMOKER, BREWING_STAND, BEACONMachine windows.
CRAFTING_TABLE, ENCHANTING_TABLE, ANVIL, SMITHING_TABLE, GRINDSTONE, LOOM, CARTOGRAPHY_TABLE, STONECUTTERVanilla workstations. With no layout they behave like the vanilla screen; GUI only manages opening and closing.
MERCHANT, VILLAGER_TRADEThe villager trade window, filled by a merchant layout.
BOOKA written book, filled by a book layout.

Layouts​

Each layout is a named entry of layoutPool. The one named in mainLayoutId is the root; the others are reached through references (composite children, scrollable innerId, frame layoutId).

LayoutUse it forKey fields
simpleFixed buttons and decoration at x/y positions.items
flexItems laid out automatically in rows.justifyContent (START, CENTER, END, SPACE_BETWEEN), alignItems, wrap, virtualHeight
paginatedA long list split into pages.itemsPerPage, slots, items, navigationButtons (NEXT, PREVIOUS, BACK, INDICATOR)
scrollableContent taller or wider than the window.innerId, virtualWidth, virtualHeight, buttons (direction, step), showDefaultButtons, defaultStep
frameSeveral independent rectangles, for example tabs, content and a footer.frames (id, x, y, width, height, layoutId)
compositeStacking layers: background, content, buttons.children (layout ids, later children draw on top)
bookThe pages of a written book.pages (MiniMessage)
merchantVillager trades with custom items.trades (result, costOne, costTwo, maxUses, criteria)
storagePersistent slots backed by a GUI Storage artifact.entry, groupKey, slots
leaderboardRanking rows with pages, from facts or from the source of another extension.leaderboard, x, y, width, height, previousButton, nextButton

A book or merchant layout only works as the main layout, and guiType is overridden to the matching window. A scrollable layout gets default arrows while showDefaultButtons is on (the default): one for every direction you gave no buttons entry, see Layouts, frames and slots.

See Layouts, frames and slots for a detailed walk through each layout.

Items and slots​

Every item of a layout is a slot description with the same fields:

FieldRole
itemThe item to display. Left empty, the slot shows the item the player holds in their main hand.
displayName, loreMiniMessage text with PlaceholderAPI support. Names are upright by default; add <italic> if you want italics. A blank displayName keeps the name of the item instead of replacing it with an empty one.
x, yColumn 0 to 8 and row from 0 at the top.
rollPerSlotFor an item repeated over several slots whose item is random: off (default) rolls once and every slot shows that result, on rolls each slot on its own when the menu opens. The result is kept while the menu stays open, unless liveItem is on.
liveItemOff (default): the item is drawn when the menu opens and kept for the whole session; on refresh only its name and lore follow. On: the item is evaluated again at every refresh, so a random item is drawn again each time. With rollPerSlot on, each repeated slot draws on its own at each refresh; with it off, all repeated slots share one draw per refresh. A blank name is still ignored.
count, direction, gap, repeatYSlot repetition, see below.
criteriaThe slot is not drawn for players who do not match.
viewPermissionPermission required to see the slot.
clickPermissionPermission required to use the slot; without it the slot is drawn but inert.
allowPickup, isGhostWhether the item can be taken out of the menu. Both are off by default; ghost items can be clicked but never moved or copied.
cooldownTicksTicks before the same slot can be clicked again.
interactionList, triggers, modifiersWhat a click does.
inputOpens a text input dialog on click.
storageIdTurns the slot into a persistent storage slot from storagePool.
buttonType, buttonPrefixMarks the slot as a button provided by another extension.
animationMoves the slot to a target position over a duration in milliseconds when the menu opens.

Slot repetition. count repeats an item along direction (right, left, down, up). gap is a step, not a spacing: 1 is adjacent, 2 leaves one empty slot between copies, and 0 behaves as 1. repeatY repeats the whole line on the perpendicular axis. Without a direction, count, gap and repeatY are ignored and a single slot is placed. These fields count slots, never the stack size of the item.

Overlaps. When two slots share a cell, the one that does something (a click action, a tag, a storage slot) wins over a purely decorative one, whatever the order. Between two of the same kind the last declared one wins. A warning naming the cell is logged once.

Click actions​

interactionList maps a click type to commands and triggers. The available types are LEFT_CLICK, RIGHT_CLICK, SHIFT_LEFT_CLICK, SHIFT_RIGHT_CLICK, MIDDLE_CLICK, DOUBLE_CLICK, NUMBER_KEY_1 to NUMBER_KEY_9, DROP, DROP_ALL and SWAP_OFFHAND.

  • commands run from the console. %player% is replaced by the player name, and PlaceholderAPI placeholders are resolved first.
  • triggers fire TypeWriter entries for the player. The slot's own triggers and modifiers fire on every left or right click, or whenever a specific interaction matches.
  • closeMenu closes the window after the action. executeReturn goes back to the previous menu.

Commands beginning with gui: are handled by GUI itself:

CommandEffect
gui:closeClose the menu.
gui:backReopen the previous menu of the session.
gui:open <entry_id> or gui:action <entry_id>Trigger another entry, usually another Open GUI.
gui:view <view_id>Switch to another view without closing the inventory.
gui:page <delta> [layout_id]Move a paginated or leaderboard layout by that many pages.
gui:scroll <dx> <dy> [layout_id]Scroll a scrollable layout.
gui:refreshRedraw the menu now.
gui:sound <sound_key>Play a sound to the player.

Open, back and close​

An Open GUI opened from another menu is pushed onto the session history, so gui:back or executeReturn returns to it. Closing with Escape ends the session. Opening a book layout ends the current session first.

Set audio to play sounds on open, close, scroll and click. Set autoRefreshTicks to redraw the menu every N ticks while it is open, which is what makes placeholders in names and lore tick like a counter or a timer.

Views, tabs and inheritance​

views turn one open_gui into several screens that share the same shell. A frame whose layoutId is @view is filled with the layout of the active view: first the view's explicit frames mapping, then the layout named <view id>_<frame id>, then the same lookups on the view's parentId. Mark a tab item with buttonPrefix view: and buttonType set to the view id and it switches view when clicked and lights up while active. The view title accepts {breadcrumb}, {view} and {root}.

baseMenuId points at another Open GUI and merges its layoutPool, views and storagePool under yours: a layout with the same id replaces the inherited one. Details in Views, tabs and inheritance.

Storage slots​

A GUI Storage artifact holds the items, per player or per group. Declare reusable configurations in the entry's storagePool, then give an item a storageId, or use a storage layout. Item names and lore of a storage slot accept {stored_name}, {stored_amount} and {stored_max}.

Default click bindings, which you can change in GUI Global Settings:

ActionDefault click
Place one item from the cursorLeft click
Place the whole cursor stackShift + left click
Take one itemRight click
Take everythingLeft click
Take a stackShift + right click
Fill from the inventorySwap offhand (F)
Drop everything on the groundDrop (Q)

dropOnClose drops what is still stored at the player's feet when the menu really closes, on Escape or on disconnect, but not when the player moves to another menu.

Extended inventory​

extendToPlayerInventory shows the player's own 36 slots as four extra rows, for a canvas of ten rows (y 0 to 9). It is client-side only: the real inventory is never modified and is restored when the menu closes, and items cannot be picked up from the bottom rows. It requires guiType CUSTOM with size SIZE_54. A root layout whose id ends with _extended enables it on its own.

Configuration​

GUI has no configuration file. Two optional manifest entries adjust it:

  • GUI Extension Configuration enables debug logging and the hideVanillaItemStats option, on by default, which hides attack damage, durability and enchantment lines on menu buttons.
  • GUI Global Settings sets the storage click bindings and the skill tree connector items.

Placeholders​

PlaceholderReturns
%typewriter_gui_storage_amount_<entry_id>_<slot_index>%Number of items stored for the player in a GUI Storage entry, 0 if empty.
%typewriter_gui_storage_has_<entry_id>_<slot_index>%true when the slot holds an item, otherwise false.

<slot_index> is y * 9 + x of the storage slot. These placeholders always read the player's own storage, never a shared group storage.

Inside menus, the following tokens are replaced by the extension: {stored_name}, {stored_amount}, {stored_max} (storage slots), {page}, {next_page}, {prev_page}, {total_pages} and {page_indicator} (the INDICATOR button of a paginated layout), and {rank}, {name}, {score}, {group}, {world} and {score_<fact_id>} (leaderboard rows), plus {score_raw} and {value_<key>} for the rows of a leaderboard source.

Entries​

6 entries, generated from the extension source.

Actions1
Artifacts2
Manifests3

Troubleshooting​

The menu opens empty. mainLayoutId is blank, or does not match any layout id in layoutPool (ids are case-sensitive). When using baseMenuId, a blank mainLayoutId falls back to the parent's. The startup check reports an unresolved main layout in the console.

A slot is missing and the console says "falls outside the grid". The item landed at a negative x or y, or past column 8. This usually comes from a too large count, which counts slots. The log names the layout and the rejected coordinates.

The console says "Slot overlap ... gap". Two slots share a cell. gap is a step: 1 places adjacent slots and 2 leaves one empty slot between each, so authors who read gap: 1 as "one gap" get copies on top of each other's neighbours. Change gap or move one slot.

A slot is visible to admins but not to players. viewPermission names a permission nobody but operators has. Blank values are ignored, but a typo is a real, operator-only node. The same rule applies to a view's viewPermission.

A button shows but does nothing. Check clickPermission, then cooldownTicks, then criteria. If the slot has a buttonType, its buttonPrefix must match the extension providing it; an unclaimed tag keeps your own interactionList but nothing else. Commands run from the console, so a command that needs a player sender fails silently.

The scrollable content does not move. Check that the content is larger than the window (virtualWidth and virtualHeight): an arrow only shows while there is something to scroll to in its direction. With showDefaultButtons off and no buttons, there is no arrow at all. A default arrow also gives way when its cell already holds a content item, a button or a decoration: nothing is logged, so move it with scrollArrows in GUI Settings or add your own buttons with a direction and a step, outside the scrolled area.

The leaderboard only lists online players. Link a GUI Leaderboard Population artifact in the leaderboard's population field to keep the last known values of offline players.

The extended menu does not show ten rows. extendToPlayerInventory needs guiType CUSTOM and size SIZE_54.

  • Shops — shop menus built on GUI layouts and the shop_button: marker.
  • Quest Codex — the quest log menu, built on the same open_gui chassis.