00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "global.hpp"
00017
00018 #include "construct_dialog.hpp"
00019 #include "foreach.hpp"
00020 #include "gamestatus.hpp"
00021 #include "game_display.hpp"
00022 #include "game_preferences.hpp"
00023 #include "gettext.hpp"
00024 #include "gui/dialogs/mp_cmd_wrapper.hpp"
00025 #include "lobby_preferences.hpp"
00026 #include "log.hpp"
00027 #include "marked-up_text.hpp"
00028 #include "menu_events.hpp"
00029 #include "multiplayer.hpp"
00030 #include "multiplayer_ui.hpp"
00031 #include "sound.hpp"
00032 #include "replay.hpp"
00033 #include "wml_separators.hpp"
00034 #include "formula_string_utils.hpp"
00035
00036 static lg::log_domain log_engine("engine");
00037 #define LOG_NG LOG_STREAM(info, log_engine)
00038 #define ERR_NG LOG_STREAM(err, log_engine)
00039
00040 static lg::log_domain log_config("config");
00041 #define ERR_CF LOG_STREAM(err, log_config)
00042
00043 static lg::log_domain log_network("network");
00044 #define LOG_NW LOG_STREAM(info, log_network)
00045 #define ERR_NW LOG_STREAM(err, log_network)
00046
00047 namespace {
00048
00049
00050 const size_t max_messages = 256;
00051
00052 class user_menu_style : public gui::menu::imgsel_style {
00053 public:
00054 user_menu_style() : gui::menu::imgsel_style("misc/selection", false,
00055 0x000000, 0x4a4440, 0x999999,
00056 0.0, 0.2, 0.2),
00057 item_size_(empty_rect)
00058 {}
00059 virtual void init();
00060 virtual SDL_Rect item_size(const std::string& ) const { return item_size_; }
00061 void set_width(const int width) { item_size_.w = width; }
00062 private:
00063 SDL_Rect item_size_;
00064 };
00065
00066 void user_menu_style::init()
00067 {
00068 imgsel_style::init();
00069 item_size_.h = font::get_max_height(font_size_);
00070 scale_images(-1, item_size_.h);
00071 item_size_.h += 2 * thickness_;
00072 }
00073
00074 user_menu_style umenu_style;
00075
00076 }
00077
00078 namespace mp {
00079
00080 void check_response(network::connection res, const config& data)
00081 {
00082 if(!res) {
00083 throw network::error(_("Connection timed out"));
00084 }
00085
00086 if (const config &err = data.child("error")) {
00087 throw network::error(err["message"]);
00088 }
00089 }
00090
00091 void level_to_gamestate(config& level, game_state& state)
00092 {
00093
00094
00095 const config &replay_data = level.child("replay");
00096 config replay_data_store;
00097 if (replay_data) {
00098 replay_data_store = replay_data;
00099 LOG_NW << "setting replay\n";
00100 state.replay_data = replay_data;
00101 recorder = replay(replay_data_store);
00102 if(!recorder.empty()) {
00103 recorder.set_skip(false);
00104 recorder.set_to_end();
00105 }
00106 }
00107
00108
00109 const std::string seed = level["random_seed"];
00110 if(! seed.empty()) {
00111 const unsigned calls = lexical_cast_default<unsigned>(level["random_calls"]);
00112 state.rng().seed_random(lexical_cast<int>(seed), calls);
00113 } else {
00114 ERR_NG << "No random seed found, random "
00115 "events will probably be out of sync.\n";
00116 }
00117
00118
00119 if (!level.child("replay_start")) {
00120 level.add_child("replay_start", level);
00121 level.child("replay_start").remove_child("multiplayer", 0);
00122 }
00123
00124
00125
00126 state.starting_pos = level.child("replay_start");
00127
00128 level["campaign_type"] = "multiplayer";
00129 state.classification().campaign_type = "multiplayer";
00130 state.classification().completion = level["completion"].str();
00131 state.classification().version = level["version"].str();
00132
00133 if (const config &vars = level.child("variables")) {
00134 state.set_variables(vars);
00135 }
00136 state.set_menu_items(level.child_range("menu_item"));
00137 state.mp_settings().set_from_config(level);
00138
00139
00140 const config &snapshot = level.child("snapshot");
00141 const bool saved_game = snapshot && snapshot.child("side");
00142
00143
00144
00145
00146 bool start_of_scenario = !saved_game && state.starting_pos.child("player");
00147
00148
00149
00150 if (saved_game) {
00151 state.snapshot = snapshot;
00152 if (const config &v = snapshot.child("variables")) {
00153 state.set_variables(v);
00154 }
00155 state.set_menu_items(snapshot.child_range("menu_item"));
00156 }
00157
00158
00159
00160 if(saved_game || start_of_scenario){
00161 config::child_itors saved_sides = saved_game ?
00162 state.snapshot.child_range("side") :
00163 state.starting_pos.child_range("side");
00164 config::const_child_itors level_sides = level.child_range("side");
00165
00166 foreach (config &side, saved_sides)
00167 {
00168 foreach (const config &lside, level_sides)
00169 {
00170 if (side["side"] == lside["side"] &&
00171 (side["current_player"] != lside["current_player"] ||
00172 side["controller"] != lside["controller"]))
00173 {
00174 side["current_player"] = lside["current_player"];
00175 side["id"] = lside["id"];
00176 side["save_id"] = lside["save_id"];
00177 side["controller"] = lside["controller"];
00178 break;
00179 }
00180 }
00181 }
00182 }
00183 if(state.get_variables().empty()) {
00184 LOG_NG << "No variables were found for the game_state." << std::endl;
00185 } else {
00186 LOG_NG << "Variables found and loaded into game_state:" << std::endl;
00187 LOG_NG << state.get_variables();
00188 }
00189 }
00190
00191 std::string get_color_string(int id)
00192 {
00193 std::string prefix = team::get_side_highlight(id);
00194 std::map<std::string, t_string>::iterator name = game_config::team_rgb_name.find(str_cast(id + 1));
00195 if(name != game_config::team_rgb_name.end()){
00196 return prefix + name->second;
00197 }else{
00198 return prefix + _("Invalid Color");
00199 }
00200 }
00201
00202 chat::chat() :
00203 message_history_(),
00204 last_update_()
00205 {
00206 }
00207
00208 void chat::add_message(const time_t& time, const std::string& user,
00209 const std::string& message)
00210 {
00211 message_history_.push_back(msg(time, user, message));
00212
00213 while (message_history_.size() > max_messages) {
00214 message_history_.pop_front();
00215
00216 if (last_update_ > 0)
00217 last_update_--;
00218 }
00219 }
00220
00221 void chat::init_textbox(gui::textbox& textbox)
00222 {
00223 for(msg_hist::const_iterator itor = message_history_.begin();
00224 itor != message_history_.end(); ++itor) {
00225 textbox.append_text(format_message(*itor), true, color_message(*itor));
00226 }
00227
00228 last_update_ = message_history_.size();
00229 }
00230
00231 void chat::update_textbox(gui::textbox& textbox)
00232 {
00233 for(msg_hist::const_iterator itor = message_history_.begin() + last_update_;
00234 itor != message_history_.end(); ++itor) {
00235 textbox.append_text(format_message(*itor), true, color_message(*itor));
00236 }
00237
00238 last_update_ = message_history_.size();
00239 }
00240
00241 std::string chat::format_message(const msg& message)
00242 {
00243 std::string msg_text = message.message;
00244 if(message.user == "server"
00245 || message.user.substr(0,29) == "whisper: server message from ") {
00246 std::string::const_iterator after_markup =
00247 font::parse_markup(message.message.begin(), message.message.end(), NULL, NULL, NULL);
00248
00249 msg_text = std::string(after_markup,message.message.end());
00250 }
00251 if(message.message.substr(0,3) == "/me") {
00252 return preferences::get_chat_timestamp(message.time) + "<" + message.user
00253 + msg_text.substr(3) + ">\n";
00254 } else {
00255 return preferences::get_chat_timestamp(message.time) + "<" + message.user
00256 + "> " + msg_text + "\n";
00257 }
00258 }
00259
00260 SDL_Color chat::color_message(const msg& message) {
00261 SDL_Color c = font::NORMAL_COLOR;
00262
00263 if(message.user == "server"
00264 || message.user.substr(0,29) == "whisper: server message from ") {
00265 font::parse_markup(message.message.begin(), message.message.end(), NULL, &c, NULL);
00266
00267 } else if(message.user.substr(0,8) == "whisper:") {
00268 c = font::LABEL_COLOR;
00269 }
00270 return c;
00271 }
00272
00273 ui::ui(game_display& disp, const std::string& title, const config& cfg, chat& c, config& gamelist) :
00274 gui::widget(disp.video()),
00275 disp_(disp),
00276 initialized_(false),
00277 gamelist_initialized_(false),
00278
00279 hotkey_handler_(&disp),
00280 disp_manager_(&disp),
00281
00282 game_config_(cfg),
00283 chat_(c),
00284 gamelist_(gamelist),
00285
00286 title_(disp.video(), title, font::SIZE_LARGE, font::TITLE_COLOR),
00287 entry_textbox_(disp.video(), 100),
00288 chat_textbox_(disp.video(), 100, "", false),
00289 users_menu_(disp.video(), std::vector<std::string>(), false, -1, -1, NULL, &umenu_style),
00290
00291 user_list_(),
00292 selected_game_(""),
00293 selected_user_(""),
00294 selected_user_changed_(false),
00295
00296 result_(CONTINUE),
00297 gamelist_refresh_(false),
00298 lobby_clock_(0)
00299 {
00300 const SDL_Rect area = create_rect(0
00301 , 0
00302 , disp.video().getx()
00303 , disp.video().gety());
00304 users_menu_.set_numeric_keypress_selection(false);
00305 set_location(area);
00306 }
00307
00308 void ui::process_network()
00309 {
00310 config data;
00311 try {
00312 const network::connection sock = network::receive_data(data);
00313
00314 if(sock) {
00315 process_network_data(data, sock);
00316 }
00317 } catch(network::error& e) {
00318 process_network_error(e);
00319 }
00320
00321
00322 if(gamelist_refresh_ && SDL_GetTicks() - lobby_clock_ > game_config::lobby_refresh)
00323 {
00324 const cursor::setter cursor_setter(cursor::WAIT);
00325 gamelist_updated(false);
00326 gamelist_refresh_ = false;
00327 lobby_clock_ = SDL_GetTicks();
00328 }
00329
00330 if (accept_connections()) {
00331 network::connection sock = network::accept_connection();
00332 if(sock) {
00333 LOG_NW << "Received connection\n";
00334
00335 process_network_connection(sock);
00336 }
00337 }
00338 }
00339
00340 ui::result ui::get_result()
00341 {
00342 return result_;
00343 }
00344
00345 ui::result ui::set_result(ui::result res)
00346 {
00347 result_ = res;
00348 return res;
00349 }
00350
00351 const int ui::xscale_base = 1024;
00352 const int ui::yscale_base = 768;
00353
00354 int ui::xscale(int x) const
00355 {
00356 return (x * width())/ui::xscale_base;
00357 }
00358
00359 int ui::yscale(int y) const
00360 {
00361 return (y * height())/ui::yscale_base;
00362 }
00363
00364 SDL_Rect ui::client_area() const
00365 {
00366 SDL_Rect res;
00367
00368 res.x = xscale(10) + 10;
00369 res.y = yscale(38) + 10;
00370 res.w = xscale(828) > 12 ? xscale(828) - 12 : 0;
00371 res.h = yscale(520) > 12 ? yscale(520) - 12 : 0;
00372
00373 return res;
00374 }
00375
00376 const config& ui::game_config() const
00377 {
00378 return game_config_;
00379 }
00380
00381 void ui::draw_contents()
00382 {
00383 hide_children();
00384
00385 surface background(image::get_image("misc/lobby.png"));
00386 background = scale_surface(background, video().getx(), video().gety());
00387 if(background == NULL)
00388 return;
00389 sdl_blit(background, NULL, video().getSurface(), NULL);
00390 update_whole_screen();
00391
00392 hide_children(false);
00393 }
00394
00395 void ui::set_location(const SDL_Rect& rect)
00396 {
00397 hide_children();
00398 widget::set_location(rect);
00399 layout_children(rect);
00400 if(!initialized_) {
00401 chat_textbox_.set_wrap(true);
00402 chat_.init_textbox(chat_textbox_);
00403 initialized_ = true;
00404 }
00405 hide_children(false);
00406 }
00407
00408 void ui::process_event()
00409 {
00410 }
00411
00412 void ui::handle_event(const SDL_Event& event)
00413 {
00414 if(event.type == SDL_KEYDOWN) {
00415 handle_key_event(event.key);
00416 }
00417 if(users_menu_.double_clicked()) {
00418 std::string usr_text = user_list_[users_menu_.selection()];
00419 Uint32 show_time = SDL_GetTicks();
00420
00421
00422
00423 disp().video().clear_all_help_strings();
00424
00425 gui2::tmp_cmd_wrapper dlg(_("Selected user: ") + usr_text);
00426 dlg.show(disp().video());
00427
00428 std::stringstream msg;
00429 switch(dlg.get_retval()) {
00430 case -1:
00431 if(!dlg.message().empty()) msg << "/msg " << usr_text << ' ' << dlg.message();
00432 break;
00433 case 1:
00434 msg << "/friend " << usr_text;
00435 break;
00436 case 2:
00437 msg << "/ignore " << usr_text;
00438 break;
00439 case 3:
00440 msg << "/remove " << usr_text;
00441 break;
00442 case 4:
00443 msg << "/query status " << usr_text;
00444 break;
00445 case 5:
00446 msg << "/query kick " << usr_text;
00447 if(!dlg.reason().empty()) msg << ' ' << dlg.reason();
00448 break;
00449 case 6:
00450 msg << "/query kban " << usr_text;
00451 if(!dlg.time().empty()) msg << ' ' << dlg.time();
00452 if(!dlg.reason().empty()) msg << ' ' << dlg.reason();
00453 }
00454
00455 chat_handler::do_speak(msg.str());
00456
00457 if(show_time + 60000 < SDL_GetTicks()) {
00458
00459 config request;
00460 request.add_child("refresh_lobby");
00461 network::send_data(request, 0);
00462 }
00463 }
00464 if(users_menu_.selection() > 0
00465 && selected_user_ != user_list_[users_menu_.selection()]) {
00466 selected_user_ = user_list_[users_menu_.selection()];
00467 selected_user_changed_ = true;
00468 }
00469 }
00470
00471 void ui::add_chat_message(const time_t& time, const std::string& speaker, int , const std::string& message, events::chat_handler::MESSAGE_TYPE )
00472 {
00473 chat_.add_message(time, speaker, message);
00474 chat_.update_textbox(chat_textbox_);
00475 }
00476
00477 void ui::send_chat_message(const std::string& message, bool )
00478 {
00479 config data, msg;
00480 msg["message"] = message;
00481 msg["sender"] = preferences::login();
00482 data.add_child("message", msg);
00483
00484 add_chat_message(time(NULL), preferences::login(),0, message);
00485 network::send_data(data, 0);
00486 }
00487
00488 void ui::handle_key_event(const SDL_KeyboardEvent& event)
00489 {
00490
00491 if((event.keysym.sym == SDLK_RETURN || event.keysym.sym == SDLK_KP_ENTER) && !entry_textbox_.text().empty()) {
00492
00493 chat_handler::do_speak(entry_textbox_.text());
00494 entry_textbox_.clear();
00495
00496 } else if(event.keysym.sym == SDLK_TAB ) {
00497 std::string text = entry_textbox_.text();
00498 std::vector<std::string> matches = user_list_;
00499
00500 matches.erase(std::remove(matches.begin(), matches.end(),
00501 preferences::login()), matches.end());
00502 const bool line_start = utils::word_completion(text, matches);
00503
00504 if (matches.empty()) return;
00505
00506 if (matches.size() == 1) {
00507 text.append(line_start ? ": " : " ");
00508 } else {
00509 std::string completion_list = utils::join(matches, " ");
00510 chat_.add_message(time(NULL), "", completion_list);
00511 chat_.update_textbox(chat_textbox_);
00512 }
00513 entry_textbox_.set_text(text);
00514 }
00515 }
00516
00517 void ui::process_message(const config& msg, const bool whisper) {
00518 const std::string& sender = msg["sender"];
00519 const std::string& message = msg["message"];
00520 std::string room = msg["room"];
00521 if (!preferences::parse_should_show_lobby_join(sender, message)) return;
00522 if (preferences::is_ignored(sender)) return;
00523
00524 preferences::parse_admin_authentication(sender, message);
00525
00526 if (whisper || utils::word_match(message, preferences::login())) {
00527 sound::play_UI_sound(game_config::sounds::receive_message_highlight);
00528 } else if (preferences::is_friend(sender)) {
00529 sound::play_UI_sound(game_config::sounds::receive_message_friend);
00530 } else if (sender == "server") {
00531 sound::play_UI_sound(game_config::sounds::receive_message_server);
00532 } else {
00533
00534
00535 }
00536
00537 std::string prefix;
00538
00539 if(whisper) {
00540 utils::string_map symbols;
00541 symbols["sender"] = msg["sender"].str();
00542 prefix = VGETTEXT("whisper: $sender", symbols);
00543 }
00544 else {
00545 prefix = msg["sender"].str();
00546 }
00547
00548 if (!room.empty()) room = room + ": ";
00549
00550 chat_.add_message(time(NULL), room + prefix, msg["message"]);
00551 chat_.update_textbox(chat_textbox_);
00552 }
00553
00554 void ui::process_network_data(const config& data, const network::connection )
00555 {
00556 if (const config &c = data.child("error")) {
00557 throw network::error(c["message"]);
00558 } else if (const config &c = data.child("message")) {
00559 process_message(c);
00560 } else if (const config &c = data.child("whisper")) {
00561 process_message(c, true);
00562 } else if(data.child("gamelist")) {
00563 const cursor::setter cursor_setter(cursor::WAIT);
00564 gamelist_initialized_ = true;
00565 gamelist_ = data;
00566 gamelist_updated(false);
00567 gamelist_refresh_ = false;
00568 lobby_clock_ = SDL_GetTicks();
00569 } else if (const config &c = data.child("gamelist_diff")) {
00570 if(gamelist_initialized_) {
00571 try {
00572 gamelist_.apply_diff(c);
00573 } catch(config::error& e) {
00574 ERR_CF << "Error while applying the gamelist diff: '"
00575 << e.message << "' Getting a new gamelist.\n";
00576 network::send_data(config("refresh_lobby"), 0);
00577 }
00578 gamelist_refresh_ = true;
00579 }
00580 } else if (const config &c = data.child("room_join")) {
00581 if (c["player"] == preferences::login()) {
00582 chat_.add_message(time(NULL), "server",
00583 "You have joined the room '" + c["room"].str() + "'");
00584 } else {
00585 chat_.add_message(time(NULL), "server",
00586 c["player"].str() + " has joined the room '" + c["room"].str() + "'");
00587 }
00588 chat_.update_textbox(chat_textbox_);
00589 } else if (const config &c = data.child("room_part")) {
00590 if (c["player"] == preferences::login()) {
00591 chat_.add_message(time(NULL), "server",
00592 "You have left the room '" + c["room"].str() + "'");
00593 } else {
00594 chat_.add_message(time(NULL), "server",
00595 c["player"].str() + " has left the room '" + c["room"].str() + "'");
00596 }
00597 chat_.update_textbox(chat_textbox_);
00598 } else if (const config &c = data.child("room_query_response")) {
00599 if (const config &ms = c.child("members")) {
00600 std::stringstream ss;
00601 ss << "Room " << c["room"].str() << " members: ";
00602 foreach (const config& m, ms.child_range("member")) {
00603 ss << m["name"] << " ";
00604 }
00605 chat_.add_message(time(NULL), "server", ss.str());
00606 chat_.update_textbox(chat_textbox_);
00607 }
00608 if (const config &rs = c.child("rooms")) {
00609 std::stringstream ss;
00610 ss << "Rooms: ";
00611 foreach (const config& r, rs.child_range("room")) {
00612 ss << r["name"].str() << "(" << r["size"].str() << ") ";
00613 }
00614 chat_.add_message(time(NULL), "server", ss.str());
00615 chat_.update_textbox(chat_textbox_);
00616 }
00617 }
00618 }
00619
00620 void ui::process_network_error(network::error& error)
00621 {
00622 ERR_NW << "Caught networking error: " << error.message << "\n";
00623
00624
00625 throw error;
00626 }
00627
00628 void ui::process_network_connection(const network::connection )
00629 {
00630 LOG_NW << "Caught network connection.\n";
00631 }
00632
00633 void ui::hide_children(bool hide)
00634 {
00635 title_.hide(hide);
00636 chat_textbox_.hide(hide);
00637 entry_textbox_.hide(hide);
00638 users_menu_.hide(hide);
00639 }
00640
00641 void ui::layout_children(const SDL_Rect& )
00642 {
00643 title_.set_location(xscale(12) + 8, yscale(38) + 8);
00644 umenu_style.set_width(xscale(159));
00645 users_menu_.set_width(xscale(159));
00646 users_menu_.set_max_width(xscale(159));
00647 users_menu_.set_location(xscale(856), yscale(42));
00648 users_menu_.set_height(yscale(715));
00649 users_menu_.set_max_height(yscale(715));
00650 chat_textbox_.set_location(xscale(11) + 4, yscale(573) + 4);
00651 chat_textbox_.set_measurements(xscale(833) - 8, yscale(143) - 8);
00652 entry_textbox_.set_location(xscale(11) + 4, yscale(732));
00653 entry_textbox_.set_width(xscale(833) - 8);
00654 }
00655
00656 bool ui::user_info::operator> (const user_info& b) const {
00657 user_info const& a = *this;
00658
00659
00660 if (a.relation == ME) {
00661 return true;
00662 }
00663 if (b.relation == ME) {
00664 return false;
00665 }
00666
00667
00668 if ((a.relation == FRIEND) && (b.relation == FRIEND)) {
00669 if (a.state != b.state) {
00670 return a.state < b.state;
00671 }
00672 return a.name < b.name;
00673 }
00674 if (a.relation == FRIEND) {
00675 return true;
00676 }
00677 if (b.relation == FRIEND) {
00678 return false;
00679 }
00680
00681
00682 if ((a.state == SEL_GAME) && (b.state == SEL_GAME)) {
00683 if (a.relation != b.relation) {
00684 return a.relation < b.relation;
00685 }
00686 return a.name < b.name;
00687 }
00688 if (a.state == SEL_GAME) {
00689 return true;
00690 }
00691 if (b.state == SEL_GAME) {
00692 return false;
00693 }
00694
00695
00696 if (a.relation != b.relation) {
00697 return a.relation < b.relation;
00698 }
00699 if (a.state != b.state) {
00700 return a.state < b.state;
00701 }
00702 return a.name < b.name;
00703 }
00704
00705 void ui::gamelist_updated(bool silent)
00706 {
00707 std::list<user_info> u_list;
00708
00709 foreach (const config &user, gamelist_.child_range("user"))
00710 {
00711 user_info u_elem;
00712 u_elem.name = user["name"].str();
00713 u_elem.state = user["available"].to_bool(true) ? LOBBY : GAME;
00714 u_elem.registered = user["registered"].to_bool();
00715 u_elem.game_id = user["game_id"].str();
00716 u_elem.location = user["location"].str();
00717 if (!u_elem.game_id.empty() && u_elem.game_id == selected_game_) {
00718 u_elem.state = SEL_GAME;
00719 }
00720 if (u_elem.name == preferences::login()) {
00721 u_elem.relation = ME;
00722 } else if (preferences::is_ignored(u_elem.name)) {
00723 u_elem.relation = IGNORED;
00724 } else if (preferences::is_friend(u_elem.name)) {
00725 u_elem.relation = FRIEND;
00726 } else {
00727 u_elem.relation = NEUTRAL;
00728 }
00729 u_list.push_back(u_elem);
00730 }
00731
00732 if (preferences::sort_list()) {
00733 u_list.sort(std::greater<user_info>());
00734 }
00735
00736
00737
00738 const std::string lobby_color_tag = "";
00739 const std::string ingame_color_tag = "#";
00740 const std::string selgame_color_tag = "<0,191,255>";
00741
00742
00743
00744 const std::string registered_user_tag = "~";
00745
00746 std::string const imgpre = IMAGE_PREFIX + std::string("misc/status-");
00747 std::vector<std::string> user_strings;
00748 std::vector<std::string> menu_strings;
00749
00750 std::list<user_info>::const_iterator u_itor = u_list.begin();
00751 while (u_itor != u_list.end()) {
00752 const std::string name_str = u_itor->name +
00753 ((u_itor->state == LOBBY) ? "" : " (" + u_itor->location + ")");
00754 std::string img_str = "";
00755 std::string color_str = "";
00756 std::string reg_str = "";
00757 switch (u_itor->state) {
00758 case LOBBY: color_str = lobby_color_tag; break;
00759 case GAME: color_str = ingame_color_tag; break;
00760 case SEL_GAME: color_str = selgame_color_tag; break;
00761 }
00762 if (preferences::iconize_list()) {
00763 switch (u_itor->relation) {
00764 case NEUTRAL: img_str = imgpre + "neutral.png" + IMG_TEXT_SEPARATOR; break;
00765 case IGNORED: img_str = imgpre + "ignore.png" + IMG_TEXT_SEPARATOR; break;
00766 case FRIEND: img_str = imgpre + "friend.png" + IMG_TEXT_SEPARATOR; break;
00767 case ME: img_str = imgpre + "self.png" + IMG_TEXT_SEPARATOR; break;
00768 }
00769 }
00770 reg_str = u_itor->registered ? registered_user_tag : "";
00771 user_strings.push_back(u_itor->name);
00772 menu_strings.push_back(img_str + reg_str + color_str + name_str + HELP_STRING_SEPARATOR + name_str);
00773 ++u_itor;
00774 }
00775
00776 set_user_list(user_strings, silent);
00777 set_user_menu_items(menu_strings);
00778 }
00779
00780 void ui::set_selected_game(const std::string& game_id)
00781 {
00782
00783 if (preferences::sort_list() && (selected_game_ != game_id)) {
00784 users_menu_.move_selection(0);
00785 }
00786 selected_game_ = game_id;
00787 }
00788
00789 void ui::set_user_menu_items(const std::vector<std::string>& list)
00790 {
00791 users_menu_.set_items(list,true,true);
00792
00793
00794 std::vector<std::string>::const_iterator i =
00795 std::find(user_list_.begin(), user_list_.end(), selected_user_);
00796 if(i != user_list_.end()) {
00797 users_menu_.move_selection_keeping_viewport(i - user_list_.begin());
00798 }
00799 }
00800
00801 void ui::set_user_list(const std::vector<std::string>& list, bool silent)
00802 {
00803 if(!silent) {
00804 if(list.size() < user_list_.size()) {
00805 sound::play_UI_sound(game_config::sounds::user_leave);
00806 } else if(list.size() > user_list_.size()) {
00807 sound::play_UI_sound(game_config::sounds::user_arrive);
00808 }
00809 }
00810
00811 user_list_ = list;
00812 }
00813
00814 std::string ui::get_selected_user_game()
00815 {
00816 const config &u = gamelist_.find_child("user", "name", selected_user_);
00817 if (u) return u["game_id"];
00818 return std::string();
00819 }
00820
00821 void ui::append_to_title(const std::string& text) {
00822 title_.set_text(title_.get_text() + text);
00823 }
00824
00825 const gui::label& ui::title() const
00826 {
00827 return title_;
00828 }
00829
00830 int find_suitable_faction(faction_list const &fl, const config &cfg)
00831 {
00832 std::vector<std::string> find;
00833 std::string search_field;
00834 if (const config::attribute_value *f = cfg.get("faction")) {
00835
00836 find.push_back(f->str());
00837 search_field = "id";
00838 } else if (cfg["faction_from_recruit"].to_bool()) {
00839
00840 find = utils::split(cfg["recruit"]);
00841 search_field = "recruit";
00842 } else if (const config::attribute_value *l = cfg.get("leader")) {
00843
00844 find.push_back(*l);
00845 search_field = "leader";
00846 } else {
00847 return -1;
00848 }
00849
00850 int res = -1, index = 0, best_score = 0;
00851 foreach (const config *faction, fl)
00852 {
00853 int faction_score = 0;
00854 std::vector<std::string> recruit = utils::split((*faction)[search_field]);
00855 foreach (const std::string &search, find) {
00856 foreach (const std::string &r, recruit) {
00857 if (r == search) {
00858 ++faction_score;
00859 break;
00860 }
00861 }
00862 }
00863 if (faction_score > best_score) {
00864 best_score = faction_score;
00865 res = index;
00866 }
00867 ++index;
00868 }
00869 return res;
00870 }
00871
00872 }