|
libecs-cpp 2.1.0
Entity Component System library in C++
|
Base class for the logic that runs in a container. More...
#include <System.hpp>

Public Member Functions | |
| System () | |
| Creates a system whose handle is a newly generated UUID. | |
| System (const std::string &handle) | |
| Creates a system with the given handle. | |
| virtual | ~System ()=default |
| Destroys the system. | |
| virtual void | Initialize () |
| Called once before the system's first Update(); override it to set the system up. | |
| virtual void | Shutdown () |
| Called once before a started system is destroyed; override it to release what the system holds. | |
| virtual void | Configure (const nlohmann::json &config) |
| Receives the system's configuration; override it to read settings. | |
| virtual void | Update () |
| Called on each pass in which the system is due; override it with the system's work. | |
| void | UpdateSystem () |
| Fires the timers that are due, then calls Update(). | |
| void | MessageSubmit (const nlohmann::json &message) |
| Delivers a message to this system. | |
| virtual nlohmann::json | Export () const =0 |
| Describes the system as JSON; every subclass implements it. | |
| size_t | MessagesWaiting () |
| Moves any delivered messages into messages, then returns how many messages are waiting to be read. | |
| std::chrono::microseconds | ElapsedGet () const |
| Returns the time that passed between the previous update of this system and the current one. | |
| double | ElapsedSecondsGet () const |
| Returns ElapsedGet() in seconds. | |
| void | ClockSet (const ecs::Clock *clock) |
| Replaces the clock this system reads. | |
| uint32_t | DeltaTimeGet () |
| Returns the whole milliseconds of this update's elapsed time. | |
| void | TimerClear (const std::string &name) |
| Cancels every timer with this name. | |
| void | TimerAdd (Timer timer) |
| Adds a timer, which first fires one full length from now. | |
| void | Log (const std::string &message, const std::string &level="info") |
| Sends a line to the container's log destination with this system's handle as a prefix. | |
Public Attributes | |
| const std::string | Handle |
| The system's handle, given to the constructor and never changed. | |
| ecs::Container * | Container = nullptr |
| The container the system is registered in, or null before registration. | |
| ecs::TypeEntityComponentList * | Components = nullptr |
| The components of the system's container (Container::Components), or null before registration. | |
| ecs::Timing | Timing |
| The schedule that decides on which passes the system is updated. | |
Protected Member Functions | |
| void | componentsClear () |
| Removes every component listed in componentsToDelete from the container and empties the list. | |
Protected Attributes | |
| std::queue< nlohmann::json > | messages |
| Messages ready to read, oldest first. | |
| std::chrono::steady_clock::time_point | lastTime = std::chrono::steady_clock::now() |
| The construction time. | |
| std::unordered_map< std::string, std::vector< std::string > > | componentsToDelete |
| Components a subclass has marked for removal, as entity handles by type name. | |
| std::vector< ecs::Timer > | timers |
| The system's timers. | |
| std::vector< std::pair< std::string, std::string > > | bufferedLogMessages |
| Lines logged before the system was registered, as (message, level) pairs in the order they were logged. | |
Base class for the logic that runs in a container.
A subclass overrides Update() with its work and Export() with a description of itself, and may override Initialize(), Shutdown() and Configure(). On each pass in which the system's Timing says an update is due, the container calls UpdateSystem(), which fires the timers that are due and then calls Update().
while(!this->messages.empty())
{
nlohmann::json message = this->messages.front();
this->messages.pop();
// use the message
}
| ecs::System::System | ( | ) |
Creates a system whose handle is a newly generated UUID.
| ecs::System::System | ( | const std::string & | handle | ) |
Creates a system with the given handle.
The handle is fixed for the life of the object and cannot be assigned afterwards.
A subclass names itself in its constructor's initialiser list:
class Foo : public ecs::System
{
public:
Foo() : ecs::System("Foo") {}
};
A plugin factory that returns a new Foo reaches the same constructor. An empty handle is refused when the system is registered.
|
virtualdefault |
Destroys the system.
Container->Log() works from a subclass's destructor.
| void ecs::System::ClockSet | ( | const ecs::Clock * | clock | ) |
Replaces the clock this system reads.
The schedule, the timers and the elapsed-time measurement start again from the new clock's time, because readings of different clocks cannot be compared. The pointer is not owned and the clock must outlive the system. A null pointer selects the real steady clock, which is the default. A container sets the clock of every system it holds with Container::ClockSet().
Thread: container thread only.
|
protected |
Removes every component listed in componentsToDelete from the container and empties the list.
Before the system is registered it logs a warning and does nothing.
|
virtual |
Receives the system's configuration; override it to read settings.
The base implementation does nothing, and the library does not call it: the code that creates the system does.
Thread: container thread only.
| uint32_t ecs::System::DeltaTimeGet | ( | ) |
Returns the whole milliseconds of this update's elapsed time.
Deprecated since 1.8.0: use ElapsedGet() or ElapsedSecondsGet().
The part of a millisecond that is left over is carried into the next update, so the running total stays within a millisecond of the true total. The value is the same on every call during one update. It is at most 4 294 967 295, which a single update longer than about 49.7 days reaches; ElapsedGet() is never limited.
Thread: container thread only.
| std::chrono::microseconds ecs::System::ElapsedGet | ( | ) | const |
Returns the time that passed between the previous update of this system and the current one.
It is measured once per update, from the same clock reading that decided the system was due, and it is the same on every call during that update, from Update(), a timer callback or any helper. Reading it changes nothing, and a system that never reads it loses no time. The values of consecutive updates add up to the time the clock moved. Nothing is clamped: after a long stall the whole stall is reported, so code that integrates over the step should cap it itself, for example with std::min(this->ElapsedSecondsGet(), 0.25).
Before the first update, and during it, the value is the system's configured interval (Timing), because there is no earlier update to measure from. A system whose interval is zero therefore reports zero for its first update.
Thread: container thread only.
| double ecs::System::ElapsedSecondsGet | ( | ) | const |
Returns ElapsedGet() in seconds.
Thread: container thread only.
|
pure virtual |
Describes the system as JSON; every subclass implements it.
It is a const query and must not add or remove systems, entities or components.
Thread: container thread only.
|
inlinevirtual |
Called once before the system's first Update(); override it to set the system up.
It is called exactly once per system, whichever way the system arrived: registered before the container started, registered later from code on the container thread (another system's Initialize() or Update(), a timer callback or a deferred function), registered in a container that the application drives with Update(), or registered as a replacement. Systems that are started together are started in registration order. A system removed before it was reached is never started.
If Initialize() throws, the error is logged with the system's handle and rethrown. The system counts as started: it is not started again, it is updated, and it receives Shutdown() when it leaves the container. The systems registered after it are started at the start of the next pass.
Container->Log() works from here.
Thread: container thread only.
| void ecs::System::Log | ( | const std::string & | message, |
| const std::string & | level = "info" |
||
| ) |
Sends a line to the container's log destination with this system's handle as a prefix.
Before the system is registered the line is held, and registering the system delivers every held line to the destination, in order. Held lines are not capped. The usual levels are "error", "warning", "info" and "debug"; any other name is passed on as given.
Thread: container thread only.
| void ecs::System::MessageSubmit | ( | const nlohmann::json & | message | ) |
Delivers a message to this system.
Returns without waiting for the system's update. The message is moved into messages at the start of the system's next UpdateSystem(), which may be later in the pass that is running. Messages from one sender arrive in the order sent, each exactly once.
Thread: any. The system must be alive.
| size_t ecs::System::MessagesWaiting | ( | ) |
Moves any delivered messages into messages, then returns how many messages are waiting to be read.
A message delivered before the call is counted.
Thread: container thread only.
|
inlinevirtual |
Called once before a started system is destroyed; override it to release what the system holds.
It is called exactly once for every system that was started, and never for one that was not. The system receives no update and no routed message afterwards. When a container stops or is destroyed, its systems are shut down last registered first.
The thread depends on how the system leaves:
An exception thrown from Shutdown() is logged at level "error" with the system's handle and swallowed on every path; the other systems still receive Shutdown() and are released. A Shutdown() that blocks is waited for, not abandoned.
Container->Log() works from here on every path.
| void ecs::System::TimerAdd | ( | Timer | timer | ) |
Adds a timer, which first fires one full length from now.
Throws std::runtime_error, adding nothing, when the length is below zero or above ecs::MAX_INTERVAL. Safe to call from a timer callback, on this system or on any other system of the same container. A timer added by one of this system's own timer callbacks is considered from the system's next update. From Update() the timer is added at once.
Thread: container thread only.
| void ecs::System::TimerClear | ( | const std::string & | name | ) |
Cancels every timer with this name.
Safe to call from a timer callback, including for the callback's own name. Cancelling and then adding the same name leaves only the new timer; adding and then cancelling removes both. From Update() the change takes effect at once.
Thread: container thread only.
|
inlinevirtual |
Called on each pass in which the system is due; override it with the system's work.
Thread: container thread only.
| void ecs::System::UpdateSystem | ( | ) |
Fires the timers that are due, then calls Update().
The container calls this on each pass in which the system is due.
The clock is read once, at the start, and that one reading decides which timers are due and sets the elapsed time of this update (see ElapsedGet()).
Timers are visited in the order they were added. A timer added by a callback does not fire in this call. A timer cleared by a callback and not yet reached does not fire. Afterwards exactly the one-shot timers that fired are removed, and the timer changes made by callbacks take effect before Update() runs. If a callback removes its own system, no further timers fire and Update() is not called. If a callback throws, the error is rethrown after the timer changes have completed. When the call is made by Container::Update(), the container also logs the error with the system's handle.
Thread: container thread only.
|
protected |
Lines logged before the system was registered, as (message, level) pairs in the order they were logged.
Container::System() delivers them. They are not capped: a system that logs without limit before it is registered holds them all in memory.
| ecs::TypeEntityComponentList* ecs::System::Components = nullptr |
The components of the system's container (Container::Components), or null before registration.
Thread: container thread only.
|
protected |
Components a subclass has marked for removal, as entity handles by type name.
A subclass fills it while it iterates Components and then calls componentsClear().
| ecs::Container* ecs::System::Container = nullptr |
The container the system is registered in, or null before registration.
Set by Container::System() only.
Thread: container thread only.
| const std::string ecs::System::Handle |
The system's handle, given to the constructor and never changed.
Thread: any.
|
protected |
The construction time.
Deprecated since 1.8.0 and not maintained by the library: use ElapsedGet().
|
protected |
Messages ready to read, oldest first.
Read them in Update() with front() and pop().
Thread: container thread only.
|
protected |
The system's timers.
Change them with TimerAdd() and TimerClear() only.
| ecs::Timing ecs::System::Timing |
The schedule that decides on which passes the system is updated.
Change the interval with Timing.SetInterval(); the default is ecs::DEFAULT_INTERVAL, about 30 updates a second.
Thread: container thread only.