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