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