~starkingdoms/starkingdoms

ref: d93da738ce01cdab35e6a50c7f1eceadfb08d406 starkingdoms/crates/unified/src/server/part.rs -rw-r--r-- 5.3 KiB
d93da738ghostly_zsh planet positions and gravity changed 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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use bevy::asset::Handle;
use bevy::prelude::*;
use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider};
use bevy_replicon::prelude::Replicated;
use crate::attachment::{Joint, JointId, JointOf, JointSnapFor, JointSnaps, Joints};
use crate::config::part::{JointOffset, PartConfig};
use crate::ecs::Part;

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

#[derive(Component, Debug)]
#[require(Transform, Replicated)]
pub struct SpawnPart(pub String);
#[derive(Component)]
struct LoadingPart(Handle<PartConfig>);
#[derive(Component, Debug)]
struct PartType(AssetId<PartConfig>);
#[derive(Component)]
/// STOP DELETING MY ASSET BEVY
struct LiveConfigHandle(Handle<PartConfig>);

// watch for SpawnPart components and start loading their config files
fn handle_spawn_part_requests(new_parts: Query<(Entity, &SpawnPart), (With<GlobalTransform>)>, mut commands: Commands, asset_server: Res<AssetServer>, assets: Res<Assets<PartConfig>>, parts: Query<(&Joints, &JointSnaps), With<Part>>,transform: Query<&GlobalTransform>) {
    for (new_part, request) in &new_parts {
        trace!(?new_part, ?request, "answering part request");

        let hdl: Handle<PartConfig> = asset_server.load(request.0.clone());

        commands.entity(new_part)
            .insert(LiveConfigHandle(hdl.clone()))
            .remove::<SpawnPart>();

        if let Some(cfg) = assets.get(&hdl) {
            spawn_part(commands.reborrow(), new_part, cfg, &hdl.id(), parts, transform,false);
        } else {
            commands.entity(new_part)
                .insert(LoadingPart(hdl.clone()));
        }
    }
}
fn update_part_requests(
    mut ev_config: EventReader<AssetEvent<PartConfig>>,
    loading_parts: Query<(Entity, &LoadingPart)>,
    existing_parts: Query<(Entity, &PartType)>,
    mut assets: ResMut<Assets<PartConfig>>,
    mut commands: Commands,
    parts: Query<(&Joints, &JointSnaps), With<Part>>,
    transform: Query<&GlobalTransform>
) {
    for ev in ev_config.read() {
        match ev {
            AssetEvent::Added { id } => {
                trace!(?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, parts, transform,false);
                    }
                }
            },
            AssetEvent::Modified { id } => {
                trace!(?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, parts, transform,true);
                    }
                }
            }
            _ => {}
        }
    }
}

fn spawn_part(mut commands: Commands, entity: Entity, part: &PartConfig, id: &AssetId<PartConfig>, parts: Query<(&Joints, &JointSnaps), With<Part>>, transform: Query<&GlobalTransform>, is_update: bool) {
    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))
        .insert(Replicated);

    for joint in &part.joints {
        if is_update {
            // find all entities
            for (joints, snaps) in &parts {
                for joint_entity in joints.iter() {
                    commands.entity(joint_entity).insert((
                        ChildOf(entity),
                        Joint {
                            id: JointId::from_part_and_joint_id(part.part.name.clone(), joint.id.clone()),
                            transform: joint.target.into()
                        },
                        <JointOffset as Into<Transform>>::into(joint.target),
                        JointOf(entity),
                        Replicated,
                    ));
                }
                for snap_entity in snaps.iter() {
                    commands.entity(snap_entity).insert((
                        <JointOffset as Into<Transform>>::into(joint.snap),
                    ));
                }
            }
        } else {
            let e = commands.spawn((
                ChildOf(entity),
                Joint {
                    id: JointId::from_part_and_joint_id(part.part.name.clone(), joint.id.clone()),
                    transform: joint.target.into()
                },
                <JointOffset as Into<Transform>>::into(joint.target),
                JointOf(entity),
                Replicated,
            )).id();
            trace!(?e, "spawned joint");

            let e = commands.spawn((
                ChildOf(entity),
                JointSnapFor(e),
                <JointOffset as Into<Transform>>::into(joint.snap),
                Replicated,
            )).id();
            trace!(?e, "spawned jointsnap");
        }
    }
}