issun_bevy/
lib.rs

1//! ISSUN Bevy Plugins
2//!
3//! Unit-testable game logic plugins for Bevy ECS.
4
5use bevy::prelude::*;
6
7pub mod plugins;
8
9/// ISSUN common system execution order (Phase 1: Simple 4-stage pipeline)
10#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
11pub enum IssunSet {
12    /// Input processing (user input, network receive)
13    Input,
14
15    /// Main logic (combat, economy, AI)
16    /// ⚠️ Phase 1: Most processing goes here
17    Logic,
18
19    /// Post-logic processing (death checks, cleanup)
20    PostLogic,
21
22    /// Visual sync (TUI updates, network send)
23    Visual,
24}
25
26/// Marker resource indicating IssunCorePlugin is installed
27///
28/// Used by other issun-bevy plugins to verify IssunCorePlugin dependency.
29#[derive(Resource)]
30pub struct IssunCorePluginMarker;
31
32/// ISSUN Core Plugin (configures SystemSet ordering once)
33///
34/// ## Usage Example
35///
36/// ```no_run
37/// use bevy::prelude::*;
38/// use issun_bevy::IssunCorePlugin;
39///
40/// App::new()
41///     .add_plugins(IssunCorePlugin)  // ← Add first
42///     .run();
43/// ```
44pub struct IssunCorePlugin;
45
46impl Plugin for IssunCorePlugin {
47    fn build(&self, app: &mut App) {
48        // Register marker resource for dependency checking
49        app.insert_resource(IssunCorePluginMarker);
50
51        // Configure SystemSet ordering
52        app.configure_sets(
53            Update,
54            (
55                IssunSet::Input,
56                IssunSet::Logic,
57                IssunSet::PostLogic,
58                IssunSet::Visual,
59            )
60                .chain(),
61        );
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_issun_core_plugin() {
71        let mut app = App::new();
72        app.add_plugins(MinimalPlugins);
73        app.add_plugins(IssunCorePlugin);
74
75        // Verify SystemSet configuration
76        app.update();
77    }
78
79    #[test]
80    fn test_system_set_ordering() {
81        use std::sync::{Arc, Mutex};
82
83        let execution_order = Arc::new(Mutex::new(Vec::new()));
84
85        let mut app = App::new();
86        app.add_plugins(MinimalPlugins);
87        app.add_plugins(IssunCorePlugin);
88
89        // Add systems for each SystemSet
90        let order1 = execution_order.clone();
91        app.add_systems(
92            Update,
93            (move || {
94                order1.lock().unwrap().push("Input");
95            })
96            .in_set(IssunSet::Input),
97        );
98
99        let order2 = execution_order.clone();
100        app.add_systems(
101            Update,
102            (move || {
103                order2.lock().unwrap().push("Logic");
104            })
105            .in_set(IssunSet::Logic),
106        );
107
108        let order3 = execution_order.clone();
109        app.add_systems(
110            Update,
111            (move || {
112                order3.lock().unwrap().push("PostLogic");
113            })
114            .in_set(IssunSet::PostLogic),
115        );
116
117        let order4 = execution_order.clone();
118        app.add_systems(
119            Update,
120            (move || {
121                order4.lock().unwrap().push("Visual");
122            })
123            .in_set(IssunSet::Visual),
124        );
125
126        // Execute
127        app.update();
128
129        // Verify execution order
130        let order = execution_order.lock().unwrap();
131        assert_eq!(
132            *order,
133            vec!["Input", "Logic", "PostLogic", "Visual"],
134            "SystemSet execution order is incorrect"
135        );
136    }
137}