Skip to content

Commit

Permalink
Discord RPC (Discord Rich Presence) tweaks (#3216)
Browse files Browse the repository at this point in the history
The changelog of this can be found in #3205 (as #3216 is the successor of #3205 and a near-copy). It was done this way because the #3205's author is on vacation, and we had pending code review changes to make.
  • Loading branch information
tederis committed Oct 24, 2023
1 parent 063b236 commit ef26810
Show file tree
Hide file tree
Showing 18 changed files with 470 additions and 160 deletions.
126 changes: 66 additions & 60 deletions Client/core/CCore.h
Expand Up @@ -45,30 +45,30 @@ class CDiscordInterface;
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>

#define BLUE_VERSION_STRING "Multi Theft Auto v" MTA_DM_BUILDTAG_LONG
#define BLUE_COPYRIGHT_STRING "Copyright (C) 2003 - %BUILD_YEAR% Multi Theft Auto"
#define BLUE_VERSION_STRING "Multi Theft Auto v" MTA_DM_BUILDTAG_LONG
#define BLUE_COPYRIGHT_STRING "Copyright (C) 2003 - %BUILD_YEAR% Multi Theft Auto"

// Configuration file path (relative to MTA install directory)
#define MTA_CONFIG_PATH "mta/config/coreconfig.xml"
#define MTA_SERVER_CACHE_PATH "mta/config/servercache.xml"
#define MTA_CONSOLE_LOG_PATH "mta/logs/console.log"
#define MTA_CONSOLE_INPUT_LOG_PATH "mta/logs/console-input.log"
#define CONFIG_ROOT "mainconfig"
#define CONFIG_NODE_CVARS "settings" // cvars node
#define CONFIG_NODE_KEYBINDS "binds" // keybinds node
#define CONFIG_NODE_JOYPAD "joypad"
#define CONFIG_NODE_UPDATER "updater"
#define CONFIG_NODE_SERVER_INT "internet_servers" // backup of last successful master server list query
#define CONFIG_NODE_SERVER_FAV "favourite_servers" // favourite servers list node
#define CONFIG_NODE_SERVER_REC "recently_played_servers" // recently played servers list node
#define CONFIG_NODE_SERVER_OPTIONS "serverbrowser_options" // saved options for the server browser
#define CONFIG_NODE_SERVER_SAVED "server_passwords" // This contains saved passwords (as appose to save_server_passwords which is a setting)
#define CONFIG_NODE_SERVER_HISTORY "connect_history"
#define CONFIG_INTERNET_LIST_TAG "internet_server"
#define CONFIG_FAVOURITE_LIST_TAG "favourite_server"
#define CONFIG_RECENT_LIST_TAG "recently_played_server"
#define CONFIG_HISTORY_LIST_TAG "connected_server"
#define IDT_TIMER1 1234
#define MTA_CONFIG_PATH "mta/config/coreconfig.xml"
#define MTA_SERVER_CACHE_PATH "mta/config/servercache.xml"
#define MTA_CONSOLE_LOG_PATH "mta/logs/console.log"
#define MTA_CONSOLE_INPUT_LOG_PATH "mta/logs/console-input.log"
#define CONFIG_ROOT "mainconfig"
#define CONFIG_NODE_CVARS "settings" // cvars node
#define CONFIG_NODE_KEYBINDS "binds" // keybinds node
#define CONFIG_NODE_JOYPAD "joypad"
#define CONFIG_NODE_UPDATER "updater"
#define CONFIG_NODE_SERVER_INT "internet_servers" // backup of last successful master server list query
#define CONFIG_NODE_SERVER_FAV "favourite_servers" // favourite servers list node
#define CONFIG_NODE_SERVER_REC "recently_played_servers" // recently played servers list node
#define CONFIG_NODE_SERVER_OPTIONS "serverbrowser_options" // saved options for the server browser
#define CONFIG_NODE_SERVER_SAVED "server_passwords" // This contains saved passwords (as appose to save_server_passwords which is a setting)
#define CONFIG_NODE_SERVER_HISTORY "connect_history"
#define CONFIG_INTERNET_LIST_TAG "internet_server"
#define CONFIG_FAVOURITE_LIST_TAG "favourite_server"
#define CONFIG_RECENT_LIST_TAG "recently_played_server"
#define CONFIG_HISTORY_LIST_TAG "connected_server"
#define IDT_TIMER1 1234

extern class CCore* g_pCore;
extern class CGraphics* g_pGraphics;
Expand All @@ -84,26 +84,26 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
~CCore();

// Subsystems (query)
eCoreVersion GetVersion();
CConsoleInterface* GetConsole();
CCommandsInterface* GetCommands();
CConnectManager* GetConnectManager() { return m_pConnectManager; };
CGame* GetGame();
CGUI* GetGUI();
CGraphicsInterface* GetGraphics();
CModManagerInterface* GetModManager();
CMultiplayer* GetMultiplayer();
CNet* GetNetwork();
CXML* GetXML() { return m_pXML; };
CXMLNode* GetConfig();
CClientVariables* GetCVars() { return &m_ClientVariables; };
CKeyBindsInterface* GetKeyBinds();
CMouseControl* GetMouseControl() { return m_pMouseControl; };
CLocalGUI* GetLocalGUI();
CLocalizationInterface* GetLocalization() { return g_pLocalization; };
CWebCoreInterface* GetWebCore();
CTrayIconInterface* GetTrayIcon() { return m_pTrayIcon; };
std::shared_ptr<CDiscordInterface> GetDiscord();
eCoreVersion GetVersion();
CConsoleInterface* GetConsole();
CCommandsInterface* GetCommands();
CConnectManager* GetConnectManager() { return m_pConnectManager; };
CGame* GetGame();
CGUI* GetGUI();
CGraphicsInterface* GetGraphics();
CModManagerInterface* GetModManager();
CMultiplayer* GetMultiplayer();
CNet* GetNetwork();
CXML* GetXML() { return m_pXML; };
CXMLNode* GetConfig();
CClientVariables* GetCVars() { return &m_ClientVariables; };
CKeyBindsInterface* GetKeyBinds();
CMouseControl* GetMouseControl() { return m_pMouseControl; };
CLocalGUI* GetLocalGUI();
CLocalizationInterface* GetLocalization() { return g_pLocalization; };
CWebCoreInterface* GetWebCore();
CTrayIconInterface* GetTrayIcon() { return m_pTrayIcon; };
std::shared_ptr<CDiscordInterface> GetDiscord();

void SaveConfig(bool bWaitUntilFinished = false);

Expand Down Expand Up @@ -285,6 +285,10 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
void SetCustomStreamingMemory(size_t szMB);
bool IsUsingCustomStreamingMemorySize();
size_t GetStreamingMemory();

const SString& GetLastConnectedServerName() const { return m_strLastConnectedServerName; }
void SetLastConnectedServerName(const SString& strServerName) { m_strLastConnectedServerName = strServerName; }

private:
void ApplyCoreInitSettings();

Expand All @@ -299,11 +303,11 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
CModelCacheManager* m_pModelCacheManager;

// Instances (put new classes here!)
CXMLFile* m_pConfigFile;
CClientVariables m_ClientVariables;
CWebCoreInterface* m_pWebCore = nullptr;
CTrayIcon* m_pTrayIcon;
std::shared_ptr<CDiscordRichPresence> m_pDiscordRichPresence;
CXMLFile* m_pConfigFile;
CClientVariables m_ClientVariables;
CWebCoreInterface* m_pWebCore = nullptr;
CTrayIcon* m_pTrayIcon;
std::shared_ptr<CDiscordRichPresence> m_pDiscordRichPresence;

// Hook interfaces.
CMessageLoopHook* m_pMessageLoopHook;
Expand Down Expand Up @@ -369,22 +373,24 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
EDiagnosticDebugType m_DiagnosticDebug;

// Below 2 are used for the UI only
float m_fMinStreamingMemory{};
float m_fMaxStreamingMemory{};
float m_fMinStreamingMemory{};
float m_fMaxStreamingMemory{};

// Custom streaming memory limit set by `engineStreamingSetMemorySize` - Reset on server connects (= set to 0), or by the scripter
// `0` means "not set" [so the value should be ignored]
size_t m_CustomStreamingMemoryLimitBytes{};

bool m_bGettingIdleCallsFromMultiplayer;
bool m_bWindowsTimerEnabled;
bool m_bModulesLoaded;
int m_iDummyProgressValue;
HANDLE m_DummyProgressTimerHandle;
SString m_strDummyProgressType;
bool m_bDummyProgressUpdateAlways;
bool m_bIsRenderingGrass;
bool m_bFakeLagCommandEnabled;
size_t m_CustomStreamingMemoryLimitBytes{};

bool m_bGettingIdleCallsFromMultiplayer;
bool m_bWindowsTimerEnabled;
bool m_bModulesLoaded;
int m_iDummyProgressValue;
HANDLE m_DummyProgressTimerHandle;
SString m_strDummyProgressType;
bool m_bDummyProgressUpdateAlways;
bool m_bIsRenderingGrass;
bool m_bFakeLagCommandEnabled;

SString m_strLastConnectedServerName{};

// Command line
static void ParseCommandLine(std::map<std::string, std::string>& options, const char*& szArgs, const char** pszNoValOptions = NULL);
Expand Down
39 changes: 32 additions & 7 deletions Client/core/CDiscordRichPresence.cpp
Expand Up @@ -64,12 +64,15 @@ void CDiscordRichPresence::SetDefaultData()
m_strDiscordAppAssetSmallText = DEFAULT_APP_ASSET_SMALL_TEXT;

m_strDiscordAppCurrentId = DEFAULT_APP_ID;
m_strDiscordAppDetails.clear();
m_strDiscordAppCustomDetails.clear();
m_strDiscordAppCustomState.clear();

m_aButtons = {};
m_bUpdateRichPresence = true;
m_bDisallowCustomDetails = true;

m_uiDiscordAppStart = 0;
m_uiDiscordAppEnd = 0;
}

void CDiscordRichPresence::UpdatePresence()
Expand All @@ -87,8 +90,10 @@ void CDiscordRichPresence::UpdatePresence()

discordPresence.state = (!m_strDiscordAppCustomState.empty() || !m_bDisallowCustomDetails) ? m_strDiscordAppCustomState.c_str() : m_strDiscordAppState.c_str();

discordPresence.details = m_strDiscordAppDetails.c_str();
discordPresence.details =
(!m_strDiscordAppCustomDetails.empty() || !m_bDisallowCustomDetails) ? m_strDiscordAppCustomDetails.c_str() : m_strDiscordAppDetails.c_str();
discordPresence.startTimestamp = m_uiDiscordAppStart;
discordPresence.endTimestamp = m_uiDiscordAppEnd;

DiscordButton buttons[2];
if (m_aButtons)
Expand All @@ -101,6 +106,9 @@ void CDiscordRichPresence::UpdatePresence()
discordPresence.buttons = buttons;
}

discordPresence.partySize = (m_bDisallowCustomDetails) ? 0 : m_iPartySize;
discordPresence.partyMax = (m_bDisallowCustomDetails) ? 0 : m_iPartyMax;

Discord_UpdatePresence(&discordPresence);
m_bUpdateRichPresence = false;
}
Expand All @@ -111,6 +119,13 @@ void CDiscordRichPresence::SetPresenceStartTimestamp(const unsigned long ulStart
m_bUpdateRichPresence = true;
}

void CDiscordRichPresence::SetPresenceEndTimestamp(const unsigned long ulEnd)
{
m_uiDiscordAppEnd = ulEnd;
m_bUpdateRichPresence = true;
}


void CDiscordRichPresence::SetAssetLargeData(const char* szAsset, const char* szAssetText)
{
SetAsset(szAsset, szAssetText, true);
Expand All @@ -125,13 +140,13 @@ void CDiscordRichPresence::SetAsset(const char* szAsset, const char* szAssetText
{
if (isLarge)
{
m_strDiscordAppAsset = (szAsset && *szAsset) ? szAsset : DEFAULT_APP_ASSET;
m_strDiscordAppAssetText = (szAssetText && *szAssetText) ? szAssetText : DEFAULT_APP_ASSET_TEXT;
m_strDiscordAppAsset = (std::strlen(szAsset) > 0 && szAsset && *szAsset) ? szAsset : DEFAULT_APP_ASSET;
m_strDiscordAppAssetText = (std::strlen(szAssetText) > 0 && szAssetText && *szAssetText) ? szAssetText : DEFAULT_APP_ASSET_TEXT;
}
else
{
m_strDiscordAppAssetSmall = (szAsset && *szAsset) ? szAsset : DEFAULT_APP_ASSET_SMALL;
m_strDiscordAppAssetSmallText = (szAssetText && *szAssetText) ? szAssetText : DEFAULT_APP_ASSET_SMALL_TEXT;
m_strDiscordAppAssetSmall = (std::strlen(szAsset) > 0 && szAsset && *szAsset) ? szAsset : DEFAULT_APP_ASSET_SMALL;
m_strDiscordAppAssetSmallText = (std::strlen(szAssetText) > 0 && szAssetText && *szAssetText) ? szAssetText : DEFAULT_APP_ASSET_SMALL_TEXT;
}
m_bUpdateRichPresence = true;
}
Expand Down Expand Up @@ -172,7 +187,11 @@ bool CDiscordRichPresence::SetPresenceButtons(unsigned short int iIndex, const c

bool CDiscordRichPresence::SetPresenceDetails(const char* szDetails, bool bCustom)
{
m_strDiscordAppDetails = szDetails;
if (bCustom)
m_strDiscordAppCustomDetails = szDetails;
else
m_strDiscordAppDetails = szDetails;

m_bUpdateRichPresence = true;
return true;
}
Expand Down Expand Up @@ -225,3 +244,9 @@ bool CDiscordRichPresence::IsDiscordCustomDetailsDisallowed() const
{
return m_bDisallowCustomDetails;
}

void CDiscordRichPresence::SetPresencePartySize(int iSize, int iMax)
{
m_iPartySize = iSize;
m_iPartyMax = iMax;
}
6 changes: 6 additions & 0 deletions Client/core/CDiscordRichPresence.h
Expand Up @@ -26,6 +26,7 @@ class CDiscordRichPresence : public CDiscordInterface

void UpdatePresence();
void SetPresenceStartTimestamp(const unsigned long ulStart);
void SetPresenceEndTimestamp(const unsigned long ulEnd);
void SetAsset(const char* szAsset, const char* szAssetText, bool bIsLarge = false);
void SetAssetLargeData(const char* szAsset, const char* szAssetText);
void SetAssetSmallData(const char* szAsset, const char* szAssetText);
Expand All @@ -34,6 +35,7 @@ class CDiscordRichPresence : public CDiscordInterface
bool SetPresenceState(const char* szState, bool bCustom = false);
bool SetPresenceDetails(const char* szDetails, bool bCustom = false);
bool SetPresenceButtons(unsigned short int iIndex, const char* szName, const char* szUrl);
void SetPresencePartySize(int iSize, int iMax);
bool SetDiscordRPCEnabled(bool bEnabled);
bool IsDiscordCustomDetailsDisallowed() const;
bool IsDiscordRPCEnabled() const;
Expand All @@ -54,6 +56,7 @@ class CDiscordRichPresence : public CDiscordInterface
std::string m_strDiscordAppState;
std::string m_strDiscordAppDetails;
std::string m_strDiscordAppCustomState;
std::string m_strDiscordAppCustomDetails;

std::optional<std::tuple<std::pair<std::string, std::string>, std::pair<std::string, std::string>>> m_aButtons;

Expand All @@ -63,4 +66,7 @@ class CDiscordRichPresence : public CDiscordInterface
bool m_bDisallowCustomDetails;
bool m_bDiscordRPCEnabled;
bool m_bUpdateRichPresence;

int m_iPartySize;
int m_iPartyMax;
};
20 changes: 20 additions & 0 deletions Client/core/CSettings.cpp
Expand Up @@ -3452,6 +3452,26 @@ void CSettings::SaveData()
CVARS_SET("allow_discord_rpc", bAllowDiscordRPC);
g_pCore->GetDiscord()->SetDiscordRPCEnabled(bAllowDiscordRPC);

if (bAllowDiscordRPC)
{
auto discord = g_pCore->GetDiscord();

if (discord)
{
const char* state = "Main menu";

if (g_pCore->IsConnected())
{
state = "In-game";

const SString& serverName = g_pCore->GetLastConnectedServerName();
discord->SetPresenceDetails(serverName.c_str(), false);
}

discord->SetPresenceState(state, false);
}
}

// Grass
bool bGrassEnabled = m_pCheckBoxGrass->GetSelected();
CVARS_SET("grass", bGrassEnabled);
Expand Down

0 comments on commit ef26810

Please sign in to comment.