use crate::config::planet::{Planet, PlanetBundle, PlanetConfigCollection}; use bevy::asset::Handle; use bevy::prelude::*; use bevy_rapier2d::dynamics::AdditionalMassProperties; use bevy_rapier2d::prelude::Collider; use bevy_replicon::prelude::Replicated; pub fn planets_plugin(app: &mut App) { app.init_resource::() .add_systems(Startup, start_loading_planets) .add_systems(Update, update_planets); } #[derive(Resource, Default)] pub struct PlanetConfigResource { handle: Option>, } fn start_loading_planets(assets: Res, mut planets: ResMut) { planets.handle = Some(assets.load("config/planets.pc.toml")); } pub fn update_planets( mut commands: Commands, mut ev_config: MessageReader>, assets: ResMut>, planets: ResMut, mut q_planets: Query<( Entity, &mut Planet, &mut Transform, &mut AdditionalMassProperties, )>, ) { let Some(handle) = planets.handle.as_ref() else { return; }; let waiting_for_asset_id = handle.id(); for ev in ev_config.read() { match ev { AssetEvent::Added { id } => { if *id == waiting_for_asset_id { debug!("planet config loaded - creating planets"); let planet_config = assets.get(*id).unwrap(); for planet in &planet_config.planets { commands .spawn(PlanetBundle { planet: planet.clone(), transform: Transform::from_xyz( planet.default_transform[0], planet.default_transform[1], planet.default_transform[2], ), collider: Collider::ball(planet.radius), additional_mass_properties: AdditionalMassProperties::Mass( planet.mass, ), }) .insert(Replicated); trace!(?planet, "new planet spawned"); } } } AssetEvent::Modified { id } => { if *id == waiting_for_asset_id { trace!("planet config modified - reloading planets"); let planet_config = assets.get(*id).unwrap(); for planet in &planet_config.planets { let existing_planet = q_planets .iter_mut() .find(|(_, p, _, _)| p.name == planet.name); if let Some((existing, mut e_planet, mut e_transform, mut e_mass)) = existing_planet { commands .entity(existing) .remove::() .insert(Collider::ball(planet.radius)); *e_planet = planet.clone(); e_transform.translation = Vec3::new( planet.default_transform[0], planet.default_transform[1], planet.default_transform[2], ); *e_mass = AdditionalMassProperties::Mass(planet.mass); trace!(?planet, "planet hot-reloaded"); } else { commands .spawn(PlanetBundle { planet: planet.clone(), transform: Transform::from_xyz( planet.default_transform[0], planet.default_transform[1], planet.default_transform[2], ), collider: Collider::ball(planet.radius), additional_mass_properties: AdditionalMassProperties::Mass( planet.mass, ), }) .insert(Replicated); trace!(?planet, "new planet spawned"); } } } } _ => {} } } }