5#include <unordered_map>
12#include <condition_variable>
13#include <libecs-cpp/json.hpp>
107 void Start(std::chrono::microseconds interval);
216 std::shared_ptr<ecs::Component>
Component(std::unique_ptr<ecs::Component> component);
231 template <
class T = ecs::Component>
232 std::shared_ptr<T>
ComponentGet(
const std::string &entity,
const std::string &type)
const
234 const std::shared_ptr<ecs::Component> *found = this->componentFind(entity, type);
239 if constexpr(std::is_same_v<T, ecs::Component>)
245 return std::dynamic_pointer_cast<T>(*found);
255 bool ComponentHas(
const std::string &entity,
const std::string &type)
const;
360 void Defer(std::function<
void()> fn);
373 void Resources(
const std::unordered_map<std::string, std::shared_ptr<ecs::Resource>> &resources);
381 std::shared_ptr<const ecs::Resource>
ResourceGet(
const std::string &name)
const;
386 std::unordered_map<std::string, std::unique_ptr<ecs::Entity>>
Entities;
410 std::unordered_map<std::string, std::unique_ptr<ecs::System>>
Systems;
426 void Log(
const std::string &message,
const std::string &level =
"info");
433 void LoggerSet(std::function<
void(
const std::string &,
const std::string &)> fn);
436 std::mutex mailboxesLock;
437 std::unordered_map<std::string, std::shared_ptr<ecs::Mailbox>> mailboxes;
438 using LogFunction = std::function<void(
const std::string &,
const std::string &)>;
440 std::mutex loggerLock;
441 std::shared_ptr<const LogFunction> logger;
448 bool started =
false;
450 bool shutdown =
false;
453 std::vector<SystemSlot> systemOrder;
454 uint32_t walkDepth = 0;
456 std::mutex deferredLock;
457 std::vector<std::function<void()>> deferred;
459 std::atomic<std::size_t> deferredCount{0};
460 bool deferredClosed =
false;
461 bool draining =
false;
463 bool orderHasGaps =
false;
468 std::unique_ptr<ecs::System> system;
472 std::vector<RetiredSystem> retiredSystems;
475 void systemRetire(std::unique_ptr<ecs::System> system,
bool notify);
479 void retiredRelease();
480 void deferredClose();
486 std::jthread containerThread;
487 void threadFunc(std::stop_token stopToken);
488 ecs::Entity *entityCreate(
const std::string &handle);
490 const std::shared_ptr<ecs::Component> *componentFind(
const std::string &entity,
const std::string &type)
const
492 auto byType = this->Components.find(type);
493 if(byType == this->Components.end())
497 auto byEntity = byType->second.find(entity);
498 if(byEntity == byType->second.end())
502 return byEntity->second ? &byEntity->second :
nullptr;
505 std::unordered_map<std::string, std::shared_ptr<ecs::Resource>> resources;
508 bool startPending =
false;
513 bool tearingDown =
false;
514 bool tornDown =
false;
520 std::mutex lifecycleLock;
521 std::condition_variable_any lifecycleChanged;
523 bool threadStarted =
false;
525 std::atomic<bool> stopRequested{
false};
527 bool stopDone =
false;
529 bool joining =
false;
533 std::atomic<bool> ownsThread{
false};
535 void threadStart(
const std::chrono::microseconds *interval);
543 bool managerStopRequest();
546 void managerStopWait();
A source of time for systems and containers.
Definition Clock.hpp:21
A container: the entities, components, systems and resources that are updated together.
Definition Container.hpp:70
std::shared_ptr< T > ComponentGet(const std::string &entity, const std::string &type) const
Looks up the component with the given type name on the given entity, as class T.
Definition Container.hpp:232
void ResourceAdd(const std::string &name, ecs::Resource r)
Stores a resource under a name, replacing any resource of that name.
bool ComponentHas(const std::string &entity, const std::string &type) const
Says whether the given entity has a component stored under the given type name.
void SystemDestroy(const std::string &handle)
Removes a system.
std::unordered_map< std::string, std::unique_ptr< ecs::System > > Systems
The systems of the container, by handle.
Definition Container.hpp:410
~Container()
Stops the container as Stop() does, then releases it.
std::unordered_map< std::string, std::unique_ptr< ecs::Entity > > Entities
The entities of the container, by handle.
Definition Container.hpp:386
void Defer(std::function< void()> fn)
Hands a function to the container thread, which runs it at the start of the next pass.
void Update()
Runs one pass: the deferred functions, then the start of new systems, then one update of each system.
ecs::TypeEntityComponentList Components
The components of the container, by type name and then by entity handle.
Definition Container.hpp:401
Container(ecs::Manager *manager)
Creates a container with a generated handle.
void LoggerSet(std::function< void(const std::string &, const std::string &)> fn)
Replaces the log destination.
void EntityDestroy(const std::string &handle)
Removes an entity and its components.
Container(ecs::Manager *manager, const std::string &handle)
Creates a container with the given handle.
void ClockSet(const ecs::Clock *clock)
Replaces the clock that the systems of this container read.
ecs::Entity * Entity(const std::string &handle)
Returns the entity with this handle, creating it if it does not exist.
void Start(std::chrono::microseconds interval)
Starts the container's own thread with the given time between passes.
void ComponentDestroy(const std::string &entity, const std::string &type)
Removes the component with the given type name from the given entity.
const std::string Handle
The container's handle: the name given to Manager::Container(), or a generated UUID.
Definition Container.hpp:395
void Log(const std::string &message, const std::string &level="info")
Sends a line to the log destination.
ecs::Entity * Entity()
Creates an entity with a generated handle.
void SystemsInitialize()
Calls System::Initialize() on every registered system that has not been started, in registration orde...
void Start(uint32_t)
Starts the container's own thread with the interval given as a number of microseconds.
std::shared_ptr< ecs::Component > Component(std::unique_ptr< ecs::Component > component)
Attaches a component to the entity named by its EntityHandle and returns the stored component.
void Start()
Starts the container's own thread, which runs 30 passes a second.
std::shared_ptr< const ecs::Resource > ResourceGet(const std::string &name) const
Returns the resource stored under a name as a shared read-only view, without copying its bytes.
ecs::System * System(std::unique_ptr< ecs::System > system)
Registers a system and returns a pointer to it.
nlohmann::json Export() const
Describes the container, its entities and its systems as JSON.
void Stop()
Stops the container and calls System::Shutdown() on every started system, last registered first.
void MessageSubmit(const nlohmann::json &message)
Sends a message to the system named in message["destination"]["system"].
ecs::Uuid UuidGet()
Generates a new identifier.
void Resources(const std::unordered_map< std::string, std::shared_ptr< ecs::Resource > > &resources)
Stores every resource in the given map under its name, replacing resources of the same names.
One thing in a container, to which components are attached.
Definition Entity.hpp:22
Creates and owns containers, routes messages between them and shuts them down.
Definition Manager.hpp:32
static const SteadyClock & Instance()
The shared instance, which lives until the process ends.
Definition Clock.hpp:41
Base class for the logic that runs in a container.
Definition System.hpp:178
A 128-bit random identifier in the standard version 4 text form (for example "550e8400-e29b-41d4-a716...
Definition Uuid.hpp:14
constexpr std::chrono::microseconds DEFAULT_INTERVAL
The interval of a new schedule: 33 333 microseconds, about 30 updates a second.
Definition Timing.hpp:17
std::unordered_map< std::string, ecs::EntityComponentList > TypeEntityComponentList
The components of a container, by type name and then by entity handle.
Definition Component.hpp:48
A block of bytes that a container stores under a name with Container::ResourceAdd().
Definition Resource.hpp:16