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
821const PACKED_X_LENGTH: u64 = 1 + 25; const PACKED_Z_LENGTH: u64 = PACKED_X_LENGTH;
823const PACKED_Y_LENGTH: u64 = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
824const PACKED_X_MASK: u64 = (1 << PACKED_X_LENGTH) - 1;
825const PACKED_Y_MASK: u64 = (1 << PACKED_Y_LENGTH) - 1;
826const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
827const Z_OFFSET: u64 = PACKED_Y_LENGTH;
828const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
829
830impl AzaleaRead for BlockPos {
831 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
832 let val = i64::azalea_read(buf)?;
833 let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
834 let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
835 let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
836 Ok(BlockPos { x, y, z })
837 }
838}
839
840impl AzaleaRead for GlobalPos {
841 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
842 Ok(GlobalPos {
843 world: ResourceLocation::azalea_read(buf)?,
844 pos: BlockPos::azalea_read(buf)?,
845 })
846 }
847}
848
849impl AzaleaRead for ChunkSectionPos {
850 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
851 let long = i64::azalea_read(buf)?;
852 Ok(ChunkSectionPos {
853 x: (long >> 42) as i32,
854 y: (long << 44 >> 44) as i32,
855 z: (long << 22 >> 42) as i32,
856 })
857 }
858}
859
860impl AzaleaWrite for BlockPos {
861 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
862 let mut val: u64 = 0;
863 val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
864 val |= (self.y as u64) & PACKED_Y_MASK;
865 val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
866 val.azalea_write(buf)
867 }
868}
869
870impl AzaleaWrite for GlobalPos {
871 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
872 ResourceLocation::azalea_write(&self.world, buf)?;
873 BlockPos::azalea_write(&self.pos, buf)?;
874
875 Ok(())
876 }
877}
878
879impl AzaleaWrite for ChunkSectionPos {
880 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
881 let long = (((self.x & 0x3FFFFF) as i64) << 42)
882 | (self.y & 0xFFFFF) as i64
883 | (((self.z & 0x3FFFFF) as i64) << 20);
884 long.azalea_write(buf)?;
885 Ok(())
886 }
887}
888
889fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
890where
891 T: FromStr,
892 <T as FromStr>::Err: fmt::Debug,
893{
894 let parts = s.split_whitespace().collect::<Vec<_>>();
895 if parts.len() != 3 {
896 return Err("Expected three values");
897 }
898
899 let x = parts[0].parse().map_err(|_| "Invalid X value")?;
900 let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
901 let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
902
903 Ok([x, y, z])
904}
905
906impl FromStr for BlockPos {
912 type Err = &'static str;
913
914 fn from_str(s: &str) -> Result<Self, Self::Err> {
915 let [x, y, z] = parse_three_values::<i32>(s)?;
916 Ok(BlockPos { x, y, z })
917 }
918}
919
920impl FromStr for Vec3 {
926 type Err = &'static str;
927
928 fn from_str(s: &str) -> Result<Self, Self::Err> {
929 let [x, y, z] = parse_three_values::<f64>(s)?;
930 Ok(Vec3 { x, y, z })
931 }
932}
933
934#[cfg(test)]
935mod tests {
936 use super::*;
937
938 #[test]
939 fn test_from_block_pos_to_chunk_pos() {
940 let block_pos = BlockPos::new(5, 78, -2);
941 let chunk_pos = ChunkPos::from(&block_pos);
942 assert_eq!(chunk_pos, ChunkPos::new(0, -1));
943 }
944
945 #[test]
946 fn test_from_block_pos_to_chunk_block_pos() {
947 let block_pos = BlockPos::new(5, 78, -2);
948 let chunk_block_pos = ChunkBlockPos::from(&block_pos);
949 assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
950 }
951
952 #[test]
953 fn test_from_entity_pos_to_block_pos() {
954 let entity_pos = Vec3 {
955 x: 31.5,
956 y: 80.0,
957 z: -16.1,
958 };
959 let block_pos = BlockPos::from(&entity_pos);
960 assert_eq!(block_pos, BlockPos::new(31, 80, -17));
961 }
962
963 #[test]
964 fn test_from_entity_pos_to_chunk_pos() {
965 let entity_pos = Vec3 {
966 x: 31.5,
967 y: 80.0,
968 z: -16.1,
969 };
970 let chunk_pos = ChunkPos::from(&entity_pos);
971 assert_eq!(chunk_pos, ChunkPos::new(1, -2));
972 }
973
974 #[test]
975 fn test_read_blockpos_from() {
976 let mut buf = Vec::new();
977 13743895338965u64.azalea_write(&mut buf).unwrap();
978 let mut buf = Cursor::new(&buf[..]);
979 let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
980 assert_eq!(block_pos, BlockPos::new(49, -43, -3));
981 }
982
983 #[test]
984 fn test_into_chunk_section_block_pos() {
985 let block_pos = BlockPos::new(0, -60, 0);
986 assert_eq!(
987 ChunkSectionBlockPos::from(block_pos),
988 ChunkSectionBlockPos::new(0, 4, 0)
989 );
990 }
991
992 #[test]
993 fn test_read_chunk_pos_from() {
994 let mut buf = Vec::new();
995 ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
996 let mut buf = Cursor::new(&buf[..]);
997 let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
998 assert_eq!(chunk_pos, ChunkPos::new(2, -1));
999 }
1000}