Skip to main content

azalea_core/
position.rs

1//! Representations of positions of various things in Minecraft.
2//!
3//! The most common ones are [`Vec3`] and [`BlockPos`], which are usually used
4//! for entity positions and block positions, respectively.
5
6use 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            /// The position where x, y, and z are all 0.
27            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            /// Get the distance of this vector to the origin by doing `x^2 + y^2 +
39            /// z^2`.
40            #[inline]
41            pub fn length_squared(&self) -> $type {
42                self.x * self.x + self.y * self.y + self.z * self.z
43            }
44
45            /// Get the squared distance from this position to another position.
46            /// Equivalent to `(self - other).length_squared()`.
47            #[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            /// Return a new instance of this position with the y coordinate
63            /// decreased by the given number.
64            #[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            /// Return a new instance of this position with the y coordinate
73            /// increased by the given number.
74            #[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            /// Return a new instance of this position with the z coordinate subtracted
84            /// by the given number.
85            #[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            /// Return a new instance of this position with the x coordinate increased
94            /// by the given number.
95            #[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            /// Return a new instance of this position with the z coordinate increased
104            /// by the given number.
105            #[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            /// Return a new instance of this position with the x coordinate subtracted
114            /// by the given number.
115            #[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            /// Make a new position with the lower coordinates for each axis.
139            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            /// Make a new position with the higher coordinates for each axis.
147            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            /// Replace the Y with 0.
156            #[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            /// Find the difference between two positions.
234            #[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/// Used to represent an exact position in the world where an entity could be.
316///
317/// For blocks, [`BlockPos`] is used instead.
318#[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            // used on hypixel
334            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    /// Get the distance of this vector to the origin by doing
344    /// `sqrt(x^2 + y^2 + z^2)`.
345    #[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    /// Get the distance from this position to another position.
351    /// Equivalent to `(self - other).length()`.
352    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    /// Whether the distance between this point and `other` is less than
396    /// `range`.
397    pub fn closer_than(&self, other: Vec3, range: f64) -> bool {
398        self.distance_squared_to(other) < range.powi(2)
399    }
400}
401
402/// A lower precision [`Vec3`], used for some fields in entity metadata.
403#[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/// The coordinates of a block in the world.
429///
430/// For entities (if the coordinates are floating-point), use [`Vec3`] instead.
431/// To convert a `BlockPos` to a `Vec3`, you'll usually want [`Self::center`].
432#[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    /// Get the absolute center of a block position by adding 0.5 to each
442    /// coordinate.
443    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    /// Get the center of the bottom of a block position by adding 0.5 to the x
452    /// and z coordinates.
453    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    /// Convert the block position into a Vec3 without centering it.
462    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    /// Get the distance of this vector from the origin by doing `x + y + z`.
471    pub fn length_manhattan(&self) -> u32 {
472        (self.x.abs() + self.y.abs() + self.z.abs()) as u32
473    }
474
475    /// Add or subtract `1` to one of this position's coordinates, depending on
476    /// the direction.
477    ///
478    /// ```
479    /// # use azalea_core::{position::BlockPos, direction::Direction};
480    /// let pos = BlockPos::new(10, 10, 10);
481    /// assert_eq!(
482    ///     pos.offset_with_direction(Direction::North),
483    ///     BlockPos::new(10, 10, 9)
484    /// );
485    /// ```
486    pub fn offset_with_direction(self, direction: Direction) -> Self {
487        self + direction.normal()
488    }
489
490    /// Get the distance (as an f64) of this BlockPos to the origin by
491    /// doing `sqrt(x^2 + y^2 + z^2)`.
492    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    /// Get the distance (as an f64) from this position to another position.
497    /// Equivalent to `(self - other).length()`.
498    ///
499    /// Note that if you're using this in a hot path, it may be more performant
500    /// to use [`BlockPos::distance_squared_to`] instead (by squaring the other
501    /// side in the comparison).
502    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        // makes sure it gets serialized correctly for the checksum
513
514        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/// An arbitrary position that's represented as 32-bit integers.
530///
531/// This is similar to [`BlockPos`], but isn't limited to representing block
532/// positions and can represent a larger range of numbers.
533#[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/// Chunk coordinates are used to represent where a chunk is in the world.
552///
553/// You can convert the x and z to block coordinates by multiplying them by 16.
554#[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
586// reading ChunkPos is done in reverse, so z first and then x
587// ........
588// mojang why
589impl 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        // optimized hash that only calls hash once
619        u64::from(*self).hash(state);
620    }
621}
622/// `nohash_hasher` lets us have IntMap<ChunkPos, _> which is significantly
623/// faster than a normal HashMap
624impl nohash_hasher::IsEnabled for ChunkPos {}
625
626/// The coordinates of a chunk section in the world.
627#[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/// The coordinates of a block inside a chunk.
642#[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    // optimized hash that only calls hash once
657    #[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        // convert to u64
666        let mut val: u64 = 0;
667        // first 32 bits are y
668        val |= pos.y as u64;
669        // next 8 bits are z
670        val |= (pos.z as u64) << 32;
671        // last 8 bits are x
672        val |= (pos.x as u64) << 40;
673        val
674    }
675}
676impl nohash_hasher::IsEnabled for ChunkBlockPos {}
677
678/// The coordinates of a block inside of a chunk section.
679///
680/// Each coordinate should be in the range 0..=15.
681#[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/// The coordinates of a biome inside of a chunk section.
690///
691/// Each coordinate should be in the range 0..=3.
692#[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/// The coordinates of a biome inside a chunk.
717///
718/// Biomes are 4x4 blocks.
719#[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    // optimized hash that only calls hash once
761    #[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.z as u16) | ((pos.y as u16) << 4) | ((pos.x as u16) << 8)
771        ((((pos.y as u16) << 4) | pos.z as u16) << 4) | pos.x as u16
772    }
773}
774impl nohash_hasher::IsEnabled for ChunkSectionBlockPos {}
775
776/// A block pos with an attached world
777#[cfg_attr(feature = "serde", derive(serde::Serialize))]
778#[derive(Clone, Debug, PartialEq)]
779pub struct GlobalPos {
780    // this is actually a ResourceKey in Minecraft, but i don't think it matters?
781    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    /// Display a block position as `x y z`.
924    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    /// Display a position as `x y z`.
930    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
931        write!(f, "{} {} {}", self.x, self.y, self.z)
932    }
933}
934
935/// A 2D vector.
936#[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; // minecraft does something a bit more complicated to get this 25
996const 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
1071/// Parses a string in the format "X Y Z" into a BlockPos.
1072///
1073/// The input string should contain three integer values separated by spaces,
1074/// representing the x, y, and z components of the vector respectively.
1075/// This can be used to parse user input or from `BlockPos::to_string`.
1076impl 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
1085/// Parses a string in the format "X Y Z" into a Vec3.
1086///
1087/// The input string should contain three floating-point values separated by
1088/// spaces, representing the x, y, and z components of the vector respectively.
1089/// This can be used to parse user input or from `Vec3::to_string`.
1090impl 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}