veloren_common/comp/body/
parts.rs1use std::cmp::Ordering;
2
3use rand::Rng;
4use serde::{Deserialize, Serialize};
5use specs::{Component, DerefFlaggedStorage};
6
7use crate::resources::Time;
8
9#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
10pub enum HeadState {
11 Attached,
12 Detached(Time),
13}
14
15impl HeadState {
16 pub fn is_attached(&self) -> bool { matches!(self, Self::Attached) }
17}
18
19#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
20#[serde(deny_unknown_fields)]
21pub struct Heads {
22 heads: Vec<HeadState>,
23}
24
25impl Heads {
26 pub fn new(amount: usize) -> Self {
27 Self {
28 heads: vec![HeadState::Attached; amount],
29 }
30 }
31
32 pub fn capacity(&self) -> usize { self.heads.len() }
33
34 pub fn amount(&self) -> usize { self.heads.iter().filter(|h| h.is_attached()).count() }
35
36 pub fn amount_missing(&self) -> usize { self.capacity() - self.amount() }
37
38 pub fn remove_one(&mut self, rng: &mut impl Rng, time: Time) -> Option<usize> {
39 if self.amount() == 0 {
40 return None;
41 }
42
43 let mut h = rng.gen_range(0..self.amount());
44
45 self.heads.iter_mut().position(|head| {
46 if matches!(head, HeadState::Attached) {
47 if h == 0 {
48 *head = HeadState::Detached(time);
49 true
50 } else {
51 h -= 1;
52 false
53 }
54 } else {
55 false
56 }
57 })
58 }
59
60 pub fn regrow_oldest(&mut self) -> bool {
61 if self.amount_missing() == 0 {
62 return false;
63 }
64
65 self.heads
66 .iter_mut()
67 .min_by(|a, b| match (a, b) {
68 (HeadState::Attached, HeadState::Attached) => Ordering::Equal,
69 (HeadState::Attached, HeadState::Detached(_)) => Ordering::Greater,
70 (HeadState::Detached(_), HeadState::Attached) => Ordering::Less,
71 (HeadState::Detached(a), HeadState::Detached(b)) => {
72 a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal)
74 },
75 })
76 .map(|head| {
77 *head = HeadState::Attached;
78 })
79 .is_some()
80 }
81
82 pub fn reset(&mut self) {
83 for head in self.heads.iter_mut() {
84 *head = HeadState::Attached;
85 }
86 }
87
88 pub fn heads_mut(&mut self) -> &mut [HeadState] { &mut self.heads }
90
91 pub fn heads(&self) -> &[HeadState] { &self.heads }
92}
93
94impl Component for Heads {
95 type Storage = DerefFlaggedStorage<Self, specs::HashMapStorage<Self>>;
96}