diff --git a/Cargo.lock b/Cargo.lock index ab4ae79..3f5cf89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3129,7 +3129,7 @@ dependencies = [ [[package]] name = "maze-ascension" -version = "1.0.0" +version = "1.0.1" dependencies = [ "anyhow", "bevy", diff --git a/Cargo.toml b/Cargo.toml index fab3a80..f5d2266 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "maze-ascension" authors = ["Kristofers Solo "] -version = "1.0.0" +version = "1.0.1" edition = "2021" [dependencies] diff --git a/src/dev_tools/ui/maze_controls.rs b/src/dev_tools/ui/maze_controls.rs index 4c64dfc..4c3535f 100644 --- a/src/dev_tools/ui/maze_controls.rs +++ b/src/dev_tools/ui/maze_controls.rs @@ -1,7 +1,7 @@ use crate::{ floor::components::{CurrentFloor, Floor}, - maze::{components::MazeConfig, events::RespawnMaze, GlobalMazeConfig}, - player::events::RespawnPlayer, + maze::{commands::RespawnMaze, components::MazeConfig, GlobalMazeConfig}, + player::commands::RespawnPlayer, screens::Screen, }; use bevy::{prelude::*, window::PrimaryWindow}; @@ -72,11 +72,12 @@ pub fn maze_controls_ui(world: &mut World) { // Handle updates if changed { maze_config.update(&global_config); - world.trigger(RespawnMaze { + RespawnMaze { floor: floor_value, config: maze_config, - }); - world.trigger(RespawnPlayer); + } + .apply(world); + RespawnPlayer.apply(world); } } }); diff --git a/src/floor/systems/spawn.rs b/src/floor/systems/spawn.rs index 9cd6c42..308598b 100644 --- a/src/floor/systems/spawn.rs +++ b/src/floor/systems/spawn.rs @@ -6,10 +6,10 @@ use crate::{ events::TransitionFloor, resources::HighestFloor, }, - maze::{components::MazeConfig, events::SpawnMaze}, + maze::{commands::SpawnMaze, components::MazeConfig}, }; -pub(super) fn spawn_floor( +pub fn spawn_floor( mut commands: Commands, query: Query<(&mut Floor, &MazeConfig), (With, Without)>, mut event_reader: EventReader, @@ -21,7 +21,7 @@ pub(super) fn spawn_floor( for event in event_reader.read() { if current_floor.0 == 1 && *event == TransitionFloor::Descend { - warn!("Cannot descend below floor 1"); + info!("Cannot descend below floor 1"); return; } @@ -30,7 +30,7 @@ pub(super) fn spawn_floor( info!("Creating level for floor {}", target_floor); - commands.trigger(SpawnMaze { + commands.queue(SpawnMaze { floor: target_floor, config: MazeConfig { start_pos: config.end_pos, diff --git a/src/hint/mod.rs b/src/hint/mod.rs index a34f165..371febd 100644 --- a/src/hint/mod.rs +++ b/src/hint/mod.rs @@ -9,5 +9,5 @@ pub(super) fn plugin(app: &mut App) { } pub fn spawn_hint_command(world: &mut World) { - let _ = world.run_system_once(systems::setup::setup); + let _ = world.run_system_once(systems::spawn::spawn_hints); } diff --git a/src/hint/systems/mod.rs b/src/hint/systems/mod.rs index 1307108..b56e322 100644 --- a/src/hint/systems/mod.rs +++ b/src/hint/systems/mod.rs @@ -1,5 +1,5 @@ mod check; -pub mod setup; +pub mod spawn; use bevy::prelude::*; use check::check_player_hints; diff --git a/src/hint/systems/setup.rs b/src/hint/systems/spawn.rs similarity index 92% rename from src/hint/systems/setup.rs rename to src/hint/systems/spawn.rs index 6b08c17..1a095a2 100644 --- a/src/hint/systems/setup.rs +++ b/src/hint/systems/spawn.rs @@ -5,7 +5,7 @@ use crate::hint::{ components::{Hint, IdleTimer}, }; -pub fn setup(mut commands: Commands, hint_assets: Res) { +pub fn spawn_hints(mut commands: Commands, hint_assets: Res) { commands.spawn(( Name::new("Movement hint"), Hint::Movement, diff --git a/src/maze/commands.rs b/src/maze/commands.rs new file mode 100644 index 0000000..c1ea38f --- /dev/null +++ b/src/maze/commands.rs @@ -0,0 +1,49 @@ +use super::{ + components::MazeConfig, + systems::{despawn::despawn_maze, respawn::respawn_maze, spawn::spawn_maze}, +}; +use bevy::{ecs::system::RunSystemOnce, prelude::*}; + +#[derive(Debug, Reflect)] +pub struct SpawnMaze { + pub floor: u8, + pub config: MazeConfig, +} + +#[derive(Debug, Reflect)] +pub struct RespawnMaze { + pub floor: u8, + pub config: MazeConfig, +} + +#[derive(Debug, Reflect)] +pub struct DespawnMaze { + pub floor: u8, +} + +impl Default for SpawnMaze { + fn default() -> Self { + Self { + floor: 1, + config: MazeConfig::default(), + } + } +} + +impl Command for SpawnMaze { + fn apply(self, world: &mut World) { + let _ = world.run_system_once_with(self, spawn_maze); + } +} + +impl Command for RespawnMaze { + fn apply(self, world: &mut World) { + let _ = world.run_system_once_with(self, respawn_maze); + } +} + +impl Command for DespawnMaze { + fn apply(self, world: &mut World) { + let _ = world.run_system_once_with(self, despawn_maze); + } +} diff --git a/src/maze/events.rs b/src/maze/events.rs deleted file mode 100644 index ead86a9..0000000 --- a/src/maze/events.rs +++ /dev/null @@ -1,28 +0,0 @@ -use super::components::MazeConfig; -use bevy::prelude::*; - -#[derive(Debug, Reflect, Event)] -pub struct SpawnMaze { - pub floor: u8, - pub config: MazeConfig, -} - -#[derive(Debug, Reflect, Event)] -pub struct RespawnMaze { - pub floor: u8, - pub config: MazeConfig, -} - -#[derive(Debug, Reflect, Event)] -pub struct DespawnMaze { - pub floor: u8, -} - -impl Default for SpawnMaze { - fn default() -> Self { - Self { - floor: 1, - config: MazeConfig::default(), - } - } -} diff --git a/src/maze/mod.rs b/src/maze/mod.rs index 5f2abc1..648f171 100644 --- a/src/maze/mod.rs +++ b/src/maze/mod.rs @@ -1,25 +1,19 @@ mod assets; +pub mod commands; pub mod components; pub mod errors; -pub mod events; pub mod resources; mod systems; -mod triggers; -use bevy::{ecs::system::RunSystemOnce, prelude::*}; -use components::HexMaze; -use events::{DespawnMaze, RespawnMaze, SpawnMaze}; +use bevy::prelude::*; +use commands::SpawnMaze; pub use resources::GlobalMazeConfig; pub(super) fn plugin(app: &mut App) { app.init_resource::() - .add_event::() - .add_event::() - .add_event::() - .register_type::() - .add_plugins((systems::plugin, triggers::plugin)); + .add_plugins(systems::plugin); } pub fn spawn_level_command(world: &mut World) { - let _ = world.run_system_once(systems::setup::setup); + SpawnMaze::default().apply(world); } diff --git a/src/maze/triggers/common.rs b/src/maze/systems/common.rs similarity index 100% rename from src/maze/triggers/common.rs rename to src/maze/systems/common.rs diff --git a/src/maze/triggers/despawn.rs b/src/maze/systems/despawn.rs similarity index 71% rename from src/maze/triggers/despawn.rs rename to src/maze/systems/despawn.rs index 15f8700..06e12df 100644 --- a/src/maze/triggers/despawn.rs +++ b/src/maze/systems/despawn.rs @@ -2,18 +2,17 @@ //! //! Module handles the cleanup of maze entities when they need to be removed, //! ensuring proper cleanup of both the maze and all its child entities. -use crate::{floor::components::Floor, maze::events::DespawnMaze}; +use crate::{floor::components::Floor, maze::commands::DespawnMaze}; use bevy::prelude::*; /// Despawns a maze and all its associated entities for a given floor. pub fn despawn_maze( - trigger: Trigger, + In(DespawnMaze { floor }): In, mut commands: Commands, query: Query<(Entity, &Floor)>, ) { - let DespawnMaze { floor } = trigger.event(); - match query.iter().find(|(_, f)| f.0 == *floor) { + match query.iter().find(|(_, f)| f.0 == floor) { Some((entity, _)) => commands.entity(entity).despawn_recursive(), _ => warn!("Floor {} not found for removal", floor), } diff --git a/src/maze/systems/mod.rs b/src/maze/systems/mod.rs index 554515c..8def9f0 100644 --- a/src/maze/systems/mod.rs +++ b/src/maze/systems/mod.rs @@ -1,4 +1,7 @@ -pub mod setup; +pub mod common; +pub mod despawn; +pub mod respawn; +pub mod spawn; use bevy::prelude::*; diff --git a/src/maze/triggers/respawn.rs b/src/maze/systems/respawn.rs similarity index 82% rename from src/maze/triggers/respawn.rs rename to src/maze/systems/respawn.rs index ac9bc47..58db5fc 100644 --- a/src/maze/triggers/respawn.rs +++ b/src/maze/systems/respawn.rs @@ -3,14 +3,15 @@ //! Module provides the ability to regenerate mazes for existing floors, //! maintaining the same floor entity but replacing its internal maze structure. -use super::{common::generate_maze, spawn::spawn_maze_tiles}; use crate::{ floor::components::Floor, - maze::{assets::MazeAssets, errors::MazeError, events::RespawnMaze, GlobalMazeConfig}, + maze::{assets::MazeAssets, commands::RespawnMaze, errors::MazeError, GlobalMazeConfig}, }; use bevy::prelude::*; use hexlab::Maze; +use super::{common::generate_maze, spawn::spawn_maze_tiles}; + /// Respawns a maze for an existing floor with a new configuration. /// /// # Behavior: @@ -20,19 +21,17 @@ use hexlab::Maze; /// - Spawns new maze tiles /// - Updates the floor's configuration pub fn respawn_maze( - trigger: Trigger, + In(RespawnMaze { floor, config }): In, mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, mut maze_query: Query<(Entity, &Floor, &mut Maze)>, global_config: Res, ) { - let RespawnMaze { floor, config } = trigger.event(); - let (entity, _, mut maze) = match maze_query .iter_mut() - .find(|(_, f, _)| f.0 == *floor) - .ok_or(MazeError::FloorNotFound(*floor)) + .find(|(_, f, _)| f.0 == floor) + .ok_or(MazeError::FloorNotFound(floor)) { Ok((entity, floor, maze)) => (entity, floor, maze), Err(e) => { @@ -41,7 +40,7 @@ pub fn respawn_maze( } }; - *maze = match generate_maze(config) { + *maze = match generate_maze(&config) { Ok(generated_maze) => generated_maze, Err(e) => { warn!("Failed to update floor ({floor}). {e}"); @@ -56,7 +55,7 @@ pub fn respawn_maze( entity, &maze, &assets, - config, + &config, &global_config, ); diff --git a/src/maze/systems/setup.rs b/src/maze/systems/setup.rs deleted file mode 100644 index 42fe9fe..0000000 --- a/src/maze/systems/setup.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::maze::events::SpawnMaze; -use bevy::prelude::*; - -pub fn setup(mut commands: Commands) { - commands.trigger(SpawnMaze::default()); -} diff --git a/src/maze/triggers/spawn.rs b/src/maze/systems/spawn.rs similarity index 92% rename from src/maze/triggers/spawn.rs rename to src/maze/systems/spawn.rs index 63e1c68..b33f932 100644 --- a/src/maze/triggers/spawn.rs +++ b/src/maze/systems/spawn.rs @@ -11,8 +11,8 @@ use crate::{ }, maze::{ assets::MazeAssets, + commands::SpawnMaze, components::{HexMaze, MazeConfig, Tile, Wall}, - events::SpawnMaze, resources::GlobalMazeConfig, }, screens::Screen, @@ -26,7 +26,7 @@ use std::f32::consts::{FRAC_PI_2, FRAC_PI_3, FRAC_PI_6}; /// Spawns a new maze for the specified floor on [`SpawnMaze`] event. pub fn spawn_maze( - trigger: Trigger, + In(SpawnMaze { floor, config }): In, mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, @@ -34,14 +34,12 @@ pub fn spawn_maze( global_config: Res, mut event_writer: EventWriter, ) { - let SpawnMaze { floor, config } = trigger.event(); - - if maze_query.iter().any(|(_, f, _)| f.0 == *floor) { - warn!("Floor {} already exists, skipping creation", floor); + if maze_query.iter().any(|(_, f, _)| f.0 == floor) { + info!("Floor {} already exists, skipping creation", floor); return; } - let maze = match generate_maze(config) { + let maze = match generate_maze(&config) { Ok(m) => m, Err(e) => { error!("Failed to generate maze for floor {floor}: {:?}", e); @@ -50,7 +48,7 @@ pub fn spawn_maze( }; // Calculate vertical offset based on floor number - let y_offset = match *floor { + let y_offset = match floor { 1 => 0, // Ground/Initial floor (floor 1) is at y=0 _ => FLOOR_Y_OFFSET, // Other floors are offset vertically } as f32; @@ -60,13 +58,13 @@ pub fn spawn_maze( Name::new(format!("Floor {}", floor)), HexMaze, maze.clone(), - Floor(*floor), + Floor(floor), config.clone(), Transform::from_translation(Vec3::ZERO.with_y(y_offset)), Visibility::Visible, StateScoped(Screen::Gameplay), )) - .insert_if(CurrentFloor, || *floor == 1) // Only floor 1 gets CurrentFloor + .insert_if(CurrentFloor, || floor == 1) // Only floor 1 gets CurrentFloor .id(); let assets = MazeAssets::new(&mut meshes, &mut materials, &global_config); @@ -75,12 +73,12 @@ pub fn spawn_maze( entity, &maze, &assets, - config, + &config, &global_config, ); // TODO: find a better way to handle double event indirection - if *floor != 1 { + if floor != 1 { event_writer.send(TransitionFloor::Ascend); } } diff --git a/src/maze/triggers/mod.rs b/src/maze/triggers/mod.rs deleted file mode 100644 index 657f989..0000000 --- a/src/maze/triggers/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub mod common; -mod despawn; -mod respawn; -mod spawn; - -use bevy::prelude::*; -use despawn::despawn_maze; -use respawn::respawn_maze; -use spawn::spawn_maze; - -pub(super) fn plugin(app: &mut App) { - app.add_observer(spawn_maze) - .add_observer(respawn_maze) - .add_observer(despawn_maze); -} diff --git a/src/player/commands.rs b/src/player/commands.rs new file mode 100644 index 0000000..fcebafd --- /dev/null +++ b/src/player/commands.rs @@ -0,0 +1,30 @@ +use bevy::{ecs::system::RunSystemOnce, prelude::*}; + +use super::systems::{despawn::despawn_players, respawn::respawn_player, spawn::spawn_player}; + +#[derive(Debug, Reflect)] +pub struct SpawnPlayer; + +#[derive(Debug, Reflect)] +pub struct RespawnPlayer; + +#[derive(Debug, Reflect)] +pub struct DespawnPlayer; + +impl Command for SpawnPlayer { + fn apply(self, world: &mut World) { + let _ = world.run_system_once(spawn_player); + } +} + +impl Command for RespawnPlayer { + fn apply(self, world: &mut World) { + let _ = world.run_system_once(respawn_player); + } +} + +impl Command for DespawnPlayer { + fn apply(self, world: &mut World) { + let _ = world.run_system_once(despawn_players); + } +} diff --git a/src/player/events.rs b/src/player/events.rs deleted file mode 100644 index 953c8c9..0000000 --- a/src/player/events.rs +++ /dev/null @@ -1,10 +0,0 @@ -use bevy::prelude::*; - -#[derive(Debug, Event)] -pub struct SpawnPlayer; - -#[derive(Debug, Event)] -pub struct RespawnPlayer; - -#[derive(Debug, Event)] -pub struct DespawnPlayer; diff --git a/src/player/mod.rs b/src/player/mod.rs index 6414c08..90a4592 100644 --- a/src/player/mod.rs +++ b/src/player/mod.rs @@ -1,25 +1,20 @@ mod assets; +pub mod commands; pub mod components; -pub mod events; mod systems; -mod triggers; use assets::PlayerAssets; use bevy::{ecs::system::RunSystemOnce, prelude::*}; use components::Player; -use events::{DespawnPlayer, RespawnPlayer, SpawnPlayer}; use crate::asset_tracking::LoadResource; pub(super) fn plugin(app: &mut App) { app.register_type::() .load_resource::() - .add_event::() - .add_event::() - .add_event::() - .add_plugins((triggers::plugin, systems::plugin)); + .add_plugins(systems::plugin); } pub fn spawn_player_command(world: &mut World) { - let _ = world.run_system_once(systems::setup::setup); + let _ = world.run_system_once(systems::spawn::spawn_player); } diff --git a/src/player/systems/despawn.rs b/src/player/systems/despawn.rs new file mode 100644 index 0000000..5ef6191 --- /dev/null +++ b/src/player/systems/despawn.rs @@ -0,0 +1,8 @@ +use crate::player::components::Player; +use bevy::prelude::*; + +pub fn despawn_players(mut commands: Commands, query: Query>) { + for entity in query.iter() { + commands.entity(entity).despawn_recursive(); + } +} diff --git a/src/player/systems/mod.rs b/src/player/systems/mod.rs index ae65cb4..4b15cc5 100644 --- a/src/player/systems/mod.rs +++ b/src/player/systems/mod.rs @@ -1,7 +1,9 @@ +pub mod despawn; mod input; mod movement; -pub mod setup; +pub mod respawn; mod sound_effect; +pub mod spawn; mod vertical_transition; use crate::{screens::Screen, AppSet}; diff --git a/src/player/systems/respawn.rs b/src/player/systems/respawn.rs new file mode 100644 index 0000000..2813672 --- /dev/null +++ b/src/player/systems/respawn.rs @@ -0,0 +1,7 @@ +use crate::player::commands::{DespawnPlayer, SpawnPlayer}; +use bevy::prelude::*; + +pub fn respawn_player(mut commands: Commands) { + commands.queue(DespawnPlayer); + commands.queue(SpawnPlayer); +} diff --git a/src/player/systems/setup.rs b/src/player/systems/setup.rs deleted file mode 100644 index 12157dd..0000000 --- a/src/player/systems/setup.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::player::events::SpawnPlayer; -use bevy::prelude::*; - -pub fn setup(mut commands: Commands) { - commands.trigger(SpawnPlayer); -} diff --git a/src/player/triggers/spawn.rs b/src/player/systems/spawn.rs similarity index 92% rename from src/player/triggers/spawn.rs rename to src/player/systems/spawn.rs index 00bbdd0..636572e 100644 --- a/src/player/triggers/spawn.rs +++ b/src/player/systems/spawn.rs @@ -4,14 +4,12 @@ use crate::{ player::{ assets::{blue_material, generate_pill_mesh}, components::{CurrentPosition, Player}, - events::SpawnPlayer, }, screens::Screen, }; use bevy::prelude::*; -pub(super) fn spawn_player( - _trigger: Trigger, +pub fn spawn_player( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, diff --git a/src/player/triggers/despawn.rs b/src/player/triggers/despawn.rs deleted file mode 100644 index 417b572..0000000 --- a/src/player/triggers/despawn.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::player::{components::Player, events::DespawnPlayer}; -use bevy::prelude::*; - -pub(super) fn despawn_players( - _trigger: Trigger, - mut commands: Commands, - query: Query>, -) { - for entity in query.iter() { - commands.entity(entity).despawn_recursive(); - } -} diff --git a/src/player/triggers/mod.rs b/src/player/triggers/mod.rs deleted file mode 100644 index fc1d3dc..0000000 --- a/src/player/triggers/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -mod despawn; -mod respawn; -mod spawn; - -use bevy::prelude::*; -use despawn::despawn_players; -use respawn::respawn_player; -use spawn::spawn_player; - -pub(super) fn plugin(app: &mut App) { - app.add_observer(spawn_player) - .add_observer(respawn_player) - .add_observer(despawn_players); -} diff --git a/src/player/triggers/respawn.rs b/src/player/triggers/respawn.rs deleted file mode 100644 index 6c83923..0000000 --- a/src/player/triggers/respawn.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::player::events::{DespawnPlayer, RespawnPlayer, SpawnPlayer}; -use bevy::prelude::*; - -pub(super) fn respawn_player(_trigger: Trigger, mut commands: Commands) { - commands.trigger(DespawnPlayer); - commands.trigger(SpawnPlayer); -}