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