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)]
491pub struct ChunkPos {
492 pub x: i32,
493 pub z: i32,
494}
495impl ChunkPos {
496 pub fn new(x: i32, z: i32) -> Self {
497 ChunkPos { x, z }
498 }
499}
500impl Add<ChunkPos> for ChunkPos {
501 type Output = Self;
502
503 fn add(self, rhs: Self) -> Self::Output {
504 Self {
505 x: self.x + rhs.x,
506 z: self.z + rhs.z,
507 }
508 }
509}
510impl Add<ChunkBlockPos> for ChunkPos {
511 type Output = BlockPos;
512
513 fn add(self, rhs: ChunkBlockPos) -> Self::Output {
514 BlockPos {
515 x: self.x * 16 + rhs.x as i32,
516 y: rhs.y,
517 z: self.z * 16 + rhs.z as i32,
518 }
519 }
520}
521
522impl From<ChunkPos> for u64 {
526 #[inline]
527 fn from(pos: ChunkPos) -> Self {
528 (pos.x as u64) | ((pos.z as u64) << 32)
529 }
530}
531impl From<u64> for ChunkPos {
532 #[inline]
533 fn from(pos: u64) -> Self {
534 ChunkPos {
535 x: (pos) as i32,
536 z: (pos >> 32) as i32,
537 }
538 }
539}
540impl AzaleaRead for ChunkPos {
541 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
542 let long = u64::azalea_read(buf)?;
543 Ok(ChunkPos::from(long))
544 }
545}
546impl AzaleaWrite for ChunkPos {
547 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
548 u64::from(*self).azalea_write(buf)?;
549 Ok(())
550 }
551}
552
553impl Hash for ChunkPos {
554 #[inline]
555 fn hash<H: Hasher>(&self, state: &mut H) {
556 u64::from(*self).hash(state);
558 }
559}
560impl nohash_hasher::IsEnabled for ChunkPos {}
563
564#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
566pub struct ChunkSectionPos {
567 pub x: i32,
568 pub y: i32,
569 pub z: i32,
570}
571vec3_impl!(ChunkSectionPos, i32);
572
573impl ChunkSectionPos {
574 pub fn block_to_section_coord(block: i32) -> i32 {
575 block >> 4
576 }
577}
578
579#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
581pub struct ChunkBlockPos {
582 pub x: u8,
583 pub y: i32,
584 pub z: u8,
585}
586
587impl ChunkBlockPos {
588 pub fn new(x: u8, y: i32, z: u8) -> Self {
589 ChunkBlockPos { x, y, z }
590 }
591}
592
593impl Hash for ChunkBlockPos {
594 #[inline]
596 fn hash<H: Hasher>(&self, state: &mut H) {
597 u64::from(*self).hash(state);
598 }
599}
600impl From<ChunkBlockPos> for u64 {
601 #[inline]
602 fn from(pos: ChunkBlockPos) -> Self {
603 let mut val: u64 = 0;
605 val |= pos.y as u64;
607 val |= (pos.z as u64) << 32;
609 val |= (pos.x as u64) << 40;
611 val
612 }
613}
614impl nohash_hasher::IsEnabled for ChunkBlockPos {}
615
616#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
620pub struct ChunkSectionBlockPos {
621 pub x: u8,
622 pub y: u8,
623 pub z: u8,
624}
625vec3_impl!(ChunkSectionBlockPos, u8);
626
627#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
631pub struct ChunkSectionBiomePos {
632 pub x: u8,
633 pub y: u8,
634 pub z: u8,
635}
636impl From<&ChunkBiomePos> for ChunkSectionBiomePos {
637 #[inline]
638 fn from(pos: &ChunkBiomePos) -> Self {
639 ChunkSectionBiomePos {
640 x: pos.x,
641 y: (pos.y & 0b11) as u8,
642 z: pos.z,
643 }
644 }
645}
646impl From<ChunkBiomePos> for ChunkSectionBiomePos {
647 #[inline]
648 fn from(pos: ChunkBiomePos) -> Self {
649 Self::from(&pos)
650 }
651}
652vec3_impl!(ChunkSectionBiomePos, u8);
653
654#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
658pub struct ChunkBiomePos {
659 pub x: u8,
660 pub y: i32,
661 pub z: u8,
662}
663impl From<&BlockPos> for ChunkBiomePos {
664 #[inline]
665 fn from(pos: &BlockPos) -> Self {
666 ChunkBiomePos::from(&ChunkBlockPos::from(pos))
667 }
668}
669impl From<BlockPos> for ChunkBiomePos {
670 #[inline]
671 fn from(pos: BlockPos) -> Self {
672 ChunkBiomePos::from(&ChunkBlockPos::from(pos))
673 }
674}
675impl From<&ChunkBlockPos> for ChunkBiomePos {
676 #[inline]
677 fn from(pos: &ChunkBlockPos) -> Self {
678 ChunkBiomePos {
679 x: pos.x >> 2,
680 y: pos.y >> 2,
681 z: pos.z >> 2,
682 }
683 }
684}
685
686impl Add<ChunkSectionBlockPos> for ChunkSectionPos {
687 type Output = BlockPos;
688
689 fn add(self, rhs: ChunkSectionBlockPos) -> Self::Output {
690 BlockPos::new(
691 self.x * 16 + rhs.x as i32,
692 self.y * 16 + rhs.y as i32,
693 self.z * 16 + rhs.z as i32,
694 )
695 }
696}
697impl Hash for ChunkSectionBlockPos {
698 #[inline]
700 fn hash<H: Hasher>(&self, state: &mut H) {
701 u16::from(*self).hash(state);
702 }
703}
704
705impl From<ChunkSectionBlockPos> for u16 {
706 #[inline]
707 fn from(pos: ChunkSectionBlockPos) -> Self {
708 ((((pos.y as u16) << 4) | pos.z as u16) << 4) | pos.x as u16
710 }
711}
712impl nohash_hasher::IsEnabled for ChunkSectionBlockPos {}
713
714#[derive(Debug, Clone, PartialEq, Serialize)]
716pub struct GlobalPos {
717 pub dimension: ResourceLocation,
719 pub pos: BlockPos,
720}
721
722impl From<&BlockPos> for ChunkPos {
723 #[inline]
724 fn from(pos: &BlockPos) -> Self {
725 ChunkPos {
726 x: pos.x >> 4,
727 z: pos.z >> 4,
728 }
729 }
730}
731impl From<BlockPos> for ChunkPos {
732 #[inline]
733 fn from(pos: BlockPos) -> Self {
734 ChunkPos {
735 x: pos.x >> 4,
736 z: pos.z >> 4,
737 }
738 }
739}
740
741impl From<BlockPos> for ChunkSectionPos {
742 #[inline]
743 fn from(pos: BlockPos) -> Self {
744 ChunkSectionPos {
745 x: pos.x >> 4,
746 y: pos.y >> 4,
747 z: pos.z >> 4,
748 }
749 }
750}
751impl From<&BlockPos> for ChunkSectionPos {
752 #[inline]
753 fn from(pos: &BlockPos) -> Self {
754 ChunkSectionPos {
755 x: pos.x >> 4,
756 y: pos.y >> 4,
757 z: pos.z >> 4,
758 }
759 }
760}
761
762impl From<ChunkSectionPos> for ChunkPos {
763 fn from(pos: ChunkSectionPos) -> Self {
764 ChunkPos { x: pos.x, z: pos.z }
765 }
766}
767impl From<&Vec3> for ChunkSectionPos {
768 fn from(pos: &Vec3) -> Self {
769 ChunkSectionPos::from(&BlockPos::from(pos))
770 }
771}
772impl From<Vec3> for ChunkSectionPos {
773 fn from(pos: Vec3) -> Self {
774 ChunkSectionPos::from(&pos)
775 }
776}
777
778impl From<&BlockPos> for ChunkBlockPos {
779 #[inline]
780 fn from(pos: &BlockPos) -> Self {
781 ChunkBlockPos {
782 x: (pos.x & 0xF) as u8,
783 y: pos.y,
784 z: (pos.z & 0xF) as u8,
785 }
786 }
787}
788impl From<BlockPos> for ChunkBlockPos {
789 #[inline]
790 fn from(pos: BlockPos) -> Self {
791 ChunkBlockPos {
792 x: (pos.x & 0xF) as u8,
793 y: pos.y,
794 z: (pos.z & 0xF) as u8,
795 }
796 }
797}
798
799impl From<BlockPos> for ChunkSectionBlockPos {
800 #[inline]
801 fn from(pos: BlockPos) -> Self {
802 ChunkSectionBlockPos {
803 x: (pos.x & 0xF) as u8,
804 y: (pos.y & 0xF) as u8,
805 z: (pos.z & 0xF) as u8,
806 }
807 }
808}
809
810impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
811 #[inline]
812 fn from(pos: &ChunkBlockPos) -> Self {
813 ChunkSectionBlockPos {
814 x: pos.x,
815 y: (pos.y & 0xF) as u8,
816 z: pos.z,
817 }
818 }
819}
820impl From<&Vec3> for BlockPos {
821 #[inline]
822 fn from(pos: &Vec3) -> Self {
823 BlockPos {
824 x: pos.x.floor() as i32,
825 y: pos.y.floor() as i32,
826 z: pos.z.floor() as i32,
827 }
828 }
829}
830impl From<Vec3> for BlockPos {
831 #[inline]
832 fn from(pos: Vec3) -> Self {
833 BlockPos::from(&pos)
834 }
835}
836
837impl From<&Vec3> for ChunkPos {
838 fn from(pos: &Vec3) -> Self {
839 ChunkPos::from(&BlockPos::from(pos))
840 }
841}
842impl From<Vec3> for ChunkPos {
843 fn from(pos: Vec3) -> Self {
844 ChunkPos::from(&pos)
845 }
846}
847
848impl From<&Vec3> for ChunkBlockPos {
849 fn from(pos: &Vec3) -> Self {
850 ChunkBlockPos::from(&BlockPos::from(pos))
851 }
852}
853impl From<Vec3> for ChunkBlockPos {
854 fn from(pos: Vec3) -> Self {
855 ChunkBlockPos::from(&pos)
856 }
857}
858
859impl fmt::Display for BlockPos {
860 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
862 write!(f, "{} {} {}", self.x, self.y, self.z)
863 }
864}
865impl fmt::Display for Vec3 {
866 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
868 write!(f, "{} {} {}", self.x, self.y, self.z)
869 }
870}
871
872#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf, Deserialize, Serialize)]
874pub struct Vec2 {
875 pub x: f32,
876 pub y: f32,
877}
878impl Vec2 {
879 const ZERO: Vec2 = Vec2 { x: 0.0, y: 0.0 };
880
881 #[inline]
882 pub fn new(x: f32, y: f32) -> Self {
883 Vec2 { x, y }
884 }
885 #[inline]
886 pub fn scale(&self, amount: f32) -> Self {
887 Vec2 {
888 x: self.x * amount,
889 y: self.y * amount,
890 }
891 }
892 #[inline]
893 pub fn dot(&self, other: Vec2) -> f32 {
894 self.x * other.x + self.y * other.y
895 }
896 #[inline]
897 pub fn normalized(&self) -> Self {
898 let length = (self.x * self.x + self.y * self.y).sqrt();
899 if length < 1e-4 {
900 return Vec2::ZERO;
901 }
902 Vec2 {
903 x: self.x / length,
904 y: self.y / length,
905 }
906 }
907 #[inline]
908 pub fn length_squared(&self) -> f32 {
909 self.x * self.x + self.y * self.y
910 }
911 #[inline]
912 pub fn length(&self) -> f32 {
913 self.length_squared().sqrt()
914 }
915}
916impl Mul<f32> for Vec2 {
917 type Output = Self;
918
919 #[inline]
920 fn mul(self, rhs: f32) -> Self::Output {
921 self.scale(rhs)
922 }
923}
924impl MulAssign<f32> for Vec2 {
925 #[inline]
926 fn mul_assign(&mut self, rhs: f32) {
927 *self = self.scale(rhs);
928 }
929}
930
931const PACKED_X_LENGTH: u64 = 1 + 25; const PACKED_Z_LENGTH: u64 = PACKED_X_LENGTH;
933const PACKED_Y_LENGTH: u64 = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
934const PACKED_X_MASK: u64 = (1 << PACKED_X_LENGTH) - 1;
935const PACKED_Y_MASK: u64 = (1 << PACKED_Y_LENGTH) - 1;
936const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
937const Z_OFFSET: u64 = PACKED_Y_LENGTH;
938const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
939
940impl AzaleaRead for BlockPos {
941 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
942 let val = i64::azalea_read(buf)?;
943 let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
944 let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
945 let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
946 Ok(BlockPos { x, y, z })
947 }
948}
949
950impl AzaleaRead for GlobalPos {
951 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
952 Ok(GlobalPos {
953 dimension: ResourceLocation::azalea_read(buf)?,
954 pos: BlockPos::azalea_read(buf)?,
955 })
956 }
957}
958
959impl AzaleaRead for ChunkSectionPos {
960 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
961 let long = i64::azalea_read(buf)?;
962 Ok(ChunkSectionPos {
963 x: (long >> 42) as i32,
964 y: (long << 44 >> 44) as i32,
965 z: (long << 22 >> 42) as i32,
966 })
967 }
968}
969
970impl AzaleaWrite for BlockPos {
971 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
972 let mut val: u64 = 0;
973 val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
974 val |= (self.y as u64) & PACKED_Y_MASK;
975 val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
976 val.azalea_write(buf)
977 }
978}
979
980impl AzaleaWrite for GlobalPos {
981 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
982 ResourceLocation::azalea_write(&self.dimension, buf)?;
983 BlockPos::azalea_write(&self.pos, buf)?;
984
985 Ok(())
986 }
987}
988
989impl AzaleaWrite for ChunkSectionPos {
990 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
991 let long = (((self.x & 0x3FFFFF) as i64) << 42)
992 | (self.y & 0xFFFFF) as i64
993 | (((self.z & 0x3FFFFF) as i64) << 20);
994 long.azalea_write(buf)?;
995 Ok(())
996 }
997}
998
999fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
1000where
1001 T: FromStr,
1002 <T as FromStr>::Err: fmt::Debug,
1003{
1004 let parts = s.split_whitespace().collect::<Vec<_>>();
1005 if parts.len() != 3 {
1006 return Err("Expected three values");
1007 }
1008
1009 let x = parts[0].parse().map_err(|_| "Invalid X value")?;
1010 let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
1011 let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
1012
1013 Ok([x, y, z])
1014}
1015
1016impl FromStr for BlockPos {
1022 type Err = &'static str;
1023
1024 fn from_str(s: &str) -> Result<Self, Self::Err> {
1025 let [x, y, z] = parse_three_values::<i32>(s)?;
1026 Ok(BlockPos { x, y, z })
1027 }
1028}
1029
1030impl FromStr for Vec3 {
1036 type Err = &'static str;
1037
1038 fn from_str(s: &str) -> Result<Self, Self::Err> {
1039 let [x, y, z] = parse_three_values::<f64>(s)?;
1040 Ok(Vec3 { x, y, z })
1041 }
1042}
1043
1044#[cfg(test)]
1045mod tests {
1046 use super::*;
1047
1048 #[test]
1049 fn test_from_block_pos_to_chunk_pos() {
1050 let block_pos = BlockPos::new(5, 78, -2);
1051 let chunk_pos = ChunkPos::from(&block_pos);
1052 assert_eq!(chunk_pos, ChunkPos::new(0, -1));
1053 }
1054
1055 #[test]
1056 fn test_from_block_pos_to_chunk_block_pos() {
1057 let block_pos = BlockPos::new(5, 78, -2);
1058 let chunk_block_pos = ChunkBlockPos::from(&block_pos);
1059 assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
1060 }
1061
1062 #[test]
1063 fn test_from_entity_pos_to_block_pos() {
1064 let entity_pos = Vec3 {
1065 x: 31.5,
1066 y: 80.0,
1067 z: -16.1,
1068 };
1069 let block_pos = BlockPos::from(&entity_pos);
1070 assert_eq!(block_pos, BlockPos::new(31, 80, -17));
1071 }
1072
1073 #[test]
1074 fn test_from_entity_pos_to_chunk_pos() {
1075 let entity_pos = Vec3 {
1076 x: 31.5,
1077 y: 80.0,
1078 z: -16.1,
1079 };
1080 let chunk_pos = ChunkPos::from(&entity_pos);
1081 assert_eq!(chunk_pos, ChunkPos::new(1, -2));
1082 }
1083
1084 #[test]
1085 fn test_read_blockpos_from() {
1086 let mut buf = Vec::new();
1087 13743895338965u64.azalea_write(&mut buf).unwrap();
1088 let mut buf = Cursor::new(&buf[..]);
1089 let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
1090 assert_eq!(block_pos, BlockPos::new(49, -43, -3));
1091 }
1092
1093 #[test]
1094 fn test_into_chunk_section_block_pos() {
1095 let block_pos = BlockPos::new(0, -60, 0);
1096 assert_eq!(
1097 ChunkSectionBlockPos::from(block_pos),
1098 ChunkSectionBlockPos::new(0, 4, 0)
1099 );
1100 }
1101
1102 #[test]
1103 fn test_read_chunk_pos_from() {
1104 let mut buf = Vec::new();
1105 ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
1106 let mut buf = Cursor::new(&buf[..]);
1107 let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
1108 assert_eq!(chunk_pos, ChunkPos::new(2, -1));
1109 }
1110}