aboutsummaryrefslogtreecommitdiff
path: root/azalea-protocol/src/packets/game/c_section_blocks_update.rs
blob: 8803e34a86a10d7b2e7df11e3eff22dddb9d1bbb (plain)
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
use std::io::{self, Cursor, Write};

use azalea_block::BlockState;
use azalea_buf::{AzBuf, AzBufVar, BufReadError};
use azalea_core::position::{ChunkSectionBlockPos, ChunkSectionPos};
use azalea_protocol_macros::ClientboundGamePacket;

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

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

impl AzBuf for BlockStateWithPosition {
    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
        let data = u64::azalea_read_var(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 })
    }
    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
        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::azalea_write_var(&data, buf)?;
        Ok(())
    }
}