~starkingdoms/starkingdoms

ref: 3e58f95adc3e9659dd60b755d9fbfecdecc69efd starkingdoms/crates/unified/src/attachment.rs -rw-r--r-- 4.0 KiB
3e58f95aghostly_zsh merge stuff 4 hours 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
//! attachment system overview
//!
//! hearty has a `Ship` marker component, and a `Parts` auto component containing all parts of the
//! ship
//!
//! parts of the ship have a `PartInShip` pointing back to hearty
//!
//! parts have many `Joint`s, which are separate children entities representing an attachment point
//! get pointers to joints with the `Joints` auto component
//!
//! joints have `JointOf` pointing to the part they belong to
//! if a part is connected to another point at a joint, that joint will have a `Peer`, pointing to
//! the Joint entity on the other part, and containing a pointer to the physics world joint
//!
//! snaps are also a thing and can be generally disregarded

use bevy::ecs::entity::MapEntities;
use crate::prelude::*;
use serde::{Deserialize, Serialize};
use std::ops::Deref;

#[derive(Component, Serialize, Deserialize)]
#[require(Replicated)]
/// The primary component for a ship structure. Will be present on Hearty
pub struct Ship;

#[derive(Component, Serialize, Deserialize, MapEntities, Deref)]
#[relationship_target(relationship = PartInShip, linked_spawn)]
#[require(Replicated)]
/// List of all parts in this Ship. Will be present on Hearty.
/// Managed automatically by attachment system (do not modify)y,

pub struct Parts(#[entities] Vec<Entity>);

#[derive(Component, Serialize, Deserialize, MapEntities, Debug)]
#[relationship(relationship_target = Parts)]
#[require(Replicated)]
/// A Pointer to the `Ship` that this part belongs to. Managed automatically by attachment system
/// (do not add/remove manually)
pub struct PartInShip(#[entities] pub Entity);

#[derive(Component, Serialize, Deserialize)]
#[require(Transform)]
#[require(Replicated)]
/// A `Joint` is a separate entity (child of a part) that represents a single possible attachment
/// point for that part.
pub struct Joint {
    pub id: JointId,
    pub transform: Transform,
}
#[derive(Component, Serialize, Deserialize, MapEntities)]
#[require(Replicated)]
/// A `Peer` is a pointer component of a `Joint` that references the Joint entity it is connected to.
/// Two joints are said to be 'peered' when they are attached to each other.
/// Two Parts are connected when they have a set of peered `Joint`s
pub struct Peer {
    #[entities]
    pub peer_joint_entity_id: Entity,
    #[entities]
    pub physics_joint: Entity
}

#[derive(Component, Serialize, Deserialize, MapEntities)]
#[relationship(relationship_target = Joints)]
#[require(Replicated)]
/// A pointer to the `Part` that this `Joint` belongs to. Managed automatically, do not add/remove
pub struct JointOf(#[entities] pub Entity);
#[derive(Component, Serialize, Deserialize, MapEntities, Debug, Clone)]
#[relationship_target(relationship = JointOf)]
#[require(Replicated)]
/// All the `Joint`s that belong to this `Part`. Managed automatically, do not modify
pub struct Joints(#[entities] Vec<Entity>);
impl Deref for Joints {
    type Target = Vec<Entity>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Component, Serialize, Deserialize, MapEntities)]
#[relationship(relationship_target = Snaps)]
#[require(Replicated)]
/// The `Part` that this Snap belongs to. A Snap is an internal entity used for snapping during
/// the attachment routine. Managed automatically.
pub struct SnapOf(#[entities] pub Entity);
#[derive(Component, Serialize, Deserialize, MapEntities)]
#[relationship_target(relationship = SnapOf)]
#[require(Replicated)]
/// All the `Snap`s of this `Joint`. Managed automatically.
pub struct Snaps(#[entities] Vec<Entity>);
impl Deref for Snaps {
    type Target = Vec<Entity>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct JointId(pub String);
impl JointId {
    #[must_use]
    pub fn from_part_and_joint_id(part: impl AsRef<str>, joint: impl AsRef<str>) -> Self {
        Self(format!("{}:{}", part.as_ref(), joint.as_ref()))
    }
}

#[derive(Serialize, Deserialize, Component, MapEntities)]
#[require(Replicated)]
/// The `Joint` that this `Snap` belongs to
pub struct SnapOfJoint(#[entities] pub Entity);