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. You
488/// can convert the x and z to block coordinates by multiplying them by 16.
489#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
490pub struct ChunkPos {
491    pub x: i32,
492    pub z: i32,
493}
494impl ChunkPos {
495    pub fn new(x: i32, z: i32) -> Self {
496        ChunkPos { x, z }
497    }
498}
499impl Add<ChunkPos> for ChunkPos {
500    type Output = Self;
501
502    fn add(self, rhs: Self) -> Self::Output {
503        Self {
504            x: self.x + rhs.x,
505            z: self.z + rhs.z,
506        }
507    }
508}
509impl Add<ChunkBlockPos> for ChunkPos {
510    type Output = BlockPos;
511
512    fn add(self, rhs: ChunkBlockPos) -> Self::Output {
513        BlockPos {
514            x: self.x * 16 + rhs.x as i32,
515            y: rhs.y,
516            z: self.z * 16 + rhs.z as i32,
517        }
518    }
519}
520
521// reading ChunkPos is done in reverse, so z first and then x
522// ........
523// mojang why
524impl From<ChunkPos> for u64 {
525    #[inline]
526    fn from(pos: ChunkPos) -> Self {
527        (pos.x as u64) | ((pos.z as u64) << 32)
528    }
529}
530impl From<u64> for ChunkPos {
531    #[inline]
532    fn from(pos: u64) -> Self {
533        ChunkPos {
534            x: (pos) as i32,
535            z: (pos >> 32) as i32,
536        }
537    }
538}
539impl AzaleaRead for ChunkPos {
540    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
541        let long = u64::azalea_read(buf)?;
542        Ok(ChunkPos::from(long))
543    }
544}
545impl AzaleaWrite for ChunkPos {
546    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
547        u64::from(*self).azalea_write(buf)?;
548        Ok(())
549    }
550}
551
552impl Hash for ChunkPos {
553    #[inline]
554    fn hash<H: Hasher>(&self, state: &mut H) {
555        // optimized hash that only calls hash once
556        u64::from(*self).hash(state);
557    }
558}
559/// nohash_hasher lets us have IntMap<ChunkPos, _> which is significantly faster
560/// than a normal HashMap
561impl nohash_hasher::IsEnabled for ChunkPos {}
562
563/// The coordinates of a chunk section in the world.
564#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
565pub struct ChunkSectionPos {
566    pub x: i32,
567    pub y: i32,
568    pub z: i32,
569}
570vec3_impl!(ChunkSectionPos, i32);
571
572impl ChunkSectionPos {
573    pub fn block_to_section_coord(block: i32) -> i32 {
574        block >> 4
575    }
576}
577
578/// The coordinates of a block inside a chunk.
579#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
580pub struct ChunkBlockPos {
581    pub x: u8,
582    pub y: i32,
583    pub z: u8,
584}
585
586impl ChunkBlockPos {
587    pub fn new(x: u8, y: i32, z: u8) -> Self {
588        ChunkBlockPos { x, y, z }
589    }
590}
591
592impl Hash for ChunkBlockPos {
593    // optimized hash that only calls hash once
594    #[inline]
595    fn hash<H: Hasher>(&self, state: &mut H) {
596        u64::from(*self).hash(state);
597    }
598}
599impl From<ChunkBlockPos> for u64 {
600    #[inline]
601    fn from(pos: ChunkBlockPos) -> Self {
602        // convert to u64
603        let mut val: u64 = 0;
604        // first 32 bits are y
605        val |= pos.y as u64;
606        // next 8 bits are z
607        val |= (pos.z as u64) << 32;
608        // last 8 bits are x
609        val |= (pos.x as u64) << 40;
610        val
611    }
612}
613impl nohash_hasher::IsEnabled for ChunkBlockPos {}
614
615/// The coordinates of a block inside a chunk section. Each coordinate should be
616/// in the range 0..=15.
617#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
618pub struct ChunkSectionBlockPos {
619    pub x: u8,
620    pub y: u8,
621    pub z: u8,
622}
623vec3_impl!(ChunkSectionBlockPos, u8);
624
625/// The coordinates of a chunk inside a chunk section. Each coordinate should be
626/// in the range 0..=3.
627#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
628pub struct ChunkSectionBiomePos {
629    pub x: u8,
630    pub y: u8,
631    pub z: u8,
632}
633impl From<&ChunkBiomePos> for ChunkSectionBiomePos {
634    #[inline]
635    fn from(pos: &ChunkBiomePos) -> Self {
636        ChunkSectionBiomePos {
637            x: pos.x,
638            y: (pos.y & 0b11) as u8,
639            z: pos.z,
640        }
641    }
642}
643impl From<ChunkBiomePos> for ChunkSectionBiomePos {
644    #[inline]
645    fn from(pos: ChunkBiomePos) -> Self {
646        Self::from(&pos)
647    }
648}
649vec3_impl!(ChunkSectionBiomePos, u8);
650
651/// The coordinates of a biome inside a chunk. Biomes are 4x4 blocks.
652#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
653pub struct ChunkBiomePos {
654    pub x: u8,
655    pub y: i32,
656    pub z: u8,
657}
658impl From<&BlockPos> for ChunkBiomePos {
659    #[inline]
660    fn from(pos: &BlockPos) -> Self {
661        ChunkBiomePos::from(&ChunkBlockPos::from(pos))
662    }
663}
664impl From<BlockPos> for ChunkBiomePos {
665    #[inline]
666    fn from(pos: BlockPos) -> Self {
667        ChunkBiomePos::from(&ChunkBlockPos::from(pos))
668    }
669}
670impl From<&ChunkBlockPos> for ChunkBiomePos {
671    #[inline]
672    fn from(pos: &ChunkBlockPos) -> Self {
673        ChunkBiomePos {
674            x: pos.x >> 2,
675            y: pos.y >> 2,
676            z: pos.z >> 2,
677        }
678    }
679}
680
681impl Add<ChunkSectionBlockPos> for ChunkSectionPos {
682    type Output = BlockPos;
683
684    fn add(self, rhs: ChunkSectionBlockPos) -> Self::Output {
685        BlockPos::new(
686            self.x * 16 + rhs.x as i32,
687            self.y * 16 + rhs.y as i32,
688            self.z * 16 + rhs.z as i32,
689        )
690    }
691}
692impl Hash for ChunkSectionBlockPos {
693    // optimized hash that only calls hash once
694    #[inline]
695    fn hash<H: Hasher>(&self, state: &mut H) {
696        u16::from(*self).hash(state);
697    }
698}
699
700impl From<ChunkSectionBlockPos> for u16 {
701    #[inline]
702    fn from(pos: ChunkSectionBlockPos) -> Self {
703        // (pos.z as u16) | ((pos.y as u16) << 4) | ((pos.x as u16) << 8)
704        ((((pos.y as u16) << 4) | pos.z as u16) << 4) | pos.x as u16
705    }
706}
707impl nohash_hasher::IsEnabled for ChunkSectionBlockPos {}
708
709/// A block pos with an attached world
710#[derive(Debug, Clone, PartialEq, Serialize)]
711pub struct GlobalPos {
712    // this is actually a ResourceKey in Minecraft, but i don't think it matters?
713    pub dimension: ResourceLocation,
714    pub pos: BlockPos,
715}
716
717impl From<&BlockPos> for ChunkPos {
718    #[inline]
719    fn from(pos: &BlockPos) -> Self {
720        ChunkPos {
721            x: pos.x >> 4,
722            z: pos.z >> 4,
723        }
724    }
725}
726impl From<BlockPos> for ChunkPos {
727    #[inline]
728    fn from(pos: BlockPos) -> Self {
729        ChunkPos {
730            x: pos.x >> 4,
731            z: pos.z >> 4,
732        }
733    }
734}
735
736impl From<BlockPos> for ChunkSectionPos {
737    #[inline]
738    fn from(pos: BlockPos) -> Self {
739        ChunkSectionPos {
740            x: pos.x >> 4,
741            y: pos.y >> 4,
742            z: pos.z >> 4,
743        }
744    }
745}
746impl From<&BlockPos> for ChunkSectionPos {
747    #[inline]
748    fn from(pos: &BlockPos) -> Self {
749        ChunkSectionPos {
750            x: pos.x >> 4,
751            y: pos.y >> 4,
752            z: pos.z >> 4,
753        }
754    }
755}
756
757impl From<ChunkSectionPos> for ChunkPos {
758    fn from(pos: ChunkSectionPos) -> Self {
759        ChunkPos { x: pos.x, z: pos.z }
760    }
761}
762impl From<&Vec3> for ChunkSectionPos {
763    fn from(pos: &Vec3) -> Self {
764        ChunkSectionPos::from(&BlockPos::from(pos))
765    }
766}
767impl From<Vec3> for ChunkSectionPos {
768    fn from(pos: Vec3) -> Self {
769        ChunkSectionPos::from(&pos)
770    }
771}
772
773impl From<&BlockPos> for ChunkBlockPos {
774    #[inline]
775    fn from(pos: &BlockPos) -> Self {
776        ChunkBlockPos {
777            x: (pos.x & 0xF) as u8,
778            y: pos.y,
779            z: (pos.z & 0xF) as u8,
780        }
781    }
782}
783impl From<BlockPos> for ChunkBlockPos {
784    #[inline]
785    fn from(pos: BlockPos) -> Self {
786        ChunkBlockPos {
787            x: (pos.x & 0xF) as u8,
788            y: pos.y,
789            z: (pos.z & 0xF) as u8,
790        }
791    }
792}
793
794impl From<BlockPos> for ChunkSectionBlockPos {
795    #[inline]
796    fn from(pos: BlockPos) -> Self {
797        ChunkSectionBlockPos {
798            x: (pos.x & 0xF) as u8,
799            y: (pos.y & 0xF) as u8,
800            z: (pos.z & 0xF) as u8,
801        }
802    }
803}
804
805impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
806    #[inline]
807    fn from(pos: &ChunkBlockPos) -> Self {
808        ChunkSectionBlockPos {
809            x: pos.x,
810            y: (pos.y & 0xF) as u8,
811            z: pos.z,
812        }
813    }
814}
815impl From<&Vec3> for BlockPos {
816    #[inline]
817    fn from(pos: &Vec3) -> Self {
818        BlockPos {
819            x: pos.x.floor() as i32,
820            y: pos.y.floor() as i32,
821            z: pos.z.floor() as i32,
822        }
823    }
824}
825impl From<Vec3> for BlockPos {
826    #[inline]
827    fn from(pos: Vec3) -> Self {
828        BlockPos::from(&pos)
829    }
830}
831
832impl From<&Vec3> for ChunkPos {
833    fn from(pos: &Vec3) -> Self {
834        ChunkPos::from(&BlockPos::from(pos))
835    }
836}
837impl From<Vec3> for ChunkPos {
838    fn from(pos: Vec3) -> Self {
839        ChunkPos::from(&pos)
840    }
841}
842
843impl From<&Vec3> for ChunkBlockPos {
844    fn from(pos: &Vec3) -> Self {
845        ChunkBlockPos::from(&BlockPos::from(pos))
846    }
847}
848impl From<Vec3> for ChunkBlockPos {
849    fn from(pos: Vec3) -> Self {
850        ChunkBlockPos::from(&pos)
851    }
852}
853
854impl fmt::Display for BlockPos {
855    /// Display a block position as `x y z`.
856    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
857        write!(f, "{} {} {}", self.x, self.y, self.z)
858    }
859}
860impl fmt::Display for Vec3 {
861    /// Display a position as `x y z`.
862    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
863        write!(f, "{} {} {}", self.x, self.y, self.z)
864    }
865}
866
867/// A 2D vector.
868#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf, Deserialize, Serialize)]
869pub struct Vec2 {
870    pub x: f32,
871    pub y: f32,
872}
873impl Vec2 {
874    const ZERO: Vec2 = Vec2 { x: 0.0, y: 0.0 };
875
876    #[inline]
877    pub fn new(x: f32, y: f32) -> Self {
878        Vec2 { x, y }
879    }
880    #[inline]
881    pub fn scale(&self, amount: f32) -> Self {
882        Vec2 {
883            x: self.x * amount,
884            y: self.y * amount,
885        }
886    }
887    #[inline]
888    pub fn dot(&self, other: Vec2) -> f32 {
889        self.x * other.x + self.y * other.y
890    }
891    #[inline]
892    pub fn normalized(&self) -> Self {
893        let length = (self.x * self.x + self.y * self.y).sqrt();
894        if length < 1e-4 {
895            return Vec2::ZERO;
896        }
897        Vec2 {
898            x: self.x / length,
899            y: self.y / length,
900        }
901    }
902    #[inline]
903    pub fn length_squared(&self) -> f32 {
904        self.x * self.x + self.y * self.y
905    }
906    #[inline]
907    pub fn length(&self) -> f32 {
908        self.length_squared().sqrt()
909    }
910}
911impl Mul<f32> for Vec2 {
912    type Output = Self;
913
914    #[inline]
915    fn mul(self, rhs: f32) -> Self::Output {
916        self.scale(rhs)
917    }
918}
919impl MulAssign<f32> for Vec2 {
920    #[inline]
921    fn mul_assign(&mut self, rhs: f32) {
922        *self = self.scale(rhs);
923    }
924}
925
926const PACKED_X_LENGTH: u64 = 1 + 25; // minecraft does something a bit more complicated to get this 25
927const PACKED_Z_LENGTH: u64 = PACKED_X_LENGTH;
928const PACKED_Y_LENGTH: u64 = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
929const PACKED_X_MASK: u64 = (1 << PACKED_X_LENGTH) - 1;
930const PACKED_Y_MASK: u64 = (1 << PACKED_Y_LENGTH) - 1;
931const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
932const Z_OFFSET: u64 = PACKED_Y_LENGTH;
933const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
934
935impl AzaleaRead for BlockPos {
936    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
937        let val = i64::azalea_read(buf)?;
938        let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
939        let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
940        let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
941        Ok(BlockPos { x, y, z })
942    }
943}
944
945impl AzaleaRead for GlobalPos {
946    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
947        Ok(GlobalPos {
948            dimension: ResourceLocation::azalea_read(buf)?,
949            pos: BlockPos::azalea_read(buf)?,
950        })
951    }
952}
953
954impl AzaleaRead for ChunkSectionPos {
955    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
956        let long = i64::azalea_read(buf)?;
957        Ok(ChunkSectionPos {
958            x: (long >> 42) as i32,
959            y: (long << 44 >> 44) as i32,
960            z: (long << 22 >> 42) as i32,
961        })
962    }
963}
964
965impl AzaleaWrite for BlockPos {
966    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
967        let mut val: u64 = 0;
968        val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
969        val |= (self.y as u64) & PACKED_Y_MASK;
970        val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
971        val.azalea_write(buf)
972    }
973}
974
975impl AzaleaWrite for GlobalPos {
976    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
977        ResourceLocation::azalea_write(&self.dimension, buf)?;
978        BlockPos::azalea_write(&self.pos, buf)?;
979
980        Ok(())
981    }
982}
983
984impl AzaleaWrite for ChunkSectionPos {
985    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
986        let long = (((self.x & 0x3FFFFF) as i64) << 42)
987            | (self.y & 0xFFFFF) as i64
988            | (((self.z & 0x3FFFFF) as i64) << 20);
989        long.azalea_write(buf)?;
990        Ok(())
991    }
992}
993
994fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
995where
996    T: FromStr,
997    <T as FromStr>::Err: fmt::Debug,
998{
999    let parts = s.split_whitespace().collect::<Vec<_>>();
1000    if parts.len() != 3 {
1001        return Err("Expected three values");
1002    }
1003
1004    let x = parts[0].parse().map_err(|_| "Invalid X value")?;
1005    let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
1006    let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
1007
1008    Ok([x, y, z])
1009}
1010
1011/// Parses a string in the format "X Y Z" into a BlockPos.
1012///
1013/// The input string should contain three integer values separated by spaces,
1014/// representing the x, y, and z components of the vector respectively.
1015/// This can be used to parse user input or from `BlockPos::to_string`.
1016impl FromStr for BlockPos {
1017    type Err = &'static str;
1018
1019    fn from_str(s: &str) -> Result<Self, Self::Err> {
1020        let [x, y, z] = parse_three_values::<i32>(s)?;
1021        Ok(BlockPos { x, y, z })
1022    }
1023}
1024
1025/// Parses a string in the format "X Y Z" into a Vec3.
1026///
1027/// The input string should contain three floating-point values separated by
1028/// spaces, representing the x, y, and z components of the vector respectively.
1029/// This can be used to parse user input or from `Vec3::to_string`.
1030impl FromStr for Vec3 {
1031    type Err = &'static str;
1032
1033    fn from_str(s: &str) -> Result<Self, Self::Err> {
1034        let [x, y, z] = parse_three_values::<f64>(s)?;
1035        Ok(Vec3 { x, y, z })
1036    }
1037}
1038
1039#[cfg(test)]
1040mod tests {
1041    use super::*;
1042
1043    #[test]
1044    fn test_from_block_pos_to_chunk_pos() {
1045        let block_pos = BlockPos::new(5, 78, -2);
1046        let chunk_pos = ChunkPos::from(&block_pos);
1047        assert_eq!(chunk_pos, ChunkPos::new(0, -1));
1048    }
1049
1050    #[test]
1051    fn test_from_block_pos_to_chunk_block_pos() {
1052        let block_pos = BlockPos::new(5, 78, -2);
1053        let chunk_block_pos = ChunkBlockPos::from(&block_pos);
1054        assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
1055    }
1056
1057    #[test]
1058    fn test_from_entity_pos_to_block_pos() {
1059        let entity_pos = Vec3 {
1060            x: 31.5,
1061            y: 80.0,
1062            z: -16.1,
1063        };
1064        let block_pos = BlockPos::from(&entity_pos);
1065        assert_eq!(block_pos, BlockPos::new(31, 80, -17));
1066    }
1067
1068    #[test]
1069    fn test_from_entity_pos_to_chunk_pos() {
1070        let entity_pos = Vec3 {
1071            x: 31.5,
1072            y: 80.0,
1073            z: -16.1,
1074        };
1075        let chunk_pos = ChunkPos::from(&entity_pos);
1076        assert_eq!(chunk_pos, ChunkPos::new(1, -2));
1077    }
1078
1079    #[test]
1080    fn test_read_blockpos_from() {
1081        let mut buf = Vec::new();
1082        13743895338965u64.azalea_write(&mut buf).unwrap();
1083        let mut buf = Cursor::new(&buf[..]);
1084        let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
1085        assert_eq!(block_pos, BlockPos::new(49, -43, -3));
1086    }
1087
1088    #[test]
1089    fn test_into_chunk_section_block_pos() {
1090        let block_pos = BlockPos::new(0, -60, 0);
1091        assert_eq!(
1092            ChunkSectionBlockPos::from(block_pos),
1093            ChunkSectionBlockPos::new(0, 4, 0)
1094        );
1095    }
1096
1097    #[test]
1098    fn test_read_chunk_pos_from() {
1099        let mut buf = Vec::new();
1100        ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
1101        let mut buf = Cursor::new(&buf[..]);
1102        let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
1103        assert_eq!(chunk_pos, ChunkPos::new(2, -1));
1104    }
1105}