Skip to main content

concinnity_core/ecs/
system_entry.rs

1//! The system table a host hands [`World::start`](crate::ecs::World::start):
2//! one entry per system in run order, plus the load-time passes that bracket
3//! them.
4//!
5//! The table is a document. Table order is run order, and the `after` / `before`
6//! edges are checked against it rather than resolved into one, so a reader can
7//! take the file top to bottom as the tick. What builds the systems is a gate
8//! per entry: it inspects the world's content and returns the constructed
9//! system, or `None` to leave it out.
10
11use alloc::boxed::Box;
12
13use crate::ecs::{Access, EventStore, PipelineContext, System, World};
14use crate::result::CnResult;
15
16/// One row of the system table. Table order is run order.
17pub struct SystemEntry {
18    /// The entry name; the system's stable display name.
19    pub name: &'static str,
20    /// Human-readable gate condition, for docs and CLI reporting.
21    pub present_when: &'static str,
22    /// Constructs the system from world content when its gate holds. Runs from
23    /// `World::start` and from `World::system_manifest`, which discards the
24    /// value, so a system's constructor must stay cheap and side-effect-free.
25    pub gate: fn(&World) -> Option<Box<dyn System>>,
26    /// Systems (by entry name) that must run earlier in the tick than this one.
27    /// Validated against table order at schedule build: the table stays the one
28    /// execution order, and an edge that contradicts it is a startup panic, not
29    /// a silent reorder.
30    pub after: &'static [&'static str],
31    /// Systems this one must run before.
32    pub before: &'static [&'static str],
33}
34
35/// A host's completion pass: it runs over the world before the gates read it,
36/// and fails the start when the world cannot be completed.
37pub type CompleteWorld = fn(&mut PipelineContext) -> Result<(), CnResult>;
38
39/// A host's system table and the load-time passes only the host can supply.
40///
41/// The entries name the host's own system types, so the table is written where
42/// those types live; everything that runs it is here.
43pub struct SystemTable {
44    /// One entry per system, in run order.
45    pub entries: &'static [SystemEntry],
46    /// Runs over the world before the gates read it, so a component the pass
47    /// injects can still bring its system into the schedule. Absent leaves the
48    /// world exactly as it was loaded.
49    pub complete_world: Option<CompleteWorld>,
50    /// Runs over the world once its systems are built and before their `init`.
51    /// Absent leaves the loaded content exactly as it was added.
52    pub before_init: Option<fn(&mut PipelineContext)>,
53    /// Pre-creates the event queues a scheduled system's declared access can
54    /// touch, so its `events_mut` never grows the store's map mid-tick. Absent
55    /// leaves every queue to be created on first use.
56    pub prepare_events: Option<fn(&mut EventStore, Access)>,
57}
58
59impl SystemTable {
60    /// A table with no systems and no load-time passes: what a world runs when
61    /// its host contributes none.
62    pub const EMPTY: Self = Self {
63        entries: &[],
64        complete_world: None,
65        before_init: None,
66        prepare_events: None,
67    };
68}