Declares that a system needs a service from the external runtime environment.
Use this for host capabilities that should not live in ECS world storage:
clocks, random generators, render bridges, audio sinks, persistence APIs,
or network clients. The matching implementation must be supplied when the
runtime is created with Game.Runtime.services(...).
Creates a resource-read declaration for a system spec.
Use this for world-level singleton data the system needs to observe but must
not mutate, such as delta time, score snapshots, configuration, or
aggregated frame input. The resulting context slot is a read-only
ReadCell.
Creates a resource-write declaration for a system spec.
Use this when the system owns mutation of one world-level singleton, such as
score, UI summaries, accumulated damage, or frame-local caches. Declaring it
here makes that authority visible in the system contract before the body is
read.
const CountUp = Game.System("CountUp", {
resources: {
score: Game.System.writeResource(Score)
}
}, ({ resources }) => {
// Mutate the singleton through the explicit write cell.
resources.score.update((score) => score + 1)
})
Creates an event-read declaration for a system spec.
Each run of the reading system sees the events published since its own
previous completed run, once, in emission order: events from earlier
systems in the same schedule, and events emitted after it ran last time.
Events are kept until every system that reads them has run, so a reader in
a schedule ticked less often than the emitter's (a fixed update below the
render rate) still receives all of them. Events nobody has read yet are
kept for the current and previous runtime.tick(...) call; a reader's
first run sees whatever is still kept. A system skipped by its run
conditions discards the events published meanwhile. Each stream is capped
at Runtime.streamCapacity entries; a reader that missed dropped ones sees
lagged() === true.
This is the usual second half of a cross-system flow: one system emits an
event, and a later system reads it and re-validates any handles or lookups
it needs.
Creates an event-write declaration for a system spec.
Emitted events are published when the system completes successfully; a
failed run publishes nothing. Readers later in the same schedule see them,
and so do readers that run in a later tick.
If the payload needs to name an entity for later work, emit a durable
Game.Entity.handle(...) (optionally with an intent component) and let the later
reader re-resolve it through lookup.getHandle(...).
const EmitHit = Game.System("EmitHit", {
events: {
hit: Game.System.writeEvent(Hit)
}
}, ({ events }) => {
events.hit.emit({ amount: 1 })
})
Declares read access to the current committed value of a finite-state machine.
Use this when gameplay logic needs to branch on the current committed phase,
but should not see queued next-state writes early. Machines are the intended
default for menus, rounds, encounters, pause flows, and other discrete modes
whose transition boundary matters.
Declares queued write access to the next value of a finite-state machine.
This is the system-side request channel for a future phase change. It does
not immediately switch the committed state; the queued value is applied only
at an explicit Game.Schedule.applyStateTransitions(...) boundary.
Use this instead of writing a plain resource when the transition timing itself is
part of the gameplay model, such as restarting a round, leaving a menu, or
entering a results screen after reset/setup schedules run.
Declares read access to the last applied transition payload of a machine.
Declares read access to committed transition events for one machine.
Transition events are published when a transition commits and read like
normal events: each run sees those published since its previous run.
This is one of the clearest signs that the modeled value should be a machine
rather than a plain state descriptor.
Declares read access to removed-component lifecycle records.
Each run returns the entities whose component was removed since the
system's previous run (removals are applied when commands are). Records are
kept until every system that reads them has run, so a reader in a schedule
ticked less often than the one that removes (rendering after several fixed
updates) still sees every removal. A system skipped by its run conditions
keeps its position, like added/changed, and sees the removals when it
runs again. Each log is capped at Runtime.streamCapacity entries; drops
show up as missed reads in the debug trace. Systems usually pair this
with host cleanup such as removing renderer-owned nodes. readDespawned
complements this for whole-entity teardown.
const DestroyRenderNodesSystem = Game.System("DestroyRenderNodes", {
removed: {
renderables: Game.System.readRemoved(Renderable)
}
}, ({ removed }) => {
for (const entityId of removed.renderables.all()) {
// destroy host-owned node here
}
})
Declares read access to relation-mutation failure records.
Declares read access to despawned-entity lifecycle records.
Each run returns the entities despawned since the system's previous run.
Records are retained like readRemoved records. Use it when host-owned state must be destroyed even if no single removed
component is the canonical trigger. readRemoved is often used
alongside this in authoritative host mirrors.
const DestroyNodesSystem = Game.System("DestroyNodes", {
despawned: {
entities: Game.System.readDespawned()
}
}, ({ despawned }) => {
for (const entityId of despawned.entities.all()) {
// destroy host-owned node here
}
})
No description provided yet.