diff options
author | Zephyron <zephyron@citron-emu.org> | 2024-12-31 16:19:25 +1000 |
---|---|---|
committer | Zephyron <zephyron@citron-emu.org> | 2024-12-31 16:19:25 +1000 |
commit | 9427e27e24a7135880ee2881c3c44988e174b41a (patch) | |
tree | 83f0062a35be144f6b162eaa823c5b3c7620146e /src/yuzu/multiplayer/lobby.cpp | |
parent | b35ae725d20960411e8588b11c12a2d55f86c9d0 (diff) |
chore: update project branding to citron
Diffstat (limited to 'src/yuzu/multiplayer/lobby.cpp')
-rw-r--r-- | src/yuzu/multiplayer/lobby.cpp | 439 |
1 files changed, 0 insertions, 439 deletions
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp deleted file mode 100644 index 77ac84295..000000000 --- a/src/yuzu/multiplayer/lobby.cpp +++ /dev/null @@ -1,439 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <QInputDialog> -#include <QList> -#include <QtConcurrent/QtConcurrentRun> -#include "common/logging/log.h" -#include "common/settings.h" -#include "core/core.h" -#include "core/hle/service/acc/profile_manager.h" -#include "core/internal_network/network_interface.h" -#include "network/network.h" -#include "ui_lobby.h" -#include "yuzu/game_list_p.h" -#include "yuzu/main.h" -#include "yuzu/multiplayer/client_room.h" -#include "yuzu/multiplayer/lobby.h" -#include "yuzu/multiplayer/lobby_p.h" -#include "yuzu/multiplayer/message.h" -#include "yuzu/multiplayer/state.h" -#include "yuzu/multiplayer/validation.h" -#include "yuzu/uisettings.h" -#ifdef ENABLE_WEB_SERVICE -#include "web_service/web_backend.h" -#endif - -Lobby::Lobby(QWidget* parent, QStandardItemModel* list, - std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_) - : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique<Ui::Lobby>()), - announce_multiplayer_session(session), system{system_}, room_network{ - system.GetRoomNetwork()} { - ui->setupUi(this); - - // setup the watcher for background connections - watcher = new QFutureWatcher<void>; - - model = new QStandardItemModel(ui->room_list); - - // Create a proxy to the game list to get the list of games owned - game_list = new QStandardItemModel; - UpdateGameList(list); - - proxy = new LobbyFilterProxyModel(this, game_list); - proxy->setSourceModel(model); - proxy->setDynamicSortFilter(true); - proxy->setFilterCaseSensitivity(Qt::CaseInsensitive); - proxy->setSortLocaleAware(true); - ui->room_list->setModel(proxy); - ui->room_list->header()->setSectionResizeMode(QHeaderView::Interactive); - ui->room_list->header()->stretchLastSection(); - ui->room_list->setAlternatingRowColors(true); - ui->room_list->setSelectionMode(QHeaderView::SingleSelection); - ui->room_list->setSelectionBehavior(QHeaderView::SelectRows); - ui->room_list->setVerticalScrollMode(QHeaderView::ScrollPerPixel); - ui->room_list->setHorizontalScrollMode(QHeaderView::ScrollPerPixel); - ui->room_list->setSortingEnabled(true); - ui->room_list->setEditTriggers(QHeaderView::NoEditTriggers); - ui->room_list->setExpandsOnDoubleClick(false); - ui->room_list->setContextMenuPolicy(Qt::CustomContextMenu); - - ui->nickname->setValidator(validation.GetNickname()); - ui->nickname->setText( - QString::fromStdString(UISettings::values.multiplayer_nickname.GetValue())); - - // Try find the best nickname by default - if (ui->nickname->text().isEmpty() || ui->nickname->text() == QStringLiteral("yuzu")) { - if (!Settings::values.yuzu_username.GetValue().empty()) { - ui->nickname->setText( - QString::fromStdString(Settings::values.yuzu_username.GetValue())); - } else if (!GetProfileUsername().empty()) { - ui->nickname->setText(QString::fromStdString(GetProfileUsername())); - } else { - ui->nickname->setText(QStringLiteral("yuzu")); - } - } - - // UI Buttons - connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby); - connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch); - 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->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom); - connect(ui->room_list, &QTreeView::clicked, this, &Lobby::OnExpandRoom); - - // Actions - connect(&room_list_watcher, &QFutureWatcher<AnnounceMultiplayerRoom::RoomList>::finished, this, - &Lobby::OnRefreshLobby); - - // Load persistent filters after events are connected to make sure they apply - ui->search->setText( - QString::fromStdString(UISettings::values.multiplayer_filter_text.GetValue())); - ui->games_owned->setChecked(UISettings::values.multiplayer_filter_games_owned.GetValue()); - ui->hide_empty->setChecked(UISettings::values.multiplayer_filter_hide_empty.GetValue()); - ui->hide_full->setChecked(UISettings::values.multiplayer_filter_hide_full.GetValue()); -} - -Lobby::~Lobby() = default; - -void Lobby::UpdateGameList(QStandardItemModel* list) { - game_list->clear(); - for (int i = 0; i < list->rowCount(); i++) { - auto parent = list->item(i, 0); - for (int j = 0; j < parent->rowCount(); j++) { - game_list->appendRow(parent->child(j)->clone()); - } - } - if (proxy) - proxy->UpdateGameList(game_list); - ui->room_list->sortByColumn(Column::GAME_NAME, Qt::AscendingOrder); -} - -void Lobby::RetranslateUi() { - ui->retranslateUi(this); -} - -QString Lobby::PasswordPrompt() { - bool ok; - const QString text = - QInputDialog::getText(this, tr("Password Required to Join"), tr("Password:"), - QLineEdit::Password, QString(), &ok); - return ok ? text : QString(); -} - -void Lobby::OnExpandRoom(const QModelIndex& index) { - QModelIndex member_index = proxy->index(index.row(), Column::MEMBER); - auto member_list = proxy->data(member_index, LobbyItemMemberList::MemberListRole).toList(); -} - -void Lobby::OnJoinRoom(const QModelIndex& source) { - if (!Network::GetSelectedNetworkInterface()) { - LOG_INFO(WebService, "Automatically selected network interface for room network."); - Network::SelectFirstNetworkInterface(); - } - - 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()) { - // Prevent the user from trying to join a room while they are already joining. - if (member->GetState() == Network::RoomMember::State::Joining) { - return; - } else if (member->IsConnected()) { - // And ask if they want to leave the room if they are already in one. - if (!NetworkMessage::WarnDisconnect()) { - return; - } - } - } - QModelIndex index = source; - // If the user double clicks on a child row (aka the player list) then use the parent instead - if (source.parent() != QModelIndex()) { - index = source.parent(); - } - if (!ui->nickname->hasAcceptableInput()) { - NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID); - return; - } - - // Get a password to pass if the room is password protected - QModelIndex password_index = proxy->index(index.row(), Column::ROOM_NAME); - bool has_password = proxy->data(password_index, LobbyItemName::PasswordRole).toBool(); - const std::string password = has_password ? PasswordPrompt().toStdString() : ""; - if (has_password && password.empty()) { - return; - } - - QModelIndex connection_index = proxy->index(index.row(), Column::HOST); - const std::string nickname = ui->nickname->text().toStdString(); - const std::string ip = - proxy->data(connection_index, LobbyItemHost::HostIPRole).toString().toStdString(); - int port = proxy->data(connection_index, LobbyItemHost::HostPortRole).toInt(); - const std::string verify_uid = - proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString(); - - // attempt to connect in a different thread - QFuture<void> f = QtConcurrent::run([nickname, ip, port, password, verify_uid, this] { - std::string token; -#ifdef ENABLE_WEB_SERVICE - if (!Settings::values.yuzu_username.GetValue().empty() && - !Settings::values.yuzu_token.GetValue().empty()) { - WebService::Client client(Settings::values.web_api_url.GetValue(), - Settings::values.yuzu_username.GetValue(), - Settings::values.yuzu_token.GetValue()); - token = client.GetExternalJWT(verify_uid).returned_data; - if (token.empty()) { - LOG_ERROR(WebService, "Could not get external JWT, verification may fail"); - } else { - LOG_INFO(WebService, "Successfully requested external JWT: size={}", token.size()); - } - } -#endif - if (auto room_member = room_network.GetRoomMember().lock()) { - room_member->Join(nickname, ip.c_str(), port, 0, Network::NoPreferredIP, password, - token); - } - }); - watcher->setFuture(f); - - // TODO(jroweboy): disable widgets and display a connecting while we wait - - // Save settings - UISettings::values.multiplayer_nickname = ui->nickname->text().toStdString(); - UISettings::values.multiplayer_filter_text = ui->search->text().toStdString(); - UISettings::values.multiplayer_filter_games_owned = ui->games_owned->isChecked(); - UISettings::values.multiplayer_filter_hide_empty = ui->hide_empty->isChecked(); - UISettings::values.multiplayer_filter_hide_full = ui->hide_full->isChecked(); - UISettings::values.multiplayer_ip = - proxy->data(connection_index, LobbyItemHost::HostIPRole).value<QString>().toStdString(); - UISettings::values.multiplayer_port = - proxy->data(connection_index, LobbyItemHost::HostPortRole).toInt(); - emit SaveConfig(); -} - -void Lobby::ResetModel() { - model->clear(); - model->insertColumns(0, Column::TOTAL); - model->setHeaderData(Column::MEMBER, Qt::Horizontal, tr("Players"), Qt::DisplayRole); - model->setHeaderData(Column::ROOM_NAME, Qt::Horizontal, tr("Room Name"), Qt::DisplayRole); - model->setHeaderData(Column::GAME_NAME, Qt::Horizontal, tr("Preferred Game"), Qt::DisplayRole); - model->setHeaderData(Column::HOST, Qt::Horizontal, tr("Host"), Qt::DisplayRole); -} - -void Lobby::RefreshLobby() { - if (auto session = announce_multiplayer_session.lock()) { - ResetModel(); - ui->refresh_list->setEnabled(false); - ui->refresh_list->setText(tr("Refreshing")); - room_list_watcher.setFuture( - QtConcurrent::run([session]() { return session->GetRoomList(); })); - } else { - // TODO(jroweboy): Display an error box about announce couldn't be started - } -} - -void Lobby::OnRefreshLobby() { - AnnounceMultiplayerRoom::RoomList new_room_list = room_list_watcher.result(); - for (auto room : new_room_list) { - // find the icon for the game if this person owns that game. - QPixmap smdh_icon; - for (int r = 0; r < game_list->rowCount(); ++r) { - auto index = game_list->index(r, 0); - auto game_id = game_list->data(index, GameListItemPath::ProgramIdRole).toULongLong(); - - if (game_id != 0 && room.information.preferred_game.id == game_id) { - smdh_icon = game_list->data(index, Qt::DecorationRole).value<QPixmap>(); - } - } - - QList<QVariant> members; - for (auto member : room.members) { - QVariant var; - var.setValue(LobbyMember{QString::fromStdString(member.username), - QString::fromStdString(member.nickname), member.game.id, - QString::fromStdString(member.game.name)}); - members.append(var); - } - - auto first_item = new LobbyItemGame( - room.information.preferred_game.id, - QString::fromStdString(room.information.preferred_game.name), smdh_icon); - auto row = QList<QStandardItem*>({ - first_item, - new LobbyItemName(room.has_password, QString::fromStdString(room.information.name)), - new LobbyItemMemberList(members, room.information.member_slots), - new LobbyItemHost(QString::fromStdString(room.information.host_username), - QString::fromStdString(room.ip), room.information.port, - QString::fromStdString(room.verify_uid)), - }); - model->appendRow(row); - // To make the rows expandable, add the member data as a child of the first column of the - // rows with people in them and have qt set them to colspan after the model is finished - // resetting - if (!room.information.description.empty()) { - first_item->appendRow( - new LobbyItemDescription(QString::fromStdString(room.information.description))); - } - if (!room.members.empty()) { - first_item->appendRow(new LobbyItemExpandedMemberList(members)); - } - } - - // Re-enable the refresh button and resize the columns - ui->refresh_list->setEnabled(true); - ui->refresh_list->setText(tr("Refresh List")); - ui->room_list->header()->stretchLastSection(); - for (int i = 0; i < Column::TOTAL - 1; ++i) { - ui->room_list->resizeColumnToContents(i); - } - - // Set the member list child items to span all columns - for (int i = 0; i < proxy->rowCount(); i++) { - auto parent = model->item(i, 0); - for (int j = 0; j < parent->rowCount(); j++) { - ui->room_list->setFirstColumnSpanned(j, proxy->index(i, 0), true); - } - } - - ui->room_list->sortByColumn(Column::GAME_NAME, Qt::AscendingOrder); -} - -std::string Lobby::GetProfileUsername() { - const auto& current_user = - system.GetProfileManager().GetUser(Settings::values.current_user.GetValue()); - Service::Account::ProfileBase profile{}; - - if (!current_user.has_value()) { - return ""; - } - - if (!system.GetProfileManager().GetProfileBase(*current_user, profile)) { - return ""; - } - - const auto text = Common::StringFromFixedZeroTerminatedBuffer( - reinterpret_cast<const char*>(profile.username.data()), profile.username.size()); - - return text; -} - -LobbyFilterProxyModel::LobbyFilterProxyModel(QWidget* parent, QStandardItemModel* list) - : QSortFilterProxyModel(parent), game_list(list) {} - -void LobbyFilterProxyModel::UpdateGameList(QStandardItemModel* list) { - game_list = list; -} - -bool LobbyFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { - // Prioritize filters by fastest to compute - - // pass over any child rows (aka row that shows the players in the room) - if (sourceParent != QModelIndex()) { - return true; - } - - // filter by empty rooms - if (filter_empty) { - QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); - 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 = - sourceModel()->data(member_list, LobbyItemMemberList::MemberListRole).toList().size(); - int max_players = - sourceModel()->data(member_list, LobbyItemMemberList::MaxPlayerRole).toInt(); - if (player_count >= max_players) { - return false; - } - } - - // filter by search parameters - if (!filter_search.isEmpty()) { - QModelIndex game_name = sourceModel()->index(sourceRow, Column::GAME_NAME, sourceParent); - QModelIndex room_name = sourceModel()->index(sourceRow, Column::ROOM_NAME, sourceParent); - QModelIndex host_name = sourceModel()->index(sourceRow, Column::HOST, sourceParent); - bool preferred_game_match = sourceModel() - ->data(game_name, LobbyItemGame::GameNameRole) - .toString() - .contains(filter_search, filterCaseSensitivity()); - bool room_name_match = sourceModel() - ->data(room_name, LobbyItemName::NameRole) - .toString() - .contains(filter_search, filterCaseSensitivity()); - bool username_match = sourceModel() - ->data(host_name, LobbyItemHost::HostUsernameRole) - .toString() - .contains(filter_search, filterCaseSensitivity()); - if (!preferred_game_match && !room_name_match && !username_match) { - return false; - } - } - - // filter by game owned - if (filter_owned) { - QModelIndex game_name = sourceModel()->index(sourceRow, Column::GAME_NAME, sourceParent); - QList<QModelIndex> owned_games; - for (int r = 0; r < game_list->rowCount(); ++r) { - owned_games.append(QModelIndex(game_list->index(r, 0))); - } - auto current_id = sourceModel()->data(game_name, LobbyItemGame::TitleIDRole).toLongLong(); - if (current_id == 0) { - // TODO(jroweboy): homebrew often doesn't have a game id and this hides them - return false; - } - bool owned = false; - for (const auto& game : owned_games) { - auto game_id = game_list->data(game, GameListItemPath::ProgramIdRole).toLongLong(); - if (current_id == game_id) { - owned = true; - } - } - if (!owned) { - return false; - } - } - - return true; -} - -void LobbyFilterProxyModel::sort(int column, Qt::SortOrder order) { - sourceModel()->sort(column, order); -} - -void LobbyFilterProxyModel::SetFilterOwned(bool filter) { - filter_owned = filter; - invalidate(); -} - -void LobbyFilterProxyModel::SetFilterEmpty(bool filter) { - filter_empty = filter; - invalidate(); -} - -void LobbyFilterProxyModel::SetFilterFull(bool filter) { - filter_full = filter; - invalidate(); -} - -void LobbyFilterProxyModel::SetFilterSearch(const QString& filter) { - filter_search = filter; - invalidate(); -} |