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