1 use mio; |
1 use std::{ |
2 use std::io::Write; |
2 io, io::Write |
3 use std::io; |
3 }; |
4 |
4 use super::{ |
5 use super::server::HWServer; |
5 server::HWServer, |
6 use super::room::HWRoom; |
6 client::ClientId, |
7 use protocol::messages::HWProtocolMessage; |
7 room::HWRoom, |
8 use protocol::messages::HWServerMessage; |
8 handlers |
9 use protocol::messages::HWServerMessage::*; |
9 }; |
10 use super::handlers; |
10 use protocol::messages::{ |
|
11 HWProtocolMessage, |
|
12 HWServerMessage, |
|
13 HWServerMessage::* |
|
14 }; |
11 |
15 |
12 pub enum Action { |
16 pub enum Action { |
|
17 SendAll(HWServerMessage), |
13 SendMe(HWServerMessage), |
18 SendMe(HWServerMessage), |
14 SendAllButMe(HWServerMessage), |
19 SendAllButMe(HWServerMessage), |
|
20 SendToSelected(Vec<ClientId>, HWServerMessage), |
15 RemoveClient, |
21 RemoveClient, |
16 ByeClient(String), |
22 ByeClient(String), |
17 ReactProtocolMessage(HWProtocolMessage), |
23 ReactProtocolMessage(HWProtocolMessage), |
18 CheckRegistered, |
24 CheckRegistered, |
19 JoinLobby, |
25 JoinLobby, |
20 AddRoom(String, Option<String>), |
26 AddRoom(String, Option<String>), |
|
27 RemoveRoom(RoomId), |
|
28 MoveToRoom(RoomId), |
|
29 MoveToLobby(String), |
|
30 ChangeMaster(RoomId, Option<ClientId>), |
|
31 SendRoomUpdate(Option<String>), |
21 Warn(String), |
32 Warn(String), |
|
33 ProtocolError(String) |
22 } |
34 } |
23 |
35 |
24 use self::Action::*; |
36 use self::Action::*; |
|
37 use server::room::RoomId; |
25 |
38 |
26 pub fn run_action(server: &mut HWServer, token: usize, action: Action) { |
39 pub fn run_action(server: &mut HWServer, token: usize, action: Action) { |
27 match action { |
40 match action { |
|
41 SendAll(msg) => |
|
42 server.send_all(msg), |
28 SendMe(msg) => |
43 SendMe(msg) => |
29 server.send_self(token, msg), |
44 server.send_self(token, msg), |
30 SendAllButMe(msg) => { |
45 SendAllButMe(msg) => |
31 server.send_others(token, msg) |
46 server.send_others(token, msg), |
32 }, |
47 SendToSelected(client_ids, msg) => |
|
48 server.send_to_selected(client_ids, msg), |
33 ByeClient(msg) => { |
49 ByeClient(msg) => { |
|
50 let room_id; |
|
51 let nick; |
|
52 { |
|
53 let c = &server.clients[token]; |
|
54 room_id = c.room_id; |
|
55 nick = c.nick.clone(); |
|
56 } |
|
57 |
|
58 let action = room_id.map (|id| { |
|
59 if id == server.lobby_id { |
|
60 SendAll(LobbyLeft(nick, msg.clone())) |
|
61 } else { |
|
62 MoveToLobby(format!("quit: {}", msg.clone())) |
|
63 } |
|
64 }); |
|
65 |
|
66 if let Some(action) = action { |
|
67 server.react(token, vec![action]); |
|
68 } |
|
69 |
34 server.react(token, vec![ |
70 server.react(token, vec![ |
35 SendMe(Bye(msg)), |
71 SendMe(Bye(msg)), |
36 RemoveClient, |
72 RemoveClient]); |
37 ]); |
|
38 }, |
73 }, |
39 RemoveClient => { |
74 RemoveClient => { |
40 server.removed_clients.push(token); |
75 server.removed_clients.push(token); |
41 if server.clients.contains(token) { |
76 if server.clients.contains(token) { |
42 server.clients.remove(token); |
77 server.clients.remove(token); |
62 } |
97 } |
63 } |
98 } |
64 joined_msg = LobbyJoined(lobby_nicks); |
99 joined_msg = LobbyJoined(lobby_nicks); |
65 } |
100 } |
66 let everyone_msg = LobbyJoined(vec![server.clients[token].nick.clone()]); |
101 let everyone_msg = LobbyJoined(vec![server.clients[token].nick.clone()]); |
|
102 let flags_msg = ClientFlags( |
|
103 "+i".to_string(), |
|
104 server.clients.iter() |
|
105 .filter(|(_, c)| c.room_id.is_some()) |
|
106 .map(|(_, c)| c.nick.clone()) |
|
107 .collect()); |
|
108 let server_msg = ServerMessage("\u{1f994} is watching".to_string()); |
|
109 let rooms_msg = Rooms(server.rooms.iter() |
|
110 .filter(|(id, _)| *id != server.lobby_id) |
|
111 .flat_map(|(_, r)| |
|
112 r.info(r.master_id.map(|id| &server.clients[id]))) |
|
113 .collect()); |
67 server.react(token, vec![ |
114 server.react(token, vec![ |
68 SendAllButMe(everyone_msg), |
115 SendAllButMe(everyone_msg), |
69 SendMe(joined_msg), |
116 SendMe(joined_msg), |
|
117 SendMe(flags_msg), |
|
118 SendMe(server_msg), |
|
119 SendMe(rooms_msg), |
70 ]); |
120 ]); |
71 }, |
121 }, |
72 AddRoom(name, password) => { |
122 AddRoom(name, password) => { |
|
123 let room_protocol; |
|
124 let room_info; |
73 let room_id = server.add_room();; |
125 let room_id = server.add_room();; |
74 { |
126 { |
75 let r = &mut server.rooms[room_id]; |
127 let r = &mut server.rooms[room_id]; |
76 let c = &mut server.clients[token]; |
128 let c = &mut server.clients[token]; |
|
129 r.master_id = Some(c.id); |
77 r.name = name; |
130 r.name = name; |
78 r.password = password; |
131 r.password = password; |
79 r.ready_players_number = 1; |
|
80 r.protocol_number = c.protocol_number; |
132 r.protocol_number = c.protocol_number; |
|
133 |
|
134 room_protocol = r.protocol_number; |
|
135 room_info = r.info(Some(&c)); |
|
136 } |
|
137 let protocol_client_ids = server.protocol_clients(room_protocol); |
|
138 server.react(token, vec![ |
|
139 SendToSelected(protocol_client_ids, RoomAdd(room_info)), |
|
140 MoveToRoom(room_id)]); |
|
141 }, |
|
142 RemoveRoom(room_id) => { |
|
143 let room_protocol; |
|
144 let room_name; |
|
145 { |
|
146 let r = &mut server.rooms[room_id]; |
|
147 room_protocol = r.protocol_number; |
|
148 room_name = r.name.clone(); |
|
149 } |
|
150 server.rooms.remove(room_id); |
|
151 let protocol_client_ids = server.protocol_clients(room_protocol); |
|
152 server.react(token, vec![ |
|
153 SendToSelected(protocol_client_ids, RoomRemove(room_name))]); |
|
154 } |
|
155 MoveToRoom(room_id) => { |
|
156 let flags_msg; |
|
157 let nick; |
|
158 { |
|
159 let r = &mut server.rooms[room_id]; |
|
160 let c = &mut server.clients[token]; |
|
161 r.players_number += 1; |
81 c.room_id = Some(room_id); |
162 c.room_id = Some(room_id); |
82 } |
163 c.is_joined_mid_game = false; |
83 }, |
164 if r.master_id == Some(c.id) { |
|
165 r.ready_players_number += 1; |
|
166 c.is_master = true; |
|
167 c.is_ready = true; |
|
168 } else { |
|
169 c.is_ready = false; |
|
170 c.is_master = false; |
|
171 } |
|
172 flags_msg = ClientFlags("+i".to_string(), vec![c.nick.clone()]); |
|
173 nick = c.nick.clone(); |
|
174 } |
|
175 let rooms_client_ids = server.room_clients(room_id); |
|
176 server.react(token, vec![ |
|
177 SendToSelected(rooms_client_ids, RoomJoined(vec![nick])), |
|
178 SendAll(flags_msg), |
|
179 SendRoomUpdate(None)]); |
|
180 }, |
|
181 MoveToLobby(msg) => { |
|
182 let mut actions = Vec::new(); |
|
183 let other_client_ids = server.other_clients_in_room(token); |
|
184 let lobby_id = server.lobby_id; |
|
185 if let (c, Some(r)) = server.client_and_room(token) { |
|
186 r.players_number -= 1; |
|
187 if c.is_ready { |
|
188 r.ready_players_number -= 1; |
|
189 } |
|
190 if r.players_number > 0 && c.is_master { |
|
191 actions.push(ChangeMaster(r.id, None)); |
|
192 } |
|
193 actions.push(SendToSelected(other_client_ids, RoomLeft(c.nick.clone(), msg))); |
|
194 actions.push(SendAll(ClientFlags("-i".to_string(), vec![c.nick.clone()]))); |
|
195 actions.push(SendRoomUpdate(Some(r.name.clone()))); |
|
196 } |
|
197 server.react(token, actions); |
|
198 actions = Vec::new(); |
|
199 |
|
200 if let (c, Some(r)) = server.client_and_room(token) { |
|
201 c.room_id = Some(lobby_id); |
|
202 if r.players_number == 0 { |
|
203 actions.push(RemoveRoom(r.id)); |
|
204 } |
|
205 } |
|
206 server.react(token, actions) |
|
207 } |
|
208 ChangeMaster(room_id, new_id) => { |
|
209 let mut actions = Vec::new(); |
|
210 let room_client_ids = server.room_clients(room_id); |
|
211 let new_id = new_id.or_else(|| |
|
212 room_client_ids.iter().find(|id| **id != token).map(|id| *id)); |
|
213 let new_nick = new_id.map(|id| server.clients[id].nick.clone()); |
|
214 |
|
215 if let (c, Some(r)) = server.client_and_room(token) { |
|
216 if let Some(id) = r.master_id { |
|
217 c.is_master = false; |
|
218 r.master_id = None; |
|
219 actions.push(SendToSelected(room_client_ids.clone(), ClientFlags("-h".to_string(), vec![c.nick.clone()]))); |
|
220 } |
|
221 r.master_id = new_id; |
|
222 if let Some(nick) = new_nick { |
|
223 actions.push(SendToSelected(room_client_ids, ClientFlags("+h".to_string(), vec![nick]))); |
|
224 } |
|
225 } |
|
226 new_id.map(|id| server.clients[id].is_master = true); |
|
227 server.react(token, actions); |
|
228 } |
|
229 SendRoomUpdate(old_name) => { |
|
230 let room_data = |
|
231 if let (c, Some(r)) = server.client_and_room(token) { |
|
232 let name = old_name.unwrap_or_else(|| r.name.clone()); |
|
233 Some((name, r.protocol_number, r.info(Some(&c)))) |
|
234 } else { |
|
235 None |
|
236 }; |
|
237 |
|
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 } |
|
244 |
84 Warn(msg) => { |
245 Warn(msg) => { |
85 run_action(server, token,SendMe(Warning(msg))); |
246 run_action(server, token,SendMe(Warning(msg))); |
86 } |
247 } |
87 //_ => unimplemented!(), |
248 ProtocolError(msg) => { |
|
249 run_action(server, token, SendMe(Error(msg))) |
|
250 } |
88 } |
251 } |
89 } |
252 } |