made it so when player quits multiplayer game, ...
...game creator chooses to replace them with ai/local player or abort. fixed problem when player joins game and then leaves
This commit is contained in:
parent
2eb5a56a1f
commit
fe9d34d6db
12 changed files with 279 additions and 178 deletions
|
@ -241,7 +241,7 @@ awaiting_connections="Waiting for players to connect"
|
|||
position_taken="Filled"
|
||||
multiplayer_save_name="multiplayer save"
|
||||
position_vacant="Available"
|
||||
observer="Observer"
|
||||
observer="&misc/observer.png,Observer"
|
||||
generic_player="player"
|
||||
|
||||
host_game="Host Multiplayer Game"
|
||||
|
@ -270,6 +270,10 @@ load_game_heading="Load Game"
|
|||
load_game_message="Choose the game to load"
|
||||
replay_game_message="Show replay of game up to save point?"
|
||||
show_replay="Show replay"
|
||||
player_leave_message="has left the game. What do you want to do?"
|
||||
replace_ai_message="Replace with AI"
|
||||
replace_local_message="Replace with local player"
|
||||
abort_game_message="Abort game"
|
||||
save_game_error="A network disconnection has occured, and the game cannot continue. Do you want to save the game?"
|
||||
network_sync_error="The games are out of sync and will have to exit. Do you want to save an error log of your game?"
|
||||
multiplayer_save_name="multiplayer save"
|
||||
|
|
|
@ -39,9 +39,11 @@
|
|||
network_game_manager::~network_game_manager()
|
||||
{
|
||||
if(network::nconnections() > 0) {
|
||||
std::cerr << "sending leave_game\n";
|
||||
config cfg;
|
||||
cfg.add_child("leave_game");
|
||||
network::send_data(cfg);
|
||||
std::cerr << "sent leave_game\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ void play_multiplayer_client(display& disp, game_data& units_data, config& cfg,
|
|||
if((**s)["controller"] == "network" &&
|
||||
(**s)["taken"] != "yes") {
|
||||
choice_map[choices.size()] = 1 + s - sides_list.begin();
|
||||
choices.push_back((**s)["name"] + " - " + (**s)["type"]);
|
||||
choices.push_back((**s)["name"] + "," + (**s)["type"]);
|
||||
}
|
||||
|
||||
race_names.push_back((**s)["name"]);
|
||||
|
|
|
@ -627,110 +627,112 @@ void mp_connect::update_network()
|
|||
std::cerr << "Received connection\n";
|
||||
network::send_data(*level_,sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config cfg;
|
||||
const config::child_list& sides = level_->get_children("side");
|
||||
config cfg;
|
||||
const config::child_list& sides = level_->get_children("side");
|
||||
|
||||
try {
|
||||
sock = network::receive_data(cfg);
|
||||
} catch(network::error& e) {
|
||||
std::cerr << "caught networking error. we are " << (network::is_server() ? "" : "NOT") << " a server\n";
|
||||
sock = 0;
|
||||
network::connection sock;
|
||||
|
||||
//if the problem isn't related to any specific connection,
|
||||
//it's a general error and we should just re-throw the error
|
||||
//likewise if we are not a server, we cannot afford any connection
|
||||
//to go down, so also re-throw the error
|
||||
if(!e.socket || !network::is_server()) {
|
||||
e.disconnect();
|
||||
throw network::error(e.message);
|
||||
}
|
||||
try {
|
||||
sock = network::receive_data(cfg);
|
||||
} catch(network::error& e) {
|
||||
std::cerr << "caught networking error. we are " << (network::is_server() ? "" : "NOT") << " a server\n";
|
||||
sock = 0;
|
||||
|
||||
bool changes = false;
|
||||
//if the problem isn't related to any specific connection,
|
||||
//it's a general error and we should just re-throw the error
|
||||
//likewise if we are not a server, we cannot afford any connection
|
||||
//to go down, so also re-throw the error
|
||||
if(!e.socket || !network::is_server()) {
|
||||
e.disconnect();
|
||||
throw network::error(e.message);
|
||||
}
|
||||
|
||||
//a socket has disconnected. Remove its positions.
|
||||
for(std::map<config*,network::connection>::iterator i = positions_.begin();
|
||||
i != positions_.end(); ++i) {
|
||||
if(i->second == e.socket) {
|
||||
changes = true;
|
||||
i->second = 0;
|
||||
i->first->values.erase("taken");
|
||||
bool changes = false;
|
||||
|
||||
// Add to combo list
|
||||
std::stringstream str;
|
||||
str << i->first->values["description"];
|
||||
//remove_player(str.str());
|
||||
i->first->values["description"]="";
|
||||
}
|
||||
}
|
||||
//a socket has disconnected. Remove its positions.
|
||||
for(std::map<config*,network::connection>::iterator i = positions_.begin();
|
||||
i != positions_.end(); ++i) {
|
||||
if(i->second == e.socket) {
|
||||
changes = true;
|
||||
i->second = 0;
|
||||
i->first->values.erase("taken");
|
||||
|
||||
//now disconnect the socket
|
||||
e.disconnect();
|
||||
// Add to combo list
|
||||
std::stringstream str;
|
||||
str << i->first->values["description"];
|
||||
//remove_player(str.str());
|
||||
i->first->values["description"]="";
|
||||
}
|
||||
}
|
||||
|
||||
//if there have been changes to the positions taken,
|
||||
//then notify other players
|
||||
if(changes) {
|
||||
//now disconnect the socket
|
||||
e.disconnect();
|
||||
|
||||
//if there have been changes to the positions taken,
|
||||
//then notify other players
|
||||
if(changes) {
|
||||
network::send_data(*level_);
|
||||
}
|
||||
}
|
||||
|
||||
//No network errors
|
||||
if(sock) {
|
||||
const int side_drop = atoi(cfg["side_drop"].c_str())-1;
|
||||
if(side_drop >= 0 && side_drop < int(sides.size())) {
|
||||
std::map<config*,network::connection>::iterator pos = positions_.find(sides[side_drop]);
|
||||
if(pos != positions_.end()) {
|
||||
pos->second = 0;
|
||||
pos->first->values.erase("taken");
|
||||
pos->first->values["description"] = "";
|
||||
network::send_data(*level_);
|
||||
}
|
||||
}
|
||||
|
||||
const int side_taken = atoi(cfg["side"].c_str())-1;
|
||||
if(side_taken >= 0 && side_taken < int(sides.size())) {
|
||||
std::map<config*,network::connection>::iterator pos = positions_.find(sides[side_taken]);
|
||||
if(pos != positions_.end()) {
|
||||
if(!pos->second) {
|
||||
std::cerr << "client has taken a valid position\n";
|
||||
|
||||
//broadcast to everyone the new game status
|
||||
pos->first->values["taken"] = "yes";
|
||||
pos->first->values["description"] = cfg["description"];
|
||||
pos->first->values["name"] = cfg["name"];
|
||||
pos->first->values["type"] = cfg["type"];
|
||||
pos->first->values["recruit"] = cfg["recruit"];
|
||||
pos->first->values["music"] = cfg["music"];
|
||||
positions_[sides[side_taken]] = sock;
|
||||
network::send_data(*level_);
|
||||
}
|
||||
}
|
||||
|
||||
//No network errors
|
||||
if(sock) {
|
||||
const int side_drop = atoi(cfg["side_drop"].c_str())-1;
|
||||
if(side_drop >= 0 && side_drop < int(sides.size())) {
|
||||
std::map<config*,network::connection>::iterator pos = positions_.find(sides[side_drop]);
|
||||
if(pos != positions_.end()) {
|
||||
pos->second = 0;
|
||||
pos->first->values.erase("taken");
|
||||
pos->first->values["description"] = "";
|
||||
network::send_data(*level_);
|
||||
}
|
||||
}
|
||||
std::cerr << "sent player data\n";
|
||||
|
||||
const int side_taken = atoi(cfg["side"].c_str())-1;
|
||||
if(side_taken >= 0 && side_taken < int(sides.size())) {
|
||||
std::map<config*,network::connection>::iterator pos = positions_.find(sides[side_taken]);
|
||||
if(pos != positions_.end()) {
|
||||
if(!pos->second) {
|
||||
std::cerr << "client has taken a valid position\n";
|
||||
//send a reply telling the client they have secured
|
||||
//the side they asked for
|
||||
std::stringstream side;
|
||||
side << (side_taken+1);
|
||||
config reply;
|
||||
reply.values["side_secured"] = side.str();
|
||||
std::cerr << "going to send data...\n";
|
||||
network::send_data(reply,sock);
|
||||
|
||||
//broadcast to everyone the new game status
|
||||
pos->first->values["taken"] = "yes";
|
||||
pos->first->values["description"] = cfg["description"];
|
||||
pos->first->values["name"] = cfg["name"];
|
||||
pos->first->values["type"] = cfg["type"];
|
||||
pos->first->values["recruit"] = cfg["recruit"];
|
||||
pos->first->values["music"] = cfg["music"];
|
||||
positions_[sides[side_taken]] = sock;
|
||||
network::send_data(*level_);
|
||||
|
||||
std::cerr << "sent player data\n";
|
||||
|
||||
//send a reply telling the client they have secured
|
||||
//the side they asked for
|
||||
std::stringstream side;
|
||||
side << (side_taken+1);
|
||||
config reply;
|
||||
reply.values["side_secured"] = side.str();
|
||||
std::cerr << "going to send data...\n";
|
||||
network::send_data(reply,sock);
|
||||
|
||||
// Add to combo list
|
||||
std::stringstream str;
|
||||
str << cfg["description"];
|
||||
add_player(str.str());
|
||||
} else {
|
||||
config response;
|
||||
response.values["failed"] = "yes";
|
||||
network::send_data(response,sock);
|
||||
}
|
||||
} else {
|
||||
std::cerr << "tried to take illegal side: " << side_taken << "\n";
|
||||
}
|
||||
// Add to combo list
|
||||
std::stringstream str;
|
||||
str << cfg["description"];
|
||||
add_player(str.str());
|
||||
} else {
|
||||
std::cerr << "tried to take unknown side: " << side_taken << "\n";
|
||||
config response;
|
||||
response.values["failed"] = "yes";
|
||||
network::send_data(response,sock);
|
||||
}
|
||||
} else {
|
||||
std::cerr << "tried to take illegal side: " << side_taken << "\n";
|
||||
}
|
||||
} else {
|
||||
std::cerr << "tried to take unknown side: " << side_taken << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
@ -28,11 +29,25 @@ partial_map::const_iterator current_connection = received_data.end();
|
|||
TCPsocket server_socket;
|
||||
|
||||
std::queue<network::connection> disconnection_queue;
|
||||
std::set<network::connection> bad_sockets;
|
||||
|
||||
}
|
||||
|
||||
namespace network {
|
||||
|
||||
error::error(const std::string& msg, connection sock) : message(msg), socket(sock)
|
||||
{
|
||||
bad_sockets.insert(socket);
|
||||
}
|
||||
|
||||
void error::disconnect()
|
||||
{
|
||||
bad_sockets.erase(socket);
|
||||
if(socket) {
|
||||
network::disconnect(socket);
|
||||
}
|
||||
}
|
||||
|
||||
manager::manager() : free_(true)
|
||||
{
|
||||
//if the network is already being managed
|
||||
|
@ -178,6 +193,9 @@ connection receive_data(config& cfg, connection connection_num, int timeout)
|
|||
throw error("",sock);
|
||||
}
|
||||
|
||||
if(bad_sockets.count(connection_num) || bad_sockets.count(0))
|
||||
return 0;
|
||||
|
||||
if(sockets.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -196,11 +214,8 @@ connection receive_data(config& cfg, connection connection_num, int timeout)
|
|||
char num_buf[4];
|
||||
size_t len = SDLNet_TCP_Recv(*i,num_buf,4);
|
||||
|
||||
if(len == 0) {
|
||||
if(len != 4) {
|
||||
throw error("Remote host disconnected",*i);
|
||||
} else if(len != 4) {
|
||||
std::cerr << "received bad packet length: " << len << "/4\n";
|
||||
throw error(std::string("network error receiving length data: ") + SDLNet_GetError(),*i);
|
||||
}
|
||||
|
||||
len = SDLNet_Read32(num_buf);
|
||||
|
@ -256,6 +271,9 @@ connection receive_data(config& cfg, connection connection_num, int timeout)
|
|||
|
||||
void send_data(const config& cfg, connection connection_num)
|
||||
{
|
||||
if(bad_sockets.count(connection_num) || bad_sockets.count(0))
|
||||
return;
|
||||
|
||||
log_scope("sending data");
|
||||
if(!connection_num) {
|
||||
std::cerr << "sockets: " << sockets.size() << "\n";
|
||||
|
@ -285,7 +303,7 @@ void send_data(const config& cfg, connection connection_num)
|
|||
value.size()+1);
|
||||
|
||||
if(res < int(value.size()+1)) {
|
||||
std::cerr << "sending data failed: " << res << "/" << value.size() << ": " << SDL_GetError() << "\n";
|
||||
std::cerr << "sending data failed: " << res << "/" << value.size() << "\n";
|
||||
throw error("Could not send data over socket",connection_num);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,12 +82,11 @@ std::pair<int,int> current_transfer_stats();
|
|||
|
||||
struct error
|
||||
{
|
||||
error(const std::string& msg, connection sock=0)
|
||||
: message(msg), socket(sock) {}
|
||||
error(const std::string& msg, connection sock=0);
|
||||
std::string message;
|
||||
connection socket;
|
||||
|
||||
void disconnect() { if(socket) { network::disconnect(socket); } }
|
||||
void disconnect();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -312,6 +312,9 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& game_config,
|
|||
sound::play_music(team_it->music());
|
||||
}
|
||||
|
||||
//goto this label if the type of a team (human/ai/networked) has changed mid-turn
|
||||
redo_turn:
|
||||
|
||||
if(!replaying && team_it->is_human()) {
|
||||
std::cerr << "is human...\n";
|
||||
|
||||
|
@ -366,10 +369,48 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& game_config,
|
|||
|
||||
for(;;) {
|
||||
network::connection res = network::receive_data(cfg);
|
||||
if(res && cfg.child("leave_game")) {
|
||||
if(res && cfg.child("leave_game") != NULL) {
|
||||
throw network::error("");
|
||||
}
|
||||
|
||||
//if a side has dropped out of the game.
|
||||
if(res && cfg["side_drop"] != "") {
|
||||
const size_t side = atoi(cfg["side_drop"].c_str())-1;
|
||||
if(side >= teams.size()) {
|
||||
std::cerr << "unknown side " << side << " is dropping game\n";
|
||||
throw network::error("");
|
||||
}
|
||||
|
||||
int action = 0;
|
||||
|
||||
//see if the side still has a leader alive. If they have
|
||||
//no leader, we assume they just want to be replaced by
|
||||
//the AI.
|
||||
const unit_map::const_iterator leader = find_leader(units,side+1);
|
||||
if(leader != units.end()) {
|
||||
std::vector<std::string> options;
|
||||
options.push_back(string_table["replace_ai_message"]);
|
||||
options.push_back(string_table["replace_local_message"]);
|
||||
options.push_back(string_table["abort_game_message"]);
|
||||
|
||||
const std::string msg = leader->second.description() + " " + string_table["player_leave_message"];
|
||||
action = gui::show_dialog(gui,NULL,"",msg,gui::OK_ONLY,&options);
|
||||
}
|
||||
|
||||
//make the player an AI, and redo this turn, in case
|
||||
//it was the current player's team who has just changed into
|
||||
//an AI.
|
||||
if(action == 0) {
|
||||
teams[side].make_ai();
|
||||
goto redo_turn;
|
||||
} else if(action == 1) {
|
||||
teams[side].make_human();
|
||||
goto redo_turn;
|
||||
} else {
|
||||
throw network::error("");
|
||||
}
|
||||
}
|
||||
|
||||
if(res && cfg.child("turn") != NULL) {
|
||||
//forward the data to other peers
|
||||
network::send_data_all_except(cfg,res);
|
||||
|
|
|
@ -16,7 +16,7 @@ bool game::is_member(network::connection player) const
|
|||
bool game::is_needed(network::connection player) const
|
||||
{
|
||||
assert(!players_.empty());
|
||||
return player == players_.front() || started_ && sides_.count(player);
|
||||
return player == players_.front();
|
||||
}
|
||||
|
||||
void game::start_game()
|
||||
|
@ -63,8 +63,7 @@ void game::remove_player(network::connection player)
|
|||
if(itor != players_.end())
|
||||
players_.erase(itor);
|
||||
|
||||
std::map<network::connection,std::string>::iterator side
|
||||
= sides_.find(player);
|
||||
std::map<network::connection,std::string>::iterator side = sides_.find(player);
|
||||
if(side != sides_.end()) {
|
||||
//send the host a notification of removal of this side
|
||||
if(players_.empty() == false) {
|
||||
|
|
|
@ -22,31 +22,45 @@ config construct_error(const std::string& msg)
|
|||
return cfg;
|
||||
}
|
||||
|
||||
void run_server()
|
||||
class server
|
||||
{
|
||||
const network::manager net_manager;
|
||||
const network::server_manager server;
|
||||
public:
|
||||
server();
|
||||
void run();
|
||||
private:
|
||||
void delete_game(std::vector<game>::iterator i);
|
||||
|
||||
config login_response;
|
||||
login_response.add_child("mustlogin");
|
||||
login_response["version"] = game_config::version;
|
||||
const network::manager net_manager_;
|
||||
const network::server_manager server_;
|
||||
|
||||
config initial_response;
|
||||
config& gamelist = initial_response.add_child("gamelist");
|
||||
config login_response_;
|
||||
|
||||
config initial_response_;
|
||||
|
||||
typedef std::map<network::connection,player> player_map;
|
||||
player_map players;
|
||||
player_map players_;
|
||||
|
||||
game not_logged_in;
|
||||
game lobby_players;
|
||||
std::vector<game> games;
|
||||
game not_logged_in_;
|
||||
game lobby_players_;
|
||||
std::vector<game> games_;
|
||||
};
|
||||
|
||||
server::server() : net_manager_(), server_()
|
||||
{
|
||||
login_response_.add_child("mustlogin");
|
||||
login_response_["version"] = game_config::version;
|
||||
}
|
||||
|
||||
void server::run()
|
||||
{
|
||||
config& gamelist = initial_response_.add_child("gamelist");
|
||||
|
||||
for(;;) {
|
||||
try {
|
||||
network::connection sock = network::accept_connection();
|
||||
if(sock) {
|
||||
network::send_data(login_response,sock);
|
||||
not_logged_in.add_player(sock);
|
||||
network::send_data(login_response_,sock);
|
||||
not_logged_in_.add_player(sock);
|
||||
}
|
||||
|
||||
config data;
|
||||
|
@ -57,7 +71,7 @@ void run_server()
|
|||
|
||||
//if someone who is not yet logged in is sending
|
||||
//login details
|
||||
if(not_logged_in.is_member(sock)) {
|
||||
if(not_logged_in_.is_member(sock)) {
|
||||
const config* const login = data.child("login");
|
||||
|
||||
//client must send a login first.
|
||||
|
@ -78,33 +92,33 @@ void run_server()
|
|||
|
||||
//check the username isn't already taken
|
||||
player_map::const_iterator p;
|
||||
for(p = players.begin(); p != players.end(); ++p) {
|
||||
for(p = players_.begin(); p != players_.end(); ++p) {
|
||||
if(p->second.name() == username) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(p != players.end()) {
|
||||
if(p != players_.end()) {
|
||||
network::send_data(construct_error(
|
||||
"This username is already taken"),sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
config* const player_cfg = &initial_response.add_child("user");
|
||||
config* const player_cfg = &initial_response_.add_child("user");
|
||||
const player new_player(username,*player_cfg);
|
||||
players.insert(std::pair<network::connection,player>(sock,new_player));
|
||||
players_.insert(std::pair<network::connection,player>(sock,new_player));
|
||||
|
||||
//remove player from the not-logged-in list and place
|
||||
//the player in the lobby
|
||||
not_logged_in.remove_player(sock);
|
||||
lobby_players.add_player(sock);
|
||||
not_logged_in_.remove_player(sock);
|
||||
lobby_players_.add_player(sock);
|
||||
|
||||
//currently update user list to all players who are in lobby
|
||||
//(later may optimize to only send new login information
|
||||
//to all but the new player)
|
||||
lobby_players.send_data(initial_response);
|
||||
lobby_players_.send_data(initial_response_);
|
||||
|
||||
} else if(lobby_players.is_member(sock)) {
|
||||
} else if(lobby_players_.is_member(sock)) {
|
||||
const config* const create_game = data.child("create_game");
|
||||
if(create_game != NULL) {
|
||||
|
||||
|
@ -112,15 +126,15 @@ void run_server()
|
|||
|
||||
//create the new game, remove the player from the
|
||||
//lobby and put him/her in the game they have created
|
||||
games.push_back(game());
|
||||
lobby_players.remove_player(sock);
|
||||
games.back().add_player(sock);
|
||||
games_.push_back(game());
|
||||
lobby_players_.remove_player(sock);
|
||||
games_.back().add_player(sock);
|
||||
|
||||
//store the game data here at the moment
|
||||
games.back().level() = *create_game;
|
||||
games_.back().level() = *create_game;
|
||||
std::stringstream converter;
|
||||
converter << games.back().id();
|
||||
games.back().level()["id"] = converter.str();
|
||||
converter << games_.back().id();
|
||||
games_.back().level()["id"] = converter.str();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -131,14 +145,14 @@ void run_server()
|
|||
const std::string& id = (*join)["id"];
|
||||
const int nid = atoi(id.c_str());
|
||||
const std::vector<game>::iterator it =
|
||||
std::find_if(games.begin(),games.end(),
|
||||
std::find_if(games_.begin(),games_.end(),
|
||||
game_id_matches(nid));
|
||||
if(it == games.end()) {
|
||||
if(it == games_.end()) {
|
||||
std::cerr << "attempt to join unknown game\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
lobby_players.remove_player(sock);
|
||||
lobby_players_.remove_player(sock);
|
||||
|
||||
//send them the game data
|
||||
network::send_data(it->level(),sock);
|
||||
|
@ -150,21 +164,20 @@ void run_server()
|
|||
//of the sender, and forward it to all players in the lobby
|
||||
config* const message = data.child("message");
|
||||
if(message != NULL) {
|
||||
const player_map::const_iterator p = players.find(sock);
|
||||
assert(p != players.end());
|
||||
const player_map::const_iterator p = players_.find(sock);
|
||||
assert(p != players_.end());
|
||||
(*message)["sender"] = p->second.name();
|
||||
lobby_players.send_data(data);
|
||||
lobby_players_.send_data(data);
|
||||
}
|
||||
|
||||
} else {
|
||||
std::vector<game>::iterator g;
|
||||
for(g = games.begin(); g != games.end(); ++g) {
|
||||
for(g = games_.begin(); g != games_.end(); ++g) {
|
||||
if(g->is_member(sock))
|
||||
break;
|
||||
}
|
||||
|
||||
if(g == games.end()) {
|
||||
std::cerr << "ERROR: unknown socket " << games.size() << "\n";
|
||||
if(g == games_.end()) {
|
||||
std::cerr << "ERROR: unknown socket " << games_.size() << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -186,7 +199,7 @@ void run_server()
|
|||
g->set_description(&desc);
|
||||
|
||||
//send all players in the lobby the list of games
|
||||
lobby_players.send_data(initial_response);
|
||||
lobby_players_.send_data(initial_response_);
|
||||
}
|
||||
|
||||
//record the new level data, and send to all players
|
||||
|
@ -218,7 +231,7 @@ void run_server()
|
|||
} else if(data.child("leave_game")) {
|
||||
const bool needed = g->is_needed(sock);
|
||||
g->remove_player(sock);
|
||||
lobby_players.add_player(sock);
|
||||
lobby_players_.add_player(sock);
|
||||
|
||||
if(needed) {
|
||||
|
||||
|
@ -229,7 +242,7 @@ void run_server()
|
|||
g->send_data(cfg);
|
||||
|
||||
//delete the game's description
|
||||
config* const gamelist = initial_response.child("gamelist");
|
||||
config* const gamelist = initial_response_.child("gamelist");
|
||||
assert(gamelist != NULL);
|
||||
const config::child_itors vg = gamelist->child_range("game");
|
||||
|
||||
|
@ -241,13 +254,13 @@ void run_server()
|
|||
|
||||
//put the players back in the lobby and send
|
||||
//them the game list and user list again
|
||||
g->send_data(initial_response);
|
||||
lobby_players.add_players(*g);
|
||||
games.erase(g);
|
||||
g->send_data(initial_response_);
|
||||
lobby_players_.add_players(*g);
|
||||
games_.erase(g);
|
||||
}
|
||||
|
||||
//send the player who has quit the new game list
|
||||
network::send_data(initial_response,sock);
|
||||
network::send_data(initial_response_,sock);
|
||||
|
||||
continue;
|
||||
} else if(data["side_secured"].empty() == false) {
|
||||
|
@ -271,37 +284,21 @@ void run_server()
|
|||
} else {
|
||||
std::cerr << "socket closed: " << e.message << "\n";
|
||||
|
||||
const std::map<network::connection,player>::iterator pl_it =
|
||||
players.find(e.socket);
|
||||
if(pl_it != players.end()) {
|
||||
const config::child_list& users = initial_response.get_children("user");
|
||||
const std::map<network::connection,player>::iterator pl_it = players_.find(e.socket);
|
||||
if(pl_it != players_.end()) {
|
||||
const config::child_list& users = initial_response_.get_children("user");
|
||||
const size_t index = std::find(users.begin(),users.end(),pl_it->second.config_address()) - users.begin();
|
||||
if(index < users.size())
|
||||
initial_response.remove_child("user",index);
|
||||
initial_response_.remove_child("user",index);
|
||||
|
||||
players.erase(pl_it);
|
||||
players_.erase(pl_it);
|
||||
}
|
||||
|
||||
not_logged_in.remove_player(e.socket);
|
||||
lobby_players.remove_player(e.socket);
|
||||
for(std::vector<game>::iterator i = games.begin();
|
||||
i != games.end(); ++i) {
|
||||
not_logged_in_.remove_player(e.socket);
|
||||
lobby_players_.remove_player(e.socket);
|
||||
for(std::vector<game>::iterator i = games_.begin(); i != games_.end(); ++i) {
|
||||
if(i->is_needed(e.socket)) {
|
||||
|
||||
//delete the game's configuration
|
||||
config* const gamelist =
|
||||
initial_response.child("gamelist");
|
||||
assert(gamelist != NULL);
|
||||
const config::child_itors vg = gamelist->child_range("game");
|
||||
const config::child_list::iterator g = std::find(vg.first,vg.second,i->description());
|
||||
if(g != vg.second) {
|
||||
const size_t index = g - vg.first;
|
||||
delete *g;
|
||||
gamelist->remove_child("game",index);
|
||||
}
|
||||
|
||||
i->disconnect();
|
||||
games.erase(i);
|
||||
delete_game(i);
|
||||
e.socket = 0;
|
||||
break;
|
||||
} else {
|
||||
|
@ -315,7 +312,7 @@ void run_server()
|
|||
|
||||
//send all players the information that a player has logged
|
||||
//out of the system
|
||||
lobby_players.send_data(initial_response);
|
||||
lobby_players_.send_data(initial_response_);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -328,10 +325,27 @@ void run_server()
|
|||
}
|
||||
}
|
||||
|
||||
void server::delete_game(std::vector<game>::iterator i)
|
||||
{
|
||||
//delete the game's configuration
|
||||
config* const gamelist = initial_response_.child("gamelist");
|
||||
assert(gamelist != NULL);
|
||||
const config::child_itors vg = gamelist->child_range("game");
|
||||
const config::child_list::iterator g = std::find(vg.first,vg.second,i->description());
|
||||
if(g != vg.second) {
|
||||
const size_t index = g - vg.first;
|
||||
delete *g;
|
||||
gamelist->remove_child("game",index);
|
||||
}
|
||||
|
||||
i->disconnect();
|
||||
games_.erase(i);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try {
|
||||
run_server();
|
||||
server().run();
|
||||
} catch(network::error& e) {
|
||||
std::cerr << "error starting server: " << e.message << "\n";
|
||||
return -1;
|
||||
|
|
15
src/team.cpp
15
src/team.cpp
|
@ -376,6 +376,21 @@ bool team::is_network() const
|
|||
return info_.controller == team_info::NETWORK;
|
||||
}
|
||||
|
||||
void team::make_human()
|
||||
{
|
||||
info_.controller = team_info::HUMAN;
|
||||
}
|
||||
|
||||
void team::make_ai()
|
||||
{
|
||||
info_.controller = team_info::AI;
|
||||
}
|
||||
|
||||
void team::make_network()
|
||||
{
|
||||
info_.controller = team_info::NETWORK;
|
||||
}
|
||||
|
||||
double team::leader_value() const
|
||||
{
|
||||
return info_.leader_value;
|
||||
|
|
|
@ -90,6 +90,10 @@ public:
|
|||
bool is_network() const;
|
||||
bool is_ai() const;
|
||||
|
||||
void make_human();
|
||||
void make_network();
|
||||
void make_ai();
|
||||
|
||||
double leader_value() const;
|
||||
double village_value() const;
|
||||
|
||||
|
|
|
@ -331,8 +331,9 @@ void menu::draw_item(int item)
|
|||
if(buffer_.get() != NULL) {
|
||||
const int ypos = items_start()+(item-first_item_on_screen_)*rect.h;
|
||||
SDL_Rect srcrect = {0,ypos,rect.w,rect.h};
|
||||
SDL_Rect dstrect = rect;
|
||||
SDL_BlitSurface(buffer_,&srcrect,
|
||||
display_->video().getSurface(),&rect);
|
||||
display_->video().getSurface(),&dstrect);
|
||||
}
|
||||
|
||||
gui::draw_solid_tinted_rectangle(x_,rect.y,width(),rect.h,
|
||||
|
@ -340,7 +341,7 @@ void menu::draw_item(int item)
|
|||
item == selected_ ? 0.6 : 0.2,
|
||||
display_->video().getSurface());
|
||||
|
||||
SDL_Rect area = {0,0,display_->x(),display_->y()};
|
||||
SDL_Rect area = display_->screen_area();
|
||||
|
||||
const std::vector<int>& widths = column_widths();
|
||||
|
||||
|
@ -420,6 +421,8 @@ SDL_Rect menu::get_item_rect(int item) const
|
|||
if(x_ > 0 && y_ > 0)
|
||||
itemRects_.insert(std::pair<int,SDL_Rect>(item,res));
|
||||
|
||||
std::cerr << "item " << item << " is " << res.w << "," << res.h << "\n";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue