~starkingdoms/starkingdoms

ref: 4ccbefd5580d250ce9105d94129613957cdb1c0d starkingdoms/crates/unified/src/server/part.rs -rw-r--r-- 3.4 KiB
4ccbefd5 — core chore(fmt,lint): pass clippy 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
use crate::attachment::{Joint, JointId, JointOf, SnapOf, SnapOfJoint};
use crate::config::part::{JointConfig, PartConfig};
use crate::ecs::{Part, PartHandle};
use bevy::prelude::Component;
use bevy::prelude::*;
use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider};
use bevy_replicon::prelude::Replicated;

pub fn part_management_plugin(app: &mut App) {
    app.add_systems(PreUpdate, (handle_ready_parts, handle_part_reloading));
}

#[derive(Bundle)]
pub struct SpawnPartBundle {
    pub req: SpawnPartRequest,
    pub transform: Transform,
}

#[derive(Component)]
pub struct SpawnPartRequest(pub Handle<PartConfig>);

// wait for parts assets to be ready, then spawn the full part
fn handle_ready_parts(
    loading_parts: Query<(Entity, &SpawnPartRequest)>,
    mut commands: Commands,
    assets: Res<Assets<PartConfig>>,
) {
    for (entity, loading_part) in &loading_parts {
        if let Some(strong_config) = assets.get(&loading_part.0) {
            // config is strong; spawn 'er in!
            commands
                .entity(entity)
                .insert(calculate_bundle(strong_config, &loading_part.0))
                .remove::<SpawnPartRequest>();
            spawn_joints(strong_config, entity, commands.reborrow());
        }
    }
}
fn handle_part_reloading(
    existing_parts: Query<(Entity, &PartHandle)>,
    assets: Res<Assets<PartConfig>>,
    mut asset_events: EventReader<AssetEvent<PartConfig>>,
    mut commands: Commands,
) {
    for event in asset_events.read() {
        if let AssetEvent::Modified { id } = event {
            let config = assets.get(*id).unwrap();
            for existing_part in existing_parts.iter() {
                if existing_part.1.0.id() == *id {
                    commands
                        .entity(existing_part.0)
                        .insert(calculate_bundle(config, &existing_part.1.0));
                }
            }
        }
    }
}

fn calculate_bundle(config: &PartConfig, handle: &Handle<PartConfig>) -> impl Bundle {
    let part = Part {
        strong_config: config.clone(),
    };
    let part_handle = PartHandle(handle.clone());
    let collider = Collider::cuboid(config.physics.width / 2.0, config.physics.height / 2.0);
    let additional_mass_properties = AdditionalMassProperties::Mass(config.physics.mass);

    (
        part,
        part_handle,
        collider,
        additional_mass_properties,
        Replicated,
    )
}
fn spawn_joint_bundle(joint: &JointConfig, part: &PartConfig, parent: &Entity) -> impl Bundle {
    let j_comp = Joint {
        id: JointId::from_part_and_joint_id(part.part.name.clone(), joint.id.clone()),
        transform: joint.target.into(),
    };
    let joint_transform: Transform = j_comp.transform;
    let joint_of = JointOf(*parent);

    (j_comp, joint_transform, joint_of, Replicated)
}
fn spawn_snap_bundle(joint: &JointConfig, parent: &Entity, p_joint: &Entity) -> impl Bundle {
    let snap_transform: Transform = joint.snap.into();
    let snap_for = SnapOf(*parent);
    let snap_of = SnapOfJoint(*p_joint);

    (snap_transform, snap_for, snap_of, Replicated)
}
fn spawn_joints(config: &PartConfig, parent: Entity, mut commands: Commands) {
    for joint in &config.joints {
        let joint_id = commands
            .spawn(spawn_joint_bundle(joint, config, &parent))
            .id();
        commands.spawn(spawn_snap_bundle(joint, &parent, &joint_id));
    }
}