veloren_common/comp/
presence.rs1use crate::{ViewDistances, character::CharacterId};
2use serde::{Deserialize, Serialize};
3use specs::Component;
4use std::time::{Duration, Instant};
5use vek::*;
6
7#[derive(Debug)]
8pub struct Presence {
9 pub terrain_view_distance: ViewDistance,
10 pub entity_view_distance: ViewDistance,
11 pub kind: PresenceKind,
15 pub lossy_terrain_compression: bool,
16}
17
18impl Presence {
19 pub fn new(view_distances: ViewDistances, kind: PresenceKind) -> Self {
20 let now = Instant::now();
21 Self {
22 terrain_view_distance: ViewDistance::new(view_distances.terrain, now),
23 entity_view_distance: ViewDistance::new(view_distances.entity, now),
24 kind,
25 lossy_terrain_compression: false,
26 }
27 }
28}
29
30impl Component for Presence {
31 type Storage = specs::DenseVecStorage<Self>;
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
35pub enum PresenceKind {
36 Spectator,
37 LoadingCharacter(CharacterId),
41 Character(CharacterId),
42 Possessor,
43}
44
45impl PresenceKind {
46 pub fn controlling_char(&self) -> bool { matches!(self, Self::Character(_) | Self::Possessor) }
50
51 pub fn character_id(&self) -> Option<CharacterId> {
52 if let Self::Character(character_id) = self {
53 Some(*character_id)
54 } else {
55 None
56 }
57 }
58
59 pub fn sync_me(&self) -> bool {
65 match self {
66 Self::Spectator | Self::LoadingCharacter(_) => false,
67 Self::Character(_) | Self::Possessor => true,
68 }
69 }
70}
71
72#[derive(PartialEq, Debug, Clone, Copy)]
73enum Direction {
74 Up,
75 Down,
76}
77
78#[derive(Debug, Clone, Copy)]
86pub struct ViewDistance {
87 direction: Direction,
88 last_direction_change_time: Instant,
89 target: Option<u32>,
90 current: u32,
91}
92
93impl ViewDistance {
94 const TIME_PER_DIR_CHANGE: Duration = Duration::from_millis(300);
96
97 pub fn new(start_value: u32, now: Instant) -> Self {
98 Self {
99 direction: Direction::Up,
100 last_direction_change_time: now.checked_sub(Self::TIME_PER_DIR_CHANGE).unwrap_or(now),
101 target: None,
102 current: start_value,
103 }
104 }
105
106 pub fn current(&self) -> u32 { self.current }
108
109 pub fn update(&mut self, now: Instant) {
112 if let Some(target_val) = self.target {
113 if now.saturating_duration_since(self.last_direction_change_time)
114 > Self::TIME_PER_DIR_CHANGE
115 {
116 self.last_direction_change_time = now;
117 self.current = target_val;
118 self.target = None;
119 }
120 }
121 }
122
123 pub fn set_target(&mut self, new_target: u32, now: Instant) {
130 use core::cmp::Ordering;
131 let new_direction = match new_target.cmp(&self.current) {
132 Ordering::Equal => return, Ordering::Less => Direction::Down,
134 Ordering::Greater => Direction::Up,
135 };
136
137 if new_direction == self.direction {
139 self.current = new_target;
140 self.target = None;
141 } else if now.saturating_duration_since(self.last_direction_change_time)
144 > Self::TIME_PER_DIR_CHANGE
145 {
146 self.direction = new_direction;
147 self.last_direction_change_time = now;
148 self.current = new_target;
149 self.target = None;
150 } else {
152 self.target = Some(new_target);
153 }
154 }
155}