spawn
SourceStarts a staged entity definition.
Use this inside a system to build an entity with an exact compile-time component proof before the spawn command is queued.
Core
Deferred command builders and typed entity-draft helpers.
This module exists for the part of ECS work that wants to describe mutation now and make it visible later. Systems often decide that an entity should be spawned, despawned, or extended while iterating queries, but the actual world change is intentionally deferred until the schedule reaches Game.Schedule.applyDeferred().
Command is therefore the write-side companion to Query:
Reach for this module when gameplay logic needs explicit world mutation, especially for setup, reset, projectiles, pickups, despawns, and relation edits that should stay schedule-visible instead of happening implicitly.
// Build drafts as values so spawn intent stays explicit inside the system.
const EnemyWave = Game.System("EnemyWave", {}, ({ commands }) =>
Fx.sync(() => {
const enemy = Game.Command.spawnWithMixed(
// Validate raw authored input through the constructed descriptor.
Game.Command.entryRaw(Position, { x: 96, y: 32 }),
// Add already-validated marker or config components directly.
Game.Command.entry(Enemy, {}),
Game.Command.entry(Health, 3)
)
if (!enemy.ok) {
return
}
// Queue the world write now. The entity becomes visible later.
commands.spawn(enemy.value)
})
)
// Make the deferred mutation boundary part of the schedule itself.
const update = Game.Schedule(
EnemyWave,
Game.Schedule.applyDeferred(),
observeSpawnedEnemies
)
Starts a staged entity definition.
entryCreates a typed component entry.
entryResultLifts a validated result into a typed component entry result.
entryRawCreates a typed component entry by validating raw input through a constructed descriptor.
insertAdds a component to an entity draft and returns a more precise draft type.
insertManyAdds multiple components to an entity draft in one flat call.
insertResultinsertRawInserts one raw component value into a draft through a constructed descriptor.
relateStages one outgoing relation edge on an entity draft.
spawnWithStarts a staged entity definition and inserts multiple components at once.
spawnWithResultspawnWithMixedStarts a staged entity definition from a mix of plain validated entries and explicit result-wrapped entries.
makeCommandsCreates a fresh command queue for a system execution.
Public command builders that stage entity and component mutations as explicit values.
Starts a staged entity definition.
Use this inside a system to build an entity with an exact compile-time component proof before the spawn command is queued.
Creates a typed component entry.
Use this when building drafts through the flat variadic helpers and you want the component/value pairing to stay visually explicit. It is especially useful once entries come from small factories or conditional branches rather than inline tuple literals.
Lifts a validated result into a typed component entry result.
This is the bridge between constructor-first validation and command authoring: validate a value separately, then preserve that success/failure shape while turning it into an entry for spawnWithResult(...) or spawnWithMixed(...).
Creates a typed component entry by validating raw input through a constructed descriptor.
Use this when spawn or reset data starts as raw numbers, vectors, sizes, or other host/authored input and you want the command path itself to surface validation failure explicitly.
// Keep raw input validation attached to the descriptor that owns it.
const position = Game.Command.entryRaw(Position, { x: 10, y: 20 })
// Carry the result forward into a mixed draft builder.
const draft = Game.Command.spawnWithMixed(
position,
Game.Command.entry(Player, {})
)
Adds a component to an entity draft and returns a more precise draft type.
This is the command-building equivalent of a typed builder pattern: each call enriches the proof carried by the draft.
Adds multiple components to an entity draft in one flat call.
This preserves the same exact proof precision as repeated insert(...) calls, but folds the proof internally instead of forcing users to nest builders manually.
No description provided yet.
Inserts one raw component value into a draft through a constructed descriptor.
const updated = Game.Command.insertRaw(
Game.Command.spawn(),
Position,
{ x: 12, y: 18 }
)
Stages one outgoing relation edge on an entity draft.
Drafts stay pure: this only records intent so the runtime can attempt to attach the relation when the spawn command is flushed.
Starts a staged entity definition and inserts multiple components at once.
This is the recommended authoring API for new entity drafts because it keeps the exact proof typing without the visual noise of nested insert(...) chains.
Reset and restart systems should prefer this helper when rebuilding world content after a transition boundary, because it keeps respawn logic flat and explicit.
This is also the normal bootstrap/setup path for initial world content: build one typed draft with spawnWith(...), then queue it through commands.spawn(...) and commit it later at the schedule's applyDeferred() boundary.
When the same entity shape appears more than once, the normal scaling path is to extract a small local draft factory that just returns Game.Command.spawnWith(...). Keep spawning explicit through commands.spawn(...).
const SetupSystem = Game.System("Setup", {}, ({ commands }) =>
Fx.sync(() => {
commands.spawn(
Game.Command.spawnWith(
[Position, { x: 0, y: 0 }],
[Velocity, { x: 1, y: 0 }]
)
)
})
)
const makeProjectileDraft = (x: number, y: number) =>
Game.Command.spawnWith(
[Position, { x, y }],
[Velocity, { x: 4, y: 0 }]
)
No description provided yet.
Starts a staged entity definition from a mix of plain validated entries and explicit result-wrapped entries.
This is the practical "normal game code" helper when some components are already valid and others must cross a constructor boundary first. It keeps the whole spawn path flat while still refusing to hide validation failure.
// Validate only the components that need constructor-backed checks.
const draft = Game.Command.spawnWithMixed(
Game.Command.entryRaw(Position, { x: 8, y: 12 }),
Game.Command.entryRaw(Collider, { width: 12, height: 12 }),
// Keep plain marker/data components inline when no extra validation is needed.
Game.Command.entry(Player, {}),
Game.Command.entry(Health, 5)
)
if (!draft.ok) {
return
}
// Queue the staged entity after all component inputs are known to be valid.
commands.spawn(draft.value)
Creates a fresh command queue for a system execution.
The returned API is intentionally imperative for system authors, but all mutations stay deferred until flush() is applied by the runtime.