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(Clone, Copy, Debug, Default, PartialEq, AzBuf, serde::Deserialize, 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()?.doubles()?;
318 let [x, y, z] = <[f64; 3]>::try_from(pos).ok()?;
319 Some(Self { x, y, z })
320 }
321}
322
323impl Vec3 {
324 pub fn length(&self) -> f64 {
327 f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
328 }
329
330 pub fn distance_to(self, other: Self) -> f64 {
333 (self - other).length()
334 }
335
336 pub fn x_rot(self, radians: f32) -> Vec3 {
337 let x_delta = math::cos(radians);
338 let y_delta = math::sin(radians);
339 let x = self.x;
340 let y = self.y * (x_delta as f64) + self.z * (y_delta as f64);
341 let z = self.z * (x_delta as f64) - self.y * (y_delta as f64);
342 Vec3 { x, y, z }
343 }
344 pub fn y_rot(self, radians: f32) -> Vec3 {
345 let x_delta = math::cos(radians);
346 let y_delta = math::sin(radians);
347 let x = self.x * (x_delta as f64) + self.z * (y_delta as f64);
348 let y = self.y;
349 let z = self.z * (x_delta as f64) - self.x * (y_delta as f64);
350 Vec3 { x, y, z }
351 }
352
353 pub fn to_block_pos_floor(&self) -> BlockPos {
354 BlockPos {
355 x: self.x.floor() as i32,
356 y: self.y.floor() as i32,
357 z: self.z.floor() as i32,
358 }
359 }
360 pub fn to_block_pos_ceil(&self) -> BlockPos {
361 BlockPos {
362 x: self.x.ceil() as i32,
363 y: self.y.ceil() as i32,
364 z: self.z.ceil() as i32,
365 }
366 }
367
368 pub fn closer_than(&self, other: Vec3, range: f64) -> bool {
371 self.distance_squared_to(other) < range.powi(2)
372 }
373}
374
375#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf)]
377pub struct Vec3f32 {
378 pub x: f32,
379 pub y: f32,
380 pub z: f32,
381}
382impl From<Vec3f32> for Vec3 {
383 fn from(v: Vec3f32) -> Self {
384 Vec3 {
385 x: v.x as f64,
386 y: v.y as f64,
387 z: v.z as f64,
388 }
389 }
390}
391impl From<Vec3> for Vec3f32 {
392 fn from(v: Vec3) -> Self {
393 Vec3f32 {
394 x: v.x as f32,
395 y: v.y as f32,
396 z: v.z as f32,
397 }
398 }
399}
400
401#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
405pub struct BlockPos {
406 pub x: i32,
407 pub y: i32,
408 pub z: i32,
409}
410vec3_impl!(BlockPos, i32);
411
412impl BlockPos {
413 pub fn center(&self) -> Vec3 {
416 Vec3 {
417 x: self.x as f64 + 0.5,
418 y: self.y as f64 + 0.5,
419 z: self.z as f64 + 0.5,
420 }
421 }
422
423 pub fn center_bottom(&self) -> Vec3 {
426 Vec3 {
427 x: self.x as f64 + 0.5,
428 y: self.y as f64,
429 z: self.z as f64 + 0.5,
430 }
431 }
432
433 pub fn to_vec3_floored(&self) -> Vec3 {
435 Vec3 {
436 x: self.x as f64,
437 y: self.y as f64,
438 z: self.z as f64,
439 }
440 }
441
442 pub fn length_manhattan(&self) -> u32 {
444 (self.x.abs() + self.y.abs() + self.z.abs()) as u32
445 }
446
447 pub fn offset_with_direction(self, direction: Direction) -> Self {
448 self + direction.normal()
449 }
450
451 pub fn length(&self) -> f64 {
454 f64::sqrt((self.x * self.x + self.y * self.y + self.z * self.z) as f64)
455 }
456
457 pub fn distance_to(self, other: Self) -> f64 {
464 (self - other).length()
465 }
466}
467impl serde::Serialize for BlockPos {
468 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
469 where
470 S: Serializer,
471 {
472 IntArray([self.x, self.y, self.z]).serialize(serializer)
474 }
475}
476impl<'de> serde::Deserialize<'de> for BlockPos {
477 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
478 where
479 D: serde::Deserializer<'de>,
480 {
481 let [x, y, z] = <[i32; 3]>::deserialize(deserializer)?;
482 Ok(BlockPos { x, y, z })
483 }
484}
485
486#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, AzBuf)]
491pub struct Vec3i {
492 #[var]
493 pub x: i32,
494 #[var]
495 pub y: i32,
496 #[var]
497 pub z: i32,
498}
499vec3_impl!(Vec3i, i32);
500impl simdnbt::FromNbtTag for Vec3i {
501 fn from_nbt_tag(tag: NbtTag) -> Option<Self> {
502 let pos = tag.list()?.ints()?;
503 let [x, y, z] = <[i32; 3]>::try_from(pos).ok()?;
504 Some(Self { x, y, z })
505 }
506}
507
508#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
512pub struct ChunkPos {
513 pub x: i32,
514 pub z: i32,
515}
516impl ChunkPos {
517 pub fn new(x: i32, z: i32) -> Self {
518 ChunkPos { x, z }
519 }
520}
521impl Add<ChunkPos> for ChunkPos {
522 type Output = Self;
523
524 fn add(self, rhs: Self) -> Self::Output {
525 Self {
526 x: self.x + rhs.x,
527 z: self.z + rhs.z,
528 }
529 }
530}
531impl Add<ChunkBlockPos> for ChunkPos {
532 type Output = BlockPos;
533
534 fn add(self, rhs: ChunkBlockPos) -> Self::Output {
535 BlockPos {
536 x: self.x * 16 + rhs.x as i32,
537 y: rhs.y,
538 z: self.z * 16 + rhs.z as i32,
539 }
540 }
541}
542
543impl From<ChunkPos> for u64 {
547 #[inline]
548 fn from(pos: ChunkPos) -> Self {
549 (pos.x as u64) | ((pos.z as u64) << 32)
550 }
551}
552impl From<u64> for ChunkPos {
553 #[inline]
554 fn from(pos: u64) -> Self {
555 ChunkPos {
556 x: (pos) as i32,
557 z: (pos >> 32) as i32,
558 }
559 }
560}
561impl AzaleaRead for ChunkPos {
562 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
563 let long = u64::azalea_read(buf)?;
564 Ok(ChunkPos::from(long))
565 }
566}
567impl AzaleaWrite for ChunkPos {
568 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
569 u64::from(*self).azalea_write(buf)?;
570 Ok(())
571 }
572}
573
574impl Hash for ChunkPos {
575 #[inline]
576 fn hash<H: Hasher>(&self, state: &mut H) {
577 u64::from(*self).hash(state);
579 }
580}
581impl nohash_hasher::IsEnabled for ChunkPos {}
584
585#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
587pub struct ChunkSectionPos {
588 pub x: i32,
589 pub y: i32,
590 pub z: i32,
591}
592vec3_impl!(ChunkSectionPos, i32);
593
594impl ChunkSectionPos {
595 pub fn block_to_section_coord(block: i32) -> i32 {
596 block >> 4
597 }
598}
599
600#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
602pub struct ChunkBlockPos {
603 pub x: u8,
604 pub y: i32,
605 pub z: u8,
606}
607
608impl ChunkBlockPos {
609 pub fn new(x: u8, y: i32, z: u8) -> Self {
610 ChunkBlockPos { x, y, z }
611 }
612}
613
614impl Hash for ChunkBlockPos {
615 #[inline]
617 fn hash<H: Hasher>(&self, state: &mut H) {
618 u64::from(*self).hash(state);
619 }
620}
621impl From<ChunkBlockPos> for u64 {
622 #[inline]
623 fn from(pos: ChunkBlockPos) -> Self {
624 let mut val: u64 = 0;
626 val |= pos.y as u64;
628 val |= (pos.z as u64) << 32;
630 val |= (pos.x as u64) << 40;
632 val
633 }
634}
635impl nohash_hasher::IsEnabled for ChunkBlockPos {}
636
637#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
641pub struct ChunkSectionBlockPos {
642 pub x: u8,
643 pub y: u8,
644 pub z: u8,
645}
646vec3_impl!(ChunkSectionBlockPos, u8);
647
648#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
652pub struct ChunkSectionBiomePos {
653 pub x: u8,
654 pub y: u8,
655 pub z: u8,
656}
657impl From<&ChunkBiomePos> for ChunkSectionBiomePos {
658 #[inline]
659 fn from(pos: &ChunkBiomePos) -> Self {
660 ChunkSectionBiomePos {
661 x: pos.x,
662 y: (pos.y & 0b11) as u8,
663 z: pos.z,
664 }
665 }
666}
667impl From<ChunkBiomePos> for ChunkSectionBiomePos {
668 #[inline]
669 fn from(pos: ChunkBiomePos) -> Self {
670 Self::from(&pos)
671 }
672}
673vec3_impl!(ChunkSectionBiomePos, u8);
674
675#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
679pub struct ChunkBiomePos {
680 pub x: u8,
681 pub y: i32,
682 pub z: u8,
683}
684impl From<&BlockPos> for ChunkBiomePos {
685 #[inline]
686 fn from(pos: &BlockPos) -> Self {
687 ChunkBiomePos::from(&ChunkBlockPos::from(pos))
688 }
689}
690impl From<BlockPos> for ChunkBiomePos {
691 #[inline]
692 fn from(pos: BlockPos) -> Self {
693 ChunkBiomePos::from(&ChunkBlockPos::from(pos))
694 }
695}
696impl From<&ChunkBlockPos> for ChunkBiomePos {
697 #[inline]
698 fn from(pos: &ChunkBlockPos) -> Self {
699 ChunkBiomePos {
700 x: pos.x >> 2,
701 y: pos.y >> 2,
702 z: pos.z >> 2,
703 }
704 }
705}
706
707impl Add<ChunkSectionBlockPos> for ChunkSectionPos {
708 type Output = BlockPos;
709
710 fn add(self, rhs: ChunkSectionBlockPos) -> Self::Output {
711 BlockPos::new(
712 self.x * 16 + rhs.x as i32,
713 self.y * 16 + rhs.y as i32,
714 self.z * 16 + rhs.z as i32,
715 )
716 }
717}
718impl Hash for ChunkSectionBlockPos {
719 #[inline]
721 fn hash<H: Hasher>(&self, state: &mut H) {
722 u16::from(*self).hash(state);
723 }
724}
725
726impl From<ChunkSectionBlockPos> for u16 {
727 #[inline]
728 fn from(pos: ChunkSectionBlockPos) -> Self {
729 ((((pos.y as u16) << 4) | pos.z as u16) << 4) | pos.x as u16
731 }
732}
733impl nohash_hasher::IsEnabled for ChunkSectionBlockPos {}
734
735#[derive(Debug, Clone, PartialEq, Serialize)]
737pub struct GlobalPos {
738 pub dimension: Identifier,
740 pub pos: BlockPos,
741}
742
743impl From<&BlockPos> for ChunkPos {
744 #[inline]
745 fn from(pos: &BlockPos) -> Self {
746 ChunkPos {
747 x: pos.x >> 4,
748 z: pos.z >> 4,
749 }
750 }
751}
752impl From<BlockPos> for ChunkPos {
753 #[inline]
754 fn from(pos: BlockPos) -> Self {
755 ChunkPos {
756 x: pos.x >> 4,
757 z: pos.z >> 4,
758 }
759 }
760}
761
762impl From<BlockPos> for ChunkSectionPos {
763 #[inline]
764 fn from(pos: BlockPos) -> Self {
765 ChunkSectionPos {
766 x: pos.x >> 4,
767 y: pos.y >> 4,
768 z: pos.z >> 4,
769 }
770 }
771}
772impl From<&BlockPos> for ChunkSectionPos {
773 #[inline]
774 fn from(pos: &BlockPos) -> Self {
775 ChunkSectionPos {
776 x: pos.x >> 4,
777 y: pos.y >> 4,
778 z: pos.z >> 4,
779 }
780 }
781}
782
783impl From<ChunkSectionPos> for ChunkPos {
784 fn from(pos: ChunkSectionPos) -> Self {
785 ChunkPos { x: pos.x, z: pos.z }
786 }
787}
788impl From<&Vec3> for ChunkSectionPos {
789 fn from(pos: &Vec3) -> Self {
790 ChunkSectionPos::from(&BlockPos::from(pos))
791 }
792}
793impl From<Vec3> for ChunkSectionPos {
794 fn from(pos: Vec3) -> Self {
795 ChunkSectionPos::from(&pos)
796 }
797}
798
799impl From<&BlockPos> for ChunkBlockPos {
800 #[inline]
801 fn from(pos: &BlockPos) -> Self {
802 ChunkBlockPos {
803 x: (pos.x & 0xF) as u8,
804 y: pos.y,
805 z: (pos.z & 0xF) as u8,
806 }
807 }
808}
809impl From<BlockPos> for ChunkBlockPos {
810 #[inline]
811 fn from(pos: BlockPos) -> Self {
812 ChunkBlockPos {
813 x: (pos.x & 0xF) as u8,
814 y: pos.y,
815 z: (pos.z & 0xF) as u8,
816 }
817 }
818}
819
820impl From<BlockPos> for ChunkSectionBlockPos {
821 #[inline]
822 fn from(pos: BlockPos) -> Self {
823 ChunkSectionBlockPos {
824 x: (pos.x & 0xF) as u8,
825 y: (pos.y & 0xF) as u8,
826 z: (pos.z & 0xF) as u8,
827 }
828 }
829}
830
831impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
832 #[inline]
833 fn from(pos: &ChunkBlockPos) -> Self {
834 ChunkSectionBlockPos {
835 x: pos.x,
836 y: (pos.y & 0xF) as u8,
837 z: pos.z,
838 }
839 }
840}
841impl From<&Vec3> for BlockPos {
842 #[inline]
843 fn from(pos: &Vec3) -> Self {
844 BlockPos {
845 x: pos.x.floor() as i32,
846 y: pos.y.floor() as i32,
847 z: pos.z.floor() as i32,
848 }
849 }
850}
851impl From<Vec3> for BlockPos {
852 #[inline]
853 fn from(pos: Vec3) -> Self {
854 BlockPos::from(&pos)
855 }
856}
857
858impl From<&Vec3> for ChunkPos {
859 fn from(pos: &Vec3) -> Self {
860 ChunkPos::from(&BlockPos::from(pos))
861 }
862}
863impl From<Vec3> for ChunkPos {
864 fn from(pos: Vec3) -> Self {
865 ChunkPos::from(&pos)
866 }
867}
868
869impl From<&Vec3> for ChunkBlockPos {
870 fn from(pos: &Vec3) -> Self {
871 ChunkBlockPos::from(&BlockPos::from(pos))
872 }
873}
874impl From<Vec3> for ChunkBlockPos {
875 fn from(pos: Vec3) -> Self {
876 ChunkBlockPos::from(&pos)
877 }
878}
879
880impl fmt::Display for BlockPos {
881 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
883 write!(f, "{} {} {}", self.x, self.y, self.z)
884 }
885}
886impl fmt::Display for Vec3 {
887 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
889 write!(f, "{} {} {}", self.x, self.y, self.z)
890 }
891}
892
893#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf, simdnbt::Deserialize, Serialize)]
895pub struct Vec2 {
896 pub x: f32,
897 pub y: f32,
898}
899impl Vec2 {
900 const ZERO: Vec2 = Vec2 { x: 0.0, y: 0.0 };
901
902 #[inline]
903 pub fn new(x: f32, y: f32) -> Self {
904 Vec2 { x, y }
905 }
906 #[inline]
907 pub fn scale(&self, amount: f32) -> Self {
908 Vec2 {
909 x: self.x * amount,
910 y: self.y * amount,
911 }
912 }
913 #[inline]
914 pub fn dot(&self, other: Vec2) -> f32 {
915 self.x * other.x + self.y * other.y
916 }
917 #[inline]
918 pub fn normalized(&self) -> Self {
919 let length = (self.x * self.x + self.y * self.y).sqrt();
920 if length < 1e-4 {
921 return Vec2::ZERO;
922 }
923 Vec2 {
924 x: self.x / length,
925 y: self.y / length,
926 }
927 }
928 #[inline]
929 pub fn length_squared(&self) -> f32 {
930 self.x * self.x + self.y * self.y
931 }
932 #[inline]
933 pub fn length(&self) -> f32 {
934 self.length_squared().sqrt()
935 }
936}
937impl Mul<f32> for Vec2 {
938 type Output = Self;
939
940 #[inline]
941 fn mul(self, rhs: f32) -> Self::Output {
942 self.scale(rhs)
943 }
944}
945impl MulAssign<f32> for Vec2 {
946 #[inline]
947 fn mul_assign(&mut self, rhs: f32) {
948 *self = self.scale(rhs);
949 }
950}
951
952const PACKED_X_LENGTH: u64 = 1 + 25; const PACKED_Z_LENGTH: u64 = PACKED_X_LENGTH;
954const PACKED_Y_LENGTH: u64 = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
955const PACKED_X_MASK: u64 = (1 << PACKED_X_LENGTH) - 1;
956const PACKED_Y_MASK: u64 = (1 << PACKED_Y_LENGTH) - 1;
957const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
958const Z_OFFSET: u64 = PACKED_Y_LENGTH;
959const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
960
961impl AzaleaRead for BlockPos {
962 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
963 let val = i64::azalea_read(buf)?;
964 let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
965 let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
966 let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
967 Ok(BlockPos { x, y, z })
968 }
969}
970
971impl AzaleaRead for GlobalPos {
972 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
973 Ok(GlobalPos {
974 dimension: Identifier::azalea_read(buf)?,
975 pos: BlockPos::azalea_read(buf)?,
976 })
977 }
978}
979
980impl AzaleaRead for ChunkSectionPos {
981 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
982 let long = i64::azalea_read(buf)?;
983 Ok(ChunkSectionPos {
984 x: (long >> 42) as i32,
985 y: (long << 44 >> 44) as i32,
986 z: (long << 22 >> 42) as i32,
987 })
988 }
989}
990
991impl AzaleaWrite for BlockPos {
992 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
993 let mut val: u64 = 0;
994 val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
995 val |= (self.y as u64) & PACKED_Y_MASK;
996 val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
997 val.azalea_write(buf)
998 }
999}
1000
1001impl AzaleaWrite for GlobalPos {
1002 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
1003 Identifier::azalea_write(&self.dimension, buf)?;
1004 BlockPos::azalea_write(&self.pos, buf)?;
1005
1006 Ok(())
1007 }
1008}
1009
1010impl AzaleaWrite for ChunkSectionPos {
1011 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
1012 let long = (((self.x & 0x3FFFFF) as i64) << 42)
1013 | (self.y & 0xFFFFF) as i64
1014 | (((self.z & 0x3FFFFF) as i64) << 20);
1015 long.azalea_write(buf)?;
1016 Ok(())
1017 }
1018}
1019
1020fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
1021where
1022 T: FromStr,
1023 <T as FromStr>::Err: fmt::Debug,
1024{
1025 let parts = s.split_whitespace().collect::<Vec<_>>();
1026 if parts.len() != 3 {
1027 return Err("Expected three values");
1028 }
1029
1030 let x = parts[0].parse().map_err(|_| "Invalid X value")?;
1031 let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
1032 let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
1033
1034 Ok([x, y, z])
1035}
1036
1037impl FromStr for BlockPos {
1043 type Err = &'static str;
1044
1045 fn from_str(s: &str) -> Result<Self, Self::Err> {
1046 let [x, y, z] = parse_three_values::<i32>(s)?;
1047 Ok(BlockPos { x, y, z })
1048 }
1049}
1050
1051impl FromStr for Vec3 {
1057 type Err = &'static str;
1058
1059 fn from_str(s: &str) -> Result<Self, Self::Err> {
1060 let [x, y, z] = parse_three_values::<f64>(s)?;
1061 Ok(Vec3 { x, y, z })
1062 }
1063}
1064
1065#[cfg(test)]
1066mod tests {
1067 use super::*;
1068
1069 #[test]
1070 fn test_from_block_pos_to_chunk_pos() {
1071 let block_pos = BlockPos::new(5, 78, -2);
1072 let chunk_pos = ChunkPos::from(&block_pos);
1073 assert_eq!(chunk_pos, ChunkPos::new(0, -1));
1074 }
1075
1076 #[test]
1077 fn test_from_block_pos_to_chunk_block_pos() {
1078 let block_pos = BlockPos::new(5, 78, -2);
1079 let chunk_block_pos = ChunkBlockPos::from(&block_pos);
1080 assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
1081 }
1082
1083 #[test]
1084 fn test_from_entity_pos_to_block_pos() {
1085 let entity_pos = Vec3 {
1086 x: 31.5,
1087 y: 80.0,
1088 z: -16.1,
1089 };
1090 let block_pos = BlockPos::from(&entity_pos);
1091 assert_eq!(block_pos, BlockPos::new(31, 80, -17));
1092 }
1093
1094 #[test]
1095 fn test_from_entity_pos_to_chunk_pos() {
1096 let entity_pos = Vec3 {
1097 x: 31.5,
1098 y: 80.0,
1099 z: -16.1,
1100 };
1101 let chunk_pos = ChunkPos::from(&entity_pos);
1102 assert_eq!(chunk_pos, ChunkPos::new(1, -2));
1103 }
1104
1105 #[test]
1106 fn test_read_blockpos_from() {
1107 let mut buf = Vec::new();
1108 13743895338965u64.azalea_write(&mut buf).unwrap();
1109 let mut buf = Cursor::new(&buf[..]);
1110 let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
1111 assert_eq!(block_pos, BlockPos::new(49, -43, -3));
1112 }
1113
1114 #[test]
1115 fn test_into_chunk_section_block_pos() {
1116 let block_pos = BlockPos::new(0, -60, 0);
1117 assert_eq!(
1118 ChunkSectionBlockPos::from(block_pos),
1119 ChunkSectionBlockPos::new(0, 4, 0)
1120 );
1121 }
1122
1123 #[test]
1124 fn test_read_chunk_pos_from() {
1125 let mut buf = Vec::new();
1126 ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
1127 let mut buf = Cursor::new(&buf[..]);
1128 let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
1129 assert_eq!(chunk_pos, ChunkPos::new(2, -1));
1130 }
1131}