azalea_protocol/packets/game/
clientbound_section_blocks_update_packet.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use std::io::{Cursor, Write};

use azalea_block::BlockState;
use azalea_buf::{
    BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
};
use azalea_core::position::{ChunkSectionBlockPos, ChunkSectionPos};
use azalea_protocol_macros::ClientboundGamePacket;

#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSectionBlocksUpdatePacket {
    pub section_pos: ChunkSectionPos,
    pub states: Vec<BlockStateWithPosition>,
}

#[derive(Clone, Debug)]
pub struct BlockStateWithPosition {
    pub pos: ChunkSectionBlockPos,
    pub state: BlockState,
}

impl McBufReadable for BlockStateWithPosition {
    fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
        let data = u64::var_read_from(buf)?;
        let position_part = data & 4095;
        let state = (data >> 12) as u32;
        let state = BlockState::try_from(state)
            .map_err(|_| BufReadError::UnexpectedEnumVariant { id: state as i32 })?;
        let pos = ChunkSectionBlockPos {
            x: (position_part >> 8 & 15) as u8,
            y: (position_part & 15) as u8,
            z: (position_part >> 4 & 15) as u8,
        };
        Ok(BlockStateWithPosition { pos, state })
    }
}

impl McBufWritable for BlockStateWithPosition {
    fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
        let data = (self.state.id as u64) << 12
            | (u64::from(self.pos.x) << 8 | u64::from(self.pos.z) << 4 | u64::from(self.pos.y));
        u64::var_write_into(&data, buf)?;
        Ok(())
    }
}