Send the player's online or local (if not online) name to the server

and all clients.
This commit is contained in:
hiker 2015-11-27 08:24:02 +11:00
parent 801b390860
commit b092b47a58
6 changed files with 225 additions and 127 deletions

View File

@ -20,13 +20,18 @@
#include "online/online_player_profile.hpp"
NetworkPlayerProfile::NetworkPlayerProfile(int race_player_id)
/** Constructor. The player id is a unique number assigned from the server
* to this player (though it might not be the index in the peer list).
*/
NetworkPlayerProfile::NetworkPlayerProfile(int race_player_id,
const irr::core::stringw &name)
{
m_race_player_id = race_player_id;
m_online_profile = NULL;
m_kart_name = "";
m_world_kart_id = 0;
m_per_player_difficulty = PLAYER_DIFFICULTY_NORMAL;
m_player_name = name;
} // BetworkPlayerProfile
// ----------------------------------------------------------------------------

View File

@ -36,12 +36,17 @@ namespace Online { class OnlineProfile; }
class NetworkPlayerProfile
{
private:
/** The id of the player for the race. */
/** 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_race_player_id;
/** The selected kart. */
/** The selected kart id. */
std::string m_kart_name;
/** The name of the player. */
irr::core::stringw m_player_name;
/** Pointer to the online profile of this player. */
Online::OnlineProfile* m_online_profile;
@ -51,8 +56,9 @@ private:
/** Per player difficulty. */
PerPlayerDifficulty m_per_player_difficulty;
public:
NetworkPlayerProfile(int race_player_id);
~NetworkPlayerProfile();
NetworkPlayerProfile(int race_player_id,
const irr::core::stringw &name);
~NetworkPlayerProfile();
int getGlobalID() const;
// ------------------------------------------------------------------------
@ -85,8 +91,13 @@ public:
Online::OnlineProfile *getOnlineProfile() { return m_online_profile; }
// ------------------------------------------------------------------------
/** Returns the per-player difficulty. */
PerPlayerDifficulty getPerPlayerDifficulty() const { return m_per_player_difficulty; }
PerPlayerDifficulty getPerPlayerDifficulty() const
{
return m_per_player_difficulty;
} // getPerPlayerDifficulty
// ------------------------------------------------------------------------
/** Returns the name of this player. */
const irr::core::stringw& getName() const { return m_player_name; }
// ------------------------------------------------------------------------
}; // class NetworkPlayerProfile

View File

@ -16,9 +16,64 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "network/network_string.hpp"
#include "utils/string_utils.hpp"
NetworkString operator+(NetworkString const& a, NetworkString const& b)
{
NetworkString ns(a);
ns += b;
return ns;
}
} // operator+
// ----------------------------------------------------------------------------
/** Adds one byte for the length of the string, and then (up to 255 of)
* the characters of the given string. */
NetworkString& NetworkString::encodeString(const std::string &value)
{
int len = value.size();
if(len<=255)
return addUInt8(len).addString(value);
else
return addUInt8(255).addString(value.substr(0, 255));
} // encodeString
// ----------------------------------------------------------------------------
/** Adds one byte for the length of the string, and then (up to 255 of)
* the characters of the given string. */
NetworkString& NetworkString::encodeString(const irr::core::stringw &value)
{
std::string v = StringUtils::wideToUtf8(value);
return encodeString(v);
} // encodeString
// ----------------------------------------------------------------------------
/** Returns a string at the given position. The first byte indicates the
* length, followed by the actual string (not 0 terminated).
* \param[in] pos Buffer position where the encoded string starts.
* \param[out] out The decoded string.
* \return number of bytes read = 1+length of string
*/
int NetworkString::decodeString(int pos, std::string *out) const
{
uint8_t len = getUInt8(pos);
*out = getString(pos+1, len);
return len;
} // decodeString
// ----------------------------------------------------------------------------
/** Returns an irrlicht wide string from the utf8 encoded string at the
* given position.
* \param[in] pos Buffer position where the encoded string starts.
* \param[out] out The decoded string.
* \return number of bytes read. If there are no special characters in the
* string that will be 1+length of string, but multi-byte encoded
* characters can mean that the length of the returned string is
* less than the number of bytes read.
*/
int NetworkString::decodeStringW(int pos, irr::core::stringw *out) const
{
std::string s;
int len = decodeString(pos, &s);
*out = StringUtils::utf8ToWide(s);
return len;
} // decodeString

View File

@ -25,6 +25,8 @@
#include "utils/types.hpp"
#include "irrString.h"
#include <assert.h>
#include <stdarg.h>
#include <string>
@ -85,6 +87,11 @@ public:
memcpy(m_string.data(), p, len);
} // NetworkString(char*, int)
// ------------------------------------------------------------------------
NetworkString& encodeString(const std::string &value);
NetworkString& encodeString(const irr::core::stringw &value);
int decodeString(int n, std::string *out) const;
int decodeStringW(int n, irr::core::stringw *out) const;
// ------------------------------------------------------------------------
NetworkString& add(const std::string &s)
{
return addUInt8(uint8_t(s.size())).as(s);
@ -218,7 +225,6 @@ public:
/** Adds a single character. */
inline NetworkString& ac(const char& value) { return addChar(value); }
// ------------------------------------------------------------------------
/** Adds a string. */
NetworkString& addString(const std::string& value)
{

View File

@ -234,10 +234,18 @@ void ClientLobbyRoomProtocol::update()
break;
case LINKED:
{
NetworkString ns(6);
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);
NetworkString ns(6+1+name_u8.size());
// 4 (size of id), global id
ns.ai8(LE_CONNECTION_REQUESTED).ai8(4)
.ai32(PlayerManager::getCurrentOnlineId());
.addUInt32(PlayerManager::getCurrentOnlineId())
.encodeString(name);
sendMessage(ns);
m_state = REQUESTING_CONNECTION;
}
@ -283,11 +291,11 @@ void ClientLobbyRoomProtocol::update()
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 5 6 7
* ------------------------------------------------
* Size | 1 | 4 | 1 | 1 |
* Data | 4 | player global id | 1 | 0 <= race id < 16 |
* ------------------------------------------------
* Byte 0 1 5 6 7 8
* -------------------------------------------------------------------
* Size | 1 | 4 | 1 | 1 | 1 | |
* Data | 4 | player global id | 1 | 0 <= race id < 16 | len | player name|
* -------------------------------------------------------------------
*/
void ClientLobbyRoomProtocol::newPlayer(Event* event)
{
@ -302,7 +310,9 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
uint32_t global_id = data.gui32(1);
uint8_t player_id = data.gui8(6);
int name_len = data.getUInt8(7);
std::string name_utf8 = data.getString(8, name_len);
core::stringw name = StringUtils::utf8ToWide(name_utf8);
if (global_id == PlayerManager::getCurrentOnlineId())
{
Log::error("ClientLobbyRoomProtocol",
@ -313,8 +323,7 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
m_setup->getProfile(global_id) == NULL)
{
Log::verbose("ClientLobbyRoomProtocol", "New player connected.");
// FIXME: what player id to use?
NetworkPlayerProfile* profile = new NetworkPlayerProfile(-1);
NetworkPlayerProfile* profile = new NetworkPlayerProfile(player_id, name);
profile->setPlayerID(player_id);
// FIXME: memory leak??
profile->setOnlineProfile(new Online::OnlineProfile(global_id, ""));
@ -369,13 +378,13 @@ void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
* Byte 0 1 2 3 7 8 12
* ----------------------------------------------------------
* Size | 1 | 1 | 1 | 4 | 1 | 4 |
* Data | 1 | 0 <= race id < 16 | 4 | priv token | 4 | global id |
* Data | 1 | 0 <= race id < 16 | 4 | priv token | 4 | global id | playernames*
* ----------------------------------------------------------
*/
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
{
NetworkString &data = event->data();
// 12 bytes should remain now
// At least 12 bytes should remain now
if (data.size() < 12 || data[0] != 1 || data[2] != 4 || data[7] != 4)
{
Log::error("ClientLobbyRoomProtocol",
@ -386,55 +395,60 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
STKPeer* peer = event->getPeer();
uint32_t global_id = data.gui32(8);
if (global_id == PlayerManager::getCurrentOnlineId())
if (global_id != PlayerManager::getCurrentOnlineId())
{
Log::info("ClientLobbyRoomProtocol",
"The server accepted the connection.");
// self profile
//FIXME
NetworkPlayerProfile* profile = new NetworkPlayerProfile(-1);
profile->setPlayerID(data.gui8(1));
profile->setOnlineProfile(PlayerManager::getCurrentOnlineProfile());
m_setup->addPlayer(profile);
// connection token
uint32_t token = data.gui32(3);
peer->setClientServerToken(token);
// add all players
data.removeFront(12); // remove the 12 first bytes
int remaining = data.size();
if (remaining%7 != 0)
{
Log::error("ClientLobbyRoomProtocol",
"ConnectionAccepted : Error in the server list");
}
remaining /= 7;
for (int i = 0; i < remaining; i++)
{
if (data[0] != 1 || data[2] != 4)
Log::error("ClientLobbyRoomProtocol",
"Bad format in players list.");
uint8_t race_id = data[1];
uint32_t global_id = data.gui32(3);
Online::OnlineProfile* new_user =
new Online::OnlineProfile(global_id, "");
// FIXME
NetworkPlayerProfile* profile2 = new NetworkPlayerProfile(-1);
profile2->setPlayerID(race_id);
profile2->setOnlineProfile(new_user);
m_setup->addPlayer(profile2);
data.removeFront(7);
}
// add self
m_server = event->getPeer();
m_state = CONNECTED;
}
else
Log::info("ClientLobbyRoomProtocol",
"Failure during the connection acceptation process.");
return;
}
// Accepted
// ========
Log::info("ClientLobbyRoomProtocol",
"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();
NetworkPlayerProfile* profile = new NetworkPlayerProfile(-1, name);
profile->setPlayerID(data.gui8(1));
profile->setOnlineProfile(PlayerManager::getCurrentOnlineProfile());
m_setup->addPlayer(profile);
// connection token
uint32_t token = data.gui32(3);
peer->setClientServerToken(token);
// Add all players
// ===============
int n = 12;
while (n < data.size())
{
if (data[n] != 1 || data[n + 2] != 4)
Log::error("ClientLobbyRoomProtocol",
"Bad format in players list.");
uint8_t race_player_id = data[n + 1];
uint32_t global_id = data.gui32(n + 3);
irr::core::stringw name;
int bytes_read = data.decodeStringW(n + 7, &name);
// FIXME - leak?
Online::OnlineProfile* new_user =
new Online::OnlineProfile(global_id, name);
NetworkPlayerProfile* profile2 =
new NetworkPlayerProfile(race_player_id, name);
profile2->setPlayerID(race_player_id);
profile2->setOnlineProfile(new_user);
m_setup->addPlayer(profile2);
n += bytes_read+7;
}
// add self
m_server = event->getPeer();
m_state = CONNECTED;
} // connectionAccepted
//-----------------------------------------------------------------------------

View File

@ -412,16 +412,16 @@ void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
*
* Format of the data :
* Byte 0 1 5
* ------------------------
* Size | 1 | 4 |
* Data | 4 | global player id |
* ------------------------
* ----------------------------------------
* Size | 1 | 4 |1| |
* Data | 4 | global player id |n| player name |
* ----------------------------------------
*/
void ServerLobbyRoomProtocol::connectionRequested(Event* event)
{
STKPeer* peer = event->getPeer();
const NetworkString &data = event->data();
if (data.size() != 5 || data[0] != 4)
if (data[0] != 4)
{
Log::warn("ServerLobbyRoomProtocol",
"Receiving badly formated message. Size is %d and first byte %d",
@ -431,68 +431,75 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
uint32_t player_id = 0;
player_id = data.getUInt32(1);
// can we add the player ?
if (m_setup->getPlayerCount() < NetworkConfig::get()->getMaxPlayers() &&
m_state==ACCEPTING_CLIENTS )
{
// add the player to the game setup
m_next_id = m_setup->getPlayerCount();
// notify everybody that there is a new player
NetworkString message(8);
// size of id -- id -- size of local id -- local id;
message.ai8(LE_NEW_PLAYER_CONNECTED).ai8(4).ai32(player_id)
.ai8(1).ai8(m_next_id);
ProtocolManager::getInstance()->sendMessageExcept(this, peer, message);
/// now answer to the peer that just connected
RandomGenerator token_generator;
// use 4 random numbers because rand_max is probably 2^15-1.
uint32_t token = (uint32_t)(((token_generator.get(RAND_MAX)<<24) & 0xff) +
((token_generator.get(RAND_MAX)<<16) & 0xff) +
((token_generator.get(RAND_MAX)<<8) & 0xff) +
((token_generator.get(RAND_MAX) & 0xff)));
std::vector<NetworkPlayerProfile*> players = m_setup->getPlayers();
// send a message to the one that asked to connect
// Size is overestimated, probably one player's data will not be sent
NetworkString message_ack(13+players.size()*7);
// connection success (129) -- size of token -- token
message_ack.ai8(LE_CONNECTION_ACCEPTED).ai8(1).ai8(m_next_id).ai8(4)
.ai32(token).ai8(4).ai32(player_id);
// add all players so that this user knows
for (unsigned int i = 0; i < players.size(); i++)
{
// do not duplicate the player into the message
if (players[i]->getPlayerID() != m_next_id &&
players[i]->getGlobalID() != player_id)
{
message_ack.ai8(1).ai8(players[i]->getPlayerID()).ai8(4)
.ai32(players[i]->getGlobalID());
}
}
sendMessage(peer, message_ack);
peer->setClientServerToken(token);
NetworkPlayerProfile* profile = new NetworkPlayerProfile(m_next_id);
// FIXME: memory leak OnlineProfile
profile->setOnlineProfile(new Online::OnlineProfile(player_id, ""));
m_setup->addPlayer(profile);
peer->setPlayerProfile(profile);
Log::verbose("ServerLobbyRoomProtocol", "New player.");
} // accept player
else // refuse the connection with code 0 (too much players)
if (m_setup->getPlayerCount() >= NetworkConfig::get()->getMaxPlayers() ||
m_state!=ACCEPTING_CLIENTS )
{
NetworkString message(3);
message.ai8(LE_CONNECTION_REFUSED);
message.ai8(1); // 1 bytes for the error code
if(m_state!=ACCEPTING_CLIENTS)
message.ai8(2); // 2 = Busy
else
message.ai8(0); // 0 = too many players
// Len, error code: 2 = busy, 0 = too many players
message.ai8(LE_CONNECTION_REFUSED).ai8(1)
.ai8(m_state!=ACCEPTING_CLIENTS ? 2 : 0);
// send only to the peer that made the request
sendMessage(peer, message);
Log::verbose("ServerLobbyRoomProtocol", "Player refused");
return;
}
// Connection accepted.
// ====================
std::string name_u8;
int name_len = data.decodeString(5, &name_u8);
core::stringw name = StringUtils::utf8ToWide(name_u8);
// add the player to the game setup
m_next_id = m_setup->getPlayerCount();
NetworkPlayerProfile* profile = new NetworkPlayerProfile(m_next_id, name);
// FIXME: memory leak OnlineProfile
profile->setOnlineProfile(new Online::OnlineProfile(player_id, ""));
m_setup->addPlayer(profile);
peer->setPlayerProfile(profile);
// notify everybody that there is a new player
NetworkString message(8);
// size of id -- id -- size of local id -- local id;
message.ai8(LE_NEW_PLAYER_CONNECTED).ai8(4).ai32(player_id)
.ai8(1).ai8(m_next_id).encodeString(name_u8);
ProtocolManager::getInstance()->sendMessageExcept(this, peer, message);
// Now answer to the peer that just connected
RandomGenerator token_generator;
// use 4 random numbers because rand_max is probably 2^15-1.
uint32_t token = (uint32_t)(((token_generator.get(RAND_MAX) << 24) & 0xff) +
((token_generator.get(RAND_MAX) << 16) & 0xff) +
((token_generator.get(RAND_MAX) << 8) & 0xff) +
((token_generator.get(RAND_MAX) & 0xff)));
std::vector<NetworkPlayerProfile*> players = m_setup->getPlayers();
// send a message to the one that asked to connect
// Size is overestimated, probably one player's data will not be sent
NetworkString message_ack(13 + players.size() * 7);
// connection success (129) -- size of token -- token
message_ack.ai8(LE_CONNECTION_ACCEPTED).ai8(1).ai8(m_next_id).ai8(4)
.ai32(token).ai8(4).ai32(player_id);
// add all players so that this user knows
for (unsigned int i = 0; i < players.size(); i++)
{
// do not duplicate the player into the message
if (players[i]->getPlayerID() != m_next_id &&
players[i]->getGlobalID() != player_id)
{
message_ack.ai8(1).ai8(players[i]->getPlayerID()).ai8(4)
.ai32(players[i]->getGlobalID())
.encodeString(players[i]->getName());
}
}
sendMessage(peer, message_ack);
peer->setClientServerToken(token);
Log::verbose("ServerLobbyRoomProtocol", "New player.");
} // connectionRequested
//-----------------------------------------------------------------------------