mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-15 00:19:00 +02:00
Some genius decided to put the entire MainWindow class into main.h and main.cpp, which is not only horrific practice but also completely destroys clangd beyond repair. Please, just don't do this. (this will probably merge conflict to hell and back) Also, fixes a bunch of issues with Ryujinx save data link: - Paths with spaces would cause mklink to fail - Add support for portable directories - Symlink detection was incorrect sometimes(????) - Some other stuff I'm forgetting Furthermore, when selecting "From Eden" and attempting to save in Ryujinx, Ryujinx would destroy the link for... some reason? So to get around this we just copy the Eden data to Ryujinx then treat it like a "From Ryujinx" op Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2929 Reviewed-by: Lizzie <lizzie@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
139 lines
5.1 KiB
C++
139 lines
5.1 KiB
C++
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include <QComboBox>
|
|
#include <QFuture>
|
|
#include <QIntValidator>
|
|
#include <QRegularExpressionValidator>
|
|
#include <QString>
|
|
#include <QtConcurrentRun>
|
|
#include "common/settings.h"
|
|
#include "core/core.h"
|
|
#include "core/internal_network/network_interface.h"
|
|
#include "network/network.h"
|
|
#include "ui_direct_connect.h"
|
|
#include "yuzu/main_window.h"
|
|
#include "yuzu/multiplayer/client_room.h"
|
|
#include "yuzu/multiplayer/direct_connect.h"
|
|
#include "yuzu/multiplayer/message.h"
|
|
#include "yuzu/multiplayer/state.h"
|
|
#include "yuzu/multiplayer/validation.h"
|
|
#include "qt_common/config/uisettings.h"
|
|
|
|
enum class ConnectionType : u8 { TraversalServer, IP };
|
|
|
|
DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent)
|
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
|
ui(std::make_unique<Ui::DirectConnect>()), system{system_} {
|
|
|
|
ui->setupUi(this);
|
|
|
|
// setup the watcher for background connections
|
|
watcher = new QFutureWatcher<void>;
|
|
connect(watcher, &QFutureWatcher<void>::finished, this, &DirectConnectWindow::OnConnection);
|
|
|
|
ui->nickname->setValidator(validation.GetNickname());
|
|
ui->nickname->setText(
|
|
QString::fromStdString(UISettings::values.multiplayer_nickname.GetValue()));
|
|
if (ui->nickname->text().isEmpty() && !Settings::values.eden_username.GetValue().empty()) {
|
|
// Use yuzu Web Service user name as nickname by default
|
|
ui->nickname->setText(QString::fromStdString(Settings::values.eden_username.GetValue()));
|
|
}
|
|
ui->ip->setValidator(validation.GetIP());
|
|
ui->ip->setText(QString::fromStdString(UISettings::values.multiplayer_ip.GetValue()));
|
|
ui->port->setValidator(validation.GetPort());
|
|
ui->port->setText(QString::number(UISettings::values.multiplayer_port.GetValue()));
|
|
|
|
// TODO(jroweboy): Show or hide the connection options based on the current value of the combo
|
|
// box. Add this back in when the traversal server support is added.
|
|
connect(ui->connect, &QPushButton::clicked, this, &DirectConnectWindow::Connect);
|
|
}
|
|
|
|
DirectConnectWindow::~DirectConnectWindow() = default;
|
|
|
|
void DirectConnectWindow::RetranslateUi() {
|
|
ui->retranslateUi(this);
|
|
}
|
|
|
|
void DirectConnectWindow::Connect() {
|
|
if (!Network::GetSelectedNetworkInterface()) {
|
|
NetworkMessage::ErrorManager::ShowError(
|
|
NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED);
|
|
return;
|
|
}
|
|
if (!ui->nickname->hasAcceptableInput()) {
|
|
NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::USERNAME_NOT_VALID);
|
|
return;
|
|
}
|
|
if (system.IsPoweredOn()) {
|
|
if (!NetworkMessage::WarnGameRunning()) {
|
|
return;
|
|
}
|
|
}
|
|
if (const auto member = 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;
|
|
}
|
|
}
|
|
}
|
|
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
|
|
UISettings::values.multiplayer_nickname = ui->nickname->text().toStdString();
|
|
UISettings::values.multiplayer_ip = ui->ip->text().toStdString();
|
|
if (!ui->port->text().isEmpty()) {
|
|
UISettings::values.multiplayer_port = ui->port->text().toInt();
|
|
} else {
|
|
UISettings::values.multiplayer_port = UISettings::values.multiplayer_port.GetDefault();
|
|
}
|
|
|
|
emit SaveConfig();
|
|
|
|
// attempt to connect in a different thread
|
|
QFuture<void> f = QtConcurrent::run([&] {
|
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
|
auto port = UISettings::values.multiplayer_port.GetValue();
|
|
room_member->Join(ui->nickname->text().toStdString(),
|
|
ui->ip->text().toStdString().c_str(), port, 0, Network::NoPreferredIP,
|
|
ui->password->text().toStdString().c_str());
|
|
}
|
|
});
|
|
watcher->setFuture(f);
|
|
// and disable widgets and display a connecting while we wait
|
|
BeginConnecting();
|
|
}
|
|
|
|
void DirectConnectWindow::BeginConnecting() {
|
|
ui->connect->setEnabled(false);
|
|
ui->connect->setText(tr("Connecting"));
|
|
}
|
|
|
|
void DirectConnectWindow::EndConnecting() {
|
|
ui->connect->setEnabled(true);
|
|
ui->connect->setText(tr("Connect"));
|
|
}
|
|
|
|
void DirectConnectWindow::OnConnection() {
|
|
EndConnecting();
|
|
|
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
|
if (room_member->IsConnected()) {
|
|
close();
|
|
}
|
|
}
|
|
}
|