Frame Lifecycle
The Plantangenet runtime coordinates via a clock-driven FrameManager managing a series of deterministic FramePhase steps per tick.
This explicit stage progression guarantees predictable dispatch of our WorldContext services, eliminating race conditions while enforcing an "update then read-drain" loop.
Phase Progression
A clock step (tick) advances the FrameManager from Idle through its active phases, eventually returning it to Idle.
stateDiagram-v2
direction LR
Idle --> BeginningFrame: begin_frame()
BeginningFrame --> Servicing
Servicing --> Active
Active --> Aggregation
Aggregation --> EndingFrame: end_frame()
EndingFrame --> Idle
note right of BeginningFrame : on_frame_init
note right of Active : on_frame_active
note right of Aggregation : on_frame_aggregation
note right of EndingFrame : on_frame_cleanup
Phase Permissions and Service Triggers
Not all FramePhases execute mutations or drive services. Below is the behavioral reference table for phase-aligned triggers.
| Phase | Mutations Allowed | Services Fire | Notes |
|---|---|---|---|
| Idle | yes | none | Safe state between frames, mutations apply immediately. |
| BeginningFrame | no | on_frame_init |
Setup/Housekeeping tasks only. |
| Servicing | yes | none (deferred) | In the future: Obligation payments, skippable. |
| Active | yes | Tier 1 (hob, deform) | Core simulation loop runs. Mutations occur. |
| Aggregation | no | Tier 2 (road/inv/ach) | Drains queues/events produced during Active phase. |
| EndingFrame | no | on_frame_cleanup |
Read-only bookkeeping. |
:::info Soft / Hard Close
During end_frame(), there are internal LifecycleHook transitions for OnFrameSoftClose and OnFrameHardClose. These are skipped by most services, but may be used by the string-keyed HookDispatcher system for internal callback cleanup.
:::
Concrete Example: Clock Tick
When the server runs with a fixed interval (e.g. set_interval(100ms)), what exactly happens on that clock tick?
- Tick initiates:
FrameManagerasserts it is currently in theIdlephase. begin_frame(None)is invoked.- Phase
BeginningFrame: Dispatcher fireson_frame_initglobally. - Phase
Servicing: (ifenable_servicingconfig is true). Currently, no simulation services mutate here. - Phase
Active: Tier 1 services (HobService,DeformationService) grab their execution budgets.HobServiceflushes its batch queue, callingmove_hobmutations, which stamp records forDeformation. - (
begin_framecompletes, returning theFrameId).end_frame()is immediately invoked by the clock task. - Phase
Aggregation: Tier 2 services (RoadService,InventoryService,AchievementService) iterate over newly appended events and drain them completely. - Phase
EndingFrame: Drains the internal memory pools and calculates systemDustAmountconservation (if configured).on_frame_cleanupis dispatched. - Return to
Idle: TheFrameManagerreturns toIdle, waiting for the next 100ms scheduled tick.