azalea_protocol/packets/game/
s_use_item_on.rs

1use std::io::{self, Cursor, Write};
2
3use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
4use azalea_core::{
5    direction::Direction,
6    hit_result::BlockHitResult,
7    position::{BlockPos, Vec3},
8};
9use azalea_protocol_macros::ServerboundGamePacket;
10
11use crate::packets::game::s_interact::InteractionHand;
12
13#[derive(Clone, Debug, AzBuf, PartialEq, ServerboundGamePacket)]
14pub struct ServerboundUseItemOn {
15    pub hand: InteractionHand,
16    pub block_hit: BlockHit,
17    #[var]
18    pub seq: u32,
19}
20
21#[derive(Clone, Debug, PartialEq)]
22pub struct BlockHit {
23    /// The block that we clicked.
24    pub block_pos: BlockPos,
25    /// The face of the block that was clicked.
26    pub direction: Direction,
27    /// The exact coordinates of the world where the block was clicked.
28    ///
29    /// In the network, this is transmitted as the difference between the
30    /// location and block position.
31    pub location: Vec3,
32    /// Whether the player's head is inside a block.
33    pub inside: bool,
34    /// Whether the player's hitting the world border.
35    pub world_border: bool,
36}
37
38impl AzaleaWrite for BlockHit {
39    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
40        self.block_pos.azalea_write(buf)?;
41        self.direction.azalea_write(buf)?;
42        f32::azalea_write(
43            &((self.location.x - f64::from(self.block_pos.x)) as f32),
44            buf,
45        )?;
46        f32::azalea_write(
47            &((self.location.y - f64::from(self.block_pos.y)) as f32),
48            buf,
49        )?;
50        f32::azalea_write(
51            &((self.location.z - f64::from(self.block_pos.z)) as f32),
52            buf,
53        )?;
54        self.inside.azalea_write(buf)?;
55        self.world_border.azalea_write(buf)?;
56        Ok(())
57    }
58}
59
60impl AzaleaRead for BlockHit {
61    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
62        let block_pos = BlockPos::azalea_read(buf)?;
63        let direction = Direction::azalea_read(buf)?;
64        let cursor_x = f32::azalea_read(buf)?;
65        let cursor_y = f32::azalea_read(buf)?;
66        let cursor_z = f32::azalea_read(buf)?;
67        let inside = bool::azalea_read(buf)?;
68        let world_border = bool::azalea_read(buf)?;
69        Ok(Self {
70            block_pos,
71            direction,
72            location: Vec3 {
73                x: f64::from(block_pos.x) + f64::from(cursor_x),
74                y: f64::from(block_pos.y) + f64::from(cursor_y),
75                z: f64::from(block_pos.z) + f64::from(cursor_z),
76            },
77            inside,
78            world_border,
79        })
80    }
81}
82
83impl From<&BlockHitResult> for BlockHit {
84    /// Converts a [`BlockHitResult`] to a [`BlockHit`].
85    ///
86    /// The only difference is that the `miss` field is not present in
87    /// [`BlockHit`].
88    fn from(hit_result: &BlockHitResult) -> Self {
89        Self {
90            block_pos: hit_result.block_pos,
91            direction: hit_result.direction,
92            location: hit_result.location,
93            inside: hit_result.inside,
94            world_border: hit_result.world_border,
95        }
96    }
97}