On this page
  1. tecs.ecs
  2. Module contents
    1. Submodules
    2. Constructors
    3. Types
    4. Functions
    5. Values
  3. Constructors
    1. newComponent
    2. newFFIComponent
    3. newFFIRelationship
    4. newRelationship
    5. newScalarComponent
    6. newTagComponent
    7. newWorld
  4. Types
    1. Archetype
    2. ArchetypeEntityObserver
    3. Bundle
    4. BundleDef
    5. Closeable
    6. Component
    7. ComponentOptions
    8. ContainerComponentOptions
    9. DoubleArray
    10. FFIComponentOptions
    11. FFIRelationshipOptions
    12. FixedOverload
    13. Phase
    14. phases
    15. Pipeline
    16. tecs.Plugin
    17. tecs.Query
    18. QueryCursor
    19. QueryDescriptor
    20. Relationship
    21. RelationshipOptions
    22. ScalarComponent
    23. ScalarComponentOptions
    24. Snapshot
    25. SnapshotComponentTableEntry
    26. SnapshotHandler
    27. SnapshotOptions
    28. SnapshotOutput
    29. SnapshotPrelude
    30. StatePolicy
    31. Stats
    32. tecs.System
    33. SystemConfig
    34. TagComponentOptions
    35. tecs.World
  5. Functions
    1. declaredComponents
    2. findComponentById
    3. findComponentByName
  6. Values
    1. ArchetypeCreated
    2. ChildOf
    3. DEFAULTMAXENTITIES
    4. Disabled
    5. EntityKey
    6. FinishSnapshotLoad
    7. MAX_ENTITIES
    8. Name
    9. OnDespawn
    10. OnSnapshotSave
    11. OnSpawn
    12. Paused
    13. RelativeTransform2D
    14. runif
    15. StartSnapshotLoad
    16. StateBlur
    17. StateEnter
    18. StateExit
    19. StateFocus
    20. Transform2D
    21. Transform3D
    22. TTL

tecs.ecs

The ECS shared by game code and engine systems.

Build queries during setup, reuse them from systems, and put all game state on entities:

local moving: tecs.Query

local function game(world: tecs.World)
    moving = world:newQuery({include = {tecs.Transform2D}})

    world:addSystem({
        name = "game.Drift",
        phase = tecs.ecs.phases.Update,
        run = function(delta: number)
            for archetype, length in moving:iter() do
                local transform <const> = archetype:getMut(
                    tecs.Transform2D
                )
                for row = 1, length do
                    transform[row].x = transform[row].x + 60 * delta
                end
            end
        end,
    })

    world:spawn(tecs.Transform2D(0, 0))
end

Read columns through archetype:get. Write through getMut so dirty-gated systems can find the change. See Worlds, Components, Queries, and Systems for the complete ECS model.

Module contents

Submodules

Submodule Description
Archetypes Archetype storage, column access, relationship lookups, dirty tracking, and lifecycle observers
Builtins The components, relationship, events and systems every world registers automatically, all on tecs.ecs
Components Component overview with world get, getMut, set, remove, has, requires, and transient
Events Address-based ECS events: observe, emit, hasObservers, newEvent, newFFIEvent, and the MessageBus router
Mutation model Mutation paths, entity lifecycle states, commit drain ordering, and visibility guarantees
Phases Game-loop phase groups and the world methods that control them
Plugins Plugins provide the one way into a world: entry arguments, composition, and patterns that scale
Profiling LuaJIT sampling profiler and trace-abort tracker through tecs.utils.profile
Queries Creating and iterating queries with include, exclude, includeAny, temp, cursors, and deferred mutations
Relationships Directed entity relationships, storage, deletion, and traversal
Save games Snapshot saving, loading, transient components, handlers, filtering, and binary format
State stack The world state stack, lifecycle policies, automatic tags, and transition events
Systems System configuration, ordering, removal, and tecs.ecs.runif predicates
World World entities, spawning, batches, deferred scopes, resources, plugins, phases, and stats
tecs.ecs.random Seeded named streams, standalone generators, and snapshot restoration

Constructors

Constructor Description
newComponent Creates and registers a new table component.
newFFIComponent Creates and registers an FFI-based component.
newFFIRelationship Creates an FFI-backed relationship with data fields.
newRelationship Creates and registers a relationship component.
newScalarComponent Creates and registers a new scalar component.
newTagComponent Creates and registers a tag component.
newWorld Creates a new World.

Types

Type Kind Description
Archetype interface Archetype stores contiguous component columns.
ArchetypeEntityObserver interface ArchetypeEntityObserver receives entity changes within an archetype.
Bundle interface Bundle names a reusable component collection.
BundleDef interface BundleDef configures a bundle.
Closeable interface An owned value that releases its active lifetime explicitly.
Component interface Component names any component definition.
ComponentOptions interface ComponentOptions configures a table component.
ContainerComponentOptions interface Shared options for creating different components.
DoubleArray interface DoubleArray names an FFI array of doubles.
FFIComponentOptions interface FFIComponentOptions configures an FFI component.
FFIRelationshipOptions interface FFIRelationshipOptions configures an FFI relationship.
FixedOverload enum FixedOverload selects fixed-step overload behavior.
Phase interface Phase identifies one system phase.
phases record Defines the predefined ECS phases, or lifecycle states, of the game and event loop.
Pipeline interface Pipeline identifies a world update pipeline.
Plugin type A plugin configures a world with systems, resources, observers, and initial entities.
Query interface A reusable filter over the archetypes in a world.
QueryCursor type QueryCursor controls an explicitly closed query traversal.
QueryDescriptor type QueryDescriptor configures a query.
Relationship interface Relationship names any relationship definition.
RelationshipOptions interface RelationshipOptions configures a relationship.
ScalarComponent interface ScalarComponent names a single-value component.
ScalarComponentOptions interface ScalarComponentOptions configures a scalar component.
Snapshot type Snapshot names serialized world state.
SnapshotComponentTableEntry type SnapshotComponentTableEntry identifies one component in a snapshot.
SnapshotHandler type SnapshotHandler saves and restores plugin data.
SnapshotOptions type SnapshotOptions controls snapshot serialization.
SnapshotOutput type SnapshotOutput collects serialized data.
SnapshotPrelude type SnapshotPrelude names snapshot metadata.
StatePolicy record StatePolicy controls state-stack participation.
Stats type Stats reports live world counts.
System type A system function runs once when its phase dispatches.
SystemConfig interface SystemConfig configures a system.
TagComponentOptions interface TagComponentOptions configures a tag component.
World interface A world owns entities, components, queries, systems, resources, events, snapshots, and the state stack.

Functions

Function Kind Description
declaredComponents Static Returns every component declared in this process.
findComponentById Static Returns a registered component by numeric id.
findComponentByName Static Returns the component registered under name.

Values

Value Type Description
ArchetypeCreated ArchetypeCreated Read-only. ArchetypeCreated fires at entity 0 after archetype creation.
ChildOf Relationship Read-only. ChildOf links a parent and child.
DEFAULT_MAX_ENTITIES integer Read-only. DEFAULTMAXENTITIES supplies 2^20 when world configuration omits maxEntities.
Disabled Component Read-only. Disabled excludes an entity from queries that do not ask for it.
EntityKey ScalarComponent Read-only. EntityKey stores a durable unique lookup key for world:byKey.
FinishSnapshotLoad FinishSnapshotLoad Read-only. FinishSnapshotLoad fires at entity 0 after every entity and data callback finishes restoration.
MAX_ENTITIES integer Read-only. MAX_ENTITIES sets the absolute World.Config.maxEntities ceiling (2^22 - 1 usable slots; the entity-id...
Name ScalarComponent Read-only. Name stores an entity label as a raw string.
OnDespawn OnDespawn Read-only. OnDespawn fires at an entity before removal.
OnSnapshotSave OnSnapshotSave Read-only. OnSnapshotSave fires at entity 0 before snapshot archetype serialization so plugins can attach keyed data...
OnSpawn OnSpawn Read-only. OnSpawn fires at an entity after spawning.
Paused Component Read-only. Paused excludes an entity from logic queries while keeping it visible.
RelativeTransform2D RelativeTransform2D Read-only. RelativeTransform2D expresses a pose relative to a ChildOf parent.
runif runIfHelpers Read-only. runif contains composable system run conditions.
StartSnapshotLoad StartSnapshotLoad Read-only. StartSnapshotLoad fires at entity 0 after world restoration and before data dispatch so plugins can...
StateBlur StateBlur Read-only. StateBlur fires at a state when another takes focus above it.
StateEnter StateEnter Read-only. StateEnter fires when a state enters the stack.
StateExit StateExit Read-only. StateExit fires when a state leaves the stack.
StateFocus StateFocus Read-only. StateFocus fires at a state when it regains focus.
Transform2D Transform2D Read-only. Transform2D positions everything a world holds.
Transform3D Transform3D Read-only. Transform3D places an entity in a right-handed 3D world.
TTL TTL Read-only. TTL despawns an entity when its time to live reaches zero.

Constructors

tecs.ecs.newComponent Static

Creates and registers a new table component. See ecs.ComponentOptions and the component docs for the shared fields / defaults / init / .new model.

function tecs.ecs.newComponent<C is Component>(
    options: ComponentOptions<C>
): C

Type Parameters

Name Constraint Description
C Component

Arguments

Name Type Description
options ComponentOptions<C> The caller supplies a process-unique name and the table component definition.

Returns

Type Description
C Returns the supplied container after permanent process-wide registration makes it callable.

tecs.ecs.newFFIComponent Static

Creates and registers an FFI-based component. Same constructor model as newComponent, but the base instance is an FFI struct.

function tecs.ecs.newFFIComponent<C is Component>(
    options: FFIComponentOptions<C>
): C

Type Parameters

Name Constraint Description
C Component

Arguments

Name Type Description
options FFIComponentOptions<C> The caller supplies fields that map to a C struct: numbers, booleans and fixed-size arrays.

Returns

Type Description
C Returns the registered component with contiguous cdata columns. Direct writes through world:get require world:markComponentDirty.

tecs.ecs.newFFIRelationship Static

Creates an FFI-backed relationship with data fields.

function tecs.ecs.newFFIRelationship<R is Relationship>(
    config: FFIRelationshipOptions<R>
): R

Type Parameters

Name Constraint Description
R Relationship

Arguments

Name Type Description
config FFIRelationshipOptions<R> The caller supplies relationship behavior and C-compatible edge fields.

Returns

Type Description
R Returns the registered relationship.

tecs.ecs.newRelationship Static

Creates and registers a relationship component.

A target-only relationship needs a name and flags. Add container and fields when each edge carries data.

function tecs.ecs.newRelationship<R is Relationship>(
    config: RelationshipOptions<R>
): R

Type Parameters

Name Constraint Description
R Relationship

Arguments

Name Type Description
config RelationshipOptions<R> The caller supplies target, exclusivity, sparsity, reverse index and cascade behavior.

Returns

Type Description
R Returns the registered relationship, callable with a target to create an instance.

tecs.ecs.newScalarComponent Static

Creates and registers a new scalar component.

function tecs.ecs.newScalarComponent<T>(
    options: ScalarComponentOptions<T>
): ScalarComponent<T>

Type Parameters

Name Constraint Description
T

Arguments

Name Type Description
options ScalarComponentOptions<T> The caller supplies the scalar type, name and defaults.

Returns

Type Description
ScalarComponent<T> Returns the registered component whose rows hold bare values.

tecs.ecs.newTagComponent Static

Creates and registers a tag component.

function tecs.ecs.newTagComponent(
    options: TagComponentOptions
): Component

Arguments

Name Type Description
options TagComponentOptions The caller supplies the tag name.

Returns

Type Description
Component Returns the registered bitset-backed tag.

tecs.ecs.newWorld Static

Creates a new World.

function tecs.ecs.newWorld(config: types.World.Config): World

Arguments

Name Type Description
config types.World.Config The caller supplies world settings or omits them for DEFAULT_MAX_ENTITIES and the default pipeline. The entity ceiling cannot grow after creation.

Returns

Type Description
World Returns an independent world with builtins registered and no systems.

Types

tecs.ecs.Archetype interface

Archetype stores contiguous component columns.

interface tecs.ecs.Archetype
    id: integer
    entities: DoubleArray
    componentList: {components.Component}

    addEntityObserver: function(self, ArchetypeEntityObserver)
    anyComponentDirty: function(self): boolean
    dirtyComponents: function(self): function(): components.Component
    forEachRelationship: function<T is components.Relationship>(
        self, row: T, callback: integer, function(T)
    )
    get: function<T is components.Component>(self, T): {T}
    getFirstRelationship: function<T is components.Relationship>(
        self, row: T, integer
    ): T
    getMut: function<T is components.Component>(self, T): {T}
    isComponentDirty: function(
        self, component: components.Component
    ): boolean
    markAllComponentsDirty: function(self)
    markComponentDirty: function(self, components.Component)
    set: function<C is components.Component>(
        self, row: integer, value: C
    )
end

tecs.ecs.Archetype.id field

Read-only. The unique identifier of the archetype in the ECS container.

tecs.ecs.Archetype.id: integer

tecs.ecs.Archetype.entities field

Read-only. Entity IDs that belong to this archetype. Length is entities[0]; rows are 1-based (entities[1] is the first entity).

tecs.ecs.Archetype.componentList field

Read-only. Components in this archetype, in the order they were passed at construction. Finalized at creation -- archetypes never add or remove components. Iterate with #componentList / ipairs to walk the archetype's signature.

tecs.ecs.Archetype.componentList: {components.Component}

tecs.ecs.Archetype:addEntityObserver Instance

Register an observer for lifecycle changes on this archetype. The observer remains attached for the archetype's lifetime. Registration applies only to this archetype; it does not discover other archetypes with the same components. See ArchetypeEntityObserver.

function tecs.ecs.Archetype.addEntityObserver(
    self, ArchetypeEntityObserver
)
Arguments
Name Type Description
self Archetype
#2 ArchetypeEntityObserver
Returns

None.

tecs.ecs.Archetype:anyComponentDirty Instance

True if any component on this archetype is currently dirty. Useful for bulk re-sync paths that don't track dirty granularity below the archetype level.

function tecs.ecs.Archetype.anyComponentDirty(self): boolean
Arguments
Name Type Description
self Archetype
Returns
Type Description
boolean

tecs.ecs.Archetype:dirtyComponents Instance

Iterate components currently marked dirty on this archetype.

function tecs.ecs.Archetype.dirtyComponents(
    self
): function(): components.Component
Arguments
Name Type Description
self Archetype
Returns
Type Description
function():components.Component

tecs.ecs.Archetype:forEachRelationship Instance

Iterate all relationship instances of the given container for the entity at row.

function tecs.ecs.Archetype.forEachRelationship<T is components.Relationship>(
    self, row: T, callback: integer, function(T)
)
Type Parameters
Name Constraint Description
T components.Relationship
Arguments
Name Type Description
self Archetype
row T 1-based row position.
callback integer Called once per matching relationship instance, in no defined order. Adding or removing relationships on this entity from inside it is not safe.
#4 function(T)
Returns

None.

tecs.ecs.Archetype:get Instance

Read-only column access. Returns the row-indexed column for the given component type, or nil if the archetype doesn't carry it. Does NOT mark the component dirty.

function tecs.ecs.Archetype.get<T is components.Component>(
    self, T
): {T}
Type Parameters
Name Constraint Description
T components.Component
Arguments
Name Type Description
self Archetype
#2 T
Returns
Type Description
{T} The archetype's live column, indexed from one and not a copy, so it is valid only until something moves an entity in or out of this archetype. Nil only when this archetype does not carry the component at all. A sparse relationship answers with a row-indexed proxy rather than a stored column, which reads the same and is not writable. Writing through this leaves the column clean, and on an FFI component that means the GPU never re-syncs.

tecs.ecs.Archetype:getFirstRelationship Instance

Get the first relationship instance of the given container for the entity at row, or nil if none exists.

function tecs.ecs.Archetype.getFirstRelationship<T is components.Relationship>(
    self, row: T, integer
): T
Type Parameters
Name Constraint Description
T components.Relationship
Arguments
Name Type Description
self Archetype
row T 1-based row position.
#3 integer
Returns
Type Description
T The one instance for an exclusive relationship, and an arbitrary one of several for a relationship that is not: "first" is storage order rather than the order they were added. Nil when the entity has none.

tecs.ecs.Archetype:getMut Instance

Mutable column access. Returns the row-indexed column AND marks the component dirty on this archetype. Use this at every site where you intend to write into the column.

function tecs.ecs.Archetype.getMut<T is components.Component>(
    self, T
): {T}
Type Parameters
Name Constraint Description
T components.Component
Arguments
Name Type Description
self Archetype
#2 T
Returns
Type Description
{T} The same column get answers with, dirty-marked before it is handed over. Marked whether or not anything is then written, so calling this in a loop that might not write defeats every dirty-gated consumer; take it on the first row that actually changes instead.

tecs.ecs.Archetype:isComponentDirty Instance

True if the given component's column on this archetype is currently marked dirty.

function tecs.ecs.Archetype.isComponentDirty(
    self, component: components.Component
): boolean
Arguments
Name Type Description
self Archetype
component components.Component False for a component this archetype does not carry, so a consumer may name one without testing membership.
Returns
Type Description
boolean True for a value write to this column, and true for any structural change to the archetype: a row moving in has every column newly written at that row.

tecs.ecs.Archetype:markAllComponentsDirty Instance

Mark every component on this archetype dirty.

Says that every column changed and says nothing about where, so a consumer that can resync single rows resyncs the whole archetype after it. Prefer markComponentDirty for a column you can name.

function tecs.ecs.Archetype.markAllComponentsDirty(self)
Arguments
Name Type Description
self Archetype
Returns

None.

tecs.ecs.Archetype:markComponentDirty Instance

Mark a single component dirty on this archetype. Idempotent.

function tecs.ecs.Archetype.markComponentDirty(
    self, components.Component
)
Arguments
Name Type Description
self Archetype
#2 components.Component
Returns

None.

tecs.ecs.Archetype:set Instance

Set a component value at a row and mark it dirty. Use for in-place updates that don't change the entity's archetype.

function tecs.ecs.Archetype.set<C is components.Component>(
    self, row: integer, value: C
)
Type Parameters
Name Constraint Description
C components.Component
Arguments
Name Type Description
self Archetype
row integer 1-based row position.
value C New component value (must carry a componentType). Stored as given rather than copied field by field, so a table component holds the caller's table afterwards.
Returns

None.

tecs.ecs.ArchetypeEntityObserver interface

ArchetypeEntityObserver receives entity changes within an archetype.

interface tecs.ecs.ArchetypeEntityObserver
    onActivated: function(self, archetype: Archetype)
    onArchetypeDestroyed: function(self, Archetype)
    onDeactivated: function(self, archetype: Archetype)
    onEntitiesAdded: function(
        self,
        archetype: Archetype,
        firstRow: integer,
        lastRow: integer,
        count: integer,
        sourceArchetype: Archetype
    )
    onEntitiesRemoved: function(
        self,
        archetype: Archetype,
        firstRow: integer,
        lastRow: integer,
        count: integer,
        destArchetype: Archetype
    )
    onEntityMove: function(
        self,
        archetype: Archetype,
        entity: integer,
        fromRow: integer,
        toRow: integer
    )
end

tecs.ecs.ArchetypeEntityObserver:onActivated Instance

Called when archetype transitions from empty to non-empty (0 -> 1 entities).

function tecs.ecs.ArchetypeEntityObserver.onActivated(
    self, archetype: Archetype
)
Arguments
Name Type Description
self ArchetypeEntityObserver
archetype Archetype The archetype that became active.
Returns

None.

tecs.ecs.ArchetypeEntityObserver:onArchetypeDestroyed Instance

Called when an archetype is being permanently destroyed (during world:compact()). Observers must remove all references to the archetype.

function tecs.ecs.ArchetypeEntityObserver.onArchetypeDestroyed(
    self, Archetype
)
Arguments
Name Type Description
self ArchetypeEntityObserver
#2 Archetype
Returns

None.

tecs.ecs.ArchetypeEntityObserver:onDeactivated Instance

Called when archetype transitions from non-empty to empty (1 -> 0 entities).

function tecs.ecs.ArchetypeEntityObserver.onDeactivated(
    self, archetype: Archetype
)
Arguments
Name Type Description
self ArchetypeEntityObserver
archetype Archetype The archetype that became inactive.
Returns

None.

tecs.ecs.ArchetypeEntityObserver:onEntitiesAdded Instance

Called once per contiguous range of entities added to the archetype.

function tecs.ecs.ArchetypeEntityObserver.onEntitiesAdded(
    self,
    archetype: Archetype,
    firstRow: integer,
    lastRow: integer,
    count: integer,
    sourceArchetype: Archetype
)
Arguments
Name Type Description
self ArchetypeEntityObserver
archetype Archetype The archetype the range was placed in.
firstRow integer The 1-based row of the first new entity.
lastRow integer The 1-based row of the last new entity (inclusive).
count integer Number of entities in the range (lastRow - firstRow + 1).
sourceArchetype Archetype The archetype the range originated from (nil for spawns).
Returns

None.

tecs.ecs.ArchetypeEntityObserver:onEntitiesRemoved Instance

Called once per contiguous range of entities removed from the archetype.

function tecs.ecs.ArchetypeEntityObserver.onEntitiesRemoved(
    self,
    archetype: Archetype,
    firstRow: integer,
    lastRow: integer,
    count: integer,
    destArchetype: Archetype
)
Arguments
Name Type Description
self ArchetypeEntityObserver
archetype Archetype The archetype the range is being removed from.
firstRow integer The 1-based row of the first removed entity.
lastRow integer The 1-based row of the last removed entity (inclusive).
count integer Number of entities in the range (lastRow - firstRow + 1).
destArchetype Archetype The archetype the range is moving to (nil for despawns).
Returns

None.

tecs.ecs.ArchetypeEntityObserver:onEntityMove Instance

Called when an entity is swap-popped into a different row. Implementing onEntitiesAdded is not required.

function tecs.ecs.ArchetypeEntityObserver.onEntityMove(
    self,
    archetype: Archetype,
    entity: integer,
    fromRow: integer,
    toRow: integer
)
Arguments
Name Type Description
self ArchetypeEntityObserver
archetype Archetype The archetype.
entity integer The entity ID that moved.
fromRow integer The original row position (0-based).
toRow integer The new row position (0-based).
Returns

None.

tecs.ecs.Bundle interface

Bundle names a reusable component collection.

interface tecs.ecs.Bundle
    interface Definition
        required: {components.Component}
        with: {components.Component: boolean | function(): components.Component}
    end

    name: string
    required: {string}
    defaulted: {string}

    spawn: function(self, ...: components.Component): integer
end

tecs.ecs.Bundle.Definition interface

Declarative bundle definition.

interface tecs.ecs.Bundle.Definition
    required: {components.Component}
    with: {components.Component: boolean | function(): components.Component}
end

tecs.ecs.Bundle.Definition.required field

Caller-writable. Components that must be provided as positional args to spawn().

tecs.ecs.Bundle.Definition.required: {components.Component}

tecs.ecs.Bundle.Definition.with field

Caller-writable. Components with defaults, keyed by component type. Value is either a factory function returning a component instance, or true to call the component's default constructor.

tecs.ecs.Bundle.Definition.with: {components.Component: boolean | function(): components.Component}

tecs.ecs.Bundle.name field

Read-only. The name of the bundle.

tecs.ecs.Bundle.name: string

tecs.ecs.Bundle.required field

Read-only. Component names that must be provided when spawning.

tecs.ecs.Bundle.required: {string}

tecs.ecs.Bundle.defaulted field

Read-only. Component names with default factories.

tecs.ecs.Bundle.defaulted: {string}

tecs.ecs.Bundle:spawn Instance

Spawn an entity using this bundle.

function tecs.ecs.Bundle.spawn(
    self, ...: components.Component
): integer
Arguments
Name Type Description
self Bundle
... components.Component Required component instances in declaration order.
Returns
Type Description
integer The entity ID.

tecs.ecs.BundleDef interface

BundleDef configures a bundle.

interface tecs.ecs.BundleDef
    required: {components.Component}
    with: {components.Component: boolean | function(): components.Component}
end

tecs.ecs.BundleDef.required field

Caller-writable. Components that must be provided as positional args to spawn().

tecs.ecs.BundleDef.required: {components.Component}

tecs.ecs.BundleDef.with field

Caller-writable. Components with defaults, keyed by component type. Value is either a factory function returning a component instance, or true to call the component's default constructor.

tecs.ecs.BundleDef.with: {components.Component: boolean | function(): components.Component}

tecs.ecs.Closeable interface

An owned value that releases its active lifetime explicitly.

close may report a delayed finalization failure. Every implementation returns true on success. Its own contract defines whether repeated calls are safe.

global interface tecs.ecs.Closeable
    close: function(self): boolean, string
end

tecs.ecs.Closeable:close Instance

Releases the value's active lifetime.

function tecs.ecs.Closeable.close(self): boolean, string
Arguments
Name Type Description
self Closeable The value to close.
Returns
Type Description
boolean Returns true when finalization succeeds.
string Returns a finalization reason when the first return is false.

tecs.ecs.Component interface

Component names any component definition.

interface tecs.ecs.Component
    componentType: self
    componentName: string
    componentId: integer
    relationshipType: Component
    wildcardContainer: Component
    target: integer
    transient: boolean

    deserialize: function(world: World, data: {string: any}): self
    init: function(self, any)
    new: function({string: any}): self
    serialize: function(instance: self): {string: any}
    metamethod __call: function(self, ...: any): self
end

tecs.ecs.Component.componentType field

Read-only. The container type of the component, available on instances and containers.

tecs.ecs.Component.componentType: self

tecs.ecs.Component.componentName field

Read-only. The name of the component.

tecs.ecs.Component.componentName: string

tecs.ecs.Component.componentId field

Read-only. The auto-incrementing ID of the component container.

tecs.ecs.Component.componentId: integer

tecs.ecs.Component.relationshipType field

Read-only. Relationship components only: the relationship container type (nil for non-relationships). For containers, this equals self. For instances, it points to the container.

tecs.ecs.Component.wildcardContainer field

Read-only. Relationship instance wildcard container (nil for non-relationships and containers). For Rel(target) dense instances, this points back to Rel.

tecs.ecs.Component.target field

Read-only. Relationship components only: The target entity ID (for relationship instances only).

tecs.ecs.Component.target: integer

tecs.ecs.Component.transient field

Read-only. True if this component is runtime-only and omitted from snapshots.

tecs.ecs.Component.transient: boolean

tecs.ecs.Component.deserialize Static

Deserialize a component instance from a plain table.

function tecs.ecs.Component.deserialize(
    world: World, data: {string: any}
): self
Arguments
Name Type Description
world World The world context for loading resources.
data {string : any} The plain table data to deserialize.
Returns
Type Description
self A new component instance.

tecs.ecs.Component.init Static

Optional post-allocation positional initializer used by the built-in factories. Runs after the base instance has been allocated and any declarative field population has occurred.

function tecs.ecs.Component.init(self, any)
Arguments
Name Type Description
#1 self
#2 any
Returns

None.

tecs.ecs.Component.new Static

Build a component instance from a table of named fields. The positional __call form is the hot path; new is the ergonomic/snapshot form.

function tecs.ecs.Component.new({string: any}): self
Arguments
Name Type Description
#1 {string : any}
Returns
Type Description
self

tecs.ecs.Component.serialize Static

Serialize a component instance to a plain table.

function tecs.ecs.Component.serialize(instance: self): {string: any}
Arguments
Name Type Description
instance self The component instance to serialize.
Returns
Type Description
{string : any} A plain table representation of the component data.

tecs.ecs.Component:__call metamethod

Creates an instance of the component from the container using positional arguments.

metamethod tecs.ecs.Component.$meta.__call(self, ...: any): self
Arguments
Name Type Description
self Component
... any Field values in declaration order. One left nil takes the field's registered default, so trailing arguments may be omitted.
Returns
Type Description
self A new instance, not a shared one, so two calls with the same arguments answer two values.

tecs.ecs.ComponentOptions interface

ComponentOptions configures a table component.

interface tecs.ecs.ComponentOptions<C is Component> is ContainerComponentOptions<C>
    fields: {string}
    defaults: {any}

    __call: function(C, any)
    deserialize: function(World, {string: any}): C
    init: function(C, any)
    new: function({string: any}): C
    serialize: function(C): {string: any}
end

Interfaces

Interface
ContainerComponentOptions<C>

Type Parameters

Name Constraint Description
C Component

tecs.ecs.ComponentOptions.fields field

Caller-writable. Ordered field names for positional construction and .new(data). Example: fields = {"x", "y"} means Component(1, 2) maps to {x = 1, y = 2} and Component.new({x = 1, y = 2}) unpacks by the same order. The generated constructor is loaded so LuaJIT sees literal field assignments.

tecs.ecs.ComponentOptions.fields: {string}

tecs.ecs.ComponentOptions.defaults field

Caller-writable. Positional defaults, in the same order as fields. Use nil for fields that have no default. Requires fields.

tecs.ecs.ComponentOptions.defaults: {any}

tecs.ecs.ComponentOptions.__call Static

Optional custom constructor hook for the container's __call. When present, Tecs allocates a base instance, applies declarative defaults, then invokes this hook as __call(instance, ...). On this path, init is NOT auto-run; call Component.init(...) explicitly from __call if desired.

function tecs.ecs.ComponentOptions.__call(C, any)
Arguments
Name Type Description
#1 C
#2 any
Returns

None.

tecs.ecs.ComponentOptions.deserialize Static

Custom deserialization function (optional). Reconstructs a component instance from a plain table.

function tecs.ecs.ComponentOptions.deserialize(World, {string: any}): C
Arguments
Name Type Description
#1 World
#2 {string : any}
Returns
Type Description
C

tecs.ecs.ComponentOptions.init Static

Optional post-allocation positional initializer. Runs after the base instance has been allocated and any declarative fields / defaults have been applied. Use for validation, normalization, or derived state. If provided without fields or new, registration errors because Tecs would have no clear way to implement .new(data).

function tecs.ecs.ComponentOptions.init(C, any)
Arguments
Name Type Description
#1 C
#2 any
Returns

None.

tecs.ecs.ComponentOptions.new Static

Optional table-form constructor, called as Component.new(data). When fields are present, Tecs generates this automatically by unpacking named fields and routing through __call.

function tecs.ecs.ComponentOptions.new({string: any}): C
Arguments
Name Type Description
#1 {string : any}
Returns
Type Description
C

tecs.ecs.ComponentOptions.serialize Static

Custom serialization function (optional). Converts a component instance to a plain table for JSON serialization.

function tecs.ecs.ComponentOptions.serialize(C): {string: any}
Arguments
Name Type Description
#1 C
Returns
Type Description
{string : any}

tecs.ecs.ContainerComponentOptions interface

Shared options for creating different components.

interface tecs.ecs.ContainerComponentOptions<C is Component> is BasicComponentOptions<C>
    container: C
end

Interfaces

Interface
BasicComponentOptions<C>

Type Parameters

Name Constraint Description
C Component

tecs.ecs.ContainerComponentOptions.container field

Caller-writable. The component container/type to use (required).

tecs.ecs.DoubleArray interface

DoubleArray names an FFI array of doubles.

interface tecs.ecs.DoubleArray is {integer}
    metamethod __len: function(self)
end

Interfaces

Interface
{integer}

tecs.ecs.DoubleArray:__len metamethod

Reads the count out of slot 0 rather than probing for a border, so #array is exact even though slot 0 is occupied and would otherwise make the array look empty to Lua's own length operator. A macro, so it costs one load at the call site.

metamethod tecs.ecs.DoubleArray.$meta.__len(self)
Arguments
Name Type Description
self DoubleArray
Returns

None.

tecs.ecs.FFIComponentOptions interface

FFIComponentOptions configures an FFI component.

interface tecs.ecs.FFIComponentOptions<C is Component> is ContainerComponentOptions<C>
    fields: {{string, string}}
    defaults: {any}
    metatable: {any: any}

    __call: function(C, any)
    deserialize: function(World, {string: any}): C
    init: function(C, any)
    new: function({string: any}): C
    serialize: function(C): {string: any}
end

Interfaces

Interface
ContainerComponentOptions<C>

Type Parameters

Name Constraint Description
C Component

tecs.ecs.FFIComponentOptions.fields field

Caller-writable. FFI field definitions for the backing struct.

tecs.ecs.FFIComponentOptions.fields: {{string, string}}

tecs.ecs.FFIComponentOptions.defaults field

Caller-writable. Positional defaults, in the same order as fields.

tecs.ecs.FFIComponentOptions.metatable field

Caller-writable. Optional metatable to apply to FFI instances (for instance methods).

tecs.ecs.FFIComponentOptions.metatable: {any: any}

tecs.ecs.FFIComponentOptions.__call Static

Optional custom constructor hook. Same semantics as ComponentOptions.__call, but the base instance is an FFI struct.

function tecs.ecs.FFIComponentOptions.__call(C, any)
Arguments
Name Type Description
#1 C
#2 any
Returns

None.

tecs.ecs.FFIComponentOptions.deserialize Static

Custom deserialization function (optional). Reconstructs a component instance from a plain table. Typically reruns the same construction path a fresh spawn would take so the restored instance gets valid runtime state.

function tecs.ecs.FFIComponentOptions.deserialize(
    World, {string: any}
): C
Arguments
Name Type Description
#1 World
#2 {string : any}
Returns
Type Description
C

tecs.ecs.FFIComponentOptions.init Static

Optional post-allocation positional initializer. Same semantics as ComponentOptions.init, but the base instance is an FFI struct.

function tecs.ecs.FFIComponentOptions.init(C, any)
Arguments
Name Type Description
#1 C
#2 any
Returns

None.

tecs.ecs.FFIComponentOptions.new Static

Optional table-form constructor. Defaults to unpacking fields by name into positional args and routing through __call.

function tecs.ecs.FFIComponentOptions.new({string: any}): C
Arguments
Name Type Description
#1 {string : any}
Returns
Type Description
C

tecs.ecs.FFIComponentOptions.serialize Static

Custom serialization function (optional). Converts a component instance to a plain table for JSON serialization. Return nil to omit the component from snapshots.

function tecs.ecs.FFIComponentOptions.serialize(C): {string: any}
Arguments
Name Type Description
#1 C
Returns
Type Description
{string : any}

tecs.ecs.FFIRelationshipOptions interface

FFIRelationshipOptions configures an FFI relationship.

interface tecs.ecs.FFIRelationshipOptions<R is Relationship> is BaseRelationshipOptions<R>, FFIComponentOptions<R>
end

Interfaces

Interface
BaseRelationshipOptions<R>
FFIComponentOptions<R>

Type Parameters

Name Constraint Description
R Relationship

tecs.ecs.FixedOverload enum

FixedOverload selects fixed-step overload behavior.

enum tecs.ecs.FixedOverload
    "accumulate"
    "drop"
end

tecs.ecs.Phase interface

Phase identifies one system phase.

interface tecs.ecs.Phase
    name: string
    position: integer
    children: {Phase}
end

tecs.ecs.Phase.name field

Read-only. The name of the phase.

tecs.ecs.Phase.name: string

tecs.ecs.Phase.position field

Read-only. The public pipeline position for this phase.

tecs.ecs.Phase.position: integer

tecs.ecs.Phase.children field

Read-only. Child phases of this phase.

tecs.ecs.Phase.children: {Phase}

tecs.ecs.phases record

Defines the predefined ECS phases, or lifecycle states, of the game and event loop.

Tecs provides these standard phases but also supports custom pipelines via World.Config.pipelineFactory. Read-only. phases contains the phases a system may join.

record tecs.ecs.phases
    record AllGroups is Phase
    end

    record MainGroup is Phase
    end

    record PreStartup is Phase
    end

    record Startup is Phase
    end

    record PostStartup is Phase
    end

    record StartupGroup is Phase
    end

    record First is Phase
    end

    record PreUpdate is Phase
    end

    record FixedFirst is Phase
    end

    record FixedPreUpdate is Phase
    end

    record FixedUpdate is Phase
    end

    record FixedPostUpdate is Phase
    end

    record FixedLast is Phase
    end

    record FixedUpdateGroup is Phase
    end

    record Update is Phase
    end

    record PostUpdate is Phase
    end

    record RenderFirst is Phase
    end

    record PreRender is Phase
    end

    record Render is Phase
    end

    record PostRender is Phase
    end

    record RenderLast is Phase
    end

    record RenderGroup is Phase
    end

    record Last is Phase
    end

    record PreShutdown is Phase
    end

    record Shutdown is Phase
    end

    record PostShutdown is Phase
    end

    record ShutdownGroup is Phase
    end

    index: {Phase}
end

tecs.ecs.phases.AllGroups record

Contains all phases that make up the ECS lifecycle.

record tecs.ecs.phases.AllGroups is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.MainGroup record

A meta-phase for the main game loop.

record tecs.ecs.phases.MainGroup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PreStartup record

Runs once at application start for critical initialization (e.g., logging, core systems).

record tecs.ecs.phases.PreStartup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.Startup record

Runs once at application start for general initialization (e.g., loading assets, creating entities).

record tecs.ecs.phases.Startup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PostStartup record

Runs once after startup for final setup (e.g., starting gameplay, enabling systems).

record tecs.ecs.phases.PostStartup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.StartupGroup record

record tecs.ecs.phases.StartupGroup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.First record

Runs at the very start of each frame (e.g., time updates, input polling).

record tecs.ecs.phases.First is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PreUpdate record

Runs before the main update (e.g., physics preparation, event processing).

record tecs.ecs.phases.PreUpdate is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.FixedFirst record

Runs at the start of each fixed timestep iteration (e.g., fixed timer updates).

record tecs.ecs.phases.FixedFirst is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.FixedPreUpdate record

Runs before fixed update (e.g., collision detection preparation).

record tecs.ecs.phases.FixedPreUpdate is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.FixedUpdate record

Runs at fixed timestep intervals for deterministic updates (e.g., physics simulation, gameplay logic).

record tecs.ecs.phases.FixedUpdate is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.FixedPostUpdate record

Runs after fixed update (e.g., collision response, constraint solving).

record tecs.ecs.phases.FixedPostUpdate is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.FixedLast record

Runs at the end of each fixed timestep iteration (e.g., state synchronization).

record tecs.ecs.phases.FixedLast is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.FixedUpdateGroup record

record tecs.ecs.phases.FixedUpdateGroup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.Update record

Main update phase, runs once per frame for gameplay logic and non-physics updates.

record tecs.ecs.phases.Update is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PostUpdate record

Runs after update and before rendering (e.g., animation, transform updates, camera updates).

record tecs.ecs.phases.PostUpdate is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.RenderFirst record

Runs at the start of rendering (e.g., clearing buffers, setting up render state).

record tecs.ecs.phases.RenderFirst is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PreRender record

Runs just before rendering (e.g., culling, sorting, batching).

record tecs.ecs.phases.PreRender is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.Render record

Main rendering phase (e.g., drawing sprites, meshes, UI).

record tecs.ecs.phases.Render is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PostRender record

Runs just after rendering (e.g., post-processing effects, screen transitions).

record tecs.ecs.phases.PostRender is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.RenderLast record

Runs at the end of rendering (e.g., presenting frame, GPU synchronization).

record tecs.ecs.phases.RenderLast is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.RenderGroup record

record tecs.ecs.phases.RenderGroup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.Last record

Runs at the very end of each frame (e.g., cleanup, metrics collection, frame timing).

record tecs.ecs.phases.Last is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PreShutdown record

Runs just before shutdown (e.g., saving game state, closing connections).

record tecs.ecs.phases.PreShutdown is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.Shutdown record

Main shutdown phase (e.g., releasing resources, destroying entities).

record tecs.ecs.phases.Shutdown is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.PostShutdown record

Runs after shutdown for final cleanup (e.g., logging shutdown metrics, final cleanup).

record tecs.ecs.phases.PostShutdown is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.ShutdownGroup record

record tecs.ecs.phases.ShutdownGroup is Phase
end
Interfaces
Interface
Phase

tecs.ecs.phases.index field

Read-only. Maps each lifecycle position to its phase definition.

tecs.ecs.phases.index: {Phase}

tecs.ecs.Pipeline interface

Pipeline identifies a world update pipeline.

interface tecs.ecs.Pipeline
    count: integer
    fixedTimestep: number
    fixedAccumulator: number
    fixedStepCount: integer
    fixedMaxSteps: integer
    fixedOverload: FixedOverload
    fixedTimeDropped: number
    fixedStepsDropped: integer

    addSystem: function(self, config: SystemConfig)
    disablePhase: function(self, phase: Phase)
    enablePhase: function(self, phase: Phase)
    registerPhase: function(self, phase: Phase)
    removeSystem: function(self, systemName: string)
    run: function(self, phase: Phase, dt: number, world: World)
    update: function(self, dt: number, world: World)
end

tecs.ecs.Pipeline.count field

Read-only. The number of systems in the pipeline.

tecs.ecs.Pipeline.count: integer

tecs.ecs.Pipeline.fixedTimestep field

Read-only. The fixed timestep interval in seconds (e.g., 1/60 for 60Hz physics).

tecs.ecs.Pipeline.fixedTimestep: number

tecs.ecs.Pipeline.fixedAccumulator field

Read-only. Accumulated time not yet consumed by fixed updates. Use with fixedTimestep to compute interpolation alpha: accumulator / timestep.

tecs.ecs.Pipeline.fixedAccumulator: number

tecs.ecs.Pipeline.fixedStepCount field

Read-only. Fixed steps run since the pipeline was made.

tecs.ecs.Pipeline.fixedStepCount: integer

tecs.ecs.Pipeline.fixedMaxSteps field

Read-only. The most fixed steps one update will run before the overload policy decides what happens to the rest. Defaults to 10.

tecs.ecs.Pipeline.fixedMaxSteps: integer

tecs.ecs.Pipeline.fixedOverload field

Read-only. What happens to the time those steps would have consumed. Defaults to "drop".

tecs.ecs.Pipeline.fixedTimeDropped field

Read-only. Simulated seconds abandoned by the "drop" policy since the pipeline was made. Stays at zero under "accumulate", which abandons nothing, and stays at zero on a machine that keeps up.

Read it. A simulation, a replay or anything networked is wrong by exactly this much, and nothing else in the world says so.

tecs.ecs.Pipeline.fixedTimeDropped: number

tecs.ecs.Pipeline.fixedStepsDropped field

Read-only. Fixed steps that were owed and never ran, on the same terms. Whole steps only: fixedTimeDropped is this many timesteps, because a drop leaves the sub-step remainder alone rather than resetting the interpolation alpha along with it.

tecs.ecs.Pipeline.fixedStepsDropped: integer

tecs.ecs.Pipeline:addSystem Instance

Add a system to the pipeline.

function tecs.ecs.Pipeline.addSystem(self, config: SystemConfig)
Arguments
Name Type Description
self Pipeline
config SystemConfig The system configuration.
Returns

None.

tecs.ecs.Pipeline:disablePhase Instance

Disable a phase.

function tecs.ecs.Pipeline.disablePhase(self, phase: Phase)
Arguments
Name Type Description
self Pipeline
phase Phase The phase to disable.
Returns

None.

tecs.ecs.Pipeline:enablePhase Instance

Enable a phase.

function tecs.ecs.Pipeline.enablePhase(self, phase: Phase)
Arguments
Name Type Description
self Pipeline
phase Phase The phase to enable.
Returns

None.

tecs.ecs.Pipeline:registerPhase Instance

Register a custom phase with the pipeline.

function tecs.ecs.Pipeline.registerPhase(self, phase: Phase)
Arguments
Name Type Description
self Pipeline
phase Phase The phase to register.
Returns

None.

tecs.ecs.Pipeline:removeSystem Instance

Remove a system from the pipeline.

function tecs.ecs.Pipeline.removeSystem(self, systemName: string)
Arguments
Name Type Description
self Pipeline
systemName string The name of the system to remove.
Returns

None.

tecs.ecs.Pipeline:run Instance

Run a specific phase.

function tecs.ecs.Pipeline.run(
    self, phase: Phase, dt: number, world: World
)
Arguments
Name Type Description
self Pipeline
phase Phase The phase to run.
dt number The delta time since the last update.
world World The world to run the phase on.
Returns

None.

tecs.ecs.Pipeline:update Instance

Update the pipeline.

function tecs.ecs.Pipeline.update(self, dt: number, world: World)
Arguments
Name Type Description
self Pipeline
dt number The delta time since the last update.
world World The world to update.
Returns

None.

tecs.Plugin type

A plugin configures a world with systems, resources, observers, and initial entities.

type tecs.Plugin = function(World)

tecs.Query interface

A reusable filter over the archetypes in a world.

interface tecs.Query
    enum Kind
        "logic"
        "render"
    end

    interface Descriptor
        name: string
        type: Kind
        include: {components.Component}
        includeAny: {components.Component}
        exclude: {components.Component}
        temp: boolean

        groupBy: function(archetype: Archetype): integer
        onEntitiesAdded: function(
            archetype: Archetype,
            firstRow: integer,
            lastRow: integer,
            count: integer
        )
        onEntitiesRemoved: function(
            archetype: Archetype,
            firstRow: integer,
            lastRow: integer,
            count: integer
        )
    end

    interface Cursor is Closeable
        type IterFn = function(
            Cursor, any
        ): (Archetype, integer, {integer})
        type GroupsIterFn = function(Cursor, any): integer
        type GroupIterFn = function(
            Cursor, any
        ): (Archetype, integer, {integer})
        group: function(
            self, groupId: integer
        ): GroupIterFn, Cursor, any
        groups: function(self): GroupsIterFn, Cursor, any
        iter: function(self): IterFn, Cursor, any
    end

    type IterFn = function(Query, any): (Archetype, integer, {integer})
    type GroupsIterFn = function(Query, any): integer
    type GroupIterFn = function(
        Query, any
    ): (Archetype, integer, {integer})
    descriptor: Descriptor

    count: function(self): integer
    getGroup: function(self, archetype: Archetype): integer
    getGroupCount: function(self, groupId: integer): integer
    group: function(self, groupId: integer): GroupIterFn, Query, any
    groups: function(self): GroupsIterFn, Query, any
    iter: function(self): IterFn, Query, any
    newCursor: function(self): Cursor
end

tecs.Query.Kind enum

Whether a query drives simulation or presentation.

enum tecs.Query.Kind
    "logic"
    "render"
end

tecs.Query.Descriptor interface

The options passed to world:newQuery.

interface tecs.Query.Descriptor
    name: string
    type: Kind
    include: {components.Component}
    includeAny: {components.Component}
    exclude: {components.Component}
    temp: boolean

    groupBy: function(archetype: Archetype): integer
    onEntitiesAdded: function(
        archetype: Archetype,
        firstRow: integer,
        lastRow: integer,
        count: integer
    )
    onEntitiesRemoved: function(
        archetype: Archetype,
        firstRow: integer,
        lastRow: integer,
        count: integer
    )
end

tecs.Query.Descriptor.name field

Caller-writable. Names the query in logs, profiles, and debug tools.

tecs.Query.Descriptor.name: string

tecs.Query.Descriptor.type field

Caller-writable. Selects simulation or presentation behavior.

"logic" excludes Paused entities, so pausing a state stops the systems that move, damage, or think. "render" records the opposite intent: paused entities keep drawing. Omitting the field leaves the query unfiltered, which matches every query written before this option existed.

tecs.Query.Descriptor.include field

Caller-writable. Lists every component a matching archetype must contain.

tecs.Query.Descriptor.include: {components.Component}

tecs.Query.Descriptor.includeAny field

Caller-writable. Lists components of which a matching archetype must contain at least one.

tecs.Query.Descriptor.exclude field

Caller-writable. Lists every component a matching archetype must omit.

tecs.Query.Descriptor.exclude: {components.Component}

tecs.Query.Descriptor.temp field

Caller-writable. Set true to match only the archetypes that exist when the query is created.

tecs.Query.Descriptor.temp: boolean

tecs.Query.Descriptor.groupBy Static

Caller-writable. Assigns an integer group to each archetype. Archetypes with the same group are iterated contiguously. Use with groups() and group(id) for efficient grouped iteration.

function tecs.Query.Descriptor.groupBy(archetype: Archetype): integer
Arguments
Name Type Description
archetype Archetype The archetype to classify.
Returns
Type Description
integer The group identifier.

tecs.Query.Descriptor.onEntitiesAdded Static

Caller-writable. Receives each contiguous range of entities that enters the query.

function tecs.Query.Descriptor.onEntitiesAdded(
    archetype: Archetype,
    firstRow: integer,
    lastRow: integer,
    count: integer
)
Arguments
Name Type Description
archetype Archetype The archetype that contains the range.
firstRow integer The first row in the range.
lastRow integer The last row in the range.
count integer The number of rows in the range.
Returns

None.

tecs.Query.Descriptor.onEntitiesRemoved Static

Caller-writable. Receives each contiguous range of entities that leaves the query.

function tecs.Query.Descriptor.onEntitiesRemoved(
    archetype: Archetype,
    firstRow: integer,
    lastRow: integer,
    count: integer
)
Arguments
Name Type Description
archetype Archetype The archetype that contains the range.
firstRow integer The first row in the range.
lastRow integer The last row in the range.
count integer The number of rows in the range.
Returns

None.

tecs.Query.Cursor interface

An opt-in query iterator that can be closed before exhaustion.

Create one with query:newCursor() when an archetype-level loop may break or return early. Call close() after leaving the loop. Natural exhaustion closes the cursor automatically, and repeated close() calls are safe.

interface tecs.Query.Cursor is Closeable
    type IterFn = function(Cursor, any): (Archetype, integer, {integer})
    type GroupsIterFn = function(Cursor, any): integer
    type GroupIterFn = function(
        Cursor, any
    ): (Archetype, integer, {integer})
    group: function(self, groupId: integer): GroupIterFn, Cursor, any
    groups: function(self): GroupsIterFn, Cursor, any
    iter: function(self): IterFn, Cursor, any
end
Interfaces
Interface
Closeable

tecs.Query.Cursor.IterFn type

The step function cursor:iter() returns. Yields the archetype, its live row count, and its entity id column; the entity column is the archetype's own, not a copy.

type tecs.Query.Cursor.IterFn = function(
    Cursor, any
): (Archetype, integer, {integer})

tecs.Query.Cursor.GroupsIterFn type

The step function cursor:groups() returns. Yields group ids in ascending order.

type tecs.Query.Cursor.GroupsIterFn = function(Cursor, any): integer

tecs.Query.Cursor.GroupIterFn type

The step function cursor:group(id) returns, with the same three values as IterFn narrowed to one group.

type tecs.Query.Cursor.GroupIterFn = function(
    Cursor, any
): (Archetype, integer, {integer})

tecs.Query.Cursor:group Instance

Iterate over active archetypes in one group.

function tecs.Query.Cursor.group(
    self, groupId: integer
): GroupIterFn, Cursor, any
Arguments
Name Type Description
self Cursor
groupId integer The group to traverse.
Returns
Type Description
GroupIterFn The cursor's grouped step function.
Cursor This cursor.
any The iterator's initial control value.

tecs.Query.Cursor:groups Instance

Iterate over active group IDs in sorted order.

function tecs.Query.Cursor.groups(self): GroupsIterFn, Cursor, any
Arguments
Name Type Description
self Cursor
Returns
Type Description
GroupsIterFn
Cursor
any

tecs.Query.Cursor:iter Instance

Iterate over every active archetype matched by the query.

function tecs.Query.Cursor.iter(self): IterFn, Cursor, any
Arguments
Name Type Description
self Cursor
Returns
Type Description
IterFn
Cursor
any

tecs.Query.IterFn type

The step function query:iter() returns. Yields the archetype, its live row count, and its entity id column; the entity column is the archetype's own, not a copy, and is only valid until the world next commits.

type tecs.Query.IterFn = function(
    Query, any
): (Archetype, integer, {integer})

tecs.Query.GroupsIterFn type

The step function query:groups() returns. Yields group ids in ascending order.

type tecs.Query.GroupsIterFn = function(Query, any): integer

tecs.Query.GroupIterFn type

The step function query:group(id) returns, with the same three values as IterFn narrowed to one group.

type tecs.Query.GroupIterFn = function(
    Query, any
): (Archetype, integer, {integer})

tecs.Query.descriptor field

Read-only. Returns the descriptor used to create the query. Exposed for inspection. Mutating it after query construction does not rebuild component masks, subscriptions, or grouping state.

tecs.Query:count Instance

Total number of entities currently matched by this query. One pass over matching archetypes, not entities.

function tecs.Query.count(self): integer
Arguments
Name Type Description
self Query
Returns
Type Description
integer

tecs.Query:getGroup Instance

Returns the cached group identifier for an archetype.

Only available when groupBy is specified. Returns nil when the archetype does not match this query.

function tecs.Query.getGroup(self, archetype: Archetype): integer
Arguments
Name Type Description
self Query
archetype Archetype The archetype to inspect.
Returns
Type Description
integer Its cached group identifier, or nil when it has none.

tecs.Query:getGroupCount Instance

Returns the total entity count for a group.

function tecs.Query.getGroupCount(self, groupId: integer): integer
Arguments
Name Type Description
self Query
groupId integer The group to count.
Returns
Type Description
integer Its entity count, or zero when the group does not exist.

tecs.Query:group Instance

Iterate over archetypes in a specific group. Only available when groupBy is specified. Usage: for archetype, len, entities in query:group(id) do ... end. Yields nothing if the group has no archetypes.

function tecs.Query.group(
    self, groupId: integer
): GroupIterFn, Query, any
Arguments
Name Type Description
self Query
groupId integer The group to traverse.
Returns
Type Description
GroupIterFn The query's grouped step function.
Query This query.
any The iterator's initial control value.

tecs.Query:groups Instance

Iterate over active group IDs in sorted order. Only available when groupBy is specified. Usage: for blendId in query:groups() do ... end.

function tecs.Query.groups(self): GroupsIterFn, Query, any
Arguments
Name Type Description
self Query
Returns
Type Description
GroupsIterFn
Query
any

tecs.Query:iter Instance

Explicit iterator protocol form. Returns (archetype, length, entities) for each matching archetype. Use archetype:get(Component) or archetype:getMut(Component) to retrieve component data.

Usage: for archetype, length, entities in query:iter() do ... end

function tecs.Query.iter(self): IterFn, Query, any
Arguments
Name Type Description
self Query
Returns
Type Description
IterFn The three values a generic for takes. Iteration opens a deferred scope on the world and closes it when the loop runs out of archetypes, so a break or an early return leaves the world deferred and every later spawn silently queues. Use newCursor() for a loop that may stop early. The entities table and the columns are the archetype's own and are valid only for that turn of the loop.
Query
any

tecs.Query:newCursor Instance

Create an opt-in cursor for a traversal that may stop early.

Cursors allocate a small traversal object. Keep using iter(), groups(), and group(id) for loops that run to exhaustion. When breaking or returning early, retain the cursor and call cursor:close() to close its deferred scope and drain staged mutations.

function tecs.Query.newCursor(self): Cursor
Arguments
Name Type Description
self Query
Returns
Type Description
Cursor A cursor the caller has to close, once, on every path out of the loop including an early return. Closing it twice is harmless; never closing it leaves the world deferred for good.

tecs.ecs.QueryCursor type

QueryCursor controls an explicitly closed query traversal.

type tecs.ecs.QueryCursor = types.Query.Cursor

tecs.ecs.QueryDescriptor type

QueryDescriptor configures a query.

type tecs.ecs.QueryDescriptor = types.Query.Descriptor

tecs.ecs.Relationship interface

Relationship names any relationship definition.

interface tecs.ecs.Relationship is Component
    exclusiveRelationship: boolean

    targeting: function(self, integer): self
end

Interfaces

Interface
Component

tecs.ecs.Relationship.exclusiveRelationship field

Read-only. Component container property indicating that the relationship is exclusive (e.g., has-one).

tecs.ecs.Relationship:targeting Instance

Returns the component type for a specific target.

function tecs.ecs.Relationship.targeting(self, integer): self
Arguments
Name Type Description
self Relationship
#2 integer
Returns
Type Description
self

tecs.ecs.RelationshipOptions interface

RelationshipOptions configures a relationship.

interface tecs.ecs.RelationshipOptions<R is Relationship> is BaseRelationshipOptions<R>, ComponentOptions<R>
end

Interfaces

Interface
BaseRelationshipOptions<R>
ComponentOptions<R>

Type Parameters

Name Constraint Description
R Relationship

tecs.ecs.ScalarComponent interface

ScalarComponent names a single-value component.

interface tecs.ecs.ScalarComponent<T> is Component
    scalarKind: ScalarKind
    scalarDefault: T
    enum ScalarKind
        "boolean"
        "number"
        "string"
    end
end

Interfaces

Interface
Component

Type Parameters

Name Constraint Description
T

tecs.ecs.ScalarComponent.scalarKind field

Read-only. Which primitive the column holds. Fixed at registration and never widened afterwards.

tecs.ecs.ScalarComponent.scalarDefault field

Read-only. The value a row takes when the component is added without one. Never nil: newScalarComponent fills an omitted default with the zero of kind (0, false or "").

tecs.ecs.ScalarComponent.ScalarKind enum

The primitives a scalar column may hold. Anything else, tables and cdata included, is a table or FFI component instead.

enum tecs.ecs.ScalarComponent.ScalarKind
    "boolean"
    "number"
    "string"
end

tecs.ecs.ScalarComponentOptions interface

ScalarComponentOptions configures a scalar component.

interface tecs.ecs.ScalarComponentOptions<T> is BasicComponentOptions<ScalarComponent<T>>
    kind: string
    default: T
end

Interfaces

Interface
BasicComponentOptions<ScalarComponent<T>>

Type Parameters

Name Constraint Description
T

tecs.ecs.ScalarComponentOptions.kind field

Caller-writable. Required. One of "number", "boolean" or "string"; anything else errors at registration rather than at first use.

tecs.ecs.ScalarComponentOptions.kind: string

tecs.ecs.ScalarComponentOptions.default field

Caller-writable. Optional. Omitting it takes the zero of kind (0, false or ""), so a scalar column never reads back nil.

tecs.ecs.Snapshot type

Snapshot names serialized world state.

type tecs.ecs.Snapshot = types.World.Snapshot

tecs.ecs.SnapshotComponentTableEntry type

SnapshotComponentTableEntry identifies one component in a snapshot.

type tecs.ecs.SnapshotComponentTableEntry = types.World.SnapshotComponentTableEntry

tecs.ecs.SnapshotHandler type

SnapshotHandler saves and restores plugin data.

type tecs.ecs.SnapshotHandler = types.World.SnapshotHandler

tecs.ecs.SnapshotOptions type

SnapshotOptions controls snapshot serialization.

type tecs.ecs.SnapshotOptions = types.World.SnapshotOptions

tecs.ecs.SnapshotOutput type

SnapshotOutput collects serialized data.

type tecs.ecs.SnapshotOutput = types.World.SnapshotOutput

tecs.ecs.SnapshotPrelude type

SnapshotPrelude names snapshot metadata.

type tecs.ecs.SnapshotPrelude = types.World.SnapshotPrelude

tecs.ecs.StatePolicy record

StatePolicy controls state-stack participation.

record tecs.ecs.StatePolicy
    record Action
        apply: string

        call: function(World)
    end

    onBlur: string | Action | function(World)
    onFocus: string | Action | function(World)
    onExit: string | Action | function(World)

    onEnter: function(World)
end

tecs.ecs.StatePolicy.Action record

Action for a state lifecycle hook. A string action ("pause", "resume", "despawn", "disable"), a plugin function, or a policy with both.

record tecs.ecs.StatePolicy.Action
    apply: string

    call: function(World)
end

tecs.ecs.StatePolicy.Action.apply field

Caller-writable. Built-in action: "pause", "resume", "despawn", "disable"

tecs.ecs.StatePolicy.Action.apply: string

tecs.ecs.StatePolicy.Action.call Static

Custom function called with the world

function tecs.ecs.StatePolicy.Action.call(World)
Arguments
Name Type Description
#1 World
Returns

None.

tecs.ecs.StatePolicy.onBlur field

Caller-writable. Fires when this state is no longer top (another state pushed on top).

tecs.ecs.StatePolicy.onBlur: string | Action | function(World)

tecs.ecs.StatePolicy.onFocus field

Caller-writable. Fires when this state becomes top again (state above popped).

tecs.ecs.StatePolicy.onFocus: string | Action | function(World)

tecs.ecs.StatePolicy.onExit field

Caller-writable. Fires when this state is popped (default: "despawn").

tecs.ecs.StatePolicy.onExit: string | Action | function(World)

tecs.ecs.StatePolicy.onEnter Static

Fires when this state is first pushed. Only accepts a plugin function.

function tecs.ecs.StatePolicy.onEnter(World)
Arguments
Name Type Description
#1 World
Returns

None.

tecs.ecs.Stats type

Stats reports live world counts.

type tecs.ecs.Stats = types.World.Stats

tecs.System type

A system function runs once when its phase dispatches.

type tecs.System = function(number, World)

tecs.ecs.SystemConfig interface

SystemConfig configures a system.

interface tecs.ecs.SystemConfig
    name: string
    phase: Phase
    run: System
    before: {string}
    after: {string}

    runIf: function(number, World, string): boolean
end

tecs.ecs.SystemConfig.name field

Caller-writable. Optional, and unique across the whole pipeline: registering a second system under a name already taken errors. Omitting it assigns a synthetic _anonymousSystemN, so removeSystem always has a handle, but the debugger, the MCP tools and profiles then show that instead of anything readable. Name every persistent system.

tecs.ecs.SystemConfig.name: string

tecs.ecs.SystemConfig.phase field

Caller-writable. Required, and must already be registered with the pipeline; addSystem errors on an unregistered phase rather than creating one.

tecs.ecs.SystemConfig.run field

Caller-writable. Required. Receives (dt, world), where dt is seconds and, in a fixed phase, is the fixed timestep rather than frame time.

tecs.ecs.SystemConfig.before field

Caller-writable. Names of systems this one must run before. A name that no system in the SAME phase carries is ignored silently: ordering is solved per phase, so a constraint naming a system in another phase does nothing. Mutual constraints across a group error as a cycle.

tecs.ecs.SystemConfig.before: {string}

tecs.ecs.SystemConfig.after field

Caller-writable. Names of systems this one must run after, on the same terms as before. Systems with no constraint between them keep registration order.

tecs.ecs.SystemConfig.after: {string}

tecs.ecs.SystemConfig.runIf Static

Optional gate evaluated immediately before each dispatch, so a false answer skips this frame only and does not unregister anything. Receives the same dt the system would have, plus the system's name, which is what a self-removing predicate passes back to removeSystem.

function tecs.ecs.SystemConfig.runIf(number, World, string): boolean
Arguments
Name Type Description
#1 number
#2 World
#3 string
Returns
Type Description
boolean

tecs.ecs.TagComponentOptions interface

TagComponentOptions configures a tag component.

interface tecs.ecs.TagComponentOptions is BasicComponentOptions<Component>
    container: Component
end

Interfaces

Interface
BasicComponentOptions<Component>

tecs.ecs.TagComponentOptions.container field

Caller-writable. Optional container to use for the tag component.

tecs.World interface

A world owns entities, components, queries, systems, resources, events, snapshots, and the state stack.

interface tecs.World
    interface Config
        timestep: number
        fixedMaxSteps: integer
        fixedOverload: FixedOverload
        maxEntities: integer

        pipelineFactory: function(
            timestep: number,
            fixedMaxSteps: integer,
            fixedOverload: FixedOverload
        ): Pipeline
    end

    interface SnapshotComponentTableEntry
        name: string
        fingerprint: string | nil
    end

    interface SnapshotPrelude
        version: integer
        nextEntityId: integer
        entityCount: integer
        archetypeCount: integer
        componentTable: {SnapshotComponentTableEntry}
    end

    interface SnapshotArchetypeEntry
        columnIndices: {integer}
        entities: {{any}}
    end

    interface SnapshotDataEntry
        key: string
        value: any
    end

    interface Snapshot
        version: integer
        nextEntityId: integer
        componentTable: {SnapshotComponentTableEntry}
        archetypes: {SnapshotArchetypeEntry}
        data: {SnapshotDataEntry}
    end

    enum SnapshotFormat
        "binary"
        "table"
    end

    interface SnapshotOptions
        format: SnapshotFormat
        buffer: StringBuffer
        path: string
        filterQuery: Query.Descriptor
        layers: {integer}
        customData: {string: any}
    end

    interface SnapshotOutput
        format: SnapshotFormat
        buffer: StringBuffer | nil
        snapshot: Snapshot | nil
    end

    interface SnapshotHandler
        name: string
        load: function(World, any) | nil
        finish: function(World, SnapshotPrelude) | nil

        save: function(world: World): any | nil
    end

    resources: Store
    interface Stats
        entities: integer
        archetypes: integer
        components: integer
        systems: integer
        fixedTimeDropped: number
        fixedStepsDropped: integer
    end

    addPlugin: function(self, plugin: Plugin)
    addSnapshotHandler: function(self, handler: SnapshotHandler)
    addSystem: function(self, config: SystemConfig)
    batchDespawn: function(self, query: Query)
    batchRemove: function(
        self, query: Query, componentType: components.Component
    )
    batchSet: function(
        self,
        query: Query,
        componentOrInstance: components.Component,
        callback: function(Archetype, integer, integer, integer)
    )
    batchSpawn: function(
        self,
        count: integer,
        componentTypes: {components.Component},
        callback: function(Archetype, integer, integer, integer)
    ): integer | nil, {integer} | nil
    batchSpawnAt: function(
        self,
        ids: {integer},
        componentTypes: {components.Component},
        callback: function(Archetype, integer, integer, integer)
    )
    byKey: function(self, key: string): integer | nil
    clearEntities: function(self)
    clearObservers: function(self, address: integer)
    commit: function(self)
    compact: function(self): integer, integer
    createState: function(
        self, name: string, policy: StatePolicy
    ): components.Component
    defer: function(self)
    despawn: function(self, entity: integer)
    dirtyArchetypes: function(self): function(): Archetype
    disablePhase: function(self, phase: Phase)
    emit: function(
        self, address: integer, eventOrType: events.Event, ...: any
    )
    enablePhase: function(self, phase: Phase)
    findArchetypes: function(
        self, component: components.Component
    ): function(): (Archetype, integer, DoubleArray)
    fixedStepCount: function(self): integer
    forEachArchetype: function(self, callback: function(Archetype))
    get: function<T is components.Component>(
        self, entity: integer, component: T
    ): T
    getBundle: function(self, name: string): Bundle | nil
    getBundles: function(self): {string: Bundle}
    getFirstRelationship: function<T is components.Relationship>(
        self, entity: integer, relationship: T
    ): T
    getFixedTiming: function(self): number, number, number
    getMut: function<T is components.Component>(
        self, entity: integer, component: T
    ): T
    getStats: function(self, fill: World.Stats): World.Stats
    has: function(
        self, entity: integer, component: components.Component
    ): boolean
    hasObservers: function<T is events.Event>(
        self, address: integer, event: T
    ): boolean
    isAlive: function(self, entity: integer): boolean
    loadSnapshot: function(self, source: any): SnapshotPrelude
    markComponentDirty: function(
        self, entity: integer, component: components.Component
    )
    newBundle: function(
        self, name: string, def: Bundle.Definition
    ): Bundle
    newQuery: function(self, descriptor: Query.Descriptor): Query
    observe: function<T is events.Event>(
        self,
        address: integer,
        event: T,
        callback: function(T),
        id: string
    )
    peekState: function(self): string
    popState: function(self)
    pushState: function(self, name: string)
    registerPhase: function(self, phase: Phase)
    remove: function(
        self, entity: integer, component: components.Component
    )
    removeSystem: function(self, systemName: string)
    requireKey: function(self, key: string): integer
    runPhase: function(self, phase: Phase, dt: number)
    saveSnapshot: function(self, opts: SnapshotOptions): SnapshotOutput
    set: function(
        self,
        entity: integer,
        component: components.Component,
        value: any
    )
    shutdown: function(self)
    spawn: function(self, ...: components.Component): integer
    spawnAt: function(self, id: integer, ...: components.Component)
    spawnBundle: function(
        self, name: string, ...: components.Component
    ): integer
    startup: function(self)
    stopObserving: function<T is events.Event>(
        self, address: integer, event: T, observer: function(T) | string
    )
    targets: function<T>(
        self,
        entity: integer,
        relationship: components.Relationship,
        callback: function(integer, T),
        context: T
    )
    traverse: function(
        self, root: integer, relationship: components.Relationship
    ): function(): (integer, integer)
    unwind: function(self)
    update: function(self, dt: number)
    walkUp: function<T>(
        self,
        entity: integer,
        relationship: components.Relationship,
        callback: function(integer, integer, T): boolean,
        context: T,
        maxDepth: number
    )
end

tecs.World.Config interface

The options passed to tecs.ecs.newWorld.

interface tecs.World.Config
    timestep: number
    fixedMaxSteps: integer
    fixedOverload: FixedOverload
    maxEntities: integer

    pipelineFactory: function(
        timestep: number,
        fixedMaxSteps: integer,
        fixedOverload: FixedOverload
    ): Pipeline
end

tecs.World.Config.timestep field

Caller-writable. Sets the positive duration of one fixed step in seconds. Defaults to 1/60.

tecs.World.Config.timestep: number

tecs.World.Config.fixedMaxSteps field

Caller-writable. Sets the positive number of fixed steps one update may run before the overload policy applies. Defaults to 10.

tecs.World.Config.fixedMaxSteps: integer

tecs.World.Config.fixedOverload field

Caller-writable. Selects what happens to catch-up steps that exceed fixedMaxSteps. Defaults to "drop".

tecs.World.Config.maxEntities field

Caller-writable. Sets the positive number of concurrent entity slots, up to 2^22 - 1. Defaults to 2^20.

tecs.World.Config.maxEntities: integer

tecs.World.Config.pipelineFactory Static

Caller-writable. Builds a custom system pipeline once during world construction. Most callers omit this field.

function tecs.World.Config.pipelineFactory(
    timestep: number,
    fixedMaxSteps: integer,
    fixedOverload: FixedOverload
): Pipeline
Arguments
Name Type Description
timestep number The configured fixed timestep.
fixedMaxSteps integer The configured fixed-step limit.
fixedOverload FixedOverload The configured overload policy.
Returns
Type Description
Pipeline The pipeline this world will run.

tecs.World.SnapshotComponentTableEntry interface

One component the snapshot's archetypes refer to. Archetype frames name components by 1-based index into the component table rather than repeating the name per archetype.

interface tecs.World.SnapshotComponentTableEntry
    name: string
    fingerprint: string | nil
end

tecs.World.SnapshotComponentTableEntry.name field

Caller-writable. Names the registered component a load resolves this entry against.

tecs.World.SnapshotComponentTableEntry.fingerprint field

Caller-writable. Carries the canonical FFI field-layout fingerprint, or nil for a non-FFI component. Binary output embeds it so a load can detect that the saved struct layout differs from the current one and route those rows through per-entity migration. nil for every non-FFI component, and absent entirely from "table" output, whose loads go through field-name-keyed deserialize and migrate without it.

tecs.World.SnapshotPrelude interface

The header of a snapshot, and what loadSnapshot answers with.

interface tecs.World.SnapshotPrelude
    version: integer
    nextEntityId: integer
    entityCount: integer
    archetypeCount: integer
    componentTable: {SnapshotComponentTableEntry}
end

tecs.World.SnapshotPrelude.version field

Read-only. Reports the snapshot format version, not the game version.

tecs.World.SnapshotPrelude.nextEntityId field

Read-only. Reports where entity slot allocation resumes. A load moves the allocator forward to this when it is ahead of where the allocator already is, and never backwards, so ids handed out after a load cannot collide with restored ones.

tecs.World.SnapshotPrelude.entityCount field

Read-only. Reports the entity count when the writer knew it, or nil for a streaming writer.

tecs.World.SnapshotPrelude.archetypeCount field

Read-only. Reports the archetype count when the writer knew it, or nil for a streaming writer.

tecs.World.SnapshotPrelude.componentTable field

Read-only. Lists every referenced component in archetype index order.

tecs.World.SnapshotPrelude.componentTable: {SnapshotComponentTableEntry}

tecs.World.SnapshotArchetypeEntry interface

One archetype's worth of entities in a "table" snapshot.

interface tecs.World.SnapshotArchetypeEntry
    columnIndices: {integer}
    entities: {{any}}
end

tecs.World.SnapshotArchetypeEntry.columnIndices field

Caller-writable. Lists 1-based indices into Snapshot.componentTable, in the same order the per-entity payloads appear.

tecs.World.SnapshotArchetypeEntry.entities field

Caller-writable. Holds one entry per entity, shaped {id, data1, ..., dataN}, where dataI is whatever the component at columnIndices[i] returned from serialize.

tecs.World.SnapshotDataEntry interface

One keyed value in a snapshot's data section.

interface tecs.World.SnapshotDataEntry
    key: string
    value: any
end

tecs.World.SnapshotDataEntry.key field

Caller-writable. Names the key a SnapshotHandler or customData entry wrote under. Keys beginning __tecs. are the engine's own.

tecs.World.SnapshotDataEntry.value field

Caller-writable. Holds the value written under key. It must survive the chosen format: a "binary" snapshot can carry anything the serializer accepts, a "table" one anything a plain Lua table can hold.

tecs.World.Snapshot interface

A whole snapshot in plain-table form, which is what saveSnapshot returns under format = "table".

interface tecs.World.Snapshot
    version: integer
    nextEntityId: integer
    componentTable: {SnapshotComponentTableEntry}
    archetypes: {SnapshotArchetypeEntry}
    data: {SnapshotDataEntry}
end

tecs.World.Snapshot.version field

Caller-writable. Sets the snapshot format version.

tecs.World.Snapshot.version: integer

tecs.World.Snapshot.nextEntityId field

Caller-writable. Sets the slot where entity allocation resumes.

tecs.World.Snapshot.componentTable field

Caller-writable. Lists the components referenced by the archetype entries; SnapshotArchetypeEntry.columnIndices points into it.

tecs.World.Snapshot.componentTable: {SnapshotComponentTableEntry}

tecs.World.Snapshot.archetypes field

Caller-writable. Lists archetypes in save order.

tecs.World.Snapshot.data field

Caller-writable. Lists keyed values after every archetype, in the order they were added, from opts.customData and from OnSnapshotSave listeners.

tecs.World.SnapshotFormat enum

Which of the two representations saveSnapshot produces.

enum tecs.World.SnapshotFormat
    "binary"
    "table"
end

tecs.World.SnapshotOptions interface

Options passed to saveSnapshot. All fields are optional.

interface tecs.World.SnapshotOptions
    format: SnapshotFormat
    buffer: StringBuffer
    path: string
    filterQuery: Query.Descriptor
    layers: {integer}
    customData: {string: any}
end

tecs.World.SnapshotOptions.format field

Caller-writable. Selects "binary" for a LuaJIT string.buffer or "table" for a plain table.

tecs.World.SnapshotOptions.buffer field

Caller-writable. Supplies a string.buffer to reset and reuse for binary output. It is reset before anything is written, so whatever it held is gone. Binary output only: passing one with format = "table" errors rather than being ignored.

tecs.World.SnapshotOptions.buffer: StringBuffer

tecs.World.SnapshotOptions.path field

Caller-writable. Supplies an optional path for binary output. When provided, saveSnapshot writes the bytes to disk and still returns the tagged buffer result. Binary output only: passing one with format = "table" errors rather than being ignored.

tecs.World.SnapshotOptions.filterQuery field

Caller-writable. Selects saved archetypes through a temporary query.

tecs.World.SnapshotOptions.layers field

Caller-writable. Allows only the listed Transform2D.layer values from 0 through 31.

tecs.World.SnapshotOptions.layers: {integer}

tecs.World.SnapshotOptions.customData field

Caller-writable. Adds keyed metadata to the snapshot.

tecs.World.SnapshotOptions.customData: {string: any}

tecs.World.SnapshotOutput interface

What saveSnapshot answers with. Exactly one of buffer and snapshot is set, and format says which; the other is nil. loadSnapshot accepts this record whole, so a round trip needs no unpacking.

interface tecs.World.SnapshotOutput
    format: SnapshotFormat
    buffer: StringBuffer | nil
    snapshot: Snapshot | nil
end

tecs.World.SnapshotOutput.format field

Read-only. Reports which representation carries the snapshot.

tecs.World.SnapshotOutput.buffer field

Read-only. Returns the bytes under format = "binary", or nil for table output. This is opts.buffer itself when one was passed, so a caller that reuses a buffer gets the same object back and must read it before the next save overwrites it.

tecs.World.SnapshotOutput.buffer: StringBuffer | nil

tecs.World.SnapshotOutput.snapshot field

Read-only. Returns the snapshot under format = "table", or nil for binary output. The table is freshly built and the caller's to keep.

tecs.World.SnapshotOutput.snapshot: Snapshot | nil

tecs.World.SnapshotHandler interface

Named snapshot participant for custom non-component data.

save writes one keyed value into the snapshot data section when it returns non-nil. load receives that value after the ECS world has been restored. finish runs after every data callback has completed.

interface tecs.World.SnapshotHandler
    name: string
    load: function(World, any) | nil
    finish: function(World, SnapshotPrelude) | nil

    save: function(world: World): any | nil
end

tecs.World.SnapshotHandler.name field

Caller-writable. Sets the non-empty key used to store the value or registration errors. Namespace it with dots ("myGame.gameState"); keys beginning __tecs. are the engine's own.

tecs.World.SnapshotHandler.load field

Caller-writable. Optionally receives saved data. Tecs calls it only when the snapshot carries this handler's key, so a snapshot saved before the handler existed simply does not call it.

tecs.World.SnapshotHandler.load: function(World, any) | nil

tecs.World.SnapshotHandler.finish field

Caller-writable. Optionally runs after every data callback has completed, which is the place for work that depends on more than one handler's value.

tecs.World.SnapshotHandler.finish: function(World, SnapshotPrelude) | nil

tecs.World.SnapshotHandler.save Static

Caller-writable. Optionally returns data to save. Returning nil writes no entry, which is how a handler declines rather than storing an empty value.

function tecs.World.SnapshotHandler.save(world: World): any | nil
Arguments
Name Type Description
world World The world being saved.
Returns
Type Description
any | nil The value to store, or nil to omit this handler.

tecs.World.resources field

Caller-writable. Stores world resources under typed keys.

tecs.World.Stats interface

Counts and fixed-step loss reported by world:getStats.

interface tecs.World.Stats
    entities: integer
    archetypes: integer
    components: integer
    systems: integer
    fixedTimeDropped: number
    fixedStepsDropped: integer
end

tecs.World.Stats.entities field

Read-only. Reports the number of active entities.

tecs.World.Stats.entities: integer

tecs.World.Stats.archetypes field

Read-only. Reports the number of archetypes.

tecs.World.Stats.archetypes: integer

tecs.World.Stats.components field

Read-only. Reports the number of registered components.

tecs.World.Stats.components: integer

tecs.World.Stats.systems field

Read-only. Reports the number of registered systems.

tecs.World.Stats.systems: integer

tecs.World.Stats.fixedTimeDropped field

Read-only. Reports simulated seconds abandoned by the fixed step overload policy.

tecs.World.Stats.fixedStepsDropped field

Read-only. Reports fixed steps abandoned by the overload policy.

tecs.World:addPlugin Instance

Add a plugin to the world.

function tecs.World.addPlugin(self, plugin: Plugin)
Arguments
Name Type Description
self World
plugin Plugin The plugin to add.
Returns

None.

tecs.World:addSnapshotHandler Instance

Register named save/load callbacks for custom snapshot data.

This is a convenience wrapper over OnSnapshotSave, StartSnapshotLoad, and FinishSnapshotLoad. Use the raw snapshot events when you need lower-level behavior such as excluding derived entities.

function tecs.World.addSnapshotHandler(self, handler: SnapshotHandler)
Arguments
Name Type Description
self World
handler SnapshotHandler Its name is an externally typed snapshot key and must remain stable across builds.
Returns

None.

tecs.World:addSystem Instance

Add a system to the world.

function tecs.World.addSystem(self, config: SystemConfig)
Arguments
Name Type Description
self World
config SystemConfig The system configuration.
Returns

None.

tecs.World:batchDespawn Instance

Bulk-despawn every entity matching query. The actual teardown is deferred until the next commit.

query must be a Query object built via world:newQuery(...) and reused across calls -- batch ops do not accept QueryDescriptors or raw component-type arrays. Build the query once outside your hot loop.

At commit time, events and relationship bookkeeping run as expected: * OnDespawn events fire for each despawned entity (global observers and per-entity observers). * Per-entity observer subscriptions are cleared after the event fans out. * Query observers receive a single onEntitiesRemoved for the full range, followed by onDeactivated when the archetype empties. * Archetypes with dense relationships or entities that are reverse-index targets fall back to per-entity despawn so cascade-delete and reverse-index unlink run correctly.

function tecs.World.batchDespawn(self, query: Query)
Arguments
Name Type Description
self World
query Query Query built via world:newQuery(...).
Returns

None.

tecs.World:batchRemove Instance

Bulk-remove a component from every entity matching query whose archetype currently carries it. Archetypes in the query that lack the component are skipped silently (no-op).

Fast path runs when the target component is plain (no bulk-incompatible behavior flag, no wildcard container, not sparse): one bulk move to src:withoutComponent(type) per matched archetype, no per-entity dispatch. Relationship-bearing or otherwise non-bulk components fall back to per-entity world:remove so reverse-index unlink and cascade delete run correctly. Other components in the source archetype do not affect path selection.

function tecs.World.batchRemove(
    self, query: Query, componentType: components.Component
)
Arguments
Name Type Description
self World
query Query Query built via world:newQuery(...).
componentType components.Component Component to remove.
Returns

None.

tecs.World:batchSet Instance

Bulk-set a component on every entity matching query.

Two modes: * Constant: world:batchSet(q, Stunned) or world:batchSet(q, Position(0, 0)). The instance is copied to every matched row. If an archetype lacks the component, entities are bulk-moved to the archetype src:withComponent(type) first, then the new column is filled. * Callback: world:batchSet(q, Position, function(arch, firstRow, lastRow, count) ... end). Component is ensured to exist (bulk move if needed), then the callback is invoked once per affected archetype with 1-based inclusive row bounds so the caller can write the column directly.

Fast path runs when the target component is "plain": it has no bulk-incompatible behavior flag, is not a dense relationship instance (no wildcard container), and is not sparse. Fast path does one move plan per (src, dst) archetype, bulk column copy, and whole-archetype truncate. Relationship-bearing or otherwise non-bulk components fall back to per-entity world:set for correctness (const form only; see below).

Callback form additionally requires the target component to be plain because the callback is the value-write step. Non-bulk components must use the constant-value form.

Sparse relationships always route through the per-entity path since they live in per-world stores, not archetype columns.

function tecs.World.batchSet(
    self,
    query: Query,
    componentOrInstance: components.Component,
    callback: function(Archetype, integer, integer, integer)
)
Arguments
Name Type Description
self World
query Query Query built via world:newQuery(...).
componentOrInstance components.Component Component instance (const mode) or component type (callback mode).
callback function(Archetype, integer, integer, integer) Optional chunk writer (arch, firstRow, lastRow, count).
Returns

None.

tecs.World:batchSpawn Instance

Bulk-spawn count entities sharing one component signature. Resolves the target archetype once at call time and defers the actual row placement and callback invocation until the next commit.

Returns (firstId, nil) when it can allocate a contiguous ID range. In that case IDs are firstId, firstId + 1, ..., firstId + count - 1.

Returns (nil, ids) when it falls back to recycled, non-contiguous IDs. In that case iterate the returned ids list explicitly.

Returned IDs are valid immediately -- you can call world:set, world:remove, or world:despawn on them before commit and the mutations are ordered correctly.

At commit time the target archetype's row range is claimed, then callback(archetype, firstRow, lastRow, count) runs so you can write per-entity data via mutable column access (archetype:getMut(Component)[row] = ...).

Relationship components (dense or sparse) are supported in the signature as either the bare container (e.g. ChildOf) or as a specific-target instance (e.g. ChildOf(parent)). When an instance is passed, its wildcard container is added to the archetype automatically -- no follow-up world:set is needed for queries on the bare container to match.

Sparse relationship columns are row-indexed proxies that error on direct writes from the callback. For per-entity varying target values, call world:set(spawnedId, SparseRel(target)) either inside the callback or any time before commit. Use firstId + i only when the return was contiguous; otherwise use the explicit ids list. The staged sparse sets drain alongside the batchSpawn placement.

function tecs.World.batchSpawn(
    self,
    count: integer,
    componentTypes: {components.Component},
    callback: function(Archetype, integer, integer, integer)
): integer | nil, {integer} | nil
Arguments
Name Type Description
self World
count integer Number of entities to spawn.
componentTypes {components.Component} Array of component types defining the archetype.
callback function(Archetype, integer, integer, integer) Called at commit with (archetype, firstRow, lastRow, count). Iterate rows with for i = firstRow, lastRow do ... end.
Returns
Type Description
integer | nil firstId First entity ID when the allocation is contiguous, otherwise nil.
{integer} | nil ids Explicit entity ID list when fallback uses non-contiguous IDs, otherwise nil.

tecs.World:batchSpawnAt Instance

Like batchSpawn, but uses the supplied entity IDs instead of allocating a new contiguous range. Intended for snapshot loads where each restored entity keeps its original ID. The archetype resolution, capacity check, and required-component expansion happen once per call regardless of ID ordering.

function tecs.World.batchSpawnAt(
    self,
    ids: {integer},
    componentTypes: {components.Component},
    callback: function(Archetype, integer, integer, integer)
)
Arguments
Name Type Description
self World
ids {integer} Explicit entity IDs to spawn, in order.
componentTypes {components.Component} Array of component types defining the archetype.
callback function(Archetype, integer, integer, integer) Called at commit with (archetype, firstRow, lastRow, count).
Returns

None.

tecs.World:byKey Instance

Return the live entity currently carrying tecs.ecs.EntityKey(key), or nil if no live entity has that key.

function tecs.World.byKey(self, key: string): integer | nil
Arguments
Name Type Description
self World
key string The durable key to find.
Returns
Type Description
integer | nil The live entity, or nil when the key has none.

tecs.World:clearEntities Instance

Wipe all entity data but preserve structural state (pipeline, registered systems, queries, query observers, archetype column capacity). Use this for per-test reuse, benchmark setup, and save/load clear-before-load.

Clears: entities, pending transaction, sparse relationship stores and queued messages. Preserves: systems, queries, archetype columns, observers.

If you need post-construction state (systems gone, queries gone), just call tecs.ecs.newWorld() -- same path, clearer intent.

function tecs.World.clearEntities(self)
Arguments
Name Type Description
self World
Returns

None.

tecs.World:clearObservers Instance

Clear all observers for an address (used on entity despawn).

function tecs.World.clearObservers(self, address: integer)
Arguments
Name Type Description
self World
address integer Every event type at this address is cleared, not one. Address zero is the world's own, so clearing it removes every broadcast observer the world has.
Returns

None.

tecs.World:commit Instance

Close one scope level and drain pending changes when the outermost scope finishes.

function tecs.World.commit(self)
Arguments
Name Type Description
self World
Returns

None.

tecs.World:compact Instance

Compact the world: prune dead archetypes whose relationship targets have been despawned and shrink overallocated archetype storage. Must be called on a quiet world (no pending mutations).

function tecs.World.compact(self): integer, integer
Arguments
Name Type Description
self World
Returns
Type Description
integer archetypesPruned Number of dead archetypes removed.
integer archetypesCompacted Number of archetypes whose storage was shrunk.

tecs.World:createState Instance

Create a named state with an optional lifecycle policy.

Returns a tag component that is auto-added to entities spawned while this state is on top of the stack.

function tecs.World.createState(
    self, name: string, policy: StatePolicy
): components.Component
Arguments
Name Type Description
self World
name string The name of the state.
policy StatePolicy Optional lifecycle policy for state transitions.
Returns
Type Description
components.Component The tag component for this state.

tecs.World:defer Instance

Open a defer scope. Mutations within the scope are staged and drained on the matching commit. Pairs with commit.

function tecs.World.defer(self)
Arguments
Name Type Description
self World
Returns

None.

tecs.World:despawn Instance

Despawn an entity.

function tecs.World.despawn(self, entity: integer)
Arguments
Name Type Description
self World
entity integer The entity to despawn.
Returns

None.

tecs.World:dirtyArchetypes Instance

Return an iterator over archetypes whose rows have been mutated since the last world:update(). Used by systems that consume dirty state incrementally (GPU shadow upload, reactive systems, debug tooling). The set is cleared automatically at the end of each update() after the pipeline finishes.

Same iteration constraint as queries: do not mutate the world during iteration.

function tecs.World.dirtyArchetypes(self): function(): Archetype
Arguments
Name Type Description
self World
Returns
Type Description
function():Archetype

tecs.World:disablePhase Instance

Disable a phase.

function tecs.World.disablePhase(self, phase: Phase)
Arguments
Name Type Description
self World
phase Phase The phase to disable.
Returns

None.

tecs.World:emit Instance

Emit an event to an address. Use 0 for world-level events, entity ID for entity events.

function tecs.World.emit(
    self, address: integer, eventOrType: events.Event, ...: any
)
Arguments
Name Type Description
self World
address integer The address to emit to (0 for world, entity ID for entity).
eventOrType events.Event The event instance to emit, or an event type plus constructor args.
... any Constructor arguments when eventOrType is an event type.
Returns

None.

tecs.World:enablePhase Instance

Enable a phase.

function tecs.World.enablePhase(self, phase: Phase)
Arguments
Name Type Description
self World
phase Phase The phase to enable.
Returns

None.

tecs.World:findArchetypes Instance

Find archetypes that have the given component.

function tecs.World.findArchetypes(
    self, component: components.Component
): function(): (Archetype, integer, DoubleArray)
Arguments
Name Type Description
self World
component components.Component The component to find.
Returns
Type Description
function(): (Archetype, integer, DoubleArray) an iterator over the archetypes that have the component.

tecs.World:fixedStepCount Instance

Fixed steps run since the world was made.

The clock for anything that advances on the simulation rather than on frame time. It counts steps rather than summing seconds, so two runs fed the same steps read the same number however many frames either of them drew, and the value stays a whole number.

Counted whether or not any system is registered in a fixed phase.

function tecs.World.fixedStepCount(self): integer
Arguments
Name Type Description
self World
Returns
Type Description
integer Steps run, from zero.

tecs.World:forEachArchetype Instance

Iterate all archetypes in the world. Mainly useful for save game / debugging tools that need to walk entity state without matching a specific component signature.

function tecs.World.forEachArchetype(
    self, callback: function(Archetype)
)
Arguments
Name Type Description
self World
callback function(Archetype) Called with each archetype.
Returns

None.

tecs.World:get Instance

Get a component instance attached to an entity.

function tecs.World.get<T is components.Component>(
    self, entity: integer, component: T
): T
Type Parameters
Name Constraint Description
T components.Component
Arguments
Name Type Description
self World
entity integer Entity ID.
component T Component type to get.
Returns
Type Description
T The component instance or nil if not found.

tecs.World:getBundle Instance

Get a registered bundle by name.

function tecs.World.getBundle(self, name: string): Bundle | nil
Arguments
Name Type Description
self World
name string The bundle name.
Returns
Type Description
Bundle | nil The bundle, or nil if not found.

tecs.World:getBundles Instance

Get all registered bundles.

function tecs.World.getBundles(self): {string: Bundle}
Arguments
Name Type Description
self World
Returns
Type Description
{string : Bundle} A fresh map of bundle name to bundle.

tecs.World:getFirstRelationship Instance

Get the first relationship instance for a relationship container on an entity. For exclusive relationships (like ChildOf), this returns the single instance.

function tecs.World.getFirstRelationship<T is components.Relationship>(
    self, entity: integer, relationship: T
): T
Type Parameters
Name Constraint Description
T components.Relationship
Arguments
Name Type Description
self World
entity integer Entity ID.
relationship T Relationship container type.
Returns
Type Description
T The relationship instance or nil if not found.

tecs.World:getFixedTiming Instance

Return fixed-step timing for interpolation consumers.

The return values are the fixed timestep, the residual time not consumed by fixed updates, and the residual divided by the timestep clamped to [0, 1]. This method does not allocate.

The fixed-step clock advances even when fixed phases are disabled.

function tecs.World.getFixedTiming(self): number, number, number
Arguments
Name Type Description
self World
Returns
Type Description
number timestep Fixed update interval in seconds.
number accumulator Residual time in seconds.
number alpha Clamped interpolation fraction.

tecs.World:getMut Instance

Mutable counterpart to get. Returns the component AND marks it dirty on the entity's archetype so dirty-gated consumers (shadow pipeline, change observers) re-process the row after subsequent cdata writes. Use this whenever you intend to mutate the component through the returned reference. get + cdata write silently bypasses dirty tracking and leaves stale state downstream.

STAGING: an entity spawned earlier in the SAME frame is staged until the commit drain, so getMut on it returns nil. Spawn with final values via constructor args instead of spawn-then-mutate.

function tecs.World.getMut<T is components.Component>(
    self, entity: integer, component: T
): T
Type Parameters
Name Constraint Description
T components.Component
Arguments
Name Type Description
self World
entity integer Entity ID.
component T Component type to get-and-mark-dirty.
Returns
Type Description
T The component instance or nil if not found.

tecs.World:getStats Instance

Get stats about the World.

function tecs.World.getStats(self, fill: World.Stats): World.Stats
Arguments
Name Type Description
self World
fill World.Stats Optional stats table to fill instead of allocating a new one. Passing one every frame is how this is read without adding a table per frame to the collector.
Returns
Type Description
World.Stats The same table fill named when one was given, so the caller already holds it. A fresh one otherwise, and either way a copy rather than a view: the numbers do not update on their own.

tecs.World:has Instance

Check whether an entity currently has a component.

For sparse relationships: - passing the relationship container checks whether the entity has any target for that relationship - passing a relationship instance checks that specific target

function tecs.World.has(
    self, entity: integer, component: components.Component
): boolean
Arguments
Name Type Description
self World
entity integer Entity ID.
component components.Component Component type (or relationship instance) to check.
Returns
Type Description
boolean true if present, false otherwise.

tecs.World:hasObservers Instance

Check if there are observers for an event at an address.

function tecs.World.hasObservers<T is events.Event>(
    self, address: integer, event: T
): boolean
Type Parameters
Name Constraint Description
T events.Event
Arguments
Name Type Description
self World
address integer The world address or entity identifier.
event T The event type to inspect.
Returns
Type Description
boolean True when the address has an observer for this event type.

tecs.World:isAlive Instance

Check if an entity is committed and alive.

function tecs.World.isAlive(self, entity: integer): boolean
Arguments
Name Type Description
self World
entity integer The entity to check.
Returns
Type Description
boolean true if the entity is committed and alive, false otherwise.

tecs.World:loadSnapshot Instance

Restore the world from either binary or table form.

source may be a Lua string, a LuaJIT string.buffer, or a snapshot table previously returned by saveSnapshot with format = "table" (or parsed from JSON).

function tecs.World.loadSnapshot(self, source: any): SnapshotPrelude
Arguments
Name Type Description
self World
source any One of the three forms above. Every entity already in the world is despawned before the first one is restored, so this replaces a world rather than merging into one.
Returns
Type Description
SnapshotPrelude What the snapshot said about itself. The prelude is read first but handed back last, so a caller that meant to reject an unwanted version reads it after the world has already been replaced.

tecs.World:markComponentDirty Instance

Mark a component dirty on the entity's archetype. Used when code mutates a component's bytes through a path that doesn't go through archetype:getMut (e.g. a smart wrapper that holds an entity id and writes through a fetched FFI cdata).

function tecs.World.markComponentDirty(
    self, entity: integer, component: components.Component
)
Arguments
Name Type Description
self World
entity integer Entity ID.
component components.Component Component type whose column was mutated.
Returns

None.

tecs.World:newBundle Instance

Create and register a bundle with the world.

function tecs.World.newBundle(
    self, name: string, def: Bundle.Definition
): Bundle
Arguments
Name Type Description
self World
name string The name of the bundle.
def Bundle.Definition Bundle definition with required and with-default components.
Returns
Type Description
Bundle The registered bundle.

tecs.World:newQuery Instance

Creates a new query. Iteration does NOT auto-mark anything dirty; mutation intent lives at the access site via archetype:getMut(Foo) inside the iter loop, which marks just that component dirty on the archetype.

function tecs.World.newQuery(
    self, descriptor: Query.Descriptor
): Query
Arguments
Name Type Description
self World
descriptor Query.Descriptor Read here and not retained, so editing it afterwards does not change the query. Give it a name for anything that outlives a call: the debugger and the profiles address queries by name.
Returns
Type Description
Query A query that keeps itself current as archetypes appear, so it is built once during plugin setup and reused. Building one inside a system's run pays the match cost every frame.

tecs.World:observe Instance

Observe an event at an address. Use 0 for world-level events, entity ID for entity events.

function tecs.World.observe<T is events.Event>(
    self, address: integer, event: T, callback: function(T), id: string
)
Type Parameters
Name Constraint Description
T events.Event
Arguments
Name Type Description
self World
address integer The address to observe (0 for world, entity ID for entity).
event T The event type to observe.
callback function(T) The callback to call when the event is emitted.
id string Optional ID for the observer.
Returns

None.

tecs.World:peekState Instance

Peek at the current top state name.

function tecs.World.peekState(self): string
Arguments
Name Type Description
self World
Returns
Type Description
string The name of the top state, or nil if the stack is empty.

tecs.World:popState Instance

Pop the current state from the state stack.

Fires the current state's onExit policy and the new top state's onFocus policy.

function tecs.World.popState(self)
Arguments
Name Type Description
self World
Returns

None.

tecs.World:pushState Instance

Push a state onto the state stack.

Fires the previous top state's onBlur policy and the new state's onEnter policy. Entities spawned after this call will automatically receive the state's tag component.

function tecs.World.pushState(self, name: string)
Arguments
Name Type Description
self World
name string The state name (must have been created with createState).
Returns

None.

tecs.World:registerPhase Instance

Register a custom phase with the world's pipeline. This allows external modules to define their own phases.

function tecs.World.registerPhase(self, phase: Phase)
Arguments
Name Type Description
self World
phase Phase The phase to register.
Returns

None.

tecs.World:remove Instance

Remove a component from an entity.

function tecs.World.remove(
    self, entity: integer, component: components.Component
)
Arguments
Name Type Description
self World
entity integer Entity ID.
component components.Component Component type to remove.
Returns

None.

tecs.World:removeSystem Instance

Remove a system from the world.

function tecs.World.removeSystem(self, systemName: string)
Arguments
Name Type Description
self World
systemName string The name of the system to remove.
Returns

None.

tecs.World:requireKey Instance

Return the live entity currently carrying tecs.ecs.EntityKey(key), or error if no live entity has that key.

function tecs.World.requireKey(self, key: string): integer
Arguments
Name Type Description
self World
key string The durable key to find.
Returns
Type Description
integer The live entity.

tecs.World:runPhase Instance

Run every system registered to phase (and its enabled descendants) with the given dt. Unlike update, this does NOT pre-commit or clear dirty bits -- it only dispatches systems. Useful for piecewise phase execution (e.g. custom game loops splitting Update and Render across distinct ticks).

function tecs.World.runPhase(self, phase: Phase, dt: number)
Arguments
Name Type Description
self World
phase Phase The phase to run.
dt number The elapsed seconds passed to its systems, or zero when omitted.
Returns

None.

tecs.World:saveSnapshot Instance

Save the world to either binary or table form.

Binary is the default. Set opts.format = "table" for a plain Lua snapshot table. opts.path is supported only for binary output.

function tecs.World.saveSnapshot(
    self, opts: SnapshotOptions
): SnapshotOutput
Arguments
Name Type Description
self World
opts SnapshotOptions May be nil, which writes binary and returns it rather than writing a file. Components registered transient are left out whatever this says, so a snapshot never carries a live handle.
Returns
Type Description
SnapshotOutput The snapshot, in whichever form was asked for. Taken from the world as it stands, so this is a point-in-time copy and later changes do not reach it.

tecs.World:set Instance

Add or update a component on an entity.

function tecs.World.set(
    self, entity: integer, component: components.Component, value: any
)
Arguments
Name Type Description
self World
entity integer Entity ID.
component components.Component The component instance or scalar component type.
value any The scalar value, or nil to use the registered default.
Returns

None.

tecs.World:shutdown Instance

Run the shutdown systems.

function tecs.World.shutdown(self)
Arguments
Name Type Description
self World
Returns

None.

tecs.World:spawn Instance

Spawn a new entity with optional variadic components.

function tecs.World.spawn(
    self, ...: components.Component
): integer
Arguments
Name Type Description
self World
... components.Component Variable number of components to add to the entity.
Returns
Type Description
integer The ID of the spawned entity.

tecs.World:spawnAt Instance

Spawn an entity at a specific packed id rather than auto- allocating. The id carries both slot and generation, so relationship targets resolve to the same entity across a save/load cycle. The caller is responsible for ensuring the id's slot is not already live.

function tecs.World.spawnAt(
    self, id: integer, ...: components.Component
)
Arguments
Name Type Description
self World
id integer The packed entity id to reuse.
... components.Component Variable number of components to add to the entity.
Returns

None.

tecs.World:spawnBundle Instance

Spawn an entity using a registered bundle.

function tecs.World.spawnBundle(
    self, name: string, ...: components.Component
): integer
Arguments
Name Type Description
self World
name string The name of the bundle.
... components.Component Component overrides (required components must be provided).
Returns
Type Description
integer The entity ID.

tecs.World:startup Instance

Run the startup systems.

function tecs.World.startup(self)
Arguments
Name Type Description
self World
Returns

None.

tecs.World:stopObserving Instance

Stop observing an event at an address.

function tecs.World.stopObserving<T is events.Event>(
    self, address: integer, event: T, observer: function(T) | string
)
Type Parameters
Name Constraint Description
T events.Event
Arguments
Name Type Description
self World
address integer The address to stop observing.
event T The event type to stop observing.
observer function(T) | string The observer function or ID.
Returns

None.

tecs.World:targets Instance

Get all source entities that target a given entity via a sparse relationship. For ChildOf, this returns the children of the entity.

The optional context is forwarded to the callback as its second argument so visitors can be hoisted to module scope and read/write state via the context table without per-call closure allocation. Context is appended last so existing single-arg callbacks (function(srcId)) keep working -- Lua silently drops extra args.

function tecs.World.targets<T>(
    self,
    entity: integer,
    relationship: components.Relationship,
    callback: function(integer, T),
    context: T
)
Type Parameters
Name Constraint Description
T
Arguments
Name Type Description
self World
entity integer The target entity ID.
relationship components.Relationship The sparse relationship container.
callback function(integer, T) Receives (sourceId, context) for each source.
context T Optional context value forwarded to the callback.
Returns

None.

tecs.World:traverse Instance

Depth-first traversal over a sparse relationship's inverse index. For example, this can be used to walk the ChildOf hierarchy of a node from the top down.

function tecs.World.traverse(
    self, root: integer, relationship: components.Relationship
): function(): (integer, integer)
Arguments
Name Type Description
self World
root integer The root entity ID.
relationship components.Relationship The sparse relationship container.
Returns
Type Description
function(): (integer, integer) An iterator yielding (depth, entityId) for each descendant.

tecs.World:unwind Instance

Close every open scope and apply what they staged.

The recovery path after something threw part way through a frame. A throw inside query:iter() skips the pop that ends the loop's scope, and a world left deferred stages every later mutation rather than applying it, silently. This is what puts it back, and it is safe on a healthy world: at depth zero it is the drain commit already does.

function tecs.World.unwind(self)
Arguments
Name Type Description
self World
Returns

None.

tecs.World:update Instance

Update the world.

function tecs.World.update(self, dt: number)
Arguments
Name Type Description
self World
dt number The time since the last update.
Returns

None.

tecs.World:walkUp Instance

Walk up a relationship chain, calling callback for each ancestor. Follows the first target per level (equivalent to repeated getFirstRelationship), so semantics match exclusive relationships like ChildOf exactly and fall back to "first edge" for non-exclusive ones.

Depth starts at 1 (direct parent) and increments per level. The callback may return false to stop the walk early; any other return value (including nil / no return) continues. maxDepth defaults to 100 and triggers a hard error if exceeded so accidental cycles surface immediately.

The optional context is passed through to the callback unchanged, so a visitor function can live at module scope and read/write its state via the context table without per-call closure allocation.

function tecs.World.walkUp<T>(
    self,
    entity: integer,
    relationship: components.Relationship,
    callback: function(integer, integer, T): boolean,
    context: T,
    maxDepth: number
)
Type Parameters
Name Constraint Description
T
Arguments
Name Type Description
self World
entity integer The entity to walk up from.
relationship components.Relationship The relationship to follow.
callback function(integer, integer, T): boolean Receives (ancestorId, depth, context). Return false to stop.
context T Optional context value forwarded to the callback as its 3rd arg.
maxDepth number Safety cap, defaults to 100. Errors if exceeded.
Returns

None.

Functions

tecs.ecs.declaredComponents Static

Returns every component declared in this process.

A fresh table per call, so the registry itself stays unwritable from outside registration.

The result omits dense relationship instances. Registration creates one stamped component per target, and no caller declared those components.

function tecs.ecs.declaredComponents(): {string: Component}

Arguments

None.

Returns

Type Description
{string :Component} Returns a fresh caller-owned name-to-component table that omits generated dense relationship instances.

tecs.ecs.findComponentById Static

Returns a registered component by numeric id.

function tecs.ecs.findComponentById(id: integer): Component

Arguments

Name Type Description
id integer The caller supplies a process-wide component id.

Returns

Type Description
Component Returns the component, or nil for an unallocated id. Numeric ids do not remain stable across runs.

tecs.ecs.findComponentByName Static

Returns the component registered under name.

The process-wide registry allocates each component id once, and every world agrees on it. This function answers which components have names; a world answers which components it carries.

Finds a dense relationship instance by its stamped name as well, which declaredComponents leaves out.

function tecs.ecs.findComponentByName(name: string): Component

Arguments

Name Type Description
name string The caller supplies the process-wide registration name.

Returns

Type Description
Component Returns the component, or nil when nothing has registered that name.

Values

tecs.ecs.ArchetypeCreated variable

Read-only. ArchetypeCreated fires at entity 0 after archetype creation.

tecs.ecs.ChildOf variable

Read-only. ChildOf links a parent and child. It stores edges sparsely and cascade-deletes children with their parent.

tecs.ecs.DEFAULTMAXENTITIES variable

Read-only. DEFAULT_MAX_ENTITIES supplies 2^20 when world configuration omits maxEntities.

tecs.ecs.DEFAULT_MAX_ENTITIES: integer

tecs.ecs.Disabled variable

Read-only. Disabled excludes an entity from queries that do not ask for it.

tecs.ecs.EntityKey variable

Read-only. EntityKey stores a durable unique lookup key for world:byKey. It supports hot reload, authored references, tooling, and save-compatible lookup.

The registered component name is the externally typed string "Key". tecs.data.Key names typed store keys.

tecs.ecs.EntityKey: ScalarComponent<string>

tecs.ecs.FinishSnapshotLoad variable

Read-only. FinishSnapshotLoad fires at entity 0 after every entity and data callback finishes restoration.

tecs.ecs.MAX_ENTITIES variable

Read-only. MAX_ENTITIES sets the absolute World.Config.maxEntities ceiling (2^22 - 1 usable slots; the entity-id format reserves slot 0).

tecs.ecs.MAX_ENTITIES: integer

tecs.ecs.Name variable

Read-only. Name stores an entity label as a raw string. It does not enforce uniqueness. Use EntityKey for durable unique lookup.

tecs.ecs.Name: ScalarComponent<string>

tecs.ecs.OnDespawn variable

Read-only. OnDespawn fires at an entity before removal.

tecs.ecs.OnDespawn: builtins.OnDespawn

tecs.ecs.OnSnapshotSave variable

Read-only. OnSnapshotSave fires at entity 0 before snapshot archetype serialization so plugins can attach keyed data or exclude derived data.

tecs.ecs.OnSnapshotSave: builtins.OnSnapshotSave

tecs.ecs.OnSpawn variable

Read-only. OnSpawn fires at an entity after spawning.

tecs.ecs.OnSpawn: builtins.OnSpawn

tecs.ecs.Paused variable

Read-only. Paused excludes an entity from logic queries while keeping it visible. Disabled excludes both logic and rendering queries.

tecs.ecs.Paused: Component

tecs.ecs.RelativeTransform2D variable

Read-only. RelativeTransform2D expresses a pose relative to a ChildOf parent. The hierarchy system composes it with the parent's Transform2D, so a game writes this component and reads the world-space transform.

tecs.ecs.runif variable

Read-only. runif contains composable system run conditions.

tecs.ecs.runif: runIfHelpers

tecs.ecs.StartSnapshotLoad variable

Read-only. StartSnapshotLoad fires at entity 0 after world restoration and before data dispatch so plugins can register their keyed handlers.

tecs.ecs.StateBlur variable

Read-only. StateBlur fires at a state when another takes focus above it.

tecs.ecs.StateBlur: builtins.StateBlur

tecs.ecs.StateEnter variable

Read-only. StateEnter fires when a state enters the stack.

tecs.ecs.StateEnter: builtins.StateEnter

tecs.ecs.StateExit variable

Read-only. StateExit fires when a state leaves the stack.

tecs.ecs.StateExit: builtins.StateExit

tecs.ecs.StateFocus variable

Read-only. StateFocus fires at a state when it regains focus.

tecs.ecs.StateFocus: builtins.StateFocus

tecs.ecs.Transform2D variable

Read-only. Transform2D positions everything a world holds. Hierarchy, physics, sequencing, and rendering all use it.

tecs.ecs.Transform2D: builtins.Transform2D

tecs.ecs.Transform3D variable

Read-only. Transform3D places an entity in a right-handed 3D world. Its quaternion turns local coordinates into world coordinates and uses (x, y, z, w) field order.

tecs.ecs.Transform3D: builtins.Transform3D

tecs.ecs.TTL variable

Read-only. TTL despawns an entity when its time to live reaches zero. The engine counts it down in FixedUpdate through a logic query, so a Paused entity does not burn through it.

tecs.ecs.TTL: builtins.TTL