Initial work on lobby redesign
This commit is contained in:
parent
4dea283965
commit
3bbec8aa27
@ -25,13 +25,13 @@
|
|||||||
#include "network/race_config.hpp"
|
#include "network/race_config.hpp"
|
||||||
#include "network/remote_kart_info.hpp"
|
#include "network/remote_kart_info.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Online { class OnlineProfile; }
|
|
||||||
class NetworkPlayerProfile;
|
class NetworkPlayerProfile;
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
/*! \class GameSetup
|
/*! \class GameSetup
|
||||||
* \brief Used to store the needed data about the players that join a game.
|
* \brief Used to store the needed data about the players that join a game.
|
||||||
|
@ -19,31 +19,6 @@
|
|||||||
#include "network/network_player_profile.hpp"
|
#include "network/network_player_profile.hpp"
|
||||||
|
|
||||||
#include "network/stk_host.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
|
/** 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
|
* is done by comparing the host id of this player with the host id of this
|
||||||
|
@ -26,10 +26,11 @@
|
|||||||
#include "utils/types.hpp"
|
#include "utils/types.hpp"
|
||||||
|
|
||||||
#include "irrString.h"
|
#include "irrString.h"
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
namespace Online { class OnlineProfile; }
|
#include <tuple>
|
||||||
|
|
||||||
|
class STKPeer;
|
||||||
|
|
||||||
/*! \class NetworkPlayerProfile
|
/*! \class NetworkPlayerProfile
|
||||||
* \brief Contains the profile of a player.
|
* \brief Contains the profile of a player.
|
||||||
@ -37,31 +38,51 @@ namespace Online { class OnlineProfile; }
|
|||||||
class NetworkPlayerProfile
|
class NetworkPlayerProfile
|
||||||
{
|
{
|
||||||
private:
|
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
|
/** 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
|
* by the server (and it might not be the index of this player in the
|
||||||
* peer list. */
|
* peer list. */
|
||||||
uint8_t m_global_player_id;
|
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). */
|
/** The kart id in the World class (pointer to AbstractKart). */
|
||||||
uint8_t m_world_kart_id;
|
uint8_t m_world_kart_id;
|
||||||
|
|
||||||
/** Per player difficulty. */
|
|
||||||
PerPlayerDifficulty m_per_player_difficulty;
|
|
||||||
public:
|
public:
|
||||||
NetworkPlayerProfile(const irr::core::stringw &name,
|
NetworkPlayerProfile(std::shared_ptr<STKPeer> peer,
|
||||||
int global_player_id, int host_id);
|
const irr::core::stringw &name, uint32_t host_id,
|
||||||
~NetworkPlayerProfile();
|
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;
|
bool isLocalPlayer() const;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets the global player id of this player. */
|
/** Sets the global player id of this player. */
|
||||||
void setGlobalPlayerId(int player_id) { m_global_player_id = player_id; }
|
void setGlobalPlayerId(int player_id) { m_global_player_id = player_id; }
|
||||||
@ -93,6 +114,15 @@ public:
|
|||||||
/** Returns the name of this player. */
|
/** Returns the name of this player. */
|
||||||
const irr::core::stringw& getName() const { return m_player_name; }
|
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
|
}; // class NetworkPlayerProfile
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "config/player_manager.hpp"
|
#include "config/player_manager.hpp"
|
||||||
#include "karts/kart_properties_manager.hpp"
|
#include "karts/kart_properties_manager.hpp"
|
||||||
|
#include "guiengine/message_queue.hpp"
|
||||||
#include "modes/world_with_rank.hpp"
|
#include "modes/world_with_rank.hpp"
|
||||||
#include "network/event.hpp"
|
#include "network/event.hpp"
|
||||||
#include "network/network_config.hpp"
|
#include "network/network_config.hpp"
|
||||||
@ -29,6 +30,7 @@
|
|||||||
#include "network/race_event_manager.hpp"
|
#include "network/race_event_manager.hpp"
|
||||||
#include "network/stk_host.hpp"
|
#include "network/stk_host.hpp"
|
||||||
#include "network/stk_peer.hpp"
|
#include "network/stk_peer.hpp"
|
||||||
|
#include "online/online_player_profile.hpp"
|
||||||
#include "online/online_profile.hpp"
|
#include "online/online_profile.hpp"
|
||||||
#include "states_screens/networking_lobby.hpp"
|
#include "states_screens/networking_lobby.hpp"
|
||||||
#include "states_screens/network_kart_selection.hpp"
|
#include "states_screens/network_kart_selection.hpp"
|
||||||
@ -201,13 +203,6 @@ void ClientLobby::voteLaps(uint8_t player_id, uint8_t laps,
|
|||||||
delete request;
|
delete request;
|
||||||
} // voteLaps
|
} // 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
|
/** 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
|
* 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_LOAD_WORLD: loadWorld(); break;
|
||||||
case LE_RACE_FINISHED: raceFinished(event); break;
|
case LE_RACE_FINISHED: raceFinished(event); break;
|
||||||
case LE_EXIT_RESULT: exitResultScreen(event); break;
|
case LE_EXIT_RESULT: exitResultScreen(event); break;
|
||||||
|
case LE_UPDATE_PLAYER_LIST: updatePlayerList(event); break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
@ -261,7 +257,6 @@ bool ClientLobby::notifyEventAsynchronous(Event* event)
|
|||||||
message_type);
|
message_type);
|
||||||
switch(message_type)
|
switch(message_type)
|
||||||
{
|
{
|
||||||
case LE_NEW_PLAYER_CONNECTED: newPlayer(event); break;
|
|
||||||
case LE_PLAYER_DISCONNECTED : disconnectedPlayer(event); break;
|
case LE_PLAYER_DISCONNECTED : disconnectedPlayer(event); break;
|
||||||
case LE_START_RACE: startGame(event); break;
|
case LE_START_RACE: startGame(event); break;
|
||||||
case LE_CONNECTION_REFUSED: connectionRefused(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_TRACK: playerTrackVote(event); break;
|
||||||
case LE_VOTE_REVERSE: playerReversedVote(event); break;
|
case LE_VOTE_REVERSE: playerReversedVote(event); break;
|
||||||
case LE_VOTE_LAPS: playerLapsVote(event); break;
|
case LE_VOTE_LAPS: playerLapsVote(event); break;
|
||||||
|
case LE_AUTHORISED: becomingServerOwner(); break;
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -321,20 +317,31 @@ void ClientLobby::update(float dt)
|
|||||||
break;
|
break;
|
||||||
case LINKED:
|
case LINKED:
|
||||||
{
|
{
|
||||||
core::stringw name;
|
// atm assume only 1 local player (no split screen yet)
|
||||||
if(PlayerManager::getCurrentOnlineState()==PlayerProfile::OS_SIGNED_IN)
|
NetworkString *ns = getNetworkString();
|
||||||
name = PlayerManager::getCurrentOnlineUserName();
|
ns->addUInt8(LE_CONNECTION_REQUESTED)
|
||||||
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());
|
.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_k = kart_properties_manager->getAllAvailableKarts();
|
||||||
auto all_t = track_manager->getAllTrackIdentifiers();
|
auto all_t = track_manager->getAllTrackIdentifiers();
|
||||||
if (all_k.size() >= 65536)
|
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
|
/*! \brief Called when a new player is disconnected
|
||||||
* \param event : Event providing the information.
|
* \param event : Event providing the information.
|
||||||
*
|
*
|
||||||
@ -447,95 +411,67 @@ void ClientLobby::disconnectedPlayer(Event* event)
|
|||||||
if (!checkDataSize(event, 1)) return;
|
if (!checkDataSize(event, 1)) return;
|
||||||
|
|
||||||
NetworkString &data = event->data();
|
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 =
|
core::stringw player_name;
|
||||||
m_game_setup->getProfile(data.getUInt8());
|
data.decodeStringW(&player_name);
|
||||||
if (m_game_setup->removePlayer(profile))
|
core::stringw msg = _("%s disconnected.", player_name);
|
||||||
{
|
// Use the friend icon to avoid an error-like message
|
||||||
Log::info("ClientLobby",
|
MessageQueue::add(MessageQueue::MT_FRIEND, msg);
|
||||||
"Player %d removed successfully.",
|
|
||||||
profile->getGlobalPlayerId());
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Log::error("ClientLobby",
|
|
||||||
"The disconnected peer wasn't known.");
|
|
||||||
}
|
|
||||||
} // while
|
|
||||||
|
|
||||||
} // disconnectedPlayer
|
} // disconnectedPlayer
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*! \brief Called when the server accepts the connection.
|
/*! \brief Called when the server accepts the connection.
|
||||||
* \param event : Event providing the information.
|
* \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)
|
void ClientLobby::connectionAccepted(Event* event)
|
||||||
{
|
{
|
||||||
// At least 3 bytes should remain now
|
// At least 4 byte should remain now
|
||||||
if(!checkDataSize(event, 3)) return;
|
if (!checkDataSize(event, 4)) return;
|
||||||
|
|
||||||
NetworkString &data = event->data();
|
NetworkString &data = event->data();
|
||||||
STKPeer* peer = event->getPeer();
|
STKPeer* peer = event->getPeer();
|
||||||
|
|
||||||
// Accepted
|
// Accepted
|
||||||
// ========
|
// ========
|
||||||
Log::info("ClientLobby",
|
Log::info("ClientLobby", "The server accepted the connection.");
|
||||||
"The server accepted the connection.");
|
|
||||||
|
|
||||||
// self profile
|
STKHost::get()->setMyHostId(data.getUInt32());
|
||||||
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);
|
|
||||||
m_game_setup->setNumLocalPlayers(1);
|
m_game_setup->setNumLocalPlayers(1);
|
||||||
// connection token
|
// connection token
|
||||||
uint32_t token = data.getToken();
|
uint32_t token = data.getToken();
|
||||||
peer->setClientServerToken(token);
|
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;
|
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
|
// Send a message to the server to start
|
||||||
NetworkString start(PROTOCOL_LOBBY_ROOM);
|
NetworkString start(PROTOCOL_LOBBY_ROOM);
|
||||||
@ -543,8 +479,7 @@ void ClientLobby::connectionAccepted(Event* event)
|
|||||||
start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN);
|
start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN);
|
||||||
STKHost::get()->sendToServer(&start, true);
|
STKHost::get()->sendToServer(&start, true);
|
||||||
}
|
}
|
||||||
|
} // becomingServerOwner
|
||||||
} // connectionAccepted
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -562,26 +497,31 @@ void ClientLobby::connectionRefused(Event* event)
|
|||||||
{
|
{
|
||||||
if (!checkDataSize(event, 1)) return;
|
if (!checkDataSize(event, 1)) return;
|
||||||
const NetworkString &data = event->data();
|
const NetworkString &data = event->data();
|
||||||
|
switch ((RejectReason)data.getUInt8()) // the second byte
|
||||||
switch (data.getUInt8()) // the second byte
|
|
||||||
{
|
{
|
||||||
case 0:
|
case RR_BUSY:
|
||||||
Log::info("ClientLobby",
|
STKHost::get()->setErrorMessage(
|
||||||
"Connection refused : too many players.");
|
_("Connection refused: Server is busy."));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case RR_BANNED:
|
||||||
Log::info("ClientLobby", "Connection refused : banned.");
|
STKHost::get()->setErrorMessage(
|
||||||
|
_("Connection refused: You are banned from the server."));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case RR_INCORRECT_PASSWORD:
|
||||||
Log::info("ClientLobby", "Client busy.");
|
STKHost::get()->setErrorMessage(
|
||||||
|
_("Connection refused: Server password is incorrect."));
|
||||||
break;
|
break;
|
||||||
case 3:
|
case RR_INCOMPATIBLE_DATA:
|
||||||
Log::info("ClientLobby", "Having incompatible karts / tracks.");
|
STKHost::get()->setErrorMessage(
|
||||||
|
_("Connection refused: Game data is incompatible."));
|
||||||
break;
|
break;
|
||||||
default:
|
case RR_TOO_MANY_PLAYERS:
|
||||||
Log::info("ClientLobby", "Connection refused.");
|
STKHost::get()->setErrorMessage(
|
||||||
|
_("Connection refused: Server is full."));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
STKHost::get()->disconnectAllPeers(false/*timeout_waiting*/);
|
||||||
|
STKHost::get()->requestShutdown();
|
||||||
} // connectionRefused
|
} // connectionRefused
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
class ClientLobby : public LobbyProtocol
|
class ClientLobby : public LobbyProtocol
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
void newPlayer(Event* event);
|
|
||||||
void disconnectedPlayer(Event* event);
|
void disconnectedPlayer(Event* event);
|
||||||
void connectionAccepted(Event* event); //!< Callback function on connection acceptation
|
void connectionAccepted(Event* event); //!< Callback function on connection acceptation
|
||||||
void connectionRefused(Event* event); //!< Callback function on connection refusal
|
void connectionRefused(Event* event); //!< Callback function on connection refusal
|
||||||
@ -26,6 +25,8 @@ private:
|
|||||||
void playerTrackVote(Event* event);
|
void playerTrackVote(Event* event);
|
||||||
void playerReversedVote(Event* event);
|
void playerReversedVote(Event* event);
|
||||||
void playerLapsVote(Event* event);
|
void playerLapsVote(Event* event);
|
||||||
|
void updatePlayerList(Event* event);
|
||||||
|
void becomingServerOwner();
|
||||||
|
|
||||||
TransportAddress m_server_address;
|
TransportAddress m_server_address;
|
||||||
|
|
||||||
@ -65,7 +66,6 @@ public:
|
|||||||
void voteLaps(uint8_t player_id, uint8_t laps, uint8_t track_nb = 0);
|
void voteLaps(uint8_t player_id, uint8_t laps, uint8_t track_nb = 0);
|
||||||
void doneWithResults();
|
void doneWithResults();
|
||||||
void startingRaceNow();
|
void startingRaceNow();
|
||||||
void leave();
|
|
||||||
|
|
||||||
const std::set<std::string>& getAvailableKarts() const
|
const std::set<std::string>& getAvailableKarts() const
|
||||||
{ return m_available_karts; }
|
{ return m_available_karts; }
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
LE_KART_SELECTION_UPDATE, // inform client about kart selected
|
LE_KART_SELECTION_UPDATE, // inform client about kart selected
|
||||||
LE_REQUEST_BEGIN, // begin of kart selection
|
LE_REQUEST_BEGIN, // begin of kart selection
|
||||||
LE_KART_SELECTION_REFUSED, // Client not auth. to start 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_KART_SELECTION, // Player selected kart
|
||||||
LE_PLAYER_DISCONNECTED, // Client disconnected
|
LE_PLAYER_DISCONNECTED, // Client disconnected
|
||||||
LE_CLIENT_LOADED_WORLD, // Client finished loading world
|
LE_CLIENT_LOADED_WORLD, // Client finished loading world
|
||||||
@ -60,6 +60,18 @@ public:
|
|||||||
LE_VOTE_TRACK, // vote for a track
|
LE_VOTE_TRACK, // vote for a track
|
||||||
LE_VOTE_REVERSE, // vote if race in reverse
|
LE_VOTE_REVERSE, // vote if race in reverse
|
||||||
LE_VOTE_LAPS, // vote number of laps
|
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:
|
protected:
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "utils/random_generator.hpp"
|
#include "utils/random_generator.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
/** This is the central game setup protocol running in the server. It is
|
/** This is the central game setup protocol running in the server. It is
|
||||||
@ -84,18 +85,9 @@
|
|||||||
*/
|
*/
|
||||||
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
||||||
{
|
{
|
||||||
|
m_has_created_server_id_file = false;
|
||||||
setHandleDisconnections(true);
|
setHandleDisconnections(true);
|
||||||
m_state = SET_PUBLIC_ADDRESS;
|
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
|
} // ServerLobby
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -113,6 +105,16 @@ ServerLobby::~ServerLobby()
|
|||||||
|
|
||||||
void ServerLobby::setup()
|
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_server_registered = false;
|
||||||
m_game_setup = STKHost::get()->setupNewGame();
|
m_game_setup = STKHost::get()->setupNewGame();
|
||||||
m_game_setup->setNumLocalPlayers(0); // no local players on a server
|
m_game_setup->setNumLocalPlayers(0); // no local players on a server
|
||||||
@ -197,11 +199,12 @@ bool ServerLobby::notifyEventAsynchronous(Event* event)
|
|||||||
void ServerLobby::createServerIdFile()
|
void ServerLobby::createServerIdFile()
|
||||||
{
|
{
|
||||||
const std::string& sid = NetworkConfig::get()->getServerIdFile();
|
const std::string& sid = NetworkConfig::get()->getServerIdFile();
|
||||||
if (!sid.empty())
|
if (!sid.empty() && !m_has_created_server_id_file)
|
||||||
{
|
{
|
||||||
std::fstream fs;
|
std::fstream fs;
|
||||||
fs.open(sid, std::ios::out);
|
fs.open(sid, std::ios::out);
|
||||||
fs.close();
|
fs.close();
|
||||||
|
m_has_created_server_id_file = true;
|
||||||
}
|
}
|
||||||
} // createServerIdFile
|
} // createServerIdFile
|
||||||
|
|
||||||
@ -265,6 +268,7 @@ void ServerLobby::asynchronousUpdate()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // asynchronousUpdate
|
} // asynchronousUpdate
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -274,6 +278,9 @@ void ServerLobby::asynchronousUpdate()
|
|||||||
*/
|
*/
|
||||||
void ServerLobby::update(float dt)
|
void ServerLobby::update(float dt)
|
||||||
{
|
{
|
||||||
|
// Check if server owner has left
|
||||||
|
updateServerOwner();
|
||||||
|
|
||||||
switch (m_state.load())
|
switch (m_state.load())
|
||||||
{
|
{
|
||||||
case SET_PUBLIC_ADDRESS:
|
case SET_PUBLIC_ADDRESS:
|
||||||
@ -463,12 +470,6 @@ void ServerLobby::signalRaceStartToClients()
|
|||||||
void ServerLobby::startSelection(const Event *event)
|
void ServerLobby::startSelection(const Event *event)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
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)
|
if (m_state != ACCEPTING_CLIENTS)
|
||||||
{
|
{
|
||||||
@ -477,21 +478,28 @@ void ServerLobby::startSelection(const Event *event)
|
|||||||
m_state.load());
|
m_state.load());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(event && !event->getPeer()->isAuthorised())
|
if (event->getPeerSP() != m_server_owner.lock())
|
||||||
{
|
{
|
||||||
Log::warn("ServerLobby",
|
Log::warn("ServerLobby",
|
||||||
"Client %lx is not authorised to start selection.",
|
"Client %lx is not authorised to start selection.",
|
||||||
event->getPeer());
|
event->getPeer());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NetworkConfig::get()->isWAN())
|
||||||
|
{
|
||||||
|
assert(m_server_registered);
|
||||||
|
unregisterServer();
|
||||||
|
m_server_registered = false;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkString *ns = getNetworkString(1);
|
NetworkString *ns = getNetworkString(1);
|
||||||
// Start selection - must be synchronous since the receiver pushes
|
// Start selection - must be synchronous since the receiver pushes
|
||||||
// a new screen, which must be donefrom the main thread.
|
// a new screen, which must be donefrom the main thread.
|
||||||
ns->setSynchronous(true);
|
ns->setSynchronous(true);
|
||||||
ns->addUInt8(LE_START_SELECTION);
|
ns->addUInt8(LE_START_SELECTION);
|
||||||
m_available_kts.lock();
|
const auto& all_k = m_available_kts.first;
|
||||||
const auto& all_k = m_available_kts.getData().first;
|
const auto& all_t = m_available_kts.second;
|
||||||
const auto& all_t = m_available_kts.getData().second;
|
|
||||||
ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size());
|
ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size());
|
||||||
for (const std::string& kart : all_k)
|
for (const std::string& kart : all_k)
|
||||||
{
|
{
|
||||||
@ -501,7 +509,6 @@ void ServerLobby::startSelection(const Event *event)
|
|||||||
{
|
{
|
||||||
ns->encodeString(track);
|
ns->encodeString(track);
|
||||||
}
|
}
|
||||||
m_available_kts.unlock();
|
|
||||||
|
|
||||||
sendMessageToPeersChangingToken(ns, /*reliable*/true);
|
sendMessageToPeersChangingToken(ns, /*reliable*/true);
|
||||||
delete ns;
|
delete ns;
|
||||||
@ -625,23 +632,21 @@ void ServerLobby::checkIncomingConnectionRequests()
|
|||||||
*/
|
*/
|
||||||
void ServerLobby::clientDisconnected(Event* event)
|
void ServerLobby::clientDisconnected(Event* event)
|
||||||
{
|
{
|
||||||
std::vector<NetworkPlayerProfile*> players_on_host =
|
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
||||||
event->getPeer()->getAllPlayerProfiles();
|
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);
|
msg->addUInt8(LE_PLAYER_DISCONNECTED);
|
||||||
|
msg->addUInt8((uint8_t)players_on_peer.size());
|
||||||
for(unsigned int i=0; i<players_on_host.size(); i++)
|
for (auto p : players_on_peer)
|
||||||
{
|
{
|
||||||
msg->addUInt8(players_on_host[i]->getGlobalPlayerId());
|
msg->encodeString(p->getName());
|
||||||
Log::info("ServerLobby", "Player disconnected : id %d",
|
|
||||||
players_on_host[i]->getGlobalPlayerId());
|
|
||||||
m_game_setup->removePlayer(players_on_host[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessageToPeersChangingToken(msg, /*reliable*/true);
|
sendMessageToPeersChangingToken(msg, /*reliable*/true);
|
||||||
|
updatePlayerList();
|
||||||
delete msg;
|
delete msg;
|
||||||
|
|
||||||
} // clientDisconnected
|
} // clientDisconnected
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -659,34 +664,62 @@ void ServerLobby::clientDisconnected(Event* event)
|
|||||||
void ServerLobby::connectionRequested(Event* event)
|
void ServerLobby::connectionRequested(Event* event)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
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();
|
const NetworkString &data = event->data();
|
||||||
|
|
||||||
// can we add the player ?
|
// can we add the player ?
|
||||||
if (m_game_setup->getPlayerCount() >= NetworkConfig::get()->getMaxPlayers() ||
|
if (m_game_setup->getPlayerCount() >=
|
||||||
|
NetworkConfig::get()->getMaxPlayers() ||
|
||||||
m_state != ACCEPTING_CLIENTS)
|
m_state != ACCEPTING_CLIENTS)
|
||||||
{
|
{
|
||||||
NetworkString *message = getNetworkString(2);
|
NetworkString *message = getNetworkString(2);
|
||||||
// Len, error code: 2 = busy, 0 = too many players
|
|
||||||
message->addUInt8(LE_CONNECTION_REFUSED)
|
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->sendPacket(message);
|
||||||
|
peer->reset();
|
||||||
delete message;
|
delete message;
|
||||||
Log::verbose("ServerLobby", "Player refused");
|
Log::verbose("ServerLobby", "Player refused");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for password
|
||||||
|
std::string password;
|
||||||
|
data.decodeString(&password);
|
||||||
|
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.
|
// Connection accepted.
|
||||||
// ====================
|
// ====================
|
||||||
|
uint8_t player_count = data.getUInt8();
|
||||||
|
for (unsigned i = 0; i < player_count; i++)
|
||||||
|
{
|
||||||
std::string name_u8;
|
std::string name_u8;
|
||||||
data.decodeString(&name_u8);
|
data.decodeString(&name_u8);
|
||||||
core::stringw name = StringUtils::utf8ToWide(name_u8);
|
core::stringw name = StringUtils::utf8ToWide(name_u8);
|
||||||
std::string password;
|
float default_kart_color = data.getFloat();
|
||||||
data.decodeString(&password);
|
uint32_t online_id = data.getUInt32();
|
||||||
bool is_authorised = (password==NetworkConfig::get()->getPassword());
|
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;
|
std::set<std::string> client_karts, client_tracks;
|
||||||
const unsigned kart_num = data.getUInt16();
|
const unsigned kart_num = data.getUInt16();
|
||||||
const unsigned track_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
|
// so that in the end the server has a list of all karts/tracks available
|
||||||
// on all clients
|
// on all clients
|
||||||
std::set<std::string> karts_erase, tracks_erase;
|
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())
|
if (client_karts.find(server_kart) == client_karts.end())
|
||||||
{
|
{
|
||||||
karts_erase.insert(server_kart);
|
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())
|
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
|
// Drop this player if he doesn't have at least 1 kart / track the same
|
||||||
// from server
|
// from server
|
||||||
if (karts_erase.size() == m_available_kts.getData().first.size() ||
|
if (karts_erase.size() == m_available_kts.first.size() ||
|
||||||
tracks_erase.size() == m_available_kts.getData().second.size())
|
tracks_erase.size() == m_available_kts.second.size())
|
||||||
{
|
{
|
||||||
NetworkString *message = getNetworkString(2);
|
NetworkString *message = getNetworkString(2);
|
||||||
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(3);
|
message->addUInt8(LE_CONNECTION_REFUSED)
|
||||||
|
.addUInt8(RR_INCOMPATIBLE_DATA);
|
||||||
peer->sendPacket(message);
|
peer->sendPacket(message);
|
||||||
|
peer->reset();
|
||||||
delete message;
|
delete message;
|
||||||
Log::verbose("ServerLobby", "Player has incompatible karts / tracks");
|
Log::verbose("ServerLobby", "Player has incompatible karts / tracks");
|
||||||
m_available_kts.unlock();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const std::string& kart_erase : karts_erase)
|
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)
|
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
|
// Now answer to the peer that just connected
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
@ -777,38 +789,83 @@ void ServerLobby::connectionRequested(Event* event)
|
|||||||
(token_generator.get(RAND_MAX) & 0xff));
|
(token_generator.get(RAND_MAX) & 0xff));
|
||||||
|
|
||||||
peer->setClientServerToken(token);
|
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
|
// send a message to the one that asked to connect
|
||||||
// Estimate 10 as average name length
|
NetworkString *message_ack = getNetworkString(4);
|
||||||
NetworkString *message_ack = getNetworkString(4 + players.size() * (2+10));
|
// connection success -- return the host id of peer
|
||||||
// connection success -- size of token -- token
|
message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt32(peer->getHostId());
|
||||||
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());
|
|
||||||
}
|
|
||||||
peer->sendPacket(message_ack);
|
peer->sendPacket(message_ack);
|
||||||
delete message_ack;
|
delete message_ack;
|
||||||
|
|
||||||
NetworkPlayerProfile* profile =
|
updatePlayerList();
|
||||||
new NetworkPlayerProfile(name, new_player_id, new_host_id);
|
|
||||||
m_game_setup->addPlayer(profile);
|
|
||||||
NetworkingLobby::getInstance()->addPlayer(profile);
|
|
||||||
|
|
||||||
Log::verbose("ServerLobby", "New player.");
|
Log::verbose("ServerLobby", "New player.");
|
||||||
|
|
||||||
} // connectionRequested
|
} // 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.
|
/*! \brief Called when a player asks to select a kart.
|
||||||
* \param event : Event providing the information.
|
* \param event : Event providing the information.
|
||||||
*
|
*
|
||||||
|
@ -6,9 +6,12 @@
|
|||||||
#include "utils/synchronised.hpp"
|
#include "utils/synchronised.hpp"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
class STKPeer;
|
||||||
|
|
||||||
class ServerLobby : public LobbyProtocol
|
class ServerLobby : public LobbyProtocol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -31,10 +34,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::atomic<ServerState> m_state;
|
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
|
/** Available karts and tracks for all clients, this will be initialized
|
||||||
* with data in server first. */
|
* with data in server first. */
|
||||||
Synchronised<std::pair<std::set<std::string>,
|
std::pair<std::set<std::string>, std::set<std::string> > m_available_kts;
|
||||||
std::set<std::string> > > m_available_kts;
|
|
||||||
|
|
||||||
/** Next id to assign to a peer. */
|
/** Next id to assign to a peer. */
|
||||||
Synchronised<int> m_next_player_id;
|
Synchronised<int> m_next_player_id;
|
||||||
@ -58,6 +64,8 @@ private:
|
|||||||
|
|
||||||
bool m_selection_enabled;
|
bool m_selection_enabled;
|
||||||
|
|
||||||
|
bool m_has_created_server_id_file;
|
||||||
|
|
||||||
/** It indicates if this server is registered with the stk server. */
|
/** It indicates if this server is registered with the stk server. */
|
||||||
std::atomic_bool m_server_registered;
|
std::atomic_bool m_server_registered;
|
||||||
|
|
||||||
@ -89,6 +97,9 @@ private:
|
|||||||
void startedRaceOnClient(Event *event);
|
void startedRaceOnClient(Event *event);
|
||||||
void unregisterServer();
|
void unregisterServer();
|
||||||
void createServerIdFile();
|
void createServerIdFile();
|
||||||
|
void updatePlayerList();
|
||||||
|
void updateServerOwner();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServerLobby();
|
ServerLobby();
|
||||||
virtual ~ServerLobby();
|
virtual ~ServerLobby();
|
||||||
|
@ -34,9 +34,9 @@ enum SoccerTeam
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Game difficulty per player. */
|
/** Game difficulty per player. */
|
||||||
enum PerPlayerDifficulty
|
enum PerPlayerDifficulty : uint8_t
|
||||||
{
|
{
|
||||||
PLAYER_DIFFICULTY_NORMAL,
|
PLAYER_DIFFICULTY_NORMAL = 0,
|
||||||
PLAYER_DIFFICULTY_HANDICAP,
|
PLAYER_DIFFICULTY_HANDICAP,
|
||||||
PLAYER_DIFFICULTY_COUNT
|
PLAYER_DIFFICULTY_COUNT
|
||||||
};
|
};
|
||||||
@ -51,7 +51,7 @@ class RemoteKartInfo
|
|||||||
SoccerTeam m_soccer_team;
|
SoccerTeam m_soccer_team;
|
||||||
bool m_network_player;
|
bool m_network_player;
|
||||||
PerPlayerDifficulty m_difficulty;
|
PerPlayerDifficulty m_difficulty;
|
||||||
|
float m_default_kart_color;
|
||||||
public:
|
public:
|
||||||
RemoteKartInfo(int player_id, const std::string& kart_name,
|
RemoteKartInfo(int player_id, const std::string& kart_name,
|
||||||
const irr::core::stringw& user_name, int host_id,
|
const irr::core::stringw& user_name, int host_id,
|
||||||
@ -75,6 +75,7 @@ public:
|
|||||||
void setGlobalPlayerId(int id) { m_global_player_id = id; }
|
void setGlobalPlayerId(int id) { m_global_player_id = id; }
|
||||||
void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; }
|
void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; }
|
||||||
void setNetworkPlayer(bool value) { m_network_player = value; }
|
void setNetworkPlayer(bool value) { m_network_player = value; }
|
||||||
|
void setDefaultKartColor(float value) { m_default_kart_color = value; }
|
||||||
void setPerPlayerDifficulty(PerPlayerDifficulty value)
|
void setPerPlayerDifficulty(PerPlayerDifficulty value)
|
||||||
{ m_difficulty = value; }
|
{ m_difficulty = value; }
|
||||||
int getHostId() const { return m_host_id; }
|
int getHostId() const { return m_host_id; }
|
||||||
@ -85,6 +86,7 @@ public:
|
|||||||
const irr::core::stringw& getPlayerName() const { return m_user_name; }
|
const irr::core::stringw& getPlayerName() const { return m_user_name; }
|
||||||
SoccerTeam getSoccerTeam() const { return m_soccer_team; }
|
SoccerTeam getSoccerTeam() const { return m_soccer_team; }
|
||||||
PerPlayerDifficulty getDifficulty() const { return m_difficulty; }
|
PerPlayerDifficulty getDifficulty() const { return m_difficulty; }
|
||||||
|
float getDefaultKartColor() const { return m_default_kart_color; }
|
||||||
|
|
||||||
bool operator<(const RemoteKartInfo& other) const
|
bool operator<(const RemoteKartInfo& other) const
|
||||||
{
|
{
|
||||||
|
@ -262,7 +262,6 @@ void STKHost::create(std::shared_ptr<Server> server, SeparateProcess* p)
|
|||||||
*/
|
*/
|
||||||
STKHost::STKHost(std::shared_ptr<Server> server)
|
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
|
// Will be overwritten with the correct value once a connection with the
|
||||||
// server is made.
|
// server is made.
|
||||||
m_host_id = 0;
|
m_host_id = 0;
|
||||||
@ -291,16 +290,14 @@ STKHost::STKHost(std::shared_ptr<Server> server)
|
|||||||
STKHost::STKHost(const irr::core::stringw &server_name)
|
STKHost::STKHost(const irr::core::stringw &server_name)
|
||||||
{
|
{
|
||||||
init();
|
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.
|
m_host_id = 0; // indicates a server host.
|
||||||
|
|
||||||
ENetAddress addr;
|
ENetAddress addr;
|
||||||
addr.host = STKHost::HOST_ANY;
|
addr.host = STKHost::HOST_ANY;
|
||||||
addr.port = NetworkConfig::get()->getServerPort();
|
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,
|
/*channel_limit*/2,
|
||||||
/*max_in_bandwidth*/0,
|
/*max_in_bandwidth*/0,
|
||||||
/*max_out_bandwidth*/ 0, &addr,
|
/*max_out_bandwidth*/ 0, &addr,
|
||||||
@ -320,6 +317,7 @@ STKHost::STKHost(const irr::core::stringw &server_name)
|
|||||||
void STKHost::init()
|
void STKHost::init()
|
||||||
{
|
{
|
||||||
m_shutdown = false;
|
m_shutdown = false;
|
||||||
|
m_authorised = false;
|
||||||
m_network = NULL;
|
m_network = NULL;
|
||||||
m_game_setup = NULL;
|
m_game_setup = NULL;
|
||||||
m_exit_timeout.store(std::numeric_limits<double>::max());
|
m_exit_timeout.store(std::numeric_limits<double>::max());
|
||||||
@ -627,13 +625,14 @@ GameSetup* STKHost::setupNewGame()
|
|||||||
void STKHost::disconnectAllPeers(bool timeout_waiting)
|
void STKHost::disconnectAllPeers(bool timeout_waiting)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_peers_mutex);
|
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
|
// Wait for at most 2 seconds for disconnect event to be generated
|
||||||
if (timeout_waiting)
|
|
||||||
m_exit_timeout.store(StkTime::getRealTime() + 2.0);
|
m_exit_timeout.store(StkTime::getRealTime() + 2.0);
|
||||||
m_peers.clear();
|
|
||||||
}
|
}
|
||||||
|
m_peers.clear();
|
||||||
} // disconnectAllPeers
|
} // disconnectAllPeers
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -694,23 +693,6 @@ void STKHost::stopListening()
|
|||||||
m_listening_thread.join();
|
m_listening_thread.join();
|
||||||
} // stopListening
|
} // 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.
|
/** \brief Thread function checking if data is received.
|
||||||
* This function tries to get data from network low-level functions as
|
* This function tries to get data from network low-level functions as
|
||||||
@ -767,6 +749,14 @@ void STKHost::mainLoop()
|
|||||||
case ECT_DISCONNECT:
|
case ECT_DISCONNECT:
|
||||||
enet_peer_disconnect(std::get<0>(p), std::get<2>(p));
|
enet_peer_disconnect(std::get<0>(p), std::get<2>(p));
|
||||||
break;
|
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;
|
Event* stk_event = NULL;
|
||||||
if (event.type == ENET_EVENT_TYPE_CONNECT)
|
if (event.type == ENET_EVENT_TYPE_CONNECT)
|
||||||
{
|
{
|
||||||
auto stk_peer =
|
auto stk_peer = std::make_shared<STKPeer>
|
||||||
std::make_shared<STKPeer>(event.peer, this);
|
(event.peer, this, m_next_unique_host_id++);
|
||||||
std::unique_lock<std::mutex> lock(m_peers_mutex);
|
std::unique_lock<std::mutex> lock(m_peers_mutex);
|
||||||
m_peers[event.peer] = stk_peer;
|
m_peers[event.peer] = stk_peer;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@ -1026,3 +1016,30 @@ void STKHost::sendToServer(NetworkString *data, bool reliable)
|
|||||||
assert(NetworkConfig::get()->isClient());
|
assert(NetworkConfig::get()->isClient());
|
||||||
m_peers.begin()->second->sendPacket(data, reliable);
|
m_peers.begin()->second->sendPacket(data, reliable);
|
||||||
} // sendToServer
|
} // 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
|
||||||
|
@ -50,7 +50,8 @@ class SeparateProcess;
|
|||||||
enum ENetCommandType : unsigned int
|
enum ENetCommandType : unsigned int
|
||||||
{
|
{
|
||||||
ECT_SEND_PACKET = 0,
|
ECT_SEND_PACKET = 0,
|
||||||
ECT_DISCONNECT = 1
|
ECT_DISCONNECT = 1,
|
||||||
|
ECT_RESET = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
class STKHost
|
class STKHost
|
||||||
@ -80,7 +81,7 @@ private:
|
|||||||
std::thread m_network_console;
|
std::thread m_network_console;
|
||||||
|
|
||||||
/** Make sure the removing or adding a peer is thread-safe. */
|
/** 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
|
/** Let (atm enet_peer_send and enet_peer_disconnect) run in the listening
|
||||||
* thread. */
|
* thread. */
|
||||||
@ -98,10 +99,10 @@ private:
|
|||||||
* getPeer()), but not decreased whena host (=peer) disconnects. This
|
* getPeer()), but not decreased whena host (=peer) disconnects. This
|
||||||
* results in a unique host id for each host, even when a host should
|
* results in a unique host id for each host, even when a host should
|
||||||
* disconnect and then reconnect. */
|
* disconnect and then reconnect. */
|
||||||
int m_next_unique_host_id;
|
uint32_t m_next_unique_host_id = 0;
|
||||||
|
|
||||||
/** Host id of this host. */
|
/** Host id of this host. */
|
||||||
uint8_t m_host_id;
|
uint32_t m_host_id = 0;
|
||||||
|
|
||||||
/** Stores data about the online game to play. */
|
/** Stores data about the online game to play. */
|
||||||
GameSetup* m_game_setup;
|
GameSetup* m_game_setup;
|
||||||
@ -113,6 +114,9 @@ private:
|
|||||||
* triggers a shutdown of the STKHost (and the Protocolmanager). */
|
* triggers a shutdown of the STKHost (and the Protocolmanager). */
|
||||||
std::atomic_bool m_shutdown;
|
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. */
|
/** Use as a timeout to waiting a disconnect event when exiting. */
|
||||||
std::atomic<double> m_exit_timeout;
|
std::atomic<double> m_exit_timeout;
|
||||||
|
|
||||||
@ -142,7 +146,6 @@ public:
|
|||||||
* a crash in release mode on windows (see #1529). */
|
* a crash in release mode on windows (see #1529). */
|
||||||
static bool m_enable_console;
|
static bool m_enable_console;
|
||||||
|
|
||||||
|
|
||||||
/** Creates the STKHost. It takes all confifguration parameters from
|
/** Creates the STKHost. It takes all confifguration parameters from
|
||||||
* NetworkConfig. This STKHost can either be a client or a server.
|
* NetworkConfig. This STKHost can either be a client or a server.
|
||||||
*/
|
*/
|
||||||
@ -199,7 +202,21 @@ public:
|
|||||||
void shutdown();
|
void shutdown();
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
void sendPacketToAllPeers(NetworkString *data, bool reliable = true);
|
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,
|
void sendPacketExcept(STKPeer* peer,
|
||||||
NetworkString *data,
|
NetworkString *data,
|
||||||
bool reliable = true);
|
bool reliable = true);
|
||||||
@ -213,8 +230,6 @@ public:
|
|||||||
std::shared_ptr<STKPeer> getServerPeerForClient() const;
|
std::shared_ptr<STKPeer> getServerPeerForClient() const;
|
||||||
std::vector<NetworkPlayerProfile*> getMyPlayerProfiles();
|
std::vector<NetworkPlayerProfile*> getMyPlayerProfiles();
|
||||||
void setErrorMessage(const irr::core::stringw &message);
|
void setErrorMessage(const irr::core::stringw &message);
|
||||||
bool isAuthorisedToControl() const;
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
void addEnetCommand(ENetPeer* peer, ENetPacket* packet, uint32_t i,
|
void addEnetCommand(ENetPeer* peer, ENetPacket* packet, uint32_t i,
|
||||||
ENetCommandType ect)
|
ENetCommandType ect)
|
||||||
{
|
{
|
||||||
@ -247,7 +262,7 @@ public:
|
|||||||
} // sendRawPacket
|
} // sendRawPacket
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns a copied list of peers. */
|
/** 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::lock_guard<std::mutex> lock(m_peers_mutex);
|
||||||
std::vector<std::shared_ptr<STKPeer> > peers;
|
std::vector<std::shared_ptr<STKPeer> > peers;
|
||||||
@ -266,17 +281,17 @@ public:
|
|||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the number of currently connected peers. */
|
/** Returns the number of currently connected peers. */
|
||||||
unsigned int getPeerCount()
|
unsigned int getPeerCount() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_peers_mutex);
|
std::lock_guard<std::mutex> lock(m_peers_mutex);
|
||||||
return m_peers.size();
|
return m_peers.size();
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets the global host id of this host. */
|
/** Sets the global host id of this host (client use). */
|
||||||
void setMyHostId(uint8_t my_host_id) { m_host_id = my_host_id; }
|
void setMyHostId(uint32_t my_host_id) { m_host_id = my_host_id; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the host id of this host. */
|
/** 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);
|
void sendToServer(NetworkString *data, bool reliable = true);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -29,27 +29,24 @@
|
|||||||
|
|
||||||
/** Constructor for an empty peer.
|
/** 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_peer_address(enet_peer->address), m_host(host)
|
||||||
{
|
{
|
||||||
m_enet_peer = enet_peer;
|
m_enet_peer = enet_peer;
|
||||||
m_is_authorised = false;
|
|
||||||
m_client_server_token = 0;
|
m_client_server_token = 0;
|
||||||
m_host_id = 0;
|
m_host_id = host_id;
|
||||||
m_token_set = false;
|
m_token_set = false;
|
||||||
} // STKPeer
|
} // STKPeer
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Destructor.
|
void STKPeer::disconnect()
|
||||||
*/
|
|
||||||
STKPeer::~STKPeer()
|
|
||||||
{
|
{
|
||||||
TransportAddress a(m_enet_peer->address);
|
TransportAddress a(m_enet_peer->address);
|
||||||
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
|
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
|
||||||
a != m_peer_address)
|
a != m_peer_address)
|
||||||
return;
|
return;
|
||||||
m_host->addEnetCommand(m_enet_peer, NULL, PDI_NORMAL, ECT_DISCONNECT);
|
m_host->addEnetCommand(m_enet_peer, NULL, PDI_NORMAL, ECT_DISCONNECT);
|
||||||
} // ~STKPeer
|
} // disconnect
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Kick this peer (used by server).
|
/** Kick this peer (used by server).
|
||||||
@ -63,6 +60,18 @@ void STKPeer::kick()
|
|||||||
m_host->addEnetCommand(m_enet_peer, NULL, PDI_KICK, ECT_DISCONNECT);
|
m_host->addEnetCommand(m_enet_peer, NULL, PDI_KICK, ECT_DISCONNECT);
|
||||||
} // kick
|
} // 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.
|
/** Sends a packet to this host.
|
||||||
* \param data The data to send.
|
* \param data The data to send.
|
||||||
@ -111,14 +120,3 @@ bool STKPeer::isSamePeer(const ENetPeer* peer) const
|
|||||||
{
|
{
|
||||||
return peer==m_enet_peer;
|
return peer==m_enet_peer;
|
||||||
} // isSamePeer
|
} // 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
|
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <enet/enet.h>
|
#include <enet/enet.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class NetworkPlayerProfile;
|
class NetworkPlayerProfile;
|
||||||
@ -62,26 +63,38 @@ protected:
|
|||||||
/** Host id of this peer. */
|
/** Host id of this peer. */
|
||||||
int m_host_id;
|
int m_host_id;
|
||||||
|
|
||||||
/** True if this peer is authorised to control a server. */
|
|
||||||
bool m_is_authorised;
|
|
||||||
|
|
||||||
TransportAddress m_peer_address;
|
TransportAddress m_peer_address;
|
||||||
|
|
||||||
STKHost* m_host;
|
STKHost* m_host;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<NetworkPlayerProfile> > m_players;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STKPeer(ENetPeer *enet_peer, STKHost* host);
|
STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id);
|
||||||
~STKPeer();
|
~STKPeer() {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void sendPacket(NetworkString *data, bool reliable = true);
|
void sendPacket(NetworkString *data, bool reliable = true);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
void disconnect();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void kick();
|
void kick();
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
void reset();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
bool isConnected() const;
|
bool isConnected() const;
|
||||||
const TransportAddress& getAddress() const { return m_peer_address; }
|
const TransportAddress& getAddress() const { return m_peer_address; }
|
||||||
bool isSamePeer(const STKPeer* peer) const;
|
bool isSamePeer(const STKPeer* peer) const;
|
||||||
bool isSamePeer(const ENetPeer* 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. */
|
/** Sets the token for this client. */
|
||||||
void setClientServerToken(const uint32_t& token)
|
void setClientServerToken(const uint32_t& token)
|
||||||
@ -90,7 +103,11 @@ public:
|
|||||||
m_token_set = true;
|
m_token_set = true;
|
||||||
} // setClientServerToken
|
} // setClientServerToken
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void unsetClientServerToken() { m_token_set = false; }
|
void unsetClientServerToken()
|
||||||
|
{
|
||||||
|
m_token_set = false;
|
||||||
|
m_client_server_token = 0;
|
||||||
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the token of this client. */
|
/** Returns the token of this client. */
|
||||||
uint32_t getClientServerToken() const { return m_client_server_token; }
|
uint32_t getClientServerToken() const { return m_client_server_token; }
|
||||||
@ -98,21 +115,9 @@ public:
|
|||||||
/** Returns if the token for this client is known. */
|
/** Returns if the token for this client is known. */
|
||||||
bool isClientServerTokenSet() const { return m_token_set; }
|
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. */
|
/** Returns the host id of this peer. */
|
||||||
int getHostId() const { return m_host_id; }
|
uint32_t 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; }
|
|
||||||
}; // STKPeer
|
}; // STKPeer
|
||||||
|
|
||||||
#endif // STK_PEER_HPP
|
#endif // STK_PEER_HPP
|
||||||
|
@ -96,10 +96,6 @@ namespace Online
|
|||||||
return m_online_state;
|
return m_online_state;
|
||||||
} // getOnlineState
|
} // 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. */
|
/** Returns the session token of the signed in user. */
|
||||||
const std::string& getToken() const { return m_token; }
|
const std::string& getToken() const { return m_token; }
|
||||||
@ -113,6 +109,9 @@ namespace Online
|
|||||||
OnlinePlayerProfile(const core::stringw &name, bool is_guest = false);
|
OnlinePlayerProfile(const core::stringw &name, bool is_guest = false);
|
||||||
virtual ~OnlinePlayerProfile() {}
|
virtual ~OnlinePlayerProfile() {}
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
/** Returns a pointer to the profile associated with the current user. */
|
||||||
|
OnlineProfile* getProfile() const { return m_profile; }
|
||||||
|
// ----------------------------------------------------------------
|
||||||
}; // class OnlinePlayerProfile
|
}; // class OnlinePlayerProfile
|
||||||
} // namespace Online
|
} // namespace Online
|
||||||
#endif // HEADER_CURRENT_ONLINE_USER_HPP
|
#endif // HEADER_CURRENT_ONLINE_USER_HPP
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include "input/input_manager.hpp"
|
#include "input/input_manager.hpp"
|
||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "network/network_config.hpp"
|
#include "network/network_config.hpp"
|
||||||
#include "network/network_player_profile.hpp"
|
|
||||||
#include "network/protocols/client_lobby.hpp"
|
#include "network/protocols/client_lobby.hpp"
|
||||||
#include "network/protocols/server_lobby.hpp"
|
#include "network/protocols/server_lobby.hpp"
|
||||||
#include "network/server.hpp"
|
#include "network/server.hpp"
|
||||||
@ -262,16 +261,25 @@ void NetworkingLobby::onDialogClose()
|
|||||||
} // 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
|
// In GUI-less server this function will be called without proper
|
||||||
// initialisation
|
// initialisation
|
||||||
if (m_player_list)
|
if (m_player_list)
|
||||||
m_player_list->addItem(StringUtils::toString(profile->getGlobalPlayerId()),
|
{
|
||||||
profile->getName());
|
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
|
} // addPlayer
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void NetworkingLobby::removePlayer(NetworkPlayerProfile *profile)
|
void NetworkingLobby::cleanPlayers()
|
||||||
{
|
{
|
||||||
} // removePlayer
|
if (m_player_list)
|
||||||
|
m_player_list->clear();
|
||||||
|
} // cleanPlayers
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "guiengine/screen.hpp"
|
#include "guiengine/screen.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
class Server;
|
class Server;
|
||||||
|
|
||||||
@ -32,8 +33,6 @@ namespace GUIEngine
|
|||||||
class TextBoxWidget;
|
class TextBoxWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NetworkPlayerProfile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Handles the main menu
|
* \brief Handles the main menu
|
||||||
* \ingroup states_screens
|
* \ingroup states_screens
|
||||||
@ -91,8 +90,9 @@ public:
|
|||||||
/** Used to insert each client chat message (reserved). */
|
/** Used to insert each client chat message (reserved). */
|
||||||
void addMoreServerInfo(const core::stringw& info);
|
void addMoreServerInfo(const core::stringw& info);
|
||||||
void setJoinedServer(std::shared_ptr<Server> server);
|
void setJoinedServer(std::shared_ptr<Server> server);
|
||||||
void addPlayer(NetworkPlayerProfile *profile);
|
void addPlayer(const std::tuple<uint32_t/*host id*/, uint32_t/*online id*/,
|
||||||
void removePlayer(NetworkPlayerProfile *profile);
|
core::stringw/*player name*/, bool/*is server owner*/>& p);
|
||||||
|
void cleanPlayers();
|
||||||
}; // class NetworkingLobby
|
}; // class NetworkingLobby
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user