Forum / Dev Talk / Snippets & Tutorials / UIs

#1 18 Aug 2026 19:02 edited 18 Aug 2026 19:02 by admin
The .bot language just grew a UI system and a type system


Two big things landed in the script engine this update, plus a pile of new commands. Here's the whole picture.
1. Scripts can build their own interface

Until now a script talked to you through
print()
and the settings panel. Now a running script can put its own tab on the launcher's rail and fill it with real controls — and read them back live.
The controls:
  • uiTab("Miner")
    — name your tab
  • uiHeader("Totals")
    — a section header
  • uiLabel("status", "Mining...")
    — a line of text you can update
  • uiProgress("trips", 4, 28)
    — a progress bar
  • uiButton("Drop all", "onDrop")
    — a button that runs a function
  • uiToggle("pause", "Pause", false)
    — an on/off switch
  • uiChoice("mode", "Mode", Mode.POWER)
    — a dropdown over an enum
  • uiInput("search", "Search", "")
    — a text field

You read the interactive ones back with
uiToggled(key)
,
uiChosen(key)
and
uiText(key)
, and there's
uiHas(key)
to check a row exists,
uiRemove(key)
and
uiClear()
to tidy up.
Two design points that make this safe rather than a footgun:
  • Rows are an upsert by key. Call
    uiLabel("status", ...)
    every pass in
    on loop
    and it updates the same row — it doesn't grow a new one each time.
  • Button clicks run between passes, on your script's thread. A click never interrupts your loop half-way and never runs two things at once. It's the same safe hand-off
    on message
    uses.

And the button callback is checked when you write it:
uiButton("Go", "onGo")
only compiles if a
fun onGo()
with no arguments actually exists. Typo the name and it's a red squiggle in the editor, not a dead button you discover in-game.
2. Enums — your own type

enum Mode { POWER, BANK, SELL }
setting Mode mode = Mode.POWER "What to do with ores"
if mode == Mode.BANK { become banking }
print(mode)        # Mode.POWER
print(mode.name)   # POWER

Each enum is a type of its own. A
Mode
never equals a string or a member of another enum — the checker refuses the comparison with a hint, so
if mode == "bank"
is caught before you ever run it. A
setting
typed with an enum becomes a dropdown on the settings panel automatically.
.name
gives you the member back as a string.
It's deliberately small: no iterating the members, no numbers behind them, no lists of them. An enum is a set of names, nothing more — which is exactly what makes it safe.
3. New commands

  • itemDefCount()
    — how many item definitions the cache holds, so you can sweep every id with
    itemDef(id)
  • replace(text, find, with)
    — literal string replace