diff --git a/src/core/announce_multiplayer_session.cpp b/src/core/announce_multiplayer_session.cpp index db9eaeac8..8f96b4ee8 100644 --- a/src/core/announce_multiplayer_session.cpp +++ b/src/core/announce_multiplayer_session.cpp @@ -20,7 +20,8 @@ namespace Core { // Time between room is announced to web_service static constexpr std::chrono::seconds announce_time_interval(15); -AnnounceMultiplayerSession::AnnounceMultiplayerSession() { +AnnounceMultiplayerSession::AnnounceMultiplayerSession(Network::RoomNetwork& room_network_) + : room_network{room_network_} { #ifdef ENABLE_WEB_SERVICE backend = std::make_unique(Settings::values.web_api_url.GetValue(), Settings::values.yuzu_username.GetValue(), @@ -31,7 +32,7 @@ AnnounceMultiplayerSession::AnnounceMultiplayerSession() { } WebService::WebResult AnnounceMultiplayerSession::Register() { - std::shared_ptr room = Network::GetRoom().lock(); + std::shared_ptr room = room_network.GetRoom().lock(); if (!room) { return WebService::WebResult{WebService::WebResult::Code::LibError, "Network is not initialized", ""}; @@ -120,7 +121,7 @@ void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { std::future future; while (!shutdown_event.WaitUntil(update_time)) { update_time += announce_time_interval; - std::shared_ptr room = Network::GetRoom().lock(); + std::shared_ptr room = room_network.GetRoom().lock(); if (!room) { break; } diff --git a/src/core/announce_multiplayer_session.h b/src/core/announce_multiplayer_session.h index 2aaf55017..5da3c1f8d 100644 --- a/src/core/announce_multiplayer_session.h +++ b/src/core/announce_multiplayer_session.h @@ -16,7 +16,8 @@ namespace Network { class Room; -} +class RoomNetwork; +} // namespace Network namespace Core { @@ -28,7 +29,7 @@ namespace Core { class AnnounceMultiplayerSession { public: using CallbackHandle = std::shared_ptr>; - AnnounceMultiplayerSession(); + AnnounceMultiplayerSession(Network::RoomNetwork& room_network_); ~AnnounceMultiplayerSession(); /** @@ -79,6 +80,9 @@ public: void UpdateCredentials(); private: + void UpdateBackendData(std::shared_ptr room); + void AnnounceMultiplayerLoop(); + Common::Event shutdown_event; std::mutex callback_mutex; std::set error_callbacks; @@ -89,8 +93,7 @@ private: std::atomic_bool registered = false; ///< Whether the room has been registered - void UpdateBackendData(std::shared_ptr room); - void AnnounceMultiplayerLoop(); + Network::RoomNetwork& room_network; }; } // namespace Core diff --git a/src/core/core.cpp b/src/core/core.cpp index 98fe6d39c..95791a07f 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -131,7 +131,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) - : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, + : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{}, cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {} SystemResultStatus Run() { @@ -320,7 +320,7 @@ struct System::Impl { if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); } - if (auto room_member = Network::GetRoomMember().lock()) { + if (auto room_member = room_network.GetRoomMember().lock()) { Network::GameInfo game_info; game_info.name = name; game_info.id = program_id; @@ -374,7 +374,7 @@ struct System::Impl { memory.Reset(); applet_manager.ClearAll(); - if (auto room_member = Network::GetRoomMember().lock()) { + if (auto room_member = room_network.GetRoomMember().lock()) { Network::GameInfo game_info{}; room_member->SendGameInfo(game_info); } @@ -451,6 +451,8 @@ struct System::Impl { std::unique_ptr audio_core; Core::Memory::Memory memory; Core::HID::HIDCore hid_core; + Network::RoomNetwork room_network; + CpuManager cpu_manager; std::atomic_bool is_powered_on{}; bool exit_lock = false; @@ -896,6 +898,14 @@ const Core::Debugger& System::GetDebugger() const { return *impl->debugger; } +Network::RoomNetwork& System::GetRoomNetwork() { + return impl->room_network; +} + +const Network::RoomNetwork& System::GetRoomNetwork() const { + return impl->room_network; +} + void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) { impl->execute_program_callback = std::move(callback); } diff --git a/src/core/core.h b/src/core/core.h index a49d1214b..13122dd61 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -97,6 +97,10 @@ namespace Core::HID { class HIDCore; } +namespace Network { +class RoomNetwork; +} + namespace Core { class ARM_Interface; @@ -379,6 +383,12 @@ public: [[nodiscard]] Core::Debugger& GetDebugger(); [[nodiscard]] const Core::Debugger& GetDebugger() const; + /// Gets a mutable reference to the Room Network. + [[nodiscard]] Network::RoomNetwork& GetRoomNetwork(); + + /// Gets an immutable reference to the Room Network. + [[nodiscard]] const Network::RoomNetwork& GetRoomNetwork() const; + void SetExitLock(bool locked); [[nodiscard]] bool GetExitLock() const; diff --git a/src/network/network.cpp b/src/network/network.cpp index 51b5d6a9f..e1401a403 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -9,11 +9,12 @@ namespace Network { -static std::shared_ptr g_room_member; ///< RoomMember (Client) for network games -static std::shared_ptr g_room; ///< Room (Server) for network games -// TODO(B3N30): Put these globals into a networking class +RoomNetwork::RoomNetwork() { + g_room = std::make_shared(); + g_room_member = std::make_shared(); +} -bool Init() { +bool RoomNetwork::Init() { if (enet_initialize() != 0) { LOG_ERROR(Network, "Error initalizing ENet"); return false; @@ -24,15 +25,15 @@ bool Init() { return true; } -std::weak_ptr GetRoom() { +std::weak_ptr RoomNetwork::GetRoom() { return g_room; } -std::weak_ptr GetRoomMember() { +std::weak_ptr RoomNetwork::GetRoomMember() { return g_room_member; } -void Shutdown() { +void RoomNetwork::Shutdown() { if (g_room_member) { if (g_room_member->IsConnected()) g_room_member->Leave(); diff --git a/src/network/network.h b/src/network/network.h index 6d002d693..74eb42bf5 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -10,16 +10,25 @@ namespace Network { -/// Initializes and registers the network device, the room, and the room member. -bool Init(); +class RoomNetwork { +public: + RoomNetwork(); -/// Returns a pointer to the room handle -std::weak_ptr GetRoom(); + /// Initializes and registers the network device, the room, and the room member. + bool Init(); -/// Returns a pointer to the room member handle -std::weak_ptr GetRoomMember(); + /// Returns a pointer to the room handle + std::weak_ptr GetRoom(); -/// Unregisters the network device, the room, and the room member and shut them down. -void Shutdown(); + /// Returns a pointer to the room member handle + std::weak_ptr GetRoomMember(); + + /// Unregisters the network device, the room, and the room member and shut them down. + void Shutdown(); + +private: + std::shared_ptr g_room_member; ///< RoomMember (Client) for network games + std::shared_ptr g_room; ///< Room (Server) for network games +}; } // namespace Network diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f1cc910c0..e56fcabff 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -273,7 +273,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); discord_rpc->Update(); - Network::Init(); + system->GetRoomNetwork().Init(); RegisterMetaTypes(); @@ -463,7 +463,7 @@ GMainWindow::~GMainWindow() { if (render_window->parent() == nullptr) { delete render_window; } - Network::Shutdown(); + system->GetRoomNetwork().Shutdown(); } void GMainWindow::RegisterMetaTypes() { @@ -828,7 +828,7 @@ void GMainWindow::InitializeWidgets() { }); multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room, - ui->action_Show_Room); + ui->action_Show_Room, system->GetRoomNetwork()); multiplayer_state->setVisible(false); // Create status bar diff --git a/src/yuzu/multiplayer/chat_room.cpp b/src/yuzu/multiplayer/chat_room.cpp index 7048ee1fc..9f2c57eee 100644 --- a/src/yuzu/multiplayer/chat_room.cpp +++ b/src/yuzu/multiplayer/chat_room.cpp @@ -28,7 +28,8 @@ class ChatMessage { public: - explicit ChatMessage(const Network::ChatEntry& chat, QTime ts = {}) { + explicit ChatMessage(const Network::ChatEntry& chat, Network::RoomNetwork& room_network, + QTime ts = {}) { /// Convert the time to their default locale defined format QLocale locale; timestamp = locale.toString(ts.isValid() ? ts : QTime::currentTime(), QLocale::ShortFormat); @@ -38,7 +39,7 @@ public: // Check for user pings QString cur_nickname, cur_username; - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network.GetRoomMember().lock()) { cur_nickname = QString::fromStdString(room->GetNickname()); cur_username = QString::fromStdString(room->GetUsername()); } @@ -173,8 +174,20 @@ ChatRoom::ChatRoom(QWidget* parent) : QWidget(parent), ui(std::make_unique(); qRegisterMetaType(); + // Connect all the widgets to the appropriate events + connect(ui->player_view, &QTreeView::customContextMenuRequested, this, + &ChatRoom::PopupContextMenu); + connect(ui->chat_message, &QLineEdit::returnPressed, this, &ChatRoom::OnSendChat); + connect(ui->chat_message, &QLineEdit::textChanged, this, &ChatRoom::OnChatTextChanged); + connect(ui->send_message, &QPushButton::clicked, this, &ChatRoom::OnSendChat); +} + +ChatRoom::~ChatRoom() = default; + +void ChatRoom::Initialize(Network::RoomNetwork* room_network_) { + room_network = room_network_; // setup the callbacks for network updates - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network->GetRoomMember().lock()) { member->BindOnChatMessageRecieved( [this](const Network::ChatEntry& chat) { emit ChatReceived(chat); }); member->BindOnStatusMessageReceived( @@ -183,20 +196,9 @@ ChatRoom::ChatRoom(QWidget* parent) : QWidget(parent), ui(std::make_uniqueplayer_view, &QTreeView::customContextMenuRequested, this, - &ChatRoom::PopupContextMenu); - connect(ui->chat_message, &QLineEdit::returnPressed, this, &ChatRoom::OnSendChat); - connect(ui->chat_message, &QLineEdit::textChanged, this, &ChatRoom::OnChatTextChanged); - connect(ui->send_message, &QPushButton::clicked, this, &ChatRoom::OnSendChat); } -ChatRoom::~ChatRoom() = default; - void ChatRoom::SetModPerms(bool is_mod) { has_mod_perms = is_mod; } @@ -219,7 +221,7 @@ void ChatRoom::AppendChatMessage(const QString& msg) { } void ChatRoom::SendModerationRequest(Network::RoomMessageTypes type, const std::string& nickname) { - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network->GetRoomMember().lock()) { auto members = room->GetMemberInformation(); auto it = std::find_if(members.begin(), members.end(), [&nickname](const Network::RoomMember::MemberInformation& member) { @@ -239,7 +241,7 @@ bool ChatRoom::ValidateMessage(const std::string& msg) { void ChatRoom::OnRoomUpdate(const Network::RoomInformation& info) { // TODO(B3N30): change title - if (auto room_member = Network::GetRoomMember().lock()) { + if (auto room_member = room_network->GetRoomMember().lock()) { SetPlayerList(room_member->GetMemberInformation()); } } @@ -258,7 +260,7 @@ void ChatRoom::OnChatReceive(const Network::ChatEntry& chat) { if (!ValidateMessage(chat.message)) { return; } - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network->GetRoomMember().lock()) { // get the id of the player auto members = room->GetMemberInformation(); auto it = std::find_if(members.begin(), members.end(), @@ -276,7 +278,7 @@ void ChatRoom::OnChatReceive(const Network::ChatEntry& chat) { return; } auto player = std::distance(members.begin(), it); - ChatMessage m(chat); + ChatMessage m(chat, *room_network); if (m.ContainsPing()) { emit UserPinged(); } @@ -315,7 +317,7 @@ void ChatRoom::OnStatusMessageReceive(const Network::StatusMessageEntry& status_ } void ChatRoom::OnSendChat() { - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network->GetRoomMember().lock()) { if (room->GetState() != Network::RoomMember::State::Joined && room->GetState() != Network::RoomMember::State::Moderator) { @@ -339,7 +341,7 @@ void ChatRoom::OnSendChat() { LOG_INFO(Network, "Cannot find self in the player list when sending a message."); } auto player = std::distance(members.begin(), it); - ChatMessage m(chat); + ChatMessage m(chat, *room_network); room->SendChatMessage(message); AppendChatMessage(m.GetPlayerChatMessage(player)); ui->chat_message->clear(); @@ -433,7 +435,7 @@ void ChatRoom::PopupContextMenu(const QPoint& menu_location) { } std::string cur_nickname; - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network->GetRoomMember().lock()) { cur_nickname = room->GetNickname(); } diff --git a/src/yuzu/multiplayer/chat_room.h b/src/yuzu/multiplayer/chat_room.h index a810377f7..9179d16fb 100644 --- a/src/yuzu/multiplayer/chat_room.h +++ b/src/yuzu/multiplayer/chat_room.h @@ -30,6 +30,7 @@ class ChatRoom : public QWidget { public: explicit ChatRoom(QWidget* parent); + void Initialize(Network::RoomNetwork* room_network); void RetranslateUi(); void SetPlayerList(const Network::RoomMember::MemberList& member_list); void Clear(); @@ -65,6 +66,7 @@ private: std::unique_ptr ui; std::unordered_set block_list; std::unordered_map icon_cache; + Network::RoomNetwork* room_network; }; Q_DECLARE_METATYPE(Network::ChatEntry); diff --git a/src/yuzu/multiplayer/client_room.cpp b/src/yuzu/multiplayer/client_room.cpp index 7b2e16e06..9bef9bdfc 100644 --- a/src/yuzu/multiplayer/client_room.cpp +++ b/src/yuzu/multiplayer/client_room.cpp @@ -19,13 +19,14 @@ #include "yuzu/multiplayer/moderation_dialog.h" #include "yuzu/multiplayer/state.h" -ClientRoomWindow::ClientRoomWindow(QWidget* parent) +ClientRoomWindow::ClientRoomWindow(QWidget* parent, Network::RoomNetwork& room_network_) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique()) { + ui(std::make_unique()), room_network{room_network_} { ui->setupUi(this); + ui->chat->Initialize(&room_network); // setup the callbacks for network updates - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { member->BindOnRoomInformationChanged( [this](const Network::RoomInformation& info) { emit RoomInformationChanged(info); }); member->BindOnStateChanged( @@ -44,7 +45,7 @@ ClientRoomWindow::ClientRoomWindow(QWidget* parent) ui->disconnect->setDefault(false); ui->disconnect->setAutoDefault(false); connect(ui->moderation, &QPushButton::clicked, [this] { - ModerationDialog dialog(this); + ModerationDialog dialog(room_network, this); dialog.exec(); }); ui->moderation->setDefault(false); @@ -91,7 +92,7 @@ void ClientRoomWindow::Disconnect() { } void ClientRoomWindow::UpdateView() { - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { if (member->IsConnected()) { ui->chat->Enable(); ui->disconnect->setEnabled(true); diff --git a/src/yuzu/multiplayer/client_room.h b/src/yuzu/multiplayer/client_room.h index 607b4073d..6303b2595 100644 --- a/src/yuzu/multiplayer/client_room.h +++ b/src/yuzu/multiplayer/client_room.h @@ -14,7 +14,7 @@ class ClientRoomWindow : public QDialog { Q_OBJECT public: - explicit ClientRoomWindow(QWidget* parent); + explicit ClientRoomWindow(QWidget* parent, Network::RoomNetwork& room_network_); ~ClientRoomWindow(); void RetranslateUi(); @@ -36,4 +36,5 @@ private: QStandardItemModel* player_list; std::unique_ptr ui; + Network::RoomNetwork& room_network; }; diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp index 837baf85c..360d66bea 100644 --- a/src/yuzu/multiplayer/direct_connect.cpp +++ b/src/yuzu/multiplayer/direct_connect.cpp @@ -21,9 +21,9 @@ enum class ConnectionType : u8 { TraversalServer, IP }; -DirectConnectWindow::DirectConnectWindow(QWidget* parent) +DirectConnectWindow::DirectConnectWindow(Network::RoomNetwork& room_network_, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique()) { + ui(std::make_unique()), room_network{room_network_} { ui->setupUi(this); @@ -58,7 +58,7 @@ void DirectConnectWindow::Connect() { NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); return; } - if (const auto member = Network::GetRoomMember().lock()) { + if (const auto member = room_network.GetRoomMember().lock()) { // Prevent the user from trying to join a room while they are already joining. if (member->GetState() == Network::RoomMember::State::Joining) { return; @@ -96,7 +96,7 @@ void DirectConnectWindow::Connect() { // attempt to connect in a different thread QFuture f = QtConcurrent::run([&] { - if (auto room_member = Network::GetRoomMember().lock()) { + if (auto room_member = room_network.GetRoomMember().lock()) { auto port = UISettings::values.multiplayer_port.GetValue(); room_member->Join(ui->nickname->text().toStdString(), "", ui->ip->text().toStdString().c_str(), port, 0, @@ -121,7 +121,7 @@ void DirectConnectWindow::EndConnecting() { void DirectConnectWindow::OnConnection() { EndConnecting(); - if (auto room_member = Network::GetRoomMember().lock()) { + if (auto room_member = room_network.GetRoomMember().lock()) { if (room_member->GetState() == Network::RoomMember::State::Joined || room_member->GetState() == Network::RoomMember::State::Moderator) { diff --git a/src/yuzu/multiplayer/direct_connect.h b/src/yuzu/multiplayer/direct_connect.h index e38961ed0..719030d29 100644 --- a/src/yuzu/multiplayer/direct_connect.h +++ b/src/yuzu/multiplayer/direct_connect.h @@ -17,7 +17,7 @@ class DirectConnectWindow : public QDialog { Q_OBJECT public: - explicit DirectConnectWindow(QWidget* parent = nullptr); + explicit DirectConnectWindow(Network::RoomNetwork& room_network_, QWidget* parent = nullptr); ~DirectConnectWindow(); void RetranslateUi(); @@ -40,4 +40,5 @@ private: QFutureWatcher* watcher; std::unique_ptr ui; Validation validation; + Network::RoomNetwork& room_network; }; diff --git a/src/yuzu/multiplayer/host_room.cpp b/src/yuzu/multiplayer/host_room.cpp index 053e22fe4..a48077544 100644 --- a/src/yuzu/multiplayer/host_room.cpp +++ b/src/yuzu/multiplayer/host_room.cpp @@ -27,9 +27,11 @@ #endif HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, - std::shared_ptr session) + std::shared_ptr session, + Network::RoomNetwork& room_network_) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique()), announce_multiplayer_session(session) { + ui(std::make_unique()), + announce_multiplayer_session(session), room_network{room_network_} { ui->setupUi(this); // set up validation for all of the fields @@ -120,7 +122,7 @@ void HostRoomWindow::Host() { NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::GAME_NOT_SELECTED); return; } - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { if (member->GetState() == Network::RoomMember::State::Joining) { return; } else if (member->IsConnected()) { @@ -144,7 +146,7 @@ void HostRoomWindow::Host() { if (ui->load_ban_list->isChecked()) { ban_list = UISettings::values.multiplayer_ban_list; } - if (auto room = Network::GetRoom().lock()) { + if (auto room = room_network.GetRoom().lock()) { const bool created = room->Create(ui->room_name->text().toStdString(), ui->room_description->toPlainText().toStdString(), "", port, password, @@ -173,7 +175,7 @@ void HostRoomWindow::Host() { QString::fromStdString(result.result_string), QMessageBox::Ok); ui->host->setEnabled(true); - if (auto room = Network::GetRoom().lock()) { + if (auto room = room_network.GetRoom().lock()) { room->Destroy(); } return; @@ -189,7 +191,7 @@ void HostRoomWindow::Host() { WebService::Client client(Settings::values.web_api_url.GetValue(), Settings::values.yuzu_username.GetValue(), Settings::values.yuzu_token.GetValue()); - if (auto room = Network::GetRoom().lock()) { + if (auto room = room_network.GetRoom().lock()) { token = client.GetExternalJWT(room->GetVerifyUID()).returned_data; } if (token.empty()) { diff --git a/src/yuzu/multiplayer/host_room.h b/src/yuzu/multiplayer/host_room.h index d84f93ffd..98a56458f 100644 --- a/src/yuzu/multiplayer/host_room.h +++ b/src/yuzu/multiplayer/host_room.h @@ -35,7 +35,8 @@ class HostRoomWindow : public QDialog { public: explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list, - std::shared_ptr session); + std::shared_ptr session, + Network::RoomNetwork& room_network_); ~HostRoomWindow(); /** @@ -54,6 +55,7 @@ private: QStandardItemModel* game_list; ComboBoxProxyModel* proxy; Validation validation; + Network::RoomNetwork& room_network; }; /** diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 1b6b782d9..0c6648ab5 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp @@ -23,9 +23,11 @@ #endif Lobby::Lobby(QWidget* parent, QStandardItemModel* list, - std::shared_ptr session) + std::shared_ptr session, + Network::RoomNetwork& room_network_) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique()), announce_multiplayer_session(session) { + ui(std::make_unique()), + announce_multiplayer_session(session), room_network{room_network_} { ui->setupUi(this); // setup the watcher for background connections @@ -113,7 +115,7 @@ void Lobby::OnExpandRoom(const QModelIndex& index) { } void Lobby::OnJoinRoom(const QModelIndex& source) { - if (const auto member = Network::GetRoomMember().lock()) { + if (const auto member = room_network.GetRoomMember().lock()) { // Prevent the user from trying to join a room while they are already joining. if (member->GetState() == Network::RoomMember::State::Joining) { return; @@ -151,7 +153,7 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString(); // attempt to connect in a different thread - QFuture f = QtConcurrent::run([nickname, ip, port, password, verify_UID] { + QFuture f = QtConcurrent::run([nickname, ip, port, password, verify_UID, this] { std::string token; #ifdef ENABLE_WEB_SERVICE if (!Settings::values.yuzu_username.GetValue().empty() && @@ -167,7 +169,7 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { } } #endif - if (auto room_member = Network::GetRoomMember().lock()) { + if (auto room_member = room_network.GetRoomMember().lock()) { room_member->Join(nickname, "", ip.c_str(), port, 0, Network::NoPreferredMac, password, token); } diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h index aea4a0e4e..ec6ec2662 100644 --- a/src/yuzu/multiplayer/lobby.h +++ b/src/yuzu/multiplayer/lobby.h @@ -30,7 +30,8 @@ class Lobby : public QDialog { public: explicit Lobby(QWidget* parent, QStandardItemModel* list, - std::shared_ptr session); + std::shared_ptr session, + Network::RoomNetwork& room_network_); ~Lobby() override; /** @@ -94,6 +95,7 @@ private: std::weak_ptr announce_multiplayer_session; QFutureWatcher* watcher; Validation validation; + Network::RoomNetwork& room_network; }; /** diff --git a/src/yuzu/multiplayer/moderation_dialog.cpp b/src/yuzu/multiplayer/moderation_dialog.cpp index e97f30ee5..fc3f36c57 100644 --- a/src/yuzu/multiplayer/moderation_dialog.cpp +++ b/src/yuzu/multiplayer/moderation_dialog.cpp @@ -17,13 +17,13 @@ enum { }; } -ModerationDialog::ModerationDialog(QWidget* parent) - : QDialog(parent), ui(std::make_unique()) { +ModerationDialog::ModerationDialog(Network::RoomNetwork& room_network_, QWidget* parent) + : QDialog(parent), ui(std::make_unique()), room_network{room_network_} { ui->setupUi(this); qRegisterMetaType(); - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { callback_handle_status_message = member->BindOnStatusMessageReceived( [this](const Network::StatusMessageEntry& status_message) { emit StatusMessageReceived(status_message); @@ -56,20 +56,20 @@ ModerationDialog::ModerationDialog(QWidget* parent) ModerationDialog::~ModerationDialog() { if (callback_handle_status_message) { - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network.GetRoomMember().lock()) { room->Unbind(callback_handle_status_message); } } if (callback_handle_ban_list) { - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network.GetRoomMember().lock()) { room->Unbind(callback_handle_ban_list); } } } void ModerationDialog::LoadBanList() { - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network.GetRoomMember().lock()) { ui->refresh->setEnabled(false); ui->refresh->setText(tr("Refreshing")); ui->unban->setEnabled(false); @@ -98,7 +98,7 @@ void ModerationDialog::PopulateBanList(const Network::Room::BanList& ban_list) { } void ModerationDialog::SendUnbanRequest(const QString& subject) { - if (auto room = Network::GetRoomMember().lock()) { + if (auto room = room_network.GetRoomMember().lock()) { room->SendModerationRequest(Network::IdModUnban, subject.toStdString()); } } diff --git a/src/yuzu/multiplayer/moderation_dialog.h b/src/yuzu/multiplayer/moderation_dialog.h index d10083d5b..8adec0cd8 100644 --- a/src/yuzu/multiplayer/moderation_dialog.h +++ b/src/yuzu/multiplayer/moderation_dialog.h @@ -20,7 +20,7 @@ class ModerationDialog : public QDialog { Q_OBJECT public: - explicit ModerationDialog(QWidget* parent = nullptr); + explicit ModerationDialog(Network::RoomNetwork& room_network_, QWidget* parent = nullptr); ~ModerationDialog(); signals: @@ -37,6 +37,8 @@ private: QStandardItemModel* model; Network::RoomMember::CallbackHandle callback_handle_status_message; Network::RoomMember::CallbackHandle callback_handle_ban_list; + + Network::RoomNetwork& room_network; }; Q_DECLARE_METATYPE(Network::Room::BanList); diff --git a/src/yuzu/multiplayer/state.cpp b/src/yuzu/multiplayer/state.cpp index ee138739b..de25225dd 100644 --- a/src/yuzu/multiplayer/state.cpp +++ b/src/yuzu/multiplayer/state.cpp @@ -20,10 +20,11 @@ #include "yuzu/util/clickable_label.h" MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model_, - QAction* leave_room_, QAction* show_room_) + QAction* leave_room_, QAction* show_room_, + Network::RoomNetwork& room_network_) : QWidget(parent), game_list_model(game_list_model_), leave_room(leave_room_), - show_room(show_room_) { - if (auto member = Network::GetRoomMember().lock()) { + show_room(show_room_), room_network{room_network_} { + if (auto member = room_network.GetRoomMember().lock()) { // register the network structs to use in slots and signals state_callback_handle = member->BindOnStateChanged( [this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); }); @@ -37,7 +38,7 @@ MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_lis qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); - announce_multiplayer_session = std::make_shared(); + announce_multiplayer_session = std::make_shared(room_network); announce_multiplayer_session->BindErrorCallback( [this](const WebService::WebResult& result) { emit AnnounceFailed(result); }); connect(this, &MultiplayerState::AnnounceFailed, this, &MultiplayerState::OnAnnounceFailed); @@ -61,13 +62,13 @@ MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_lis MultiplayerState::~MultiplayerState() { if (state_callback_handle) { - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { member->Unbind(state_callback_handle); } } if (error_callback_handle) { - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { member->Unbind(error_callback_handle); } } @@ -205,14 +206,15 @@ static void BringWidgetToFront(QWidget* widget) { void MultiplayerState::OnViewLobby() { if (lobby == nullptr) { - lobby = new Lobby(this, game_list_model, announce_multiplayer_session); + lobby = new Lobby(this, game_list_model, announce_multiplayer_session, room_network); } BringWidgetToFront(lobby); } void MultiplayerState::OnCreateRoom() { if (host_room == nullptr) { - host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session); + host_room = + new HostRoomWindow(this, game_list_model, announce_multiplayer_session, room_network); } BringWidgetToFront(host_room); } @@ -220,9 +222,9 @@ void MultiplayerState::OnCreateRoom() { bool MultiplayerState::OnCloseRoom() { if (!NetworkMessage::WarnCloseRoom()) return false; - if (auto room = Network::GetRoom().lock()) { + if (auto room = room_network.GetRoom().lock()) { // if you are in a room, leave it - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { member->Leave(); LOG_DEBUG(Frontend, "Left the room (as a client)"); } @@ -257,10 +259,10 @@ void MultiplayerState::HideNotification() { } void MultiplayerState::OnOpenNetworkRoom() { - if (auto member = Network::GetRoomMember().lock()) { + if (auto member = room_network.GetRoomMember().lock()) { if (member->IsConnected()) { if (client_room == nullptr) { - client_room = new ClientRoomWindow(this); + client_room = new ClientRoomWindow(this, room_network); connect(client_room, &ClientRoomWindow::ShowNotification, this, &MultiplayerState::ShowNotification); } @@ -275,7 +277,7 @@ void MultiplayerState::OnOpenNetworkRoom() { void MultiplayerState::OnDirectConnectToRoom() { if (direct_connect == nullptr) { - direct_connect = new DirectConnectWindow(this); + direct_connect = new DirectConnectWindow(room_network, this); } BringWidgetToFront(direct_connect); } diff --git a/src/yuzu/multiplayer/state.h b/src/yuzu/multiplayer/state.h index 414454acb..bdd5cc954 100644 --- a/src/yuzu/multiplayer/state.h +++ b/src/yuzu/multiplayer/state.h @@ -20,7 +20,7 @@ class MultiplayerState : public QWidget { public: explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room, - QAction* show_room); + QAction* show_room, Network::RoomNetwork& room_network_); ~MultiplayerState(); /** @@ -87,6 +87,7 @@ private: Network::RoomMember::CallbackHandle error_callback_handle; bool show_notification = false; + Network::RoomNetwork& room_network; }; Q_DECLARE_METATYPE(WebService::WebResult);