Skip to content

Commit

Permalink
Have the server send the player list to the client (#5924)
Browse files Browse the repository at this point in the history
* Have the server send the player list to the client

Currently the client generates the player list based on the Client active object list, the issue with this is that we can't be sure all player active objects will be sent to the client, so this could result in players showing up when someone run `/status` but auto complete not working with their nick and CSM not being aware of the player
  • Loading branch information
red-001 authored and nerzhul committed Jun 8, 2017
1 parent 5bd33a1 commit 4221c1b
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/client.h
Expand Up @@ -348,6 +348,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
void handleCommand_EyeOffset(NetworkPacket* pkt);
void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
void handleCommand_SrpBytesSandB(NetworkPacket* pkt);

void ProcessData(NetworkPacket *pkt);
Expand Down
5 changes: 3 additions & 2 deletions src/content_cao.cpp
Expand Up @@ -624,7 +624,8 @@ void GenericCAO::initialize(const std::string &data)
m_is_visible = false;
player->setCAO(this);
}
m_env->addPlayerName(m_name.c_str());
if (m_client->getProtoVersion() < 33)
m_env->addPlayerName(m_name.c_str());
}
}

Expand Down Expand Up @@ -667,7 +668,7 @@ void GenericCAO::processInitData(const std::string &data)

GenericCAO::~GenericCAO()
{
if (m_is_player) {
if (m_is_player && m_client->getProtoVersion() < 33) {
m_env->removePlayerName(m_name.c_str());
}
removeFromScene(true);
Expand Down
2 changes: 1 addition & 1 deletion src/network/clientopcodes.cpp
Expand Up @@ -110,7 +110,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_DELETE_PARTICLESPAWNER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeleteParticleSpawner }, // 0x53
{ "TOCLIENT_CLOUD_PARAMS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CloudParams }, // 0x54
{ "TOCLIENT_FADE_SOUND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FadeSound }, // 0x55
null_command_handler,
{ "TOCLIENT_UPDATE_PLAYER_LIST", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_UpdatePlayerList }, // 0x56
null_command_handler,
null_command_handler,
null_command_handler,
Expand Down
22 changes: 22 additions & 0 deletions src/network/clientpackethandler.cpp
Expand Up @@ -1270,6 +1270,28 @@ void Client::handleCommand_EyeOffset(NetworkPacket* pkt)
*pkt >> player->eye_offset_first >> player->eye_offset_third;
}

void Client::handleCommand_UpdatePlayerList(NetworkPacket* pkt)
{
u8 type;
u16 num_players;
*pkt >> type >> num_players;
PlayerListModifer notice_type = (PlayerListModifer) type;

for (u16 i = 0; i < num_players; i++) {
std::string name;
*pkt >> name;
switch (notice_type) {
case PLAYER_LIST_INIT:
case PLAYER_LIST_ADD:
m_env.addPlayerName(name);
continue;
case PLAYER_LIST_REMOVE:
m_env.removePlayerName(name);
continue;
}
}
}

void Client::handleCommand_SrpBytesSandB(NetworkPacket* pkt)
{
if ((m_chosen_auth_mech != AUTH_MECHANISM_LEGACY_PASSWORD)
Expand Down
22 changes: 21 additions & 1 deletion src/network/networkprotocol.h
Expand Up @@ -155,9 +155,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Stop sending TOSERVER_CLIENT_READY
PROTOCOL VERSION 32:
Add fading sounds
PROTOCOL VERSION 33:
Add TOCLIENT_UPDATE_PLAYER_LIST and send the player list to the client,
instead of guessing based on the active object list.
*/

#define LATEST_PROTOCOL_VERSION 32
#define LATEST_PROTOCOL_VERSION 33

// Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 24
Expand Down Expand Up @@ -629,6 +633,14 @@ enum ToClientCommand
float step
float gain
*/
TOCLIENT_UPDATE_PLAYER_LIST = 0x56,
/*
u8 type
u16 number of players
for each player
u16 len
u8[len] player name
*/

TOCLIENT_SRP_BYTES_S_B = 0x60,
/*
Expand Down Expand Up @@ -965,4 +977,12 @@ const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
"This server has experienced an internal error. You will now be disconnected."
};

enum PlayerListModifer: u8
{
PLAYER_LIST_INIT,
PLAYER_LIST_ADD,
PLAYER_LIST_REMOVE,
};


#endif
2 changes: 1 addition & 1 deletion src/network/serveropcodes.cpp
Expand Up @@ -199,7 +199,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_DELETE_PARTICLESPAWNER", 0, true }, // 0x53
{ "TOCLIENT_CLOUD_PARAMS", 0, true }, // 0x54
{ "TOCLIENT_FADE_SOUND", 0, true }, // 0x55
null_command_factory,
{ "TOCLIENT_UPDATE_PLAYER_LIST", 0, true }, // 0x56
null_command_factory,
null_command_factory,
null_command_factory,
Expand Down
13 changes: 13 additions & 0 deletions src/network/serverpackethandler.cpp
Expand Up @@ -705,6 +705,19 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
peer_id, major_ver, minor_ver, patch_ver,
full_ver);

const std::vector<std::string> &players = m_clients.getPlayerNames();
NetworkPacket list_pkt(TOCLIENT_UPDATE_PLAYER_LIST, 0, peer_id);
list_pkt << (u8) PLAYER_LIST_INIT << (u16) players.size();
for (const std::string &player: players) {
list_pkt << player;
}
m_clients.send(peer_id, 0, &list_pkt, true);

NetworkPacket notice_pkt(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
// (u16) 1 + std::string represents a pseudo vector serialization representation
notice_pkt << (u8) PLAYER_LIST_ADD << (u16) 1 << std::string(playersao->getPlayer()->getName());
m_clients.sendToAll(&notice_pkt);

m_clients.event(peer_id, CSE_SetClientReady);
m_script->on_joinplayer(playersao);
// Send shutdown timer if shutdown has been scheduled
Expand Down
6 changes: 6 additions & 0 deletions src/server.cpp
Expand Up @@ -2787,6 +2787,12 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
PlayerSAO *playersao = player->getPlayerSAO();
assert(playersao);

// inform connected clients
NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
// (u16) 1 + std::string represents a vector serialization representation
notice << (u8) PLAYER_LIST_REMOVE << (u16) 1 << std::string(playersao->getPlayer()->getName());
m_clients.sendToAll(&notice);
// run scripts
m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);

playersao->disconnected();
Expand Down

0 comments on commit 4221c1b

Please sign in to comment.