1use super::{Fluid, Ori, ship::figuredata::ShipSpec};
2use crate::{
3 comp::{body::ship::figuredata::VoxelCollider, inventory::item::armor::Friction},
4 consts::WATER_DENSITY,
5 terrain::Block,
6 uid::Uid,
7 util::Dir,
8};
9use hashbrown::HashMap;
10use serde::{Deserialize, Serialize};
11use specs::{Component, DerefFlaggedStorage, NullStorage, VecStorage};
12use std::sync::Arc;
13use vek::*;
14
15#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
17pub struct Pos(pub Vec3<f32>);
18
19impl Component for Pos {
20 type Storage = VecStorage<Self>;
21}
22
23#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
25pub struct Vel(pub Vec3<f32>);
26
27impl Vel {
28 pub fn zero() -> Self { Vel(Vec3::zero()) }
29
30 pub fn to_dir(&self) -> Dir { Dir::from_unnormalized(self.0).unwrap_or_default() }
31}
32
33impl Component for Vel {
34 type Storage = VecStorage<Self>;
35}
36
37#[derive(Copy, Clone, Debug)]
39pub struct PosVelOriDefer {
40 pub pos: Option<Pos>,
41 pub vel: Option<Vel>,
42 pub ori: Option<Ori>,
43}
44
45impl Component for PosVelOriDefer {
46 type Storage = VecStorage<Self>;
47}
48
49#[derive(Copy, Clone, Default, Debug, PartialEq)]
53pub struct PreviousPhysCache {
54 pub velocity: Vec3<f32>,
55 pub velocity_dt: Vec3<f32>,
56 pub in_fluid: Option<Fluid>,
57 pub center: Vec3<f32>,
60 pub collision_boundary: f32,
62 pub scale: f32,
63 pub scaled_radius: f32,
65 pub neighborhood_radius: f32,
67 pub origins: Option<(Vec2<f32>, Vec2<f32>)>,
69 pub pos: Option<Pos>,
70 pub ori: Quaternion<f32>,
71}
72
73impl Component for PreviousPhysCache {
74 type Storage = VecStorage<Self>;
75}
76
77#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
79pub struct Scale(pub f32);
80
81impl Component for Scale {
82 type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
83}
84
85#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
87pub struct Mass(pub f32);
88
89impl Default for Mass {
90 fn default() -> Mass { Mass(1.0) }
91}
92
93impl Component for Mass {
94 type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
95}
96
97#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
100pub struct Density(pub f32);
101
102impl Default for Density {
103 fn default() -> Density { Density(WATER_DENSITY) }
104}
105
106impl Component for Density {
107 type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
108}
109
110#[derive(Clone, Debug, Serialize, Deserialize)]
112pub enum Collider {
113 Voxel {
117 id: String,
118 },
119 Volume(Arc<VoxelCollider>),
121 CapsulePrism(CapsulePrism),
123 Point,
124}
125
126#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
127pub struct CapsulePrism {
128 pub p0: Vec2<f32>,
129 pub p1: Vec2<f32>,
130 pub radius: f32,
131 pub z_min: f32,
132 pub z_max: f32,
133}
134
135impl Collider {
136 pub fn is_voxel(&self) -> bool { matches!(self, Collider::Voxel { .. } | Collider::Volume(_)) }
137
138 pub fn get_vol<'a>(&'a self, ship_spec: &'a ShipSpec) -> Option<&'a VoxelCollider> {
139 match self {
140 Collider::Voxel { id } => ship_spec.colliders.get(id),
141 Collider::Volume(vol) => Some(&**vol),
142 _ => None,
143 }
144 }
145
146 pub fn bounding_radius(&self) -> f32 {
147 match self {
148 Collider::Voxel { .. } | Collider::Volume(_) => 1.0,
149 Collider::CapsulePrism(CapsulePrism { radius, p0, p1, .. }) => {
150 let a = p0.distance(*p1);
151 a / 2.0 + *radius
152 },
153 Collider::Point => 0.0,
154 }
155 }
156
157 pub fn get_height(&self) -> f32 {
158 let (z_min, z_max) = self.get_z_limits(1.0);
159 z_max - z_min
160 }
161
162 pub fn get_z_limits(&self, modifier: f32) -> (f32, f32) {
163 match self {
164 Collider::Voxel { .. } | Collider::Volume(_) => (0.0, 2.0),
165 Collider::CapsulePrism(CapsulePrism { z_min, z_max, .. }) => {
166 (*z_min * modifier, *z_max * modifier)
167 },
168 Collider::Point => (0.0, 0.0),
169 }
170 }
171}
172
173impl Component for Collider {
174 type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
175}
176
177#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
178pub struct Sticky;
179
180impl Component for Sticky {
181 type Storage = DerefFlaggedStorage<Self, NullStorage<Self>>;
182}
183
184#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
185pub struct Immovable;
186
187impl Component for Immovable {
188 type Storage = DerefFlaggedStorage<Self, NullStorage<Self>>;
189}
190
191#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
193pub struct PhysicsState {
194 pub on_ground: Option<Block>,
195 pub on_ceiling: bool,
196 pub on_wall: Option<Vec3<f32>>,
197 pub touch_entities: HashMap<Uid, Vec3<f32>>,
198 pub in_fluid: Option<Fluid>,
199 pub ground_vel: Vec3<f32>,
200 pub footwear: Friction,
201 pub skating_last_height: f32,
202 pub skating_active: bool,
203}
204
205impl PhysicsState {
206 pub fn reset(&mut self) {
207 let mut touch_entities = std::mem::take(&mut self.touch_entities);
209 touch_entities.clear();
210 *self = Self {
211 touch_entities,
212 ground_vel: self.ground_vel, ..Self::default()
215 }
216 }
217
218 pub fn on_surface(&self) -> Option<Vec3<f32>> {
219 self.on_ground
220 .map(|_| -Vec3::unit_z())
221 .or_else(|| self.on_ceiling.then_some(Vec3::unit_z()))
222 .or(self.on_wall)
223 }
224
225 pub fn in_liquid(&self) -> Option<f32> { self.in_fluid.and_then(|fluid| fluid.depth()) }
226}
227
228impl Component for PhysicsState {
229 type Storage = VecStorage<Self>;
230}
231
232#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
235pub struct ForceUpdate {
236 flag: bool,
237 counter: u64,
238}
239
240impl ForceUpdate {
241 pub fn forced() -> Self {
242 Self {
243 flag: true,
244 counter: 0,
245 }
246 }
247
248 pub fn update(&mut self) {
249 self.flag = true;
250 self.counter = self.counter.wrapping_add(1);
251 }
252
253 pub fn clear(&mut self) { self.flag = false; }
254
255 pub fn is_forced(&self) -> bool { self.flag }
256
257 pub fn counter(&self) -> u64 { self.counter }
258}
259
260impl Component for ForceUpdate {
261 type Storage = VecStorage<Self>;
262}