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 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;
46pub(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
114pub 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_ship);
158 self.handle_serial_events(handle_shoot);
159 self.handle_serial_events(handle_throw);
160 self.handle_serial_events(handle_shockwave);
161 self.handle_serial_events(handle_create_special_entity);
162 self.handle_serial_events(handle_create_item_drop);
163 self.handle_serial_events(handle_create_object);
164 self.handle_serial_events(handle_create_aura_entity);
165 self.handle_serial_events(handle_summon_beam_pillars);
166 self.handle_serial_events(handle_delete);
167
168 self.handle_serial_events(handle_character_delete);
169 self.handle_serial_events(|this, ev: ExitIngameEvent| {
170 handle_exit_ingame(this, ev.entity, false)
171 });
172 let mut already_disconnected_clients = HashSet::new();
173 self.handle_serial_events(|this, ev: ClientDisconnectEvent| {
174 if let Some(event) =
175 handle_client_disconnect(this, ev.0, ev.1, false, &mut already_disconnected_clients)
176 {
177 frontend_events.push(event);
178 }
179 });
180 self.handle_serial_events(|this, ev: ClientDisconnectWithoutPersistenceEvent| {
181 if let Some(event) = handle_client_disconnect(
182 this,
183 ev.0,
184 common::comp::DisconnectReason::Kicked,
185 true,
186 &mut already_disconnected_clients,
187 ) {
188 frontend_events.push(event);
189 }
190 });
191 self.handle_serial_events(handle_possess);
192 self.handle_serial_events(handle_transform);
193 self.handle_serial_events(handle_start_interaction);
194 self.handle_serial_events(|this, ev: CommandEvent| {
195 this.process_command(ev.0, ev.1, ev.2);
196 });
197 self.handle_serial_events(|this, ev: ChatEvent| {
198 this.state.send_chat(ev.msg, ev.from_client);
199 });
200 self.handle_serial_events(handle_mount);
201 self.handle_serial_events(handle_tame_pet);
202 self.handle_serial_events(handle_process_trade_action);
203 self.handle_serial_events(handle_set_battle_mode);
204 }
205
206 pub fn handle_events(&mut self) -> Vec<Event> {
207 let mut frontend_events = Vec::new();
208
209 span!(guard, "run event systems");
210 self.event_dispatcher.dispatch(self.state.ecs());
212 drop(guard);
213
214 span!(guard, "handle serial events");
215 self.handle_all_serial_events(&mut frontend_events);
216 drop(guard);
217
218 self.state.maintain_ecs();
219
220 #[cfg(debug_assertions)]
221 {
222 event_types::check_event_handlers(self.state.ecs_mut())
223 }
224
225 frontend_events
226 }
227
228 pub fn create_event_dispatcher(pools: Arc<rayon::ThreadPool>) -> SendDispatcher<'static> {
229 span!(_guard, "create event dispatcher");
230 let mut dispatch_builder = DispatcherBuilder::new().with_pool(pools);
233 register_event_systems(&mut dispatch_builder);
234 dispatch_builder
235 .build()
236 .try_into_sendable()
237 .ok()
238 .expect("This should be sendable")
239 }
240}