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/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…
	
	Add table
		Add a link
		
	
		Reference in a new issue