Permalink
Browse files

Adds a UI for accepting Discord join requests in Dolphin

also did these things
fixed crash from joining user that isn't hosting via a direct connection
current game stat can now pass to override the current game in config
uses ip endpoint from dolphin.org
  • Loading branch information...
yourWaifu committed Jul 20, 2018
1 parent b7c241e commit c2aedb7649b09250485f96b85345afeb94a14eca
@@ -1330,6 +1330,7 @@ void NetPlayClient::OnTraversalStateChanged()
Disconnect();
m_dialog->OnTraversalError(m_traversal_client->GetFailureReason());
}
m_dialog->OnTraversalStateChanged(state);
}
// called from ---NETPLAY--- thread
@@ -47,6 +47,7 @@ class NetPlayUI
virtual void OnConnectionLost() = 0;
virtual void OnConnectionError(const std::string& message) = 0;
virtual void OnTraversalError(TraversalClient::FailureReason error) = 0;
virtual void OnTraversalStateChanged(TraversalClient::State state) = 0;
virtual void OnSaveDataSyncFailure() = 0;
virtual bool IsRecording() = 0;
@@ -809,8 +809,15 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
void NetPlayServer::OnTraversalStateChanged()
{
if (m_dialog && m_traversal_client->GetState() == TraversalClient::Failure)
if (!m_dialog)
return;
const TraversalClient::State state = m_traversal_client->GetState();
if (state == TraversalClient::Failure)
m_dialog->OnTraversalError(m_traversal_client->GetFailureReason());
m_dialog->OnTraversalStateChanged(state);
}
// called from ---GUI--- thread
@@ -9,6 +9,7 @@ add_executable(dolphin-emu
AboutDialog.cpp
CheatsManager.cpp
DiscordHandler.cpp
DiscordJoinRequestDialog.cpp
FIFO/FIFOPlayerWindow.cpp
FIFO/FIFOAnalyzer.cpp
HotkeyScheduler.cpp
@@ -0,0 +1,81 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#ifdef USE_DISCORD_PRESENCE
#include <iterator>
#include <QApplication>
#include "DolphinQt/DiscordHandler.h"
#include "Common/Thread.h"
#include "UICommon/DiscordPresence.h"
DiscordHandler::DiscordHandler(QWidget* parent) : QObject{parent}, m_parent{parent}
{
connect(this, &DiscordHandler::JoinRequest, this, &DiscordHandler::ShowNewJoinRequest);
}
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::DiscordJoinRequest(const char* id, const std::string& discord_tag,
const char* avatar)
{
m_request_dialogs.emplace_front(m_parent, id, discord_tag, avatar);
emit DiscordHandler::JoinRequest();
}
void DiscordHandler::DiscordJoin()
{
emit DiscordHandler::Join();
}
void DiscordHandler::ShowNewJoinRequest()
{
m_request_dialogs.front().show();
QApplication::alert(nullptr, DiscordJoinRequestDialog::s_max_lifetime_seconds * 1000);
}
void DiscordHandler::Run()
{
while (!m_stop_requested.IsSet())
{
if (m_thread.joinable())
Discord::CallPendingCallbacks();
// close and remove dead requests
for (auto request_dialog = m_request_dialogs.rbegin();
request_dialog != m_request_dialogs.rend(); ++request_dialog)
{
if (std::time(nullptr) < request_dialog->GetCloseTimestamp())
continue;
request_dialog->close();
std::advance(request_dialog, 1);
m_request_dialogs.erase(request_dialog.base());
}
Common::SleepCurrentThread(1000 * 2);
}
}
#endif
@@ -0,0 +1,43 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
// Note using a ifdef around this class causes link issues with qt
#include <list>
#include <thread>
#include <QObject>
#include "Common/Flag.h"
#include "DolphinQt/DiscordJoinRequestDialog.h"
#include "UICommon/DiscordPresence.h"
class DiscordHandler : public QObject, public Discord::Handler
{
Q_OBJECT
public:
explicit DiscordHandler(QWidget* parent);
~DiscordHandler();
void Start();
void Stop();
void DiscordJoin() override;
void DiscordJoinRequest(const char* id, const std::string& discord_tag,
const char* avatar) override;
void ShowNewJoinRequest();
signals:
void Join();
void JoinRequest();
private:
void Run();
QWidget* m_parent;
Common::Flag m_stop_requested;
std::thread m_thread;
std::list<DiscordJoinRequestDialog> m_request_dialogs;
};
@@ -0,0 +1,90 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#ifdef USE_DISCORD_PRESENCE
#include <QGridLayout>
#include <QLabel>
#include <QPixmap>
#include <QPushButton>
#include <discord-rpc/include/discord_rpc.h>
#include "Common/HttpRequest.h"
#include "Common/StringUtil.h"
#include "DolphinQt/DiscordJoinRequestDialog.h"
DiscordJoinRequestDialog::DiscordJoinRequestDialog(QWidget* parent, const char* id,
const std::string& discord_tag,
const char* avatar)
: QDialog(parent), m_user_id(id), m_close_timestamp(std::time(nullptr) + s_max_lifetime_seconds)
{
setWindowTitle(tr("Request to Join Your Party"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QPixmap avatar_pixmap;
if (avatar[0] != '\0')
{
const std::string avatar_endpoint =
StringFromFormat("https://cdn.discordapp.com/avatars/%s/%s.png", id, avatar);
Common::HttpRequest request;
Common::HttpRequest::Response response = request.Get(avatar_endpoint);
if (response.has_value())
avatar_pixmap.loadFromData(response->data(), static_cast<uint>(response->size()), "png");
}
CreateMainLayout(discord_tag, avatar_pixmap);
ConnectWidgets();
}
std::time_t DiscordJoinRequestDialog::GetCloseTimestamp() const
{
return m_close_timestamp;
}
void DiscordJoinRequestDialog::CreateMainLayout(const std::string& discord_tag,
const QPixmap& avatar)
{
m_main_layout = new QGridLayout;
m_invite_button = new QPushButton(QString::fromWCharArray(L"\u2714 Invite"));
m_decline_button = new QPushButton(QString::fromWCharArray(L"\u2716 Decline"));
m_ignore_button = new QPushButton(tr("Ignore"));
if (!avatar.isNull())
{
QLabel* picture = new QLabel();
picture->setPixmap(avatar);
m_main_layout->addWidget(picture, 1, 0, 1, 3, Qt::AlignHCenter);
}
m_main_layout->addWidget(new QLabel(tr(discord_tag.c_str())), 2, 0, 3, 3, Qt::AlignHCenter);
m_main_layout->addWidget(new QLabel(tr("wants to join your party.")), 4, 0, 4, 3,
Qt::AlignHCenter);
m_main_layout->addWidget(m_invite_button, 8, 0);
m_main_layout->addWidget(m_decline_button, 8, 1);
m_main_layout->addWidget(m_ignore_button, 8, 2);
setLayout(m_main_layout);
}
void DiscordJoinRequestDialog::ConnectWidgets()
{
connect(m_invite_button, &QPushButton::clicked, [this] { Reply(DISCORD_REPLY_YES); });
connect(m_decline_button, &QPushButton::clicked, [this] { Reply(DISCORD_REPLY_NO); });
connect(m_ignore_button, &QPushButton::clicked, [this] { Reply(DISCORD_REPLY_IGNORE); });
connect(this, &QDialog::rejected, this, [this] { Reply(DISCORD_REPLY_IGNORE); });
}
void DiscordJoinRequestDialog::Reply(int reply)
{
Discord_Respond(m_user_id, reply);
close();
}
#endif
@@ -0,0 +1,35 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <QDialog>
#include <ctime>
class QGridLayout;
class QPixmap;
class DiscordJoinRequestDialog : public QDialog
{
Q_OBJECT
public:
explicit DiscordJoinRequestDialog(QWidget* parent, const char* id, const std::string& discord_tag,
const char* avatar);
std::time_t GetCloseTimestamp() const;
static constexpr std::time_t s_max_lifetime_seconds = 30;
private:
void CreateMainLayout(const std::string& discord_tag, const QPixmap& avatar);
void ConnectWidgets();
void Reply(int reply);
QGridLayout* m_main_layout;
QPushButton* m_invite_button;
QPushButton* m_decline_button;
QPushButton* m_ignore_button;
const char* const m_user_id;
const std::time_t m_close_timestamp;
};
@@ -108,6 +108,7 @@
<QtMoc Include="Config\PropertiesDialog.h" />
<QtMoc Include="Config\SettingsWindow.h" />
<QtMoc Include="DiscordHandler.h" />
<QtMoc Include="DiscordJoinRequestDialog.h" />
<QtMoc Include="FIFO\FIFOAnalyzer.h" />
<QtMoc Include="FIFO\FIFOPlayerWindow.h" />
<QtMoc Include="TAS\GCTASInputWindow.h" />
@@ -177,6 +178,7 @@
<ClCompile Include="$(QtMocOutPrefix)CodeWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)ControllersWindow.cpp" />
<ClCompile Include="$(QtMocOutPrefix)DiscordHandler.cpp" />
<ClCompile Include="$(QtMocOutPrefix)DiscordJoinRequestDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)DoubleClickEventFilter.cpp" />
<ClCompile Include="$(QtMocOutPrefix)ElidedButton.cpp" />
<ClCompile Include="$(QtMocOutPrefix)FlowLayout.cpp" />
@@ -323,6 +325,7 @@
<ClCompile Include="Debugger\MemoryWidget.cpp" />
<ClCompile Include="Debugger\MemoryViewWidget.cpp" />
<ClCompile Include="DiscordHandler.cpp" />
<ClCompile Include="DiscordJoinRequestDialog.cpp" />
<ClCompile Include="FIFO\FIFOAnalyzer.cpp" />
<ClCompile Include="FIFO\FIFOPlayerWindow.cpp" />
<ClCompile Include="QtUtils\WinIconHelper.cpp" />
@@ -1044,23 +1044,24 @@ 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
#ifdef USE_DISCORD_PRESENCE
m_netplay_discord = new DiscordHandler(this);
#endif
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);
#ifdef USE_DISCORD_PRESENCE
connect(m_netplay_discord, &DiscordHandler::Join, this, &MainWindow::NetPlayJoin);
Discord::InitNetPlayFunctionality([this] { m_netplay_discord->DiscordJoin(); });
Discord::InitNetPlayFunctionality(*m_netplay_discord);
m_netplay_discord->Start();
#endif
}
bool MainWindow::NetPlayJoin()
Oops, something went wrong.

0 comments on commit c2aedb7

Please sign in to comment.