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