QuestLines GUI
Define custom in-game screens as declarative .gui.json files. Buttons can
execute any QuestLines action, elements can be conditionally hidden by any requirement,
and text fields support all Core text variables. Open any screen from a quest response
with the opengui: action.
What It Is
QuestLines GUI lets server admins build custom in-game UI screens without writing any
Hytale UI code. Each screen is a .gui.json file in
mods/QuestLinesGUI/. The plugin loads these files at startup and exposes
them via the /qlgui command and the opengui: Core action.
Because the plugin hooks into QuestLines Core’s action and requirement systems, GUIs are first-class quest citizens: a button that awards gold, completes a quest, or navigates to another screen uses the exact same action strings as dialogue responses. Elements can be hidden or shown based on any requirement the player currently meets.
QuestLines GUI loads without Core, but buttons will not execute actions and
requirements will not be evaluated. The opengui: action is only
registered when both plugins are present.
Data Model
Each file in mods/QuestLinesGUI/ named <id>.gui.json
defines one GUI screen. The ID is taken from the filename; an explicit "Id"
field inside the JSON overrides it. All JSON keys are PascalCase.
GuiDefinition
| Field | Type | Default | Description |
|---|---|---|---|
| Title | string | "" | Screen title shown in the window header. |
| Width | int | 480 | Panel width in pixels. |
| Height | int | 420 | Panel height in pixels. |
| CloseButton | bool | true | Whether an X close button is shown. |
| Layout | string | "Vertical" | Element layout direction. Vertical stacks elements top-to-bottom. |
| Padding | int | 12 | Inner padding in pixels. |
| DefaultCloseOnClick | bool | false | If true, every interactive element closes the GUI when clicked (unless overridden on the element). |
| DefaultRefresh | bool | true | If true, every interactive element re-renders the GUI after clicking (unless overridden on the element). Set false for buttons that close the screen. |
| Elements | list | [] | Ordered list of element definitions. |
{
"Title": "The Blacksmith",
"Width": 400,
"Height": 320,
"DefaultCloseOnClick": false,
"DefaultRefresh": true,
"Elements": [ /* element objects */ ]
}
Element Types
Every element has a "Type" field and an optional "Id" string.
Most elements also accept a "Requirements" list — if any requirement fails,
the element is hidden entirely. Requirements use the same format as quest page requirements.
| Type | Purpose |
|---|---|
label | Non-interactive text. Supports text variables. |
button | Clickable button that executes a list of Core actions. |
spacer | Empty vertical gap for layout spacing. |
divider | Thin horizontal rule for visual separation. |
panel | Grouping container. The whole panel is hidden if its requirements fail. |
image | Static image from a resource-pack path. |
itemicon | Single item icon rendered by the Hytale item renderer. |
progressbar | Horizontal or circular progress bar. Value supports text variables. |
checkbox | Labeled checkbox. Checked state is derived from requirements; click fires separate action lists. |
hyvatar | Player avatar (head, body, bust, or full render). Username supports text variables. |
itemgrid | Inventory-style grid of item slots. Each slot can have actions, requirements, and a tooltip. |
label
| Field | Default | Description |
|---|---|---|
| Text | "" | Display text. Supports Core text variables (e.g. {player}, {track:id}). |
| Color | "#cccccc" | Hex color string. |
| Bold | false | Whether the text is bold. |
| Align | "Start" | Horizontal alignment: Start or Center. |
| Width | 0 | Fixed width in pixels. 0 = auto. |
| FontSize | 0 | Font size. 0 = default. |
button
| Field | Default | Description |
|---|---|---|
| Text | "" | Button label text. |
| Actions | [] | List of Core action strings executed on click. |
| Style | "default" | Visual style hint (passed to the Hytale button renderer). |
| Width | 0 | Fixed width in pixels. 0 = auto. |
| CloseOnClick | null | Override the GUI-level default. null inherits. |
| Refresh | null | Override the GUI-level default. null inherits. |
spacer
| Field | Default | Description |
|---|---|---|
| Height | 10 | Gap height in pixels. |
divider
| Field | Default | Description |
|---|---|---|
| Color | "#333333" | Hex color of the rule. |
| Height | 1 | Rule thickness in pixels. |
panel
A container element that groups child elements. The entire panel — including all its children — is hidden
if any of its Requirements fail. This is useful for showing or hiding whole sections based
on quest state.
| Field | Default | Description |
|---|---|---|
| Layout | "Vertical" | Child element layout direction. |
| Padding | 8 | Inner padding in pixels. |
| Background | null | Optional background color or texture path. |
| Elements | [] | Child element definitions. |
image
| Field | Default | Description |
|---|---|---|
| Src | "" | Image path relative to UI/Custom/. Supports text variables. |
| Width | 0 | Display width in pixels. 0 = natural. |
| Height | 0 | Display height in pixels. 0 = natural. |
itemicon
| Field | Default | Description |
|---|---|---|
| ItemId | "" | Hytale item ID. Supports text variables. |
| Size | 0 | Icon size in pixels (square). 0 = default. |
progressbar
The Value field supports Core text variables and resolves to a number.
A value of 0.0–1.0 is used directly as the fill fraction. A value > 1.0 is treated
as a percentage (divided by 100). Use Max together with a raw tracker
value to compute the fraction automatically.
| Field | Default | Description |
|---|---|---|
| Value | "0" | Fill value. String — supports text variables (e.g. "{track:killboss}"). |
| Max | 0 | If > 0, the resolved value is divided by Max to get a 0–1 fraction. |
| Width | 200 | Bar width in pixels. |
| Height | 20 | Bar height in pixels. |
| Color | null | Optional hex fill color. |
| Circular | false | Render as a circular/ring progress indicator. |
| MaskTexturePath | null | Optional custom mask texture for shaped fills. |
// Fixed fraction
{ "Type": "progressbar", "Value": "0.75", "Width": 200 }
// From a named tracker (kill 10 bosses)
{ "Type": "progressbar", "Value": "{track:killboss}", "Max": 10, "Width": 200 }
// Circular
{ "Type": "progressbar", "Value": "0.5", "Circular": true, "Width": 48, "Height": 48 }
checkbox
The checkbox renders as checked or unchecked based on whether the player meets all
CheckedRequirements at render time. Clicking a checked box fires
UncheckActions; clicking an unchecked box fires CheckActions.
| Field | Default | Description |
|---|---|---|
| Label | "" | Text shown next to the checkbox. |
| CheckedRequirements | [] | Requirements that determine the initial checked state. |
| CheckActions | [] | Actions fired when the player checks the box. |
| UncheckActions | [] | Actions fired when the player unchecks the box. |
| CloseOnClick | null | Override the GUI-level default. |
| Refresh | null | Override the GUI-level default. |
{
"Type": "checkbox",
"Label": "Show quest notifications",
"CheckedRequirements": ["hasTag:notif_on"],
"CheckActions": ["addTag:notif_on"],
"UncheckActions": ["removeTag:notif_on"],
"Refresh": true
}
hyvatar
Renders a Hytale player avatar. Use "{player}" as the username to show the viewing player’s own skin.
| Field | Default | Description |
|---|---|---|
| Username | "{player}" | Player username. Supports text variables. |
| Render | "head" | Avatar type: head, body, bust, or full. |
| Size | 64 | Pixel size (square). |
itemgrid
An inventory-style grid of item slots. Each slot can have its own actions, requirements,
and click requirements. ItemId, Name, and Description
in each slot support Core text variables.
| Field | Default | Description |
|---|---|---|
| SlotsPerRow | 5 | Number of slots per row. |
| DisplayItemQuantity | true | Whether to show quantity numbers on slots. |
| SlotSpacing | null | Pixel gap between slots. Null = default. |
| SlotSize | null | Slot size in pixels. Null = default. |
| Slots | [] | List of slot objects (see below). |
Each slot in Slots:
| Slot Field | Default | Description |
|---|---|---|
| ItemId | "" | Item to render. Supports text variables. |
| Quantity | 1 | Stack count displayed. |
| Name | null | Optional tooltip name override. Supports text variables. |
| Description | null | Optional tooltip body. Supports text variables. |
| Actions | [] | Core actions executed when the slot is clicked. |
| Requirements | [] | If any requirement fails, the slot is hidden. |
| ClickRequirements | [] | If any requirement fails, the click is silently blocked (slot remains visible). |
| CloseOnClick | null | Override the GUI-level default. |
| Refresh | null | Override the GUI-level default. |
Core Integration
opengui: action
When both QuestLines GUI and QuestLines Core are installed, the plugin registers an
opengui:<guiId> action with Core. This action can be used anywhere
Core actions are accepted: response Actions lists, page LoadActions,
button actions in other GUIs, or via the developer API.
// Open a shop screen from a dialogue response
"opengui:blacksmith_shop"
// Auto-open a welcome screen once (via LoadActions)
Requirements: ["questNotStarted:welcome"]
LoadActions: ["questStarted:welcome", "opengui:welcome_screen"]
Requirements on elements
Any element or slot that has a "Requirements" list is hidden when any
requirement in that list fails. Requirements use the same format as quest page
requirements — hasTag:vip, questCompleted:intro,
track:killboss:5, etc.
{
"Type": "button",
"Text": "VIP Shop",
"Requirements": ["hasTag:vip"],
"Actions": ["opengui:vip_shop"]
}
Text variables in elements
label.Text, progressbar.Value, image.Src,
itemicon.ItemId, hyvatar.Username, and itemgrid slot fields
all pass through the Core text variable engine. Every variable available in dialogue
is also available in GUIs — {player}, {track:id},
{variable:name}, etc.
Actions in buttons
Button and itemgrid slot Actions lists accept any Core action string.
This includes quest actions (questCompleted:), economy actions
(economy:give:500), navigation (opengui:otherId), and
everything else in the Actions reference.
In-Game Editor
QuestLines GUI ships with a basic in-game editor accessible via /qlgui editor
or /qlgui edit <id>. The editor lets you inspect and modify GUI
definitions directly in-game without editing JSON files by hand.
The editor supports a preview mode: clicking Preview opens the GUI as a player would see it. Closing the preview automatically reopens the editor session. Changes are only written to disk when you explicitly save.
You can always edit .gui.json files directly in any text editor.
Run /qlgui reload to pick up changes from disk without restarting
the server.
Commands
Root command: /qlgui. Requires questlines.admin permission.
| Command | Description |
|---|---|
| /qlgui open <guiId> [player] |
Open a GUI for yourself or for a named online player. The optional
player argument defaults to self.
|
| /qlgui list | List all loaded GUI IDs. |
| /qlgui reload | Reload all .gui.json files from disk. Use after hand-editing files. |
| /qlgui create <id> | Create a new empty GUI with the given ID and open the in-game editor for it. |
| /qlgui edit <id> | Open the in-game editor for an existing GUI. |
| /qlgui editor | Open the editor hub (GUI list screen) to browse and edit all loaded GUIs. |
Permissions
| Permission | Default | Description |
|---|---|---|
| questlines.admin | false |
Required for all /qlgui subcommands. The opengui:
action (triggered from quest responses) does not require this permission —
it is executed by the server on the player’s behalf.
|
Data Directory
QuestLines GUI stores all GUI definitions in mods/QuestLinesGUI/. Each
file is named <guiId>.gui.json. The plugin scans this directory at
startup and on /qlgui reload.
Files edited in the in-game editor are saved back to this directory and reloaded immediately into the in-memory cache without requiring a server restart or a manual reload command.
Full Example
A simple shop screen with a VIP-only section and a progress bar:
// mods/QuestLinesGUI/blacksmith_shop.gui.json
{
"Title": "Aldric's Forge",
"Width": 420,
"Height": 380,
"DefaultCloseOnClick": false,
"Elements": [
{
"Type": "label",
"Text": "Welcome, {player}!",
"Bold": true,
"Align": "Center"
},
{ "Type": "divider" },
{
"Type": "label",
"Text": "Smith reputation: {track:smith_rep} / 100",
"Color": "#aabbcc"
},
{
"Type": "progressbar",
"Value": "{track:smith_rep}",
"Max": 100,
"Color": "#e08040",
"Width": 380
},
{ "Type": "spacer", "Height": 8 },
{
"Type": "button",
"Text": "Buy Iron Sword (50g)",
"Actions": ["economy:take:50", "item:iron_sword:1"]
},
{
"Type": "button",
"Text": "Buy Legendary Blade (VIP only)",
"Requirements": ["hasTag:vip"],
"Actions": ["economy:take:500", "item:legendary_blade:1"]
},
{
"Type": "button",
"Text": "Close",
"CloseOnClick": true,
"Actions": []
}
]
}