use crate::apogee_core_v1::apogee_condition_v1; use crate::ecs; use bevy_ecs::prelude::*; use std::collections::HashSet; use std::sync; #[derive(Component, Debug, Clone, Copy, PartialEq, Eq)] pub struct Condition; #[derive(Component)] pub struct Name(pub sync::Arc); #[derive(Component)] pub struct Fulfilled; #[derive(Component, Debug, Clone, Copy, PartialEq, Eq)] pub struct Immutable(pub bool); #[derive(Component, Default)] pub struct Objects(pub Vec); #[derive(Bundle)] pub struct Bundle { pub marker: Condition, pub name: Name, pub immutable: Immutable, pub objects: Objects, } pub fn spawn( commands: &mut Commands, conditions: &mut ecs::ConditionRegistry, managers: &ecs::Managers, name: sync::Arc, immutable: bool, ) -> Entity { let entity = commands .spawn(Bundle { marker: Condition, name: Name(sync::Arc::clone(&name)), immutable: Immutable(immutable), objects: Objects::default(), }) .id(); conditions.by_name.insert(sync::Arc::clone(&name), entity); managers.condition_added(&name); entity } pub fn resolve( commands: &mut Commands, conditions: &mut ecs::ConditionRegistry, managers: &ecs::Managers, name: sync::Arc, immutable: bool, ) -> Entity { if let Some(entity) = conditions.by_name.get(&name).copied() { if immutable { commands.entity(entity).insert(Immutable(true)); } entity } else { spawn(commands, conditions, managers, name, immutable) } } pub fn sync_objects( mut removed_fulfilled: RemovedComponents, changed_fulfilled: Query>, mut conditions: Query< ( Entity, Ref, Ref, Has, &mut Objects, ), With, >, ) { let mut fulfillment_changed = removed_fulfilled.read().collect::>(); fulfillment_changed.extend(changed_fulfilled.iter()); for (entity, name, immutable, fulfilled, mut objects) in &mut conditions { objects .bypass_change_detection() .0 .retain(|object| object.try_client().is_some()); if objects.is_changed() { for object in &objects.0 { object.send_name(&name.0); object.send_fulfilled(u32::from(fulfilled)); object.send_can_modify(u32::from(!immutable.0)); object.send_done(); } continue; } for object in &objects.0 { if name.is_changed() { object.send_name(&name.0); } if fulfillment_changed.contains(&entity) { object.send_fulfilled(u32::from(fulfilled)); } if immutable.is_changed() { object.send_can_modify(u32::from(!immutable.0)); } object.send_done(); } } } impl hyprwire::Dispatch for crate::Apogee { fn event( &mut self, object: &apogee_condition_v1::ApogeeConditionV1, event: ::Event<'_>, ) { let Some(condition) = self .world .resource_mut::() .by_object .get(object) .copied() else { return; }; match event { apogee_condition_v1::Event::Start => { self.world.trigger(Start { entity: condition, object: object.clone(), }); } apogee_condition_v1::Event::Stop => { self.world.trigger(Stop { entity: condition, object: object.clone(), }); } } } } #[derive(Event)] pub struct Stop { entity: Entity, object: apogee_condition_v1::ApogeeConditionV1, } pub fn handle_stop( stop: On, mut commands: Commands, conditions: Query<&Immutable, With>, ) { let Ok(immutable) = conditions.get(stop.entity) else { stop.object.send_error( crate::apogee_core_v1::StartError::NotFound, "condition was not found", ); return; }; if immutable.0 { stop.object.send_error( crate::apogee_core_v1::StartError::Immutable, "condition cannot be modified manually", ); return; } commands.entity(stop.entity).remove::(); stop.object.send_ok(); } #[derive(Event)] pub struct Start { entity: Entity, object: apogee_condition_v1::ApogeeConditionV1, } pub fn handle_start( start: On, mut commands: Commands, conditions: Query<&Immutable, With>, ) { let Ok(immutable) = conditions.get(start.entity) else { start.object.send_error( crate::apogee_core_v1::StartError::NotFound, "condition was not found", ); return; }; if immutable.0 { start.object.send_error( crate::apogee_core_v1::StartError::Immutable, "condition cannot be modified manually", ); return; } commands.entity(start.entity).insert(Fulfilled); start.object.send_ok(); }