Clean up Server, ServersManager and quick play

For now we choose the server with the least player for quick play
This commit is contained in:
Benau
2018-03-05 01:54:44 +08:00
parent 58757c2927
commit 2b56a97b08
24 changed files with 319 additions and 591 deletions

View File

@@ -214,6 +214,7 @@
#include "network/network_string.hpp"
#include "network/rewind_manager.hpp"
#include "network/rewind_queue.hpp"
#include "network/server.hpp"
#include "network/servers_manager.hpp"
#include "network/stk_host.hpp"
#include "online/profile_manager.hpp"
@@ -1089,13 +1090,13 @@ int handleCmdLine()
Log::info("main", "Try to connect to server '%s'.",
ip.toString().c_str() );
irr::core::stringw name = StringUtils::utf8ToWide(ip.toString());
ServersManager::get()->addServer(new Server(0, name,
auto server = std::make_shared<Server>(0, name,
NetworkConfig::get()->getMaxPlayers(), 0,
race_manager->getDifficulty(),
NetworkConfig::get()->getServerGameMode(race_manager->getMinorMode(),
race_manager->getMajorMode()), ip));
ServersManager::get()->setJoinedServer(0);
STKHost::create();
race_manager->getMajorMode()), ip);
NetworkingLobby::getInstance()->setJoinedServer(server);
STKHost::create(server);
}
if (CommandLine::has("--wan-server", &s))
@@ -1768,9 +1769,7 @@ int main(int argc, char *argv[] )
HardwareStats::reportHardwareStats();
}
// This can only be the case if --connect-now was used, which adds
// a server to the server list.
if (ServersManager::get()->getNumServers()==1)
if (STKHost::existHost())
{
NetworkingLobby::getInstance()->push();
}

View File

@@ -21,6 +21,7 @@
#include "network/stk_host.hpp"
#include "network/stk_peer.hpp"
#include "utils/log.hpp"
#include "utils/time.hpp"
#include <string.h>

View File

@@ -210,7 +210,6 @@ void ClientLobby::leave()
m_server->disconnect();
STKHost::get()->removePeer(m_server);
m_server_address.clear();
ServersManager::get()->unsetJoinedServer();
} // leave
//-----------------------------------------------------------------------------

View File

@@ -26,37 +26,21 @@
#include "network/protocols/client_lobby.hpp"
#include "network/protocol_manager.hpp"
#include "network/servers_manager.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "network/stk_peer.hpp"
#include "states_screens/networking_lobby.hpp"
#include "utils/time.hpp"
#include "utils/log.hpp"
// ----------------------------------------------------------------------------
/** Connects to a server. This is the quick connect constructor, which
* will pick a server randomly.
*/
ConnectToServer::ConnectToServer() : Protocol(PROTOCOL_CONNECTION)
{
m_server_id = 0;
m_host_id = 0;
m_quick_join = true;
m_server_address.clear();
setHandleConnections(true);
} // ConnectToServer()
// ----------------------------------------------------------------------------
/** Specify server to connect to.
* \param server_id Id of server to connect to.
* \param host_id Id of host.
* \param server Server to connect to (if nullptr than we use quick play).
*/
ConnectToServer::ConnectToServer(uint32_t server_id, uint32_t host_id)
ConnectToServer::ConnectToServer(std::shared_ptr<Server> server)
: Protocol(PROTOCOL_CONNECTION)
{
m_server_id = server_id;
m_host_id = host_id;
m_quick_join = false;
m_server = ServersManager::get()->getServerByID(m_server_id);
m_server_address.copy(m_server->getAddress());
m_server = server;
setHandleConnections(true);
} // ConnectToServer(server, host)
@@ -88,6 +72,34 @@ void ConnectToServer::asynchronousUpdate()
{
case SET_PUBLIC_ADDRESS:
{
if (!m_server)
{
while (!ServersManager::get()->refresh())
StkTime::sleep(1);
while (!ServersManager::get()->listUpdated())
StkTime::sleep(1);
if (!ServersManager::get()->getServers().empty())
{
// For quick play we choose the server with the least player
ServersManager::get()->sortServers([]
(const std::shared_ptr<Server> a,
const std::shared_ptr<Server> b)->bool
{
return a->getCurrentPlayers() < b->getCurrentPlayers();
});
m_server = ServersManager::get()->getServers()[0];
ServersManager::get()->cleanUpServers();
}
else
{
// Shutdown STKHost (go back to online menu too)
STKHost::get()->setErrorMessage(
_("No quick play server available."));
STKHost::get()->requestShutdown();
m_state = EXITING;
return;
}
}
STKHost::get()->setPublicAddress();
// Set to DONE will stop STKHost is not connected
m_state = STKHost::get()->getPublicAddress().isUnset() ?
@@ -97,26 +109,17 @@ void ConnectToServer::asynchronousUpdate()
case REGISTER_SELF_ADDRESS:
{
registerWithSTKServer(); // Register us with STK server
if (m_quick_join)
{
handleQuickConnect();
// Quick connect will give us the server details,
// so we can immediately try to connect to the server
m_state = REQUESTING_CONNECTION;
}
else
{
m_state = GOT_SERVER_ADDRESS;
}
m_state = GOT_SERVER_ADDRESS;
}
break;
case GOT_SERVER_ADDRESS:
{
assert(!m_quick_join);
assert(m_server);
m_server_address.copy(m_server->getAddress());
Log::info("ConnectToServer", "Server's address known");
m_state = REQUESTING_CONNECTION;
auto request_connection =
std::make_shared<RequestConnection>(m_server_id);
std::make_shared<RequestConnection>(m_server);
request_connection->requestStart();
m_current_protocol = request_connection;
// Reset timer for next usage
@@ -124,6 +127,7 @@ void ConnectToServer::asynchronousUpdate()
break;
}
case REQUESTING_CONNECTION:
{
if (!m_current_protocol.expired())
{
return;
@@ -172,6 +176,7 @@ void ConnectToServer::asynchronousUpdate()
waitingAloha(true/*is_wan*/);
}
break;
}
case CONNECTING: // waiting the server to answer our connection
{
// Every 5 seconds
@@ -224,6 +229,12 @@ void ConnectToServer::update(float dt)
{
switch(m_state.load())
{
case REQUESTING_CONNECTION:
{
assert(m_server);
NetworkingLobby::getInstance()->setJoinedServer(m_server);
break;
}
case DONE:
{
// lobby room protocol if we're connected only
@@ -241,7 +252,7 @@ void ConnectToServer::update(float dt)
{
// Shutdown STKHost (go back to online menu too)
STKHost::get()->setErrorMessage(
_("Cannot connect to server %s.", m_server->getName()));
_("Cannot connect to server %s.", m_server->getName()));
STKHost::get()->requestShutdown();
}
requestTerminate();
@@ -293,45 +304,6 @@ void ConnectToServer::registerWithSTKServer()
} // registerWithSTKServer
// ----------------------------------------------------------------------------
/** Called to request a quick connect from the STK server.
*/
void ConnectToServer::handleQuickConnect()
{
Online::XMLRequest *request = new Online::XMLRequest();
NetworkConfig::get()->setUserDetails(request, "quick-join");
request->executeNow();
const XMLNode * result = request->getXMLData();
std::string success;
if(result->get("success", &success) && success=="yes")
{
uint32_t ip;
result->get("ip", &ip);
m_server_address.setIP(ip);
uint16_t port;
// If we are using a LAN connection, we need the private (local) port
if (m_server_address.getIP() ==
STKHost::get()->getPublicAddress().getIP())
{
result->get("private_port", &port);
}
else
result->get("port", &port);
m_server_address.setPort(port);
Log::debug("GetPeerAddress", "Address gotten successfully.");
}
else
{
Log::error("GetPeerAddress", "Failed to get address.");
}
delete request;
} // handleQuickConnect
// ----------------------------------------------------------------------------
/** Called when the server is on the same LAN. It uses broadcast to
* find and conntect to the server. For WAN game, it makes sure server recieve

View File

@@ -23,6 +23,7 @@
#include "network/transport_address.hpp"
#include "utils/cpp2011.hpp"
#include <atomic>
#include <memory>
#include <string>
class Server;
@@ -32,14 +33,11 @@ class ConnectToServer : public Protocol
private:
double m_timer = 0.0;
TransportAddress m_server_address;
uint32_t m_server_id;
uint32_t m_host_id;
std::shared_ptr<Server> m_server;
unsigned m_tried_connection = 0;
const Server* m_server = NULL;
/** Protocol currently being monitored. */
std::weak_ptr<Protocol> m_current_protocol;
bool m_quick_join;
/** State for finite state machine. */
enum ConnectState : unsigned int
@@ -57,12 +55,10 @@ private:
std::atomic<ConnectState> m_state;
void registerWithSTKServer();
void handleQuickConnect();
void waitingAloha(bool is_wan);
public:
ConnectToServer();
ConnectToServer(uint32_t server_id, uint32_t host_id);
ConnectToServer(std::shared_ptr<Server> server);
virtual ~ConnectToServer();
virtual bool notifyEventAsynchronous(Event* event) OVERRIDE;

View File

@@ -31,6 +31,7 @@
#include "network/stk_host.hpp"
#include "network/stk_peer.hpp"
#include "utils/log.hpp"
#include "utils/time.hpp"
// ============================================================================
std::weak_ptr<GameProtocol> GameProtocol::m_game_protocol;

View File

@@ -22,20 +22,20 @@
#include "network/network.hpp"
#include "network/network_config.hpp"
#include "network/protocol_manager.hpp"
#include "network/servers_manager.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "online/xml_request.hpp"
using namespace Online;
/** Constructor. Stores the server id.
* \param server_id Id of the server.
* \param server Server to be joined.
*/
RequestConnection::RequestConnection(uint32_t server_id)
RequestConnection::RequestConnection(std::shared_ptr<Server> server)
: Protocol(PROTOCOL_SILENT)
{
m_server_id = server_id;
m_request = NULL;
m_server = server;
m_request = NULL;
} // RequestConnection
// ----------------------------------------------------------------------------
@@ -51,20 +51,6 @@ void RequestConnection::setup()
m_state = NONE;
} // setup
// ----------------------------------------------------------------------------
/** The callback for the server join request. It informs the server manager
* of a successful join request.
*/
void RequestConnection::ServerJoinRequest::callback()
{
if (isSuccess())
{
uint32_t server_id;
getXMLData()->get("serverid", &server_id);
ServersManager::get()->setJoinedServer(server_id);
}
} // ServerJoinRequest::callback
// ----------------------------------------------------------------------------
/** This implements a finite state machine to monitor the server join
* request asynchronously.
@@ -98,19 +84,17 @@ void RequestConnection::asynchronousUpdate()
}
NetworkConfig::get()->setServerIdFile("");
}
const Server *server =
ServersManager::get()->getServerByID(m_server_id);
BareNetworkString message(std::string("connection-request"));
STKHost::get()->sendRawPacket(message, server->getAddress());
STKHost::get()->sendRawPacket(message, m_server->getAddress());
NetworkConfig::get()->setDirectConnect(false);
m_state = DONE;
}
else
{
m_request = new ServerJoinRequest();
m_request = new Online::XMLRequest();
NetworkConfig::get()->setUserDetails(m_request,
"request-connection");
m_request->addParameter("server_id", m_server_id);
m_request->addParameter("server_id", m_server->getServerId());
m_request->queue();
m_state = REQUEST_PENDING;
}
@@ -135,7 +119,7 @@ void RequestConnection::asynchronousUpdate()
{
Log::error("RequestConnection",
"Fail to make a request to connecto to server %d",
m_server_id);
m_server->getServerId());
}
}
else

View File

@@ -4,11 +4,14 @@
#include "network/protocol.hpp"
#include "online/xml_request.hpp"
#include <memory>
class Server;
class RequestConnection : public Protocol
{
protected:
/** Id of the server to join. */
uint32_t m_server_id;
std::shared_ptr<Server> m_server;
/** The request to join a server. */
Online::XMLRequest *m_request;
@@ -25,18 +28,7 @@ protected:
public:
// --------------------------------------------------------------------
/** A simple request class to ask to join a server.
*/
class ServerJoinRequest : public Online::XMLRequest
{
virtual void callback();
public:
ServerJoinRequest() : Online::XMLRequest() {}
}; // ServerJoinRequest
// --------------------------------------------------------------------
RequestConnection(uint32_t server_id);
RequestConnection(std::shared_ptr<Server> server);
virtual ~RequestConnection();
virtual void setup() OVERRIDE;
virtual void asynchronousUpdate() OVERRIDE;

View File

@@ -21,8 +21,6 @@
#include "utils/constants.hpp"
#include "utils/string_utils.hpp"
Server::SortOrder Server::m_sort_order = Server::SO_NAME;
/** Constructor based on XML data received from the stk server.
* \param xml The data for one server as received as part of the
* get-all stk-server request.
@@ -77,8 +75,10 @@ Server::Server(unsigned server_id, const core::stringw &name, int max_players,
const TransportAddress &address)
{
m_name = name;
m_lower_case_name = StringUtils::toLowerCase(StringUtils::wideToUtf8(name));
m_satisfaction_score = 0;
m_server_id = server_id;
m_host_id = 0;
m_current_players = current_players;
m_max_players = max_players;
m_address.copy(address);

View File

@@ -41,17 +41,6 @@ class Server
{
public:
/** Set the sort order used in the comparison function. */
enum SortOrder
{
SO_NAME = 0, // Sorted alphabetically by name
SO_PLAYERS = 1,
SO_DIFFICULTY = 2,
SO_GAME_MODE = 3,
SO_SCORE = 4 // Sorted on satisfaction score (unused)
};
protected:
/** The server name to be displayed. */
irr::core::stringw m_name;
@@ -88,9 +77,6 @@ protected:
RaceManager::Difficulty m_difficulty;
/** The sort order to be used in the comparison. */
static SortOrder m_sort_order;
public:
/** Initialises the object from an XML node. */
@@ -103,10 +89,8 @@ public:
/** Returns ip address and port of this server. */
const TransportAddress& getAddress() const { return m_address; }
// ------------------------------------------------------------------------
/** Sets the sort order used in the comparison function. It is static, so
* that each instance can access the sort order. */
static void setSortOrder(SortOrder so) { m_sort_order = so; }
/** Returns the lower case name of the server. */
const std::string& getLowerCaseName() const { return m_lower_case_name; }
// ------------------------------------------------------------------------
/** Returns the name of the server. */
const irr::core::stringw& getName() const { return m_name; }
@@ -114,7 +98,8 @@ public:
/** Returns the ID of this server. */
const uint32_t getServerId() const { return m_server_id; }
// ------------------------------------------------------------------------
/** Returns the unique host id of this server. */
/** Returns the unique host id of this server (wan game only), which is
* the user id in STK addon server of the server owner. */
const uint32_t getHostId() const { return m_host_id; }
// ------------------------------------------------------------------------
/** Returns the maximum number of players allowed on this server. */
@@ -130,34 +115,7 @@ public:
{ return m_major_mode; }
// ------------------------------------------------------------------------
RaceManager::Difficulty getDifficulty() const { return m_difficulty; }
// ------------------------------------------------------------------------
/** Compares two servers according to the sort order currently defined.
* \param a The addon to compare this addon to.
*/
bool operator<(const Server &server) const
{
switch (m_sort_order)
{
case SO_SCORE:
return m_satisfaction_score < server.m_satisfaction_score;
break;
case SO_NAME:
// m_id is the lower case name
return m_lower_case_name < server.m_lower_case_name;
break;
case SO_PLAYERS:
return m_current_players < server.m_current_players;
break;
case SO_DIFFICULTY:
return m_difficulty < server.m_difficulty;
break;
case SO_GAME_MODE:
return m_minor_mode < server.m_minor_mode;
break;
} // switch
return true;
} // operator<
}; // Server
#endif // HEADER_SERVER_HPP

View File

@@ -22,8 +22,10 @@
#include "network/network.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "online/xml_request.hpp"
#include "online/request_manager.hpp"
#include "utils/translation.hpp"
#include "utils/time.hpp"
@@ -33,59 +35,36 @@
#define SERVER_REFRESH_INTERVAL 5.0f
static ServersManager* manager_singleton(NULL);
static ServersManager* g_manager_singleton(NULL);
// ============================================================================
ServersManager* ServersManager::get()
{
if (manager_singleton == NULL)
manager_singleton = new ServersManager();
if (g_manager_singleton == NULL)
g_manager_singleton = new ServersManager();
return manager_singleton;
return g_manager_singleton;
} // get
// ------------------------------------------------------------------------
// ============================================================================
void ServersManager::deallocate()
{
delete manager_singleton;
manager_singleton = NULL;
delete g_manager_singleton;
g_manager_singleton = NULL;
} // deallocate
// ===========================================================-=============
// ----------------------------------------------------------------------------
ServersManager::ServersManager()
{
m_last_load_time.setAtomic(0.0f);
m_joined_server.setAtomic(NULL);
m_last_load_time.store(0.0f);
m_list_updated = false;
} // ServersManager
// ------------------------------------------------------------------------
// ----------------------------------------------------------------------------
ServersManager::~ServersManager()
{
cleanUpServers();
} // ~ServersManager
// ------------------------------------------------------------------------
/** Removes all stored server information. After this call the list of
* servers can be refreshed.
*/
void ServersManager::cleanUpServers()
{
if(m_joined_server.getAtomic()!=NULL)
{
// m_joinsed_server is a pointer into the m_server structure,
// we can not modify this data structure while this pointer exists.
Log::warn("ServersManager", "Server cleanUp while being already "
"connected to a server.");
return;
}
m_sorted_servers.lock();
m_sorted_servers.getData().clearAndDeleteAll();
m_sorted_servers.unlock();
m_mapped_servers.lock();
m_mapped_servers.getData().clear();
m_mapped_servers.unlock();
} // cleanUpServers
// ----------------------------------------------------------------------------
/** Returns a WAN update-list-of-servers request. It queries the
* STK server for an up-to-date list of servers.
@@ -98,12 +77,13 @@ Online::XMLRequest* ServersManager::getWANRefreshRequest() const
class WANRefreshRequest : public Online::XMLRequest
{
public:
WANRefreshRequest() : Online::XMLRequest(/*manage_memory*/false,
WANRefreshRequest() : Online::XMLRequest(/*manage_memory*/true,
/*priority*/100) {}
// --------------------------------------------------------------------
virtual void callback()
virtual void afterOperation() OVERRIDE
{
ServersManager::get()->refresh(isSuccess(), getXMLData());
Online::XMLRequest::afterOperation();
ServersManager::get()->setWanServers(isSuccess(), getXMLData());
} // callback
// --------------------------------------------------------------------
}; // RefreshRequest
@@ -132,7 +112,7 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
public:
/** High priority for this request. */
LANRefreshRequest() : XMLRequest(false, 100) {m_success = false;}
LANRefreshRequest() : XMLRequest(true, 100) {m_success = false;}
// --------------------------------------------------------------------
virtual ~LANRefreshRequest() {}
// --------------------------------------------------------------------
@@ -169,9 +149,11 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
// any local servers.
double start_time = StkTime::getRealTime();
const double DURATION = 1.0;
int cur_server_id = ServersManager::get()->getNumServers();
const auto& servers = ServersManager::get()->getServers();
int cur_server_id = servers.size();
assert(cur_server_id == 0);
while(StkTime::getRealTime() - start_time < DURATION)
std::vector<std::shared_ptr<Server> > servers_now;
while (StkTime::getRealTime() - start_time < DURATION)
{
TransportAddress sender;
int len = broadcast->receiveRawPacket(buffer, LEN, &sender, 1);
@@ -187,16 +169,14 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
uint16_t my_port = s.getUInt16();
uint8_t difficulty = s.getUInt8();
uint8_t mode = s.getUInt8();
Server* server = new Server(cur_server_id++, name,
max_players,players, difficulty, mode, sender);
ServersManager::get()->addServer(server);
m_success = true;
servers_now.emplace_back(std::make_shared<Server>
(cur_server_id++, name, max_players, players,
difficulty, mode, sender));
} // if received_data
} // while still waiting
m_success = true;
ServersManager::get()->setLanServers(servers_now);
delete broadcast;
if (!m_success)
m_info = _("No LAN server detected");
} // operation
// --------------------------------------------------------------------
/** This function is necessary, otherwise the XML- and HTTP-Request
@@ -212,133 +192,46 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
// ----------------------------------------------------------------------------
/** Factory function to create either a LAN or a WAN update-of-server
* requests. The current list of servers is also cleared/
* requests. The current list of servers is also cleared.
*/
Online::XMLRequest* ServersManager::getRefreshRequest(bool request_now)
bool ServersManager::refresh()
{
if (StkTime::getRealTime() - m_last_load_time.getAtomic()
if (StkTime::getRealTime() - m_last_load_time.load()
< SERVER_REFRESH_INTERVAL)
{
// Avoid too frequent refreshing
return NULL;
}
if(m_joined_server.getAtomic()!=NULL)
{
// m_joinsed_server is a pointer into the m_server structure,
// we can not modify this data structure while this pointer exists.
Log::warn("ServersManager", "Server refresh while being already "
"connected to a server.");
return NULL;
return false;
}
cleanUpServers();
Online::XMLRequest *request =
NetworkConfig::get()->isWAN() ? getWANRefreshRequest()
: getLANRefreshRequest();
if (request_now)
Online::RequestManager::get()->addRequest(request);
return request;
} // getRefreshRequest
m_list_updated = false;
if (NetworkConfig::get()->isWAN())
Online::RequestManager::get()->addRequest(getWANRefreshRequest());
else
Online::RequestManager::get()->addRequest(getLANRefreshRequest());
return true;
} // refresh
// ----------------------------------------------------------------------------
/** Callback from the refresh request.
/** Callback from the refresh request for wan servers.
* \param success If the refresh was successful.
* \param input The XML data describing the server.
*/
void ServersManager::refresh(bool success, const XMLNode *input)
void ServersManager::setWanServers(bool success, const XMLNode* input)
{
if (!success)
{
Log::error("Server Manager", "Could not refresh server list");
m_list_updated = true;
return;
}
const XMLNode *servers_xml = input->getNode("servers");
for (unsigned int i = 0; i < servers_xml->getNumNodes(); i++)
{
addServer(new Server(*servers_xml->getNode(i)));
m_servers.emplace_back(
std::make_shared<Server>(*servers_xml->getNode(i)));
}
m_last_load_time.setAtomic((float)StkTime::getRealTime());
m_last_load_time.store((float)StkTime::getRealTime());
m_list_updated = true;
} // refresh
// ----------------------------------------------------------------------------
const Server* ServersManager::getQuickPlay() const
{
if (m_sorted_servers.getData().size() > 0)
return getServerBySort(0);
return NULL;
} // getQuickPlay
// ----------------------------------------------------------------------------
/** Sets a pointer to the server to which this client is connected. From now
* on the list of servers must not be modified (else this pointer might
* become invalid).
*/
void ServersManager::setJoinedServer(uint32_t id)
{
MutexLocker(m_mapped_servers);
m_joined_server.getData() = m_mapped_servers.getData().at(id);
} // setJoinedServer
// ----------------------------------------------------------------------------
/** Unsets the server to which this client is connected.
*/
void ServersManager::unsetJoinedServer()
{
MutexLocker(m_joined_server);
m_joined_server.getData() = NULL;
} // unsetJoinedServer
// ----------------------------------------------------------------------------
/** Adds a server to the list of known servers.
* \param server The server to add.
*/
void ServersManager::addServer(Server *server)
{
m_sorted_servers.lock();
m_sorted_servers.getData().push_back(server);
m_sorted_servers.unlock();
m_mapped_servers.lock();
m_mapped_servers.getData()[server->getServerId()] = server;
m_mapped_servers.unlock();
} // addServer
// ----------------------------------------------------------------------------
int ServersManager::getNumServers() const
{
MutexLocker(m_sorted_servers);
return m_sorted_servers.getData().size();
} // getNumServers
// ----------------------------------------------------------------------------
const Server* ServersManager::getServerBySort(int index) const
{
MutexLocker(m_sorted_servers);
return m_sorted_servers.getData().get(index);
} // getServerBySort
// ------------------------------------------------------------------------
const Server* ServersManager::getServerByID(uint32_t id) const
{
MutexLocker(m_mapped_servers);
return m_mapped_servers.getData().at(id);
} // getServerByID
// ----------------------------------------------------------------------------
Server* ServersManager::getJoinedServer() const
{
return m_joined_server.getAtomic();
} // getJoinedServer
// ----------------------------------------------------------------------------
void ServersManager::sort(bool sort_desc)
{
MutexLocker(m_sorted_servers);
m_sorted_servers.getData().insertionSort(0, sort_desc);
} // sort

View File

@@ -19,13 +19,17 @@
#ifndef HEADER_SERVERS_MANAGER_HPP
#define HEADER_SERVERS_MANAGER_HPP
#include "online/request_manager.hpp"
#include "network/server.hpp"
#include "utils/ptr_vector.hpp"
#include "utils/synchronised.hpp"
#include "utils/types.hpp"
#include <atomic>
#include <algorithm>
#include <cassert>
#include <functional>
#include <memory>
#include <string>
#include <vector>
namespace Online { class XMLRequest; }
class Server;
class XMLNode;
/**
* \brief
@@ -34,40 +38,51 @@ namespace Online { class XMLRequest; }
class ServersManager
{
private:
/** List of servers */
std::vector<std::shared_ptr<Server> > m_servers;
std::atomic<float> m_last_load_time;
std::atomic_bool m_list_updated;
// ------------------------------------------------------------------------
ServersManager();
// ------------------------------------------------------------------------
~ServersManager();
/** Sorted vector of servers */
Synchronised<PtrVector<Server> > m_sorted_servers;
/** Maps server id's to the same servers*/
Synchronised<std::map<uint32_t, Server*> > m_mapped_servers;
/** This is a pointer to a copy of the server, the moment it got joined */
Synchronised<Server *> m_joined_server;
Synchronised<float> m_last_load_time;
void refresh(bool success, const XMLNode * input);
Online::XMLRequest * getWANRefreshRequest() const;
Online::XMLRequest * getLANRefreshRequest() const;
// ------------------------------------------------------------------------
void setWanServers(bool success, const XMLNode* input);
// ------------------------------------------------------------------------
void setLanServers(std::vector<std::shared_ptr<Server> >& servers)
{
m_servers = std::move(servers);
m_list_updated = true;
}
// ------------------------------------------------------------------------
Online::XMLRequest* getWANRefreshRequest() const;
// ------------------------------------------------------------------------
Online::XMLRequest* getLANRefreshRequest() const;
public:
// ------------------------------------------------------------------------
// Singleton
static ServersManager* get();
static void deallocate();
void cleanUpServers();
Online::XMLRequest * getRefreshRequest(bool request_now = true);
void setJoinedServer(uint32_t server_id);
void unsetJoinedServer();
void addServer(Server * server);
int getNumServers() const;
const Server * getServerByID(uint32_t server_id) const;
const Server * getServerBySort(int index) const;
void sort(bool sort_desc);
Server * getJoinedServer() const;
// Returns the best server to join
const Server * getQuickPlay() const;
static ServersManager* get();
// ------------------------------------------------------------------------
static void deallocate();
// ------------------------------------------------------------------------
void cleanUpServers() { m_servers.clear(); }
// ------------------------------------------------------------------------
void sortServers(std::function<bool(const std::shared_ptr<Server> a,
const std::shared_ptr<Server> b)> sorting_function)
{
assert(m_list_updated);
std::sort(m_servers.begin(), m_servers.end(), sorting_function);
}
// ------------------------------------------------------------------------
bool refresh();
// ------------------------------------------------------------------------
const std::vector<std::shared_ptr<Server> >& getServers() const
{ return m_servers; }
// ------------------------------------------------------------------------
bool listUpdated() const { return m_list_updated; }
}; // class ServersManager
#endif // HEADER_SERVERS_MANAGER_HPP

View File

@@ -28,7 +28,6 @@
#include "network/protocols/connect_to_server.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/protocol_manager.hpp"
#include "network/servers_manager.hpp"
#include "network/stk_peer.hpp"
#include "utils/log.hpp"
#include "utils/separate_process.hpp"
@@ -66,15 +65,14 @@
STKHost *STKHost::m_stk_host = NULL;
bool STKHost::m_enable_console = false;
void STKHost::create(SeparateProcess* p)
void STKHost::create(std::shared_ptr<Server> server, SeparateProcess* p)
{
assert(m_stk_host == NULL);
if (NetworkConfig::get()->isServer())
m_stk_host = new STKHost(NetworkConfig::get()->getServerName());
else
{
Server *server = ServersManager::get()->getJoinedServer();
m_stk_host = new STKHost(server->getServerId(), 0);
m_stk_host = new STKHost(server);
}
m_stk_host->m_separate_process = p;
if (!m_stk_host->m_network)
@@ -256,7 +254,7 @@ void STKHost::create(SeparateProcess* p)
// ============================================================================
/** Constructor for a client
*/
STKHost::STKHost(uint32_t server_id, uint32_t host_id)
STKHost::STKHost(std::shared_ptr<Server> server)
{
m_next_unique_host_id = -1;
// Will be overwritten with the correct value once a connection with the
@@ -266,7 +264,7 @@ STKHost::STKHost(uint32_t server_id, uint32_t host_id)
ENetAddress ea;
ea.host = STKHost::HOST_ANY;
ea.port = NetworkConfig::get()->getClientPort();
ea.port = NetworkConfig::get()->getClientPort();
m_network = new Network(/*peer_count*/1, /*channel_limit*/2,
/*max_in_bandwidth*/0, /*max_out_bandwidth*/0,
@@ -278,7 +276,7 @@ STKHost::STKHost(uint32_t server_id, uint32_t host_id)
}
setPrivatePort();
std::make_shared<ConnectToServer>(server_id, host_id)->requestStart();
std::make_shared<ConnectToServer>(server)->requestStart();
} // STKHost
// ----------------------------------------------------------------------------
@@ -382,7 +380,6 @@ STKHost::~STKHost()
*/
void STKHost::shutdown()
{
ServersManager::get()->unsetJoinedServer();
ProtocolManager::lock()->abort();
deleteAllPeers();
destroy();

View File

@@ -39,9 +39,11 @@
#include <enet/enet.h>
#include <atomic>
#include <memory>
#include <thread>
class GameSetup;
class Server;
class SeparateProcess;
class STKHost
@@ -114,7 +116,7 @@ private:
/** An error message, which is set by a protocol to be displayed
* in the GUI. */
STKHost(uint32_t server_id, uint32_t host_id);
STKHost(std::shared_ptr<Server> server);
STKHost(const irr::core::stringw &server_name);
virtual ~STKHost();
void init();
@@ -131,7 +133,8 @@ public:
/** Creates the STKHost. It takes all confifguration parameters from
* NetworkConfig. This STKHost can either be a client or a server.
*/
static void create(SeparateProcess* p = NULL);
static void create(std::shared_ptr<Server> server = nullptr,
SeparateProcess* p = NULL);
// ------------------------------------------------------------------------
/** Returns the instance of STKHost. */

View File

@@ -23,6 +23,7 @@
#include "network/stk_host.hpp"
#include "network/transport_address.hpp"
#include "utils/log.hpp"
#include "utils/time.hpp"
#include <string.h>

View File

@@ -26,7 +26,7 @@
#include "modes/demo_world.hpp"
#include "network/protocols/lobby_protocol.hpp"
#include "network/network_config.hpp"
#include "network/servers_manager.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
@@ -179,20 +179,14 @@ void CreateServerScreen::createServer()
if (!password.empty())
password = std::string(" --server-password=") + password;
ServersManager::get()->cleanUpServers();
TransportAddress server_address(0x7f000001,
NetworkConfig::get()->getServerDiscoveryPort());
TransportAddress address(0x7f000001,
NetworkConfig::get()->getServerDiscoveryPort());
Server *server = new Server(0/*server_id*/, name, max_players,
/*current_player*/0, (RaceManager::Difficulty)
auto server = std::make_shared<Server>(0/*server_id*/, name,
max_players, /*current_player*/0, (RaceManager::Difficulty)
difficulty_widget->getSelection(PLAYER_ID_GAME_MASTER),
NetworkConfig::get()->getServerGameMode(race_manager->getMinorMode(),
race_manager->getMajorMode()), server_address);
ServersManager::get()->addServer(server);
ServersManager::get()->setJoinedServer(0);
#undef USE_GRAPHICS_SERVER
#ifdef USE_GRAPHICS_SERVER
@@ -255,7 +249,7 @@ void CreateServerScreen::createServer()
SeparateProcess* sp =
new SeparateProcess(SeparateProcess::getCurrentExecutableLocation(),
server_cfg.str() + password);
STKHost::create(sp);
STKHost::create(server, sp);
#endif
} // createServer

View File

@@ -17,17 +17,12 @@
#include "states_screens/dialogs/server_info_dialog.hpp"
#include "audio/sfx_manager.hpp"
#include "guiengine/engine.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/request_connection.hpp"
#include "network/servers_manager.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "states_screens/dialogs/registration_dialog.hpp"
#include "states_screens/networking_lobby.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
#include <IGUIEnvironment.h>
@@ -43,22 +38,17 @@ using namespace Online;
* \param from_server_creation: true if the dialog shows the data of this
* server (i.e. while it is being created).
*/
ServerInfoDialog::ServerInfoDialog(uint32_t server_id, uint32_t host_id,
bool from_server_creation)
: ModalDialog(0.8f,0.8f), m_server_id(server_id)
, m_host_id(host_id)
ServerInfoDialog::ServerInfoDialog(std::shared_ptr<Server> server)
: ModalDialog(0.8f,0.8f), m_server(server)
{
Log::info("ServerInfoDialog", "Server id is %d, Host id is %d",
server_id, host_id);
server->getServerId(), server->getHostId());
m_self_destroy = false;
m_enter_lobby = false;
m_from_server_creation = from_server_creation;
loadFromFile("online/server_info_dialog.stkgui");
GUIEngine::LabelWidget *name = getWidget<LabelWidget>("server_name");
assert(name);
const Server * server = ServersManager::get()->getServerByID(m_server_id);
name->setText(server->getName(),false);
core::stringw difficulty = race_manager->getDifficultyName(server->getDifficulty());
@@ -69,10 +59,6 @@ ServerInfoDialog::ServerInfoDialog(uint32_t server_id, uint32_t host_id,
GUIEngine::LabelWidget *gamemode = getWidget<LabelWidget>("server_game_mode");
gamemode->setText(mode, false);
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
if (m_from_server_creation)
m_info_widget->setText(_("Server successfully created. You can now join it."), true);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_join_widget = getWidget<IconButtonWidget>("join");
@@ -92,10 +78,9 @@ ServerInfoDialog::~ServerInfoDialog()
// -----------------------------------------------------------------------------
void ServerInfoDialog::requestJoin()
{
ServersManager::get()->setJoinedServer(m_server_id);
STKHost::create();
STKHost::create(m_server);
ModalDialog::dismiss();
NetworkingLobby::getInstance()->setJoinedServer(m_server);
NetworkingLobby::getInstance()->push();
} // requestJoin
@@ -146,17 +131,10 @@ bool ServerInfoDialog::onEscapePressed()
// -----------------------------------------------------------------------------
void ServerInfoDialog::onUpdate(float dt)
{
//If we want to open the registration dialog, we need to close this one first
if (m_enter_lobby) m_self_destroy = true;
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
{
ModalDialog::dismiss();
if (m_from_server_creation)
StateManager::get()->popMenu();
else if (m_enter_lobby)
NetworkingLobby::getInstance()->push();
return;
}
} // onUpdate

View File

@@ -23,11 +23,13 @@
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "network/server.hpp"
#include "utils/types.hpp"
#include <memory>
#include <irrString.h>
class Server;
/** \brief Dialog that allows a user to sign in
* \ingroup states_screens
*/
@@ -35,16 +37,9 @@ class ServerInfoDialog : public GUIEngine::ModalDialog
{
private:
bool m_self_destroy;
bool m_enter_lobby;
bool m_from_server_creation;
const uint32_t m_server_id;
uint32_t m_host_id;
/** The gui element for messages. */
GUIEngine::LabelWidget *m_info_widget;
const std::shared_ptr<Server> m_server;
GUIEngine::RibbonWidget *m_options_widget;
@@ -56,7 +51,7 @@ private:
public:
ServerInfoDialog(uint32_t server_id, uint32_t host_id, bool just_created = false);
ServerInfoDialog(std::shared_ptr<Server> server);
~ServerInfoDialog();
void onEnterPressedInternal();

View File

@@ -32,7 +32,6 @@
#include "network/protocols/client_lobby.hpp"
#include "network/stk_host.hpp"
#include "states_screens/race_setup_screen.hpp"
#include "states_screens/server_selection.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/tracks_screen.hpp"
#include "states_screens/waiting_for_others.hpp"
@@ -222,7 +221,6 @@ bool NetworkKartSelectionScreen::onEscapePressed()
{
// then remove the lobby screen (you left the server)
StateManager::get()->popMenu();
ServerSelection::getInstance()->refresh();
STKHost::get()->shutdown();
return true; // remove the screen
} // onEscapePressed

View File

@@ -36,7 +36,7 @@
#include "network/network_player_profile.hpp"
#include "network/protocols/client_lobby.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/servers_manager.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
@@ -103,36 +103,6 @@ void NetworkingLobby::init()
m_server_info.clear();
Screen::init();
setInitialFocus();
Server* server = ServersManager::get()->getJoinedServer();
if (server)
{
m_server_name = server->getName();
core::stringw each_line;
//I18N: In the networking lobby
each_line = _("Server name: %s", m_server_name);
m_server_info.push_back(each_line);
const core::stringw& difficulty_name =
race_manager->getDifficultyName(server->getDifficulty());
//I18N: In the networking lobby
each_line = _("Difficulty: %s", difficulty_name);
m_server_info.push_back(each_line);
//I18N: In the networking lobby
each_line = _("Max players: %d", server->getMaxPlayers());
m_server_info.push_back(each_line);
//I18N: In the networking lobby
core::stringw mode = RaceManager::getNameOf(server->getRaceMinorMode());
each_line = _("Game mode: %s", mode);
race_manager->setMinorMode(server->getRaceMinorMode());
race_manager->setMajorMode(server->getRaceMajorMode());
race_manager->setDifficulty(server->getDifficulty());
m_server_info.push_back(each_line);
}
m_start_button->setVisible(false);
// For now create the active player and bind it to the right
@@ -142,6 +112,44 @@ void NetworkingLobby::init()
StateManager::get()->createActivePlayer(profile, device);
} // init
// ----------------------------------------------------------------------------
void NetworkingLobby::setJoinedServer(std::shared_ptr<Server> server)
{
if (server == m_joined_server)
return;
m_joined_server = server;
m_server_info.clear();
if (!m_joined_server)
return;
core::stringw each_line;
//I18N: In the networking lobby
each_line = _("Server name: %s", m_joined_server->getName());
m_server_info.push_back(each_line);
const core::stringw& difficulty_name =
race_manager->getDifficultyName(m_joined_server->getDifficulty());
//I18N: In the networking lobby
each_line = _("Difficulty: %s", difficulty_name);
m_server_info.push_back(each_line);
//I18N: In the networking lobby
each_line = _("Max players: %d", m_joined_server->getMaxPlayers());
m_server_info.push_back(each_line);
//I18N: In the networking lobby
core::stringw mode = RaceManager::getNameOf(m_joined_server->getRaceMinorMode());
each_line = _("Game mode: %s", mode);
race_manager->setMinorMode(m_joined_server->getRaceMinorMode());
race_manager->setMajorMode(m_joined_server->getRaceMajorMode());
race_manager->setDifficulty(m_joined_server->getDifficulty());
m_server_info.push_back(each_line);
} // setJoinedServer
// ----------------------------------------------------------------------------
void NetworkingLobby::addMoreServerInfo(const core::stringw& info)
{
@@ -153,8 +161,17 @@ void NetworkingLobby::onUpdate(float delta)
auto lp = LobbyProtocol::get<LobbyProtocol>();
if (!lp)
{
const core::stringw connect_msg = StringUtils::loadingDots(
_("Connecting to server %s", m_server_name));
core::stringw connect_msg;
if (m_joined_server)
{
connect_msg = StringUtils::loadingDots(
_("Connecting to server %s", m_joined_server->getName()));
}
else if (NetworkConfig::get()->isClient())
{
connect_msg =
StringUtils::loadingDots(_("Finding a quick play server"));
}
m_text_bubble->setText(connect_msg, true);
m_start_button->setVisible(false);
}
@@ -177,7 +194,6 @@ void NetworkingLobby::onUpdate(float delta)
} // onUpdate
// ----------------------------------------------------------------------------
void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
const int playerID)
{

View File

@@ -19,6 +19,7 @@
#define HEADER_NETWORKING_LOBBY_HPP
#include "guiengine/screen.hpp"
#include <memory>
class Server;
@@ -45,7 +46,7 @@ private:
NetworkingLobby();
core::stringw m_server_name;
std::shared_ptr<Server> m_joined_server;
std::vector<core::stringw> m_server_info;
GUIEngine::IconButtonWidget * m_back_widget;
@@ -89,6 +90,7 @@ public:
/** Used to insert each client chat message (reserved). */
void addMoreServerInfo(const core::stringw& info);
void setJoinedServer(std::shared_ptr<Server> server);
void addPlayer(NetworkPlayerProfile *profile);
void removePlayer(NetworkPlayerProfile *profile);
}; // class NetworkingLobby

View File

@@ -20,13 +20,10 @@
#include "audio/sfx_manager.hpp"
#include "config/player_manager.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/screen.hpp"
#include "guiengine/widget.hpp"
#include "network/network_config.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/connect_to_server.hpp"
#include "network/protocols/request_connection.hpp"
#include "network/stk_host.hpp"
#include "network/servers_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/create_server_screen.hpp"
@@ -103,6 +100,8 @@ void OnlineProfileServers::eventCallback(Widget* widget, const std::string& name
}
else if (selection == "quick_wan_play")
{
NetworkConfig::get()->setIsWAN();
NetworkConfig::get()->setIsServer(false);
doQuickPlay();
}
}
@@ -110,55 +109,11 @@ void OnlineProfileServers::eventCallback(Widget* widget, const std::string& name
} // eventCallback
// ----------------------------------------------------------------------------
void OnlineProfileServers::doQuickPlay()
{
// Refresh server list.
HTTPRequest* refresh_request = ServersManager::get()->getRefreshRequest(false);
if (refresh_request != NULL) // consider request done
{
refresh_request->executeNow();
delete refresh_request;
}
else
{
Log::error("OnlineScreen", "Could not get the server list.");
return;
}
// select first one
const Server *server = ServersManager::get()->getQuickPlay();
if(!server)
{
Log::error("OnlineProfileServers", "Can not find quick play server.");
return;
}
// do a join request
XMLRequest *join_request = new RequestConnection::ServerJoinRequest();
if (!join_request)
{
SFXManager::get()->quickSound("anvil");
return;
}
PlayerManager::setUserDetails(join_request, "request-connection",
Online::API::SERVER_PATH);
join_request->addParameter("server_id", server->getServerId());
join_request->executeNow();
if (join_request->isSuccess())
{
delete join_request;
NetworkingLobby::getInstance()->push();
auto cts = std::make_shared<ConnectToServer>(server->getServerId(),
server->getHostId());
ProtocolManager::lock()->requestStart(cts);
}
else
{
SFXManager::get()->quickSound("anvil");
}
STKHost::create();
NetworkingLobby::getInstance()->setJoinedServer(nullptr);
NetworkingLobby::getInstance()->push();
} // doQuickPlay
// ----------------------------------------------------------------------------

View File

@@ -20,8 +20,8 @@
#include "audio/sfx_manager.hpp"
#include "guiengine/modaldialog.hpp"
#include "network/network_config.hpp"
#include "network/server.hpp"
#include "network/servers_manager.hpp"
#include "online/xml_request.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/dialogs/server_info_dialog.hpp"
#include "states_screens/state_manager.hpp"
@@ -40,7 +40,7 @@ DEFINE_SCREEN_SINGLETON( ServerSelection );
*/
ServerSelection::ServerSelection() : Screen("online/server_selection.stkgui")
{
m_refresh_request = NULL;
m_refreshing_server = false;
} // ServerSelection
// ----------------------------------------------------------------------------
@@ -55,12 +55,8 @@ ServerSelection::~ServerSelection()
*/
void ServerSelection::tearDown()
{
// If the refresh request is being executed, and stk should exit,
// then a crash can happen when the refresh request is deleted, but
// then the request manager tries to activate this request. So only
// delete this request if it is finished.
if(m_refresh_request && m_refresh_request->isDone())
delete m_refresh_request;
ServersManager::get()->cleanUpServers();
m_server_list_widget->clear();
} // tearDown
// ----------------------------------------------------------------------------
@@ -69,16 +65,16 @@ void ServerSelection::tearDown()
*/
void ServerSelection::refresh()
{
m_refresh_request = ServersManager::get()->getRefreshRequest();
// If the request was created (i.e. no error, and not re-requested within
// 5 seconds), clear the list and display the waiting message:
if(m_refresh_request)
if (ServersManager::get()->refresh())
{
m_server_list_widget->clear();
m_server_list_widget->addItem("spacer", L"");
m_server_list_widget->addItem("loading",
StringUtils::loadingDots(_("Fetching servers")));
m_reload_widget->setActive(false);
m_refreshing_server = true;
}
} // refresh
@@ -113,10 +109,6 @@ void ServerSelection::init()
{
Screen::init();
m_sort_desc = true;
// Set the default sort order
Server::setSortOrder(Server::SO_NAME);
/** Triggers the loading of the server list in the servers manager. */
refresh();
} // init
@@ -124,16 +116,37 @@ void ServerSelection::init()
// ----------------------------------------------------------------------------
/** Loads the list of all servers. The gui element will be
* updated.
* \param type Must be 'kart' or 'track'.
* \param sort_case what sorting method will be used.
*/
void ServerSelection::loadList()
void ServerSelection::loadList(unsigned sort_case)
{
m_server_list_widget->clear();
ServersManager *manager = ServersManager::get();
manager->sort(m_sort_desc);
for(int i=0; i < manager->getNumServers(); i++)
m_server_list_widget->clear();
ServersManager::get()->sortServers([sort_case, this]
(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:
return c->getRaceMinorMode() > d->getRaceMinorMode();
break;
} // switch
assert(false);
return false;
});
for (auto server : ServersManager::get()->getServers())
{
const Server *server = manager->getServerBySort(i);
core::stringw num_players;
num_players.append(StringUtils::toWString(server->getCurrentPlayers()));
num_players.append("/");
@@ -142,7 +155,8 @@ void ServerSelection::loadList()
row.push_back(GUIEngine::ListWidget::ListCell(server->getName(),-1,3));
row.push_back(GUIEngine::ListWidget::ListCell(num_players,-1,1,true));
core::stringw difficulty = race_manager->getDifficultyName(server->getDifficulty());
core::stringw difficulty =
race_manager->getDifficultyName(server->getDifficulty());
row.push_back(GUIEngine::ListWidget::ListCell(difficulty, -1, 1, true));
core::stringw mode = RaceManager::getNameOf(server->getRaceMinorMode());
@@ -158,23 +172,14 @@ void ServerSelection::loadList()
*/
void ServerSelection::onColumnClicked(int column_id)
{
switch(column_id)
{
case 0: Server::setSortOrder(Server::SO_NAME); break;
case 1: Server::setSortOrder(Server::SO_PLAYERS); break;
case 2: Server::setSortOrder(Server::SO_DIFFICULTY); break;
case 3: Server::setSortOrder(Server::SO_GAME_MODE); break;
default: assert(0); break;
} // switch
/** \brief Toggle the sort order after column click **/
m_sort_desc = !m_sort_desc;
loadList();
loadList(column_id);
} // onColumnClicked
// ----------------------------------------------------------------------------
void ServerSelection::eventCallback( GUIEngine::Widget* widget,
const std::string& name,
const int playerID)
void ServerSelection::eventCallback(GUIEngine::Widget* widget,
const std::string& name,
const int playerID)
{
if (name == "back")
{
@@ -191,17 +196,14 @@ void ServerSelection::eventCallback( GUIEngine::Widget* widget,
int selected_index = m_server_list_widget->getSelectionID();
// This can happen e.g. when the list is empty and the user
// clicks somewhere.
if(selected_index >= ServersManager::get()->getNumServers() ||
selected_index<0 )
if (selected_index < 0 ||
m_refreshing_server ||
selected_index >= (int)ServersManager::get()->getServers().size())
{
return;
}
const Server *server =
ServersManager::get()->getServerBySort(selected_index);
uint32_t server_id = server->getServerId();
uint32_t host_id = server->getHostId();
new ServerInfoDialog(server_id, host_id);
new ServerInfoDialog(
ServersManager::get()->getServers()[selected_index]);
} // click on server
} // eventCallback
@@ -213,17 +215,16 @@ void ServerSelection::eventCallback( GUIEngine::Widget* widget,
void ServerSelection::onUpdate(float dt)
{
if (!m_refresh_request) return;
if (!m_refreshing_server) return;
if (m_refresh_request->isDone())
if (ServersManager::get()->listUpdated())
{
if (m_refresh_request->isSuccess())
m_refreshing_server = false;
if (!ServersManager::get()->getServers().empty())
{
int selection = m_server_list_widget->getSelectionID();
std::string selection_str = m_server_list_widget->getSelectionInternalName();
loadList();
loadList(0);
// restore previous selection
if (selection != -1 && selection_str != "spacer" && selection_str != "loading")
m_server_list_widget->setSelectionID(selection);
@@ -231,37 +232,18 @@ void ServerSelection::onUpdate(float dt)
else
{
SFXManager::get()->quickSound("anvil");
new MessageDialog(m_refresh_request->getInfo());
new MessageDialog(_("No server is available."));
m_server_list_widget->clear();
}
delete m_refresh_request;
m_refresh_request = NULL;
m_reload_widget->setActive(true);
}
else
{
int selection = m_server_list_widget->getSelectionID();
std::string selection_str = m_server_list_widget->getSelectionInternalName();
m_server_list_widget->clear();
loadList();
m_server_list_widget->addItem("spacer", L"");
m_server_list_widget->addItem("loading",
StringUtils::loadingDots(_("Fetching servers")));
// restore previous selection
if (selection != -1 && selection_str != "spacer" && selection_str != "loading")
m_server_list_widget->setSelectionID(selection);
}
// In case of auto-connect command line parameter, select the first server asap
if (NetworkConfig::get()->isAutoConnect() &&
m_refresh_request == NULL &&
m_server_list_widget->getItemCount() > 0)
m_refreshing_server == false &&
!ServersManager::get()->getServers().empty())
{
ServerInfoDialog *sid = new ServerInfoDialog(/*server*/0,
/*host id*/0, false);
ServerInfoDialog *sid = new ServerInfoDialog(ServersManager::get()->getServers()[0]);
sid->requestJoin();
}
} // onUpdate

View File

@@ -39,24 +39,21 @@ private:
ServerSelection();
~ServerSelection();
GUIEngine::IconButtonWidget * m_reload_widget;
GUIEngine::LabelWidget * m_update_status;
GUIEngine::ListWidget * m_server_list_widget;
GUIEngine::IconButtonWidget* m_reload_widget;
GUIEngine::LabelWidget* m_update_status;
GUIEngine::ListWidget* m_server_list_widget;
/** \brief To check (and set) if sort order is descending **/
bool m_sort_desc;
bool m_sort_desc;
/** A pointer to the http request for getting a server list. */
const Online::XMLRequest *m_refresh_request;
bool m_refreshing_server;
public:
/** Load the servers into the main list.*/
void loadList(unsigned sort_case);
void refresh();
/** Load the addons into the main list.*/
void loadList();
public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE;