1use common_net::msg::{ClientType, ServerGeneral, ServerMsg};
2use network::{ConnectAddr, Message, Participant, Stream, StreamError, StreamParams};
3use serde::{Serialize, de::DeserializeOwned};
4use specs::Component;
5use std::{net::SocketAddr, sync::atomic::AtomicBool};
6
7pub struct Client {
14 pub client_type: ClientType,
15 pub participant: Option<Participant>,
16 pub current_ip_addrs: Vec<SocketAddr>,
17 connected_from_addr: ConnectAddr,
18 pub last_ping: f64,
19 pub login_msg_sent: AtomicBool,
20 pub locale: Option<String>,
21
22 general_stream: Stream,
26 ping_stream: Stream,
27 register_stream: Stream,
28 character_screen_stream: Stream,
29 in_game_stream: Stream,
30 terrain_stream: Stream,
31
32 general_stream_params: StreamParams,
33 ping_stream_params: StreamParams,
34 register_stream_params: StreamParams,
35 character_screen_stream_params: StreamParams,
36 in_game_stream_params: StreamParams,
37 terrain_stream_params: StreamParams,
38}
39
40pub struct PreparedMsg {
41 stream_id: u8,
42 message: Message,
43}
44
45impl Component for Client {
46 type Storage = specs::DenseVecStorage<Self>;
47}
48
49impl Client {
50 pub(crate) fn new(
51 client_type: ClientType,
52 participant: Participant,
53 connected_from: ConnectAddr,
54 last_ping: f64,
55 locale: Option<String>,
56 general_stream: Stream,
57 ping_stream: Stream,
58 register_stream: Stream,
59 character_screen_stream: Stream,
60 in_game_stream: Stream,
61 terrain_stream: Stream,
62 ) -> Self {
63 let general_stream_params = general_stream.params();
64 let ping_stream_params = ping_stream.params();
65 let register_stream_params = register_stream.params();
66 let character_screen_stream_params = character_screen_stream.params();
67 let in_game_stream_params = in_game_stream.params();
68 let terrain_stream_params = terrain_stream.params();
69 Client {
70 client_type,
71 participant: Some(participant),
72 current_ip_addrs: connected_from.socket_addr().into_iter().collect(),
73 connected_from_addr: connected_from,
74 last_ping,
75 locale,
76 login_msg_sent: AtomicBool::new(false),
77 general_stream,
78 ping_stream,
79 register_stream,
80 character_screen_stream,
81 in_game_stream,
82 terrain_stream,
83 general_stream_params,
84 ping_stream_params,
85 register_stream_params,
86 character_screen_stream_params,
87 in_game_stream_params,
88 terrain_stream_params,
89 }
90 }
91
92 pub(crate) fn connected_from_addr(&self) -> &ConnectAddr { &self.connected_from_addr }
93
94 pub(crate) fn send<M: Into<ServerMsg>>(&self, msg: M) -> Result<(), StreamError> {
95 let prepared = self.prepare(msg);
98 self.send_prepared(&prepared)
99 }
153
154 pub(crate) fn send_fallible<M: Into<ServerMsg>>(&self, msg: M) { let _ = self.send(msg); }
156
157 pub(crate) fn send_prepared(&self, msg: &PreparedMsg) -> Result<(), StreamError> {
158 match msg.stream_id {
159 0 => self.register_stream.send_raw(&msg.message),
160 1 => self.character_screen_stream.send_raw(&msg.message),
161 2 => self.in_game_stream.send_raw(&msg.message),
162 3 => self.general_stream.send_raw(&msg.message),
163 4 => self.ping_stream.send_raw(&msg.message),
164 5 => self.terrain_stream.send_raw(&msg.message),
165 _ => unreachable!("invalid stream id"),
166 }
167 }
168
169 pub(crate) fn prepare<M: Into<ServerMsg>>(&self, msg: M) -> PreparedMsg {
170 match msg.into() {
171 ServerMsg::Info(m) => PreparedMsg::new(0, &m, &self.register_stream_params),
172 ServerMsg::Init(m) => PreparedMsg::new(0, &m, &self.register_stream_params),
173 ServerMsg::RegisterAnswer(m) => PreparedMsg::new(0, &m, &self.register_stream_params),
174 ServerMsg::General(g) => {
175 match g {
176 ServerGeneral::CharacterDataLoadResult(_)
178 | ServerGeneral::CharacterListUpdate(_)
179 | ServerGeneral::CharacterActionError(_)
180 | ServerGeneral::CharacterCreated(_)
181 | ServerGeneral::CharacterEdited(_)
182 | ServerGeneral::CharacterSuccess
183 | ServerGeneral::SpectatorSuccess(_) => {
184 PreparedMsg::new(1, &g, &self.character_screen_stream_params)
185 },
186 ServerGeneral::GroupUpdate(_)
188 | ServerGeneral::Invite { .. }
189 | ServerGeneral::InvitePending(_)
190 | ServerGeneral::InviteComplete { .. }
191 | ServerGeneral::ExitInGameSuccess
192 | ServerGeneral::InventoryUpdate(_, _)
193 | ServerGeneral::GroupInventoryUpdate(_, _)
194 | ServerGeneral::Dialogue(_, _)
195 | ServerGeneral::SetViewDistance(_)
196 | ServerGeneral::Outcomes(_)
197 | ServerGeneral::Knockback(_)
198 | ServerGeneral::SiteEconomy(_)
199 | ServerGeneral::UpdatePendingTrade(_, _, _)
200 | ServerGeneral::FinishedTrade(_)
201 | ServerGeneral::MapMarker(_)
202 | ServerGeneral::WeatherUpdate(_)
203 | ServerGeneral::LocalWindUpdate(_)
204 | ServerGeneral::SpectatePosition(_)
205 | ServerGeneral::UpdateRecipes
206 | ServerGeneral::Gizmos(_) => {
207 PreparedMsg::new(2, &g, &self.in_game_stream_params)
208 },
209 ServerGeneral::TerrainChunkUpdate { .. }
211 | ServerGeneral::LodZoneUpdate { .. }
212 | ServerGeneral::TerrainBlockUpdates(_) => {
213 PreparedMsg::new(5, &g, &self.terrain_stream_params)
214 },
215 ServerGeneral::PlayerListUpdate(_)
217 | ServerGeneral::ChatMsg(_)
218 | ServerGeneral::ChatMode(_)
219 | ServerGeneral::SetPlayerEntity(_)
220 | ServerGeneral::TimeOfDay(_, _, _, _)
221 | ServerGeneral::EntitySync(_)
222 | ServerGeneral::CompSync(_, _)
223 | ServerGeneral::CreateEntity(_)
224 | ServerGeneral::DeleteEntity(_)
225 | ServerGeneral::Disconnect(_)
226 | ServerGeneral::Notification(_)
227 | ServerGeneral::SetPlayerRole(_)
228 | ServerGeneral::PluginData(_) => {
229 PreparedMsg::new(3, &g, &self.general_stream_params)
230 },
231 }
232 },
233 ServerMsg::Ping(m) => PreparedMsg::new(4, &m, &self.ping_stream_params),
234 }
235 }
236
237 pub(crate) fn terrain_params(&self) -> StreamParams { self.terrain_stream_params.clone() }
238
239 pub(crate) fn prepare_chunk_update_msg(
242 terrain_chunk_update: ServerGeneral,
243 params: &StreamParams,
244 ) -> PreparedMsg {
245 if !matches!(
246 terrain_chunk_update,
247 ServerGeneral::TerrainChunkUpdate { .. }
248 ) {
249 unreachable!("You must not call this function without a terrain chunk update!")
250 }
251 PreparedMsg::new(5, &terrain_chunk_update, params)
252 }
253
254 pub(crate) fn recv<M: DeserializeOwned>(
255 &mut self,
256 stream_id: u8,
257 ) -> Result<Option<M>, StreamError> {
258 match stream_id {
260 0 => self.register_stream.try_recv(),
261 1 => self.character_screen_stream.try_recv(),
262 2 => self.in_game_stream.try_recv(),
263 3 => self.general_stream.try_recv(),
264 4 => self.ping_stream.try_recv(),
265 5 => self.terrain_stream.try_recv(),
266 _ => unreachable!("invalid stream id"),
267 }
268 }
269}
270
271impl PreparedMsg {
272 fn new<M: Serialize + ?Sized>(id: u8, msg: &M, stream_params: &StreamParams) -> PreparedMsg {
273 Self {
274 stream_id: id,
275 message: Message::serialize(&msg, stream_params.clone()),
276 }
277 }
278}