gui/dialogs/lobby/lobby_data.cpp

Go to the documentation of this file.
00001 /* $Id: lobby_data.cpp 54051 2012-04-30 21:52:38Z brilliand $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Tomasz Sniatowski <kailoran@gmail.com>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "gui/dialogs/lobby/lobby_data.hpp"
00017 
00018 #include "config.hpp"
00019 #include "game_preferences.hpp"
00020 #include "filesystem.hpp"
00021 #include "foreach.hpp"
00022 #include "formula_string_utils.hpp"
00023 #include "gettext.hpp"
00024 #include "network.hpp"
00025 #include "log.hpp"
00026 #include "map.hpp"
00027 #include "map_exception.hpp"
00028 #include "wml_exception.hpp"
00029 
00030 #include <iterator>
00031 
00032 static lg::log_domain log_config("config");
00033 #define ERR_CF LOG_STREAM(err, log_config)
00034 static lg::log_domain log_engine("engine");
00035 #define WRN_NG LOG_STREAM(warn, log_engine)
00036 
00037 static lg::log_domain log_lobby("lobby");
00038 #define DBG_LB LOG_STREAM(info, log_lobby)
00039 #define LOG_LB LOG_STREAM(info, log_lobby)
00040 #define ERR_LB LOG_STREAM(err, log_lobby)
00041 
00042 chat_message::chat_message(const time_t& timestamp, const std::string& user, const std::string& message)
00043 : timestamp(timestamp), user(user), message(message)
00044 {
00045 }
00046 
00047 chat_log::chat_log()
00048 : history_()
00049 {
00050 }
00051 
00052 void chat_log::add_message(const time_t& timestamp, const std::string& user, const std::string& message)
00053 {
00054     history_.push_back(chat_message(timestamp, user, message));
00055 }
00056 
00057 
00058 void chat_log::add_message(const std::string& user, const std::string& message) {
00059     add_message(time(NULL), user, message);
00060 }
00061 
00062 void chat_log::clear()
00063 {
00064     history_.clear();
00065 }
00066 
00067 room_info::room_info(const std::string& name)
00068     : name_(name)
00069     , members_()
00070     , log_()
00071 {
00072 }
00073 
00074 bool room_info::is_member(const std::string& user) const
00075 {
00076     return members_.find(user) != members_.end();
00077 }
00078 
00079 void room_info::add_member(const std::string& user)
00080 {
00081     members_.insert(user);
00082 }
00083 
00084 void room_info::remove_member(const std::string& user)
00085 {
00086     members_.erase(user);
00087 }
00088 
00089 void room_info::process_room_members(const config& data)
00090 {
00091     members_.clear();
00092     foreach (const config& m, data.child_range("member")) {
00093         members_.insert(m["name"]);
00094     }
00095 }
00096 
00097 user_info::user_info(const config& c)
00098     : name(c["name"])
00099     , game_id(c["game_id"])
00100     , relation(ME)
00101     , state(game_id == 0 ? LOBBY : GAME)
00102     , registered(c["registered"].to_bool())
00103     , observing(c["status"] == "observing")
00104 {
00105     update_relation();
00106 }
00107 
00108 void user_info::update_state(int selected_game_id, const room_info* current_room /*= NULL*/)
00109 {
00110     if (game_id != 0) {
00111         if (game_id == selected_game_id) {
00112             state = SEL_GAME;
00113         } else {
00114             state = GAME;
00115         }
00116     } else {
00117         if (current_room != NULL && current_room->is_member(name)) {
00118             state = SEL_ROOM;
00119         } else {
00120             state = LOBBY;
00121         }
00122     }
00123     update_relation();
00124 }
00125 
00126 void user_info::update_relation()
00127 {
00128     if (name == preferences::login()) {
00129         relation = ME;
00130     } else if (preferences::is_ignored(name)) {
00131         relation = IGNORED;
00132     } else if (preferences::is_friend(name)) {
00133         relation = FRIEND;
00134     } else {
00135         relation = NEUTRAL;
00136     }
00137 }
00138 
00139 namespace {
00140 
00141 std::string make_short_name(const std::string& long_name)
00142 {
00143     if (long_name.empty()) return "";
00144     std::string sh;
00145     bool had_space = true;
00146     for (size_t i = 1; i < long_name.size(); ++i) {
00147         if (long_name[i] == ' ') {
00148             had_space = true;
00149         } else if (had_space && long_name[i] != '?') {
00150             sh += long_name[i];
00151             had_space = false;
00152         }
00153     }
00154     return sh;
00155 }
00156 
00157 } //end anonymous namespace
00158 
00159 game_info::game_info(const config& game, const config& game_config)
00160 : mini_map()
00161 , id(game["id"])
00162 , map_data(game["map_data"])
00163 , name(game["name"])
00164 , scenario()
00165 , remote_scenario(false)
00166 , map_info()
00167 , map_size_info()
00168 , era()
00169 , era_short()
00170 , gold(game["mp_village_gold"])
00171 , support(game["mp_village_support"])
00172 , xp(game["experience_modifier"] + "%")
00173 , vision()
00174 , status()
00175 , time_limit()
00176 , vacant_slots(lexical_cast_default<int>(game["slots"], 0)) // Can't use to_int() here.
00177 , current_turn(0)
00178 , reloaded(game["savegame"].to_bool())
00179 , started(false)
00180 , fog(game["mp_fog"].to_bool())
00181 , shroud(game["mp_shroud"].to_bool())
00182 , observers(game["observer"].to_bool(true))
00183 , shuffle_sides(game["shuffle_sides"].to_bool(true))
00184 , use_map_settings(game["mp_use_map_settings"].to_bool())
00185 , verified(true)
00186 , password_required(game["password"].to_bool())
00187 , have_era(true)
00188 , has_friends(false)
00189 , has_ignored(false)
00190 , display_status(NEW)
00191 {
00192     std::string turn = game["turn"];
00193     if (!game["mp_era"].empty())
00194     {
00195         const config &era_cfg = game_config.find_child("era", "id", game["mp_era"]);
00196         utils::string_map symbols;
00197         symbols["era_id"] = game["mp_era"];
00198         if (era_cfg) {
00199             era = era_cfg["name"].str();
00200             era_short = era_cfg["short_name"].str();
00201             if (era_short.empty()) {
00202                 era_short = make_short_name(era);
00203             }
00204         } else {
00205             have_era = !game["require_era"].to_bool(true);
00206             era = vgettext("Unknown era: $era_id", symbols);
00207             era_short = "?" + make_short_name(era);
00208             verified = false;
00209         }
00210     } else {
00211         era = _("Unknown era");
00212         era_short = "??";
00213         verified = false;
00214     }
00215     map_info = era;
00216 
00217     if (map_data.empty()) {
00218         map_data = read_map(game["mp_scenario"]);
00219     }
00220 
00221     if (map_data.empty()) {
00222         map_info += " — ??×??";
00223     } else {
00224         try {
00225             gamemap map(game_config, map_data);
00226             //mini_map = image::getMinimap(minimap_size_, minimap_size_, map, 0);
00227             std::ostringstream msi;
00228             msi << map.w() << utils::unicode_multiplication_sign << map.h();
00229             map_size_info = msi.str();
00230             map_info += " — " + map_size_info;
00231         } catch (incorrect_map_format_error &e) {
00232             ERR_CF << "illegal map: " << e.message << "\n";
00233             verified = false;
00234         } catch (twml_exception& e) {
00235             ERR_CF <<  "map could not be loaded: " << e.dev_message << '\n';
00236             verified = false;
00237         }
00238     }
00239     map_info += " ";
00240     if (!game["mp_scenario"].empty())
00241     {
00242         // check if it's a multiplayer scenario
00243         const config *level_cfg = &game_config.find_child("multiplayer", "id", game["mp_scenario"]);
00244         if (!*level_cfg) {
00245             // check if it's a user map
00246             level_cfg = &game_config.find_child("generic_multiplayer", "id", game["mp_scenario"]);
00247         }
00248         if (*level_cfg) {
00249             scenario = (*level_cfg)["name"].str();
00250             map_info += scenario;
00251             // reloaded games do not match the original scenario hash,
00252             // so it makes no sense to test them, they always would appear
00253             // as remote scenarios
00254             if (!reloaded) {
00255                 if (const config& hashes = game_config.child("multiplayer_hashes")) {
00256                     std::string hash = game["hash"];
00257                     bool hash_found = false;
00258                     foreach (const config::attribute &i, hashes.attribute_range()) {
00259                         if (i.first == game["mp_scenario"] && i.second == hash) {
00260                             hash_found = true;
00261                             break;
00262                         }
00263                     }
00264                     if(!hash_found) {
00265                         remote_scenario = true;
00266                         map_info += " — ";
00267                         map_info += _("Remote scenario");
00268                         verified = false;
00269                     }
00270                 }
00271             }
00272         } else {
00273             utils::string_map symbols;
00274             symbols["scenario_id"] = game["mp_scenario"];
00275             scenario = vgettext("Unknown scenario: $scenario_id", symbols);
00276             map_info += scenario;
00277             verified = false;
00278         }
00279     } else {
00280         scenario = _("Unknown scenario");
00281         map_info += scenario;
00282         verified = false;
00283     }
00284     if (reloaded) {
00285         map_info += " — ";
00286         map_info += _("Reloaded game");
00287         verified = false;
00288     }
00289 
00290     if (!turn.empty()) {
00291         started = true;
00292         int index = turn.find_first_of('/');
00293         if (index > -1){
00294             const std::string current_turn_string = turn.substr(0, index);
00295             current_turn = lexical_cast<unsigned int>(current_turn_string);
00296         }
00297         status = _("Turn ") + turn;
00298     } else {
00299         started = false;
00300         if (vacant_slots > 0) {
00301             status = std::string(_n("Vacant Slot:", "Vacant Slots:",
00302                     vacant_slots)) + " " + game["slots"];
00303         }
00304     }
00305 
00306     if (fog) {
00307         vision = _("Fog");
00308         if (shroud) {
00309             vision += "/";
00310             vision += _("Shroud");
00311         }
00312     } else if (shroud) {
00313         vision = _("Shroud");
00314     } else {
00315         vision = _("none");
00316     }
00317     if (game["mp_countdown"].to_bool()) {
00318         time_limit =   game["mp_countdown_init_time"].str() + "+"
00319                      + game["mp_countdown_turn_bonus"].str() + "/"
00320                      + game["mp_countdown_action_bonus"].str();
00321     } else {
00322         time_limit = "";
00323     }
00324 }
00325 
00326 bool game_info::can_join() const
00327 {
00328     return have_era && !started && vacant_slots > 0;
00329 }
00330 
00331 bool game_info::can_observe() const
00332 {
00333     return (have_era && observers) || preferences::is_authenticated();
00334 }
00335 
00336 const char* game_info::display_status_string() const
00337 {
00338     switch (display_status) {
00339         case game_info::CLEAN:
00340             return "clean";
00341         case game_info::NEW:
00342             return "new";
00343         case game_info::DELETED:
00344             return "deleted";
00345         case game_info::UPDATED:
00346             return "updated";
00347         default:
00348             ERR_CF << "BAD display_status " << display_status
00349                 << " in game " << id << "\n";
00350             return "?";
00351     }
00352 }
00353 
00354 game_filter_stack::game_filter_stack()
00355 : filters_()
00356 {
00357 }
00358 
00359 game_filter_stack::~game_filter_stack()
00360 {
00361     foreach (game_filter_base* f, filters_) {
00362         delete f;
00363     }
00364 }
00365 
00366 void game_filter_stack::append(game_filter_base *f)
00367 {
00368     filters_.push_back(f);
00369 }
00370 
00371 void game_filter_stack::clear()
00372 {
00373     foreach (game_filter_base* f, filters_) {
00374         delete f;
00375     }
00376     filters_.clear();
00377 }
00378 
00379 bool game_filter_and_stack::match(const game_info &game) const
00380 {
00381     foreach (game_filter_base* f, filters_) {
00382         if (!f->match(game)) return false;
00383     }
00384     return true;
00385 }
00386 
00387 bool game_filter_general_string_part::match(const game_info &game) const
00388 {
00389     const std::string& s1 = game.map_info;
00390     const std::string& s2 = game.name;
00391     return
00392         std::search(
00393             s1.begin(), s1.end(), value_.begin(), value_.end(), chars_equal_insensitive
00394         ) != s1.end()
00395         ||
00396         std::search(
00397             s2.begin(), s2.end(), value_.begin(), value_.end(), chars_equal_insensitive
00398         ) != s2.end();
00399 }
00400 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:58 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs