~starkingdoms/starkingdoms

ref: a85763a0e59339d07d2589197fb2a3985e3f92d0 starkingdoms/crates/unified/src/server/planets.rs -rw-r--r-- 4.4 KiB
a85763a0ghostly_zsh feat: orbit prediction 17 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use crate::config::planet::{Planet, PlanetBundle, PlanetConfigCollection};
use bevy::asset::Handle;
use crate::prelude::*;
use bevy_replicon::prelude::Replicated;

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: MessageReader<AssetEvent<PlanetConfigCollection>>,
    assets: ResMut<Assets<PlanetConfigCollection>>,
    planets: ResMut<PlanetConfigResource>,
    mut q_planets: Query<(
        Entity,
        &mut Planet,
        &mut Transform,
        &mut Mass,
    )>,
) {
    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::circle(planet.radius),
                                mass: 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::<Collider>()
                                .insert(Collider::circle(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 = 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::circle(planet.radius),
                                    mass: Mass(
                                        planet.mass,
                                    ),
                                })
                                .insert(Replicated);
                            trace!(?planet, "new planet spawned");
                        }
                    }
                }
            }
            _ => {}
        }
    }
}