From 6e83a8f51e95bb4f5d820e625eea8b20047105bb Mon Sep 17 00:00:00 2001 From: kimden <23140380+kimden@users.noreply.github.com> Date: Mon, 31 Mar 2025 02:41:00 +0400 Subject: [PATCH 1/3] Initial, by far incomplete decorator implementation It was done in January, then I got disappointed and started rewriting all code, now it doesn't seem like very nasty to have --- src/network/network_player_profile.cpp | 12 ++++ src/network/network_player_profile.hpp | 5 ++ src/network/protocols/command_manager.cpp | 70 +++++++++++-------- src/network/protocols/server_lobby.cpp | 46 ++++++++---- src/network/protocols/server_lobby.hpp | 11 +++ src/network/stk_host.cpp | 2 +- src/network/stk_peer.cpp | 6 ++ src/network/stk_peer.hpp | 2 + src/utils/chat_manager.cpp | 7 +- src/utils/chat_manager.hpp | 4 +- .../name_decorators/generic_decorator.cpp | 25 +++++++ .../name_decorators/generic_decorator.hpp | 45 ++++++++++++ src/utils/team_manager.cpp | 2 +- 13 files changed, 188 insertions(+), 49 deletions(-) create mode 100644 src/utils/name_decorators/generic_decorator.cpp create mode 100644 src/utils/name_decorators/generic_decorator.hpp diff --git a/src/network/network_player_profile.cpp b/src/network/network_player_profile.cpp index b00045d075e..ac44a2fcc03 100644 --- a/src/network/network_player_profile.cpp +++ b/src/network/network_player_profile.cpp @@ -19,6 +19,9 @@ #include "network/network_player_profile.hpp" #include "network/network_config.hpp" #include "network/stk_host.hpp" +#include "utils/string_utils.hpp" +#include "utils/name_decorators/generic_decorator.hpp" + // ---------------------------------------------------------------------------- /** Returns true if this player is local, i.e. running on this computer. This @@ -31,3 +34,12 @@ bool NetworkPlayerProfile::isLocalPlayer() const return NetworkConfig::get()->isClient() && m_host_id == STKHost::get()->getMyHostId(); } // isLocalPlayer + +// ---------------------------------------------------------------------------- +/** Asks decorator for a name to show in a certain conditions. + */ +core::stringw NetworkPlayerProfile::getDecoratedName(std::shared_ptr decorator) +{ + return StringUtils::utf8ToWide(decorator->decorate(StringUtils::wideToUtf8(m_player_name))); +} // getDecoratedName +// ---------------------------------------------------------------------------- diff --git a/src/network/network_player_profile.hpp b/src/network/network_player_profile.hpp index 1e68278851b..7df9c6eca40 100644 --- a/src/network/network_player_profile.hpp +++ b/src/network/network_player_profile.hpp @@ -33,6 +33,7 @@ #include class STKPeer; +class GenericDecorator; enum KartTeam : int8_t; enum HandicapLevel : uint8_t; @@ -188,6 +189,10 @@ class NetworkPlayerProfile void setKartData(const KartData& data) { m_kart_data = data; } // ------------------------------------------------------------------------ const KartData& getKartData() const { return m_kart_data; } + // ------------------------------------------------------------------------ + core::stringw getDecoratedName(std::shared_ptr decorator); + // ------------------------------------------------------------------------ + }; // class NetworkPlayerProfile #endif // HEADER_NETWORK_PLAYER_PROFILE diff --git a/src/network/protocols/command_manager.cpp b/src/network/protocols/command_manager.cpp index b75aede7e78..305ba2a6536 100644 --- a/src/network/protocols/command_manager.cpp +++ b/src/network/protocols/command_manager.cpp @@ -1006,7 +1006,7 @@ void CommandManager::process_auth(Context& context) + command->getFullName(); else { - auto profile = peer->getPlayerProfiles()[0]; + auto profile = peer->getMainProfile(); std::string username = StringUtils::wideToUtf8(profile->getName()); int online_id = profile->getOnlineId(); if (online_id == 0) @@ -1319,7 +1319,7 @@ void CommandManager::process_addons(Context& context) ))); if (apply_filters) getAssetManager()->applyAllFilters(from, false); // happily the type is never karts in this line - std::vector>> result; + std::vector>>> result; for (const std::string& s: from) result.push_back({s, {}}); @@ -1335,19 +1335,18 @@ void CommandManager::process_addons(Context& context) if (!p->hasPlayerProfiles()) continue; ++num_players; - std::string username = p->getMainName(); const auto& kt = p->getClientAssets(); const auto& container = (argv[1] == "kart" ? kt.first : kt.second); for (auto& pr: result) if (container.find(pr.first) == container.end()) - pr.second.push_back(username); + pr.second.push_back(p->getMainProfile()); } std::random_device rd; std::mt19937 g(rd()); std::shuffle(result.begin(), result.end(), g); std::stable_sort(result.begin(), result.end(), - [](const std::pair>& a, - const std::pair>& b) -> bool { + [](const std::pair>>& a, + const std::pair>>& b) -> bool { if (a.second.size() != b.second.size()) return a.second.size() > b.second.size(); return false; @@ -1367,15 +1366,15 @@ void CommandManager::process_addons(Context& context) { auto result2 = result; result.clear(); - std::string asking_username = ""; + std::shared_ptr asker = {}; if (peer->hasPlayerProfiles()) - asking_username = peer->getMainName(); + asker = peer->getMainProfile(); for (unsigned i = 0; i < result2.size(); ++i) { bool present = false; for (unsigned j = 0; j < result2[i].second.size(); ++j) { - if (result2[i].second[j] == asking_username) + if (result2[i].second[j] == asker) { present = true; break; @@ -1417,7 +1416,7 @@ void CommandManager::process_addons(Context& context) std::sort(result[i].second.begin(), result[i].second.end()); for (unsigned j = 0; j < result[i].second.size(); ++j) { - response += " " + result[i].second[j]; + response += " " + getLobby()->encodeProfileNameForPeer(result[i].second[j], peer.get()); } } } @@ -1451,7 +1450,7 @@ void CommandManager::process_checkaddon(Context& context) const unsigned HAS_MAP = 2; unsigned server_status = 0; - std::vector players[4]; + std::vector> players[4]; auto asset_manager = getAssetManager(); if (asset_manager->hasAddonKart(id)) @@ -1470,14 +1469,14 @@ void CommandManager::process_checkaddon(Context& context) || !getCrownManager()->canRace(p) || p->isCommandSpectator() || !p->hasPlayerProfiles()) continue; - std::string username = p->getMainName(); + const auto& kt = p->getClientAssets(); unsigned status = 0; if (kt.first.find(id) != kt.first.end()) status |= HAS_KART; if (kt.second.find(id) != kt.second.end()) status |= HAS_MAP; - players[status].push_back(username); + players[status].push_back(p->getMainProfile()); } std::string response = ""; @@ -1512,10 +1511,10 @@ void CommandManager::process_checkaddon(Context& context) response += "doesn't have"; response += " " + item_name[item] + " " + argv[1] + "\n"; - std::vector categories[2]; + std::vector> categories[2]; for (unsigned status = 0; status < 4; ++status) { - for (const std::string& s: players[status]) + for (const std::shared_ptr& s: players[status]) categories[(status & item ? 1 : 0)].push_back(s); } for (int i = 0; i < 2; ++i) @@ -1534,7 +1533,7 @@ void CommandManager::process_checkaddon(Context& context) { if (j) response += ", "; - response += categories[i][j]; + response += getLobby()->encodeProfileNameForPeer(categories[i][j], peer.get()); } if (categories[i].size() > 5) response += ", ..."; @@ -1892,7 +1891,7 @@ void CommandManager::process_everypas(Context& context) if (argv.size() > 2) sorting_direction = argv[2]; std::string response = "Addon scores:"; - using Pair = std::pair>; + using Pair = std::pair, std::vector>; std::vector result; for (const auto& p: STKHost::get()->getPeers()) { @@ -1900,12 +1899,11 @@ void CommandManager::process_everypas(Context& context) continue; if (!p->hasPlayerProfiles()) continue; - std::string player_name = p->getMainName(); auto &scores = p->getAddonsScores(); std::vector overall; for (int item = 0; item < AS_TOTAL; item++) overall.push_back(scores[item]); - result.emplace_back(player_name, overall); + result.emplace_back(p->getMainProfile(), overall); } int sorting_idx = -1; if (sorting_type == "kart" || sorting_type == "karts") @@ -1918,17 +1916,24 @@ void CommandManager::process_everypas(Context& context) sorting_idx = 3; if (sorting_idx != -1) { + // Sorting order for equal players WILL DEPEND ON NAME DECORATOR! + // This sorting is clearly bad because we ask lobby every time. Change it later. + auto lobby = getLobby(); + std::stable_sort(result.begin(), result.end(), [lobby, peer](const Pair& lhs, const Pair& rhs) -> bool { + return lobby->encodeProfileNameForPeer(lhs.first, peer.get()) + < lobby->encodeProfileNameForPeer(rhs.first, peer.get()); + }); if (sorting_direction == "asc") std::sort(result.begin(), result.end(), [sorting_idx] (const Pair& lhs, const Pair& rhs) -> bool { int diff = lhs.second[sorting_idx] - rhs.second[sorting_idx]; - return (diff < 0 || (diff == 0 && lhs.first < rhs.first)); + return diff < 0; }); else - std::sort(result.begin(), result.end(), [sorting_idx] + std::stable_sort(result.begin(), result.end(), [sorting_idx] (const Pair& lhs, const Pair& rhs) -> bool { int diff = lhs.second[sorting_idx] - rhs.second[sorting_idx]; - return (diff > 0 || (diff == 0 && lhs.first < rhs.first)); + return diff > 0; }); } // I don't really know if it should be soccer or field, both are used @@ -1936,7 +1941,7 @@ void CommandManager::process_everypas(Context& context) std::vector desc = { "karts", "tracks", "arenas", "fields" }; for (auto& row: result) { - response += "\n" + row.first; + response += "\n" + getLobby()->encodeProfileNameForPeer(row.first, peer.get()); bool negative = true; for (int item = 0; item < AS_TOTAL; item++) negative &= row.second[item] == -1; @@ -3140,7 +3145,7 @@ void CommandManager::process_register(Context& context) } if (!peer->hasPlayerProfiles()) return; - int online_id = peer->getPlayerProfiles()[0]->getOnlineId(); + int online_id = peer->getMainProfile()->getOnlineId(); if (online_id <= 0) { getLobby()->sendStringToPeer(peer, "Please join with a valid online STK account."); @@ -3341,7 +3346,7 @@ void CommandManager::process_role(Context& context) if (player_peer) { if (player_peer->hasPlayerProfiles()) - getTeamManager()->setTeamInLobby(player_peer->getPlayerProfiles()[0], KART_TEAM_RED); + getTeamManager()->setTeamInLobby(player_peer->getMainProfile(), KART_TEAM_RED); getLobby()->sendStringToPeer(player_peer, StringUtils::insertValues(role_changed, Conversions::roleCharToString(role_char))); } @@ -3361,7 +3366,7 @@ void CommandManager::process_role(Context& context) if (player_peer) { if (player_peer->hasPlayerProfiles()) - getTeamManager()->setTeamInLobby(player_peer->getPlayerProfiles()[0], KART_TEAM_BLUE); + getTeamManager()->setTeamInLobby(player_peer->getMainProfile(), KART_TEAM_BLUE); getLobby()->sendStringToPeer(player_peer, StringUtils::insertValues(role_changed, Conversions::roleCharToString(role_char))); } @@ -3374,7 +3379,7 @@ void CommandManager::process_role(Context& context) if (player_peer) { if (player_peer->hasPlayerProfiles()) - getTeamManager()->setTeamInLobby(player_peer->getPlayerProfiles()[0], KART_TEAM_NONE); + getTeamManager()->setTeamInLobby(player_peer->getMainProfile(), KART_TEAM_NONE); getLobby()->sendStringToPeer(player_peer, StringUtils::insertValues(role_changed, Conversions::roleCharToString(role_char))); } @@ -3385,7 +3390,7 @@ void CommandManager::process_role(Context& context) if (player_peer) { if (player_peer->hasPlayerProfiles()) - getTeamManager()->setTeamInLobby(player_peer->getPlayerProfiles()[0], KART_TEAM_NONE); + getTeamManager()->setTeamInLobby(player_peer->getMainProfile(), KART_TEAM_NONE); getLobby()->sendStringToPeer(player_peer, StringUtils::insertValues(role_changed, Conversions::roleCharToString(role_char))); } @@ -3545,7 +3550,8 @@ void CommandManager::process_test(Context& context) std::string username = "Vote"; if (peer.get() && peer->hasPlayerProfiles()) { - username = peer->getMainName(); + username = getLobby()->encodeProfileNameForPeer( + peer->getMainProfile(), peer.get()); } username = "{" + argv[1].substr(4) + "} " + username; getLobby()->sendStringToAllPeers(username + ", " + argv[2] + ", " + argv[3]); @@ -3807,9 +3813,13 @@ void CommandManager::process_why_hourglass(Context& context) error(context); return; } + + std::string encoded_name = getLobby()->encodeProfileNameForPeer( + player_peer->getMainProfile(), peer.get()); + getLobby()->sendStringToPeer(peer, StringUtils::insertValues( getCrownManager()->getWhyPeerCannotPlayAsString(player_peer), - player_name)); + encoded_name)); } // process_why_hourglass // ======================================================================== diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 6f7b3345af1..973053116ae 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -60,6 +60,7 @@ #include "utils/lobby_settings.hpp" #include "utils/lobby_queues.hpp" #include "utils/map_vote_handler.hpp" +#include "utils/name_decorators/generic_decorator.hpp" #include "utils/team_manager.hpp" #include "utils/tournament.hpp" #include "utils/translation.hpp" @@ -77,13 +78,14 @@ namespace { void encodePlayers(BareNetworkString* bns, - std::vector >& players) + std::vector >& players, + const std::shared_ptr& decorator) { bns->addUInt8((uint8_t)players.size()); for (unsigned i = 0; i < players.size(); i++) { std::shared_ptr& player = players[i]; - bns->encodeString(player->getName()) + bns->encodeString(player->getDecoratedName(decorator)) .addUInt32(player->getHostId()) .addFloat(player->getDefaultKartColor()) .addUInt32(player->getOnlineId()) @@ -239,6 +241,7 @@ ServerLobby::ServerLobby() : LobbyProtocol() m_ranking = std::make_shared(); } + m_name_decorator = std::make_shared(); m_items_complete_state = new BareNetworkString(); m_server_id_online.store(0); m_difficulty.store(ServerConfig::m_server_difficulty); @@ -371,7 +374,7 @@ void ServerLobby::handleChat(Event* event) target_team = (KartTeam)event->data().getUInt8(); getChatManager()->handleNormalChatMessage(peer, - StringUtils::wideToUtf8(message), target_team); + StringUtils::wideToUtf8(message), target_team, m_name_decorator); } // handleChat //----------------------------------------------------------------------------- @@ -509,7 +512,7 @@ void ServerLobby::pollDatabase() } if (!is_kicked && !p->getPlayerProfiles().empty()) { - uint32_t online_id = p->getPlayerProfiles()[0]->getOnlineId(); + uint32_t online_id = p->getMainProfile()->getOnlineId(); for (auto& item: online_id_ban_list) { if (item.online_id == online_id) @@ -556,7 +559,7 @@ void ServerLobby::writePlayerReport(Event* event) std::shared_ptr reporter = event->getPeerSP(); if (!reporter->hasPlayerProfiles()) return; - auto reporter_npp = reporter->getPlayerProfiles()[0]; + auto reporter_npp = reporter->getMainProfile(); uint32_t reporting_host_id = event->data().getUInt32(); core::stringw info; @@ -567,7 +570,7 @@ void ServerLobby::writePlayerReport(Event* event) auto reporting_peer = STKHost::get()->findPeerByHostId(reporting_host_id); if (!reporting_peer || !reporting_peer->hasPlayerProfiles()) return; - auto reporting_npp = reporting_peer->getPlayerProfiles()[0]; + auto reporting_npp = reporting_peer->getMainProfile(); bool written = db_connector->writeReport(reporter, reporter_npp, reporting_peer, reporting_npp, info); @@ -977,7 +980,7 @@ NetworkString* ServerLobby::getLoadWorldMessage( load_world_message->addUInt8(LE_LOAD_WORLD); getSettings()->encodeDefaultVote(load_world_message); load_world_message->addUInt8(live_join ? 1 : 0); - encodePlayers(load_world_message, players); + encodePlayers(load_world_message, players, m_name_decorator); load_world_message->addUInt32(m_item_seed); if (RaceManager::get()->isBattleMode()) { @@ -1290,7 +1293,7 @@ void ServerLobby::finishedLoadingLiveJoinClient(Event* event) // starting of race std::vector > players = getLivePlayers(); - encodePlayers(ns, players); + encodePlayers(ns, players, m_name_decorator); for (unsigned i = 0; i < players.size(); i++) players[i]->getKartData().encode(ns); } @@ -2699,7 +2702,7 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, if (getSettings()->isRanked()) { - getRankingForPlayer(peer->getPlayerProfiles()[0]); + getRankingForPlayer(peer->getMainProfile()); } } @@ -2820,7 +2823,7 @@ void ServerLobby::updatePlayerList(bool update_when_reset_server) for (auto profile : all_profiles) { PlayerListProfilePacket packet; - auto profile_name = profile->getName(); + auto profile_name = profile->getDecoratedName(m_name_decorator); // get OS information auto version_os = StringUtils::extractVersionOS(profile->getPeer()->getUserVersion()); @@ -3024,9 +3027,12 @@ void ServerLobby::handlePlayerVote(Event* event) } // Store vote: - vote.m_player_name = event->getPeer()->getPlayerProfiles()[0]->getName(); + vote.m_player_name = event->getPeer()->getMainProfile()->getName(); addVote(event->getPeer()->getHostId(), vote); + // After adding the vote, show decorated name instead + vote.m_player_name = event->getPeer()->getMainProfile()->getDecoratedName(m_name_decorator); + // Now inform all clients about the vote NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM); other.setSynchronous(true); @@ -3352,7 +3358,7 @@ void ServerLobby::addWaitingPlayersToGame() uint32_t online_id = profile->getOnlineId(); if (getSettings()->isRanked() && !m_ranking->has(online_id)) { - getRankingForPlayer(peer->getPlayerProfiles()[0]); + getRankingForPlayer(peer->getMainProfile()); } } // Re-activiate the ai @@ -4169,7 +4175,7 @@ void ServerLobby::writeOwnReport(std::shared_ptr reporter, std::shared_ reporting = reporter; if (!reporter->hasPlayerProfiles()) return; - auto reporter_npp = reporter->getPlayerProfiles()[0]; + auto reporter_npp = reporter->getMainProfile(); if (info.empty()) return; @@ -4177,7 +4183,7 @@ void ServerLobby::writeOwnReport(std::shared_ptr reporter, std::shared_ if (!reporting->hasPlayerProfiles()) return; - auto reporting_npp = reporting->getPlayerProfiles()[0]; + auto reporting_npp = reporting->getMainProfile(); bool written = db_connector->writeReport(reporter, reporter_npp, reporting, reporting_npp, info_w); @@ -4225,6 +4231,16 @@ void ServerLobby::sendStringToAllPeers(const std::string& s) } // sendStringToAllPeers //----------------------------------------------------------------------------- +std::string ServerLobby::encodeProfileNameForPeer( + std::shared_ptr npp, + STKPeer* peer) +{ + if (npp) + return StringUtils::wideToUtf8(npp->getDecoratedName(m_name_decorator)); + return ""; +} // encodeProfileNameForPeer +//----------------------------------------------------------------------------- + bool ServerLobby::canVote(std::shared_ptr peer) const { if (!peer || peer->getPlayerProfiles().empty()) @@ -4297,7 +4313,7 @@ bool ServerLobby::writeOnePlayerReport(std::shared_ptr reporter, return false; if (!reporter->hasPlayerProfiles()) return false; - auto reporter_npp = reporter->getPlayerProfiles()[0]; + auto reporter_npp = reporter->getMainProfile(); auto info_w = StringUtils::utf8ToWide(info); bool written = db_connector->writeReport(reporter, reporter_npp, diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp index 4b12fea64e8..d45022f7dd2 100644 --- a/src/network/protocols/server_lobby.hpp +++ b/src/network/protocols/server_lobby.hpp @@ -44,6 +44,7 @@ class BareNetworkString; class CommandManager; class DatabaseConnector; +class GenericDecorator; class HitProcessor; class KartElimination; class LobbyAssetManager; @@ -174,6 +175,8 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser std::shared_ptr m_ranking; + std::shared_ptr m_name_decorator; + unsigned m_item_seed; uint64_t m_client_starting_time; @@ -331,7 +334,15 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser // int getTrackMaxPlayers(std::string& name) const; void sendStringToPeer(std::shared_ptr peer, const std::string& s); + + // TODO: When using different decorators for everyone, you would need + // a structure to store "player profile" placeholders in a string, so that + // you can apply decorators at the very last moment inside sendStringToAllPeers + // and similar functions. void sendStringToAllPeers(const std::string& s); + std::string encodeProfileNameForPeer( + std::shared_ptr npp, + STKPeer* peer); int getPermissions(std::shared_ptr peer) const; bool isSoccerGoalTarget() const; diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index adc7c91a6a7..c378114da14 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -1446,7 +1446,7 @@ std::set STKHost::getAllPlayerOnlineIds() const if (!peer.second->getPlayerProfiles().empty()) { online_ids.insert( - peer.second->getPlayerProfiles()[0]->getOnlineId()); + peer.second->getMainProfile()->getOnlineId()); } } lock.unlock(); diff --git a/src/network/stk_peer.cpp b/src/network/stk_peer.cpp index 5032ecde567..5d10a76218b 100644 --- a/src/network/stk_peer.cpp +++ b/src/network/stk_peer.cpp @@ -197,6 +197,12 @@ void STKPeer::setCrypto(std::unique_ptr&& c) } // setCrypto // ---------------------------------------------------------------------------- +std::shared_ptr STKPeer::getMainProfile() +{ + return m_players[0]; +} // getMainProfile +// ---------------------------------------------------------------------------- + // A method for convenience only. // For now, returns an empty string if there are no profiles. // Might be better to throw an exception. I will see later. diff --git a/src/network/stk_peer.hpp b/src/network/stk_peer.hpp index efd0f91d556..17a3a3bd8a3 100644 --- a/src/network/stk_peer.hpp +++ b/src/network/stk_peer.hpp @@ -383,6 +383,8 @@ class STKPeer : public NoCopy // ------------------------------------------------------------------------ void setAngryHost(bool val) { m_angry_host.store(val); } // ------------------------------------------------------------------------ + std::shared_ptr getMainProfile(); + // ------------------------------------------------------------------------ std::string getMainName() const; // ------------------------------------------------------------------------ }; // STKPeer diff --git a/src/utils/chat_manager.cpp b/src/utils/chat_manager.cpp index bf903a6fbce..33ede044dbd 100644 --- a/src/utils/chat_manager.cpp +++ b/src/utils/chat_manager.cpp @@ -162,7 +162,8 @@ void ChatManager::onPeerDisconnect(std::shared_ptr peer) //----------------------------------------------------------------------------- void ChatManager::handleNormalChatMessage(std::shared_ptr peer, - std::string message, KartTeam target_team) + std::string message, KartTeam target_team, + const std::shared_ptr& decorator) { // Update so that the peer is not kicked peer->updateLastActivity(); @@ -194,6 +195,10 @@ void ChatManager::handleNormalChatMessage(std::shared_ptr peer, return; } + std::string new_prefix = StringUtils::wideToUtf8( + peer->getMainProfile()->getDecoratedName(decorator)) + ": "; + message = new_prefix + message.substr(prefix.length()); + if (message.size() == 0) return; diff --git a/src/utils/chat_manager.hpp b/src/utils/chat_manager.hpp index e3523cb5a30..a060837c816 100644 --- a/src/utils/chat_manager.hpp +++ b/src/utils/chat_manager.hpp @@ -31,6 +31,7 @@ class STKPeer; enum KartTeam : int8_t; struct KartTeamSet; +class GenericDecorator; class ChatManager: public LobbyContextComponent { @@ -78,7 +79,8 @@ class ChatManager: public LobbyContextComponent int getChatConsecutiveInterval() const { return m_chat_consecutive_interval; } void handleNormalChatMessage(std::shared_ptr peer, - std::string message, KartTeam target_team); + std::string message, KartTeam target_team, + const std::shared_ptr& decorator); bool shouldMessageBeSent(std::shared_ptr sender, std::shared_ptr target, diff --git a/src/utils/name_decorators/generic_decorator.cpp b/src/utils/name_decorators/generic_decorator.cpp new file mode 100644 index 00000000000..12c8fcf53a4 --- /dev/null +++ b/src/utils/name_decorators/generic_decorator.cpp @@ -0,0 +1,25 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2004-2020 Steve Baker , +// Copyright (C) 2004-2020 Ingo Ruhnke +// Copyright (C) 2006-2020 SuperTuxKart-Team +// Copyright (C) 2020 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "utils/name_decorators/generic_decorator.hpp" + + +//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/name_decorators/generic_decorator.hpp b/src/utils/name_decorators/generic_decorator.hpp new file mode 100644 index 00000000000..effd2e2255f --- /dev/null +++ b/src/utils/name_decorators/generic_decorator.hpp @@ -0,0 +1,45 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2004-2020 Steve Baker , +// Copyright (C) 2004-2020 Ingo Ruhnke +// Copyright (C) 2006-2020 SuperTuxKart-Team +// Copyright (C) 2020 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef GENERIC_DECORATOR_HPP +#define GENERIC_DECORATOR_HPP + +// #include "network/network_player_profile.hpp" +// #include "utils/types.hpp" +// #include +#include +// #include +// #include +// #include +// #include + +class GenericDecorator +{ +public: + virtual std::string decorate(const std::string& s) + { + return s; + } +}; + + + +#endif diff --git a/src/utils/team_manager.cpp b/src/utils/team_manager.cpp index 7cd2f1b6d99..c78a9e71ce9 100644 --- a/src/utils/team_manager.cpp +++ b/src/utils/team_manager.cpp @@ -424,7 +424,7 @@ void TeamManager::changeColors() { // kimden: you assume that only [0] can be checked, but in other places // of the code you are somehow not so sure about that... :) - auto pp = peer->getPlayerProfiles()[0]; + auto pp = peer->getMainProfile(); if (pp->getTeam() == KART_TEAM_RED) setTeamInLobby(pp, KART_TEAM_BLUE); else if (pp->getTeam() == KART_TEAM_BLUE) From bb811d314acc04a7203c74c93fb98d8a01dd0acc Mon Sep 17 00:00:00 2001 From: kimden <23140380+kimden@users.noreply.github.com> Date: Wed, 2 Apr 2025 03:35:26 +0400 Subject: [PATCH 2/3] =?UTF-8?q?updateServerOwner=20=E2=86=92=20CrownManage?= =?UTF-8?q?r=20minus=20sort?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/network/protocols/server_lobby.cpp | 76 +++++++++++++++----------- src/utils/crown_manager.cpp | 29 ++++++++++ src/utils/crown_manager.hpp | 6 ++ 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 973053116ae..9d86a4bd3f4 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -2906,54 +2906,65 @@ void ServerLobby::updatePlayerList(bool update_when_reset_server) }, pl); delete pl; } // updatePlayerList - //----------------------------------------------------------------------------- + void ServerLobby::updateServerOwner(bool force) { - if (m_state.load() < WAITING_FOR_START_GAME || - m_state.load() > RESULT_DISPLAY || - getCrownManager()->isOwnerLess()) + ServerState state = m_state.load(); + if (state < WAITING_FOR_START_GAME || state > RESULT_DISPLAY) + return; + + if (getCrownManager()->isOwnerLess()) return; + if (!force && !m_server_owner.expired()) return; + auto peers = STKHost::get()->getPeers(); - if (peers.empty()) - return; - std::sort(peers.begin(), peers.end(), [](const std::shared_ptr a, - const std::shared_ptr b)->bool - { - if (a->isCommandSpectator() ^ b->isCommandSpectator()) - return b->isCommandSpectator(); - return a->getRejoinTime() < b->getRejoinTime(); - }); - std::shared_ptr owner; - for (auto peer: peers) + if (m_process_type != PT_MAIN) { - // Only matching host id can be server owner in case of - // graphics-client-server - if (peer->isValidated() && !peer->isAIPeer() && - (m_process_type == PT_MAIN || - peer->getHostId() == m_client_server_host_id.load())) + auto id = m_client_server_host_id.load(); + for (unsigned i = 0; i < peers.size(); ) { - owner = peer; - break; + const auto& peer = peers[i]; + if (peer->getHostId() != id) + { + std::swap(peers[i], peers.back()); + peers.pop_back(); + continue; + } + ++i; } } - if (owner) + + for (unsigned i = 0; i < peers.size(); ) { - if (m_server_owner.expired() || m_server_owner.lock() != owner) + const auto& peer = peers[i]; + if (!peer->isValidated() || peer->isAIPeer()) { - NetworkString* ns = getNetworkString(); - ns->setSynchronous(true); - ns->addUInt8(LE_SERVER_OWNERSHIP); - owner->sendPacket(ns); - delete ns; + std::swap(peers[i], peers.back()); + peers.pop_back(); + continue; } - m_server_owner = owner; - m_server_owner_id.store(owner->getHostId()); - updatePlayerList(); + ++i; } + + if (peers.empty()) + return; + + std::shared_ptr owner = getCrownManager()->getFirstInCrownOrder(peers); + if (m_server_owner.expired() || m_server_owner.lock() != owner) + { + NetworkString* ns = getNetworkString(); + ns->setSynchronous(true); + ns->addUInt8(LE_SERVER_OWNERSHIP); + owner->sendPacket(ns); + delete ns; + } + m_server_owner = owner; + m_server_owner_id.store(owner->getHostId()); + updatePlayerList(); } // updateServerOwner //----------------------------------------------------------------------------- @@ -3618,6 +3629,7 @@ void ServerLobby::handleServerConfiguration(std::shared_ptr peer, auto assets = peer->getClientAssets(); if (!peer->isValidated() || assets.second.empty()) // this check will fail hard when I introduce vavriable limits continue; + if (getAssetManager()->checkIfNoCommonMaps(assets)) { NetworkString *message = getNetworkString(2); diff --git a/src/utils/crown_manager.cpp b/src/utils/crown_manager.cpp index 3493103d690..65da8cd3f70 100644 --- a/src/utils/crown_manager.cpp +++ b/src/utils/crown_manager.cpp @@ -278,4 +278,33 @@ void CrownManager::setSpectateModeProperly(std::shared_ptr peer, Always if (mode == ASM_NONE) getTeamManager()->checkNoTeamSpectator(peer); } // setSpectateModeProperly +//----------------------------------------------------------------------------- + +// This was a sorting comparator in original code. +// Peers are guaranteed to already be validated and non-AI, +// and eligible for crown (theoretically) +std::shared_ptr CrownManager::getFirstInCrownOrder( + const std::vector>& peers) +{ + if (peers.empty()) // Shouldn't happen but just in case + return {}; + + unsigned best = 0; + for (unsigned i = 1; i < peers.size(); ++i) + if (defaultOrderComparator(peers[i], peers[best])) + best = i; + + return peers[best]; +} // getFirstInCrownOrder +//----------------------------------------------------------------------------- + +bool CrownManager::defaultOrderComparator( + const std::shared_ptr a, + const std::shared_ptr b) +{ + if (a->isCommandSpectator() ^ b->isCommandSpectator()) + return b->isCommandSpectator(); + + return a->getRejoinTime() < b->getRejoinTime(); +} // defaultOrderComparator //----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/crown_manager.hpp b/src/utils/crown_manager.hpp index bf2c3ce0a83..e1731a16971 100644 --- a/src/utils/crown_manager.hpp +++ b/src/utils/crown_manager.hpp @@ -50,6 +50,12 @@ class CrownManager: public LobbyContextComponent void setSpectateModeProperly(std::shared_ptr peer, AlwaysSpectateMode mode); + std::shared_ptr getFirstInCrownOrder( + const std::vector>& peers); + + bool defaultOrderComparator(const std::shared_ptr a, + const std::shared_ptr b); + private: bool m_only_host_riding; bool m_owner_less; From fc6ba847013518606b217ab09297541e408484e5 Mon Sep 17 00:00:00 2001 From: kimden <23140380+kimden@users.noreply.github.com> Date: Wed, 2 Apr 2025 23:16:55 +0400 Subject: [PATCH 3/3] Minus one method --- src/network/protocols/server_lobby.cpp | 19 ++++++------------- src/network/protocols/server_lobby.hpp | 1 - 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 9d86a4bd3f4..f56873d7614 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -1049,7 +1049,9 @@ void ServerLobby::rejectLiveJoin(std::shared_ptr peer, BackLobbyReason reset->addUInt8(LE_BACK_LOBBY).addUInt8(blr); peer->sendPacket(reset, PRM_RELIABLE); delete reset; + updatePlayerList(); + NetworkString* server_info = getNetworkString(); server_info->setSynchronous(true); server_info->addUInt8(LE_SERVER_INFO); @@ -2059,7 +2061,10 @@ void ServerLobby::checkRaceFinished() if (getSettings()->isStoringResults()) { - storeResults(); + if (m_game_info) + m_game_info->fillAndStoreResults(); + else + Log::warn("ServerLobby", "GameInfo is not accessible??"); } if (getSettings()->isRanked()) @@ -4156,18 +4161,6 @@ void ServerLobby::handleServerCommand(Event* event) } // handleServerCommand //----------------------------------------------------------------------------- -void ServerLobby::storeResults() -{ - if (!m_game_info) - { - Log::warn("ServerLobby", "GameInfo is not accessible??"); - return; - } - - m_game_info->fillAndStoreResults(); -} // storeResults -//----------------------------------------------------------------------------- - void ServerLobby::resetToDefaultSettings() { if (getSettings()->isServerConfigurable() && !getSettings()->isPreservingMode()) diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp index d45022f7dd2..5f0d1b01423 100644 --- a/src/network/protocols/server_lobby.hpp +++ b/src/network/protocols/server_lobby.hpp @@ -323,7 +323,6 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser return std::find(m_ai_profiles.begin(), m_ai_profiles.end(), npp) != m_ai_profiles.end(); } - void storeResults(); uint32_t getServerIdOnline() const { return m_server_id_online; } void setClientServerHostId(uint32_t id) { m_client_server_host_id = id; } void resetToDefaultSettings();