Skip to main content

Cookbook

Complete, working patterns to copy and adapt. Each recipe lists the layouts involved and the ideas it demonstrates.

1. Scrollable list with arrows

Layouts: composite → [simple border + scrollable(simple)]. Shows: virtual size, anchored buttons, gui:scroll.
"mainLayoutId": "main",
"layoutPool": [
  { "case": "composite", "value": { "id": "main", "children": ["list_scroll", "border"] } },
  { "case": "scrollable", "value": {
      "id": "list_scroll", "innerId": "list_content",
      "virtualWidth": 9, "virtualHeight": 15,
      "buttons": [
        { "direction": "UP",   "step": 1, "item": { "x": 8, "y": 0, "item": { "material": "ARROW" }, "displayName": "<white>▲" } },
        { "direction": "DOWN", "step": 1, "item": { "x": 8, "y": 5, "item": { "material": "ARROW" }, "displayName": "<white>▼" } }
      ] } },
  { "case": "simple", "value": { "id": "list_content", "items": [
      /* rows 0..14 of content — anything below row 5 is reached by scrolling */
  ] } },
  { "case": "simple", "value": { "id": "border", "items": [
      { "x": 8, "y": 1, "count": 4, "direction": "down",
        "item": { "material": "GRAY_STAINED_GLASS_PANE" }, "displayName": " " }
  ] } }
]
The border column under the arrows keeps the scroll rail visually clean. Content and rail are separate layers, so the rail never scrolls.

2. Paginated shop

Layouts: composite → [simple chrome + paginated]. Shows: itemsPerPage, physical slots, per-item interactions.
{ "case": "paginated", "value": {
    "id": "shop",
    "itemsPerPage": 21,
    "slots": [10,11,12,13,14,15,16, 19,20,21,22,23,24,25, 28,29,30,31,32,33,34],
    "items": [
      { "item": { "material": "DIAMOND_SWORD" },
        "displayName": "<aqua>Epee <gray>— <gold>500⛁",
        "lore": ["<gray>Left-click to buy"],
        "interactions": [
          { "type": "LEFT", "commands": ["shop buy %player% epee"] },
          { "type": "RIGHT", "commands": ["shop preview %player% epee"] }
        ] }
      /* …one entry per product, pages fill automatically */
    ],
    "previousPage": { "item": { "x": 0, "y": 5, "item": { "material": "ARROW" }, "displayName": "<white>◀" } },
    "nextPage":     { "item": { "x": 8, "y": 5, "item": { "material": "ARROW" }, "displayName": "<white>▶" } }
} }

3. Confirmation menu (with gui:back)

Shows: menu-to-menu navigation and the session history. Open this menu from the dangerous button with gui:open <this entry id>. The cancel button returns to the previous menu with gui:back — no hardcoded parent id needed.
"guiType": "CHEST", "size": "ROWS_3",
"title": "<red>Confirm?",
"layoutPool": [
  { "case": "simple", "value": { "id": "main", "items": [
    { "x": 2, "y": 1, "item": { "material": "LIME_WOOL" },
      "displayName": "<green>Confirm",
      "interactions": [ { "type": "LEFT",
        "commands": ["island reset %player%"], "closeMenu": true } ] },
    { "x": 6, "y": 1, "item": { "material": "RED_WOOL" },
      "displayName": "<red>Cancel",
      "interactions": [ { "type": "LEFT", "commands": [], "executeReturn": true } ] }
  ] } }
]

4. Quota deposit (storage + triggers)

Layouts: storage. Shows: requiredItem quotas, shared groupKey, storage placeholders.
{ "case": "storage", "value": {
    "id": "bank_deposit",
    "entry": "<gui_storage artifact id>",
    "groupKey": "island_%island_id%",
    "slots": [
      { "x": 4, "y": 1,
        "requiredItem": { "material": "IRON_INGOT" }, "requiredAmount": 32,
        "onReachRequired": ["<trigger: unlock next tier>"],
        "placeholder": { "material": "LIGHT_GRAY_STAINED_GLASS_PANE" } }
    ] } }
Pair it with an info slot using storage placeholders in its lore:
{ "x": 4, "y": 0, "item": { "material": "BOOK" },
  "displayName": "<yellow>Progress",
  "lore": ["<gray>Deposited: <white>{stored_amount}/{stored_max}"] }

Tips that apply everywhere

  • Layer order = z-order in composite children: background first, buttons last.
  • Give every scrollable/paginated layout a unique id — scroll and page state are tracked per id.
  • Use criteria on items to show/hide buttons per player (locked features, permissions via facts).
  • Keep decorative panes’ displayName as " " (a space) to hide the vanilla item name.