Skip to main content
System events are how systems communicate with each other inside a single shard. They are internal messages that one system emits and other systems receive during the same tick. Unlike events, which are broadcast to game clients, system events never leave the server. They’re useful for decoupling systems that need to react to each other’s logic. System events are scoped to a single tick: they’re produced and consumed within the tick, then cleared.

Defining System Events

System events are plain Go structs that implement the SystemEvent interface. This interface requires a single Name() method that returns a unique string identifier:

Using System Events

Just like with components and commands, you must declare the system events a system can access in its state struct.

Emitting System Events

Add a cardinal.WithSystemEventEmitter[T] field to your system state type, where T is your system event type:
Use Emit to send a system event:
A system cannot have multiple WithSystemEventEmitter fields with the same system event type.

Receiving System Events

Add a cardinal.WithSystemEventReceiver[T] field to your system state type:
Use Iter to loop through all system events of that type received this tick:
A system cannot have multiple WithSystemEventReceiver fields with the same system event type. However, different systems can receive the same system event type.

Scheduling and Ordering

Systems run in the order they are registered. To ensure emitters run before receivers, register emitting systems first:
If a receiver runs before its emitter, it will not receive any system events for that tick, as they haven’t been emitted yet. Multiple systems can receive the same system event type, and they will each get all events emitted that tick.