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, AzaleaRead, AzaleaWrite, BufReadError};
16use serde::{Serialize, Serializer};
17use simdnbt::Deserialize;
18
19use crate::{codec_utils::IntArray, direction::Direction, identifier::Identifier, math};
20
21macro_rules! vec3_impl {
22    ($name:ident, $type:ty) => {
23        impl $name {
24            /// The position where x, y, and z are all 0.
25            pub const ZERO: Self = Self {
26                x: 0 as $type,
27                y: 0 as $type,
28                z: 0 as $type,
29            };
30
31            #[inline]
32            pub const fn new(x: $type, y: $type, z: $type) -> Self {
33                Self { x, y, z }
34            }
35
36            /// Get the distance of this vector to the origin by doing `x^2 + y^2 +
37            /// z^2`.
38            #[inline]
39            pub fn length_squared(&self) -> $type {
40                self.x * self.x + self.y * self.y + self.z * self.z
41            }
42
43            /// Get the squared distance from this position to another position.
44            /// Equivalent to `(self - other).length_squared()`.
45            #[inline]
46            pub fn distance_squared_to(self, other: Self) -> $type {
47                (self - other).length_squared()
48            }
49
50            #[inline]
51            pub fn horizontal_distance_squared(&self) -> $type {
52                self.x * self.x + self.z * self.z
53            }
54
55            #[inline]
56            pub fn horizontal_distance_squared_to(self, other: Self) -> $type {
57                (self - other).horizontal_distance_squared()
58            }
59
60            /// Return a new instance of this position with the y coordinate
61            /// decreased by the given number.
62            #[inline]
63            pub fn down(&self, y: $type) -> Self {
64                Self {
65                    x: self.x,
66                    y: self.y - y,
67                    z: self.z,
68                }
69            }
70            /// Return a new instance of this position with the y coordinate
71            /// increased by the given number.
72            #[inline]
73            pub fn up(&self, y: $type) -> Self {
74                Self {
75                    x: self.x,
76                    y: self.y + y,
77                    z: self.z,
78                }
79            }
80
81            /// Return a new instance of this position with the z coordinate subtracted
82            /// by the given number.
83            #[inline]
84            pub fn north(&self, z: $type) -> Self {
85                Self {
86                    x: self.x,
87                    y: self.y,
88                    z: self.z - z,
89                }
90            }
91            /// Return a new instance of this position with the x coordinate increased
92            /// by the given number.
93            #[inline]
94            pub fn east(&self, x: $type) -> Self {
95                Self {
96                    x: self.x + x,
97                    y: self.y,
98                    z: self.z,
99                }
100            }
101            /// Return a new instance of this position with the z coordinate increased
102            /// by the given number.
103            #[inline]
104            pub fn south(&self, z: $type) -> Self {
105                Self {
106                    x: self.x,
107                    y: self.y,
108                    z: self.z + z,
109                }
110            }
111            /// Return a new instance of this position with the x coordinate subtracted
112            /// by the given number.
113            #[inline]
114            pub fn west(&self, x: $type) -> Self {
115                Self {
116                    x: self.x - x,
117                    y: self.y,
118                    z: self.z,
119                }
120            }
121
122            #[inline]
123            pub fn dot(&self, other: Self) -> $type {
124                self.x * other.x + self.y * other.y + self.z * other.z
125            }
126
127            /// Make a new position with the lower coordinates for each axis.
128            pub fn min(&self, other: Self) -> Self {
129                Self {
130                    x: self.x.min(other.x),
131                    y: self.x.min(other.y),
132                    z: self.x.min(other.z),
133                }
134            }
135            /// Make a new position with the higher coordinates for each axis.
136            pub fn max(&self, other: Self) -> Self {
137                Self {
138                    x: self.x.max(other.x),
139                    y: self.x.max(other.y),
140                    z: self.x.max(other.z),
141                }
142            }
143
144            /// Replace the Y with 0.
145            #[inline]
146            pub fn xz(&self) -> Self {
147                Self {
148                    x: self.x,
149                    y: <$type>::default(),
150                    z: self.z,
151                }
152            }
153
154            pub fn with_x(&self, x: $type) -> Self {
155                Self { x, ..*self }
156            }
157            pub fn with_y(&self, y: $type) -> Self {
158                Self { y, ..*self }
159            }
160            pub fn with_z(&self, z: $type) -> Self {
161                Self { z, ..*self }
162            }
163        }
164
165        impl Add for &$name {
166            type Output = $name;
167
168            #[inline]
169            fn add(self, rhs: Self) -> Self::Output {
170                $name {
171                    x: self.x + rhs.x,
172                    y: self.y + rhs.y,
173                    z: self.z + rhs.z,
174                }
175            }
176        }
177        impl Add for $name {
178            type Output = $name;
179
180            #[inline]
181            fn add(self, rhs: Self) -> Self::Output {
182                (&self).add(&rhs)
183            }
184        }
185        impl Add<$type> for $name {
186            type Output = Self;
187
188            #[inline]
189            fn add(self, rhs: $type) -> Self::Output {
190                Self {
191                    x: self.x + rhs,
192                    y: self.y + rhs,
193                    z: self.z + rhs,
194                }
195            }
196        }
197
198        impl AddAssign for $name {
199            #[inline]
200            fn add_assign(&mut self, rhs: Self) {
201                self.x += rhs.x;
202                self.y += rhs.y;
203                self.z += rhs.z;
204            }
205        }
206        impl Rem<$type> for $name {
207            type Output = Self;
208
209            #[inline]
210            fn rem(self, rhs: $type) -> Self::Output {
211                Self {
212                    x: self.x % rhs,
213                    y: self.y % rhs,
214                    z: self.z % rhs,
215                }
216            }
217        }
218
219        impl Sub for &$name {
220            type Output = $name;
221
222            /// Find the difference between two positions.
223            #[inline]
224            fn sub(self, other: Self) -> Self::Output {
225                Self::Output {
226                    x: self.x - other.x,
227                    y: self.y - other.y,
228                    z: self.z - other.z,
229                }
230            }
231        }
232        impl Sub for $name {
233            type Output = Self;
234
235            #[inline]
236            fn sub(self, other: Self) -> Self::Output {
237                (&self).sub(&other)
238            }
239        }
240
241        impl Mul<$type> for $name {
242            type Output = Self;
243
244            #[inline]
245            fn mul(self, multiplier: $type) -> Self::Output {
246                Self {
247                    x: self.x * multiplier,
248                    y: self.y * multiplier,
249                    z: self.z * multiplier,
250                }
251            }
252        }
253        impl MulAssign<$type> for $name {
254            #[inline]
255            fn mul_assign(&mut self, multiplier: $type) {
256                self.x *= multiplier;
257                self.y *= multiplier;
258                self.z *= multiplier;
259            }
260        }
261
262        impl Div<$type> for $name {
263            type Output = Self;
264
265            #[inline]
266            fn div(self, divisor: $type) -> Self::Output {
267                Self {
268                    x: self.x / divisor,
269                    y: self.y / divisor,
270                    z: self.z / divisor,
271                }
272            }
273        }
274        impl DivAssign<$type> for $name {
275            #[inline]
276            fn div_assign(&mut self, divisor: $type) {
277                self.x /= divisor;
278                self.y /= divisor;
279                self.z /= divisor;
280            }
281        }
282
283        impl From<($type, $type, $type)> for $name {
284            #[inline]
285            fn from(pos: ($type, $type, $type)) -> Self {
286                Self::new(pos.0, pos.1, pos.2)
287            }
288        }
289        impl From<&($type, $type, $type)> for $name {
290            #[inline]
291            fn from(pos: &($type, $type, $type)) -> Self {
292                Self::new(pos.0, pos.1, pos.2)
293            }
294        }
295        impl From<$name> for ($type, $type, $type) {
296            #[inline]
297            fn from(pos: $name) -> Self {
298                (pos.x, pos.y, pos.z)
299            }
300        }
301    };
302}
303
304/// Used to represent an exact position in the world where an entity could be.
305///
306/// For blocks, [`BlockPos`] is used instead.
307#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf, serde::Deserialize, serde::Serialize)]
308pub struct Vec3 {
309    pub x: f64,
310    pub y: f64,
311    pub z: f64,
312}
313vec3_impl!(Vec3, f64);
314
315impl Vec3 {
316    /// Get the distance of this vector to the origin by doing
317    /// `sqrt(x^2 + y^2 + z^2)`.
318    pub fn length(&self) -> f64 {
319        f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
320    }
321
322    /// Get the distance from this position to another position.
323    /// Equivalent to `(self - other).length()`.
324    pub fn distance_to(self, other: Self) -> f64 {
325        (self - other).length()
326    }
327
328    pub fn x_rot(self, radians: f32) -> Vec3 {
329        let x_delta = math::cos(radians);
330        let y_delta = math::sin(radians);
331        let x = self.x;
332        let y = self.y * (x_delta as f64) + self.z * (y_delta as f64);
333        let z = self.z * (x_delta as f64) - self.y * (y_delta as f64);
334        Vec3 { x, y, z }
335    }
336    pub fn y_rot(self, radians: f32) -> Vec3 {
337        let x_delta = math::cos(radians);
338        let y_delta = math::sin(radians);
339        let x = self.x * (x_delta as f64) + self.z * (y_delta as f64);
340        let y = self.y;
341        let z = self.z * (x_delta as f64) - self.x * (y_delta as f64);
342        Vec3 { x, y, z }
343    }
344
345    pub fn to_block_pos_floor(&self) -> BlockPos {
346        BlockPos {
347            x: self.x.floor() as i32,
348            y: self.y.floor() as i32,
349            z: self.z.floor() as i32,
350        }
351    }
352    pub fn to_block_pos_ceil(&self) -> BlockPos {
353        BlockPos {
354            x: self.x.ceil() as i32,
355            y: self.y.ceil() as i32,
356            z: self.z.ceil() as i32,
357        }
358    }
359
360    /// Whether the distance between this point and `other` is less than
361    /// `range`.
362    pub fn closer_than(&self, other: Vec3, range: f64) -> bool {
363        self.distance_squared_to(other) < range.powi(2)
364    }
365}
366
367/// A lower precision [`Vec3`], used for some fields in entity metadata.
368#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf)]
369pub struct Vec3f32 {
370    pub x: f32,
371    pub y: f32,
372    pub z: f32,
373}
374impl From<Vec3f32> for Vec3 {
375    fn from(v: Vec3f32) -> Self {
376        Vec3 {
377            x: v.x as f64,
378            y: v.y as f64,
379            z: v.z as f64,
380        }
381    }
382}
383impl From<Vec3> for Vec3f32 {
384    fn from(v: Vec3) -> Self {
385        Vec3f32 {
386            x: v.x as f32,
387            y: v.y as f32,
388            z: v.z as f32,
389        }
390    }
391}
392
393/// The coordinates of a block in the world.
394///
395/// For entities (if the coordinates are floating-point), use [`Vec3`] instead.
396#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
397pub struct BlockPos {
398    pub x: i32,
399    pub y: i32,
400    pub z: i32,
401}
402vec3_impl!(BlockPos, i32);
403
404impl BlockPos {
405    /// Get the absolute center of a block position by adding 0.5 to each
406    /// coordinate.
407    pub fn center(&self) -> Vec3 {
408        Vec3 {
409            x: self.x as f64 + 0.5,
410            y: self.y as f64 + 0.5,
411            z: self.z as f64 + 0.5,
412        }
413    }
414
415    /// Get the center of the bottom of a block position by adding 0.5 to the x
416    /// and z coordinates.
417    pub fn center_bottom(&self) -> Vec3 {
418        Vec3 {
419            x: self.x as f64 + 0.5,
420            y: self.y as f64,
421            z: self.z as f64 + 0.5,
422        }
423    }
424
425    /// Convert the block position into a Vec3 without centering it.
426    pub fn to_vec3_floored(&self) -> Vec3 {
427        Vec3 {
428            x: self.x as f64,
429            y: self.y as f64,
430            z: self.z as f64,
431        }
432    }
433
434    /// Get the distance of this vector from the origin by doing `x + y + z`.
435    pub fn length_manhattan(&self) -> u32 {
436        (self.x.abs() + self.y.abs() + self.z.abs()) as u32
437    }
438
439    pub fn offset_with_direction(self, direction: Direction) -> Self {
440        self + direction.normal()
441    }
442
443    /// Get the distance (as an f64) of this BlockPos to the origin by
444    /// doing `sqrt(x^2 + y^2 + z^2)`.
445    pub fn length(&self) -> f64 {
446        f64::sqrt((self.x * self.x + self.y * self.y + self.z * self.z) as f64)
447    }
448
449    /// Get the distance (as an f64) from this position to another position.
450    /// Equivalent to `(self - other).length()`.
451    ///
452    /// Note that if you're using this in a hot path, it may be more performant
453    /// to use [`BlockPos::distance_squared_to`] instead (by squaring the other
454    /// side in the comparison).
455    pub fn distance_to(self, other: Self) -> f64 {
456        (self - other).length()
457    }
458}
459impl serde::Serialize for BlockPos {
460    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
461    where
462        S: Serializer,
463    {
464        // makes sure it gets serialized correctly for the checksum
465        IntArray([self.x, self.y, self.z]).serialize(serializer)
466    }
467}
468impl<'de> serde::Deserialize<'de> for BlockPos {
469    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
470    where
471        D: serde::Deserializer<'de>,
472    {
473        let [x, y, z] = <[i32; 3]>::deserialize(deserializer)?;
474        Ok(BlockPos { x, y, z })
475    }
476}
477
478/// An arbitrary position that's represented as 32-bit integers.
479///
480/// This is similar to [`BlockPos`], but isn't limited to representing block
481/// positions and can represent a larger range of numbers.
482#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, AzBuf)]
483pub struct Vec3i {
484    #[var]
485    pub x: i32,
486    #[var]
487    pub y: i32,
488    #[var]
489    pub z: i32,
490}
491vec3_impl!(Vec3i, i32);
492
493/// Chunk coordinates are used to represent where a chunk is in the world.
494///
495/// You can convert the x and z to block coordinates by multiplying them by 16.
496#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
497pub struct ChunkPos {
498    pub x: i32,
499    pub z: i32,
500}
501impl ChunkPos {
502    pub fn new(x: i32, z: i32) -> Self {
503        ChunkPos { x, z }
504    }
505}
506impl Add<ChunkPos> for ChunkPos {
507    type Output = Self;
508
509    fn add(self, rhs: Self) -> Self::Output {
510        Self {
511            x: self.x + rhs.x,
512            z: self.z + rhs.z,
513        }
514    }
515}
516impl Add<ChunkBlockPos> for ChunkPos {
517    type Output = BlockPos;
518
519    fn add(self, rhs: ChunkBlockPos) -> Self::Output {
520        BlockPos {
521            x: self.x * 16 + rhs.x as i32,
522            y: rhs.y,
523            z: self.z * 16 + rhs.z as i32,
524        }
525    }
526}
527
528// reading ChunkPos is done in reverse, so z first and then x
529// ........
530// mojang why
531impl From<ChunkPos> for u64 {
532    #[inline]
533    fn from(pos: ChunkPos) -> Self {
534        (pos.x as u64) | ((pos.z as u64) << 32)
535    }
536}
537impl From<u64> for ChunkPos {
538    #[inline]
539    fn from(pos: u64) -> Self {
540        ChunkPos {
541            x: (pos) as i32,
542            z: (pos >> 32) as i32,
543        }
544    }
545}
546impl AzaleaRead for ChunkPos {
547    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
548        let long = u64::azalea_read(buf)?;
549        Ok(ChunkPos::from(long))
550    }
551}
552impl AzaleaWrite for ChunkPos {
553    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
554        u64::from(*self).azalea_write(buf)?;
555        Ok(())
556    }
557}
558
559impl Hash for ChunkPos {
560    #[inline]
561    fn hash<H: Hasher>(&self, state: &mut H) {
562        // optimized hash that only calls hash once
563        u64::from(*self).hash(state);
564    }
565}
566/// `nohash_hasher` lets us have IntMap<ChunkPos, _> which is significantly
567/// faster than a normal HashMap
568impl nohash_hasher::IsEnabled for ChunkPos {}
569
570/// The coordinates of a chunk section in the world.
571#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
572pub struct ChunkSectionPos {
573    pub x: i32,
574    pub y: i32,
575    pub z: i32,
576}
577vec3_impl!(ChunkSectionPos, i32);
578
579impl ChunkSectionPos {
580    pub fn block_to_section_coord(block: i32) -> i32 {
581        block >> 4
582    }
583}
584
585/// The coordinates of a block inside a chunk.
586#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
587pub struct ChunkBlockPos {
588    pub x: u8,
589    pub y: i32,
590    pub z: u8,
591}
592
593impl ChunkBlockPos {
594    pub fn new(x: u8, y: i32, z: u8) -> Self {
595        ChunkBlockPos { x, y, z }
596    }
597}
598
599impl Hash for ChunkBlockPos {
600    // optimized hash that only calls hash once
601    #[inline]
602    fn hash<H: Hasher>(&self, state: &mut H) {
603        u64::from(*self).hash(state);
604    }
605}
606impl From<ChunkBlockPos> for u64 {
607    #[inline]
608    fn from(pos: ChunkBlockPos) -> Self {
609        // convert to u64
610        let mut val: u64 = 0;
611        // first 32 bits are y
612        val |= pos.y as u64;
613        // next 8 bits are z
614        val |= (pos.z as u64) << 32;
615        // last 8 bits are x
616        val |= (pos.x as u64) << 40;
617        val
618    }
619}
620impl nohash_hasher::IsEnabled for ChunkBlockPos {}
621
622/// The coordinates of a block inside of a chunk section.
623///
624/// Each coordinate should be in the range 0..=15.
625#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
626pub struct ChunkSectionBlockPos {
627    pub x: u8,
628    pub y: u8,
629    pub z: u8,
630}
631vec3_impl!(ChunkSectionBlockPos, u8);
632
633/// The coordinates of a biome inside of a chunk section.
634///
635/// Each coordinate should be in the range 0..=3.
636#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
637pub struct ChunkSectionBiomePos {
638    pub x: u8,
639    pub y: u8,
640    pub z: u8,
641}
642impl From<&ChunkBiomePos> for ChunkSectionBiomePos {
643    #[inline]
644    fn from(pos: &ChunkBiomePos) -> Self {
645        ChunkSectionBiomePos {
646            x: pos.x,
647            y: (pos.y & 0b11) as u8,
648            z: pos.z,
649        }
650    }
651}
652impl From<ChunkBiomePos> for ChunkSectionBiomePos {
653    #[inline]
654    fn from(pos: ChunkBiomePos) -> Self {
655        Self::from(&pos)
656    }
657}
658vec3_impl!(ChunkSectionBiomePos, u8);
659
660/// The coordinates of a biome inside a chunk.
661///
662/// Biomes are 4x4 blocks.
663#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
664pub struct ChunkBiomePos {
665    pub x: u8,
666    pub y: i32,
667    pub z: u8,
668}
669impl From<&BlockPos> for ChunkBiomePos {
670    #[inline]
671    fn from(pos: &BlockPos) -> Self {
672        ChunkBiomePos::from(&ChunkBlockPos::from(pos))
673    }
674}
675impl From<BlockPos> for ChunkBiomePos {
676    #[inline]
677    fn from(pos: BlockPos) -> Self {
678        ChunkBiomePos::from(&ChunkBlockPos::from(pos))
679    }
680}
681impl From<&ChunkBlockPos> for ChunkBiomePos {
682    #[inline]
683    fn from(pos: &ChunkBlockPos) -> Self {
684        ChunkBiomePos {
685            x: pos.x >> 2,
686            y: pos.y >> 2,
687            z: pos.z >> 2,
688        }
689    }
690}
691
692impl Add<ChunkSectionBlockPos> for ChunkSectionPos {
693    type Output = BlockPos;
694
695    fn add(self, rhs: ChunkSectionBlockPos) -> Self::Output {
696        BlockPos::new(
697            self.x * 16 + rhs.x as i32,
698            self.y * 16 + rhs.y as i32,
699            self.z * 16 + rhs.z as i32,
700        )
701    }
702}
703impl Hash for ChunkSectionBlockPos {
704    // optimized hash that only calls hash once
705    #[inline]
706    fn hash<H: Hasher>(&self, state: &mut H) {
707        u16::from(*self).hash(state);
708    }
709}
710
711impl From<ChunkSectionBlockPos> for u16 {
712    #[inline]
713    fn from(pos: ChunkSectionBlockPos) -> Self {
714        // (pos.z as u16) | ((pos.y as u16) << 4) | ((pos.x as u16) << 8)
715        ((((pos.y as u16) << 4) | pos.z as u16) << 4) | pos.x as u16
716    }
717}
718impl nohash_hasher::IsEnabled for ChunkSectionBlockPos {}
719
720/// A block pos with an attached world
721#[derive(Debug, Clone, PartialEq, Serialize)]
722pub struct GlobalPos {
723    // this is actually a ResourceKey in Minecraft, but i don't think it matters?
724    pub dimension: Identifier,
725    pub pos: BlockPos,
726}
727
728impl From<&BlockPos> for ChunkPos {
729    #[inline]
730    fn from(pos: &BlockPos) -> Self {
731        ChunkPos {
732            x: pos.x >> 4,
733            z: pos.z >> 4,
734        }
735    }
736}
737impl From<BlockPos> for ChunkPos {
738    #[inline]
739    fn from(pos: BlockPos) -> Self {
740        ChunkPos {
741            x: pos.x >> 4,
742            z: pos.z >> 4,
743        }
744    }
745}
746
747impl From<BlockPos> for ChunkSectionPos {
748    #[inline]
749    fn from(pos: BlockPos) -> Self {
750        ChunkSectionPos {
751            x: pos.x >> 4,
752            y: pos.y >> 4,
753            z: pos.z >> 4,
754        }
755    }
756}
757impl From<&BlockPos> for ChunkSectionPos {
758    #[inline]
759    fn from(pos: &BlockPos) -> Self {
760        ChunkSectionPos {
761            x: pos.x >> 4,
762            y: pos.y >> 4,
763            z: pos.z >> 4,
764        }
765    }
766}
767
768impl From<ChunkSectionPos> for ChunkPos {
769    fn from(pos: ChunkSectionPos) -> Self {
770        ChunkPos { x: pos.x, z: pos.z }
771    }
772}
773impl From<&Vec3> for ChunkSectionPos {
774    fn from(pos: &Vec3) -> Self {
775        ChunkSectionPos::from(&BlockPos::from(pos))
776    }
777}
778impl From<Vec3> for ChunkSectionPos {
779    fn from(pos: Vec3) -> Self {
780        ChunkSectionPos::from(&pos)
781    }
782}
783
784impl From<&BlockPos> for ChunkBlockPos {
785    #[inline]
786    fn from(pos: &BlockPos) -> Self {
787        ChunkBlockPos {
788            x: (pos.x & 0xF) as u8,
789            y: pos.y,
790            z: (pos.z & 0xF) as u8,
791        }
792    }
793}
794impl From<BlockPos> for ChunkBlockPos {
795    #[inline]
796    fn from(pos: BlockPos) -> Self {
797        ChunkBlockPos {
798            x: (pos.x & 0xF) as u8,
799            y: pos.y,
800            z: (pos.z & 0xF) as u8,
801        }
802    }
803}
804
805impl From<BlockPos> for ChunkSectionBlockPos {
806    #[inline]
807    fn from(pos: BlockPos) -> Self {
808        ChunkSectionBlockPos {
809            x: (pos.x & 0xF) as u8,
810            y: (pos.y & 0xF) as u8,
811            z: (pos.z & 0xF) as u8,
812        }
813    }
814}
815
816impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
817    #[inline]
818    fn from(pos: &ChunkBlockPos) -> Self {
819        ChunkSectionBlockPos {
820            x: pos.x,
821            y: (pos.y & 0xF) as u8,
822            z: pos.z,
823        }
824    }
825}
826impl From<&Vec3> for BlockPos {
827    #[inline]
828    fn from(pos: &Vec3) -> Self {
829        BlockPos {
830            x: pos.x.floor() as i32,
831            y: pos.y.floor() as i32,
832            z: pos.z.floor() as i32,
833        }
834    }
835}
836impl From<Vec3> for BlockPos {
837    #[inline]
838    fn from(pos: Vec3) -> Self {
839        BlockPos::from(&pos)
840    }
841}
842
843impl From<&Vec3> for ChunkPos {
844    fn from(pos: &Vec3) -> Self {
845        ChunkPos::from(&BlockPos::from(pos))
846    }
847}
848impl From<Vec3> for ChunkPos {
849    fn from(pos: Vec3) -> Self {
850        ChunkPos::from(&pos)
851    }
852}
853
854impl From<&Vec3> for ChunkBlockPos {
855    fn from(pos: &Vec3) -> Self {
856        ChunkBlockPos::from(&BlockPos::from(pos))
857    }
858}
859impl From<Vec3> for ChunkBlockPos {
860    fn from(pos: Vec3) -> Self {
861        ChunkBlockPos::from(&pos)
862    }
863}
864
865impl fmt::Display for BlockPos {
866    /// Display a block position as `x y z`.
867    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
868        write!(f, "{} {} {}", self.x, self.y, self.z)
869    }
870}
871impl fmt::Display for Vec3 {
872    /// Display a position as `x y z`.
873    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
874        write!(f, "{} {} {}", self.x, self.y, self.z)
875    }
876}
877
878/// A 2D vector.
879#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf, Deserialize, Serialize)]
880pub struct Vec2 {
881    pub x: f32,
882    pub y: f32,
883}
884impl Vec2 {
885    const ZERO: Vec2 = Vec2 { x: 0.0, y: 0.0 };
886
887    #[inline]
888    pub fn new(x: f32, y: f32) -> Self {
889        Vec2 { x, y }
890    }
891    #[inline]
892    pub fn scale(&self, amount: f32) -> Self {
893        Vec2 {
894            x: self.x * amount,
895            y: self.y * amount,
896        }
897    }
898    #[inline]
899    pub fn dot(&self, other: Vec2) -> f32 {
900        self.x * other.x + self.y * other.y
901    }
902    #[inline]
903    pub fn normalized(&self) -> Self {
904        let length = (self.x * self.x + self.y * self.y).sqrt();
905        if length < 1e-4 {
906            return Vec2::ZERO;
907        }
908        Vec2 {
909            x: self.x / length,
910            y: self.y / length,
911        }
912    }
913    #[inline]
914    pub fn length_squared(&self) -> f32 {
915        self.x * self.x + self.y * self.y
916    }
917    #[inline]
918    pub fn length(&self) -> f32 {
919        self.length_squared().sqrt()
920    }
921}
922impl Mul<f32> for Vec2 {
923    type Output = Self;
924
925    #[inline]
926    fn mul(self, rhs: f32) -> Self::Output {
927        self.scale(rhs)
928    }
929}
930impl MulAssign<f32> for Vec2 {
931    #[inline]
932    fn mul_assign(&mut self, rhs: f32) {
933        *self = self.scale(rhs);
934    }
935}
936
937const PACKED_X_LENGTH: u64 = 1 + 25; // minecraft does something a bit more complicated to get this 25
938const PACKED_Z_LENGTH: u64 = PACKED_X_LENGTH;
939const PACKED_Y_LENGTH: u64 = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
940const PACKED_X_MASK: u64 = (1 << PACKED_X_LENGTH) - 1;
941const PACKED_Y_MASK: u64 = (1 << PACKED_Y_LENGTH) - 1;
942const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
943const Z_OFFSET: u64 = PACKED_Y_LENGTH;
944const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
945
946impl AzaleaRead for BlockPos {
947    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
948        let val = i64::azalea_read(buf)?;
949        let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
950        let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
951        let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
952        Ok(BlockPos { x, y, z })
953    }
954}
955
956impl AzaleaRead for GlobalPos {
957    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
958        Ok(GlobalPos {
959            dimension: Identifier::azalea_read(buf)?,
960            pos: BlockPos::azalea_read(buf)?,
961        })
962    }
963}
964
965impl AzaleaRead for ChunkSectionPos {
966    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
967        let long = i64::azalea_read(buf)?;
968        Ok(ChunkSectionPos {
969            x: (long >> 42) as i32,
970            y: (long << 44 >> 44) as i32,
971            z: (long << 22 >> 42) as i32,
972        })
973    }
974}
975
976impl AzaleaWrite for BlockPos {
977    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
978        let mut val: u64 = 0;
979        val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
980        val |= (self.y as u64) & PACKED_Y_MASK;
981        val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
982        val.azalea_write(buf)
983    }
984}
985
986impl AzaleaWrite for GlobalPos {
987    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
988        Identifier::azalea_write(&self.dimension, buf)?;
989        BlockPos::azalea_write(&self.pos, buf)?;
990
991        Ok(())
992    }
993}
994
995impl AzaleaWrite for ChunkSectionPos {
996    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
997        let long = (((self.x & 0x3FFFFF) as i64) << 42)
998            | (self.y & 0xFFFFF) as i64
999            | (((self.z & 0x3FFFFF) as i64) << 20);
1000        long.azalea_write(buf)?;
1001        Ok(())
1002    }
1003}
1004
1005fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
1006where
1007    T: FromStr,
1008    <T as FromStr>::Err: fmt::Debug,
1009{
1010    let parts = s.split_whitespace().collect::<Vec<_>>();
1011    if parts.len() != 3 {
1012        return Err("Expected three values");
1013    }
1014
1015    let x = parts[0].parse().map_err(|_| "Invalid X value")?;
1016    let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
1017    let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
1018
1019    Ok([x, y, z])
1020}
1021
1022/// Parses a string in the format "X Y Z" into a BlockPos.
1023///
1024/// The input string should contain three integer values separated by spaces,
1025/// representing the x, y, and z components of the vector respectively.
1026/// This can be used to parse user input or from `BlockPos::to_string`.
1027impl FromStr for BlockPos {
1028    type Err = &'static str;
1029
1030    fn from_str(s: &str) -> Result<Self, Self::Err> {
1031        let [x, y, z] = parse_three_values::<i32>(s)?;
1032        Ok(BlockPos { x, y, z })
1033    }
1034}
1035
1036/// Parses a string in the format "X Y Z" into a Vec3.
1037///
1038/// The input string should contain three floating-point values separated by
1039/// spaces, representing the x, y, and z components of the vector respectively.
1040/// This can be used to parse user input or from `Vec3::to_string`.
1041impl FromStr for Vec3 {
1042    type Err = &'static str;
1043
1044    fn from_str(s: &str) -> Result<Self, Self::Err> {
1045        let [x, y, z] = parse_three_values::<f64>(s)?;
1046        Ok(Vec3 { x, y, z })
1047    }
1048}
1049
1050#[cfg(test)]
1051mod tests {
1052    use super::*;
1053
1054    #[test]
1055    fn test_from_block_pos_to_chunk_pos() {
1056        let block_pos = BlockPos::new(5, 78, -2);
1057        let chunk_pos = ChunkPos::from(&block_pos);
1058        assert_eq!(chunk_pos, ChunkPos::new(0, -1));
1059    }
1060
1061    #[test]
1062    fn test_from_block_pos_to_chunk_block_pos() {
1063        let block_pos = BlockPos::new(5, 78, -2);
1064        let chunk_block_pos = ChunkBlockPos::from(&block_pos);
1065        assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
1066    }
1067
1068    #[test]
1069    fn test_from_entity_pos_to_block_pos() {
1070        let entity_pos = Vec3 {
1071            x: 31.5,
1072            y: 80.0,
1073            z: -16.1,
1074        };
1075        let block_pos = BlockPos::from(&entity_pos);
1076        assert_eq!(block_pos, BlockPos::new(31, 80, -17));
1077    }
1078
1079    #[test]
1080    fn test_from_entity_pos_to_chunk_pos() {
1081        let entity_pos = Vec3 {
1082            x: 31.5,
1083            y: 80.0,
1084            z: -16.1,
1085        };
1086        let chunk_pos = ChunkPos::from(&entity_pos);
1087        assert_eq!(chunk_pos, ChunkPos::new(1, -2));
1088    }
1089
1090    #[test]
1091    fn test_read_blockpos_from() {
1092        let mut buf = Vec::new();
1093        13743895338965u64.azalea_write(&mut buf).unwrap();
1094        let mut buf = Cursor::new(&buf[..]);
1095        let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
1096        assert_eq!(block_pos, BlockPos::new(49, -43, -3));
1097    }
1098
1099    #[test]
1100    fn test_into_chunk_section_block_pos() {
1101        let block_pos = BlockPos::new(0, -60, 0);
1102        assert_eq!(
1103            ChunkSectionBlockPos::from(block_pos),
1104            ChunkSectionBlockPos::new(0, 4, 0)
1105        );
1106    }
1107
1108    #[test]
1109    fn test_read_chunk_pos_from() {
1110        let mut buf = Vec::new();
1111        ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
1112        let mut buf = Cursor::new(&buf[..]);
1113        let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
1114        assert_eq!(chunk_pos, ChunkPos::new(2, -1));
1115    }
1116}