summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/announce_multiplayer_room.h1
-rw-r--r--src/common/parent_of_member.h2
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/core.cpp9
-rw-r--r--src/core/file_sys/system_archive/shared_font.cpp2
-rw-r--r--src/core/hle/service/acc/acc.cpp2
-rw-r--r--src/core/hle/service/am/am.cpp2
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp2
-rw-r--r--src/core/hle/service/apm/apm_controller.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp14
-rw-r--r--src/core/hle/service/ldn/ldn_types.h16
-rw-r--r--src/core/hle/service/mm/mm_u.cpp10
-rw-r--r--src/core/hle/service/ns/iplatform_service_manager.cpp (renamed from src/core/hle/service/ns/pl_u.cpp)34
-rw-r--r--src/core/hle/service/ns/iplatform_service_manager.h (renamed from src/core/hle/service/ns/pl_u.h)6
-rw-r--r--src/core/hle/service/ns/ns.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp4
-rw-r--r--src/core/hle/service/sockets/bsd.cpp6
-rw-r--r--src/core/internal_network/socket_proxy.cpp8
-rw-r--r--src/dedicated_room/CMakeLists.txt2
-rw-r--r--src/dedicated_room/yuzu_room.cpp9
-rw-r--r--src/input_common/drivers/sdl_driver.cpp11
-rw-r--r--src/network/CMakeLists.txt6
-rw-r--r--src/network/announce_multiplayer_session.cpp (renamed from src/core/announce_multiplayer_session.cpp)0
-rw-r--r--src/network/announce_multiplayer_session.h (renamed from src/core/announce_multiplayer_session.h)0
-rw-r--r--src/network/room.cpp14
-rw-r--r--src/network/room_member.cpp6
-rw-r--r--src/network/room_member.h2
-rw-r--r--src/yuzu/configuration/configure_debug.cpp2
-rw-r--r--src/yuzu/configuration/configure_debug.h4
-rw-r--r--src/yuzu/configuration/configure_debug.ui7
-rw-r--r--src/yuzu/main.cpp2
-rw-r--r--src/yuzu/multiplayer/chat_room.cpp25
-rw-r--r--src/yuzu/multiplayer/client_room.cpp2
-rw-r--r--src/yuzu/multiplayer/direct_connect.cpp17
-rw-r--r--src/yuzu/multiplayer/direct_connect.h7
-rw-r--r--src/yuzu/multiplayer/host_room.cpp19
-rw-r--r--src/yuzu/multiplayer/host_room.h6
-rw-r--r--src/yuzu/multiplayer/lobby.cpp20
-rw-r--r--src/yuzu/multiplayer/lobby.h9
-rw-r--r--src/yuzu/multiplayer/message.cpp10
-rw-r--r--src/yuzu/multiplayer/message.h9
-rw-r--r--src/yuzu/multiplayer/state.cpp13
-rw-r--r--src/yuzu/multiplayer/state.h9
43 files changed, 242 insertions, 100 deletions
diff --git a/src/common/announce_multiplayer_room.h b/src/common/announce_multiplayer_room.h
index cb004e0eb..4a3100fa4 100644
--- a/src/common/announce_multiplayer_room.h
+++ b/src/common/announce_multiplayer_room.h
@@ -16,6 +16,7 @@ namespace AnnounceMultiplayerRoom {
16struct GameInfo { 16struct GameInfo {
17 std::string name{""}; 17 std::string name{""};
18 u64 id{0}; 18 u64 id{0};
19 std::string version{""};
19}; 20};
20 21
21struct Member { 22struct Member {
diff --git a/src/common/parent_of_member.h b/src/common/parent_of_member.h
index 70b1c5624..8e03f17d8 100644
--- a/src/common/parent_of_member.h
+++ b/src/common/parent_of_member.h
@@ -11,7 +11,7 @@ namespace Common {
11namespace detail { 11namespace detail {
12template <typename T, size_t Size, size_t Align> 12template <typename T, size_t Size, size_t Align>
13struct TypedStorageImpl { 13struct TypedStorageImpl {
14 std::aligned_storage_t<Size, Align> storage_; 14 alignas(Align) u8 storage_[Size];
15}; 15};
16} // namespace detail 16} // namespace detail
17 17
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8db9a3c65..806e7ff6c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -2,8 +2,6 @@
2# SPDX-License-Identifier: GPL-2.0-or-later 2# SPDX-License-Identifier: GPL-2.0-or-later
3 3
4add_library(core STATIC 4add_library(core STATIC
5 announce_multiplayer_session.cpp
6 announce_multiplayer_session.h
7 arm/arm_interface.h 5 arm/arm_interface.h
8 arm/arm_interface.cpp 6 arm/arm_interface.cpp
9 arm/dynarmic/arm_dynarmic_32.cpp 7 arm/dynarmic/arm_dynarmic_32.cpp
@@ -540,14 +538,14 @@ add_library(core STATIC
540 hle/service/npns/npns.cpp 538 hle/service/npns/npns.cpp
541 hle/service/npns/npns.h 539 hle/service/npns/npns.h
542 hle/service/ns/errors.h 540 hle/service/ns/errors.h
541 hle/service/ns/iplatform_service_manager.cpp
542 hle/service/ns/iplatform_service_manager.h
543 hle/service/ns/language.cpp 543 hle/service/ns/language.cpp
544 hle/service/ns/language.h 544 hle/service/ns/language.h
545 hle/service/ns/ns.cpp 545 hle/service/ns/ns.cpp
546 hle/service/ns/ns.h 546 hle/service/ns/ns.h
547 hle/service/ns/pdm_qry.cpp 547 hle/service/ns/pdm_qry.cpp
548 hle/service/ns/pdm_qry.h 548 hle/service/ns/pdm_qry.h
549 hle/service/ns/pl_u.cpp
550 hle/service/ns/pl_u.h
551 hle/service/nvdrv/devices/nvdevice.h 549 hle/service/nvdrv/devices/nvdevice.h
552 hle/service/nvdrv/devices/nvdisp_disp0.cpp 550 hle/service/nvdrv/devices/nvdisp_disp0.cpp
553 hle/service/nvdrv/devices/nvdisp_disp0.h 551 hle/service/nvdrv/devices/nvdisp_disp0.h
diff --git a/src/core/core.cpp b/src/core/core.cpp
index ea32a4a8d..e651ce100 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -319,10 +319,19 @@ struct System::Impl {
319 if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { 319 if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
320 LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); 320 LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result);
321 } 321 }
322
323 std::string title_version;
324 const FileSys::PatchManager pm(program_id, system.GetFileSystemController(),
325 system.GetContentProvider());
326 const auto metadata = pm.GetControlMetadata();
327 if (metadata.first != nullptr) {
328 title_version = metadata.first->GetVersionString();
329 }
322 if (auto room_member = room_network.GetRoomMember().lock()) { 330 if (auto room_member = room_network.GetRoomMember().lock()) {
323 Network::GameInfo game_info; 331 Network::GameInfo game_info;
324 game_info.name = name; 332 game_info.name = name;
325 game_info.id = program_id; 333 game_info.id = program_id;
334 game_info.version = title_version;
326 room_member->SendGameInfo(game_info); 335 room_member->SendGameInfo(game_info);
327 } 336 }
328 337
diff --git a/src/core/file_sys/system_archive/shared_font.cpp b/src/core/file_sys/system_archive/shared_font.cpp
index f841988ff..3210583f0 100644
--- a/src/core/file_sys/system_archive/shared_font.cpp
+++ b/src/core/file_sys/system_archive/shared_font.cpp
@@ -9,7 +9,7 @@
9#include "core/file_sys/system_archive/data/font_standard.h" 9#include "core/file_sys/system_archive/data/font_standard.h"
10#include "core/file_sys/system_archive/shared_font.h" 10#include "core/file_sys/system_archive/shared_font.h"
11#include "core/file_sys/vfs_vector.h" 11#include "core/file_sys/vfs_vector.h"
12#include "core/hle/service/ns/pl_u.h" 12#include "core/hle/service/ns/iplatform_service_manager.h"
13 13
14namespace FileSys::SystemArchive { 14namespace FileSys::SystemArchive {
15 15
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index def105832..bb838e285 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -534,7 +534,7 @@ public:
534 534
535private: 535private:
536 void CheckAvailability(Kernel::HLERequestContext& ctx) { 536 void CheckAvailability(Kernel::HLERequestContext& ctx) {
537 LOG_WARNING(Service_ACC, "(STUBBED) called"); 537 LOG_DEBUG(Service_ACC, "(STUBBED) called");
538 IPC::ResponseBuilder rb{ctx, 3}; 538 IPC::ResponseBuilder rb{ctx, 3};
539 rb.Push(ResultSuccess); 539 rb.Push(ResultSuccess);
540 rb.Push(false); // TODO: Check when this is supposed to return true and when not 540 rb.Push(false); // TODO: Check when this is supposed to return true and when not
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 118f226e4..6fb7e198e 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -754,7 +754,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
754} 754}
755 755
756void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { 756void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
757 LOG_WARNING(Service_AM, "(STUBBED) called"); 757 LOG_DEBUG(Service_AM, "(STUBBED) called");
758 758
759 IPC::ResponseBuilder rb{ctx, 3}; 759 IPC::ResponseBuilder rb{ctx, 3};
760 rb.Push(ResultSuccess); 760 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 4b804b78c..14aa6f69e 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -21,7 +21,7 @@
21#include "core/hle/service/am/am.h" 21#include "core/hle/service/am/am.h"
22#include "core/hle/service/am/applets/applet_web_browser.h" 22#include "core/hle/service/am/applets/applet_web_browser.h"
23#include "core/hle/service/filesystem/filesystem.h" 23#include "core/hle/service/filesystem/filesystem.h"
24#include "core/hle/service/ns/pl_u.h" 24#include "core/hle/service/ns/iplatform_service_manager.h"
25#include "core/loader/loader.h" 25#include "core/loader/loader.h"
26 26
27namespace Service::AM::Applets { 27namespace Service::AM::Applets {
diff --git a/src/core/hle/service/apm/apm_controller.cpp b/src/core/hle/service/apm/apm_controller.cpp
index 4e710491b..d6de84066 100644
--- a/src/core/hle/service/apm/apm_controller.cpp
+++ b/src/core/hle/service/apm/apm_controller.cpp
@@ -80,7 +80,7 @@ PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(Performa
80} 80}
81 81
82void Controller::SetClockSpeed(u32 mhz) { 82void Controller::SetClockSpeed(u32 mhz) {
83 LOG_INFO(Service_APM, "called, mhz={:08X}", mhz); 83 LOG_DEBUG(Service_APM, "called, mhz={:08X}", mhz);
84 // TODO(DarkLordZach): Actually signal core_timing to change clock speed. 84 // TODO(DarkLordZach): Actually signal core_timing to change clock speed.
85 // TODO(Rodrigo): Remove [[maybe_unused]] when core_timing is used. 85 // TODO(Rodrigo): Remove [[maybe_unused]] when core_timing is used.
86} 86}
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 7909141c0..3d3457160 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -819,12 +819,12 @@ void Hid::EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx
819 const auto result = controller.EnableSixAxisSensorUnalteredPassthrough( 819 const auto result = controller.EnableSixAxisSensorUnalteredPassthrough(
820 parameters.sixaxis_handle, parameters.enabled); 820 parameters.sixaxis_handle, parameters.enabled);
821 821
822 LOG_WARNING(Service_HID, 822 LOG_DEBUG(Service_HID,
823 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, " 823 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
824 "applet_resource_user_id={}", 824 "applet_resource_user_id={}",
825 parameters.enabled, parameters.sixaxis_handle.npad_type, 825 parameters.enabled, parameters.sixaxis_handle.npad_type,
826 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, 826 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
827 parameters.applet_resource_user_id); 827 parameters.applet_resource_user_id);
828 828
829 IPC::ResponseBuilder rb{ctx, 2}; 829 IPC::ResponseBuilder rb{ctx, 2};
830 rb.Push(result); 830 rb.Push(result);
@@ -846,7 +846,7 @@ void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext&
846 const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled( 846 const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled(
847 parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled); 847 parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
848 848
849 LOG_WARNING( 849 LOG_DEBUG(
850 Service_HID, 850 Service_HID,
851 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 851 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
852 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, 852 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h
index 0c07a7397..6231e936d 100644
--- a/src/core/hle/service/ldn/ldn_types.h
+++ b/src/core/hle/service/ldn/ldn_types.h
@@ -113,7 +113,7 @@ enum class LinkLevel : s8 {
113 Bad, 113 Bad,
114 Low, 114 Low,
115 Good, 115 Good,
116 Excelent, 116 Excellent,
117}; 117};
118 118
119struct NodeLatestUpdate { 119struct NodeLatestUpdate {
@@ -145,11 +145,19 @@ struct NetworkId {
145static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size"); 145static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
146 146
147struct Ssid { 147struct Ssid {
148 u8 length; 148 u8 length{};
149 std::array<char, SsidLengthMax + 1> raw; 149 std::array<char, SsidLengthMax + 1> raw{};
150
151 Ssid() = default;
152
153 explicit Ssid(std::string_view data) {
154 length = static_cast<u8>(std::min(data.size(), SsidLengthMax));
155 data.copy(raw.data(), length);
156 raw[length] = 0;
157 }
150 158
151 std::string GetStringValue() const { 159 std::string GetStringValue() const {
152 return std::string(raw.data(), length); 160 return std::string(raw.data());
153 } 161 }
154}; 162};
155static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size"); 163static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size");
diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp
index 5ebb124a7..ba8c0e230 100644
--- a/src/core/hle/service/mm/mm_u.cpp
+++ b/src/core/hle/service/mm/mm_u.cpp
@@ -46,7 +46,7 @@ private:
46 IPC::RequestParser rp{ctx}; 46 IPC::RequestParser rp{ctx};
47 min = rp.Pop<u32>(); 47 min = rp.Pop<u32>();
48 max = rp.Pop<u32>(); 48 max = rp.Pop<u32>();
49 LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); 49 LOG_DEBUG(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max);
50 50
51 current = min; 51 current = min;
52 IPC::ResponseBuilder rb{ctx, 2}; 52 IPC::ResponseBuilder rb{ctx, 2};
@@ -54,7 +54,7 @@ private:
54 } 54 }
55 55
56 void GetOld(Kernel::HLERequestContext& ctx) { 56 void GetOld(Kernel::HLERequestContext& ctx) {
57 LOG_WARNING(Service_MM, "(STUBBED) called"); 57 LOG_DEBUG(Service_MM, "(STUBBED) called");
58 58
59 IPC::ResponseBuilder rb{ctx, 3}; 59 IPC::ResponseBuilder rb{ctx, 3};
60 rb.Push(ResultSuccess); 60 rb.Push(ResultSuccess);
@@ -81,8 +81,8 @@ private:
81 u32 input_id = rp.Pop<u32>(); 81 u32 input_id = rp.Pop<u32>();
82 min = rp.Pop<u32>(); 82 min = rp.Pop<u32>();
83 max = rp.Pop<u32>(); 83 max = rp.Pop<u32>();
84 LOG_WARNING(Service_MM, "(STUBBED) called, input_id=0x{:X}, min=0x{:X}, max=0x{:X}", 84 LOG_DEBUG(Service_MM, "(STUBBED) called, input_id=0x{:X}, min=0x{:X}, max=0x{:X}", input_id,
85 input_id, min, max); 85 min, max);
86 86
87 current = min; 87 current = min;
88 IPC::ResponseBuilder rb{ctx, 2}; 88 IPC::ResponseBuilder rb{ctx, 2};
@@ -90,7 +90,7 @@ private:
90 } 90 }
91 91
92 void Get(Kernel::HLERequestContext& ctx) { 92 void Get(Kernel::HLERequestContext& ctx) {
93 LOG_WARNING(Service_MM, "(STUBBED) called"); 93 LOG_DEBUG(Service_MM, "(STUBBED) called");
94 94
95 IPC::ResponseBuilder rb{ctx, 3}; 95 IPC::ResponseBuilder rb{ctx, 3};
96 rb.Push(ResultSuccess); 96 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/iplatform_service_manager.cpp
index cc11f3e08..fd047ff26 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/iplatform_service_manager.cpp
@@ -20,7 +20,7 @@
20#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
21#include "core/hle/kernel/physical_memory.h" 21#include "core/hle/kernel/physical_memory.h"
22#include "core/hle/service/filesystem/filesystem.h" 22#include "core/hle/service/filesystem/filesystem.h"
23#include "core/hle/service/ns/pl_u.h" 23#include "core/hle/service/ns/iplatform_service_manager.h"
24 24
25namespace Service::NS { 25namespace Service::NS {
26 26
@@ -99,7 +99,7 @@ static u32 GetU32Swapped(const u8* data) {
99 return Common::swap32(value); 99 return Common::swap32(value);
100} 100}
101 101
102struct PL_U::Impl { 102struct IPlatformServiceManager::Impl {
103 const FontRegion& GetSharedFontRegion(std::size_t index) const { 103 const FontRegion& GetSharedFontRegion(std::size_t index) const {
104 if (index >= shared_font_regions.size() || shared_font_regions.empty()) { 104 if (index >= shared_font_regions.size() || shared_font_regions.empty()) {
105 // No font fallback 105 // No font fallback
@@ -134,16 +134,16 @@ struct PL_U::Impl {
134 std::vector<FontRegion> shared_font_regions; 134 std::vector<FontRegion> shared_font_regions;
135}; 135};
136 136
137PL_U::PL_U(Core::System& system_) 137IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_)
138 : ServiceFramework{system_, "pl:u"}, impl{std::make_unique<Impl>()} { 138 : ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} {
139 // clang-format off 139 // clang-format off
140 static const FunctionInfo functions[] = { 140 static const FunctionInfo functions[] = {
141 {0, &PL_U::RequestLoad, "RequestLoad"}, 141 {0, &IPlatformServiceManager::RequestLoad, "RequestLoad"},
142 {1, &PL_U::GetLoadState, "GetLoadState"}, 142 {1, &IPlatformServiceManager::GetLoadState, "GetLoadState"},
143 {2, &PL_U::GetSize, "GetSize"}, 143 {2, &IPlatformServiceManager::GetSize, "GetSize"},
144 {3, &PL_U::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"}, 144 {3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"},
145 {4, &PL_U::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, 145 {4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
146 {5, &PL_U::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"}, 146 {5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
147 {6, nullptr, "GetSharedFontInOrderOfPriorityForSystem"}, 147 {6, nullptr, "GetSharedFontInOrderOfPriorityForSystem"},
148 {100, nullptr, "RequestApplicationFunctionAuthorization"}, 148 {100, nullptr, "RequestApplicationFunctionAuthorization"},
149 {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, 149 {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
@@ -206,9 +206,9 @@ PL_U::PL_U(Core::System& system_)
206 } 206 }
207} 207}
208 208
209PL_U::~PL_U() = default; 209IPlatformServiceManager::~IPlatformServiceManager() = default;
210 210
211void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) { 211void IPlatformServiceManager::RequestLoad(Kernel::HLERequestContext& ctx) {
212 IPC::RequestParser rp{ctx}; 212 IPC::RequestParser rp{ctx};
213 const u32 shared_font_type{rp.Pop<u32>()}; 213 const u32 shared_font_type{rp.Pop<u32>()};
214 // Games don't call this so all fonts should be loaded 214 // Games don't call this so all fonts should be loaded
@@ -218,7 +218,7 @@ void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
218 rb.Push(ResultSuccess); 218 rb.Push(ResultSuccess);
219} 219}
220 220
221void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) { 221void IPlatformServiceManager::GetLoadState(Kernel::HLERequestContext& ctx) {
222 IPC::RequestParser rp{ctx}; 222 IPC::RequestParser rp{ctx};
223 const u32 font_id{rp.Pop<u32>()}; 223 const u32 font_id{rp.Pop<u32>()};
224 LOG_DEBUG(Service_NS, "called, font_id={}", font_id); 224 LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
@@ -228,7 +228,7 @@ void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) {
228 rb.Push<u32>(static_cast<u32>(LoadState::Done)); 228 rb.Push<u32>(static_cast<u32>(LoadState::Done));
229} 229}
230 230
231void PL_U::GetSize(Kernel::HLERequestContext& ctx) { 231void IPlatformServiceManager::GetSize(Kernel::HLERequestContext& ctx) {
232 IPC::RequestParser rp{ctx}; 232 IPC::RequestParser rp{ctx};
233 const u32 font_id{rp.Pop<u32>()}; 233 const u32 font_id{rp.Pop<u32>()};
234 LOG_DEBUG(Service_NS, "called, font_id={}", font_id); 234 LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
@@ -238,7 +238,7 @@ void PL_U::GetSize(Kernel::HLERequestContext& ctx) {
238 rb.Push<u32>(impl->GetSharedFontRegion(font_id).size); 238 rb.Push<u32>(impl->GetSharedFontRegion(font_id).size);
239} 239}
240 240
241void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) { 241void IPlatformServiceManager::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
242 IPC::RequestParser rp{ctx}; 242 IPC::RequestParser rp{ctx};
243 const u32 font_id{rp.Pop<u32>()}; 243 const u32 font_id{rp.Pop<u32>()};
244 LOG_DEBUG(Service_NS, "called, font_id={}", font_id); 244 LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
@@ -248,7 +248,7 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
248 rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset); 248 rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset);
249} 249}
250 250
251void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { 251void IPlatformServiceManager::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
252 // Map backing memory for the font data 252 // Map backing memory for the font data
253 LOG_DEBUG(Service_NS, "called"); 253 LOG_DEBUG(Service_NS, "called");
254 254
@@ -261,7 +261,7 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
261 rb.PushCopyObjects(&kernel.GetFontSharedMem()); 261 rb.PushCopyObjects(&kernel.GetFontSharedMem());
262} 262}
263 263
264void PL_U::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) { 264void IPlatformServiceManager::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) {
265 IPC::RequestParser rp{ctx}; 265 IPC::RequestParser rp{ctx};
266 const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for 266 const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
267 LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code); 267 LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code);
diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/iplatform_service_manager.h
index 07d0ac934..ed6eda89f 100644
--- a/src/core/hle/service/ns/pl_u.h
+++ b/src/core/hle/service/ns/iplatform_service_manager.h
@@ -36,10 +36,10 @@ constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{
36void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output); 36void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output);
37void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset); 37void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset);
38 38
39class PL_U final : public ServiceFramework<PL_U> { 39class IPlatformServiceManager final : public ServiceFramework<IPlatformServiceManager> {
40public: 40public:
41 explicit PL_U(Core::System& system_); 41 explicit IPlatformServiceManager(Core::System& system_, const char* service_name_);
42 ~PL_U() override; 42 ~IPlatformServiceManager() override;
43 43
44private: 44private:
45 void RequestLoad(Kernel::HLERequestContext& ctx); 45 void RequestLoad(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index aafc8fe03..f7318c3cb 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -9,10 +9,10 @@
9#include "core/file_sys/vfs.h" 9#include "core/file_sys/vfs.h"
10#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
11#include "core/hle/service/ns/errors.h" 11#include "core/hle/service/ns/errors.h"
12#include "core/hle/service/ns/iplatform_service_manager.h"
12#include "core/hle/service/ns/language.h" 13#include "core/hle/service/ns/language.h"
13#include "core/hle/service/ns/ns.h" 14#include "core/hle/service/ns/ns.h"
14#include "core/hle/service/ns/pdm_qry.h" 15#include "core/hle/service/ns/pdm_qry.h"
15#include "core/hle/service/ns/pl_u.h"
16#include "core/hle/service/set/set.h" 16#include "core/hle/service/set/set.h"
17 17
18namespace Service::NS { 18namespace Service::NS {
@@ -764,7 +764,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system
764 764
765 std::make_shared<PDM_QRY>(system)->InstallAsService(service_manager); 765 std::make_shared<PDM_QRY>(system)->InstallAsService(service_manager);
766 766
767 std::make_shared<PL_U>(system)->InstallAsService(service_manager); 767 std::make_shared<IPlatformServiceManager>(system, "pl:s")->InstallAsService(service_manager);
768 std::make_shared<IPlatformServiceManager>(system, "pl:u")->InstallAsService(service_manager);
768} 769}
769 770
770} // namespace Service::NS 771} // namespace Service::NS
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 728bfa00b..d8518149d 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -198,7 +198,7 @@ NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output)
198 IocParamParams params; 198 IocParamParams params;
199 std::memcpy(&params, input.data(), sizeof(params)); 199 std::memcpy(&params, input.data(), sizeof(params));
200 200
201 LOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.param); 201 LOG_DEBUG(Service_NVDRV, "(STUBBED) called type={}", params.param);
202 202
203 auto object = GetObject(params.handle); 203 auto object = GetObject(params.handle);
204 if (!object) { 204 if (!object) {
@@ -243,7 +243,7 @@ NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
243 IocFreeParams params; 243 IocFreeParams params;
244 std::memcpy(&params, input.data(), sizeof(params)); 244 std::memcpy(&params, input.data(), sizeof(params));
245 245
246 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 246 LOG_DEBUG(Service_NVDRV, "(STUBBED) called");
247 247
248 auto itr = handles.find(params.handle); 248 auto itr = handles.find(params.handle);
249 if (itr == handles.end()) { 249 if (itr == handles.end()) {
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index e08c3cb67..cc679cc81 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -933,7 +933,11 @@ BSD::BSD(Core::System& system_, const char* name)
933 } 933 }
934} 934}
935 935
936BSD::~BSD() = default; 936BSD::~BSD() {
937 if (auto room_member = room_network.GetRoomMember().lock()) {
938 room_member->Unbind(proxy_packet_received);
939 }
940}
937 941
938BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { 942BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} {
939 // clang-format off 943 // clang-format off
diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp
index 49d067f4c..0c746bd82 100644
--- a/src/core/internal_network/socket_proxy.cpp
+++ b/src/core/internal_network/socket_proxy.cpp
@@ -26,6 +26,12 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) {
26 closed) { 26 closed) {
27 return; 27 return;
28 } 28 }
29
30 if (!broadcast && packet.broadcast) {
31 LOG_INFO(Network, "Received broadcast packet, but not configured for broadcast mode");
32 return;
33 }
34
29 std::lock_guard guard(packets_mutex); 35 std::lock_guard guard(packets_mutex);
30 received_packets.push(packet); 36 received_packets.push(packet);
31} 37}
@@ -203,7 +209,7 @@ std::pair<s32, Errno> ProxySocket::SendTo(u32 flags, const std::vector<u8>& mess
203 packet.local_endpoint = local_endpoint; 209 packet.local_endpoint = local_endpoint;
204 packet.remote_endpoint = *addr; 210 packet.remote_endpoint = *addr;
205 packet.protocol = protocol; 211 packet.protocol = protocol;
206 packet.broadcast = broadcast; 212 packet.broadcast = broadcast && packet.remote_endpoint.ip[3] == 255;
207 213
208 auto& ip = local_endpoint.ip; 214 auto& ip = local_endpoint.ip;
209 auto ipv4 = Network::GetHostIPv4Address(); 215 auto ipv4 = Network::GetHostIPv4Address();
diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt
index b674b915b..737aedbe4 100644
--- a/src/dedicated_room/CMakeLists.txt
+++ b/src/dedicated_room/CMakeLists.txt
@@ -10,7 +10,7 @@ add_executable(yuzu-room
10 10
11create_target_directory_groups(yuzu-room) 11create_target_directory_groups(yuzu-room)
12 12
13target_link_libraries(yuzu-room PRIVATE common core network) 13target_link_libraries(yuzu-room PRIVATE common network)
14if (ENABLE_WEB_SERVICE) 14if (ENABLE_WEB_SERVICE)
15 target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) 15 target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE)
16 target_link_libraries(yuzu-room PRIVATE web_service) 16 target_link_libraries(yuzu-room PRIVATE web_service)
diff --git a/src/dedicated_room/yuzu_room.cpp b/src/dedicated_room/yuzu_room.cpp
index 482e772fb..7b6deba41 100644
--- a/src/dedicated_room/yuzu_room.cpp
+++ b/src/dedicated_room/yuzu_room.cpp
@@ -27,8 +27,8 @@
27#include "common/scm_rev.h" 27#include "common/scm_rev.h"
28#include "common/settings.h" 28#include "common/settings.h"
29#include "common/string_util.h" 29#include "common/string_util.h"
30#include "core/announce_multiplayer_session.h"
31#include "core/core.h" 30#include "core/core.h"
31#include "network/announce_multiplayer_session.h"
32#include "network/network.h" 32#include "network/network.h"
33#include "network/room.h" 33#include "network/room.h"
34#include "network/verify_user.h" 34#include "network/verify_user.h"
@@ -75,6 +75,12 @@ static constexpr char BanListMagic[] = "YuzuRoom-BanList-1";
75 75
76static constexpr char token_delimiter{':'}; 76static constexpr char token_delimiter{':'};
77 77
78static void PadToken(std::string& token) {
79 while (token.size() % 4 != 0) {
80 token.push_back('=');
81 }
82}
83
78static std::string UsernameFromDisplayToken(const std::string& display_token) { 84static std::string UsernameFromDisplayToken(const std::string& display_token) {
79 std::size_t outlen; 85 std::size_t outlen;
80 86
@@ -300,6 +306,7 @@ int main(int argc, char** argv) {
300 if (username.empty()) { 306 if (username.empty()) {
301 LOG_INFO(Network, "Hosting a public room"); 307 LOG_INFO(Network, "Hosting a public room");
302 Settings::values.web_api_url = web_api_url; 308 Settings::values.web_api_url = web_api_url;
309 PadToken(token);
303 Settings::values.yuzu_username = UsernameFromDisplayToken(token); 310 Settings::values.yuzu_username = UsernameFromDisplayToken(token);
304 username = Settings::values.yuzu_username.GetValue(); 311 username = Settings::values.yuzu_username.GetValue();
305 Settings::values.yuzu_token = TokenFromDisplayToken(token); 312 Settings::values.yuzu_token = TokenFromDisplayToken(token);
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index de388ec4c..5cc1ccbd9 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -40,13 +40,13 @@ public:
40 void EnableMotion() { 40 void EnableMotion() {
41 if (sdl_controller) { 41 if (sdl_controller) {
42 SDL_GameController* controller = sdl_controller.get(); 42 SDL_GameController* controller = sdl_controller.get();
43 if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) { 43 has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL);
44 has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO);
45 if (has_accel) {
44 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); 46 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
45 has_accel = true;
46 } 47 }
47 if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) { 48 if (has_gyro) {
48 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); 49 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
49 has_gyro = true;
50 } 50 }
51 } 51 }
52 } 52 }
@@ -305,6 +305,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
305 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); 305 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
306 PreSetController(joystick->GetPadIdentifier()); 306 PreSetController(joystick->GetPadIdentifier());
307 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); 307 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
308 joystick->EnableMotion();
308 joystick_map[guid].emplace_back(std::move(joystick)); 309 joystick_map[guid].emplace_back(std::move(joystick));
309 return; 310 return;
310 } 311 }
@@ -316,6 +317,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
316 317
317 if (joystick_it != joystick_guid_list.end()) { 318 if (joystick_it != joystick_guid_list.end()) {
318 (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); 319 (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
320 (*joystick_it)->EnableMotion();
319 return; 321 return;
320 } 322 }
321 323
@@ -323,6 +325,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
323 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); 325 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
324 PreSetController(joystick->GetPadIdentifier()); 326 PreSetController(joystick->GetPadIdentifier());
325 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); 327 SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel());
328 joystick->EnableMotion();
326 joystick_guid_list.emplace_back(std::move(joystick)); 329 joystick_guid_list.emplace_back(std::move(joystick));
327} 330}
328 331
diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt
index 312f79b68..6f8ca4b90 100644
--- a/src/network/CMakeLists.txt
+++ b/src/network/CMakeLists.txt
@@ -2,6 +2,8 @@
2# SPDX-License-Identifier: GPL-3.0-or-later 2# SPDX-License-Identifier: GPL-3.0-or-later
3 3
4add_library(network STATIC 4add_library(network STATIC
5 announce_multiplayer_session.cpp
6 announce_multiplayer_session.h
5 network.cpp 7 network.cpp
6 network.h 8 network.h
7 packet.cpp 9 packet.cpp
@@ -17,3 +19,7 @@ add_library(network STATIC
17create_target_directory_groups(network) 19create_target_directory_groups(network)
18 20
19target_link_libraries(network PRIVATE common enet Boost::boost) 21target_link_libraries(network PRIVATE common enet Boost::boost)
22if (ENABLE_WEB_SERVICE)
23 target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE)
24 target_link_libraries(network PRIVATE web_service)
25endif()
diff --git a/src/core/announce_multiplayer_session.cpp b/src/network/announce_multiplayer_session.cpp
index 6737ce85a..6737ce85a 100644
--- a/src/core/announce_multiplayer_session.cpp
+++ b/src/network/announce_multiplayer_session.cpp
diff --git a/src/core/announce_multiplayer_session.h b/src/network/announce_multiplayer_session.h
index db790f7d2..db790f7d2 100644
--- a/src/core/announce_multiplayer_session.h
+++ b/src/network/announce_multiplayer_session.h
diff --git a/src/network/room.cpp b/src/network/room.cpp
index b06797bf1..8c63b255b 100644
--- a/src/network/room.cpp
+++ b/src/network/room.cpp
@@ -221,7 +221,7 @@ public:
221 * Extracts the game name from a received ENet packet and broadcasts it. 221 * Extracts the game name from a received ENet packet and broadcasts it.
222 * @param event The ENet event that was received. 222 * @param event The ENet event that was received.
223 */ 223 */
224 void HandleGameNamePacket(const ENetEvent* event); 224 void HandleGameInfoPacket(const ENetEvent* event);
225 225
226 /** 226 /**
227 * Removes the client from the members list if it was in it and announces the change 227 * Removes the client from the members list if it was in it and announces the change
@@ -234,7 +234,7 @@ public:
234void Room::RoomImpl::ServerLoop() { 234void Room::RoomImpl::ServerLoop() {
235 while (state != State::Closed) { 235 while (state != State::Closed) {
236 ENetEvent event; 236 ENetEvent event;
237 if (enet_host_service(server, &event, 50) > 0) { 237 if (enet_host_service(server, &event, 5) > 0) {
238 switch (event.type) { 238 switch (event.type) {
239 case ENET_EVENT_TYPE_RECEIVE: 239 case ENET_EVENT_TYPE_RECEIVE:
240 switch (event.packet->data[0]) { 240 switch (event.packet->data[0]) {
@@ -242,7 +242,7 @@ void Room::RoomImpl::ServerLoop() {
242 HandleJoinRequest(&event); 242 HandleJoinRequest(&event);
243 break; 243 break;
244 case IdSetGameInfo: 244 case IdSetGameInfo:
245 HandleGameNamePacket(&event); 245 HandleGameInfoPacket(&event);
246 break; 246 break;
247 case IdProxyPacket: 247 case IdProxyPacket:
248 HandleProxyPacket(&event); 248 HandleProxyPacket(&event);
@@ -778,6 +778,7 @@ void Room::RoomImpl::BroadcastRoomInformation() {
778 packet.Write(member.fake_ip); 778 packet.Write(member.fake_ip);
779 packet.Write(member.game_info.name); 779 packet.Write(member.game_info.name);
780 packet.Write(member.game_info.id); 780 packet.Write(member.game_info.id);
781 packet.Write(member.game_info.version);
781 packet.Write(member.user_data.username); 782 packet.Write(member.user_data.username);
782 packet.Write(member.user_data.display_name); 783 packet.Write(member.user_data.display_name);
783 packet.Write(member.user_data.avatar_url); 784 packet.Write(member.user_data.avatar_url);
@@ -817,6 +818,7 @@ void Room::RoomImpl::HandleProxyPacket(const ENetEvent* event) {
817 in_packet.IgnoreBytes(sizeof(u16)); // Port 818 in_packet.IgnoreBytes(sizeof(u16)); // Port
818 819
819 in_packet.IgnoreBytes(sizeof(u8)); // Protocol 820 in_packet.IgnoreBytes(sizeof(u8)); // Protocol
821
820 bool broadcast; 822 bool broadcast;
821 in_packet.Read(broadcast); // Broadcast 823 in_packet.Read(broadcast); // Broadcast
822 824
@@ -909,7 +911,7 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) {
909 } 911 }
910} 912}
911 913
912void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) { 914void Room::RoomImpl::HandleGameInfoPacket(const ENetEvent* event) {
913 Packet in_packet; 915 Packet in_packet;
914 in_packet.Append(event->packet->data, event->packet->dataLength); 916 in_packet.Append(event->packet->data, event->packet->dataLength);
915 917
@@ -917,6 +919,7 @@ void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) {
917 GameInfo game_info; 919 GameInfo game_info;
918 in_packet.Read(game_info.name); 920 in_packet.Read(game_info.name);
919 in_packet.Read(game_info.id); 921 in_packet.Read(game_info.id);
922 in_packet.Read(game_info.version);
920 923
921 { 924 {
922 std::lock_guard lock(member_mutex); 925 std::lock_guard lock(member_mutex);
@@ -935,7 +938,8 @@ void Room::RoomImpl::HandleGameNamePacket(const ENetEvent* event) {
935 if (game_info.name.empty()) { 938 if (game_info.name.empty()) {
936 LOG_INFO(Network, "{} is not playing", display_name); 939 LOG_INFO(Network, "{} is not playing", display_name);
937 } else { 940 } else {
938 LOG_INFO(Network, "{} is playing {}", display_name, game_info.name); 941 LOG_INFO(Network, "{} is playing {} ({})", display_name, game_info.name,
942 game_info.version);
939 } 943 }
940 } 944 }
941 } 945 }
diff --git a/src/network/room_member.cpp b/src/network/room_member.cpp
index 9f08bf611..06818af78 100644
--- a/src/network/room_member.cpp
+++ b/src/network/room_member.cpp
@@ -103,7 +103,7 @@ public:
103 103
104 /** 104 /**
105 * Extracts a ProxyPacket from a received ENet packet. 105 * Extracts a ProxyPacket from a received ENet packet.
106 * @param event The ENet event that was received. 106 * @param event The ENet event that was received.
107 */ 107 */
108 void HandleProxyPackets(const ENetEvent* event); 108 void HandleProxyPackets(const ENetEvent* event);
109 109
@@ -159,7 +159,7 @@ void RoomMember::RoomMemberImpl::MemberLoop() {
159 while (IsConnected()) { 159 while (IsConnected()) {
160 std::lock_guard lock(network_mutex); 160 std::lock_guard lock(network_mutex);
161 ENetEvent event; 161 ENetEvent event;
162 if (enet_host_service(client, &event, 100) > 0) { 162 if (enet_host_service(client, &event, 5) > 0) {
163 switch (event.type) { 163 switch (event.type) {
164 case ENET_EVENT_TYPE_RECEIVE: 164 case ENET_EVENT_TYPE_RECEIVE:
165 switch (event.packet->data[0]) { 165 switch (event.packet->data[0]) {
@@ -315,6 +315,7 @@ void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* ev
315 packet.Read(member.fake_ip); 315 packet.Read(member.fake_ip);
316 packet.Read(member.game_info.name); 316 packet.Read(member.game_info.name);
317 packet.Read(member.game_info.id); 317 packet.Read(member.game_info.id);
318 packet.Read(member.game_info.version);
318 packet.Read(member.username); 319 packet.Read(member.username);
319 packet.Read(member.display_name); 320 packet.Read(member.display_name);
320 packet.Read(member.avatar_url); 321 packet.Read(member.avatar_url);
@@ -622,6 +623,7 @@ void RoomMember::SendGameInfo(const GameInfo& game_info) {
622 packet.Write(static_cast<u8>(IdSetGameInfo)); 623 packet.Write(static_cast<u8>(IdSetGameInfo));
623 packet.Write(game_info.name); 624 packet.Write(game_info.name);
624 packet.Write(game_info.id); 625 packet.Write(game_info.id);
626 packet.Write(game_info.version);
625 room_member_impl->Send(std::move(packet)); 627 room_member_impl->Send(std::move(packet));
626} 628}
627 629
diff --git a/src/network/room_member.h b/src/network/room_member.h
index 4252b7146..f578f7f6a 100644
--- a/src/network/room_member.h
+++ b/src/network/room_member.h
@@ -146,7 +146,7 @@ public:
146 const std::string& password = "", const std::string& token = ""); 146 const std::string& password = "", const std::string& token = "");
147 147
148 /** 148 /**
149 * Sends a WiFi packet to the room. 149 * Sends a Proxy packet to the room.
150 * @param packet The WiFi packet to send. 150 * @param packet The WiFi packet to send.
151 */ 151 */
152 void SendProxyPacket(const ProxyPacket& packet); 152 void SendProxyPacket(const ProxyPacket& packet);
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index e16d127a8..04d397750 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -14,7 +14,7 @@
14#include "yuzu/uisettings.h" 14#include "yuzu/uisettings.h"
15 15
16ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent) 16ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent)
17 : QWidget(parent), ui{std::make_unique<Ui::ConfigureDebug>()}, system{system_} { 17 : QScrollArea(parent), ui{std::make_unique<Ui::ConfigureDebug>()}, system{system_} {
18 ui->setupUi(this); 18 ui->setupUi(this);
19 SetConfiguration(); 19 SetConfiguration();
20 20
diff --git a/src/yuzu/configuration/configure_debug.h b/src/yuzu/configuration/configure_debug.h
index 64d68ab8f..42d30f170 100644
--- a/src/yuzu/configuration/configure_debug.h
+++ b/src/yuzu/configuration/configure_debug.h
@@ -4,7 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <memory> 6#include <memory>
7#include <QWidget> 7#include <QScrollArea>
8 8
9namespace Core { 9namespace Core {
10class System; 10class System;
@@ -14,7 +14,7 @@ namespace Ui {
14class ConfigureDebug; 14class ConfigureDebug;
15} 15}
16 16
17class ConfigureDebug : public QWidget { 17class ConfigureDebug : public QScrollArea {
18 Q_OBJECT 18 Q_OBJECT
19 19
20public: 20public:
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 4c16274fc..47b8b80f1 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -1,7 +1,11 @@
1<?xml version="1.0" encoding="UTF-8"?> 1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0"> 2<ui version="4.0">
3 <class>ConfigureDebug</class> 3 <class>ConfigureDebug</class>
4 <widget class="QWidget" name="ConfigureDebug"> 4 <widget class="QScrollArea" name="ConfigureDebug">
5 <property name="widgetResizable">
6 <bool>true</bool>
7 </property>
8 <widget class="QWidget">
5 <layout class="QVBoxLayout" name="verticalLayout_1"> 9 <layout class="QVBoxLayout" name="verticalLayout_1">
6 <item> 10 <item>
7 <layout class="QVBoxLayout" name="verticalLayout_2"> 11 <layout class="QVBoxLayout" name="verticalLayout_2">
@@ -322,6 +326,7 @@
322 </item> 326 </item>
323 </layout> 327 </layout>
324 </widget> 328 </widget>
329 </widget>
325 <tabstops> 330 <tabstops>
326 <tabstop>log_filter_edit</tabstop> 331 <tabstop>log_filter_edit</tabstop>
327 <tabstop>toggle_console</tabstop> 332 <tabstop>toggle_console</tabstop>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e103df977..a85adc072 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -860,7 +860,7 @@ void GMainWindow::InitializeWidgets() {
860 }); 860 });
861 861
862 multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room, 862 multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room,
863 ui->action_Show_Room, system->GetRoomNetwork()); 863 ui->action_Show_Room, *system);
864 multiplayer_state->setVisible(false); 864 multiplayer_state->setVisible(false);
865 865
866 // Create status bar 866 // Create status bar
diff --git a/src/yuzu/multiplayer/chat_room.cpp b/src/yuzu/multiplayer/chat_room.cpp
index 1968a3c75..9e672f82e 100644
--- a/src/yuzu/multiplayer/chat_room.cpp
+++ b/src/yuzu/multiplayer/chat_room.cpp
@@ -16,7 +16,7 @@
16#include <QUrl> 16#include <QUrl>
17#include <QtConcurrent/QtConcurrentRun> 17#include <QtConcurrent/QtConcurrentRun>
18#include "common/logging/log.h" 18#include "common/logging/log.h"
19#include "core/announce_multiplayer_session.h" 19#include "network/announce_multiplayer_session.h"
20#include "ui_chat_room.h" 20#include "ui_chat_room.h"
21#include "yuzu/game_list_p.h" 21#include "yuzu/game_list_p.h"
22#include "yuzu/multiplayer/chat_room.h" 22#include "yuzu/multiplayer/chat_room.h"
@@ -122,19 +122,22 @@ public:
122 static const int UsernameRole = Qt::UserRole + 2; 122 static const int UsernameRole = Qt::UserRole + 2;
123 static const int AvatarUrlRole = Qt::UserRole + 3; 123 static const int AvatarUrlRole = Qt::UserRole + 3;
124 static const int GameNameRole = Qt::UserRole + 4; 124 static const int GameNameRole = Qt::UserRole + 4;
125 static const int GameVersionRole = Qt::UserRole + 5;
125 126
126 PlayerListItem() = default; 127 PlayerListItem() = default;
127 explicit PlayerListItem(const std::string& nickname, const std::string& username, 128 explicit PlayerListItem(const std::string& nickname, const std::string& username,
128 const std::string& avatar_url, const std::string& game_name) { 129 const std::string& avatar_url,
130 const AnnounceMultiplayerRoom::GameInfo& game_info) {
129 setEditable(false); 131 setEditable(false);
130 setData(QString::fromStdString(nickname), NicknameRole); 132 setData(QString::fromStdString(nickname), NicknameRole);
131 setData(QString::fromStdString(username), UsernameRole); 133 setData(QString::fromStdString(username), UsernameRole);
132 setData(QString::fromStdString(avatar_url), AvatarUrlRole); 134 setData(QString::fromStdString(avatar_url), AvatarUrlRole);
133 if (game_name.empty()) { 135 if (game_info.name.empty()) {
134 setData(QObject::tr("Not playing a game"), GameNameRole); 136 setData(QObject::tr("Not playing a game"), GameNameRole);
135 } else { 137 } else {
136 setData(QString::fromStdString(game_name), GameNameRole); 138 setData(QString::fromStdString(game_info.name), GameNameRole);
137 } 139 }
140 setData(QString::fromStdString(game_info.version), GameVersionRole);
138 } 141 }
139 142
140 QVariant data(int role) const override { 143 QVariant data(int role) const override {
@@ -149,7 +152,13 @@ public:
149 } else { 152 } else {
150 name = QStringLiteral("%1 (%2)").arg(nickname, username); 153 name = QStringLiteral("%1 (%2)").arg(nickname, username);
151 } 154 }
152 return QStringLiteral("%1\n %2").arg(name, data(GameNameRole).toString()); 155 const QString version = data(GameVersionRole).toString();
156 QString version_string;
157 if (!version.isEmpty()) {
158 version_string = QStringLiteral("(%1)").arg(version);
159 }
160 return QStringLiteral("%1\n %2 %3")
161 .arg(name, data(GameNameRole).toString(), version_string);
153 } 162 }
154}; 163};
155 164
@@ -167,6 +176,10 @@ ChatRoom::ChatRoom(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::C
167 176
168 ui->chat_history->document()->setMaximumBlockCount(max_chat_lines); 177 ui->chat_history->document()->setMaximumBlockCount(max_chat_lines);
169 178
179 auto font = ui->chat_history->font();
180 font.setPointSizeF(10);
181 ui->chat_history->setFont(font);
182
170 // register the network structs to use in slots and signals 183 // register the network structs to use in slots and signals
171 qRegisterMetaType<Network::ChatEntry>(); 184 qRegisterMetaType<Network::ChatEntry>();
172 qRegisterMetaType<Network::StatusMessageEntry>(); 185 qRegisterMetaType<Network::StatusMessageEntry>();
@@ -366,7 +379,7 @@ void ChatRoom::SetPlayerList(const Network::RoomMember::MemberList& member_list)
366 if (member.nickname.empty()) 379 if (member.nickname.empty())
367 continue; 380 continue;
368 QStandardItem* name_item = new PlayerListItem(member.nickname, member.username, 381 QStandardItem* name_item = new PlayerListItem(member.nickname, member.username,
369 member.avatar_url, member.game_info.name); 382 member.avatar_url, member.game_info);
370 383
371#ifdef ENABLE_WEB_SERVICE 384#ifdef ENABLE_WEB_SERVICE
372 if (!icon_cache.count(member.avatar_url) && !member.avatar_url.empty()) { 385 if (!icon_cache.count(member.avatar_url) && !member.avatar_url.empty()) {
diff --git a/src/yuzu/multiplayer/client_room.cpp b/src/yuzu/multiplayer/client_room.cpp
index 86baafbf0..b34a8d004 100644
--- a/src/yuzu/multiplayer/client_room.cpp
+++ b/src/yuzu/multiplayer/client_room.cpp
@@ -10,7 +10,7 @@
10#include <QTime> 10#include <QTime>
11#include <QtConcurrent/QtConcurrentRun> 11#include <QtConcurrent/QtConcurrentRun>
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "core/announce_multiplayer_session.h" 13#include "network/announce_multiplayer_session.h"
14#include "ui_client_room.h" 14#include "ui_client_room.h"
15#include "yuzu/game_list_p.h" 15#include "yuzu/game_list_p.h"
16#include "yuzu/multiplayer/client_room.h" 16#include "yuzu/multiplayer/client_room.h"
diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp
index 4c0ea0a6b..017063074 100644
--- a/src/yuzu/multiplayer/direct_connect.cpp
+++ b/src/yuzu/multiplayer/direct_connect.cpp
@@ -8,6 +8,8 @@
8#include <QString> 8#include <QString>
9#include <QtConcurrent/QtConcurrentRun> 9#include <QtConcurrent/QtConcurrentRun>
10#include "common/settings.h" 10#include "common/settings.h"
11#include "core/core.h"
12#include "core/internal_network/network_interface.h"
11#include "network/network.h" 13#include "network/network.h"
12#include "ui_direct_connect.h" 14#include "ui_direct_connect.h"
13#include "yuzu/main.h" 15#include "yuzu/main.h"
@@ -20,9 +22,10 @@
20 22
21enum class ConnectionType : u8 { TraversalServer, IP }; 23enum class ConnectionType : u8 { TraversalServer, IP };
22 24
23DirectConnectWindow::DirectConnectWindow(Network::RoomNetwork& room_network_, QWidget* parent) 25DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent)
24 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), 26 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
25 ui(std::make_unique<Ui::DirectConnect>()), room_network{room_network_} { 27 ui(std::make_unique<Ui::DirectConnect>()), system{system_}, room_network{
28 system.GetRoomNetwork()} {
26 29
27 ui->setupUi(this); 30 ui->setupUi(this);
28 31
@@ -53,10 +56,20 @@ void DirectConnectWindow::RetranslateUi() {
53} 56}
54 57
55void DirectConnectWindow::Connect() { 58void DirectConnectWindow::Connect() {
59 if (!Network::GetSelectedNetworkInterface()) {
60 NetworkMessage::ErrorManager::ShowError(
61 NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED);
62 return;
63 }
56 if (!ui->nickname->hasAcceptableInput()) { 64 if (!ui->nickname->hasAcceptableInput()) {
57 NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); 65 NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID);
58 return; 66 return;
59 } 67 }
68 if (system.IsPoweredOn()) {
69 if (!NetworkMessage::WarnGameRunning()) {
70 return;
71 }
72 }
60 if (const auto member = room_network.GetRoomMember().lock()) { 73 if (const auto member = room_network.GetRoomMember().lock()) {
61 // Prevent the user from trying to join a room while they are already joining. 74 // Prevent the user from trying to join a room while they are already joining.
62 if (member->GetState() == Network::RoomMember::State::Joining) { 75 if (member->GetState() == Network::RoomMember::State::Joining) {
diff --git a/src/yuzu/multiplayer/direct_connect.h b/src/yuzu/multiplayer/direct_connect.h
index 4e1043053..e39dd1e0d 100644
--- a/src/yuzu/multiplayer/direct_connect.h
+++ b/src/yuzu/multiplayer/direct_connect.h
@@ -12,11 +12,15 @@ namespace Ui {
12class DirectConnect; 12class DirectConnect;
13} 13}
14 14
15namespace Core {
16class System;
17}
18
15class DirectConnectWindow : public QDialog { 19class DirectConnectWindow : public QDialog {
16 Q_OBJECT 20 Q_OBJECT
17 21
18public: 22public:
19 explicit DirectConnectWindow(Network::RoomNetwork& room_network_, QWidget* parent = nullptr); 23 explicit DirectConnectWindow(Core::System& system_, QWidget* parent = nullptr);
20 ~DirectConnectWindow(); 24 ~DirectConnectWindow();
21 25
22 void RetranslateUi(); 26 void RetranslateUi();
@@ -39,5 +43,6 @@ private:
39 QFutureWatcher<void>* watcher; 43 QFutureWatcher<void>* watcher;
40 std::unique_ptr<Ui::DirectConnect> ui; 44 std::unique_ptr<Ui::DirectConnect> ui;
41 Validation validation; 45 Validation validation;
46 Core::System& system;
42 Network::RoomNetwork& room_network; 47 Network::RoomNetwork& room_network;
43}; 48};
diff --git a/src/yuzu/multiplayer/host_room.cpp b/src/yuzu/multiplayer/host_room.cpp
index d70a9a3c8..0c6adfd04 100644
--- a/src/yuzu/multiplayer/host_room.cpp
+++ b/src/yuzu/multiplayer/host_room.cpp
@@ -12,7 +12,9 @@
12#include <QtConcurrent/QtConcurrentRun> 12#include <QtConcurrent/QtConcurrentRun>
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/settings.h" 14#include "common/settings.h"
15#include "core/announce_multiplayer_session.h" 15#include "core/core.h"
16#include "core/internal_network/network_interface.h"
17#include "network/announce_multiplayer_session.h"
16#include "ui_host_room.h" 18#include "ui_host_room.h"
17#include "yuzu/game_list_p.h" 19#include "yuzu/game_list_p.h"
18#include "yuzu/main.h" 20#include "yuzu/main.h"
@@ -27,10 +29,11 @@
27 29
28HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, 30HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
29 std::shared_ptr<Core::AnnounceMultiplayerSession> session, 31 std::shared_ptr<Core::AnnounceMultiplayerSession> session,
30 Network::RoomNetwork& room_network_) 32 Core::System& system_)
31 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), 33 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
32 ui(std::make_unique<Ui::HostRoom>()), 34 ui(std::make_unique<Ui::HostRoom>()),
33 announce_multiplayer_session(session), room_network{room_network_} { 35 announce_multiplayer_session(session), system{system_}, room_network{
36 system.GetRoomNetwork()} {
34 ui->setupUi(this); 37 ui->setupUi(this);
35 38
36 // set up validation for all of the fields 39 // set up validation for all of the fields
@@ -105,6 +108,11 @@ std::unique_ptr<Network::VerifyUser::Backend> HostRoomWindow::CreateVerifyBacken
105} 108}
106 109
107void HostRoomWindow::Host() { 110void HostRoomWindow::Host() {
111 if (!Network::GetSelectedNetworkInterface()) {
112 NetworkMessage::ErrorManager::ShowError(
113 NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED);
114 return;
115 }
108 if (!ui->username->hasAcceptableInput()) { 116 if (!ui->username->hasAcceptableInput()) {
109 NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); 117 NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID);
110 return; 118 return;
@@ -121,6 +129,11 @@ void HostRoomWindow::Host() {
121 NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::GAME_NOT_SELECTED); 129 NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::GAME_NOT_SELECTED);
122 return; 130 return;
123 } 131 }
132 if (system.IsPoweredOn()) {
133 if (!NetworkMessage::WarnGameRunning()) {
134 return;
135 }
136 }
124 if (auto member = room_network.GetRoomMember().lock()) { 137 if (auto member = room_network.GetRoomMember().lock()) {
125 if (member->GetState() == Network::RoomMember::State::Joining) { 138 if (member->GetState() == Network::RoomMember::State::Joining) {
126 return; 139 return;
diff --git a/src/yuzu/multiplayer/host_room.h b/src/yuzu/multiplayer/host_room.h
index a968042d0..034cb2eef 100644
--- a/src/yuzu/multiplayer/host_room.h
+++ b/src/yuzu/multiplayer/host_room.h
@@ -17,8 +17,9 @@ class HostRoom;
17} 17}
18 18
19namespace Core { 19namespace Core {
20class System;
20class AnnounceMultiplayerSession; 21class AnnounceMultiplayerSession;
21} 22} // namespace Core
22 23
23class ConnectionError; 24class ConnectionError;
24class ComboBoxProxyModel; 25class ComboBoxProxyModel;
@@ -35,7 +36,7 @@ class HostRoomWindow : public QDialog {
35public: 36public:
36 explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list, 37 explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list,
37 std::shared_ptr<Core::AnnounceMultiplayerSession> session, 38 std::shared_ptr<Core::AnnounceMultiplayerSession> session,
38 Network::RoomNetwork& room_network_); 39 Core::System& system_);
39 ~HostRoomWindow(); 40 ~HostRoomWindow();
40 41
41 /** 42 /**
@@ -54,6 +55,7 @@ private:
54 QStandardItemModel* game_list; 55 QStandardItemModel* game_list;
55 ComboBoxProxyModel* proxy; 56 ComboBoxProxyModel* proxy;
56 Validation validation; 57 Validation validation;
58 Core::System& system;
57 Network::RoomNetwork& room_network; 59 Network::RoomNetwork& room_network;
58}; 60};
59 61
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp
index 1cc518279..107d40547 100644
--- a/src/yuzu/multiplayer/lobby.cpp
+++ b/src/yuzu/multiplayer/lobby.cpp
@@ -6,6 +6,8 @@
6#include <QtConcurrent/QtConcurrentRun> 6#include <QtConcurrent/QtConcurrentRun>
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "common/settings.h" 8#include "common/settings.h"
9#include "core/core.h"
10#include "core/internal_network/network_interface.h"
9#include "network/network.h" 11#include "network/network.h"
10#include "ui_lobby.h" 12#include "ui_lobby.h"
11#include "yuzu/game_list_p.h" 13#include "yuzu/game_list_p.h"
@@ -22,11 +24,11 @@
22#endif 24#endif
23 25
24Lobby::Lobby(QWidget* parent, QStandardItemModel* list, 26Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
25 std::shared_ptr<Core::AnnounceMultiplayerSession> session, 27 std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_)
26 Network::RoomNetwork& room_network_)
27 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), 28 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
28 ui(std::make_unique<Ui::Lobby>()), 29 ui(std::make_unique<Ui::Lobby>()),
29 announce_multiplayer_session(session), room_network{room_network_} { 30 announce_multiplayer_session(session), system{system_}, room_network{
31 system.GetRoomNetwork()} {
30 ui->setupUi(this); 32 ui->setupUi(this);
31 33
32 // setup the watcher for background connections 34 // setup the watcher for background connections
@@ -114,6 +116,18 @@ void Lobby::OnExpandRoom(const QModelIndex& index) {
114} 116}
115 117
116void Lobby::OnJoinRoom(const QModelIndex& source) { 118void Lobby::OnJoinRoom(const QModelIndex& source) {
119 if (!Network::GetSelectedNetworkInterface()) {
120 NetworkMessage::ErrorManager::ShowError(
121 NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED);
122 return;
123 }
124
125 if (system.IsPoweredOn()) {
126 if (!NetworkMessage::WarnGameRunning()) {
127 return;
128 }
129 }
130
117 if (const auto member = room_network.GetRoomMember().lock()) { 131 if (const auto member = room_network.GetRoomMember().lock()) {
118 // Prevent the user from trying to join a room while they are already joining. 132 // Prevent the user from trying to join a room while they are already joining.
119 if (member->GetState() == Network::RoomMember::State::Joining) { 133 if (member->GetState() == Network::RoomMember::State::Joining) {
diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h
index 82744ca94..2696aec21 100644
--- a/src/yuzu/multiplayer/lobby.h
+++ b/src/yuzu/multiplayer/lobby.h
@@ -9,7 +9,7 @@
9#include <QSortFilterProxyModel> 9#include <QSortFilterProxyModel>
10#include <QStandardItemModel> 10#include <QStandardItemModel>
11#include "common/announce_multiplayer_room.h" 11#include "common/announce_multiplayer_room.h"
12#include "core/announce_multiplayer_session.h" 12#include "network/announce_multiplayer_session.h"
13#include "network/network.h" 13#include "network/network.h"
14#include "yuzu/multiplayer/validation.h" 14#include "yuzu/multiplayer/validation.h"
15 15
@@ -20,6 +20,10 @@ class Lobby;
20class LobbyModel; 20class LobbyModel;
21class LobbyFilterProxyModel; 21class LobbyFilterProxyModel;
22 22
23namespace Core {
24class System;
25}
26
23/** 27/**
24 * Listing of all public games pulled from services. The lobby should be simple enough for users to 28 * Listing of all public games pulled from services. The lobby should be simple enough for users to
25 * find the game they want to play, and join it. 29 * find the game they want to play, and join it.
@@ -30,7 +34,7 @@ class Lobby : public QDialog {
30public: 34public:
31 explicit Lobby(QWidget* parent, QStandardItemModel* list, 35 explicit Lobby(QWidget* parent, QStandardItemModel* list,
32 std::shared_ptr<Core::AnnounceMultiplayerSession> session, 36 std::shared_ptr<Core::AnnounceMultiplayerSession> session,
33 Network::RoomNetwork& room_network_); 37 Core::System& system_);
34 ~Lobby() override; 38 ~Lobby() override;
35 39
36 /** 40 /**
@@ -94,6 +98,7 @@ private:
94 std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; 98 std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
95 QFutureWatcher<void>* watcher; 99 QFutureWatcher<void>* watcher;
96 Validation validation; 100 Validation validation;
101 Core::System& system;
97 Network::RoomNetwork& room_network; 102 Network::RoomNetwork& room_network;
98}; 103};
99 104
diff --git a/src/yuzu/multiplayer/message.cpp b/src/yuzu/multiplayer/message.cpp
index 94d7a38b8..758b5b731 100644
--- a/src/yuzu/multiplayer/message.cpp
+++ b/src/yuzu/multiplayer/message.cpp
@@ -49,6 +49,9 @@ const ConnectionError ErrorManager::PERMISSION_DENIED(
49 QT_TR_NOOP("You do not have enough permission to perform this action.")); 49 QT_TR_NOOP("You do not have enough permission to perform this action."));
50const ConnectionError ErrorManager::NO_SUCH_USER(QT_TR_NOOP( 50const ConnectionError ErrorManager::NO_SUCH_USER(QT_TR_NOOP(
51 "The user you are trying to kick/ban could not be found.\nThey may have left the room.")); 51 "The user you are trying to kick/ban could not be found.\nThey may have left the room."));
52const ConnectionError ErrorManager::NO_INTERFACE_SELECTED(
53 QT_TR_NOOP("No network interface is selected.\nPlease go to Configure -> System -> Network and "
54 "make a selection."));
52 55
53static bool WarnMessage(const std::string& title, const std::string& text) { 56static bool WarnMessage(const std::string& title, const std::string& text) {
54 return QMessageBox::Ok == QMessageBox::warning(nullptr, QObject::tr(title.c_str()), 57 return QMessageBox::Ok == QMessageBox::warning(nullptr, QObject::tr(title.c_str()),
@@ -60,6 +63,13 @@ void ErrorManager::ShowError(const ConnectionError& e) {
60 QMessageBox::critical(nullptr, tr("Error"), tr(e.GetString().c_str())); 63 QMessageBox::critical(nullptr, tr("Error"), tr(e.GetString().c_str()));
61} 64}
62 65
66bool WarnGameRunning() {
67 return WarnMessage(
68 QT_TR_NOOP("Game already running"),
69 QT_TR_NOOP("Joining a room when the game is already running is discouraged "
70 "and can cause the room feature not to work correctly.\nProceed anyway?"));
71}
72
63bool WarnCloseRoom() { 73bool WarnCloseRoom() {
64 return WarnMessage( 74 return WarnMessage(
65 QT_TR_NOOP("Leave Room"), 75 QT_TR_NOOP("Leave Room"),
diff --git a/src/yuzu/multiplayer/message.h b/src/yuzu/multiplayer/message.h
index 812495c72..f038b9a1f 100644
--- a/src/yuzu/multiplayer/message.h
+++ b/src/yuzu/multiplayer/message.h
@@ -43,11 +43,20 @@ public:
43 static const ConnectionError IP_COLLISION; 43 static const ConnectionError IP_COLLISION;
44 static const ConnectionError PERMISSION_DENIED; 44 static const ConnectionError PERMISSION_DENIED;
45 static const ConnectionError NO_SUCH_USER; 45 static const ConnectionError NO_SUCH_USER;
46 static const ConnectionError NO_INTERFACE_SELECTED;
46 /** 47 /**
47 * Shows a standard QMessageBox with a error message 48 * Shows a standard QMessageBox with a error message
48 */ 49 */
49 static void ShowError(const ConnectionError& e); 50 static void ShowError(const ConnectionError& e);
50}; 51};
52
53/**
54 * Show a standard QMessageBox with a warning message about joining a room when
55 * the game is already running
56 * return true if the user wants to close the network connection
57 */
58bool WarnGameRunning();
59
51/** 60/**
52 * Show a standard QMessageBox with a warning message about leaving the room 61 * Show a standard QMessageBox with a warning message about leaving the room
53 * return true if the user wants to close the network connection 62 * return true if the user wants to close the network connection
diff --git a/src/yuzu/multiplayer/state.cpp b/src/yuzu/multiplayer/state.cpp
index dba76b22b..66e098296 100644
--- a/src/yuzu/multiplayer/state.cpp
+++ b/src/yuzu/multiplayer/state.cpp
@@ -8,6 +8,7 @@
8#include <QStandardItemModel> 8#include <QStandardItemModel>
9#include "common/announce_multiplayer_room.h" 9#include "common/announce_multiplayer_room.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "core/core.h"
11#include "yuzu/game_list.h" 12#include "yuzu/game_list.h"
12#include "yuzu/multiplayer/client_room.h" 13#include "yuzu/multiplayer/client_room.h"
13#include "yuzu/multiplayer/direct_connect.h" 14#include "yuzu/multiplayer/direct_connect.h"
@@ -19,10 +20,9 @@
19#include "yuzu/util/clickable_label.h" 20#include "yuzu/util/clickable_label.h"
20 21
21MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model_, 22MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model_,
22 QAction* leave_room_, QAction* show_room_, 23 QAction* leave_room_, QAction* show_room_, Core::System& system_)
23 Network::RoomNetwork& room_network_)
24 : QWidget(parent), game_list_model(game_list_model_), leave_room(leave_room_), 24 : QWidget(parent), game_list_model(game_list_model_), leave_room(leave_room_),
25 show_room(show_room_), room_network{room_network_} { 25 show_room(show_room_), system{system_}, room_network{system.GetRoomNetwork()} {
26 if (auto member = room_network.GetRoomMember().lock()) { 26 if (auto member = room_network.GetRoomMember().lock()) {
27 // register the network structs to use in slots and signals 27 // register the network structs to use in slots and signals
28 state_callback_handle = member->BindOnStateChanged( 28 state_callback_handle = member->BindOnStateChanged(
@@ -208,15 +208,14 @@ static void BringWidgetToFront(QWidget* widget) {
208 208
209void MultiplayerState::OnViewLobby() { 209void MultiplayerState::OnViewLobby() {
210 if (lobby == nullptr) { 210 if (lobby == nullptr) {
211 lobby = new Lobby(this, game_list_model, announce_multiplayer_session, room_network); 211 lobby = new Lobby(this, game_list_model, announce_multiplayer_session, system);
212 } 212 }
213 BringWidgetToFront(lobby); 213 BringWidgetToFront(lobby);
214} 214}
215 215
216void MultiplayerState::OnCreateRoom() { 216void MultiplayerState::OnCreateRoom() {
217 if (host_room == nullptr) { 217 if (host_room == nullptr) {
218 host_room = 218 host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session, system);
219 new HostRoomWindow(this, game_list_model, announce_multiplayer_session, room_network);
220 } 219 }
221 BringWidgetToFront(host_room); 220 BringWidgetToFront(host_room);
222} 221}
@@ -279,7 +278,7 @@ void MultiplayerState::OnOpenNetworkRoom() {
279 278
280void MultiplayerState::OnDirectConnectToRoom() { 279void MultiplayerState::OnDirectConnectToRoom() {
281 if (direct_connect == nullptr) { 280 if (direct_connect == nullptr) {
282 direct_connect = new DirectConnectWindow(room_network, this); 281 direct_connect = new DirectConnectWindow(system, this);
283 } 282 }
284 BringWidgetToFront(direct_connect); 283 BringWidgetToFront(direct_connect);
285} 284}
diff --git a/src/yuzu/multiplayer/state.h b/src/yuzu/multiplayer/state.h
index 9c60712d5..c92496413 100644
--- a/src/yuzu/multiplayer/state.h
+++ b/src/yuzu/multiplayer/state.h
@@ -4,7 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <QWidget> 6#include <QWidget>
7#include "core/announce_multiplayer_session.h" 7#include "network/announce_multiplayer_session.h"
8#include "network/network.h" 8#include "network/network.h"
9 9
10class QStandardItemModel; 10class QStandardItemModel;
@@ -14,12 +14,16 @@ class ClientRoomWindow;
14class DirectConnectWindow; 14class DirectConnectWindow;
15class ClickableLabel; 15class ClickableLabel;
16 16
17namespace Core {
18class System;
19}
20
17class MultiplayerState : public QWidget { 21class MultiplayerState : public QWidget {
18 Q_OBJECT; 22 Q_OBJECT;
19 23
20public: 24public:
21 explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room, 25 explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room,
22 QAction* show_room, Network::RoomNetwork& room_network_); 26 QAction* show_room, Core::System& system_);
23 ~MultiplayerState(); 27 ~MultiplayerState();
24 28
25 /** 29 /**
@@ -86,6 +90,7 @@ private:
86 Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle; 90 Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle;
87 91
88 bool show_notification = false; 92 bool show_notification = false;
93 Core::System& system;
89 Network::RoomNetwork& room_network; 94 Network::RoomNetwork& room_network;
90}; 95};
91 96