~starkingdoms/starkingdoms

ref: b072b09c00e6892310c6ee9187f441e95ae89ccf starkingdoms/crates/unified/src/server/part.rs -rw-r--r-- 3.1 KiB
b072b09c — core feat: part & attachment beginnings 5 months 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
use bevy::asset::Handle;
use bevy::prelude::*;
use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider};
use crate::config::part::PartConfig;
use crate::ecs::Part;

pub fn part_config_plugin(app: &mut App) {
    app.add_systems(PreUpdate, handle_spawn_part_requests)
        .add_systems(Update, (update_part_requests, hotreload));
}

#[derive(Component, Debug)]
pub struct SpawnPart(pub String);
#[derive(Component)]
struct LoadingPart(Handle<PartConfig>);
#[derive(Component, Debug)]
struct PartType(AssetId<PartConfig>);

// watch for new SpawnPart components and start loading their config files
fn handle_spawn_part_requests(new_parts: Query<(Entity, &SpawnPart), Added<SpawnPart>>, mut commands: Commands, asset_server: Res<AssetServer>) {
    for (new_part, request) in &new_parts {
        info!(?new_part, ?request, "answering part request");
        commands.entity(new_part)
            .remove::<SpawnPart>()
            .insert(LoadingPart(asset_server.load(request.0.clone())));
    }
}
fn update_part_requests(
    mut ev_config: EventReader<AssetEvent<PartConfig>>,
    loading_parts: Query<(Entity, &LoadingPart)>,
    assets: ResMut<Assets<PartConfig>>,
    mut commands: Commands
) {
    for ev in ev_config.read() {
        match ev {
            AssetEvent::Added { id } => {
                info!(?id, "asset added");
                for (loading_part, req) in &loading_parts {
                    if req.0.id() == *id {
                        let Some(asset) = assets.get(*id) else { continue; };
                        spawn_part(commands.reborrow(), loading_part, asset, id);
                    }
                }
            },
            AssetEvent::Modified { id } => {
                warn!("asset modification missed!");
            }
            _ => {}
        }
    }
}
fn hotreload(
    mut ev_config: EventReader<AssetEvent<PartConfig>>,
    existing_parts: Query<(Entity, &PartType)>,
    assets: ResMut<Assets<PartConfig>>,
    mut commands: Commands
) {
    for ev in ev_config.read() {
        match ev {
            AssetEvent::Modified { id } => {
                info!(?id, "updating part");
                for (existing_part, ptype) in &existing_parts {
                    if ptype.0 == *id {
                        let Some(asset) = assets.get(ptype.0) else { continue; };
                        spawn_part(commands.reborrow(), existing_part, asset, id);
                    }
                }
            }
            AssetEvent::Added { id } => {
                warn!("asset addition missed!");
            }
            _ => {}
        }
    }
}

fn spawn_part(mut commands: Commands, entity: Entity, part: &PartConfig, id: &AssetId<PartConfig>) {
    commands.entity(entity)
        .remove::<LoadingPart>()
        .insert(Part {
            sprite: part.part.sprite_disconnected.clone(),
            width: part.physics.width,
            height: part.physics.height,
            mass: part.physics.mass,
        })
        .insert(Collider::cuboid(part.physics.width / 2.0, part.physics.height / 2.0))
        .insert(AdditionalMassProperties::Mass(part.physics.mass))
        .insert(PartType(*id));
}