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