# ecs

`import "github.com/matjam/bunyip/ecs"`

Package ecs is the engine's entity component system. Entities are cheap handles, components are plain Go structs stored in dense per-type columns, and queries iterate every entity carrying a set of components with no lookups in the loop.

Storage is by archetype. Every distinct set of component types gets a table with one column per type, and an entity lives in exactly one table. Adding or removing a component moves the entity to another table, so structural changes cost a copy, while iterating a hundred thousand entities reads a few slices in order.

	w := ecs.NewWorld()
	e := w.SpawnWith(Position{1, 2}, Velocity{0.5, 0})
	q := w.Query2[Position, Velocity]()
	q.Each(func(e ecs.Entity, p *Position, v *Velocity) {
		p.X += v.X
	})

Systems are functions registered on the world and run in order by Update. Resources are singletons such as the score or the rules. Events are per-Update queues that carry values between systems; Update clears them before running the first system.

### Query lifetime and mutation {#hdr-Query_lifetime_and_mutation}

Query callbacks receive pointers into component storage. Use them before a structural change touches their table; do not retain them across frames. Rows are visited last to first and matched table lengths are captured at the start of a walk. The currently visited entity may be restructured or despawned, but changes to other entities must be deferred with World.Defer or an explicit Commands buffer. Despawning a parent also removes its children, so defer that operation. Do not nest a walk of the same query within its callback. The world's Each methods share a cached query per world and ordered component set, so nesting the same helper and component set has the same restriction. Worlds and their queries require externally serialized access.

### Persistence and scenes {#hdr-Persistence_and_scenes}

Worlds save and load as JSON. Register names each component and resource type so files stay valid across builds. Save writes every live entity, its parent links and the registered resources, and Load recreates them with fresh handles, rewriting the Entity fields inside components. A Prefab is a template of components (and child prefabs) that spawns independent copies. Clone and CloneTree copy an entity that already exists.

A Scene is a JSON document of entities to spawn as a unit: a level, a room, a squad. Instantiate spawns a copy and returns a SceneInstance that finds its entities by name and despawns them again, so several copies live side by side; ExportScene captures live entities back into a document. A scene entity may reference a prefab from a PrefabLibrary and override its components.

## Variables

<a id="None"></a>

```go
var None = Entity{}
```

None is the absent entity.

## Functions

<a id="NameOf"></a>

### NameOf

```go
func NameOf(w *World, e Entity) (string, bool)
```

NameOf returns the entity's name, and false when it has none or the name is empty.

<a id="Register"></a>

### Register

```go
func Register[T any](name string)
```

Register names a component or resource type for Save, Load and prefab files. The name is what the file holds, so choose one that stays stable when the type moves or is renamed. Registering the same type under the same name again does nothing; binding a name or a type that is already bound to something else panics. gfx.Transform, gfx.Transform2 and ecs.Name are registered under those names by default. A registered type is also stored in typed columns when it first reaches a world through SpawnWith, Load or a prefab, so spawning it that way costs the same as through Add.

<a id="SetParent"></a>

### SetParent

```go
func SetParent(w *World, child, parent Entity)
```

SetParent attaches child under parent, or detaches it with None. A child follows its parent's transform (see WorldMatrix) and is despawned with it. A missing parent detaches the child. Self-parenting is ignored; an attempted longer cycle detaches the child from its old parent.

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
	"github.com/matjam/bunyip/gfx"
	"github.com/matjam/bunyip/lin"
)

func main() {
	// A turret on a tank: the turret's transform is relative to the tank.
	w := ecs.NewWorld()
	tank := w.SpawnWith(gfx.At(10, 0, 0))
	turret := w.SpawnWith(gfx.At(0, 1, 0))
	ecs.SetParent(w, turret, tank)
	fmt.Println(ecs.WorldMatrix(w, turret).MulPoint(lin.Vec3{}))
	w.Despawn(tank) // children go with their parent
	fmt.Println(w.Alive(turret))
}
```

Output:

```
{10 1 0}
false
```

<a id="UpdateWorldMatrices"></a>

### UpdateWorldMatrices

```go
func UpdateWorldMatrices(w *World)
```

UpdateWorldMatrices composes every entity's world matrix in one walk from the roots down and caches the results, so WorldMatrix costs a slice index instead of a climb up the parent chain. Call it from a system after the ones that move transforms and before the ones that read world positions. The cache lasts until the next World.Update, so Draw reads what the last Update left; spawning, changing a parent link or despawning drops it, and a transform written after the pass is not seen until the pass runs again.

<a id="WorldMatrix"></a>

### WorldMatrix

```go
func WorldMatrix(w *World, e Entity) lin.Mat4
```

WorldMatrix composes the gfx.Transform components from the root down to e; entities without one contribute identity. When UpdateWorldMatrices has run in this update the cached matrix is returned instead of walking the chain.

## Types

<a id="Children"></a>

<a id="Children.List"></a>

### Children

```go
type Children struct{ List []Entity }
```

Children lists an entity's direct children; SetParent maintains it.

<a id="Commands"></a>

### Commands

```go
type Commands struct {
	// contains filtered or unexported fields
}
```

Commands record structural changes to apply later with Apply, for code running inside a query that must not change other entities' tables mid-iteration. The zero value is ready to use. Component values passed to Spawn and Add are retained until Apply, not deep-copied; do not mutate their referenced storage before then. The argument slice itself is copied, so it may be reused at once. World.Defer manages a command buffer for a single closure.

<a id="Commands.Add"></a>

#### Commands.Add

```go
func (c *Commands) Add(e Entity, comps ...any)
```

Add records attaching component values to an entity.

<a id="Commands.Apply"></a>

#### Commands.Apply

```go
func (c *Commands) Apply(w *World)
```

Apply runs the recorded changes in order and clears the buffer.

<a id="Commands.Despawn"></a>

#### Commands.Despawn

```go
func (c *Commands) Despawn(e Entity)
```

Despawn records removing an entity.

<a id="Commands.Len"></a>

#### Commands.Len

```go
func (c *Commands) Len() int
```

Len is the number of pending commands.

<a id="Commands.Remove"></a>

#### Commands.Remove

```go
func (c *Commands) Remove[T any](e Entity)
```

Remove records detaching a T from an entity, the deferred form of World.Remove. Commands apply when their scope finishes or Apply is called.

<a id="Commands.Spawn"></a>

#### Commands.Spawn

```go
func (c *Commands) Spawn(comps ...any)
```

Spawn records creating an entity with components.

<a id="ComponentID"></a>

### ComponentID

```go
type ComponentID uint16
```

ComponentID numbers a component type within a world.

<a id="Entity"></a>

### Entity

```go
type Entity struct {
	// contains filtered or unexported fields
}
```

Entity identifies a thing in a World. The zero Entity is None. A handle from a despawned entity is never confused with a new one that reused its slot.

<a id="ChildrenOf"></a>

#### ChildrenOf

```go
func ChildrenOf(w *World, e Entity) []Entity
```

ChildrenOf returns the entity's direct children; do not modify the slice.

<a id="Clone"></a>

#### Clone

```go
func Clone(w *World, e Entity) Entity
```

Clone makes a new entity carrying copies of e's components, attached to e's parent. Children are not copied; CloneTree does that. Entity fields that referred to e refer to the copy.

The copy is deep through exported fields: slices, maps, pointers and interface values get their own storage. Unexported fields are copied as values, so a slice or pointer in one is shared with the original. Custom JSON methods are not used for cloning. Remapper handles entity references, not general deep copying; initialize private mutable state separately when it must be independent in the clone.

<a id="CloneTree"></a>

#### CloneTree

```go
func CloneTree(w *World, e Entity) Entity
```

CloneTree clones e and all its descendants, keeping the hierarchy between the copies and attaching the root copy to e's parent. Entity fields that referred to something in the tree refer to its copy; references outside the tree are kept as they are.

<a id="ParentOf"></a>

#### ParentOf

```go
func ParentOf(w *World, e Entity) (Entity, bool)
```

ParentOf returns the entity's parent, if it has one.

<a id="SceneRef"></a>

#### SceneRef

```go
func SceneRef(n int) Entity
```

SceneRef returns the value to put in a component's Entity field to refer to the entity numbered n in a scene, counting from one. Instantiate rewrites it to the handle that entity was given. A number of zero, or one no entity has, is None.

<a id="Entity.ID"></a>

#### Entity.ID

```go
func (e Entity) ID() uint64
```

ID combines the slot and generation, for debugging and maps. It is unique among live entities within one world, not across worlds.

<a id="Entity.MarshalJSON"></a>

#### Entity.MarshalJSON

```go
func (e Entity) MarshalJSON() ([]byte, error)
```

MarshalJSON encodes the entity as its ID, so components and resources holding entities save and load with encoding/json. Load rewrites the IDs to the handles it creates.

<a id="Entity.MarshalText"></a>

#### Entity.MarshalText

```go
func (e Entity) MarshalText() ([]byte, error)
```

MarshalText encodes the entity as its ID, for use as a map key.

<a id="Entity.String"></a>

#### Entity.String

```go
func (e Entity) String() string
```

String formats the entity as index and generation.

<a id="Entity.UnmarshalJSON"></a>

#### Entity.UnmarshalJSON

```go
func (e *Entity) UnmarshalJSON(b []byte) error
```

UnmarshalJSON decodes an entity written by MarshalJSON.

<a id="Entity.UnmarshalText"></a>

#### Entity.UnmarshalText

```go
func (e *Entity) UnmarshalText(b []byte) error
```

UnmarshalText decodes an entity written by MarshalText.

<a id="Entity.Valid"></a>

#### Entity.Valid

```go
func (e Entity) Valid() bool
```

Valid reports whether the handle is nonzero. It does not check whether the entity is still alive; use World.Alive for that.

<a id="Filter"></a>

### Filter

```go
type Filter func(w *World, incl, excl *mask)
```

Filter narrows a query beyond the components it reads.

<a id="With"></a>

#### With

```go
func With[T any]() Filter
```

With requires entities to carry T without reading it.

<a id="Without"></a>

#### Without

```go
func Without[T any]() Filter
```

Without excludes entities carrying T.

<a id="InstantiateOptions"></a>

<a id="InstantiateOptions.Prefabs"></a>

<a id="InstantiateOptions.Parent"></a>

<a id="InstantiateOptions.Offset"></a>

<a id="InstantiateOptions.SkipUnknown"></a>

### InstantiateOptions

```go
type InstantiateOptions struct {
	// Prefabs resolves the scene's prefab references. The zero value
	// falls back to the world's PrefabLibrary resource.
	Prefabs PrefabLibrary
	// Parent hangs every root of the instance under this entity, which
	// is how a level goes under a container or a room under a floor.
	// The zero value, None, leaves the roots unparented.
	Parent Entity
	// Offset moves each root of the instance by this much, added to the
	// position in its gfx.Transform or gfx.Transform2. A root with
	// neither component is not moved. The zero value moves nothing.
	Offset lin.Vec3
	// SkipUnknown leaves out components stored under a name this build
	// has not registered instead of failing with UnregisteredError.
	SkipUnknown bool
}
```

InstantiateOptions adjust World.Instantiate.

<a id="LoadOptions"></a>

<a id="LoadOptions.SkipUnknown"></a>

### LoadOptions

```go
type LoadOptions struct {
	// SkipUnknown leaves out components and resources saved under a
	// name this build has not registered instead of failing with
	// UnregisteredError.
	SkipUnknown bool
}
```

LoadOptions adjust World.Load.

<a id="MissingPrefabError"></a>

<a id="MissingPrefabError.Name"></a>

### MissingPrefabError

```go
type MissingPrefabError struct{ Name string }
```

MissingPrefabError reports a scene reference to a prefab the library does not hold, or holds as nil. Name is the name the scene asked for.

<a id="MissingPrefabError.Error"></a>

#### MissingPrefabError.Error

```go
func (e *MissingPrefabError) Error() string
```

Error identifies the unresolved prefab name.

<a id="Name"></a>

<a id="Name.Text"></a>

### Name

```go
type Name struct{ Text string }
```

Name labels an entity so a scene can find it again. Instantiate adds one to every entity its scene names, and ExportScene writes it back as the scene entity's name instead of as a component. The zero value is the empty name, which no lookup matches.

<a id="Parent"></a>

<a id="Parent.Entity"></a>

### Parent

```go
type Parent struct{ Entity Entity }
```

Parent links an entity under another; SetParent maintains it.

<a id="Prefab"></a>

### Prefab

```go
type Prefab struct {
	// contains filtered or unexported fields
}
```

Prefab is a template of components, with child prefabs for a hierarchy, that Spawn stamps into a world any number of times. Build one in code with NewPrefab and Child, read one from JSON with ParsePrefab, or take one from a live entity with PrefabOf.

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
	"github.com/matjam/bunyip/gfx"
)

type Position struct{ X, Y float32 }

type Health struct{ HP int }

func main() {
	// A template spawns as many independent copies as the game needs.
	tank := ecs.NewPrefab(Position{0, 0}, Health{10}).
		Child(ecs.NewPrefab(gfx.At(0, 1, 0))) // the turret
	w := ecs.NewWorld()
	a := tank.Spawn(w)
	b := tank.Spawn(w)
	if h, ok := w.Get[Health](a); ok {
		h.HP = 3
	}
	hb, _ := w.Get[Health](b)
	fmt.Println(hb.HP, len(ecs.ChildrenOf(w, a)), w.Len())
}
```

Output:

```
10 1 4
```

<a id="NewPrefab"></a>

#### NewPrefab

```go
func NewPrefab(comps ...any) *Prefab
```

NewPrefab makes a prefab from component values. Pointers are refused; pass the struct.

<a id="ParsePrefab"></a>

#### ParsePrefab

```go
func ParsePrefab(data []byte) (*Prefab, error)
```

ParsePrefab reads a prefab from JSON. The form is an object with a "components" object keyed by registered name, each value encoded as in a save file, and an optional "children" array of the same form. An unregistered name is an UnregisteredError.

<a id="PrefabOf"></a>

#### PrefabOf

```go
func PrefabOf(w *World, e Entity) *Prefab
```

PrefabOf snapshots an entity and its descendants as a prefab, leaving out Parent and Children. Spawning it gives a copy of the tree.

<a id="Prefab.Child"></a>

#### Prefab.Child

```go
func (p *Prefab) Child(children ...*Prefab) *Prefab
```

Child adds child prefabs, spawned under the instance with SetParent, and returns the prefab for chaining.

<a id="Prefab.Children"></a>

#### Prefab.Children

```go
func (p *Prefab) Children() []*Prefab
```

Children returns the prefab's child prefabs; do not modify the slice.

<a id="Prefab.Components"></a>

#### Prefab.Components

```go
func (p *Prefab) Components() []any
```

Components returns copies of the prefab's component values.

<a id="Prefab.MarshalJSON"></a>

#### Prefab.MarshalJSON

```go
func (p Prefab) MarshalJSON() ([]byte, error)
```

MarshalJSON writes the prefab in the form ParsePrefab reads. A component type without a registered name is an UnregisteredError.

<a id="Prefab.Spawn"></a>

#### Prefab.Spawn

```go
func (p *Prefab) Spawn(w *World) Entity
```

Spawn creates an entity from the prefab, and its children under it. Every instance gets its own copy of the components (see Clone for how deep the copy goes), so changing one does not change the others or the prefab.

<a id="Prefab.UnmarshalJSON"></a>

#### Prefab.UnmarshalJSON

```go
func (p *Prefab) UnmarshalJSON(data []byte) error
```

UnmarshalJSON reads the form MarshalJSON writes.

<a id="PrefabLibrary"></a>

### PrefabLibrary

```go
type PrefabLibrary map[string]*Prefab
```

PrefabLibrary holds prefabs under the names scene documents reference. Build one at start-up and either pass it in InstantiateOptions or store it on the world with SetResource, which is where Instantiate looks when the options carry none. The zero value is an empty library, and every reference into it is a MissingPrefabError.

<a id="Query1"></a>

### Query1

```go
type Query1[A any] struct {
	// contains filtered or unexported fields
}
```

Query1 iterates entities with an A.

<a id="Query1.Count"></a>

#### Query1.Count

```go
func (q *Query1[A]) Count() int
```

Count is the number of matching entities.

<a id="Query1.Each"></a>

#### Query1.Each

```go
func (q *Query1[A]) Each(fn func(e Entity, a *A))
```

Each calls fn for every matching entity. The package's query lifetime and mutation rules apply; do not recursively walk this query from fn.

<a id="Query1.First"></a>

#### Query1.First

```go
func (q *Query1[A]) First() (Entity, *A, bool)
```

First returns one matching entity, if any, in unspecified order. Its component pointer has the same storage lifetime as a pointer from Get.

<a id="Query2"></a>

### Query2

```go
type Query2[A, B any] struct {
	// contains filtered or unexported fields
}
```

Query2 iterates entities with an A and a B.

<a id="Query2.Count"></a>

#### Query2.Count

```go
func (q *Query2[A, B]) Count() int
```

Count is the number of matching entities.

<a id="Query2.Each"></a>

#### Query2.Each

```go
func (q *Query2[A, B]) Each(fn func(e Entity, a *A, b *B))
```

Each calls fn for every matching entity. The package's query lifetime and mutation rules apply; do not recursively walk this query from fn.

<a id="Query3"></a>

### Query3

```go
type Query3[A, B, C any] struct {
	// contains filtered or unexported fields
}
```

Query3 iterates entities with an A, a B and a C.

<a id="Query3.Count"></a>

#### Query3.Count

```go
func (q *Query3[A, B, C]) Count() int
```

Count is the number of matching entities.

<a id="Query3.Each"></a>

#### Query3.Each

```go
func (q *Query3[A, B, C]) Each(fn func(e Entity, a *A, b *B, c *C))
```

Each calls fn for every matching entity. The package's query lifetime and mutation rules apply; do not recursively walk this query from fn.

<a id="Query4"></a>

### Query4

```go
type Query4[A, B, C, D any] struct {
	// contains filtered or unexported fields
}
```

Query4 iterates entities with four components.

<a id="Query4.Count"></a>

#### Query4.Count

```go
func (q *Query4[A, B, C, D]) Count() int
```

Count is the number of matching entities.

<a id="Query4.Each"></a>

#### Query4.Each

```go
func (q *Query4[A, B, C, D]) Each(fn func(e Entity, a *A, b *B, c *C, d *D))
```

Each calls fn for every matching entity. The package's query lifetime and mutation rules apply; do not recursively walk this query from fn.

<a id="Remapper"></a>

<a id="Remapper.Remap"></a>

### Remapper

```go
type Remapper interface {
	Remap(fn func(Entity) Entity)
}
```

Remapper is implemented by components and resources that hold entities somewhere Load and CloneTree cannot see: unexported fields, or values behind an interface they should not rewrite. Remap replaces every entity the value holds with fn of it. A type without Remap has its exported fields walked with reflection instead, which covers Entity fields, slices, arrays, maps and pointers of them.

<a id="SaveOptions"></a>

<a id="SaveOptions.SkipUnregistered"></a>

<a id="SaveOptions.Indent"></a>

### SaveOptions

```go
type SaveOptions struct {
	// SkipUnregistered leaves out components and resources whose type
	// has no registered name instead of failing with UnregisteredError.
	SkipUnregistered bool
	// Indent writes the file with line breaks and indentation.
	Indent bool
}
```

SaveOptions adjust World.Save.

<a id="Scene"></a>

<a id="Scene.Name"></a>

<a id="Scene.Properties"></a>

<a id="Scene.Entities"></a>

### Scene

```go
type Scene struct {
	// Name labels the scene. It is written to the document and read
	// back; nothing else uses it. The zero value is no name.
	Name string
	// Properties are the game's own values, such as the music track or
	// the wave number. They are encoded with the scene and come back
	// decoded by encoding/json, so a number arrives as a float64. The
	// zero value is no properties.
	Properties map[string]any
	// Entities are the entities the scene spawns, in the order
	// Instantiate creates them. The zero value is an empty scene.
	Entities []SceneEntity
	// contains filtered or unexported fields
}
```

Scene is a document of entities a world spawns as a unit: a name, free-form properties for the game's own use, and a list of entities with their components, parent links and prefab references. Read one with ParseScene, build one with NewScene, take one from a live world with World.ExportScene, and spawn it with World.Instantiate.

Entities are numbered from one in Entities order. SceneEntity.Parent holds that number, and so does an Entity field inside a component, so zero means no parent and the None entity in both places.

<a id="NewScene"></a>

#### NewScene

```go
func NewScene(name string) *Scene
```

NewScene makes an empty scene with a name.

<a id="ParseScene"></a>

#### ParseScene

```go
func ParseScene(data []byte) (*Scene, error)
```

ParseScene reads a scene document: a JSON object with a "version" of 1, an optional "name" and "properties", and an "entities" array. Each entity has an optional "name", an optional "parent" holding another entity's number counted from one, an optional "prefab" naming a prefab in the library Instantiate uses, and a "components" object keyed by registered name with each value encoded as a save file encodes it.

A version other than 1, a parent outside the scene or in a cycle, and two entities with the same name are all errors. Component names are checked by Instantiate, not here, so a scene parses in a build that has not registered every type in it.

<a id="Scene.AddEntity"></a>

#### Scene.AddEntity

```go
func (s *Scene) AddEntity(name string, comps ...any) (int, error)
```

AddEntity appends an entity carrying the component values and returns its number, its place in the scene counted from one. Pass an empty name for an entity nothing needs to find again. Each component is encoded the way World.Save encodes it, so its type needs a name from Register; a type without one is an UnregisteredError and nothing is added. Use SceneRef for an Entity field that points at another entity of the scene.

<a id="Scene.AddPrefab"></a>

#### Scene.AddPrefab

```go
func (s *Scene) AddPrefab(name, prefab string, overrides ...any) (int, error)
```

AddPrefab appends an entity built from the library prefab called prefab and returns its number. Each override replaces the prefab's whole component of that type rather than merging field by field, and the prefab's children spawn as they are. Instantiate fails with a MissingPrefabError when its library has no prefab of that name.

<a id="Scene.Encode"></a>

#### Scene.Encode

```go
func (s *Scene) Encode() ([]byte, error)
```

Encode writes the scene as the document ParseScene reads, indented so it stays readable in a text editor and useful in version control. A scene whose parent links are out of range or circular, or that names two entities the same, is an error.

<a id="Scene.SetParent"></a>

#### Scene.SetParent

```go
func (s *Scene) SetParent(child, parent int)
```

SetParent hangs the entity numbered child under the entity numbered parent, both counted from one. A parent of zero makes the child a root. A number outside the scene, or a child equal to its parent, is ignored.

<a id="Scene.SetProperty"></a>

#### Scene.SetProperty

```go
func (s *Scene) SetProperty(key string, v any)
```

SetProperty stores a free-form value under key for the game's own use. It is encoded with the scene and comes back decoded by encoding/json, so a number arrives as a float64.

<a id="SceneEntity"></a>

<a id="SceneEntity.Name"></a>

<a id="SceneEntity.Parent"></a>

<a id="SceneEntity.Prefab"></a>

<a id="SceneEntity.Components"></a>

### SceneEntity

```go
type SceneEntity struct {
	// Name labels the entity for SceneInstance.Entity and becomes a
	// Name component on the spawned entity. Names are unique within a
	// scene. The zero value leaves the entity unnamed.
	Name string `json:"name,omitempty"`
	// Parent is the number of the entity this one hangs under, counted
	// from one in Scene.Entities order. The zero value makes it a root
	// of the scene.
	Parent int `json:"parent,omitempty"`
	// Prefab names a prefab in the library Instantiate uses. The zero
	// value builds the entity from Components alone; otherwise the
	// prefab is spawned and each entry of Components replaces the
	// prefab's whole component of that type.
	Prefab string `json:"prefab,omitempty"`
	// Components holds each component encoded the way World.Save
	// encodes it, keyed by the name Register gave its type. The zero
	// value is no components.
	Components map[string]json.RawMessage `json:"components,omitempty"`
}
```

SceneEntity is one entity of a Scene.

<a id="SceneInstance"></a>

<a id="SceneInstance.Roots"></a>

<a id="SceneInstance.Spawned"></a>

### SceneInstance

```go
type SceneInstance struct {
	// Roots are the entities the scene left unparented, in scene order.
	// With InstantiateOptions.Parent they hang under that entity.
	Roots []Entity
	// Spawned lists every entity the copy created, in scene order, with
	// a prefab's children after the entity that referenced it.
	Spawned []Entity
	// contains filtered or unexported fields
}
```

SceneInstance is one spawned copy of a scene. Keep it to find the copy's entities by name and to remove the copy again.

<a id="SceneInstance.Despawn"></a>

#### SceneInstance.Despawn

```go
func (si *SceneInstance) Despawn(w *World)
```

Despawn removes every entity the copy spawned, along with any children they have gained since, and leaves other copies of the same scene alone. Entities already gone are skipped. The instance is empty afterwards.

<a id="SceneInstance.Entity"></a>

#### SceneInstance.Entity

```go
func (si *SceneInstance) Entity(name string) (Entity, bool)
```

Entity returns the entity this copy of the scene gave the name, and false when the scene names nothing that. This lookup does not check whether the entity has since despawned; use World.Alive to check it.

<a id="System"></a>

### System

```go
type System func(w *World, dt float64)
```

System is a step of the simulation run by World.Update.

<a id="SystemStat"></a>

<a id="SystemStat.Name"></a>

<a id="SystemStat.MS"></a>

### SystemStat

```go
type SystemStat struct {
	Name string
	MS   float64
}
```

SystemStat is the last Update's timing for one system.

<a id="UnregisteredError"></a>

<a id="UnregisteredError.Names"></a>

### UnregisteredError

```go
type UnregisteredError struct {
	Names []string
}
```

UnregisteredError reports types Save met that have no registered name, or names Load or ParsePrefab met that no type is registered under. Names holds the Go type names or the file's names respectively.

<a id="UnregisteredError.Error"></a>

#### UnregisteredError.Error

```go
func (e *UnregisteredError) Error() string
```

Error lists the unregistered names encountered by the operation.

<a id="World"></a>

### World

```go
type World struct {
	// contains filtered or unexported fields
}
```

World holds entities, their components, systems, resources and events. Construct it with NewWorld; the zero value is not initialized. A world supports at most 256 distinct component types and is not concurrency-safe.

<a id="NewWorld"></a>

#### NewWorld

```go
func NewWorld() *World
```

NewWorld makes an empty world.

<a id="World.Add"></a>

#### World.Add

```go
func (w *World) Add[T any](e Entity, v T)
```

Add attaches a component, or replaces it when already present.

<a id="World.AddSystem"></a>

#### World.AddSystem

```go
func (w *World) AddSystem(name string, fn System)
```

AddSystem registers a system; systems run in registration order.

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
)

type Health struct{ HP int }

func main() {
	type Score struct{ Points int }
	type Killed struct{ Entity ecs.Entity }

	w := ecs.NewWorld()
	w.SetResource(Score{})
	w.SpawnWith(Health{1})
	w.SpawnWith(Health{5})

	// Systems run in order; producers before consumers.
	damage := w.Query1[Health]()
	w.AddSystem("damage", func(w *ecs.World, dt float64) {
		damage.Each(func(e ecs.Entity, h *Health) {
			h.HP--
			if h.HP <= 0 {
				w.Despawn(e) // safe: the visited entity may be despawned
				w.Emit(Killed{e})
			}
		})
	})
	w.AddSystem("score", func(w *ecs.World, dt float64) {
		w.Resource[Score]().Points += 10 * len(w.Events[Killed]())
	})
	w.Update(1.0 / 60)
	fmt.Println(w.Resource[Score]().Points, w.Len())
}
```

Output:

```
10 1
```

<a id="World.Alive"></a>

#### World.Alive

```go
func (w *World) Alive(e Entity) bool
```

Alive reports whether the entity still exists.

<a id="World.ComponentValues"></a>

#### World.ComponentValues

```go
func (w *World) ComponentValues(e Entity) []any
```

ComponentValues returns a shallow copy of each component as an any value, in the same order as Components. Replacing fields in the copy requires Add to write them back; slices, maps and pointers still share their underlying storage with the entity. A dead entity returns nil.

<a id="World.Components"></a>

#### World.Components

```go
func (w *World) Components(e Entity) []reflect.Type
```

Components lists the component types an entity carries.

<a id="World.Count"></a>

#### World.Count

```go
func (w *World) Count[T any]() int
```

Count returns how many entities carry a T.

<a id="World.Defer"></a>

#### World.Defer

```go
func (w *World) Defer(fn func(*Commands))
```

Defer records structural changes in fn and applies them, in order, after fn returns normally. Wrap the whole query walk in this scope so changes to other entities wait until the walk finishes. If fn panics, pending commands are discarded and the panic propagates.

Each scope has its own queue: a nested scope applies when its own fn returns. This is not a transaction; direct world writes and changes from completed nested scopes are not rolled back. Do not retain the command buffer or call Apply on it inside fn. Use a separate Commands value when commands need to survive beyond one closure.

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
)

type Position struct{ X, Y float32 }

type Health struct{ HP int }

func main() {
	w := ecs.NewWorld()
	w.SpawnWith(Health{3})
	w.SpawnWith(Health{0})

	// Changing other entities while a query walks them is not allowed;
	// the scope applies the recorded changes after the walk finishes.
	w.Defer(func(cmd *ecs.Commands) {
		w.Each(func(e ecs.Entity, h *Health) {
			if h.HP == 0 {
				cmd.Spawn(Position{1, 1}) // a corpse
				cmd.Despawn(e)
			}
		})
	})
	fmt.Println(w.Count[Health](), w.Count[Position]())
}
```

Output:

```
1 1
```

<a id="World.Despawn"></a>

#### World.Despawn

```go
func (w *World) Despawn(e Entity)
```

Despawn removes an entity, its components and its children.

<a id="World.Each"></a>

#### World.Each

```go
func (w *World) Each[T any](fn func(e Entity, t *T))
```

Each is a one-off iteration over entities with a T, for code that does not keep a query around. The query it needs is built once per world and component set and kept, so calling this every frame costs no more than a query of your own.

<a id="World.Each2"></a>

#### World.Each2

```go
func (w *World) Each2[A, B any](fn func(e Entity, a *A, b *B))
```

Each2 is a one-off iteration over entities with an A and a B.

<a id="World.Each3"></a>

#### World.Each3

```go
func (w *World) Each3[A, B, C any](fn func(e Entity, a *A, b *B, c *C))
```

Each3 is a one-off iteration over entities with an A, a B and a C.

<a id="World.Each4"></a>

#### World.Each4

```go
func (w *World) Each4[A, B, C, D any](fn func(e Entity, a *A, b *B, c *C, d *D))
```

Each4 is a one-off iteration over entities with four components.

<a id="World.Emit"></a>

#### World.Emit

```go
func (w *World) Emit[T any](ev T)
```

Emit queues an event for systems to read with Events.

<a id="World.Entities"></a>

#### World.Entities

```go
func (w *World) Entities() []Entity
```

Entities lists every live entity, in no particular order.

<a id="World.Events"></a>

#### World.Events

```go
func (w *World) Events[T any]() []T
```

Events returns the events of type T emitted since the start of this Update. Draw sees what the last Update emitted. The slice belongs to the event queue; copy it to retain events across Emit or Update calls.

<a id="World.ExportScene"></a>

#### World.ExportScene

```go
func (w *World) ExportScene(roots ...Entity) (*Scene, error)
```

ExportScene captures entities and everything under them as a scene document Instantiate spawns again, which is how a game writes out what it built or what the player changed. Pass the roots to capture, or none to capture every entity in the world that has no parent.

Each entity's components are encoded the way World.Save encodes them, its Name component becomes the scene entity's name, and an Entity field pointing at another captured entity becomes that entity's number; a reference to anything else becomes None. A component type with no name from Register fails the call with an UnregisteredError naming every such type.

The document holds components, never prefab references, because a live entity does not remember which prefab made it.

<a id="World.Get"></a>

#### World.Get

```go
func (w *World) Get[T any](e Entity) (*T, bool)
```

Get returns a pointer to the entity's component. The pointer is valid until the next structural change (Add, Remove, Despawn, Spawn) that touches its table, so read or write it right away.

<a id="World.Has"></a>

#### World.Has

```go
func (w *World) Has[T any](e Entity) bool
```

Has reports whether the entity carries a T.

<a id="World.Instantiate"></a>

#### World.Instantiate

```go
func (w *World) Instantiate(scene *Scene, opts ...InstantiateOptions) (*SceneInstance, error)
```

Instantiate spawns a copy of the scene into the world and returns what it made. Every call makes fresh entities, so several copies of one scene live side by side. Components are decoded and attached, the scene's parent links are rebuilt, every named entity gets a Name component, and an Entity field holding an entity number is rewritten to the handle that entity was given; a number the scene does not use becomes None. A prefab reference spawns the library's prefab with its children and writes the entity's own components over the prefab's.

A component name this build has not registered fails the call with an UnregisteredError listing the names, unless InstantiateOptions.SkipUnknown is set, and a prefab reference the library cannot resolve is a MissingPrefabError. Nothing is left in the world when the call fails.

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
	"github.com/matjam/bunyip/gfx"
	"github.com/matjam/bunyip/lin"
)

type Position struct{ X, Y float32 }

type Health struct{ HP int }

func main() {
	// Register names once, at start-up; a scene file holds these.
	ecs.Register[Position]("Position")
	ecs.Register[Health]("Health")

	// A camp of two: the guard's Leader field points at the chief, which
	// the document writes as the chief's number in the entity list.
	doc := []byte(`{
	  "version": 1,
	  "name": "west camp",
	  "properties": {"music": "wind.ogg"},
	  "entities": [
	    {"name": "camp", "components": {"gfx.Transform": {"Position": {"X": 40}}}},
	    {"name": "chief", "parent": 1, "prefab": "orc", "components": {"Health": {"HP": 40}}},
	    {"parent": 1, "prefab": "orc", "components": {"gfx.Transform": {"Position": {"X": 2}}}}
	  ]
	}`)
	scene, err := ecs.ParseScene(doc)
	if err != nil {
		fmt.Println(err)
		return
	}

	w := ecs.NewWorld()
	w.SetResource(ecs.PrefabLibrary{"orc": ecs.NewPrefab(Health{8}, gfx.Transform{})})

	// Two copies of the camp, the second a hundred units east.
	west, err := w.Instantiate(scene)
	if err != nil {
		fmt.Println(err)
		return
	}
	if _, err := w.Instantiate(scene, ecs.InstantiateOptions{Offset: lin.V3(100, 0, 0)}); err != nil {
		fmt.Println(err)
		return
	}
	chief, _ := west.Entity("chief")
	h, _ := w.Get[Health](chief)
	fmt.Println(scene.Properties["music"], h.HP, w.Len())

	// Removing one copy takes its entities and leaves the other whole.
	west.Despawn(w)
	fmt.Println(w.Len())
}
```

Output:

```
wind.ogg 40 6
3
```

<a id="World.Len"></a>

#### World.Len

```go
func (w *World) Len() int
```

Len is the number of live entities.

<a id="World.Load"></a>

#### World.Load

```go
func (w *World) Load(in io.Reader, opts ...LoadOptions) error
```

Load adds the entities and resources of a file written by Save to the world. Every entity gets a new handle; parent links, Children lists and the Entity fields inside components and resources are rewritten to the new handles (see Remapper), and a reference to an entity the file does not contain becomes None. Loaded resources replace the world's. Entities already in the world are untouched.

Names with no registered type fail the load before anything is added, with an UnregisteredError listing them, unless LoadOptions.SkipUnknown is set. A value that fails to decode stops the load part way.

<a id="World.MustResource"></a>

#### World.MustResource

```go
func (w *World) MustResource[T any]() *T
```

MustResource returns the world's T and panics when it is missing.

<a id="World.Query1"></a>

#### World.Query1

```go
func (w *World) Query1[A any](filters ...Filter) *Query1[A]
```

Query1 makes a query; keep it and reuse it across frames.

<a id="World.Query2"></a>

#### World.Query2

```go
func (w *World) Query2[A, B any](filters ...Filter) *Query2[A, B]
```

Query2 makes a query; keep it and reuse it across frames.

<a id="World.Query3"></a>

#### World.Query3

```go
func (w *World) Query3[A, B, C any](filters ...Filter) *Query3[A, B, C]
```

Query3 makes a query; keep it and reuse it across frames.

<a id="World.Query4"></a>

#### World.Query4

```go
func (w *World) Query4[A, B, C, D any](filters ...Filter) *Query4[A, B, C, D]
```

Query4 makes a query; keep it and reuse it across frames.

<a id="World.Remove"></a>

#### World.Remove

```go
func (w *World) Remove[T any](e Entity)
```

Remove detaches a component; nothing happens if the entity has none.

<a id="World.Resource"></a>

#### World.Resource

```go
func (w *World) Resource[T any]() *T
```

Resource returns a pointer to the world's T, or nil when unset.

<a id="World.Resources"></a>

#### World.Resources

```go
func (w *World) Resources() []string
```

Resources lists the type names of the resources set on the world, sorted, for a debug view that shows what a world holds.

<a id="World.Save"></a>

#### World.Save

```go
func (w *World) Save(out io.Writer, opts ...SaveOptions) error
```

Save writes every live entity as JSON: its ID, its parent and children, and each component encoded with encoding/json under its registered name. Registered resources follow. Parent and Children components are written as the links, not as components. A component or resource type without a registered name fails the save with an UnregisteredError naming every such type, unless SaveOptions.SkipUnregistered is set.

Example:

```go
package main

import (
	"bytes"
	"fmt"

	"github.com/matjam/bunyip/ecs"
)

type Position struct{ X, Y float32 }

type Health struct{ HP int }

func main() {
	// Register names once, at start-up, so files outlive renames.
	ecs.Register[Position]("Position")
	ecs.Register[Health]("Health")

	w := ecs.NewWorld()
	w.SpawnWith(Position{1, 2}, Health{5})
	var save bytes.Buffer
	if err := w.Save(&save); err != nil {
		fmt.Println(err)
	}

	loaded := ecs.NewWorld()
	if err := loaded.Load(&save); err != nil {
		fmt.Println(err)
	}
	loaded.Each(func(e ecs.Entity, p *Position) { fmt.Println(p.X, p.Y) })
}
```

Output:

```
1 2
```

<a id="World.SetComponent"></a>

#### World.SetComponent

```go
func (w *World) SetComponent(e Entity, v any)
```

SetComponent attaches a component given as a value, replacing the one the entity carries of that type. It is what an editor or a debug panel writes an edited component back through, where the type is known only at run time; game code that knows the type calls Add. The value must not be a pointer, and nothing happens if the entity is gone.

<a id="World.SetResource"></a>

#### World.SetResource

```go
func (w *World) SetResource[T any](v T)
```

SetResource stores a singleton value of type T on the world: the rules, the score, the input state, anything there is one of.

<a id="World.SetSystemEnabled"></a>

#### World.SetSystemEnabled

```go
func (w *World) SetSystemEnabled(name string, on bool)
```

SetSystemEnabled turns a system on or off by the name it was registered under, for a debugger that pauses part of the simulation. A system that is off is skipped by Update and keeps its place in the order; a name no system has is ignored. Systems start on.

<a id="World.Spawn"></a>

#### World.Spawn

```go
func (w *World) Spawn() Entity
```

Spawn creates an entity with no components.

<a id="World.SpawnWith"></a>

#### World.SpawnWith

```go
func (w *World) SpawnWith(comps ...any) Entity
```

SpawnWith creates an entity carrying the given component values.

<a id="World.Stats"></a>

#### World.Stats

```go
func (w *World) Stats() []SystemStat
```

Stats reports each system's most recent timing in milliseconds. The returned slice belongs to the world; do not modify it, and copy it to retain a snapshot across updates. Disabled systems keep their last timing.

<a id="World.SystemEnabled"></a>

#### World.SystemEnabled

```go
func (w *World) SystemEnabled(name string) bool
```

SystemEnabled reports whether a system runs. A name no system has reads as off.

<a id="World.Update"></a>

#### World.Update

```go
func (w *World) Update(dt float64)
```

Update runs every system in order with dt. Events emitted during the previous Update (or between updates, in Draw) are cleared first, so order systems with producers before consumers. A system turned off with SetSystemEnabled is skipped and keeps its last timing.

<a id="World.Updates"></a>

#### World.Updates

```go
func (w *World) Updates() uint64
```

Updates counts the Update calls the world has run, so a debug view can tell whether the simulation advanced between two frames.

## Examples

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
)

type Position struct{ X, Y float32 }
type Velocity struct{ X, Y float32 }
type Health struct{ HP int }

func main() {
	w := ecs.NewWorld()
	w.SpawnWith(Position{0, 0}, Velocity{1, 0}, Health{10})
	w.SpawnWith(Position{5, 5}, Velocity{0, 1})
	w.SpawnWith(Position{9, 9}) // no velocity: never moves

	// A query walks every entity with both components; keep it and reuse it.
	movers := w.Query2[Position, Velocity]()
	movers.Each(func(e ecs.Entity, p *Position, v *Velocity) {
		p.X += v.X
		p.Y += v.Y
	})
	// Iteration order is by table and then by row, not by spawn order.
	w.Each(func(e ecs.Entity, p *Position) { fmt.Println(p.X, p.Y) })
	fmt.Println(movers.Count(), "movers of", w.Len())
}
```

Output:

```
1 0
5 6
9 9
2 movers of 3
```
