chunkedge_protocol/
chunk_section_pos.rs

1use std::fmt;
2use std::io::Write;
3
4use bitfield_struct::bitfield;
5use chunkedge_binary::{Decode, Encode};
6use derive_more::From;
7use thiserror::Error;
8
9use crate::{BiomePos, BlockPos};
10
11#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
12pub struct ChunkSectionPos {
13    pub x: i32,
14    pub y: i32,
15    pub z: i32,
16}
17
18impl ChunkSectionPos {
19    pub const fn new(x: i32, y: i32, z: i32) -> Self {
20        Self { x, y, z }
21    }
22
23    pub const fn packed(self) -> Result<PackedChunkSectionPos, Error> {
24        match (self.x, self.y, self.z) {
25            (-2097152..=2097151, -524288..=524287, -2097152..=2097151) => {
26                Ok(PackedChunkSectionPos::new()
27                    .with_x(self.x)
28                    .with_y(self.y)
29                    .with_z(self.z))
30            }
31            _ => Err(Error(self)),
32        }
33    }
34}
35
36impl fmt::Display for ChunkSectionPos {
37    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38        fmt::Debug::fmt(&(self.x, self.y, self.z), f)
39    }
40}
41
42impl Encode for ChunkSectionPos {
43    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
44        self.packed()?.encode(w)
45    }
46}
47
48impl Decode<'_> for ChunkSectionPos {
49    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
50        PackedChunkSectionPos::decode(r).map(Into::into)
51    }
52}
53
54impl From<BlockPos> for ChunkSectionPos {
55    fn from(pos: BlockPos) -> Self {
56        Self {
57            x: pos.x.div_euclid(16),
58            y: pos.y.div_euclid(16),
59            z: pos.z.div_euclid(16),
60        }
61    }
62}
63
64impl From<BiomePos> for ChunkSectionPos {
65    fn from(pos: BiomePos) -> Self {
66        Self {
67            x: pos.x.div_euclid(4),
68            y: pos.y.div_euclid(4),
69            z: pos.z.div_euclid(4),
70        }
71    }
72}
73
74#[bitfield(u64)]
75#[derive(PartialEq, Eq, Ord, PartialOrd, Encode, Decode)]
76pub struct PackedChunkSectionPos {
77    #[bits(20)]
78    pub y: i32,
79    #[bits(22)]
80    pub z: i32,
81    #[bits(22)]
82    pub x: i32,
83}
84
85impl From<PackedChunkSectionPos> for ChunkSectionPos {
86    fn from(pos: PackedChunkSectionPos) -> Self {
87        Self {
88            x: pos.x(),
89            y: pos.y(),
90            z: pos.z(),
91        }
92    }
93}
94
95impl TryFrom<ChunkSectionPos> for PackedChunkSectionPos {
96    type Error = Error;
97
98    fn try_from(pos: ChunkSectionPos) -> Result<Self, Self::Error> {
99        pos.packed()
100    }
101}
102
103#[derive(Copy, Clone, PartialEq, Eq, Debug, Error, From)]
104#[error("chunk section position of {0} is out of range")]
105pub struct Error(pub ChunkSectionPos);