-module(ecsalt). -moduledoc "Entity Component System". -export([new/0, new/1, delete/1]). -export([proc/2, to_map/1]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Types and Records %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -include("ecsalt.hrl"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % API %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -doc """ Create a new ECS world with default ETS options. Returns an opaque world record used by all other API functions. See also new/1, especially if you need to start ECSalt with public tables for multi-process access. """. -spec new() -> world(). new() -> new([]). -doc """ Create a new ECS world with custom ETS options (e.g., read concurrency, public tables). Table types are enforced internally and cannot be overridden. Returns an opaque world record used by all other API functions. """. -spec new(list()) -> world(). new(ETSOpts) -> SafeOpts = ETSOpts -- [set, bag, duplicate_bag, ordered_set], #world{ systems = [], entities = ets:new(entities, [set | SafeOpts]), components = ets:new(components, [bag | SafeOpts]) }. -doc "Stop the ECS and delete the ETS tables". -spec delete(world()) -> ok. delete(#world{entities = ETable, components = CTable}) -> true = ets:delete(ETable), true = ets:delete(CTable), ok. -doc """ Convert the component list for a given entity ID to a map. Warning: this can potentially create an unbounded number of atoms! """. -spec to_map(entity()) -> map(). to_map({EntityID, Components}) -> % Create the component map EMap = maps:from_list(Components), % Add the ID EMap#{id => EntityID}. -doc """ For every registered system, trigger the proc callback with some extra data specified by Data and gather results. """. -spec proc(term(), world()) -> [any()]. proc(Data, World) -> #world{systems = Systems} = World, Fun = fun({_Prio, Sys}, Acc) -> Result = case Sys of {M, F, 2} -> M:F(Data, World); SysFun -> SysFun(Data, World) end, [{Sys, Result} | Acc] end, lists:foldl(Fun, [], Systems).