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