From 7cdce09bda9ff18bd02e22ddbe1b3fe95b204192 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Tue, 29 Jul 2025 19:37:35 +0800 Subject: Cache bool setting retrievals in updateDiscordActivity As suggested by Andrey Kleschev. getBOOL and getF32 are expensive, so using `static LLCachedControl<>` is the way to do it in llappviewer.cpp. --- indra/newview/llappviewer.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b5175fbf71..fee2a742f5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5994,7 +5994,8 @@ void LLAppViewer::updateDiscordActivity() return; } - if (gSavedSettings.getBOOL("ShowDiscordActivityDetails")) + static LLCachedControl show_details(gSavedSettings, "ShowDiscordActivityDetails", false); + if (show_details) { LLAvatarName av_name; LLAvatarNameCache::get(gAgent.getID(), &av_name); @@ -6005,7 +6006,8 @@ void LLAppViewer::updateDiscordActivity() activity.SetDetails(name); } - if (gSavedSettings.getBOOL("ShowDiscordActivityState")) + static LLCachedControl show_state(gSavedSettings, "ShowDiscordActivityState", false); + if (show_state) { auto agent_pos_region = gAgent.getPositionAgent(); S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f); @@ -6033,7 +6035,8 @@ void LLAppViewer::updateDiscordActivity() uuid_vec_t chat_radius_uuids, near_me_uuids; auto position = gAgent.getPositionGlobal(); world->getAvatars(&chat_radius_uuids, NULL, position, CHAT_NORMAL_RADIUS); - world->getAvatars(&near_me_uuids, NULL, position, gSavedSettings.getF32("MPVNearMeRange")); + static LLCachedControl range(gSavedSettings, "MPVNearMeRange", 4096.0f); + world->getAvatars(&near_me_uuids, NULL, position, range); discordpp::ActivityParty party; party.SetId(location); party.SetCurrentSize(chat_radius_uuids.size()); -- cgit v1.2.3 From c40796a34472bfe51e7d9956cd5b9b74bd7739cf Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Tue, 29 Jul 2025 19:42:45 +0800 Subject: Check Discord creds existence before getting token as suggested by Andrey Kleshchev, anticipating external factors such as user moving settings from another PC. --- indra/newview/llappviewer.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fee2a742f5..16e2027af1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5933,10 +5933,14 @@ void LLAppViewer::initDiscordSocial() }); if (gSavedSettings.getBOOL("EnableDiscord")) { - gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, gSecAPIHandler->loadCredential("Discord")->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) { - if (result.Successful()) - gDiscordClient->Connect(); - }); + auto credential = gSecAPIHandler->loadCredential("Discord"); + if (credential.notNull()) + { + gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, credential->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) { + if (result.Successful()) + gDiscordClient->Connect(); + }); + } } } @@ -5971,12 +5975,18 @@ void LLAppViewer::handleDiscordSocial(const LLSD& value) } else { - gDiscordClient->RevokeToken(APPLICATION_ID, gSecAPIHandler->loadCredential("Discord")->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) { - if (result.Successful()) - gDiscordClient->Disconnect(); - auto cred = new LLCredential("Discord"); - gSecAPIHandler->deleteCredential(cred); - }); + auto credential = gSecAPIHandler->loadCredential("Discord"); + if (credential.notNull()) + { + gDiscordClient->RevokeToken(APPLICATION_ID, credential->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) { + if (result.Successful()) + { + gDiscordClient->Disconnect(); + } + auto cred = new LLCredential("Discord"); + gSecAPIHandler->deleteCredential(cred); + }); + } } } -- cgit v1.2.3 From 19cf8ae0b0f2fe9a41331c635228c9454b604206 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Tue, 29 Jul 2025 19:46:51 +0800 Subject: Tracy visibility for looped Discord function calls As suggested by Andrey Kleshchev. They likely can get pricey so they need to be visible in the profiler. --- indra/newview/llappviewer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 16e2027af1..de9d380f30 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1356,7 +1356,10 @@ bool LLAppViewer::doFrame() TimePoint fpsLimitFrameStartTime = std::chrono::steady_clock::now(); #ifdef LL_DISCORD - discordpp::RunCallbacks(); + { + LL_PROFILE_ZONE_NAMED("discord_callbacks"); + discordpp::RunCallbacks(); + } #endif LL_RECORD_BLOCK_TIME(FTM_FRAME); @@ -5992,6 +5995,7 @@ void LLAppViewer::handleDiscordSocial(const LLSD& value) void LLAppViewer::updateDiscordActivity() { + LL_PROFILE_ZONE_SCOPED; discordpp::Activity activity; activity.SetType(discordpp::ActivityTypes::Playing); discordpp::ActivityTimestamps timestamps; -- cgit v1.2.3 From 275bc9d0e373c8018167c8f4b0ac79e8b782d0ec Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 30 Jul 2025 12:48:44 +0800 Subject: Discord-related error handling/logging plus delay saving Discord credentials to only after the access token is successfully updated on Discord, and try to disconnect from Discord when the integration gets disabled regardless whether there are credentials to delete or not and whether there's an access token to revoke or not. --- indra/newview/llappviewer.cpp | 50 ++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index de9d380f30..f65b6f309b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5942,8 +5942,15 @@ void LLAppViewer::initDiscordSocial() gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, credential->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) { if (result.Successful()) gDiscordClient->Connect(); + else + LL_WARNS("Discord") << result.Error() << LL_ENDL; }); } + else + { + LL_WARNS("Discord") << "Integration was enabled, but no credentials. Disabling integration." << LL_ENDL; + gSavedSettings.setBOOL("EnableDiscord", false); + } } } @@ -5961,34 +5968,53 @@ void LLAppViewer::handleDiscordSocial(const LLSD& value) if (result.Successful()) { gDiscordClient->GetToken(APPLICATION_ID, code, codeVerifier.Verifier(), redirectUri, [](discordpp::ClientResult result, std::string accessToken, std::string, discordpp::AuthorizationTokenType, int32_t, std::string) { - gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, accessToken, [](discordpp::ClientResult result) { - if (result.Successful()) - gDiscordClient->Connect(); - }); - LLSD authenticator = LLSD::emptyMap(); - authenticator["token"] = accessToken; - gSecAPIHandler->saveCredential(gSecAPIHandler->createCredential("Discord", LLSD::emptyMap(), authenticator), true); + if (result.Successful()) + { + gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, accessToken, [accessToken](discordpp::ClientResult result) { + if (result.Successful()) + { + LLSD authenticator = LLSD::emptyMap(); + authenticator["token"] = accessToken; + gSecAPIHandler->saveCredential(gSecAPIHandler->createCredential("Discord", LLSD::emptyMap(), authenticator), true); + gDiscordClient->Connect(); + } + else + { + LL_WARNS("Discord") << result.Error() << LL_ENDL; + } + }); + } + else + { + LL_WARNS("Discord") << result.Error() << LL_ENDL; + } }); } else { + LL_WARNS("Discord") << result.Error() << LL_ENDL; gSavedSettings.setBOOL("EnableDiscord", false); } }); } else { + gDiscordClient->Disconnect(); auto credential = gSecAPIHandler->loadCredential("Discord"); if (credential.notNull()) { gDiscordClient->RevokeToken(APPLICATION_ID, credential->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) { if (result.Successful()) - { - gDiscordClient->Disconnect(); - } - auto cred = new LLCredential("Discord"); - gSecAPIHandler->deleteCredential(cred); + LL_INFOS("Discord") << "Access token successfully revoked." << LL_ENDL; + else + LL_WARNS("Discord") << "No access token to revoke." << LL_ENDL; }); + auto cred = new LLCredential("Discord"); + gSecAPIHandler->deleteCredential(cred); + } + else + { + LL_WARNS("Discord") << "Credentials are already nonexistent." << LL_ENDL; } } } -- cgit v1.2.3 From 7ddb99117ecdaa1d27719908aca6283a0f90d74e Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 30 Jul 2025 17:06:44 +0800 Subject: Use getAvatars already called for Discord Party numbers so we don't have to make any extra getAvatars calls just for this, as it's pricy in crowds, and we'll just be piggybacking `updateSpeakerList` and `updateNearbyList`. --- indra/newview/llappviewer.cpp | 26 ++++++++++++++++++-------- indra/newview/llappviewer.h | 2 ++ indra/newview/llpanelpeople.cpp | 3 +++ indra/newview/llspeakers.cpp | 3 +++ 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f65b6f309b..ec03377ccb 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -283,6 +283,8 @@ using namespace LL; #include static std::shared_ptr gDiscordClient; static uint64_t gDiscordTimestampsStart; +static int32_t gDiscordPartyCurrentSize; +static int32_t gDiscordPartyMaxSize; #endif static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); @@ -5926,6 +5928,8 @@ void LLAppViewer::metricsSend(bool enable_reporting) void LLAppViewer::initDiscordSocial() { + gDiscordPartyCurrentSize = 1; + gDiscordPartyMaxSize = 0; gDiscordTimestampsStart = time(nullptr); gDiscordClient = std::make_shared(); gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { @@ -6071,20 +6075,26 @@ void LLAppViewer::updateDiscordActivity() auto location = llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z); activity.SetState(location); - auto world = LLWorld::getInstance(); - uuid_vec_t chat_radius_uuids, near_me_uuids; - auto position = gAgent.getPositionGlobal(); - world->getAvatars(&chat_radius_uuids, NULL, position, CHAT_NORMAL_RADIUS); - static LLCachedControl range(gSavedSettings, "MPVNearMeRange", 4096.0f); - world->getAvatars(&near_me_uuids, NULL, position, range); discordpp::ActivityParty party; party.SetId(location); - party.SetCurrentSize(chat_radius_uuids.size()); - party.SetMaxSize(near_me_uuids.size()); + party.SetCurrentSize(gDiscordPartyCurrentSize); + party.SetMaxSize(gDiscordPartyMaxSize); activity.SetParty(party); } gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); } +void LLAppViewer::updateDiscordPartyCurrentSize(int32_t size) +{ + gDiscordPartyCurrentSize = size; + updateDiscordActivity(); +} + +void LLAppViewer::updateDiscordPartyMaxSize(int32_t size) +{ + gDiscordPartyMaxSize = size; + updateDiscordActivity(); +} + #endif diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 283975833e..b60f7ae084 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -254,6 +254,8 @@ public: static void initDiscordSocial(); static void handleDiscordSocial(const LLSD& value); static void updateDiscordActivity(); + static void updateDiscordPartyCurrentSize(int32_t size); + static void updateDiscordPartyMaxSize(int32_t size); #endif protected: diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 72fa553023..da7f524146 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -843,6 +843,9 @@ void LLPanelPeople::updateNearbyList() LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("MPVNearMeRange")); mNearbyList->setDirty(); +#ifdef LL_DISCORD + LLAppViewer::updateDiscordPartyMaxSize(mNearbyList->getIDs().size()); +#endif DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); LLActiveSpeakerMgr::instance().update(true); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 4956c188fb..46a88ba512 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -1026,6 +1026,9 @@ void LLLocalSpeakerMgr::updateSpeakerList() uuid_vec_t avatar_ids; std::vector positions; LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS); +#ifdef LL_DISCORD + LLAppViewer::updateDiscordPartyCurrentSize(avatar_ids.size()); +#endif for(U32 i=0; i Date: Wed, 30 Jul 2025 17:53:36 +0800 Subject: Assemble Discord Activity Details only once by saving it to a static global string for reuse. --- indra/newview/llappviewer.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ec03377ccb..252c3adec0 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -283,6 +283,7 @@ using namespace LL; #include static std::shared_ptr gDiscordClient; static uint64_t gDiscordTimestampsStart; +static std::string gDiscordActivityDetails; static int32_t gDiscordPartyCurrentSize; static int32_t gDiscordPartyMaxSize; #endif @@ -6041,13 +6042,16 @@ void LLAppViewer::updateDiscordActivity() static LLCachedControl show_details(gSavedSettings, "ShowDiscordActivityDetails", false); if (show_details) { - LLAvatarName av_name; - LLAvatarNameCache::get(gAgent.getID(), &av_name); - auto name = av_name.getUserName(); - auto displayName = av_name.getDisplayName(); - if (name != displayName) - name = displayName + " (" + name + ")"; - activity.SetDetails(name); + if (gDiscordActivityDetails.empty()) + { + LLAvatarName av_name; + LLAvatarNameCache::get(gAgent.getID(), &av_name); + gDiscordActivityDetails = av_name.getUserName(); + auto displayName = av_name.getDisplayName(); + if (gDiscordActivityDetails != displayName) + gDiscordActivityDetails = displayName + " (" + gDiscordActivityDetails + ")"; + } + activity.SetDetails(gDiscordActivityDetails); } static LLCachedControl show_state(gSavedSettings, "ShowDiscordActivityState", false); -- cgit v1.2.3 From ee69e4fdd4566f1ffd44c46e799d5b9a0b653076 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 30 Jul 2025 18:07:24 +0800 Subject: Remove updateDiscordActivity call in startup loop The State field (region & coords) is updated well enough without it now. --- indra/newview/llstartup.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index dfad169813..8d010553a0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2327,10 +2327,6 @@ bool idle_startup() do_startup_frame(); } -#ifdef LL_DISCORD - LLAppViewer::updateDiscordActivity(); -#endif - return true; } -- cgit v1.2.3 From b929c7f6fd5260d8442b57c9027cbdd8556b4a84 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 30 Jul 2025 22:18:58 +0800 Subject: Rename handleDiscordSocial to toggleDiscordIntegration --- indra/newview/llappviewer.cpp | 2 +- indra/newview/llappviewer.h | 2 +- indra/newview/llfloaterpreference.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 252c3adec0..8dec75e64e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5959,7 +5959,7 @@ void LLAppViewer::initDiscordSocial() } } -void LLAppViewer::handleDiscordSocial(const LLSD& value) +void LLAppViewer::toggleDiscordIntegration(const LLSD& value) { static const uint64_t APPLICATION_ID = 1393451183741599796; if (value.asBoolean()) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index b60f7ae084..61a568a151 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -252,7 +252,7 @@ public: #ifdef LL_DISCORD static void initDiscordSocial(); - static void handleDiscordSocial(const LLSD& value); + static void toggleDiscordIntegration(const LLSD& value); static void updateDiscordActivity(); static void updateDiscordPartyCurrentSize(int32_t size); static void updateDiscordPartyMaxSize(int32_t size); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 4c8122bf71..2a6360cef8 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -367,7 +367,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this)); mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // Hook up for filtering #ifdef LL_DISCORD - gSavedSettings.getControl("EnableDiscord")->getCommitSignal()->connect(boost::bind(&LLAppViewer::handleDiscordSocial, _2)); + gSavedSettings.getControl("EnableDiscord")->getCommitSignal()->connect(boost::bind(&LLAppViewer::toggleDiscordIntegration, _2)); gSavedSettings.getControl("ShowDiscordActivityDetails")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity)); gSavedSettings.getControl("ShowDiscordActivityState")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity)); #endif -- cgit v1.2.3 From 0146a8b3119e2c6c652dd7b608de9efcdbd3fd50 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 30 Jul 2025 22:22:36 +0800 Subject: Update Discord Activity only when integration is enabled No need to check setting for the status change callback one, because getting there would need to be connected to Discord first, which in turn needs the integration to be enabled first. --- indra/newview/llpanelpeople.cpp | 3 ++- indra/newview/llspeakers.cpp | 3 ++- indra/newview/llviewermessage.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index da7f524146..bf2462d7d9 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -844,7 +844,8 @@ void LLPanelPeople::updateNearbyList() LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("MPVNearMeRange")); mNearbyList->setDirty(); #ifdef LL_DISCORD - LLAppViewer::updateDiscordPartyMaxSize(mNearbyList->getIDs().size()); + if (gSavedSettings.getBOOL("EnableDiscord")) + LLAppViewer::updateDiscordPartyMaxSize(mNearbyList->getIDs().size()); #endif DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 46a88ba512..12a9d5e9b7 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -1027,7 +1027,8 @@ void LLLocalSpeakerMgr::updateSpeakerList() std::vector positions; LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS); #ifdef LL_DISCORD - LLAppViewer::updateDiscordPartyCurrentSize(avatar_ids.size()); + if (gSavedSettings.getBOOL("EnableDiscord")) + LLAppViewer::updateDiscordPartyCurrentSize(avatar_ids.size()); #endif for(U32 i=0; i Date: Thu, 31 Jul 2025 20:42:38 +0800 Subject: Optimise nearby tab distance & arrival time impl by not having extra calls to getAvatars, by avoiding unnecessary function overhead which actually make it possible to share some iterative code, and by piggybacking updateNearbyList and updateArrivalTime which is already done periodically though the range had to be lengthened to match nearby list range which is MPVNearMeRange instead of SLv's NearMeRange. Minimise differences from SLv too (arrival time really doesn't need to be updated *every* second.. every 5 seconds is just okay). --- indra/newview/llavatarlist.cpp | 70 +++++++++++++---------------------------- indra/newview/llavatarlist.h | 4 +-- indra/newview/llpanelpeople.cpp | 4 ++- 3 files changed, 27 insertions(+), 51 deletions(-) diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 5f9d03ca66..834288a93e 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -48,12 +48,11 @@ #include "llvoiceclient.h" #include "llviewercontrol.h" // for gSavedSettings #include "lltooldraganddrop.h" -#include "llworld.h" static LLDefaultChildRegistry::Register r("avatar_list"); // Last interaction time update period. -static const F32 LIT_UPDATE_PERIOD = 1; +static const F32 LIT_UPDATE_PERIOD = 5; // Maximum number of avatars that can be added to a list in one pass. // Used to limit time spent for avatar list update per frame. @@ -187,6 +186,12 @@ std::string LLAvatarList::getAvatarName(LLAvatarName av_name) return mShowCompleteName? av_name.getCompleteName(false, mForceCompleteName) : av_name.getDisplayName(); } +void LLAvatarList::setAvatarsPositions(const std::map& avatarsPositions) +{ + mAvatarsPositions.clear(); + mAvatarsPositions = avatarsPositions; +} + // virtual void LLAvatarList::draw() { @@ -205,13 +210,22 @@ void LLAvatarList::draw() if ((mShowLastInteractionTime || mAvatarDistance || mAvatarArrivalTime) && mLITUpdateTimer->hasExpired()) { - if (mAvatarArrivalTime) + if (mAvatarArrivalTime || mAvatarDistance) { - updateAvatarArrivalTime(); - } - if (mAvatarDistance) - { - updateAvatarDistance(); + std::vector items; + getItems(items); + for (auto it = items.begin(); it != items.end(); it++) + { + auto item = static_cast(*it); + if (mAvatarArrivalTime) + { + auto secs_since = LLDate::now().secondsSinceEpoch() - LLRecentPeople::instance().getArrivalTimeByID(item->getAvatarId()); + if (secs_since >= 0) + item->setAvatarArrivalTime(secs_since); + } + if (mAvatarDistance) + item->setAvatarDistance(dist_vec(mAvatarsPositions[item->getAvatarId()], gAgent.getPositionGlobal())); + } } if (mShowLastInteractionTime) { @@ -554,46 +568,6 @@ void LLAvatarList::computeDifference( LLCommonUtils::computeDifference(vnew_unsorted, vcur, vadded, vremoved); } -void LLAvatarList::updateAvatarArrivalTime() -{ - std::vector items; - getItems(items); - auto uuids = getIDs(); - std::vector positions; - auto me_pos = gAgent.getPositionGlobal(); - LLWorld::getInstance()->getAvatars(&uuids, &positions, me_pos, gSavedSettings.getF32("MPVNearMeRange")); - LLRecentPeople::instance().updateAvatarsArrivalTime(uuids); - for (auto it = items.begin(); it != items.end(); it++) - { - auto item = static_cast(*it); - auto secs_since = LLDate::now().secondsSinceEpoch() - LLRecentPeople::instance().getArrivalTimeByID(item->getAvatarId()); - if (secs_since >= 0) - item->setAvatarArrivalTime(secs_since); - } -} - - void LLAvatarList::updateAvatarDistance() -{ - std::vector items; - getItems(items); - auto uuids = getIDs(); - std::vector positions; - auto me_pos = gAgent.getPositionGlobal(); - LLWorld::getInstance()->getAvatars(&uuids, &positions, me_pos, gSavedSettings.getF32("MPVNearMeRange")); - std::map avatarsPositions; - auto pos_it = positions.begin(); - auto id_it = uuids.begin(); - for (;pos_it != positions.end() && id_it != uuids.end(); ++pos_it, ++id_it) - { - avatarsPositions[*id_it] = *pos_it; - } - for (auto it = items.begin(); it != items.end(); it++) - { - auto item = static_cast(*it); - item->setAvatarDistance(dist_vec(avatarsPositions[item->getAvatarId()], me_pos)); - } -} - // Refresh shown time of our last interaction with all listed avatars. void LLAvatarList::updateLastInteractionTimes() { diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 97b4f05985..5ef7eeb041 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -74,6 +74,7 @@ public: uuid_vec_t& getIDs() { return mIDs; } bool contains(const LLUUID& id); + void setAvatarsPositions(const std::map& avatarsPositions); void setContextMenu(LLListContextMenu* menu) { mContextMenu = menu; } void setSessionID(const LLUUID& session_id) { mSessionID = session_id; } const LLUUID& getSessionID() { return mSessionID; } @@ -114,8 +115,6 @@ protected: const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved); - void updateAvatarArrivalTime(); - void updateAvatarDistance(); void updateLastInteractionTimes(); void rebuildNames(); void onItemDoubleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); @@ -144,6 +143,7 @@ private: uuid_vec_t mIDs; LLUUID mSessionID; + std::map mAvatarsPositions; LLListContextMenu* mContextMenu; commit_signal_t mRefreshCompleteSignal; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index bf2462d7d9..6d1c71b893 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -160,6 +160,7 @@ public: mAvatarsPositions[*id_it] = *pos_it; } }; + const id_to_pos_map_t& getAvatarsPositions() const { return mAvatarsPositions; } protected: virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const @@ -849,6 +850,7 @@ void LLPanelPeople::updateNearbyList() #endif DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); + mNearbyList->setAvatarsPositions(DISTANCE_COMPARATOR.getAvatarsPositions()); LLActiveSpeakerMgr::instance().update(true); } @@ -1569,7 +1571,7 @@ bool LLPanelPeople::updateNearbyArrivalTime() { std::vector positions; std::vector uuids; - static LLCachedControl range(gSavedSettings, "NearMeRange"); + static LLCachedControl range(gSavedSettings, "MPVNearMeRange"); LLWorld::getInstance()->getAvatars(&uuids, &positions, gAgent.getPositionGlobal(), range); LLRecentPeople::instance().updateAvatarsArrivalTime(uuids); return LLApp::isExiting(); -- cgit v1.2.3 From 3c464b4d8bb9bed58edc0418a8c91e8a609b5160 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Thu, 31 Jul 2025 23:39:09 +0800 Subject: Optimise arrival & departure notifications by not having extra calls to getAvatars. The avatars' positions member had to be moved to an object that is accessible from VOAvatar too, and that would be the global Agent. It makes sense too, that it's the object that keeps the positions of other agents. It even has a section for positions too. --- indra/newview/llagent.cpp | 6 ++++++ indra/newview/llagent.h | 3 +++ indra/newview/llavatarlist.cpp | 11 ++++------- indra/newview/llavatarlist.h | 2 -- indra/newview/llpanelpeople.cpp | 2 +- indra/newview/llvoavatar.cpp | 41 ++++++++++++++++------------------------- 6 files changed, 30 insertions(+), 35 deletions(-) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f7b48d25f2..0cd343b46e 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1305,6 +1305,12 @@ const LLVector3 &LLAgent::getPositionAgent() return mFrameAgent.getOrigin(); } +void LLAgent::setAvatarsPositions(const std::map& avatarsPositions) +{ + mAvatarsPositions.clear(); + mAvatarsPositions = avatarsPositions; +} + boost::signals2::connection LLAgent::whenPositionChanged(position_signal_t::slot_type fn) { return mOnPositionChanged.connect(fn); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index b475782946..a2d2ecea9f 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -195,6 +195,8 @@ public: // Call once per frame to update position, angles (radians). void updateAgentPosition(const F32 dt, const F32 yaw, const S32 mouse_x, const S32 mouse_y); void setPositionAgent(const LLVector3 ¢er); + void setAvatarsPositions(const std::map& avatarsPositions); + const std::map& getAvatarsPositions() const { return mAvatarsPositions;} boost::signals2::connection whenPositionChanged(position_signal_t::slot_type fn); @@ -205,6 +207,7 @@ private: position_signal_t mOnPositionChanged; LLVector3d mLastTestGlobal; + std::map mAvatarsPositions; //-------------------------------------------------------------------- // Velocity diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 834288a93e..e29be0c757 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -186,12 +186,6 @@ std::string LLAvatarList::getAvatarName(LLAvatarName av_name) return mShowCompleteName? av_name.getCompleteName(false, mForceCompleteName) : av_name.getDisplayName(); } -void LLAvatarList::setAvatarsPositions(const std::map& avatarsPositions) -{ - mAvatarsPositions.clear(); - mAvatarsPositions = avatarsPositions; -} - // virtual void LLAvatarList::draw() { @@ -224,7 +218,10 @@ void LLAvatarList::draw() item->setAvatarArrivalTime(secs_since); } if (mAvatarDistance) - item->setAvatarDistance(dist_vec(mAvatarsPositions[item->getAvatarId()], gAgent.getPositionGlobal())); + { + auto avatarsPositions = gAgent.getAvatarsPositions(); + item->setAvatarDistance(dist_vec(avatarsPositions[item->getAvatarId()], gAgent.getPositionGlobal())); + } } } if (mShowLastInteractionTime) diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 5ef7eeb041..e6e0728a3f 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -74,7 +74,6 @@ public: uuid_vec_t& getIDs() { return mIDs; } bool contains(const LLUUID& id); - void setAvatarsPositions(const std::map& avatarsPositions); void setContextMenu(LLListContextMenu* menu) { mContextMenu = menu; } void setSessionID(const LLUUID& session_id) { mSessionID = session_id; } const LLUUID& getSessionID() { return mSessionID; } @@ -143,7 +142,6 @@ private: uuid_vec_t mIDs; LLUUID mSessionID; - std::map mAvatarsPositions; LLListContextMenu* mContextMenu; commit_signal_t mRefreshCompleteSignal; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 6d1c71b893..aca8cf189b 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -850,7 +850,7 @@ void LLPanelPeople::updateNearbyList() #endif DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); - mNearbyList->setAvatarsPositions(DISTANCE_COMPARATOR.getAvatarsPositions()); + gAgent.setAvatarsPositions(DISTANCE_COMPARATOR.getAvatarsPositions()); LLActiveSpeakerMgr::instance().update(true); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 53832422d8..082b1349cf 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -818,7 +818,8 @@ LLVOAvatar::~LLVOAvatar() { sInstances.remove(this); - if (gSavedSettings.getBOOL("IMShowArrivalsDepartures")) + static LLCachedControl show_arrival_departures(gSavedSettings, "IMShowArrivalsDepartures", false); + if (show_arrival_departures) { LLAvatarName av_name; LLAvatarNameCache::get(getID(), &av_name); @@ -2583,31 +2584,21 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, { mDebugExistenceTimer.reset(); debugAvatarRezTime("AvatarRezArrivedNotification", "avatar arrived"); - if (gSavedSettings.getBOOL("IMShowArrivalsDepartures")) + static LLCachedControl show_arrival_departures(gSavedSettings, "IMShowArrivalsDepartures", false); + if (show_arrival_departures) { - uuid_vec_t uuids; - std::vector positions; - LLWorld::getInstance()->getAvatars(&uuids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("MPVNearMeRange")); - auto pos_it = positions.begin(); - auto id_it = uuids.begin(); - for (;pos_it != positions.end() && id_it != uuids.end(); ++pos_it, ++id_it) - { - if (*id_it == getID() && !isSelf()) - { - LLAvatarName av_name; - LLAvatarNameCache::get(getID(), &av_name); - auto display_name = av_name.getDisplayName(); - if (!display_name.empty()) - { - LLChat chat{llformat("%s arrived (%.1f m).", display_name.c_str(), dist_vec(*pos_it, gAgent.getPositionGlobal()))}; - chat.mFromName = display_name; - chat.mFromID = getID(); - LLSD args; - args["COLOR"] = "ChatHistoryTextColor"; - LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); - } - break; - } + LLAvatarName av_name; + LLAvatarNameCache::get(getID(), &av_name); + auto display_name = av_name.getDisplayName(); + if (!display_name.empty()) + { + auto avatarsPositions = gAgent.getAvatarsPositions(); + LLChat chat{llformat("%s arrived (%.1f m).", display_name.c_str(), dist_vec(avatarsPositions[getID()], gAgent.getPositionGlobal()))}; + chat.mFromName = display_name; + chat.mFromID = getID(); + LLSD args; + args["COLOR"] = "ChatHistoryTextColor"; + LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); } } } -- cgit v1.2.3 From 7588afc86a016c00e6263284bc0db6d684c43895 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Fri, 1 Aug 2025 18:25:28 +0800 Subject: Increase chance of arrival notification, correctly Full (user) name should suffice for the chat log, as it's the one that is more of a reference anyway instead of display name. The other avatar's display name is still displayed on the header anyway. Seems like display names have higher chance of being empty, that we would miss it being logged/notified because of that. Also, now that we've optimised the avatars' positions' retrieval, the numbers can come later after some avatar arrives, that getting the position using the avatar's ID as the key would result in zero. In that case, rather than reporting wrong distances (like 403996.2), it's better to just skip distance information (it shouldn't matter that much anyway). --- indra/newview/llvoavatar.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 082b1349cf..f52d45b4b9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -821,13 +821,11 @@ LLVOAvatar::~LLVOAvatar() static LLCachedControl show_arrival_departures(gSavedSettings, "IMShowArrivalsDepartures", false); if (show_arrival_departures) { - LLAvatarName av_name; - LLAvatarNameCache::get(getID(), &av_name); - auto display_name = av_name.getDisplayName(); - if (!display_name.empty()) + auto full_name = getFullname(); + if (!full_name.empty()) { - LLChat chat{llformat("%s left.", display_name.c_str())}; - chat.mFromName = display_name; + LLChat chat{llformat("%s left.", full_name.c_str())}; + chat.mFromName = full_name; chat.mFromID = getID(); LLSD args; args["COLOR"] = "ChatHistoryTextColor"; @@ -2587,15 +2585,15 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, static LLCachedControl show_arrival_departures(gSavedSettings, "IMShowArrivalsDepartures", false); if (show_arrival_departures) { - LLAvatarName av_name; - LLAvatarNameCache::get(getID(), &av_name); - auto display_name = av_name.getDisplayName(); - if (!display_name.empty()) + auto full_name = getFullname(); + if (!full_name.empty()) { auto avatarsPositions = gAgent.getAvatarsPositions(); - LLChat chat{llformat("%s arrived (%.1f m).", display_name.c_str(), dist_vec(avatarsPositions[getID()], gAgent.getPositionGlobal()))}; - chat.mFromName = display_name; - chat.mFromID = getID(); + auto id = getID(); + auto avatarPosition = avatarsPositions[id]; + LLChat chat{std::string{full_name + " arrived" + (avatarPosition.isExactlyZero() ? "" : llformat(" (%.1f m)", dist_vec(avatarPosition, gAgent.getPositionGlobal()))) + "."}}; + chat.mFromName = full_name; + chat.mFromID = id; LLSD args; args["COLOR"] = "ChatHistoryTextColor"; LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); -- cgit v1.2.3