00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "global.hpp"
00020
00021 #include "config.hpp"
00022 #include "filesystem.hpp"
00023 #include "game_display.hpp"
00024 #include "marked-up_text.hpp"
00025 #include "minimap.hpp"
00026 #include "multiplayer_lobby.hpp"
00027 #include "replay.hpp"
00028 #include "wml_separators.hpp"
00029 #include "game_config.hpp"
00030 #include "gettext.hpp"
00031 #include "log.hpp"
00032 #include "playmp_controller.hpp"
00033 #include "show_dialog.hpp"
00034 #include "sound.hpp"
00035 #include "wml_exception.hpp"
00036
00037 #define ERR_CF LOG_STREAM(err, config)
00038
00039 namespace {
00040 std::vector<std::string> empty_string_vector;
00041 }
00042
00043 namespace mp {
00044 gamebrowser::gamebrowser(CVideo& video, const config* map_hashes) :
00045 menu(video, empty_string_vector, false, -1, -1, NULL, &menu::bluebg_style),
00046 gold_icon_locator_("themes/gold.png"),
00047 xp_icon_locator_("themes/units.png"),
00048 vision_icon_locator_("misc/invisible.png"),
00049 time_limit_icon_locator_("themes/sand-clock.png"),
00050 observer_icon_locator_(game_config::observer_image),
00051 no_observer_icon_locator_("misc/no_observer.png"), map_hashes_(map_hashes),
00052 item_height_(100), margin_(5), minimap_size_(item_height_ - 2*margin_), h_padding_(5),
00053 header_height_(20), selected_(0), visible_range_(std::pair<size_t,size_t>(0,0)),
00054 double_clicked_(false), ignore_next_doubleclick_(false), last_was_doubleclick_(false)
00055 {
00056 set_numeric_keypress_selection(false);
00057 }
00058
00059 void gamebrowser::set_inner_location(const SDL_Rect& rect)
00060 {
00061 set_full_size(games_.size());
00062 set_shown_size(rect.h / row_height());
00063 bg_register(rect);
00064 scroll(get_position());
00065 }
00066
00067 void gamebrowser::scroll(unsigned int pos)
00068 {
00069 if(pos < games_.size()) {
00070 visible_range_.first = pos;
00071 visible_range_.second = minimum<size_t>(pos + inner_location().h / row_height(), games_.size());
00072 set_dirty();
00073 }
00074 }
00075
00076 SDL_Rect gamebrowser::get_item_rect(size_t index) const {
00077 if(index < visible_range_.first || index > visible_range_.second) {
00078 const SDL_Rect res = { 0, 0, 0, 0 };
00079 return res;
00080 }
00081 const SDL_Rect& loc = inner_location();
00082 const SDL_Rect res = { loc.x, loc.y + (index - visible_range_.first) * row_height(), loc.w, row_height()};
00083 return res;
00084 }
00085
00086 void gamebrowser::draw()
00087 {
00088 if(hidden())
00089 return;
00090 if(dirty()) {
00091 bg_restore();
00092 util::scoped_ptr<clip_rect_setter> clipper(NULL);
00093 if(clip_rect())
00094 clipper.assign(new clip_rect_setter(video().getSurface(), *clip_rect()));
00095 draw_contents();
00096 update_rect(location());
00097 set_dirty(false);
00098 }
00099 }
00100
00101 void gamebrowser::draw_contents()
00102 {
00103 if(!games_.empty()) {
00104 for(size_t i = visible_range_.first; i != visible_range_.second; ++i) {
00105 style_->draw_row(*this,i,get_item_rect(i),(i==selected_)? SELECTED_ROW : NORMAL_ROW);
00106 }
00107 } else {
00108 const SDL_Rect rect = inner_location();
00109 font::draw_text(&video(), rect, font::SIZE_NORMAL, font::NORMAL_COLOUR, _("--no games open--"), rect.x + margin_, rect.y + margin_);
00110 }
00111 }
00112
00113 void gamebrowser::draw_row(const size_t index, const SDL_Rect& item_rect, ROW_TYPE ) {
00114 const game_item& game = games_[index];
00115 int xpos = item_rect.x + margin_;
00116 int ypos = item_rect.y + margin_;
00117
00118
00119 if (game.mini_map != NULL) {
00120 int minimap_x = xpos + (minimap_size_ - game.mini_map->w)/2;
00121 int minimap_y = ypos + (minimap_size_ - game.mini_map->h)/2;
00122 video().blit_surface(minimap_x, minimap_y, game.mini_map);
00123 }
00124 xpos += minimap_size_ + margin_;
00125
00126
00127 SDL_Color font_color;
00128 if (!game.password_required) {
00129 font_color = font::BAD_COLOUR;
00130 } else if (game.vacant_slots > 0) {
00131 if (game.reloaded || game.started) {
00132 font_color = font::YELLOW_COLOUR;
00133 } else {
00134 font_color = font::GOOD_COLOUR;
00135 }
00136 } else {
00137 if (game.observers) {
00138 font_color = font::NORMAL_COLOUR;
00139 } else {
00140 font_color = font::BAD_COLOUR;
00141 }
00142 }
00143
00144 const surface status_text(font::get_rendered_text(game.status,
00145 font::SIZE_NORMAL, font_color));
00146 const int status_text_width = status_text ? status_text->w : 0;
00147
00148
00149 const surface name_surf(font::get_rendered_text(
00150 font::make_text_ellipsis(game.name, font::SIZE_PLUS,
00151 (item_rect.x + item_rect.w) - xpos - margin_ - status_text_width - h_padding_),
00152 font::SIZE_PLUS, font_color));
00153 video().blit_surface(xpos, ypos, name_surf);
00154
00155
00156 if(status_text) {
00157
00158 video().blit_surface(item_rect.x + item_rect.w - margin_ - status_text_width,
00159 ypos + name_surf->h - status_text->h, status_text);
00160 }
00161
00162
00163 ypos = item_rect.y + item_rect.h/2;
00164
00165
00166 const surface map_info_surf(font::get_rendered_text(
00167 font::make_text_ellipsis(game.map_info, font::SIZE_NORMAL,
00168 (item_rect.x + item_rect.w) - xpos - margin_),
00169 font::SIZE_NORMAL, font::NORMAL_COLOUR));
00170 if(map_info_surf) {
00171 video().blit_surface(xpos, ypos - map_info_surf->h/2, map_info_surf);
00172 }
00173
00174
00175 ypos = item_rect.y + item_rect.h - margin_;
00176
00177
00178 const surface observer_icon(image::get_image(game.observers
00179 ? observer_icon_locator_ : no_observer_icon_locator_));
00180 if(observer_icon) {
00181 video().blit_surface(xpos, ypos - observer_icon->h, observer_icon);
00182
00183
00184
00185 ypos -= observer_icon->h/2;
00186 xpos += observer_icon->w + 2 * h_padding_;
00187 }
00188
00189
00190 const surface gold_icon(image::get_image(gold_icon_locator_));
00191 if(gold_icon) {
00192 video().blit_surface(xpos, ypos - gold_icon->h/2, gold_icon);
00193
00194 xpos += gold_icon->w + h_padding_;
00195 }
00196
00197
00198 const surface gold_text(font::get_rendered_text(game.gold, font::SIZE_NORMAL,
00199 game.use_map_settings ? font::GRAY_COLOUR : font::NORMAL_COLOUR));
00200 if(gold_text) {
00201 video().blit_surface(xpos, ypos - gold_text->h/2, gold_text);
00202
00203 xpos += gold_text->w + 2 * h_padding_;
00204 }
00205
00206
00207 const surface xp_icon(image::get_image(xp_icon_locator_));
00208 if(xp_icon) {
00209 video().blit_surface(xpos, ypos - xp_icon->h/2, xp_icon);
00210
00211 xpos += xp_icon->w + h_padding_;
00212 }
00213
00214
00215 const surface xp_text(font::get_rendered_text(game.xp, font::SIZE_NORMAL,
00216 font::NORMAL_COLOUR));
00217 if(xp_text) {
00218 video().blit_surface(xpos, ypos - xp_text->h/2, xp_text);
00219
00220 xpos += xp_text->w + 2 * h_padding_;
00221 }
00222
00223 if(!game.time_limit.empty()) {
00224
00225 const surface time_icon(image::get_image(time_limit_icon_locator_));
00226 video().blit_surface(xpos, ypos - time_icon->h/2, time_icon);
00227
00228 xpos += time_icon->w + h_padding_;
00229
00230
00231 const surface time_text(font::get_rendered_text(game.time_limit,
00232 font::SIZE_NORMAL, font::NORMAL_COLOUR));
00233 video().blit_surface(xpos, ypos - time_text->h/2, time_text);
00234
00235 xpos += time_text->w + 2 * h_padding_;
00236 }
00237
00238
00239 const surface vision_icon(image::get_image(vision_icon_locator_));
00240 if(vision_icon) {
00241 video().blit_surface(xpos, ypos - vision_icon->h/2, vision_icon);
00242
00243 xpos += vision_icon->w + h_padding_;
00244 }
00245
00246
00247 const surface vision_text(font::get_rendered_text(
00248 font::make_text_ellipsis(game.vision, font::SIZE_NORMAL,
00249 (item_rect.x + item_rect.w) - xpos - margin_),
00250 font::SIZE_NORMAL,
00251 game.use_map_settings ? font::GRAY_COLOUR : font::NORMAL_COLOUR));
00252 if(vision_text) {
00253 video().blit_surface(xpos, ypos - vision_text->h/2, vision_text);
00254 }
00255
00256
00257 if (game.use_map_settings) {
00258 xpos += vision_text->w + 4 * h_padding_;
00259 const surface map_settings_text(font::get_rendered_text(
00260 font::make_text_ellipsis(_("Use map settings"), font::SIZE_NORMAL,
00261 (item_rect.x + item_rect.w) - xpos - margin_),
00262 font::SIZE_NORMAL,
00263 (game.verified && game.vacant_slots > 0)
00264 ? font::GOOD_COLOUR : font::NORMAL_COLOUR));
00265 video().blit_surface(xpos, ypos - map_settings_text->h/2, map_settings_text);
00266 }
00267 }
00268
00269 void gamebrowser::handle_event(const SDL_Event& event)
00270 {
00271 scrollarea::handle_event(event);
00272 if(event.type == SDL_KEYDOWN) {
00273 if(focus(&event) && !games_.empty()) {
00274 switch(event.key.keysym.sym) {
00275 case SDLK_UP:
00276 if(selected_ > 0) {
00277 --selected_;
00278 adjust_position(selected_);
00279 set_dirty();
00280 }
00281 break;
00282 case SDLK_DOWN:
00283 if(selected_ < games_.size() - 1) {
00284 ++selected_;
00285 adjust_position(selected_);
00286 set_dirty();
00287 }
00288 break;
00289 case SDLK_PAGEUP:
00290 {
00291 const long items_on_screen = visible_range_.second - visible_range_.first;
00292 selected_ = static_cast<size_t>(maximum<long>(static_cast<long>(selected_) - items_on_screen, 0));
00293 adjust_position(selected_);
00294 set_dirty();
00295 }
00296 break;
00297 case SDLK_PAGEDOWN:
00298 {
00299 const size_t items_on_screen = visible_range_.second - visible_range_.first;
00300 selected_ = minimum<size_t>(selected_ + items_on_screen, games_.size() - 1);
00301 adjust_position(selected_);
00302 set_dirty();
00303 }
00304 break;
00305 case SDLK_HOME:
00306 selected_ = 0;
00307 adjust_position(selected_);
00308 set_dirty();
00309 break;
00310 case SDLK_END:
00311 selected_ = games_.size() - 1;
00312 adjust_position(selected_);
00313 set_dirty();
00314 break;
00315 default:
00316 break;
00317 }
00318 }
00319 } else if((event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT) || event.type == DOUBLE_CLICK_EVENT) {
00320 int x = 0;
00321 int y = 0;
00322 if(event.type == SDL_MOUSEBUTTONDOWN) {
00323 x = event.button.x;
00324 y = event.button.y;
00325 } else {
00326 x = (long)event.user.data1;
00327 y = (long)event.user.data2;
00328 }
00329 const SDL_Rect& loc = inner_location();
00330
00331 if(!games_.empty() && point_in_rect(x, y, loc)) {
00332 for(size_t i = visible_range_.first; i != visible_range_.second; ++i) {
00333 const SDL_Rect& item_rect = get_item_rect(i);
00334
00335 if(point_in_rect(x, y, item_rect)) {
00336 set_focus(true);
00337 selected_ = i;
00338 break;
00339 }
00340 }
00341 if(event.type == DOUBLE_CLICK_EVENT) {
00342 if (ignore_next_doubleclick_) {
00343 ignore_next_doubleclick_ = false;
00344 } else if(selection_is_joinable() || selection_is_observable()) {
00345 double_clicked_ = true;
00346 last_was_doubleclick_ = true;
00347 }
00348 } else if (last_was_doubleclick_) {
00349
00350
00351
00352
00353 SDL_Event ev;
00354 SDL_PeepEvents(&ev, 1, SDL_PEEKEVENT,
00355 SDL_EVENTMASK(DOUBLE_CLICK_EVENT));
00356 if (ev.type == DOUBLE_CLICK_EVENT) {
00357 ignore_next_doubleclick_ = true;
00358 }
00359 last_was_doubleclick_ = false;
00360 }
00361 }
00362 }
00363 }
00364
00365 struct minimap_cache_item {
00366 std::string map_data;
00367 surface mini_map;
00368 std::string map_info_size;
00369 };
00370
00371 void gamebrowser::set_game_items(const config& cfg, const config& game_config)
00372 {
00373 const bool scrolled_to_max = (has_scrollbar() && get_position() == get_max_position());
00374 const bool selection_visible = (selected_ >= visible_range_.first && selected_ <= visible_range_.second);
00375 const std::string selected_game = (selected_ < games_.size()) ? games_[selected_].id : "";
00376
00377 item_height_ = 100;
00378
00379
00380 std::vector<minimap_cache_item> minimap_cache;
00381 for(std::vector<game_item>::iterator oldgame = games_.begin(); oldgame != games_.end(); ++oldgame) {
00382 minimap_cache_item item;
00383 item.map_data = oldgame->map_data;
00384 item.mini_map = oldgame->mini_map;
00385 item.map_info_size = oldgame->map_info_size;
00386 minimap_cache.push_back(item);
00387 }
00388
00389 games_.clear();
00390 config::child_list games = cfg.get_children("game");
00391 config::child_iterator game;
00392
00393 for(game = games.begin(); game != games.end(); ++game) {
00394 bool verified = true;
00395 games_.push_back(game_item());
00396 games_.back().password_required = (**game)["password"] == "yes";
00397 games_.back().reloaded = (**game)["savegame"] == "yes";
00398 games_.back().have_era = true;
00399 if((**game)["mp_era"] != "") {
00400 const config* const era_cfg = game_config.find_child("era", "id", (**game)["mp_era"]);
00401 utils::string_map symbols;
00402 symbols["era_id"] = (**game)["mp_era"];
00403 if (era_cfg != NULL) {
00404 games_.back().map_info = era_cfg->get_attribute("name");
00405 } else {
00406 if((**game)["require_era"] == "yes") {
00407 games_.back().have_era = false;
00408 }
00409 games_.back().map_info = vgettext("Unknown era: $era_id", symbols);
00410 verified = false;
00411 }
00412 } else {
00413 games_.back().map_info = _("Unknown era");
00414 verified = false;
00415 }
00416 games_.back().map_data = (**game)["map_data"];
00417 if(games_.back().map_data.empty()) {
00418 games_.back().map_data = read_map((**game)["map"]);
00419 }
00420
00421 if(! games_.back().map_data.empty()) {
00422 try {
00423 std::vector<minimap_cache_item>::iterator i;
00424 bool found = false;
00425 for(i = minimap_cache.begin(); i != minimap_cache.end() && !found; ++i) {
00426 if (i->map_data == games_.back().map_data) {
00427 found = true;
00428 games_.back().map_info_size = i->map_info_size;
00429 games_.back().mini_map = i->mini_map;
00430 }
00431 }
00432 if (!found) {
00433
00434 gamemap map(game_config, games_.back().map_data);
00435 games_.back().mini_map = image::getMinimap(minimap_size_, minimap_size_, map, 0);
00436 games_.back().map_info_size = lexical_cast_default<std::string, int>(map.w(), "??")
00437 + std::string("x") + lexical_cast_default<std::string, int>(map.h(), "??");
00438 }
00439 games_.back().map_info += " - " + games_.back().map_info_size;
00440 } catch(gamemap::incorrect_format_exception &e) {
00441 ERR_CF << "illegal map: " << e.msg_ << "\n";
00442 verified = false;
00443 } catch(twml_exception& e) {
00444 ERR_CF << "map could not be loaded: " << e.dev_message << '\n';
00445 verified = false;
00446 }
00447 } else {
00448 games_.back().map_info += " - ??x??";
00449 }
00450 games_.back().map_info += " ";
00451 if((**game)["mp_scenario"] != "") {
00452
00453 const config* level_cfg = game_config.find_child("multiplayer", "id", (**game)["mp_scenario"]);
00454 if(level_cfg == NULL) {
00455
00456 level_cfg = game_config.find_child("generic_multiplayer", "id", (**game)["mp_scenario"]);
00457 }
00458 if(level_cfg) {
00459 games_.back().map_info += level_cfg->get_attribute("name");
00460
00461
00462
00463 if (map_hashes_ && !games_.back().reloaded) {
00464 const std::string& hash = (**game)["hash"];
00465 bool hash_found = false;
00466 for(string_map::const_iterator i = map_hashes_->values.begin(); i != map_hashes_->values.end(); ++i) {
00467 if(i->first == (**game)["mp_scenario"] && i->second == hash) {
00468 hash_found = true;
00469 break;
00470 }
00471 }
00472 if(!hash_found) {
00473 games_.back().map_info += " - ";
00474 games_.back().map_info += _("Remote scenario");
00475 verified = false;
00476 }
00477 }
00478 } else {
00479 utils::string_map symbols;
00480 symbols["scenario_id"] = (**game)["mp_scenario"];
00481 games_.back().map_info += vgettext("Unknown scenario: $scenario_id", symbols);
00482 verified = false;
00483 }
00484 } else {
00485 games_.back().map_info += _("Unknown scenario");
00486 verified = false;
00487 }
00488 if (games_.back().reloaded) {
00489 games_.back().map_info += " - ";
00490 games_.back().map_info += _("Reloaded game");
00491 verified = false;
00492 }
00493 games_.back().id = (**game)["id"];
00494 games_.back().name = (**game)["name"];
00495 const std::string& turn = (**game)["turn"];
00496 const std::string& slots = (**game)["slots"];
00497 games_.back().vacant_slots = lexical_cast_default<size_t>(slots, 0);
00498 games_.back().current_turn = 0;
00499 if(turn != "") {
00500 games_.back().started = true;
00501 int index = turn.find_first_of('/');
00502 if (index > -1){
00503 const std::string current_turn = turn.substr(0, index);
00504 games_.back().current_turn = lexical_cast<unsigned int>(current_turn);
00505 }
00506 games_.back().status = _("Turn ") + turn;
00507 } else {
00508 games_.back().started = false;
00509 if (games_.back().vacant_slots > 0) {
00510 games_.back().status = std::string(_n("Vacant Slot:", "Vacant Slots:",
00511 games_.back().vacant_slots)) + " " + slots;
00512 if (games_.back().password_required) {
00513 games_.back().status += std::string(" (") + std::string(_("Password Required")) + ")";
00514 }
00515 }
00516 }
00517
00518 games_.back().use_map_settings = ((**game)["mp_use_map_settings"] == "yes");
00519 games_.back().gold = (**game)["mp_village_gold"];
00520 if((**game)["mp_fog"] == "yes") {
00521 games_.back().vision = _("Fog");
00522 games_.back().fog = true;
00523 if((**game)["mp_shroud"] == "yes") {
00524 games_.back().vision += "/";
00525 games_.back().vision += _("Shroud");
00526 games_.back().shroud = true;
00527 } else {
00528 games_.back().shroud = false;
00529 }
00530 } else if((**game)["mp_shroud"] == "yes") {
00531 games_.back().vision = _("Shroud");
00532 games_.back().fog = false;
00533 games_.back().shroud = true;
00534 } else {
00535 games_.back().vision = _("none");
00536 games_.back().fog = false;
00537 games_.back().shroud = false;
00538 }
00539 if((**game)["mp_countdown"] == "yes" ) {
00540 games_.back().time_limit = (**game)["mp_countdown_init_time"] + " / +"
00541 + (**game)["mp_countdown_turn_bonus"] + " "
00542 + (**game)["mp_countdown_action_bonus"];
00543 } else {
00544 games_.back().time_limit = "";
00545 }
00546 games_.back().xp = (**game)["experience_modifier"] + "%";
00547 games_.back().observers = (**game)["observer"] != "no" ? true : false;
00548 games_.back().verified = verified;
00549 }
00550 set_full_size(games_.size());
00551 set_shown_size(inner_location().h / row_height());
00552
00553
00554 if (!selected_game.empty()) {
00555 for (unsigned int i=0; i < games_.size(); i++) {
00556 if (games_[i].id == selected_game) {
00557 selected_ = i;
00558 break;
00559 }
00560 }
00561 }
00562 if(selected_ >= games_.size())
00563 selected_ = maximum<long>(static_cast<long>(games_.size()) - 1, 0);
00564
00565 if (scrolled_to_max) {
00566 set_position(get_max_position());
00567 } else {
00568
00569 if (selection_visible && (visible_range_.first > selected_
00570 || visible_range_.second < selected_)) {
00571 set_position(selected_);
00572 }
00573 }
00574 scroll(get_position());
00575 set_dirty();
00576 }
00577
00578 lobby::lobby_sorter::lobby_sorter(const config& cfg) : cfg_(cfg)
00579 {
00580 set_alpha_sort(1);
00581 }
00582
00583 bool lobby::lobby_sorter::column_sortable(int column) const
00584 {
00585 switch(column)
00586 {
00587 case MAP_COLUMN:
00588 case STATUS_COLUMN:
00589 return true;
00590 default:
00591 return basic_sorter::column_sortable(column);
00592 }
00593 }
00594
00595 bool lobby::lobby_sorter::less(int column, const gui::menu::item& row1, const gui::menu::item& row2) const
00596 {
00597 const config* const list = cfg_.child("gamelist");
00598 if(list == NULL) {
00599 return false;
00600 }
00601
00602 const config::child_list& games = list->get_children("game");
00603 if(row1.id >= games.size() || row2.id >= games.size()) {
00604 return false;
00605 }
00606
00607 const config& game1 = *games[row1.id];
00608 const config& game2 = *games[row2.id];
00609
00610 if(column == MAP_COLUMN) {
00611 size_t mapsize1 = game1["map_data"].size();
00612 if(mapsize1 == 0) {
00613 mapsize1 = game1["map"].size();
00614 }
00615
00616 size_t mapsize2 = game2["map_data"].size();
00617 if(mapsize2 == 0) {
00618 mapsize2 = game2["map"].size();
00619 }
00620
00621 return mapsize1 < mapsize2;
00622
00623 } else if(column == STATUS_COLUMN) {
00624 const int nslots1 = atoi(game1["slots"].c_str());
00625 const int nslots2 = atoi(game2["slots"].c_str());
00626
00627 const int turn1 = atoi(game1["turn"].c_str());
00628 const int turn2 = atoi(game2["turn"].c_str());
00629
00630 if(nslots1 > nslots2) {
00631 return true;
00632 } else if(nslots1 < nslots2) {
00633 return false;
00634 } else {
00635 return turn1 < turn2;
00636 }
00637 } else {
00638 return basic_sorter::less(column,row1,row2);
00639 }
00640
00641 return false;
00642 }
00643
00644 lobby::lobby(game_display& disp, const config& cfg, chat& c, config& gamelist) :
00645 mp::ui(disp, _("Game Lobby"), cfg, c, gamelist),
00646
00647 observe_game_(disp.video(), _("Observe Game")),
00648 join_game_(disp.video(), _("Join Game")),
00649 create_game_(disp.video(), _("Create Game")),
00650 skip_replay_(disp.video(), _("Quick Replays"), gui::button::TYPE_CHECK),
00651 #ifndef USE_TINY_GUI
00652 game_preferences_(disp.video(), _("Preferences")),
00653 #endif
00654 quit_game_(disp.video(), _("Quit")),
00655 last_selected_game_(-1), sorter_(gamelist),
00656 games_menu_(disp.video(),cfg.child("multiplayer_hashes"))
00657 {
00658 skip_replay_.set_check(preferences::skip_mp_replay());
00659 skip_replay_.set_help_string(_("Skip quickly to the active turn when observing"));
00660 game_config::debug = false;
00661 gamelist_updated();
00662 sound::play_music_repeatedly(game_config::lobby_music);
00663 }
00664
00665 void lobby::hide_children(bool hide)
00666 {
00667 ui::hide_children(hide);
00668
00669 games_menu_.hide(hide);
00670 observe_game_.hide(hide);
00671 join_game_.hide(hide);
00672 create_game_.hide(hide);
00673 skip_replay_.hide(hide);
00674 #ifndef USE_TINY_GUI
00675 game_preferences_.hide(hide);
00676 #endif
00677 quit_game_.hide(hide);
00678 }
00679
00680 void lobby::layout_children(const SDL_Rect& rect)
00681 {
00682 ui::layout_children(rect);
00683
00684 #ifdef USE_TINY_GUI
00685 int btn_space = 3;
00686 int xborder = 0;
00687 int yborder = 0;
00688 #else
00689 int btn_space = 5;
00690 int xborder = 10;
00691 int yborder = 7;
00692 #endif
00693
00694
00695 join_game_.set_location(xscale(xborder), yscale(yborder));
00696 observe_game_.set_location(join_game_.location().x + join_game_.location().w + btn_space, yscale(yborder));
00697 create_game_.set_location(observe_game_.location().x + observe_game_.location().w + btn_space, yscale(yborder));
00698
00699 #ifndef USE_TINY_GUI
00700
00701 quit_game_.set_location(xscale(xscale_base - xborder) - quit_game_.location().w, yscale(yborder));
00702
00703
00704 int space = (quit_game_.location().x - create_game_.location().x - create_game_.location().w
00705 - skip_replay_.location().w - game_preferences_.location().w - btn_space) / 2;
00706 if (space < btn_space) space = btn_space;
00707 skip_replay_.set_location(create_game_.location().x + create_game_.location().w + space, yscale(yborder));
00708 game_preferences_.set_location(quit_game_.location().x - game_preferences_.location().w - space, yscale(yborder));
00709 #else
00710 skip_replay_.set_location(create_game_.location().x + create_game_.location().w, yscale(yborder));
00711 quit_game_.set_location(skip_replay_.location().x + skip_replay_.location().w + btn_space, yscale(yborder));
00712 #endif
00713
00714 games_menu_.set_location(client_area().x, client_area().y + title().height());
00715 games_menu_.set_measurements(client_area().w, client_area().h
00716 - title().height() - gui::ButtonVPadding);
00717 }
00718
00719 void lobby::gamelist_updated(bool silent)
00720 {
00721 ui::gamelist_updated(silent);
00722
00723 const config* list = gamelist().child("gamelist");
00724 if(list == NULL) {
00725
00726 return;
00727 }
00728 games_menu_.set_game_items(*list, game_config());
00729 join_game_.enable(games_menu_.selection_is_joinable());
00730 observe_game_.enable(games_menu_.selection_is_observable());
00731 }
00732
00733 void lobby::process_event()
00734 {
00735 join_game_.enable(games_menu_.selection_is_joinable());
00736 observe_game_.enable(games_menu_.selection_is_observable());
00737
00738 const bool observe = (observe_game_.pressed() || (games_menu_.selected() && !games_menu_.selection_is_joinable())) && games_menu_.selection_is_observable();
00739 const bool join = (join_game_.pressed() || games_menu_.selected()) && games_menu_.selection_is_joinable();
00740 games_menu_.reset_selection();
00741 preferences::set_skip_mp_replay(skip_replay_.checked());
00742 playmp_controller::set_replay_last_turn(0);
00743 preferences::set_message_private(false);
00744
00745 int selected_game = games_menu_.selection();
00746 if (selected_game != last_selected_game_) {
00747 if (games_menu_.empty()) {
00748 set_selected_game("");
00749 } else {
00750 set_selected_game(games_menu_.selected_game().id);
00751 }
00752 ui::gamelist_updated();
00753 last_selected_game_ = selected_game;
00754 }
00755
00756 if(join || observe) {
00757 const int selected = games_menu_.selection();
00758 if(!games_menu_.empty() && selected >= 0) {
00759 gamebrowser::game_item game = games_menu_.selected_game();
00760
00761 std::string password;
00762 if(join && game.password_required) {
00763 const int res = gui::show_dialog(disp_, NULL, _("Password Required"),
00764 _("Joining this game requires a password."),
00765 gui::OK_CANCEL, NULL, NULL, _("Password: "), &password);
00766 if(res != 0) {
00767 return;
00768 }
00769 }
00770
00771 config response;
00772 config& join = response.add_child("join");
00773 join["id"] = game.id;
00774 if (observe){
00775 join["observe"] = "yes";
00776 }
00777 else{
00778 join["observe"] = "no";
00779 }
00780
00781 if(!password.empty()) {
00782 join["password"] = password;
00783 }
00784 network::send_data(response, 0, true);
00785
00786 if(observe) {
00787 if (game.started){
00788 playmp_controller::set_replay_last_turn(game.current_turn);
00789 }
00790 set_result(OBSERVE);
00791 } else {
00792 set_result(JOIN);
00793 }
00794 }
00795 return;
00796 }
00797
00798 if(create_game_.pressed()) {
00799 set_result(CREATE);
00800 return;
00801 }
00802
00803 #ifndef USE_TINY_GUI
00804 if(game_preferences_.pressed()) {
00805 set_result(PREFERENCES);
00806 return;
00807 }
00808 #endif
00809
00810 if(quit_game_.pressed()) {
00811 recorder.set_skip(false);
00812 set_result(QUIT);
00813 return;
00814 }
00815 }
00816
00817 void lobby::process_network_data(const config& data, const network::connection sock)
00818 {
00819 ui::process_network_data(data, sock);
00820
00821
00822 last_selected_game_ = -1;
00823 }
00824
00825 }
00826