1use std::str::FromStr;
7use std::{
8 fmt,
9 hash::Hash,
10 io::{Cursor, Write},
11 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, Sub},
12};
13
14use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
15
16use crate::direction::Direction;
17use crate::math;
18use crate::resource_location::ResourceLocation;
19
20macro_rules! vec3_impl {
21 ($name:ident, $type:ty) => {
22 impl $name {
23 #[inline]
24 pub const fn new(x: $type, y: $type, z: $type) -> Self {
25 Self { x, y, z }
26 }
27
28 #[inline]
31 pub fn length_squared(&self) -> $type {
32 self.x * self.x + self.y * self.y + self.z * self.z
33 }
34
35 #[inline]
38 pub fn distance_squared_to(&self, other: &Self) -> $type {
39 (self - other).length_squared()
40 }
41
42 #[inline]
43 pub fn horizontal_distance_squared(&self) -> $type {
44 self.x * self.x + self.z * self.z
45 }
46
47 #[inline]
48 pub fn horizontal_distance_squared_to(&self, other: &Self) -> $type {
49 (self - other).horizontal_distance_squared()
50 }
51
52 #[inline]
55 pub fn down(&self, y: $type) -> Self {
56 Self {
57 x: self.x,
58 y: self.y - y,
59 z: self.z,
60 }
61 }
62 #[inline]
65 pub fn up(&self, y: $type) -> Self {
66 Self {
67 x: self.x,
68 y: self.y + y,
69 z: self.z,
70 }
71 }
72
73 #[inline]
76 pub fn north(&self, z: $type) -> Self {
77 Self {
78 x: self.x,
79 y: self.y,
80 z: self.z - z,
81 }
82 }
83 #[inline]
86 pub fn east(&self, x: $type) -> Self {
87 Self {
88 x: self.x + x,
89 y: self.y,
90 z: self.z,
91 }
92 }
93 #[inline]
96 pub fn south(&self, z: $type) -> Self {
97 Self {
98 x: self.x,
99 y: self.y,
100 z: self.z + z,
101 }
102 }
103 #[inline]
106 pub fn west(&self, x: $type) -> Self {
107 Self {
108 x: self.x - x,
109 y: self.y,
110 z: self.z,
111 }
112 }
113
114 #[inline]
115 pub fn dot(&self, other: Self) -> $type {
116 self.x * other.x + self.y * other.y + self.z * other.z
117 }
118
119 #[inline]
121 pub fn xz(&self) -> Self {
122 Self {
123 x: self.x,
124 y: <$type>::default(),
125 z: self.z,
126 }
127 }
128 }
129
130 impl Add for &$name {
131 type Output = $name;
132
133 #[inline]
134 fn add(self, rhs: Self) -> Self::Output {
135 $name {
136 x: self.x + rhs.x,
137 y: self.y + rhs.y,
138 z: self.z + rhs.z,
139 }
140 }
141 }
142 impl Add for $name {
143 type Output = $name;
144
145 #[inline]
146 fn add(self, rhs: Self) -> Self::Output {
147 (&self).add(&rhs)
148 }
149 }
150 impl Add<$type> for $name {
151 type Output = Self;
152
153 #[inline]
154 fn add(self, rhs: $type) -> Self::Output {
155 Self {
156 x: self.x + rhs,
157 y: self.y + rhs,
158 z: self.z + rhs,
159 }
160 }
161 }
162
163 impl AddAssign for $name {
164 #[inline]
165 fn add_assign(&mut self, rhs: Self) {
166 self.x += rhs.x;
167 self.y += rhs.y;
168 self.z += rhs.z;
169 }
170 }
171 impl Rem<$type> for $name {
172 type Output = Self;
173
174 #[inline]
175 fn rem(self, rhs: $type) -> Self::Output {
176 Self {
177 x: self.x % rhs,
178 y: self.y % rhs,
179 z: self.z % rhs,
180 }
181 }
182 }
183
184 impl Sub for &$name {
185 type Output = $name;
186
187 #[inline]
189 fn sub(self, other: Self) -> Self::Output {
190 Self::Output {
191 x: self.x - other.x,
192 y: self.y - other.y,
193 z: self.z - other.z,
194 }
195 }
196 }
197 impl Sub for $name {
198 type Output = Self;
199
200 #[inline]
201 fn sub(self, other: Self) -> Self::Output {
202 (&self).sub(&other)
203 }
204 }
205
206 impl Mul<$type> for $name {
207 type Output = Self;
208
209 #[inline]
210 fn mul(self, multiplier: $type) -> Self::Output {
211 Self {
212 x: self.x * multiplier,
213 y: self.y * multiplier,
214 z: self.z * multiplier,
215 }
216 }
217 }
218 impl MulAssign<$type> for $name {
219 #[inline]
220 fn mul_assign(&mut self, multiplier: $type) {
221 self.x *= multiplier;
222 self.y *= multiplier;
223 self.z *= multiplier;
224 }
225 }
226
227 impl Div<$type> for $name {
228 type Output = Self;
229
230 #[inline]
231 fn div(self, divisor: $type) -> Self::Output {
232 Self {
233 x: self.x / divisor,
234 y: self.y / divisor,
235 z: self.z / divisor,
236 }
237 }
238 }
239 impl DivAssign<$type> for $name {
240 #[inline]
241 fn div_assign(&mut self, divisor: $type) {
242 self.x /= divisor;
243 self.y /= divisor;
244 self.z /= divisor;
245 }
246 }
247
248 impl From<($type, $type, $type)> for $name {
249 #[inline]
250 fn from(pos: ($type, $type, $type)) -> Self {
251 Self::new(pos.0, pos.1, pos.2)
252 }
253 }
254 impl From<&($type, $type, $type)> for $name {
255 #[inline]
256 fn from(pos: &($type, $type, $type)) -> Self {
257 Self::new(pos.0, pos.1, pos.2)
258 }
259 }
260 impl From<$name> for ($type, $type, $type) {
261 #[inline]
262 fn from(pos: $name) -> Self {
263 (pos.x, pos.y, pos.z)
264 }
265 }
266 };
267}
268
269#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf)]
273#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
274pub struct Vec3 {
275 pub x: f64,
276 pub y: f64,
277 pub z: f64,
278}
279vec3_impl!(Vec3, f64);
280
281impl Vec3 {
282 pub const ZERO: Vec3 = Vec3::new(0.0, 0.0, 0.0);
283
284 pub fn length(&self) -> f64 {
287 f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
288 }
289
290 pub fn distance_to(&self, other: &Self) -> f64 {
293 (self - other).length()
294 }
295
296 pub fn x_rot(self, radians: f32) -> Vec3 {
297 let x_delta = math::cos(radians);
298 let y_delta = math::sin(radians);
299 let x = self.x;
300 let y = self.y * (x_delta as f64) + self.z * (y_delta as f64);
301 let z = self.z * (x_delta as f64) - self.y * (y_delta as f64);
302 Vec3 { x, y, z }
303 }
304 pub fn y_rot(self, radians: f32) -> Vec3 {
305 let x_delta = math::cos(radians);
306 let y_delta = math::sin(radians);
307 let x = self.x * (x_delta as f64) + self.z * (y_delta as f64);
308 let y = self.y;
309 let z = self.z * (x_delta as f64) - self.x * (y_delta as f64);
310 Vec3 { x, y, z }
311 }
312}
313
314#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
317#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
318pub struct BlockPos {
319 pub x: i32,
320 pub y: i32,
321 pub z: i32,
322}
323vec3_impl!(BlockPos, i32);
324
325impl BlockPos {
326 pub fn center(&self) -> Vec3 {
329 Vec3 {
330 x: self.x as f64 + 0.5,
331 y: self.y as f64 + 0.5,
332 z: self.z as f64 + 0.5,
333 }
334 }
335
336 pub fn to_vec3_floored(&self) -> Vec3 {
338 Vec3 {
339 x: self.x as f64,
340 y: self.y as f64,
341 z: self.z as f64,
342 }
343 }
344
345 pub fn length_manhattan(&self) -> u32 {
347 (self.x.abs() + self.y.abs() + self.z.abs()) as u32
348 }
349
350 pub fn min(&self, other: &Self) -> Self {
363 Self {
364 x: self.x.min(other.x),
365 y: self.y.min(other.y),
366 z: self.z.min(other.z),
367 }
368 }
369
370 pub fn max(&self, other: &Self) -> Self {
383 Self {
384 x: self.x.max(other.x),
385 y: self.y.max(other.y),
386 z: self.z.max(other.z),
387 }
388 }
389
390 pub fn offset_with_direction(self, direction: Direction) -> Self {
391 self + direction.normal()
392 }
393}
394
395#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
398pub struct ChunkPos {
399 pub x: i32,
400 pub z: i32,
401}
402impl ChunkPos {
403 pub fn new(x: i32, z: i32) -> Self {
404 ChunkPos { x, z }
405 }
406}
407impl Add<ChunkPos> for ChunkPos {
408 type Output = Self;
409
410 fn add(self, rhs: Self) -> Self::Output {
411 Self {
412 x: self.x + rhs.x,
413 z: self.z + rhs.z,
414 }
415 }
416}
417
418impl From<ChunkPos> for u64 {
422 #[inline]
423 fn from(pos: ChunkPos) -> Self {
424 (pos.x as u64) | ((pos.z as u64) << 32)
425 }
426}
427impl From<u64> for ChunkPos {
428 #[inline]
429 fn from(pos: u64) -> Self {
430 ChunkPos {
431 x: (pos) as i32,
432 z: (pos >> 32) as i32,
433 }
434 }
435}
436impl AzaleaRead for ChunkPos {
437 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
438 let long = u64::azalea_read(buf)?;
439 Ok(ChunkPos::from(long))
440 }
441}
442impl AzaleaWrite for ChunkPos {
443 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
444 u64::from(*self).azalea_write(buf)?;
445 Ok(())
446 }
447}
448
449impl Hash for ChunkPos {
450 #[inline]
451 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
452 u64::from(*self).hash(state);
454 }
455}
456impl nohash_hasher::IsEnabled for ChunkPos {}
459
460#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
462pub struct ChunkSectionPos {
463 pub x: i32,
464 pub y: i32,
465 pub z: i32,
466}
467vec3_impl!(ChunkSectionPos, i32);
468
469impl ChunkSectionPos {
470 pub fn block_to_section_coord(block: i32) -> i32 {
471 block >> 4
472 }
473}
474
475#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
477pub struct ChunkBlockPos {
478 pub x: u8,
479 pub y: i32,
480 pub z: u8,
481}
482
483impl ChunkBlockPos {
484 pub fn new(x: u8, y: i32, z: u8) -> Self {
485 ChunkBlockPos { x, y, z }
486 }
487}
488
489impl Hash for ChunkBlockPos {
490 #[inline]
492 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
493 u64::from(*self).hash(state);
494 }
495}
496impl From<ChunkBlockPos> for u64 {
497 #[inline]
498 fn from(pos: ChunkBlockPos) -> Self {
499 let mut val: u64 = 0;
501 val |= pos.y as u64;
503 val |= (pos.z as u64) << 32;
505 val |= (pos.x as u64) << 40;
507 val
508 }
509}
510impl nohash_hasher::IsEnabled for ChunkBlockPos {}
511
512#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
515pub struct ChunkSectionBlockPos {
516 pub x: u8,
517 pub y: u8,
518 pub z: u8,
519}
520vec3_impl!(ChunkSectionBlockPos, u8);
521
522impl Add<ChunkSectionBlockPos> for ChunkSectionPos {
523 type Output = BlockPos;
524
525 fn add(self, rhs: ChunkSectionBlockPos) -> Self::Output {
526 BlockPos::new(
527 self.x * 16 + rhs.x as i32,
528 self.y * 16 + rhs.y as i32,
529 self.z * 16 + rhs.z as i32,
530 )
531 }
532}
533impl Hash for ChunkSectionBlockPos {
534 #[inline]
536 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
537 u16::from(*self).hash(state);
538 }
539}
540
541impl From<ChunkSectionBlockPos> for u16 {
542 #[inline]
543 fn from(pos: ChunkSectionBlockPos) -> Self {
544 ((((pos.y as u16) << 4) | pos.z as u16) << 4) | pos.x as u16
546 }
547}
548impl nohash_hasher::IsEnabled for ChunkSectionBlockPos {}
549
550#[derive(Debug, Clone, PartialEq)]
552pub struct GlobalPos {
553 pub world: ResourceLocation,
555 pub pos: BlockPos,
556}
557
558impl From<&BlockPos> for ChunkPos {
559 #[inline]
560 fn from(pos: &BlockPos) -> Self {
561 ChunkPos {
562 x: pos.x >> 4,
563 z: pos.z >> 4,
564 }
565 }
566}
567impl From<BlockPos> for ChunkPos {
568 #[inline]
569 fn from(pos: BlockPos) -> Self {
570 ChunkPos {
571 x: pos.x >> 4,
572 z: pos.z >> 4,
573 }
574 }
575}
576
577impl From<BlockPos> for ChunkSectionPos {
578 #[inline]
579 fn from(pos: BlockPos) -> Self {
580 ChunkSectionPos {
581 x: pos.x >> 4,
582 y: pos.y >> 4,
583 z: pos.z >> 4,
584 }
585 }
586}
587impl From<&BlockPos> for ChunkSectionPos {
588 #[inline]
589 fn from(pos: &BlockPos) -> Self {
590 ChunkSectionPos {
591 x: pos.x >> 4,
592 y: pos.y >> 4,
593 z: pos.z >> 4,
594 }
595 }
596}
597
598impl From<ChunkSectionPos> for ChunkPos {
599 fn from(pos: ChunkSectionPos) -> Self {
600 ChunkPos { x: pos.x, z: pos.z }
601 }
602}
603
604impl From<&BlockPos> for ChunkBlockPos {
605 #[inline]
606 fn from(pos: &BlockPos) -> Self {
607 ChunkBlockPos {
608 x: (pos.x & 0xF) as u8,
609 y: pos.y,
610 z: (pos.z & 0xF) as u8,
611 }
612 }
613}
614impl From<BlockPos> for ChunkBlockPos {
615 #[inline]
616 fn from(pos: BlockPos) -> Self {
617 ChunkBlockPos {
618 x: (pos.x & 0xF) as u8,
619 y: pos.y,
620 z: (pos.z & 0xF) as u8,
621 }
622 }
623}
624
625impl From<BlockPos> for ChunkSectionBlockPos {
626 #[inline]
627 fn from(pos: BlockPos) -> Self {
628 ChunkSectionBlockPos {
629 x: (pos.x & 0xF) as u8,
630 y: (pos.y & 0xF) as u8,
631 z: (pos.z & 0xF) as u8,
632 }
633 }
634}
635
636impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
637 #[inline]
638 fn from(pos: &ChunkBlockPos) -> Self {
639 ChunkSectionBlockPos {
640 x: pos.x,
641 y: (pos.y & 0xF) as u8,
642 z: pos.z,
643 }
644 }
645}
646impl From<&Vec3> for BlockPos {
647 #[inline]
648 fn from(pos: &Vec3) -> Self {
649 BlockPos {
650 x: pos.x.floor() as i32,
651 y: pos.y.floor() as i32,
652 z: pos.z.floor() as i32,
653 }
654 }
655}
656impl From<Vec3> for BlockPos {
657 #[inline]
658 fn from(pos: Vec3) -> Self {
659 BlockPos::from(&pos)
660 }
661}
662
663impl From<&Vec3> for ChunkPos {
664 fn from(pos: &Vec3) -> Self {
665 ChunkPos::from(&BlockPos::from(pos))
666 }
667}
668impl From<Vec3> for ChunkPos {
669 fn from(pos: Vec3) -> Self {
670 ChunkPos::from(&pos)
671 }
672}
673
674impl From<&Vec3> for ChunkBlockPos {
675 fn from(pos: &Vec3) -> Self {
676 ChunkBlockPos::from(&BlockPos::from(pos))
677 }
678}
679impl From<Vec3> for ChunkBlockPos {
680 fn from(pos: Vec3) -> Self {
681 ChunkBlockPos::from(&pos)
682 }
683}
684
685impl fmt::Display for BlockPos {
686 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
688 write!(f, "{} {} {}", self.x, self.y, self.z)
689 }
690}
691impl fmt::Display for Vec3 {
692 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
694 write!(f, "{} {} {}", self.x, self.y, self.z)
695 }
696}
697
698const PACKED_X_LENGTH: u64 = 1 + 25; const PACKED_Z_LENGTH: u64 = PACKED_X_LENGTH;
700const PACKED_Y_LENGTH: u64 = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH;
701const PACKED_X_MASK: u64 = (1 << PACKED_X_LENGTH) - 1;
702const PACKED_Y_MASK: u64 = (1 << PACKED_Y_LENGTH) - 1;
703const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
704const Z_OFFSET: u64 = PACKED_Y_LENGTH;
705const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
706
707impl AzaleaRead for BlockPos {
708 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
709 let val = i64::azalea_read(buf)?;
710 let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
711 let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
712 let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
713 Ok(BlockPos { x, y, z })
714 }
715}
716
717impl AzaleaRead for GlobalPos {
718 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
719 Ok(GlobalPos {
720 world: ResourceLocation::azalea_read(buf)?,
721 pos: BlockPos::azalea_read(buf)?,
722 })
723 }
724}
725
726impl AzaleaRead for ChunkSectionPos {
727 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
728 let long = i64::azalea_read(buf)?;
729 Ok(ChunkSectionPos {
730 x: (long >> 42) as i32,
731 y: (long << 44 >> 44) as i32,
732 z: (long << 22 >> 42) as i32,
733 })
734 }
735}
736
737impl AzaleaWrite for BlockPos {
738 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
739 let mut val: u64 = 0;
740 val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
741 val |= (self.y as u64) & PACKED_Y_MASK;
742 val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
743 val.azalea_write(buf)
744 }
745}
746
747impl AzaleaWrite for GlobalPos {
748 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
749 ResourceLocation::azalea_write(&self.world, buf)?;
750 BlockPos::azalea_write(&self.pos, buf)?;
751
752 Ok(())
753 }
754}
755
756impl AzaleaWrite for ChunkSectionPos {
757 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
758 let long = (((self.x & 0x3FFFFF) as i64) << 42)
759 | (self.y & 0xFFFFF) as i64
760 | (((self.z & 0x3FFFFF) as i64) << 20);
761 long.azalea_write(buf)?;
762 Ok(())
763 }
764}
765
766fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
767where
768 T: FromStr,
769 <T as FromStr>::Err: fmt::Debug,
770{
771 let parts = s.split_whitespace().collect::<Vec<_>>();
772 if parts.len() != 3 {
773 return Err("Expected three values");
774 }
775
776 let x = parts[0].parse().map_err(|_| "Invalid X value")?;
777 let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
778 let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
779
780 Ok([x, y, z])
781}
782
783impl FromStr for BlockPos {
789 type Err = &'static str;
790
791 fn from_str(s: &str) -> Result<Self, Self::Err> {
792 let [x, y, z] = parse_three_values::<i32>(s)?;
793 Ok(BlockPos { x, y, z })
794 }
795}
796
797impl FromStr for Vec3 {
803 type Err = &'static str;
804
805 fn from_str(s: &str) -> Result<Self, Self::Err> {
806 let [x, y, z] = parse_three_values::<f64>(s)?;
807 Ok(Vec3 { x, y, z })
808 }
809}
810
811#[cfg(test)]
812mod tests {
813 use super::*;
814
815 #[test]
816 fn test_from_block_pos_to_chunk_pos() {
817 let block_pos = BlockPos::new(5, 78, -2);
818 let chunk_pos = ChunkPos::from(&block_pos);
819 assert_eq!(chunk_pos, ChunkPos::new(0, -1));
820 }
821
822 #[test]
823 fn test_from_block_pos_to_chunk_block_pos() {
824 let block_pos = BlockPos::new(5, 78, -2);
825 let chunk_block_pos = ChunkBlockPos::from(&block_pos);
826 assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14));
827 }
828
829 #[test]
830 fn test_from_entity_pos_to_block_pos() {
831 let entity_pos = Vec3 {
832 x: 31.5,
833 y: 80.0,
834 z: -16.1,
835 };
836 let block_pos = BlockPos::from(&entity_pos);
837 assert_eq!(block_pos, BlockPos::new(31, 80, -17));
838 }
839
840 #[test]
841 fn test_from_entity_pos_to_chunk_pos() {
842 let entity_pos = Vec3 {
843 x: 31.5,
844 y: 80.0,
845 z: -16.1,
846 };
847 let chunk_pos = ChunkPos::from(&entity_pos);
848 assert_eq!(chunk_pos, ChunkPos::new(1, -2));
849 }
850
851 #[test]
852 fn test_read_blockpos_from() {
853 let mut buf = Vec::new();
854 13743895338965u64.azalea_write(&mut buf).unwrap();
855 let mut buf = Cursor::new(&buf[..]);
856 let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
857 assert_eq!(block_pos, BlockPos::new(49, -43, -3));
858 }
859
860 #[test]
861 fn test_into_chunk_section_block_pos() {
862 let block_pos = BlockPos::new(0, -60, 0);
863 assert_eq!(
864 ChunkSectionBlockPos::from(block_pos),
865 ChunkSectionBlockPos::new(0, 4, 0)
866 );
867 }
868
869 #[test]
870 fn test_read_chunk_pos_from() {
871 let mut buf = Vec::new();
872 ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
873 let mut buf = Cursor::new(&buf[..]);
874 let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
875 assert_eq!(chunk_pos, ChunkPos::new(2, -1));
876 }
877}