1use std::{
7 fmt,
8 hash::{Hash, Hasher},
9 io,
10 io::{Cursor, Write},
11 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, Sub},
12 str::FromStr,
13};
14
15use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
16use serde::{Serialize, Serializer};
17use simdnbt::Deserialize;
18
19use crate::{codec_utils::IntArray, direction::Direction, identifier::Identifier, math};
20
21macro_rules! vec3_impl {
22 ($name:ident, $type:ty) => {
23 impl $name {
24 pub const ZERO: Self = Self {
26 x: 0 as $type,
27 y: 0 as $type,
28 z: 0 as $type,
29 };
30
31 #[inline]
32 pub const fn new(x: $type, y: $type, z: $type) -> Self {
33 Self { x, y, z }
34 }
35
36 #[inline]
39 pub fn length_squared(&self) -> $type {
40 self.x * self.x + self.y * self.y + self.z * self.z
41 }
42
43 #[inline]
46 pub fn distance_squared_to(self, other: Self) -> $type {
47 (self - other).length_squared()
48 }
49
50 #[inline]
51 pub fn horizontal_distance_squared(&self) -> $type {
52 self.x * self.x + self.z * self.z
53 }
54
55 #[inline]
56 pub fn horizontal_distance_squared_to(self, other: Self) -> $type {
57 (self - other).horizontal_distance_squared()
58 }
59
60 #[inline]
63 pub fn down(&self, y: $type) -> Self {
64 Self {
65 x: self.x,
66 y: self.y - y,
67 z: self.z,
68 }
69 }
70 #[inline]
73 pub fn up(&self, y: $type) -> Self {
74 Self {
75 x: self.x,
76 y: self.y + y,
77 z: self.z,
78 }
79 }
80
81 #[inline]
84 pub fn north(&self, z: $type) -> Self {
85 Self {
86 x: self.x,
87 y: self.y,
88 z: self.z - z,
89 }
90 }
91 #[inline]
94 pub fn east(&self, x: $type) -> Self {
95 Self {
96 x: self.x + x,
97 y: self.y,
98 z: self.z,
99 }
100 }
101 #[inline]
104 pub fn south(&self, z: $type) -> Self {
105 Self {
106 x: self.x,
107 y: self.y,
108 z: self.z + z,
109 }
110 }
111 #[inline]
114 pub fn west(&self, x: $type) -> Self {
115 Self {
116 x: self.x - x,
117 y: self.y,
118 z: self.z,
119 }
120 }
121
122 #[inline]
123 pub fn dot(&self, other: Self) -> $type {
124 self.x * other.x + self.y * other.y + self.z * other.z
125 }
126
127 pub fn min(&self, other: Self) -> Self {
129 Self {
130 x: self.x.min(other.x),
131 y: self.x.min(other.y),
132 z: self.x.min(other.z),
133 }
134 }
135 pub fn max(&self, other: Self) -> Self {
137 Self {
138 x: self.x.max(other.x),
139 y: self.x.max(other.y),
140 z: self.x.max(other.z),
141 }
142 }
143
144 #[inline]
146 pub fn xz(&self) -> Self {
147 Self {
148 x: self.x,
149 y: <$type>::default(),
150 z: self.z,
151 }
152 }
153
154 pub fn with_x(&self, x: $type) -> Self {
155 Self { x, ..*self }
156 }
157 pub fn with_y(&self, y: $type) -> Self {
158 Self { y, ..*self }
159 }
160 pub fn with_z(&self, z: $type) -> Self {
161 Self { z, ..*self }
162 }
163 }
164
165 impl Add for &$name {
166 type Output = $name;
167
168 #[inline]
169 fn add(self, rhs: Self) -> Self::Output {
170 $name {
171 x: self.x + rhs.x,
172 y: self.y + rhs.y,
173 z: self.z + rhs.z,
174 }
175 }
176 }
177 impl Add for $name {
178 type Output = $name;
179
180 #[inline]
181 fn add(self, rhs: Self) -> Self::Output {
182 (&self).add(&rhs)
183 }
184 }
185 impl Add<$type> for $name {
186 type Output = Self;
187
188 #[inline]
189 fn add(self, rhs: $type) -> Self::Output {
190 Self {
191 x: self.x + rhs,
192 y: self.y + rhs,
193 z: self.z + rhs,
194 }
195 }
196 }
197
198 impl AddAssign for $name {
199 #[inline]
200 fn add_assign(&mut self, rhs: Self) {
201 self.x += rhs.x;
202 self.y += rhs.y;
203 self.z += rhs.z;
204 }
205 }
206 impl Rem<$type> for $name {
207 type Output = Self;
208
209 #[inline]
210 fn rem(self, rhs: $type) -> Self::Output {
211 Self {
212 x: self.x % rhs,
213 y: self.y % rhs,
214 z: self.z % rhs,
215 }
216 }
217 }
218
219 impl Sub for &$name {
220 type Output = $name;
221
222 #[inline]
224 fn sub(self, other: Self) -> Self::Output {
225 Self::Output {
226 x: self.x - other.x,
227 y: self.y - other.y,
228 z: self.z - other.z,
229 }
230 }
231 }
232 impl Sub for $name {
233 type Output = Self;
234
235 #[inline]
236 fn sub(self, other: Self) -> Self::Output {
237 (&self).sub(&other)
238 }
239 }
240
241 impl Mul<$type> for $name {
242 type Output = Self;
243
244 #[inline]
245 fn mul(self, multiplier: $type) -> Self::Output {
246 Self {
247 x: self.x * multiplier,
248 y: self.y * multiplier,
249 z: self.z * multiplier,
250 }
251 }
252 }
253 impl MulAssign<$type> for $name {
254 #[inline]
255 fn mul_assign(&mut self, multiplier: $type) {
256 self.x *= multiplier;
257 self.y *= multiplier;
258 self.z *= multiplier;
259 }
260 }
261
262 impl Div<$type> for $name {
263 type Output = Self;
264
265 #[inline]
266 fn div(self, divisor: $type) -> Self::Output {
267 Self {
268 x: self.x / divisor,
269 y: self.y / divisor,
270 z: self.z / divisor,
271 }
272 }
273 }
274 impl DivAssign<$type> for $name {
275 #[inline]
276 fn div_assign(&mut self, divisor: $type) {
277 self.x /= divisor;
278 self.y /= divisor;
279 self.z /= divisor;
280 }
281 }
282
283 impl From<($type, $type, $type)> for $name {
284 #[inline]
285 fn from(pos: ($type, $type, $type)) -> Self {
286 Self::new(pos.0, pos.1, pos.2)
287 }
288 }
289 impl From<&($type, $type, $type)> for $name {
290 #[inline]
291 fn from(pos: &($type, $type, $type)) -> Self {
292 Self::new(pos.0, pos.1, pos.2)
293 }
294 }
295 impl From<$name> for ($type, $type, $type) {
296 #[inline]
297 fn from(pos: $name) -> Self {
298 (pos.x, pos.y, pos.z)
299 }
300 }
301 };
302}
303
304#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf, serde::Deserialize, serde::Serialize)]
308pub struct Vec3 {
309 pub x: f64,
310 pub y: f64,
311 pub z: f64,
312}
313vec3_impl!(Vec3, f64);
314
315impl Vec3 {
316 pub fn length(&self) -> f64 {
319 f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
320 }
321
322 pub fn distance_to(self, other: Self) -> f64 {
325 (self - other).length()
326 }
327
328 pub fn x_rot(self, radians: f32) -> Vec3 {
329 let x_delta = math::cos(radians);
330 let y_delta = math::sin(radians);
331 let x = self.x;
332 let y = self.y * (x_delta as f64) + self.z * (y_delta as f64);
333 let z = self.z * (x_delta as f64) - self.y * (y_delta as f64);
334 Vec3 { x, y, z }
335 }
336 pub fn y_rot(self, radians: f32) -> Vec3 {
337 let x_delta = math::cos(radians);
338 let y_delta = math::sin(radians);
339 let x = self.x * (x_delta as f64) + self.z * (y_delta as f64);
340 let y = self.y;
341 let z = self.z * (x_delta as f64) - self.x * (y_delta as f64);
342 Vec3 { x, y, z }
343 }
344
345 pub fn to_block_pos_floor(&self) -> BlockPos {
346 BlockPos {
347 x: self.x.floor() as i32,
348 y: self.y.floor() as i32,
349 z: self.z.floor() as i32,
350 }
351 }
352 pub fn to_block_pos_ceil(&self) -> BlockPos {
353 BlockPos {
354 x: self.x.ceil() as i32,
355 y: self.y.ceil() as i32,
356 z: self.z.ceil() as i32,
357 }
358 }
359
360 pub fn closer_than(&self, other: Vec3, range: f64) -> bool {
363 self.distance_squared_to(other) < range.powi(2)
364 }
365}
366
367#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf)]
369pub struct Vec3f32 {
370 pub x: f32,
371 pub y: f32,
372 pub z: f32,
373}
374impl From<Vec3f32> for Vec3 {
375 fn from(v: Vec3f32) -> Self {
376 Vec3 {
377 x: v.x as f64,
378 y: v.y as f64,
379 z: v.z as f64,
380 }
381 }
382}
383impl From<Vec3> for Vec3f32 {
384 fn from(v: Vec3) -> Self {
385 Vec3f32 {
386 x: v.x as f32,
387 y: v.y as f32,
388 z: v.z as f32,
389 }
390 }
391}
392
393#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
397pub struct BlockPos {
398 pub x: i32,
399 pub y: i32,
400 pub z: i32,
401}
402vec3_impl!(BlockPos, i32);
403
404impl BlockPos {
405 pub fn center(&self) -> Vec3 {
408 Vec3 {
409 x: self.x as f64 + 0.5,
410 y: self.y as f64 + 0.5,
411 z: self.z as f64 + 0.5,
412 }
413 }
414
415 pub fn center_bottom(&self) -> Vec3 {
418 Vec3 {
419 x: self.x as f64 + 0.5,
420 y: self.y as f64,
421 z: self.z as f64 + 0.5,
422 }
423 }
424
425 pub fn to_vec3_floored(&self) -> Vec3 {
427 Vec3 {
428 x: self.x as f64,
429 y: self.y as f64,
430 z: self.z as f64,
431 }
432 }
433
434 pub fn length_manhattan(&self) -> u32 {
436 (self.x.abs() + self.y.abs() + self.z.abs()) as u32
437 }
438
439 pub fn offset_with_direction(self, direction: Direction) -> Self {
440 self + direction.normal()
441 }
442
443 pub fn length(&self) -> f64 {
446 f64::sqrt((self.x * self.x + self.y * self.y + self.z * self.z) as f64)
447 }
448
449 pub fn distance_to(self, other: Self) -> f64 {
456 (self - other).length()
457 }
458}
459impl serde::Serialize for BlockPos {
460 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
461 where
462 S: Serializer,
463 {
464 IntArray([self.x, self.y, self.z]).serialize(serializer)
466 }
467}
468impl<'de> serde::Deserialize<'de> for BlockPos {
469 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
470 where
471 D: serde::Deserializer<'de>,
472 {
473 let [x, y, z] = <[i32; 3]>::deserialize(deserializer)?;
474 Ok(BlockPos { x, y, z })
475 }
476}
477
478#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, AzBuf)]
483pub struct Vec3i {
484 #[var]
485 pub x: i32,
486 #[var]
487 pub y: i32,
488 #[var]
489 pub z: i32,
490}
491vec3_impl!(Vec3i, i32);
492
493#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
497pub struct ChunkPos {
498 pub x: i32,
499 pub z: i32,
500}
501impl ChunkPos {
502 pub fn new(x: i32, z: i32) -> Self {
503 ChunkPos { x, z }
504 }
505}
506impl Add<ChunkPos> for ChunkPos {
507 type Output = Self;
508
509 fn add(self, rhs: Self) -> Self::Output {
510 Self {
511 x: self.x + rhs.x,
512 z: self.z + rhs.z,
513 }
514 }
515}
516impl Add<ChunkBlockPos> for ChunkPos {
517 type Output = BlockPos;
518
519 fn add(self, rhs: ChunkBlockPos) -> Self::Output {
520 BlockPos {
521 x: self.x * 16 + rhs.x as i32,
522 y: rhs.y,
523 z: self.z * 16 + rhs.z as i32,
524 }
525 }
526}
527
528impl From<ChunkPos> for u64 {
532 #[inline]
533 fn from(pos: ChunkPos) -> Self {
534 (pos.x as u64) | ((pos.z as u64) << 32)
535 }
536}
537impl From<u64> for ChunkPos {
538 #[inline]
539 fn from(pos: u64) -> Self {
540 ChunkPos {
541 x: (pos) as i32,
542 z: (pos >> 32) as i32,
543 }
544 }
545}
546impl AzaleaRead for ChunkPos {
547 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
548 let long = u64::azalea_read(buf)?;
549 Ok(ChunkPos::from(long))
550 }
551}
552impl AzaleaWrite for ChunkPos {
553 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
554 u64::from(*self).azalea_write(buf)?;
555 Ok(())
556 }
557}
558
559impl Hash for ChunkPos {
560 #[inline]
561 fn hash<H: Hasher>(&self, state: &mut H) {
562 u64::from(*self).hash(state);
564 }
565}
566impl nohash_hasher::IsEnabled for ChunkPos {}
569
570#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
572pub struct ChunkSectionPos {
573 pub x: i32,
574 pub y: i32,
575 pub z: i32,
576}
577vec3_impl!(ChunkSectionPos, i32);
578
579impl ChunkSectionPos {
580 pub fn block_to_section_coord(block: i32) -> i32 {
581 block >> 4
582 }
583}
584
585#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
587pub struct ChunkBlockPos {
588 pub x: u8,
589 pub y: i32,
590 pub z: u8,
591}
592
593impl ChunkBlockPos {
594 pub fn new(x: u8, y: i32, z: u8) -> Self {
595 ChunkBlockPos { x, y, z }
596 }
597}
598
599impl Hash for ChunkBlockPos {
600 #[inline]
602 fn hash<H: Hasher>(&self, state: &mut H) {
603 u64::from(*self).hash(state);
604 }
605}
606impl From<ChunkBlockPos> for u64 {
607 #[inline]
608 fn from(pos: ChunkBlockPos) -> Self {
609 let mut val: u64 = 0;
611 val |= pos.y as u64;
613 val |= (pos.z as u64) << 32;
615 val |= (pos.x as u64) << 40;
617 val
618 }
619}
620impl nohash_hasher::IsEnabled for ChunkBlockPos {}
621
622#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
626pub struct ChunkSectionBlockPos {
627 pub x: u8,
628 pub y: u8,
629 pub z: u8,
630}
631vec3_impl!(ChunkSectionBlockPos, u8);
632
633#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
637pub struct ChunkSectionBiomePos {
638 pub x: u8,
639 pub y: u8,
640 pub z: u8,
641}
642impl From<&ChunkBiomePos> for ChunkSectionBiomePos {
643 #[inline]
644 fn from(pos: &ChunkBiomePos) -> Self {
645 ChunkSectionBiomePos {
646 x: pos.x,
647 y: (pos.y & 0b11) as u8,
648 z: pos.z,
649 }
650 }
651}
652impl From<ChunkBiomePos> for ChunkSectionBiomePos {
653 #[inline]
654 fn from(pos: ChunkBiomePos) -> Self {
655 Self::from(&pos)
656 }
657}
658vec3_impl!(ChunkSectionBiomePos, u8);
659
660#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
664pub struct ChunkBiomePos {
665 pub x: u8,
666 pub y: i32,
667 pub z: u8,
668}
669impl From<&BlockPos> for ChunkBiomePos {
670 #[inline]
671 fn from(pos: &BlockPos) -> Self {
672 ChunkBiomePos::from(&ChunkBlockPos::from(pos))
673 }
674}
675impl From<BlockPos> for ChunkBiomePos {
676 #[inline]
677 fn from(pos: BlockPos) -> Self {
678 ChunkBiomePos::from(&ChunkBlockPos::from(pos))
679 }
680}
681impl From<&ChunkBlockPos> for ChunkBiomePos {
682 #[inline]
683 fn from(pos: &ChunkBlockPos) -> Self {
684 ChunkBiomePos {
685 x: pos.x >> 2,
686 y: pos.y >> 2,
687 z: pos.z >> 2,
688 }
689 }
690}
691
692impl Add<ChunkSectionBlockPos> for ChunkSectionPos {
693 type Output = BlockPos;
694
695 fn add(self, rhs: ChunkSectionBlockPos) -> Self::Output {
696 BlockPos::new(
697 self.x * 16 + rhs.x as i32,
698 self.y * 16 + rhs.y as i32,
699 self.z * 16 + rhs.z as i32,
700 )
701 }
702}
703impl Hash for ChunkSectionBlockPos {
704 #[inline]
706 fn hash<H: Hasher>(&self, state: &mut H) {
707 u16::from(*self).hash(state);
708 }
709}
710
711impl From<ChunkSectionBlockPos> for u16 {
712 #[inline]
713 fn from(pos: ChunkSectionBlockPos) -> Self {
714 ((((pos.y as u16) << 4) | pos.z as u16) << 4) | pos.x as u16
716 }
717}
718impl nohash_hasher::IsEnabled for ChunkSectionBlockPos {}
719
720#[derive(Debug, Clone, PartialEq, Serialize)]
722pub struct GlobalPos {
723 pub dimension: Identifier,
725 pub pos: BlockPos,
726}
727
728impl From<&BlockPos> for ChunkPos {
729 #[inline]
730 fn from(pos: &BlockPos) -> Self {
731 ChunkPos {
732 x: pos.x >> 4,
733 z: pos.z >> 4,
734 }
735 }
736}
737impl From<BlockPos> for ChunkPos {
738 #[inline]
739 fn from(pos: BlockPos) -> Self {
740 ChunkPos {
741 x: pos.x >> 4,
742 z: pos.z >> 4,
743 }
744 }
745}
746
747impl From<BlockPos> for ChunkSectionPos {
748 #[inline]
749 fn from(pos: BlockPos) -> Self {
750 ChunkSectionPos {
751 x: pos.x >> 4,
752 y: pos.y >> 4,
753 z: pos.z >> 4,
754 }
755 }
756}
757impl From<&BlockPos> for ChunkSectionPos {
758 #[inline]
759 fn from(pos: &BlockPos) -> Self {
760 ChunkSectionPos {
761 x: pos.x >> 4,
762 y: pos.y >> 4,
763 z: pos.z >> 4,
764 }
765 }
766}
767
768impl From<ChunkSectionPos> for ChunkPos {
769 fn from(pos: ChunkSectionPos) -> Self {
770 ChunkPos { x: pos.x, z: pos.z }
771 }
772}
773impl From<&Vec3> for ChunkSectionPos {
774 fn from(pos: &Vec3) -> Self {
775 ChunkSectionPos::from(&BlockPos::from(pos))
776 }
777}
778impl From<Vec3> for ChunkSectionPos {
779 fn from(pos: Vec3) -> Self {
780 ChunkSectionPos::from(&pos)
781 }
782}
783
784impl From<&BlockPos> for ChunkBlockPos {
785 #[inline]
786 fn from(pos: &BlockPos) -> Self {
787 ChunkBlockPos {
788 x: (pos.x & 0xF) as u8,
789 y: pos.y,
790 z: (pos.z & 0xF) as u8,
791 }
792 }
793}
794impl From<BlockPos> for ChunkBlockPos {
795 #[inline]
796 fn from(pos: BlockPos) -> Self {
797 ChunkBlockPos {
798 x: (pos.x & 0xF) as u8,
799 y: pos.y,
800 z: (pos.z & 0xF) as u8,
801 }
802 }
803}
804
805impl From<BlockPos> for ChunkSectionBlockPos {
806 #[inline]
807 fn from(pos: BlockPos) -> Self {
808 ChunkSectionBlockPos {
809 x: (pos.x & 0xF) as u8,
810 y: (pos.y & 0xF) as u8,
811 z: (pos.z & 0xF) as u8,
812 }
813 }
814}
815
816impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
817 #[inline]
818 fn from(pos: &ChunkBlockPos) -> Self {
819 ChunkSectionBlockPos {
820 x: pos.x,
821 y: (pos.y & 0xF) as u8,
822 z: pos.z,
823 }
824 }
825}
826impl From<&Vec3> for BlockPos {
827 #[inline]
828 fn from(pos: &Vec3) -> Self {
829 BlockPos {
830 x: pos.x.floor() as i32,
831 y: pos.y.floor() as i32,
832 z: pos.z.floor() as i32,
833 }
834 }
835}
836impl From<Vec3> for BlockPos {
837 #[inline]
838 fn from(pos: Vec3) -> Self {
839 BlockPos::from(&pos)
840 }
841}
842
843impl From<&Vec3> for ChunkPos {
844 fn from(pos: &Vec3) -> Self {
845 ChunkPos::from(&BlockPos::from(pos))
846 }
847}
848impl From<Vec3> for ChunkPos {
849 fn from(pos: Vec3) -> Self {
850 ChunkPos::from(&pos)
851 }
852}
853
854impl From<&Vec3> for ChunkBlockPos {
855 fn from(pos: &Vec3) -> Self {
856 ChunkBlockPos::from(&BlockPos::from(pos))
857 }
858}
859impl From<Vec3> for ChunkBlockPos {
860 fn from(pos: Vec3) -> Self {
861 ChunkBlockPos::from(&pos)
862 }
863}
864
865impl fmt::Display for BlockPos {
866 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
868 write!(f, "{} {} {}", self.x, self.y, self.z)
869 }
870}
871impl fmt::Display for Vec3 {
872 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
874 write!(f, "{} {} {}", self.x, self.y, self.z)
875 }
876}
877
878#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf, Deserialize, Serialize)]
880pub struct Vec2 {
881 pub x: f32,
882 pub y: f32,
883}
884impl Vec2 {
885 const ZERO: Vec2 = Vec2 { x: 0.0, y: 0.0 };
886
887 #[inline]
888 pub fn new(x: f32, y: f32) -> Self {
889 Vec2 { x, y }
890 }
891 #[inline]
892 pub fn scale(&self, amount: f32) -> Self {
893 Vec2 {
894 x: self.x * amount,
895 y: self.y * amount,
896 }
897 }
898 #[inline]
899 pub fn dot(&self, other: Vec2) -> f32 {
900 self.x * other.x + self.y * other.y
901 }
902 #[inline]
903 pub fn normalized(&self) -> Self {
904 let length = (self.x * self.x + self.y * self.y).sqrt();
905 if length < 1e-4 {
906 return Vec2::ZERO;
907 }
908 Vec2 {
909 x: self.x / length,
910 y: self.y / length,
911 }
912 }
913 #[inline]
914 pub fn length_squared(&self) -> f32 {
915 self.x * self.x + self.y * self.y
916 }
917 #[inline]
918 pub fn length(&self) -> f32 {
919 self.length_squared().sqrt()
920 }
921}
922impl Mul<f32> for Vec2 {
923 type Output = Self;
924
925 #[inline]
926 fn mul(self, rhs: f32) -> Self::Output {
927 self.scale(rhs)
928 }
929}
930impl MulAssign<f32> for Vec2 {
931 #[inline]
932 fn mul_assign(&mut self, rhs: f32) {
933 *self = self.scale(rhs);
934 }
935}
936
937const PACKED_X_LENGTH: u64 = 1 + 25; const PACKED_Z_LENGTH: u64 = PACKED_X_LENGTH;
939const PACKED_Y_LENGTH: u64 = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
940const PACKED_X_MASK: u64 = (1 << PACKED_X_LENGTH) - 1;
941const PACKED_Y_MASK: u64 = (1 << PACKED_Y_LENGTH) - 1;
942const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
943const Z_OFFSET: u64 = PACKED_Y_LENGTH;
944const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
945
946impl AzaleaRead for BlockPos {
947 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
948 let val = i64::azalea_read(buf)?;
949 let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
950 let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
951 let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
952 Ok(BlockPos { x, y, z })
953 }
954}
955
956impl AzaleaRead for GlobalPos {
957 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
958 Ok(GlobalPos {
959 dimension: Identifier::azalea_read(buf)?,
960 pos: BlockPos::azalea_read(buf)?,
961 })
962 }
963}
964
965impl AzaleaRead for ChunkSectionPos {
966 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
967 let long = i64::azalea_read(buf)?;
968 Ok(ChunkSectionPos {
969 x: (long >> 42) as i32,
970 y: (long << 44 >> 44) as i32,
971 z: (long << 22 >> 42) as i32,
972 })
973 }
974}
975
976impl AzaleaWrite for BlockPos {
977 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
978 let mut val: u64 = 0;
979 val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
980 val |= (self.y as u64) & PACKED_Y_MASK;
981 val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
982 val.azalea_write(buf)
983 }
984}
985
986impl AzaleaWrite for GlobalPos {
987 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
988 Identifier::azalea_write(&self.dimension, buf)?;
989 BlockPos::azalea_write(&self.pos, buf)?;
990
991 Ok(())
992 }
993}
994
995impl AzaleaWrite for ChunkSectionPos {
996 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
997 let long = (((self.x & 0x3FFFFF) as i64) << 42)
998 | (self.y & 0xFFFFF) as i64
999 | (((self.z & 0x3FFFFF) as i64) << 20);
1000 long.azalea_write(buf)?;
1001 Ok(())
1002 }
1003}
1004
1005fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
1006where
1007 T: FromStr,
1008 <T as FromStr>::Err: fmt::Debug,
1009{
1010 let parts = s.split_whitespace().collect::<Vec<_>>();
1011 if parts.len() != 3 {
1012 return Err("Expected three values");
1013 }
1014
1015 let x = parts[0].parse().map_err(|_| "Invalid X value")?;
1016 let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
1017 let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
1018
1019 Ok([x, y, z])
1020}
1021
1022impl FromStr for BlockPos {
1028 type Err = &'static str;
1029
1030 fn from_str(s: &str) -> Result<Self, Self::Err> {
1031 let [x, y, z] = parse_three_values::<i32>(s)?;
1032 Ok(BlockPos { x, y, z })
1033 }
1034}
1035
1036impl FromStr for Vec3 {
1042 type Err = &'static str;
1043
1044 fn from_str(s: &str) -> Result<Self, Self::Err> {
1045 let [x, y, z] = parse_three_values::<f64>(s)?;
1046 Ok(Vec3 { x, y, z })
1047 }
1048}
1049
1050#[cfg(test)]
1051mod tests {
1052 use super::*;
1053
1054 #[test]
1055 fn test_from_block_pos_to_chunk_pos() {
1056 let block_pos = BlockPos::new(5, 78, -2);
1057 let chunk_pos = ChunkPos::from(&block_pos);
1058 assert_eq!(chunk_pos, ChunkPos::new(0, -1));
1059 }
1060
1061 #[test]
1062 fn test_from_block_pos_to_chunk_block_pos() {
1063 let block_pos = BlockPos::new(5, 78, -2);
1064 let chunk_block_pos = ChunkBlockPos::from(&block_pos);
1065 assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
1066 }
1067
1068 #[test]
1069 fn test_from_entity_pos_to_block_pos() {
1070 let entity_pos = Vec3 {
1071 x: 31.5,
1072 y: 80.0,
1073 z: -16.1,
1074 };
1075 let block_pos = BlockPos::from(&entity_pos);
1076 assert_eq!(block_pos, BlockPos::new(31, 80, -17));
1077 }
1078
1079 #[test]
1080 fn test_from_entity_pos_to_chunk_pos() {
1081 let entity_pos = Vec3 {
1082 x: 31.5,
1083 y: 80.0,
1084 z: -16.1,
1085 };
1086 let chunk_pos = ChunkPos::from(&entity_pos);
1087 assert_eq!(chunk_pos, ChunkPos::new(1, -2));
1088 }
1089
1090 #[test]
1091 fn test_read_blockpos_from() {
1092 let mut buf = Vec::new();
1093 13743895338965u64.azalea_write(&mut buf).unwrap();
1094 let mut buf = Cursor::new(&buf[..]);
1095 let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
1096 assert_eq!(block_pos, BlockPos::new(49, -43, -3));
1097 }
1098
1099 #[test]
1100 fn test_into_chunk_section_block_pos() {
1101 let block_pos = BlockPos::new(0, -60, 0);
1102 assert_eq!(
1103 ChunkSectionBlockPos::from(block_pos),
1104 ChunkSectionBlockPos::new(0, 4, 0)
1105 );
1106 }
1107
1108 #[test]
1109 fn test_read_chunk_pos_from() {
1110 let mut buf = Vec::new();
1111 ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
1112 let mut buf = Cursor::new(&buf[..]);
1113 let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
1114 assert_eq!(chunk_pos, ChunkPos::new(2, -1));
1115 }
1116}