GUI API
Namespace: hexis.gui
GUI operations require the inventory/container to be OPEN. The player CANNOT move while interacting with GUIs. This is enforced automatically by the GUI Interaction Guard.
Automatic Safety (GUI Interaction Guard)
All GUI click operations are automatically protected against anti-cheat detection. You don't need to add manual delays — the system handles this for you.
What Happens Automatically
| Protection | Behavior | When |
|---|---|---|
| First-click delay | 200-500ms randomized delay | Before the FIRST click after a container opens |
| Inter-click delay | 100-150ms minimum gap | Between every consecutive click |
| Movement lock | Stops pathfinder, camera, and movement keys | On first GUI click, released when container closes |
These protections are enforced at the Java API level. Existing scripts automatically benefit without any code changes.
Bypassing Inter-Click Delay
For minigame scripts (Harp, Chronomatron) where the server expects fast consecutive clicks, use unsafe = true to bypass the inter-click delay:
-- Normal scripts — safe by default (100-150ms between clicks)
hexis.gui.click(slot)
-- Minigame scripts — bypass inter-click delay
hexis.gui.click({ slot = slot_id, unsafe = true })
Only use unsafe = true for Hypixel minigames that require fast clicking. NPC menus, bazaar, auction house, and quest UIs should always use the default safe behavior.
Safe Mode (Legacy)
hexis.gui.safe_mode()
Manually stops ALL activity (combat, movement, camera) before GUI interaction.
The GUI Interaction Guard now handles movement locking automatically on the first click. You only need safe_mode() if you want to stop movement before opening a container (e.g., to prevent walking into an NPC).
hexis.gui.safe_mode() -- Optional: stop movement before opening
hexis.gui.open()
Opening/Closing
hexis.gui.open()
Opens player inventory.
hexis.gui.safe_mode()
hexis.gui.open()
hexis.wait(0.3)
hexis.gui.close()
Closes current GUI.
hexis.gui.close()
hexis.gui.wait_for(title, timeout)
Waits for a GUI with matching title to open.
hexis.gui.wait_for("Bazaar", 5) -- Wait up to 5 seconds
State Checks
hexis.gui.is_open()
Returns true if any GUI screen is open.
if hexis.gui.is_open() then
hexis.log.info("GUI is open")
end
hexis.gui.get_title()
Returns current GUI title, or nil if none open.
local title = hexis.gui.get_title()
if title then
hexis.log.info("Current GUI: " .. title)
end
hexis.gui.has_title(pattern)
Returns true if current GUI title contains pattern.
if hexis.gui.has_title("Bazaar") then
hexis.log.info("Bazaar is open!")
end
hexis.gui.get_hovered_item()
Returns information about the item currently under the cursor, or nil if no item is hovered.
local item = hexis.gui.get_hovered_item()
if item then
hexis.log.info("Hovering: " .. item.name)
end
Finding Items
hexis.gui.click_item(options)
Recommended. Finds an item in the current GUI and clicks it in one call. This is the preferred way to interact with menu items.
-- Find and click by name
hexis.gui.click_item({name = "Sell Inventory"})
-- Find and click by lore
hexis.gui.click_item({lore = "Click to confirm"})
-- Combine criteria (AND logic)
hexis.gui.click_item({name = "Diamond", lore = "Click to buy"})
hexis.gui.click_item_by_lore(pattern)
Shorthand for finding and clicking an item by lore text.
hexis.gui.click_item_by_lore("Click to claim")
hexis.gui.find(options)
gui.find is a legacy binding from the YAML scripting system. It may not return values directly in Lua. Use click_item() for combined find+click, or get_slots() for custom scanning logic.
Finds an item in current GUI by name, lore, type, or color.
-- Instead of gui.find, prefer these alternatives:
-- Option 1: Find and click in one step
hexis.gui.click_item({name = "Diamond", lore = "Click to buy"})
-- Option 2: Scan slots manually for custom logic
local slots = hexis.gui.get_slots(0, 53)
for _, slot in ipairs(slots) do
if not slot.empty and slot.name:find("Diamond") then
hexis.gui.click(slot.id)
break
end
end
hexis.gui.get_slot_info(slot)
Gets detailed information about a single slot.
Returns a table with: id, name, type, row, col, color, empty, lore, count, has_glint
| Field | Type | Description |
|---|---|---|
id | number | Slot index |
name | string | Item display name |
type | string | Item type identifier |
row | number | Row in container (0-indexed) |
col | number | Column in container (0-indexed) |
color | string | Dyed color name ("red", "blue", etc. or "none") |
empty | boolean | Whether slot is empty |
count | number | Stack size (0 if empty) |
has_glint | boolean | Whether item has enchantment glint (foil effect) |
lore | table | Array of lore line strings |
local info = hexis.gui.get_slot_info(5)
if info and not info.empty then
hexis.log.info("Slot 5: " .. info.name .. " x" .. info.count)
if info.has_glint then
hexis.log.info(" Has enchantment glint!")
end
end
hexis.gui.get_slots(from, to)
Bulk-scans a range of slots and returns an array of slot info tables. Each entry has the same fields as get_slot_info.
-- Scan all container slots (e.g., first 54 slots of a double chest)
local slots = hexis.gui.get_slots(0, 53)
for _, slot in ipairs(slots) do
if not slot.empty and slot.has_glint then
hexis.log.info("Glinting item at slot " .. slot.id .. ": " .. slot.name)
end
end
hexis.gui.get_container_size()
Returns the number of container slots (excluding player inventory). Useful to know the range for get_slots.
local size = hexis.gui.get_container_size()
local slots = hexis.gui.get_slots(0, size - 1)
Clicking
hexis.gui.click(slot) / hexis.gui.click(options)
Clicks a slot by index. Automatically enforces anti-cheat safety delays.
-- Simple syntax
hexis.gui.click(slot)
-- Table syntax with options
hexis.gui.click({ slot = 10, button = "right" })
hexis.gui.click({ slot = 10, action = "shift" })
hexis.gui.click({ slot = 10, hotbar = 0 }) -- Swap with hotbar
-- Minigame bypass (skip inter-click delay)
hexis.gui.click({ slot = slot_id, unsafe = true })
| Option | Type | Description |
|---|---|---|
slot | number | Slot index to click |
button | string | "left" (default) or "right" |
action | string | "shift" for shift-click, "right" for right-click |
hotbar | number | Hotbar slot (0-8) to swap with |
unsafe | boolean | Skip inter-click delay (for minigames only) |
hexis.gui.click_item(options)
Find and click an item in one step. Same safety delays apply automatically.
hexis.gui.click_item({
name = "Confirm",
required = true, -- Fail if not found
action = "shift", -- "shift" or "right"
delay = 0.2, -- Delay after click
unsafe = true -- Optional: skip inter-click delay
})
hexis.gui.click_item_by_lore(pattern)
Find and click item by lore text.
hexis.gui.click_item_by_lore("Click to sell")
Slot Watcher
Main-thread slot watcher for detecting item changes in real-time. Useful for games like Chronomatron where items change too fast for cross-thread polling to catch.
The watcher runs on the main client tick thread, detecting changes via both individual slot packets and bulk content packets. Changes are queued and consumed from Lua via poll_slot_changes().
hexis.gui.watch_slots(slot_ids)
Start watching specific slots for item changes.
| Parameter | Type | Description |
|---|---|---|
slot_ids | table | Array of slot indices to watch |
-- Watch slots 12, 13, 14 and the control slot
hexis.gui.watch_slots({12, 13, 14, 49})
hexis.gui.poll_slot_changes()
Drains all pending slot change events from the watcher queue. Returns an array of change tables.
Each change table has:
| Field | Type | Description |
|---|---|---|
slot | number | Slot index that changed |
type | string | Item type identifier |
name | string | Item display name |
has_foil | boolean | Whether item has enchantment glint |
local changes = hexis.gui.poll_slot_changes()
for _, c in ipairs(changes) do
if c.has_foil then
hexis.log.info("Slot " .. c.slot .. " gained foil: " .. c.name)
end
end
hexis.gui.stop_watching()
Stops the slot watcher and clears all state.
hexis.gui.stop_watching()
Use the slot watcher when you need to detect transient item changes that happen faster than your script's poll rate. For static reads, get_slot_info() is simpler and sufficient.
Hotbar
hexis.gui.switch_hotbar(slot)
Switches to hotbar slot (0-8).
hexis.gui.switch_hotbar(0) -- Switch to first slot
Example Usage
Basic Container Navigation
-- Open bazaar and buy item (safe_mode optional, guard handles delays)
hexis.chat.command("/bz")
hexis.gui.wait_for("Bazaar", 5)
hexis.gui.click_item({name = "Buy Instantly"}) -- First click: 200-500ms delay auto-applied
hexis.wait(0.3) -- Wait for server response
hexis.gui.click_item({ -- Second click: 100-150ms inter-click delay
name = "Confirm",
required = true
})
hexis.gui.close()
Minigame Solver (Harp)
-- Watch for note changes and click reactively
hexis.gui.watch_slots(ALL_SLOTS)
while hexis.script.is_running() and hexis.gui.is_open() do
local changes = hexis.gui.poll_slot_changes()
for _, change in ipairs(changes) do
if change.type:find("quartz_block") then
hexis.wait(0.1)
hexis.gui.click({ slot = change.slot, unsafe = true }) -- Fast clicks OK
end
end
hexis.wait(0.02)
end
hexis.gui.stop_watching()