Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add Discord Join Net Play functionally
  • Loading branch information
yourWaifu committed Aug 1, 2018
1 parent 14e156c commit b7c241e
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 3 deletions.
1 change: 1 addition & 0 deletions Source/Core/DolphinQt/CMakeLists.txt
Expand Up @@ -8,6 +8,7 @@ set(CMAKE_AUTOMOC ON)
add_executable(dolphin-emu
AboutDialog.cpp
CheatsManager.cpp
DiscordHandler.cpp
FIFO/FIFOPlayerWindow.cpp
FIFO/FIFOAnalyzer.cpp
HotkeyScheduler.cpp
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/DolphinQt/DolphinQt.vcxproj
Expand Up @@ -107,6 +107,7 @@
<QtMoc Include="Config\PatchesWidget.h" />
<QtMoc Include="Config\PropertiesDialog.h" />
<QtMoc Include="Config\SettingsWindow.h" />
<QtMoc Include="DiscordHandler.h" />
<QtMoc Include="FIFO\FIFOAnalyzer.h" />
<QtMoc Include="FIFO\FIFOPlayerWindow.h" />
<QtMoc Include="TAS\GCTASInputWindow.h" />
Expand Down Expand Up @@ -175,6 +176,7 @@
<ClCompile Include="$(QtMocOutPrefix)CodeViewWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)CodeWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)ControllersWindow.cpp" />
<ClCompile Include="$(QtMocOutPrefix)DiscordHandler.cpp" />
<ClCompile Include="$(QtMocOutPrefix)DoubleClickEventFilter.cpp" />
<ClCompile Include="$(QtMocOutPrefix)ElidedButton.cpp" />
<ClCompile Include="$(QtMocOutPrefix)FlowLayout.cpp" />
Expand Down Expand Up @@ -320,6 +322,7 @@
<ClCompile Include="Debugger\JITWidget.cpp" />
<ClCompile Include="Debugger\MemoryWidget.cpp" />
<ClCompile Include="Debugger\MemoryViewWidget.cpp" />
<ClCompile Include="DiscordHandler.cpp" />
<ClCompile Include="FIFO\FIFOAnalyzer.cpp" />
<ClCompile Include="FIFO\FIFOPlayerWindow.cpp" />
<ClCompile Include="QtUtils\WinIconHelper.cpp" />
Expand Down
11 changes: 11 additions & 0 deletions Source/Core/DolphinQt/MainWindow.cpp
Expand Up @@ -67,6 +67,7 @@
#include "DolphinQt/Debugger/MemoryWidget.h"
#include "DolphinQt/Debugger/RegisterWidget.h"
#include "DolphinQt/Debugger/WatchWidget.h"
#include "DolphinQt/DiscordHandler.h"
#include "DolphinQt/FIFO/FIFOPlayerWindow.h"
#include "DolphinQt/GCMemcardManager.h"
#include "DolphinQt/GameList/GameList.h"
Expand Down Expand Up @@ -1043,14 +1044,23 @@ void MainWindow::BootWiiSystemMenu()
void MainWindow::NetPlayInit()
{
m_netplay_setup_dialog = new NetPlaySetupDialog(this);
<<<<<<< HEAD:Source/Core/DolphinQt/MainWindow.cpp
m_netplay_dialog = new NetPlayDialog;
=======
m_netplay_dialog = new NetPlayDialog(this);
m_netplay_discord = new DiscordHandler();
>>>>>>> Add Discord Join Net Play functionally:Source/Core/DolphinQt2/MainWindow.cpp

connect(m_netplay_dialog, &NetPlayDialog::Boot, this,
[this](const QString& path) { StartGame(path); });
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::ForceStop);
connect(m_netplay_dialog, &NetPlayDialog::rejected, this, &MainWindow::NetPlayQuit);
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::Join, this, &MainWindow::NetPlayJoin);
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::Host, this, &MainWindow::NetPlayHost);
connect(m_netplay_discord, &DiscordHandler::Join, this, &MainWindow::NetPlayJoin);

Discord::InitNetPlayFunctionality([this] { m_netplay_discord->DiscordJoin(); });
m_netplay_discord->Start();
}

bool MainWindow::NetPlayJoin()
Expand Down Expand Up @@ -1169,6 +1179,7 @@ void MainWindow::NetPlayQuit()
{
Settings::Instance().ResetNetPlayClient();
Settings::Instance().ResetNetPlayServer();
Discord::UpdateDiscordPresence();
}

void MainWindow::EnableScreenSaver(bool enable)
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/DolphinQt/MainWindow.h
Expand Up @@ -19,6 +19,7 @@ struct BootParameters;
class CheatsManager;
class CodeWidget;
class ControllersWindow;
class DiscordHandler;
class DragEnterEvent;
class FIFOPlayerWindow;
class GameList;
Expand Down Expand Up @@ -183,6 +184,7 @@ class MainWindow final : public QMainWindow
ControllersWindow* m_controllers_window;
SettingsWindow* m_settings_window;
NetPlayDialog* m_netplay_dialog;
DiscordHandler* m_netplay_discord;
NetPlaySetupDialog* m_netplay_setup_dialog;
GraphicsWindow* m_graphics_window;
static constexpr int num_gc_controllers = 4;
Expand Down
38 changes: 38 additions & 0 deletions Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp
Expand Up @@ -29,6 +29,7 @@

#include "Common/CommonPaths.h"
#include "Common/Config/Config.h"
#include "Common/HttpRequest.h"
#include "Common/TraversalClient.h"

#include "Core/Config/GraphicsSettings.h"
Expand All @@ -49,6 +50,7 @@
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"

#include "UICommon/DiscordPresence.h"
#include "UICommon/GameFile.h"

#include "VideoCommon/VideoConfig.h"
Expand Down Expand Up @@ -418,6 +420,7 @@ void NetPlayDialog::show(std::string nickname, bool use_traversal)
m_nickname = nickname;
m_use_traversal = use_traversal;
m_buffer_size = 0;
m_old_player_count = 0;

m_room_box->clear();
m_chat_edit->clear();
Expand Down Expand Up @@ -565,6 +568,41 @@ void NetPlayDialog::UpdateGUI()
m_hostcode_action_button->setText(tr("Copy"));
m_hostcode_action_button->setEnabled(true);
}

if (m_old_player_count != player_count)
{
if (m_use_traversal)
{
const auto host_id = g_TraversalClient->GetHostID();
Discord::UpdateDiscordPresence(player_count, Discord::SecretType::RoomID,
std::string(host_id.begin(), host_id.end()));
}
else
{
// Temporary soluation
// To Do: Don't rely on a service that Dolphin devs aren't in control of. Ask one of the
// project managers about this.

Common::HttpRequest request;
Common::HttpRequest::Response response = request.Get("https://www.myexternalip.com/raw");

if (!response.has_value())
return;

// The response ends with a /n and the - 1 removes that
std::string exernalIPAddress = std::string(response->begin(), response->end() - 1);
std::string port = std::to_string(Settings::Instance().GetNetPlayServer()->GetPort());
std::string secret;
secret.reserve(exernalIPAddress.length() + 1 + port.length());
secret += exernalIPAddress;
secret += ':';
secret += port;

Discord::UpdateDiscordPresence(player_count, Discord::SecretType::IPAddress, secret);
}

m_old_player_count = player_count;
}
}

// NetPlayUI methods
Expand Down
45 changes: 45 additions & 0 deletions Source/Core/DolphinQt2/DiscordHandler.cpp
@@ -0,0 +1,45 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "DolphinQt2/DiscordHandler.h"

#include "Common/Thread.h"

#include "UICommon/DiscordPresence.h"

DiscordHandler::DiscordHandler() = default;

DiscordHandler::~DiscordHandler()
{
Stop();
}

void DiscordHandler::Start()
{
m_stop_requested.Set(false);
m_thread = std::thread(&DiscordHandler::Run, this);
}

void DiscordHandler::Stop()
{
m_stop_requested.Set(true);

if (m_thread.joinable())
m_thread.join();
}

void DiscordHandler::DiscordJoin()
{
emit DiscordHandler::Join();
}

void DiscordHandler::Run()
{
while (!m_stop_requested.IsSet())
{
Common::SleepCurrentThread(1000 * 2);

Discord::CallPendingCallbacks();
}
}
30 changes: 30 additions & 0 deletions Source/Core/DolphinQt2/DiscordHandler.h
@@ -0,0 +1,30 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include <thread>

#include <QObject>

#include "Common/Flag.h"

class DiscordHandler : public QObject
{
Q_OBJECT
public:
explicit DiscordHandler();
~DiscordHandler();

void Start();
void Stop();
void DiscordJoin();
signals:
void Join();

private:
void Run();
Common::Flag m_stop_requested;
std::thread m_thread;
};
122 changes: 120 additions & 2 deletions Source/Core/UICommon/DiscordPresence.cpp
Expand Up @@ -2,10 +2,14 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "UICommon/DiscordPresence.h"
#include "Common/Hash.h"

#include "Core/Config/NetplaySettings.h"
#include "Core/Config/UISettings.h"
#include "Core/ConfigManager.h"

#include "UICommon/DiscordPresence.h"

#ifdef USE_DISCORD_PRESENCE

#include <ctime>
Expand All @@ -15,20 +19,96 @@

namespace Discord
{
#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

void Init()
{
#ifdef USE_DISCORD_PRESENCE
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
return;

DiscordEventHandlers handlers = {};

handlers.ready = HandleDiscordReady;
handlers.joinGame = HandleDiscordJoin;
// The number is the client ID for Dolphin, it's used for images and the appication name
Discord_Initialize("455712169795780630", &handlers, 1, nullptr);
UpdateDiscordPresence();
#endif
}

void UpdateDiscordPresence()
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)
{
#ifdef USE_DISCORD_PRESENCE
if (!Config::Get(Config::MAIN_USE_DISCORD_PRESENCE))
Expand All @@ -41,6 +121,44 @@ void UpdateDiscordPresence()
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);

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();

Discord_UpdatePresence(&discord_presence);
#endif
}
Expand Down

0 comments on commit b7c241e

Please sign in to comment.