mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00: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/message.h | ||||
|     multiplayer/message.cpp | ||||
|     multiplayer/state.cpp | ||||
|     multiplayer/state.h | ||||
|     multiplayer/validation.h | ||||
|     ui_settings.cpp | ||||
|     ui_settings.h | ||||
|  |  | |||
|  | @ -31,11 +31,7 @@ | |||
| #include "citra_qt/game_list.h" | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "citra_qt/main.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/ui_settings.h" | ||||
| #include "citra_qt/updater/updater.h" | ||||
| #include "citra_qt/util/clickable_label.h" | ||||
|  | @ -137,16 +133,6 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { | |||
| 
 | ||||
|     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") | ||||
|                        .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); | ||||
|     show(); | ||||
|  | @ -173,12 +159,6 @@ GMainWindow::~GMainWindow() { | |||
|         delete render_window; | ||||
| 
 | ||||
|     Pica::g_debug_context.reset(); | ||||
| 
 | ||||
|     if (state_callback_handle) { | ||||
|         if (auto member = Network::GetRoomMember().lock()) { | ||||
|             member->Unbind(state_callback_handle); | ||||
|         } | ||||
|     } | ||||
|     Network::Shutdown(); | ||||
| } | ||||
| 
 | ||||
|  | @ -192,6 +172,8 @@ void GMainWindow::InitializeWidgets() { | |||
|     game_list = new GameList(this); | ||||
|     ui.horizontalLayout->addWidget(game_list); | ||||
| 
 | ||||
|     multiplayer_state = new MultiplayerState(this, game_list->GetModel()); | ||||
| 
 | ||||
|     // Setup updater
 | ||||
|     updater = new Updater(this); | ||||
|     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 " | ||||
|            "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}) { | ||||
|         label->setVisible(false); | ||||
|         label->setFrameStyle(QFrame::NoFrame); | ||||
|         label->setContentsMargins(4, 0, 4, 0); | ||||
|         statusBar()->addPermanentWidget(label, 0); | ||||
|     } | ||||
|     statusBar()->addPermanentWidget(network_status_text, 0); | ||||
|     statusBar()->addPermanentWidget(network_status_icon, 0); | ||||
|     network_status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16)); | ||||
|     network_status_text->setText(tr("Not Connected. Click here to find a room!")); | ||||
|     statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); | ||||
|     statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); | ||||
|     statusBar()->setVisible(true); | ||||
| 
 | ||||
|     // 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::CIAInstallReport, this, &GMainWindow::OnCIAInstallReport); | ||||
|     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() { | ||||
|  | @ -462,12 +431,16 @@ void GMainWindow::ConnectMenuEvents() { | |||
|     connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible); | ||||
| 
 | ||||
|     // Multiplayer
 | ||||
|     connect(ui.action_View_Lobby, &QAction::triggered, this, &GMainWindow::OnViewLobby); | ||||
|     connect(ui.action_Start_Room, &QAction::triggered, this, &GMainWindow::OnCreateRoom); | ||||
|     connect(ui.action_Stop_Room, &QAction::triggered, this, &GMainWindow::OnCloseRoom); | ||||
|     connect(ui.action_Connect_To_Room, &QAction::triggered, this, | ||||
|             &GMainWindow::OnDirectConnectToRoom); | ||||
|     connect(ui.action_Chat, &QAction::triggered, this, &GMainWindow::OnOpenNetworkRoom); | ||||
|     connect(ui.action_View_Lobby, &QAction::triggered, multiplayer_state, | ||||
|             &MultiplayerState::OnViewLobby); | ||||
|     connect(ui.action_Start_Room, &QAction::triggered, multiplayer_state, | ||||
|             &MultiplayerState::OnCreateRoom); | ||||
|     connect(ui.action_Stop_Room, &QAction::triggered, multiplayer_state, | ||||
|             &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_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() { | ||||
|     emu_thread->SetRunning(true); | ||||
|     qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); | ||||
|  | @ -1129,80 +1078,6 @@ void GMainWindow::OnCreateGraphicsSurfaceViewer() { | |||
|     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() { | ||||
|     if (emu_thread == nullptr) { | ||||
|         status_bar_update_timer.stop(); | ||||
|  | @ -1335,17 +1210,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { | |||
|         ShutdownGame(); | ||||
| 
 | ||||
|     render_window->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(); | ||||
| 
 | ||||
|     multiplayer_state->Close(); | ||||
|     QWidget::closeEvent(event); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ class GraphicsTracingWidget; | |||
| class GraphicsVertexShaderWidget; | ||||
| class GRenderWindow; | ||||
| class MicroProfileDialog; | ||||
| class MultiplayerState; | ||||
| class ProfilerWidget; | ||||
| template <typename> | ||||
| class QFutureWatcher; | ||||
|  | @ -37,16 +38,6 @@ class RegistersWidget; | |||
| class Updater; | ||||
| class WaitTreeWidget; | ||||
| 
 | ||||
| // Multiplayer forward declarations
 | ||||
| class Lobby; | ||||
| class HostRoomWindow; | ||||
| class ClientRoomWindow; | ||||
| class DirectConnectWindow; | ||||
| 
 | ||||
| namespace Core { | ||||
| class AnnounceMultiplayerSession; | ||||
| } | ||||
| 
 | ||||
| class GMainWindow : public QMainWindow { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
|  | @ -94,16 +85,6 @@ signals: | |||
|     // Signal that tells widgets to update icons to use the current theme
 | ||||
|     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: | ||||
|     void InitializeWidgets(); | ||||
|     void InitializeDebugWidgets(); | ||||
|  | @ -173,8 +154,6 @@ private slots: | |||
|     /// Called whenever a user selects the "File->Select Game List Root" menu item
 | ||||
|     void OnMenuSelectGameListRoot(); | ||||
|     void OnMenuRecentFile(); | ||||
|     void OnNetworkStateChanged(const Network::RoomMember::State& state); | ||||
|     void OnAnnounceFailed(const Common::WebResult&); | ||||
|     void OnConfigure(); | ||||
|     void OnToggleFilterBar(); | ||||
|     void OnDisplayTitleBars(bool); | ||||
|  | @ -211,12 +190,10 @@ private: | |||
|     QLabel* emu_speed_label = nullptr; | ||||
|     QLabel* game_fps_label = nullptr; | ||||
|     QLabel* emu_frametime_label = nullptr; | ||||
|     ClickableLabel* network_status_icon = nullptr; | ||||
|     ClickableLabel* network_status_text = nullptr; | ||||
|     QTimer status_bar_update_timer; | ||||
| 
 | ||||
|     MultiplayerState* multiplayer_state = nullptr; | ||||
|     std::unique_ptr<Config> config; | ||||
|     std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; | ||||
| 
 | ||||
|     // Whether emulation is currently running in Citra.
 | ||||
|     bool emulation_running = false; | ||||
|  | @ -237,14 +214,6 @@ private: | |||
|     bool explicit_update_check = 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]; | ||||
| 
 | ||||
|     QTranslator translator; | ||||
|  | @ -260,4 +229,3 @@ protected: | |||
| 
 | ||||
| Q_DECLARE_METATYPE(size_t); | ||||
| 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/direct_connect.h" | ||||
| #include "citra_qt/multiplayer/message.h" | ||||
| #include "citra_qt/multiplayer/state.h" | ||||
| #include "citra_qt/multiplayer/validation.h" | ||||
| #include "citra_qt/ui_settings.h" | ||||
| #include "core/settings.h" | ||||
|  | @ -124,7 +125,7 @@ void DirectConnectWindow::OnConnection() { | |||
|             ShowError(NetworkMessage::USERNAME_IN_USE); | ||||
|             break; | ||||
|         case Network::RoomMember::State::Joining: | ||||
|             auto parent = static_cast<GMainWindow*>(parentWidget()); | ||||
|             auto parent = static_cast<MultiplayerState*>(parentWidget()); | ||||
|             parent->OnOpenNetworkRoom(); | ||||
|             close(); | ||||
|         } | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "citra_qt/main.h" | ||||
| #include "citra_qt/multiplayer/host_room.h" | ||||
| #include "citra_qt/multiplayer/message.h" | ||||
| #include "citra_qt/multiplayer/state.h" | ||||
| #include "citra_qt/multiplayer/validation.h" | ||||
| #include "citra_qt/ui_settings.h" | ||||
| #include "common/logging/log.h" | ||||
|  | @ -136,8 +137,8 @@ void HostRoomWindow::OnConnection() { | |||
|                     LOG_ERROR(Network, "Starting announce session failed"); | ||||
|                 } | ||||
|             } | ||||
|             auto parent = static_cast<GMainWindow*>(parentWidget()); | ||||
|             parent->ChangeRoomState(); | ||||
|             auto parent = static_cast<MultiplayerState*>(parentWidget()); | ||||
|             // parent->ChangeRoomState();
 | ||||
|             parent->OnOpenNetworkRoom(); | ||||
|             close(); | ||||
|             emit Closed(); | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
| #include "citra_qt/multiplayer/lobby.h" | ||||
| #include "citra_qt/multiplayer/lobby_p.h" | ||||
| #include "citra_qt/multiplayer/message.h" | ||||
| #include "citra_qt/multiplayer/state.h" | ||||
| #include "citra_qt/multiplayer/validation.h" | ||||
| #include "citra_qt/ui_settings.h" | ||||
| #include "common/logging/log.h" | ||||
|  | @ -51,9 +52,9 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | |||
|     ui->nickname->setText(UISettings::values.nickname); | ||||
| 
 | ||||
|     // 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->chat, &QPushButton::pressed, p, &GMainWindow::OnOpenNetworkRoom); | ||||
|     connect(ui->chat, &QPushButton::pressed, p, &MultiplayerState::OnOpenNetworkRoom); | ||||
|     connect(ui->games_owned, &QCheckBox::stateChanged, proxy, | ||||
|             &LobbyFilterProxyModel::SetFilterOwned); | ||||
|     connect(ui->hide_full, &QCheckBox::stateChanged, proxy, &LobbyFilterProxyModel::SetFilterFull); | ||||
|  | @ -64,7 +65,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | |||
|     // Actions
 | ||||
|     connect(this, &Lobby::LobbyRefreshed, this, &Lobby::OnRefreshLobby); | ||||
|     // 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
 | ||||
|     if (auto member = Network::GetRoomMember().lock()) { | ||||
|  | @ -90,8 +91,6 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | |||
|     ui->chat->setDisabled(true); | ||||
| } | ||||
| 
 | ||||
| Lobby::~Lobby() {} | ||||
| 
 | ||||
| const QString Lobby::PasswordPrompt() { | ||||
|     bool ok; | ||||
|     const QString text = | ||||
|  | @ -305,7 +304,7 @@ void Lobby::OnConnection() { | |||
|             ShowError(NetworkMessage::UNABLE_TO_CONNECT); | ||||
|             break; | ||||
|         case Network::RoomMember::State::Joining: | ||||
|             auto parent = static_cast<GMainWindow*>(parentWidget()); | ||||
|             auto parent = static_cast<MultiplayerState*>(parentWidget()); | ||||
|             parent->OnOpenNetworkRoom(); | ||||
|             close(); | ||||
|             break; | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ class Lobby : public QDialog { | |||
| public: | ||||
|     explicit Lobby(QWidget* parent, QStandardItemModel* list, | ||||
|                    std::shared_ptr<Core::AnnounceMultiplayerSession> session); | ||||
|     ~Lobby(); | ||||
|     ~Lobby() = default; | ||||
| 
 | ||||
| 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue