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