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.