diff --git a/data/gui/dialogs/online/server_info_dialog.stkgui b/data/gui/dialogs/online/server_info_dialog.stkgui index 676bb71a0..045f97e84 100644 --- a/data/gui/dialogs/online/server_info_dialog.stkgui +++ b/data/gui/dialogs/online/server_info_dialog.stkgui @@ -29,6 +29,8 @@ + diff --git a/data/gui/screens/online/server_selection.stkgui b/data/gui/screens/online/server_selection.stkgui index a79343092..f08e09bda 100644 --- a/data/gui/screens/online/server_selection.stkgui +++ b/data/gui/screens/online/server_selection.stkgui @@ -3,11 +3,12 @@
+
-
+
diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index 04224087a..dc7367f07 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -803,6 +803,11 @@ namespace UserConfigParams PARAM_PREFIX bool m_profiler_enabled PARAM_DEFAULT( false ); // ---- Networking + PARAM_PREFIX StringToUIntUserConfigParam m_server_bookmarks + PARAM_DEFAULT(StringToUIntUserConfigParam("server-bookmarks", + "Wan server bookmarks", + {{ "server-bookmarks", "server-name", "owner" }}, {})); + PARAM_PREFIX StringToUIntUserConfigParam m_address_history PARAM_DEFAULT(StringToUIntUserConfigParam("address-history", "Last 5 IP addresses that user entered", diff --git a/src/network/server.cpp b/src/network/server.cpp index 3217fbf83..dc06a01c2 100644 --- a/src/network/server.cpp +++ b/src/network/server.cpp @@ -240,6 +240,13 @@ void Server::setAddress(const SocketAddress& addr) m_address.reset(new SocketAddress(addr)); } // setAddress +// ---------------------------------------------------------------------------- +std::string Server::getBookmarkKey() const +{ + return StringUtils::xmlEncode(m_name) + + StringUtils::toString(m_server_owner); +} // getBookmarkKey + // ---------------------------------------------------------------------------- void UserDefinedServer::saveServer() const { diff --git a/src/network/server.hpp b/src/network/server.hpp index 892a43642..4a5b10c3b 100644 --- a/src/network/server.hpp +++ b/src/network/server.hpp @@ -208,6 +208,8 @@ public: // ------------------------------------------------------------------------ void setReconnectWhenQuitLobby(bool val) { m_reconnect_when_quit_lobby = val; } + // ------------------------------------------------------------------------ + std::string getBookmarkKey() const; }; // Server class UserDefinedServer : public Server diff --git a/src/states_screens/dialogs/server_info_dialog.cpp b/src/states_screens/dialogs/server_info_dialog.cpp index 7217bdaca..afc8017e9 100644 --- a/src/states_screens/dialogs/server_info_dialog.cpp +++ b/src/states_screens/dialogs/server_info_dialog.cpp @@ -17,6 +17,8 @@ #include "states_screens/dialogs/server_info_dialog.hpp" +#include "io/file_manager.hpp" +#include "graphics/irr_driver.hpp" #include "guiengine/engine.hpp" #include "guiengine/widgets/icon_button_widget.hpp" #include "guiengine/widgets/label_widget.hpp" @@ -27,6 +29,7 @@ #include "network/server_config.hpp" #include "network/stk_host.hpp" #include "states_screens/online/networking_lobby.hpp" +#include "states_screens/online/server_selection.hpp" #include "states_screens/state_manager.hpp" #include "tracks/track.hpp" #include "utils/string_utils.hpp" @@ -54,6 +57,11 @@ ServerInfoDialog::ServerInfoDialog(std::shared_ptr server) m_self_destroy = false; m_join_server = false; + m_bookmark_icon = irr_driver->getTexture + (file_manager->getAsset(FileManager::GUI_ICON, "story_mode_book.png")); + m_remove_icon = irr_driver->getTexture + (file_manager->getAsset(FileManager::GUI_ICON, "remove.png")); + loadFromFile("online/server_info_dialog.stkgui"); getWidget("title")->setText(server->getName(), true); @@ -145,6 +153,8 @@ ServerInfoDialog::ServerInfoDialog(std::shared_ptr server) { getWidget("player-list")->setVisible(false); } + if (m_server->getServerOwner() != 0) + updateBookmarkStatus(false); } // ServerInfoDialog // ----------------------------------------------------------------------------- @@ -186,11 +196,16 @@ GUIEngine::EventPropagation m_self_destroy = true; return GUIEngine::EVENT_BLOCK; } - else if(selection == m_join_widget->m_properties[PROP_ID]) + else if (selection == m_join_widget->m_properties[PROP_ID]) { m_join_server = true; return GUIEngine::EVENT_BLOCK; } + else if (selection == m_bookmark_widget->m_properties[PROP_ID]) + { + updateBookmarkStatus(true); + return GUIEngine::EVENT_BLOCK; + } } return GUIEngine::EVENT_LET; } // processEvent @@ -234,3 +249,45 @@ void ServerInfoDialog::onUpdate(float dt) if (m_join_server) requestJoin(); } // onUpdate + +// ----------------------------------------------------------------------------- +void ServerInfoDialog::updateBookmarkStatus(bool change_bookmark) +{ + const std::string& key = m_server->getBookmarkKey(); + std::map& bookmarks = + UserConfigParams::m_server_bookmarks; + auto it = bookmarks.find(key); + if (it == bookmarks.end()) + { + if (change_bookmark) + { + bookmarks[key] = m_server->getServerOwner(); + m_bookmark_widget->setLabel(_("Remove from bookmarks")); + m_bookmark_widget->setImage(m_remove_icon); + } + } + else + { + if (change_bookmark) + { + bookmarks.erase(key); + m_bookmark_widget->setLabel(_("Bookmark this server")); + m_bookmark_widget->setImage(m_bookmark_icon); + } + else + { + m_bookmark_widget->setLabel(_("Remove from bookmarks")); + m_bookmark_widget->setImage(m_remove_icon); + } + } + ServerSelection::getInstance()->copyFromServerList(); +} // updateBookmarkStatus + +// ----------------------------------------------------------------------------- +void ServerInfoDialog::beforeAddingWidgets() +{ + m_bookmark_widget = getWidget("bookmark"); + assert(m_bookmark_widget != NULL); + if (m_server->getServerOwner() == 0) + m_bookmark_widget->setVisible(false); +} diff --git a/src/states_screens/dialogs/server_info_dialog.hpp b/src/states_screens/dialogs/server_info_dialog.hpp index e7d96b071..205ada4e1 100644 --- a/src/states_screens/dialogs/server_info_dialog.hpp +++ b/src/states_screens/dialogs/server_info_dialog.hpp @@ -54,15 +54,23 @@ private: /** The cancel button. */ GUIEngine::IconButtonWidget *m_cancel_widget; + GUIEngine::IconButtonWidget *m_bookmark_widget; + /** Specify server password if needed. */ GUIEngine::TextBoxWidget* m_password; + video::ITexture* m_bookmark_icon; + + video::ITexture* m_remove_icon; + + void updateBookmarkStatus(bool change_bookmark); public: ServerInfoDialog(std::shared_ptr server); ~ServerInfoDialog(); void onEnterPressedInternal(); GUIEngine::EventPropagation processEvent(const std::string& eventSource); + virtual void beforeAddingWidgets(); virtual bool onEscapePressed(); virtual void onUpdate(float dt); diff --git a/src/states_screens/online/server_selection.cpp b/src/states_screens/online/server_selection.cpp index 20a07fb11..16a1b008b 100644 --- a/src/states_screens/online/server_selection.cpp +++ b/src/states_screens/online/server_selection.cpp @@ -42,7 +42,7 @@ #include using namespace Online; - +bool g_bookmarks_next = false; // ---------------------------------------------------------------------------- /** Constructor, which loads the stkgui file. */ @@ -112,6 +112,12 @@ void ServerSelection::loadedFromFile() assert(m_searcher != NULL); m_ipv6->setState(false); m_icon_bank = new irr::gui::STKModifiedSpriteBank(GUIEngine::getGUIEnv()); + m_bookmark_widget = getWidget("bookmark"); + assert(m_bookmark_widget != NULL); + m_bookmark_icon = irr_driver->getTexture + (file_manager->getAsset(FileManager::GUI_ICON, "story_mode_book.png")); + m_global_icon = irr_driver->getTexture + (file_manager->getAsset(FileManager::GUI_ICON, "main_network.png")); } // loadedFromFile // ---------------------------------------------------------------------------- @@ -141,7 +147,9 @@ void ServerSelection::beforeAddingWidget() void ServerSelection::init() { Screen::init(); + m_last_load_time = -5000; + updateHeader(); #ifndef ENABLE_IPV6 m_ipv6->setState(false); @@ -207,6 +215,7 @@ void ServerSelection::init() void ServerSelection::loadList() { m_server_list_widget->clear(); + std::stable_sort(m_servers.begin(), m_servers.end(), [this] (const std::shared_ptr a, const std::shared_ptr b)->bool @@ -323,6 +332,12 @@ void ServerSelection::eventCallback(GUIEngine::Widget* widget, { refresh(); } + else if (name == "bookmark") + { + g_bookmarks_next = !g_bookmarks_next; + updateHeader(); + copyFromServerList(); + } else if (name == "private_server" || name == "ipv6") { if (!m_ip_warning_shown && m_ipv6->getState() && @@ -401,6 +416,24 @@ void ServerSelection::onUpdate(float dt) m_refreshing_server = false; if (!m_server_list->m_servers.empty()) { + std::set all_possible_keys; + if (NetworkConfig::get()->isWAN()) + { + // Remove offline server from bookmarks + for (auto& server : m_server_list->m_servers) + all_possible_keys.insert(server->getBookmarkKey()); + std::map& bookmarks = + UserConfigParams::m_server_bookmarks; + auto it = bookmarks.begin(); + while (it != bookmarks.end()) + { + if (all_possible_keys.find(it->first) == + all_possible_keys.end()) + it = bookmarks.erase(it); + else + it++; + } + } int selection = m_server_list_widget->getSelectionID(); std::string selection_str = m_server_list_widget ->getSelectionInternalName(); @@ -460,6 +493,18 @@ void ServerSelection::copyFromServerList() return false; }), m_servers.end()); } + if (g_bookmarks_next) + { + m_servers.erase(std::remove_if(m_servers.begin(), m_servers.end(), + [](const std::shared_ptr& a)->bool + { + const std::string& key = a->getBookmarkKey(); + auto it = UserConfigParams::m_server_bookmarks.find(key); + if (it == UserConfigParams::m_server_bookmarks.end()) + return true; + return false; + }), m_servers.end()); + } loadList(); } // copyFromServerList @@ -469,3 +514,14 @@ void ServerSelection::unloaded() delete m_icon_bank; m_icon_bank = NULL; } // unloaded + +// ---------------------------------------------------------------------------- +void ServerSelection::updateHeader() +{ + m_bookmark_widget->setImage(g_bookmarks_next ? + m_global_icon : m_bookmark_icon); + if (g_bookmarks_next) + getWidget("title_header")->setText(_("Server Bookmarks")); + else + getWidget("title_header")->setText(_("Server Selection")); +} // updateHeader diff --git a/src/states_screens/online/server_selection.hpp b/src/states_screens/online/server_selection.hpp index 5c96b2b5c..a6a996b26 100644 --- a/src/states_screens/online/server_selection.hpp +++ b/src/states_screens/online/server_selection.hpp @@ -64,6 +64,9 @@ private: GUIEngine::CheckBoxWidget* m_private_server; GUIEngine::CheckBoxWidget* m_ipv6; GUIEngine::IconButtonWidget* m_reload_widget; + GUIEngine::IconButtonWidget* m_bookmark_widget; + video::ITexture* m_bookmark_icon; + video::ITexture* m_global_icon; GUIEngine::LabelWidget* m_update_status; GUIEngine::ListWidget* m_server_list_widget; GUIEngine::TextBoxWidget* m_searcher; @@ -81,7 +84,7 @@ private: /** Load the servers into the main list.*/ void loadList(); - void copyFromServerList(); + void updateHeader(); void refresh(); @@ -118,6 +121,7 @@ public: virtual bool onEnterPressed(const irr::core::stringw& text) OVERRIDE { return false; } + void copyFromServerList(); }; // ServerSelection #endif