direct_connect.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <QComboBox>
  4. #include <QFuture>
  5. #include <QIntValidator>
  6. #include <QRegExpValidator>
  7. #include <QString>
  8. #include <QtConcurrent/QtConcurrentRun>
  9. #include "common/settings.h"
  10. #include "network/network.h"
  11. #include "ui_direct_connect.h"
  12. #include "yuzu/main.h"
  13. #include "yuzu/multiplayer/client_room.h"
  14. #include "yuzu/multiplayer/direct_connect.h"
  15. #include "yuzu/multiplayer/message.h"
  16. #include "yuzu/multiplayer/state.h"
  17. #include "yuzu/multiplayer/validation.h"
  18. #include "yuzu/uisettings.h"
  19. enum class ConnectionType : u8 { TraversalServer, IP };
  20. DirectConnectWindow::DirectConnectWindow(Network::RoomNetwork& room_network_, QWidget* parent)
  21. : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
  22. ui(std::make_unique<Ui::DirectConnect>()), room_network{room_network_} {
  23. ui->setupUi(this);
  24. // setup the watcher for background connections
  25. watcher = new QFutureWatcher<void>;
  26. connect(watcher, &QFutureWatcher<void>::finished, this, &DirectConnectWindow::OnConnection);
  27. ui->nickname->setValidator(validation.GetNickname());
  28. ui->nickname->setText(UISettings::values.multiplayer_nickname.GetValue());
  29. if (ui->nickname->text().isEmpty() && !Settings::values.yuzu_username.GetValue().empty()) {
  30. // Use yuzu Web Service user name as nickname by default
  31. ui->nickname->setText(QString::fromStdString(Settings::values.yuzu_username.GetValue()));
  32. }
  33. ui->ip->setValidator(validation.GetIP());
  34. ui->ip->setText(UISettings::values.multiplayer_ip.GetValue());
  35. ui->port->setValidator(validation.GetPort());
  36. ui->port->setText(QString::number(UISettings::values.multiplayer_port.GetValue()));
  37. // TODO(jroweboy): Show or hide the connection options based on the current value of the combo
  38. // box. Add this back in when the traversal server support is added.
  39. connect(ui->connect, &QPushButton::clicked, this, &DirectConnectWindow::Connect);
  40. }
  41. DirectConnectWindow::~DirectConnectWindow() = default;
  42. void DirectConnectWindow::RetranslateUi() {
  43. ui->retranslateUi(this);
  44. }
  45. void DirectConnectWindow::Connect() {
  46. if (!ui->nickname->hasAcceptableInput()) {
  47. NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID);
  48. return;
  49. }
  50. if (const auto member = room_network.GetRoomMember().lock()) {
  51. // Prevent the user from trying to join a room while they are already joining.
  52. if (member->GetState() == Network::RoomMember::State::Joining) {
  53. return;
  54. } else if (member->IsConnected()) {
  55. // And ask if they want to leave the room if they are already in one.
  56. if (!NetworkMessage::WarnDisconnect()) {
  57. return;
  58. }
  59. }
  60. }
  61. switch (static_cast<ConnectionType>(ui->connection_type->currentIndex())) {
  62. case ConnectionType::TraversalServer:
  63. break;
  64. case ConnectionType::IP:
  65. if (!ui->ip->hasAcceptableInput()) {
  66. NetworkMessage::ErrorManager::ShowError(
  67. NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID);
  68. return;
  69. }
  70. if (!ui->port->hasAcceptableInput()) {
  71. NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::PORT_NOT_VALID);
  72. return;
  73. }
  74. break;
  75. }
  76. // Store settings
  77. UISettings::values.multiplayer_nickname = ui->nickname->text();
  78. UISettings::values.multiplayer_ip = ui->ip->text();
  79. if (ui->port->isModified() && !ui->port->text().isEmpty()) {
  80. UISettings::values.multiplayer_port = ui->port->text().toInt();
  81. } else {
  82. UISettings::values.multiplayer_port = UISettings::values.multiplayer_port.GetDefault();
  83. }
  84. // attempt to connect in a different thread
  85. QFuture<void> f = QtConcurrent::run([&] {
  86. if (auto room_member = room_network.GetRoomMember().lock()) {
  87. auto port = UISettings::values.multiplayer_port.GetValue();
  88. room_member->Join(ui->nickname->text().toStdString(), "",
  89. ui->ip->text().toStdString().c_str(), port, 0,
  90. Network::NoPreferredMac, ui->password->text().toStdString().c_str());
  91. }
  92. });
  93. watcher->setFuture(f);
  94. // and disable widgets and display a connecting while we wait
  95. BeginConnecting();
  96. }
  97. void DirectConnectWindow::BeginConnecting() {
  98. ui->connect->setEnabled(false);
  99. ui->connect->setText(tr("Connecting"));
  100. }
  101. void DirectConnectWindow::EndConnecting() {
  102. ui->connect->setEnabled(true);
  103. ui->connect->setText(tr("Connect"));
  104. }
  105. void DirectConnectWindow::OnConnection() {
  106. EndConnecting();
  107. if (auto room_member = room_network.GetRoomMember().lock()) {
  108. if (room_member->GetState() == Network::RoomMember::State::Joined ||
  109. room_member->GetState() == Network::RoomMember::State::Moderator) {
  110. close();
  111. }
  112. }
  113. }