
# tecs.events


Typed events and address-based message buses.

Define a record, initialize it in place, and register it once:

```teal
local record Damaged is tecs.events.Event
    amount: number

    metamethod __call: function(self, amount: number): Damaged
end

Damaged.init = function(event: Damaged, amount: number)
    event.amount = amount
end

tecs.events.newEvent(Damaged)
```

Worlds use the same event definitions and address routing as a standalone
[`MessageBus`](/modules/events/#tecs.events.MessageBus). Address `0` conventionally
names a whole world, while entity IDs address individual entities.

Event delivery is synchronous. The emitter owns an event instance during
dispatch, so observers treat its fields as read-only and copy values they need
to retain. A table event constructed directly, such as `Damaged(10)`, is an
independent value the caller may keep.

## Module contents

### Constructors

| Constructor | Description |
| --- | --- |
| [`newEvent`](/modules/events/#tecs.events.newEvent) | Configures a table event with a callable constructor. |
| [`newFFIEvent`](/modules/events/#tecs.events.newFFIEvent) | Configures an FFI event with a callable constructor. |
| [`newMessageBus`](/modules/events/#tecs.events.newMessageBus) | Creates an independent address-based event message bus. |

### Types

| Type | Kind | Description |
| --- | --- | --- |
| [`Event`](/modules/events/#tecs.events.Event) | <span class="tealdoc-kind-badge tealdoc-kind-interface">interface</span> | Event names a registered event definition or one of its instances. |
| [`EventInit`](/modules/events/#tecs.events.EventInit) | <span class="tealdoc-kind-badge tealdoc-kind-type">type</span> | EventInit initializes an event instance from constructor arguments. |
| [`EventListener`](/modules/events/#tecs.events.EventListener) | <span class="tealdoc-kind-badge tealdoc-kind-type">type</span> | EventListener synchronously receives an event of its declared type. |
| [`MessageBus`](/modules/events/#tecs.events.MessageBus) | <span class="tealdoc-kind-badge tealdoc-kind-interface">interface</span> | MessageBus routes typed events by integer address. |

## Constructors

<a id="tecs.events.newEvent"></a>
### tecs.events.newEvent <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Configures a table event with a callable constructor.

Registration mutates the supplied definition by assigning its event ID
and constructor metatable. Register each definition once.



```teal
function tecs.events.newEvent<E is Event>(event: E)
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `E` | [`Event`](/modules/events/#tecs.events.Event) |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `event` | `E` | The caller supplies the event record to configure in place. |

#### Returns

None.

<a id="tecs.events.newFFIEvent"></a>
### tecs.events.newFFIEvent <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Configures an FFI event with a callable constructor.

Registration mutates the supplied definition. Field names must be
unique C identifiers. `eventId` and `typeId` are reserved. Use
`double` for entity IDs so their packed slot and generation remain
exact.



```teal
function tecs.events.newFFIEvent<E is Event>(
    event: E, fields: {{string, string}}, structName: string
)
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `E` | [`Event`](/modules/events/#tecs.events.Event) |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `event` | `E` | The caller supplies the event record to configure in place. |
| `fields` | `{{string, string}}` | The caller supplies each field name and C type in constructor order. |
| `structName` | `string` | The caller supplies a shared C struct name or omits it to generate one. |

#### Returns

None.

<a id="tecs.events.newMessageBus"></a>
### tecs.events.newMessageBus <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates an independent address-based event message bus.



```teal
function tecs.events.newMessageBus(): MessageBus
```

#### Arguments

None.

#### Returns

| Type | Description |
| --- | --- |
| [`MessageBus`](/modules/events/#tecs.events.MessageBus) | Returns an empty message bus with no observers. |

## Types

<a id="tecs.events.Event"></a>
### tecs.events.Event <span class="tealdoc-kind-badge tealdoc-kind-interface">interface</span>

`Event` names a registered event definition or one of its instances.


```teal
interface tecs.events.Event
    eventId: integer
end
```

<a id="tecs.events.Event.eventId"></a>
#### tecs.events.Event.eventId <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. The unique ID of the event.


```teal
tecs.events.Event.eventId: integer
```

<a id="tecs.events.EventInit"></a>
### tecs.events.EventInit <span class="tealdoc-kind-badge tealdoc-kind-type">type</span>

`EventInit` initializes an event instance from constructor arguments.


```teal
type tecs.events.EventInit = function<E is Event>(E, ...: any)
```

<a id="tecs.events.EventListener"></a>
### tecs.events.EventListener <span class="tealdoc-kind-badge tealdoc-kind-type">type</span>

`EventListener` synchronously receives an event of its declared type.


```teal
type tecs.events.EventListener = function<E is Event>(E)
```

<a id="tecs.events.MessageBus"></a>
### tecs.events.MessageBus <span class="tealdoc-kind-badge tealdoc-kind-interface">interface</span>

`MessageBus` routes typed events by integer address.


```teal
interface tecs.events.MessageBus
    emit: function<E is Event>(MessageBus, integer, E)
    hasObservers: function<E is Event>(MessageBus, integer, E): boolean
    observeOnce: function<E is Event>(
        MessageBus, integer, E, function(E)
    )
    stopObserving: function<E is Event>(
        MessageBus, integer, E, function(E) | string
    )
    clearAddress: function(self, integer)
    clearEntityObservers: function(self)
    observe: function<E is Event>(
        self,
        address: integer,
        eventType: E,
        observer: function(E),
        id: string
    )
    reset: function(self)
end
```

<a id="tecs.events.MessageBus.emit"></a>
#### tecs.events.MessageBus.emit <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Emit an event to all observers at the specified address.


```teal
function tecs.events.MessageBus.emit<E is Event>(MessageBus, integer, E)
```

##### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `E` | [`Event`](/modules/events/#tecs.events.Event) |  |

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | [`MessageBus`](/modules/events/#tecs.events.MessageBus) |  |
| `#2` | `integer` |  |
| `#3` | `E` |  |

##### Returns

None.

<a id="tecs.events.MessageBus.hasObservers"></a>
#### tecs.events.MessageBus.hasObservers <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Check if any observers exist for an event type at an address.


```teal
function tecs.events.MessageBus.hasObservers<E is Event>(
    MessageBus, integer, E
): boolean
```

##### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `E` | [`Event`](/modules/events/#tecs.events.Event) |  |

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | [`MessageBus`](/modules/events/#tecs.events.MessageBus) |  |
| `#2` | `integer` |  |
| `#3` | `E` |  |

##### Returns

| Type | Description |
| --- | --- |
| `boolean` |  |

<a id="tecs.events.MessageBus.observeOnce"></a>
#### tecs.events.MessageBus.observeOnce <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Observe an event type at a specific address, at most once.


```teal
function tecs.events.MessageBus.observeOnce<E is Event>(
    MessageBus, integer, E, function(E)
)
```

##### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `E` | [`Event`](/modules/events/#tecs.events.Event) |  |

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | [`MessageBus`](/modules/events/#tecs.events.MessageBus) |  |
| `#2` | `integer` |  |
| `#3` | `E` |  |
| `#4` | `function(E)` |  |

##### Returns

None.

<a id="tecs.events.MessageBus.stopObserving"></a>
#### tecs.events.MessageBus.stopObserving <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Stop observing an event type at a specific address.


```teal
function tecs.events.MessageBus.stopObserving<E is Event>(
    MessageBus, integer, E, function(E) | string
)
```

##### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `E` | [`Event`](/modules/events/#tecs.events.Event) |  |

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | [`MessageBus`](/modules/events/#tecs.events.MessageBus) |  |
| `#2` | `integer` |  |
| `#3` | `E` |  |
| `#4` | <code>function(E) &#124; string</code> |  |

##### Returns

None.

<a id="tecs.events.MessageBus.clearAddress"></a>
#### tecs.events.MessageBus:clearAddress <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

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


```teal
function tecs.events.MessageBus.clearAddress(self, integer)
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `MessageBus` |  |
| `#2` | `integer` |  |

##### Returns

None.

<a id="tecs.events.MessageBus.clearEntityObservers"></a>
#### tecs.events.MessageBus:clearEntityObservers <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Clear per-entity observers (every address except the global
address 0), preserving global subscriptions. Used by
world:clearEntities so query infrastructure stays subscribed.


```teal
function tecs.events.MessageBus.clearEntityObservers(self)
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `MessageBus` |  |

##### Returns

None.

<a id="tecs.events.MessageBus.observe"></a>
#### tecs.events.MessageBus:observe <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Observe an event type at a specific address.
Address 0 is for world-level events, entity IDs for entity events.



```teal
function tecs.events.MessageBus.observe<E is Event>(
    self,
    address: integer,
    eventType: E,
    observer: function(E),
    id: string
)
```

##### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `E` | [`Event`](/modules/events/#tecs.events.Event) |  |

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | [`MessageBus`](/modules/events/#tecs.events.MessageBus) | The message bus that owns the subscription. |
| `address` | `integer` | Use 0 for world-level events or an entity ID for entity events. |
| `eventType` | `E` | The registered event type to observe. |
| `observer` | `function(E)` | Called synchronously with each matching event. |
| `id` | `string` | An optional stable name accepted by `stopObserving`. |

##### Returns

None.

<a id="tecs.events.MessageBus.reset"></a>
#### tecs.events.MessageBus:reset <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Reset the entire message bus.


```teal
function tecs.events.MessageBus.reset(self)
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `MessageBus` |  |

##### Returns

None.