azalea_protocol/packets/game/
s_use_item_on.rs

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