mirror of
https://github.com/kristoferssolo/maze-ascension.git
synced 2025-10-21 19:20:34 +00:00
refactor(maze): remove triggers and observers
This commit is contained in:
parent
b64930ed9e
commit
77407f7a90
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
floor::components::{CurrentFloor, Floor},
|
||||
maze::{components::MazeConfig, events::RespawnMaze, GlobalMazeConfig},
|
||||
maze::{commands::RespawnMaze, components::MazeConfig, GlobalMazeConfig},
|
||||
player::events::RespawnPlayer,
|
||||
screens::Screen,
|
||||
};
|
||||
@ -72,10 +72,11 @@ 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,
|
||||
});
|
||||
}
|
||||
.apply(world);
|
||||
world.trigger(RespawnPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::{
|
||||
events::TransitionFloor,
|
||||
resources::HighestFloor,
|
||||
},
|
||||
maze::{components::MazeConfig, events::SpawnMaze},
|
||||
maze::{commands::SpawnMaze, components::MazeConfig},
|
||||
};
|
||||
|
||||
pub(super) fn spawn_floor(
|
||||
@ -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,
|
||||
|
||||
49
src/maze/commands.rs
Normal file
49
src/maze/commands.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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::<GlobalMazeConfig>()
|
||||
.add_event::<SpawnMaze>()
|
||||
.add_event::<RespawnMaze>()
|
||||
.add_event::<DespawnMaze>()
|
||||
.register_type::<HexMaze>()
|
||||
.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);
|
||||
}
|
||||
|
||||
@ -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<DespawnMaze>,
|
||||
In(DespawnMaze { floor }): In<DespawnMaze>,
|
||||
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),
|
||||
}
|
||||
@ -1,4 +1,7 @@
|
||||
pub mod setup;
|
||||
pub mod common;
|
||||
pub mod despawn;
|
||||
pub mod respawn;
|
||||
pub mod spawn;
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
|
||||
@ -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<RespawnMaze>,
|
||||
In(RespawnMaze { floor, config }): In<RespawnMaze>,
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
mut maze_query: Query<(Entity, &Floor, &mut Maze)>,
|
||||
global_config: Res<GlobalMazeConfig>,
|
||||
) {
|
||||
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,
|
||||
);
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
use crate::maze::events::SpawnMaze;
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub fn setup(mut commands: Commands) {
|
||||
commands.trigger(SpawnMaze::default());
|
||||
}
|
||||
@ -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<SpawnMaze>,
|
||||
In(SpawnMaze { floor, config }): In<SpawnMaze>,
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
@ -34,14 +34,12 @@ pub fn spawn_maze(
|
||||
global_config: Res<GlobalMazeConfig>,
|
||||
mut event_writer: EventWriter<TransitionFloor>,
|
||||
) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user