nurtex_protocol/types/
vector.rs1use nurtex_codec::Buffer;
2use nurtex_codec::types::variable::VarI32;
3
4#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct Vector3 {
7 pub x: f64,
8 pub y: f64,
9 pub z: f64,
10}
11
12impl Vector3 {
13 pub fn new(x: f64, y: f64, z: f64) -> Self {
15 Self { x, y, z }
16 }
17
18 pub fn from_lp_vector3(lp_vector3: LpVector3) -> Self {
20 Self {
21 x: lp_vector3.x,
22 y: lp_vector3.y,
23 z: lp_vector3.z,
24 }
25 }
26
27 pub fn zero() -> Self {
29 Self { x: 0.0, y: 0.0, z: 0.0 }
30 }
31
32 pub fn delta(&self, other: Vector3) -> Self {
34 let dx = self.x - other.x;
35 let dy = self.y - other.y;
36 let dz = self.z - other.z;
37
38 Self { x: dx, y: dy, z: dz }
39 }
40
41 pub fn with_delta(&mut self, x: i16, y: i16, z: i16) {
43 self.x += x as f64;
44 self.y += y as f64;
45 self.z += z as f64;
46 }
47
48 pub fn with_velocity(&mut self, velocity: Vector3) {
50 self.x += velocity.x;
51 self.y += velocity.y;
52 self.z += velocity.z;
53 }
54}
55
56impl Buffer for Vector3 {
57 fn read_buf(buffer: &mut std::io::Cursor<&[u8]>) -> Option<Self> {
58 Some(Self {
59 x: f64::read_buf(buffer)?,
60 y: f64::read_buf(buffer)?,
61 z: f64::read_buf(buffer)?,
62 })
63 }
64
65 fn write_buf(&self, buffer: &mut impl std::io::Write) -> std::io::Result<()> {
66 self.x.write_buf(buffer)?;
67 self.y.write_buf(buffer)?;
68 self.z.write_buf(buffer)?;
69 Ok(())
70 }
71}
72
73#[derive(Debug, Clone, Copy, PartialEq)]
75pub struct LpVector3 {
76 pub x: f64,
77 pub y: f64,
78 pub z: f64,
79}
80
81impl LpVector3 {
82 const MAX_QUANTIZED_VALUE: f64 = 32766.0;
83
84 pub fn new(x: f64, y: f64, z: f64) -> Self {
86 Self { x, y, z }
87 }
88
89 pub fn zero() -> Self {
91 Self { x: 0.0, y: 0.0, z: 0.0 }
92 }
93
94 pub fn to_vector3(&self) -> Vector3 {
96 Vector3 { x: self.x, y: self.y, z: self.z }
97 }
98
99 fn pack(value: f64) -> i64 {
101 ((value * 0.5 + 0.5) * Self::MAX_QUANTIZED_VALUE).round() as i64
102 }
103
104 fn unpack(value: i64) -> f64 {
106 let v = (value & 32767) as f64;
107 (v.min(Self::MAX_QUANTIZED_VALUE)) * 2.0 / Self::MAX_QUANTIZED_VALUE - 1.0
108 }
109}
110
111impl Buffer for LpVector3 {
112 fn read_buf(buffer: &mut std::io::Cursor<&[u8]>) -> Option<Self> {
113 let byte1 = u8::read_buf(buffer)? as i32;
114
115 if byte1 == 0 {
116 return Some(Self { x: 0.0, y: 0.0, z: 0.0 });
117 }
118
119 let byte2 = u8::read_buf(buffer)? as i32;
120 let bytes3to4 = u32::read_buf(buffer)? as i64;
121
122 let packed = (bytes3to4 << 16) | ((byte2 as i64) << 8) | (byte1 as i64);
123
124 let mut scale_factor = (byte1 & 3) as i64;
125
126 if (byte1 & 4) == 4 {
127 scale_factor |= (i32::read_var(buffer)? as i64 & 0xFFFFFFFF) << 2;
128 }
129
130 let scale_factor_d = scale_factor as f64;
131
132 Some(Self {
133 x: Self::unpack(packed >> 3) * scale_factor_d,
134 y: Self::unpack(packed >> 18) * scale_factor_d,
135 z: Self::unpack(packed >> 33) * scale_factor_d,
136 })
137 }
138
139 fn write_buf(&self, buffer: &mut impl std::io::Write) -> std::io::Result<()> {
140 let max_coordinate = self.x.abs().max(self.y.abs().max(self.z.abs()));
141
142 if max_coordinate < 3.051944088384301e-5 {
143 0u8.write_buf(buffer)?;
144 } else {
145 let max_coordinate_i = max_coordinate as i64;
146 let scale_factor = if max_coordinate > max_coordinate_i as f64 {
147 max_coordinate_i + 1
148 } else {
149 max_coordinate_i
150 };
151
152 let need_continuation = (scale_factor & 3) != scale_factor;
153 let packed_scale = if need_continuation { (scale_factor & 3) | 4 } else { scale_factor };
154
155 let packed_x = Self::pack(self.x / scale_factor as f64) << 3;
156 let packed_y = Self::pack(self.y / scale_factor as f64) << 18;
157 let packed_z = Self::pack(self.z / scale_factor as f64) << 33;
158
159 let packed = packed_z | packed_y | packed_x | packed_scale;
160
161 ((packed & 0xFF) as u8).write_buf(buffer)?;
162 (((packed >> 8) & 0xFF) as u8).write_buf(buffer)?;
163 ((packed >> 16) as u32).write_buf(buffer)?;
164
165 if need_continuation {
166 ((scale_factor >> 2) as i32).write_var(buffer)?;
167 }
168 }
169
170 Ok(())
171 }
172}