valence_equipment/
interaction_broadcast.rs

1use valence_inventory::{HeldItem, Inventory, PlayerAction};
2use valence_server::entity::living::LivingFlags;
3use valence_server::event_loop::PacketEvent;
4use valence_server::interact_item::InteractItemEvent;
5use valence_server::protocol::packets::play::PlayerActionC2s;
6use valence_server::ItemKind;
7
8use super::*;
9
10/// This component will broadcast item interactions (e.g. drawing a bow, eating
11/// food) to other players using `LivingFlags::set_using_item`.
12#[derive(Debug, Default, Clone, Component)]
13pub struct EquipmentInteractionBroadcast;
14
15// Sets flag to true when the client starts interacting with an
16// item.
17pub(crate) fn start_interaction(
18    mut clients: Query<
19        (&Inventory, &HeldItem, &mut LivingFlags),
20        (With<Client>, With<EquipmentInteractionBroadcast>),
21    >,
22    mut events: EventReader<InteractItemEvent>,
23) {
24    for event in events.read() {
25        if let Ok((inv, held_item, mut flags)) = clients.get_mut(event.client) {
26            let item = inv.slot(held_item.slot()).item;
27            let has_arrows = inv.first_slot_with_item(ItemKind::Arrow, i8::MAX).is_some();
28            if (item == ItemKind::Bow && !has_arrows)
29                || (item == ItemKind::Crossbow
30                    && !has_arrows
31                    && inv.slot(45).item != ItemKind::FireworkRocket)
32            {
33                continue;
34            }
35            flags.set_using_item(true);
36        }
37    }
38}
39
40// Sets flag to false when the client stops interacting with an
41// item.
42pub(crate) fn stop_interaction(
43    mut clients: Query<&mut LivingFlags, (With<Client>, With<EquipmentInteractionBroadcast>)>,
44    mut packets: EventReader<PacketEvent>,
45) {
46    for packet in packets.read() {
47        if let Some(pkt) = packet.decode::<PlayerActionC2s>() {
48            if pkt.action == PlayerAction::ReleaseUseItem {
49                if let Ok(mut flags) = clients.get_mut(packet.client) {
50                    flags.set_using_item(false);
51                }
52            }
53        }
54    }
55}