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 PreparedMsg::new(2, &g, &self.in_game_stream_params)
207 },
208 ServerGeneral::TerrainChunkUpdate { .. }
210 | ServerGeneral::LodZoneUpdate { .. }
211 | ServerGeneral::TerrainBlockUpdates(_) => {
212 PreparedMsg::new(5, &g, &self.terrain_stream_params)
213 },
214 ServerGeneral::PlayerListUpdate(_)
216 | ServerGeneral::ChatMsg(_)
217 | ServerGeneral::ChatMode(_)
218 | ServerGeneral::SetPlayerEntity(_)
219 | ServerGeneral::TimeOfDay(_, _, _, _)
220 | ServerGeneral::EntitySync(_)
221 | ServerGeneral::CompSync(_, _)
222 | ServerGeneral::CreateEntity(_)
223 | ServerGeneral::DeleteEntity(_)
224 | ServerGeneral::Disconnect(_)
225 | ServerGeneral::Notification(_)
226 | ServerGeneral::SetPlayerRole(_)
227 | ServerGeneral::PluginData(_) => {
228 PreparedMsg::new(3, &g, &self.general_stream_params)
229 },
230 }
231 },
232 ServerMsg::Ping(m) => PreparedMsg::new(4, &m, &self.ping_stream_params),
233 }
234 }
235
236 pub(crate) fn terrain_params(&self) -> StreamParams { self.terrain_stream_params.clone() }
237
238 pub(crate) fn prepare_chunk_update_msg(
241 terrain_chunk_update: ServerGeneral,
242 params: &StreamParams,
243 ) -> PreparedMsg {
244 if !matches!(
245 terrain_chunk_update,
246 ServerGeneral::TerrainChunkUpdate { .. }
247 ) {
248 unreachable!("You must not call this function without a terrain chunk update!")
249 }
250 PreparedMsg::new(5, &terrain_chunk_update, params)
251 }
252
253 pub(crate) fn recv<M: DeserializeOwned>(
254 &mut self,
255 stream_id: u8,
256 ) -> Result<Option<M>, StreamError> {
257 match stream_id {
259 0 => self.register_stream.try_recv(),
260 1 => self.character_screen_stream.try_recv(),
261 2 => self.in_game_stream.try_recv(),
262 3 => self.general_stream.try_recv(),
263 4 => self.ping_stream.try_recv(),
264 5 => self.terrain_stream.try_recv(),
265 _ => unreachable!("invalid stream id"),
266 }
267 }
268}
269
270impl PreparedMsg {
271 fn new<M: Serialize + ?Sized>(id: u8, msg: &M, stream_params: &StreamParams) -> PreparedMsg {
272 Self {
273 stream_id: id,
274 message: Message::serialize(&msg, stream_params.clone()),
275 }
276 }
277}