1 use crate::protocol::messages::server_chat; |
|
2 use crate::server::client::HWClient; |
|
3 use crate::server::coretypes::ClientId; |
|
4 use crate::server::coretypes::GameCfg; |
|
5 use crate::server::coretypes::RoomId; |
|
6 use crate::server::coretypes::Vote; |
|
7 use crate::server::coretypes::VoteType; |
|
8 use crate::server::room::HWRoom; |
|
9 use crate::utils::to_engine_msg; |
|
10 use crate::{ |
1 use crate::{ |
|
2 protocol::messages::server_chat, |
11 protocol::messages::{ |
3 protocol::messages::{ |
12 HWProtocolMessage::{self, Rnd}, |
4 HWProtocolMessage::{self, Rnd}, |
13 HWServerMessage::{ |
5 HWServerMessage::{self, *}, |
14 self, Bye, ChatMsg, ClientFlags, ForwardEngineMessage, HedgehogsNumber, Kicked, |
|
15 LobbyJoined, LobbyLeft, Notice, RoomLeft, RoomRemove, RoomUpdated, Rooms, |
|
16 ServerMessage, TeamRemove, |
|
17 }, |
|
18 }, |
6 }, |
19 server::{actions::Action, core::HWServer}, |
7 server::{ |
|
8 actions::Action, |
|
9 client::HWClient, |
|
10 core::HWServer, |
|
11 coretypes::{ClientId, GameCfg, RoomId, Vote, VoteType}, |
|
12 room::HWRoom, |
|
13 }, |
|
14 utils::to_engine_msg, |
20 }; |
15 }; |
|
16 |
|
17 use super::Response; |
|
18 |
21 use rand::{self, thread_rng, Rng}; |
19 use rand::{self, thread_rng, Rng}; |
22 use std::iter::once; |
20 use std::{iter::once, mem::replace}; |
23 use std::mem::replace; |
|
24 |
21 |
25 pub fn rnd_reply(options: &[String]) -> HWServerMessage { |
22 pub fn rnd_reply(options: &[String]) -> HWServerMessage { |
26 let mut rng = thread_rng(); |
23 let mut rng = thread_rng(); |
27 let reply = if options.is_empty() { |
24 let reply = if options.is_empty() { |
28 (*rng.choose(&["heads", "tails"]).unwrap()).to_owned() |
25 (*rng.choose(&["heads", "tails"]).unwrap()).to_owned() |
34 nick: "[random]".to_owned(), |
31 nick: "[random]".to_owned(), |
35 msg: reply.clone(), |
32 msg: reply.clone(), |
36 } |
33 } |
37 } |
34 } |
38 |
35 |
39 pub fn process_login(server: &mut HWServer, response: &mut super::Response) { |
36 pub fn process_login(server: &mut HWServer, response: &mut Response) { |
40 let client_id = response.client_id(); |
37 let client_id = response.client_id(); |
41 let nick = server.clients[client_id].nick.clone(); |
38 let nick = server.clients[client_id].nick.clone(); |
42 |
39 |
43 let has_nick_clash = server |
40 let has_nick_clash = server |
44 .clients |
41 .clients |
95 |
92 |
96 pub fn remove_teams( |
93 pub fn remove_teams( |
97 room: &mut HWRoom, |
94 room: &mut HWRoom, |
98 team_names: Vec<String>, |
95 team_names: Vec<String>, |
99 is_in_game: bool, |
96 is_in_game: bool, |
100 response: &mut super::Response, |
97 response: &mut Response, |
101 ) { |
98 ) { |
102 if let Some(ref mut info) = room.game_info { |
99 if let Some(ref mut info) = room.game_info { |
103 for team_name in &team_names { |
100 for team_name in &team_names { |
104 info.left_teams.push(team_name.clone()); |
101 info.left_teams.push(team_name.clone()); |
105 |
102 |
138 room.remove_team(&team_name); |
135 room.remove_team(&team_name); |
139 response.add(TeamRemove(team_name).send_all().in_room(room.id)); |
136 response.add(TeamRemove(team_name).send_all().in_room(room.id)); |
140 } |
137 } |
141 } |
138 } |
142 |
139 |
143 pub fn exit_room(client: &HWClient, room: &mut HWRoom, response: &mut super::Response, msg: &str) { |
140 pub fn exit_room(client: &HWClient, room: &mut HWRoom, response: &mut Response, msg: &str) { |
144 if room.players_number > 1 || room.is_fixed() { |
141 if room.players_number > 1 || room.is_fixed() { |
145 room.players_number -= 1; |
142 room.players_number -= 1; |
146 if client.is_ready() && room.ready_players_number > 0 { |
143 if client.is_ready() && room.ready_players_number > 0 { |
147 room.ready_players_number -= 1; |
144 room.ready_players_number -= 1; |
148 } |
145 } |
173 response.add(update_msg.send_all().with_protocol(room.protocol_number)); |
170 response.add(update_msg.send_all().with_protocol(room.protocol_number)); |
174 |
171 |
175 response.add(ClientFlags("-i".to_string(), vec![client.nick.clone()]).send_all()); |
172 response.add(ClientFlags("-i".to_string(), vec![client.nick.clone()]).send_all()); |
176 } |
173 } |
177 |
174 |
178 pub fn remove_client(server: &mut HWServer, response: &mut super::Response, msg: String) { |
175 pub fn remove_client(server: &mut HWServer, response: &mut Response, msg: String) { |
179 let client_id = response.client_id(); |
176 let client_id = response.client_id(); |
180 let lobby_id = server.lobby_id; |
177 let lobby_id = server.lobby_id; |
181 let client = &mut server.clients[client_id]; |
178 let client = &mut server.clients[client_id]; |
182 let (nick, room_id) = (client.nick.clone(), client.room_id); |
179 let (nick, room_id) = (client.nick.clone(), client.room_id); |
183 |
180 |
195 |
192 |
196 pub fn get_room_update( |
193 pub fn get_room_update( |
197 room_name: Option<String>, |
194 room_name: Option<String>, |
198 room: &HWRoom, |
195 room: &HWRoom, |
199 master: Option<&HWClient>, |
196 master: Option<&HWClient>, |
200 response: &mut super::Response, |
197 response: &mut Response, |
201 ) { |
198 ) { |
202 let update_msg = RoomUpdated(room_name.unwrap_or(room.name.clone()), room.info(master)); |
199 let update_msg = RoomUpdated(room_name.unwrap_or(room.name.clone()), room.info(master)); |
203 response.add(update_msg.send_all().with_protocol(room.protocol_number)); |
200 response.add(update_msg.send_all().with_protocol(room.protocol_number)); |
204 } |
201 } |
205 |
202 |
206 pub fn apply_voting_result( |
203 pub fn apply_voting_result( |
207 server: &mut HWServer, |
204 server: &mut HWServer, |
208 room_id: RoomId, |
205 room_id: RoomId, |
209 response: &mut super::Response, |
206 response: &mut Response, |
210 kind: VoteType, |
207 kind: VoteType, |
211 ) { |
208 ) { |
212 let client_id = response.client_id; |
209 let client_id = response.client_id; |
213 |
210 |
214 match kind { |
211 match kind { |
232 response.add( |
229 response.add( |
233 server_chat(location.to_string()) |
230 server_chat(location.to_string()) |
234 .send_all() |
231 .send_all() |
235 .in_room(room_id), |
232 .in_room(room_id), |
236 ); |
233 ); |
237 get_room_update( |
234 let room = &server.rooms[room_id]; |
238 None, |
235 let room_master = if let Some(id) = room.master_id { |
239 &server.rooms[room_id], |
236 Some(&server.clients[id]) |
240 Some(&server.clients[client_id]), |
237 } else { |
241 response, |
238 None |
242 ); |
239 }; |
|
240 get_room_update(None, room, room_master, response); |
243 |
241 |
244 for (_, c) in server.clients.iter() { |
242 for (_, c) in server.clients.iter() { |
245 if c.room_id == Some(room_id) { |
243 if c.room_id == Some(room_id) { |
246 /*SendRoomData { |
244 /*SendRoomData { |
247 to: c.id, |
245 to: c.id, |
285 ); |
283 ); |
286 } |
284 } |
287 } |
285 } |
288 } |
286 } |
289 |
287 |
290 fn add_vote(room: &mut HWRoom, response: &mut super::Response, vote: Vote) -> Option<bool> { |
288 fn add_vote(room: &mut HWRoom, response: &mut Response, vote: Vote) -> Option<bool> { |
291 let client_id = response.client_id; |
289 let client_id = response.client_id; |
292 let mut result = None; |
290 let mut result = None; |
293 |
291 |
294 if let Some(ref mut voting) = room.voting { |
292 if let Some(ref mut voting) = room.voting { |
295 if vote.is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) { |
293 if vote.is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) { |
313 } |
311 } |
314 |
312 |
315 result |
313 result |
316 } |
314 } |
317 |
315 |
318 pub fn submit_vote(server: &mut HWServer, vote: Vote, response: &mut super::Response) { |
316 pub fn submit_vote(server: &mut HWServer, vote: Vote, response: &mut Response) { |
319 let client_id = response.client_id; |
317 let client_id = response.client_id; |
320 let client = &server.clients[client_id]; |
318 let client = &server.clients[client_id]; |
321 |
319 |
322 if let Some(room_id) = client.room_id { |
320 if let Some(room_id) = client.room_id { |
323 let room = &mut server.rooms[room_id]; |
321 let room = &mut server.rooms[room_id]; |
334 } |
332 } |
335 } |
333 } |
336 } |
334 } |
337 } |
335 } |
338 |
336 |
|
337 pub fn start_game(server: &mut HWServer, room_id: RoomId, response: &mut Response) { |
|
338 let (room_clients, room_nicks): (Vec<_>, Vec<_>) = server |
|
339 .clients |
|
340 .iter() |
|
341 .map(|(id, c)| (id, c.nick.clone())) |
|
342 .unzip(); |
|
343 let room = &mut server.rooms[room_id]; |
|
344 |
|
345 if !room.has_multiple_clans() { |
|
346 response.add( |
|
347 Warning("The game can't be started with less than two clans!".to_string()).send_self(), |
|
348 ); |
|
349 } else if room.protocol_number <= 43 && room.players_number != room.ready_players_number { |
|
350 response.add(Warning("Not all players are ready".to_string()).send_self()); |
|
351 } else if room.game_info.is_some() { |
|
352 response.add(Warning("The game is already in progress".to_string()).send_self()); |
|
353 } else { |
|
354 room.start_round(); |
|
355 for id in room_clients { |
|
356 let c = &mut server.clients[id]; |
|
357 c.set_is_in_game(false); |
|
358 c.team_indices = room.client_team_indices(c.id); |
|
359 } |
|
360 response.add(RunGame.send_all().in_room(room.id)); |
|
361 response.add( |
|
362 ClientFlags("+g".to_string(), room_nicks) |
|
363 .send_all() |
|
364 .in_room(room.id), |
|
365 ); |
|
366 |
|
367 let room_master = if let Some(id) = room.master_id { |
|
368 Some(&server.clients[id]) |
|
369 } else { |
|
370 None |
|
371 }; |
|
372 get_room_update(None, room, room_master, response); |
|
373 } |
|
374 } |
|
375 |
|
376 pub fn end_game(server: &mut HWServer, room_id: RoomId, response: &mut Response) { |
|
377 let room = &mut server.rooms[room_id]; |
|
378 room.ready_players_number = 1; |
|
379 let room_master = if let Some(id) = room.master_id { |
|
380 Some(&server.clients[id]) |
|
381 } else { |
|
382 None |
|
383 }; |
|
384 get_room_update(None, room, room_master, response); |
|
385 response.add(RoundFinished.send_all().in_room(room_id)); |
|
386 |
|
387 if let Some(info) = replace(&mut room.game_info, None) { |
|
388 for (_, client) in server.clients.iter() { |
|
389 if client.room_id == Some(room_id) && client.is_joined_mid_game() { |
|
390 //SendRoomData { to: client.id, teams: false, config: true, flags: false} |
|
391 |
|
392 response.extend( |
|
393 info.left_teams |
|
394 .iter() |
|
395 .map(|name| TeamRemove(name.clone()).send(client.id)), |
|
396 ); |
|
397 } |
|
398 } |
|
399 } |
|
400 |
|
401 let nicks: Vec<_> = server |
|
402 .clients |
|
403 .iter_mut() |
|
404 .filter(|(_, c)| c.room_id == Some(room_id)) |
|
405 .map(|(_, c)| { |
|
406 c.set_is_ready(c.is_master()); |
|
407 c.set_is_joined_mid_game(false); |
|
408 c |
|
409 }) |
|
410 .filter_map(|c| { |
|
411 if !c.is_master() { |
|
412 Some(c.nick.clone()) |
|
413 } else { |
|
414 None |
|
415 } |
|
416 }) |
|
417 .collect(); |
|
418 |
|
419 if !nicks.is_empty() { |
|
420 let msg = if room.protocol_number < 38 { |
|
421 LegacyReady(false, nicks) |
|
422 } else { |
|
423 ClientFlags("-r".to_string(), nicks) |
|
424 }; |
|
425 response.add(msg.send_all().in_room(room_id)); |
|
426 } |
|
427 } |
|
428 |
339 #[cfg(test)] |
429 #[cfg(test)] |
340 mod tests { |
430 mod tests { |
341 use super::*; |
431 use super::*; |
342 use crate::protocol::messages::HWServerMessage::ChatMsg; |
432 use crate::protocol::messages::HWServerMessage::ChatMsg; |
343 use crate::server::actions::PendingMessage; |
433 use crate::server::actions::PendingMessage; |