2018-05-27 04:24:13 +00:00
|
|
|
|
// Copyright 2018 Dolphin Emulator Project
|
|
|
|
|
// Licensed under GPLv2+
|
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
2018-07-03 21:50:08 +00:00
|
|
|
|
#include "Common/Hash.h"
|
|
|
|
|
|
|
|
|
|
#include "Core/Config/NetplaySettings.h"
|
2018-06-08 20:56:11 +00:00
|
|
|
|
#include "Core/Config/UISettings.h"
|
|
|
|
|
#include "Core/ConfigManager.h"
|
|
|
|
|
|
2018-07-03 21:50:08 +00:00
|
|
|
|
#include "UICommon/DiscordPresence.h"
|
|
|
|
|
|
2018-06-08 20:56:11 +00:00
|
|
|
|
#ifdef USE_DISCORD_PRESENCE
|
2018-05-27 04:24:13 +00:00
|
|
|
|
|
|
|
|
|
#include <ctime>
|
|
|
|
|
#include <discord-rpc/include/discord_rpc.h>
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace Discord
|
|
|
|
|
{
|
2018-07-03 21:50:08 +00:00
|
|
|
|
#ifdef USE_DISCORD_PRESENCE
|
|
|
|
|
static JoinFunction join_function = nullptr;
|
|
|
|
|
static const char* username = "";
|
|
|
|
|
|
|
|
|
|
static void HandleDiscordReady(const DiscordUser* user)
|
|
|
|
|
{
|
|
|
|
|
username = user->username;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void HandleDiscordJoin(const char* join_secret)
|
|
|
|
|
{
|
|
|
|
|
if (join_function == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (Config::Get(Config::NETPLAY_NICKNAME) == Config::NETPLAY_NICKNAME.default_value)
|
|
|
|
|
Config::SetBaseOrCurrent(Config::NETPLAY_NICKNAME, username);
|
|
|
|
|
|
|
|
|
|
std::string secret(join_secret);
|
|
|
|
|
|
|
|
|
|
size_t offset = 0;
|
|
|
|
|
std::string type = secret.substr(offset, secret.find('\n'));
|
|
|
|
|
offset += type.length() + 1;
|
|
|
|
|
|
|
|
|
|
switch (static_cast<SecretType>(std::stol(type)))
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
case SecretType::Empty:
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case SecretType::IPAddress:
|
|
|
|
|
{
|
|
|
|
|
Config::SetBaseOrCurrent(Config::NETPLAY_TRAVERSAL_CHOICE, "direct");
|
|
|
|
|
|
|
|
|
|
std::string host = secret.substr(offset, secret.find_last_of(':') - offset);
|
|
|
|
|
Config::SetBaseOrCurrent(Config::NETPLAY_HOST_CODE, host);
|
|
|
|
|
|
|
|
|
|
offset += host.length();
|
|
|
|
|
if (secret[offset] == ':')
|
|
|
|
|
Config::SetBaseOrCurrent(Config::NETPLAY_CONNECT_PORT, std::stoul(secret.substr(offset + 1)));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SecretType::RoomID:
|
|
|
|
|
{
|
|
|
|
|
Config::SetBaseOrCurrent(Config::NETPLAY_TRAVERSAL_CHOICE, "traversal");
|
|
|
|
|
|
|
|
|
|
Config::SetBaseOrCurrent(Config::NETPLAY_HOST_CODE, secret.substr(offset));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
join_function();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-05-27 04:24:13 +00:00
|
|
|
|
void Init()
|
|
|
|
|
{
|
|
|
|
|
#ifdef USE_DISCORD_PRESENCE
|
2018-06-08 20:56:11 +00:00
|
|
|
|
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
|
2018-05-30 03:44:20 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-05-27 04:24:13 +00:00
|
|
|
|
DiscordEventHandlers handlers = {};
|
2018-07-03 21:50:08 +00:00
|
|
|
|
|
|
|
|
|
handlers.ready = HandleDiscordReady;
|
|
|
|
|
handlers.joinGame = HandleDiscordJoin;
|
2018-05-27 04:24:13 +00:00
|
|
|
|
// The number is the client ID for Dolphin, it's used for images and the appication name
|
2018-06-08 20:56:11 +00:00
|
|
|
|
Discord_Initialize("455712169795780630", &handlers, 1, nullptr);
|
2018-05-27 04:24:13 +00:00
|
|
|
|
UpdateDiscordPresence();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-03 21:50:08 +00:00
|
|
|
|
void CallPendingCallbacks()
|
|
|
|
|
{
|
|
|
|
|
#ifdef USE_DISCORD_PRESENCE
|
|
|
|
|
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Discord_RunCallbacks();
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitNetPlayFunctionality(const JoinFunction& join)
|
|
|
|
|
{
|
|
|
|
|
#ifdef USE_DISCORD_PRESENCE
|
|
|
|
|
join_function = std::move(join);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UpdateDiscordPresence(const int party_size, SecretType type, const std::string& secret)
|
2018-05-27 04:24:13 +00:00
|
|
|
|
{
|
|
|
|
|
#ifdef USE_DISCORD_PRESENCE
|
2018-06-08 20:56:11 +00:00
|
|
|
|
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
|
2018-05-30 03:44:20 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-05-27 04:24:13 +00:00
|
|
|
|
const std::string& title = SConfig::GetInstance().GetTitleDescription();
|
|
|
|
|
|
|
|
|
|
DiscordRichPresence discord_presence = {};
|
|
|
|
|
discord_presence.largeImageKey = "dolphin_logo";
|
|
|
|
|
discord_presence.largeImageText = "Dolphin is an emulator for the GameCube and the Wii.";
|
|
|
|
|
discord_presence.details = title.empty() ? "Not in-game" : title.c_str();
|
|
|
|
|
discord_presence.startTimestamp = std::time(nullptr);
|
2018-07-03 21:50:08 +00:00
|
|
|
|
|
|
|
|
|
if (0 < party_size)
|
|
|
|
|
{
|
|
|
|
|
if (party_size < 4)
|
|
|
|
|
{
|
|
|
|
|
discord_presence.state = "In a party";
|
|
|
|
|
discord_presence.partySize = party_size;
|
|
|
|
|
discord_presence.partyMax = 4;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// others can still join to spectate
|
|
|
|
|
discord_presence.state = "In a full party";
|
|
|
|
|
discord_presence.partySize = party_size;
|
|
|
|
|
// Note: joining still works without partyMax
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string party_ID;
|
|
|
|
|
std::string secret_final;
|
|
|
|
|
if (type != SecretType::Empty)
|
|
|
|
|
{
|
|
|
|
|
// Declearing party_ID or secret_final here will deallocate the variable before passing the
|
|
|
|
|
// values over to Discord_UpdatePresence.
|
|
|
|
|
|
|
|
|
|
const size_t secret_length = secret.length();
|
|
|
|
|
party_ID = std::to_string(
|
|
|
|
|
Common::HashAdler32(reinterpret_cast<const u8*>(secret.c_str()), secret_length));
|
|
|
|
|
|
|
|
|
|
const std::string secret_type = std::to_string(static_cast<int>(type));
|
|
|
|
|
secret_final.reserve(secret_type.length() + 1 + secret_length);
|
|
|
|
|
secret_final += secret_type;
|
|
|
|
|
secret_final += '\n';
|
|
|
|
|
secret_final += secret;
|
|
|
|
|
}
|
|
|
|
|
discord_presence.partyId = party_ID.c_str();
|
|
|
|
|
discord_presence.joinSecret = secret_final.c_str();
|
|
|
|
|
|
2018-05-27 04:24:13 +00:00
|
|
|
|
Discord_UpdatePresence(&discord_presence);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shutdown()
|
|
|
|
|
{
|
|
|
|
|
#ifdef USE_DISCORD_PRESENCE
|
2018-06-08 20:56:11 +00:00
|
|
|
|
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
|
2018-05-30 03:44:20 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-06-01 02:54:15 +00:00
|
|
|
|
Discord_ClearPresence();
|
2018-05-27 04:24:13 +00:00
|
|
|
|
Discord_Shutdown();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2018-06-06 04:16:42 +00:00
|
|
|
|
|
|
|
|
|
void SetDiscordPresenceEnabled(bool enabled)
|
|
|
|
|
{
|
2018-06-08 20:56:11 +00:00
|
|
|
|
if (Config::Get(Config::MAIN_USE_DISCORD_PRESENCE) == enabled)
|
2018-06-06 04:16:42 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-06-08 20:56:11 +00:00
|
|
|
|
if (Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
|
2018-06-06 04:16:42 +00:00
|
|
|
|
Discord::Shutdown();
|
|
|
|
|
|
2018-06-08 20:56:11 +00:00
|
|
|
|
Config::SetBase(Config::MAIN_USE_DISCORD_PRESENCE, enabled);
|
2018-06-06 04:16:42 +00:00
|
|
|
|
|
2018-06-08 20:56:11 +00:00
|
|
|
|
if (Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
|
2018-06-06 04:16:42 +00:00
|
|
|
|
Discord::Init();
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-27 04:24:13 +00:00
|
|
|
|
} // namespace Discord
|