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