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);