1
Fork 0
mirror of https://github.com/redstrate/Astra.git synced 2025-04-20 11:47:46 +00:00
astra/src/xivlauncher.cpp

262 lines
9.2 KiB
C++
Raw Normal View History

2021-11-01 09:54:58 -04:00
#include <QPushButton>
#include <QProcess>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrlQuery>
#include <QDir>
#include <QFormLayout>
#include <QLineEdit>
#include <QRegularExpression>
#include <QComboBox>
#include <QJsonObject>
#include <QJsonDocument>
#include <QCheckBox>
#include <keychain.h>
#include <QMessageBox>
2021-11-01 13:14:00 -04:00
#include <QMenuBar>
2021-11-01 09:54:58 -04:00
#include "xivlauncher.h"
#include "sapphirelauncher.h"
#include "squarelauncher.h"
#include "squareboot.h"
2021-11-01 13:14:00 -04:00
#include "settingswindow.h"
2021-11-01 09:54:58 -04:00
void LauncherWindow::setSSL(QNetworkRequest& request) {
QSslConfiguration config;
config.setProtocol(QSsl::AnyProtocol);
config.setPeerVerifyMode(QSslSocket::VerifyNone);
request.setSslConfiguration(config);
}
void LauncherWindow::buildRequest(QNetworkRequest& request) {
setSSL(request);
request.setHeader(QNetworkRequest::UserAgentHeader,
QString("SQEXAuthor/2.0.0(Windows 6.2; ja-jp; %1)").arg(QSysInfo::bootUniqueId()));
request.setRawHeader("Accept",
"image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*");
request.setRawHeader("Accept-Encoding", "gzip, deflate");
request.setRawHeader("Accept-Language", "en-us");
}
void LauncherWindow::launch(const LoginAuth auth) {
auto process = new QProcess(this);
process->setProcessChannelMode(QProcess::ForwardedChannels);
bool isWine = false;
QString winePath;
QString ffxivPath;
#if defined(Q_OS_WIN)
ffxivPath = gamePath + "\\game\\ffxiv_dx11.exe";
#endif
#if defined(Q_OS_MACOS)
isWine = true;
// TODO: this is assuming FFXIV is installed in /Applications
winePath = "/Applications/FINAL FANTASY XIV ONLINE.app/Contents/SharedSupport/finalfantasyxiv/FINAL FANTASY XIV ONLINE/wine";
ffxivPath = QDir::homePath() + "/Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn/game/ffxiv_dx11.exe";
#endif
#if defined(Q_OS_LINUX)
isWine = true;
// TODO: this is assuming you want to use the wine in your PATH, which isn't always the case
winePath = "wine";
// TODO: this is assuming it's in your default WINEPREFIX
ffxivPath = gamePath + "/game/ffxiv_dx11.exe";
process->setWorkingDirectory(gamePath + "/game/");
#endif
QList<QString> arguments;
if (isWine) {
arguments.push_back(ffxivPath);
}
// i wonder what these mean...
arguments.push_back("DEV.DataPathType=1");
arguments.push_back("DEV.UseSqPack=1");
// by the way, it looks like setting graphics options is possible via these too, i wonder what
// else is hiding :-)))
arguments.push_back(QString("DEV.MaxEntitledExpansionID=%1").arg(auth.maxExpansion));
arguments.push_back(QString("DEV.TestSID=%1").arg(auth.SID));
arguments.push_back(QString("SYS.Region=%1").arg(auth.region));
arguments.push_back(QString("language=%1").arg(language));
arguments.push_back(QString("ver=%1").arg(gameVersion));
if(!auth.lobbyhost.isEmpty()) {
arguments.push_back(QString("DEV.GMServerHost=%1").arg(auth.frontierHost));
for(int i = 1; i < 9; i++)
arguments.push_back(QString("DEV.LobbyHost0%1=%2 DEV.LobbyPort0%1=54994").arg(QString::number(i), auth.lobbyhost));
}
if (isWine) {
2021-11-01 13:14:00 -04:00
QStringList env = QProcess::systemEnvironment();
//env << "DXVK_FILTER_DEVICE_NAME=AMD";
process->setEnvironment(env);
2021-11-01 09:54:58 -04:00
process->start(winePath, arguments);
} else {
process->start(ffxivPath, arguments);
}
}
QString LauncherWindow::readVersion(QString path) {
QFile file(path);
file.open(QFile::OpenModeFlag::ReadOnly);
return file.readAll();
}
void LauncherWindow::readInitialInformation() {
#if defined(Q_OS_WIN)
gamePath = "C:\\Program Files (x86\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn";
#endif
#if defined(Q_OS_MACOS)
gamePath = QDir::homePath() + "/Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn";
#endif
#if defined(Q_OS_LINUX)
// TODO: this is assuming it's in your default WINEPREFIX
gamePath = QDir::homePath() + "/.wine/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn";
#endif
bootVersion = readVersion(gamePath + "/boot/ffxivboot.ver");
gameVersion = readVersion(gamePath + "/game/ffxivgame.ver");
}
LauncherWindow::LauncherWindow(QWidget* parent) :
QMainWindow(parent) {
mgr = new QNetworkAccessManager();
sapphireLauncher = new SapphireLauncher(*this);
squareLauncher = new SquareLauncher(*this);
squareBoot = new SquareBoot(*this, *squareLauncher);
2021-11-01 13:14:00 -04:00
QMenu* fileMenu = menuBar()->addMenu("File");
QAction* settingsAction = fileMenu->addAction("Settings...");
connect(settingsAction, &QAction::triggered, [=] {
auto window = new SettingsWindow(*this);
window->show();
});
2021-11-01 09:54:58 -04:00
const auto savedServerType = settings.value("serverType", 0).toInt();
const auto savedLobbyURL = settings.value("lobbyURL", "127.0.0.1").toString();
const auto shouldRememberUsername = settings.value("rememberUsername", false).toBool();
const auto shouldRememberPassword = settings.value("rememberPassword", false).toBool();
auto layout = new QFormLayout();
auto serverType = new QComboBox();
serverType->insertItem(0, "Square Enix");
serverType->insertItem(1, "Sapphire");
serverType->setCurrentIndex(savedServerType);
layout->addRow("Server Lobby", serverType);
auto lobbyServerURL = new QLineEdit();
lobbyServerURL->setText(savedLobbyURL);
layout->addRow("Lobby URL", lobbyServerURL);
auto usernameEdit = new QLineEdit();
layout->addRow("Username", usernameEdit);
if(shouldRememberUsername) {
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
job->setKey("username");
job->start();
connect(job, &QKeychain::ReadPasswordJob::finished, [=](QKeychain::Job* j) {
usernameEdit->setText(job->textData());
});
}
auto rememberUsernameBox = new QCheckBox();
rememberUsernameBox->setChecked(shouldRememberUsername);
layout->addRow("Remember Username?", rememberUsernameBox);
auto passwordEdit = new QLineEdit();
passwordEdit->setEchoMode(QLineEdit::EchoMode::Password);
layout->addRow("Password", passwordEdit);
if(shouldRememberPassword) {
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
job->setKey("password");
job->start();
connect(job, &QKeychain::ReadPasswordJob::finished, [=](QKeychain::Job* j) {
passwordEdit->setText(job->textData());
});
}
auto rememberPasswordBox = new QCheckBox();
rememberPasswordBox->setChecked(shouldRememberPassword);
layout->addRow("Remember Password?", rememberPasswordBox);
auto otpEdit = new QLineEdit();
layout->addRow("One-Time Password", otpEdit);
auto loginButton = new QPushButton("Login");
layout->addRow(loginButton);
auto registerButton = new QPushButton("Register");
layout->addRow(registerButton);
const auto refreshControls = [=](int index) {
lobbyServerURL->setEnabled(index == 1);
registerButton->setEnabled(index == 1);
otpEdit->setEnabled(index == 0);
};
refreshControls(serverType->currentIndex());
connect(serverType, &QComboBox::currentIndexChanged, [=](int index) {
refreshControls(index);
});
auto emptyWidget = new QWidget();
emptyWidget->setLayout(layout);
setCentralWidget(emptyWidget);
readInitialInformation();
connect(loginButton, &QPushButton::released, [=] {
auto info = LoginInformation{usernameEdit->text(), passwordEdit->text(), otpEdit->text()};
settings.setValue("rememberUsername", rememberUsernameBox->checkState() == Qt::CheckState::Checked);
if(rememberUsernameBox->checkState() == Qt::CheckState::Checked) {
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
job->setTextData(usernameEdit->text());
job->setKey("username");
job->start();
}
settings.setValue("rememberPassword", rememberPasswordBox->checkState() == Qt::CheckState::Checked);
if(rememberPasswordBox->checkState() == Qt::CheckState::Checked) {
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
job->setTextData(passwordEdit->text());
job->setKey("password");
job->start();
}
settings.setValue("serverType", serverType->currentIndex());
settings.setValue("lobbyURL", lobbyServerURL->text());
if(serverType->currentIndex() == 0) {
// begin se's booting process
squareBoot->bootCheck(info);
} else {
sapphireLauncher->login(lobbyServerURL->text(), info);
}
});
connect(registerButton, &QPushButton::released, [=] {
if(serverType->currentIndex() == 1) {
auto info = LoginInformation{usernameEdit->text(), passwordEdit->text(), otpEdit->text()};
sapphireLauncher->registerAccount(lobbyServerURL->text(), info);
}
});
}
LauncherWindow::~LauncherWindow() = default;