diff --git a/src/client.h b/src/client.h index 9aec0d061..c94936d85 100644 --- a/src/client.h +++ b/src/client.h @@ -348,6 +348,7 @@ public: 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); diff --git a/src/content_cao.cpp b/src/content_cao.cpp index c904082d6..a5a55fd7e 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -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()); } } @@ -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); diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index bdcb1dfce..cb504b373 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -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, diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index d002ae10d..9eb6d8dca 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -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) diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 7126c237b..f003cf26a 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -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 @@ -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, /* @@ -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 diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index 19978a2b6..3f9706d6a 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -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, diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 90b747e46..f33b1a523 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -705,6 +705,19 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt) peer_id, major_ver, minor_ver, patch_ver, full_ver); + const std::vector &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(¬ice_pkt); + m_clients.event(peer_id, CSE_SetClientReady); m_script->on_joinplayer(playersao); // Send shutdown timer if shutdown has been scheduled diff --git a/src/server.cpp b/src/server.cpp index b2fdecfa9..0351fa13b 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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(¬ice); + // run scripts m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT); playersao->disconnected();