Computer callbacks and state
Use the native descriptor. All calls use computer.method(...)
with exact arity except the documented optional arguments. start executes once
per explicit successful Run/Apply, not after ordinary load. Every callback gets
fresh locals/environment and a copied event. Use state for continuity.
Complete method reference
| Signature | Return values | Contract |
|---|---|---|
computer.getID() |
string | Current opaque entity ID |
computer.getLabel() |
string or one nil | Descriptive label, not unique/addressable |
computer.setLabel(label?) |
none | String of at most 64 bytes; omitted/nil clears; empty/duplicate labels allowed |
computer.getTick() |
Tick | Current synchronized simulation tick |
computer.getLimits() |
copied map | All common limits |
computer.getState(key) |
copied Data or one nil | Key: nonempty string of at most 64 bytes |
computer.setState(key, value) |
none | Atomically validate/copy nonnil Data; false and empty strings are values |
computer.deleteState(key) |
boolean | True only if present and removed |
computer.log(text) |
none | String, bounded rolling diagnostic output |
computer.stop() |
does not return | Stop this run through unavoidable host cleanup, even inside pcall |
computer.on(event_name, handler_name) |
subscription string | Create an independent general-event registration |
computer.off(subscription_id) |
boolean | Remove own run's registration; false if already removed |
computer.after(delay_ticks, handler_name, payload?) |
timer string | One-shot positive integer tick delay |
computer.every(interval_ticks, handler_name, payload?) |
timer string | Recurring positive integer tick interval |
computer.cancelTimer(timer_id) |
boolean | Cancel deadline and admitted undispatched event; false if neither remains |
State: at most 256 root entries, 65,536 accounted bytes and 4,096 nodes total; Data depth 16, per-table entries 1,024, strings 16,384 bytes. Keys/container metadata count too. Rejected updates preserve the old value. Snapshots do not mutate originals; nil is not a state value, use deleteState. Payloads use copied nonnil Data when supplied; metadata must also fit the event envelope.
Logs keep the newest 64 entries / 16,384 bytes, evicting oldest. An entry must be a string within supported bounds. There is no program access to editor drafts, other computers' state/lifecycle, wall clock or arbitrary Factorio objects.
General events
Register declared handler names, never functions. Each on call is independent:
two registrations intentionally yield two deliveries. IDs belong to this
computer/run; another run's subscription/timer ID is invalid, not an alias.
| Registerable event | Additional fields beyond BaseEvent |
|---|---|
| peripheral_attach | peripheral, peripheral_type, wire; discovery timing |
| peripheral_detach | peripheral, peripheral_type, wire, reason |
| monitor_resize | peripheral, wire, wires, old_width, old_height, width, height, reason |
| monitor_touch | peripheral, wire, wires, x, y, player_index, sample_tick |
| power_restored | outage_start_tick, restored_tick |
power_restored occurs once after a real outage for retained subscriptions, not
cold load. No power-loss/stop/fault guest callback is required for safety. start,
timer and signal_changed are not accepted by computer.on. Logic uses
its own subscribe; timers address a named handler directly.
There is no guest on_tick.
TimerEvent
A timer handler receives name="timer" plus BaseEvent,
timer_id:string, scheduled_tick:Tick, interval_ticks:integer?,
missed:integer, payload:Data?. One-shots omit interval_ticks; omitted payload
is nil. Durations are ticks, not seconds, and current_tick + duration must fit
9007199254740991. Equal deadlines use creation order.
One-shots are consumed once on queue admission. Recurring overdue intervals
coalesce into one event: scheduled_tick retains the first due deadline, missed
counts skipped intervals, and the next deadline remains aligned. Already queued
recurring notifications also coalesce rather than burst after an outage. Event
tick is dispatch time, not its deadline. Cancel removes admitted work too.
Run lifecycle and errors
Save commits source, not execution. Successful Apply cancels old work/output, creates a new generation and queues start; explicit state remains. Failed candidate validation preserves the old active run. Stop/fault cancels current work but preserves recoverable source/state/logs. Reset State is a separate stopped, confirmed editor action. Editor workflow and lifecycle cover conflicts and material-item recovery.
Ordinary errors are catchable; uncaught errors fault this run. Fatal quota/stop signals cannot be swallowed or forged. Earlier successful effects remain, except mandatory cleanup of this run's still-owned logic output. Outages pause callbacks, discard transient event history, retain timers/registrations/state and request input resync. Load does not replay startup, timers already consumed, or effects.
For a complete timer/state program see language example; for robust error inspection see database example. Do not busy-loop on network/busy failures or assume a new source revision refreshes same-tick budgets.