~starkingdoms/starkingdoms

ref: 04beb9f36db6a39a3be1263a79cdf80af900dbe0 starkingdoms/crates/unified/src/server/part.rs -rw-r--r-- 2.8 KiB
04beb9f3 — core fix: anchors 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
use bevy::ecs::spawn::SpawnRelatedBundle;
use bevy::prelude::Component;
use bevy::prelude::*;
use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider};
use bevy_replicon::prelude::Replicated;
use crate::attachment::{Joint, JointId, JointOf, SnapOf, SnapOfJoint};
use crate::config::part::{JointConfig, PartConfig};
use crate::ecs::{Part, PartHandle};

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

#[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
pub 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 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);
    let child_of = ChildOf(*parent);

    (
        j_comp,
        joint_transform,
        joint_of,
        child_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);
    let child_of = ChildOf(*parent);

    (
        snap_transform,
        snap_for,
        snap_of,
        child_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));
    }
}