# 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: ```teal 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 = archetype:getMut( tecs.Transform2D ) for row = 1, length do transform[row].x = transform[row].x + 60 * delta end end end, }) world:spawn(tecs.Transform2D(0, 0)) end ``` Read columns through `archetype:get`. Write through `getMut` so dirty-gated systems can find the change. See [Worlds](/modules/ecs/world), [Components](/modules/ecs/components/), [Queries](/modules/ecs/queries/), and [Systems](/modules/ecs/systems) for the complete ECS model. ## Module contents ### Submodules | Submodule | Description | | --- | --- | | [`Archetypes`](/modules/ecs/archetype/) | Archetype storage, column access, relationship lookups, dirty tracking, and lifecycle observers | | [`Builtins`](/modules/ecs/builtins/) | The components, relationship, events and systems every world registers automatically, all on tecs.ecs | | [`Components`](/modules/ecs/components/) | Component overview with world get, getMut, set, remove, has, requires, and transient | | [`Events`](/modules/ecs/events/) | Address-based ECS events: observe, emit, hasObservers, newEvent, newFFIEvent, and the MessageBus router | | [`Mutation model`](/modules/ecs/mutation-model/) | Mutation paths, entity lifecycle states, commit drain ordering, and visibility guarantees | | [`Phases`](/modules/ecs/phases/) | Game-loop phase groups and the world methods that control them | | [`Plugins`](/modules/ecs/plugins/) | Plugins provide the one way into a world: entry arguments, composition, and patterns that scale | | [`Profiling`](/modules/ecs/profiling/) | LuaJIT sampling profiler and trace-abort tracker through tecs.utils.profile | | [`Queries`](/modules/ecs/queries/) | Creating and iterating queries with include, exclude, includeAny, temp, cursors, and deferred mutations | | [`Relationships`](/modules/ecs/relationships/) | Directed entity relationships, storage, deletion, and traversal | | [`Save games`](/modules/ecs/save-games/) | Snapshot saving, loading, transient components, handlers, filtering, and binary format | | [`State stack`](/modules/ecs/states/) | The world state stack, lifecycle policies, automatic tags, and transition events | | [`Systems`](/modules/ecs/systems/) | System configuration, ordering, removal, and tecs.ecs.runif predicates | | [`World`](/modules/ecs/world/) | World entities, spawning, batches, deferred scopes, resources, plugins, phases, and stats | | [`tecs.ecs.random`](/modules/ecs/random/) | Seeded named streams, standalone generators, and snapshot restoration | ### Constructors | Constructor | Description | | --- | --- | | [`newComponent`](/modules/ecs/#tecs.ecs.newComponent) | Creates and registers a new table component. | | [`newFFIComponent`](/modules/ecs/#tecs.ecs.newFFIComponent) | Creates and registers an FFI-based component. | | [`newFFIRelationship`](/modules/ecs/#tecs.ecs.newFFIRelationship) | Creates an FFI-backed relationship with data fields. | | [`newRelationship`](/modules/ecs/#tecs.ecs.newRelationship) | Creates and registers a relationship component. | | [`newScalarComponent`](/modules/ecs/#tecs.ecs.newScalarComponent) | Creates and registers a new scalar component. | | [`newTagComponent`](/modules/ecs/#tecs.ecs.newTagComponent) | Creates and registers a tag component. | | [`newWorld`](/modules/ecs/#tecs.ecs.newWorld) | Creates a new World. | ### Types | Type | Kind | Description | | --- | --- | --- | | [`Archetype`](/modules/ecs/#tecs.ecs.Archetype) | interface | Archetype stores contiguous component columns. | | [`ArchetypeEntityObserver`](/modules/ecs/#tecs.ecs.ArchetypeEntityObserver) | interface | ArchetypeEntityObserver receives entity changes within an archetype. | | [`Bundle`](/modules/ecs/#tecs.ecs.Bundle) | interface | Bundle names a reusable component collection. | | [`BundleDef`](/modules/ecs/#tecs.ecs.BundleDef) | interface | BundleDef configures a bundle. | | [`Closeable`](/modules/ecs/#tecs.ecs.Closeable) | interface | An owned value that releases its active lifetime explicitly. | | [`Component`](/modules/ecs/#tecs.ecs.Component) | interface | Component names any component definition. | | [`ComponentOptions`](/modules/ecs/#tecs.ecs.ComponentOptions) | interface | ComponentOptions configures a table component. | | [`ContainerComponentOptions`](/modules/ecs/#tecs.ecs.ContainerComponentOptions) | interface | Shared options for creating different components. | | [`DoubleArray`](/modules/ecs/#tecs.ecs.DoubleArray) | interface | DoubleArray names an FFI array of doubles. | | [`FFIComponentOptions`](/modules/ecs/#tecs.ecs.FFIComponentOptions) | interface | FFIComponentOptions configures an FFI component. | | [`FFIRelationshipOptions`](/modules/ecs/#tecs.ecs.FFIRelationshipOptions) | interface | FFIRelationshipOptions configures an FFI relationship. | | [`FixedOverload`](/modules/ecs/#tecs.ecs.FixedOverload) | enum | FixedOverload selects fixed-step overload behavior. | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | interface | Phase identifies one system phase. | | [`phases`](/modules/ecs/#tecs.ecs.phases) | record | Defines the predefined ECS phases, or lifecycle states, of the game and event loop. | | [`Pipeline`](/modules/ecs/#tecs.ecs.Pipeline) | interface | Pipeline identifies a world update pipeline. | | [`Plugin`](/modules/ecs/#tecs.Plugin) | type | A plugin configures a world with systems, resources, observers, and initial entities. | | [`Query`](/modules/ecs/#tecs.Query) | interface | A reusable filter over the archetypes in a world. | | [`QueryCursor`](/modules/ecs/#tecs.ecs.QueryCursor) | type | QueryCursor controls an explicitly closed query traversal. | | [`QueryDescriptor`](/modules/ecs/#tecs.ecs.QueryDescriptor) | type | QueryDescriptor configures a query. | | [`Relationship`](/modules/ecs/#tecs.ecs.Relationship) | interface | Relationship names any relationship definition. | | [`RelationshipOptions`](/modules/ecs/#tecs.ecs.RelationshipOptions) | interface | RelationshipOptions configures a relationship. | | [`ScalarComponent`](/modules/ecs/#tecs.ecs.ScalarComponent) | interface | ScalarComponent names a single-value component. | | [`ScalarComponentOptions`](/modules/ecs/#tecs.ecs.ScalarComponentOptions) | interface | ScalarComponentOptions configures a scalar component. | | [`Snapshot`](/modules/ecs/#tecs.ecs.Snapshot) | type | Snapshot names serialized world state. | | [`SnapshotComponentTableEntry`](/modules/ecs/#tecs.ecs.SnapshotComponentTableEntry) | type | SnapshotComponentTableEntry identifies one component in a snapshot. | | [`SnapshotHandler`](/modules/ecs/#tecs.ecs.SnapshotHandler) | type | SnapshotHandler saves and restores plugin data. | | [`SnapshotOptions`](/modules/ecs/#tecs.ecs.SnapshotOptions) | type | SnapshotOptions controls snapshot serialization. | | [`SnapshotOutput`](/modules/ecs/#tecs.ecs.SnapshotOutput) | type | SnapshotOutput collects serialized data. | | [`SnapshotPrelude`](/modules/ecs/#tecs.ecs.SnapshotPrelude) | type | SnapshotPrelude names snapshot metadata. | | [`StatePolicy`](/modules/ecs/#tecs.ecs.StatePolicy) | record | StatePolicy controls state-stack participation. | | [`Stats`](/modules/ecs/#tecs.ecs.Stats) | type | Stats reports live world counts. | | [`System`](/modules/ecs/#tecs.System) | type | A system function runs once when its phase dispatches. | | [`SystemConfig`](/modules/ecs/#tecs.ecs.SystemConfig) | interface | SystemConfig configures a system. | | [`TagComponentOptions`](/modules/ecs/#tecs.ecs.TagComponentOptions) | interface | TagComponentOptions configures a tag component. | | [`World`](/modules/ecs/#tecs.World) | interface | A world owns entities, components, queries, systems, resources, events, snapshots, and the state stack. | ### Functions | Function | Kind | Description | | --- | --- | --- | | [`declaredComponents`](/modules/ecs/#tecs.ecs.declaredComponents) | Static | Returns every component declared in this process. | | [`findComponentById`](/modules/ecs/#tecs.ecs.findComponentById) | Static | Returns a registered component by numeric id. | | [`findComponentByName`](/modules/ecs/#tecs.ecs.findComponentByName) | Static | Returns the component registered under name. | ### Values | Value | Type | Description | | --- | --- | --- | | [`ArchetypeCreated`](/modules/ecs/#tecs.ecs.ArchetypeCreated) | [`ArchetypeCreated`](/modules/ecs/#tecs.ecs.ArchetypeCreated) | Read-only. ArchetypeCreated fires at entity 0 after archetype creation. | | [`ChildOf`](/modules/ecs/#tecs.ecs.ChildOf) | [`Relationship`](/modules/ecs/#tecs.ecs.Relationship) | Read-only. ChildOf links a parent and child. | | [`DEFAULT_MAX_ENTITIES`](/modules/ecs/#tecs.ecs.DEFAULT_MAX_ENTITIES) | `integer` | Read-only. DEFAULT_MAX_ENTITIES supplies 2^20 when world configuration omits maxEntities. | | [`Disabled`](/modules/ecs/#tecs.ecs.Disabled) | [`Component`](/modules/ecs/#tecs.ecs.Component) | Read-only. Disabled excludes an entity from queries that do not ask for it. | | [`EntityKey`](/modules/ecs/#tecs.ecs.EntityKey) | [`ScalarComponent`](/modules/ecs/#tecs.ecs.ScalarComponent) | Read-only. EntityKey stores a durable unique lookup key for world:byKey. | | [`FinishSnapshotLoad`](/modules/ecs/#tecs.ecs.FinishSnapshotLoad) | [`FinishSnapshotLoad`](/modules/ecs/#tecs.ecs.FinishSnapshotLoad) | Read-only. FinishSnapshotLoad fires at entity 0 after every entity and data callback finishes restoration. | | [`MAX_ENTITIES`](/modules/ecs/#tecs.ecs.MAX_ENTITIES) | `integer` | Read-only. MAX_ENTITIES sets the absolute World.Config.maxEntities ceiling (2^22 - 1 usable slots; the entity-id... | | [`Name`](/modules/ecs/#tecs.ecs.Name) | [`ScalarComponent`](/modules/ecs/#tecs.ecs.ScalarComponent) | Read-only. Name stores an entity label as a raw string. | | [`OnDespawn`](/modules/ecs/#tecs.ecs.OnDespawn) | [`OnDespawn`](/modules/ecs/#tecs.ecs.OnDespawn) | Read-only. OnDespawn fires at an entity before removal. | | [`OnSnapshotSave`](/modules/ecs/#tecs.ecs.OnSnapshotSave) | [`OnSnapshotSave`](/modules/ecs/#tecs.ecs.OnSnapshotSave) | Read-only. OnSnapshotSave fires at entity 0 before snapshot archetype serialization so plugins can attach keyed data... | | [`OnSpawn`](/modules/ecs/#tecs.ecs.OnSpawn) | [`OnSpawn`](/modules/ecs/#tecs.ecs.OnSpawn) | Read-only. OnSpawn fires at an entity after spawning. | | [`Paused`](/modules/ecs/#tecs.ecs.Paused) | [`Component`](/modules/ecs/#tecs.ecs.Component) | Read-only. Paused excludes an entity from logic queries while keeping it visible. | | [`RelativeTransform2D`](/modules/ecs/#tecs.ecs.RelativeTransform2D) | [`RelativeTransform2D`](/modules/ecs/#tecs.ecs.RelativeTransform2D) | Read-only. RelativeTransform2D expresses a pose relative to a ChildOf parent. | | [`runif`](/modules/ecs/#tecs.ecs.runif) | `runIfHelpers` | Read-only. runif contains composable system run conditions. | | [`StartSnapshotLoad`](/modules/ecs/#tecs.ecs.StartSnapshotLoad) | [`StartSnapshotLoad`](/modules/ecs/#tecs.ecs.StartSnapshotLoad) | Read-only. StartSnapshotLoad fires at entity 0 after world restoration and before data dispatch so plugins can... | | [`StateBlur`](/modules/ecs/#tecs.ecs.StateBlur) | [`StateBlur`](/modules/ecs/#tecs.ecs.StateBlur) | Read-only. StateBlur fires at a state when another takes focus above it. | | [`StateEnter`](/modules/ecs/#tecs.ecs.StateEnter) | [`StateEnter`](/modules/ecs/#tecs.ecs.StateEnter) | Read-only. StateEnter fires when a state enters the stack. | | [`StateExit`](/modules/ecs/#tecs.ecs.StateExit) | [`StateExit`](/modules/ecs/#tecs.ecs.StateExit) | Read-only. StateExit fires when a state leaves the stack. | | [`StateFocus`](/modules/ecs/#tecs.ecs.StateFocus) | [`StateFocus`](/modules/ecs/#tecs.ecs.StateFocus) | Read-only. StateFocus fires at a state when it regains focus. | | [`Transform2D`](/modules/ecs/#tecs.ecs.Transform2D) | [`Transform2D`](/modules/ecs/#tecs.ecs.Transform2D) | Read-only. Transform2D positions everything a world holds. | | [`Transform3D`](/modules/ecs/#tecs.ecs.Transform3D) | [`Transform3D`](/modules/ecs/#tecs.ecs.Transform3D) | Read-only. Transform3D places an entity in a right-handed 3D world. | | [`TTL`](/modules/ecs/#tecs.ecs.TTL) | [`TTL`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.newComponent( options: ComponentOptions ): C ``` #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `C` | [`Component`](/modules/ecs/#tecs.ecs.Component) | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | [`ComponentOptions`](/modules/ecs/#tecs.ecs.ComponentOptions)`` | 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. ```teal function tecs.ecs.newFFIComponent( options: FFIComponentOptions ): C ``` #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `C` | [`Component`](/modules/ecs/#tecs.ecs.Component) | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | [`FFIComponentOptions`](/modules/ecs/#tecs.ecs.FFIComponentOptions)`` | 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. ```teal function tecs.ecs.newFFIRelationship( config: FFIRelationshipOptions ): R ``` #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `R` | [`Relationship`](/modules/ecs/#tecs.ecs.Relationship) | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `config` | [`FFIRelationshipOptions`](/modules/ecs/#tecs.ecs.FFIRelationshipOptions)`` | 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. ```teal function tecs.ecs.newRelationship( config: RelationshipOptions ): R ``` #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `R` | [`Relationship`](/modules/ecs/#tecs.ecs.Relationship) | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `config` | [`RelationshipOptions`](/modules/ecs/#tecs.ecs.RelationshipOptions)`` | 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. ```teal function tecs.ecs.newScalarComponent( options: ScalarComponentOptions ): ScalarComponent ``` #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | [`ScalarComponentOptions`](/modules/ecs/#tecs.ecs.ScalarComponentOptions)`` | The caller supplies the scalar type, name and defaults. | #### Returns | Type | Description | | --- | --- | | [`ScalarComponent`](/modules/ecs/#tecs.ecs.ScalarComponent)`` | Returns the registered component whose rows hold bare values. | ### tecs.ecs.newTagComponent Static Creates and registers a tag component. ```teal function tecs.ecs.newTagComponent( options: TagComponentOptions ): Component ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | [`TagComponentOptions`](/modules/ecs/#tecs.ecs.TagComponentOptions) | The caller supplies the tag name. | #### Returns | Type | Description | | --- | --- | | [`Component`](/modules/ecs/#tecs.ecs.Component) | Returns the registered bitset-backed tag. | ### tecs.ecs.newWorld Static Creates a new World. ```teal function tecs.ecs.newWorld(config: types.World.Config): World ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `config` | [`types.World.Config`](/modules/ecs/#tecs.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`](/modules/ecs/#tecs.World) | Returns an independent world with builtins registered and no systems. | ## Types ### tecs.ecs.Archetype interface `Archetype` stores contiguous component columns. ```teal 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( self, row: T, callback: integer, function(T) ) get: function(self, T): {T} getFirstRelationship: function( self, row: T, integer ): T getMut: function(self, T): {T} isComponentDirty: function( self, component: components.Component ): boolean markAllComponentsDirty: function(self) markComponentDirty: function(self, components.Component) set: function( self, row: integer, value: C ) end ``` #### tecs.ecs.Archetype.id field Read-only. The unique identifier of the archetype in the ECS container. ```teal tecs.ecs.Archetype.id: integer ``` #### tecs.ecs.Archetype.entities field Read-only. Entity IDs that belong to this archetype. Length is `entities[0]`; rows are 1-based (`entities[1]` is the first entity). ```teal tecs.ecs.Archetype.entities: DoubleArray ``` #### tecs.ecs.Archetype.componentList field Read-only. Components in this archetype, in the order they were passed at construction. Finalized at creation -- archetypes never add or remove components. Iterate with `#componentList` / `ipairs` to walk the archetype's signature. ```teal 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`. ```teal 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. ```teal function tecs.ecs.Archetype.anyComponentDirty(self): boolean ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Archetype` | | ##### Returns | Type | Description | | --- | --- | | `boolean` | | #### tecs.ecs.Archetype:dirtyComponents Instance Iterate components currently marked dirty on this archetype. ```teal function tecs.ecs.Archetype.dirtyComponents( self ): function(): components.Component ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Archetype` | | ##### Returns | Type | Description | | --- | --- | | `function(): `[`components.Component`](/modules/ecs/#tecs.ecs.Component) | | #### tecs.ecs.Archetype:forEachRelationship Instance Iterate all relationship instances of the given container for the entity at `row`. ```teal function tecs.ecs.Archetype.forEachRelationship( self, row: T, callback: integer, function(T) ) ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`components.Relationship`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.Archetype.get( self, T ): {T} ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.Archetype.getFirstRelationship( self, row: T, integer ): T ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`components.Relationship`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.Archetype.getMut( self, T ): {T} ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.Archetype.isComponentDirty( self, component: components.Component ): boolean ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Archetype` | | | `component` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal 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. ```teal function tecs.ecs.Archetype.markComponentDirty( self, components.Component ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Archetype` | | | `#2` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.Archetype.set( self, row: integer, value: C ) ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `C` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal interface tecs.ecs.ArchetypeEntityObserver onActivated: function(self, archetype: Archetype) onArchetypeDestroyed: function(self, Archetype) onDeactivated: function(self, archetype: Archetype) onEntitiesAdded: function( self, archetype: Archetype, firstRow: integer, lastRow: integer, count: integer, sourceArchetype: Archetype ) onEntitiesRemoved: function( self, archetype: Archetype, firstRow: integer, lastRow: integer, count: integer, destArchetype: Archetype ) onEntityMove: function( self, archetype: Archetype, entity: integer, fromRow: integer, toRow: integer ) end ``` #### tecs.ecs.ArchetypeEntityObserver:onActivated Instance Called when archetype transitions from empty to non-empty (0 -> 1 entities). ```teal function tecs.ecs.ArchetypeEntityObserver.onActivated( self, archetype: Archetype ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ArchetypeEntityObserver` | | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.ArchetypeEntityObserver.onArchetypeDestroyed( self, Archetype ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ArchetypeEntityObserver` | | | `#2` | [`Archetype`](/modules/ecs/#tecs.ecs.Archetype) | | ##### Returns None. #### tecs.ecs.ArchetypeEntityObserver:onDeactivated Instance Called when archetype transitions from non-empty to empty (1 -> 0 entities). ```teal function tecs.ecs.ArchetypeEntityObserver.onDeactivated( self, archetype: Archetype ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ArchetypeEntityObserver` | | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.Archetype) | The archetype that became inactive. | ##### Returns None. #### tecs.ecs.ArchetypeEntityObserver:onEntitiesAdded Instance Called once per contiguous range of entities added to the archetype. ```teal function tecs.ecs.ArchetypeEntityObserver.onEntitiesAdded( self, archetype: Archetype, firstRow: integer, lastRow: integer, count: integer, sourceArchetype: Archetype ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ArchetypeEntityObserver` | | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.ArchetypeEntityObserver.onEntitiesRemoved( self, archetype: Archetype, firstRow: integer, lastRow: integer, count: integer, destArchetype: Archetype ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ArchetypeEntityObserver` | | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.ArchetypeEntityObserver.onEntityMove( self, archetype: Archetype, entity: integer, fromRow: integer, toRow: integer ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ArchetypeEntityObserver` | | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal interface tecs.ecs.Bundle interface Definition required: {components.Component} with: {components.Component: boolean | function(): components.Component} end name: string required: {string} defaulted: {string} spawn: function(self, ...: components.Component): integer end ``` #### tecs.ecs.Bundle.Definition interface Declarative bundle definition. ```teal interface tecs.ecs.Bundle.Definition required: {components.Component} with: {components.Component: boolean | function(): components.Component} end ``` ##### tecs.ecs.Bundle.Definition.required field Caller-writable. Components that must be provided as positional args to spawn(). ```teal 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. ```teal tecs.ecs.Bundle.Definition.with: {components.Component: boolean | function(): components.Component} ``` #### tecs.ecs.Bundle.name field Read-only. The name of the bundle. ```teal tecs.ecs.Bundle.name: string ``` #### tecs.ecs.Bundle.required field Read-only. Component names that must be provided when spawning. ```teal tecs.ecs.Bundle.required: {string} ``` #### tecs.ecs.Bundle.defaulted field Read-only. Component names with default factories. ```teal tecs.ecs.Bundle.defaulted: {string} ``` #### tecs.ecs.Bundle:spawn Instance Spawn an entity using this bundle. ```teal function tecs.ecs.Bundle.spawn( self, ...: components.Component ): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Bundle` | | | `...` | [`components.Component`](/modules/ecs/#tecs.ecs.Component) | Required component instances in declaration order. | ##### Returns | Type | Description | | --- | --- | | `integer` | The entity ID. | ### tecs.ecs.BundleDef interface `BundleDef` configures a bundle. ```teal interface tecs.ecs.BundleDef required: {components.Component} with: {components.Component: boolean | function(): components.Component} end ``` #### tecs.ecs.BundleDef.required field Caller-writable. Components that must be provided as positional args to spawn(). ```teal tecs.ecs.BundleDef.required: {components.Component} ``` #### tecs.ecs.BundleDef.with field Caller-writable. Components with defaults, keyed by component type. Value is either a factory function returning a component instance, or `true` to call the component's default constructor. ```teal tecs.ecs.BundleDef.with: {components.Component: boolean | function(): components.Component} ``` ### tecs.ecs.Closeable interface An owned value that releases its active lifetime explicitly. `close` may report a delayed finalization failure. Every implementation returns true on success. Its own contract defines whether repeated calls are safe. ```teal global interface tecs.ecs.Closeable close: function(self): boolean, string end ``` #### tecs.ecs.Closeable:close Instance Releases the value's active lifetime. ```teal function tecs.ecs.Closeable.close(self): boolean, string ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Closeable` | The value to close. | ##### Returns | Type | Description | | --- | --- | | `boolean` | Returns true when finalization succeeds. | | `string` | Returns a finalization reason when the first return is false. | ### tecs.ecs.Component interface `Component` names any component definition. ```teal interface tecs.ecs.Component componentType: self componentName: string componentId: integer relationshipType: Component wildcardContainer: Component target: integer transient: boolean deserialize: function(world: World, data: {string: any}): self init: function(self, any) new: function({string: any}): self serialize: function(instance: self): {string: any} metamethod __call: function(self, ...: any): self end ``` #### tecs.ecs.Component.componentType field Read-only. The container type of the component, available on instances and containers. ```teal tecs.ecs.Component.componentType: self ``` #### tecs.ecs.Component.componentName field Read-only. The name of the component. ```teal tecs.ecs.Component.componentName: string ``` #### tecs.ecs.Component.componentId field Read-only. The auto-incrementing ID of the component container. ```teal tecs.ecs.Component.componentId: integer ``` #### tecs.ecs.Component.relationshipType field Read-only. Relationship components only: the relationship container type (nil for non-relationships). For containers, this equals self. For instances, it points to the container. ```teal tecs.ecs.Component.relationshipType: Component ``` #### tecs.ecs.Component.wildcardContainer field Read-only. Relationship instance wildcard container (nil for non-relationships and containers). For `Rel(target)` dense instances, this points back to `Rel`. ```teal tecs.ecs.Component.wildcardContainer: Component ``` #### tecs.ecs.Component.target field Read-only. Relationship components only: The target entity ID (for relationship instances only). ```teal tecs.ecs.Component.target: integer ``` #### tecs.ecs.Component.transient field Read-only. True if this component is runtime-only and omitted from snapshots. ```teal tecs.ecs.Component.transient: boolean ``` #### tecs.ecs.Component.deserialize Static Deserialize a component instance from a plain table. ```teal function tecs.ecs.Component.deserialize( world: World, data: {string: any} ): self ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | `World` | The world context for loading resources. | | `data` | `{string : any}` | The plain table data to deserialize. | ##### Returns | Type | Description | | --- | --- | | `self` | A new component instance. | #### tecs.ecs.Component.init Static Optional post-allocation positional initializer used by the built-in factories. Runs after the base instance has been allocated and any declarative field population has occurred. ```teal 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. ```teal function tecs.ecs.Component.new({string: any}): self ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `{string : any}` | | ##### Returns | Type | Description | | --- | --- | | `self` | | #### tecs.ecs.Component.serialize Static Serialize a component instance to a plain table. ```teal function tecs.ecs.Component.serialize(instance: self): {string: any} ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `instance` | `self` | The component instance to serialize. | ##### Returns | Type | Description | | --- | --- | | `{string : any}` | A plain table representation of the component data. | #### tecs.ecs.Component:__call metamethod Creates an instance of the component from the container using positional arguments. ```teal metamethod tecs.ecs.Component.$meta.__call(self, ...: any): self ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Component` | | | `...` | `any` | Field values in declaration order. One left nil takes the field's registered default, so trailing arguments may be omitted. | ##### Returns | Type | Description | | --- | --- | | `self` | A new instance, not a shared one, so two calls with the same arguments answer two values. | ### tecs.ecs.ComponentOptions interface `ComponentOptions` configures a table component. ```teal interface tecs.ecs.ComponentOptions is ContainerComponentOptions fields: {string} defaults: {any} __call: function(C, any) deserialize: function(World, {string: any}): C init: function(C, any) new: function({string: any}): C serialize: function(C): {string: any} end ``` #### Interfaces | Interface | | --- | | [`ContainerComponentOptions`](/modules/ecs/#tecs.ecs.ContainerComponentOptions)`` | #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `C` | [`Component`](/modules/ecs/#tecs.ecs.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 `load`ed so LuaJIT sees literal field assignments. ```teal 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`. ```teal 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. ```teal 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. ```teal function tecs.ecs.ComponentOptions.deserialize(World, {string: any}): C ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `World` | | | `#2` | `{string : any}` | | ##### Returns | Type | Description | | --- | --- | | `C` | | #### tecs.ecs.ComponentOptions.init Static Optional post-allocation positional initializer. Runs after the base instance has been allocated and any declarative `fields` / `defaults` have been applied. Use for validation, normalization, or derived state. If provided without `fields` or `new`, registration errors because Tecs would have no clear way to implement `.new(data)`. ```teal 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`. ```teal function tecs.ecs.ComponentOptions.new({string: any}): C ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `{string : any}` | | ##### Returns | Type | Description | | --- | --- | | `C` | | #### tecs.ecs.ComponentOptions.serialize Static Custom serialization function (optional). Converts a component instance to a plain table for JSON serialization. ```teal 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. ```teal interface tecs.ecs.ContainerComponentOptions is BasicComponentOptions container: C end ``` #### Interfaces | Interface | | --- | | `BasicComponentOptions` | #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `C` | [`Component`](/modules/ecs/#tecs.ecs.Component) | | #### tecs.ecs.ContainerComponentOptions.container field Caller-writable. The component container/type to use (required). ```teal tecs.ecs.ContainerComponentOptions.container: C ``` ### tecs.ecs.DoubleArray interface `DoubleArray` names an FFI array of doubles. ```teal interface tecs.ecs.DoubleArray is {integer} metamethod __len: function(self) end ``` #### Interfaces | Interface | | --- | | `{integer}` | #### tecs.ecs.DoubleArray:__len metamethod Reads the count out of slot 0 rather than probing for a border, so `#array` is exact even though slot 0 is occupied and would otherwise make the array look empty to Lua's own length operator. A macro, so it costs one load at the call site. ```teal metamethod tecs.ecs.DoubleArray.$meta.__len(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `DoubleArray` | | ##### Returns None. ### tecs.ecs.FFIComponentOptions interface `FFIComponentOptions` configures an FFI component. ```teal interface tecs.ecs.FFIComponentOptions is ContainerComponentOptions fields: {{string, string}} defaults: {any} metatable: {any: any} __call: function(C, any) deserialize: function(World, {string: any}): C init: function(C, any) new: function({string: any}): C serialize: function(C): {string: any} end ``` #### Interfaces | Interface | | --- | | [`ContainerComponentOptions`](/modules/ecs/#tecs.ecs.ContainerComponentOptions)`` | #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `C` | [`Component`](/modules/ecs/#tecs.ecs.Component) | | #### tecs.ecs.FFIComponentOptions.fields field Caller-writable. FFI field definitions for the backing struct. ```teal tecs.ecs.FFIComponentOptions.fields: {{string, string}} ``` #### tecs.ecs.FFIComponentOptions.defaults field Caller-writable. Positional defaults, in the same order as `fields`. ```teal tecs.ecs.FFIComponentOptions.defaults: {any} ``` #### tecs.ecs.FFIComponentOptions.metatable field Caller-writable. Optional metatable to apply to FFI instances (for instance methods). ```teal 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. ```teal 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. ```teal function tecs.ecs.FFIComponentOptions.deserialize( World, {string: any} ): C ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `World` | | | `#2` | `{string : any}` | | ##### Returns | Type | Description | | --- | --- | | `C` | | #### tecs.ecs.FFIComponentOptions.init Static Optional post-allocation positional initializer. Same semantics as `ComponentOptions.init`, but the base instance is an FFI struct. ```teal 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`. ```teal function tecs.ecs.FFIComponentOptions.new({string: any}): C ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `{string : any}` | | ##### Returns | Type | Description | | --- | --- | | `C` | | #### tecs.ecs.FFIComponentOptions.serialize Static Custom serialization function (optional). Converts a component instance to a plain table for JSON serialization. Return `nil` to omit the component from snapshots. ```teal 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. ```teal interface tecs.ecs.FFIRelationshipOptions is BaseRelationshipOptions, FFIComponentOptions end ``` #### Interfaces | Interface | | --- | | `BaseRelationshipOptions` | | [`FFIComponentOptions`](/modules/ecs/#tecs.ecs.FFIComponentOptions)`` | #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `R` | [`Relationship`](/modules/ecs/#tecs.ecs.Relationship) | | ### tecs.ecs.FixedOverload enum `FixedOverload` selects fixed-step overload behavior. ```teal enum tecs.ecs.FixedOverload "accumulate" "drop" end ``` ### tecs.ecs.Phase interface `Phase` identifies one system phase. ```teal interface tecs.ecs.Phase name: string position: integer children: {Phase} end ``` #### tecs.ecs.Phase.name field Read-only. The name of the phase. ```teal tecs.ecs.Phase.name: string ``` #### tecs.ecs.Phase.position field Read-only. The public pipeline position for this phase. ```teal tecs.ecs.Phase.position: integer ``` #### tecs.ecs.Phase.children field Read-only. Child phases of this phase. ```teal tecs.ecs.Phase.children: {Phase} ``` ### tecs.ecs.phases record Defines the predefined ECS phases, or lifecycle states, of the game and event loop. Tecs provides these standard phases but also supports custom pipelines via World.Config.pipelineFactory. Read-only. `phases` contains the phases a system may join. ```teal record tecs.ecs.phases record AllGroups is Phase end record MainGroup is Phase end record PreStartup is Phase end record Startup is Phase end record PostStartup is Phase end record StartupGroup is Phase end record First is Phase end record PreUpdate is Phase end record FixedFirst is Phase end record FixedPreUpdate is Phase end record FixedUpdate is Phase end record FixedPostUpdate is Phase end record FixedLast is Phase end record FixedUpdateGroup is Phase end record Update is Phase end record PostUpdate is Phase end record RenderFirst is Phase end record PreRender is Phase end record Render is Phase end record PostRender is Phase end record RenderLast is Phase end record RenderGroup is Phase end record Last is Phase end record PreShutdown is Phase end record Shutdown is Phase end record PostShutdown is Phase end record ShutdownGroup is Phase end index: {Phase} end ``` #### tecs.ecs.phases.AllGroups record Contains all phases that make up the ECS lifecycle. ```teal record tecs.ecs.phases.AllGroups is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.MainGroup record A meta-phase for the main game loop. ```teal record tecs.ecs.phases.MainGroup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PreStartup record Runs once at application start for critical initialization (e.g., logging, core systems). ```teal record tecs.ecs.phases.PreStartup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.Startup record Runs once at application start for general initialization (e.g., loading assets, creating entities). ```teal record tecs.ecs.phases.Startup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PostStartup record Runs once after startup for final setup (e.g., starting gameplay, enabling systems). ```teal record tecs.ecs.phases.PostStartup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.StartupGroup record ```teal record tecs.ecs.phases.StartupGroup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.First record Runs at the very start of each frame (e.g., time updates, input polling). ```teal record tecs.ecs.phases.First is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PreUpdate record Runs before the main update (e.g., physics preparation, event processing). ```teal record tecs.ecs.phases.PreUpdate is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.FixedFirst record Runs at the start of each fixed timestep iteration (e.g., fixed timer updates). ```teal record tecs.ecs.phases.FixedFirst is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.FixedPreUpdate record Runs before fixed update (e.g., collision detection preparation). ```teal record tecs.ecs.phases.FixedPreUpdate is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.FixedUpdate record Runs at fixed timestep intervals for deterministic updates (e.g., physics simulation, gameplay logic). ```teal record tecs.ecs.phases.FixedUpdate is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.FixedPostUpdate record Runs after fixed update (e.g., collision response, constraint solving). ```teal record tecs.ecs.phases.FixedPostUpdate is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.FixedLast record Runs at the end of each fixed timestep iteration (e.g., state synchronization). ```teal record tecs.ecs.phases.FixedLast is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.FixedUpdateGroup record ```teal record tecs.ecs.phases.FixedUpdateGroup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.Update record Main update phase, runs once per frame for gameplay logic and non-physics updates. ```teal record tecs.ecs.phases.Update is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PostUpdate record Runs after update and before rendering (e.g., animation, transform updates, camera updates). ```teal record tecs.ecs.phases.PostUpdate is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.RenderFirst record Runs at the start of rendering (e.g., clearing buffers, setting up render state). ```teal record tecs.ecs.phases.RenderFirst is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PreRender record Runs just before rendering (e.g., culling, sorting, batching). ```teal record tecs.ecs.phases.PreRender is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.Render record Main rendering phase (e.g., drawing sprites, meshes, UI). ```teal record tecs.ecs.phases.Render is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PostRender record Runs just after rendering (e.g., post-processing effects, screen transitions). ```teal record tecs.ecs.phases.PostRender is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.RenderLast record Runs at the end of rendering (e.g., presenting frame, GPU synchronization). ```teal record tecs.ecs.phases.RenderLast is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.RenderGroup record ```teal record tecs.ecs.phases.RenderGroup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.Last record Runs at the very end of each frame (e.g., cleanup, metrics collection, frame timing). ```teal record tecs.ecs.phases.Last is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PreShutdown record Runs just before shutdown (e.g., saving game state, closing connections). ```teal record tecs.ecs.phases.PreShutdown is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.Shutdown record Main shutdown phase (e.g., releasing resources, destroying entities). ```teal record tecs.ecs.phases.Shutdown is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.PostShutdown record Runs after shutdown for final cleanup (e.g., logging shutdown metrics, final cleanup). ```teal record tecs.ecs.phases.PostShutdown is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.ShutdownGroup record ```teal record tecs.ecs.phases.ShutdownGroup is Phase end ``` ##### Interfaces | Interface | | --- | | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | #### tecs.ecs.phases.index field Read-only. Maps each lifecycle position to its phase definition. ```teal tecs.ecs.phases.index: {Phase} ``` ### tecs.ecs.Pipeline interface `Pipeline` identifies a world update pipeline. ```teal interface tecs.ecs.Pipeline count: integer fixedTimestep: number fixedAccumulator: number fixedStepCount: integer fixedMaxSteps: integer fixedOverload: FixedOverload fixedTimeDropped: number fixedStepsDropped: integer addSystem: function(self, config: SystemConfig) disablePhase: function(self, phase: Phase) enablePhase: function(self, phase: Phase) registerPhase: function(self, phase: Phase) removeSystem: function(self, systemName: string) run: function(self, phase: Phase, dt: number, world: World) update: function(self, dt: number, world: World) end ``` #### tecs.ecs.Pipeline.count field Read-only. The number of systems in the pipeline. ```teal tecs.ecs.Pipeline.count: integer ``` #### tecs.ecs.Pipeline.fixedTimestep field Read-only. The fixed timestep interval in seconds (e.g., 1/60 for 60Hz physics). ```teal tecs.ecs.Pipeline.fixedTimestep: number ``` #### tecs.ecs.Pipeline.fixedAccumulator field Read-only. Accumulated time not yet consumed by fixed updates. Use with fixedTimestep to compute interpolation alpha: accumulator / timestep. ```teal tecs.ecs.Pipeline.fixedAccumulator: number ``` #### tecs.ecs.Pipeline.fixedStepCount field Read-only. Fixed steps run since the pipeline was made. ```teal tecs.ecs.Pipeline.fixedStepCount: integer ``` #### tecs.ecs.Pipeline.fixedMaxSteps field Read-only. The most fixed steps one `update` will run before the overload policy decides what happens to the rest. Defaults to 10. ```teal tecs.ecs.Pipeline.fixedMaxSteps: integer ``` #### tecs.ecs.Pipeline.fixedOverload field Read-only. What happens to the time those steps would have consumed. Defaults to `"drop"`. ```teal tecs.ecs.Pipeline.fixedOverload: FixedOverload ``` #### tecs.ecs.Pipeline.fixedTimeDropped field Read-only. Simulated seconds abandoned by the `"drop"` policy since the pipeline was made. Stays at zero under `"accumulate"`, which abandons nothing, and stays at zero on a machine that keeps up. Read it. A simulation, a replay or anything networked is wrong by exactly this much, and nothing else in the world says so. ```teal tecs.ecs.Pipeline.fixedTimeDropped: number ``` #### tecs.ecs.Pipeline.fixedStepsDropped field Read-only. Fixed steps that were owed and never ran, on the same terms. Whole steps only: `fixedTimeDropped` is this many timesteps, because a drop leaves the sub-step remainder alone rather than resetting the interpolation alpha along with it. ```teal tecs.ecs.Pipeline.fixedStepsDropped: integer ``` #### tecs.ecs.Pipeline:addSystem Instance Add a system to the pipeline. ```teal 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. ```teal function tecs.ecs.Pipeline.disablePhase(self, phase: Phase) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Pipeline` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | The phase to disable. | ##### Returns None. #### tecs.ecs.Pipeline:enablePhase Instance Enable a phase. ```teal function tecs.ecs.Pipeline.enablePhase(self, phase: Phase) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Pipeline` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | The phase to enable. | ##### Returns None. #### tecs.ecs.Pipeline:registerPhase Instance Register a custom phase with the pipeline. ```teal function tecs.ecs.Pipeline.registerPhase(self, phase: Phase) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Pipeline` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | The phase to register. | ##### Returns None. #### tecs.ecs.Pipeline:removeSystem Instance Remove a system from the pipeline. ```teal 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. ```teal function tecs.ecs.Pipeline.run( self, phase: Phase, dt: number, world: World ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Pipeline` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.Pipeline.update(self, dt: number, world: World) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Pipeline` | | | `dt` | `number` | The delta time since the last update. | | `world` | `World` | The world to update. | ##### Returns None. ### tecs.Plugin type A plugin configures a world with systems, resources, observers, and initial entities. ```teal type tecs.Plugin = function(World) ``` ### tecs.Query interface A reusable filter over the archetypes in a world. ```teal interface tecs.Query enum Kind "logic" "render" end interface Descriptor name: string type: Kind include: {components.Component} includeAny: {components.Component} exclude: {components.Component} temp: boolean groupBy: function(archetype: Archetype): integer onEntitiesAdded: function( archetype: Archetype, firstRow: integer, lastRow: integer, count: integer ) onEntitiesRemoved: function( archetype: Archetype, firstRow: integer, lastRow: integer, count: integer ) end interface Cursor is Closeable type IterFn = function( Cursor, any ): (Archetype, integer, {integer}) type GroupsIterFn = function(Cursor, any): integer type GroupIterFn = function( Cursor, any ): (Archetype, integer, {integer}) group: function( self, groupId: integer ): GroupIterFn, Cursor, any groups: function(self): GroupsIterFn, Cursor, any iter: function(self): IterFn, Cursor, any end type IterFn = function(Query, any): (Archetype, integer, {integer}) type GroupsIterFn = function(Query, any): integer type GroupIterFn = function( Query, any ): (Archetype, integer, {integer}) descriptor: Descriptor count: function(self): integer getGroup: function(self, archetype: Archetype): integer getGroupCount: function(self, groupId: integer): integer group: function(self, groupId: integer): GroupIterFn, Query, any groups: function(self): GroupsIterFn, Query, any iter: function(self): IterFn, Query, any newCursor: function(self): Cursor end ``` #### tecs.Query.Kind enum Whether a query drives simulation or presentation. ```teal enum tecs.Query.Kind "logic" "render" end ``` #### tecs.Query.Descriptor interface The options passed to `world:newQuery`. ```teal interface tecs.Query.Descriptor name: string type: Kind include: {components.Component} includeAny: {components.Component} exclude: {components.Component} temp: boolean groupBy: function(archetype: Archetype): integer onEntitiesAdded: function( archetype: Archetype, firstRow: integer, lastRow: integer, count: integer ) onEntitiesRemoved: function( archetype: Archetype, firstRow: integer, lastRow: integer, count: integer ) end ``` ##### tecs.Query.Descriptor.name field Caller-writable. Names the query in logs, profiles, and debug tools. ```teal tecs.Query.Descriptor.name: string ``` ##### tecs.Query.Descriptor.type field Caller-writable. Selects simulation or presentation behavior. `"logic"` excludes `Paused` entities, so pausing a state stops the systems that move, damage, or think. `"render"` records the opposite intent: paused entities keep drawing. Omitting the field leaves the query unfiltered, which matches every query written before this option existed. ```teal tecs.Query.Descriptor.type: Kind ``` ##### tecs.Query.Descriptor.include field Caller-writable. Lists every component a matching archetype must contain. ```teal 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. ```teal tecs.Query.Descriptor.includeAny: {components.Component} ``` ##### tecs.Query.Descriptor.exclude field Caller-writable. Lists every component a matching archetype must omit. ```teal 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. ```teal tecs.Query.Descriptor.temp: boolean ``` ##### tecs.Query.Descriptor.groupBy Static Caller-writable. Assigns an integer group to each archetype. Archetypes with the same group are iterated contiguously. Use with groups() and group(id) for efficient grouped iteration. ```teal function tecs.Query.Descriptor.groupBy(archetype: Archetype): integer ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.Query.Descriptor.onEntitiesAdded( archetype: Archetype, firstRow: integer, lastRow: integer, count: integer ) ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.Query.Descriptor.onEntitiesRemoved( archetype: Archetype, firstRow: integer, lastRow: integer, count: integer ) ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal interface tecs.Query.Cursor is Closeable type IterFn = function(Cursor, any): (Archetype, integer, {integer}) type GroupsIterFn = function(Cursor, any): integer type GroupIterFn = function( Cursor, any ): (Archetype, integer, {integer}) group: function(self, groupId: integer): GroupIterFn, Cursor, any groups: function(self): GroupsIterFn, Cursor, any iter: function(self): IterFn, Cursor, any end ``` ##### Interfaces | Interface | | --- | | [`Closeable`](/modules/ecs/#tecs.ecs.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. ```teal type tecs.Query.Cursor.IterFn = function( Cursor, any ): (Archetype, integer, {integer}) ``` ##### tecs.Query.Cursor.GroupsIterFn type The step function `cursor:groups()` returns. Yields group ids in ascending order. ```teal type tecs.Query.Cursor.GroupsIterFn = function(Cursor, any): integer ``` ##### tecs.Query.Cursor.GroupIterFn type The step function `cursor:group(id)` returns, with the same three values as `IterFn` narrowed to one group. ```teal type tecs.Query.Cursor.GroupIterFn = function( Cursor, any ): (Archetype, integer, {integer}) ``` ##### tecs.Query.Cursor:group Instance Iterate over active archetypes in one group. ```teal function tecs.Query.Cursor.group( self, groupId: integer ): GroupIterFn, Cursor, any ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Cursor` | | | `groupId` | `integer` | The group to traverse. | ###### Returns | Type | Description | | --- | --- | | [`GroupIterFn`](/modules/ecs/#tecs.Query.Cursor.GroupIterFn) | The cursor's grouped step function. | | [`Cursor`](/modules/ecs/#tecs.Query.Cursor) | This cursor. | | `any` | The iterator's initial control value. | ##### tecs.Query.Cursor:groups Instance Iterate over active group IDs in sorted order. ```teal function tecs.Query.Cursor.groups(self): GroupsIterFn, Cursor, any ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Cursor` | | ###### Returns | Type | Description | | --- | --- | | [`GroupsIterFn`](/modules/ecs/#tecs.Query.Cursor.GroupsIterFn) | | | [`Cursor`](/modules/ecs/#tecs.Query.Cursor) | | | `any` | | ##### tecs.Query.Cursor:iter Instance Iterate over every active archetype matched by the query. ```teal function tecs.Query.Cursor.iter(self): IterFn, Cursor, any ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Cursor` | | ###### Returns | Type | Description | | --- | --- | | [`IterFn`](/modules/ecs/#tecs.Query.Cursor.IterFn) | | | [`Cursor`](/modules/ecs/#tecs.Query.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. ```teal type tecs.Query.IterFn = function( Query, any ): (Archetype, integer, {integer}) ``` #### tecs.Query.GroupsIterFn type The step function `query:groups()` returns. Yields group ids in ascending order. ```teal type tecs.Query.GroupsIterFn = function(Query, any): integer ``` #### tecs.Query.GroupIterFn type The step function `query:group(id)` returns, with the same three values as `IterFn` narrowed to one group. ```teal type tecs.Query.GroupIterFn = function( Query, any ): (Archetype, integer, {integer}) ``` #### tecs.Query.descriptor field Read-only. Returns the descriptor used to create the query. Exposed for inspection. Mutating it after query construction does not rebuild component masks, subscriptions, or grouping state. ```teal tecs.Query.descriptor: Descriptor ``` #### tecs.Query:count Instance Total number of entities currently matched by this query. One pass over matching archetypes, not entities. ```teal function tecs.Query.count(self): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Query` | | ##### Returns | Type | Description | | --- | --- | | `integer` | | #### tecs.Query:getGroup Instance Returns the cached group identifier for an archetype. Only available when `groupBy` is specified. Returns nil when the archetype does not match this query. ```teal function tecs.Query.getGroup(self, archetype: Archetype): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Query` | | | `archetype` | [`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.Query.getGroupCount(self, groupId: integer): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Query` | | | `groupId` | `integer` | The group to count. | ##### Returns | Type | Description | | --- | --- | | `integer` | Its entity count, or zero when the group does not exist. | #### tecs.Query:group Instance Iterate over archetypes in a specific group. Only available when groupBy is specified. Usage: `for archetype, len, entities in query:group(id) do ... end`. Yields nothing if the group has no archetypes. ```teal function tecs.Query.group( self, groupId: integer ): GroupIterFn, Query, any ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Query` | | | `groupId` | `integer` | The group to traverse. | ##### Returns | Type | Description | | --- | --- | | [`GroupIterFn`](/modules/ecs/#tecs.Query.GroupIterFn) | The query's grouped step function. | | [`Query`](/modules/ecs/#tecs.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`. ```teal function tecs.Query.groups(self): GroupsIterFn, Query, any ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Query` | | ##### Returns | Type | Description | | --- | --- | | [`GroupsIterFn`](/modules/ecs/#tecs.Query.GroupsIterFn) | | | [`Query`](/modules/ecs/#tecs.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` ```teal function tecs.Query.iter(self): IterFn, Query, any ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Query` | | ##### Returns | Type | Description | | --- | --- | | [`IterFn`](/modules/ecs/#tecs.Query.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`](/modules/ecs/#tecs.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. ```teal function tecs.Query.newCursor(self): Cursor ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Query` | | ##### Returns | Type | Description | | --- | --- | | [`Cursor`](/modules/ecs/#tecs.Query.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. ```teal type tecs.ecs.QueryCursor = types.Query.Cursor ``` ### tecs.ecs.QueryDescriptor type `QueryDescriptor` configures a query. ```teal type tecs.ecs.QueryDescriptor = types.Query.Descriptor ``` ### tecs.ecs.Relationship interface `Relationship` names any relationship definition. ```teal interface tecs.ecs.Relationship is Component exclusiveRelationship: boolean targeting: function(self, integer): self end ``` #### Interfaces | Interface | | --- | | [`Component`](/modules/ecs/#tecs.ecs.Component) | #### tecs.ecs.Relationship.exclusiveRelationship field Read-only. Component container property indicating that the relationship is exclusive (e.g., has-one). ```teal tecs.ecs.Relationship.exclusiveRelationship: boolean ``` #### tecs.ecs.Relationship:targeting Instance Returns the component type for a specific target. ```teal function tecs.ecs.Relationship.targeting(self, integer): self ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Relationship` | | | `#2` | `integer` | | ##### Returns | Type | Description | | --- | --- | | `self` | | ### tecs.ecs.RelationshipOptions interface `RelationshipOptions` configures a relationship. ```teal interface tecs.ecs.RelationshipOptions is BaseRelationshipOptions, ComponentOptions end ``` #### Interfaces | Interface | | --- | | `BaseRelationshipOptions` | | [`ComponentOptions`](/modules/ecs/#tecs.ecs.ComponentOptions)`` | #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `R` | [`Relationship`](/modules/ecs/#tecs.ecs.Relationship) | | ### tecs.ecs.ScalarComponent interface `ScalarComponent` names a single-value component. ```teal interface tecs.ecs.ScalarComponent is Component scalarKind: ScalarKind scalarDefault: T enum ScalarKind "boolean" "number" "string" end end ``` #### Interfaces | Interface | | --- | | [`Component`](/modules/ecs/#tecs.ecs.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. ```teal tecs.ecs.ScalarComponent.scalarKind: ScalarKind ``` #### tecs.ecs.ScalarComponent.scalarDefault field Read-only. The value a row takes when the component is added without one. Never nil: `newScalarComponent` fills an omitted `default` with the zero of `kind` (`0`, `false` or `""`). ```teal tecs.ecs.ScalarComponent.scalarDefault: T ``` #### tecs.ecs.ScalarComponent.ScalarKind enum The primitives a scalar column may hold. Anything else, tables and cdata included, is a table or FFI component instead. ```teal enum tecs.ecs.ScalarComponent.ScalarKind "boolean" "number" "string" end ``` ### tecs.ecs.ScalarComponentOptions interface `ScalarComponentOptions` configures a scalar component. ```teal interface tecs.ecs.ScalarComponentOptions is BasicComponentOptions> kind: string default: T end ``` #### Interfaces | Interface | | --- | | `BasicComponentOptions<`[`ScalarComponent`](/modules/ecs/#tecs.ecs.ScalarComponent)`>` | #### 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. ```teal tecs.ecs.ScalarComponentOptions.kind: string ``` #### tecs.ecs.ScalarComponentOptions.default field Caller-writable. Optional. Omitting it takes the zero of `kind` (`0`, `false` or `""`), so a scalar column never reads back nil. ```teal tecs.ecs.ScalarComponentOptions.default: T ``` ### tecs.ecs.Snapshot type `Snapshot` names serialized world state. ```teal type tecs.ecs.Snapshot = types.World.Snapshot ``` ### tecs.ecs.SnapshotComponentTableEntry type `SnapshotComponentTableEntry` identifies one component in a snapshot. ```teal type tecs.ecs.SnapshotComponentTableEntry = types.World.SnapshotComponentTableEntry ``` ### tecs.ecs.SnapshotHandler type `SnapshotHandler` saves and restores plugin data. ```teal type tecs.ecs.SnapshotHandler = types.World.SnapshotHandler ``` ### tecs.ecs.SnapshotOptions type `SnapshotOptions` controls snapshot serialization. ```teal type tecs.ecs.SnapshotOptions = types.World.SnapshotOptions ``` ### tecs.ecs.SnapshotOutput type `SnapshotOutput` collects serialized data. ```teal type tecs.ecs.SnapshotOutput = types.World.SnapshotOutput ``` ### tecs.ecs.SnapshotPrelude type `SnapshotPrelude` names snapshot metadata. ```teal type tecs.ecs.SnapshotPrelude = types.World.SnapshotPrelude ``` ### tecs.ecs.StatePolicy record `StatePolicy` controls state-stack participation. ```teal record tecs.ecs.StatePolicy record Action apply: string call: function(World) end onBlur: string | Action | function(World) onFocus: string | Action | function(World) onExit: string | Action | function(World) onEnter: function(World) end ``` #### tecs.ecs.StatePolicy.Action record Action for a state lifecycle hook. A string action ("pause", "resume", "despawn", "disable"), a plugin function, or a policy with both. ```teal record tecs.ecs.StatePolicy.Action apply: string call: function(World) end ``` ##### tecs.ecs.StatePolicy.Action.apply field Caller-writable. Built-in action: "pause", "resume", "despawn", "disable" ```teal tecs.ecs.StatePolicy.Action.apply: string ``` ##### tecs.ecs.StatePolicy.Action.call Static Custom function called with the world ```teal function tecs.ecs.StatePolicy.Action.call(World) ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | [`World`](/modules/ecs/#tecs.World) | | ###### Returns None. #### tecs.ecs.StatePolicy.onBlur field Caller-writable. Fires when this state is no longer top (another state pushed on top). ```teal 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). ```teal tecs.ecs.StatePolicy.onFocus: string | Action | function(World) ``` #### tecs.ecs.StatePolicy.onExit field Caller-writable. Fires when this state is popped (default: "despawn"). ```teal 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. ```teal function tecs.ecs.StatePolicy.onEnter(World) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | [`World`](/modules/ecs/#tecs.World) | | ##### Returns None. ### tecs.ecs.Stats type `Stats` reports live world counts. ```teal type tecs.ecs.Stats = types.World.Stats ``` ### tecs.System type A system function runs once when its phase dispatches. ```teal type tecs.System = function(number, World) ``` ### tecs.ecs.SystemConfig interface `SystemConfig` configures a system. ```teal interface tecs.ecs.SystemConfig name: string phase: Phase run: System before: {string} after: {string} runIf: function(number, World, string): boolean end ``` #### tecs.ecs.SystemConfig.name field Caller-writable. Optional, and unique across the whole pipeline: registering a second system under a name already taken errors. Omitting it assigns a synthetic `_anonymousSystemN`, so `removeSystem` always has a handle, but the debugger, the MCP tools and profiles then show that instead of anything readable. Name every persistent system. ```teal tecs.ecs.SystemConfig.name: string ``` #### tecs.ecs.SystemConfig.phase field Caller-writable. Required, and must already be registered with the pipeline; `addSystem` errors on an unregistered phase rather than creating one. ```teal tecs.ecs.SystemConfig.phase: Phase ``` #### tecs.ecs.SystemConfig.run field Caller-writable. Required. Receives `(dt, world)`, where `dt` is seconds and, in a fixed phase, is the fixed timestep rather than frame time. ```teal tecs.ecs.SystemConfig.run: System ``` #### tecs.ecs.SystemConfig.before field Caller-writable. Names of systems this one must run before. A name that no system in the SAME phase carries is ignored silently: ordering is solved per phase, so a constraint naming a system in another phase does nothing. Mutual constraints across a group error as a cycle. ```teal 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. ```teal 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`. ```teal function tecs.ecs.SystemConfig.runIf(number, World, string): boolean ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `number` | | | `#2` | `World` | | | `#3` | `string` | | ##### Returns | Type | Description | | --- | --- | | `boolean` | | ### tecs.ecs.TagComponentOptions interface `TagComponentOptions` configures a tag component. ```teal interface tecs.ecs.TagComponentOptions is BasicComponentOptions container: Component end ``` #### Interfaces | Interface | | --- | | `BasicComponentOptions<`[`Component`](/modules/ecs/#tecs.ecs.Component)`>` | #### tecs.ecs.TagComponentOptions.container field Caller-writable. Optional container to use for the tag component. ```teal tecs.ecs.TagComponentOptions.container: Component ``` ### tecs.World interface A world owns entities, components, queries, systems, resources, events, snapshots, and the state stack. ```teal 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( self, entity: integer, component: T ): T getBundle: function(self, name: string): Bundle | nil getBundles: function(self): {string: Bundle} getFirstRelationship: function( self, entity: integer, relationship: T ): T getFixedTiming: function(self): number, number, number getMut: function( 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( 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( 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( self, address: integer, event: T, observer: function(T) | string ) targets: function( 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( self, entity: integer, relationship: components.Relationship, callback: function(integer, integer, T): boolean, context: T, maxDepth: number ) end ``` #### tecs.World.Config interface The options passed to `tecs.ecs.newWorld`. ```teal interface tecs.World.Config timestep: number fixedMaxSteps: integer fixedOverload: FixedOverload maxEntities: integer pipelineFactory: function( timestep: number, fixedMaxSteps: integer, fixedOverload: FixedOverload ): Pipeline end ``` ##### tecs.World.Config.timestep field Caller-writable. Sets the positive duration of one fixed step in seconds. Defaults to 1/60. ```teal tecs.World.Config.timestep: number ``` ##### tecs.World.Config.fixedMaxSteps field Caller-writable. Sets the positive number of fixed steps one update may run before the overload policy applies. Defaults to 10. ```teal tecs.World.Config.fixedMaxSteps: integer ``` ##### tecs.World.Config.fixedOverload field Caller-writable. Selects what happens to catch-up steps that exceed `fixedMaxSteps`. Defaults to `"drop"`. ```teal tecs.World.Config.fixedOverload: FixedOverload ``` ##### tecs.World.Config.maxEntities field Caller-writable. Sets the positive number of concurrent entity slots, up to 2^22 - 1. Defaults to 2^20. ```teal tecs.World.Config.maxEntities: integer ``` ##### tecs.World.Config.pipelineFactory Static Caller-writable. Builds a custom system pipeline once during world construction. Most callers omit this field. ```teal function tecs.World.Config.pipelineFactory( timestep: number, fixedMaxSteps: integer, fixedOverload: FixedOverload ): Pipeline ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `timestep` | `number` | The configured fixed timestep. | | `fixedMaxSteps` | `integer` | The configured fixed-step limit. | | `fixedOverload` | [`FixedOverload`](/modules/ecs/#tecs.ecs.FixedOverload) | The configured overload policy. | ###### Returns | Type | Description | | --- | --- | | [`Pipeline`](/modules/ecs/#tecs.ecs.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. ```teal interface tecs.World.SnapshotComponentTableEntry name: string fingerprint: string | nil end ``` ##### tecs.World.SnapshotComponentTableEntry.name field Caller-writable. Names the registered component a load resolves this entry against. ```teal tecs.World.SnapshotComponentTableEntry.name: string ``` ##### tecs.World.SnapshotComponentTableEntry.fingerprint field Caller-writable. Carries the canonical FFI field-layout fingerprint, or nil for a non-FFI component. Binary output embeds it so a load can detect that the saved struct layout differs from the current one and route those rows through per-entity migration. nil for every non-FFI component, and absent entirely from `"table"` output, whose loads go through field-name-keyed `deserialize` and migrate without it. ```teal tecs.World.SnapshotComponentTableEntry.fingerprint: string | nil ``` #### tecs.World.SnapshotPrelude interface The header of a snapshot, and what `loadSnapshot` answers with. ```teal interface tecs.World.SnapshotPrelude version: integer nextEntityId: integer entityCount: integer archetypeCount: integer componentTable: {SnapshotComponentTableEntry} end ``` ##### tecs.World.SnapshotPrelude.version field Read-only. Reports the snapshot format version, not the game version. ```teal tecs.World.SnapshotPrelude.version: integer ``` ##### tecs.World.SnapshotPrelude.nextEntityId field Read-only. Reports where entity slot allocation resumes. A load moves the allocator forward to this when it is ahead of where the allocator already is, and never backwards, so ids handed out after a load cannot collide with restored ones. ```teal tecs.World.SnapshotPrelude.nextEntityId: integer ``` ##### tecs.World.SnapshotPrelude.entityCount field Read-only. Reports the entity count when the writer knew it, or nil for a streaming writer. ```teal tecs.World.SnapshotPrelude.entityCount: integer ``` ##### tecs.World.SnapshotPrelude.archetypeCount field Read-only. Reports the archetype count when the writer knew it, or nil for a streaming writer. ```teal tecs.World.SnapshotPrelude.archetypeCount: integer ``` ##### tecs.World.SnapshotPrelude.componentTable field Read-only. Lists every referenced component in archetype index order. ```teal tecs.World.SnapshotPrelude.componentTable: {SnapshotComponentTableEntry} ``` #### tecs.World.SnapshotArchetypeEntry interface One archetype's worth of entities in a `"table"` snapshot. ```teal interface tecs.World.SnapshotArchetypeEntry columnIndices: {integer} entities: {{any}} end ``` ##### tecs.World.SnapshotArchetypeEntry.columnIndices field Caller-writable. Lists 1-based indices into `Snapshot.componentTable`, in the same order the per-entity payloads appear. ```teal 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`. ```teal tecs.World.SnapshotArchetypeEntry.entities: {{any}} ``` #### tecs.World.SnapshotDataEntry interface One keyed value in a snapshot's data section. ```teal interface tecs.World.SnapshotDataEntry key: string value: any end ``` ##### tecs.World.SnapshotDataEntry.key field Caller-writable. Names the key a `SnapshotHandler` or `customData` entry wrote under. Keys beginning `__tecs.` are the engine's own. ```teal tecs.World.SnapshotDataEntry.key: string ``` ##### tecs.World.SnapshotDataEntry.value field Caller-writable. Holds the value written under `key`. It must survive the chosen format: a `"binary"` snapshot can carry anything the serializer accepts, a `"table"` one anything a plain Lua table can hold. ```teal tecs.World.SnapshotDataEntry.value: any ``` #### tecs.World.Snapshot interface A whole snapshot in plain-table form, which is what `saveSnapshot` returns under `format = "table"`. ```teal interface tecs.World.Snapshot version: integer nextEntityId: integer componentTable: {SnapshotComponentTableEntry} archetypes: {SnapshotArchetypeEntry} data: {SnapshotDataEntry} end ``` ##### tecs.World.Snapshot.version field Caller-writable. Sets the snapshot format version. ```teal tecs.World.Snapshot.version: integer ``` ##### tecs.World.Snapshot.nextEntityId field Caller-writable. Sets the slot where entity allocation resumes. ```teal tecs.World.Snapshot.nextEntityId: integer ``` ##### tecs.World.Snapshot.componentTable field Caller-writable. Lists the components referenced by the archetype entries; `SnapshotArchetypeEntry.columnIndices` points into it. ```teal tecs.World.Snapshot.componentTable: {SnapshotComponentTableEntry} ``` ##### tecs.World.Snapshot.archetypes field Caller-writable. Lists archetypes in save order. ```teal tecs.World.Snapshot.archetypes: {SnapshotArchetypeEntry} ``` ##### 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. ```teal tecs.World.Snapshot.data: {SnapshotDataEntry} ``` #### tecs.World.SnapshotFormat enum Which of the two representations `saveSnapshot` produces. ```teal enum tecs.World.SnapshotFormat "binary" "table" end ``` #### tecs.World.SnapshotOptions interface Options passed to `saveSnapshot`. All fields are optional. ```teal interface tecs.World.SnapshotOptions format: SnapshotFormat buffer: StringBuffer path: string filterQuery: Query.Descriptor layers: {integer} customData: {string: any} end ``` ##### tecs.World.SnapshotOptions.format field Caller-writable. Selects `"binary"` for a LuaJIT `string.buffer` or `"table"` for a plain table. ```teal tecs.World.SnapshotOptions.format: SnapshotFormat ``` ##### 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. ```teal tecs.World.SnapshotOptions.buffer: StringBuffer ``` ##### tecs.World.SnapshotOptions.path field Caller-writable. Supplies an optional path for binary output. When provided, `saveSnapshot` writes the bytes to disk and still returns the tagged buffer result. Binary output only: passing one with `format = "table"` errors rather than being ignored. ```teal tecs.World.SnapshotOptions.path: string ``` ##### tecs.World.SnapshotOptions.filterQuery field Caller-writable. Selects saved archetypes through a temporary query. ```teal tecs.World.SnapshotOptions.filterQuery: Query.Descriptor ``` ##### tecs.World.SnapshotOptions.layers field Caller-writable. Allows only the listed `Transform2D.layer` values from 0 through 31. ```teal tecs.World.SnapshotOptions.layers: {integer} ``` ##### tecs.World.SnapshotOptions.customData field Caller-writable. Adds keyed metadata to the snapshot. ```teal 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. ```teal interface tecs.World.SnapshotOutput format: SnapshotFormat buffer: StringBuffer | nil snapshot: Snapshot | nil end ``` ##### tecs.World.SnapshotOutput.format field Read-only. Reports which representation carries the snapshot. ```teal tecs.World.SnapshotOutput.format: SnapshotFormat ``` ##### 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. ```teal tecs.World.SnapshotOutput.buffer: StringBuffer | nil ``` ##### tecs.World.SnapshotOutput.snapshot field Read-only. Returns the snapshot under `format = "table"`, or nil for binary output. The table is freshly built and the caller's to keep. ```teal tecs.World.SnapshotOutput.snapshot: Snapshot | nil ``` #### tecs.World.SnapshotHandler interface Named snapshot participant for custom non-component data. `save` writes one keyed value into the snapshot data section when it returns non-nil. `load` receives that value after the ECS world has been restored. `finish` runs after every data callback has completed. ```teal interface tecs.World.SnapshotHandler name: string load: function(World, any) | nil finish: function(World, SnapshotPrelude) | nil save: function(world: World): any | nil end ``` ##### tecs.World.SnapshotHandler.name field Caller-writable. Sets the non-empty key used to store the value or registration errors. Namespace it with dots (`"myGame.gameState"`); keys beginning `__tecs.` are the engine's own. ```teal tecs.World.SnapshotHandler.name: string ``` ##### tecs.World.SnapshotHandler.load field Caller-writable. Optionally receives saved data. Tecs calls it only when the snapshot carries this handler's key, so a snapshot saved before the handler existed simply does not call it. ```teal tecs.World.SnapshotHandler.load: function(World, any) | nil ``` ##### tecs.World.SnapshotHandler.finish field Caller-writable. Optionally runs after every data callback has completed, which is the place for work that depends on more than one handler's value. ```teal tecs.World.SnapshotHandler.finish: function(World, SnapshotPrelude) | nil ``` ##### tecs.World.SnapshotHandler.save Static Caller-writable. Optionally returns data to save. Returning nil writes no entry, which is how a handler declines rather than storing an empty value. ```teal function tecs.World.SnapshotHandler.save(world: World): any | nil ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.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. ```teal tecs.World.resources: Store ``` #### tecs.World.Stats interface Counts and fixed-step loss reported by `world:getStats`. ```teal interface tecs.World.Stats entities: integer archetypes: integer components: integer systems: integer fixedTimeDropped: number fixedStepsDropped: integer end ``` ##### tecs.World.Stats.entities field Read-only. Reports the number of active entities. ```teal tecs.World.Stats.entities: integer ``` ##### tecs.World.Stats.archetypes field Read-only. Reports the number of archetypes. ```teal tecs.World.Stats.archetypes: integer ``` ##### tecs.World.Stats.components field Read-only. Reports the number of registered components. ```teal tecs.World.Stats.components: integer ``` ##### tecs.World.Stats.systems field Read-only. Reports the number of registered systems. ```teal tecs.World.Stats.systems: integer ``` ##### tecs.World.Stats.fixedTimeDropped field Read-only. Reports simulated seconds abandoned by the fixed step overload policy. ```teal tecs.World.Stats.fixedTimeDropped: number ``` ##### tecs.World.Stats.fixedStepsDropped field Read-only. Reports fixed steps abandoned by the overload policy. ```teal tecs.World.Stats.fixedStepsDropped: integer ``` #### tecs.World:addPlugin Instance Add a plugin to the world. ```teal function tecs.World.addPlugin(self, plugin: Plugin) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `plugin` | [`Plugin`](/modules/ecs/#tecs.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. ```teal function tecs.World.addSnapshotHandler(self, handler: SnapshotHandler) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `handler` | [`SnapshotHandler`](/modules/ecs/#tecs.World.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. ```teal function tecs.World.addSystem(self, config: SystemConfig) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `config` | [`SystemConfig`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.batchDespawn(self, query: Query) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `query` | [`Query`](/modules/ecs/#tecs.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. ```teal function tecs.World.batchRemove( self, query: Query, componentType: components.Component ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `query` | [`Query`](/modules/ecs/#tecs.Query) | Query built via `world:newQuery(...)`. | | `componentType` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.batchSet( self, query: Query, componentOrInstance: components.Component, callback: function(Archetype, integer, integer, integer) ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `query` | [`Query`](/modules/ecs/#tecs.Query) | Query built via `world:newQuery(...)`. | | `componentOrInstance` | [`components.Component`](/modules/ecs/#tecs.ecs.Component) | Component instance (const mode) or component type (callback mode). | | `callback` | `function(`[`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.batchSpawn( self, count: integer, componentTypes: {components.Component}, callback: function(Archetype, integer, integer, integer) ): integer | nil, {integer} | nil ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `count` | `integer` | Number of entities to spawn. | | `componentTypes` | `{`[`components.Component`](/modules/ecs/#tecs.ecs.Component)`}` | Array of component types defining the archetype. | | `callback` | `function(`[`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal 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`](/modules/ecs/#tecs.ecs.Component)`}` | Array of component types defining the archetype. | | `callback` | `function(`[`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.byKey(self, key: string): integer | nil ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `key` | `string` | The durable key to find. | ##### Returns | Type | Description | | --- | --- | | integer | nil | The live entity, or nil when the key has none. | #### tecs.World:clearEntities Instance Wipe all entity data but preserve structural state (pipeline, registered systems, queries, query observers, archetype column capacity). Use this for per-test reuse, benchmark setup, and save/load clear-before-load. Clears: entities, pending transaction, sparse relationship stores and queued messages. Preserves: systems, queries, archetype columns, observers. If you need post-construction state (systems gone, queries gone), just call `tecs.ecs.newWorld()` -- same path, clearer intent. ```teal 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). ```teal 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. ```teal 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). ```teal function tecs.World.compact(self): integer, integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns | Type | Description | | --- | --- | | `integer` | archetypesPruned Number of dead archetypes removed. | | `integer` | archetypesCompacted Number of archetypes whose storage was shrunk. | #### tecs.World:createState Instance Create a named state with an optional lifecycle policy. Returns a tag component that is auto-added to entities spawned while this state is on top of the stack. ```teal function tecs.World.createState( self, name: string, policy: StatePolicy ): components.Component ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `name` | `string` | The name of the state. | | `policy` | `StatePolicy` | Optional lifecycle policy for state transitions. | ##### Returns | Type | Description | | --- | --- | | [`components.Component`](/modules/ecs/#tecs.ecs.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`. ```teal function tecs.World.defer(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns None. #### tecs.World:despawn Instance Despawn an entity. ```teal 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. ```teal function tecs.World.dirtyArchetypes(self): function(): Archetype ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns | Type | Description | | --- | --- | | `function(): `[`Archetype`](/modules/ecs/#tecs.ecs.Archetype) | | #### tecs.World:disablePhase Instance Disable a phase. ```teal function tecs.World.disablePhase(self, phase: Phase) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.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. ```teal 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. ```teal function tecs.World.enablePhase(self, phase: Phase) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | The phase to enable. | ##### Returns None. #### tecs.World:findArchetypes Instance Find archetypes that have the given component. ```teal function tecs.World.findArchetypes( self, component: components.Component ): function(): (Archetype, integer, DoubleArray) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `component` | [`components.Component`](/modules/ecs/#tecs.ecs.Component) | The component to find. | ##### Returns | Type | Description | | --- | --- | | `function(): (`[`Archetype`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.fixedStepCount(self): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns | Type | Description | | --- | --- | | `integer` | Steps run, from zero. | #### tecs.World:forEachArchetype Instance Iterate all archetypes in the world. Mainly useful for save game / debugging tools that need to walk entity state without matching a specific component signature. ```teal function tecs.World.forEachArchetype( self, callback: function(Archetype) ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `callback` | `function(`[`Archetype`](/modules/ecs/#tecs.ecs.Archetype)`)` | Called with each archetype. | ##### Returns None. #### tecs.World:get Instance Get a component instance attached to an entity. ```teal function tecs.World.get( self, entity: integer, component: T ): T ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.getBundle(self, name: string): Bundle | nil ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `name` | `string` | The bundle name. | ##### Returns | Type | Description | | --- | --- | | Bundle | nil | The bundle, or nil if not found. | #### tecs.World:getBundles Instance Get all registered bundles. ```teal function tecs.World.getBundles(self): {string: Bundle} ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns | Type | Description | | --- | --- | | `{string : Bundle}` | A fresh map of bundle name to bundle. | #### tecs.World:getFirstRelationship Instance Get the first relationship instance for a relationship container on an entity. For exclusive relationships (like ChildOf), this returns the single instance. ```teal function tecs.World.getFirstRelationship( self, entity: integer, relationship: T ): T ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`components.Relationship`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.getFixedTiming(self): number, number, number ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns | Type | Description | | --- | --- | | `number` | timestep Fixed update interval in seconds. | | `number` | accumulator Residual time in seconds. | | `number` | alpha Clamped interpolation fraction. | #### tecs.World:getMut Instance Mutable counterpart to `get`. Returns the component AND marks it dirty on the entity's archetype so dirty-gated consumers (shadow pipeline, change observers) re-process the row after subsequent cdata writes. Use this whenever you intend to mutate the component through the returned reference. `get` + cdata write silently bypasses dirty tracking and leaves stale state downstream. STAGING: an entity spawned earlier in the SAME frame is staged until the commit drain, so getMut on it returns nil. Spawn with final values via constructor args instead of spawn-then-mutate. ```teal function tecs.World.getMut( self, entity: integer, component: T ): T ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.getStats(self, fill: World.Stats): World.Stats ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `fill` | `World.Stats` | Optional stats table to fill instead of allocating a new one. Passing one every frame is how this is read without adding a table per frame to the collector. | ##### Returns | Type | Description | | --- | --- | | `World.Stats` | The same table `fill` named when one was given, so the caller already holds it. A fresh one otherwise, and either way a copy rather than a view: the numbers do not update on their own. | #### tecs.World:has Instance Check whether an entity currently has a component. For sparse relationships: - passing the relationship container checks whether the entity has any target for that relationship - passing a relationship instance checks that specific target ```teal function tecs.World.has( self, entity: integer, component: components.Component ): boolean ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `entity` | `integer` | Entity ID. | | `component` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.hasObservers( self, address: integer, event: T ): boolean ``` ##### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | `events.Event` | | ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `address` | `integer` | The world address or entity identifier. | | `event` | `T` | The event type to inspect. | ##### Returns | Type | Description | | --- | --- | | `boolean` | True when the address has an observer for this event type. | #### tecs.World:isAlive Instance Check if an entity is committed and alive. ```teal function tecs.World.isAlive(self, entity: integer): boolean ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `entity` | `integer` | The entity to check. | ##### Returns | Type | Description | | --- | --- | | `boolean` | true if the entity is committed and alive, false otherwise. | #### tecs.World:loadSnapshot Instance Restore the world from either binary or table form. `source` may be a Lua string, a LuaJIT `string.buffer`, or a snapshot table previously returned by `saveSnapshot` with `format = "table"` (or parsed from JSON). ```teal function tecs.World.loadSnapshot(self, source: any): SnapshotPrelude ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `source` | `any` | One of the three forms above. Every entity already in the world is despawned before the first one is restored, so this replaces a world rather than merging into one. | ##### Returns | Type | Description | | --- | --- | | [`SnapshotPrelude`](/modules/ecs/#tecs.World.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). ```teal function tecs.World.markComponentDirty( self, entity: integer, component: components.Component ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `entity` | `integer` | Entity ID. | | `component` | [`components.Component`](/modules/ecs/#tecs.ecs.Component) | Component type whose column was mutated. | ##### Returns None. #### tecs.World:newBundle Instance Create and register a bundle with the world. ```teal function tecs.World.newBundle( self, name: string, def: Bundle.Definition ): Bundle ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `name` | `string` | The name of the bundle. | | `def` | `Bundle.Definition` | Bundle definition with required and with-default components. | ##### Returns | Type | Description | | --- | --- | | `Bundle` | The registered bundle. | #### tecs.World:newQuery Instance Creates a new query. Iteration does NOT auto-mark anything dirty; mutation intent lives at the access site via `archetype:getMut(Foo)` inside the iter loop, which marks just that component dirty on the archetype. ```teal function tecs.World.newQuery( self, descriptor: Query.Descriptor ): Query ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `descriptor` | [`Query.Descriptor`](/modules/ecs/#tecs.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`](/modules/ecs/#tecs.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. ```teal function tecs.World.observe( 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. ```teal function tecs.World.peekState(self): string ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns | Type | Description | | --- | --- | | `string` | The name of the top state, or nil if the stack is empty. | #### tecs.World:popState Instance Pop the current state from the state stack. Fires the current state's onExit policy and the new top state's onFocus policy. ```teal 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. ```teal 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. ```teal function tecs.World.registerPhase(self, phase: Phase) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.Phase) | The phase to register. | ##### Returns None. #### tecs.World:remove Instance Remove a component from an entity. ```teal function tecs.World.remove( self, entity: integer, component: components.Component ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `entity` | `integer` | Entity ID. | | `component` | [`components.Component`](/modules/ecs/#tecs.ecs.Component) | Component type to remove. | ##### Returns None. #### tecs.World:removeSystem Instance Remove a system from the world. ```teal 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. ```teal function tecs.World.requireKey(self, key: string): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `key` | `string` | The durable key to find. | ##### Returns | Type | Description | | --- | --- | | `integer` | The live entity. | #### tecs.World:runPhase Instance Run every system registered to `phase` (and its enabled descendants) with the given `dt`. Unlike `update`, this does NOT pre-commit or clear dirty bits -- it only dispatches systems. Useful for piecewise phase execution (e.g. custom game loops splitting Update and Render across distinct ticks). ```teal function tecs.World.runPhase(self, phase: Phase, dt: number) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `phase` | [`Phase`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.saveSnapshot( self, opts: SnapshotOptions ): SnapshotOutput ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `opts` | [`SnapshotOptions`](/modules/ecs/#tecs.World.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`](/modules/ecs/#tecs.World.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. ```teal function tecs.World.set( self, entity: integer, component: components.Component, value: any ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `entity` | `integer` | Entity ID. | | `component` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal 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. ```teal function tecs.World.spawn( self, ...: components.Component ): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `...` | [`components.Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.spawnAt( self, id: integer, ...: components.Component ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `id` | `integer` | The packed entity id to reuse. | | `...` | [`components.Component`](/modules/ecs/#tecs.ecs.Component) | Variable number of components to add to the entity. | ##### Returns None. #### tecs.World:spawnBundle Instance Spawn an entity using a registered bundle. ```teal function tecs.World.spawnBundle( self, name: string, ...: components.Component ): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | | `name` | `string` | The name of the bundle. | | `...` | [`components.Component`](/modules/ecs/#tecs.ecs.Component) | Component overrides (required components must be provided). | ##### Returns | Type | Description | | --- | --- | | `integer` | The entity ID. | #### tecs.World:startup Instance Run the startup systems. ```teal function tecs.World.startup(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns None. #### tecs.World:stopObserving Instance Stop observing an event at an address. ```teal function tecs.World.stopObserving( 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. ```teal function tecs.World.targets( 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`](/modules/ecs/#tecs.ecs.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. ```teal 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`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.World.unwind(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `World` | | ##### Returns None. #### tecs.World:update Instance Update the world. ```teal 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. ```teal function tecs.World.walkUp( 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`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.declaredComponents(): {string: Component} ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `{string : `[`Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.findComponentById(id: integer): Component ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `id` | `integer` | The caller supplies a process-wide component id. | #### Returns | Type | Description | | --- | --- | | [`Component`](/modules/ecs/#tecs.ecs.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. ```teal function tecs.ecs.findComponentByName(name: string): Component ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | The caller supplies the process-wide registration name. | #### Returns | Type | Description | | --- | --- | | [`Component`](/modules/ecs/#tecs.ecs.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. ```teal tecs.ecs.ArchetypeCreated: builtins.ArchetypeCreated ``` ### tecs.ecs.ChildOf variable Read-only. [`ChildOf`](/modules/ecs/#tecs.ecs.ChildOf) links a parent and child. It stores edges sparsely and cascade-deletes children with their parent. ```teal tecs.ecs.ChildOf: Relationship ``` ### tecs.ecs.DEFAULT_MAX_ENTITIES variable Read-only. `DEFAULT_MAX_ENTITIES` supplies 2^20 when world configuration omits `maxEntities`. ```teal tecs.ecs.DEFAULT_MAX_ENTITIES: integer ``` ### tecs.ecs.Disabled variable Read-only. [`Disabled`](/modules/ecs/#tecs.ecs.Disabled) excludes an entity from queries that do not ask for it. ```teal tecs.ecs.Disabled: Component ``` ### tecs.ecs.EntityKey variable Read-only. [`EntityKey`](/modules/ecs/#tecs.ecs.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`](/modules/data/#tecs.data.Key) names typed store keys. ```teal tecs.ecs.EntityKey: ScalarComponent ``` ### tecs.ecs.FinishSnapshotLoad variable Read-only. `FinishSnapshotLoad` fires at entity 0 after every entity and data callback finishes restoration. ```teal tecs.ecs.FinishSnapshotLoad: builtins.FinishSnapshotLoad ``` ### tecs.ecs.MAX_ENTITIES variable Read-only. `MAX_ENTITIES` sets the absolute `World.Config.maxEntities` ceiling (2^22 - 1 usable slots; the entity-id format reserves slot 0). ```teal tecs.ecs.MAX_ENTITIES: integer ``` ### tecs.ecs.Name variable Read-only. [`Name`](/modules/ecs/#tecs.ecs.Name) stores an entity label as a raw string. It does not enforce uniqueness. Use [`EntityKey`](/modules/ecs/#tecs.ecs.EntityKey) for durable unique lookup. ```teal tecs.ecs.Name: ScalarComponent ``` ### tecs.ecs.OnDespawn variable Read-only. `OnDespawn` fires at an entity before removal. ```teal tecs.ecs.OnDespawn: builtins.OnDespawn ``` ### tecs.ecs.OnSnapshotSave variable Read-only. `OnSnapshotSave` fires at entity 0 before snapshot archetype serialization so plugins can attach keyed data or exclude derived data. ```teal tecs.ecs.OnSnapshotSave: builtins.OnSnapshotSave ``` ### tecs.ecs.OnSpawn variable Read-only. `OnSpawn` fires at an entity after spawning. ```teal tecs.ecs.OnSpawn: builtins.OnSpawn ``` ### tecs.ecs.Paused variable Read-only. [`Paused`](/modules/ecs/#tecs.ecs.Paused) excludes an entity from logic queries while keeping it visible. [`Disabled`](/modules/ecs/#tecs.ecs.Disabled) excludes both logic and rendering queries. ```teal tecs.ecs.Paused: Component ``` ### tecs.ecs.RelativeTransform2D variable Read-only. [`RelativeTransform2D`](/modules/ecs/#tecs.ecs.RelativeTransform2D) expresses a pose relative to a [`ChildOf`](/modules/ecs/#tecs.ecs.ChildOf) parent. The hierarchy system composes it with the parent's [`Transform2D`](/modules/ecs/#tecs.ecs.Transform2D), so a game writes this component and reads the world-space transform. ```teal tecs.ecs.RelativeTransform2D: builtins.RelativeTransform2D ``` ### tecs.ecs.runif variable Read-only. `runif` contains composable system run conditions. ```teal tecs.ecs.runif: runIfHelpers ``` ### tecs.ecs.StartSnapshotLoad variable Read-only. `StartSnapshotLoad` fires at entity 0 after world restoration and before data dispatch so plugins can register their keyed handlers. ```teal tecs.ecs.StartSnapshotLoad: builtins.StartSnapshotLoad ``` ### tecs.ecs.StateBlur variable Read-only. `StateBlur` fires at a state when another takes focus above it. ```teal tecs.ecs.StateBlur: builtins.StateBlur ``` ### tecs.ecs.StateEnter variable Read-only. `StateEnter` fires when a state enters the stack. ```teal tecs.ecs.StateEnter: builtins.StateEnter ``` ### tecs.ecs.StateExit variable Read-only. `StateExit` fires when a state leaves the stack. ```teal tecs.ecs.StateExit: builtins.StateExit ``` ### tecs.ecs.StateFocus variable Read-only. `StateFocus` fires at a state when it regains focus. ```teal tecs.ecs.StateFocus: builtins.StateFocus ``` ### tecs.ecs.Transform2D variable Read-only. [`Transform2D`](/modules/ecs/#tecs.ecs.Transform2D) positions everything a world holds. Hierarchy, physics, sequencing, and rendering all use it. ```teal tecs.ecs.Transform2D: builtins.Transform2D ``` ### tecs.ecs.Transform3D variable Read-only. `Transform3D` places an entity in a right-handed 3D world. Its quaternion turns local coordinates into world coordinates and uses `(x, y, z, w)` field order. ```teal tecs.ecs.Transform3D: builtins.Transform3D ``` ### tecs.ecs.TTL variable Read-only. [`TTL`](/modules/ecs/#tecs.ecs.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`](/modules/ecs/#tecs.ecs.Paused) entity does not burn through it. ```teal tecs.ecs.TTL: builtins.TTL ```