View Source Ecspanse.Command (ECSpanse v0.10.0)
The Ecspanse.Command
module provides a set of functions for managing entities, components and resources in the Ecspanse
engine.
Commands are the only way to change the state of components and resources in Ecspanse
. These commands can only be run from systems, otherwise an error will be thrown.
The Ecspanse.Command
module includes functions for managing relationships between entities, such as adding and removing children and parents.
All entity and component related commands can run for batches (lists) for performance reasons.
All commands raise an error if the command fails.
Entity Relationships
The Ecspanse.Command
module provides functions for managing relationships between entities.
This is aslo a powerful tool to manage different kind of collections.
Ecspanse entities relationships are bidirectional associations
When adding or removing children or parents, they are automatically added or removed from the corresponding parent or children entities. The same applies when despawning entities.
Summary
Entities
Clones the specified entity and returns a new entity with the same components.
Clones the specified entity and all of its descendants and returns the newly cloned entity.
The same as despawn_entity!/1
but despawns multiple entities at once.
It takes a list of entities as argument and returns :ok
. See despawn_entity!/1
for more details.
The same as despawn_entity_and_descendants!/1
but despawns multiple entities and their descendants at once.
It takes a list of entities as argument and returns :ok
.
Despawns the specified entity and removes all of its components. It also removes the despawned entity from its parent and child entities, if any.
The same as despawn_entity!/1
but recursively despawns also all descendant tree of the entity.
The same as spawn_entity!/1
but spawns multiple entities at once.
It takes a list of entity specs as argument and returns a list of Ecspanse.Entity structs.
Spawns a new entity with the given components and relations provided by the Ecspanse.Entity.entity_spec() type.
When creating a new entity, at least one of the components:
, children:
or parents:
must be provided in the entity spec, otherwise the entity cannot be persisted.
Relationships
Adds an entity as child to a parent entity.
The same as add_child!/2
but can perform multiple operations at once.
For example, adding multiple children to multiple parents.
Adds a parent entity to a child entity.
The same as add_parent!/2
but can perform multiple operations at once.
For example, adding multiple parents to multiple children.
Removes a child entity from a parent entity.
The same as remove_child!/2
but can perform multiple operations at once.
For example, removing multiple children from multiple parents.
Removes a parent entity from a child entity.
The same as remove_parent!/2
but can perform multiple operations at once.
For example, removing multiple parents from multiple children.
Components
The same as add_component!/2
but fetches the component after adding it.
Adds a new component to the specified entity.
The same as add_component!/2
but adds multiple components to multiple entities at once.
Removes an existing component from its entity. The components is destroyed.
The same as remove_component!/1
but removes multiple components at once.
The same as update_component!/2
but fetches the component after updating it.
Updates the state of an existing component.
The same as update_component!/2
but updates multiple components at once.
Resources
Deletes an existing global resource.
Inserts a new global resource.
Updates an existing global resource.
Entities
@spec clone_entity!(Ecspanse.Entity.t(), opts :: keyword()) :: Ecspanse.Entity.t()
Clones the specified entity and returns a new entity with the same components.
Due to the potentially large number of components that may be affected by this operation,
it is recommended to run this function in a synchronous system (such as a frame_start
or frame_end
system)
to avoid the need to lock all involved components.
Note
The entity's
Ecspanse.Component.Children
andEcspanse.Component.Parents
components are not cloned. Usedeep_clone_entity!/2
to clone the entity and all of its descendants.
Options
:id
- a custom unique ID for the entity (binary). If not provided, a random UUID will be generated.
Entity ID
The entity IDs must be unique. Attention when providing the
:id
option. If the provided ID is not unique, cloning the entity will raise an error.
Examples
%Ecspanse.Entity{} = entity = Ecspanse.Command.clone_entity!(compass_entity)
@spec deep_clone_entity!(Ecspanse.Entity.t(), [{:opts, keyword()}]) :: Ecspanse.Entity.t()
Clones the specified entity and all of its descendants and returns the newly cloned entity.
Due to the potentially large number of components that may be affected by this operation,
it is recommended to run this function in a synchronous system (such as a frame_start
or frame_end
system)
to avoid the need to lock all involved components.
Options
:id
- a custom unique ID for the entity (binary). If not provided, a random UUID will be generated.
Entity ID
The entity IDs must be unique. Attention when providing the
:id
option. If the provided ID is not unique, cloning the entity will raise an error.
The cloned descendants entities will receive a random UUID as ID by default.
Cloning descendants
The deep cloning operates only for the descendants of the entity. If any of the descendants has a parent that is not a descendant of the entity, the parent will not be cloned or referenced.
If this is a desired behaviour, the parents should be added manually after the deep cloning.
Examples
%Ecspanse.Entity{} = entity = Ecspanse.Command.deep_clone_entity!(enemy_entity)
@spec despawn_entities!([Ecspanse.Entity.t()]) :: :ok
The same as despawn_entity!/1
but despawns multiple entities at once.
It takes a list of entities as argument and returns :ok
. See despawn_entity!/1
for more details.
@spec despawn_entities_and_descendants!([Ecspanse.Entity.t()]) :: :ok
The same as despawn_entity_and_descendants!/1
but despawns multiple entities and their descendants at once.
It takes a list of entities as argument and returns :ok
.
@spec despawn_entity!(Ecspanse.Entity.t()) :: :ok
Despawns the specified entity and removes all of its components. It also removes the despawned entity from its parent and child entities, if any.
Due to the potentially large number of components that may be affected by this operation,
it is recommended to run this function in a synchronous system (such as a frame_start
or frame_end
system)
to avoid the need to lock all involved components.
Examples
:ok = Ecspanse.Command.despawn_entity!(hero_entity)
@spec despawn_entity_and_descendants!(Ecspanse.Entity.t()) :: :ok
The same as despawn_entity!/1
but recursively despawns also all descendant tree of the entity.
This means that it will despawn the children of the entity, and their children, and so on.
It is an efficient way to remove an entire entity tree with just one operation. Extra attention required for entities with shared children.
See despawn_entity!/1
for more details.
@spec spawn_entities!([Ecspanse.Entity.entity_spec()]) :: [Ecspanse.Entity.t()]
The same as spawn_entity!/1
but spawns multiple entities at once.
It takes a list of entity specs as argument and returns a list of Ecspanse.Entity structs.
See spawn_entity!/1
for more details.
@spec spawn_entity!(Ecspanse.Entity.entity_spec()) :: Ecspanse.Entity.t()
Spawns a new entity with the given components and relations provided by the Ecspanse.Entity.entity_spec() type.
When creating a new entity, at least one of the components:
, children:
or parents:
must be provided in the entity spec, otherwise the entity cannot be persisted.
Due to the potentially large number of components that may be affected by this operation,
it is recommended to run this function in a synchronous system (such as a frame_start
or frame_end
system)
to avoid the need to lock all involved components.
Examples
%Ecspanse.Entity{} = Ecspanse.Command.spawn_entity!(
{
Ecspanse.Entity,
id: "my_custom_id",
components: [Demo.Components.Hero, {Demo.Components.Position, [x: 5, y: 3], [:hero, :map]}],
children: [potion_entity, sword_entity],
parents: [map_entity]
}
)
Relationships
@spec add_child!(Ecspanse.Entity.t(), child :: Ecspanse.Entity.t()) :: :ok
Adds an entity as child to a parent entity.
Examples
:ok = Ecspanse.Command.add_child!(hero_entity, sword_entity)
@spec add_children!([{Ecspanse.Entity.t(), children :: [Ecspanse.Entity.t()]}]) :: :ok
The same as add_child!/2
but can perform multiple operations at once.
For example, adding multiple children to multiple parents.
It takes a list of two element tuples as argument, where the first element of the tuple is the parent entity and the second element is a list of children entities.
Examples
:ok = Ecspanse.Command.add_children!([
{hero_entity, [sword_entity]},
{market_entity, [map_entity, potion_entity]}
])
@spec add_parent!(Ecspanse.Entity.t(), parent :: Ecspanse.Entity.t()) :: :ok
Adds a parent entity to a child entity.
Examples
:ok = Ecspanse.Command.add_parent!(sword_entity, hero_entity)
@spec add_parents!([{Ecspanse.Entity.t(), parents :: [Ecspanse.Entity.t()]}]) :: :ok
The same as add_parent!/2
but can perform multiple operations at once.
For example, adding multiple parents to multiple children.
It takes a list of two element tuples as argument, where the first element of the tuple is the child entity and the second element is a list of parent entities.
Examples
:ok = Ecspanse.Command.add_parents!([
{sword_entity, [hero_entity]},
{map_entity, [market_entity, vendor_entity]}
])
@spec remove_child!(Ecspanse.Entity.t(), child :: Ecspanse.Entity.t()) :: :ok
Removes a child entity from a parent entity.
Examples
:ok = Ecspanse.Command.remove_child!(hero_entity, sword_entity)
@spec remove_children!([{Ecspanse.Entity.t(), children :: [Ecspanse.Entity.t()]}]) :: :ok
The same as remove_child!/2
but can perform multiple operations at once.
For example, removing multiple children from multiple parents.
It takes a list of two element tuples as argument, where the first element of the tuple is the parent entity and the second element is a list of children entities.
Examples
:ok = Ecspanse.Command.remove_children!([
{hero_entity, [sword_entity]},
{market_entity, [map_entity, potion_entity]}
])
@spec remove_parent!(Ecspanse.Entity.t(), parent :: Ecspanse.Entity.t()) :: :ok
Removes a parent entity from a child entity.
Examples
:ok = Ecspanse.Command.remove_parent!(sword_entity, hero_entity)
@spec remove_parents!([{Ecspanse.Entity.t(), parents :: [Ecspanse.Entity.t()]}]) :: :ok
The same as remove_parent!/2
but can perform multiple operations at once.
For example, removing multiple parents from multiple children.
It takes a list of two element tuples as argument, where the first element of the tuple is the child entity and the second element is a list of parent entities.
Examples
:ok = Ecspanse.Command.remove_parents!([
{sword_entity, [hero_entity]},
{map_entity, [market_entity, vendor_entity]}
])
Components
@spec add_and_fetch_component!( Ecspanse.Entity.t(), Ecspanse.Component.component_spec() ) :: {:ok, component_state :: struct()}
The same as add_component!/2
but fetches the component after adding it.
@spec add_component!(Ecspanse.Entity.t(), Ecspanse.Component.component_spec()) :: :ok
Adds a new component to the specified entity.
Info
An entity cannot have multiple components of the same type. If an attempt is made to insert a component that already exists for the entity, an error will be raised.
Examples
:ok = Ecspanse.Command.add_component!(hero_entity, Demo.Components.Gold)
:ok = Ecspanse.Command.add_component!(hero_entity, {Demo.Components.Gold, [amount: 5], [:resource, :available]})
@spec add_components!([{Ecspanse.Entity.t(), [Ecspanse.Component.component_spec()]}]) :: :ok
The same as add_component!/2
but adds multiple components to multiple entities at once.
It takes a list of two element tuples as argument, where the first element of the tuple is the entity and the second element is a list of component specs.
Examples
:ok = Ecspanse.Command.add_components!([
{inventory_item_entity, [Demo.Components.Sword]},
{hero_entity, [Demo.Components.Position, Demo.Components.Hero]}
])
@spec remove_component!(component :: struct()) :: :ok
Removes an existing component from its entity. The components is destroyed.
Examples
:ok = Ecspanse.Command.remove_component!(invisibility_component)
@spec remove_components!([component :: struct()]) :: :ok
The same as remove_component!/1
but removes multiple components at once.
@spec update_and_fetch_component!( current_component :: struct(), state_changes :: keyword() ) :: {:ok, component_state :: struct()}
The same as update_component!/2
but fetches the component after updating it.
Updates the state of an existing component.
The function takes two arguments: the component struct to update and a keyword list of changes to apply.
Examples
:ok = Ecspanse.Command.update_component!(position_component, x: :12)
The same as update_component!/2
but updates multiple components at once.
It takes a list of two element tuples as argument, where the first element of the tuple is the component struct and the second element is a keyword list of changes to apply.
Examples
:ok = Ecspanse.Command.update_components!([
{position_component, x: 7, y: 9},
{gold_component, amount: 12}
])
Resources
Deletes an existing global resource.
Note
Resources can be created, updated or deleted only from synchronous systems.
Examples
%Demo.Resources.Lobby{} = Ecspanse.Command.delete_resource!(lobby_resource)
@spec insert_resource!(resource_spec :: Ecspanse.Resource.resource_spec()) :: resource :: struct()
Inserts a new global resource.
Info
An Ecspanse instance can only hold one resource of each type at a time. If an attempt is made to insert a resource that already exists, an error will be raised.
Note
Resources can be created, updated or deleted only from synchronous systems.
Examples
%Demo.Resources.Lobby{} = Ecspanse.Command.insert_resource!({Demo.Resources.Lobby, player_count: 0})
@spec update_resource!(resource :: struct(), state_changes :: keyword()) :: updated_resource :: struct()
Updates an existing global resource.
Note
Resources can be created, updated or deleted only from synchronous systems.
Examples
%Demo.Resources.Lobby{} = Ecspanse.Command.update_resource!(lobby_resource, player_count: 1)