overlord_event_system/
lib.rs

1pub use behaviors::BehaviorRegistry;
2pub use event_system::event::LogicalTimestamp;
3pub use event_system::net;
4pub use event_system::net::EventTimestamped;
5pub use event_system::random::Seed;
6pub use event_system::script::types::ConditionalProgress;
7pub use event_system::system::{
8    EventHandleResult, EventHandler, EventHandlerContext, EventMeta, SystemConfig,
9};
10
11use event_system::event::EventPluginized;
12use rand::SeedableRng;
13
14pub mod attributes;
15pub mod behaviors;
16pub mod bundles;
17pub mod cases;
18pub mod entities;
19pub mod event;
20pub mod fight;
21pub mod gacha;
22pub mod game_config_helpers;
23pub mod logic;
24pub mod mechanics;
25pub mod party;
26pub mod quests;
27pub mod state;
28
29/// DB-free handler over the pure game logic. Routes every event to
30/// `OverlordLogic`; used by tests and simulations through the synchronous
31/// `System::run`.
32pub struct PureEventHandler {
33    logic: logic::handler::OverlordLogic,
34}
35
36impl PureEventHandler {
37    pub fn new(logic: logic::handler::OverlordLogic) -> Self {
38        Self { logic }
39    }
40}
41
42impl EventHandler<event::OverlordEvent, state::OverlordState> for PureEventHandler {
43    type Context = ();
44
45    async fn create_context_for_batch(
46        &self,
47        _state: &state::OverlordState,
48    ) -> anyhow::Result<Self::Context> {
49        Ok(())
50    }
51
52    async fn handle_event(
53        &mut self,
54        _ctx: &Self::Context,
55        event: &event::OverlordEvent,
56        meta: EventMeta,
57        prev_state: &state::OverlordState,
58        state: state::OverlordState,
59    ) -> anyhow::Result<EventHandleResult<event::OverlordEvent, state::OverlordState>> {
60        // Historical async RNG stream: `with_ts` of the pre-increment
61        // timestamp. Former-sync bodies use `with_ts(logical_ts)`; the
62        // asymmetry is historical and may be unified later as an isolated
63        // change with deliberate test-expectation updates.
64        let rand_gen =
65            rand::rngs::StdRng::seed_from_u64(meta.session_seed.with_ts(meta.logical_ts - 1));
66        let mut result = self
67            .logic
68            .handle_event(event, state, rand_gen, meta.current_tick);
69
70        if *result.state() != *prev_state {
71            let (new_state, result_events) = result.state_and_events_mut();
72            let mut events: Vec<EventPluginized<event::OverlordEvent, state::OverlordState>> = self
73                .logic
74                .compute_fields(new_state, prev_state)
75                .into_iter()
76                .map(EventPluginized::now)
77                .collect();
78            events.append(result_events);
79            *result_events = events;
80        }
81
82        Ok(result)
83    }
84
85    fn compute_fields(
86        &self,
87        state: &mut state::OverlordState,
88        prev_state: &state::OverlordState,
89    ) -> Vec<event::OverlordEvent> {
90        self.logic.compute_fields(state, prev_state)
91    }
92
93    fn collect_due_scheduled(&mut self, current_tick: u64) -> Vec<event::OverlordEvent> {
94        self.logic.collect_due_scheduled(current_tick)
95    }
96
97    async fn finalize_state(
98        &self,
99        _ctx: &Self::Context,
100        _state: &mut state::OverlordState,
101    ) -> anyhow::Result<()> {
102        Ok(())
103    }
104
105    async fn persist_in_memory_state(
106        &self,
107        _ctx: &Self::Context,
108        _state: &state::OverlordState,
109    ) -> anyhow::Result<()> {
110        Ok(())
111    }
112}
113
114pub type System<H> = event_system::system::System<
115    event::OverlordEvent,
116    state::OverlordState,
117    H,
118    event_system::plugin::delayed::RealDelayedPlugin<event::OverlordEvent>,
119    event_system::plugin::cron::RealCronPlugin<event::OverlordEvent, state::OverlordState>,
120>;
121
122pub const TICKER_UNIT_DURATION_MS: u128 = 1;
123
124pub fn new_system<H>(handler: H, session_seed: Seed, zero_tick: bool) -> System<H>
125where
126    H: EventHandler<event::OverlordEvent, state::OverlordState>,
127{
128    System::new(
129        SystemConfig {
130            ticker_unit_duration_ms: if zero_tick {
131                0
132            } else {
133                TICKER_UNIT_DURATION_MS
134            },
135            ..Default::default()
136        },
137        handler,
138        state::OverlordState::default(),
139        session_seed,
140    )
141}