Initial work on lobby redesign

This commit is contained in:
Benau 2018-03-12 00:18:53 +08:00
parent 4dea283965
commit 3bbec8aa27
16 changed files with 461 additions and 392 deletions

View File

@ -25,13 +25,13 @@
#include "network/race_config.hpp"
#include "network/remote_kart_info.hpp"
#include <vector>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
namespace Online { class OnlineProfile; }
class NetworkPlayerProfile;
// ============================================================================
/*! \class GameSetup
* \brief Used to store the needed data about the players that join a game.

View File

@ -19,31 +19,6 @@
#include "network/network_player_profile.hpp"
#include "network/stk_host.hpp"
#include "online/online_player_profile.hpp"
/** Constructor.
* \param global_player_id A unique number assigned from the server to this
* player (though it might not be the index in the peer list).
* \param name Name of this player.
* \param global_player_id Global id of this player.
* \param host_id The id of the host the player is connected from.
*/
NetworkPlayerProfile::NetworkPlayerProfile(const irr::core::stringw &name,
int global_player_id,
int host_id )
{
m_global_player_id = global_player_id;
m_host_id = host_id;
m_kart_name = "";
m_world_kart_id = 0;
m_per_player_difficulty = PLAYER_DIFFICULTY_NORMAL;
m_player_name = name;
} // BetworkPlayerProfile
// ----------------------------------------------------------------------------
NetworkPlayerProfile::~NetworkPlayerProfile()
{
} // ~NetworkPlayerProfile
// ----------------------------------------------------------------------------
/** Returns true if this player is local, i.e. running on this computer. This
* is done by comparing the host id of this player with the host id of this
@ -52,4 +27,4 @@ NetworkPlayerProfile::~NetworkPlayerProfile()
bool NetworkPlayerProfile::isLocalPlayer() const
{
return m_host_id == STKHost::get()->getMyHostId();
} // isLocalPlayer
} // isLocalPlayer

View File

@ -26,10 +26,11 @@
#include "utils/types.hpp"
#include "irrString.h"
#include <memory>
#include <string>
namespace Online { class OnlineProfile; }
#include <tuple>
class STKPeer;
/*! \class NetworkPlayerProfile
* \brief Contains the profile of a player.
@ -37,31 +38,51 @@ namespace Online { class OnlineProfile; }
class NetworkPlayerProfile
{
private:
std::weak_ptr<STKPeer> m_peer;
/** The name of the player. */
irr::core::stringw m_player_name;
/** Host id of this player. */
uint32_t m_host_id;
float m_default_kart_color;
uint32_t m_online_id;
/** Per player difficulty. */
PerPlayerDifficulty m_per_player_difficulty;
/** The selected kart id. */
std::string m_kart_name;
/** The unique id of the player for this race. The number is assigned
* by the server (and it might not be the index of this player in the
* peer list. */
uint8_t m_global_player_id;
/** Host id of this player. */
uint8_t m_host_id;
/** The selected kart id. */
std::string m_kart_name;
/** The name of the player. */
irr::core::stringw m_player_name;
/** The kart id in the World class (pointer to AbstractKart). */
uint8_t m_world_kart_id;
/** Per player difficulty. */
PerPlayerDifficulty m_per_player_difficulty;
public:
NetworkPlayerProfile(const irr::core::stringw &name,
int global_player_id, int host_id);
~NetworkPlayerProfile();
NetworkPlayerProfile(std::shared_ptr<STKPeer> peer,
const irr::core::stringw &name, uint32_t host_id,
float default_kart_color, uint32_t online_id,
PerPlayerDifficulty per_player_difficulty)
{
m_peer = peer;
m_player_name = name;
m_host_id = host_id;
m_default_kart_color = default_kart_color;
m_online_id = online_id;
m_per_player_difficulty = per_player_difficulty;
m_global_player_id = 0;
m_world_kart_id = 0;
}
// ------------------------------------------------------------------------
~NetworkPlayerProfile() {}
// ------------------------------------------------------------------------
bool isLocalPlayer() const;
// ------------------------------------------------------------------------
/** Sets the global player id of this player. */
void setGlobalPlayerId(int player_id) { m_global_player_id = player_id; }
@ -93,6 +114,15 @@ public:
/** Returns the name of this player. */
const irr::core::stringw& getName() const { return m_player_name; }
// ------------------------------------------------------------------------
float getDefaultKartColor() const { return m_default_kart_color; }
// ------------------------------------------------------------------------
uint32_t getOnlineID() const { return m_online_id; }
// ------------------------------------------------------------------------
std::shared_ptr<STKPeer> getPeer() const { return m_peer.lock(); }
// ------------------------------------------------------------------------
/** Returns the minimun info for networking lobby screen. */
std::tuple<uint32_t, uint32_t, irr::core::stringw> toTuple() const
{ return std::make_tuple(m_host_id, m_online_id, m_player_name); }
}; // class NetworkPlayerProfile

View File

@ -20,6 +20,7 @@
#include "config/player_manager.hpp"
#include "karts/kart_properties_manager.hpp"
#include "guiengine/message_queue.hpp"
#include "modes/world_with_rank.hpp"
#include "network/event.hpp"
#include "network/network_config.hpp"
@ -29,6 +30,7 @@
#include "network/race_event_manager.hpp"
#include "network/stk_host.hpp"
#include "network/stk_peer.hpp"
#include "online/online_player_profile.hpp"
#include "online/online_profile.hpp"
#include "states_screens/networking_lobby.hpp"
#include "states_screens/network_kart_selection.hpp"
@ -201,13 +203,6 @@ void ClientLobby::voteLaps(uint8_t player_id, uint8_t laps,
delete request;
} // voteLaps
//-----------------------------------------------------------------------------
/** Called when a client selects to exit a server.
*/
void ClientLobby::leave()
{
} // leave
//-----------------------------------------------------------------------------
/** Called from the gui when a client clicked on 'continue' on the race result
* screen. It notifies the server that this client has exited the screen and
@ -239,6 +234,7 @@ bool ClientLobby::notifyEvent(Event* event)
case LE_LOAD_WORLD: loadWorld(); break;
case LE_RACE_FINISHED: raceFinished(event); break;
case LE_EXIT_RESULT: exitResultScreen(event); break;
case LE_UPDATE_PLAYER_LIST: updatePlayerList(event); break;
default:
return false;
break;
@ -261,7 +257,6 @@ bool ClientLobby::notifyEventAsynchronous(Event* event)
message_type);
switch(message_type)
{
case LE_NEW_PLAYER_CONNECTED: newPlayer(event); break;
case LE_PLAYER_DISCONNECTED : disconnectedPlayer(event); break;
case LE_START_RACE: startGame(event); break;
case LE_CONNECTION_REFUSED: connectionRefused(event); break;
@ -273,6 +268,7 @@ bool ClientLobby::notifyEventAsynchronous(Event* event)
case LE_VOTE_TRACK: playerTrackVote(event); break;
case LE_VOTE_REVERSE: playerReversedVote(event); break;
case LE_VOTE_LAPS: playerLapsVote(event); break;
case LE_AUTHORISED: becomingServerOwner(); break;
} // switch
return true;
@ -321,20 +317,31 @@ void ClientLobby::update(float dt)
break;
case LINKED:
{
core::stringw name;
if(PlayerManager::getCurrentOnlineState()==PlayerProfile::OS_SIGNED_IN)
name = PlayerManager::getCurrentOnlineUserName();
else
name = PlayerManager::getCurrentPlayer()->getName();
std::string name_u8 = StringUtils::wideToUtf8(name);
const std::string &password = NetworkConfig::get()->getPassword();
NetworkString *ns = getNetworkString(6+1+name_u8.size()
+1+password.size());
// 4 (size of id), global id
ns->addUInt8(LE_CONNECTION_REQUESTED).encodeString(name)
.encodeString(NetworkConfig::get()->getPassword());
// atm assume only 1 local player (no split screen yet)
NetworkString *ns = getNetworkString();
ns->addUInt8(LE_CONNECTION_REQUESTED)
.encodeString(NetworkConfig::get()->getPassword());
uint8_t num_player = 1;
ns->addUInt8(num_player);
for (unsigned i = 0; i < num_player; i++)
{
core::stringw name;
PlayerProfile* player = PlayerManager::getCurrentPlayer();
if (PlayerManager::getCurrentOnlineState() ==
PlayerProfile::OS_SIGNED_IN)
name = PlayerManager::getCurrentOnlineUserName();
else
name = player->getName();
std::string name_u8 = StringUtils::wideToUtf8(name);
ns->encodeString(name_u8).addFloat(player->getDefaultKartColor());
Online::OnlinePlayerProfile* opp =
dynamic_cast<Online::OnlinePlayerProfile*>(player);
ns->addUInt32(opp && opp->getProfile() ?
opp->getProfile()->getID() : 0);
// Assume no handicap player now
ns->addUInt8(PLAYER_DIFFICULTY_NORMAL);
}
auto all_k = kart_properties_manager->getAllAvailableKarts();
auto all_t = track_manager->getAllTrackIdentifiers();
if (all_k.size() >= 65536)
@ -389,49 +396,6 @@ void ClientLobby::update(float dt)
//-----------------------------------------------------------------------------
/*! \brief Called when a new player is connected to the server
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 2
* -------------------------------------
* Size | 1 | 1 | |
* Data | player_id | hostid | player name |
* -------------------------------------
*/
void ClientLobby::newPlayer(Event* event)
{
if (!checkDataSize(event, 2)) return;
const NetworkString &data = event->data();
uint8_t player_id = data.getUInt8();
uint8_t host_id = data.getUInt8();
core::stringw name;
data.decodeStringW(&name);
// FIXME need adjusting when splitscreen is used/
if(STKHost::get()->getGameSetup()->isLocalMaster(player_id))
{
Log::error("ClientLobby",
"The server notified me that I'm a new player in the "
"room (not normal).");
}
else if (m_game_setup->getProfile(player_id) == NULL)
{
Log::verbose("ClientLobby", "New player connected.");
NetworkPlayerProfile* profile =
new NetworkPlayerProfile(name, player_id, host_id);
m_game_setup->addPlayer(profile);
NetworkingLobby::getInstance()->addPlayer(profile);
}
else
{
Log::error("ClientLobby",
"One of the player notified in the list is myself.");
}
} // newPlayer
//-----------------------------------------------------------------------------
/*! \brief Called when a new player is disconnected
* \param event : Event providing the information.
*
@ -447,95 +411,67 @@ void ClientLobby::disconnectedPlayer(Event* event)
if (!checkDataSize(event, 1)) return;
NetworkString &data = event->data();
while(data.size()>0)
unsigned disconnected_player_count = data.getUInt8();
for (unsigned i = 0; i < disconnected_player_count; i++)
{
const NetworkPlayerProfile *profile =
m_game_setup->getProfile(data.getUInt8());
if (m_game_setup->removePlayer(profile))
{
Log::info("ClientLobby",
"Player %d removed successfully.",
profile->getGlobalPlayerId());
}
else
{
Log::error("ClientLobby",
"The disconnected peer wasn't known.");
}
} // while
core::stringw player_name;
data.decodeStringW(&player_name);
core::stringw msg = _("%s disconnected.", player_name);
// Use the friend icon to avoid an error-like message
MessageQueue::add(MessageQueue::MT_FRIEND, msg);
}
} // disconnectedPlayer
//-----------------------------------------------------------------------------
/*! \brief Called when the server accepts the connection.
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 2 3
* ---------------------------------------------------------
* Size | 1 | 1 | 1 | |
* Data | player_id| hostid | authorised |playernames* |
* ---------------------------------------------------------
*/
void ClientLobby::connectionAccepted(Event* event)
{
// At least 3 bytes should remain now
if(!checkDataSize(event, 3)) return;
// At least 4 byte should remain now
if (!checkDataSize(event, 4)) return;
NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
// Accepted
// ========
Log::info("ClientLobby",
"The server accepted the connection.");
Log::info("ClientLobby", "The server accepted the connection.");
// self profile
irr::core::stringw name;
if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
name = PlayerManager::getCurrentOnlineUserName();
else
name = PlayerManager::getCurrentPlayer()->getName();
uint8_t my_player_id = data.getUInt8();
uint8_t my_host_id = data.getUInt8();
uint8_t authorised = data.getUInt8();
// Store this client's authorisation status in the peer information
// for the server.
event->getPeer()->setAuthorised(authorised!=0);
STKHost::get()->setMyHostId(my_host_id);
NetworkPlayerProfile* profile =
new NetworkPlayerProfile(name, my_player_id, my_host_id);
STKHost::get()->getGameSetup()->setLocalMaster(my_player_id);
STKHost::get()->setMyHostId(data.getUInt32());
m_game_setup->setNumLocalPlayers(1);
// connection token
uint32_t token = data.getToken();
peer->setClientServerToken(token);
// Add all players
// ===============
while (data.size() > 0)
{
uint8_t player_id = data.getUInt8();
uint8_t host_id = data.getUInt8();
irr::core::stringw name;
data.decodeStringW(&name);
NetworkPlayerProfile* profile2 =
new NetworkPlayerProfile(name, player_id, host_id);
m_game_setup->addPlayer(profile2);
// Inform the network lobby of all players so that the GUI can
// show all currently connected players.
NetworkingLobby::getInstance()->addPlayer(profile2);
}
// Add self after other players so that player order is identical
// on server and all clients.
m_game_setup->addPlayer(profile);
NetworkingLobby::getInstance()->addPlayer(profile);
m_state = CONNECTED;
if (NetworkConfig::get()->isAutoConnect())
} // connectionAccepted
//-----------------------------------------------------------------------------
void ClientLobby::updatePlayerList(Event* event)
{
if (!checkDataSize(event, 1)) return;
NetworkString &data = event->data();
unsigned player_count = data.getUInt8();
NetworkingLobby::getInstance()->cleanPlayers();
for (unsigned i = 0; i < player_count; i++)
{
std::tuple<uint32_t, uint32_t, core::stringw, bool> pl;
std::get<0>(pl) = data.getUInt32();
std::get<1>(pl) = data.getUInt32();
data.decodeStringW(&std::get<2>(pl));
std::get<3>(pl) = data.getUInt8() == 1;
NetworkingLobby::getInstance()->addPlayer(pl);
}
} // updatePlayerList
//-----------------------------------------------------------------------------
void ClientLobby::becomingServerOwner()
{
MessageQueue::add(MessageQueue::MT_GENERIC,
_("You are now the owner of server."));
STKHost::get()->setAuthorisedToControl(true);
if (m_state == CONNECTED && NetworkConfig::get()->isAutoConnect())
{
// Send a message to the server to start
NetworkString start(PROTOCOL_LOBBY_ROOM);
@ -543,8 +479,7 @@ void ClientLobby::connectionAccepted(Event* event)
start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN);
STKHost::get()->sendToServer(&start, true);
}
} // connectionAccepted
} // becomingServerOwner
//-----------------------------------------------------------------------------
@ -562,26 +497,31 @@ void ClientLobby::connectionRefused(Event* event)
{
if (!checkDataSize(event, 1)) return;
const NetworkString &data = event->data();
switch (data.getUInt8()) // the second byte
switch ((RejectReason)data.getUInt8()) // the second byte
{
case 0:
Log::info("ClientLobby",
"Connection refused : too many players.");
case RR_BUSY:
STKHost::get()->setErrorMessage(
_("Connection refused: Server is busy."));
break;
case 1:
Log::info("ClientLobby", "Connection refused : banned.");
case RR_BANNED:
STKHost::get()->setErrorMessage(
_("Connection refused: You are banned from the server."));
break;
case 2:
Log::info("ClientLobby", "Client busy.");
case RR_INCORRECT_PASSWORD:
STKHost::get()->setErrorMessage(
_("Connection refused: Server password is incorrect."));
break;
case 3:
Log::info("ClientLobby", "Having incompatible karts / tracks.");
case RR_INCOMPATIBLE_DATA:
STKHost::get()->setErrorMessage(
_("Connection refused: Game data is incompatible."));
break;
default:
Log::info("ClientLobby", "Connection refused.");
case RR_TOO_MANY_PLAYERS:
STKHost::get()->setErrorMessage(
_("Connection refused: Server is full."));
break;
}
STKHost::get()->disconnectAllPeers(false/*timeout_waiting*/);
STKHost::get()->requestShutdown();
} // connectionRefused
//-----------------------------------------------------------------------------

View File

@ -9,7 +9,6 @@
class ClientLobby : public LobbyProtocol
{
private:
void newPlayer(Event* event);
void disconnectedPlayer(Event* event);
void connectionAccepted(Event* event); //!< Callback function on connection acceptation
void connectionRefused(Event* event); //!< Callback function on connection refusal
@ -26,6 +25,8 @@ private:
void playerTrackVote(Event* event);
void playerReversedVote(Event* event);
void playerLapsVote(Event* event);
void updatePlayerList(Event* event);
void becomingServerOwner();
TransportAddress m_server_address;
@ -65,7 +66,6 @@ public:
void voteLaps(uint8_t player_id, uint8_t laps, uint8_t track_nb = 0);
void doneWithResults();
void startingRaceNow();
void leave();
const std::set<std::string>& getAvailableKarts() const
{ return m_available_karts; }

View File

@ -42,7 +42,7 @@ public:
LE_KART_SELECTION_UPDATE, // inform client about kart selected
LE_REQUEST_BEGIN, // begin of kart selection
LE_KART_SELECTION_REFUSED, // Client not auth. to start selection
LE_NEW_PLAYER_CONNECTED, // inform client about new player
LE_UPDATE_PLAYER_LIST, // inform client about player list update
LE_KART_SELECTION, // Player selected kart
LE_PLAYER_DISCONNECTED, // Client disconnected
LE_CLIENT_LOADED_WORLD, // Client finished loading world
@ -60,6 +60,18 @@ public:
LE_VOTE_TRACK, // vote for a track
LE_VOTE_REVERSE, // vote if race in reverse
LE_VOTE_LAPS, // vote number of laps
LE_CHAT,
LE_FINAL_PLAYER_LIST,
LE_AUTHORISED
};
enum RejectReason : uint8_t
{
RR_BUSY = 0,
RR_BANNED = 1,
RR_INCORRECT_PASSWORD = 2,
RR_INCOMPATIBLE_DATA = 3,
RR_TOO_MANY_PLAYERS = 4
};
protected:

View File

@ -41,6 +41,7 @@
#include "utils/random_generator.hpp"
#include "utils/time.hpp"
#include <algorithm>
#include <fstream>
/** This is the central game setup protocol running in the server. It is
@ -84,18 +85,9 @@
*/
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
{
m_has_created_server_id_file = false;
setHandleDisconnections(true);
m_state = SET_PUBLIC_ADDRESS;
// We use maximum 16bit unsigned limit
auto all_k = kart_properties_manager->getAllAvailableKarts();
auto all_t = track_manager->getAllTrackIdentifiers();
if (all_k.size() >= 65536)
all_k.resize(65535);
if (all_t.size() >= 65536)
all_t.resize(65535);
m_available_kts.getData().first = { all_k.begin(), all_k.end() };
m_available_kts.getData().second = { all_t.begin(), all_t.end() };
} // ServerLobby
//-----------------------------------------------------------------------------
@ -113,6 +105,16 @@ ServerLobby::~ServerLobby()
void ServerLobby::setup()
{
// We use maximum 16bit unsigned limit
auto all_k = kart_properties_manager->getAllAvailableKarts();
auto all_t = track_manager->getAllTrackIdentifiers();
if (all_k.size() >= 65536)
all_k.resize(65535);
if (all_t.size() >= 65536)
all_t.resize(65535);
m_available_kts.first = { all_k.begin(), all_k.end() };
m_available_kts.second = { all_t.begin(), all_t.end() };
m_server_registered = false;
m_game_setup = STKHost::get()->setupNewGame();
m_game_setup->setNumLocalPlayers(0); // no local players on a server
@ -197,11 +199,12 @@ bool ServerLobby::notifyEventAsynchronous(Event* event)
void ServerLobby::createServerIdFile()
{
const std::string& sid = NetworkConfig::get()->getServerIdFile();
if (!sid.empty())
if (!sid.empty() && !m_has_created_server_id_file)
{
std::fstream fs;
fs.open(sid, std::ios::out);
fs.close();
m_has_created_server_id_file = true;
}
} // createServerIdFile
@ -265,6 +268,7 @@ void ServerLobby::asynchronousUpdate()
default:
break;
}
} // asynchronousUpdate
//-----------------------------------------------------------------------------
@ -274,6 +278,9 @@ void ServerLobby::asynchronousUpdate()
*/
void ServerLobby::update(float dt)
{
// Check if server owner has left
updateServerOwner();
switch (m_state.load())
{
case SET_PUBLIC_ADDRESS:
@ -463,12 +470,6 @@ void ServerLobby::signalRaceStartToClients()
void ServerLobby::startSelection(const Event *event)
{
std::lock_guard<std::mutex> lock(m_connection_mutex);
if (NetworkConfig::get()->isWAN())
{
assert(m_server_registered);
unregisterServer();
m_server_registered = false;
}
if (m_state != ACCEPTING_CLIENTS)
{
@ -477,21 +478,28 @@ void ServerLobby::startSelection(const Event *event)
m_state.load());
return;
}
if(event && !event->getPeer()->isAuthorised())
if (event->getPeerSP() != m_server_owner.lock())
{
Log::warn("ServerLobby",
"Client %lx is not authorised to start selection.",
event->getPeer());
return;
}
if (NetworkConfig::get()->isWAN())
{
assert(m_server_registered);
unregisterServer();
m_server_registered = false;
}
NetworkString *ns = getNetworkString(1);
// Start selection - must be synchronous since the receiver pushes
// a new screen, which must be donefrom the main thread.
ns->setSynchronous(true);
ns->addUInt8(LE_START_SELECTION);
m_available_kts.lock();
const auto& all_k = m_available_kts.getData().first;
const auto& all_t = m_available_kts.getData().second;
const auto& all_k = m_available_kts.first;
const auto& all_t = m_available_kts.second;
ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size());
for (const std::string& kart : all_k)
{
@ -501,7 +509,6 @@ void ServerLobby::startSelection(const Event *event)
{
ns->encodeString(track);
}
m_available_kts.unlock();
sendMessageToPeersChangingToken(ns, /*reliable*/true);
delete ns;
@ -625,23 +632,21 @@ void ServerLobby::checkIncomingConnectionRequests()
*/
void ServerLobby::clientDisconnected(Event* event)
{
std::vector<NetworkPlayerProfile*> players_on_host =
event->getPeer()->getAllPlayerProfiles();
std::lock_guard<std::mutex> lock(m_connection_mutex);
auto players_on_peer = event->getPeer()->getPlayerProfiles();
if (players_on_peer.empty())
return;
NetworkString *msg = getNetworkString(2);
NetworkString* msg = getNetworkString(2);
msg->addUInt8(LE_PLAYER_DISCONNECTED);
for(unsigned int i=0; i<players_on_host.size(); i++)
msg->addUInt8((uint8_t)players_on_peer.size());
for (auto p : players_on_peer)
{
msg->addUInt8(players_on_host[i]->getGlobalPlayerId());
Log::info("ServerLobby", "Player disconnected : id %d",
players_on_host[i]->getGlobalPlayerId());
m_game_setup->removePlayer(players_on_host[i]);
msg->encodeString(p->getName());
}
sendMessageToPeersChangingToken(msg, /*reliable*/true);
updatePlayerList();
delete msg;
} // clientDisconnected
//-----------------------------------------------------------------------------
@ -659,34 +664,62 @@ void ServerLobby::clientDisconnected(Event* event)
void ServerLobby::connectionRequested(Event* event)
{
std::lock_guard<std::mutex> lock(m_connection_mutex);
STKPeer* peer = event->getPeer();
std::shared_ptr<STKPeer> peer = event->getPeerSP();
peer->cleanPlayerProfiles();
const NetworkString &data = event->data();
// can we add the player ?
if (m_game_setup->getPlayerCount() >= NetworkConfig::get()->getMaxPlayers() ||
m_state!=ACCEPTING_CLIENTS )
if (m_game_setup->getPlayerCount() >=
NetworkConfig::get()->getMaxPlayers() ||
m_state != ACCEPTING_CLIENTS)
{
NetworkString *message = getNetworkString(2);
// Len, error code: 2 = busy, 0 = too many players
message->addUInt8(LE_CONNECTION_REFUSED)
.addUInt8(m_state!=ACCEPTING_CLIENTS ? 2 : 0);
.addUInt8(m_state != ACCEPTING_CLIENTS ?
RR_BUSY : RR_TOO_MANY_PLAYERS);
// send only to the peer that made the request
// send only to the peer that made the request and disconect it now
peer->sendPacket(message);
peer->reset();
delete message;
Log::verbose("ServerLobby", "Player refused");
return;
}
// Connection accepted.
// ====================
std::string name_u8;
data.decodeString(&name_u8);
core::stringw name = StringUtils::utf8ToWide(name_u8);
// Check for password
std::string password;
data.decodeString(&password);
bool is_authorised = (password==NetworkConfig::get()->getPassword());
if (password != NetworkConfig::get()->getPassword())
{
NetworkString *message = getNetworkString(2);
message->addUInt8(LE_CONNECTION_REFUSED)
.addUInt8(RR_INCORRECT_PASSWORD);
// send only to the peer that made the request and disconect it now
peer->sendPacket(message);
peer->reset();
delete message;
Log::verbose("ServerLobby", "Player refused: incorrect password");
return;
}
// Connection accepted.
// ====================
uint8_t player_count = data.getUInt8();
for (unsigned i = 0; i < player_count; i++)
{
std::string name_u8;
data.decodeString(&name_u8);
core::stringw name = StringUtils::utf8ToWide(name_u8);
float default_kart_color = data.getFloat();
uint32_t online_id = data.getUInt32();
PerPlayerDifficulty per_player_difficulty =
(PerPlayerDifficulty)data.getUInt8();
peer->addPlayer(std::make_shared<NetworkPlayerProfile>
(peer, name, peer->getHostId(), default_kart_color, online_id,
per_player_difficulty));
}
std::set<std::string> client_karts, client_tracks;
const unsigned kart_num = data.getUInt16();
const unsigned track_num = data.getUInt16();
@ -707,14 +740,14 @@ void ServerLobby::connectionRequested(Event* event)
// so that in the end the server has a list of all karts/tracks available
// on all clients
std::set<std::string> karts_erase, tracks_erase;
for (const std::string& server_kart : m_available_kts.getData().first)
for (const std::string& server_kart : m_available_kts.first)
{
if (client_karts.find(server_kart) == client_karts.end())
{
karts_erase.insert(server_kart);
}
}
for (const std::string& server_track : m_available_kts.getData().second)
for (const std::string& server_track : m_available_kts.second)
{
if (client_tracks.find(server_track) == client_tracks.end())
{
@ -724,48 +757,27 @@ void ServerLobby::connectionRequested(Event* event)
// Drop this player if he doesn't have at least 1 kart / track the same
// from server
if (karts_erase.size() == m_available_kts.getData().first.size() ||
tracks_erase.size() == m_available_kts.getData().second.size())
if (karts_erase.size() == m_available_kts.first.size() ||
tracks_erase.size() == m_available_kts.second.size())
{
NetworkString *message = getNetworkString(2);
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(3);
message->addUInt8(LE_CONNECTION_REFUSED)
.addUInt8(RR_INCOMPATIBLE_DATA);
peer->sendPacket(message);
peer->reset();
delete message;
Log::verbose("ServerLobby", "Player has incompatible karts / tracks");
m_available_kts.unlock();
return;
}
for (const std::string& kart_erase : karts_erase)
{
m_available_kts.getData().first.erase(kart_erase);
m_available_kts.first.erase(kart_erase);
}
for (const std::string& track_erase : tracks_erase)
{
m_available_kts.getData().second.erase(track_erase);
m_available_kts.second.erase(track_erase);
}
m_available_kts.unlock();
// Get the unique global ID for this player.
m_next_player_id.lock();
m_next_player_id.getData()++;
int new_player_id = m_next_player_id.getData();
m_next_player_id.unlock();
if(m_game_setup->getLocalMasterID()==0)
m_game_setup->setLocalMaster(new_player_id);
// The host id has already been incremented when the peer
// was added, so it is the right id now.
int new_host_id = STKHost::get()->getNextHostId();
// Notify everybody that there is a new player
// -------------------------------------------
NetworkString *message = getNetworkString(3+1+name_u8.size());
// size of id -- id -- size of local id -- local id;
message->addUInt8(LE_NEW_PLAYER_CONNECTED).addUInt8(new_player_id)
.addUInt8(new_host_id).encodeString(name_u8);
STKHost::get()->sendPacketExcept(peer, message);
delete message;
// Now answer to the peer that just connected
// ------------------------------------------
@ -777,38 +789,83 @@ void ServerLobby::connectionRequested(Event* event)
(token_generator.get(RAND_MAX) & 0xff));
peer->setClientServerToken(token);
peer->setAuthorised(is_authorised);
peer->setHostId(new_host_id);
const std::vector<NetworkPlayerProfile*> &players = m_game_setup->getPlayers();
// send a message to the one that asked to connect
// Estimate 10 as average name length
NetworkString *message_ack = getNetworkString(4 + players.size() * (2+10));
// connection success -- size of token -- token
message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt8(new_player_id)
.addUInt8(new_host_id).addUInt8(is_authorised);
// Add all players so that this user knows (this new player is only added
// to the list of players later, so the new player's info is not included)
for (unsigned int i = 0; i < players.size(); i++)
{
message_ack->addUInt8(players[i]->getGlobalPlayerId())
.addUInt8(players[i]->getHostId())
.encodeString(players[i]->getName());
}
NetworkString *message_ack = getNetworkString(4);
// connection success -- return the host id of peer
message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt32(peer->getHostId());
peer->sendPacket(message_ack);
delete message_ack;
NetworkPlayerProfile* profile =
new NetworkPlayerProfile(name, new_player_id, new_host_id);
m_game_setup->addPlayer(profile);
NetworkingLobby::getInstance()->addPlayer(profile);
updatePlayerList();
Log::verbose("ServerLobby", "New player.");
} // connectionRequested
//-----------------------------------------------------------------------------
void ServerLobby::updatePlayerList()
{
if (m_state.load() != ACCEPTING_CLIENTS)
return;
auto all_profiles = STKHost::get()->getAllPlayerProfiles();
NetworkString* pl = getNetworkString();
pl->setSynchronous(true);
pl->addUInt8(LE_UPDATE_PLAYER_LIST).addUInt8((uint8_t)all_profiles.size());
for (auto profile : all_profiles)
{
pl->addUInt32(profile->getHostId()).addUInt32(profile->getOnlineID())
.encodeString(profile->getName());
uint8_t server_owner = 0;
if (m_server_owner.lock() == profile->getPeer())
server_owner = 1;
pl->addUInt8(server_owner);
}
sendMessageToPeersChangingToken(pl);
delete pl;
} // updatePlayerList
//-----------------------------------------------------------------------------
void ServerLobby::updateServerOwner()
{
if (m_state.load() < ACCEPTING_CLIENTS ||
m_state.load() > RESULT_DISPLAY)
return;
if (!m_server_owner.expired())
return;
auto peers = STKHost::get()->getPeers();
if (peers.empty())
return;
std::sort(peers.begin(), peers.end(), [](const std::shared_ptr<STKPeer> a,
const std::shared_ptr<STKPeer> b)->bool
{
return a->getHostId() < b->getHostId();
});
std::shared_ptr<STKPeer> owner;
std::lock_guard<std::mutex> lock(m_connection_mutex);
// Make sure no one access the weak pointer or adding player to peers
for (auto peer: peers)
{
// Only 127.0.0.1 can be server owner in case of graphics-client-server
if (peer->hasPlayerProfiles() &&
(NetworkConfig::get()->getServerIdFile().empty() ||
peer->getAddress().getIP() == 0x7f000001))
{
owner = peer;
break;
}
}
if (owner)
{
NetworkString* ns = getNetworkString();
ns->addUInt8(LE_AUTHORISED);
owner->sendPacket(ns);
delete ns;
m_server_owner = owner;
updatePlayerList();
}
} // updateServerOwner
//-----------------------------------------------------------------------------
/*! \brief Called when a player asks to select a kart.
* \param event : Event providing the information.
*

View File

@ -6,9 +6,12 @@
#include "utils/synchronised.hpp"
#include <atomic>
#include <memory>
#include <mutex>
#include <set>
class STKPeer;
class ServerLobby : public LobbyProtocol
{
public:
@ -31,10 +34,13 @@ public:
private:
std::atomic<ServerState> m_state;
/** Hold the next connected peer for server owner if current one expired
* (disconnected). */
std::weak_ptr<STKPeer> m_server_owner;
/** Available karts and tracks for all clients, this will be initialized
* with data in server first. */
Synchronised<std::pair<std::set<std::string>,
std::set<std::string> > > m_available_kts;
std::pair<std::set<std::string>, std::set<std::string> > m_available_kts;
/** Next id to assign to a peer. */
Synchronised<int> m_next_player_id;
@ -58,6 +64,8 @@ private:
bool m_selection_enabled;
bool m_has_created_server_id_file;
/** It indicates if this server is registered with the stk server. */
std::atomic_bool m_server_registered;
@ -89,6 +97,9 @@ private:
void startedRaceOnClient(Event *event);
void unregisterServer();
void createServerIdFile();
void updatePlayerList();
void updateServerOwner();
public:
ServerLobby();
virtual ~ServerLobby();

View File

@ -34,9 +34,9 @@ enum SoccerTeam
};
/** Game difficulty per player. */
enum PerPlayerDifficulty
enum PerPlayerDifficulty : uint8_t
{
PLAYER_DIFFICULTY_NORMAL,
PLAYER_DIFFICULTY_NORMAL = 0,
PLAYER_DIFFICULTY_HANDICAP,
PLAYER_DIFFICULTY_COUNT
};
@ -51,7 +51,7 @@ class RemoteKartInfo
SoccerTeam m_soccer_team;
bool m_network_player;
PerPlayerDifficulty m_difficulty;
float m_default_kart_color;
public:
RemoteKartInfo(int player_id, const std::string& kart_name,
const irr::core::stringw& user_name, int host_id,
@ -75,6 +75,7 @@ public:
void setGlobalPlayerId(int id) { m_global_player_id = id; }
void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; }
void setNetworkPlayer(bool value) { m_network_player = value; }
void setDefaultKartColor(float value) { m_default_kart_color = value; }
void setPerPlayerDifficulty(PerPlayerDifficulty value)
{ m_difficulty = value; }
int getHostId() const { return m_host_id; }
@ -85,6 +86,7 @@ public:
const irr::core::stringw& getPlayerName() const { return m_user_name; }
SoccerTeam getSoccerTeam() const { return m_soccer_team; }
PerPlayerDifficulty getDifficulty() const { return m_difficulty; }
float getDefaultKartColor() const { return m_default_kart_color; }
bool operator<(const RemoteKartInfo& other) const
{

View File

@ -262,7 +262,6 @@ void STKHost::create(std::shared_ptr<Server> server, SeparateProcess* p)
*/
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
// server is made.
m_host_id = 0;
@ -291,16 +290,14 @@ STKHost::STKHost(std::shared_ptr<Server> server)
STKHost::STKHost(const irr::core::stringw &server_name)
{
init();
// The host id will be increased whenever a new peer is added, so the
// first client will have host id 1 (host id 0 is the server).
m_next_unique_host_id = 0;
m_host_id = 0; // indicates a server host.
ENetAddress addr;
addr.host = STKHost::HOST_ANY;
addr.port = NetworkConfig::get()->getServerPort();
m_network = new Network(NetworkConfig::get()->getMaxPlayers(),
// Reserver 1 peer to handle full server message
m_network = new Network(NetworkConfig::get()->getMaxPlayers() + 1,
/*channel_limit*/2,
/*max_in_bandwidth*/0,
/*max_out_bandwidth*/ 0, &addr,
@ -320,6 +317,7 @@ STKHost::STKHost(const irr::core::stringw &server_name)
void STKHost::init()
{
m_shutdown = false;
m_authorised = false;
m_network = NULL;
m_game_setup = NULL;
m_exit_timeout.store(std::numeric_limits<double>::max());
@ -627,13 +625,14 @@ GameSetup* STKHost::setupNewGame()
void STKHost::disconnectAllPeers(bool timeout_waiting)
{
std::lock_guard<std::mutex> lock(m_peers_mutex);
if (!m_peers.empty())
if (!m_peers.empty() && timeout_waiting)
{
for (auto peer : m_peers)
peer.second->disconnect();
// Wait for at most 2 seconds for disconnect event to be generated
if (timeout_waiting)
m_exit_timeout.store(StkTime::getRealTime() + 2.0);
m_peers.clear();
m_exit_timeout.store(StkTime::getRealTime() + 2.0);
}
m_peers.clear();
} // disconnectAllPeers
//-----------------------------------------------------------------------------
@ -694,23 +693,6 @@ void STKHost::stopListening()
m_listening_thread.join();
} // stopListening
// ----------------------------------------------------------------------------
/** Returns true if this client instance is allowed to control the server.
* A client can authorise itself by providing the server's password. It is
* then allowed to control the server (e.g. start kart selection).
* The information if this client was authorised by the server is actually
* stored in the peer (which is the server peer on a client).
*/
bool STKHost::isAuthorisedToControl() const
{
assert(NetworkConfig::get()->isClient());
// If we are not properly connected (i.e. only enet connection, but not
// stk logic), no peer is authorised.
if(m_peers.size()==0)
return false;
return m_peers.begin()->second->isAuthorised();
} // isAuthorisedToControl
// ----------------------------------------------------------------------------
/** \brief Thread function checking if data is received.
* This function tries to get data from network low-level functions as
@ -767,6 +749,14 @@ void STKHost::mainLoop()
case ECT_DISCONNECT:
enet_peer_disconnect(std::get<0>(p), std::get<2>(p));
break;
case ECT_RESET:
// Flush enet before reset (so previous command is send)
enet_host_flush(host);
enet_peer_reset(std::get<0>(p));
// Remove the stk peer of it
std::lock_guard<std::mutex> lock(m_peers_mutex);
m_peers.erase(std::get<0>(p));
break;
}
}
@ -778,8 +768,8 @@ void STKHost::mainLoop()
Event* stk_event = NULL;
if (event.type == ENET_EVENT_TYPE_CONNECT)
{
auto stk_peer =
std::make_shared<STKPeer>(event.peer, this);
auto stk_peer = std::make_shared<STKPeer>
(event.peer, this, m_next_unique_host_id++);
std::unique_lock<std::mutex> lock(m_peers_mutex);
m_peers[event.peer] = stk_peer;
lock.unlock();
@ -1026,3 +1016,30 @@ void STKHost::sendToServer(NetworkString *data, bool reliable)
assert(NetworkConfig::get()->isClient());
m_peers.begin()->second->sendPacket(data, reliable);
} // sendToServer
//-----------------------------------------------------------------------------
std::vector<std::shared_ptr<NetworkPlayerProfile> >
STKHost::getAllPlayerProfiles() const
{
std::vector<std::shared_ptr<NetworkPlayerProfile> > p;
std::unique_lock<std::mutex> lock(m_peers_mutex);
for (auto peer : m_peers)
{
auto peer_profile = peer.second->getPlayerProfiles();
p.insert(p.end(), peer_profile.begin(), peer_profile.end());
}
lock.unlock();
return p;
} // getAllPlayerProfiles
//-----------------------------------------------------------------------------
std::shared_ptr<STKPeer> STKHost::findPeerByHostId(uint32_t id) const
{
std::lock_guard<std::mutex> lock(m_peers_mutex);
auto ret = std::find_if(m_peers.begin(), m_peers.end(),
[id](const std::pair<ENetPeer*, std::shared_ptr<STKPeer> >& p)
{
return p.second->getHostId() == id;
});
return ret != m_peers.end() ? ret->second : nullptr;
} // findPeerByHostId

View File

@ -50,7 +50,8 @@ class SeparateProcess;
enum ENetCommandType : unsigned int
{
ECT_SEND_PACKET = 0,
ECT_DISCONNECT = 1
ECT_DISCONNECT = 1,
ECT_RESET = 2
};
class STKHost
@ -80,7 +81,7 @@ private:
std::thread m_network_console;
/** Make sure the removing or adding a peer is thread-safe. */
std::mutex m_peers_mutex;
mutable std::mutex m_peers_mutex;
/** Let (atm enet_peer_send and enet_peer_disconnect) run in the listening
* thread. */
@ -98,10 +99,10 @@ private:
* getPeer()), but not decreased whena host (=peer) disconnects. This
* results in a unique host id for each host, even when a host should
* disconnect and then reconnect. */
int m_next_unique_host_id;
uint32_t m_next_unique_host_id = 0;
/** Host id of this host. */
uint8_t m_host_id;
uint32_t m_host_id = 0;
/** Stores data about the online game to play. */
GameSetup* m_game_setup;
@ -113,6 +114,9 @@ private:
* triggers a shutdown of the STKHost (and the Protocolmanager). */
std::atomic_bool m_shutdown;
/** True if this local host is authorised to control a server. */
std::atomic_bool m_authorised;
/** Use as a timeout to waiting a disconnect event when exiting. */
std::atomic<double> m_exit_timeout;
@ -142,7 +146,6 @@ public:
* a crash in release mode on windows (see #1529). */
static bool m_enable_console;
/** Creates the STKHost. It takes all confifguration parameters from
* NetworkConfig. This STKHost can either be a client or a server.
*/
@ -199,7 +202,21 @@ public:
void shutdown();
//-------------------------------------------------------------------------
void sendPacketToAllPeers(NetworkString *data, bool reliable = true);
//-------------------------------------------------------------------------
// ------------------------------------------------------------------------
/** Returns true if this client instance is allowed to control the server.
* It will auto transfer ownership if previous server owner disconnected.
*/
bool isAuthorisedToControl() const { return m_authorised.load(); }
// ------------------------------------------------------------------------
/** Sets if this local host is authorised to control the server. */
void setAuthorisedToControl(bool authorised)
{ m_authorised.store(authorised); }
// ------------------------------------------------------------------------
std::vector<std::shared_ptr<NetworkPlayerProfile> >
getAllPlayerProfiles() const;
// ------------------------------------------------------------------------
std::shared_ptr<STKPeer> findPeerByHostId(uint32_t id) const;
// ------------------------------------------------------------------------
void sendPacketExcept(STKPeer* peer,
NetworkString *data,
bool reliable = true);
@ -213,8 +230,6 @@ public:
std::shared_ptr<STKPeer> getServerPeerForClient() const;
std::vector<NetworkPlayerProfile*> getMyPlayerProfiles();
void setErrorMessage(const irr::core::stringw &message);
bool isAuthorisedToControl() const;
//-------------------------------------------------------------------------
void addEnetCommand(ENetPeer* peer, ENetPacket* packet, uint32_t i,
ENetCommandType ect)
{
@ -247,7 +262,7 @@ public:
} // sendRawPacket
// ------------------------------------------------------------------------
/** Returns a copied list of peers. */
std::vector<std::shared_ptr<STKPeer> > getPeers()
std::vector<std::shared_ptr<STKPeer> > getPeers() const
{
std::lock_guard<std::mutex> lock(m_peers_mutex);
std::vector<std::shared_ptr<STKPeer> > peers;
@ -266,17 +281,17 @@ public:
}
// ------------------------------------------------------------------------
/** Returns the number of currently connected peers. */
unsigned int getPeerCount()
unsigned int getPeerCount() const
{
std::lock_guard<std::mutex> lock(m_peers_mutex);
return m_peers.size();
}
// ------------------------------------------------------------------------
/** Sets the global host id of this host. */
void setMyHostId(uint8_t my_host_id) { m_host_id = my_host_id; }
/** Sets the global host id of this host (client use). */
void setMyHostId(uint32_t my_host_id) { m_host_id = my_host_id; }
// ------------------------------------------------------------------------
/** Returns the host id of this host. */
uint8_t getMyHostId() const { return m_host_id; }
uint32_t getMyHostId() const { return m_host_id; }
// ------------------------------------------------------------------------
void sendToServer(NetworkString *data, bool reliable = true);
// ------------------------------------------------------------------------

View File

@ -29,27 +29,24 @@
/** Constructor for an empty peer.
*/
STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host)
STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id)
: m_peer_address(enet_peer->address), m_host(host)
{
m_enet_peer = enet_peer;
m_is_authorised = false;
m_client_server_token = 0;
m_host_id = 0;
m_host_id = host_id;
m_token_set = false;
} // STKPeer
//-----------------------------------------------------------------------------
/** Destructor.
*/
STKPeer::~STKPeer()
void STKPeer::disconnect()
{
TransportAddress a(m_enet_peer->address);
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
a != m_peer_address)
return;
m_host->addEnetCommand(m_enet_peer, NULL, PDI_NORMAL, ECT_DISCONNECT);
} // ~STKPeer
} // disconnect
//-----------------------------------------------------------------------------
/** Kick this peer (used by server).
@ -63,6 +60,18 @@ void STKPeer::kick()
m_host->addEnetCommand(m_enet_peer, NULL, PDI_KICK, ECT_DISCONNECT);
} // kick
//-----------------------------------------------------------------------------
/** Forcefully disconnects a peer (used by server).
*/
void STKPeer::reset()
{
TransportAddress a(m_enet_peer->address);
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
a != m_peer_address)
return;
m_host->addEnetCommand(m_enet_peer, NULL, 0, ECT_RESET);
} // reset
//-----------------------------------------------------------------------------
/** Sends a packet to this host.
* \param data The data to send.
@ -111,14 +120,3 @@ bool STKPeer::isSamePeer(const ENetPeer* peer) const
{
return peer==m_enet_peer;
} // isSamePeer
//-----------------------------------------------------------------------------
/** Returns the list of all player profiles connected to this peer. Note that
* this function is somewhat expensive (it loops over all network profiles
* to find the ones with the same host id as this peer.
*/
std::vector<NetworkPlayerProfile*> STKPeer::getAllPlayerProfiles()
{
return m_host->getGameSetup()->getAllPlayersOnHost(getHostId());
} // getAllPlayerProfiles

View File

@ -29,6 +29,7 @@
#include <enet/enet.h>
#include <memory>
#include <vector>
class NetworkPlayerProfile;
@ -62,26 +63,38 @@ protected:
/** Host id of this peer. */
int m_host_id;
/** True if this peer is authorised to control a server. */
bool m_is_authorised;
TransportAddress m_peer_address;
STKHost* m_host;
std::vector<std::shared_ptr<NetworkPlayerProfile> > m_players;
public:
STKPeer(ENetPeer *enet_peer, STKHost* host);
~STKPeer();
STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id);
~STKPeer() {}
// ------------------------------------------------------------------------
void sendPacket(NetworkString *data, bool reliable = true);
// ------------------------------------------------------------------------
void disconnect();
// ------------------------------------------------------------------------
void kick();
// ------------------------------------------------------------------------
void reset();
// ------------------------------------------------------------------------
bool isConnected() const;
const TransportAddress& getAddress() const { return m_peer_address; }
bool isSamePeer(const STKPeer* peer) const;
bool isSamePeer(const ENetPeer* peer) const;
std::vector<NetworkPlayerProfile*> getAllPlayerProfiles();
// ------------------------------------------------------------------------
std::vector<std::shared_ptr<NetworkPlayerProfile> >
getPlayerProfiles() const { return m_players; }
// ------------------------------------------------------------------------
bool hasPlayerProfiles() const { return !m_players.empty(); }
// ------------------------------------------------------------------------
void cleanPlayerProfiles() { m_players.clear(); }
// ------------------------------------------------------------------------
void addPlayer(std::shared_ptr<NetworkPlayerProfile> p)
{ m_players.push_back(p); }
// ------------------------------------------------------------------------
/** Sets the token for this client. */
void setClientServerToken(const uint32_t& token)
@ -90,7 +103,11 @@ public:
m_token_set = true;
} // setClientServerToken
// ------------------------------------------------------------------------
void unsetClientServerToken() { m_token_set = false; }
void unsetClientServerToken()
{
m_token_set = false;
m_client_server_token = 0;
}
// ------------------------------------------------------------------------
/** Returns the token of this client. */
uint32_t getClientServerToken() const { return m_client_server_token; }
@ -98,21 +115,9 @@ public:
/** Returns if the token for this client is known. */
bool isClientServerTokenSet() const { return m_token_set; }
// ------------------------------------------------------------------------
/** Sets the host if of this peer. */
void setHostId(int host_id) { m_host_id = host_id; }
// ------------------------------------------------------------------------
/** Returns the host id of this peer. */
int getHostId() const { return m_host_id; }
// ------------------------------------------------------------------------
/** Sets if this peer is authorised to control the server. */
void setAuthorised(bool authorised) { m_is_authorised = authorised; }
// ------------------------------------------------------------------------
/** Returns if this peer is authorised to control the server. The server
* uses this to check if a peer is allowed certain commands; and a client
* uses this function (in which case this peer is actually the server
* peer) to see if this client is allowed certain command (i.e. to
* display additional GUI elements). */
bool isAuthorised() const { return m_is_authorised; }
uint32_t getHostId() const { return m_host_id; }
}; // STKPeer
#endif // STK_PEER_HPP

View File

@ -96,10 +96,6 @@ namespace Online
return m_online_state;
} // getOnlineState
// ----------------------------------------------------------------
/** Returns a pointer to the profile associated with the current user. */
OnlineProfile* getProfile() const { return m_profile; }
// ----------------------------------------------------------------
/** Returns the session token of the signed in user. */
const std::string& getToken() const { return m_token; }
@ -113,6 +109,9 @@ namespace Online
OnlinePlayerProfile(const core::stringw &name, bool is_guest = false);
virtual ~OnlinePlayerProfile() {}
// ----------------------------------------------------------------
/** Returns a pointer to the profile associated with the current user. */
OnlineProfile* getProfile() const { return m_profile; }
// ----------------------------------------------------------------
}; // class OnlinePlayerProfile
} // namespace Online
#endif // HEADER_CURRENT_ONLINE_USER_HPP

View File

@ -34,7 +34,6 @@
#include "input/input_manager.hpp"
#include "io/file_manager.hpp"
#include "network/network_config.hpp"
#include "network/network_player_profile.hpp"
#include "network/protocols/client_lobby.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/server.hpp"
@ -262,16 +261,25 @@ void NetworkingLobby::onDialogClose()
} // onDialogClose()
// ----------------------------------------------------------------------------
void NetworkingLobby::addPlayer(NetworkPlayerProfile *profile)
void NetworkingLobby::addPlayer(const std::tuple<uint32_t, uint32_t,
core::stringw, bool>& p)
{
// In GUI-less server this function will be called without proper
// initialisation
if(m_player_list)
m_player_list->addItem(StringUtils::toString(profile->getGlobalPlayerId()),
profile->getName());
if (m_player_list)
{
const std::string internal_name =
StringUtils::toString(std::get<0>(p)) + "_" +
StringUtils::toString(std::get<1>(p));
m_player_list->addItem(internal_name, std::get<2>(p));
if (std::get<3>(p))
m_player_list->markItemRed(internal_name, true);
}
} // addPlayer
// ----------------------------------------------------------------------------
void NetworkingLobby::removePlayer(NetworkPlayerProfile *profile)
void NetworkingLobby::cleanPlayers()
{
} // removePlayer
if (m_player_list)
m_player_list->clear();
} // cleanPlayers

View File

@ -20,6 +20,7 @@
#include "guiengine/screen.hpp"
#include <memory>
#include <tuple>
class Server;
@ -32,8 +33,6 @@ namespace GUIEngine
class TextBoxWidget;
}
class NetworkPlayerProfile;
/**
* \brief Handles the main menu
* \ingroup states_screens
@ -91,8 +90,9 @@ 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);
void addPlayer(const std::tuple<uint32_t/*host id*/, uint32_t/*online id*/,
core::stringw/*player name*/, bool/*is server owner*/>& p);
void cleanPlayers();
}; // class NetworkingLobby
#endif