tecs.sequence

Snapshot-safe programs, waits, ownership, actions, and tween timelines.

Sequences store control flow as data. A snapshot, a rewind, or a reload can therefore preserve a playback's program, instruction pointer, waits, bindings, and parameters. A coroutine cannot be serialized, so the sequencer compiles authored steps into instructions and stores each playback's cursor, wait, and branch as ordinary data. nupp.tasks owns the world's logical update; it cannot own a playback that has to survive a save file.

Programs and actions#

Register an action on the world, name it from a program, and bind each playback to the entities it acts on:

tecs.sequence.registerAction(world, "game.lockControls", function(_world, _context): nil
    controlsLocked = true
end)

local intro <const> = tecs.sequence.define("game.bossIntro", {
    tecs.sequence.call("game.lockControls"),
    tecs.sequence.wait(1.5),
    tecs.sequence.emit("boss.ready"),
})

local playback <const> = tecs.sequence.play(world, intro, {owner = encounter, bindings = {boss = bossEntity}})

Program names are a snapshot compatibility surface. Use stable qualified names. Redefining a name publishes a new version: running playbacks keep the version they started on, and later play calls use the new one. Action bodies resolve by name when they run, so a reload can replace action code without moving a live instruction pointer.

Actions run synchronously and cannot suspend. An action that raises faults its playback after preserving the mutations it already completed.

Clocks and waits#

"fixed" advances once per fixed step and serves deterministic gameplay. "frame" advances once per gameplay frame and serves scripted input, which needs exactly one decision per frame however many fixed steps that frame runs. "presentation" advances once per frame carrying the frame's real elapsed time, and serves values the simulation never reads.

Durations are seconds. Step and tick values count whole advances of the program's clock. Every positive duration waits at least one tick, and waitSteps(0) yields until the next tick and gives a loop a fresh instruction budget.

ecs.newWorld({nominalFrameTime = seconds}), or Application.Config.world, sets the duration used to convert frame and presentation waits to ticks. It is positive and finite and defaults to 1/60 in both windowed and headless sessions. setNominalFrameTime(world, seconds) changes future conversions in that world only; already scheduled tick deadlines do not move. Restore a saved playback into a world configured for its intended cadence.

sourceKey(key, component, fields) resolves a moving tween destination through World.byKey on each evaluation, including after snapshot load or a new entity claims the key. TrackingTarget.key does the same when its entity is zero. An explicit entity id takes precedence and a stale id does not fall back to the key. A missing source contributes zero, as other missing tracking sources do.

Ownership#

owner ties a playback to an entity, and despawning that entity cancels the playback. A named channel gives one owner a replaceable slot, so starting a second playback on the same channel cancels the first.

Pause uses named holders, and a playback resumes only after every holder releases it. A branch inherits owner, bindings, parameters, budget, and pause state, and cannot outlive its parent.

Each playback receives a bounded instruction budget per tick and faults with budgetExceeded rather than hanging the frame.

Timelines#

A timeline compiles tweens into the same runtime and keeps the same ownership, clock, channel, pause, and snapshot rules. Targets interpolate component fields. A parallel block shares a start time, and a sequential block starts after the one before it ends.

Program construction#

A sequence is written by calling the node constructors. The API has no generic row decoder or shared data schema. A game that stores sequences as data decodes its own schema into these constructors.

Module contents

Types

TypeKindDescription
ActiontypeDefines a registered effect that runs synchronously and cannot suspend.
ActionContextrecordProvides the context a registered action receives.
AwaitablerecordDefines the response an await step's provider must give.
ClockIdtypeSelects the clock a program runs against.
DefineOptionstypeConfigures define.
EasingFunctiontypeMaps normalized input progress to eased output progress.
EasingNametypeNames a built-in easing curve.
EmissionrecordThe payload an emit step delivers at address zero.
EntityRefrecordReferences an entity supplied at play time.
EvaluatorrecordDefines the evaluator an eval step runs every tick.
FaultReasontypeExplains why a cursor stopped running.
HandletypeIdentifies one playback through a generation-checked reference that remains meaningful across a snapshot load.
NoderecordRepresents one authored step produced by a node constructor.
PlaybackModetypeSelects how a timeline repeats.
PlaybackStatetypeDescribes the lifecycle state of one playback.
PlayOptionstypeConfigures play.
ProgramrecordRepresents a compiled, immutable program shared by every playback of it.
QueryConditiontypeDescribes the condition awaited by a waitQuery step.
RunOptionstypeConfigures a nested tweenRun operation.
StatusrecordReports a playback's current state.
SteprecordDescribes one step a playback reaches without branching.
TargetrecordDescribes the component and one to four numeric fields a timeline operation writes.
TargetNametypeNames a built-in component-field target.
TimelineNoderecordRepresents one authored timeline operation.
TimelineOptionstypeConfigures timeline.
TrackingTargetrecordSelects a dynamic tracking-source entity.
TrackSourcerecordProvides a live component-field tracking source.
TweenOutcometypeReports how the playback awaited by waitTween ended.

Functions

FunctionKindDescription
activeCountfunctionReturns the number of live playbacks, for tests and diagnostics.
awaitfunctionBuilds a step that waits for work outside the sequencer to finish.
bindfunctionReferences an entity supplied through PlayOptions.bindings.
callfunctionBuilds a step that runs a registered action.
cancelfunctionStops a playback and releases its cursor.
cancelOwnedByfunctionCancels every playback owned by an entity.
currentStepfunctionReturns a clock's current tick as counted by the sequencer.
definefunctionCompiles a program under a stable symbolic name.
disassemblefunctionRenders a program as readable instructions.
easingfunctionReturns a built-in easing curve by name.
emitfunctionBuilds a step that emits a sequence event at address zero.
evalfunctionBuilds a step that evaluates a registered evaluator every tick until it finishes.
forkfunctionBuilds a step that starts a branch alongside the rest of the program.
hasActionfunctionReports whether a world has registered an action name.
hasQueryfunctionReports whether a world has registered a query name.
joinfunctionBuilds a step that waits for every branch not yet joined.
loopfunctionBuilds a step that repeats a block.
parallelfunctionBuilds a step that forks several blocks and waits for all of them.
pausefunctionSuspends a playback, its branches, and anything it started.
playfunctionStarts a program.
playbacksfunctionReturns handles for every live playback in a stable order.
playTweenfunctionBuilds a step that plays a registered timeline on a bound entity.
pluginfunctionInstalls the sequencer into a world.
programfunctionReturns the newest version of a defined program, or a requested version.
programNamesfunctionReturns the names of every defined program, sorted.
registerActionfunctionRegisters an action a call step can name.
registerAwaitablefunctionRegisters a provider an await step can name.
registerEvaluatorfunctionRegisters an evaluator an eval step can name.
registerQueryfunctionRegisters a query a waitQuery step can name.
resumefunctionReleases one holder's claim on a paused playback.
setInstructionBudgetfunctionSets the per-tick instruction budget for playbacks that ask for none.
setNominalFrameTimefunctionSets the nominal frame duration a frame or presentation wait converts seconds against.
signalfunctionRaises a named signal and wakes every playback blocked on it.
signalOnEventfunctionRaises a signal whenever an event emits at address zero.
sourceKeyfunctionReads a moving destination from the live entity holding a world key.
sourceOwnfunctionReads a moving destination from the animated entity itself.
sourceRelatedfunctionReads a moving destination from the entity a relationship points at.
sourceTrackingfunctionReads a moving destination from the entity named by the animated entity's TrackingTarget.
statusfunctionReturns a playback's status.
targetAnglefunctionInterpolates one field as an angle, taking the short way round.
targetFieldfunctionInterpolates one numeric field of a component.
targetField2functionInterpolates two numeric fields of a component together.
timelinefunctionCompiles a tween timeline into a program under a stable name.
tweenAdjustfunctionBuilds a timeline operation that interpolates by a delta from the starting value.
tweenEmitfunctionBuilds a timeline operation that emits a named sequence event.
tweenParallelfunctionBuilds a timeline operation that runs blocks concurrently and ends with the longest.
tweenRunfunctionBuilds a timeline operation that runs a nested timeline from its own spec.
tweenTofunctionBuilds a timeline operation that interpolates to an absolute destination.
tweenTrackfunctionBuilds a timeline operation that interpolates toward a destination that keeps moving.
tweenWaitfunctionBuilds a timeline operation that advances the cursor without changing anything.
upcomingfunctionReturns the actions and emissions a playback will certainly perform next, and their timing.
waitfunctionBuilds a step that waits a duration in seconds.
waitingOnfunctionReturns how many playbacks currently wait on a signal name.
waitQueryfunctionBuilds a step that blocks until a registered query matches or stops matching.
waitSignalfunctionBuilds a step that blocks until signal raises a named signal.
waitStepsfunctionBuilds a step that waits a whole number of ticks of the program's clock.
waitTweenfunctionBuilds a step that waits for the playback the most recent playTween started.

Values

ValueKindDescription
DEFAULT_BUDGETvariableThe per-tick instruction budget a world gives a playback that asks for none.
TrackingTargetvariableThe process-wide component a tweenTrack tracking source reads.

Types#

Actiontype#

type Action = function(exclusive world: entityworld.World, ctx: ActionContext): nil

Defines a registered effect that runs synchronously and cannot suspend.

ActionContextrecord#

record ActionContext
    handle: Handle
    owner: integer
    args: {any}
    params: {[string]: any}?
    cursor: Cursor?
    entity: function(borrows self: ActionContext, borrows world: entityworld.World, name: string): integer?
    bind: function(exclusive self: ActionContext, name: string, entity: integer?): nil
end

Provides the context a registered action receives.

Methods

entity#
entity: function(borrows self: ActionContext, borrows world: entityworld.World, name: string): integer?

Resolves a named binding to a live entity.

The world is a parameter rather than a field of this record, because the sequencer reuses one context across calls and may not keep a view of the world the running tick borrows. An action already has the world it ran under.

Arguments
NameTypeDescription
borrows selfActionContext

the context the running action received

borrows worldentityworld.World

the world the running action received

namestring

the binding name supplied through PlayOptions.bindings

Returns
TypeDescription
integer?

the entity id, or nil when the binding is missing or its entity is no longer alive

bind#
bind: function(exclusive self: ActionContext, name: string, entity: integer?): nil

Names an entity for the steps that follow, so an action that creates one can hand it on.

Bindings travel with the playback and survive a snapshot. Passing nil forgets the name.

Arguments
NameTypeDescription
exclusive selfActionContext

the context the running action received

namestring

the binding name later steps resolve

entityinteger?

the entity id to bind, or nil to forget the name

Returns
TypeDescription
nil

Fields

handle#
handle: Handle

Read-only. Identifies the playback, for status or cancel from inside an action.

owner#
owner: integer

Read-only. Reports the owner supplied at play, or zero.

args#
args: {any}

Read-only. Carries the call node's constants with every entity reference already resolved to an entity id.

params#
params: {[string]: any}?

Read-only. Carries the params supplied at play, or nil.

cursor#
cursor: Cursor?

Engine-owned. Points at the running cursor. Game code uses entity and bind instead of reading this.

Awaitablerecord#

record Awaitable
    isPending: function(borrows world: entityworld.World, entity: integer, key: string?): boolean
    setPaused: (function(exclusive world: entityworld.World, entity: integer, key: string?, paused: boolean): nil)?
end

Defines the response an await step's provider must give.

Methods

isPending#
isPending: function(borrows world: entityworld.World, entity: integer, key: string?): boolean

Caller-writable. Reports whether the work named by entity and key is still going. The sequencer calls this at a fixed-step boundary for every cursor parked on the name, so it must be cheap and must not mutate the world. Reporting false for work that never started is correct: a program waiting on an animation that is already over should carry on rather than hang.

Arguments
NameTypeDescription
borrows worldentityworld.World
entityinteger
keystring?
Returns
TypeDescription
boolean

Fields

setPaused#
setPaused: (function(exclusive world: entityworld.World, entity: integer, key: string?, paused: boolean): nil)?

Caller-writable. Stops and starts the work when the provider knows how, so pausing a cutscene stops the animation it waits on. Optional.

ClockIdtype#

type ClockId = "fixed" | "frame" | "presentation"

Selects the clock a program runs against.

DefineOptionstype#

type DefineOptions = {clock: ClockId?}

Configures define.

EasingFunctiontype#

type EasingFunction = function(t: number): number

Maps normalized input progress to eased output progress.

EasingNametype#

type EasingName = "linear"
| "quadIn"
| "quadOut"
| "quadInOut"
| "quadOutIn"
| "cubicIn"
| "cubicOut"
| "cubicInOut"
| "cubicOutIn"
| "quartIn"
| "quartOut"
| "quartInOut"
| "quartOutIn"
| "quintIn"
| "quintOut"
| "quintInOut"
| "quintOutIn"
| "sineIn"
| "sineOut"
| "sineInOut"
| "sineOutIn"
| "expoIn"
| "expoOut"
| "expoInOut"
| "expoOutIn"
| "backIn"
| "backOut"
| "backInOut"
| "backOutIn"
| "elasticIn"
| "elasticOut"
| "elasticInOut"
| "elasticOutIn"
| "bounceIn"
| "bounceOut"
| "bounceInOut"
| "bounceOutIn"

Names a built-in easing curve.

Emissionrecord#

record Emission
    name: string
    args: {any}
    handle: Handle
end
@derive(events.Event)@event(name="SequenceEmission")

The payload an emit step delivers at address zero.

Fields

name#
name: string

Read-only. Carries the name supplied to sequence.emit.

args#
args: {any}

Read-only. Carries the emitted constants with bindings resolved. This list is built per emission and is the observer's to keep.

handle#
handle: Handle

Read-only. Identifies the playback that emitted it.

EntityRefrecord#

record EntityRef
    bindName: string
    isBinding: boolean
end

References an entity supplied at play time.

Fields

bindName#
bindName: string

Read-only. Names the binding this reference resolves.

isBinding#
isBinding: boolean

Read-only. Marks this table apart from an ordinary table argument.

Evaluatorrecord#

record Evaluator
    resolve: (function(data: any): any)?
    newState: (function(program: Program, data: any, cursor: Cursor): any)?
    step: function(exclusive world: entityworld.World, cursor: Cursor, dt: number): boolean
    save: (function(state: any): any)?
    load: (function(program: Program, data: any, saved: any): any)?
end

Defines the evaluator an eval step runs every tick.

Methods

step#
step: function(exclusive world: entityworld.World, cursor: Cursor, dt: number): boolean

Caller-writable. Advances one cursor by dt and returns true once the cursor should move on to the next instruction.

Arguments
NameTypeDescription
exclusive worldentityworld.World
cursorCursor
dtnumber
Returns
TypeDescription
boolean

Fields

resolve#
resolve: (function(data: any): any)?

Caller-writable. Turns the constant an eval step carries into the form that is cheapest to read every tick. Runs once per program constant and the result is shared by every playback of it.

newState#
newState: (function(program: Program, data: any, cursor: Cursor): any)?

Caller-writable. Builds per-cursor working state, or nil when the evaluator needs none.

save#
save: (function(state: any): any)?

Caller-writable. Turns working state into something a snapshot can carry. Without both save and load an evaluating playback comes back at the start of its state rather than where it was.

load#
load: (function(program: Program, data: any, saved: any): any)?

Caller-writable. Rebuilds working state from what save produced.

FaultReasontype#

type FaultReason = "unregisteredAction"
| "actionError"
| "budgetExceeded"
| "branchFaulted"
| "unregisteredQuery"
| "unregisteredEvaluator"
| "unregisteredAwaitable"
| "unregisteredTween"

Explains why a cursor stopped running.

Handletype#

type Handle = integer

Identifies one playback through a generation-checked reference that remains meaningful across a snapshot load.

Noderecord#

record Node
    kind: string
    text: string?
    number: number?
    count: integer?
    args: any
    nodes: {Node}?
    blocks: {{Node}}?
end

Represents one authored step produced by a node constructor.

Fields

kind#
kind: string

Read-only. Names the step this node compiles to.

text#
text: string?

Read-only. Carries the step's name argument, when it takes one.

number#
number: number?

Read-only. Carries the step's numeric argument, when it takes one.

count#
count: integer?

Read-only. Carries the step's integer argument, when it takes one.

args#
args: any

Read-only. Carries the step's constant, when it takes one. Most steps carry a list; an evaluating step carries whatever its evaluator reads.

nodes#
nodes: {Node}?

Read-only. Carries the step's nested block, when it takes one.

blocks#
blocks: {{Node}}?

Read-only. Carries one block per branch for a parallel step.

PlaybackModetype#

type PlaybackMode = "once" | "loop" | "pingPong"

Selects how a timeline repeats.

PlaybackStatetype#

type PlaybackState = "running" | "paused" | "completed" | "canceled" | "faulted"

Describes the lifecycle state of one playback.

PlayOptionstype#

type PlayOptions = {
    owner: integer?,
    bindings: {[string]: integer}?,
    params: {[string]: any}?,
    budget: integer?,
    channel: string?
}

Configures play.

Programrecord#

record Program
    name: string
    version: integer
    clock: ClockId
    code: {integer}
    consts: {any}
    loopCounts: {[integer]: integer}
    bindingArgs: {[integer]: boolean}
    evalResolved: {[integer]: any}?
end

Represents a compiled, immutable program shared by every playback of it.

Fields

name#
name: string

Read-only. Reports the name passed to define.

version#
version: integer

Read-only. Reports the monotonic version, starting at one.

clock#
clock: ClockId

Read-only. Reports the clock this program's waits count.

code#
code: {integer}

Engine-owned. Holds the flat instruction array. Game code reads it through disassemble rather than directly.

consts#
consts: {any}

Engine-owned. Holds the constant pool the instructions index.

loopCounts#
loopCounts: {[integer]: integer}

Engine-owned. Maps a jump's address to the iteration count it seeds.

bindingArgs#
bindingArgs: {[integer]: boolean}

Engine-owned. Marks the constant indexes whose argument list holds an entity reference, so a call with plain constants copies nothing.

evalResolved#
evalResolved: {[integer]: any}?

Engine-owned. Caches one resolved constant per evaluating instruction.

QueryConditiontype#

type QueryCondition = "any" | "empty"

Describes the condition awaited by a waitQuery step.

RunOptionstype#

type RunOptions = {
    mode: PlaybackMode?,
    count: integer?
}

Configures a nested tweenRun operation.

Statusrecord#

record Status
    state: PlaybackState
    program: string
    version: integer
    pc: integer
    wakeAt: integer?
    waitingFor: string?
    waitingQuery: string?
    waitingCondition: QueryCondition?
    waitingAwaitable: string?
    waitingAwaitableEntity: integer?
    waitingTween: Handle?
    tweenOutcome: TweenOutcome?
    branches: integer
    joining: boolean
    fault: FaultReason?
    faultMessage: string?
end

Reports a playback's current state.

Fields

state#

Read-only. Reports the lifecycle state.

program#
program: string

Read-only. Names the program this playback runs.

version#
version: integer

Read-only. Reports the program version this playback runs.

pc#
pc: integer

Read-only. Reports the instruction index.

wakeAt#
wakeAt: integer?

Read-only. Reports the tick this playback next runs on, or nil when it is blocked on something other than a time.

waitingFor#
waitingFor: string?

Read-only. Names the signal this playback is blocked on.

waitingQuery#
waitingQuery: string?

Read-only. Names the query this playback is blocked on.

waitingCondition#
waitingCondition: QueryCondition?

Read-only. Reports the query condition this playback waits for.

waitingAwaitable#
waitingAwaitable: string?

Read-only. Names the awaitable provider this playback is blocked on.

waitingAwaitableEntity#
waitingAwaitableEntity: integer?

Read-only. Names the entity this playback's awaitable is asked about.

waitingTween#
waitingTween: Handle?

Read-only. Identifies the playback this one is blocked on.

tweenOutcome#
tweenOutcome: TweenOutcome?

Read-only. Reports how the last awaited playback ended.

branches#
branches: integer

Read-only. Counts live branches this playback forked and has not joined.

joining#
joining: boolean

Read-only. Reports whether this playback waits at a join.

fault#
fault: FaultReason?

Read-only. Explains a faulted playback.

faultMessage#
faultMessage: string?

Read-only. Reports the message accompanying a fault.

Steprecord#

record Step
    ticks: integer
    kind: string
    name: string
    args: {any}
end

Describes one step a playback reaches without branching.

Fields

ticks#
ticks: integer

Read-only. Counts ticks of the program's clock from the reference point until this step runs.

kind#
kind: string

Read-only. Holds "call" or "emit".

name#
name: string

Read-only. Names the action for a call or the event for an emit.

args#
args: {any}

Read-only. Carries the step's constants, unresolved. This list is the program's own rather than a copy, so read it and do not write to it.

Targetrecord#

record Target
    id: string
    componentName: string
    component: components.Component?
    fields: {string}
    mode: TargetMode
end

Describes the component and one to four numeric fields a timeline operation writes.

Fields

id#
id: string

Read-only. Identifies this target in a compiled slot. A built-in carries its TargetName; one built from a component carries the component name joined to its fields.

componentName#
componentName: string

Read-only. Names the component whose fields move.

component#
component: components.Component?

Engine-owned. Caches the resolved component, which a target restored from a snapshot looks up on first use.

fields#
fields: {string}

Read-only. Names the fields written, in the order the destinations line up with them.

mode#
mode: TargetMode

Read-only. Selects how the destinations are interpreted.

TargetNametype#

type TargetName = "transform.x"
| "transform.y"
| "transform.xy"
| "transform.rotation"
| "transform.rotationShortest"
| "transform.scaleX"
| "transform.scaleY"
| "transform.scaleXY"
| "color.a"
| "color.rgba"

Names a built-in component-field target.

TimelineNoderecord#

record TimelineNode
    kind: OperationKind
    duration: number?
    easingName: EasingName?
    target: Target?
    source: TrackSource?
    t1: number?
    t2: number?
    t3: number?
    t4: number?
    name: string?
    nested: {TimelineNode}?
    mode: PlaybackMode?
    count: integer?
    branches: {{TimelineNode}}?
end

Represents one authored timeline operation.

Fields

kind#
kind: OperationKind

Read-only. Names the operation.

duration#
duration: number?

Read-only. Reports the seconds this operation occupies.

easingName#
easingName: EasingName?

Read-only. Names the curve an interpolation follows.

target#
target: Target?

Read-only. Selects the component fields an interpolation writes.

source#
source: TrackSource?

Read-only. Selects where a tracking interpolation reads its destination.

t1#
t1: number?

Read-only. Carries the destination for the target's first field.

t2#
t2: number?

Read-only. Carries the destination for the second field.

t3#
t3: number?

Read-only. Carries the destination for the third field.

t4#
t4: number?

Read-only. Carries the destination for the fourth field.

name#
name: string?

Read-only. Names the event an emit operation fires.

nested#
nested: {TimelineNode}?

Read-only. Carries the nested spec a run operation plays.

mode#

Read-only. Selects how a run operation repeats.

count#
count: integer?

Read-only. Counts the passes a repeating run operation makes.

branches#
branches: {{TimelineNode}}?

Read-only. Carries one block per concurrent branch of a parallel operation.

TimelineOptionstype#

type TimelineOptions = {clock: ClockId?}

Configures timeline.

TrackingTargetrecord#

record TrackingTarget
    entity: integer
    key: string
end

Selects a dynamic tracking-source entity.

Fields

entity#
entity: integer

Caller-writable. Names the source entity directly, or zero for none.

key#
key: string

Caller-writable. Names the source entity by world key when entity is zero. Resolution follows the current live claimant on every evaluation. This persisted field name is a compatibility surface.

TrackSourcerecord#

record TrackSource
    kind: TrackSourceKind
    key: string?
    relationshipName: string?
    relationship: components.Component?
    componentName: string
    component: components.Component?
    fields: {string}
end

Provides a live component-field tracking source.

Fields

kind#
kind: TrackSourceKind

Read-only. Selects which entity the source reads from.

key#
key: string?

Read-only. Names the world key a keyed source resolves on every evaluation.

relationshipName#
relationshipName: string?

Read-only. Names the relationship traversed by a related source.

relationship#
relationship: components.Component?

Engine-owned. Caches the resolved relationship component.

componentName#
componentName: string

Read-only. Names the component the source reads.

component#
component: components.Component?

Engine-owned. Caches the resolved component.

fields#
fields: {string}

Read-only. Names the fields read, lined up with the target's own.

TweenOutcometype#

type TweenOutcome = "completed" | "canceled" | "replaced" | "targetLost"

Reports how the playback awaited by waitTween ended.

Functions#

activeCountfunction#

function activeCount(exclusive world: ecs.World): integer

Returns the number of live playbacks, for tests and diagnostics.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playbacks

Returns

TypeDescription
integer

the count, with branches and playTween-started playbacks counted individually

awaitfunction#

function await(provider: string, target: EntityRef, key: string?): Node

Builds a step that waits for work outside the sequencer to finish.

A subsystem registers a provider under a name and answers whether the work is still going; this parks the playback until it is not. The sequencer never learns what the work is, which is how a program waits on a sprite animation without the sequencer requiring the renderer. A binding that is missing or dead is not a fault, and neither is a provider reporting work that never started.

Arguments

NameTypeDescription
providerstring

the registered provider name, checked before the binding; an unregistered name faults the playback with unregisteredAwaitable

targetEntityRef

a bind reference and nothing else

keystring?

handed to the provider unread, for a provider that answers about more than one thing per entity

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the provider name is empty or the target is not a bind reference

bindfunction#

function bind(name: string): EntityRef

References an entity supplied through PlayOptions.bindings.

The reference resolves when the instruction using it runs rather than at play, so a binding may name an entity that does not exist yet. A missing binding resolves to nothing instead of faulting.

Arguments

NameTypeDescription
namestring

the binding name, which must not be empty

Returns

TypeDescription
EntityRef

a reference to put in a call or emit argument list, or to hand to playTween or await

Raises

  • when the name is empty

callfunction#

function call(action: string, ...: any): Node

Builds a step that runs a registered action.

The action name resolves per world when the instruction runs, so a program may name an action registered later. A name still unregistered when the step runs faults the playback with unregisteredAction. The step costs no tick.

Arguments

NameTypeDescription
actionstring

the registered action name

...any

the constants the action receives, which are the same values for every playback of this program; put anything that differs between two playbacks in PlayOptions.params instead

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the action name is empty

cancelfunction#

function cancel(exclusive world: ecs.World, handle: Handle): boolean

Stops a playback and releases its cursor.

This is safe on a finished handle. Cancelling takes the branches the playback forked with it, and a playback parked in a waitTween on the one canceled is told canceled and resumes. What a playTween started is a playback in its own right and is not canceled with the one that started it, unlike a pause, which cascades to it; stop it through its owner with cancelOwnedBy.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playback

handleHandle

the playback to stop, read against this world's cursor arena

Returns

TypeDescription
boolean

false when the handle names nothing running, whether it already finished or was already canceled

cancelOwnedByfunction#

function cancelOwnedBy(exclusive world: ecs.World, owner: integer, reason: TweenOutcome?): integer

Cancels every playback owned by an entity.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playbacks

ownerinteger

an entity id; nothing owns a playback started without an owner, so no argument reaches one and only cancel on its handle stops it

reasonTweenOutcome?

what a playback parked in a waitTween on one of these is told, defaulting to canceled

Returns

TypeDescription
integer

the number of canceled playbacks, counting each cursor once and reaching branches through their inherited owner

currentStepfunction#

function currentStep(exclusive world: ecs.World, clock: ClockId?): integer

Returns a clock's current tick as counted by the sequencer.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the clock counters

clockClockId?

which of the three counters to read, defaulting to "fixed"

Returns

TypeDescription
integer

the ticks of that one clock, counted from when this world's sequencer state was created and comparable only against another reading of the same clock

definefunction#

function define(name: string, nodes: {Node}, options: DefineOptions?): Program

Compiles a program under a stable symbolic name.

Defining over a name already in use publishes a new version rather than replacing the old one: playbacks already running keep the version they started on, and only later play calls see the new one.

Arguments

NameTypeDescription
namestring

the stable symbolic name, which is a snapshot compatibility surface

nodes{Node}

the authored steps, which may be empty, in which case the program completes on its first tick

optionsDefineOptions?

the clock the program's waits count, defaulting to "fixed"

Returns

TypeDescription
Program

the compiled program, immutable and shared by every playback of it, so the same value plays on any number of worlds

Raises

  • when the name is empty, the clock is not one of the three names, or an entry is not a step

disassemblefunction#

function disassemble(value: Program, pc: integer?): string

Renders a program as readable instructions.

Arguments

NameTypeDescription
valueProgram

a program from define or timeline

pcinteger?

the instruction to mark, as a playback's status reports it, or nil for an unmarked listing

Returns

TypeDescription
string

a header naming the program and its version, then one line per instruction, newline separated, for reading rather than for parsing

easingfunction#

function easing(name: EasingName): EasingFunction?

Returns a built-in easing curve by name.

Arguments

NameTypeDescription
nameEasingName

the curve name

Returns

TypeDescription
EasingFunction?

the curve, or nil when the name names no built-in

emitfunction#

function emit(event: string, ...: any): Node

Builds a step that emits a sequence event at address zero.

The step occupies no tick, so the step after it runs in the same one. Each emission copies its argument list and sends it with the event, so an observer may keep it, unlike the list an action receives.

Arguments

NameTypeDescription
eventstring

the name carried on the emission

...any

the constants delivered on the emission with every entity reference already resolved

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the event name is empty

evalfunction#

function eval(evaluator: string, data: any): Node

Builds a step that evaluates a registered evaluator every tick until it finishes.

Unlike every other step this one does not hand the tick back: the playback joins its clock's active set and the runtime steps it each tick. Values that move every frame need this behavior.

Arguments

NameTypeDescription
evaluatorstring

the registered evaluator name, resolved when the instruction runs; an unregistered name faults the playback with unregisteredEvaluator

dataany

the constant the evaluator receives, passed through its resolve once per program constant and shared by every playback, so it must remain plain data and the evaluator must not write per-playback state into it

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the evaluator name is empty

forkfunction#

function fork(nodes: {Node}): Node

Builds a step that starts a branch alongside the rest of the program.

The branch is a playback of its own running the same program at a different instruction, inheriting the owner, bindings, parameters, and instruction budget of the playback that forked it. It starts once that playback next waits, joins, or ends, within the same tick. A branch never outlives its parent, and a branch that faults takes its parent with it, faulted branchFaulted, rather than leaving a join one branch short forever.

Arguments

NameTypeDescription
nodes{Node}

the branch body, which must not be empty and which reads and writes the forking playback's own bindings table rather than a copy

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the block is empty

hasActionfunction#

function hasAction(exclusive world: ecs.World, name: string): boolean

Reports whether a world has registered an action name.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the action registry

namestring

the action name to find

Returns

TypeDescription
boolean

false for a name this world never registered, including one another world has

hasQueryfunction#

function hasQuery(exclusive world: ecs.World, name: string): boolean

Reports whether a world has registered a query name.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the query registry

namestring

the query name to find

Returns

TypeDescription
boolean

false for a name this world never registered

joinfunction#

function join(): Node

Builds a step that waits for every branch not yet joined.

It falls straight through when there are none, and when the last branch finishes the waiting playback resumes within that same tick.

Returns

TypeDescription
Node

a step for define, not to be put in a second program

loopfunction#

function loop(count: integer?, nodes: {Node}): Node

Builds a step that repeats a block.

Arguments

NameTypeDescription
countinteger?

the iterations, or nil to repeat until canceled

nodes{Node}

the block, which must not be empty and which is run in order and started again from its first node

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the count is not a positive whole number, or the block is empty

parallelfunction#

function parallel(blocks: {{Node}}): Node

Builds a step that forks several blocks and waits for all of them.

This is a fork per block followed by one join. Blocks start in argument order, and each shares the playback's bindings table as a fork does.

Arguments

NameTypeDescription
blocks{{Node}}

one non-empty block per branch

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when no block is supplied or one of them is empty

pausefunction#

function pause(exclusive world: ecs.World, handle: Handle, holder: string?): boolean

Suspends a playback, its branches, and anything it started.

Pause is holder counted: two systems can hold the same playback for unrelated reasons, and it runs again only when the last one lets go, so whichever resumes first cannot undo the other. Its wait, if any, resumes from where it paused, and what it is waiting on stops with it when the awaitable provider knows how.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playback

handleHandle

the playback to pause

holderstring?

any string, treated as a set rather than a count, so two pauses under the same holder are one hold; it defaults to "user"

Returns

TypeDescription
boolean

whether the playback stopped, which is false when another holder already had it or the handle names nothing running

playfunction#

function play(exclusive world: ecs.World, value: Program, options: PlayOptions?): Handle

Starts a program.

The first instruction runs on the next tick of the program's own clock, never inside this call.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the new playback

valueProgram

a program from define or timeline, not a name; the playback runs this version for its whole life

optionsPlayOptions?

the owner, bindings, parameters, budget, and channel; taking a channel another playback on the same owner holds cancels that one first, reporting replaced to anything waiting on it

Returns

TypeDescription
Handle

a handle to the new playback, carrying a generation so one whose playback has ended never names a later playback that took the same slot

playbacksfunction#

function playbacks(exclusive world: ecs.World): {Handle}

Returns handles for every live playback in a stable order.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playbacks

Returns

TypeDescription
{Handle}

a caller-owned table ordered by cursor slot, which is stable within a run but differs from creation order because new playbacks reuse free slots

playTweenfunction#

function playTween(timeline: string, target: EntityRef, params: {[string]: any}?): Node

Builds a step that plays a registered timeline on a bound entity.

The step costs no tick. It starts a separate playback owned by the bound entity, running on the named program's clock and using this playback's instruction budget. A binding that is missing or dead is not a fault: nothing plays, and a following waitTween resumes at once reporting targetLost.

Arguments

NameTypeDescription
timelinestring

the timeline name, resolved when the instruction runs and always to the newest version; an undefined name faults the playback with unregisteredTween

targetEntityRef

a bind reference and nothing else

params{[string]: any}?

the started playback's parameters, so mode, count, speed, delay and channel shape it as they do for play

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the timeline name is empty or the target is not a bind reference

pluginfunction#

function plugin(exclusive world: ecs.World): nil

Installs the sequencer into a world.

Installing twice on the same world does nothing, so a world that scripts input may install the sequencer itself rather than relying on the application having done it.

Arguments

NameTypeDescription
exclusive worldecs.World

the world receiving sequencer state, systems, and the snapshot handler

Returns

TypeDescription
nil

programfunction#

function program(name: string, version: integer?): Program?

Returns the newest version of a defined program, or a requested version.

Every version a playback still runs stays reachable, and the newest version of a name is never dropped.

Arguments

NameTypeDescription
namestring

a name previously passed to define or timeline

versioninteger?

the version to look up, starting at one, or nil for the newest

Returns

TypeDescription
Program?

the program, or nil when the name was never defined or that version has been dropped

programNamesfunction#

function programNames(): {string}

Returns the names of every defined program, sorted.

Returns

TypeDescription
{string}

a caller-owned list; registration is process-wide, so this spans every world in the process

registerActionfunction#

function registerAction(exclusive world: ecs.World, name: string, action: Action): nil

Registers an action a call step can name.

Actions must obey the deterministic-action contract to keep replay and rewind meaningful: no wall-clock reads, no file or network access, and randomness only from a generator whose state travels with the snapshot.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the action registry

namestring

the action name, which is per world unlike an evaluator or an awaitable; registering it twice replaces the action, and a playback resolves the name at each call, so one already running picks the new one up

actionAction

the body, which faults its playback with actionError when it raises, leaving whatever it already wrote to the world written

Returns

TypeDescription
nil

Raises

  • when the name is empty

registerAwaitablefunction#

function registerAwaitable(name: string, provider: Awaitable): nil

Registers a provider an await step can name.

Registration is process-wide, like an evaluator, because a provider is code. Registering a name twice replaces the provider, so a playback already parked on the name asks the new one at the next fixed step.

Arguments

NameTypeDescription
namestring

the provider name

providerAwaitable

the provider, which must carry isPending; without setPaused it leaves its work running when a pause stops the waiting playback

Returns

TypeDescription
nil

Raises

  • when the name is empty or the provider has no isPending

registerEvaluatorfunction#

function registerEvaluator(name: string, evaluator: Evaluator): nil

Registers an evaluator an eval step can name.

Registration is process-wide, like a program: an evaluator is code, and two worlds evaluating the same name run the same thing. Registering a name twice replaces it.

Arguments

NameTypeDescription
namestring

the evaluator name

evaluatorEvaluator

the evaluator, which must carry step; without save and load a playback evaluating this name comes back from a snapshot at the start of its state rather than where it was

Returns

TypeDescription
nil

Raises

  • when the name is empty or the evaluator has no step

registerQueryfunction#

function registerQuery(exclusive world: ecs.World, name: string, descriptor: ecs.QueryDescriptor): nil

Registers a query a waitQuery step can name.

Registering a name again re-tests every playback already parked on it, against the new query, at the next fixed step.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the query registry

namestring

the query name

descriptorecs.QueryDescriptor

the include and exclude constraints

Returns

TypeDescription
nil

Raises

  • when the name is empty

resumefunction#

function resume(exclusive world: ecs.World, handle: Handle, holder: string?): boolean

Releases one holder's claim on a paused playback.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playback

handleHandle

the paused playback

holderstring?

the string that took the hold, defaulting to "user"; releasing one that never held it changes nothing

Returns

TypeDescription
boolean

whether the playback started running again, which is true only for the last holder to let go; a wake time that passed while it was held runs it on the next tick rather than immediately

setInstructionBudgetfunction#

function setInstructionBudget(exclusive world: ecs.World, instructions: integer): nil

Sets the per-tick instruction budget for playbacks that ask for none.

The budget caps how many instructions one playback runs per tick, and exceeding it faults the playback with budgetExceeded rather than deferring the rest, so it guards against a loop with no wait in it rather than acting as a scheduler. It applies to playbacks started after this call.

Arguments

NameTypeDescription
exclusive worldecs.World

the world the budget applies to

instructionsinteger

the budget, which must be at least one

Returns

TypeDescription
nil

Raises

  • when the budget is less than one

setNominalFrameTimefunction#

function setNominalFrameTime(exclusive world: ecs.World, seconds: number): nil

Sets the nominal frame duration a frame or presentation wait converts seconds against.

The nominal duration is used rather than a frame's measured time because a wake is a tick number fixed when the wait runs and never revisited.

Arguments

NameTypeDescription
exclusive worldecs.World

the world whose future waits use this duration.

secondsnumber

the positive finite nominal duration in seconds.

Returns

TypeDescription
nil

Raises

  • when the duration is not positive and finite.

signalfunction#

function signal(exclusive world: ecs.World, name: string): integer

Raises a named signal and wakes every playback blocked on it.

Delivery happens on the next fixed step. Raising a signal nothing waits on is not an error and is not remembered: a playback that reaches waitSignal afterwards keeps waiting.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the signal state

namestring

the signal name, registered nowhere

Returns

TypeDescription
integer

the number of playbacks waiting on the name now, which may differ from the set the next fixed step wakes

Raises

  • when the name is empty

signalOnEventfunction#

function signalOnEvent<E is events.Emittable>(exclusive world: ecs.World, name: string, event: Type<E>): nil

Raises a signal whenever an event emits at address zero.

An ECS event is an edge, like a signal, so this wires one to the other rather than adding a separate kind of wait. Delivery follows the ordinary signal rule and waiters wake on the next fixed step.

Type parameters

NameDescription
E

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the observer and the signal state

namestring

the signal to raise, once per emission

eventType<E>

the event definition, observed at address zero and only there; the observer lasts for the life of the world

Returns

TypeDescription
nil

Raises

  • when the name is empty

sourceKeyfunction#

function sourceKey(key: string, component: ecs.Component, fields: {string}): TrackSource

Reads a moving destination from the live entity holding a world key. Missing or despawned sources contribute zero until a live entity claims the key.

Arguments

NameTypeDescription
keystring

the non-empty key resolved on every evaluation.

componentecs.Component

the component to read from that entity.

fields{string}

the fields aligned with the target's fields.

Returns

TypeDescription
TrackSource

the keyed tracking source.

Raises

  • when the key is empty.

sourceOwnfunction#

function sourceOwn(component: ecs.Component, fields: {string}): TrackSource

Reads a moving destination from the animated entity itself.

Arguments

NameTypeDescription
componentecs.Component

the component read

fields{string}

the fields read, lined up with the target's own

Returns

TypeDescription
TrackSource

the source

sourceRelatedfunction#

function sourceRelated(relationship: ecs.Component, component: ecs.Component, fields: {string}): TrackSource

Reads a moving destination from the entity a relationship points at.

Arguments

NameTypeDescription
relationshipecs.Component

the relationship traversed from the animated entity

componentecs.Component

the component read on the target entity

fields{string}

the fields read, lined up with the target's own

Returns

TypeDescription
TrackSource

the source

sourceTrackingfunction#

function sourceTracking(component: ecs.Component, fields: {string}): TrackSource

Reads a moving destination from the entity named by the animated entity's TrackingTarget.

Arguments

NameTypeDescription
componentecs.Component

the component read

fields{string}

the fields read, lined up with the target's own

Returns

TypeDescription
TrackSource

the source

statusfunction#

function status(exclusive world: ecs.World, handle: Handle): Status?

Returns a playback's status.

A finished playback still answers, with state saying how it ended, until a later play takes its slot. The waiting fields are filled only while the playback lives.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playback

handleHandle

the playback to inspect, read against this world's cursor arena

Returns

TypeDescription
Status?

a caller-owned status, or nil for a handle this world never issued

targetAnglefunction#

function targetAngle(component: ecs.Component, fieldName: string): Target

Interpolates one field as an angle, taking the short way round.

Arguments

NameTypeDescription
componentecs.Component

the component whose field moves

fieldNamestring

the radian-valued field name

Returns

TypeDescription
Target

the target

targetFieldfunction#

function targetField(component: ecs.Component, fieldName: string): Target

Interpolates one numeric field of a component.

Arguments

NameTypeDescription
componentecs.Component

the component whose field moves

fieldNamestring

the field name

Returns

TypeDescription
Target

the target, which holds no per-playback state and is safe to share

targetField2function#

function targetField2(component: ecs.Component, first: string, second: string): Target

Interpolates two numeric fields of a component together.

Arguments

NameTypeDescription
componentecs.Component

the component whose fields move

firststring

the field the first destination lines up with

secondstring

the field the second destination lines up with

Returns

TypeDescription
Target

the target

timelinefunction#

function timeline(name: string, spec: {TimelineNode}, options: TimelineOptions?): Program

Compiles a tween timeline into a program under a stable name.

The compiled slots travel in the program's constant pool, so a timeline is snapshot safe for the same reason every other program is. Play it with play, giving the entity it animates as the owner: a playback with no owner has nothing to write to and completes on its first tick.

A playback reads four parameters, all optional: mode is "once", "loop", or "pingPong"; count is the passes a finite repeat makes; speed is a playback multiplier defaulting to one; and delay is the seconds to wait before the first frame. They are read when the playback builds its state, so a speed of zero or less, a negative delay, or a repeat of a zero-length timeline faults the playback with actionError rather than raising from play.

Arguments

NameTypeDescription
namestring

the stable symbolic name, sharing define's namespace and versioning

spec{TimelineNode}

the timeline operations in execution order

optionsTimelineOptions?

the clock the timeline is evaluated against, defaulting to "presentation"; "fixed" makes it deterministic from a snapshot alone at the cost of stepping at the simulation's rate

Returns

TypeDescription
Program

the compiled program, also reachable by name through program

Raises

  • when the clock is neither "fixed" nor "presentation", or an operation is invalid

tweenAdjustfunction#

function tweenAdjust(duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, t1: number, t2: number?, t3: number?, t4: number?): TimelineNode

Builds a timeline operation that interpolates by a delta from the starting value.

Arguments

NameTypeDescription
durationnumber

the seconds it occupies, which must be greater than zero

curveEasingName | EasingFunction

a name from the built-in curves, or one of those curve values

targetTargetName | Target

which component fields move and in which order

t1number

the signed change applied to the target's first field

t2number?

the change applied to the second field

t3number?

the change applied to the third field

t4number?

the change applied to the fourth field

Returns

TypeDescription
TimelineNode

an operation for a timeline spec

Raises

  • when the curve names no built-in

tweenEmitfunction#

function tweenEmit(name: string): TimelineNode

Builds a timeline operation that emits a named sequence event.

It occupies no time, so what follows it starts at the same instant. The emission carries the entity the timeline is animating as its one argument and the timeline's own playback as its handle. It fires as the cursor passes the point going forward, so a ping-pong return leg does not fire it a second time.

Arguments

NameTypeDescription
namestring

the name carried on the emission

Returns

TypeDescription
TimelineNode

an operation for a timeline spec

tweenParallelfunction#

function tweenParallel(blocks: {{TimelineNode}}): TimelineNode

Builds a timeline operation that runs blocks concurrently and ends with the longest.

Every block starts where the operation sits, and what follows starts after the last of them ends. Two blocks writing the same component field is not an error, and the later one in argument order wins each tick.

Arguments

NameTypeDescription
blocks{{TimelineNode}}

one block per concurrent branch, each run in sequence within itself

Returns

TypeDescription
TimelineNode

an operation for a timeline spec

tweenRunfunction#

function tweenRun(spec: {TimelineNode}, options: RunOptions?): TimelineNode

Builds a timeline operation that runs a nested timeline from its own spec.

The nested timeline occupies a window of the parent equal to its own length times its pass count, so a repeating nested run needs a finite count. Its operations keep their per-playback state separately from the parent's.

Arguments

NameTypeDescription
spec{TimelineNode}

the nested operations, which this call reads rather than rewrites

optionsRunOptions?

omit to run the nested timeline once; "loop" and "pingPong" need a count here

Returns

TypeDescription
TimelineNode

an operation for a timeline spec

Raises

  • when a repeating nested run carries no finite count

tweenTofunction#

function tweenTo(duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, t1: number, t2: number?, t3: number?, t4: number?): TimelineNode

Builds a timeline operation that interpolates to an absolute destination.

The operation reads its starting values from the entity on its first tick rather than during compilation, so the same timeline played on two entities starts from wherever each of them is.

Arguments

NameTypeDescription
durationnumber

the seconds it occupies, which must be greater than zero

curveEasingName | EasingFunction

a name from the built-in curves, or one of those curve values

targetTargetName | Target

which component fields move and in which order the destinations line up with them

t1number

the destination for the target's first field, in that field's own units: pixels for a translate, radians for a rotation, zero through one for a color channel

t2number?

the destination for the second field

t3number?

the destination for the third field

t4number?

the destination for the fourth field, with anything past the target's field count ignored and an omitted field treated as zero

Returns

TypeDescription
TimelineNode

an operation for a timeline spec

Raises

  • when the curve names no built-in

tweenTrackfunction#

function tweenTrack(duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, from: TrackSource): TimelineNode

Builds a timeline operation that interpolates toward a destination that keeps moving.

The first tick fixes the start as tweenTo does, and each later tick reads the destination again while the operation remains inside its window. Once the window ends the operation holds its last destination. A source whose entity or component is missing reads as zero rather than faulting.

Arguments

NameTypeDescription
durationnumber

the seconds it occupies, which must be greater than zero

curveEasingName | EasingFunction

a name from the built-in curves, or one of those curve values

targetTargetName | Target

which component fields move and which fields of the source line up with them

fromTrackSource

where the destination is read each tick

Returns

TypeDescription
TimelineNode

an operation for a timeline spec

Raises

  • when the curve names no built-in

tweenWaitfunction#

function tweenWait(duration: number): TimelineNode

Builds a timeline operation that advances the cursor without changing anything.

Arguments

NameTypeDescription
durationnumber

the seconds it occupies, where zero performs no work

Returns

TypeDescription
TimelineNode

an operation for a timeline spec

upcomingfunction#

function upcoming(exclusive world: ecs.World, handle: Handle, withinTicks: integer?): {Step}

Returns the actions and emissions a playback will certainly perform next, and their timing.

The walk covers the straight-line run ahead of where the playback sits, accumulating waits, and stops at the first instruction whose successor requires execution.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the playback

handleHandle

the playback to inspect

withinTicksinteger?

report only what is due within this many ticks of the playback's own clock, or nil for everything the walk can reach

Returns

TypeDescription
{Step}

a caller-owned list of the calls and emissions ahead, in order; empty for a handle that names nothing running and for one parked on a signal, a query, a join, a tween, or an evaluator, since none of those has a predictable start. A wait written in seconds also ends the walk.

waitfunction#

function wait(seconds: number): Node

Builds a step that waits a duration in seconds.

The duration converts to whole ticks when the instruction runs, rounded to nearest, and any non-zero duration waits at least one tick. Zero still costs a tick: the cursor resumes on the program's next tick rather than carrying on within this one.

Arguments

NameTypeDescription
secondsnumber

the non-negative duration

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the duration is negative

waitingOnfunction#

function waitingOn(exclusive world: ecs.World, name: string): integer

Returns how many playbacks currently wait on a signal name.

Arguments

NameTypeDescription
exclusive worldecs.World

the world that owns the waiting playbacks

namestring

the signal name to count

Returns

TypeDescription
integer

zero for a name nothing waits on; a signal raised during this step leaves its waiters in the count until the next step delivers it

waitQueryfunction#

function waitQuery(name: string, condition: QueryCondition): Node

Builds a step that blocks until a registered query matches or stops matching.

Unlike a signal, which is an edge, this is a condition on the world: a wait whose condition already holds resumes rather than waiting for a transition that has already happened. The condition is evaluated at the start of a fixed step rather than at the instruction, so a query wait costs at least one step.

Arguments

NameTypeDescription
namestring

the registered query name, resolved per world when the instruction runs

conditionQueryCondition

"any" to wait for a match or "empty" to wait for none

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the name is empty or the condition is neither value

waitSignalfunction#

function waitSignal(name: string): Node

Builds a step that blocks until signal raises a named signal.

The next fixed step delivers signals after signal runs, so a signal one sequence raises never runs another within the same step. A signal raised before the wait is not remembered.

Arguments

NameTypeDescription
namestring

the signal name, which is registered nowhere

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the name is empty

waitStepsfunction#

function waitSteps(steps: integer): Node

Builds a step that waits a whole number of ticks of the program's clock.

Arguments

NameTypeDescription
stepsinteger

the non-negative tick count, where zero yields until the next tick

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Raises

  • when the count is negative or not a whole number

waitTweenfunction#

function waitTween(): Node

Builds a step that waits for the playback the most recent playTween started.

It resumes when that specific playback completes, is canceled, loses its channel, or loses its entity, so it never waits forever, and status reports the outcome as tweenOutcome. A waitTween that no playTween preceded falls straight through without costing a tick.

Returns

TypeDescription
Node

a step for define, not to be put in a second program

Values#

DEFAULT_BUDGETvariable#

const DEFAULT_BUDGET: integer

The per-tick instruction budget a world gives a playback that asks for none.

TrackingTargetvariable#

const TrackingTarget: components.TableComponent<TrackingTarget>

The process-wide component a tweenTrack tracking source reads.