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