From c6fad73657aaa07e439aab94f6349a173c06e1de Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 23 Jul 2025 06:57:11 +0800 Subject: Fix linking to c_dfDIJoystick error when on SDL Copied from llwindowwin32.cpp. --- indra/llwindow/llwindowsdl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 69332e36b6..1f9a841032 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -106,6 +106,10 @@ bool hasHIDPI = 0; # include #endif //LL_X11 +#if LL_WINDOWS && !LL_MESA_HEADLESS +#pragma comment(lib, "dinput8") +#endif + // TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for a similar // set of reasons): Stash a pointer to the LLWindowSDL object here and // maintain in the constructor and destructor. This assumes that there will -- cgit v1.2.3 From f0f3169e8ea14219ae179efdebf87a395ae5a029 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 23 Jul 2025 21:07:10 +0800 Subject: RLV shared folder needs to be directly under root --- indra/newview/rlvhandler.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 066543987f..18de822512 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -29,6 +29,7 @@ #include "llagent.h" #include "llstartup.h" #include "llappearancemgr.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llmoveview.h" #include "llviewercontrol.h" @@ -243,9 +244,11 @@ ECmdRet ReplyHandler::onCommand(const RlvCommand& rlvCmd, template<> template<> ECmdRet ReplyHandler::onCommand(const RlvCommand& rlvCmd, std::string& strReply) { - auto folderID = findDescendentCategoryIDByName(gInventory.getRootFolderID(), "#RLV"); - if (folderID == LLUUID::null) + auto folderID = gInventory.getRootFolderID(); + LLNameCategoryCollector has_name("#RLV"); + if (!gInventory.hasMatchingDirectDescendent(folderID, has_name)) return ECmdRet::FailedNoSharedRoot; + folderID = findDescendentCategoryIDByName(folderID, "#RLV"); strReply = ""; LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; -- cgit v1.2.3 From 1878bf4eb76e4a79d1622aa6b907362bb94bc0f6 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 23 Jul 2025 21:08:12 +0800 Subject: Shared macros for attach-related RLV commands --- indra/newview/rlvhandler.cpp | 78 +++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 18de822512..e9bd715a98 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -307,58 +307,48 @@ ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) return ECmdRet::Succeeded; } +#define RESTRAINED_LOVE_OUTFIT(A) \ + auto folderID = gInventory.getRootFolderID();\ + LLNameCategoryCollector has_name("#RLV");\ + if (!gInventory.hasMatchingDirectDescendent(folderID, has_name))\ + return ECmdRet::FailedNoSharedRoot;\ + folderID = findDescendentCategoryIDByName(folderID, "#RLV");\ + std::vector optionList;\ + auto option = rlvCmd.getOption();\ + if (!option.empty())\ + {\ + folderID = findDescendentCategoryIDByName(folderID, option);\ + if (folderID == LLUUID::null)\ + {\ + Util::parseStringList(option, optionList, "/");\ + auto iter = optionList.begin();\ + for(; optionList.end() != iter; ++iter)\ + {\ + auto name = *iter;\ + if (!name.empty())\ + folderID = findDescendentCategoryIDByName(folderID, name);\ + }\ + }\ + A\ + }\ + return ECmdRet::Succeeded; + +#define RESTRAINED_LOVE_REPLACE \ + LLAppearanceMgr::instance().replaceCurrentOutfit(folderID); + +#define RESTRAINED_LOVE_ADD \ + LLAppearanceMgr::instance().addCategoryToCurrentOutfit(folderID); + template<> template<> ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) { - auto rlvFolderID = findDescendentCategoryIDByName(gInventory.getRootFolderID(), "#RLV"); - if (rlvFolderID == LLUUID::null) - return ECmdRet::FailedNoSharedRoot; - std::vector optionList; - auto option = rlvCmd.getOption(); - if (!option.empty()) - { - auto folderID = findDescendentCategoryIDByName(rlvFolderID, option); - if (folderID == LLUUID::null) - { - Util::parseStringList(option, optionList, "/"); - auto iter = optionList.begin(); - for(; optionList.end() != iter; ++iter) - { - auto name = *iter; - if (!name.empty()) - folderID = findDescendentCategoryIDByName(folderID, name); - } - } - LLAppearanceMgr::instance().replaceCurrentOutfit(folderID); - } - return ECmdRet::Succeeded; + RESTRAINED_LOVE_OUTFIT(RESTRAINED_LOVE_REPLACE); } template<> template<> ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) { - auto rlvFolderID = findDescendentCategoryIDByName(gInventory.getRootFolderID(), "#RLV"); - if (rlvFolderID == LLUUID::null) - return ECmdRet::FailedNoSharedRoot; - std::vector optionList; - auto option = rlvCmd.getOption(); - if (!option.empty()) - { - auto folderID = findDescendentCategoryIDByName(rlvFolderID, option); - if (folderID == LLUUID::null) - { - Util::parseStringList(option, optionList, "/"); - auto iter = optionList.begin(); - for(; optionList.end() != iter; ++iter) - { - auto name = *iter; - if (!name.empty()) - folderID = findDescendentCategoryIDByName(folderID, name); - } - } - LLAppearanceMgr::instance().addCategoryToCurrentOutfit(folderID); - } - return ECmdRet::Succeeded; + RESTRAINED_LOVE_OUTFIT(RESTRAINED_LOVE_ADD); } // AddRem -- cgit v1.2.3 From 4ad9d65514374006a9474c9fd42254c95680458f Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 23 Jul 2025 21:41:07 +0800 Subject: @detach:=force implementation Per specification, the folder must be directly under "#RLV" for this to work, hence not using the shared folder ID retrieval macro. --- indra/newview/rlvhandler.cpp | 22 ++++++++++++++++++++++ indra/newview/rlvhelper.cpp | 1 + 2 files changed, 23 insertions(+) diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index e9bd715a98..14343143cd 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -351,6 +351,28 @@ ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd RESTRAINED_LOVE_OUTFIT(RESTRAINED_LOVE_ADD); } +template<> template<> +ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) +{ + auto folderID = gInventory.getRootFolderID(); + LLNameCategoryCollector has_name("#RLV"); + if (!gInventory.hasMatchingDirectDescendent(folderID, has_name)) + return ECmdRet::FailedNoSharedRoot; + folderID = findDescendentCategoryIDByName(folderID, "#RLV"); + std::vector optionList; + auto option = rlvCmd.getOption(); + if (!option.empty()) + { + LLNameCategoryCollector is_named(option); + if (gInventory.hasMatchingDirectDescendent(folderID, is_named)) + { + folderID = findDescendentCategoryIDByName(folderID, option); + LLAppearanceMgr::instance().takeOffOutfit(folderID); + } + } + return ECmdRet::Succeeded; +} + // AddRem ECmdRet CommandHandlerBaseImpl::processCommand(const RlvCommand& rlvCmd, BhvrHandlerFunc* pHandler, BhvrToggleHandlerFunc* pToggleHandler) diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 4a0b394acb..53f07b9bd3 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -62,6 +62,7 @@ BehaviourDictionary::BehaviourDictionary() addEntry(new ForceProcessor("unsit")); addEntry(new ForceProcessor("attach")); addEntry(new ForceProcessor("attachover")); + addEntry(new ForceProcessor("detach")); // AddRem addEntry(new BehaviourProcessor("sit")); -- cgit v1.2.3 From f31e224bbd8bf522542a16ec116f21de12a397ef Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 23 Jul 2025 22:21:54 +0800 Subject: Minimal @remoutfit[:]=force implementation Copying from LLEditTakeOff implementation in llviewermenu.cpp. --- indra/newview/rlvdefines.h | 1 + indra/newview/rlvhandler.cpp | 24 ++++++++++++++++++++++++ indra/newview/rlvhelper.cpp | 1 + 3 files changed, 26 insertions(+) diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 649aa75d14..4437adcf1b 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -98,6 +98,7 @@ namespace Rlv SitGround, Unsit, Detach, + RemOutfit, GetInv, Attach, AttachOver, diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 14343143cd..8eee7e36a6 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -339,6 +339,30 @@ ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) #define RESTRAINED_LOVE_ADD \ LLAppearanceMgr::instance().addCategoryToCurrentOutfit(folderID); +template<> template<> +ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) +{ + std::vector optionList; + auto option = rlvCmd.getOption(); + if (option.empty()) + { + LLAppearanceMgr::instance().removeAllClothesFromAvatar(); + } + else + { + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(option); + if (type >= LLWearableType::WT_SHAPE + && type < LLWearableType::WT_COUNT + && (gAgentWearables.getWearableCount(type) > 0)) + { + U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; + LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); + LLAppearanceMgr::instance().removeItemFromAvatar(item_id); + } + } + return ECmdRet::Succeeded; +} + template<> template<> ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) { diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 53f07b9bd3..2c14434194 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -60,6 +60,7 @@ BehaviourDictionary::BehaviourDictionary() addEntry(new ForceProcessor("sit")); addEntry(new ForceProcessor("sitground")); addEntry(new ForceProcessor("unsit")); + addEntry(new ForceProcessor("remoutfit")); addEntry(new ForceProcessor("attach")); addEntry(new ForceProcessor("attachover")); addEntry(new ForceProcessor("detach")); -- cgit v1.2.3 From 145ae5aeea43080bbf14de66d3d3886e01b8bb34 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Wed, 23 Jul 2025 22:31:19 +0800 Subject: Reorganise shared macros closer to "attach" code and reindent the appearance manager functions to call to match how they will be placed on the combining macro. --- indra/newview/rlvhandler.cpp | 52 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 8eee7e36a6..2cc06b3bbc 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -307,6 +307,30 @@ ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) return ECmdRet::Succeeded; } +template<> template<> +ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) +{ + std::vector optionList; + auto option = rlvCmd.getOption(); + if (option.empty()) + { + LLAppearanceMgr::instance().removeAllClothesFromAvatar(); + } + else + { + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(option); + if (type >= LLWearableType::WT_SHAPE + && type < LLWearableType::WT_COUNT + && (gAgentWearables.getWearableCount(type) > 0)) + { + U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; + LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); + LLAppearanceMgr::instance().removeItemFromAvatar(item_id); + } + } + return ECmdRet::Succeeded; +} + #define RESTRAINED_LOVE_OUTFIT(A) \ auto folderID = gInventory.getRootFolderID();\ LLNameCategoryCollector has_name("#RLV");\ @@ -334,34 +358,10 @@ ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) return ECmdRet::Succeeded; #define RESTRAINED_LOVE_REPLACE \ - LLAppearanceMgr::instance().replaceCurrentOutfit(folderID); + LLAppearanceMgr::instance().replaceCurrentOutfit(folderID); #define RESTRAINED_LOVE_ADD \ - LLAppearanceMgr::instance().addCategoryToCurrentOutfit(folderID); - -template<> template<> -ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) -{ - std::vector optionList; - auto option = rlvCmd.getOption(); - if (option.empty()) - { - LLAppearanceMgr::instance().removeAllClothesFromAvatar(); - } - else - { - LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(option); - if (type >= LLWearableType::WT_SHAPE - && type < LLWearableType::WT_COUNT - && (gAgentWearables.getWearableCount(type) > 0)) - { - U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; - LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); - LLAppearanceMgr::instance().removeItemFromAvatar(item_id); - } - } - return ECmdRet::Succeeded; -} + LLAppearanceMgr::instance().addCategoryToCurrentOutfit(folderID); template<> template<> ECmdRet ForceHandler::onCommand(const RlvCommand& rlvCmd) -- cgit v1.2.3 From dccf087d652ecf98d24927a397c38cc0c9db3ab4 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Sun, 27 Jul 2025 14:26:47 +0800 Subject: Move Discord-related code to llappviewer.cpp The doFrame is the one called over and over again, so running the Discord callbacks from there shouldn't have one extra function overhead, while running the Discord initialisation is only once so it's much more okay to have the extra function overhead there. --- indra/newview/llappviewer.cpp | 44 +++++++++++++++++++++++++++++++++++++++++- indra/newview/llappviewer.h | 5 +++++ indra/newview/llstartup.cpp | 44 +----------------------------------------- indra/newview/llstartup.h | 5 ----- indra/newview/llviewermenu.cpp | 3 ++- 5 files changed, 51 insertions(+), 50 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 419d2cb842..d70287ac83 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -278,6 +278,12 @@ using namespace LL; #pragma warning (disable:4702) #endif +#ifdef LL_DISCORD +#define DISCORDPP_IMPLEMENTATION +#include +static std::shared_ptr gDiscordClient; +#endif + static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor @@ -1349,7 +1355,7 @@ bool LLAppViewer::doFrame() TimePoint fpsLimitFrameStartTime = std::chrono::steady_clock::now(); #ifdef LL_DISCORD - LLStartUp::runDiscordCallbacks(); + discordpp::RunCallbacks(); #endif LL_RECORD_BLOCK_TIME(FTM_FRAME); @@ -5911,3 +5917,39 @@ void LLAppViewer::metricsSend(bool enable_reporting) // resolution in time. gViewerAssetStats->restart(); } + +#ifdef LL_DISCORD + +void LLAppViewer::initDiscordSocial() +{ + gDiscordClient = std::make_shared(); + gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { + if (status == discordpp::Client::Status::Ready) { + discordpp::Activity activity; + activity.SetType(discordpp::ActivityTypes::Playing); + gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); + } + }); +} + +void LLAppViewer::handleDiscordSocial() +{ + static const uint64_t DISCORD_APPLICATION_ID = 1393451183741599796; + discordpp::AuthorizationArgs discordAuthArgs{}; + discordAuthArgs.SetClientId(DISCORD_APPLICATION_ID); + discordAuthArgs.SetScopes(discordpp::Client::GetDefaultPresenceScopes()); + auto discordCodeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier(); + discordAuthArgs.SetCodeChallenge(discordCodeVerifier.Challenge()); + gDiscordClient->Authorize(discordAuthArgs, [discordCodeVerifier](auto result, auto code, auto redirectUri) { + if (result.Successful()) { + gDiscordClient->GetToken(DISCORD_APPLICATION_ID, code, discordCodeVerifier.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(); + }); + }); + } + }); +} + +#endif diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 3da0246ccf..dc10738249 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -250,6 +250,11 @@ public: // Note: mQuitRequested can be aborted by user. void outOfMemorySoftQuit(); +#ifdef LL_DISCORD + static void initDiscordSocial(); + static void handleDiscordSocial(); +#endif + protected: virtual bool initWindow(); // Initialize the viewer's window. virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 834b99555e..8d010553a0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -217,12 +217,6 @@ #include "fsfloatersearch.h" -#ifdef LL_DISCORD -#define DISCORDPP_IMPLEMENTATION -#include -static std::shared_ptr gDiscordClient; -#endif - // // exported globals // @@ -758,14 +752,7 @@ bool idle_startup() } #ifdef LL_DISCORD - gDiscordClient = std::make_shared(); - gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { - if (status == discordpp::Client::Status::Ready) { - discordpp::Activity activity; - activity.SetType(discordpp::ActivityTypes::Playing); - gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); - } - }); + LLAppViewer::initDiscordSocial(); #endif // @@ -3447,35 +3434,6 @@ bool LLStartUp::startLLProxy() return proxy_ok; } -#ifdef LL_DISCORD - -void LLStartUp::runDiscordCallbacks() -{ - discordpp::RunCallbacks(); -} - -void LLStartUp::handleDiscordSocial() -{ - static const uint64_t DISCORD_APPLICATION_ID = 1393451183741599796; - discordpp::AuthorizationArgs discordAuthArgs{}; - discordAuthArgs.SetClientId(DISCORD_APPLICATION_ID); - discordAuthArgs.SetScopes(discordpp::Client::GetDefaultPresenceScopes()); - auto discordCodeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier(); - discordAuthArgs.SetCodeChallenge(discordCodeVerifier.Challenge()); - gDiscordClient->Authorize(discordAuthArgs, [discordCodeVerifier](auto result, auto code, auto redirectUri) { - if (result.Successful()) { - gDiscordClient->GetToken(DISCORD_APPLICATION_ID, code, discordCodeVerifier.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(); - }); - }); - } - }); -} - -#endif - bool login_alert_done(const LLSD& notification, const LLSD& response) { LLPanelLogin::giveFocus(); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index cf1d38bb18..c07926facb 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -129,11 +129,6 @@ public: static LLViewerStats::PhaseMap& getPhases() { return *sPhases; } -#ifdef LL_DISCORD - static void runDiscordCallbacks(); - static void handleDiscordSocial(); -#endif - private: friend class LLStartupListener; static LLSLURL sStartSLURL; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4383fc87e5..2c022d0a4c 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -144,6 +144,7 @@ #include "llwindow.h" #include "llpathfindingmanager.h" #include "llstartup.h" +#include "llappviewer.h" #include "boost/unordered_map.hpp" #include #include @@ -8945,7 +8946,7 @@ void handle_report_bug(const LLSD& param) #ifdef LL_DISCORD void handle_discord_social(const LLSD& param) { - LLStartUp::handleDiscordSocial(); + LLAppViewer::handleDiscordSocial(); } #endif -- cgit v1.2.3 From 8f5dc603b7320dc0522bca053d2cf0c5abc5f2c5 Mon Sep 17 00:00:00 2001 From: Secret Foxtail Date: Sun, 27 Jul 2025 05:24:16 -0600 Subject: panel_preferences_privacy tabs Add tab and checkboxes for discord social SDK integration options to panel_preferences_privacy.xml --- .../default/xui/en/panel_preferences_privacy.xml | 54 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index f1a38dc894..219f307f64 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -1,15 +1,31 @@ - + + + log in to change @@ -114,3 +130,33 @@ (People and/or Objects you have blocked) + + + + + + + + + + -- cgit v1.2.3 From 01dfd0f960b1cd500fbbe9b544a7c22cd0ab548a Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Sun, 27 Jul 2025 19:32:42 +0800 Subject: Shorten Discord-related local variable names and minimise difference from SL main. --- indra/newview/llappviewer.cpp | 16 ++++++++-------- indra/newview/llstartup.h | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d70287ac83..17f8c3e367 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5934,15 +5934,15 @@ void LLAppViewer::initDiscordSocial() void LLAppViewer::handleDiscordSocial() { - static const uint64_t DISCORD_APPLICATION_ID = 1393451183741599796; - discordpp::AuthorizationArgs discordAuthArgs{}; - discordAuthArgs.SetClientId(DISCORD_APPLICATION_ID); - discordAuthArgs.SetScopes(discordpp::Client::GetDefaultPresenceScopes()); - auto discordCodeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier(); - discordAuthArgs.SetCodeChallenge(discordCodeVerifier.Challenge()); - gDiscordClient->Authorize(discordAuthArgs, [discordCodeVerifier](auto result, auto code, auto redirectUri) { + static const uint64_t APPLICATION_ID = 1393451183741599796; + discordpp::AuthorizationArgs args{}; + args.SetClientId(APPLICATION_ID); + args.SetScopes(discordpp::Client::GetDefaultPresenceScopes()); + auto codeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier(); + args.SetCodeChallenge(codeVerifier.Challenge()); + gDiscordClient->Authorize(args, [codeVerifier](auto result, auto code, auto redirectUri) { if (result.Successful()) { - gDiscordClient->GetToken(DISCORD_APPLICATION_ID, code, discordCodeVerifier.Verifier(), redirectUri, [](discordpp::ClientResult result, std::string accessToken, std::string, discordpp::AuthorizationTokenType, int32_t, std::string) { + 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(); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index c07926facb..a827fbc487 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -128,7 +128,6 @@ public: static bool startLLProxy(); // Initialize the SOCKS 5 proxy static LLViewerStats::PhaseMap& getPhases() { return *sPhases; } - private: friend class LLStartupListener; static LLSLURL sStartSLURL; -- cgit v1.2.3 From ec86ee28171428824cde4afe88d1165e80633233 Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Sun, 27 Jul 2025 22:38:14 +0800 Subject: Connect to Discord now through privacy tab Now the access token is saved the way passwords are saved, but without a username, so we can have some persistence without having to implement an OAuth2 backend server cause we would have to store those tokens there anyway still and that would even require more disclosure that the user token gets saved on a server, and it's just simpler to not go that way. Discord Social SDK doesn't have to have a helper for sending code to a custom server anyway, that we would have to have some asynchronous HTTP requestor ready. Show location check button gets enabled only when Discord integration is enabled, though it's not functioning yet. --- indra/newview/app_settings/settings.xml | 11 ++++ indra/newview/llappviewer.cpp | 72 +++++++++++++++------- indra/newview/llappviewer.h | 2 +- indra/newview/llfloaterpreference.cpp | 10 +++ indra/newview/llviewermenu.cpp | 10 --- indra/newview/skins/default/xui/en/menu_login.xml | 7 --- indra/newview/skins/default/xui/en/menu_viewer.xml | 7 --- .../default/xui/en/panel_preferences_privacy.xml | 2 + 8 files changed, 74 insertions(+), 47 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 315018bbee..a2e0a8dbbe 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1161,6 +1161,17 @@ Value 1 + EnableDiscord + + Comment + When set, connect to Discord to enable Rich Presence + Persist + 1 + Type + Boolean + Value + 0 + EnableDiskCacheDebugInfo Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 17f8c3e367..030c778990 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5922,34 +5922,62 @@ void LLAppViewer::metricsSend(bool enable_reporting) void LLAppViewer::initDiscordSocial() { - gDiscordClient = std::make_shared(); - gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { - if (status == discordpp::Client::Status::Ready) { - discordpp::Activity activity; - activity.SetType(discordpp::ActivityTypes::Playing); - gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); - } + gDiscordClient = std::make_shared(); + gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { + if (status == discordpp::Client::Status::Ready) + { + discordpp::Activity activity; + activity.SetType(discordpp::ActivityTypes::Playing); + gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); + } + }); + if (gSavedSettings.getBOOL("EnableDiscord")) + { + gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, gSecAPIHandler->loadCredential("Discord")->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) { + if (result.Successful()) + gDiscordClient->Connect(); }); + } } -void LLAppViewer::handleDiscordSocial() +void LLAppViewer::handleDiscordSocial(bool enable) { static const uint64_t APPLICATION_ID = 1393451183741599796; - discordpp::AuthorizationArgs args{}; - args.SetClientId(APPLICATION_ID); - args.SetScopes(discordpp::Client::GetDefaultPresenceScopes()); - auto codeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier(); - args.SetCodeChallenge(codeVerifier.Challenge()); - gDiscordClient->Authorize(args, [codeVerifier](auto result, auto code, auto redirectUri) { - 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(); + if (enable) + { + discordpp::AuthorizationArgs args{}; + args.SetClientId(APPLICATION_ID); + args.SetScopes(discordpp::Client::GetDefaultPresenceScopes()); + auto codeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier(); + args.SetCodeChallenge(codeVerifier.Challenge()); + gDiscordClient->Authorize(args, [codeVerifier](auto result, auto code, auto redirectUri) { + 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); + }); + } + else + { + gSavedSettings.setBOOL("EnableDiscord", false); + } + }); + } + 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); + }); + } } #endif diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index dc10738249..8ff07accbe 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(); + static void handleDiscordSocial(bool enable); #endif protected: diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index fdac390e8a..136683296f 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -237,6 +237,13 @@ void handleAppearanceCameraMovementChanged(const LLSD& newvalue) } } +#ifdef LL_DISCORD +void handleDiscordSocial(const LLSD& newvalue) +{ + LLAppViewer::handleDiscordSocial(newvalue.asBoolean()); +} +#endif + void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator) { numerator = 0; @@ -366,6 +373,9 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance())); 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(&handleDiscordSocial, _2)); +#endif } void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2c022d0a4c..810ebd90a5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8943,13 +8943,6 @@ void handle_report_bug(const LLSD& param) LLWeb::loadURLExternal(url); } -#ifdef LL_DISCORD -void handle_discord_social(const LLSD& param) -{ - LLAppViewer::handleDiscordSocial(); -} -#endif - void handle_buy_currency_test() { std::string url = @@ -9928,9 +9921,6 @@ void initialize_menus() commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2)); commit.add("Advanced.ReportBug", boost::bind(&handle_report_bug, _2)); -#ifdef LL_DISCORD - commit.add("Advanced.DiscordSocial", boost::bind(&handle_discord_social, _2)); -#endif view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest"); view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr"); view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory"); diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 04514e8a52..5fff9b7bc0 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -109,13 +109,6 @@ function="Advanced.ReportBug"/> - - - - diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 56261ce874..1ec59bf2eb 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1817,13 +1817,6 @@ function="World.EnvPreset" function="Advanced.ReportBug"/> - - - - Date: Mon, 28 Jul 2025 15:13:36 +0800 Subject: Location for Discord Rich Presence Activity State I was going to use LLAgentUI::buildLocationString but there's no location format that shows only region and coords without having to have the parcel name empty, so I copied buildLocationString implementation in the case of LOCATION_FORMAT_NO_MATURITY but when the parcel name is empty. I had to make updateDiscordActivity check agent's ID and the existence of agent avatar pointer first before trying to set Activity Details or State, cause I like the "Show location" button be checkable not only after online when both the ID & pointer will have existed. I think this way is simpler than programmatically enabling the "Show location" button after the user is logged in. I put a trigger to Activity update somewhere after the user is logged in for now, not yet after a TP. The elapsed time gets reset whenever Activity is updated for now, but I'll try to make elapsed time extended instead. No Party for now, because I couldn't find a way to make a Party shown without showing its CurrentSize (I could still get away not showing its MaxSize by setting it to 0), so the State (location) is shown above the elapsed time, not on the right of it. I'll try to figure out to get some representative numbers for its CurrentSize & MaxSize next. Also no privacy on hiding the username for now, until the UI is ready. --- indra/newview/app_settings/settings.xml | 11 ++++++++ indra/newview/llappviewer.cpp | 32 ++++++++++++++++++++++ indra/newview/llappviewer.h | 1 + indra/newview/llfloaterpreference.cpp | 8 ++++++ indra/newview/llstartup.cpp | 3 ++ .../default/xui/en/panel_preferences_privacy.xml | 1 + 6 files changed, 56 insertions(+) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a2e0a8dbbe..bb7211514d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1172,6 +1172,17 @@ Value 0 + ShowDiscordActivityState + + Comment + When set, show location on Discord Rich Presence + Persist + 1 + Type + Boolean + Value + 0 + EnableDiskCacheDebugInfo Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 030c778990..3d8dfd39e6 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5980,4 +5980,36 @@ void LLAppViewer::handleDiscordSocial(bool enable) } } +void LLAppViewer::updateDiscordActivity() +{ + discordpp::Activity activity; + activity.SetType(discordpp::ActivityTypes::Playing); + if (gAgentAvatarp) + activity.SetDetails(gAgentAvatarp->getFullname()); + if (gAgent.getID() != LLUUID::null && gSavedSettings.getBOOL("ShowDiscordActivityState")) + { + auto agent_pos_region = gAgent.getPositionAgent(); + S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f); + S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f); + S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f); + F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared(); + const F32 FLY_CUTOFF = 6.f; + const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; + const F32 WALK_CUTOFF = 1.5f; + const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; + if (velocity_mag_sq > FLY_CUTOFF_SQ) + { + pos_x -= pos_x % 4; + pos_y -= pos_y % 4; + } + else if (velocity_mag_sq > WALK_CUTOFF_SQ) + { + pos_x -= pos_x % 2; + pos_y -= pos_y % 2; + } + activity.SetState(llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z)); + } + gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); +} + #endif diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 8ff07accbe..79db515970 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -253,6 +253,7 @@ public: #ifdef LL_DISCORD static void initDiscordSocial(); static void handleDiscordSocial(bool enable); + static void updateDiscordActivity(); #endif protected: diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 136683296f..c6e839c5de 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -238,10 +238,17 @@ void handleAppearanceCameraMovementChanged(const LLSD& newvalue) } #ifdef LL_DISCORD + void handleDiscordSocial(const LLSD& newvalue) { LLAppViewer::handleDiscordSocial(newvalue.asBoolean()); } + +void handleDiscordActivityState(const LLSD& newvalue) +{ + LLAppViewer::updateDiscordActivity(); +} + #endif void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator) @@ -375,6 +382,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // Hook up for filtering #ifdef LL_DISCORD gSavedSettings.getControl("EnableDiscord")->getCommitSignal()->connect(boost::bind(&handleDiscordSocial, _2)); + gSavedSettings.getControl("ShowDiscordActivityState")->getCommitSignal()->connect(boost::bind(&handleDiscordActivityState, _2)); #endif } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8d010553a0..2f40beb9c4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2082,6 +2082,9 @@ bool idle_startup() // We have a region, and just did a big inventory download. // We can estimate the user's connection speed, and set their // max bandwidth accordingly. JC +#ifdef LL_DISCORD + LLAppViewer::updateDiscordActivity(); +#endif if (gSavedSettings.getBOOL("FirstLoginThisInstall")) { // This is actually a pessimistic computation, because TCP may not have enough diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 8d78618a21..86bc23d699 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -150,6 +150,7 @@ Date: Mon, 28 Jul 2025 16:14:04 +0800 Subject: Update Rich Presence location on region change I had to find a spot in source code where it doesn't cause a crash (it did in LLAgent::setRegion), but I'm not removing the one in llstartup.cpp because on login, the one in llviewermessage.cpp gets only the placeholder coords (10, 10, 10). --- indra/newview/llviewermessage.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 47d7d42bf7..d6f1b96a7b 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3072,6 +3072,10 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) } } +#ifdef LL_DISCORD + LLAppViewer::updateDiscordActivity(); +#endif + if ( LLTracker::isTracking(NULL) ) { // Check distance to beacon, if < 5m, remove beacon -- cgit v1.2.3 From 94f51d5a4b16d76e46e53802cc188da8c9eb795b Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Mon, 28 Jul 2025 16:33:28 +0800 Subject: Show display name too on Discord Rich Presence Avatar name cache can be used right away upon login now after I moved the update call to the end of PRECACHE section in llstartup. --- indra/newview/llappviewer.cpp | 17 ++++++++++++++--- indra/newview/llstartup.cpp | 7 ++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3d8dfd39e6..9124651e84 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5982,11 +5982,21 @@ void LLAppViewer::handleDiscordSocial(bool enable) void LLAppViewer::updateDiscordActivity() { + if (gAgent.getID() == LLUUID::null) + return; + discordpp::Activity activity; activity.SetType(discordpp::ActivityTypes::Playing); - if (gAgentAvatarp) - activity.SetDetails(gAgentAvatarp->getFullname()); - if (gAgent.getID() != LLUUID::null && gSavedSettings.getBOOL("ShowDiscordActivityState")) + + 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 (gSavedSettings.getBOOL("ShowDiscordActivityState")) { auto agent_pos_region = gAgent.getPositionAgent(); S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f); @@ -6009,6 +6019,7 @@ void LLAppViewer::updateDiscordActivity() } activity.SetState(llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z)); } + gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 2f40beb9c4..dfad169813 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2082,9 +2082,6 @@ bool idle_startup() // We have a region, and just did a big inventory download. // We can estimate the user's connection speed, and set their // max bandwidth accordingly. JC -#ifdef LL_DISCORD - LLAppViewer::updateDiscordActivity(); -#endif if (gSavedSettings.getBOOL("FirstLoginThisInstall")) { // This is actually a pessimistic computation, because TCP may not have enough @@ -2330,6 +2327,10 @@ bool idle_startup() do_startup_frame(); } +#ifdef LL_DISCORD + LLAppViewer::updateDiscordActivity(); +#endif + return true; } -- cgit v1.2.3 From 705cd43ae88b5d095e7953ef8ddf670f3bbc9e1a Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Mon, 28 Jul 2025 17:01:34 +0800 Subject: Show Discord Rich Presence Activity Party By setting CurrentSize to the number of people within chat radius, and MaxSize to the number of people within (MP's) near range. --- indra/newview/llappviewer.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9124651e84..bc97e5b852 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -6017,7 +6017,19 @@ void LLAppViewer::updateDiscordActivity() pos_x -= pos_x % 2; pos_y -= pos_y % 2; } - activity.SetState(llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z)); + 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); + world->getAvatars(&near_me_uuids, NULL, position, gSavedSettings.getF32("MPVNearMeRange")); + discordpp::ActivityParty party; + party.SetId(location); + party.SetCurrentSize(chat_radius_uuids.size()); + party.SetMaxSize(near_me_uuids.size()); + activity.SetParty(party); } gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); -- cgit v1.2.3 From dbb0336d4a4739759371f52ab305fa2bd9237f3b Mon Sep 17 00:00:00 2001 From: Erik Kundiman Date: Mon, 28 Jul 2025 17:49:15 +0800 Subject: Call updateDiscordActivity too in Discord init so when the user enables the integration after being logged in, the init can show the name and location right away. --- indra/newview/llappviewer.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index bc97e5b852..caf56d5c79 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5926,9 +5926,7 @@ void LLAppViewer::initDiscordSocial() gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { if (status == discordpp::Client::Status::Ready) { - discordpp::Activity activity; - activity.SetType(discordpp::ActivityTypes::Playing); - gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); + updateDiscordActivity(); } }); if (gSavedSettings.getBOOL("EnableDiscord")) -- cgit v1.2.3 From c1adf320af2ca2afd9ed05cccc9031b99fc7ee60 Mon Sep 17 00:00:00 2001 From: Secret Foxtail Date: Mon, 28 Jul 2025 05:23:18 -0600 Subject: Discord Rich Presence: Hide name & connect to llappviewer.cpp Add option to show/hide avatar name in privacy panel & connect rich presense directly to llappviewer.cpp --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llappviewer.cpp | 21 ++++++++++++--------- indra/newview/llappviewer.h | 2 +- indra/newview/llfloaterpreference.cpp | 19 +++---------------- .../default/xui/en/panel_preferences_privacy.xml | 12 ++++++++++++ 5 files changed, 39 insertions(+), 26 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index bb7211514d..7ada2925bf 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1172,6 +1172,17 @@ Value 0 + ShowDiscordActivityDetails + + Comment + When set, show avatar name on Discord Rich Presence + Persist + 1 + Type + Boolean + Value + 0 + ShowDiscordActivityState Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index caf56d5c79..2ea8b65ee1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5938,10 +5938,10 @@ void LLAppViewer::initDiscordSocial() } } -void LLAppViewer::handleDiscordSocial(bool enable) +void LLAppViewer::handleDiscordSocial(const LLSD& value) { static const uint64_t APPLICATION_ID = 1393451183741599796; - if (enable) + if (value.asBoolean()) { discordpp::AuthorizationArgs args{}; args.SetClientId(APPLICATION_ID); @@ -5986,13 +5986,16 @@ void LLAppViewer::updateDiscordActivity() discordpp::Activity activity; activity.SetType(discordpp::ActivityTypes::Playing); - 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 (gSavedSettings.getBOOL("ShowDiscordActivityDetails")) + { + 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 (gSavedSettings.getBOOL("ShowDiscordActivityState")) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 79db515970..2185295b30 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(bool enable); + static void handleDiscordSocial(const LLSD& newvalue); static void updateDiscordActivity(); #endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index c6e839c5de..4c8122bf71 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -237,20 +237,6 @@ void handleAppearanceCameraMovementChanged(const LLSD& newvalue) } } -#ifdef LL_DISCORD - -void handleDiscordSocial(const LLSD& newvalue) -{ - LLAppViewer::handleDiscordSocial(newvalue.asBoolean()); -} - -void handleDiscordActivityState(const LLSD& newvalue) -{ - LLAppViewer::updateDiscordActivity(); -} - -#endif - void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator) { numerator = 0; @@ -381,8 +367,9 @@ 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(&handleDiscordSocial, _2)); - gSavedSettings.getControl("ShowDiscordActivityState")->getCommitSignal()->connect(boost::bind(&handleDiscordActivityState, _2)); + gSavedSettings.getControl("EnableDiscord")->getCommitSignal()->connect(boost::bind(&LLAppViewer::handleDiscordSocial, _2)); + gSavedSettings.getControl("ShowDiscordActivityDetails")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity)); + gSavedSettings.getControl("ShowDiscordActivityState")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity)); #endif } diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 86bc23d699..809c001904 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -148,6 +148,18 @@ top_pad="20" width="350" /> + + Date: Mon, 28 Jul 2025 20:36:54 +0800 Subject: Discord time elapsed not reset on region change Time elapses right after viewer launch even before login. Plus parameter name change in header to make it the same as in implementation. --- indra/newview/llappviewer.cpp | 14 +++++++++++--- indra/newview/llappviewer.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2ea8b65ee1..b5175fbf71 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -282,6 +282,7 @@ using namespace LL; #define DISCORDPP_IMPLEMENTATION #include static std::shared_ptr gDiscordClient; +static uint64_t gDiscordTimestampsStart; #endif static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); @@ -5922,6 +5923,7 @@ void LLAppViewer::metricsSend(bool enable_reporting) void LLAppViewer::initDiscordSocial() { + gDiscordTimestampsStart = time(nullptr); gDiscordClient = std::make_shared(); gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { if (status == discordpp::Client::Status::Ready) @@ -5980,11 +5982,17 @@ void LLAppViewer::handleDiscordSocial(const LLSD& value) void LLAppViewer::updateDiscordActivity() { - if (gAgent.getID() == LLUUID::null) - return; - discordpp::Activity activity; activity.SetType(discordpp::ActivityTypes::Playing); + discordpp::ActivityTimestamps timestamps; + timestamps.SetStart(gDiscordTimestampsStart); + activity.SetTimestamps(timestamps); + + if (gAgent.getID() == LLUUID::null) + { + gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); + return; + } if (gSavedSettings.getBOOL("ShowDiscordActivityDetails")) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 2185295b30..283975833e 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& newvalue); + static void handleDiscordSocial(const LLSD& value); static void updateDiscordActivity(); #endif -- cgit v1.2.3