valence_protocol/
chunk_section_pos.rs

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