1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-17 03:53:07 +01:00

Ensure player names are unique

Do this by cheating a little: create a map with count of clients using
given username and increment it each time such a username is
encountered. This yields very similar results to actually counting users
holding given name, but saves all the error-prone string parsing.
This commit is contained in:
Michał Janiszewski
2016-05-24 00:20:41 +02:00
parent 2627ddc836
commit 18d656e012
2 changed files with 34 additions and 15 deletions

View File

@@ -203,15 +203,15 @@ void NetworkPlayer::Read(NetworkPacket& packet)
void NetworkPlayer::Write(NetworkPacket& packet)
{
packet.WriteString((const char*)name);
packet.WriteString((const char*)name.c_str());
packet << id << flags << group;
}
void NetworkPlayer::SetName(const char* name)
void NetworkPlayer::SetName(const std::string &name)
{
safe_strcpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name));
NetworkPlayer::name[sizeof(NetworkPlayer::name) - 1] = 0;
utf8_remove_format_codes((utf8*)NetworkPlayer::name, false);
// 36 == 31 + strlen(" #255");
NetworkPlayer::name = name.substr(0, 36);
utf8_remove_format_codes((utf8*)NetworkPlayer::name.data(), false);
}
void NetworkPlayer::AddMoneySpent(money32 cost)
@@ -790,7 +790,8 @@ bool Network::BeginServer(unsigned short port, const char* address)
LoadGroups();
NetworkPlayer* player = AddPlayer("");
player->SetName(gConfigNetwork.player_name);
std::string player_name(gConfigNetwork.player_name);
player->SetName(MakePlayerNameUnique(player_name.substr(0, 31)));
player->flags |= NETWORK_PLAYER_FLAG_ISSERVER;
player->group = 0;
player_id = player->id;
@@ -1076,7 +1077,7 @@ const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text)
if (fromplayer) {
lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE);
lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE);
safe_strcpy(lineCh, (const char*)fromplayer->name, sizeof(fromplayer->name));
safe_strcpy(lineCh, (const char*)fromplayer->name.c_str(), fromplayer->name.size() + 1);
strcat(lineCh, ": ");
lineCh = strchr(lineCh, '\0');
}
@@ -1800,7 +1801,7 @@ void Network::RemoveClient(std::unique_ptr<NetworkConnection>& connection)
if (connection_player) {
char text[256];
const char * has_disconnected_args[2] = {
(char *) connection_player->name,
(char *) connection_player->name.c_str(),
connection->getLastDisconnectReason()
};
if (has_disconnected_args[1]) {
@@ -1810,7 +1811,7 @@ void Network::RemoveClient(std::unique_ptr<NetworkConnection>& connection)
}
chat_history_add(text);
gNetwork.Server_Send_EVENT_PLAYER_DISCONNECTED((char*)connection_player->name, connection->getLastDisconnectReason());
gNetwork.Server_Send_EVENT_PLAYER_DISCONNECTED((char*)connection_player->name.c_str(), connection->getLastDisconnectReason());
}
player_list.erase(std::remove_if(player_list.begin(), player_list.end(), [connection_player](std::unique_ptr<NetworkPlayer>& player){
return player.get() == connection_player;
@@ -1847,6 +1848,20 @@ NetworkPlayer* Network::AddPlayer(const std::string &keyhash)
return addedplayer;
}
std::string Network::MakePlayerNameUnique(const std::string &name)
{
std::string new_name = name.substr(0, 31);
decltype(username_count_map.begin()) it;
while ((it = username_count_map.find(new_name)) != username_count_map.end()) {
it->second++;
new_name.append(" #");
new_name.append(std::to_string(it->second));
}
// username is guaranteed (to the point where counter overflows) to be unique now.
username_count_map[new_name] = 1;
return new_name;
}
void Network::PrintError()
{
#ifdef __WINDOWS__
@@ -1943,9 +1958,11 @@ void Network::Server_Client_Joined(const char* name, const std::string &keyhash,
NetworkPlayer* player = AddPlayer(keyhash);
connection.player = player;
if (player) {
player->SetName(name);
std::string string_name(name);
string_name = MakePlayerNameUnique(string_name.substr(0, 31));
player->SetName(string_name);
char text[256];
const char * player_name = (const char *) player->name;
const char * player_name = (const char *) player->name.c_str();
format_string(text, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &player_name);
chat_history_add(text);
Server_Send_MAP(&connection);
@@ -2376,7 +2393,7 @@ int network_get_num_players()
const char* network_get_player_name(unsigned int index)
{
return (const char*)gNetwork.player_list[index]->name;
return (const char*)gNetwork.player_list[index]->name.c_str();
}
uint32 network_get_player_flags(unsigned int index)
@@ -2484,7 +2501,7 @@ void network_chat_show_connected_message()
keyboard_shortcut_format_string(templateString, gShortcutKeys[SHORTCUT_OPEN_CHAT_WINDOW]);
utf8 buffer[256];
NetworkPlayer server;
safe_strcpy((char*)&server.name, "Server", sizeof(server.name));
server.name = "Server";
format_string(buffer, STR_MULTIPLAYER_CONNECTED_CHAT_HINT, &templateString);
const char *formatted = Network::FormatChat(&server, buffer);
chat_history_add(formatted);

View File

@@ -171,10 +171,10 @@ public:
NetworkPlayer() = default;
void Read(NetworkPacket& packet);
void Write(NetworkPacket& packet);
void SetName(const char* name);
void SetName(const std::string &name);
void AddMoneySpent(money32 cost);
uint8 id = 0;
uint8 name[32 + 1] = { 0 };
std::string name;
uint16 ping = 0;
uint8 flags = 0;
uint8 group = 0;
@@ -409,9 +409,11 @@ private:
void AddClient(SOCKET socket);
void RemoveClient(std::unique_ptr<NetworkConnection>& connection);
NetworkPlayer* AddPlayer(const std::string &keyhash);
std::string MakePlayerNameUnique(const std::string &name);
void PrintError();
const char* GetMasterServerUrl();
std::string GenerateAdvertiseKey();
std::map<std::string, uint8> username_count_map;
struct GameCommand
{