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);
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());
}
}
GenericCAO::~GenericCAO()
{
- if (m_is_player) {
+ if (m_is_player && m_client->getProtoVersion() < 33) {
m_env->removePlayerName(m_name.c_str());
}
removeFromScene(true);
{ "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,
*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)
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
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,
/*
"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
{ "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,
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(¬ice_pkt);
+
m_clients.event(peer_id, CSE_SetClientReady);
m_script->on_joinplayer(playersao);
// Send shutdown timer if shutdown has been scheduled
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();