# HG changeset patch # User alfadur # Date 1549475320 -10800 # Node ID 4569d8d502868fcac0b86a3530ac7bc3f80d7dd0 # Parent 5122c584804e8dafddfe5dc9b739fb22d336e77e Server action refactoring part B of N diff -r 5122c584804e -r 4569d8d50286 rust/hedgewars-server/src/server/actions.rs --- a/rust/hedgewars-server/src/server/actions.rs Wed Feb 06 00:57:01 2019 +0300 +++ b/rust/hedgewars-server/src/server/actions.rs Wed Feb 06 20:48:40 2019 +0300 @@ -103,9 +103,7 @@ pub enum Action { ChangeMaster(RoomId, Option), - StartRoomGame(RoomId), SendTeamRemovalMessage(String), - FinishRoomGame(RoomId), SendRoomData { to: ClientId, teams: bool, @@ -229,40 +227,7 @@ server.clients[id].set_is_master(true) } } - StartRoomGame(room_id) => { - let (room_clients, room_nicks): (Vec<_>, Vec<_>) = server - .clients - .iter() - .map(|(id, c)| (id, c.nick.clone())) - .unzip(); - let room = &mut server.rooms[room_id]; - - if !room.has_multiple_clans() { - /*Warn( - "The game can't be started with less than two clans!".to_string(), - )*/ - } else if room.protocol_number <= 43 && room.players_number != room.ready_players_number - { - /*Warn("Not all players are ready".to_string())*/ - } else if room.game_info.is_some() { - /*Warn("The game is already in progress".to_string())*/ - } else { - room.start_round(); - for id in room_clients { - let c = &mut server.clients[id]; - c.set_is_in_game(false); - c.team_indices = room.client_team_indices(c.id); - } - /*RunGame.send_all().in_room(room.id).action(),*/ - //SendRoomUpdate(None), - /*ClientFlags("+g".to_string(), room_nicks) - .send_all() - .in_room(room.id) - .action(),*/ - } - } SendTeamRemovalMessage(team_name) => { - let mut actions = Vec::new(); if let Some(r) = server.room(client_id) { if let Some(ref mut info) = r.game_info { let msg = once(b'F').chain(team_name.bytes()); @@ -275,7 +240,7 @@ );*/ info.teams_in_game -= 1; if info.teams_in_game == 0 { - actions.push(FinishRoomGame(r.id)); + //actions.push(FinishRoomGame(r.id)); } let remove_msg = to_engine_msg(once(b'F').chain(team_name.bytes())); if let Some(m) = &info.sync_msg { @@ -295,56 +260,5 @@ } } } - FinishRoomGame(room_id) => { - let mut actions = Vec::new(); - - let r = &mut server.rooms[room_id]; - r.ready_players_number = 1; - //actions.push(SendRoomUpdate(None)); - //actions.push(RoundFinished.send_all().in_room(r.id).action()); - - if let Some(info) = replace(&mut r.game_info, None) { - for (_, c) in server.clients.iter() { - if c.room_id == Some(room_id) && c.is_joined_mid_game() { - actions.push(SendRoomData { - to: c.id, - teams: false, - config: true, - flags: false, - }); - for name in &info.left_teams { - //actions.push(TeamRemove(name.clone()).send(c.id).action()); - } - } - } - } - - let nicks: Vec<_> = server - .clients - .iter_mut() - .filter(|(_, c)| c.room_id == Some(room_id)) - .map(|(_, c)| { - c.set_is_ready(c.is_master()); - c.set_is_joined_mid_game(false); - c - }) - .filter_map(|c| { - if !c.is_master() { - Some(c.nick.clone()) - } else { - None - } - }) - .collect(); - - if !nicks.is_empty() { - let msg = if r.protocol_number < 38 { - LegacyReady(false, nicks) - } else { - ClientFlags("-r".to_string(), nicks) - }; - //actions.push(msg.send_all().in_room(room_id).action()); - } - } } } diff -r 5122c584804e -r 4569d8d50286 rust/hedgewars-server/src/server/handlers/common.rs --- a/rust/hedgewars-server/src/server/handlers/common.rs Wed Feb 06 00:57:01 2019 +0300 +++ b/rust/hedgewars-server/src/server/handlers/common.rs Wed Feb 06 20:48:40 2019 +0300 @@ -1,26 +1,23 @@ -use crate::protocol::messages::server_chat; -use crate::server::client::HWClient; -use crate::server::coretypes::ClientId; -use crate::server::coretypes::GameCfg; -use crate::server::coretypes::RoomId; -use crate::server::coretypes::Vote; -use crate::server::coretypes::VoteType; -use crate::server::room::HWRoom; -use crate::utils::to_engine_msg; use crate::{ + protocol::messages::server_chat, protocol::messages::{ HWProtocolMessage::{self, Rnd}, - HWServerMessage::{ - self, Bye, ChatMsg, ClientFlags, ForwardEngineMessage, HedgehogsNumber, Kicked, - LobbyJoined, LobbyLeft, Notice, RoomLeft, RoomRemove, RoomUpdated, Rooms, - ServerMessage, TeamRemove, - }, + HWServerMessage::{self, *}, }, - server::{actions::Action, core::HWServer}, + server::{ + actions::Action, + client::HWClient, + core::HWServer, + coretypes::{ClientId, GameCfg, RoomId, Vote, VoteType}, + room::HWRoom, + }, + utils::to_engine_msg, }; + +use super::Response; + use rand::{self, thread_rng, Rng}; -use std::iter::once; -use std::mem::replace; +use std::{iter::once, mem::replace}; pub fn rnd_reply(options: &[String]) -> HWServerMessage { let mut rng = thread_rng(); @@ -36,7 +33,7 @@ } } -pub fn process_login(server: &mut HWServer, response: &mut super::Response) { +pub fn process_login(server: &mut HWServer, response: &mut Response) { let client_id = response.client_id(); let nick = server.clients[client_id].nick.clone(); @@ -97,7 +94,7 @@ room: &mut HWRoom, team_names: Vec, is_in_game: bool, - response: &mut super::Response, + response: &mut Response, ) { if let Some(ref mut info) = room.game_info { for team_name in &team_names { @@ -140,7 +137,7 @@ } } -pub fn exit_room(client: &HWClient, room: &mut HWRoom, response: &mut super::Response, msg: &str) { +pub fn exit_room(client: &HWClient, room: &mut HWRoom, response: &mut Response, msg: &str) { if room.players_number > 1 || room.is_fixed() { room.players_number -= 1; if client.is_ready() && room.ready_players_number > 0 { @@ -175,7 +172,7 @@ response.add(ClientFlags("-i".to_string(), vec![client.nick.clone()]).send_all()); } -pub fn remove_client(server: &mut HWServer, response: &mut super::Response, msg: String) { +pub fn remove_client(server: &mut HWServer, response: &mut Response, msg: String) { let client_id = response.client_id(); let lobby_id = server.lobby_id; let client = &mut server.clients[client_id]; @@ -197,7 +194,7 @@ room_name: Option, room: &HWRoom, master: Option<&HWClient>, - response: &mut super::Response, + response: &mut Response, ) { let update_msg = RoomUpdated(room_name.unwrap_or(room.name.clone()), room.info(master)); response.add(update_msg.send_all().with_protocol(room.protocol_number)); @@ -206,7 +203,7 @@ pub fn apply_voting_result( server: &mut HWServer, room_id: RoomId, - response: &mut super::Response, + response: &mut Response, kind: VoteType, ) { let client_id = response.client_id; @@ -234,12 +231,13 @@ .send_all() .in_room(room_id), ); - get_room_update( - None, - &server.rooms[room_id], - Some(&server.clients[client_id]), - response, - ); + let room = &server.rooms[room_id]; + let room_master = if let Some(id) = room.master_id { + Some(&server.clients[id]) + } else { + None + }; + get_room_update(None, room, room_master, response); for (_, c) in server.clients.iter() { if c.room_id == Some(room_id) { @@ -287,7 +285,7 @@ } } -fn add_vote(room: &mut HWRoom, response: &mut super::Response, vote: Vote) -> Option { +fn add_vote(room: &mut HWRoom, response: &mut Response, vote: Vote) -> Option { let client_id = response.client_id; let mut result = None; @@ -315,7 +313,7 @@ result } -pub fn submit_vote(server: &mut HWServer, vote: Vote, response: &mut super::Response) { +pub fn submit_vote(server: &mut HWServer, vote: Vote, response: &mut Response) { let client_id = response.client_id; let client = &server.clients[client_id]; @@ -336,6 +334,98 @@ } } +pub fn start_game(server: &mut HWServer, room_id: RoomId, response: &mut Response) { + let (room_clients, room_nicks): (Vec<_>, Vec<_>) = server + .clients + .iter() + .map(|(id, c)| (id, c.nick.clone())) + .unzip(); + let room = &mut server.rooms[room_id]; + + if !room.has_multiple_clans() { + response.add( + Warning("The game can't be started with less than two clans!".to_string()).send_self(), + ); + } else if room.protocol_number <= 43 && room.players_number != room.ready_players_number { + response.add(Warning("Not all players are ready".to_string()).send_self()); + } else if room.game_info.is_some() { + response.add(Warning("The game is already in progress".to_string()).send_self()); + } else { + room.start_round(); + for id in room_clients { + let c = &mut server.clients[id]; + c.set_is_in_game(false); + c.team_indices = room.client_team_indices(c.id); + } + response.add(RunGame.send_all().in_room(room.id)); + response.add( + ClientFlags("+g".to_string(), room_nicks) + .send_all() + .in_room(room.id), + ); + + let room_master = if let Some(id) = room.master_id { + Some(&server.clients[id]) + } else { + None + }; + get_room_update(None, room, room_master, response); + } +} + +pub fn end_game(server: &mut HWServer, room_id: RoomId, response: &mut Response) { + let room = &mut server.rooms[room_id]; + room.ready_players_number = 1; + let room_master = if let Some(id) = room.master_id { + Some(&server.clients[id]) + } else { + None + }; + get_room_update(None, room, room_master, response); + response.add(RoundFinished.send_all().in_room(room_id)); + + if let Some(info) = replace(&mut room.game_info, None) { + for (_, client) in server.clients.iter() { + if client.room_id == Some(room_id) && client.is_joined_mid_game() { + //SendRoomData { to: client.id, teams: false, config: true, flags: false} + + response.extend( + info.left_teams + .iter() + .map(|name| TeamRemove(name.clone()).send(client.id)), + ); + } + } + } + + let nicks: Vec<_> = server + .clients + .iter_mut() + .filter(|(_, c)| c.room_id == Some(room_id)) + .map(|(_, c)| { + c.set_is_ready(c.is_master()); + c.set_is_joined_mid_game(false); + c + }) + .filter_map(|c| { + if !c.is_master() { + Some(c.nick.clone()) + } else { + None + } + }) + .collect(); + + if !nicks.is_empty() { + let msg = if room.protocol_number < 38 { + LegacyReady(false, nicks) + } else { + ClientFlags("-r".to_string(), nicks) + }; + response.add(msg.send_all().in_room(room_id)); + } +} + #[cfg(test)] mod tests { use super::*; diff -r 5122c584804e -r 4569d8d50286 rust/hedgewars-server/src/server/handlers/inroom.rs --- a/rust/hedgewars-server/src/server/handlers/inroom.rs Wed Feb 06 00:57:01 2019 +0300 +++ b/rust/hedgewars-server/src/server/handlers/inroom.rs Wed Feb 06 20:48:40 2019 +0300 @@ -155,19 +155,21 @@ RoomName(new_name) => { if is_name_illegal(&new_name) { response.add(Warning("Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string()).send_self()); - } else if server.rooms[room_id].is_fixed() { - response.add(Warning("Access denied.".to_string()).send_self()); } else if server.has_room(&new_name) { response.add( Warning("A room with the same name already exists.".to_string()).send_self(), ); } else { - let mut old_name = new_name.clone(); - let client = &server.clients[client_id]; let room = &mut server.rooms[room_id]; - swap(&mut room.name, &mut old_name); - super::common::get_room_update(Some(old_name), room, Some(&client), response); - }; + if room.is_fixed() || room.master_id != Some(client_id) { + response.add(Warning("Access denied.".to_string()).send_self()); + } else { + let mut old_name = new_name.clone(); + let client = &server.clients[client_id]; + swap(&mut room.name, &mut old_name); + super::common::get_room_update(Some(old_name), room, Some(&client), response); + } + } } ToggleReady => { if let (client, Some(room)) = server.client_and_room(client_id) { @@ -193,50 +195,54 @@ } } AddTeam(info) => { - if let (client, Some(room)) = server.client_and_room(client_id) { - if room.teams.len() >= room.team_limit as usize { - response.add(Warning("Too many teams!".to_string()).send_self()); - } else if room.addable_hedgehogs() == 0 { - response.add(Warning("Too many hedgehogs!".to_string()).send_self()); - } else if room.find_team(|t| t.name == info.name) != None { - response.add( - Warning("There's already a team with same name in the list.".to_string()) - .send_self(), - ); - } else if room.game_info.is_some() { - response.add( - Warning("Joining not possible: Round is in progress.".to_string()) - .send_self(), - ); - } else if room.is_team_add_restricted() { - response.add( - Warning("This room currently does not allow adding new teams.".to_string()) - .send_self(), - ); + let client = &mut server.clients[client_id]; + let room = &mut server.rooms[room_id]; + if room.teams.len() >= room.team_limit as usize { + response.add(Warning("Too many teams!".to_string()).send_self()); + } else if room.addable_hedgehogs() == 0 { + response.add(Warning("Too many hedgehogs!".to_string()).send_self()); + } else if room.find_team(|t| t.name == info.name) != None { + response.add( + Warning("There's already a team with same name in the list.".to_string()) + .send_self(), + ); + } else if room.game_info.is_some() { + response.add( + Warning("Joining not possible: Round is in progress.".to_string()).send_self(), + ); + } else if room.is_team_add_restricted() { + response.add( + Warning("This room currently does not allow adding new teams.".to_string()) + .send_self(), + ); + } else { + let team = room.add_team(client.id, *info, client.protocol_number < 42); + client.teams_in_game += 1; + client.clan = Some(team.color); + response.add(TeamAccepted(team.name.clone()).send_self()); + response.add( + TeamAdd(HWRoom::team_info(&client, team)) + .send_all() + .in_room(room_id) + .but_self(), + ); + response.add( + TeamColor(team.name.clone(), team.color) + .send_all() + .in_room(room_id), + ); + response.add( + HedgehogsNumber(team.name.clone(), team.hedgehogs_number) + .send_all() + .in_room(room_id), + ); + + let room_master = if let Some(id) = room.master_id { + Some(&server.clients[id]) } else { - let team = room.add_team(client.id, *info, client.protocol_number < 42); - client.teams_in_game += 1; - client.clan = Some(team.color); - response.add(TeamAccepted(team.name.clone()).send_self()); - response.add( - TeamAdd(HWRoom::team_info(&client, team)) - .send_all() - .in_room(room_id) - .but_self(), - ); - response.add( - TeamColor(team.name.clone(), team.color) - .send_all() - .in_room(room_id), - ); - response.add( - HedgehogsNumber(team.name.clone(), team.hedgehogs_number) - .send_all() - .in_room(room_id), - ); - - super::common::get_room_update(None, room, Some(&client), response); - } + None + }; + super::common::get_room_update(None, room, room_master, response); } } RemoveTeam(name) => {