rust/hedgewars-server/src/handlers/common.rs
changeset 15525 16d3c9acd715
parent 15523 f4f6060b536c
child 15526 24f692e791d3
equal deleted inserted replaced
15524:fbcee515b946 15525:16d3c9acd715
     1 use crate::{
     1 use crate::{
     2     core::{
     2     core::{
     3         client::HwClient,
     3         client::HwClient,
     4         room::HwRoom,
     4         room::HwRoom,
     5         server::{EndGameResult, HwServer, JoinRoomError, LeaveRoomResult, StartGameError},
     5         server::{
     6         types::{ClientId, GameCfg, RoomId, TeamInfo, Vote, VoteType},
     6             EndGameResult, HwRoomControl, HwServer, JoinRoomError, LeaveRoomResult, StartGameError,
       
     7             VoteError, VoteResult,
       
     8         },
       
     9         types::{ClientId, GameCfg, RoomId, TeamInfo, Vote, VoteType, MAX_HEDGEHOGS_PER_TEAM},
     7     },
    10     },
     8     protocol::messages::{
    11     protocol::messages::{
     9         add_flags, remove_flags, server_chat,
    12         add_flags, remove_flags, server_chat,
    10         HwProtocolMessage::{self, Rnd},
    13         HwProtocolMessage::{self, Rnd},
    11         HwServerMessage::{self, *},
    14         HwServerMessage::{self, *},
   339     if !nicks.is_empty() {
   342     if !nicks.is_empty() {
   340         response.add(ClientFlags(add_flags(&[Flags::Ready]), nicks).send(to_client));
   343         response.add(ClientFlags(add_flags(&[Flags::Ready]), nicks).send(to_client));
   341     }
   344     }
   342 }
   345 }
   343 
   346 
   344 pub fn apply_voting_result(
   347 pub fn check_vote(
   345     server: &mut HwServer,
   348     server: &HwServer,
       
   349     room: &HwRoom,
       
   350     kind: &VoteType,
       
   351     response: &mut Response,
       
   352 ) -> bool {
       
   353     let error = match &kind {
       
   354         VoteType::Kick(nick) => {
       
   355             if server
       
   356                 .find_client(&nick)
       
   357                 .filter(|c| c.room_id == Some(room.id))
       
   358                 .is_some()
       
   359             {
       
   360                 None
       
   361             } else {
       
   362                 Some("/callvote kick: No such user!".to_string())
       
   363             }
       
   364         }
       
   365         VoteType::Map(None) => {
       
   366             let names: Vec<_> = room.saves.keys().cloned().collect();
       
   367             if names.is_empty() {
       
   368                 Some("/callvote map: No maps saved in this room!".to_string())
       
   369             } else {
       
   370                 Some(format!("Available maps: {}", names.join(", ")))
       
   371             }
       
   372         }
       
   373         VoteType::Map(Some(name)) => {
       
   374             if room.saves.get(&name[..]).is_some() {
       
   375                 None
       
   376             } else {
       
   377                 Some("/callvote map: No such map!".to_string())
       
   378             }
       
   379         }
       
   380         VoteType::Pause => {
       
   381             if room.game_info.is_some() {
       
   382                 None
       
   383             } else {
       
   384                 Some("/callvote pause: No game in progress!".to_string())
       
   385             }
       
   386         }
       
   387         VoteType::NewSeed => None,
       
   388         VoteType::HedgehogsPerTeam(number) => match number {
       
   389             1..=MAX_HEDGEHOGS_PER_TEAM => None,
       
   390             _ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string()),
       
   391         },
       
   392     };
       
   393 
       
   394     match error {
       
   395         None => true,
       
   396         Some(msg) => {
       
   397             response.add(server_chat(msg).send_self());
       
   398             false
       
   399         }
       
   400     }
       
   401 }
       
   402 
       
   403 pub fn get_vote_data(
   346     room_id: RoomId,
   404     room_id: RoomId,
   347     response: &mut Response,
   405     result: &Result<VoteResult, VoteError>,
   348     kind: VoteType,
   406     response: &mut Response,
   349 ) {
   407 ) {
   350     match kind {
   408     match result {
   351         VoteType::Kick(nick) => {
   409         Ok(VoteResult::Submitted) => {
   352             if let Some(kicked_client) = server.find_client(&nick) {
   410             response.add(server_chat("Your vote has been counted.".to_string()).send_self())
   353                 let kicked_id = kicked_client.id;
   411         }
   354                 if kicked_client.room_id == Some(room_id) {
   412         Ok(VoteResult::Succeeded(_)) | Ok(VoteResult::Failed) => response.add(
   355                     if let Some(mut room_control) = server.get_room_control(kicked_client.id) {
   413             server_chat("Voting closed.".to_string())
       
   414                 .send_all()
       
   415                 .in_room(room_id),
       
   416         ),
       
   417         Err(VoteError::NoVoting) => {
       
   418             response.add(server_chat("There's no voting going on.".to_string()).send_self())
       
   419         }
       
   420         Err(VoteError::AlreadyVoted) => {
       
   421             response.add(server_chat("You already have voted.".to_string()).send_self())
       
   422         }
       
   423     }
       
   424 }
       
   425 
       
   426 pub fn handle_vote(
       
   427     mut room_control: HwRoomControl,
       
   428     result: Result<VoteResult, VoteError>,
       
   429     response: &mut super::Response,
       
   430 ) {
       
   431     let room_id = room_control.room().id;
       
   432     super::common::get_vote_data(room_control.room().id, &result, response);
       
   433 
       
   434     if let Ok(VoteResult::Succeeded(kind)) = result {
       
   435         match kind {
       
   436             VoteType::Kick(nick) => {
       
   437                 if let Some(kicked_client) = room_control.server().find_client(&nick) {
       
   438                     let kicked_id = kicked_client.id;
       
   439                     if let Some(mut room_control) = room_control.change_client(kicked_id) {
   356                         response.add(Kicked.send(kicked_id));
   440                         response.add(Kicked.send(kicked_id));
   357                         let result = room_control.leave_room();
   441                         let result = room_control.leave_room();
   358                         get_room_leave_result(
   442                         super::common::get_room_leave_result(
   359                             room_control.server(),
   443                             room_control.server(),
   360                             room_control.room(),
   444                             room_control.room(),
   361                             "kicked",
   445                             "kicked",
   362                             result,
   446                             result,
   363                             response,
   447                             response,
   364                         );
   448                         );
   365                     }
   449                     }
   366                 }
   450                 }
   367             }
   451             }
   368         }
   452             VoteType::Map(None) => (),
   369         VoteType::Map(None) => (),
   453             VoteType::Map(Some(name)) => {
   370         VoteType::Map(Some(name)) => {
   454                 if let Some(location) = room_control.load_config(&name) {
   371             if let Some(location) = server.room_mut(room_id).load_config(&name) {
   455                     let msg = server_chat(location.to_string());
   372                 response.add(
   456                     let room = room_control.room();
   373                     server_chat(location.to_string())
   457                     response.add(msg.send_all().in_room(room.id));
   374                         .send_all()
   458 
   375                         .in_room(room_id),
   459                     let room_master = room.master_id.map(|id| room_control.server().client(id));
   376                 );
   460 
   377                 let room = &server.room(room_id);
   461                     super::common::get_room_update(None, room, room_master, response);
   378                 let room_master = if let Some(id) = room.master_id {
   462 
   379                     Some(server.client(id))
   463                     for client_id in room_control.server().room_clients(room.id) {
   380                 } else {
   464                         super::common::get_room_config(room, client_id, response);
   381                     None
       
   382                 };
       
   383                 get_room_update(None, room, room_master, response);
       
   384 
       
   385                 for client in server.iter_clients() {
       
   386                     if client.room_id == Some(room_id) {
       
   387                         super::common::get_room_config(server.room(room_id), client.id, response);
       
   388                     }
   465                     }
   389                 }
   466                 }
   390             }
   467             }
   391         }
   468             VoteType::Pause => {
   392         VoteType::Pause => {
   469                 if room_control.toggle_pause() {
   393             if let Some(ref mut info) = server.room_mut(room_id).game_info {
   470                     response.add(
   394                 info.is_paused = !info.is_paused;
   471                         server_chat("Pause toggled.".to_string())
   395                 response.add(
   472                             .send_all()
   396                     server_chat("Pause toggled.".to_string())
   473                             .in_room(room_id),
   397                         .send_all()
   474                     );
   398                         .in_room(room_id),
   475                     response.add(
       
   476                         ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
       
   477                             .send_all()
       
   478                             .in_room(room_id),
       
   479                     );
       
   480                 }
       
   481             }
       
   482             VoteType::NewSeed => {
       
   483                 let seed = thread_rng().gen_range(0, 1_000_000_000).to_string();
       
   484                 let cfg = GameCfg::Seed(seed);
       
   485                 response.add(cfg.to_server_msg().send_all().in_room(room_id));
       
   486                 room_control.set_config(cfg);
       
   487             }
       
   488             VoteType::HedgehogsPerTeam(number) => {
       
   489                 let nicks = room_control.set_hedgehogs_number(number);
       
   490                 response.extend(
       
   491                     nicks
       
   492                         .into_iter()
       
   493                         .map(|n| HedgehogsNumber(n, number).send_all().in_room(room_id)),
   399                 );
   494                 );
   400                 response.add(
       
   401                     ForwardEngineMessage(vec![to_engine_msg(once(b'I'))])
       
   402                         .send_all()
       
   403                         .in_room(room_id),
       
   404                 );
       
   405             }
       
   406         }
       
   407         VoteType::NewSeed => {
       
   408             let seed = thread_rng().gen_range(0, 1_000_000_000).to_string();
       
   409             let cfg = GameCfg::Seed(seed);
       
   410             response.add(cfg.to_server_msg().send_all().in_room(room_id));
       
   411             server.room_mut(room_id).set_config(cfg);
       
   412         }
       
   413         VoteType::HedgehogsPerTeam(number) => {
       
   414             let r = server.room_mut(room_id);
       
   415             let nicks = r.set_hedgehogs_number(number);
       
   416 
       
   417             response.extend(
       
   418                 nicks
       
   419                     .into_iter()
       
   420                     .map(|n| HedgehogsNumber(n, number).send_all().in_room(room_id)),
       
   421             );
       
   422         }
       
   423     }
       
   424 }
       
   425 
       
   426 fn add_vote(room: &mut HwRoom, response: &mut Response, vote: Vote) -> Option<bool> {
       
   427     let client_id = response.client_id;
       
   428     let mut result = None;
       
   429 
       
   430     if let Some(ref mut voting) = room.voting {
       
   431         if vote.is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) {
       
   432             response.add(server_chat("Your vote has been counted.".to_string()).send_self());
       
   433             voting.votes.push((client_id, vote.is_pro));
       
   434             let i = voting.votes.iter();
       
   435             let pro = i.clone().filter(|(_, v)| *v).count();
       
   436             let contra = i.filter(|(_, v)| !*v).count();
       
   437             let success_quota = voting.voters.len() / 2 + 1;
       
   438             if vote.is_forced && vote.is_pro || pro >= success_quota {
       
   439                 result = Some(true);
       
   440             } else if vote.is_forced && !vote.is_pro || contra > voting.voters.len() - success_quota
       
   441             {
       
   442                 result = Some(false);
       
   443             }
       
   444         } else {
       
   445             response.add(server_chat("You already have voted.".to_string()).send_self());
       
   446         }
       
   447     } else {
       
   448         response.add(server_chat("There's no voting going on.".to_string()).send_self());
       
   449     }
       
   450 
       
   451     result
       
   452 }
       
   453 
       
   454 pub fn submit_vote(server: &mut HwServer, vote: Vote, response: &mut Response) {
       
   455     let client_id = response.client_id;
       
   456     let client = server.client(client_id);
       
   457 
       
   458     if let Some(room_id) = client.room_id {
       
   459         let room = server.room_mut(room_id);
       
   460 
       
   461         if let Some(res) = add_vote(room, response, vote) {
       
   462             response.add(
       
   463                 server_chat("Voting closed.".to_string())
       
   464                     .send_all()
       
   465                     .in_room(room.id),
       
   466             );
       
   467             let voting = replace(&mut room.voting, None).unwrap();
       
   468             if res {
       
   469                 apply_voting_result(server, room_id, response, voting.kind);
       
   470             }
   495             }
   471         }
   496         }
   472     }
   497     }
   473 }
   498 }
   474 
   499 
   505     room_id: RoomId,
   530     room_id: RoomId,
   506     result: EndGameResult,
   531     result: EndGameResult,
   507     response: &mut Response,
   532     response: &mut Response,
   508 ) {
   533 ) {
   509     let room = server.room(room_id);
   534     let room = server.room(room_id);
   510     let room_master = if let Some(id) = room.master_id {
   535     let room_master = room.master_id.map(|id| server.client(id));
   511         Some(server.client(id))
       
   512     } else {
       
   513         None
       
   514     };
       
   515 
   536 
   516     get_room_update(None, room, room_master, response);
   537     get_room_update(None, room, room_master, response);
   517     response.add(RoundFinished.send_all().in_room(room_id));
   538     response.add(RoundFinished.send_all().in_room(room_id));
   518 
   539 
   519     for client_id in result.joined_mid_game_clients {
   540     for client_id in result.joined_mid_game_clients {