From 07e02a1acf8f48c3379dfa17aaea46cef2c9136f Mon Sep 17 00:00:00 2001 From: Tobias Date: Wed, 8 Mar 2023 00:51:46 +0100 Subject: [PATCH] Port multiplayer related PRs from yuzu (yuzu-emu/yuzu#9661 and yuzu-emu/yuzu#9713) (#6319) Co-authored-by: SoRadGaming Co-authored-by: Luke Sawczak --- src/citra_qt/multiplayer/direct_connect.cpp | 21 ++++++----------- src/citra_qt/multiplayer/direct_connect.ui | 23 +++++++++---------- src/citra_qt/multiplayer/lobby.cpp | 20 +++++++++++++++-- src/citra_qt/multiplayer/lobby.h | 2 ++ src/citra_qt/multiplayer/lobby.ui | 7 ++++++ src/citra_qt/multiplayer/validation.h | 25 +++++++++++++++++---- 6 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/citra_qt/multiplayer/direct_connect.cpp b/src/citra_qt/multiplayer/direct_connect.cpp index feaea69c9..6cef55845 100644 --- a/src/citra_qt/multiplayer/direct_connect.cpp +++ b/src/citra_qt/multiplayer/direct_connect.cpp @@ -70,20 +70,13 @@ void DirectConnectWindow::Connect() { } } } - switch (static_cast(ui->connection_type->currentIndex())) { - case ConnectionType::TraversalServer: - break; - case ConnectionType::IP: - if (!ui->ip->hasAcceptableInput()) { - NetworkMessage::ErrorManager::ShowError( - NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID); - return; - } - if (!ui->port->hasAcceptableInput()) { - NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::PORT_NOT_VALID); - return; - } - break; + if (!ui->ip->hasAcceptableInput()) { + NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID); + return; + } + if (!ui->port->hasAcceptableInput()) { + NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::PORT_NOT_VALID); + return; } // Store settings diff --git a/src/citra_qt/multiplayer/direct_connect.ui b/src/citra_qt/multiplayer/direct_connect.ui index 681b6bf69..4a328189a 100644 --- a/src/citra_qt/multiplayer/direct_connect.ui +++ b/src/citra_qt/multiplayer/direct_connect.ui @@ -26,20 +26,11 @@ 0 - - - - - IP Address - - - - - 5 + 0 0 @@ -53,17 +44,17 @@ - IP + Server Address - <html><head/><body><p>IPv4 address of the host</p></body></html> + <html><head/><body><p>Server address of the host</p></body></html> - 16 + 253 @@ -85,6 +76,12 @@ 24872 + + + 65 + 50 + + diff --git a/src/citra_qt/multiplayer/lobby.cpp b/src/citra_qt/multiplayer/lobby.cpp index d74bbf3ab..72f11b9db 100644 --- a/src/citra_qt/multiplayer/lobby.cpp +++ b/src/citra_qt/multiplayer/lobby.cpp @@ -66,6 +66,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, // UI Buttons connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby); connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned); + connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty); connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull); connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch); connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom); @@ -282,12 +283,22 @@ bool LobbyFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s return true; } + // filter by empty rooms + if (filter_empty) { + QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); + const int player_count = + sourceModel()->data(member_list, LobbyItemMemberList::MemberListRole).toList().size(); + if (player_count == 0) { + return false; + } + } + // filter by filled rooms if (filter_full) { QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); - int player_count = + const int player_count = sourceModel()->data(member_list, LobbyItemMemberList::MemberListRole).toList().size(); - int max_players = + const int max_players = sourceModel()->data(member_list, LobbyItemMemberList::MaxPlayerRole).toInt(); if (player_count >= max_players) { return false; @@ -352,6 +363,11 @@ void LobbyFilterProxyModel::SetFilterOwned(bool filter) { invalidate(); } +void LobbyFilterProxyModel::SetFilterEmpty(bool filter) { + filter_empty = filter; + invalidate(); +} + void LobbyFilterProxyModel::SetFilterFull(bool filter) { filter_full = filter; invalidate(); diff --git a/src/citra_qt/multiplayer/lobby.h b/src/citra_qt/multiplayer/lobby.h index 985b82ba7..129b25497 100644 --- a/src/citra_qt/multiplayer/lobby.h +++ b/src/citra_qt/multiplayer/lobby.h @@ -116,12 +116,14 @@ public: public slots: void SetFilterOwned(bool); + void SetFilterEmpty(bool); void SetFilterFull(bool); void SetFilterSearch(const QString&); private: QStandardItemModel* game_list; bool filter_owned = false; + bool filter_empty = false; bool filter_full = false; QString filter_search; }; diff --git a/src/citra_qt/multiplayer/lobby.ui b/src/citra_qt/multiplayer/lobby.ui index 4c9901c9a..0ef0ef762 100644 --- a/src/citra_qt/multiplayer/lobby.ui +++ b/src/citra_qt/multiplayer/lobby.ui @@ -77,6 +77,13 @@ + + + + Hide Empty Rooms + + + diff --git a/src/citra_qt/multiplayer/validation.h b/src/citra_qt/multiplayer/validation.h index 1c215a190..ecf3069d9 100644 --- a/src/citra_qt/multiplayer/validation.h +++ b/src/citra_qt/multiplayer/validation.h @@ -37,11 +37,28 @@ private: QRegExp nickname_regex = QRegExp(QStringLiteral("^[a-zA-Z0-9._- ]{4,20}$")); QRegExpValidator nickname; - /// ipv4 address only - // TODO remove this when we support hostnames in direct connect + /// ipv4 / ipv6 / hostnames QRegExp ip_regex = QRegExp(QStringLiteral( - "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|" - "2[0-4][0-9]|25[0-5])")); + // IPv4 regex + "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|" + // IPv6 regex + "^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|" + "(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-" + "5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|" + "(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" + "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|" + "(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]" + "\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" + "(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[" + "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" + "(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[" + "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" + "(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[" + "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" + "(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?" + "\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?$|" + // Hostname regex + "^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}$")); QRegExpValidator ip; /// port must be between 0 and 65535