00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "../global.hpp"
00016
00017 #include "../game_config.hpp"
00018 #include "../log.hpp"
00019 #include "../map.hpp"
00020
00021 #include "game.hpp"
00022 #include "player.hpp"
00023
00024 #include <algorithm>
00025 #include <iostream>
00026 #include <memory>
00027 #include <cassert>
00028 #include <sstream>
00029
00030 #define ERR_GAME LOG_STREAM(err, mp_server)
00031 #define WRN_GAME LOG_STREAM(warn, mp_server)
00032 #define LOG_GAME LOG_STREAM(info, mp_server)
00033 #define DBG_GAME LOG_STREAM(debug, mp_server)
00034
00035 namespace chat_message {
00036
00037 const size_t max_message_length = 256;
00038 static void truncate_message(const simple_wml::string_span& str, simple_wml::node& message) {
00039
00040
00041 if(str.size() > chat_message::max_message_length) {
00042 std::string tmp(str.begin(), str.end());
00043
00044
00045 utils::truncate_as_wstring(tmp, max_message_length);
00046 message.set_attr_dup("message", tmp.c_str());
00047 }
00048 }
00049
00050 }
00051
00052 int game::id_num = 1;
00053
00054 game::game(player_map& players, const network::connection host, const std::string name)
00055 : player_info_(&players), id_(id_num++), name_(name), owner_(host),
00056 sides_(gamemap::MAX_PLAYERS), sides_taken_(gamemap::MAX_PLAYERS),
00057 side_controllers_(gamemap::MAX_PLAYERS), nsides_(0), started_(false),
00058 description_(NULL), end_turn_(0), all_observers_muted_(false)
00059 {
00060
00061 if (owner_ == 0) return;
00062 players_.push_back(owner_);
00063 const player_map::iterator pl = player_info_->find(owner_);
00064 if (pl == player_info_->end()) {
00065 ERR_GAME << "ERROR: Could not find host in player_info_. (socket: "
00066 << owner_ << ")\n";
00067 return;
00068 }
00069
00070 pl->second.mark_available(id_, name_);
00071
00072 }
00073
00074 game::~game()
00075 {
00076 for(std::vector<simple_wml::document*>::iterator i = history_.begin(); i != history_.end(); ++i) {
00077 delete *i;
00078 }
00079 }
00080
00081 bool game::allow_observers() const {
00082 return level_["observer"].to_bool(true);
00083 }
00084
00085 bool game::is_observer(const network::connection player) const {
00086 return std::find(observers_.begin(),observers_.end(),player) != observers_.end();
00087 }
00088
00089 bool game::is_muted_observer(const network::connection player) const {
00090 if (is_observer(player)) {
00091 if (all_observers_muted_) return true;
00092 } else {
00093 return false;
00094 }
00095 return std::find(muted_observers_.begin(), muted_observers_.end(), player)
00096 != muted_observers_.end();
00097 }
00098
00099 bool game::is_player(const network::connection player) const {
00100 return std::find(players_.begin(),players_.end(),player) != players_.end();
00101 }
00102
00103 namespace {
00104 std::string describe_turns(int turn, const simple_wml::string_span& num_turns)
00105 {
00106 char buf[50];
00107 snprintf(buf,sizeof(buf),"%d/",int(turn));
00108
00109 if(num_turns == "-1") {
00110 return buf + std::string("-");
00111 } else {
00112 return buf + std::string(num_turns.begin(), num_turns.end());
00113 }
00114 }
00115
00116 }
00117
00118 void game::start_game(const player_map::const_iterator starter) {
00119
00120 const bool advance = started_;
00121 started_ = true;
00122
00123 const simple_wml::node& s = level_.root();
00124 const bool save = s["savegame"].to_bool();
00125 LOG_GAME << network::ip_address(starter->first) << "\t"
00126 << starter->second.name() << "\t" << (advance ? "advanced" : "started")
00127 << (save ? " reloaded" : "") << " game:\t\"" << name_ << "\" (" << id_
00128 << "). Settings: map: " << s["id"]
00129 << "\tera: " << (s.child("era") ? (*s.child("era"))["id"] : "")
00130 << "\tXP: " << s["experience_modifier"]
00131 << "\tGPV: " << s["mp_village_gold"]
00132 << "\tfog: " << s["mp_fog"]
00133 << "\tshroud: " << s["mp_shroud"]
00134 << "\tobservers: " << s["observer"]
00135 << "\ttimer: " << s["mp_countdown"]
00136 << (s["mp_countdown"].to_bool() ?
00137 "\treservoir time: " + s["mp_countdown_reservoir_time"].to_string() +
00138 "\tinit time: " + s["mp_countdown_init_time"].to_string() +
00139 "\taction bonus: " + s["mp_countdown_action_bonus"].to_string() +
00140 "\tturn bonus: " + s["mp_countdown_turn_bonus"].to_string() : "")
00141 << "\n";
00142
00143 nsides_ = 0;
00144
00145
00146
00147 const simple_wml::node::child_list& sides = level_.root().children("side");
00148 for(simple_wml::node::child_list::const_iterator s = sides.begin(); s != sides.end(); ++s) {
00149 nsides_++;
00150 if((**s)["controller"] != "null" && !advance) {
00151 (*s)->set_attr("controller", "human");
00152 }
00153 }
00154
00155 DBG_GAME << "Number of sides: " << nsides_ << "\n";
00156 int turn = 1;
00157 int side = 0;
00158
00159 if (s.child("snapshot")) {
00160 turn = lexical_cast_default<int>((*s.child("snapshot"))["turn_at"], 1);
00161 side = lexical_cast_default<int>((*s.child("snapshot"))["playing_team"], 0);
00162 LOG_GAME << "Reload from turn: " << turn
00163 << ". Current side is: " << side + 1 << ".\n";
00164 }
00165 end_turn_ = (turn - 1) * nsides_ + side - 1;
00166 end_turn();
00167 history_.clear();
00168 if (advance) {
00169
00170 update_side_data();
00171
00172
00173 static simple_wml::document notify_next_scenario("[notify_next_scenario]\n[/notify_next_scenario]\n", simple_wml::INIT_COMPRESSED);
00174 send_data(notify_next_scenario, starter->first);
00175 }
00176
00177 send_observerjoins();
00178 }
00179
00180
00181
00182
00183
00184
00185
00186 bool game::take_side(const player_map::const_iterator user)
00187 {
00188 DBG_GAME << "take_side...\n";
00189 DBG_GAME << debug_player_info();
00190
00191 if (started_) return false;
00192
00193 simple_wml::document cfg;
00194 cfg.root().set_attr_dup("name", user->second.name().c_str());
00195 cfg.root().set_attr("faction", "random");
00196 cfg.root().set_attr("leader", "random");
00197 cfg.root().set_attr("gender", "random");
00198
00199 size_t side_num;
00200
00201 const simple_wml::node::child_list& sides = level_.root().children("side");
00202 for(simple_wml::node::child_list::const_iterator side = sides.begin(); side != sides.end(); ++side) {
00203 if((**side)["controller"] == "network"
00204 && ((**side)["save_id"] == user->second.name().c_str()
00205 || (**side)["current_player"] == user->second.name().c_str()))
00206 {
00207 side_num = (**side)["side"].to_int();
00208 if (side_num < 1 || side_num > gamemap::MAX_PLAYERS) continue;
00209 if (sides_taken_[side_num - 1]) continue;
00210 side_controllers_[side_num - 1] = "network";
00211 sides_[side_num - 1] = user->first;
00212 sides_taken_[side_num - 1] = true;
00213 cfg.root().set_attr_dup("side", (**side)["side"]);
00214
00215
00216 simple_wml::string_span data = cfg.output_compressed();
00217 network::send_raw_data(data.begin(), data.size(), owner_);
00218 DBG_GAME << "take_side: took side " << side_num << " because the name matched\n";
00219 DBG_GAME << debug_player_info();
00220 return true;
00221 }
00222 }
00223
00224 for(simple_wml::node::child_list::const_iterator side = sides.begin(); side != sides.end(); ++side) {
00225 if((**side)["controller"] == "network") {
00226
00227 try {
00228 side_num = (**side)["side"].to_int();
00229 } catch (bad_lexical_cast&) { continue; }
00230 if (side_num < 1 || side_num > gamemap::MAX_PLAYERS) continue;
00231 if (sides_taken_[side_num - 1]) continue;
00232
00233 side_controllers_[side_num - 1] = "network";
00234 sides_[side_num - 1] = user->first;
00235 sides_taken_[side_num - 1] = true;
00236 cfg.root().set_attr_dup("side", (**side)["side"]);
00237
00238 simple_wml::string_span data = cfg.output_compressed();
00239 network::send_raw_data(data.begin(), data.size(), owner_);
00240 DBG_GAME << "take_side: took the first free network side which was " << side_num << "\n";
00241 DBG_GAME << debug_player_info();
00242 return true;
00243 }
00244 }
00245 DBG_GAME << "take_side: there are no more sides available\n";
00246
00247 return false;
00248 }
00249
00250
00251 void game::update_side_data() {
00252 DBG_GAME << "update_side_data...\n";
00253 DBG_GAME << debug_player_info();
00254
00255 const user_vector users = all_game_users();
00256
00257 side_controllers_.clear();
00258 side_controllers_.resize(gamemap::MAX_PLAYERS);
00259 sides_taken_.clear();
00260
00261 sides_taken_.resize(gamemap::MAX_PLAYERS);
00262 sides_.clear();
00263 sides_.resize(gamemap::MAX_PLAYERS);
00264 players_.clear();
00265 observers_.clear();
00266
00267 const simple_wml::node::child_list& level_sides = level_.root().children("side");
00268
00269
00270
00271
00272
00273
00274 for (user_vector::const_iterator user = users.begin(); user != users.end(); ++user) {
00275 const player_map::const_iterator info = player_info_->find(*user);
00276 if (info == player_info_->end()) {
00277 ERR_GAME << "Game: " << id_
00278 << " ERROR: unable to find user info for connection: "
00279 << *user << "\n";
00280 continue;
00281 }
00282
00283 bool side_found = false;
00284 for (simple_wml::node::child_list::const_iterator side = level_sides.begin();
00285 side != level_sides.end(); ++side)
00286 {
00287 size_t side_num = (**side)["side"].to_int();
00288 if (side_num < 1 || side_num > gamemap::MAX_PLAYERS
00289 || sides_taken_[side_num - 1]) continue;
00290
00291 if ((**side)["controller"] == "network") {
00292 side_controllers_[side_num - 1] = "network";
00293 if ((**side)["current_player"] == info->second.name().c_str()) {
00294 sides_[side_num - 1] = *user;
00295 sides_taken_[side_num - 1] = true;
00296 side_found = true;
00297 } else sides_taken_[side_num - 1] = false;
00298 } else if ((**side)["controller"] == "ai") {
00299 side_controllers_[side_num - 1] = "ai";
00300 sides_[side_num - 1] = owner_;
00301 sides_taken_[side_num - 1] = true;
00302 side_found = true;
00303 } else if ((**side)["controller"] == "human") {
00304 side_controllers_[side_num - 1] = "human";
00305 sides_[side_num - 1] = owner_;
00306 sides_taken_[side_num - 1] = true;
00307 side_found = true;
00308 } else if ((**side)["controller"] == "null") {
00309 side_controllers_[side_num - 1] = "null";
00310 }
00311 }
00312 if (side_found) {
00313 players_.push_back(*user);
00314 } else {
00315 observers_.push_back(*user);
00316 }
00317 }
00318 DBG_GAME << debug_player_info();
00319 }
00320
00321 void game::transfer_side_control(const network::connection sock, const simple_wml::node& cfg) {
00322 DBG_GAME << "transfer_side_control...\n";
00323 if (!is_player(sock) && sock != owner_) {
00324 send_server_message("You cannot change controllers: not a player.", sock);
00325 return;
00326 }
00327
00328
00329 const user_vector::iterator pl = std::find(players_.begin(), players_.end(), sock);
00330 if (pl == players_.end()) {
00331 ERR_GAME << "ERROR: Not a player of this game. (socket: " << sock << ")\n";
00332 return;
00333 }
00334 const simple_wml::string_span& newplayer_name = cfg["player"];
00335
00336 player_map::const_iterator newplayer;
00337 for (newplayer = player_info_->begin(); newplayer != player_info_->end(); newplayer++) {
00338 if (newplayer_name == newplayer->second.name().c_str()) {
00339 break;
00340 }
00341 }
00342
00343 if (newplayer == player_info_->end() || !is_member(newplayer->first)) {
00344 send_server_message("Player/Observer not in this game", sock);
00345 return;
00346 }
00347
00348 const unsigned int side_num = cfg["side"].to_int();
00349 if(side_num < 1 || side_num > gamemap::MAX_PLAYERS) {
00350 std::ostringstream msg;
00351 msg << "The side number has to be between 1 and "
00352 << gamemap::MAX_PLAYERS << ".";
00353 send_server_message(msg.str().c_str(), sock);
00354 return;
00355 }
00356
00357 if (side_num > level_.root().children("side").size()) {
00358 send_server_message("Invalid side number.", sock);
00359 return;
00360 }
00361
00362 network::connection old_player = sides_[side_num - 1];
00363 const std::string old_player_name =
00364 (player_info_->find(old_player) != player_info_->end()
00365 ? player_info_->find(old_player)->second.name() : "");
00366
00367 if (sock != old_player && sock != owner_) {
00368 std::stringstream msg;
00369 msg << "You can't give away side " << side_num << ". It's controlled by '"
00370 << old_player_name << "' not you.";
00371 DBG_GAME << msg.str() << "\n";
00372 send_server_message(msg.str().c_str(), sock);
00373 return;
00374 }
00375 if (newplayer->first == old_player) {
00376 std::stringstream msg;
00377 msg << "That's already " << newplayer_name << "'s side, silly.";
00378 send_server_message(msg.str().c_str(), sock);
00379 return;
00380 }
00381 sides_[side_num - 1] = 0;
00382 bool host_leave = false;
00383
00384 if (std::find(sides_.begin(), sides_.end(), old_player) == sides_.end()) {
00385 observers_.push_back(old_player);
00386 players_.erase(std::remove(players_.begin(), players_.end(), old_player), players_.end());
00387
00388 send_and_record_server_message((old_player_name + " becomes an observer.").c_str());
00389
00390 simple_wml::document observer_join;
00391 observer_join.root().add_child("observer").set_attr_dup("name", old_player_name.c_str());
00392 send_data(observer_join, old_player);
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 }
00404 side_controllers_[side_num - 1] = "network";
00405 sides_taken_[side_num - 1] = true;
00406 sides_[side_num - 1] = newplayer->first;
00407
00408 send_change_controller(side_num, newplayer, false);
00409 if (host_leave) transfer_ai_sides();
00410
00411
00412 if (is_observer(newplayer->first)) {
00413 players_.push_back(newplayer->first);
00414 observers_.erase(std::remove(observers_.begin(), observers_.end(), newplayer->first), observers_.end());
00415
00416 send_observerquit(newplayer);
00417 }
00418 }
00419
00420
00421 void game::send_change_controller(const size_t side_num,
00422 const player_map::const_iterator newplayer, const bool player_left)
00423 {
00424 if (newplayer == player_info_->end()) {
00425 return;
00426 }
00427
00428 const std::string& side = lexical_cast<std::string, size_t>(side_num);
00429 if (started_) {
00430 send_and_record_server_message((newplayer->second.name()
00431 + " takes control of side " + side + ".").c_str());
00432 }
00433
00434 simple_wml::document response;
00435 simple_wml::node& change = response.root().add_child("change_controller");
00436
00437 change.set_attr("side", side.c_str());
00438 change.set_attr("player", newplayer->second.name().c_str());
00439
00440
00441 change.set_attr("controller", "network");
00442 send_data(response, newplayer->first);
00443
00444
00445
00446
00447 if (!player_left) {
00448 change.set_attr("controller", "human");
00449 send_to_one(response, newplayer->first);
00450 }
00451
00452
00453 const simple_wml::node::child_list& side_list = level_.root().children("side");
00454 const unsigned int index = side_num - 1;
00455 assert(index < side_list.size());
00456 side_list[index]->set_attr_dup("current_player", newplayer->second.name().c_str());
00457 }
00458
00459 void game::transfer_ai_sides() {
00460 bool ai_transfer = false;
00461
00462 for (size_t side = 0; side < side_controllers_.size(); ++side){
00463
00464 if (side_controllers_[side] != "ai") continue;
00465
00466 ai_transfer = true;
00467 simple_wml::document drop;
00468 const std::string side_drop = lexical_cast<std::string, size_t>(side + 1);
00469 drop.root().set_attr("side_drop", side_drop.c_str());
00470 drop.root().set_attr("controller", "ai");
00471 const simple_wml::string_span data = drop.output_compressed();
00472 network::send_raw_data(data.begin(), data.size(), owner_);
00473 sides_[side] = owner_;
00474 }
00475 if (ai_transfer) {
00476 send_and_record_server_message("AI sides transferred to new host.");
00477 }
00478 }
00479
00480 void game::notify_new_host(){
00481 const std::string owner_name =
00482 (player_info_->find(owner_) != player_info_->end()
00483 ? player_info_->find(owner_)->second.name() : "");
00484 simple_wml::document cfg;
00485 simple_wml::node& cfg_host_transfer = cfg.root().add_child("host_transfer");
00486
00487
00488 cfg_host_transfer.set_attr("name", owner_name.c_str());
00489 cfg_host_transfer.set_attr("value", "1");
00490 const simple_wml::string_span data = cfg.output_compressed();
00491 network::send_raw_data(data.begin(), data.size(), owner_);
00492 send_and_record_server_message((owner_name
00493 + " has been chosen as the new host.").c_str());
00494 }
00495
00496 bool game::describe_slots() {
00497 if(started_ || description_ == NULL)
00498 return false;
00499
00500 int available_slots = 0;
00501 int num_sides = level_.root().children("side").size();
00502 int i = 0;
00503 const simple_wml::node::child_list& side_list = level_.root().children("side");
00504 for(simple_wml::node::child_list::const_iterator it = side_list.begin(); it != side_list.end(); ++it, ++i) {
00505 if (((**it)["allow_player"].to_bool(true) == false) || (**it)["controller"] == "null") {
00506 num_sides--;
00507 } else {
00508 if (!sides_taken_[i])
00509 available_slots++;
00510 }
00511 }
00512 char buf[50];
00513 snprintf(buf,sizeof(buf), "%d/%d", available_slots, num_sides);
00514
00515 if ((*description_)["slots"] != buf) {
00516 description_->set_attr_dup("slots", buf);
00517 return true;
00518 } else {
00519 return false;
00520 }
00521 }
00522
00523
00524 bool game::player_is_banned(const network::connection sock) const {
00525 std::vector<std::string>::const_iterator ban =
00526 std::find(bans_.begin(), bans_.end(), network::ip_address(sock));
00527 return ban != bans_.end();
00528 }
00529
00530 void game::mute_all_observers() {
00531 all_observers_muted_ = !all_observers_muted_;
00532 if (all_observers_muted_) {
00533 send_and_record_server_message("All observers have been muted.");
00534 } else {
00535 send_and_record_server_message("Muting of all observers has been removed.");
00536 }
00537 }
00538
00539
00540
00541 void game::mute_observer(const simple_wml::node& mute, const player_map::const_iterator muter) {
00542 if (muter->first != owner_) {
00543 send_server_message("You cannot mute: not the game host.", muter->first);
00544 return;
00545 }
00546 const simple_wml::string_span& name = mute["username"];
00547 if (name.empty()) {
00548 if (all_observers_muted_) {
00549 send_server_message("All observers are muted.", muter->first);
00550 return;
00551 }
00552 std::string muted_nicks = "";
00553 for (user_vector::const_iterator muted_obs = muted_observers_.begin();
00554 muted_obs != muted_observers_.end(); ++muted_obs)
00555 {
00556 if (muted_nicks != "") {
00557 muted_nicks += ", ";
00558 }
00559 muted_nicks += player_info_->find(*muted_obs)->second.name();
00560 }
00561
00562 send_server_message(("Muted observers: " + muted_nicks).c_str(), muter->first);
00563 return;
00564 }
00565 const player_map::const_iterator user = find_user(name);
00566
00567
00568 if (user == player_info_->end() || !is_observer(user->first)) {
00569 send_server_message("Observer not found.", muter->first);
00570 return;
00571 }
00572
00573 if (user->first == muter->first) {
00574 send_server_message("Don't mute yourself, silly.", muter->first);
00575 return;
00576 }
00577 if (is_muted_observer(user->first)) {
00578 send_server_message((user->second.name() + " is already muted.").c_str(), muter->first);
00579 return;
00580 }
00581 muted_observers_.push_back(user->first);
00582 LOG_GAME << network::ip_address(muter->first) << "\t"
00583 << muter->second.name() << " muted: " << user->second.name()
00584 << "\tfrom game:\t\"" << name_ << "\" (" << id_ << ")\n";
00585 send_and_record_server_message((user->second.name() + " has been muted.").c_str());
00586 }
00587
00588
00589
00590 network::connection game::kick_member(const simple_wml::node& kick,
00591 const player_map::const_iterator kicker)
00592 {
00593 if (kicker->first != owner_) {
00594 send_server_message("You cannot kick: not the game host", kicker->first);
00595 return 0;
00596 }
00597 const simple_wml::string_span& name = kick["username"];
00598 const player_map::const_iterator user = find_user(name);
00599 if (user == player_info_->end() || !is_member(user->first)) {
00600 send_server_message("Not a member of this game.", kicker->first);
00601 return 0;
00602 }
00603 if (user->first == kicker->first) {
00604 send_server_message("Don't kick yourself, silly.", kicker->first);
00605 return 0;
00606 }
00607 LOG_GAME << network::ip_address(kicker->first) << "\t"
00608 << kicker->second.name() << "\tkicked: " << user->second.name()
00609 << "\tfrom game:\t\"" << name_ << "\" (" << id_ << ")\n";
00610 send_and_record_server_message((name.to_string() + " has been kicked.").c_str());
00611
00612
00613 static simple_wml::document leave_game("[leave_game]\n[/leave_game]\n", simple_wml::INIT_COMPRESSED);
00614 static const simple_wml::string_span leave_game_data = leave_game.output_compressed();
00615 network::send_raw_data(leave_game_data.begin(), leave_game_data.size(), user->first);
00616 remove_player(user->first);
00617 return user->first;
00618 }
00619
00620
00621
00622
00623
00624 network::connection game::ban_user(const simple_wml::node& ban,
00625 const player_map::const_iterator banner)
00626 {
00627 if (banner->first != owner_) {
00628 send_server_message("You cannot ban: not the game host", banner->first);
00629 return 0;
00630 }
00631 const simple_wml::string_span& name = ban["username"];
00632 const player_map::const_iterator user = find_user(name);
00633 if (user == player_info_->end()) {
00634 send_server_message("User not found", banner->first);
00635 return 0;
00636 }
00637 if (user->first == banner->first) {
00638 send_server_message("Don't ban yourself, silly.", banner->first);
00639 return 0;
00640 }
00641 if (player_is_banned(user->first)) {
00642 std::ostringstream stream;
00643 stream << name << " is already banned.";
00644 send_server_message(stream.str().c_str(), banner->first);
00645 return 0;
00646 }
00647 LOG_GAME << network::ip_address(banner->first) << "\t"
00648 << banner->second.name() << "\tbanned: " << name << "\tfrom game:\t"
00649 << name_ << "\" (" << id_ << ")\n";
00650 bans_.push_back(network::ip_address(user->first));
00651 send_and_record_server_message((name.to_string() + " has been banned.").c_str());
00652 if (is_member(user->first)) {
00653
00654 static simple_wml::document leave_game("[leave_game]\n[/leave_game]\n", simple_wml::INIT_COMPRESSED);
00655 static const simple_wml::string_span leave_game_data = leave_game.output_compressed();
00656 network::send_raw_data(leave_game_data.begin(), leave_game_data.size(), user->first);
00657 remove_player(user->first);
00658 return user->first;
00659 }
00660
00661 return 0;
00662 }
00663
00664 void game::process_message(simple_wml::document& data, const player_map::iterator user) {
00665
00666 if (owner_ != 0) {
00667 } else if (user->second.silenced()) {
00668 return;
00669 } else if (user->second.is_message_flooding()) {
00670 send_server_message(
00671 "Warning: you are sending too many messages too fast. "
00672 "Your message has not been relayed.", user->first);
00673 return;
00674 }
00675
00676 simple_wml::node* const message = data.root().child("message");
00677 assert(message);
00678 message->set_attr_dup("sender", user->second.name().c_str());
00679
00680 const simple_wml::string_span& msg = (*message)["message"];
00681 chat_message::truncate_message(msg, *message);
00682
00683
00684 if (owner_ != 0) {
00685 } else if (msg.size() >= 3 && simple_wml::string_span(msg.begin(), 4) == "/me ") {
00686 LOG_GAME << network::ip_address(user->first) << "\t<"
00687 << user->second.name() << simple_wml::string_span(msg.begin() + 3, msg.size() - 3) << ">\n";
00688 } else {
00689 LOG_GAME << network::ip_address(user->first) << "\t<"
00690 << user->second.name() << "> " << msg << "\n";
00691 }
00692
00693 send_data(data, user->first);
00694 }
00695
00696 bool game::is_legal_command(const simple_wml::node& command, bool is_player) {
00697
00698 if (!command.one_child()) return false;
00699
00700 if (command.child("speak")) return true;
00701 if (is_player
00702 && (command.child("label")
00703 || command.child("clear_labels")
00704 || command.child("rename")
00705 || command.child("countdown_update")
00706 || command.child("advance_unit")
00707 || command.child("choose")))
00708 {
00709 return true;
00710 }
00711 return false;
00712 }
00713
00714
00715
00716
00717
00718
00719
00720 bool game::process_turn(simple_wml::document& data, const player_map::const_iterator user) {
00721
00722 if (!started_) return false;
00723 simple_wml::node* const turn = data.root().child("turn");
00724 bool turn_ended = false;
00725
00726
00727
00728 bool repackage = false;
00729 int index = 0;
00730 std::vector<int> marked;
00731 const simple_wml::node::child_list& commands = turn->children("command");
00732 simple_wml::node::child_list::const_iterator command;
00733 for (command = commands.begin(); command != commands.end(); ++command) {
00734 if (!is_current_player(user->first)
00735 && !is_legal_command(**command, is_player(user->first))) {
00736 std::cerr << "ILLEGAL COMMAND: (((" << data.output() << ")))\n";
00737 std::stringstream msg;
00738 msg << "Removing illegal command from: " << user->second.name()
00739 << ". Current player is: "
00740 << (player_info_->find(current_player()) != player_info_->end()
00741 ? player_info_->find(current_player())->second.name()
00742 : "(unfound) ")
00743 << ".\n";
00744 LOG_GAME << msg.str();
00745 send_and_record_server_message(msg.str().c_str());
00746
00747
00748 marked.push_back(index - marked.size());
00749 } else if ((**command).child("speak")) {
00750 simple_wml::node& speak = *(**command).child("speak");
00751 if (!(speak["team_name"] == "")
00752 || (is_muted_observer(user->first))) {
00753 repackage = true;
00754 }
00755
00756 const simple_wml::string_span& msg = speak["message"];
00757 chat_message::truncate_message(msg, speak);
00758
00759
00760
00761 speak.set_attr_dup("id", user->second.name().c_str());
00762
00763 if (is_player(user->first)) {
00764 const size_t side_num = speak["side"].to_int();
00765 if (side_num < 1 || side_num > gamemap::MAX_PLAYERS
00766 || sides_[side_num - 1] != user->first) {
00767 if (user->first == current_player()) {
00768 speak.set_attr_dup("side", lexical_cast<std::string>(current_side() + 1).c_str());
00769 } else {
00770 const side_vector::const_iterator s =
00771 std::find(sides_.begin(), sides_.end(), user->first);
00772 speak.set_attr_dup("side", lexical_cast<std::string>(s - sides_.begin() + 1).c_str());
00773 }
00774 }
00775 }
00776 } else if (is_current_player(user->first) && (**command).child("end_turn")) {
00777 turn_ended = end_turn();
00778 }
00779 ++index;
00780 }
00781 for(std::vector<int>::const_iterator j = marked.begin(); j != marked.end(); ++j) {
00782 turn->remove_child("command",*j);
00783 }
00784 if (turn->no_children()) {
00785 return false;
00786 }
00787 if (!repackage) {
00788 record_data(data.clone());
00789 send_data(data, user->first);
00790 return turn_ended;
00791 }
00792 for (command = commands.begin(); command != commands.end(); ++command) {
00793 simple_wml::node* const speak = (**command).child("speak");
00794 if (speak == NULL) {
00795 simple_wml::document* mdata = new simple_wml::document;
00796 simple_wml::node& turn = mdata->root().add_child("turn");
00797 (**command).copy_into(turn.add_child("command"));
00798 send_data(*mdata, user->first);
00799 record_data(mdata);
00800 continue;
00801 }
00802 const simple_wml::string_span& team_name = (*speak)["team_name"];
00803
00804 if (team_name == game_config::observer_team_name.c_str()) {
00805
00806 } else if (is_muted_observer(user->first)) {
00807 send_server_message("You have been muted, others can't see your message!", user->first);
00808 continue;
00809
00810 } else if (!is_on_team(team_name, user->first)) {
00811 std::ostringstream msg;
00812 msg << "Removing illegal message from " << user->second.name() << " to " << std::string(team_name.begin(), team_name.end()) << ".";
00813 const std::string& msg_str = msg.str();
00814 LOG_GAME << msg_str << std::endl;
00815 send_and_record_server_message(msg_str.c_str());
00816 continue;
00817 }
00818
00819 std::auto_ptr<simple_wml::document> message(new simple_wml::document);
00820 simple_wml::node& turn = message->root().add_child("turn");
00821 simple_wml::node& command = turn.add_child("command");
00822 speak->copy_into(command.add_child("speak"));
00823 if (team_name == "") {
00824 send_data(*message, user->first);
00825 record_data(message.release());
00826 } else if (team_name == game_config::observer_team_name) {
00827 send_data_observers(*message, user->first);
00828 record_data(message.release());
00829 } else {
00830 send_data_team(*message, team_name, user->first);
00831 }
00832 }
00833 return turn_ended;
00834 }
00835
00836 bool game::end_turn() {
00837
00838 ++end_turn_;
00839 bool turn_ended = false;
00840 if ((current_side()) == 0) {
00841 turn_ended = true;
00842 }
00843
00844 for (int i = 0; i < nsides_ && nsides_ <= gamemap::MAX_PLAYERS && side_controllers_[current_side()] == "null"; ++i) {
00845 ++end_turn_;
00846 if (current_side() == 0) {
00847 turn_ended = true;
00848 }
00849 }
00850 if (!turn_ended) return false;
00851
00852 if (description_ == NULL) {
00853 return false;
00854 }
00855
00856 description_->set_attr_dup("turn", describe_turns(current_turn(), level_["turns"]).c_str());
00857
00858 return true;
00859 }
00860
00861 void game::add_player(const network::connection player, bool observer) {
00862 if(is_member(player)) {
00863 ERR_GAME << "ERROR: Player is already in this game. (socket: "
00864 << player << ")\n";
00865 return;
00866 }
00867
00868 if (owner_ == 0) {
00869 observers_.push_back(player);
00870 return;
00871 }
00872 const player_map::iterator user = player_info_->find(player);
00873 if (user == player_info_->end()) {
00874 ERR_GAME << "ERROR: Could not find user in player_info_. (socket: "
00875 << owner_ << ")\n";
00876 return;
00877 }
00878 user->second.mark_available(id_, name_);
00879 DBG_GAME << debug_player_info();
00880 bool became_observer = false;
00881 if (!started_ && !observer && take_side(user)) {
00882 DBG_GAME << "adding player...\n";
00883 players_.push_back(player);
00884 send_server_message((user->second.name()
00885 + " has joined the game.").c_str(), player);
00886 } else if (!allow_observers()) {
00887 return;
00888 } else {
00889 if (!observer) became_observer = true;
00890 DBG_GAME << "adding observer...\n";
00891 observers_.push_back(player);
00892
00893 simple_wml::document observer_join;
00894 observer_join.root().add_child("observer").set_attr_dup("name", user->second.name().c_str());
00895
00896
00897 send_data(observer_join, player);
00898 }
00899 DBG_GAME << debug_player_info();
00900
00901
00902 simple_wml::string_span level_data = level_.output_compressed();
00903 network::send_raw_data(level_data.begin(), level_data.size(), player);
00904 if(started_) {
00905
00906 static simple_wml::document start_game_doc("[start_game]\n[/start_game]\n", simple_wml::INIT_COMPRESSED);
00907 static const simple_wml::string_span start_game = start_game_doc.output_compressed();
00908 network::send_raw_data(start_game.begin(), start_game.size(), player);
00909
00910
00911
00912 send_observerjoins(player);
00913
00914 send_history(player);
00915 } else {
00916 send_user_list();
00917 }
00918
00919 if (became_observer) {
00920
00921 send_server_message("You are an observer.", player);
00922 }
00923 }
00924
00925
00926
00927
00928 bool game::remove_player(const network::connection player, const bool disconnect) {
00929 if (!is_member(player)) {
00930 ERR_GAME << "ERROR: User is not in this game. (socket: "
00931 << player << ")\n";
00932 return false;
00933 }
00934
00935 if (owner_ == 0) {
00936 const user_vector::iterator itor =
00937 std::find(observers_.begin(), observers_.end(), player);
00938 if (itor != observers_.end()) {
00939 observers_.erase(itor);
00940 } else {
00941 ERR_GAME << "ERROR: Observer is not in this game. (socket: "
00942 << player << ")\n";
00943 }
00944 return false;
00945 }
00946 DBG_GAME << debug_player_info();
00947 DBG_GAME << "removing player...\n";
00948
00949 const bool host = (player == owner_);
00950 const bool observer = is_observer(player);
00951 players_.erase(std::remove(players_.begin(), players_.end(), player), players_.end());
00952 observers_.erase(std::remove(observers_.begin(), observers_.end(), player), observers_.end());
00953 const bool game_ended = (players_.empty() || (host && !started_));
00954 const player_map::iterator user = player_info_->find(player);
00955 if (user == player_info_->end()) {
00956 ERR_GAME << "ERROR: Could not find user in player_info_. (socket: "
00957 << player << ")\n";
00958 return false;
00959 }
00960 LOG_GAME << network::ip_address(user->first) << "\t" << user->second.name()
00961 << (game_ended ? (started_ ? "\tended" : "\taborted") : "\thas left")
00962 << " game:\t\"" << name_ << "\" (" << id_ << ")"
00963 << (game_ended && started_ ? " at turn: "
00964 + lexical_cast_default<std::string,size_t>(current_turn())
00965 + " with reason: '" + termination_reason() + "'" : "")
00966 << (observer ? " as an observer" : "")
00967 << (disconnect ? " and disconnected" : "")
00968 << ". (socket: " << user->first << ")\n";
00969 if (game_ended) {
00970 send_server_message_to_all((user->second.name() + " ended the game.").c_str(), player);
00971 return true;
00972 }
00973
00974
00975 if (!disconnect) user->second.mark_available();
00976 if (observer) {
00977 send_observerquit(user);
00978 } else {
00979 send_and_record_server_message((user->second.name()
00980 + (disconnect ? " has disconnected." : " has left the game.")).c_str(), player);
00981 }
00982
00983 if (host) {
00984 owner_ = players_.front();
00985 notify_new_host();
00986 }
00987
00988
00989
00990 for (side_vector::iterator side = sides_.begin(); side != sides_.end(); ++side) {
00991 if (*side != player) continue;
00992 size_t side_num = side - sides_.begin();
00993 side_controllers_[side_num] = "human";
00994 sides_taken_[side_num] = true;
00995 sides_[side_num] = owner_;
00996
00997 if (!is_player(owner_)) {
00998 DBG_GAME << "making the owner a player...\n";
00999 observers_.erase(std::remove(observers_.begin(), observers_.end(), owner_), observers_.end());
01000 players_.push_back(owner_);
01001 send_observerquit(player_info_->find(owner_));
01002 }
01003 send_change_controller(side_num + 1, player_info_->find(owner_));
01004
01005
01006 char side_drop_buf[64];
01007 sprintf(side_drop_buf, "%d", static_cast<int>(side_num + 1));
01008 simple_wml::document drop;
01009 drop.root().set_attr("side_drop", side_drop_buf);
01010 drop.root().set_attr("controller", side_controllers_[side_num].c_str());
01011
01012 send_to_one(drop, owner_);
01013 }
01014 if (host) transfer_ai_sides();
01015 DBG_GAME << debug_player_info();
01016
01017 send_user_list(player);
01018 return false;
01019 }
01020
01021 void game::send_user_list(const network::connection exclude) const {
01022
01023
01024 if (started_ || description_ == NULL) return;
01025
01026 simple_wml::document cfg;
01027 cfg.root().add_child("gamelist");
01028 user_vector users = all_game_users();
01029 for(user_vector::const_iterator p = users.begin(); p != users.end(); ++p) {
01030 const player_map::const_iterator pl = player_info_->find(*p);
01031 if (pl != player_info_->end()) {
01032
01033
01034 cfg.root().add_child("user").set_attr("name", pl->second.name().c_str());
01035 }
01036 }
01037 send_data(cfg, exclude);
01038 }
01039
01040
01041 void game::load_next_scenario(const player_map::const_iterator user) const {
01042 send_server_message_to_all((user->second.name() + " advances to the next scenario").c_str(), user->first);
01043 simple_wml::document cfg_scenario;
01044 level_.root().copy_into(cfg_scenario.root().add_child("next_scenario"));
01045 simple_wml::string_span data = cfg_scenario.output_compressed();
01046 network::send_raw_data(data.begin(), data.size(), user->first);
01047
01048 send_history(user->first);
01049
01050 send_observerjoins(user->first);
01051 }
01052
01053 void game::send_data(simple_wml::document& data, const network::connection exclude) const
01054 {
01055 simple_wml::string_span s = data.output_compressed();
01056 const user_vector& users = all_game_users();
01057 for(user_vector::const_iterator i = users.begin(); i != users.end(); ++i) {
01058 if (*i != exclude) {
01059 network::send_raw_data(s.begin(), s.size(), *i);
01060 }
01061 }
01062 }
01063
01064 void game::send_to_one(simple_wml::document& data, const network::connection sock) const
01065 {
01066 simple_wml::string_span s = data.output_compressed();
01067 network::send_raw_data(s.begin(), s.size(), sock);
01068 }
01069
01070 void game::send_data_team(simple_wml::document& data,
01071 const simple_wml::string_span& team,
01072 const network::connection exclude) const
01073 {
01074 simple_wml::string_span s = data.output_compressed();
01075 for(user_vector::const_iterator i = players_.begin(); i != players_.end(); ++i) {
01076 if(*i != exclude && is_on_team(team,*i)) {
01077 network::send_raw_data(s.begin(), s.size(), *i);
01078 }
01079 }
01080 }
01081
01082 void game::send_data_observers(simple_wml::document& data, const network::connection exclude) const {
01083 simple_wml::string_span s = data.output_compressed();
01084 for(user_vector::const_iterator i = observers_.begin(); i != observers_.end(); ++i) {
01085 if (*i != exclude) {
01086 network::send_raw_data(s.begin(), s.size(), *i);
01087 }
01088 }
01089 }
01090
01091 bool game::is_on_team(const simple_wml::string_span& team, const network::connection player) const {
01092 side_vector::const_iterator side = std::find(sides_.begin(), sides_.end(), player);
01093 if(side == sides_.end()) {
01094 return false;
01095 }
01096 const std::string side_str =
01097 lexical_cast<std::string, size_t>(side - sides_.begin() + 1);
01098 const simple_wml::node::child_list& side_list = level_.root().children("side");
01099 for(simple_wml::node::child_list::const_iterator i = side_list.begin();
01100 i != side_list.end(); ++i) {
01101 if((**i)["side"] == side_str.c_str()) {
01102 return (**i)["team_name"] == team;
01103 }
01104 }
01105
01106 return false;
01107 }
01108
01109
01110
01111 void game::send_observerjoins(const network::connection sock) const {
01112 for (user_vector::const_iterator ob = observers_.begin(); ob != observers_.end(); ++ob) {
01113 if (*ob == sock) continue;
01114 const player_map::const_iterator obs = player_info_->find(*ob);
01115 if (obs == player_info_->end()) {
01116 ERR_GAME << "Game: " << id_
01117 << " ERROR: Can not find observer in player_info_. (socket: "
01118 << *ob << ")\n";
01119 continue;
01120 }
01121
01122 simple_wml::document cfg;
01123 cfg.root().add_child("observer").set_attr_dup("name", obs->second.name().c_str());
01124 if (sock == 0) {
01125
01126 send_data(cfg, *ob);
01127 } else {
01128
01129 const simple_wml::string_span& data = cfg.output_compressed();
01130 network::send_raw_data(data.begin(), data.size(), sock);
01131 }
01132 }
01133 }
01134
01135 void game::send_observerquit(const player_map::const_iterator observer) const {
01136 if (observer == player_info_->end()) {
01137 return;
01138 }
01139 simple_wml::document observer_quit;
01140
01141
01142
01143 observer_quit.root().add_child("observer_quit").set_attr("name", observer->second.name().c_str());
01144 send_data(observer_quit, observer->first);
01145 }
01146
01147 void game::send_history(const network::connection sock) const
01148 {
01149 if(history_.empty()) {
01150 return;
01151 }
01152
01153
01154
01155
01156 std::string buf;
01157 for(std::vector<simple_wml::document*>::iterator i = history_.begin();
01158 i != history_.end(); ++i) {
01159 buf += (*i)->output();
01160 delete *i;
01161 }
01162
01163 simple_wml::document* doc = new simple_wml::document(buf.c_str(), simple_wml::INIT_STATIC);
01164 const simple_wml::string_span& data = doc->output_compressed();
01165 doc->compress();
01166 network::send_raw_data(data.begin(), data.size(), sock);
01167 history_.clear();
01168 history_.push_back(doc);
01169 }
01170
01171 void game::record_data(simple_wml::document* data) {
01172 data->compress();
01173 history_.push_back(data);
01174 }
01175
01176 void game::set_description(simple_wml::node* desc) {
01177 description_ = desc;
01178 if(!password_.empty()) {
01179 description_->set_attr("password", "yes");
01180 }
01181 }
01182
01183 void game::set_termination_reason(const std::string& reason) {
01184 if (reason == "out of sync") {
01185 simple_wml::string_span era;
01186 if (level_.child("era")) {
01187 era = level_.child("era")->attr("id");
01188 }
01189 termination_ = "out of sync - " + era.to_string();
01190 }
01191 if (termination_.empty()) { termination_ = reason; }
01192 }
01193
01194 void game::add_players(const game& other_game, const bool observer) {
01195 user_vector users = other_game.all_game_users();
01196 if (observer){
01197 observers_.insert(observers_.end(), users.begin(), users.end());
01198 }
01199 else{
01200 players_.insert(players_.end(), users.begin(), users.end());
01201 }
01202 }
01203
01204 const user_vector game::all_game_users() const {
01205 user_vector res;
01206
01207 res.insert(res.end(), players_.begin(), players_.end());
01208 res.insert(res.end(), observers_.begin(), observers_.end());
01209
01210 return res;
01211 }
01212
01213 std::string game::debug_player_info() const {
01214 std::stringstream result;
01215 result << "game id: " << id_ << "\n";
01216
01217 for (user_vector::const_iterator p = players_.begin(); p != players_.end(); p++){
01218 const player_map::const_iterator user = player_info_->find(*p);
01219 if (user != player_info_->end()){
01220 result << "player: " << user->second.name().c_str() << "\n";
01221 }
01222 else{
01223 result << "player: '" << *p << "' not found\n";
01224 }
01225 }
01226
01227 for (user_vector::const_iterator o = observers_.begin(); o != observers_.end(); o++){
01228 const player_map::const_iterator user = player_info_->find(*o);
01229 if (user != player_info_->end()){
01230 result << "observer: " << user->second.name().c_str() << "\n";
01231 }
01232 else{
01233 result << "observer: '" << *o << "' not found\n";
01234 }
01235 }
01236
01237
01238
01239
01240
01241 return result.str();
01242 }
01243
01244
01245 player_map::const_iterator game::find_user(const simple_wml::string_span& name) const {
01246 player_map::const_iterator pl;
01247 for (pl = player_info_->begin(); pl != player_info_->end(); pl++) {
01248 if (name == pl->second.name().c_str()) {
01249 return pl;
01250 }
01251 }
01252 return player_info_->end();
01253 }
01254
01255 void game::send_and_record_server_message(const char* message,
01256 const network::connection exclude)
01257 {
01258 simple_wml::document* doc = new simple_wml::document;
01259 send_server_message(message, 0, doc);
01260 send_data(*doc, exclude);
01261 if (started_) record_data(doc);
01262 }
01263
01264 void game::send_server_message_to_all(const char* message, network::connection exclude) const
01265 {
01266 simple_wml::document doc;
01267 send_server_message(message, 0, &doc);
01268 send_data(doc, exclude);
01269 }
01270
01271 void game::send_server_message(const char* message, network::connection sock, simple_wml::document* docptr) const
01272 {
01273 simple_wml::document docbuf;
01274 if(docptr == NULL) {
01275 docptr = &docbuf;
01276 }
01277
01278 simple_wml::document& doc = *docptr;
01279 if (started_) {
01280 simple_wml::node& cmd = doc.root().add_child("turn");
01281 simple_wml::node& cfg = cmd.add_child("command");
01282 simple_wml::node& msg = cfg.add_child("speak");
01283 msg.set_attr("id", "server");
01284 msg.set_attr_dup("message", message);
01285 } else {
01286 simple_wml::node& msg = doc.root().add_child("message");
01287 msg.set_attr("sender", "server");
01288 msg.set_attr_dup("message", message);
01289 }
01290
01291 if(sock) {
01292 send_to_one(doc, sock);
01293 }
01294 }