diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e9c30fdad..6045ebc734 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,8 +297,10 @@ set(GAME_INCLUDE_DIRS extern ${CMAKE_BINARY_DIR}) +find_package(Threads REQUIRED) set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd - aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt) + aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt + Threads::Threads) list(APPEND GAME_LIBS libzstd_static) @@ -320,46 +322,13 @@ if (DUSK_MOVIE_SUPPORT) list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1) endif () -option(DUSK_ENABLE_DISCORD_RPC "Enable Discord Rich Presence support" ON) -if (DUSK_ENABLE_DISCORD_RPC AND NOT ANDROID AND NOT IOS AND NOT TVOS) - - FetchContent_Populate(discord_rpc - URL https://github.com/discord/discord-rpc/archive/refs/tags/v3.4.0.tar.gz - URL_HASH SHA256=e13427019027acd187352dacba6c65953af66fdf3c35fcf38fc40b454a9d7855 - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - ) - # RapidJSON is a git submodule absent from the discord-rpc tarball; fetch separately. - FetchContent_Populate(rapidjson - URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.tar.gz - URL_HASH SHA256=bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - ) - - if (NOT TARGET discord-rpc) - set(_drpc ${discord_rpc_SOURCE_DIR}/src) - set(_drpc_src - ${_drpc}/discord_rpc.cpp - ${_drpc}/rpc_connection.cpp - ${_drpc}/serialization.cpp - ) - if (WIN32) - list(APPEND _drpc_src ${_drpc}/connection_win.cpp ${_drpc}/discord_register_win.cpp) - elseif (APPLE) - list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_osx.m) - else () - list(APPEND _drpc_src ${_drpc}/connection_unix.cpp ${_drpc}/discord_register_linux.cpp) - endif () - add_library(discord-rpc STATIC ${_drpc_src}) - target_include_directories(discord-rpc PUBLIC - ${discord_rpc_SOURCE_DIR}/include - ${rapidjson_SOURCE_DIR}/include - ) - if (UNIX) - target_link_libraries(discord-rpc PUBLIC pthread) - endif () - endif () - list(APPEND GAME_LIBS discord-rpc) - list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD_RPC=1) +set(DUSK_ENABLE_DISCORD_DEFAULT ON) +if (DEFINED DUSK_ENABLE_DISCORD_RPC AND NOT DEFINED DUSK_ENABLE_DISCORD) + set(DUSK_ENABLE_DISCORD_DEFAULT ${DUSK_ENABLE_DISCORD_RPC}) +endif () +option(DUSK_ENABLE_DISCORD "Enable Discord Rich Presence support" ${DUSK_ENABLE_DISCORD_DEFAULT}) +if (DUSK_ENABLE_DISCORD AND NOT ANDROID AND NOT IOS AND NOT TVOS) + list(APPEND GAME_COMPILE_DEFS DUSK_DISCORD=1) endif () # Edit & Continue diff --git a/files.cmake b/files.cmake index f06884fb35..a463ce5129 100644 --- a/files.cmake +++ b/files.cmake @@ -1512,6 +1512,8 @@ set(DUSK_FILES src/dusk/OSReport.cpp src/dusk/OSThread.cpp src/dusk/OSMutex.cpp + src/dusk/discord.cpp + src/dusk/discord.hpp src/dusk/discord_presence.cpp src/dusk/version.cpp ) diff --git a/include/dusk/discord_presence.hpp b/include/dusk/discord_presence.hpp index 899b2ad5f9..ebecc2d07b 100644 --- a/include/dusk/discord_presence.hpp +++ b/include/dusk/discord_presence.hpp @@ -1,18 +1,14 @@ #pragma once -#ifdef DUSK_DISCORD_RPC +#ifdef DUSK_DISCORD -namespace dusk { -namespace discord { +namespace dusk::discord { -void Initialize(); +void initialize(); +void run_callbacks(); +void update_presence(); +void shutdown(); -void RunCallbacks(); +} // namespace dusk::discord -void UpdatePresence(); - -void Shutdown(); -} -} - -#endif // DUSK_DISCORD_RPC +#endif // DUSK_DISCORD diff --git a/src/dusk/discord_presence.cpp b/src/dusk/discord_presence.cpp index 3b12075c8b..6b2c7c912b 100644 --- a/src/dusk/discord_presence.cpp +++ b/src/dusk/discord_presence.cpp @@ -1,38 +1,39 @@ -#ifdef DUSK_DISCORD_RPC +#ifdef DUSK_DISCORD #include "dusk/discord_presence.hpp" +#include "d/d_com_inf_game.h" +#include "discord.hpp" #include "dusk/logging.h" #include "dusk/main.h" #include "dusk/map_loader_definitions.h" -#include "d/d_com_inf_game.h" -#include "discord_rpc.h" #include "fmt/format.h" #include -#include #include +#include +#include -namespace dusk { -namespace discord { +namespace dusk::discord { static int64_t g_startTime = 0; static bool g_initialized = false; -static const char* APPLICATION_ID = "1495632471994405035"; +static constexpr const char* kApplicationId = "1495632471994405035"; -static void OnReady(const DiscordUser* user) { - DuskLog.info("Discord: Connected as {}", user->username); +static void on_ready(const rpc::User& user) { + DuskLog.info("Discord: Connected as {}", user.username); } -static void OnDisconnected(int errorCode, const char* message) { +static void on_disconnected(int errorCode, std::string_view message) { DuskLog.warn("Discord: Disconnected ({}: {})", errorCode, message); } -static void OnError(int errorCode, const char* message) { +static void on_error(int errorCode, std::string_view message) { DuskLog.warn("Discord: Error ({}: {})", errorCode, message); } -static const char* LookupMapName(const char* mapFile) { - if (!mapFile || mapFile[0] == '\0') return nullptr; +static const char* lookup_map_name(const char* mapFile) { + if (!mapFile || mapFile[0] == '\0') + return nullptr; for (const auto& region : gameRegions) { for (const auto& map : region.maps) { if (map.mapFile && strcmp(mapFile, map.mapFile) == 0) { @@ -43,80 +44,80 @@ static const char* LookupMapName(const char* mapFile) { return nullptr; } -void Initialize() { - g_startTime = static_cast( - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch() - ).count() - ); +void initialize() { + g_startTime = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); - DiscordEventHandlers handlers{}; - handlers.ready = OnReady; - handlers.disconnected = OnDisconnected; - handlers.errored = OnError; - Discord_Initialize(APPLICATION_ID, &handlers, 0, nullptr); + rpc::EventHandlers handlers{}; + handlers.ready = on_ready; + handlers.disconnected = on_disconnected; + handlers.error = on_error; + rpc::initialize(kApplicationId, std::move(handlers)); g_initialized = true; DuskLog.info("Discord Rich Presence initialized"); } -void RunCallbacks() { - if (!g_initialized) return; - Discord_RunCallbacks(); +void run_callbacks() { + if (!g_initialized) + return; + rpc::run_callbacks(); } -void UpdatePresence() { - if (!g_initialized) return; +void update_presence() { + if (!g_initialized) + return; - static auto lastUpdate = std::chrono::steady_clock::time_point{}; + static auto sLastUpdate = std::chrono::steady_clock::time_point{}; const auto now = std::chrono::steady_clock::now(); - if (now - lastUpdate < std::chrono::seconds(15)) return; - lastUpdate = now; + if (now - sLastUpdate < std::chrono::seconds(15)) + return; + sLastUpdate = now; - static std::string detailsBuf; - static std::string stateBuf; + static std::string sDetailsBuf; + static std::string sStateBuf; - DiscordRichPresence presence{}; + rpc::Presence presence{}; presence.startTimestamp = g_startTime; presence.largeImageKey = "icon"; presence.largeImageText = "Dusk"; - if (dusk::IsGameLaunched) { + if (IsGameLaunched) { const char* stageName = dComIfGp_getLastPlayStageName(); // stageName is empty until a room is actually entered if (stageName[0] != '\0') { - const char* locationName = LookupMapName(stageName); + const char* locationName = lookup_map_name(stageName); if (locationName) { - detailsBuf = locationName; - } - else { - detailsBuf = "Twilight Princess"; + sDetailsBuf = locationName; + } else { + sDetailsBuf = "Twilight Princess"; } - presence.details = detailsBuf.c_str(); + presence.details = sDetailsBuf; - stateBuf = fmt::format(FMT_STRING("{}/{} \u2665 | {} Rupees"), + sStateBuf = fmt::format(FMT_STRING("{}/{} \u2665 | {} Rupees"), dComIfGs_getLife() / 4, dComIfGs_getMaxLife() / 5, dComIfGs_getRupee()); - presence.state = stateBuf.c_str(); + presence.state = sStateBuf; } } - Discord_UpdatePresence(&presence); + rpc::update_presence(std::move(presence)); DuskLog.debug("Discord Rich Presence sent"); } -void Shutdown() { - if (!g_initialized) return; - Discord_ClearPresence(); - Discord_Shutdown(); +void shutdown() { + if (!g_initialized) + return; + rpc::clear_presence(); + rpc::shutdown(); g_initialized = false; DuskLog.info("Discord Rich Presence shut down"); } -} // namespace discord -} // namespace dusk +} // namespace dusk::discord -#endif // DUSK_DISCORD_RPC +#endif // DUSK_DISCORD diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index c2984e3863..8d3bd0ce63 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -307,9 +307,9 @@ void main01(void) { FrameMark; -#ifdef DUSK_DISCORD_RPC - dusk::discord::RunCallbacks(); - dusk::discord::UpdatePresence(); +#ifdef DUSK_DISCORD + dusk::discord::run_callbacks(); + dusk::discord::update_presence(); #endif } while (dusk::IsRunning); @@ -571,8 +571,8 @@ int game_main(int argc, char* argv[]) { auroraInfo = aurora_initialize(argc, argv, &config); } -#ifdef DUSK_DISCORD_RPC - dusk::discord::Initialize(); +#ifdef DUSK_DISCORD + dusk::discord::initialize(); #endif VISetWindowTitle( @@ -613,8 +613,8 @@ int game_main(int argc, char* argv[]) { // pre game launch ui main loop if (!launchUILoop()) { dusk::ShutdownCrashReporting(); -#ifdef DUSK_DISCORD_RPC - dusk::discord::Shutdown(); +#ifdef DUSK_DISCORD + dusk::discord::shutdown(); #endif dusk::ui::shutdown(); aurora_shutdown(); @@ -674,8 +674,8 @@ int game_main(int argc, char* argv[]) { // Notifies all CVs and causes threads to exit OSResetSystem(OS_RESET_SHUTDOWN, 0, 0); -#ifdef DUSK_DISCORD_RPC - dusk::discord::Shutdown(); +#ifdef DUSK_DISCORD + dusk::discord::shutdown(); #endif dusk::ui::shutdown(); aurora_shutdown();