veloren_server/events/
mod.rs

1use std::{marker::PhantomData, sync::Arc};
2
3use crate::{Server, events::entity_creation::handle_create_npc_group, state_ext::StateExt};
4use common::event::{
5    ChatEvent, ClientDisconnectEvent, ClientDisconnectWithoutPersistenceEvent, CommandEvent,
6    EventBus, ExitIngameEvent,
7};
8use common_base::span;
9use entity_creation::handle_summon_beam_pillars;
10use hashbrown::HashSet;
11use player::handle_set_battle_mode;
12use specs::{
13    DispatcherBuilder, Entity as EcsEntity, ReadExpect, WorldExt, WriteExpect,
14    shred::SendDispatcher,
15};
16
17use self::{
18    entity_creation::{
19        handle_create_aura_entity, handle_create_item_drop, handle_create_npc,
20        handle_create_object, handle_create_ship, handle_create_special_entity,
21        handle_initialize_character, handle_initialize_spectator, handle_loaded_character_data,
22        handle_shockwave, handle_shoot, handle_throw,
23    },
24    entity_manipulation::{handle_delete, handle_start_interaction, handle_transform},
25    interaction::handle_tame_pet,
26    mounting::handle_mount,
27    player::{
28        handle_character_delete, handle_client_disconnect, handle_exit_ingame, handle_possess,
29    },
30    trade::handle_process_trade_action,
31};
32
33mod entity_creation;
34mod entity_manipulation;
35mod event_types;
36mod group_manip;
37mod information;
38mod interaction;
39mod inventory_manip;
40mod invite;
41mod mounting;
42mod player;
43mod trade;
44
45pub(crate) use event_types::register_event_busses;
46/// Shared utilities used by other code **in this crate**
47pub(crate) mod shared {
48    pub(crate) use super::{
49        entity_manipulation::{TransformEntityError, transform_entity},
50        group_manip::update_map_markers,
51        trade::cancel_trades_for,
52    };
53}
54
55pub trait ServerEvent: Send + Sync + 'static {
56    type SystemData<'a>: specs::SystemData<'a>;
57
58    const NAME: &'static str = std::any::type_name::<Self>();
59
60    fn handle(events: impl ExactSizeIterator<Item = Self>, data: Self::SystemData<'_>);
61}
62
63struct EventHandler<T>(PhantomData<T>);
64impl<T> Default for EventHandler<T> {
65    fn default() -> Self { Self(PhantomData) }
66}
67
68impl<'a, T: ServerEvent> common_ecs::System<'a> for EventHandler<T> {
69    type SystemData = (
70        ReadExpect<'a, crate::metrics::ServerEventMetrics>,
71        WriteExpect<'a, EventBus<T>>,
72        T::SystemData<'a>,
73    );
74
75    const NAME: &'static str = T::NAME;
76    const ORIGIN: common_ecs::Origin = common_ecs::Origin::Server;
77    const PHASE: common_ecs::Phase = common_ecs::Phase::Apply;
78
79    fn run(_job: &mut common_ecs::Job<Self>, (metrics, mut ev, data): Self::SystemData) {
80        span!(guard, "Recv events");
81        let events = ev.recv_all_mut();
82        drop(guard);
83
84        span!(guard, "Add metrics for event");
85        metrics
86            .event_count
87            .with_label_values(&[T::NAME])
88            .inc_by(events.len() as u64);
89        drop(guard);
90
91        span!(guard, "Handle events");
92        T::handle(events, data);
93        drop(guard);
94    }
95}
96
97fn event_dispatch<T: ServerEvent>(builder: &mut DispatcherBuilder, dependencies: &[&str]) {
98    common_ecs::dispatch::<EventHandler<T>>(builder, dependencies);
99}
100
101fn event_sys_name<T: ServerEvent>() -> String {
102    <EventHandler<T> as common_ecs::System>::sys_name()
103}
104
105pub fn register_event_systems(builder: &mut DispatcherBuilder) {
106    inventory_manip::register_event_systems(builder);
107    entity_manipulation::register_event_systems(builder);
108    interaction::register_event_systems(builder);
109    invite::register_event_systems(builder);
110    group_manip::register_event_systems(builder);
111    information::register_event_systems(builder);
112}
113
114/// Server frontend events.
115///
116/// These events are returned to the frontend that ticks the server.
117pub enum Event {
118    ClientConnected {
119        entity: EcsEntity,
120    },
121    ClientDisconnected {
122        entity: EcsEntity,
123    },
124    Chat {
125        entity: Option<EcsEntity>,
126        msg: String,
127    },
128}
129
130impl Server {
131    fn handle_serial_events<T: Send + 'static, F: FnMut(&mut Self, T)>(&mut self, mut f: F) {
132        if let Some(bus) = self.state.ecs_mut().get_mut::<EventBus<T>>() {
133            let events = bus.recv_all_mut();
134            let server_event_metrics = self
135                .state
136                .ecs()
137                .read_resource::<crate::metrics::ServerEventMetrics>();
138            server_event_metrics
139                .event_count
140                .with_label_values(&[std::any::type_name::<T>()])
141                .inc_by(events.len() as u64);
142            drop(server_event_metrics);
143
144            for ev in events {
145                f(self, ev)
146            }
147        }
148    }
149
150    fn handle_all_serial_events(&mut self, frontend_events: &mut Vec<Event>) {
151        self.handle_serial_events(handle_initialize_character);
152        self.handle_serial_events(handle_initialize_spectator);
153        self.handle_serial_events(handle_loaded_character_data);
154        self.handle_serial_events(|this, ev| {
155            handle_create_npc(this, ev);
156        });
157        self.handle_serial_events(handle_create_npc_group);
158        self.handle_serial_events(handle_create_ship);
159        self.handle_serial_events(handle_shoot);
160        self.handle_serial_events(handle_throw);
161        self.handle_serial_events(handle_shockwave);
162        self.handle_serial_events(handle_create_special_entity);
163        self.handle_serial_events(handle_create_item_drop);
164        self.handle_serial_events(handle_create_object);
165        self.handle_serial_events(handle_create_aura_entity);
166        self.handle_serial_events(handle_summon_beam_pillars);
167        self.handle_serial_events(handle_delete);
168
169        self.handle_serial_events(handle_character_delete);
170        self.handle_serial_events(|this, ev: ExitIngameEvent| {
171            handle_exit_ingame(this, ev.entity, false)
172        });
173        let mut already_disconnected_clients = HashSet::new();
174        self.handle_serial_events(|this, ev: ClientDisconnectEvent| {
175            if let Some(event) =
176                handle_client_disconnect(this, ev.0, ev.1, false, &mut already_disconnected_clients)
177            {
178                frontend_events.push(event);
179            }
180        });
181        self.handle_serial_events(|this, ev: ClientDisconnectWithoutPersistenceEvent| {
182            if let Some(event) = handle_client_disconnect(
183                this,
184                ev.0,
185                common::comp::DisconnectReason::Kicked,
186                true,
187                &mut already_disconnected_clients,
188            ) {
189                frontend_events.push(event);
190            }
191        });
192        self.handle_serial_events(handle_possess);
193        self.handle_serial_events(handle_transform);
194        self.handle_serial_events(handle_start_interaction);
195        self.handle_serial_events(|this, ev: CommandEvent| {
196            this.process_command(ev.0, ev.1, ev.2);
197        });
198        self.handle_serial_events(|this, ev: ChatEvent| {
199            this.state.send_chat(ev.msg, ev.from_client);
200        });
201        self.handle_serial_events(handle_mount);
202        self.handle_serial_events(handle_tame_pet);
203        self.handle_serial_events(handle_process_trade_action);
204        self.handle_serial_events(handle_set_battle_mode);
205    }
206
207    pub fn handle_events(&mut self) -> Vec<Event> {
208        let mut frontend_events = Vec::new();
209
210        span!(guard, "run event systems");
211        // This dispatches all the systems in parallel.
212        self.event_dispatcher.dispatch(self.state.ecs());
213        drop(guard);
214
215        span!(guard, "handle serial events");
216        self.handle_all_serial_events(&mut frontend_events);
217        drop(guard);
218
219        self.state.maintain_ecs();
220
221        #[cfg(debug_assertions)]
222        {
223            event_types::check_event_handlers(self.state.ecs_mut())
224        }
225
226        frontend_events
227    }
228
229    pub fn create_event_dispatcher(pools: Arc<rayon::ThreadPool>) -> SendDispatcher<'static> {
230        span!(_guard, "create event dispatcher");
231        // Run systems to handle events.
232        // Create and run a dispatcher for ecs systems.
233        let mut dispatch_builder = DispatcherBuilder::new().with_pool(pools);
234        register_event_systems(&mut dispatch_builder);
235        dispatch_builder
236            .build()
237            .try_into_sendable()
238            .ok()
239            .expect("This should be sendable")
240    }
241}