use bevy::asset::Handle;
use bevy::prelude::*;
use bevy_rapier2d::dynamics::AdditionalMassProperties;
use bevy_rapier2d::prelude::Collider;
use bevy_replicon::prelude::Replicated;
use crate::config::planet::{Planet, PlanetBundle, PlanetConfigCollection};
pub fn planets_plugin(app: &mut App) {
app
.init_resource::<PlanetConfigResource>()
.add_systems(Startup, start_loading_planets)
.add_systems(Update, update_planets);
}
#[derive(Resource, Default)]
pub struct PlanetConfigResource {
handle: Option<Handle<PlanetConfigCollection>>
}
fn start_loading_planets(assets: Res<AssetServer>, mut planets: ResMut<PlanetConfigResource>) {
planets.handle = Some(assets.load("config/planets.pc.toml"));
}
pub fn update_planets(
mut commands: Commands,
mut ev_config: EventReader<AssetEvent<PlanetConfigCollection>>,
mut assets: ResMut<Assets<PlanetConfigCollection>>,
mut planets: ResMut<PlanetConfigResource>,
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 {
info!("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);
info!(?planet, "new planet spawned");
}
}
},
AssetEvent::Modified { id } => {
if *id == waiting_for_asset_id {
info!("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::<Collider>()
.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);
info!(?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);
info!(?planet, "new planet spawned");
}
}
}
},
_ => {}
}
}
}