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