valence_server/
interact_entity.rs

1use bevy_app::prelude::*;
2use bevy_ecs::prelude::*;
3use valence_entity::EntityManager;
4pub use valence_protocol::packets::play::player_interact_entity_c2s::EntityInteraction;
5use valence_protocol::packets::play::PlayerInteractEntityC2s;
6
7use crate::event_loop::{EventLoopPreUpdate, PacketEvent};
8
9pub struct InteractEntityPlugin;
10
11impl Plugin for InteractEntityPlugin {
12    fn build(&self, app: &mut App) {
13        app.add_event::<InteractEntityEvent>()
14            .add_systems(EventLoopPreUpdate, handle_interact_entity);
15    }
16}
17
18#[derive(Event, Copy, Clone, Debug)]
19pub struct InteractEntityEvent {
20    pub client: Entity,
21    /// The entity being interacted with.
22    pub entity: Entity,
23    /// If the client was sneaking during the interaction.
24    pub sneaking: bool,
25    /// The kind of interaction that occurred.
26    pub interact: EntityInteraction,
27}
28
29fn handle_interact_entity(
30    mut packets: EventReader<PacketEvent>,
31    entities: Res<EntityManager>,
32    mut events: EventWriter<InteractEntityEvent>,
33) {
34    for packet in packets.read() {
35        if let Some(pkt) = packet.decode::<PlayerInteractEntityC2s>() {
36            // TODO: check that the entity is in the same instance as the player.
37            // TODO: check that the distance between the player and the interacted entity is
38            // within some configurable tolerance level.
39
40            if let Some(entity) = entities.get_by_id(pkt.entity_id.0) {
41                events.send(InteractEntityEvent {
42                    client: packet.client,
43                    entity,
44                    sneaking: pkt.sneaking,
45                    interact: pkt.interact,
46                });
47            }
48        }
49    }
50}