2013-07-11 21:07:26 -04:00
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
2015-03-29 20:31:42 -04:00
|
|
|
// Copyright (C) 2010-2015 Lucas Baudin, Joerg Henrichs
|
2013-07-11 21:07:26 -04:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 3
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
#include "states_screens/server_selection.hpp"
|
|
|
|
|
2014-09-17 07:38:21 -04:00
|
|
|
#include "audio/sfx_manager.hpp"
|
2018-03-13 12:50:19 -04:00
|
|
|
#include "guiengine/widgets/check_box_widget.hpp"
|
|
|
|
#include "guiengine/widgets/icon_button_widget.hpp"
|
|
|
|
#include "guiengine/widgets/label_widget.hpp"
|
2013-07-11 21:07:26 -04:00
|
|
|
#include "guiengine/modaldialog.hpp"
|
2017-01-24 22:29:48 -05:00
|
|
|
#include "network/network_config.hpp"
|
2018-03-04 12:54:44 -05:00
|
|
|
#include "network/server.hpp"
|
2015-11-12 01:52:04 -05:00
|
|
|
#include "network/servers_manager.hpp"
|
2013-07-11 21:07:26 -04:00
|
|
|
#include "states_screens/dialogs/message_dialog.hpp"
|
2013-07-12 19:12:31 -04:00
|
|
|
#include "states_screens/dialogs/server_info_dialog.hpp"
|
2013-07-11 21:07:26 -04:00
|
|
|
#include "states_screens/state_manager.hpp"
|
|
|
|
#include "utils/translation.hpp"
|
2013-07-12 19:12:31 -04:00
|
|
|
#include "utils/string_utils.hpp"
|
2014-09-17 07:38:21 -04:00
|
|
|
|
2018-03-13 12:50:19 -04:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
2013-07-11 21:07:26 -04:00
|
|
|
|
2013-07-19 17:20:32 -04:00
|
|
|
using namespace Online;
|
2013-07-18 19:02:18 -04:00
|
|
|
|
2013-07-11 21:07:26 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-02 00:24:05 -05:00
|
|
|
/** Constructor, which loads the stkgui file.
|
|
|
|
*/
|
2013-07-12 19:12:31 -04:00
|
|
|
ServerSelection::ServerSelection() : Screen("online/server_selection.stkgui")
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
2018-03-04 12:54:44 -05:00
|
|
|
m_refreshing_server = false;
|
2018-04-25 14:26:23 -04:00
|
|
|
m_refresh_timer = 0.0f;
|
2013-07-11 21:07:26 -04:00
|
|
|
} // ServerSelection
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-02 00:24:05 -05:00
|
|
|
/** Destructor.
|
|
|
|
*/
|
2013-07-21 13:41:02 -04:00
|
|
|
ServerSelection::~ServerSelection()
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
2013-07-21 13:41:02 -04:00
|
|
|
} // ServerSelection
|
|
|
|
|
2013-07-22 21:37:49 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-02 00:24:05 -05:00
|
|
|
/** Clean up.
|
|
|
|
*/
|
2013-07-22 21:37:49 -04:00
|
|
|
void ServerSelection::tearDown()
|
|
|
|
{
|
2018-03-13 12:50:19 -04:00
|
|
|
m_servers.clear();
|
2018-03-04 12:54:44 -05:00
|
|
|
ServersManager::get()->cleanUpServers();
|
|
|
|
m_server_list_widget->clear();
|
2013-07-22 21:37:49 -04:00
|
|
|
} // tearDown
|
|
|
|
|
2013-07-21 13:41:02 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-01 17:16:39 -05:00
|
|
|
/** Requests the servers manager to update its list of servers, and disables
|
|
|
|
* the 'refresh' button (till the refresh was finished).
|
|
|
|
*/
|
2018-04-25 14:26:23 -04:00
|
|
|
void ServerSelection::refresh(bool full_refresh)
|
2013-07-21 13:41:02 -04:00
|
|
|
{
|
2015-11-01 17:16:39 -05:00
|
|
|
// If the request was created (i.e. no error, and not re-requested within
|
|
|
|
// 5 seconds), clear the list and display the waiting message:
|
2018-04-25 14:26:23 -04:00
|
|
|
if (ServersManager::get()->refresh(full_refresh))
|
2015-11-01 17:16:39 -05:00
|
|
|
{
|
|
|
|
m_server_list_widget->clear();
|
|
|
|
m_reload_widget->setActive(false);
|
2018-03-04 12:54:44 -05:00
|
|
|
m_refreshing_server = true;
|
2018-04-25 14:26:23 -04:00
|
|
|
m_refresh_timer = 0.0f;
|
2015-11-01 17:16:39 -05:00
|
|
|
}
|
2015-10-09 01:47:18 -04:00
|
|
|
} // refresh
|
2013-07-21 13:41:02 -04:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-02 00:24:05 -05:00
|
|
|
/** Set pointers to the various widgets.
|
|
|
|
*/
|
2013-07-21 13:41:02 -04:00
|
|
|
void ServerSelection::loadedFromFile()
|
|
|
|
{
|
2013-07-11 21:07:26 -04:00
|
|
|
m_reload_widget = getWidget<GUIEngine::IconButtonWidget>("reload");
|
2013-07-22 16:00:08 -04:00
|
|
|
assert(m_reload_widget != NULL);
|
2013-07-11 21:07:26 -04:00
|
|
|
m_server_list_widget = getWidget<GUIEngine::ListWidget>("server_list");
|
|
|
|
assert(m_server_list_widget != NULL);
|
|
|
|
m_server_list_widget->setColumnListener(this);
|
2018-03-13 12:50:19 -04:00
|
|
|
m_private_server = getWidget<GUIEngine::CheckBoxWidget>("private_server");
|
|
|
|
assert(m_private_server != NULL);
|
|
|
|
m_private_server->setState(false);
|
2013-07-11 21:07:26 -04:00
|
|
|
} // loadedFromFile
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-02 00:24:05 -05:00
|
|
|
/** Clear the server list, which will be reloaded.
|
|
|
|
*/
|
2013-07-11 21:07:26 -04:00
|
|
|
void ServerSelection::beforeAddingWidget()
|
|
|
|
{
|
|
|
|
m_server_list_widget->clearColumns();
|
2018-03-26 00:27:40 -04:00
|
|
|
m_server_list_widget->addColumn( _("Name"), 3);
|
2013-07-14 17:47:48 -04:00
|
|
|
m_server_list_widget->addColumn( _("Players"), 1);
|
2016-03-10 18:48:40 -05:00
|
|
|
m_server_list_widget->addColumn(_("Difficulty"), 1);
|
2018-03-26 00:27:40 -04:00
|
|
|
m_server_list_widget->addColumn(_("Game mode"), 2);
|
2018-03-23 01:41:07 -04:00
|
|
|
if (NetworkConfig::get()->isWAN())
|
2018-03-25 14:11:04 -04:00
|
|
|
{
|
2018-03-26 13:02:31 -04:00
|
|
|
// I18N: In server selection screen, owner of server, only displayed
|
|
|
|
// if it's localhost or friends'
|
|
|
|
m_server_list_widget->addColumn(_("Owner"), 1);
|
2018-03-25 14:11:04 -04:00
|
|
|
// I18N: In server selection screen, distance to server
|
2018-03-26 23:56:36 -04:00
|
|
|
m_server_list_widget->addColumn(_("Distance (km)"), 1);
|
2018-03-25 14:11:04 -04:00
|
|
|
}
|
2015-10-09 01:47:18 -04:00
|
|
|
} // beforeAddingWidget
|
|
|
|
|
2013-07-11 21:07:26 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-02 00:24:05 -05:00
|
|
|
/** Triggers a refresh of the server list.
|
|
|
|
*/
|
2013-07-11 21:07:26 -04:00
|
|
|
void ServerSelection::init()
|
|
|
|
{
|
|
|
|
Screen::init();
|
|
|
|
m_sort_desc = true;
|
2015-11-01 17:16:39 -05:00
|
|
|
/** Triggers the loading of the server list in the servers manager. */
|
2018-04-25 14:26:23 -04:00
|
|
|
refresh(true);
|
2013-07-11 21:07:26 -04:00
|
|
|
} // init
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/** Loads the list of all servers. The gui element will be
|
|
|
|
* updated.
|
2018-03-04 12:54:44 -05:00
|
|
|
* \param sort_case what sorting method will be used.
|
2013-07-11 21:07:26 -04:00
|
|
|
*/
|
2018-03-04 12:54:44 -05:00
|
|
|
void ServerSelection::loadList(unsigned sort_case)
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
2018-03-04 12:54:44 -05:00
|
|
|
m_server_list_widget->clear();
|
2018-03-13 12:50:19 -04:00
|
|
|
std::sort(m_servers.begin(), m_servers.end(), [sort_case, this]
|
2018-03-04 12:54:44 -05:00
|
|
|
(const std::shared_ptr<Server> a,
|
|
|
|
const std::shared_ptr<Server> b)->bool
|
|
|
|
{
|
|
|
|
std::shared_ptr<Server> c = m_sort_desc ? a : b;
|
|
|
|
std::shared_ptr<Server> d = m_sort_desc ? b : a;
|
|
|
|
switch (sort_case)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return c->getLowerCaseName() > d->getLowerCaseName();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
return c->getCurrentPlayers() > d->getCurrentPlayers();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
return c->getDifficulty() > d->getDifficulty();
|
|
|
|
break;
|
|
|
|
case 3:
|
2018-03-30 13:19:23 -04:00
|
|
|
return c->getServerMode() > d->getServerMode();
|
2018-03-04 12:54:44 -05:00
|
|
|
break;
|
2018-03-23 01:41:07 -04:00
|
|
|
case 4:
|
2018-05-16 04:07:08 -04:00
|
|
|
return !(c->getServerOwnerName() < d->getServerOwnerName());
|
2018-03-23 01:41:07 -04:00
|
|
|
break;
|
2018-03-25 14:11:04 -04:00
|
|
|
case 5:
|
|
|
|
return c->getDistance() > d->getDistance();
|
|
|
|
break;
|
2018-03-04 12:54:44 -05:00
|
|
|
} // switch
|
|
|
|
assert(false);
|
|
|
|
return false;
|
|
|
|
});
|
2018-03-13 12:50:19 -04:00
|
|
|
for (auto server : m_servers)
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
2013-07-14 17:47:48 -04:00
|
|
|
core::stringw num_players;
|
|
|
|
num_players.append(StringUtils::toWString(server->getCurrentPlayers()));
|
|
|
|
num_players.append("/");
|
|
|
|
num_players.append(StringUtils::toWString(server->getMaxPlayers()));
|
2014-01-29 19:20:57 -05:00
|
|
|
std::vector<GUIEngine::ListWidget::ListCell> row;
|
2018-03-26 00:27:40 -04:00
|
|
|
row.push_back(GUIEngine::ListWidget::ListCell(server->getName(), -1, 3));
|
|
|
|
row.push_back(GUIEngine::ListWidget::ListCell(num_players, -1, 1, true));
|
2016-03-10 18:48:40 -05:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
core::stringw difficulty =
|
|
|
|
race_manager->getDifficultyName(server->getDifficulty());
|
2016-03-10 18:48:40 -05:00
|
|
|
row.push_back(GUIEngine::ListWidget::ListCell(difficulty, -1, 1, true));
|
|
|
|
|
2018-03-30 13:19:23 -04:00
|
|
|
core::stringw mode =
|
|
|
|
NetworkConfig::get()->getModeName(server->getServerMode());
|
2018-03-26 00:27:40 -04:00
|
|
|
row.push_back(GUIEngine::ListWidget::ListCell(mode, -1, 2, true));
|
2016-03-10 18:48:40 -05:00
|
|
|
|
2018-03-23 01:41:07 -04:00
|
|
|
if (NetworkConfig::get()->isWAN())
|
|
|
|
{
|
2018-05-16 04:07:08 -04:00
|
|
|
row.push_back(GUIEngine::ListWidget::ListCell(
|
|
|
|
server->getServerOwnerName(), -1, 1, true));
|
2018-03-25 14:11:04 -04:00
|
|
|
// I18N: In server selection screen, unknown distance to server
|
|
|
|
core::stringw distance = _("Unknown");
|
|
|
|
if (!(server->getDistance() < 0.0f))
|
|
|
|
distance = StringUtils::toWString(server->getDistance());
|
|
|
|
row.push_back(GUIEngine::ListWidget::ListCell(distance, -1, 1,
|
|
|
|
true));
|
2018-03-23 01:41:07 -04:00
|
|
|
}
|
2013-07-14 17:47:48 -04:00
|
|
|
m_server_list_widget->addItem("server", row);
|
2013-07-11 21:07:26 -04:00
|
|
|
}
|
|
|
|
} // loadList
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-02 00:24:05 -05:00
|
|
|
/** Change the sort order if a column was clicked.
|
|
|
|
* \param column_id ID of the column that was clicked.
|
|
|
|
*/
|
2013-07-11 21:07:26 -04:00
|
|
|
void ServerSelection::onColumnClicked(int column_id)
|
|
|
|
{
|
|
|
|
m_sort_desc = !m_sort_desc;
|
2018-03-04 12:54:44 -05:00
|
|
|
loadList(column_id);
|
2013-07-11 21:07:26 -04:00
|
|
|
} // onColumnClicked
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2018-03-04 12:54:44 -05:00
|
|
|
void ServerSelection::eventCallback(GUIEngine::Widget* widget,
|
|
|
|
const std::string& name,
|
|
|
|
const int playerID)
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
|
|
|
if (name == "back")
|
|
|
|
{
|
|
|
|
StateManager::get()->escapePressed();
|
|
|
|
}
|
|
|
|
else if (name == "reload")
|
|
|
|
{
|
2018-04-25 14:26:23 -04:00
|
|
|
refresh(true);
|
2013-07-11 21:07:26 -04:00
|
|
|
}
|
2018-03-13 12:50:19 -04:00
|
|
|
else if (name == "private_server")
|
|
|
|
{
|
|
|
|
copyFromServersManager();
|
|
|
|
}
|
2013-07-11 21:07:26 -04:00
|
|
|
else if (name == m_server_list_widget->m_properties[GUIEngine::PROP_ID])
|
|
|
|
{
|
2015-10-08 18:43:50 -04:00
|
|
|
int selected_index = m_server_list_widget->getSelectionID();
|
2015-11-16 02:44:14 -05:00
|
|
|
// This can happen e.g. when the list is empty and the user
|
|
|
|
// clicks somewhere.
|
2018-03-05 00:04:17 -05:00
|
|
|
if (selected_index < 0 || m_refreshing_server ||
|
2018-03-13 12:50:19 -04:00
|
|
|
selected_index >= (int)m_servers.size())
|
2015-11-27 20:32:00 -05:00
|
|
|
{
|
2015-11-16 02:44:14 -05:00
|
|
|
return;
|
2015-11-27 20:32:00 -05:00
|
|
|
}
|
2018-03-13 12:50:19 -04:00
|
|
|
new ServerInfoDialog(m_servers[selected_index]);
|
2015-11-04 15:55:59 -05:00
|
|
|
} // click on server
|
2013-07-11 21:07:26 -04:00
|
|
|
|
|
|
|
} // eventCallback
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2015-11-01 17:16:39 -05:00
|
|
|
/** If a refresh of the server list was requested, check if it is finished and
|
|
|
|
* if so, update the list of servers.
|
|
|
|
*/
|
2014-01-21 15:43:17 -05:00
|
|
|
void ServerSelection::onUpdate(float dt)
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
2018-03-05 00:04:17 -05:00
|
|
|
// In case of auto-connect command line parameter, select the first server asap
|
|
|
|
if (NetworkConfig::get()->isAutoConnect() &&
|
|
|
|
m_refreshing_server == false &&
|
2018-03-13 12:50:19 -04:00
|
|
|
!m_servers.empty())
|
2018-03-05 00:04:17 -05:00
|
|
|
{
|
2018-03-13 12:50:19 -04:00
|
|
|
ServerInfoDialog *sid = new ServerInfoDialog(m_servers[0]);
|
2018-03-05 00:04:17 -05:00
|
|
|
sid->requestJoin();
|
|
|
|
}
|
2018-04-25 14:26:23 -04:00
|
|
|
|
|
|
|
if (ServersManager::get()->getServers().empty() && !m_refreshing_server &&
|
|
|
|
!NetworkConfig::get()->isWAN())
|
|
|
|
{
|
|
|
|
m_refresh_timer += dt;
|
|
|
|
|
|
|
|
if (m_refresh_timer > 10.0f)
|
|
|
|
{
|
|
|
|
refresh(false);
|
|
|
|
}
|
|
|
|
}
|
2018-03-05 00:04:17 -05:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
if (!m_refreshing_server) return;
|
2015-11-01 17:16:39 -05:00
|
|
|
|
2018-03-04 12:54:44 -05:00
|
|
|
if (ServersManager::get()->listUpdated())
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
2018-03-04 12:54:44 -05:00
|
|
|
m_refreshing_server = false;
|
|
|
|
if (!ServersManager::get()->getServers().empty())
|
2013-07-11 21:07:26 -04:00
|
|
|
{
|
2016-04-04 19:46:41 -04:00
|
|
|
int selection = m_server_list_widget->getSelectionID();
|
2018-03-13 12:50:19 -04:00
|
|
|
std::string selection_str = m_server_list_widget
|
|
|
|
->getSelectionInternalName();
|
|
|
|
copyFromServersManager();
|
2016-04-04 19:46:41 -04:00
|
|
|
// restore previous selection
|
2018-03-06 01:40:29 -05:00
|
|
|
if (selection != -1 && selection_str != "loading")
|
2016-04-04 19:46:41 -04:00
|
|
|
m_server_list_widget->setSelectionID(selection);
|
2013-07-11 21:07:26 -04:00
|
|
|
}
|
2013-07-12 19:12:31 -04:00
|
|
|
else
|
|
|
|
{
|
2015-11-01 17:16:39 -05:00
|
|
|
SFXManager::get()->quickSound("anvil");
|
2016-04-04 19:46:41 -04:00
|
|
|
m_server_list_widget->clear();
|
2018-04-25 14:26:23 -04:00
|
|
|
m_server_list_widget->addItem("loading",
|
|
|
|
_("No server is available."));
|
2013-07-12 19:12:31 -04:00
|
|
|
}
|
2015-11-01 17:16:39 -05:00
|
|
|
m_reload_widget->setActive(true);
|
2013-07-11 21:07:26 -04:00
|
|
|
}
|
2018-03-06 01:40:29 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
m_server_list_widget->clear();
|
|
|
|
m_server_list_widget->addItem("loading",
|
|
|
|
StringUtils::loadingDots(_("Fetching servers")));
|
|
|
|
}
|
2017-01-24 22:29:48 -05:00
|
|
|
|
2013-07-11 21:07:26 -04:00
|
|
|
} // onUpdate
|
2018-03-13 12:50:19 -04:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void ServerSelection::copyFromServersManager()
|
|
|
|
{
|
|
|
|
m_servers = ServersManager::get()->getServers();
|
|
|
|
if (m_servers.empty())
|
|
|
|
return;
|
|
|
|
m_servers.erase(std::remove_if(m_servers.begin(), m_servers.end(),
|
|
|
|
[this](const std::shared_ptr<Server> a)->bool
|
|
|
|
{
|
|
|
|
return a->isPasswordProtected() != m_private_server->getState();
|
|
|
|
}), m_servers.end());
|
|
|
|
loadList(0);
|
|
|
|
} // copyFromServersManager
|