mirror of
https://github.com/Lime3DS/Lime3DS
synced 2024-12-26 09:02:44 -06:00
Split multiplayer code into its own class
This commit is contained in:
parent
ddbbab8fd6
commit
f346a9d372
9 changed files with 253 additions and 195 deletions
|
@ -69,6 +69,8 @@ add_executable(citra-qt
|
||||||
multiplayer/lobby.cpp
|
multiplayer/lobby.cpp
|
||||||
multiplayer/message.h
|
multiplayer/message.h
|
||||||
multiplayer/message.cpp
|
multiplayer/message.cpp
|
||||||
|
multiplayer/state.cpp
|
||||||
|
multiplayer/state.h
|
||||||
multiplayer/validation.h
|
multiplayer/validation.h
|
||||||
ui_settings.cpp
|
ui_settings.cpp
|
||||||
ui_settings.h
|
ui_settings.h
|
||||||
|
|
|
@ -31,11 +31,7 @@
|
||||||
#include "citra_qt/game_list.h"
|
#include "citra_qt/game_list.h"
|
||||||
#include "citra_qt/hotkeys.h"
|
#include "citra_qt/hotkeys.h"
|
||||||
#include "citra_qt/main.h"
|
#include "citra_qt/main.h"
|
||||||
#include "citra_qt/multiplayer/client_room.h"
|
#include "citra_qt/multiplayer/state.h"
|
||||||
#include "citra_qt/multiplayer/direct_connect.h"
|
|
||||||
#include "citra_qt/multiplayer/host_room.h"
|
|
||||||
#include "citra_qt/multiplayer/lobby.h"
|
|
||||||
#include "citra_qt/multiplayer/message.h"
|
|
||||||
#include "citra_qt/ui_settings.h"
|
#include "citra_qt/ui_settings.h"
|
||||||
#include "citra_qt/updater/updater.h"
|
#include "citra_qt/updater/updater.h"
|
||||||
#include "citra_qt/util/clickable_label.h"
|
#include "citra_qt/util/clickable_label.h"
|
||||||
|
@ -137,16 +133,6 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) {
|
||||||
|
|
||||||
Network::Init();
|
Network::Init();
|
||||||
|
|
||||||
if (auto member = Network::GetRoomMember().lock()) {
|
|
||||||
// register the network structs to use in slots and signals
|
|
||||||
qRegisterMetaType<Network::RoomMember::State>();
|
|
||||||
state_callback_handle = member->BindOnStateChanged(
|
|
||||||
[this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); });
|
|
||||||
connect(this, &GMainWindow::NetworkStateChanged, this, &GMainWindow::OnNetworkStateChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
qRegisterMetaType<Common::WebResult>();
|
|
||||||
|
|
||||||
setWindowTitle(QString("Citra %1| %2-%3")
|
setWindowTitle(QString("Citra %1| %2-%3")
|
||||||
.arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));
|
.arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));
|
||||||
show();
|
show();
|
||||||
|
@ -173,12 +159,6 @@ GMainWindow::~GMainWindow() {
|
||||||
delete render_window;
|
delete render_window;
|
||||||
|
|
||||||
Pica::g_debug_context.reset();
|
Pica::g_debug_context.reset();
|
||||||
|
|
||||||
if (state_callback_handle) {
|
|
||||||
if (auto member = Network::GetRoomMember().lock()) {
|
|
||||||
member->Unbind(state_callback_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Network::Shutdown();
|
Network::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +172,8 @@ void GMainWindow::InitializeWidgets() {
|
||||||
game_list = new GameList(this);
|
game_list = new GameList(this);
|
||||||
ui.horizontalLayout->addWidget(game_list);
|
ui.horizontalLayout->addWidget(game_list);
|
||||||
|
|
||||||
|
multiplayer_state = new MultiplayerState(this, game_list->GetModel());
|
||||||
|
|
||||||
// Setup updater
|
// Setup updater
|
||||||
updater = new Updater(this);
|
updater = new Updater(this);
|
||||||
UISettings::values.updater_found = updater->HasUpdater();
|
UISettings::values.updater_found = updater->HasUpdater();
|
||||||
|
@ -220,24 +202,14 @@ void GMainWindow::InitializeWidgets() {
|
||||||
tr("Time taken to emulate a 3DS frame, not counting framelimiting or v-sync. For "
|
tr("Time taken to emulate a 3DS frame, not counting framelimiting or v-sync. For "
|
||||||
"full-speed emulation this should be at most 16.67 ms."));
|
"full-speed emulation this should be at most 16.67 ms."));
|
||||||
|
|
||||||
announce_multiplayer_session = std::make_shared<Core::AnnounceMultiplayerSession>();
|
|
||||||
announce_multiplayer_session->BindErrorCallback(
|
|
||||||
[this](const Common::WebResult& result) { emit AnnounceFailed(result); });
|
|
||||||
connect(this, &GMainWindow::AnnounceFailed, this, &GMainWindow::OnAnnounceFailed);
|
|
||||||
network_status_text = new ClickableLabel(this);
|
|
||||||
network_status_icon = new ClickableLabel(this);
|
|
||||||
network_status_text->setToolTip(tr("Current connection status"));
|
|
||||||
|
|
||||||
for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) {
|
for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) {
|
||||||
label->setVisible(false);
|
label->setVisible(false);
|
||||||
label->setFrameStyle(QFrame::NoFrame);
|
label->setFrameStyle(QFrame::NoFrame);
|
||||||
label->setContentsMargins(4, 0, 4, 0);
|
label->setContentsMargins(4, 0, 4, 0);
|
||||||
statusBar()->addPermanentWidget(label, 0);
|
statusBar()->addPermanentWidget(label, 0);
|
||||||
}
|
}
|
||||||
statusBar()->addPermanentWidget(network_status_text, 0);
|
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0);
|
||||||
statusBar()->addPermanentWidget(network_status_icon, 0);
|
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0);
|
||||||
network_status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16));
|
|
||||||
network_status_text->setText(tr("Not Connected. Click here to find a room!"));
|
|
||||||
statusBar()->setVisible(true);
|
statusBar()->setVisible(true);
|
||||||
|
|
||||||
// Removes an ugly inner border from the status bar widgets under Linux
|
// Removes an ugly inner border from the status bar widgets under Linux
|
||||||
|
@ -431,9 +403,6 @@ void GMainWindow::ConnectWidgetEvents() {
|
||||||
connect(this, &GMainWindow::UpdateProgress, this, &GMainWindow::OnUpdateProgress);
|
connect(this, &GMainWindow::UpdateProgress, this, &GMainWindow::OnUpdateProgress);
|
||||||
connect(this, &GMainWindow::CIAInstallReport, this, &GMainWindow::OnCIAInstallReport);
|
connect(this, &GMainWindow::CIAInstallReport, this, &GMainWindow::OnCIAInstallReport);
|
||||||
connect(this, &GMainWindow::CIAInstallFinished, this, &GMainWindow::OnCIAInstallFinished);
|
connect(this, &GMainWindow::CIAInstallFinished, this, &GMainWindow::OnCIAInstallFinished);
|
||||||
|
|
||||||
connect(network_status_text, &ClickableLabel::clicked, this, &GMainWindow::OnOpenNetworkRoom);
|
|
||||||
connect(network_status_icon, &ClickableLabel::clicked, this, &GMainWindow::OnOpenNetworkRoom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::ConnectMenuEvents() {
|
void GMainWindow::ConnectMenuEvents() {
|
||||||
|
@ -462,12 +431,16 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
|
connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
|
||||||
|
|
||||||
// Multiplayer
|
// Multiplayer
|
||||||
connect(ui.action_View_Lobby, &QAction::triggered, this, &GMainWindow::OnViewLobby);
|
connect(ui.action_View_Lobby, &QAction::triggered, multiplayer_state,
|
||||||
connect(ui.action_Start_Room, &QAction::triggered, this, &GMainWindow::OnCreateRoom);
|
&MultiplayerState::OnViewLobby);
|
||||||
connect(ui.action_Stop_Room, &QAction::triggered, this, &GMainWindow::OnCloseRoom);
|
connect(ui.action_Start_Room, &QAction::triggered, multiplayer_state,
|
||||||
connect(ui.action_Connect_To_Room, &QAction::triggered, this,
|
&MultiplayerState::OnCreateRoom);
|
||||||
&GMainWindow::OnDirectConnectToRoom);
|
connect(ui.action_Stop_Room, &QAction::triggered, multiplayer_state,
|
||||||
connect(ui.action_Chat, &QAction::triggered, this, &GMainWindow::OnOpenNetworkRoom);
|
&MultiplayerState::OnCloseRoom);
|
||||||
|
connect(ui.action_Connect_To_Room, &QAction::triggered, multiplayer_state,
|
||||||
|
&MultiplayerState::OnDirectConnectToRoom);
|
||||||
|
connect(ui.action_Chat, &QAction::triggered, multiplayer_state,
|
||||||
|
&MultiplayerState::OnOpenNetworkRoom);
|
||||||
|
|
||||||
ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key());
|
ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key());
|
||||||
ui.action_Screen_Layout_Swap_Screens->setShortcut(
|
ui.action_Screen_Layout_Swap_Screens->setShortcut(
|
||||||
|
@ -931,30 +904,6 @@ void GMainWindow::OnMenuRecentFile() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnNetworkStateChanged(const Network::RoomMember::State& state) {
|
|
||||||
LOG_INFO(Frontend, "network state change");
|
|
||||||
if (state == Network::RoomMember::State::Joined) {
|
|
||||||
network_status_icon->setPixmap(QIcon::fromTheme("connected").pixmap(16));
|
|
||||||
network_status_text->setText(tr("Connected"));
|
|
||||||
ui.action_Chat->setEnabled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
network_status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16));
|
|
||||||
network_status_text->setText(tr("Not Connected"));
|
|
||||||
ui.action_Chat->setDisabled(true);
|
|
||||||
|
|
||||||
ChangeRoomState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnAnnounceFailed(const Common::WebResult& result) {
|
|
||||||
announce_multiplayer_session->Stop();
|
|
||||||
QMessageBox::warning(
|
|
||||||
this, tr("Error"),
|
|
||||||
tr("Announcing the room failed.\nThe room will not get listed publicly.\nError: ") +
|
|
||||||
QString::fromStdString(result.result_string),
|
|
||||||
QMessageBox::Ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnStartGame() {
|
void GMainWindow::OnStartGame() {
|
||||||
emu_thread->SetRunning(true);
|
emu_thread->SetRunning(true);
|
||||||
qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
|
qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
|
||||||
|
@ -1129,80 +1078,6 @@ void GMainWindow::OnCreateGraphicsSurfaceViewer() {
|
||||||
graphicsSurfaceViewerWidget->show();
|
graphicsSurfaceViewerWidget->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BringWidgetToFront(QWidget* widget) {
|
|
||||||
widget->show();
|
|
||||||
widget->activateWindow();
|
|
||||||
widget->raise();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnViewLobby() {
|
|
||||||
if (lobby == nullptr) {
|
|
||||||
lobby = new Lobby(this, game_list->GetModel(), announce_multiplayer_session);
|
|
||||||
connect(lobby, &Lobby::Closed, [&] {
|
|
||||||
LOG_INFO(Frontend, "Destroying lobby");
|
|
||||||
// lobby->close();
|
|
||||||
lobby = nullptr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
BringWidgetToFront(lobby);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnCreateRoom() {
|
|
||||||
if (host_room == nullptr) {
|
|
||||||
host_room = new HostRoomWindow(this, game_list->GetModel(), announce_multiplayer_session);
|
|
||||||
connect(host_room, &HostRoomWindow::Closed, [&] {
|
|
||||||
// host_room->close();
|
|
||||||
LOG_INFO(Frontend, "Destroying host room");
|
|
||||||
host_room = nullptr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
BringWidgetToFront(host_room);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnCloseRoom() {
|
|
||||||
if (auto room = Network::GetRoom().lock()) {
|
|
||||||
if (room->GetState() == Network::Room::State::Open) {
|
|
||||||
if (NetworkMessage::WarnCloseRoom()) {
|
|
||||||
room->Destroy();
|
|
||||||
announce_multiplayer_session->Stop();
|
|
||||||
// host_room->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnOpenNetworkRoom() {
|
|
||||||
if (auto member = Network::GetRoomMember().lock()) {
|
|
||||||
if (member->IsConnected()) {
|
|
||||||
if (client_room == nullptr) {
|
|
||||||
client_room = new ClientRoomWindow(this);
|
|
||||||
connect(client_room, &ClientRoomWindow::Closed, [&] {
|
|
||||||
LOG_INFO(Frontend, "Destroying client room");
|
|
||||||
// client_room->close();
|
|
||||||
client_room = nullptr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
BringWidgetToFront(client_room);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the user is not a member of a room, show the lobby instead.
|
|
||||||
// This is currently only used on the clickable label in the status bar
|
|
||||||
OnViewLobby();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnDirectConnectToRoom() {
|
|
||||||
if (direct_connect == nullptr) {
|
|
||||||
direct_connect = new DirectConnectWindow(this);
|
|
||||||
connect(direct_connect, &DirectConnectWindow::Closed, [&] {
|
|
||||||
LOG_INFO(Frontend, "Destroying direct connect");
|
|
||||||
// direct_connect->close();
|
|
||||||
direct_connect = nullptr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
BringWidgetToFront(direct_connect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::UpdateStatusBar() {
|
void GMainWindow::UpdateStatusBar() {
|
||||||
if (emu_thread == nullptr) {
|
if (emu_thread == nullptr) {
|
||||||
status_bar_update_timer.stop();
|
status_bar_update_timer.stop();
|
||||||
|
@ -1335,17 +1210,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
|
||||||
ShutdownGame();
|
ShutdownGame();
|
||||||
|
|
||||||
render_window->close();
|
render_window->close();
|
||||||
|
multiplayer_state->Close();
|
||||||
// Close Multiplayer windows
|
|
||||||
if (host_room)
|
|
||||||
host_room->close();
|
|
||||||
if (direct_connect)
|
|
||||||
direct_connect->close();
|
|
||||||
if (client_room)
|
|
||||||
client_room->close();
|
|
||||||
if (lobby)
|
|
||||||
lobby->close();
|
|
||||||
|
|
||||||
QWidget::closeEvent(event);
|
QWidget::closeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ class GraphicsTracingWidget;
|
||||||
class GraphicsVertexShaderWidget;
|
class GraphicsVertexShaderWidget;
|
||||||
class GRenderWindow;
|
class GRenderWindow;
|
||||||
class MicroProfileDialog;
|
class MicroProfileDialog;
|
||||||
|
class MultiplayerState;
|
||||||
class ProfilerWidget;
|
class ProfilerWidget;
|
||||||
template <typename>
|
template <typename>
|
||||||
class QFutureWatcher;
|
class QFutureWatcher;
|
||||||
|
@ -37,16 +38,6 @@ class RegistersWidget;
|
||||||
class Updater;
|
class Updater;
|
||||||
class WaitTreeWidget;
|
class WaitTreeWidget;
|
||||||
|
|
||||||
// Multiplayer forward declarations
|
|
||||||
class Lobby;
|
|
||||||
class HostRoomWindow;
|
|
||||||
class ClientRoomWindow;
|
|
||||||
class DirectConnectWindow;
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class AnnounceMultiplayerSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
class GMainWindow : public QMainWindow {
|
class GMainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -94,16 +85,6 @@ signals:
|
||||||
// Signal that tells widgets to update icons to use the current theme
|
// Signal that tells widgets to update icons to use the current theme
|
||||||
void UpdateThemedIcons();
|
void UpdateThemedIcons();
|
||||||
|
|
||||||
void NetworkStateChanged(const Network::RoomMember::State&);
|
|
||||||
void AnnounceFailed(const Common::WebResult&);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void OnViewLobby();
|
|
||||||
void OnCreateRoom();
|
|
||||||
void OnCloseRoom();
|
|
||||||
void OnOpenNetworkRoom();
|
|
||||||
void OnDirectConnectToRoom();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitializeWidgets();
|
void InitializeWidgets();
|
||||||
void InitializeDebugWidgets();
|
void InitializeDebugWidgets();
|
||||||
|
@ -173,8 +154,6 @@ private slots:
|
||||||
/// Called whenever a user selects the "File->Select Game List Root" menu item
|
/// Called whenever a user selects the "File->Select Game List Root" menu item
|
||||||
void OnMenuSelectGameListRoot();
|
void OnMenuSelectGameListRoot();
|
||||||
void OnMenuRecentFile();
|
void OnMenuRecentFile();
|
||||||
void OnNetworkStateChanged(const Network::RoomMember::State& state);
|
|
||||||
void OnAnnounceFailed(const Common::WebResult&);
|
|
||||||
void OnConfigure();
|
void OnConfigure();
|
||||||
void OnToggleFilterBar();
|
void OnToggleFilterBar();
|
||||||
void OnDisplayTitleBars(bool);
|
void OnDisplayTitleBars(bool);
|
||||||
|
@ -211,12 +190,10 @@ private:
|
||||||
QLabel* emu_speed_label = nullptr;
|
QLabel* emu_speed_label = nullptr;
|
||||||
QLabel* game_fps_label = nullptr;
|
QLabel* game_fps_label = nullptr;
|
||||||
QLabel* emu_frametime_label = nullptr;
|
QLabel* emu_frametime_label = nullptr;
|
||||||
ClickableLabel* network_status_icon = nullptr;
|
|
||||||
ClickableLabel* network_status_text = nullptr;
|
|
||||||
QTimer status_bar_update_timer;
|
QTimer status_bar_update_timer;
|
||||||
|
|
||||||
|
MultiplayerState* multiplayer_state = nullptr;
|
||||||
std::unique_ptr<Config> config;
|
std::unique_ptr<Config> config;
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
|
||||||
|
|
||||||
// Whether emulation is currently running in Citra.
|
// Whether emulation is currently running in Citra.
|
||||||
bool emulation_running = false;
|
bool emulation_running = false;
|
||||||
|
@ -237,14 +214,6 @@ private:
|
||||||
bool explicit_update_check = false;
|
bool explicit_update_check = false;
|
||||||
bool defer_update_prompt = false;
|
bool defer_update_prompt = false;
|
||||||
|
|
||||||
// Multiplayer windows
|
|
||||||
Lobby* lobby = nullptr;
|
|
||||||
HostRoomWindow* host_room = nullptr;
|
|
||||||
ClientRoomWindow* client_room = nullptr;
|
|
||||||
DirectConnectWindow* direct_connect = nullptr;
|
|
||||||
|
|
||||||
Network::RoomMember::CallbackHandle<Network::RoomMember::State> state_callback_handle;
|
|
||||||
|
|
||||||
QAction* actions_recent_files[max_recent_files_item];
|
QAction* actions_recent_files[max_recent_files_item];
|
||||||
|
|
||||||
QTranslator translator;
|
QTranslator translator;
|
||||||
|
@ -260,4 +229,3 @@ protected:
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(size_t);
|
Q_DECLARE_METATYPE(size_t);
|
||||||
Q_DECLARE_METATYPE(Service::AM::InstallStatus);
|
Q_DECLARE_METATYPE(Service::AM::InstallStatus);
|
||||||
Q_DECLARE_METATYPE(Common::WebResult);
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "citra_qt/multiplayer/client_room.h"
|
#include "citra_qt/multiplayer/client_room.h"
|
||||||
#include "citra_qt/multiplayer/direct_connect.h"
|
#include "citra_qt/multiplayer/direct_connect.h"
|
||||||
#include "citra_qt/multiplayer/message.h"
|
#include "citra_qt/multiplayer/message.h"
|
||||||
|
#include "citra_qt/multiplayer/state.h"
|
||||||
#include "citra_qt/multiplayer/validation.h"
|
#include "citra_qt/multiplayer/validation.h"
|
||||||
#include "citra_qt/ui_settings.h"
|
#include "citra_qt/ui_settings.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
@ -124,7 +125,7 @@ void DirectConnectWindow::OnConnection() {
|
||||||
ShowError(NetworkMessage::USERNAME_IN_USE);
|
ShowError(NetworkMessage::USERNAME_IN_USE);
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::State::Joining:
|
case Network::RoomMember::State::Joining:
|
||||||
auto parent = static_cast<GMainWindow*>(parentWidget());
|
auto parent = static_cast<MultiplayerState*>(parentWidget());
|
||||||
parent->OnOpenNetworkRoom();
|
parent->OnOpenNetworkRoom();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "citra_qt/main.h"
|
#include "citra_qt/main.h"
|
||||||
#include "citra_qt/multiplayer/host_room.h"
|
#include "citra_qt/multiplayer/host_room.h"
|
||||||
#include "citra_qt/multiplayer/message.h"
|
#include "citra_qt/multiplayer/message.h"
|
||||||
|
#include "citra_qt/multiplayer/state.h"
|
||||||
#include "citra_qt/multiplayer/validation.h"
|
#include "citra_qt/multiplayer/validation.h"
|
||||||
#include "citra_qt/ui_settings.h"
|
#include "citra_qt/ui_settings.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
@ -136,8 +137,8 @@ void HostRoomWindow::OnConnection() {
|
||||||
LOG_ERROR(Network, "Starting announce session failed");
|
LOG_ERROR(Network, "Starting announce session failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto parent = static_cast<GMainWindow*>(parentWidget());
|
auto parent = static_cast<MultiplayerState*>(parentWidget());
|
||||||
parent->ChangeRoomState();
|
// parent->ChangeRoomState();
|
||||||
parent->OnOpenNetworkRoom();
|
parent->OnOpenNetworkRoom();
|
||||||
close();
|
close();
|
||||||
emit Closed();
|
emit Closed();
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "citra_qt/multiplayer/lobby.h"
|
#include "citra_qt/multiplayer/lobby.h"
|
||||||
#include "citra_qt/multiplayer/lobby_p.h"
|
#include "citra_qt/multiplayer/lobby_p.h"
|
||||||
#include "citra_qt/multiplayer/message.h"
|
#include "citra_qt/multiplayer/message.h"
|
||||||
|
#include "citra_qt/multiplayer/state.h"
|
||||||
#include "citra_qt/multiplayer/validation.h"
|
#include "citra_qt/multiplayer/validation.h"
|
||||||
#include "citra_qt/ui_settings.h"
|
#include "citra_qt/ui_settings.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
@ -51,9 +52,9 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
ui->nickname->setText(UISettings::values.nickname);
|
ui->nickname->setText(UISettings::values.nickname);
|
||||||
|
|
||||||
// UI Buttons
|
// UI Buttons
|
||||||
GMainWindow* p = reinterpret_cast<GMainWindow*>(parent);
|
MultiplayerState* p = reinterpret_cast<MultiplayerState*>(parent);
|
||||||
connect(ui->refresh_list, &QPushButton::pressed, this, &Lobby::RefreshLobby);
|
connect(ui->refresh_list, &QPushButton::pressed, this, &Lobby::RefreshLobby);
|
||||||
connect(ui->chat, &QPushButton::pressed, p, &GMainWindow::OnOpenNetworkRoom);
|
connect(ui->chat, &QPushButton::pressed, p, &MultiplayerState::OnOpenNetworkRoom);
|
||||||
connect(ui->games_owned, &QCheckBox::stateChanged, proxy,
|
connect(ui->games_owned, &QCheckBox::stateChanged, proxy,
|
||||||
&LobbyFilterProxyModel::SetFilterOwned);
|
&LobbyFilterProxyModel::SetFilterOwned);
|
||||||
connect(ui->hide_full, &QCheckBox::stateChanged, proxy, &LobbyFilterProxyModel::SetFilterFull);
|
connect(ui->hide_full, &QCheckBox::stateChanged, proxy, &LobbyFilterProxyModel::SetFilterFull);
|
||||||
|
@ -64,7 +65,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
// Actions
|
// Actions
|
||||||
connect(this, &Lobby::LobbyRefreshed, this, &Lobby::OnRefreshLobby);
|
connect(this, &Lobby::LobbyRefreshed, this, &Lobby::OnRefreshLobby);
|
||||||
// TODO(jroweboy): change this slot to OnConnected?
|
// TODO(jroweboy): change this slot to OnConnected?
|
||||||
connect(this, &Lobby::Connected, p, &GMainWindow::OnOpenNetworkRoom);
|
connect(this, &Lobby::Connected, p, &MultiplayerState::OnOpenNetworkRoom);
|
||||||
|
|
||||||
// setup the callbacks for network updates
|
// setup the callbacks for network updates
|
||||||
if (auto member = Network::GetRoomMember().lock()) {
|
if (auto member = Network::GetRoomMember().lock()) {
|
||||||
|
@ -90,8 +91,6 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
ui->chat->setDisabled(true);
|
ui->chat->setDisabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lobby::~Lobby() {}
|
|
||||||
|
|
||||||
const QString Lobby::PasswordPrompt() {
|
const QString Lobby::PasswordPrompt() {
|
||||||
bool ok;
|
bool ok;
|
||||||
const QString text =
|
const QString text =
|
||||||
|
@ -305,7 +304,7 @@ void Lobby::OnConnection() {
|
||||||
ShowError(NetworkMessage::UNABLE_TO_CONNECT);
|
ShowError(NetworkMessage::UNABLE_TO_CONNECT);
|
||||||
break;
|
break;
|
||||||
case Network::RoomMember::State::Joining:
|
case Network::RoomMember::State::Joining:
|
||||||
auto parent = static_cast<GMainWindow*>(parentWidget());
|
auto parent = static_cast<MultiplayerState*>(parentWidget());
|
||||||
parent->OnOpenNetworkRoom();
|
parent->OnOpenNetworkRoom();
|
||||||
close();
|
close();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Lobby : public QDialog {
|
||||||
public:
|
public:
|
||||||
explicit Lobby(QWidget* parent, QStandardItemModel* list,
|
explicit Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> session);
|
std::shared_ptr<Core::AnnounceMultiplayerSession> session);
|
||||||
~Lobby();
|
~Lobby() = default;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**
|
/**
|
||||||
|
|
157
src/citra_qt/multiplayer/state.cpp
Normal file
157
src/citra_qt/multiplayer/state.cpp
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
// Copyright 2018 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include "citra_qt/game_list.h"
|
||||||
|
#include "citra_qt/multiplayer/client_room.h"
|
||||||
|
#include "citra_qt/multiplayer/direct_connect.h"
|
||||||
|
#include "citra_qt/multiplayer/host_room.h"
|
||||||
|
#include "citra_qt/multiplayer/lobby.h"
|
||||||
|
#include "citra_qt/multiplayer/message.h"
|
||||||
|
#include "citra_qt/multiplayer/state.h"
|
||||||
|
#include "citra_qt/util/clickable_label.h"
|
||||||
|
#include "common/announce_multiplayer_room.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
|
||||||
|
MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model)
|
||||||
|
: QWidget(parent), game_list_model(game_list_model) {
|
||||||
|
if (auto member = Network::GetRoomMember().lock()) {
|
||||||
|
// register the network structs to use in slots and signals
|
||||||
|
qRegisterMetaType<Network::RoomMember::State>();
|
||||||
|
state_callback_handle = member->BindOnStateChanged(
|
||||||
|
[this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); });
|
||||||
|
connect(this, &MultiplayerState::NetworkStateChanged, this,
|
||||||
|
&MultiplayerState::OnNetworkStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
qRegisterMetaType<Common::WebResult>();
|
||||||
|
announce_multiplayer_session = std::make_shared<Core::AnnounceMultiplayerSession>();
|
||||||
|
announce_multiplayer_session->BindErrorCallback(
|
||||||
|
[this](const Common::WebResult& result) { emit AnnounceFailed(result); });
|
||||||
|
connect(this, &MultiplayerState::AnnounceFailed, this, &MultiplayerState::OnAnnounceFailed);
|
||||||
|
|
||||||
|
status_text = new ClickableLabel(this);
|
||||||
|
status_icon = new ClickableLabel(this);
|
||||||
|
status_text->setToolTip(tr("Current connection status"));
|
||||||
|
status_text->setText(tr("Not Connected. Click here to find a room!"));
|
||||||
|
status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16));
|
||||||
|
|
||||||
|
connect(status_text, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom);
|
||||||
|
connect(status_icon, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiplayerState::~MultiplayerState() {
|
||||||
|
if (state_callback_handle) {
|
||||||
|
if (auto member = Network::GetRoomMember().lock()) {
|
||||||
|
member->Unbind(state_callback_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::Close() {
|
||||||
|
if (host_room)
|
||||||
|
host_room->close();
|
||||||
|
if (direct_connect)
|
||||||
|
direct_connect->close();
|
||||||
|
if (client_room)
|
||||||
|
client_room->close();
|
||||||
|
if (lobby)
|
||||||
|
lobby->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& state) {
|
||||||
|
NGLOG_DEBUG(Frontend, "Network state change");
|
||||||
|
if (state == Network::RoomMember::State::Joined) {
|
||||||
|
status_icon->setPixmap(QIcon::fromTheme("connected").pixmap(16));
|
||||||
|
status_text->setText(tr("Connected"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16));
|
||||||
|
status_text->setText(tr("Not Connected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnAnnounceFailed(const Common::WebResult& result) {
|
||||||
|
announce_multiplayer_session->Stop();
|
||||||
|
QMessageBox::warning(this, tr("Error"),
|
||||||
|
tr("Failed to announce the room to the public lobby.\nThe room will not "
|
||||||
|
"get listed publicly.\nError: ") +
|
||||||
|
QString::fromStdString(result.result_string),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BringWidgetToFront(QWidget* widget) {
|
||||||
|
widget->show();
|
||||||
|
widget->activateWindow();
|
||||||
|
widget->raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnViewLobby() {
|
||||||
|
if (lobby == nullptr) {
|
||||||
|
lobby = new Lobby(this, game_list_model, announce_multiplayer_session);
|
||||||
|
connect(lobby, &Lobby::Closed, [&] {
|
||||||
|
LOG_INFO(Frontend, "Destroying lobby");
|
||||||
|
// lobby->close();
|
||||||
|
lobby = nullptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
BringWidgetToFront(lobby);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnCreateRoom() {
|
||||||
|
if (host_room == nullptr) {
|
||||||
|
host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session);
|
||||||
|
connect(host_room, &HostRoomWindow::Closed, [&] {
|
||||||
|
// host_room->close();
|
||||||
|
LOG_INFO(Frontend, "Destroying host room");
|
||||||
|
host_room = nullptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
BringWidgetToFront(host_room);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnCloseRoom() {
|
||||||
|
if (auto room = Network::GetRoom().lock()) {
|
||||||
|
if (room->GetState() == Network::Room::State::Open) {
|
||||||
|
if (NetworkMessage::WarnCloseRoom()) {
|
||||||
|
room->Destroy();
|
||||||
|
announce_multiplayer_session->Stop();
|
||||||
|
// host_room->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnOpenNetworkRoom() {
|
||||||
|
if (auto member = Network::GetRoomMember().lock()) {
|
||||||
|
if (member->IsConnected()) {
|
||||||
|
if (client_room == nullptr) {
|
||||||
|
client_room = new ClientRoomWindow(this);
|
||||||
|
connect(client_room, &ClientRoomWindow::Closed, [&] {
|
||||||
|
LOG_INFO(Frontend, "Destroying client room");
|
||||||
|
// client_room->close();
|
||||||
|
client_room = nullptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
BringWidgetToFront(client_room);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the user is not a member of a room, show the lobby instead.
|
||||||
|
// This is currently only used on the clickable label in the status bar
|
||||||
|
OnViewLobby();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnDirectConnectToRoom() {
|
||||||
|
if (direct_connect == nullptr) {
|
||||||
|
direct_connect = new DirectConnectWindow(this);
|
||||||
|
connect(direct_connect, &DirectConnectWindow::Closed, [&] {
|
||||||
|
LOG_INFO(Frontend, "Destroying direct connect");
|
||||||
|
// direct_connect->close();
|
||||||
|
direct_connect = nullptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
BringWidgetToFront(direct_connect);
|
||||||
|
}
|
65
src/citra_qt/multiplayer/state.h
Normal file
65
src/citra_qt/multiplayer/state.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// Copyright 2018 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "network/network.h"
|
||||||
|
|
||||||
|
class QStandardItemModel;
|
||||||
|
class Lobby;
|
||||||
|
class HostRoomWindow;
|
||||||
|
class ClientRoomWindow;
|
||||||
|
class DirectConnectWindow;
|
||||||
|
class ClickableLabel;
|
||||||
|
namespace Core {
|
||||||
|
class AnnounceMultiplayerSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiplayerState : public QWidget {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list);
|
||||||
|
~MultiplayerState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close all open multiplayer related dialogs
|
||||||
|
*/
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
ClickableLabel* GetStatusText() const {
|
||||||
|
return status_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickableLabel* GetStatusIcon() const {
|
||||||
|
return status_icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void OnNetworkStateChanged(const Network::RoomMember::State& state);
|
||||||
|
void OnViewLobby();
|
||||||
|
void OnCreateRoom();
|
||||||
|
void OnCloseRoom();
|
||||||
|
void OnOpenNetworkRoom();
|
||||||
|
void OnDirectConnectToRoom();
|
||||||
|
void OnAnnounceFailed(const Common::WebResult&);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void NetworkStateChanged(const Network::RoomMember::State&);
|
||||||
|
void AnnounceFailed(const Common::WebResult&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Lobby* lobby = nullptr;
|
||||||
|
HostRoomWindow* host_room = nullptr;
|
||||||
|
ClientRoomWindow* client_room = nullptr;
|
||||||
|
DirectConnectWindow* direct_connect = nullptr;
|
||||||
|
ClickableLabel* status_icon = nullptr;
|
||||||
|
ClickableLabel* status_text = nullptr;
|
||||||
|
QStandardItemModel* game_list_model = nullptr;
|
||||||
|
std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
||||||
|
Network::RoomMember::CallbackHandle<Network::RoomMember::State> state_callback_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Common::WebResult);
|
Loading…
Reference in a new issue