Runtime API
This is the set of global functions and object methods that an exported program uses at
runtime. You mostly need it when writing your own Lua on top of a
UI Only Export, or when hand‑editing a
Full Export's logic/ files.
These functions live in utils/functions.lua; the Screen and component methods live
in components/.
Globals
Declared in utils/vars.lua:
| Global | Type | Description |
|---|---|---|
running | boolean | The main loop runs while this is true. Set it false to quit. |
screens | table | Every Screen object, filled in by screens/*.lua. |
monitors | table | Wrapped monitor peripherals, refreshed by updateMonitors(). |
workingScreens | table | Names of the screens shown on startup. |
| your variables | any | Each project variable becomes a global here. |
Screen functions
Available in Full and UI Only exports (utils/functions.lua).
getScreen(name)
Returns a registered screen. name may be:
"terminal"— the working screen currently bound to the computer's terminal;"monitor:<peripheral name>"— the screen on a specific monitor;- a screen's own name, e.g.
"Screen_1".
local screen = getScreen("terminal")
📝 Note — Logic Only: In a Logic Only Export,
getScreen()is a stub that always returns a single shared screen object, regardless of the name.
navigate(oldScreenName, newScreenName)
Switches which screen is active on a display, reassigns monitors, and redraws. This is what the navigate to screen block calls.
navigate(screen.name, "Screen_2")
drawScreens()
Resolves layout and redraws every working screen. UI Only exports call this once at the
end of startup.lua; you can call it yourself after changing the UI.
refreshScreen()
Alias for drawScreens().
updateMonitors() / setupMonitorsToScreens(old, new)
Re‑scan attached monitor peripherals and (re)assign screens to compatible displays based
on each screen's displayType and monitor size constraints. Called automatically; you
rarely invoke these directly.
Screen methods
A Screen is created in each screens/*.lua file. Useful methods:
| Method | Description |
|---|---|
screen:getChild(name) | Return the child element with that name (or nil). |
screen:childSetProp(name, prop, value) | Set a child's property and redraw. Uses a set<Prop> method if one exists, else assigns directly. |
screen:addChild(element) | Register an element on the screen. |
screen:addDrawOrder(name) | Add a top‑level element to the draw order. |
screen:getTopTouchedElement(x, y) | The top‑most element at a coordinate (hit‑testing). |
screen:draw() | Draw the screen and run its onUpdate / onceLoaded. |
screen:setBlinking(state, x, y) | Toggle the cursor blink (used by inputs). |
screen.events
The handlers your block logic attaches to:
| Field | Shape | Fired by |
|---|---|---|
onceLoaded | function() | the first time the screen is drawn |
onUpdate | function() | every draw |
onKeyPress | { [keyName] = function() } | key events |
onTimer | list of { func, last, interval } | the timer tick |
onRedstone | function() | redstone changes |
onModemMessage | { ["ch_<n>"] = function(side, ch, reply, msg, dist) } | modem messages |
local screen = getScreen("Screen_1")
screen.events.onceLoaded = function()
screen:childSetProp("label1", "text", "Ready")
end
table.insert(screen.events.onTimer, { func = function()
-- runs every 2 seconds
end, last = 0, interval = 2 })
Element methods (BaseObject)
Every component inherits these from BaseObject:
| Method | Description |
|---|---|
el:setText(text) | Set the text and fire its text_changed event. |
el:setVisible(visible) | Show or hide the element. |
el:isVisible() | Whether it's currently visible. |
el:getScreen() | The screen that owns it. |
el:getMonitor() | The monitor/terminal it draws to. |
el:checkTouch(x, y) | Whether a coordinate is inside it. |
Element events
Each element has an events table. Your “when <element> <event>” blocks register
functions here, and the main loop calls them:
local btn = screen:getChild("button1")
btn.events["clicked"] = function(x, y) end
btn.events["released"] = function(x, y) end
The events available depend on the element type — for example a Button fires clicked,
focused, and released, while a Slider fires value_changed.
Reading & writing properties
Property changes should go through childSetProp so the screen redraws and any setter
runs:
-- set (redraws automatically)
screen:childSetProp("progressbar1", "progress", 75)
screen:childSetProp("label1", "text", "Done")
screen:childSetProp("button1", "visible", false)
-- read (direct access is fine)
local current = screen:getChild("slider1").value
childSetProp looks for a method named set<Prop> (e.g. setText, setVisible) and
calls it if present; otherwise it assigns the field directly. Either way it redraws.
A minimal hand‑written program
Putting it together — the kind of loop you'd add to a UI Only export to make it interactive:
local screen = getScreen("terminal")
screen:getChild("button1").events["released"] = function()
screen:childSetProp("label1", "text", "Clicked!")
end
while running do
drawScreens()
local event, p1, p2, p3 = os.pullEvent()
if event == "mouse_click" then
local hit = screen:getTopTouchedElement(p2, p3)
if hit and hit.onClickEvent then hit:onClickEvent(p2, p3) end
if hit and hit.onReleaseEvent then hit:onReleaseEvent(p2, p3) end
end
end