1 use crate::{ |
1 use crate::{ |
2 core::{ |
2 core::{ |
3 client::HwClient, |
3 client::HwClient, |
4 room::HwRoom, |
4 room::HwRoom, |
5 server::{HwServer, JoinRoomError}, |
5 server::{HwServer, JoinRoomError, LeaveRoomResult}, |
6 types::{ClientId, GameCfg, RoomId, TeamInfo, Vote, VoteType}, |
6 types::{ClientId, GameCfg, RoomId, TeamInfo, Vote, VoteType}, |
7 }, |
7 }, |
8 protocol::messages::{ |
8 protocol::messages::{ |
9 add_flags, remove_flags, server_chat, |
9 add_flags, remove_flags, server_chat, |
10 HwProtocolMessage::{self, Rnd}, |
10 HwProtocolMessage::{self, Rnd}, |
94 } |
94 } |
95 } |
95 } |
96 |
96 |
97 response.add(server_msg.send_self()); |
97 response.add(server_msg.send_self()); |
98 response.add(rooms_msg.send_self()); |
98 response.add(rooms_msg.send_self()); |
99 } |
|
100 |
|
101 pub fn remove_teams( |
|
102 room: &mut HwRoom, |
|
103 team_names: Vec<String>, |
|
104 is_in_game: bool, |
|
105 response: &mut Response, |
|
106 ) { |
|
107 if let Some(ref mut info) = room.game_info { |
|
108 for team_name in &team_names { |
|
109 info.left_teams.push(team_name.clone()); |
|
110 |
|
111 if is_in_game { |
|
112 let msg = once(b'F').chain(team_name.bytes()); |
|
113 response.add( |
|
114 ForwardEngineMessage(vec![to_engine_msg(msg)]) |
|
115 .send_all() |
|
116 .in_room(room.id) |
|
117 .but_self(), |
|
118 ); |
|
119 |
|
120 info.teams_in_game -= 1; |
|
121 |
|
122 let remove_msg = to_engine_msg(once(b'F').chain(team_name.bytes())); |
|
123 if let Some(m) = &info.sync_msg { |
|
124 info.msg_log.push(m.clone()); |
|
125 info.sync_msg = None |
|
126 } |
|
127 info.msg_log.push(remove_msg.clone()); |
|
128 |
|
129 response.add( |
|
130 ForwardEngineMessage(vec![remove_msg]) |
|
131 .send_all() |
|
132 .in_room(room.id) |
|
133 .but_self(), |
|
134 ); |
|
135 } |
|
136 } |
|
137 } |
|
138 |
|
139 for team_name in team_names { |
|
140 room.remove_team(&team_name); |
|
141 response.add(TeamRemove(team_name).send_all().in_room(room.id)); |
|
142 } |
|
143 } |
|
144 |
|
145 fn remove_client_from_room( |
|
146 client: &mut HwClient, |
|
147 room: &mut HwRoom, |
|
148 response: &mut Response, |
|
149 msg: &str, |
|
150 ) { |
|
151 room.players_number -= 1; |
|
152 if room.players_number > 0 || room.is_fixed() { |
|
153 if client.is_ready() && room.ready_players_number > 0 { |
|
154 room.ready_players_number -= 1; |
|
155 } |
|
156 |
|
157 let team_names: Vec<_> = room |
|
158 .client_teams(client.id) |
|
159 .map(|t| t.name.clone()) |
|
160 .collect(); |
|
161 remove_teams(room, team_names, client.is_in_game(), response); |
|
162 |
|
163 if room.players_number > 0 { |
|
164 response.add( |
|
165 RoomLeft(client.nick.clone(), msg.to_string()) |
|
166 .send_all() |
|
167 .in_room(room.id) |
|
168 .but_self(), |
|
169 ); |
|
170 } |
|
171 |
|
172 if client.is_master() && !room.is_fixed() { |
|
173 client.set_is_master(false); |
|
174 response.add( |
|
175 ClientFlags( |
|
176 remove_flags(&[Flags::RoomMaster]), |
|
177 vec![client.nick.clone()], |
|
178 ) |
|
179 .send_all() |
|
180 .in_room(room.id), |
|
181 ); |
|
182 room.master_id = None; |
|
183 } |
|
184 } |
|
185 |
|
186 client.room_id = None; |
|
187 |
|
188 let update_msg = if room.players_number == 0 && !room.is_fixed() { |
|
189 RoomRemove(room.name.clone()) |
|
190 } else { |
|
191 RoomUpdated(room.name.clone(), room.info(Some(&client))) |
|
192 }; |
|
193 response.add(update_msg.send_all().with_protocol(room.protocol_number)); |
|
194 |
|
195 response.add(ClientFlags(remove_flags(&[Flags::InRoom]), vec![client.nick.clone()]).send_all()); |
|
196 } |
99 } |
197 |
100 |
198 pub fn change_master( |
101 pub fn change_master( |
199 server: &mut HwServer, |
102 server: &mut HwServer, |
200 room_id: RoomId, |
103 room_id: RoomId, |
289 JoinRoomError::Full => response.warn(ROOM_FULL), |
192 JoinRoomError::Full => response.warn(ROOM_FULL), |
290 JoinRoomError::Restricted => response.warn(ROOM_JOIN_RESTRICTED), |
193 JoinRoomError::Restricted => response.warn(ROOM_JOIN_RESTRICTED), |
291 } |
194 } |
292 } |
195 } |
293 |
196 |
294 pub fn exit_room(server: &mut HwServer, client_id: ClientId, response: &mut Response, msg: &str) { |
197 pub fn get_remove_teams_data( |
295 let client = &mut server.clients[client_id]; |
198 room_id: RoomId, |
296 |
199 was_in_game: bool, |
297 if let Some(room_id) = client.room_id { |
200 removed_teams: Vec<String>, |
298 let room = &mut server.rooms[room_id]; |
201 response: &mut Response, |
299 |
202 ) { |
300 remove_client_from_room(client, room, response, msg); |
203 if was_in_game { |
301 |
204 for team_name in &removed_teams { |
302 if !room.is_fixed() { |
205 let msg = once(b'F').chain(team_name.bytes()); |
303 if room.players_number == 0 { |
206 response.add( |
304 server.rooms.remove(room_id); |
207 ForwardEngineMessage(vec![to_engine_msg(msg)]) |
305 } else if room.master_id == None { |
208 .send_all() |
306 let new_master_id = server.room_clients(room_id).next(); |
209 .in_room(room_id) |
307 if let Some(new_master_id) = new_master_id { |
210 .but_self(), |
308 let new_master_nick = server.clients[new_master_id].nick.clone(); |
211 ); |
309 let room = &mut server.rooms[room_id]; |
212 |
310 room.master_id = Some(new_master_id); |
213 let remove_msg = to_engine_msg(once(b'F').chain(team_name.bytes())); |
311 server.clients[new_master_id].set_is_master(true); |
214 |
312 |
215 response.add( |
313 if room.protocol_number < 42 { |
216 ForwardEngineMessage(vec![remove_msg]) |
314 room.name = new_master_nick.clone(); |
217 .send_all() |
315 } |
218 .in_room(room_id) |
316 |
219 .but_self(), |
317 room.set_join_restriction(false); |
220 ); |
318 room.set_team_add_restriction(false); |
221 } |
319 room.set_unregistered_players_restriction(true); |
222 } |
320 |
223 |
|
224 for team_name in removed_teams { |
|
225 response.add(TeamRemove(team_name).send_all().in_room(room_id)); |
|
226 } |
|
227 } |
|
228 |
|
229 pub fn get_room_leave_data( |
|
230 server: &HwServer, |
|
231 room: &HwRoom, |
|
232 leave_message: &str, |
|
233 result: LeaveRoomResult, |
|
234 response: &mut Response, |
|
235 ) { |
|
236 let client = server.client(response.client_id); |
|
237 response.add(ClientFlags(remove_flags(&[Flags::InRoom]), vec![client.nick.clone()]).send_all()); |
|
238 |
|
239 match (result) { |
|
240 LeaveRoomResult::RoomRemoved => { |
|
241 response.add( |
|
242 RoomRemove(room.name.clone()) |
|
243 .send_all() |
|
244 .with_protocol(room.protocol_number), |
|
245 ); |
|
246 } |
|
247 |
|
248 LeaveRoomResult::RoomRemains { |
|
249 is_empty, |
|
250 was_master, |
|
251 new_master, |
|
252 was_in_game, |
|
253 removed_teams, |
|
254 } => { |
|
255 if !is_empty { |
|
256 response.add( |
|
257 RoomLeft(client.nick.clone(), leave_message.to_string()) |
|
258 .send_all() |
|
259 .in_room(room.id) |
|
260 .but_self(), |
|
261 ); |
|
262 } |
|
263 |
|
264 if was_master { |
|
265 response.add( |
|
266 ClientFlags( |
|
267 remove_flags(&[Flags::RoomMaster]), |
|
268 vec![client.nick.clone()], |
|
269 ) |
|
270 .send_all() |
|
271 .in_room(room.id), |
|
272 ); |
|
273 |
|
274 if let Some(new_master_id) = new_master { |
|
275 let new_master_nick = server.client(new_master_id).nick.clone(); |
321 response.add( |
276 response.add( |
322 ClientFlags(add_flags(&[Flags::RoomMaster]), vec![new_master_nick]) |
277 ClientFlags(add_flags(&[Flags::RoomMaster]), vec![new_master_nick]) |
323 .send_all() |
278 .send_all() |
324 .in_room(room.id), |
279 .in_room(room.id), |
325 ); |
280 ); |
326 } |
281 } |
327 } |
282 } |
|
283 |
|
284 get_remove_teams_data(room.id, was_in_game, removed_teams, response); |
|
285 |
|
286 response.add( |
|
287 RoomUpdated(room.name.clone(), room.info(Some(&client))) |
|
288 .send_all() |
|
289 .with_protocol(room.protocol_number), |
|
290 ); |
328 } |
291 } |
329 } |
292 } |
330 } |
293 } |
331 |
294 |
332 pub fn remove_client(server: &mut HwServer, response: &mut Response, msg: String) { |
295 pub fn remove_client(server: &mut HwServer, response: &mut Response, msg: String) { |
333 let client_id = response.client_id(); |
296 let client_id = response.client_id(); |
334 let client = &mut server.clients[client_id]; |
297 let client = server.client(client_id); |
335 let nick = client.nick.clone(); |
298 let nick = client.nick.clone(); |
336 |
299 |
337 exit_room(server, client_id, response, &msg); |
300 if let Some(room_id) = client.room_id { |
|
301 match server.leave_room(client_id) { |
|
302 Ok(result) => { |
|
303 let room = server.room(room_id); |
|
304 super::common::get_room_leave_data(server, room, &msg, result, response) |
|
305 } |
|
306 Err(_) => (), |
|
307 } |
|
308 } |
338 |
309 |
339 server.remove_client(client_id); |
310 server.remove_client(client_id); |
340 |
311 |
341 response.add(LobbyLeft(nick, msg.clone()).send_all()); |
312 response.add(LobbyLeft(nick, msg.clone()).send_all()); |
342 response.add(Bye(msg).send_self()); |
313 response.add(Bye(msg).send_self()); |
421 VoteType::Kick(nick) => { |
392 VoteType::Kick(nick) => { |
422 if let Some(client) = server.find_client(&nick) { |
393 if let Some(client) = server.find_client(&nick) { |
423 if client.room_id == Some(room_id) { |
394 if client.room_id == Some(room_id) { |
424 let id = client.id; |
395 let id = client.id; |
425 response.add(Kicked.send(id)); |
396 response.add(Kicked.send(id)); |
426 exit_room(server, id, response, "kicked"); |
397 match server.leave_room(response.client_id) { |
|
398 Ok(result) => { |
|
399 let room = server.room(room_id); |
|
400 super::common::get_room_leave_data( |
|
401 server, room, "kicked", result, response, |
|
402 ) |
|
403 } |
|
404 Err(_) => (), |
|
405 } |
427 } |
406 } |
428 } |
407 } |
429 } |
408 } |
430 VoteType::Map(None) => (), |
409 VoteType::Map(None) => (), |
431 VoteType::Map(Some(name)) => { |
410 VoteType::Map(Some(name)) => { |