diff --git a/data/core/images/lobby/status-idle-f.png b/data/core/images/lobby/status-idle-f.png
new file mode 100644
index 00000000000..20421c4cb62
Binary files /dev/null and b/data/core/images/lobby/status-idle-f.png differ
diff --git a/data/core/images/lobby/status-idle-i.png b/data/core/images/lobby/status-idle-i.png
new file mode 100644
index 00000000000..669ef93fc69
Binary files /dev/null and b/data/core/images/lobby/status-idle-i.png differ
diff --git a/data/core/images/lobby/status-idle-n.png b/data/core/images/lobby/status-idle-n.png
new file mode 100644
index 00000000000..91a71e31418
Binary files /dev/null and b/data/core/images/lobby/status-idle-n.png differ
diff --git a/data/core/images/lobby/status-idle-s.png b/data/core/images/lobby/status-idle-s.png
new file mode 100644
index 00000000000..50b9e18ad4d
Binary files /dev/null and b/data/core/images/lobby/status-idle-s.png differ
diff --git a/data/core/images/lobby/status-lobby-f.png b/data/core/images/lobby/status-lobby-f.png
new file mode 100644
index 00000000000..5b3d590f9c3
Binary files /dev/null and b/data/core/images/lobby/status-lobby-f.png differ
diff --git a/data/core/images/lobby/status-lobby-i.png b/data/core/images/lobby/status-lobby-i.png
new file mode 100644
index 00000000000..b5e0dbb5d59
Binary files /dev/null and b/data/core/images/lobby/status-lobby-i.png differ
diff --git a/data/core/images/lobby/status-lobby-n.png b/data/core/images/lobby/status-lobby-n.png
new file mode 100644
index 00000000000..90c4d960d56
Binary files /dev/null and b/data/core/images/lobby/status-lobby-n.png differ
diff --git a/data/core/images/lobby/status-lobby-s.png b/data/core/images/lobby/status-lobby-s.png
new file mode 100644
index 00000000000..97b882f2442
Binary files /dev/null and b/data/core/images/lobby/status-lobby-s.png differ
diff --git a/data/core/images/lobby/status-obs-f.png b/data/core/images/lobby/status-obs-f.png
new file mode 100644
index 00000000000..3d48830d371
Binary files /dev/null and b/data/core/images/lobby/status-obs-f.png differ
diff --git a/data/core/images/lobby/status-obs-i.png b/data/core/images/lobby/status-obs-i.png
new file mode 100644
index 00000000000..727fb0bf2b9
Binary files /dev/null and b/data/core/images/lobby/status-obs-i.png differ
diff --git a/data/core/images/lobby/status-obs-n.png b/data/core/images/lobby/status-obs-n.png
new file mode 100644
index 00000000000..5ea0248e396
Binary files /dev/null and b/data/core/images/lobby/status-obs-n.png differ
diff --git a/data/core/images/lobby/status-playing-f.png b/data/core/images/lobby/status-playing-f.png
new file mode 100644
index 00000000000..4ca90d955e1
Binary files /dev/null and b/data/core/images/lobby/status-playing-f.png differ
diff --git a/data/core/images/lobby/status-playing-i.png b/data/core/images/lobby/status-playing-i.png
new file mode 100644
index 00000000000..1357f3f24cb
Binary files /dev/null and b/data/core/images/lobby/status-playing-i.png differ
diff --git a/data/core/images/lobby/status-playing-n.png b/data/core/images/lobby/status-playing-n.png
new file mode 100644
index 00000000000..18b42a66169
Binary files /dev/null and b/data/core/images/lobby/status-playing-n.png differ
diff --git a/data/gui/default/window/lobby_main.cfg b/data/gui/default/window/lobby_main.cfg
index 8daa22b92c3..018715938a0 100644
--- a/data/gui/default/window/lobby_main.cfg
+++ b/data/gui/default/window/lobby_main.cfg
@@ -203,11 +203,20 @@
definition = "default"
[grid]
[row]
+ [column]
+ border = "all"
+ border_size = 1
+ [image]
+ id = "main_icon"
+ definition = "default"
+ label = ""
+ [/image]
+ [/column]
[column]
grow_factor = 1
horizontal_grow = "true"
- border = "all"
- border_size = 5
+ border = "top,right,bottom"
+ border_size = 3
[label]
id = "player"
definition = "default"
diff --git a/src/gui/dialogs/lobby_main.cpp b/src/gui/dialogs/lobby_main.cpp
index 4557f8d122d..2b89a638f29 100644
--- a/src/gui/dialogs/lobby_main.cpp
+++ b/src/gui/dialogs/lobby_main.cpp
@@ -194,7 +194,7 @@ tlobby_main::tlobby_main(const config& game_config, lobby_info& info)
, gamelistbox_(NULL), chat_log_container_(NULL)
, chat_input_(NULL), window_(NULL)
, lobby_info_(info), preferences_callback_(NULL)
-, open_windows_(), active_window_(0)
+, open_windows_(), active_window_(0), selected_game_id_()
{
}
@@ -230,6 +230,11 @@ void set_visible_if_exists(tgrid* grid, const char* id, bool visible)
}
}
+std::string colorize(const std::string& str, const std::string& color)
+{
+ return "" + str + "";
+}
+
} //end anonymous namespace
void tlobby_main::update_gamelist()
@@ -309,11 +314,50 @@ void tlobby_main::update_gamelist()
}
}
update_selected_game();
+
+ lobby_info_.update_user_statuses(selected_game_id_, active_window_room());
userlistbox_->clear();
foreach (const user_info& user, lobby_info_.users())
{
std::map data;
- add_label_data(data, "player", user.name);
+ std::stringstream icon_ss;
+ std::string name = user.name;
+ icon_ss << "lobby/status";
+ switch (user.state) {
+ case user_info::SEL_ROOM:
+ /* fall through */
+ case user_info::LOBBY:
+ icon_ss << "-lobby";
+ break;
+ case user_info::SEL_GAME:
+ name = colorize(name, "cyan");
+ icon_ss << (user.observing ? "-obs" : "-playing");
+ break;
+ case user_info::GAME:
+ name = colorize(name, "red");
+ icon_ss << (user.observing ? "-obs" : "-playing"); break;
+ default:
+ ERR_NG << "Bad user state in lobby: " << user.state << "\n";
+ }
+ switch (user.relation) {
+ case user_info::ME:
+ /* fall through */
+ case user_info::NEUTRAL:
+ icon_ss << "-n";
+ break;
+ case user_info::FRIEND:
+ icon_ss << "-f";
+ break;
+ case user_info::IGNORED:
+ icon_ss << "-i";
+ break;
+ default:
+ ERR_NG << "Bad user relation in lobby: " << user.relation << "\n";
+ }
+ icon_ss << ".png";
+ add_label_data(data, "player", name);
+ add_label_data(data, "main_icon", icon_ss.str());
+
userlistbox_->add_row(data);
}
window_->invalidate_layout();
@@ -327,6 +371,9 @@ void tlobby_main::update_selected_game()
const game_info& game = *lobby_info_.games_filtered()[idx];
can_observe = game.can_observe();
can_join = game.can_join();
+ selected_game_id_ = game.id;
+ } else {
+ selected_game_id_ = 0;
}
window_->get_widget("observe_global", false).set_active(can_observe);
window_->get_widget("join_global", false).set_active(can_join);
@@ -392,6 +439,12 @@ void tlobby_main::post_show(twindow& /*window*/)
window_ = NULL;
}
+room_info* tlobby_main::active_window_room()
+{
+ const tlobby_chat_window& t = open_windows_[active_window_];
+ if (t.whisper) return NULL;
+ return lobby_info_.get_room(t.name);
+}
tlobby_chat_window* tlobby_main::room_window_open(const std::string& room, bool open_new)
{
@@ -735,7 +788,7 @@ bool tlobby_main::do_game_join(int idx, bool observe)
}
config response;
config& join = response.add_child("join");
- join["id"] = game.id;
+ join["id"] = lexical_cast(game.id);
join["observe"] = observe ? "yes" : "no";
if (join && game.password_required) {
std::string password;
diff --git a/src/gui/dialogs/lobby_main.hpp b/src/gui/dialogs/lobby_main.hpp
index 3dc07e3cc7c..b21f7c7b345 100644
--- a/src/gui/dialogs/lobby_main.hpp
+++ b/src/gui/dialogs/lobby_main.hpp
@@ -115,6 +115,12 @@ private:
*/
legacy_result legacy_result_;
+ /**
+ * Get the room* corresponding to the currently active window, or NULL
+ * if a whisper window is active at the moment
+ */
+ room_info* active_window_room();
+
/**
* Check if a room window for "room" is open, if open_new is true
* then it will be created if not found.
@@ -300,6 +306,8 @@ private:
ttoggle_button* filter_invert_;
ttext_box* filter_text_;
+
+ int selected_game_id_;
};
} // namespace gui2
diff --git a/src/lobby_data.cpp b/src/lobby_data.cpp
index 758c3bd8757..7d3ce8e0398 100644
--- a/src/lobby_data.cpp
+++ b/src/lobby_data.cpp
@@ -96,15 +96,17 @@ user_info::user_info()
, relation(ME)
, state(LOBBY)
, registered()
+ , observing()
{
}
user_info::user_info(const config& c)
: name(c["name"])
- , game_id(c["game_id"])
+ , game_id(lexical_cast_default(c["game_id"]))
, relation(ME)
- , state(c["available"] == "no" ? GAME : LOBBY)
+ , state(game_id == 0 ? LOBBY : GAME)
, registered(utils::string_bool(c["registered"]))
+ , observing(c["status"] == "observing")
{
if (name == preferences::login()) {
relation = ME;
@@ -117,12 +119,20 @@ user_info::user_info(const config& c)
}
}
-void user_info::update_state(const std::string& selected_game_id, const room_info* current_room /*= NULL*/)
+void user_info::update_state(int selected_game_id, const room_info* current_room /*= NULL*/)
{
- if (!game_id.empty() && game_id == selected_game_id) {
- state = SEL_GAME;
- } else if (state == LOBBY && current_room != NULL && current_room->is_member(name)) {
- state = SEL_ROOM;
+ if (game_id != 0) {
+ if (game_id == selected_game_id) {
+ state = SEL_GAME;
+ } else {
+ state = GAME;
+ }
+ } else if (state == LOBBY) {
+ if (current_room != NULL && current_room->is_member(name)) {
+ state = SEL_ROOM;
+ } else {
+ state = LOBBY;
+ }
}
}
@@ -178,7 +188,7 @@ std::string make_short_name(const std::string long_name)
game_info::game_info(const config& game, const config& game_config)
: mini_map()
-, id(game["id"])
+, id(lexical_cast_default(game["id"]))
, map_data(game["map_data"])
, name(game["name"])
, scenario()
@@ -456,8 +466,8 @@ void lobby_info::parse_gamelist()
games_by_id_.insert(std::make_pair(gi.id, &gi));
}
foreach (user_info& ui, users_) {
- if (!ui.game_id.empty()) {
- std::map::iterator i = games_by_id_.find(ui.game_id);
+ if (ui.game_id != 0) {
+ std::map::iterator i = games_by_id_.find(ui.game_id);
if (i == games_by_id_.end()) {
WRN_NG << "User " << ui.name << " has unknown game_id: " << ui.game_id << "\n";
} else {
@@ -551,3 +561,10 @@ void lobby_info::apply_game_filter()
}
}
}
+
+void lobby_info::update_user_statuses(int game_id, const room_info *room)
+{
+ foreach (user_info& user, users_) {
+ user.update_state(game_id, room);
+ }
+}
diff --git a/src/lobby_data.hpp b/src/lobby_data.hpp
index 1ba2333dab4..15805cc6592 100644
--- a/src/lobby_data.hpp
+++ b/src/lobby_data.hpp
@@ -88,7 +88,7 @@ struct user_info
user_info();
user_info(const config& c);
- void update_state(const std::string& selected_game_id, const room_info* current_room = NULL);
+ void update_state(int selected_game_id, const room_info* current_room = NULL);
enum user_relation { ME, FRIEND, NEUTRAL, IGNORED };
enum user_state { LOBBY, SEL_ROOM, GAME, SEL_GAME };
@@ -96,10 +96,11 @@ struct user_info
bool operator> (const user_info& b) const;
std::string name;
- std::string game_id;
+ int game_id;
user_relation relation;
user_state state;
bool registered;
+ bool observing;
};
/**
@@ -114,7 +115,7 @@ struct game_info
bool can_observe() const;
surface mini_map;
- std::string id;
+ int id;
std::string map_data;
std::string name;
std::string scenario;
@@ -269,6 +270,8 @@ public:
chat_log& get_whisper_log(const std::string& name);
+ void update_user_statuses(int game_id, const room_info* room);
+
const std::vector& rooms() const { return rooms_; }
const std::vector& games() const { return games_; }
const std::vector& games_filtered();
@@ -281,7 +284,7 @@ private:
bool gamelist_initialized_;
std::vector rooms_;
std::vector games_;
- std::map games_by_id_;
+ std::map games_by_id_;
std::vector games_filtered_;
std::vector users_;
std::map whispers_;
diff --git a/src/server/game.cpp b/src/server/game.cpp
index 482505304dd..bfd980113ee 100644
--- a/src/server/game.cpp
+++ b/src/server/game.cpp
@@ -74,7 +74,7 @@ game::game(player_map& players, const network::connection host,
}
// Mark the host as unavailable in the lobby.
pl->second.mark_available(id_, name_);
- p1->second.set_status(player::PLAYING);
+ pl->second.set_status(player::PLAYING);
}
game::~game()
@@ -277,7 +277,7 @@ void game::update_side_data() {
// * Find the username.
// * Find the side this username corresponds to.
for (user_vector::const_iterator user = users.begin(); user != users.end(); ++user) {
- const player_map::const_iterator info = player_info_->find(*user);
+ player_map::iterator info = player_info_->find(*user);
if (info == player_info_->end()) {
ERR_GAME << "Game: " << id_
<< " ERROR: unable to find user info for connection: "
@@ -343,7 +343,7 @@ void game::transfer_side_control(const network::connection sock, const simple_wm
const simple_wml::string_span& newplayer_name = cfg["player"];
const network::connection old_player = sides_[side_num - 1];
- const player_map::const_iterator oldplayer = player_info_->find(old_player);
+ const player_map::iterator oldplayer = player_info_->find(old_player);
if (oldplayer == player_info_->end()) {
WRN_GAME << "Could not find old player in player_info_. (socket: "
<< old_player << ")\n";
@@ -380,7 +380,7 @@ void game::transfer_side_control(const network::connection sock, const simple_wm
return;
}
//find the player that is passed control
- player_map::const_iterator newplayer;
+ player_map::iterator newplayer;
for (newplayer = player_info_->begin(); newplayer != player_info_->end(); newplayer++) {
if (newplayer_name == newplayer->second.name().c_str()) {
break;
@@ -1044,7 +1044,7 @@ bool game::remove_player(const network::connection player, const bool disconnect
if (*side != player) continue;
if (side_controllers_[side_num] == "ai") ai_transfer = true;
- player_map::const_iterator o = player_info_->find(owner_);
+ player_map::iterator o = player_info_->find(owner_);
const std::string owner_name = (o != player_info_->end() ? o->second.name() : "(unknown)");
change_controller(side_num, owner_, owner_name);
// Check whether the host is actually a player and make him one if not.