Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 99 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Optionally install [Mod Menu](https://modrinth.com/mod/modmenu) to see loaded GU

| Command | Description |
|---------|-------------|
| `/guiapi` | Show help (same as `/guiapi help`) |
| `/guiapi open <id>` | Open a GUI for yourself |
| `/guiapi open <id> <targets>` | Open a GUI for target players |
| `/guiapi list` | List all loaded GUI definitions |
Expand Down Expand Up @@ -54,25 +55,41 @@ The GUI ID used in commands is `<namespace>:<name>` — matching the file path u

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `title` | string | `"GUI"` | Inventory title. Supports `§` color codes. |
| `title` | string | `"GUI"` | Inventory title. Supports `§` color codes and placeholders. |
| `rows` | int 1–6 | `3` | Number of rows (9 slots each). |
| `buttons` | array | `[]` | List of button definitions. |
| `on_open` | action[] | `[]` | Actions executed when the GUI is opened. |
| `on_close` | action[] | `[]` | Actions executed when the GUI is closed (any reason). |
| `buttons` | button[] | `[]` | List of button definitions. |

### Button fields

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `slot` | int | `0` | Zero-based slot index (0–`rows*9-1`). |
| `page` | int | `0` | Which page this button appears on. |
| `item` | string | `"minecraft:stone"` | Item ID, e.g. `minecraft:diamond`. |
| `name` | string | `""` | Display name. Supports `§` color codes. |
| `lore` | string[] | `[]` | Lore lines shown below the name. |
| `item` | string | `"minecraft:stone"` | Item ID. |
| `name` | string | `""` | Display name. Supports color codes and placeholders. |
| `lore` | string[] | `[]` | Lore lines. Supports placeholders. |
| `glint` | boolean | `false` | Apply enchantment glint effect. |
| `click_type` | string | `"any"` | Which click triggers actions: `any` · `left` · `right` · `shift` |
| `condition` | object | — | Visibility condition (see below). |
| `actions` | array | `[close]` | Actions executed in order on click (see below). |
| `actions` | action[] | `[close]` | Actions executed in order on click. |
| `toggle` | object | — | Toggle definition — replaces `item`/`actions` (see below). |

> **Legacy:** A single `"action": {}` object is still accepted for backwards compatibility.
> **Legacy:** A single `"action": {}` object is still accepted.

### Placeholders

Supported in `title`, button `name`, `lore`, `message` values, and `run_command` values.

| Placeholder | Resolves to |
|-------------|-------------|
| `{player}` | Player's display name |
| `{gui}` | GUI ID (`namespace:name`) |
| `{page}` | Current page index (0-based) |
| `{page1}` | Current page index (1-based) |
| `{pages}` | Total page count |
| `{score:objective}` | Player's score in the given scoreboard objective |

### `click_type` values

Expand All @@ -87,10 +104,10 @@ The GUI ID used in commands is `<namespace>:<name>` — matching the file path u

| Type | `value` field | `run_with` | Description |
|------|--------------|------------|-------------|
| `run_command` | Command string (with or without leading `/`) | `player` · `console` | Run a command. Default executor: player. |
| `run_command` | Command string | `player` · `console` | Run a command. Default: player. Supports placeholders. |
| `close` | — | — | Close the GUI. |
| `open_gui` | `namespace:name` | — | Close and open another GUI. |
| `message` | Text string | — | Send a chat message to the player. |
| `message` | Text string | — | Send a chat message to the player. Supports placeholders. |
| `next_page` | — | — | Go to the next page. |
| `prev_page` | — | — | Go to the previous page. |
| `goto_page` | Page index (string) | — | Jump to a specific page. |
Expand All @@ -104,10 +121,27 @@ Conditions control button **visibility**. Hidden buttons cannot be clicked.
| Type | `value` format | Visible when |
|------|---------------|--------------|
| `has_tag` | Tag name | Player has the scoreboard tag |
| `not_tag` | Tag name | Player does **not** have the scoreboard tag |
| `score_gt` | `"objective:threshold"` | Player's score > threshold |
| `score_lt` | `"objective:threshold"` | Player's score < threshold |
| `score_eq` | `"objective:value"` | Player's score == value |

### Toggle buttons

A toggle button shows different item/name/lore/actions depending on a scoreboard tag on the player. Replace the `item` and `actions` fields with a `toggle` object.

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `tag` | string | `""` | Scoreboard tag that stores the on/off state. |
| `item_on` / `item_off` | string | lime/gray dye | Item shown in each state. |
| `name_on` / `name_off` | string | `§aEnabled` / `§7Disabled` | Display name in each state. |
| `lore_on` / `lore_off` | string[] | `[]` | Lore in each state. |
| `glint_on` / `glint_off` | boolean | `false` | Glint in each state. |
| `actions_on` | action[] | `[tag @s remove <tag>]` | Actions when clicking while ON. Default removes the tag. |
| `actions_off` | action[] | `[tag @s add <tag>]` | Actions when clicking while OFF. Default adds the tag. |

The default `actions_on`/`actions_off` use `run_with: console` and handle the tag automatically — you only need to specify them if you want additional side effects.

---

## Examples
Expand All @@ -133,26 +167,65 @@ Conditions control button **visibility**. Hidden buttons cannot be clicked.
}
```

### Right-click vs left-click on the same slot
### Placeholder in name and lore

```json
{
"slot": 4,
"item": "minecraft:player_head",
"name": "§6{player}",
"lore": [
"§7Page {page1}/{pages}",
"§7Coins: §e{score:coins}"
]
}
```

### on_open and on_close hooks

```json
{
"slot": 13,
"item": "minecraft:paper",
"name": "§7Left or Right Click",
"title": "§aShop",
"rows": 3,
"on_open": [{ "type": "run_command", "value": "tag @s add in_shop", "run_with": "console" }],
"on_close": [{ "type": "run_command", "value": "tag @s remove in_shop", "run_with": "console" }],
"buttons": []
}
```

### Toggle button

```json
{
"slot": 4,
"toggle": {
"tag": "notifications_on",
"item_on": "minecraft:bell",
"item_off": "minecraft:barrier",
"name_on": "§aNotifications: ON",
"name_off": "§cNotifications: OFF",
"lore_on": ["§7Click to disable."],
"lore_off": ["§7Click to enable."]
}
}
```

### Left-click vs right-click on the same slot

```json
{
"slot": 13, "item": "minecraft:paper", "name": "§fInteract",
"click_type": "left",
"actions": [{ "type": "message", "value": "§aYou left-clicked!" }]
"actions": [{ "type": "message", "value": "§aLeft!" }]
},
{
"slot": 13,
"item": "minecraft:paper",
"name": "§7Left or Right Click",
"slot": 13, "item": "minecraft:paper", "name": "§fInteract",
"click_type": "right",
"actions": [{ "type": "message", "value": "§eYou right-clicked!" }]
"actions": [{ "type": "message", "value": "§eRight!" }]
}
```

> Two buttons can share a slot if they have different `click_type` values. The first matching one wins.
> Two buttons can share a slot with different `click_type` values. The first matching one wins.

### Conditional button (tag-gated)

Expand All @@ -166,23 +239,7 @@ Conditions control button **visibility**. Hidden buttons cannot be clicked.
}
```

### Multi-page GUI

```json
{
"title": "§9Item Shop",
"rows": 4,
"buttons": [
{ "slot": 0, "page": 0, "item": "minecraft:apple", "name": "§aApple", "actions": [{ "type": "run_command", "value": "give @s minecraft:apple" }] },
{ "slot": 1, "page": 0, "item": "minecraft:bread", "name": "§aBread", "actions": [{ "type": "run_command", "value": "give @s minecraft:bread" }] },
{ "slot": 26, "page": 0, "item": "minecraft:arrow", "name": "§7Next →", "actions": [{ "type": "next_page" }] },
{ "slot": 0, "page": 1, "item": "minecraft:diamond", "name": "§bDiamond", "actions": [{ "type": "run_command", "value": "give @s minecraft:diamond" }] },
{ "slot": 27, "page": 1, "item": "minecraft:arrow", "name": "§7← Back", "actions": [{ "type": "prev_page" }] }
]
}
```

### Console command (elevated execution)
### Console command

```json
{
Expand Down Expand Up @@ -216,15 +273,16 @@ Requires **Java 21**.
src/main/java/dev/toolkitmc/guiapi/
├── GuiApiMod.java ModInitializer — registers reload listener and command
├── command/
│ └── GuiCommand.java /guiapi open|list|reload|help
│ └── GuiCommand.java /guiapi open|list|reload|help (bare /guiapi → help)
├── gui/
│ ├── GuiDefinition.java JSON data model (title, rows, buttons, actions, conditions)
│ ├── GuiScreenHandler.java Extends GenericContainerScreenHandler; blocks slot interaction
│ └── BarrelGuiHandler.java Opens inventory screens; evaluates conditions; dispatches actions
│ ├── GuiDefinition.java JSON model: title, rows, buttons, toggle, on_open/close
│ ├── GuiScreenHandler.java Extends GenericContainerScreenHandler; blocks interaction
│ └── BarrelGuiHandler.java Opens screens; evaluates conditions; resolves placeholders;
│ dispatches actions; fires on_open/on_close hooks
├── loader/
│ └── GuiRegistry.java Loads data/<ns>/gui/*.json on resource reload
└── modmenu/
└── GuiApiModMenuEntry.java Optional Mod Menu info screen (compile-only dependency)
└── GuiApiModMenuEntry.java Optional Mod Menu info screen
```

---
Expand Down
38 changes: 29 additions & 9 deletions example-datapack/data/example/gui/admin_panel.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
{
"title": "§6Admin Panel",
"title": "§6Admin Panel §8— {player}",
"rows": 3,
"on_open": [
{ "type": "run_command", "value": "tag @s add in_admin_panel", "run_with": "console" }
],
"on_close": [
{ "type": "run_command", "value": "tag @s remove in_admin_panel", "run_with": "console" }
],
"buttons": [
{
"slot": 10,
Expand All @@ -14,7 +20,7 @@
{
"slot": 12,
"item": "minecraft:compass",
"name": "§bSpawn",
"name": "§bSpawn §8(Left)",
"lore": ["§7Teleport to spawn.", "§8Left-click only."],
"click_type": "left",
"actions": [
Expand All @@ -25,13 +31,26 @@
{
"slot": 12,
"item": "minecraft:compass",
"name": "§bSpawn",
"lore": ["§7See your coordinates.", "§8Right-click only."],
"name": "§bCoords §8(Right)",
"lore": ["§7Show your coordinates.", "§8Right-click only."],
"click_type": "right",
"actions": [
{ "type": "run_command", "value": "execute as @s run data get entity @s Pos" }
]
},
{
"slot": 13,
"toggle": {
"tag": "pvp_enabled",
"item_on": "minecraft:iron_sword",
"item_off": "minecraft:shield",
"name_on": "§cPvP: ON",
"name_off": "§aPvP: OFF",
"lore_on": ["§7Click to disable PvP."],
"lore_off": ["§7Click to enable PvP."],
"glint_on": true
}
},
{
"slot": 14,
"item": "minecraft:ender_pearl",
Expand All @@ -45,23 +64,24 @@
"slot": 15,
"item": "minecraft:nether_star",
"name": "§cAdmin Tools",
"lore": ["§7Only visible with the §cadmin§7 tag.", "§8Shift-click to open."],
"lore": [
"§7Only visible with the §cadmin§7 tag.",
"§8Shift-click to activate."
],
"glint": true,
"click_type": "shift",
"condition": { "type": "has_tag", "value": "admin" },
"actions": [
{ "type": "run_command", "value": "gamemode creative @s", "run_with": "console" },
{ "type": "message", "value": "§aCreative mode enabled." },
{ "type": "close" }
]
},
{
"slot": 16,
"item": "minecraft:barrier",
"name": "§cClose",
"lore": [],
"actions": [
{ "type": "close" }
]
"actions": [{ "type": "close" }]
}
]
}
Loading