Merge pull request #8822 from FearlessTobi/multiplayer-fixes
network: Fixes and improvements to the room feature
This commit is contained in:
		| @@ -16,6 +16,7 @@ namespace AnnounceMultiplayerRoom { | |||||||
| struct GameInfo { | struct GameInfo { | ||||||
|     std::string name{""}; |     std::string name{""}; | ||||||
|     u64 id{0}; |     u64 id{0}; | ||||||
|  |     std::string version{""}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct Member { | struct Member { | ||||||
|   | |||||||
| @@ -2,8 +2,6 @@ | |||||||
| # SPDX-License-Identifier: GPL-2.0-or-later | # SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  |  | ||||||
| add_library(core STATIC | add_library(core STATIC | ||||||
|     announce_multiplayer_session.cpp |  | ||||||
|     announce_multiplayer_session.h |  | ||||||
|     arm/arm_interface.h |     arm/arm_interface.h | ||||||
|     arm/arm_interface.cpp |     arm/arm_interface.cpp | ||||||
|     arm/dynarmic/arm_dynarmic_32.cpp |     arm/dynarmic/arm_dynarmic_32.cpp | ||||||
|   | |||||||
| @@ -319,10 +319,19 @@ struct System::Impl { | |||||||
|         if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { |         if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { | ||||||
|             LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); |             LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         std::string title_version; | ||||||
|  |         const FileSys::PatchManager pm(program_id, system.GetFileSystemController(), | ||||||
|  |                                        system.GetContentProvider()); | ||||||
|  |         const auto metadata = pm.GetControlMetadata(); | ||||||
|  |         if (metadata.first != nullptr) { | ||||||
|  |             title_version = metadata.first->GetVersionString(); | ||||||
|  |         } | ||||||
|         if (auto room_member = room_network.GetRoomMember().lock()) { |         if (auto room_member = room_network.GetRoomMember().lock()) { | ||||||
|             Network::GameInfo game_info; |             Network::GameInfo game_info; | ||||||
|             game_info.name = name; |             game_info.name = name; | ||||||
|             game_info.id = program_id; |             game_info.id = program_id; | ||||||
|  |             game_info.version = title_version; | ||||||
|             room_member->SendGameInfo(game_info); |             room_member->SendGameInfo(game_info); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -534,7 +534,7 @@ public: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|     void CheckAvailability(Kernel::HLERequestContext& ctx) { |     void CheckAvailability(Kernel::HLERequestContext& ctx) { | ||||||
|         LOG_WARNING(Service_ACC, "(STUBBED) called"); |         LOG_DEBUG(Service_ACC, "(STUBBED) called"); | ||||||
|         IPC::ResponseBuilder rb{ctx, 3}; |         IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|         rb.Push(ResultSuccess); |         rb.Push(ResultSuccess); | ||||||
|         rb.Push(false); // TODO: Check when this is supposed to return true and when not |         rb.Push(false); // TODO: Check when this is supposed to return true and when not | ||||||
|   | |||||||
| @@ -113,7 +113,7 @@ enum class LinkLevel : s8 { | |||||||
|     Bad, |     Bad, | ||||||
|     Low, |     Low, | ||||||
|     Good, |     Good, | ||||||
|     Excelent, |     Excellent, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct NodeLatestUpdate { | struct NodeLatestUpdate { | ||||||
| @@ -145,11 +145,19 @@ struct NetworkId { | |||||||
| static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size"); | static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size"); | ||||||
|  |  | ||||||
| struct Ssid { | struct Ssid { | ||||||
|     u8 length; |     u8 length{}; | ||||||
|     std::array<char, SsidLengthMax + 1> raw; |     std::array<char, SsidLengthMax + 1> raw{}; | ||||||
|  |  | ||||||
|  |     Ssid() = default; | ||||||
|  |  | ||||||
|  |     explicit Ssid(std::string_view data) { | ||||||
|  |         length = static_cast<u8>(std::min(data.size(), SsidLengthMax)); | ||||||
|  |         data.copy(raw.data(), length); | ||||||
|  |         raw[length] = 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     std::string GetStringValue() const { |     std::string GetStringValue() const { | ||||||
|         return std::string(raw.data(), length); |         return std::string(raw.data()); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size"); | static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size"); | ||||||
|   | |||||||
| @@ -933,7 +933,11 @@ BSD::BSD(Core::System& system_, const char* name) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| BSD::~BSD() = default; | BSD::~BSD() { | ||||||
|  |     if (auto room_member = room_network.GetRoomMember().lock()) { | ||||||
|  |         room_member->Unbind(proxy_packet_received); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { | BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|   | |||||||
| @@ -26,6 +26,12 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) { | |||||||
|         closed) { |         closed) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (!broadcast && packet.broadcast) { | ||||||
|  |         LOG_INFO(Network, "Received broadcast packet, but not configured for broadcast mode"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     std::lock_guard guard(packets_mutex); |     std::lock_guard guard(packets_mutex); | ||||||
|     received_packets.push(packet); |     received_packets.push(packet); | ||||||
| } | } | ||||||
| @@ -203,7 +209,7 @@ std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, const std::vector<u8>& mess | |||||||
|     packet.local_endpoint = local_endpoint; |     packet.local_endpoint = local_endpoint; | ||||||
|     packet.remote_endpoint = *addr; |     packet.remote_endpoint = *addr; | ||||||
|     packet.protocol = protocol; |     packet.protocol = protocol; | ||||||
|     packet.broadcast = broadcast; |     packet.broadcast = broadcast && packet.remote_endpoint.ip[3] == 255; | ||||||
|  |  | ||||||
|     auto& ip = local_endpoint.ip; |     auto& ip = local_endpoint.ip; | ||||||
|     auto ipv4 = Network::GetHostIPv4Address(); |     auto ipv4 = Network::GetHostIPv4Address(); | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ add_executable(yuzu-room | |||||||
|  |  | ||||||
| create_target_directory_groups(yuzu-room) | create_target_directory_groups(yuzu-room) | ||||||
|  |  | ||||||
| target_link_libraries(yuzu-room PRIVATE common core network) | target_link_libraries(yuzu-room PRIVATE common network) | ||||||
| if (ENABLE_WEB_SERVICE) | if (ENABLE_WEB_SERVICE) | ||||||
|     target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) |     target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) | ||||||
|     target_link_libraries(yuzu-room PRIVATE web_service) |     target_link_libraries(yuzu-room PRIVATE web_service) | ||||||
|   | |||||||
| @@ -27,8 +27,8 @@ | |||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
| #include "common/settings.h" | #include "common/settings.h" | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/announce_multiplayer_session.h" |  | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | #include "network/announce_multiplayer_session.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
| #include "network/room.h" | #include "network/room.h" | ||||||
| #include "network/verify_user.h" | #include "network/verify_user.h" | ||||||
| @@ -75,6 +75,12 @@ static constexpr char BanListMagic[] = "YuzuRoom-BanList-1"; | |||||||
|  |  | ||||||
| static constexpr char token_delimiter{':'}; | static constexpr char token_delimiter{':'}; | ||||||
|  |  | ||||||
|  | static void PadToken(std::string& token) { | ||||||
|  |     while (token.size() % 4 != 0) { | ||||||
|  |         token.push_back('='); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static std::string UsernameFromDisplayToken(const std::string& display_token) { | static std::string UsernameFromDisplayToken(const std::string& display_token) { | ||||||
|     std::size_t outlen; |     std::size_t outlen; | ||||||
|  |  | ||||||
| @@ -300,6 +306,7 @@ int main(int argc, char** argv) { | |||||||
|         if (username.empty()) { |         if (username.empty()) { | ||||||
|             LOG_INFO(Network, "Hosting a public room"); |             LOG_INFO(Network, "Hosting a public room"); | ||||||
|             Settings::values.web_api_url = web_api_url; |             Settings::values.web_api_url = web_api_url; | ||||||
|  |             PadToken(token); | ||||||
|             Settings::values.yuzu_username = UsernameFromDisplayToken(token); |             Settings::values.yuzu_username = UsernameFromDisplayToken(token); | ||||||
|             username = Settings::values.yuzu_username.GetValue(); |             username = Settings::values.yuzu_username.GetValue(); | ||||||
|             Settings::values.yuzu_token = TokenFromDisplayToken(token); |             Settings::values.yuzu_token = TokenFromDisplayToken(token); | ||||||
|   | |||||||
| @@ -2,6 +2,8 @@ | |||||||
| # SPDX-License-Identifier: GPL-3.0-or-later | # SPDX-License-Identifier: GPL-3.0-or-later | ||||||
|  |  | ||||||
| add_library(network STATIC | add_library(network STATIC | ||||||
|  |     announce_multiplayer_session.cpp | ||||||
|  |     announce_multiplayer_session.h | ||||||
|     network.cpp |     network.cpp | ||||||
|     network.h |     network.h | ||||||
|     packet.cpp |     packet.cpp | ||||||
| @@ -17,3 +19,7 @@ add_library(network STATIC | |||||||
| create_target_directory_groups(network) | create_target_directory_groups(network) | ||||||
|  |  | ||||||
| target_link_libraries(network PRIVATE common enet Boost::boost) | target_link_libraries(network PRIVATE common enet Boost::boost) | ||||||
|  | if (ENABLE_WEB_SERVICE) | ||||||
|  |     target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE) | ||||||
|  |     target_link_libraries(network PRIVATE web_service) | ||||||
|  | endif() | ||||||
|   | |||||||
| @@ -221,7 +221,7 @@ public: | |||||||
|      * Extracts the game name from a received ENet packet and broadcasts it. |      * Extracts the game name from a received ENet packet and broadcasts it. | ||||||
|      * @param event The ENet event that was received. |      * @param event The ENet event that was received. | ||||||
|      */ |      */ | ||||||
|     void HandleGameNamePacket(const ENetEvent* event); |     void HandleGameInfoPacket(const ENetEvent* event); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Removes the client from the members list if it was in it and announces the change |      * Removes the client from the members list if it was in it and announces the change | ||||||
| @@ -234,7 +234,7 @@ public: | |||||||
| void Room::RoomImpl::ServerLoop() { | void Room::RoomImpl::ServerLoop() { | ||||||
|     while (state != State::Closed) { |     while (state != State::Closed) { | ||||||
|         ENetEvent event; |         ENetEvent event; | ||||||
|         if (enet_host_service(server, &event, 50) > 0) { |         if (enet_host_service(server, &event, 5) > 0) { | ||||||
|             switch (event.type) { |             switch (event.type) { | ||||||
|             case ENET_EVENT_TYPE_RECEIVE: |             case ENET_EVENT_TYPE_RECEIVE: | ||||||
|                 switch (event.packet->data[0]) { |                 switch (event.packet->data[0]) { | ||||||
| @@ -242,7 +242,7 @@ void Room::RoomImpl::ServerLoop() { | |||||||
|                     HandleJoinRequest(&event); |                     HandleJoinRequest(&event); | ||||||
|                     break; |                     break; | ||||||
|                 case IdSetGameInfo: |                 case IdSetGameInfo: | ||||||
|                     HandleGameNamePacket(&event); |                     HandleGameInfoPacket(&event); | ||||||
|                     break; |                     break; | ||||||
|                 case IdProxyPacket: |                 case IdProxyPacket: | ||||||
|                     HandleProxyPacket(&event); |                     HandleProxyPacket(&event); | ||||||
| @@ -778,6 +778,7 @@ void Room::RoomImpl::BroadcastRoomInformation() { | |||||||
|             packet.Write(member.fake_ip); |             packet.Write(member.fake_ip); | ||||||
|             packet.Write(member.game_info.name); |             packet.Write(member.game_info.name); | ||||||
|             packet.Write(member.game_info.id); |             packet.Write(member.game_info.id); | ||||||
|  |             packet.Write(member.game_info.version); | ||||||
|             packet.Write(member.user_data.username); |             packet.Write(member.user_data.username); | ||||||
|             packet.Write(member.user_data.display_name); |             packet.Write(member.user_data.display_name); | ||||||
|             packet.Write(member.user_data.avatar_url); |             packet.Write(member.user_data.avatar_url); | ||||||
| @@ -817,6 +818,7 @@ void Room::RoomImpl::HandleProxyPacket(const ENetEvent* event) { | |||||||
|     in_packet.IgnoreBytes(sizeof(u16)); // Port |     in_packet.IgnoreBytes(sizeof(u16)); // Port | ||||||
|  |  | ||||||
|     in_packet.IgnoreBytes(sizeof(u8)); // Protocol |     in_packet.IgnoreBytes(sizeof(u8)); // Protocol | ||||||
|  |  | ||||||
|     bool broadcast; |     bool broadcast; | ||||||
|     in_packet.Read(broadcast); // Broadcast |     in_packet.Read(broadcast); // Broadcast | ||||||
|  |  | ||||||
| @@ -909,7 +911,7 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) { | void Room::RoomImpl::HandleGameInfoPacket(const ENetEvent* event) { | ||||||
|     Packet in_packet; |     Packet in_packet; | ||||||
|     in_packet.Append(event->packet->data, event->packet->dataLength); |     in_packet.Append(event->packet->data, event->packet->dataLength); | ||||||
|  |  | ||||||
| @@ -917,6 +919,7 @@ void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) { | |||||||
|     GameInfo game_info; |     GameInfo game_info; | ||||||
|     in_packet.Read(game_info.name); |     in_packet.Read(game_info.name); | ||||||
|     in_packet.Read(game_info.id); |     in_packet.Read(game_info.id); | ||||||
|  |     in_packet.Read(game_info.version); | ||||||
|  |  | ||||||
|     { |     { | ||||||
|         std::lock_guard lock(member_mutex); |         std::lock_guard lock(member_mutex); | ||||||
| @@ -935,7 +938,8 @@ void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) { | |||||||
|             if (game_info.name.empty()) { |             if (game_info.name.empty()) { | ||||||
|                 LOG_INFO(Network, "{} is not playing", display_name); |                 LOG_INFO(Network, "{} is not playing", display_name); | ||||||
|             } else { |             } else { | ||||||
|                 LOG_INFO(Network, "{} is playing {}", display_name, game_info.name); |                 LOG_INFO(Network, "{} is playing {} ({})", display_name, game_info.name, | ||||||
|  |                          game_info.version); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -103,7 +103,7 @@ public: | |||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Extracts a ProxyPacket from a received ENet packet. |      * Extracts a ProxyPacket from a received ENet packet. | ||||||
|      * @param event The  ENet event that was received. |      * @param event The ENet event that was received. | ||||||
|      */ |      */ | ||||||
|     void HandleProxyPackets(const ENetEvent* event); |     void HandleProxyPackets(const ENetEvent* event); | ||||||
|  |  | ||||||
| @@ -159,7 +159,7 @@ void RoomMember::RoomMemberImpl::MemberLoop() { | |||||||
|     while (IsConnected()) { |     while (IsConnected()) { | ||||||
|         std::lock_guard lock(network_mutex); |         std::lock_guard lock(network_mutex); | ||||||
|         ENetEvent event; |         ENetEvent event; | ||||||
|         if (enet_host_service(client, &event, 100) > 0) { |         if (enet_host_service(client, &event, 5) > 0) { | ||||||
|             switch (event.type) { |             switch (event.type) { | ||||||
|             case ENET_EVENT_TYPE_RECEIVE: |             case ENET_EVENT_TYPE_RECEIVE: | ||||||
|                 switch (event.packet->data[0]) { |                 switch (event.packet->data[0]) { | ||||||
| @@ -315,6 +315,7 @@ void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* ev | |||||||
|         packet.Read(member.fake_ip); |         packet.Read(member.fake_ip); | ||||||
|         packet.Read(member.game_info.name); |         packet.Read(member.game_info.name); | ||||||
|         packet.Read(member.game_info.id); |         packet.Read(member.game_info.id); | ||||||
|  |         packet.Read(member.game_info.version); | ||||||
|         packet.Read(member.username); |         packet.Read(member.username); | ||||||
|         packet.Read(member.display_name); |         packet.Read(member.display_name); | ||||||
|         packet.Read(member.avatar_url); |         packet.Read(member.avatar_url); | ||||||
| @@ -622,6 +623,7 @@ void RoomMember::SendGameInfo(const GameInfo& game_info) { | |||||||
|     packet.Write(static_cast<u8>(IdSetGameInfo)); |     packet.Write(static_cast<u8>(IdSetGameInfo)); | ||||||
|     packet.Write(game_info.name); |     packet.Write(game_info.name); | ||||||
|     packet.Write(game_info.id); |     packet.Write(game_info.id); | ||||||
|  |     packet.Write(game_info.version); | ||||||
|     room_member_impl->Send(std::move(packet)); |     room_member_impl->Send(std::move(packet)); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -146,7 +146,7 @@ public: | |||||||
|               const std::string& password = "", const std::string& token = ""); |               const std::string& password = "", const std::string& token = ""); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Sends a WiFi packet to the room. |      * Sends a Proxy packet to the room. | ||||||
|      * @param packet The WiFi packet to send. |      * @param packet The WiFi packet to send. | ||||||
|      */ |      */ | ||||||
|     void SendProxyPacket(const ProxyPacket& packet); |     void SendProxyPacket(const ProxyPacket& packet); | ||||||
|   | |||||||
| @@ -860,7 +860,7 @@ void GMainWindow::InitializeWidgets() { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room, |     multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room, | ||||||
|                                              ui->action_Show_Room, system->GetRoomNetwork()); |                                              ui->action_Show_Room, *system); | ||||||
|     multiplayer_state->setVisible(false); |     multiplayer_state->setVisible(false); | ||||||
|  |  | ||||||
|     // Create status bar |     // Create status bar | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ | |||||||
| #include <QUrl> | #include <QUrl> | ||||||
| #include <QtConcurrent/QtConcurrentRun> | #include <QtConcurrent/QtConcurrentRun> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/announce_multiplayer_session.h" | #include "network/announce_multiplayer_session.h" | ||||||
| #include "ui_chat_room.h" | #include "ui_chat_room.h" | ||||||
| #include "yuzu/game_list_p.h" | #include "yuzu/game_list_p.h" | ||||||
| #include "yuzu/multiplayer/chat_room.h" | #include "yuzu/multiplayer/chat_room.h" | ||||||
| @@ -122,19 +122,22 @@ public: | |||||||
|     static const int UsernameRole = Qt::UserRole + 2; |     static const int UsernameRole = Qt::UserRole + 2; | ||||||
|     static const int AvatarUrlRole = Qt::UserRole + 3; |     static const int AvatarUrlRole = Qt::UserRole + 3; | ||||||
|     static const int GameNameRole = Qt::UserRole + 4; |     static const int GameNameRole = Qt::UserRole + 4; | ||||||
|  |     static const int GameVersionRole = Qt::UserRole + 5; | ||||||
|  |  | ||||||
|     PlayerListItem() = default; |     PlayerListItem() = default; | ||||||
|     explicit PlayerListItem(const std::string& nickname, const std::string& username, |     explicit PlayerListItem(const std::string& nickname, const std::string& username, | ||||||
|                             const std::string& avatar_url, const std::string& game_name) { |                             const std::string& avatar_url, | ||||||
|  |                             const AnnounceMultiplayerRoom::GameInfo& game_info) { | ||||||
|         setEditable(false); |         setEditable(false); | ||||||
|         setData(QString::fromStdString(nickname), NicknameRole); |         setData(QString::fromStdString(nickname), NicknameRole); | ||||||
|         setData(QString::fromStdString(username), UsernameRole); |         setData(QString::fromStdString(username), UsernameRole); | ||||||
|         setData(QString::fromStdString(avatar_url), AvatarUrlRole); |         setData(QString::fromStdString(avatar_url), AvatarUrlRole); | ||||||
|         if (game_name.empty()) { |         if (game_info.name.empty()) { | ||||||
|             setData(QObject::tr("Not playing a game"), GameNameRole); |             setData(QObject::tr("Not playing a game"), GameNameRole); | ||||||
|         } else { |         } else { | ||||||
|             setData(QString::fromStdString(game_name), GameNameRole); |             setData(QString::fromStdString(game_info.name), GameNameRole); | ||||||
|         } |         } | ||||||
|  |         setData(QString::fromStdString(game_info.version), GameVersionRole); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     QVariant data(int role) const override { |     QVariant data(int role) const override { | ||||||
| @@ -149,7 +152,13 @@ public: | |||||||
|         } else { |         } else { | ||||||
|             name = QStringLiteral("%1 (%2)").arg(nickname, username); |             name = QStringLiteral("%1 (%2)").arg(nickname, username); | ||||||
|         } |         } | ||||||
|         return QStringLiteral("%1\n      %2").arg(name, data(GameNameRole).toString()); |         const QString version = data(GameVersionRole).toString(); | ||||||
|  |         QString version_string; | ||||||
|  |         if (!version.isEmpty()) { | ||||||
|  |             version_string = QStringLiteral("(%1)").arg(version); | ||||||
|  |         } | ||||||
|  |         return QStringLiteral("%1\n      %2 %3") | ||||||
|  |             .arg(name, data(GameNameRole).toString(), version_string); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -167,6 +176,10 @@ ChatRoom::ChatRoom(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::C | |||||||
|  |  | ||||||
|     ui->chat_history->document()->setMaximumBlockCount(max_chat_lines); |     ui->chat_history->document()->setMaximumBlockCount(max_chat_lines); | ||||||
|  |  | ||||||
|  |     auto font = ui->chat_history->font(); | ||||||
|  |     font.setPointSizeF(10); | ||||||
|  |     ui->chat_history->setFont(font); | ||||||
|  |  | ||||||
|     // register the network structs to use in slots and signals |     // register the network structs to use in slots and signals | ||||||
|     qRegisterMetaType<Network::ChatEntry>(); |     qRegisterMetaType<Network::ChatEntry>(); | ||||||
|     qRegisterMetaType<Network::StatusMessageEntry>(); |     qRegisterMetaType<Network::StatusMessageEntry>(); | ||||||
| @@ -366,7 +379,7 @@ void ChatRoom::SetPlayerList(const Network::RoomMember::MemberList& member_list) | |||||||
|         if (member.nickname.empty()) |         if (member.nickname.empty()) | ||||||
|             continue; |             continue; | ||||||
|         QStandardItem* name_item = new PlayerListItem(member.nickname, member.username, |         QStandardItem* name_item = new PlayerListItem(member.nickname, member.username, | ||||||
|                                                       member.avatar_url, member.game_info.name); |                                                       member.avatar_url, member.game_info); | ||||||
|  |  | ||||||
| #ifdef ENABLE_WEB_SERVICE | #ifdef ENABLE_WEB_SERVICE | ||||||
|         if (!icon_cache.count(member.avatar_url) && !member.avatar_url.empty()) { |         if (!icon_cache.count(member.avatar_url) && !member.avatar_url.empty()) { | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
| #include <QTime> | #include <QTime> | ||||||
| #include <QtConcurrent/QtConcurrentRun> | #include <QtConcurrent/QtConcurrentRun> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/announce_multiplayer_session.h" | #include "network/announce_multiplayer_session.h" | ||||||
| #include "ui_client_room.h" | #include "ui_client_room.h" | ||||||
| #include "yuzu/game_list_p.h" | #include "yuzu/game_list_p.h" | ||||||
| #include "yuzu/multiplayer/client_room.h" | #include "yuzu/multiplayer/client_room.h" | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ | |||||||
| #include <QString> | #include <QString> | ||||||
| #include <QtConcurrent/QtConcurrentRun> | #include <QtConcurrent/QtConcurrentRun> | ||||||
| #include "common/settings.h" | #include "common/settings.h" | ||||||
|  | #include "core/core.h" | ||||||
|  | #include "core/internal_network/network_interface.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
| #include "ui_direct_connect.h" | #include "ui_direct_connect.h" | ||||||
| #include "yuzu/main.h" | #include "yuzu/main.h" | ||||||
| @@ -20,9 +22,10 @@ | |||||||
|  |  | ||||||
| enum class ConnectionType : u8 { TraversalServer, IP }; | enum class ConnectionType : u8 { TraversalServer, IP }; | ||||||
|  |  | ||||||
| DirectConnectWindow::DirectConnectWindow(Network::RoomNetwork& room_network_, QWidget* parent) | DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent) | ||||||
|     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), |     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), | ||||||
|       ui(std::make_unique<Ui::DirectConnect>()), room_network{room_network_} { |       ui(std::make_unique<Ui::DirectConnect>()), system{system_}, room_network{ | ||||||
|  |                                                                       system.GetRoomNetwork()} { | ||||||
|  |  | ||||||
|     ui->setupUi(this); |     ui->setupUi(this); | ||||||
|  |  | ||||||
| @@ -53,10 +56,20 @@ void DirectConnectWindow::RetranslateUi() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void DirectConnectWindow::Connect() { | void DirectConnectWindow::Connect() { | ||||||
|  |     if (!Network::GetSelectedNetworkInterface()) { | ||||||
|  |         NetworkMessage::ErrorManager::ShowError( | ||||||
|  |             NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     if (!ui->nickname->hasAcceptableInput()) { |     if (!ui->nickname->hasAcceptableInput()) { | ||||||
|         NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); |         NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |     if (system.IsPoweredOn()) { | ||||||
|  |         if (!NetworkMessage::WarnGameRunning()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     if (const auto member = room_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. |         // Prevent the user from trying to join a room while they are already joining. | ||||||
|         if (member->GetState() == Network::RoomMember::State::Joining) { |         if (member->GetState() == Network::RoomMember::State::Joining) { | ||||||
|   | |||||||
| @@ -12,11 +12,15 @@ namespace Ui { | |||||||
| class DirectConnect; | class DirectConnect; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  |  | ||||||
| class DirectConnectWindow : public QDialog { | class DirectConnectWindow : public QDialog { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|  |  | ||||||
| public: | public: | ||||||
|     explicit DirectConnectWindow(Network::RoomNetwork& room_network_, QWidget* parent = nullptr); |     explicit DirectConnectWindow(Core::System& system_, QWidget* parent = nullptr); | ||||||
|     ~DirectConnectWindow(); |     ~DirectConnectWindow(); | ||||||
|  |  | ||||||
|     void RetranslateUi(); |     void RetranslateUi(); | ||||||
| @@ -39,5 +43,6 @@ private: | |||||||
|     QFutureWatcher<void>* watcher; |     QFutureWatcher<void>* watcher; | ||||||
|     std::unique_ptr<Ui::DirectConnect> ui; |     std::unique_ptr<Ui::DirectConnect> ui; | ||||||
|     Validation validation; |     Validation validation; | ||||||
|  |     Core::System& system; | ||||||
|     Network::RoomNetwork& room_network; |     Network::RoomNetwork& room_network; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -12,7 +12,9 @@ | |||||||
| #include <QtConcurrent/QtConcurrentRun> | #include <QtConcurrent/QtConcurrentRun> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/settings.h" | #include "common/settings.h" | ||||||
| #include "core/announce_multiplayer_session.h" | #include "core/core.h" | ||||||
|  | #include "core/internal_network/network_interface.h" | ||||||
|  | #include "network/announce_multiplayer_session.h" | ||||||
| #include "ui_host_room.h" | #include "ui_host_room.h" | ||||||
| #include "yuzu/game_list_p.h" | #include "yuzu/game_list_p.h" | ||||||
| #include "yuzu/main.h" | #include "yuzu/main.h" | ||||||
| @@ -27,10 +29,11 @@ | |||||||
|  |  | ||||||
| HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, | HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, | ||||||
|                                std::shared_ptr<Core::AnnounceMultiplayerSession> session, |                                std::shared_ptr<Core::AnnounceMultiplayerSession> session, | ||||||
|                                Network::RoomNetwork& room_network_) |                                Core::System& system_) | ||||||
|     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), |     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), | ||||||
|       ui(std::make_unique<Ui::HostRoom>()), |       ui(std::make_unique<Ui::HostRoom>()), | ||||||
|       announce_multiplayer_session(session), room_network{room_network_} { |       announce_multiplayer_session(session), system{system_}, room_network{ | ||||||
|  |                                                                   system.GetRoomNetwork()} { | ||||||
|     ui->setupUi(this); |     ui->setupUi(this); | ||||||
|  |  | ||||||
|     // set up validation for all of the fields |     // set up validation for all of the fields | ||||||
| @@ -105,6 +108,11 @@ std::unique_ptr<Network::VerifyUser::Backend> HostRoomWindow::CreateVerifyBacken | |||||||
| } | } | ||||||
|  |  | ||||||
| void HostRoomWindow::Host() { | void HostRoomWindow::Host() { | ||||||
|  |     if (!Network::GetSelectedNetworkInterface()) { | ||||||
|  |         NetworkMessage::ErrorManager::ShowError( | ||||||
|  |             NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     if (!ui->username->hasAcceptableInput()) { |     if (!ui->username->hasAcceptableInput()) { | ||||||
|         NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); |         NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); | ||||||
|         return; |         return; | ||||||
| @@ -121,6 +129,11 @@ void HostRoomWindow::Host() { | |||||||
|         NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::GAME_NOT_SELECTED); |         NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::GAME_NOT_SELECTED); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |     if (system.IsPoweredOn()) { | ||||||
|  |         if (!NetworkMessage::WarnGameRunning()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     if (auto member = room_network.GetRoomMember().lock()) { |     if (auto member = room_network.GetRoomMember().lock()) { | ||||||
|         if (member->GetState() == Network::RoomMember::State::Joining) { |         if (member->GetState() == Network::RoomMember::State::Joining) { | ||||||
|             return; |             return; | ||||||
|   | |||||||
| @@ -17,8 +17,9 @@ class HostRoom; | |||||||
| } | } | ||||||
|  |  | ||||||
| namespace Core { | namespace Core { | ||||||
|  | class System; | ||||||
| class AnnounceMultiplayerSession; | class AnnounceMultiplayerSession; | ||||||
| } | } // namespace Core | ||||||
|  |  | ||||||
| class ConnectionError; | class ConnectionError; | ||||||
| class ComboBoxProxyModel; | class ComboBoxProxyModel; | ||||||
| @@ -35,7 +36,7 @@ class HostRoomWindow : public QDialog { | |||||||
| public: | public: | ||||||
|     explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list, |     explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list, | ||||||
|                             std::shared_ptr<Core::AnnounceMultiplayerSession> session, |                             std::shared_ptr<Core::AnnounceMultiplayerSession> session, | ||||||
|                             Network::RoomNetwork& room_network_); |                             Core::System& system_); | ||||||
|     ~HostRoomWindow(); |     ~HostRoomWindow(); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -54,6 +55,7 @@ private: | |||||||
|     QStandardItemModel* game_list; |     QStandardItemModel* game_list; | ||||||
|     ComboBoxProxyModel* proxy; |     ComboBoxProxyModel* proxy; | ||||||
|     Validation validation; |     Validation validation; | ||||||
|  |     Core::System& system; | ||||||
|     Network::RoomNetwork& room_network; |     Network::RoomNetwork& room_network; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ | |||||||
| #include <QtConcurrent/QtConcurrentRun> | #include <QtConcurrent/QtConcurrentRun> | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/settings.h" | #include "common/settings.h" | ||||||
|  | #include "core/core.h" | ||||||
|  | #include "core/internal_network/network_interface.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
| #include "ui_lobby.h" | #include "ui_lobby.h" | ||||||
| #include "yuzu/game_list_p.h" | #include "yuzu/game_list_p.h" | ||||||
| @@ -22,11 +24,11 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | ||||||
|              std::shared_ptr<Core::AnnounceMultiplayerSession> session, |              std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_) | ||||||
|              Network::RoomNetwork& room_network_) |  | ||||||
|     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), |     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), | ||||||
|       ui(std::make_unique<Ui::Lobby>()), |       ui(std::make_unique<Ui::Lobby>()), | ||||||
|       announce_multiplayer_session(session), room_network{room_network_} { |       announce_multiplayer_session(session), system{system_}, room_network{ | ||||||
|  |                                                                   system.GetRoomNetwork()} { | ||||||
|     ui->setupUi(this); |     ui->setupUi(this); | ||||||
|  |  | ||||||
|     // setup the watcher for background connections |     // setup the watcher for background connections | ||||||
| @@ -114,6 +116,18 @@ void Lobby::OnExpandRoom(const QModelIndex& index) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void Lobby::OnJoinRoom(const QModelIndex& source) { | void Lobby::OnJoinRoom(const QModelIndex& source) { | ||||||
|  |     if (!Network::GetSelectedNetworkInterface()) { | ||||||
|  |         NetworkMessage::ErrorManager::ShowError( | ||||||
|  |             NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (system.IsPoweredOn()) { | ||||||
|  |         if (!NetworkMessage::WarnGameRunning()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (const auto member = room_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. |         // Prevent the user from trying to join a room while they are already joining. | ||||||
|         if (member->GetState() == Network::RoomMember::State::Joining) { |         if (member->GetState() == Network::RoomMember::State::Joining) { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| #include <QSortFilterProxyModel> | #include <QSortFilterProxyModel> | ||||||
| #include <QStandardItemModel> | #include <QStandardItemModel> | ||||||
| #include "common/announce_multiplayer_room.h" | #include "common/announce_multiplayer_room.h" | ||||||
| #include "core/announce_multiplayer_session.h" | #include "network/announce_multiplayer_session.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
| #include "yuzu/multiplayer/validation.h" | #include "yuzu/multiplayer/validation.h" | ||||||
|  |  | ||||||
| @@ -20,6 +20,10 @@ class Lobby; | |||||||
| class LobbyModel; | class LobbyModel; | ||||||
| class LobbyFilterProxyModel; | class LobbyFilterProxyModel; | ||||||
|  |  | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Listing of all public games pulled from services. The lobby should be simple enough for users to |  * Listing of all public games pulled from services. The lobby should be simple enough for users to | ||||||
|  * find the game they want to play, and join it. |  * find the game they want to play, and join it. | ||||||
| @@ -30,7 +34,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, | ||||||
|                    Network::RoomNetwork& room_network_); |                    Core::System& system_); | ||||||
|     ~Lobby() override; |     ~Lobby() override; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -94,6 +98,7 @@ private: | |||||||
|     std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; |     std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; | ||||||
|     QFutureWatcher<void>* watcher; |     QFutureWatcher<void>* watcher; | ||||||
|     Validation validation; |     Validation validation; | ||||||
|  |     Core::System& system; | ||||||
|     Network::RoomNetwork& room_network; |     Network::RoomNetwork& room_network; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -49,6 +49,9 @@ const ConnectionError ErrorManager::PERMISSION_DENIED( | |||||||
|     QT_TR_NOOP("You do not have enough permission to perform this action.")); |     QT_TR_NOOP("You do not have enough permission to perform this action.")); | ||||||
| const ConnectionError ErrorManager::NO_SUCH_USER(QT_TR_NOOP( | const ConnectionError ErrorManager::NO_SUCH_USER(QT_TR_NOOP( | ||||||
|     "The user you are trying to kick/ban could not be found.\nThey may have left the room.")); |     "The user you are trying to kick/ban could not be found.\nThey may have left the room.")); | ||||||
|  | const ConnectionError ErrorManager::NO_INTERFACE_SELECTED( | ||||||
|  |     QT_TR_NOOP("No network interface is selected.\nPlease go to Configure -> System -> Network and " | ||||||
|  |                "make a selection.")); | ||||||
|  |  | ||||||
| static bool WarnMessage(const std::string& title, const std::string& text) { | static bool WarnMessage(const std::string& title, const std::string& text) { | ||||||
|     return QMessageBox::Ok == QMessageBox::warning(nullptr, QObject::tr(title.c_str()), |     return QMessageBox::Ok == QMessageBox::warning(nullptr, QObject::tr(title.c_str()), | ||||||
| @@ -60,6 +63,13 @@ void ErrorManager::ShowError(const ConnectionError& e) { | |||||||
|     QMessageBox::critical(nullptr, tr("Error"), tr(e.GetString().c_str())); |     QMessageBox::critical(nullptr, tr("Error"), tr(e.GetString().c_str())); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool WarnGameRunning() { | ||||||
|  |     return WarnMessage( | ||||||
|  |         QT_TR_NOOP("Game already running"), | ||||||
|  |         QT_TR_NOOP("Joining a room when the game is already running is discouraged " | ||||||
|  |                    "and can cause the room feature not to work correctly.\nProceed anyway?")); | ||||||
|  | } | ||||||
|  |  | ||||||
| bool WarnCloseRoom() { | bool WarnCloseRoom() { | ||||||
|     return WarnMessage( |     return WarnMessage( | ||||||
|         QT_TR_NOOP("Leave Room"), |         QT_TR_NOOP("Leave Room"), | ||||||
|   | |||||||
| @@ -43,11 +43,20 @@ public: | |||||||
|     static const ConnectionError IP_COLLISION; |     static const ConnectionError IP_COLLISION; | ||||||
|     static const ConnectionError PERMISSION_DENIED; |     static const ConnectionError PERMISSION_DENIED; | ||||||
|     static const ConnectionError NO_SUCH_USER; |     static const ConnectionError NO_SUCH_USER; | ||||||
|  |     static const ConnectionError NO_INTERFACE_SELECTED; | ||||||
|     /** |     /** | ||||||
|      *  Shows a standard QMessageBox with a error message |      *  Shows a standard QMessageBox with a error message | ||||||
|      */ |      */ | ||||||
|     static void ShowError(const ConnectionError& e); |     static void ShowError(const ConnectionError& e); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Show a standard QMessageBox with a warning message about joining a room when | ||||||
|  |  * the game is already running | ||||||
|  |  * return true if the user wants to close the network connection | ||||||
|  |  */ | ||||||
|  | bool WarnGameRunning(); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Show a standard QMessageBox with a warning message about leaving the room |  * Show a standard QMessageBox with a warning message about leaving the room | ||||||
|  * return true if the user wants to close the network connection |  * return true if the user wants to close the network connection | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| #include <QStandardItemModel> | #include <QStandardItemModel> | ||||||
| #include "common/announce_multiplayer_room.h" | #include "common/announce_multiplayer_room.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "core/core.h" | ||||||
| #include "yuzu/game_list.h" | #include "yuzu/game_list.h" | ||||||
| #include "yuzu/multiplayer/client_room.h" | #include "yuzu/multiplayer/client_room.h" | ||||||
| #include "yuzu/multiplayer/direct_connect.h" | #include "yuzu/multiplayer/direct_connect.h" | ||||||
| @@ -19,10 +20,9 @@ | |||||||
| #include "yuzu/util/clickable_label.h" | #include "yuzu/util/clickable_label.h" | ||||||
|  |  | ||||||
| MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model_, | MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model_, | ||||||
|                                    QAction* leave_room_, QAction* show_room_, |                                    QAction* leave_room_, QAction* show_room_, Core::System& system_) | ||||||
|                                    Network::RoomNetwork& room_network_) |  | ||||||
|     : QWidget(parent), game_list_model(game_list_model_), leave_room(leave_room_), |     : QWidget(parent), game_list_model(game_list_model_), leave_room(leave_room_), | ||||||
|       show_room(show_room_), room_network{room_network_} { |       show_room(show_room_), system{system_}, room_network{system.GetRoomNetwork()} { | ||||||
|     if (auto member = room_network.GetRoomMember().lock()) { |     if (auto member = room_network.GetRoomMember().lock()) { | ||||||
|         // register the network structs to use in slots and signals |         // register the network structs to use in slots and signals | ||||||
|         state_callback_handle = member->BindOnStateChanged( |         state_callback_handle = member->BindOnStateChanged( | ||||||
| @@ -208,15 +208,14 @@ static void BringWidgetToFront(QWidget* widget) { | |||||||
|  |  | ||||||
| void MultiplayerState::OnViewLobby() { | void MultiplayerState::OnViewLobby() { | ||||||
|     if (lobby == nullptr) { |     if (lobby == nullptr) { | ||||||
|         lobby = new Lobby(this, game_list_model, announce_multiplayer_session, room_network); |         lobby = new Lobby(this, game_list_model, announce_multiplayer_session, system); | ||||||
|     } |     } | ||||||
|     BringWidgetToFront(lobby); |     BringWidgetToFront(lobby); | ||||||
| } | } | ||||||
|  |  | ||||||
| void MultiplayerState::OnCreateRoom() { | void MultiplayerState::OnCreateRoom() { | ||||||
|     if (host_room == nullptr) { |     if (host_room == nullptr) { | ||||||
|         host_room = |         host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session, system); | ||||||
|             new HostRoomWindow(this, game_list_model, announce_multiplayer_session, room_network); |  | ||||||
|     } |     } | ||||||
|     BringWidgetToFront(host_room); |     BringWidgetToFront(host_room); | ||||||
| } | } | ||||||
| @@ -279,7 +278,7 @@ void MultiplayerState::OnOpenNetworkRoom() { | |||||||
|  |  | ||||||
| void MultiplayerState::OnDirectConnectToRoom() { | void MultiplayerState::OnDirectConnectToRoom() { | ||||||
|     if (direct_connect == nullptr) { |     if (direct_connect == nullptr) { | ||||||
|         direct_connect = new DirectConnectWindow(room_network, this); |         direct_connect = new DirectConnectWindow(system, this); | ||||||
|     } |     } | ||||||
|     BringWidgetToFront(direct_connect); |     BringWidgetToFront(direct_connect); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <QWidget> | #include <QWidget> | ||||||
| #include "core/announce_multiplayer_session.h" | #include "network/announce_multiplayer_session.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
|  |  | ||||||
| class QStandardItemModel; | class QStandardItemModel; | ||||||
| @@ -14,12 +14,16 @@ class ClientRoomWindow; | |||||||
| class DirectConnectWindow; | class DirectConnectWindow; | ||||||
| class ClickableLabel; | class ClickableLabel; | ||||||
|  |  | ||||||
|  | namespace Core { | ||||||
|  | class System; | ||||||
|  | } | ||||||
|  |  | ||||||
| class MultiplayerState : public QWidget { | class MultiplayerState : public QWidget { | ||||||
|     Q_OBJECT; |     Q_OBJECT; | ||||||
|  |  | ||||||
| public: | public: | ||||||
|     explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room, |     explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room, | ||||||
|                               QAction* show_room, Network::RoomNetwork& room_network_); |                               QAction* show_room, Core::System& system_); | ||||||
|     ~MultiplayerState(); |     ~MultiplayerState(); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -86,6 +90,7 @@ private: | |||||||
|     Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle; |     Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle; | ||||||
|  |  | ||||||
|     bool show_notification = false; |     bool show_notification = false; | ||||||
|  |     Core::System& system; | ||||||
|     Network::RoomNetwork& room_network; |     Network::RoomNetwork& room_network; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user