1use crate::{
2 comp,
3 link::{Is, Link, LinkHandle, Role},
4 mounting::{Rider, VolumeRider},
5 uid::{IdMaps, Uid},
6};
7use serde::{Deserialize, Serialize};
8use specs::{Entities, Read, ReadStorage, WriteStorage};
9use vek::*;
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct Leader;
13
14impl Role for Leader {
15 type Link = Tethered;
16}
17
18#[derive(Serialize, Deserialize, Debug)]
19pub struct Follower;
20
21impl Role for Follower {
22 type Link = Tethered;
23}
24
25#[derive(Serialize, Deserialize, Debug)]
26pub struct Tethered {
27 pub leader: Uid,
28 pub follower: Uid,
29 pub tether_length: f32,
30}
31
32#[derive(Debug)]
33pub enum TetherError {
34 NoSuchEntity,
35 NotTetherable,
36}
37
38impl Link for Tethered {
39 type CreateData<'a> = (
40 Read<'a, IdMaps>,
41 WriteStorage<'a, Is<Leader>>,
42 WriteStorage<'a, Is<Follower>>,
43 ReadStorage<'a, Is<Rider>>,
44 ReadStorage<'a, Is<VolumeRider>>,
45 );
46 type DeleteData<'a> = (
47 Read<'a, IdMaps>,
48 WriteStorage<'a, Is<Leader>>,
49 WriteStorage<'a, Is<Follower>>,
50 );
51 type Error = TetherError;
52 type PersistData<'a> = (
53 Read<'a, IdMaps>,
54 Entities<'a>,
55 ReadStorage<'a, comp::Health>,
56 ReadStorage<'a, Is<Leader>>,
57 ReadStorage<'a, Is<Follower>>,
58 );
59
60 fn create(
61 this: &LinkHandle<Self>,
62 (id_maps, is_leaders, is_followers, is_riders, is_volume_rider): &mut Self::CreateData<'_>,
63 ) -> Result<(), Self::Error> {
64 let entity = |uid: Uid| id_maps.uid_entity(uid);
65
66 if this.leader == this.follower {
67 Err(TetherError::NotTetherable)
69 } else if let Some((leader, follower)) = entity(this.leader).zip(entity(this.follower)) {
70 if !is_riders.contains(follower)
73 && !is_volume_rider.contains(follower)
74 && !is_followers.contains(follower)
75 && (!is_leaders.contains(follower) || !is_followers.contains(leader))
77 {
78 let _ = is_leaders.insert(leader, this.make_role());
79 let _ = is_followers.insert(follower, this.make_role());
80 Ok(())
81 } else {
82 Err(TetherError::NotTetherable)
83 }
84 } else {
85 Err(TetherError::NoSuchEntity)
86 }
87 }
88
89 fn persist(
90 this: &LinkHandle<Self>,
91 (id_maps, entities, healths, is_leaders, is_followers): &mut Self::PersistData<'_>,
92 ) -> bool {
93 let entity = |uid: Uid| id_maps.uid_entity(uid);
94
95 if let Some((leader, follower)) = entity(this.leader).zip(entity(this.follower)) {
96 let is_alive = |entity| {
97 entities.is_alive(entity) && healths.get(entity).is_none_or(|h| !h.is_dead)
98 };
99
100 is_alive(leader)
102 && is_alive(follower)
103 && is_leaders.get(leader).is_some()
104 && is_followers.get(follower).is_some()
105 } else {
106 false
107 }
108 }
109
110 fn delete(
111 this: &LinkHandle<Self>,
112 (id_maps, is_leaders, is_followers): &mut Self::DeleteData<'_>,
113 ) {
114 let entity = |uid: Uid| id_maps.uid_entity(uid);
115
116 let leader = entity(this.leader);
117 let follower = entity(this.follower);
118
119 leader.map(|leader| is_leaders.remove(leader));
121 follower.map(|follower| is_followers.remove(follower));
122 }
123}