On this page
- tecs.ecs
Types
- Archetype
- ArchetypeEntityObserver
- Bundle
- BundleDef
- Closeable
- Component
- ComponentOptions
- ContainerComponentOptions
- DoubleArray
- FFIComponentOptions
- FFIRelationshipOptions
- FixedOverload
- Phase
- phases
- Pipeline
- tecs.Plugin
- tecs.Query
- QueryCursor
- QueryDescriptor
- Relationship
- RelationshipOptions
- ScalarComponent
- ScalarComponentOptions
- Snapshot
- SnapshotComponentTableEntry
- SnapshotHandler
- SnapshotOptions
- SnapshotOutput
- SnapshotPrelude
- StatePolicy
- Stats
- tecs.System
- SystemConfig
- TagComponentOptions
- tecs.World
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))
endRead 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>
): CType 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>
): CType 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>
): RType 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>
): RType 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
): ComponentArguments
| 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.
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
)
endtecs.ecs.Archetype.id field
Read-only. The unique identifier of the archetype in the ECS container.
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.entities: DoubleArraytecs.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): booleanArguments
| Name | Type | Description |
|---|---|---|
self |
Archetype |
Returns
| Type | Description |
|---|---|
boolean |
tecs.ecs.Archetype:dirtyComponents Instance
Iterate components currently marked dirty on this archetype.
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.
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
): TType 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.
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.
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.
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.
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
)
endtecs.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
endtecs.ecs.Bundle.Definition interface
Declarative bundle definition.
interface tecs.ecs.Bundle.Definition
required: {components.Component}
with: {components.Component: boolean | function(): components.Component}
endtecs.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.required field
Read-only. Component names that must be provided when spawning.
tecs.ecs.Bundle.defaulted field
Read-only. Component names with default factories.
tecs.ecs.Bundle:spawn Instance
Spawn an entity using this bundle.
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}
endtecs.ecs.BundleDef.required field
Caller-writable. Components that must be provided as positional args to spawn().
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.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
endtecs.ecs.Closeable:close Instance
Releases the value's active lifetime.
function tecs.ecs.Closeable.close(self): boolean, stringArguments
| 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}
__call: function(self, ...: any): self
endtecs.ecs.Component.componentType field
Read-only. The container type of the component, available on instances and containers.
tecs.ecs.Component.componentType: selftecs.ecs.Component.componentName field
Read-only. The name of the component.
tecs.ecs.Component.componentName: stringtecs.ecs.Component.componentId field
Read-only. The auto-incrementing ID of the component container.
tecs.ecs.Component.componentId: integertecs.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.relationshipType: Componenttecs.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.wildcardContainer: Componenttecs.ecs.Component.target field
Read-only. Relationship components only: The target entity ID (for relationship instances only).
tecs.ecs.Component.transient field
Read-only. True if this component is runtime-only and omitted from snapshots.
tecs.ecs.Component.deserialize Static
Deserialize a component instance from a plain table.
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}): selfArguments
| 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
Creates an instance of the component from the container using positional arguments.
tecs.ecs.Component.$meta.__call(self, ...: any): selfArguments
| 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}
endInterfaces
| 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}): CArguments
| 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}): CArguments
| 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
endInterfaces
| 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.ContainerComponentOptions.container: Ctecs.ecs.DoubleArray interface
DoubleArray names an FFI array of doubles.
interface tecs.ecs.DoubleArray is {integer}
__len: function(self)
endInterfaces
| Interface |
|---|
{integer} |
tecs.ecs.DoubleArray:__len
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.
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}
endInterfaces
| 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.defaults: {any}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}
): CArguments
| 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}): CArguments
| 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>
endInterfaces
| 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"
endtecs.ecs.Phase interface
Phase identifies one system phase.
tecs.ecs.Phase.name field
Read-only. The name of the phase.
tecs.ecs.Phase.position field
Read-only. The public pipeline position for this phase.
tecs.ecs.Phase.children field
Read-only. Child phases of this 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}
endtecs.ecs.phases.AllGroups record
Contains all phases that make up the ECS lifecycle.
record tecs.ecs.phases.AllGroups is Phase
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.MainGroup record
A meta-phase for the main game loop.
record tecs.ecs.phases.MainGroup is Phase
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.StartupGroup record
record tecs.ecs.phases.StartupGroup is Phase
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.FixedPreUpdate record
Runs before fixed update (e.g., collision detection preparation).
record tecs.ecs.phases.FixedPreUpdate is Phase
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.FixedPostUpdate record
Runs after fixed update (e.g., collision response, constraint solving).
record tecs.ecs.phases.FixedPostUpdate is Phase
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.FixedUpdateGroup record
record tecs.ecs.phases.FixedUpdateGroup is Phase
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.PreRender record
Runs just before rendering (e.g., culling, sorting, batching).
record tecs.ecs.phases.PreRender is Phase
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.Render record
Main rendering phase (e.g., drawing sprites, meshes, UI).
record tecs.ecs.phases.Render is Phase
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.RenderGroup record
record tecs.ecs.phases.RenderGroup is Phase
endInterfaces
| 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
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.Shutdown record
Main shutdown phase (e.g., releasing resources, destroying entities).
record tecs.ecs.phases.Shutdown is Phase
endInterfaces
| 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
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.ShutdownGroup record
record tecs.ecs.phases.ShutdownGroup is Phase
endInterfaces
| Interface |
|---|
Phase |
tecs.ecs.phases.index field
Read-only. Maps each lifecycle position to its phase definition.
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)
endtecs.ecs.Pipeline.count field
Read-only. The number of systems in the pipeline.
tecs.ecs.Pipeline.fixedTimestep field
Read-only. The fixed timestep interval in seconds (e.g., 1/60 for 60Hz physics).
tecs.ecs.Pipeline.fixedTimestep: numbertecs.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: numbertecs.ecs.Pipeline.fixedStepCount field
Read-only. Fixed steps run since the pipeline was made.
tecs.ecs.Pipeline.fixedStepCount: integertecs.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: integertecs.ecs.Pipeline.fixedOverload field
Read-only. What happens to the time those steps would have consumed. Defaults to "drop".
tecs.ecs.Pipeline.fixedOverload: FixedOverloadtecs.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: numbertecs.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: integertecs.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.
Arguments
| Name | Type | Description |
|---|---|---|
self |
Pipeline |
|
phase |
Phase |
The phase to disable. |
Returns
None.
tecs.ecs.Pipeline:enablePhase Instance
Enable a 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.
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.
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.
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
endtecs.Query.Kind enum
Whether a query drives simulation or presentation.
enum tecs.Query.Kind
"logic"
"render"
endtecs.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
)
endtecs.Query.Descriptor.name field
Caller-writable. Names the query in logs, profiles, and debug tools.
tecs.Query.Descriptor.name: stringtecs.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.type: Kindtecs.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.includeAny: {components.Component}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: booleantecs.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): integerArguments
| 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
endInterfaces
| 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.
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): integertecs.Query.Cursor.GroupIterFn type
The step function cursor:group(id) returns, with the same three values as IterFn narrowed to one group.
tecs.Query.Cursor:group Instance
Iterate over active archetypes in one group.
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.
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.
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.
tecs.Query.GroupsIterFn type
The step function query:groups() returns. Yields group ids in ascending order.
type tecs.Query.GroupsIterFn = function(Query, any): integertecs.Query.GroupIterFn type
The step function query:group(id) returns, with the same three values as IterFn narrowed to one group.
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.descriptor: Descriptortecs.Query:count Instance
Total number of entities currently matched by this query. One pass over matching archetypes, not entities.
function tecs.Query.count(self): integerArguments
| 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.
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): integerArguments
| 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.
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.
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
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.
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.Cursortecs.ecs.QueryDescriptor type
QueryDescriptor configures a query.
type tecs.ecs.QueryDescriptor = types.Query.Descriptortecs.ecs.Relationship interface
Relationship names any relationship definition.
interface tecs.ecs.Relationship is Component
exclusiveRelationship: boolean
targeting: function(self, integer): self
endInterfaces
| 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.exclusiveRelationship: booleantecs.ecs.Relationship:targeting Instance
Returns the component type for a specific target.
function tecs.ecs.Relationship.targeting(self, integer): selfArguments
| 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>
endInterfaces
| 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
endInterfaces
| 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.scalarKind: ScalarKindtecs.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.scalarDefault: Ttecs.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"
endtecs.ecs.ScalarComponentOptions interface
ScalarComponentOptions configures a scalar component.
interface tecs.ecs.ScalarComponentOptions<T> is BasicComponentOptions<ScalarComponent<T>>
kind: string
default: T
endInterfaces
| 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: stringtecs.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.ScalarComponentOptions.default: Ttecs.ecs.Snapshot type
Snapshot names serialized world state.
tecs.ecs.SnapshotComponentTableEntry type
SnapshotComponentTableEntry identifies one component in a snapshot.
type tecs.ecs.SnapshotComponentTableEntry = types.World.SnapshotComponentTableEntrytecs.ecs.SnapshotHandler type
SnapshotHandler saves and restores plugin data.
type tecs.ecs.SnapshotHandler = types.World.SnapshotHandlertecs.ecs.SnapshotOptions type
SnapshotOptions controls snapshot serialization.
type tecs.ecs.SnapshotOptions = types.World.SnapshotOptionstecs.ecs.SnapshotOutput type
SnapshotOutput collects serialized data.
type tecs.ecs.SnapshotOutput = types.World.SnapshotOutputtecs.ecs.SnapshotPrelude type
SnapshotPrelude names snapshot metadata.
type tecs.ecs.SnapshotPrelude = types.World.SnapshotPreludetecs.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)
endtecs.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.
tecs.ecs.StatePolicy.Action.apply field
Caller-writable. Built-in action: "pause", "resume", "despawn", "disable"
tecs.ecs.StatePolicy.Action.apply: stringtecs.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.
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
endtecs.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: stringtecs.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.phase: Phasetecs.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.run: Systemtecs.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): booleanArguments
| Name | Type | Description |
|---|---|---|
#1 |
number |
|
#2 |
World |
|
#3 |
string |
Returns
| Type | Description |
|---|---|
boolean |
tecs.ecs.TagComponentOptions interface
TagComponentOptions configures a tag component.
Interfaces
| Interface |
|---|
BasicComponentOptions<Component> |
tecs.ecs.TagComponentOptions.container field
Caller-writable. Optional container to use for the tag component.
tecs.ecs.TagComponentOptions.container: Componenttecs.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
)
endtecs.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
endtecs.World.Config.timestep field
Caller-writable. Sets the positive duration of one fixed step in seconds. Defaults to 1/60.
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: integertecs.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: integertecs.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
): PipelineArguments
| 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
endtecs.World.SnapshotComponentTableEntry.name field
Caller-writable. Names the registered component a load resolves this entry against.
tecs.World.SnapshotComponentTableEntry.name: stringtecs.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.SnapshotComponentTableEntry.fingerprint: string | niltecs.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}
endtecs.World.SnapshotPrelude.version field
Read-only. Reports the snapshot format version, not the game version.
tecs.World.SnapshotPrelude.version: integertecs.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.nextEntityId: integertecs.World.SnapshotPrelude.entityCount field
Read-only. Reports the entity count when the writer knew it, or nil for a streaming writer.
tecs.World.SnapshotPrelude.entityCount: integertecs.World.SnapshotPrelude.archetypeCount field
Read-only. Reports the archetype count when the writer knew it, or nil for a streaming writer.
tecs.World.SnapshotPrelude.archetypeCount: integertecs.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}}
endtecs.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.columnIndices: {integer}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.SnapshotArchetypeEntry.entities: {{any}}tecs.World.SnapshotDataEntry interface
One keyed value in a snapshot's data section.
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.key: stringtecs.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.SnapshotDataEntry.value: anytecs.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}
endtecs.World.Snapshot.version field
Caller-writable. Sets the snapshot format version.
tecs.World.Snapshot.nextEntityId field
Caller-writable. Sets the slot where entity allocation resumes.
tecs.World.Snapshot.nextEntityId: integertecs.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.Snapshot.data: {SnapshotDataEntry}tecs.World.SnapshotFormat enum
Which of the two representations saveSnapshot produces.
enum tecs.World.SnapshotFormat
"binary"
"table"
endtecs.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}
endtecs.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: StringBuffertecs.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.path: stringtecs.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
endtecs.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 | niltecs.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 | niltecs.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
endtecs.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.name: stringtecs.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) | niltecs.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) | niltecs.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 | nilArguments
| 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
endtecs.World.Stats.entities field
Read-only. Reports the number of active entities.
tecs.World.Stats.archetypes field
Read-only. Reports the number of archetypes.
tecs.World.Stats.archetypes: integertecs.World.Stats.components field
Read-only. Reports the number of registered components.
tecs.World.Stats.components: integertecs.World.Stats.systems field
Read-only. Reports the number of registered systems.
tecs.World.Stats.fixedTimeDropped field
Read-only. Reports simulated seconds abandoned by the fixed step overload policy.
tecs.World.Stats.fixedTimeDropped: numbertecs.World.Stats.fixedStepsDropped field
Read-only. Reports fixed steps abandoned by the overload policy.
tecs.World.Stats.fixedStepsDropped: integertecs.World:addPlugin Instance
Add a plugin to the world.
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.
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.
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} | nilArguments
| 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 | nilArguments
| 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, integerArguments
| 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.ComponentArguments
| 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.
Arguments
| Name | Type | Description |
|---|---|---|
self |
World |
Returns
| Type | Description |
|---|---|
function():Archetype |
tecs.World:disablePhase Instance
Disable a 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.
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): integerArguments
| 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.
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.
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.
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.
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
): TType 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, numberArguments
| 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.
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.
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
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
): booleanType 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): booleanArguments
| 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): SnapshotPreludeArguments
| 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).
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
): BundleArguments
| 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
): QueryArguments
| 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): stringArguments
| 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.
Arguments
| Name | Type | Description |
|---|---|---|
self |
World |
|
phase |
Phase |
The phase to register. |
Returns
None.
tecs.World:remove Instance
Remove a component from an entity.
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): integerArguments
| 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).
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
): SnapshotOutputArguments
| 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.
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.
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.
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.
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): ComponentArguments
| 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): ComponentArguments
| 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.ArchetypeCreated: builtins.ArchetypeCreatedtecs.ecs.ChildOf variable
Read-only. ChildOf links a parent and child. It stores edges sparsely and cascade-deletes children with their parent.
tecs.ecs.ChildOf: Relationshiptecs.ecs.DEFAULTMAXENTITIES variable
Read-only. DEFAULT_MAX_ENTITIES supplies 2^20 when world configuration omits maxEntities.
tecs.ecs.DEFAULT_MAX_ENTITIES: integertecs.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.FinishSnapshotLoad: builtins.FinishSnapshotLoadtecs.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: integertecs.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.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.OnSnapshotSavetecs.ecs.OnSpawn variable
Read-only. OnSpawn fires at an entity after spawning.
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.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.RelativeTransform2D: builtins.RelativeTransform2Dtecs.ecs.runif variable
Read-only. runif contains composable system run conditions.
tecs.ecs.runif: runIfHelperstecs.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.StartSnapshotLoad: builtins.StartSnapshotLoadtecs.ecs.StateBlur variable
Read-only. StateBlur fires at a state when another takes focus above it.
tecs.ecs.StateEnter variable
Read-only. StateEnter fires when a state enters the stack.
tecs.ecs.StateEnter: builtins.StateEntertecs.ecs.StateExit variable
Read-only. StateExit fires when a state leaves the stack.
tecs.ecs.StateFocus variable
Read-only. StateFocus fires at a state when it regains focus.
tecs.ecs.StateFocus: builtins.StateFocustecs.ecs.Transform2D variable
Read-only. Transform2D positions everything a world holds. Hierarchy, physics, sequencing, and rendering all use it.
tecs.ecs.Transform2D: builtins.Transform2Dtecs.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.Transform3Dtecs.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.