chunkedge_protocol/
chunk_section_pos.rs1use 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);