mirror of
https://github.com/redstrate/Astra.git
synced 2025-04-20 11:47:46 +00:00
Separate main launcher core and launcher window, add basic command line support
This commit is contained in:
parent
6d03631b66
commit
9bd6e9c977
16 changed files with 364 additions and 328 deletions
|
@ -12,12 +12,16 @@ add_subdirectory(external)
|
|||
|
||||
add_executable(xivlauncher
|
||||
src/main.cpp
|
||||
src/xivlauncher.cpp
|
||||
src/launchercore.cpp
|
||||
src/sapphirelauncher.cpp
|
||||
src/squareboot.cpp
|
||||
src/squarelauncher.cpp
|
||||
src/settingswindow.cpp
|
||||
src/blowfish.cpp src/assetupdater.cpp src/assetupdater.h)
|
||||
src/blowfish.cpp
|
||||
src/assetupdater.cpp
|
||||
src/assetupdater.h
|
||||
src/launcherwindow.cpp
|
||||
src/launcherwindow.h)
|
||||
|
||||
target_link_libraries(xivlauncher Qt5::Core Qt5::Widgets Qt5::Network qt5keychain QuaZip)
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <quazip/JlCompress.h>
|
||||
|
||||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
|
||||
const QString dalamudRemotePath = "https://goatcorp.github.io/dalamud-distrib/";
|
||||
const QString dalamudVersion = "latest";
|
||||
|
@ -14,19 +14,19 @@ const QString dalamudVersion = "latest";
|
|||
const QString nativeLauncherRemotePath = "https://github.com/redstrate/nativelauncher/releases/download/";
|
||||
const QString nativeLauncherVersion = "v1.0.0";
|
||||
|
||||
AssetUpdater::AssetUpdater(LauncherWindow &launcher) : launcher(launcher) {
|
||||
AssetUpdater::AssetUpdater(LauncherCore &launcher) : launcher(launcher) {
|
||||
connect(launcher.mgr, &QNetworkAccessManager::finished, this, &AssetUpdater::finishDownload);
|
||||
|
||||
launcher.mgr->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
}
|
||||
|
||||
void AssetUpdater::update() {
|
||||
void AssetUpdater::update(const ProfileSettings& profile) {
|
||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
|
||||
const bool hasDalamud = QFile::exists(dataDir + "/NativeLauncher.exe") && QFile::exists(dataDir + "/Dalamud");
|
||||
|
||||
// first we determine if we need dalamud
|
||||
const bool needsDalamud = launcher.currentProfile().enableDalamud && !hasDalamud;
|
||||
const bool needsDalamud = profile.enableDalamud && !hasDalamud;
|
||||
if(needsDalamud) {
|
||||
// download nativelauncher release (needed to launch the game with fixed ACLs)
|
||||
{
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
#include <QObject>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
class LauncherWindow;
|
||||
class LauncherCore;
|
||||
class QNetworkReply;
|
||||
struct ProfileSettings;
|
||||
|
||||
class AssetUpdater : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AssetUpdater(LauncherWindow& launcher);
|
||||
AssetUpdater(LauncherCore& launcher);
|
||||
|
||||
void update();
|
||||
void update(const ProfileSettings& profile);
|
||||
void finishDownload(QNetworkReply* reply);
|
||||
void beginInstall();
|
||||
|
||||
|
@ -19,7 +20,7 @@ signals:
|
|||
void finishedUpdating();
|
||||
|
||||
private:
|
||||
LauncherWindow& launcher;
|
||||
LauncherCore& launcher;
|
||||
|
||||
QTemporaryDir tempDir;
|
||||
};
|
|
@ -27,7 +27,7 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
#include "sapphirelauncher.h"
|
||||
#include "squarelauncher.h"
|
||||
#include "squareboot.h"
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include "blowfish.h"
|
||||
#include "assetupdater.h"
|
||||
|
||||
void LauncherWindow::setSSL(QNetworkRequest& request) {
|
||||
void LauncherCore::setSSL(QNetworkRequest& request) {
|
||||
QSslConfiguration config;
|
||||
config.setProtocol(QSsl::AnyProtocol);
|
||||
config.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
|
@ -43,7 +43,7 @@ void LauncherWindow::setSSL(QNetworkRequest& request) {
|
|||
request.setSslConfiguration(config);
|
||||
}
|
||||
|
||||
void LauncherWindow::buildRequest(QNetworkRequest& request) {
|
||||
void LauncherCore::buildRequest(QNetworkRequest& request) {
|
||||
setSSL(request);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,
|
||||
QString("SQEXAuthor/2.0.0(Windows 6.2; ja-jp; %1)").arg(QString(QSysInfo::bootUniqueId())));
|
||||
|
@ -106,20 +106,20 @@ QString encryptGameArg(QString arg) {
|
|||
return QString("//**sqex0003%1%2**//").arg(base64, QString(checksum));
|
||||
}
|
||||
|
||||
void LauncherWindow::launchGame(const LoginAuth auth) {
|
||||
void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth auth) {
|
||||
QList<QString> arguments;
|
||||
|
||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
|
||||
if(currentProfile().enableDalamud) {
|
||||
if(profile.enableDalamud) {
|
||||
arguments.push_back(dataDir + "/NativeLauncher.exe");
|
||||
}
|
||||
|
||||
// now for the actual game...
|
||||
if(currentProfile().useDX9) {
|
||||
arguments.push_back(currentProfile().gamePath + "\\game\\ffxiv.exe");
|
||||
if(profile.useDX9) {
|
||||
arguments.push_back(profile.gamePath + "\\game\\ffxiv.exe");
|
||||
} else {
|
||||
arguments.push_back(currentProfile().gamePath + "\\game\\ffxiv_dx11.exe");
|
||||
arguments.push_back(profile.gamePath + "\\game\\ffxiv_dx11.exe");
|
||||
}
|
||||
|
||||
struct Argument {
|
||||
|
@ -133,8 +133,8 @@ void LauncherWindow::launchGame(const LoginAuth auth) {
|
|||
gameArgs.push_back({"DEV.MaxEntitledExpansionID", QString::number(auth.maxExpansion)});
|
||||
gameArgs.push_back({"DEV.TestSID", auth.SID});
|
||||
gameArgs.push_back({"SYS.Region", QString::number(auth.region)});
|
||||
gameArgs.push_back({"language", QString::number(currentProfile().language)});
|
||||
gameArgs.push_back({"ver", currentProfile().gameVersion});
|
||||
gameArgs.push_back({"language", QString::number(profile.language)});
|
||||
gameArgs.push_back({"ver", profile.gameVersion});
|
||||
|
||||
if(!auth.lobbyhost.isEmpty()) {
|
||||
gameArgs.push_back({"DEV.GMServerHost", auth.frontierHost});
|
||||
|
@ -146,8 +146,8 @@ void LauncherWindow::launchGame(const LoginAuth auth) {
|
|||
|
||||
auto gameProcess = new QProcess(this);
|
||||
|
||||
if(currentProfile().enableDalamud) {
|
||||
connect(gameProcess, &QProcess::readyReadStandardOutput, [this, gameProcess] {
|
||||
if(profile.enableDalamud) {
|
||||
connect(gameProcess, &QProcess::readyReadStandardOutput, [this, gameProcess, profile] {
|
||||
QString output = gameProcess->readAllStandardOutput();
|
||||
|
||||
auto dalamudProcess = new QProcess();
|
||||
|
@ -162,11 +162,11 @@ void LauncherWindow::launchGame(const LoginAuth auth) {
|
|||
|
||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
|
||||
dalamudProcess->start(currentProfile().winePath, {dataDir + "/Dalamud/" + "Dalamud.Injector.exe", output});
|
||||
dalamudProcess->start(profile.winePath, {dataDir + "/Dalamud/" + "Dalamud.Injector.exe", output});
|
||||
});
|
||||
}
|
||||
|
||||
if(currentProfile().encryptArguments) {
|
||||
if(profile.encryptArguments) {
|
||||
QString argJoined;
|
||||
for(auto arg : gameArgs) {
|
||||
argJoined += QString(" /%1 =%2").arg(arg.key, arg.value);
|
||||
|
@ -174,47 +174,46 @@ void LauncherWindow::launchGame(const LoginAuth auth) {
|
|||
|
||||
auto earg = encryptGameArg(argJoined);
|
||||
arguments.append(earg);
|
||||
launchExecutable(gameProcess, arguments);
|
||||
launchExecutable(profile, gameProcess, arguments);
|
||||
} else {
|
||||
for(auto arg : gameArgs) {
|
||||
arguments.push_back(QString(" %1=%2").arg(arg.key, arg.value));
|
||||
}
|
||||
|
||||
launchExecutable(gameProcess, arguments);
|
||||
launchExecutable(profile, gameProcess, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherWindow::launchExecutable(const QStringList args) {
|
||||
void LauncherCore::launchExecutable(const ProfileSettings& profile, const QStringList args) {
|
||||
auto process = new QProcess(this);
|
||||
launchExecutable(process, args);
|
||||
launchExecutable(profile, process, args);
|
||||
}
|
||||
|
||||
void LauncherWindow::launchExecutable(QProcess* process, const QStringList args) {
|
||||
void LauncherCore::launchExecutable(const ProfileSettings& profile, QProcess* process, const QStringList args) {
|
||||
QList<QString> arguments;
|
||||
QStringList env = QProcess::systemEnvironment();
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
if(currentProfile().useGamescope) {
|
||||
if(profile.useGamescope) {
|
||||
arguments.push_back("gamescope");
|
||||
arguments.push_back("-f");
|
||||
arguments.push_back("-b");
|
||||
}
|
||||
|
||||
if(currentProfile().useGamemode)
|
||||
if(profile.useGamemode)
|
||||
arguments.push_back("gamemoderun");
|
||||
|
||||
if(currentProfile().useEsync) {
|
||||
if(profile.useEsync)
|
||||
env << "WINEESYNC=1";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
|
||||
env << "WINEPREFIX=" + currentProfile().winePrefixPath;
|
||||
env << "WINEPREFIX=" + profile.winePrefixPath;
|
||||
|
||||
if(currentProfile().enableDXVKhud)
|
||||
if(profile.enableDXVKhud)
|
||||
env << "DXVK_HUD=full";
|
||||
|
||||
arguments.push_back(currentProfile().winePath);
|
||||
arguments.push_back(profile.winePath);
|
||||
#endif
|
||||
|
||||
arguments.append(args);
|
||||
|
@ -222,20 +221,20 @@ void LauncherWindow::launchExecutable(QProcess* process, const QStringList args)
|
|||
auto executable = arguments[0];
|
||||
arguments.removeFirst();
|
||||
|
||||
process->setWorkingDirectory(currentProfile().gamePath + "/game/");
|
||||
process->setWorkingDirectory(profile.gamePath + "/game/");
|
||||
process->setEnvironment(env);
|
||||
|
||||
process->start(executable, arguments);
|
||||
}
|
||||
|
||||
QString LauncherWindow::readVersion(QString path) {
|
||||
QString LauncherCore::readVersion(QString path) {
|
||||
QFile file(path);
|
||||
file.open(QFile::OpenModeFlag::ReadOnly);
|
||||
|
||||
return file.readAll();
|
||||
}
|
||||
|
||||
void LauncherWindow::readInitialInformation() {
|
||||
void LauncherCore::readInitialInformation() {
|
||||
defaultProfileIndex = settings.value("defaultProfile", 0).toInt();
|
||||
|
||||
auto profiles = settings.childGroups();
|
||||
|
@ -312,7 +311,7 @@ void LauncherWindow::readInitialInformation() {
|
|||
readGameVersion();
|
||||
}
|
||||
|
||||
void LauncherWindow::readWineInfo(ProfileSettings& profile) {
|
||||
void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
||||
#if defined(Q_OS_MAC)
|
||||
switch(profile.wineVersion) {
|
||||
case 0: // system wine
|
||||
|
@ -339,15 +338,14 @@ void LauncherWindow::readWineInfo(ProfileSettings& profile) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void LauncherWindow::readGameVersion() {
|
||||
void LauncherCore::readGameVersion() {
|
||||
for(auto& profile : profileSettings) {
|
||||
profile.bootVersion = readVersion(profile.gamePath + "/boot/ffxivboot.ver");
|
||||
profile.gameVersion = readVersion(profile.gamePath + "/game/ffxivgame.ver");
|
||||
}
|
||||
}
|
||||
|
||||
LauncherWindow::LauncherWindow(QWidget* parent) :
|
||||
QMainWindow(parent), settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::applicationName()) {
|
||||
LauncherCore::LauncherCore() : settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::applicationName()) {
|
||||
mgr = new QNetworkAccessManager();
|
||||
sapphireLauncher = new SapphireLauncher(*this);
|
||||
squareLauncher = new SquareLauncher(*this);
|
||||
|
@ -355,152 +353,17 @@ LauncherWindow::LauncherWindow(QWidget* parent) :
|
|||
assetUpdater = new AssetUpdater(*this);
|
||||
|
||||
readInitialInformation();
|
||||
|
||||
QMenu* fileMenu = menuBar()->addMenu("File");
|
||||
// sorry linux users, for some reason my global menu does not like qt6 apps right now
|
||||
#if defined(Q_OS_LINUX)
|
||||
menuBar()->setNativeMenuBar(false);
|
||||
#endif
|
||||
|
||||
QAction* settingsAction = fileMenu->addAction("Settings...");
|
||||
connect(settingsAction, &QAction::triggered, [=] {
|
||||
auto window = new SettingsWindow(*this);
|
||||
connect(this, &LauncherWindow::settingsChanged, window, &SettingsWindow::reloadControls);
|
||||
window->show();
|
||||
});
|
||||
|
||||
QMenu* toolsMenu = menuBar()->addMenu("Tools");
|
||||
|
||||
QAction* launchOfficial = toolsMenu->addAction("Launch Official Client...");
|
||||
connect(launchOfficial, &QAction::triggered, [=] {
|
||||
launchExecutable({currentProfile().gamePath + "/boot/ffxivboot64.exe"});
|
||||
});
|
||||
|
||||
QAction* launchSysInfo = toolsMenu->addAction("Launch System Info...");
|
||||
connect(launchSysInfo, &QAction::triggered, [=] {
|
||||
launchExecutable({currentProfile().gamePath + "/boot/ffxivsysinfo64.exe"});
|
||||
});
|
||||
|
||||
QAction* launchCfgBackup = toolsMenu->addAction("Launch Config Backup...");
|
||||
connect(launchCfgBackup, &QAction::triggered, [=] {
|
||||
launchExecutable({currentProfile().gamePath + "/boot/ffxivconfig64.exe"});
|
||||
});
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
|
||||
QMenu* wineMenu = toolsMenu->addMenu("Wine");
|
||||
|
||||
QAction* wineCfg = wineMenu->addAction("winecfg");
|
||||
connect(wineCfg, &QAction::triggered, [=] {
|
||||
launchExecutable({"winecfg.exe"});
|
||||
});
|
||||
|
||||
QAction* controlPanel = wineMenu->addAction("Control Panel");
|
||||
connect(controlPanel, &QAction::triggered, [=] {
|
||||
launchExecutable({"control.exe"});
|
||||
});
|
||||
#endif
|
||||
|
||||
auto layout = new QFormLayout();
|
||||
|
||||
profileSelect = new QComboBox();
|
||||
connect(profileSelect, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
reloadControls();
|
||||
});
|
||||
|
||||
layout->addRow("Profile", profileSelect);
|
||||
|
||||
usernameEdit = new QLineEdit();
|
||||
layout->addRow("Username", usernameEdit);
|
||||
|
||||
rememberUsernameBox = new QCheckBox();
|
||||
connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) {
|
||||
currentProfile().rememberUsername = rememberUsernameBox->isChecked();
|
||||
saveSettings();
|
||||
});
|
||||
layout->addRow("Remember Username?", rememberUsernameBox);
|
||||
|
||||
passwordEdit = new QLineEdit();
|
||||
passwordEdit->setEchoMode(QLineEdit::EchoMode::Password);
|
||||
layout->addRow("Password", passwordEdit);
|
||||
|
||||
rememberPasswordBox = new QCheckBox();
|
||||
connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) {
|
||||
currentProfile().rememberPassword = rememberPasswordBox->isChecked();
|
||||
saveSettings();
|
||||
});
|
||||
layout->addRow("Remember Password?", rememberPasswordBox);
|
||||
|
||||
otpEdit = new QLineEdit();
|
||||
layout->addRow("One-Time Password", otpEdit);
|
||||
|
||||
auto loginButton = new QPushButton("Login");
|
||||
layout->addRow(loginButton);
|
||||
|
||||
registerButton = new QPushButton("Register");
|
||||
layout->addRow(registerButton);
|
||||
|
||||
auto emptyWidget = new QWidget();
|
||||
emptyWidget->setLayout(layout);
|
||||
setCentralWidget(emptyWidget);
|
||||
|
||||
connect(assetUpdater, &AssetUpdater::finishedUpdating, [=] {
|
||||
auto info = LoginInformation{usernameEdit->text(), passwordEdit->text(), otpEdit->text()};
|
||||
|
||||
if(currentProfile().rememberUsername) {
|
||||
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
||||
job->setTextData(usernameEdit->text());
|
||||
job->setKey(currentProfile().name + "-username");
|
||||
job->start();
|
||||
}
|
||||
|
||||
if(currentProfile().rememberPassword) {
|
||||
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
||||
job->setTextData(passwordEdit->text());
|
||||
job->setKey(currentProfile().name + "-password");
|
||||
job->start();
|
||||
}
|
||||
|
||||
if(currentProfile().isSapphire) {
|
||||
sapphireLauncher->login(currentProfile().lobbyURL, info);
|
||||
} else {
|
||||
squareBoot->bootCheck(info);
|
||||
}
|
||||
});
|
||||
|
||||
connect(loginButton, &QPushButton::released, [=] {
|
||||
// update the assets first if needed, then it calls the slot above :-)
|
||||
assetUpdater->update();
|
||||
});
|
||||
|
||||
connect(registerButton, &QPushButton::released, [=] {
|
||||
if(currentProfile().isSapphire) {
|
||||
auto info = LoginInformation{usernameEdit->text(), passwordEdit->text(), otpEdit->text()};
|
||||
sapphireLauncher->registerAccount(currentProfile().lobbyURL, info);
|
||||
}
|
||||
});
|
||||
|
||||
reloadControls();
|
||||
}
|
||||
|
||||
LauncherWindow::~LauncherWindow() = default;
|
||||
|
||||
ProfileSettings LauncherWindow::currentProfile() const {
|
||||
return getProfile(profileSelect->currentIndex());
|
||||
}
|
||||
|
||||
ProfileSettings& LauncherWindow::currentProfile() {
|
||||
return getProfile(profileSelect->currentIndex());
|
||||
}
|
||||
|
||||
ProfileSettings LauncherWindow::getProfile(int index) const {
|
||||
ProfileSettings LauncherCore::getProfile(int index) const {
|
||||
return profileSettings[index];
|
||||
}
|
||||
|
||||
ProfileSettings& LauncherWindow::getProfile(int index) {
|
||||
ProfileSettings& LauncherCore::getProfile(int index) {
|
||||
return profileSettings[index];
|
||||
}
|
||||
|
||||
int LauncherWindow::getProfileIndex(QString name) {
|
||||
int LauncherCore::getProfileIndex(QString name) {
|
||||
for(int i = 0; i < profileSettings.size(); i++) {
|
||||
if(profileSettings[i].name == name)
|
||||
return i;
|
||||
|
@ -509,7 +372,7 @@ int LauncherWindow::getProfileIndex(QString name) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
QList<QString> LauncherWindow::profileList() const {
|
||||
QList<QString> LauncherCore::profileList() const {
|
||||
QList<QString> list;
|
||||
for(auto profile : profileSettings) {
|
||||
list.append(profile.name);
|
||||
|
@ -518,7 +381,7 @@ QList<QString> LauncherWindow::profileList() const {
|
|||
return list;
|
||||
}
|
||||
|
||||
int LauncherWindow::addProfile() {
|
||||
int LauncherCore::addProfile() {
|
||||
ProfileSettings newProfile;
|
||||
newProfile.uuid = QUuid::createUuid();
|
||||
newProfile.name = "New Profile";
|
||||
|
@ -530,7 +393,7 @@ int LauncherWindow::addProfile() {
|
|||
return profileSettings.size() - 1;
|
||||
}
|
||||
|
||||
int LauncherWindow::deleteProfile(QString name) {
|
||||
int LauncherCore::deleteProfile(QString name) {
|
||||
int index = 0;
|
||||
for(int i = 0; i < profileSettings.size(); i++) {
|
||||
if(profileSettings[i].name == name)
|
||||
|
@ -547,7 +410,7 @@ int LauncherWindow::deleteProfile(QString name) {
|
|||
return index - 1;
|
||||
}
|
||||
|
||||
void LauncherWindow::saveSettings() {
|
||||
void LauncherCore::saveSettings() {
|
||||
settings.setValue("defaultProfile", defaultProfileIndex);
|
||||
|
||||
for(int i = 0; i < profileSettings.size(); i++) {
|
||||
|
@ -583,51 +446,3 @@ void LauncherWindow::saveSettings() {
|
|||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherWindow::reloadControls() {
|
||||
if(currentlyReloadingControls)
|
||||
return;
|
||||
|
||||
currentlyReloadingControls = true;
|
||||
|
||||
const int oldIndex = profileSelect->currentIndex();
|
||||
|
||||
profileSelect->clear();
|
||||
|
||||
for(const auto& profile : profileList()) {
|
||||
profileSelect->addItem(profile);
|
||||
}
|
||||
|
||||
profileSelect->setCurrentIndex(oldIndex);
|
||||
|
||||
if(profileSelect->currentIndex() == -1) {
|
||||
profileSelect->setCurrentIndex(defaultProfileIndex);
|
||||
}
|
||||
|
||||
rememberUsernameBox->setChecked(currentProfile().rememberUsername);
|
||||
if(currentProfile().rememberUsername) {
|
||||
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
||||
job->setKey(currentProfile().name + "-username");
|
||||
job->start();
|
||||
|
||||
connect(job, &QKeychain::ReadPasswordJob::finished, [=](QKeychain::Job* j) {
|
||||
usernameEdit->setText(job->textData());
|
||||
});
|
||||
}
|
||||
|
||||
rememberPasswordBox->setChecked(currentProfile().rememberPassword);
|
||||
if(currentProfile().rememberPassword) {
|
||||
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
||||
job->setKey(currentProfile().name + "-password");
|
||||
job->start();
|
||||
|
||||
connect(job, &QKeychain::ReadPasswordJob::finished, [=](QKeychain::Job* j) {
|
||||
passwordEdit->setText(job->textData());
|
||||
});
|
||||
}
|
||||
|
||||
registerButton->setEnabled(currentProfile().isSapphire);
|
||||
otpEdit->setEnabled(!currentProfile().isSapphire);
|
||||
|
||||
currentlyReloadingControls = false;
|
||||
}
|
|
@ -4,9 +4,6 @@
|
|||
#include <QNetworkAccessManager>
|
||||
#include <QFuture>
|
||||
#include <QSettings>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
#include <QUuid>
|
||||
#include <QProcess>
|
||||
|
||||
|
@ -45,6 +42,8 @@ struct ProfileSettings {
|
|||
};
|
||||
|
||||
struct LoginInformation {
|
||||
ProfileSettings* settings = nullptr;
|
||||
|
||||
QString username, password, oneTimePassword;
|
||||
};
|
||||
|
||||
|
@ -57,18 +56,13 @@ struct LoginAuth {
|
|||
QString lobbyhost, frontierHost;
|
||||
};
|
||||
|
||||
class LauncherWindow : public QMainWindow {
|
||||
class LauncherCore : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LauncherWindow(QWidget* parent = nullptr);
|
||||
|
||||
~LauncherWindow() override;
|
||||
LauncherCore();
|
||||
|
||||
QNetworkAccessManager* mgr;
|
||||
|
||||
ProfileSettings currentProfile() const;
|
||||
ProfileSettings& currentProfile();
|
||||
|
||||
ProfileSettings getProfile(int index) const;
|
||||
ProfileSettings& getProfile(int index);
|
||||
|
||||
|
@ -77,9 +71,9 @@ public:
|
|||
int addProfile();
|
||||
int deleteProfile(QString name);
|
||||
|
||||
void launchGame(const LoginAuth auth);
|
||||
void launchExecutable(QStringList args);
|
||||
void launchExecutable(QProcess* process, QStringList args);
|
||||
void launchGame(const ProfileSettings& settings, const LoginAuth auth);
|
||||
void launchExecutable(const ProfileSettings& settings, QStringList args);
|
||||
void launchExecutable(const ProfileSettings& settings, QProcess* process, QStringList args);
|
||||
void buildRequest(QNetworkRequest& request);
|
||||
void setSSL(QNetworkRequest& request);
|
||||
QString readVersion(QString path);
|
||||
|
@ -90,26 +84,15 @@ public:
|
|||
|
||||
QSettings settings;
|
||||
|
||||
public slots:
|
||||
void reloadControls();
|
||||
|
||||
signals:
|
||||
void settingsChanged();
|
||||
|
||||
private:
|
||||
bool currentlyReloadingControls = false;
|
||||
|
||||
SapphireLauncher* sapphireLauncher;
|
||||
SquareBoot* squareBoot;
|
||||
SquareLauncher* squareLauncher;
|
||||
AssetUpdater* assetUpdater;
|
||||
|
||||
QComboBox* profileSelect;
|
||||
QLineEdit* usernameEdit, *passwordEdit;
|
||||
QLineEdit* otpEdit;
|
||||
QCheckBox* rememberUsernameBox, *rememberPasswordBox;
|
||||
QPushButton* registerButton;
|
||||
|
||||
QVector<ProfileSettings> profileSettings;
|
||||
int defaultProfileIndex = 0;
|
||||
signals:
|
||||
void settingsChanged();
|
||||
|
||||
private:
|
||||
QVector<ProfileSettings> profileSettings;
|
||||
};
|
192
src/launcherwindow.cpp
Normal file
192
src/launcherwindow.cpp
Normal file
|
@ -0,0 +1,192 @@
|
|||
#include "launcherwindow.h"
|
||||
|
||||
#include <QMenuBar>
|
||||
#include <keychain.h>
|
||||
#include <QFormLayout>
|
||||
|
||||
#include "settingswindow.h"
|
||||
#include "squareboot.h"
|
||||
#include "squarelauncher.h"
|
||||
#include "sapphirelauncher.h"
|
||||
#include "assetupdater.h"
|
||||
|
||||
LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindow(parent), core(core) {
|
||||
connect(&core, &LauncherCore::settingsChanged, this, &LauncherWindow::reloadControls);
|
||||
|
||||
QMenu* fileMenu = menuBar()->addMenu("File");
|
||||
|
||||
QAction* settingsAction = fileMenu->addAction("Settings...");
|
||||
connect(settingsAction, &QAction::triggered, [=] {
|
||||
auto window = new SettingsWindow(*this, this->core);
|
||||
connect(&this->core, &LauncherCore::settingsChanged, window, &SettingsWindow::reloadControls);
|
||||
window->show();
|
||||
});
|
||||
|
||||
QMenu* toolsMenu = menuBar()->addMenu("Tools");
|
||||
|
||||
QAction* launchOfficial = toolsMenu->addAction("Launch Official Client...");
|
||||
connect(launchOfficial, &QAction::triggered, [=] {
|
||||
this->core.launchExecutable(currentProfile(), {currentProfile().gamePath + "/boot/ffxivboot64.exe"});
|
||||
});
|
||||
|
||||
QAction* launchSysInfo = toolsMenu->addAction("Launch System Info...");
|
||||
connect(launchSysInfo, &QAction::triggered, [=] {
|
||||
this->core.launchExecutable(currentProfile(), {currentProfile().gamePath + "/boot/ffxivsysinfo64.exe"});
|
||||
});
|
||||
|
||||
QAction* launchCfgBackup = toolsMenu->addAction("Launch Config Backup...");
|
||||
connect(launchCfgBackup, &QAction::triggered, [=] {
|
||||
this->core.launchExecutable(currentProfile(), {currentProfile().gamePath + "/boot/ffxivconfig64.exe"});
|
||||
});
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
|
||||
QMenu* wineMenu = toolsMenu->addMenu("Wine");
|
||||
|
||||
QAction* wineCfg = wineMenu->addAction("winecfg");
|
||||
connect(wineCfg, &QAction::triggered, [=] {
|
||||
this->core.launchExecutable(currentProfile(), {"winecfg.exe"});
|
||||
});
|
||||
|
||||
QAction* controlPanel = wineMenu->addAction("Control Panel");
|
||||
connect(controlPanel, &QAction::triggered, [=] {
|
||||
this->core.launchExecutable(currentProfile(), {"control.exe"});
|
||||
});
|
||||
#endif
|
||||
|
||||
auto layout = new QFormLayout();
|
||||
|
||||
profileSelect = new QComboBox();
|
||||
connect(profileSelect, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
reloadControls();
|
||||
});
|
||||
|
||||
layout->addRow("Profile", profileSelect);
|
||||
|
||||
usernameEdit = new QLineEdit();
|
||||
layout->addRow("Username", usernameEdit);
|
||||
|
||||
rememberUsernameBox = new QCheckBox();
|
||||
connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) {
|
||||
currentProfile().rememberUsername = rememberUsernameBox->isChecked();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
layout->addRow("Remember Username?", rememberUsernameBox);
|
||||
|
||||
passwordEdit = new QLineEdit();
|
||||
passwordEdit->setEchoMode(QLineEdit::EchoMode::Password);
|
||||
layout->addRow("Password", passwordEdit);
|
||||
|
||||
rememberPasswordBox = new QCheckBox();
|
||||
connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) {
|
||||
currentProfile().rememberPassword = rememberPasswordBox->isChecked();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
layout->addRow("Remember Password?", rememberPasswordBox);
|
||||
|
||||
otpEdit = new QLineEdit();
|
||||
layout->addRow("One-Time Password", otpEdit);
|
||||
|
||||
auto loginButton = new QPushButton("Login");
|
||||
layout->addRow(loginButton);
|
||||
|
||||
registerButton = new QPushButton("Register");
|
||||
layout->addRow(registerButton);
|
||||
|
||||
auto emptyWidget = new QWidget();
|
||||
emptyWidget->setLayout(layout);
|
||||
setCentralWidget(emptyWidget);
|
||||
|
||||
connect(core.assetUpdater, &AssetUpdater::finishedUpdating, [=] {
|
||||
auto info = LoginInformation{¤tProfile(), usernameEdit->text(), passwordEdit->text(), otpEdit->text()};
|
||||
|
||||
if(currentProfile().rememberUsername) {
|
||||
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
||||
job->setTextData(usernameEdit->text());
|
||||
job->setKey(currentProfile().name + "-username");
|
||||
job->start();
|
||||
}
|
||||
|
||||
if(currentProfile().rememberPassword) {
|
||||
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
||||
job->setTextData(passwordEdit->text());
|
||||
job->setKey(currentProfile().name + "-password");
|
||||
job->start();
|
||||
}
|
||||
|
||||
if(currentProfile().isSapphire) {
|
||||
this->core.sapphireLauncher->login(currentProfile().lobbyURL, info);
|
||||
} else {
|
||||
this->core.squareBoot->bootCheck(info);
|
||||
}
|
||||
});
|
||||
|
||||
connect(loginButton, &QPushButton::released, [=] {
|
||||
// update the assets first if needed, then it calls the slot above :-)
|
||||
this->core.assetUpdater->update(currentProfile());
|
||||
});
|
||||
|
||||
connect(registerButton, &QPushButton::released, [=] {
|
||||
if(currentProfile().isSapphire) {
|
||||
auto info = LoginInformation{¤tProfile(), usernameEdit->text(), passwordEdit->text(), otpEdit->text()};
|
||||
this->core.sapphireLauncher->registerAccount(currentProfile().lobbyURL, info);
|
||||
}
|
||||
});
|
||||
|
||||
reloadControls();
|
||||
}
|
||||
|
||||
ProfileSettings LauncherWindow::currentProfile() const {
|
||||
return core.getProfile(profileSelect->currentIndex());
|
||||
}
|
||||
|
||||
ProfileSettings& LauncherWindow::currentProfile() {
|
||||
return core.getProfile(profileSelect->currentIndex());
|
||||
}
|
||||
|
||||
void LauncherWindow::reloadControls() {
|
||||
if(currentlyReloadingControls)
|
||||
return;
|
||||
|
||||
currentlyReloadingControls = true;
|
||||
|
||||
const int oldIndex = profileSelect->currentIndex();
|
||||
|
||||
profileSelect->clear();
|
||||
|
||||
for(const auto& profile : core.profileList()) {
|
||||
profileSelect->addItem(profile);
|
||||
}
|
||||
|
||||
profileSelect->setCurrentIndex(oldIndex);
|
||||
|
||||
if(profileSelect->currentIndex() == -1) {
|
||||
profileSelect->setCurrentIndex(core.defaultProfileIndex);
|
||||
}
|
||||
|
||||
rememberUsernameBox->setChecked(currentProfile().rememberUsername);
|
||||
if(currentProfile().rememberUsername) {
|
||||
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
||||
job->setKey(currentProfile().name + "-username");
|
||||
job->start();
|
||||
|
||||
connect(job, &QKeychain::ReadPasswordJob::finished, [=](QKeychain::Job* j) {
|
||||
usernameEdit->setText(job->textData());
|
||||
});
|
||||
}
|
||||
|
||||
rememberPasswordBox->setChecked(currentProfile().rememberPassword);
|
||||
if(currentProfile().rememberPassword) {
|
||||
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
||||
job->setKey(currentProfile().name + "-password");
|
||||
job->start();
|
||||
|
||||
connect(job, &QKeychain::ReadPasswordJob::finished, [=](QKeychain::Job* j) {
|
||||
passwordEdit->setText(job->textData());
|
||||
});
|
||||
}
|
||||
|
||||
registerButton->setEnabled(currentProfile().isSapphire);
|
||||
otpEdit->setEnabled(!currentProfile().isSapphire);
|
||||
|
||||
currentlyReloadingControls = false;
|
||||
}
|
31
src/launcherwindow.h
Normal file
31
src/launcherwindow.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "launchercore.h"
|
||||
|
||||
class LauncherWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LauncherWindow(LauncherCore& core, QWidget* parent = nullptr);
|
||||
|
||||
ProfileSettings currentProfile() const;
|
||||
ProfileSettings& currentProfile();
|
||||
|
||||
public slots:
|
||||
void reloadControls();
|
||||
|
||||
private:
|
||||
LauncherCore& core;
|
||||
|
||||
bool currentlyReloadingControls = false;
|
||||
|
||||
QComboBox* profileSelect;
|
||||
QLineEdit* usernameEdit, *passwordEdit;
|
||||
QLineEdit* otpEdit;
|
||||
QCheckBox* rememberUsernameBox, *rememberPasswordBox;
|
||||
QPushButton* registerButton;
|
||||
};
|
15
src/main.cpp
15
src/main.cpp
|
@ -1,5 +1,8 @@
|
|||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
#include "launcherwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
|
@ -13,7 +16,15 @@ int main(int argc, char* argv[]) {
|
|||
QCoreApplication::setApplicationName("xivlauncher-debug");
|
||||
#endif
|
||||
|
||||
LauncherWindow w;
|
||||
LauncherCore c;
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Cross-platform FFXIV Launcher");
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.process(app);
|
||||
|
||||
LauncherWindow w(c);
|
||||
w.show();
|
||||
|
||||
return app.exec();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QNetworkReply>
|
||||
|
||||
SapphireLauncher::SapphireLauncher(LauncherWindow& window) : window(window) {
|
||||
SapphireLauncher::SapphireLauncher(LauncherCore& window) : window(window) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ void SapphireLauncher::login(QString lobbyUrl, const LoginInformation& info) {
|
|||
auth.frontierHost = document["frontierHost"].toString();
|
||||
auth.region = 3;
|
||||
|
||||
window.launchGame(auth);
|
||||
window.launchGame(*info.settings, auth);
|
||||
} else {
|
||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Invalid username/password.");
|
||||
messageBox->show();
|
||||
|
@ -64,6 +64,6 @@ void SapphireLauncher::registerAccount(QString lobbyUrl, const LoginInformation&
|
|||
auth.frontierHost = document["frontierHost"].toString();
|
||||
auth.region = 3;
|
||||
|
||||
window.launchGame(auth);
|
||||
window.launchGame(*info.settings, auth);
|
||||
});
|
||||
}
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
#include <QString>
|
||||
|
||||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
|
||||
class SapphireLauncher : QObject {
|
||||
public:
|
||||
SapphireLauncher(LauncherWindow& window);
|
||||
SapphireLauncher(LauncherCore& window);
|
||||
|
||||
void login(QString lobbyUrl, const LoginInformation& info);
|
||||
void registerAccount(QString lobbyUrl, const LoginInformation& info);
|
||||
|
||||
private:
|
||||
LauncherWindow& window;
|
||||
LauncherCore& window;
|
||||
};
|
|
@ -11,9 +11,10 @@
|
|||
#include <QProcess>
|
||||
#include <QGridLayout>
|
||||
|
||||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
#include "launcherwindow.h"
|
||||
|
||||
SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window(window), QWidget(parent) {
|
||||
SettingsWindow::SettingsWindow(LauncherWindow& window, LauncherCore& core, QWidget* parent) : core(core), window(window), QWidget(parent) {
|
||||
setWindowTitle("Settings");
|
||||
setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||
|
||||
|
@ -30,17 +31,17 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
|
||||
auto addProfileButton = new QPushButton("Add Profile");
|
||||
connect(addProfileButton, &QPushButton::pressed, [=] {
|
||||
profileWidget->setCurrentRow(this->window.addProfile());
|
||||
profileWidget->setCurrentRow(this->core.addProfile());
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
mainLayout->addWidget(addProfileButton, 2, 0);
|
||||
|
||||
deleteProfileButton = new QPushButton("Delete Profile");
|
||||
connect(deleteProfileButton, &QPushButton::pressed, [=] {
|
||||
profileWidget->setCurrentRow(this->window.deleteProfile(getCurrentProfile().name));
|
||||
profileWidget->setCurrentRow(this->core.deleteProfile(getCurrentProfile().name));
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
mainLayout->addWidget(deleteProfileButton, 3, 0);
|
||||
|
||||
|
@ -49,7 +50,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
getCurrentProfile().name = nameEdit->text();
|
||||
|
||||
reloadControls();
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
mainLayout->addWidget(nameEdit, 0, 1);
|
||||
|
||||
|
@ -66,10 +67,10 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
|
||||
connect(directXCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
getCurrentProfile().useDX9 = directXCombo->currentIndex() == 1;
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
|
||||
currentGameDirectory = new QLabel(window.currentProfile().gamePath);
|
||||
currentGameDirectory = new QLabel();
|
||||
currentGameDirectory->setWordWrap(true);
|
||||
gameBoxLayout->addRow("Game Directory", currentGameDirectory);
|
||||
|
||||
|
@ -78,9 +79,9 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
getCurrentProfile().gamePath = QFileDialog::getExistingDirectory(this, "Open Game Directory");
|
||||
|
||||
this->reloadControls();
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
|
||||
this->window.readGameVersion();
|
||||
this->core.readGameVersion();
|
||||
});
|
||||
gameBoxLayout->addWidget(selectDirectoryButton);
|
||||
|
||||
|
@ -100,7 +101,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(encryptArgumentsBox, &QCheckBox::stateChanged, [=](int) {
|
||||
getCurrentProfile().encryptArguments = encryptArgumentsBox->isChecked();
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
loginBoxLayout->addRow("Encrypt Game Arguments", encryptArgumentsBox);
|
||||
|
||||
|
@ -108,7 +109,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(enableDalamudBox, &QCheckBox::stateChanged, [=](int) {
|
||||
getCurrentProfile().enableDalamud = enableDalamudBox->isChecked();
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
loginBoxLayout->addRow("Enable Dalamud Injection", enableDalamudBox);
|
||||
|
||||
|
@ -120,8 +121,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
getCurrentProfile().isSapphire = index == 1;
|
||||
|
||||
reloadControls();
|
||||
this->window.reloadControls();
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
|
||||
loginBoxLayout->addRow("Server Lobby", serverType);
|
||||
|
@ -129,7 +129,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
lobbyServerURL = new QLineEdit();
|
||||
connect(lobbyServerURL, &QLineEdit::editingFinished, [=] {
|
||||
getCurrentProfile().lobbyURL = lobbyServerURL->text();
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
loginBoxLayout->addRow("Lobby URL", lobbyServerURL);
|
||||
|
||||
|
@ -137,8 +137,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) {
|
||||
getCurrentProfile().rememberUsername = rememberUsernameBox->isChecked();
|
||||
|
||||
this->window.reloadControls();
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
loginBoxLayout->addRow("Remember Username?", rememberUsernameBox);
|
||||
|
||||
|
@ -146,8 +145,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) {
|
||||
getCurrentProfile().rememberPassword = rememberPasswordBox->isChecked();
|
||||
|
||||
this->window.reloadControls();
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
loginBoxLayout->addRow("Remember Password?", rememberPasswordBox);
|
||||
|
||||
|
@ -163,7 +161,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
infoLabel->setWordWrap(true);
|
||||
wineBoxLayout->addWidget(infoLabel);
|
||||
|
||||
winePathLabel = new QLabel(window.currentProfile().winePath);
|
||||
winePathLabel = new QLabel();
|
||||
winePathLabel->setWordWrap(true);
|
||||
wineBoxLayout->addRow("Wine Executable", winePathLabel);
|
||||
|
||||
|
@ -184,19 +182,19 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(wineVersionCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [this](int index) {
|
||||
getCurrentProfile().wineVersion = index;
|
||||
|
||||
this->window.readWineInfo(getCurrentProfile());
|
||||
this->window.saveSettings();
|
||||
this->core.readWineInfo(getCurrentProfile());
|
||||
this->core.saveSettings();
|
||||
this->reloadControls();
|
||||
});
|
||||
|
||||
connect(selectWineButton, &QPushButton::pressed, [this] {
|
||||
getCurrentProfile().winePath = QFileDialog::getOpenFileName(this, "Open Wine Executable");
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
this->reloadControls();
|
||||
});
|
||||
|
||||
winePrefixDirectory = new QLabel(window.currentProfile().winePrefixPath);
|
||||
winePrefixDirectory = new QLabel();
|
||||
winePrefixDirectory->setWordWrap(true);
|
||||
wineBoxLayout->addRow("Wine Prefix", winePrefixDirectory);
|
||||
|
||||
|
@ -204,7 +202,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(selectPrefixButton, &QPushButton::pressed, [this] {
|
||||
getCurrentProfile().winePrefixPath = QFileDialog::getExistingDirectory(this, "Open Wine Prefix");
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
this->reloadControls();
|
||||
});
|
||||
wineBoxLayout->addWidget(selectPrefixButton);
|
||||
|
@ -216,12 +214,11 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
wineBoxLayout->addWidget(openPrefixButton);
|
||||
|
||||
auto enableDXVKhud = new QCheckBox("Enable DXVK HUD");
|
||||
enableDXVKhud->setChecked(window.currentProfile().enableDXVKhud);
|
||||
wineBoxLayout->addWidget(enableDXVKhud);
|
||||
|
||||
connect(enableDXVKhud, &QCheckBox::stateChanged, [this](int state) {
|
||||
this->window.currentProfile().enableDXVKhud = state;
|
||||
this->window.settings.setValue("enableDXVKhud", static_cast<bool>(state));
|
||||
getCurrentProfile().enableDXVKhud = state;
|
||||
this->core.settings.setValue("enableDXVKhud", static_cast<bool>(state));
|
||||
});
|
||||
#endif
|
||||
|
||||
|
@ -237,7 +234,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(useEsync, &QCheckBox::stateChanged, [this](int state) {
|
||||
getCurrentProfile().useEsync = state;
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
|
||||
useGamescope = new QCheckBox("Use Gamescope");
|
||||
|
@ -251,7 +248,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(useGamescope, &QCheckBox::stateChanged, [this](int state) {
|
||||
getCurrentProfile().useGamescope = state;
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
|
||||
useGamemode = new QCheckBox("Use Gamemode");
|
||||
|
@ -265,7 +262,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
|||
connect(useGamemode, &QCheckBox::stateChanged, [this](int state) {
|
||||
getCurrentProfile().useGamemode = state;
|
||||
|
||||
this->window.saveSettings();
|
||||
this->core.saveSettings();
|
||||
});
|
||||
#endif
|
||||
|
||||
|
@ -282,15 +279,15 @@ void SettingsWindow::reloadControls() {
|
|||
|
||||
profileWidget->clear();
|
||||
|
||||
for(auto profile : window.profileList()) {
|
||||
for(const auto& profile : core.profileList()) {
|
||||
profileWidget->addItem(profile);
|
||||
}
|
||||
profileWidget->setCurrentRow(oldRow);
|
||||
|
||||
// deleting the main profile is unsupported behavior
|
||||
deleteProfileButton->setEnabled(window.profileList().size() > 1);
|
||||
deleteProfileButton->setEnabled(core.profileList().size() > 1);
|
||||
|
||||
ProfileSettings& profile = window.getProfile(profileWidget->currentRow());
|
||||
ProfileSettings& profile = core.getProfile(profileWidget->currentRow());
|
||||
nameEdit->setText(profile.name);
|
||||
|
||||
// game
|
||||
|
@ -325,7 +322,7 @@ void SettingsWindow::reloadControls() {
|
|||
}
|
||||
|
||||
ProfileSettings& SettingsWindow::getCurrentProfile() {
|
||||
return this->window.getProfile(profileWidget->currentRow());
|
||||
return this->core.getProfile(profileWidget->currentRow());
|
||||
}
|
||||
|
||||
void SettingsWindow::openPath(const QString path) {
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
|
||||
class LauncherCore;
|
||||
class LauncherWindow;
|
||||
struct ProfileSettings;
|
||||
|
||||
class SettingsWindow : public QWidget {
|
||||
public:
|
||||
SettingsWindow(LauncherWindow& window, QWidget* parent = nullptr);
|
||||
SettingsWindow(LauncherWindow& window, LauncherCore& core, QWidget* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void reloadControls();
|
||||
|
@ -48,4 +49,5 @@ private:
|
|||
bool currentlyReloadingControls = false;
|
||||
|
||||
LauncherWindow& window;
|
||||
LauncherCore& core;
|
||||
};
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "squarelauncher.h"
|
||||
|
||||
SquareBoot::SquareBoot(LauncherWindow& window, SquareLauncher& launcher) : window(window), launcher(launcher) {
|
||||
SquareBoot::SquareBoot(LauncherCore& window, SquareLauncher& launcher) : window(window), launcher(launcher) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ void SquareBoot::bootCheck(LoginInformation& info) {
|
|||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost("patch-bootver.ffxiv.com");
|
||||
url.setPath(QString("/http/win32/ffxivneo_release_boot/%1").arg(window.currentProfile().bootVersion));
|
||||
url.setPath(QString("/http/win32/ffxivneo_release_boot/%1").arg(info.settings->bootVersion));
|
||||
url.setQuery(query);
|
||||
|
||||
auto request = QNetworkRequest(url);
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
|
||||
class SquareLauncher;
|
||||
|
||||
class SquareBoot : public QObject {
|
||||
public:
|
||||
SquareBoot(LauncherWindow& window, SquareLauncher& launcher);
|
||||
SquareBoot(LauncherCore& window, SquareLauncher& launcher);
|
||||
|
||||
void bootCheck(LoginInformation& info);
|
||||
|
||||
private:
|
||||
LauncherWindow& window;
|
||||
LauncherCore& window;
|
||||
SquareLauncher& launcher;
|
||||
};
|
|
@ -6,9 +6,9 @@
|
|||
#include <QRegularExpressionMatch>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
|
||||
SquareLauncher::SquareLauncher(LauncherWindow& window) : window(window) {
|
||||
SquareLauncher::SquareLauncher(LauncherCore& window) : window(window) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ void SquareLauncher::login(const LoginInformation& info, const QUrl referer) {
|
|||
auth.region = parts[5].toInt();
|
||||
auth.maxExpansion = parts[13].toInt();
|
||||
|
||||
readExpansionVersions(auth.maxExpansion);
|
||||
readExpansionVersions(info, auth.maxExpansion);
|
||||
|
||||
registerSession(info);
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
|||
QUrl url;
|
||||
url.setScheme("https");
|
||||
url.setHost("patch-gamever.ffxiv.com");
|
||||
url.setPath(QString("/http/win32/ffxivneo_release_game/%1/%2").arg(window.currentProfile().gameVersion, SID));
|
||||
url.setPath(QString("/http/win32/ffxivneo_release_game/%1/%2").arg(info.settings->gameVersion, SID));
|
||||
|
||||
auto request = QNetworkRequest(url);
|
||||
window.setSSL(request);
|
||||
|
@ -111,7 +111,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
|||
request.setRawHeader("User-Agent", "FFXIV PATCH CLIENT");
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
|
||||
|
||||
QString report = window.currentProfile().bootVersion + "=" + getBootHash();
|
||||
QString report = info.settings->bootVersion + "=" + getBootHash(info);
|
||||
|
||||
for(int i = 0; i < expansionVersions.size(); i++)
|
||||
report += QString("\nex%1\t%2").arg(QString::number(i + 1), expansionVersions[i]);
|
||||
|
@ -121,7 +121,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
|||
if(reply->rawHeaderList().contains("X-Patch-Unique-Id")) {
|
||||
auth.SID = reply->rawHeader("X-Patch-Unique-Id");
|
||||
|
||||
window.launchGame(auth);
|
||||
window.launchGame(*info.settings, auth);
|
||||
} else {
|
||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Failed the anti-tamper check. Please restore your game to the original state or update the game.");
|
||||
messageBox->show();
|
||||
|
@ -129,7 +129,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
|||
});
|
||||
}
|
||||
|
||||
QString SquareLauncher::getBootHash() {
|
||||
QString SquareLauncher::getBootHash(const LoginInformation& info) {
|
||||
const QList<QString> fileList =
|
||||
{
|
||||
"ffxivboot.exe",
|
||||
|
@ -142,7 +142,7 @@ QString SquareLauncher::getBootHash() {
|
|||
|
||||
QString result;
|
||||
for (int i = 0; i < fileList.count(); i++) {
|
||||
result += fileList[i] + "/" + getFileHash(window.currentProfile().gamePath + "/boot/" + fileList[i]);
|
||||
result += fileList[i] + "/" + getFileHash(info.settings->gamePath + "/boot/" + fileList[i]);
|
||||
|
||||
if (i != fileList.length() - 1)
|
||||
result += ",";
|
||||
|
@ -151,9 +151,9 @@ QString SquareLauncher::getBootHash() {
|
|||
return result;
|
||||
}
|
||||
|
||||
void SquareLauncher::readExpansionVersions(int max) {
|
||||
void SquareLauncher::readExpansionVersions(const LoginInformation& info, int max) {
|
||||
expansionVersions.clear();
|
||||
|
||||
for(int i = 0; i < max; i++)
|
||||
expansionVersions.push_back(window.readVersion(QString("%1/game/sqpack/ex%2/ex%2.ver").arg(window.currentProfile().gamePath, QString::number(i + 1))));
|
||||
expansionVersions.push_back(window.readVersion(QString("%1/game/sqpack/ex%2/ex%2.ver").arg(info.settings->gamePath, QString::number(i + 1))));
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "xivlauncher.h"
|
||||
#include "launchercore.h"
|
||||
|
||||
class SquareLauncher : public QObject {
|
||||
public:
|
||||
SquareLauncher(LauncherWindow& window);
|
||||
SquareLauncher(LauncherCore& window);
|
||||
|
||||
void getStored(const LoginInformation& info);
|
||||
|
||||
void login(const LoginInformation& info, const QUrl referer);
|
||||
void login(const LoginInformation& info, QUrl referer);
|
||||
|
||||
void registerSession(const LoginInformation& info);
|
||||
|
||||
private:
|
||||
QString getBootHash();
|
||||
void readExpansionVersions(int max);
|
||||
QString getBootHash(const LoginInformation& info);
|
||||
void readExpansionVersions(const LoginInformation& info, int max);
|
||||
|
||||
QString stored, SID;
|
||||
LoginAuth auth;
|
||||
|
||||
LauncherWindow& window;
|
||||
LauncherCore& window;
|
||||
|
||||
QList<QString> expansionVersions;
|
||||
};
|
Loading…
Add table
Reference in a new issue