1 use std::{ |
1 use std::{ |
2 io, io::Write |
2 io, io::Write |
3 }; |
3 }; |
4 use super::{ |
4 use super::{ |
5 server::HWServer, |
5 server::HWServer, |
6 client::ClientId, |
6 room::RoomId, |
|
7 client::{ClientId, HWClient}, |
7 room::HWRoom, |
8 room::HWRoom, |
8 handlers |
9 handlers |
9 }; |
10 }; |
10 use protocol::messages::{ |
11 use protocol::messages::{ |
11 HWProtocolMessage, |
12 HWProtocolMessage, |
12 HWServerMessage, |
13 HWServerMessage, |
13 HWServerMessage::* |
14 HWServerMessage::* |
14 }; |
15 }; |
15 |
16 |
|
17 pub enum Destination { |
|
18 ToSelf, |
|
19 ToAll { |
|
20 room_id: Option<RoomId>, |
|
21 protocol: Option<u32>, |
|
22 skip_self: bool |
|
23 } |
|
24 } |
|
25 |
|
26 pub struct PendingMessage { |
|
27 pub destination: Destination, |
|
28 pub message: HWServerMessage |
|
29 } |
|
30 |
|
31 impl PendingMessage { |
|
32 pub fn send_self(message: HWServerMessage) -> PendingMessage { |
|
33 PendingMessage{ destination: Destination::ToSelf, message } |
|
34 } |
|
35 |
|
36 pub fn send_all(message: HWServerMessage) -> PendingMessage { |
|
37 let destination = Destination::ToAll { |
|
38 room_id: None, |
|
39 protocol: None, |
|
40 skip_self: false, |
|
41 }; |
|
42 PendingMessage{ destination, message } |
|
43 } |
|
44 |
|
45 pub fn in_room(mut self, clients_room_id: RoomId) -> PendingMessage { |
|
46 if let Destination::ToAll {ref mut room_id, ..} = self.destination { |
|
47 *room_id = Some(clients_room_id) |
|
48 } |
|
49 self |
|
50 } |
|
51 |
|
52 pub fn with_protocol(mut self, protocol_number: u32) -> PendingMessage { |
|
53 if let Destination::ToAll {ref mut protocol, ..} = self.destination { |
|
54 *protocol = Some(protocol_number) |
|
55 } |
|
56 self |
|
57 } |
|
58 |
|
59 pub fn but_self(mut self) -> PendingMessage { |
|
60 if let Destination::ToAll {ref mut skip_self, ..} = self.destination { |
|
61 *skip_self = true |
|
62 } |
|
63 self |
|
64 } |
|
65 |
|
66 pub fn action(self) -> Action { Send(self) } |
|
67 } |
|
68 |
|
69 impl Into<Action> for PendingMessage { |
|
70 fn into(self) -> Action { self.action() } |
|
71 } |
|
72 |
|
73 impl HWServerMessage { |
|
74 pub fn send_self(self) -> PendingMessage { PendingMessage::send_self(self) } |
|
75 pub fn send_all(self) -> PendingMessage { PendingMessage::send_all(self) } |
|
76 } |
|
77 |
16 pub enum Action { |
78 pub enum Action { |
17 SendAll(HWServerMessage), |
79 Send(PendingMessage), |
18 SendMe(HWServerMessage), |
|
19 SendAllButMe(HWServerMessage), |
|
20 SendToSelected(Vec<ClientId>, HWServerMessage), |
|
21 RemoveClient, |
80 RemoveClient, |
22 ByeClient(String), |
81 ByeClient(String), |
23 ReactProtocolMessage(HWProtocolMessage), |
82 ReactProtocolMessage(HWProtocolMessage), |
24 CheckRegistered, |
83 CheckRegistered, |
25 JoinLobby, |
84 JoinLobby, |
26 AddRoom(String, Option<String>), |
85 AddRoom(String, Option<String>), |
27 RemoveRoom(RoomId), |
86 RemoveRoom(RoomId), |
28 MoveToRoom(RoomId), |
87 MoveToRoom(RoomId), |
29 MoveToLobby(String), |
88 MoveToLobby(String), |
30 ChangeMaster(RoomId, Option<ClientId>), |
89 ChangeMaster(RoomId, Option<ClientId>), |
|
90 RemoveTeam(String), |
|
91 RemoveClientTeams, |
31 SendRoomUpdate(Option<String>), |
92 SendRoomUpdate(Option<String>), |
32 Warn(String), |
93 Warn(String), |
33 ProtocolError(String) |
94 ProtocolError(String) |
34 } |
95 } |
35 |
96 |
36 use self::Action::*; |
97 use self::Action::*; |
37 use server::room::RoomId; |
98 |
38 |
99 pub fn run_action(server: &mut HWServer, client_id: usize, action: Action) { |
39 pub fn run_action(server: &mut HWServer, token: usize, action: Action) { |
|
40 match action { |
100 match action { |
41 SendAll(msg) => |
101 Send(msg) => server.send(client_id, msg.destination, msg.message), |
42 server.send_all(msg), |
|
43 SendMe(msg) => |
|
44 server.send_self(token, msg), |
|
45 SendAllButMe(msg) => |
|
46 server.send_others(token, msg), |
|
47 SendToSelected(client_ids, msg) => |
|
48 server.send_to_selected(client_ids, msg), |
|
49 ByeClient(msg) => { |
102 ByeClient(msg) => { |
50 let room_id; |
103 let room_id; |
51 let nick; |
104 let nick; |
52 { |
105 { |
53 let c = &server.clients[token]; |
106 let c = &server.clients[client_id]; |
54 room_id = c.room_id; |
107 room_id = c.room_id; |
55 nick = c.nick.clone(); |
108 nick = c.nick.clone(); |
56 } |
109 } |
57 |
110 |
58 let action = room_id.map (|id| { |
111 room_id.map (|id| { |
59 if id == server.lobby_id { |
112 if id != server.lobby_id { |
60 SendAll(LobbyLeft(nick, msg.clone())) |
113 server.react(client_id, vec![ |
61 } else { |
114 MoveToLobby(format!("quit: {}", msg.clone()))]); |
62 MoveToLobby(format!("quit: {}", msg.clone())) |
|
63 } |
115 } |
64 }); |
116 }); |
65 |
117 |
66 if let Some(action) = action { |
118 server.react(client_id, vec![ |
67 server.react(token, vec![action]); |
119 LobbyLeft(nick, msg.clone()).send_all().action(), |
68 } |
120 Bye(msg).send_self().action(), |
69 |
|
70 server.react(token, vec![ |
|
71 SendMe(Bye(msg)), |
|
72 RemoveClient]); |
121 RemoveClient]); |
73 }, |
122 }, |
74 RemoveClient => { |
123 RemoveClient => { |
75 server.removed_clients.push(token); |
124 server.removed_clients.push(client_id); |
76 if server.clients.contains(token) { |
125 if server.clients.contains(client_id) { |
77 server.clients.remove(token); |
126 server.clients.remove(client_id); |
78 } |
127 } |
79 }, |
128 }, |
80 ReactProtocolMessage(msg) => |
129 ReactProtocolMessage(msg) => |
81 handlers::handle(server, token, msg), |
130 handlers::handle(server, client_id, msg), |
82 CheckRegistered => |
131 CheckRegistered => |
83 if server.clients[token].protocol_number > 0 && server.clients[token].nick != "" { |
132 if server.clients[client_id].protocol_number > 0 && server.clients[client_id].nick != "" { |
84 server.react(token, vec![ |
133 server.react(client_id, vec![ |
85 JoinLobby, |
134 JoinLobby, |
86 ]); |
135 ]); |
87 }, |
136 }, |
88 JoinLobby => { |
137 JoinLobby => { |
89 server.clients[token].room_id = Some(server.lobby_id); |
138 server.clients[client_id].room_id = Some(server.lobby_id); |
90 |
139 |
91 let joined_msg; |
140 let joined_msg; |
92 { |
141 { |
93 let mut lobby_nicks = Vec::new(); |
142 let mut lobby_nicks = Vec::new(); |
94 for (_, c) in server.clients.iter() { |
143 for (_, c) in server.clients.iter() { |
109 let rooms_msg = Rooms(server.rooms.iter() |
158 let rooms_msg = Rooms(server.rooms.iter() |
110 .filter(|(id, _)| *id != server.lobby_id) |
159 .filter(|(id, _)| *id != server.lobby_id) |
111 .flat_map(|(_, r)| |
160 .flat_map(|(_, r)| |
112 r.info(r.master_id.map(|id| &server.clients[id]))) |
161 r.info(r.master_id.map(|id| &server.clients[id]))) |
113 .collect()); |
162 .collect()); |
114 server.react(token, vec![ |
163 server.react(client_id, vec![ |
115 SendAllButMe(everyone_msg), |
164 everyone_msg.send_all().but_self().action(), |
116 SendMe(joined_msg), |
165 joined_msg.send_self().action(), |
117 SendMe(flags_msg), |
166 flags_msg.send_self().action(), |
118 SendMe(server_msg), |
167 server_msg.send_self().action(), |
119 SendMe(rooms_msg), |
168 rooms_msg.send_self().action(), |
120 ]); |
169 ]); |
121 }, |
170 }, |
122 AddRoom(name, password) => { |
171 AddRoom(name, password) => { |
123 let room_protocol; |
|
124 let room_info; |
|
125 let room_id = server.add_room();; |
172 let room_id = server.add_room();; |
126 { |
173 let actions = { |
127 let r = &mut server.rooms[room_id]; |
174 let r = &mut server.rooms[room_id]; |
128 let c = &mut server.clients[token]; |
175 let c = &mut server.clients[client_id]; |
129 r.master_id = Some(c.id); |
176 r.master_id = Some(c.id); |
130 r.name = name; |
177 r.name = name; |
131 r.password = password; |
178 r.password = password; |
132 r.protocol_number = c.protocol_number; |
179 r.protocol_number = c.protocol_number; |
133 |
180 |
134 room_protocol = r.protocol_number; |
181 vec![ |
135 room_info = r.info(Some(&c)); |
182 RoomAdd(r.info(Some(&c))).send_all() |
136 } |
183 .with_protocol(r.protocol_number).action(), |
137 let protocol_client_ids = server.protocol_clients(room_protocol); |
184 MoveToRoom(room_id)] |
138 server.react(token, vec![ |
185 }; |
139 SendToSelected(protocol_client_ids, RoomAdd(room_info)), |
186 server.react(client_id, actions); |
140 MoveToRoom(room_id)]); |
|
141 }, |
187 }, |
142 RemoveRoom(room_id) => { |
188 RemoveRoom(room_id) => { |
143 let room_protocol; |
189 let actions = { |
144 let room_name; |
|
145 { |
|
146 let r = &mut server.rooms[room_id]; |
190 let r = &mut server.rooms[room_id]; |
147 room_protocol = r.protocol_number; |
191 vec![RoomRemove(r.name.clone()).send_all() |
148 room_name = r.name.clone(); |
192 .with_protocol(r.protocol_number).action()] |
149 } |
193 }; |
150 server.rooms.remove(room_id); |
194 server.rooms.remove(room_id); |
151 let protocol_client_ids = server.protocol_clients(room_protocol); |
195 server.react(client_id, actions); |
152 server.react(token, vec![ |
|
153 SendToSelected(protocol_client_ids, RoomRemove(room_name))]); |
|
154 } |
196 } |
155 MoveToRoom(room_id) => { |
197 MoveToRoom(room_id) => { |
156 let flags_msg; |
198 let actions = { |
157 let nick; |
|
158 { |
|
159 let r = &mut server.rooms[room_id]; |
199 let r = &mut server.rooms[room_id]; |
160 let c = &mut server.clients[token]; |
200 let c = &mut server.clients[client_id]; |
161 r.players_number += 1; |
201 r.players_number += 1; |
162 c.room_id = Some(room_id); |
202 c.room_id = Some(room_id); |
163 c.is_joined_mid_game = false; |
203 c.is_joined_mid_game = false; |
164 if r.master_id == Some(c.id) { |
204 if r.master_id == Some(c.id) { |
165 r.ready_players_number += 1; |
205 r.ready_players_number += 1; |
167 c.is_ready = true; |
207 c.is_ready = true; |
168 } else { |
208 } else { |
169 c.is_ready = false; |
209 c.is_ready = false; |
170 c.is_master = false; |
210 c.is_master = false; |
171 } |
211 } |
172 flags_msg = ClientFlags("+i".to_string(), vec![c.nick.clone()]); |
212 let flags_msg = ClientFlags("+i".to_string(), vec![c.nick.clone()]); |
173 nick = c.nick.clone(); |
213 |
174 } |
214 vec![RoomJoined(vec![c.nick.clone()]).send_all().in_room(room_id).action(), |
175 let rooms_client_ids = server.room_clients(room_id); |
215 flags_msg.send_all().action(), |
176 server.react(token, vec![ |
216 SendRoomUpdate(None)] |
177 SendToSelected(rooms_client_ids, RoomJoined(vec![nick])), |
217 }; |
178 SendAll(flags_msg), |
218 server.react(client_id, actions); |
179 SendRoomUpdate(None)]); |
|
180 }, |
219 }, |
181 MoveToLobby(msg) => { |
220 MoveToLobby(msg) => { |
182 let mut actions = Vec::new(); |
221 let mut actions = Vec::new(); |
183 let other_client_ids = server.other_clients_in_room(token); |
|
184 let lobby_id = server.lobby_id; |
222 let lobby_id = server.lobby_id; |
185 if let (c, Some(r)) = server.client_and_room(token) { |
223 if let (c, Some(r)) = server.client_and_room(client_id) { |
186 r.players_number -= 1; |
224 r.players_number -= 1; |
187 if c.is_ready { |
225 if c.is_ready { |
188 r.ready_players_number -= 1; |
226 r.ready_players_number -= 1; |
189 } |
227 } |
190 if r.players_number > 0 && c.is_master { |
228 if r.players_number > 0 && c.is_master { |
191 actions.push(ChangeMaster(r.id, None)); |
229 actions.push(ChangeMaster(r.id, None)); |
192 } |
230 } |
193 actions.push(SendToSelected(other_client_ids, RoomLeft(c.nick.clone(), msg))); |
231 actions.push(RemoveClientTeams); |
194 actions.push(SendAll(ClientFlags("-i".to_string(), vec![c.nick.clone()]))); |
232 actions.push(RoomLeft(c.nick.clone(), msg) |
|
233 .send_all().in_room(r.id).but_self().action()); |
|
234 actions.push(ClientFlags("-i".to_string(), vec![c.nick.clone()]) |
|
235 .send_all().action()); |
195 actions.push(SendRoomUpdate(Some(r.name.clone()))); |
236 actions.push(SendRoomUpdate(Some(r.name.clone()))); |
196 } |
237 } |
197 server.react(token, actions); |
238 server.react(client_id, actions); |
198 actions = Vec::new(); |
239 actions = Vec::new(); |
199 |
240 |
200 if let (c, Some(r)) = server.client_and_room(token) { |
241 if let (c, Some(r)) = server.client_and_room(client_id) { |
201 c.room_id = Some(lobby_id); |
242 c.room_id = Some(lobby_id); |
202 if r.players_number == 0 { |
243 if r.players_number == 0 { |
203 actions.push(RemoveRoom(r.id)); |
244 actions.push(RemoveRoom(r.id)); |
204 } |
245 } |
205 } |
246 } |
206 server.react(token, actions) |
247 server.react(client_id, actions) |
207 } |
248 } |
208 ChangeMaster(room_id, new_id) => { |
249 ChangeMaster(room_id, new_id) => { |
209 let mut actions = Vec::new(); |
250 let mut actions = Vec::new(); |
210 let room_client_ids = server.room_clients(room_id); |
251 let room_client_ids = server.room_clients(room_id); |
211 let new_id = new_id.or_else(|| |
252 let new_id = new_id.or_else(|| |
212 room_client_ids.iter().find(|id| **id != token).map(|id| *id)); |
253 room_client_ids.iter().find(|id| **id != client_id).map(|id| *id)); |
213 let new_nick = new_id.map(|id| server.clients[id].nick.clone()); |
254 let new_nick = new_id.map(|id| server.clients[id].nick.clone()); |
214 |
255 |
215 if let (c, Some(r)) = server.client_and_room(token) { |
256 if let (c, Some(r)) = server.client_and_room(client_id) { |
216 if let Some(id) = r.master_id { |
257 match r.master_id { |
217 c.is_master = false; |
258 Some(id) if id == c.id => { |
218 r.master_id = None; |
259 c.is_master = false; |
219 actions.push(SendToSelected(room_client_ids.clone(), ClientFlags("-h".to_string(), vec![c.nick.clone()]))); |
260 r.master_id = None; |
|
261 actions.push(ClientFlags("-h".to_string(), vec![c.nick.clone()]) |
|
262 .send_all().in_room(r.id).action()); |
|
263 } |
|
264 Some(_) => unreachable!(), |
|
265 None => {} |
220 } |
266 } |
221 r.master_id = new_id; |
267 r.master_id = new_id; |
222 if let Some(nick) = new_nick { |
268 if let Some(nick) = new_nick { |
223 actions.push(SendToSelected(room_client_ids, ClientFlags("+h".to_string(), vec![nick]))); |
269 actions.push(ClientFlags("+h".to_string(), vec![nick]) |
|
270 .send_all().in_room(r.id).action()); |
224 } |
271 } |
225 } |
272 } |
226 new_id.map(|id| server.clients[id].is_master = true); |
273 new_id.map(|id| server.clients[id].is_master = true); |
227 server.react(token, actions); |
274 server.react(client_id, actions); |
|
275 } |
|
276 RemoveTeam(name) => { |
|
277 let actions = if let (c, Some(r)) = server.client_and_room(client_id) { |
|
278 r.remove_team(&name); |
|
279 vec![TeamRemove(name).send_all().in_room(r.id).action(), |
|
280 SendRoomUpdate(None)] |
|
281 } else { |
|
282 Vec::new() |
|
283 }; |
|
284 server.react(client_id, actions); |
|
285 }, |
|
286 RemoveClientTeams => { |
|
287 let actions = if let (c, Some(r)) = server.client_and_room(client_id) { |
|
288 r.client_teams(c.id).map(|t| RemoveTeam(t.name.clone())).collect() |
|
289 } else { |
|
290 Vec::new() |
|
291 }; |
|
292 server.react(client_id, actions); |
228 } |
293 } |
229 SendRoomUpdate(old_name) => { |
294 SendRoomUpdate(old_name) => { |
230 let room_data = |
295 let actions = if let (c, Some(r)) = server.client_and_room(client_id) { |
231 if let (c, Some(r)) = server.client_and_room(token) { |
296 let name = old_name.unwrap_or_else(|| r.name.clone()); |
232 let name = old_name.unwrap_or_else(|| r.name.clone()); |
297 vec![RoomUpdated(name, r.info(Some(&c))) |
233 Some((name, r.protocol_number, r.info(Some(&c)))) |
298 .send_all().with_protocol(r.protocol_number).action()] |
234 } else { |
299 } else { |
235 None |
300 Vec::new() |
236 }; |
301 }; |
237 |
302 server.react(client_id, actions); |
238 if let Some((room_name, protocol, room_info)) = room_data { |
|
239 let protocol_clients = server.protocol_clients(protocol); |
|
240 server.react(token, |
|
241 vec![SendToSelected(protocol_clients, RoomUpdated(room_name, room_info))]); |
|
242 } |
|
243 } |
303 } |
244 |
304 |
245 Warn(msg) => { |
305 Warn(msg) => { |
246 run_action(server, token,SendMe(Warning(msg))); |
306 run_action(server, client_id, Warning(msg).send_self().action()); |
247 } |
307 } |
248 ProtocolError(msg) => { |
308 ProtocolError(msg) => { |
249 run_action(server, token, SendMe(Error(msg))) |
309 run_action(server, client_id, Error(msg).send_self().action()) |
250 } |
310 } |
251 } |
311 } |
252 } |
312 } |