azalea_protocol/packets/game/
c_set_equipment.rs

1use std::io::Cursor;
2
3use azalea_buf::{AzBuf, BufReadError};
4use azalea_buf::{AzaleaRead, AzaleaWrite};
5use azalea_inventory::ItemStack;
6use azalea_protocol_macros::ClientboundGamePacket;
7use azalea_world::MinecraftEntityId;
8
9#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
10pub struct ClientboundSetEquipment {
11    #[var]
12    pub entity_id: MinecraftEntityId,
13    pub slots: EquipmentSlots,
14}
15
16#[derive(Clone, Debug)]
17pub struct EquipmentSlots {
18    pub slots: Vec<(EquipmentSlot, ItemStack)>,
19}
20
21impl AzaleaRead for EquipmentSlots {
22    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
23        let mut slots = vec![];
24
25        loop {
26            let equipment_byte = u8::azalea_read(buf)?;
27            let equipment_slot =
28                EquipmentSlot::from_byte(equipment_byte & 127).ok_or_else(|| {
29                    BufReadError::UnexpectedEnumVariant {
30                        id: equipment_byte.into(),
31                    }
32                })?;
33            let item = ItemStack::azalea_read(buf)?;
34            slots.push((equipment_slot, item));
35            if equipment_byte & 128 == 0 {
36                break;
37            };
38        }
39
40        Ok(EquipmentSlots { slots })
41    }
42}
43impl AzaleaWrite for EquipmentSlots {
44    fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
45        for i in 0..self.slots.len() {
46            let (equipment_slot, item) = &self.slots[i];
47            let mut equipment_byte = *equipment_slot as u8;
48            if i != self.slots.len() - 1 {
49                equipment_byte |= 128;
50            }
51            equipment_byte.azalea_write(buf)?;
52            item.azalea_write(buf)?;
53        }
54
55        Ok(())
56    }
57}
58
59#[derive(Clone, Debug, Copy, AzBuf)]
60pub enum EquipmentSlot {
61    MainHand = 0,
62    OffHand = 1,
63    Feet = 2,
64    Legs = 3,
65    Chest = 4,
66    Head = 5,
67}
68
69impl EquipmentSlot {
70    #[must_use]
71    pub fn from_byte(byte: u8) -> Option<Self> {
72        match byte {
73            0 => Some(EquipmentSlot::MainHand),
74            1 => Some(EquipmentSlot::OffHand),
75            2 => Some(EquipmentSlot::Feet),
76            3 => Some(EquipmentSlot::Legs),
77            4 => Some(EquipmentSlot::Chest),
78            5 => Some(EquipmentSlot::Head),
79            _ => None,
80        }
81    }
82}