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 zero() -> Self {
21 Self { x: 0.0, y: 0.0, z: 0.0 }
22 }
23
24 pub fn delta(&self, other: Vector3) -> Self {
26 let dx = self.x - other.x;
27 let dy = self.y - other.y;
28 let dz = self.z - other.z;
29
30 Self { x: dx, y: dy, z: dz }
31 }
32}
33
34impl Buffer for Vector3 {
35 fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
36 Some(Self {
37 x: f64::read_buf(buffer)?,
38 y: f64::read_buf(buffer)?,
39 z: f64::read_buf(buffer)?,
40 })
41 }
42
43 fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
44 self.x.write_buf(buffer)?;
45 self.y.write_buf(buffer)?;
46 self.z.write_buf(buffer)?;
47 Ok(())
48 }
49}
50
51#[derive(Debug, Clone, Copy, PartialEq)]
53pub struct LpVector3 {
54 pub x: f64,
55 pub y: f64,
56 pub z: f64,
57}
58
59impl LpVector3 {
60 const MAX_QUANTIZED_VALUE: f64 = 32766.0;
61
62 pub fn new(x: f64, y: f64, z: f64) -> Self {
64 Self { x, y, z }
65 }
66
67 pub fn zero() -> Self {
69 Self { x: 0.0, y: 0.0, z: 0.0 }
70 }
71
72 fn pack(value: f64) -> i64 {
74 ((value * 0.5 + 0.5) * Self::MAX_QUANTIZED_VALUE).round() as i64
75 }
76
77 fn unpack(value: i64) -> f64 {
79 let v = (value & 32767) as f64;
80 (v.min(Self::MAX_QUANTIZED_VALUE)) * 2.0 / Self::MAX_QUANTIZED_VALUE - 1.0
81 }
82}
83
84impl Buffer for LpVector3 {
85 fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
86 let byte1 = u8::read_buf(buffer)? as i32;
87
88 if byte1 == 0 {
89 return Some(Self { x: 0.0, y: 0.0, z: 0.0 });
90 }
91
92 let byte2 = u8::read_buf(buffer)? as i32;
93 let bytes3to4 = u32::read_buf(buffer)? as i64;
94
95 let packed = (bytes3to4 << 16) | ((byte2 as i64) << 8) | (byte1 as i64);
96
97 let mut scale_factor = (byte1 & 3) as i64;
98
99 if (byte1 & 4) == 4 {
100 scale_factor |= (i32::read_varint(buffer)? as i64 & 0xFFFFFFFF) << 2;
101 }
102
103 let scale_factor_d = scale_factor as f64;
104
105 Some(Self {
106 x: Self::unpack(packed >> 3) * scale_factor_d,
107 y: Self::unpack(packed >> 18) * scale_factor_d,
108 z: Self::unpack(packed >> 33) * scale_factor_d,
109 })
110 }
111
112 fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
113 let max_coordinate = self.x.abs().max(self.y.abs().max(self.z.abs()));
114
115 if max_coordinate < 3.051944088384301e-5 {
116 0u8.write_buf(buffer)?;
117 } else {
118 let max_coordinate_i = max_coordinate as i64;
119 let scale_factor = if max_coordinate > max_coordinate_i as f64 {
120 max_coordinate_i + 1
121 } else {
122 max_coordinate_i
123 };
124
125 let need_continuation = (scale_factor & 3) != scale_factor;
126 let packed_scale = if need_continuation { (scale_factor & 3) | 4 } else { scale_factor };
127
128 let packed_x = Self::pack(self.x / scale_factor as f64) << 3;
129 let packed_y = Self::pack(self.y / scale_factor as f64) << 18;
130 let packed_z = Self::pack(self.z / scale_factor as f64) << 33;
131
132 let packed = packed_z | packed_y | packed_x | packed_scale;
133
134 ((packed & 0xFF) as u8).write_buf(buffer)?;
135 (((packed >> 8) & 0xFF) as u8).write_buf(buffer)?;
136 ((packed >> 16) as u32).write_buf(buffer)?;
137
138 if need_continuation {
139 ((scale_factor >> 2) as i32).write_varint(buffer)?;
140 }
141 }
142
143 Ok(())
144 }
145}