Documentation
¶
Index ¶
- Constants
- Variables
- func Alive(ws *worldState, eid EntityID) bool
- func Destroy(ws *worldState, eid EntityID) bool
- func Get[T Component](ws *worldState, eid EntityID) (T, error)
- func Has[T Component](ws *worldState, eid EntityID) bool
- func RegisterSystem[T any](w *World, system System[T], opts ...SystemOption)
- func Remove[T Component](ws *worldState, eid EntityID) error
- func Set[T Component](ws *worldState, eid EntityID, component T) error
- type BaseSystemState
- type Command
- type CommandContext
- type CommandID
- type Component
- type Contains
- type EntityID
- type Event
- type EventKind
- type Exact
- type RawEvent
- type Ref
- type SearchMatch
- type SearchParam
- type System
- type SystemEvent
- type SystemHook
- type SystemOption
- type WithCommand
- type WithEvent
- type WithSystemEventEmitter
- type WithSystemEventReceiver
- type World
- func (w *World) CustomTick(fn func(*worldState))
- func (w *World) Deserialize(data []byte) error
- func (w *World) InitSchedulers()
- func (w *World) InitSystems() error
- func (w *World) NewSearch(params SearchParam) ([]map[string]any, error)
- func (w *World) Serialize() ([]byte, error)
- func (w *World) Tick(commands []micro.Command) ([]RawEvent, error)
Constants ¶
const ( // FieldComponent is the systemStateFieldType for Contains and Exact. FieldComponent systemStateFieldType = iota // FieldSystemEventReceiver is the systemStateFieldType for WithSystemEventReceiver. FieldSystemEventReceiver // FieldSystemEventEmitter is the systemStateFieldType for WithSystemEventEmitter. FieldSystemEventEmitter // FieldBase is the systemStateFieldType for BaseSystemState. FieldBase // FieldEvent is the systemStateFieldType for WithEvent. FieldEvent // FieldCommand is the systemStateFieldType for WithCommand. FieldCommand )
const CustomEventKindStart = 16
const MaxCommandID = math.MaxUint32 - 1
MaxCommandID is the maximum number of command types that can be registered.
Variables ¶
var ( // ErrEntityNotFound is returned when attempting to operate on a non-existent entity // or when an entity cannot be found in the expected location. ErrEntityNotFound = eris.New("entity does not exist") // ErrComponentNotFound is returned when attempting to operate on a component that isn't // registered (used) in any systems. ErrComponentNotFound = eris.New("component is not registered") )
Functions ¶
func Destroy ¶
Destroy deletes an entity and all its components from the world. Returns true if the entity is deleted, false otherwise.
func Get ¶
Get gets a component from an entity. Returns an error if the entity doesn't exist or doesn't contain the component type.
func Has ¶
Has checks if an entity has a specific component type. Returns false if either the entity doesn't exist or doesn't have the component.
func RegisterSystem ¶
func RegisterSystem[T any](w *World, system System[T], opts ...SystemOption)
Types ¶
type BaseSystemState ¶
type BaseSystemState struct {
// contains filtered or unexported fields
}
BaseSystemState is a barebones system state field that can be embedded in your custom system state types to allow your systems to access the world state. It provides a raw event emitter that can be used to emit custom events.
Example:
// Define your system state by embedding BaseState.
type DebugSystemState struct {
ecs.BaseSystemState
// Other fields...
}
// Your system function receives a pointer to your system state.
func DebugSystem(state *DebugSystemState) error {
state.EmitRawEvent(EventKindCustom, "my custom event")
return nil
}
func (*BaseSystemState) EmitRawEvent ¶
func (b *BaseSystemState) EmitRawEvent(kind EventKind, payload any)
EmitRawEvent emits a raw event to the world with the given event kind and payload.
func (*BaseSystemState) UnsafeWorldState ¶
func (b *BaseSystemState) UnsafeWorldState() *worldState
UnsafeWorldState returns a pointer to the world's underlying state. Use this only when you know what you're doing as it's possible to mess up the world state.
type Command ¶
type Command interface {
micro.ShardCommand
}
Command is the interface that all commands must implement. Commands are predefined user actions that are handled by systems.
type CommandContext ¶
type CommandContext[T Command] struct { // contains filtered or unexported fields }
CommandContext wraps a micro.Command and provides typed access to command data and metadata.
func (CommandContext[T]) Payload ¶
func (c CommandContext[T]) Payload() T
Payload returns the strongly-typed command payload.
func (CommandContext[T]) Persona ¶
func (c CommandContext[T]) Persona() string
Persona returns the persona (sender) of the command.
type Component ¶
type Component interface {
// Name returns a unique string identifier for the component type.
// This should be consistent across program executions.
Name() string
}
Component is the interface that all components must implement. Components are pure data containers that can be attached to entities.
type Contains ¶
type Contains[T any] struct { // contains filtered or unexported fields }
Contains provides a search that matches archetypes containing all specified component types, potentially along with additional components.
Example:
type MovementSystemState struct {
Movers ecs.Contains[struct {
Position ecs.Ref[Position]
Velocity ecs.Ref[Velocity]
}]
// Other fields...
}
// Your system function receives a pointer to your system state.
func MovementSystem(state *MovementSystemState) error {
for entity, mover := range state.Movers.Iter() {
// Process entity and compnents.
}
return nil
}
func (*Contains) Create ¶
func (s *Contains) Create() (EntityID, T)
Create creates a new entity with the given components. Returns an error if any of the components are not defined in the search field.
This is the recommended system-friendly alternative to ecs.Create() for creating entities within systems.
Example:
entity, err := state.Mob.Create(Health{Value: 100}, Position{X: 0, Y: 0})
if err != nil {
state.Logger().Error().Err(err).Msg("Failed to create entity")
}
// Use entity...
func (*Contains) Destroy ¶
Destroy deletes an entity and all its components from the world.
This is the recommended system-friendly alternative to ecs.Destroy() for destroying entities within systems.
type Event ¶
type Event = Command
Event is an interface that all events must implement. Events are packets of information that are sent from systems to the outside world.
type EventKind ¶
type EventKind uint8
EventKind is a type that represents the kind of event.
const ( // EventKindDefault is the default event kind. EventKindDefault EventKind = 1 )
type Exact ¶
type Exact[T any] struct { // contains filtered or unexported fields }
Exact provides a search that matches archetypes containing exactly the specified component types, without any additional components.
Example:
type PlayerSystemState struct {
Players ecs.Exact[struct {
Tag ecs.Ref[PlayerTag]
Health ecs.Ref[Health]
}]
// Other fields...
}
// Your system function receives a pointer to your system state.
func PlayerSystem(state *PlayerSystemState) error {
for entity, player := range state.Players.Iter() {
// Process entity and compnents.
}
return nil
}
func (*Exact) Create ¶
func (s *Exact) Create() (EntityID, T)
Create creates a new entity with the given components. Returns an error if any of the components are not defined in the search field.
This is the recommended system-friendly alternative to ecs.Create() for creating entities within systems.
Example:
entity, err := state.Mob.Create(Health{Value: 100}, Position{X: 0, Y: 0})
if err != nil {
state.Logger().Error().Err(err).Msg("Failed to create entity")
}
// Use entity...
type RawEvent ¶
type RawEvent struct {
Kind EventKind // The kind of event
Payload any // The payload of the event
}
RawEvent is the format of ECS output. It has a kind and a payload. The kind determines the type of event contained in the payload. Users of ECS can define custom event kinds and handle them in their own event handlers.
type Ref ¶
type Ref[T Component] struct { // contains filtered or unexported fields }
Ref provides a type-safe handle to a component on an entity.
func (*Ref[T]) Get ¶
func (r *Ref[T]) Get() T
Get retrieves the component value for this Ref's entity.
This is the recommended system-friendly alternative to ecs.Get() for accessing components within systems.
Example:
for _, player := range state.Players.Iter() {
health := player.Health.Get()
}
func (*Ref[T]) Set ¶
func (r *Ref[T]) Set(component T)
Set updates the component value for this Ref's entity.
This is the recommended system-friendly alternative to ecs.Set() for modifying components within systems.
Example:
for _, player := range state.Players.Iter() {
player.Health.Set(Health{HP: 100})
}
type SearchMatch ¶
type SearchMatch string
SearchMatch is the type of match to use for the search.
const ( // MatchExact matches entities that have exactly the specified components. MatchExact SearchMatch = "exact" // MatchContains matches entities that contains the specified components, but may have other // components as well. MatchContains SearchMatch = "contains" )
type SearchParam ¶
type SearchParam struct {
Find []string // List of component names to search for
Match SearchMatch // A match type to use for the search
Where string // Optional expr language string to filter the results.
}
SearchParam contains paramters for a search query. We use expr lang for the where clause to filter the entities, please refer to its documentation for more details: https://expr-lang.org/docs/getting-started.
type SystemEvent ¶
type SystemEvent = Command
SystemEvent is an interface that all system events must implement. SystemEvents are events emitted by a system to be handled by another system.
type SystemHook ¶
type SystemHook uint8
SystemHook defines when a system should be executed in the update cycle.
const ( // PreUpdate runs before the main update. PreUpdate SystemHook = 0 // Update runs during the main update phase. Update SystemHook = 1 // PostUpdate runs after the main update. PostUpdate SystemHook = 2 // Init runs once during world initialization. Init SystemHook = 3 )
type SystemOption ¶
type SystemOption func(*systemConfig)
SystemOption is a function that configures a SystemConfig.
func WithHook ¶
func WithHook(hook SystemHook) SystemOption
WithHook returns an option to set the system hook.
func WithModifier ¶
func WithModifier(fieldType systemStateFieldType, fn func(any) error) SystemOption
WithModifier returns an option to set a modifier for a specific field type.
type WithCommand ¶
type WithCommand[T Command] struct { // contains filtered or unexported fields }
WithCommand is a generic system state field that allows systems to receive commands of type T. The commands are automatically registered when the system is registered.
Example:
// Define a command type for spawning players.
type SpawnPlayer struct{ Nickname string }
func (SpawnPlayer) Name() string { return "spawn-player" }
// Define your system state.
type SpawnSystemState struct {
SpawnPlayerCommands ecs.WithCommand[SpawnPlayer]
// Other fields...
}
// Your system function receives a pointer to your system state.
func SpawnSystem(state *SpawnSystemState) error {
for cmd := range state.SpawnPlayerCommands.Iter() {
persona := cmd.Persona()
spawnData := cmd.Payload()
// Process spawn commands based on persona and payload.
}
return nil
}
func (*WithCommand[T]) Iter ¶
func (m *WithCommand[T]) Iter() iter.Seq[CommandContext[T]]
Iter returns an iterator over all commands of type T.
Example usage:
for cmd := range state.SpawnPlayerCommands.Iter() {
persona := cmd.Persona()
payload := cmd.Payload()
// Process each command
}
type WithEvent ¶
type WithEvent[T Event] struct { // contains filtered or unexported fields }
WithEvent is a generic system state field that allows systems to emit events of type T.
Example:
// Define an event type for level ups.
type LevelUp struct{ Nickname string }
func (LevelUp) Name() string { return "level-up" }
type LevelUpSystemState struct {
LevelUpEvents ecs.WithEvent[LevelUp]
// Other fields...
}
// Your system function receives a pointer to your system state.
func LevelUpSystem(state *LevelUpSystemState) error {
// Emit a level up event.
state.LevelUpEvents.Emit(LevelUp{Nickname: "Player1"})
return nil
}
type WithSystemEventEmitter ¶
type WithSystemEventEmitter[T SystemEvent] struct { // contains filtered or unexported fields }
WithSystemEventEmitter is a generic system state field that allows systems to emit system events of type T. System events are automatically registered when the system is registered.
Example:
// Define a system event for player deaths.
type PlayerDeath struct{ Nickname string }
func (PlayerDeath) Name() string { return "player-death" }
type CombatSystemState struct {
PlayerDeathSystemEvents ecs.WithSystemEventEmitter[PlayerDeath]
// Other fields...
}
// Your system function receives a pointer to your system state.
func CombatSystem(state *CombatSystemState) error {
// Emit a player death event to be handled in another system.
state.PlayerDeathEvents.Emit(PlayerDeath{Nickname: "Player1"})
return nil
}
func (*WithSystemEventEmitter[T]) Emit ¶
func (s *WithSystemEventEmitter[T]) Emit(systemEvent T)
Emit emits a system event of type T.
Example:
state.PlayerDeathEvents.Emit(PlayerDeath{Nickname: "Player1"})
type WithSystemEventReceiver ¶
type WithSystemEventReceiver[T SystemEvent] struct { // contains filtered or unexported fields }
WithSystemEventReceiver is a generic system state field that allows systems to receive system events of type T. System events are automatically registered when the system is registered.
Example:
// Define a system event for player deaths.
type PlayerDeath struct{ Nickname string }
func (PlayerDeath) Name() string { return "player-death" }
type GraveyardSystemState struct {
PlayerDeathSystemEvents ecs.WithSystemEventReceiver[PlayerDeath]
// Other fields...
}
// Your system function receives a pointer to your system state.
func GraveyardSystem(state *GraveyardSystemState) error {
// Receive system events emitted from another system.
for systemEvent := range state.PlayerDeathSystemEvents.Iter() {
// Process the system event.
}
return nil
}
func (*WithSystemEventReceiver[T]) Iter ¶
func (s *WithSystemEventReceiver[T]) Iter() iter.Seq[T]
Iter returns an iterator over all system events of type T.
Example usage:
for systemEvent := range state.PlayerDeathEvents.Iter() {
// Process each system event
}
type World ¶
type World struct {
// contains filtered or unexported fields
}
World represents the root ECS state with double buffering support.
func (*World) CustomTick ¶
func (w *World) CustomTick(fn func(*worldState))
CustomTick allows for a custom update function to be run instead of the registered systems. This function is for testing and internal use only!
func (*World) Deserialize ¶
Deserialize populates the World's state from a byte slice. This should only be called after the World has been properly initialized with components registered.
func (*World) InitSchedulers ¶
func (w *World) InitSchedulers()
InitSchedulers initializes the system schedulers by creating their schedules.
func (*World) InitSystems ¶
InitSystems runs all registered init systems.
func (*World) NewSearch ¶
func (w *World) NewSearch(params SearchParam) ([]map[string]any, error)
NewSearch returns a map of entities that match the given search parameters.
func (*World) Serialize ¶
Serialize converts the World's state to a byte slice for serialization. Only serializes the WorldState as components, systems, and managers are recreated on startup.
func (*World) Tick ¶
Tick passes external events into the event manager and executes the registered systems in order. If any system returns an error, the entire tick is considered failed, changes are discarded, and the error is returned. If the tick succeeds, the events emmitted during the tick is returned.