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
|
add_executable(xivlauncher
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/xivlauncher.cpp
|
src/launchercore.cpp
|
||||||
src/sapphirelauncher.cpp
|
src/sapphirelauncher.cpp
|
||||||
src/squareboot.cpp
|
src/squareboot.cpp
|
||||||
src/squarelauncher.cpp
|
src/squarelauncher.cpp
|
||||||
src/settingswindow.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)
|
target_link_libraries(xivlauncher Qt5::Core Qt5::Widgets Qt5::Network qt5keychain QuaZip)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <quazip/JlCompress.h>
|
#include <quazip/JlCompress.h>
|
||||||
|
|
||||||
#include "xivlauncher.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
const QString dalamudRemotePath = "https://goatcorp.github.io/dalamud-distrib/";
|
const QString dalamudRemotePath = "https://goatcorp.github.io/dalamud-distrib/";
|
||||||
const QString dalamudVersion = "latest";
|
const QString dalamudVersion = "latest";
|
||||||
|
@ -14,19 +14,19 @@ const QString dalamudVersion = "latest";
|
||||||
const QString nativeLauncherRemotePath = "https://github.com/redstrate/nativelauncher/releases/download/";
|
const QString nativeLauncherRemotePath = "https://github.com/redstrate/nativelauncher/releases/download/";
|
||||||
const QString nativeLauncherVersion = "v1.0.0";
|
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);
|
connect(launcher.mgr, &QNetworkAccessManager::finished, this, &AssetUpdater::finishDownload);
|
||||||
|
|
||||||
launcher.mgr->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
launcher.mgr->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetUpdater::update() {
|
void AssetUpdater::update(const ProfileSettings& profile) {
|
||||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
|
|
||||||
const bool hasDalamud = QFile::exists(dataDir + "/NativeLauncher.exe") && QFile::exists(dataDir + "/Dalamud");
|
const bool hasDalamud = QFile::exists(dataDir + "/NativeLauncher.exe") && QFile::exists(dataDir + "/Dalamud");
|
||||||
|
|
||||||
// first we determine if we need dalamud
|
// first we determine if we need dalamud
|
||||||
const bool needsDalamud = launcher.currentProfile().enableDalamud && !hasDalamud;
|
const bool needsDalamud = profile.enableDalamud && !hasDalamud;
|
||||||
if(needsDalamud) {
|
if(needsDalamud) {
|
||||||
// download nativelauncher release (needed to launch the game with fixed ACLs)
|
// download nativelauncher release (needed to launch the game with fixed ACLs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,15 +3,16 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
class LauncherWindow;
|
class LauncherCore;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
|
struct ProfileSettings;
|
||||||
|
|
||||||
class AssetUpdater : public QObject {
|
class AssetUpdater : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
AssetUpdater(LauncherWindow& launcher);
|
AssetUpdater(LauncherCore& launcher);
|
||||||
|
|
||||||
void update();
|
void update(const ProfileSettings& profile);
|
||||||
void finishDownload(QNetworkReply* reply);
|
void finishDownload(QNetworkReply* reply);
|
||||||
void beginInstall();
|
void beginInstall();
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ signals:
|
||||||
void finishedUpdating();
|
void finishedUpdating();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LauncherWindow& launcher;
|
LauncherCore& launcher;
|
||||||
|
|
||||||
QTemporaryDir tempDir;
|
QTemporaryDir tempDir;
|
||||||
};
|
};
|
|
@ -27,7 +27,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "xivlauncher.h"
|
#include "launchercore.h"
|
||||||
#include "sapphirelauncher.h"
|
#include "sapphirelauncher.h"
|
||||||
#include "squarelauncher.h"
|
#include "squarelauncher.h"
|
||||||
#include "squareboot.h"
|
#include "squareboot.h"
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
#include "blowfish.h"
|
#include "blowfish.h"
|
||||||
#include "assetupdater.h"
|
#include "assetupdater.h"
|
||||||
|
|
||||||
void LauncherWindow::setSSL(QNetworkRequest& request) {
|
void LauncherCore::setSSL(QNetworkRequest& request) {
|
||||||
QSslConfiguration config;
|
QSslConfiguration config;
|
||||||
config.setProtocol(QSsl::AnyProtocol);
|
config.setProtocol(QSsl::AnyProtocol);
|
||||||
config.setPeerVerifyMode(QSslSocket::VerifyNone);
|
config.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
|
@ -43,7 +43,7 @@ void LauncherWindow::setSSL(QNetworkRequest& request) {
|
||||||
request.setSslConfiguration(config);
|
request.setSslConfiguration(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherWindow::buildRequest(QNetworkRequest& request) {
|
void LauncherCore::buildRequest(QNetworkRequest& request) {
|
||||||
setSSL(request);
|
setSSL(request);
|
||||||
request.setHeader(QNetworkRequest::UserAgentHeader,
|
request.setHeader(QNetworkRequest::UserAgentHeader,
|
||||||
QString("SQEXAuthor/2.0.0(Windows 6.2; ja-jp; %1)").arg(QString(QSysInfo::bootUniqueId())));
|
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));
|
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;
|
QList<QString> arguments;
|
||||||
|
|
||||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
|
|
||||||
if(currentProfile().enableDalamud) {
|
if(profile.enableDalamud) {
|
||||||
arguments.push_back(dataDir + "/NativeLauncher.exe");
|
arguments.push_back(dataDir + "/NativeLauncher.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
// now for the actual game...
|
// now for the actual game...
|
||||||
if(currentProfile().useDX9) {
|
if(profile.useDX9) {
|
||||||
arguments.push_back(currentProfile().gamePath + "\\game\\ffxiv.exe");
|
arguments.push_back(profile.gamePath + "\\game\\ffxiv.exe");
|
||||||
} else {
|
} else {
|
||||||
arguments.push_back(currentProfile().gamePath + "\\game\\ffxiv_dx11.exe");
|
arguments.push_back(profile.gamePath + "\\game\\ffxiv_dx11.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Argument {
|
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.MaxEntitledExpansionID", QString::number(auth.maxExpansion)});
|
||||||
gameArgs.push_back({"DEV.TestSID", auth.SID});
|
gameArgs.push_back({"DEV.TestSID", auth.SID});
|
||||||
gameArgs.push_back({"SYS.Region", QString::number(auth.region)});
|
gameArgs.push_back({"SYS.Region", QString::number(auth.region)});
|
||||||
gameArgs.push_back({"language", QString::number(currentProfile().language)});
|
gameArgs.push_back({"language", QString::number(profile.language)});
|
||||||
gameArgs.push_back({"ver", currentProfile().gameVersion});
|
gameArgs.push_back({"ver", profile.gameVersion});
|
||||||
|
|
||||||
if(!auth.lobbyhost.isEmpty()) {
|
if(!auth.lobbyhost.isEmpty()) {
|
||||||
gameArgs.push_back({"DEV.GMServerHost", auth.frontierHost});
|
gameArgs.push_back({"DEV.GMServerHost", auth.frontierHost});
|
||||||
|
@ -146,8 +146,8 @@ void LauncherWindow::launchGame(const LoginAuth auth) {
|
||||||
|
|
||||||
auto gameProcess = new QProcess(this);
|
auto gameProcess = new QProcess(this);
|
||||||
|
|
||||||
if(currentProfile().enableDalamud) {
|
if(profile.enableDalamud) {
|
||||||
connect(gameProcess, &QProcess::readyReadStandardOutput, [this, gameProcess] {
|
connect(gameProcess, &QProcess::readyReadStandardOutput, [this, gameProcess, profile] {
|
||||||
QString output = gameProcess->readAllStandardOutput();
|
QString output = gameProcess->readAllStandardOutput();
|
||||||
|
|
||||||
auto dalamudProcess = new QProcess();
|
auto dalamudProcess = new QProcess();
|
||||||
|
@ -162,11 +162,11 @@ void LauncherWindow::launchGame(const LoginAuth auth) {
|
||||||
|
|
||||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
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;
|
QString argJoined;
|
||||||
for(auto arg : gameArgs) {
|
for(auto arg : gameArgs) {
|
||||||
argJoined += QString(" /%1 =%2").arg(arg.key, arg.value);
|
argJoined += QString(" /%1 =%2").arg(arg.key, arg.value);
|
||||||
|
@ -174,47 +174,46 @@ void LauncherWindow::launchGame(const LoginAuth auth) {
|
||||||
|
|
||||||
auto earg = encryptGameArg(argJoined);
|
auto earg = encryptGameArg(argJoined);
|
||||||
arguments.append(earg);
|
arguments.append(earg);
|
||||||
launchExecutable(gameProcess, arguments);
|
launchExecutable(profile, gameProcess, arguments);
|
||||||
} else {
|
} else {
|
||||||
for(auto arg : gameArgs) {
|
for(auto arg : gameArgs) {
|
||||||
arguments.push_back(QString(" %1=%2").arg(arg.key, arg.value));
|
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);
|
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;
|
QList<QString> arguments;
|
||||||
QStringList env = QProcess::systemEnvironment();
|
QStringList env = QProcess::systemEnvironment();
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
if(currentProfile().useGamescope) {
|
if(profile.useGamescope) {
|
||||||
arguments.push_back("gamescope");
|
arguments.push_back("gamescope");
|
||||||
arguments.push_back("-f");
|
arguments.push_back("-f");
|
||||||
arguments.push_back("-b");
|
arguments.push_back("-b");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentProfile().useGamemode)
|
if(profile.useGamemode)
|
||||||
arguments.push_back("gamemoderun");
|
arguments.push_back("gamemoderun");
|
||||||
|
|
||||||
if(currentProfile().useEsync) {
|
if(profile.useEsync)
|
||||||
env << "WINEESYNC=1";
|
env << "WINEESYNC=1";
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
|
#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";
|
env << "DXVK_HUD=full";
|
||||||
|
|
||||||
arguments.push_back(currentProfile().winePath);
|
arguments.push_back(profile.winePath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
arguments.append(args);
|
arguments.append(args);
|
||||||
|
@ -222,20 +221,20 @@ void LauncherWindow::launchExecutable(QProcess* process, const QStringList args)
|
||||||
auto executable = arguments[0];
|
auto executable = arguments[0];
|
||||||
arguments.removeFirst();
|
arguments.removeFirst();
|
||||||
|
|
||||||
process->setWorkingDirectory(currentProfile().gamePath + "/game/");
|
process->setWorkingDirectory(profile.gamePath + "/game/");
|
||||||
process->setEnvironment(env);
|
process->setEnvironment(env);
|
||||||
|
|
||||||
process->start(executable, arguments);
|
process->start(executable, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LauncherWindow::readVersion(QString path) {
|
QString LauncherCore::readVersion(QString path) {
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
file.open(QFile::OpenModeFlag::ReadOnly);
|
file.open(QFile::OpenModeFlag::ReadOnly);
|
||||||
|
|
||||||
return file.readAll();
|
return file.readAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherWindow::readInitialInformation() {
|
void LauncherCore::readInitialInformation() {
|
||||||
defaultProfileIndex = settings.value("defaultProfile", 0).toInt();
|
defaultProfileIndex = settings.value("defaultProfile", 0).toInt();
|
||||||
|
|
||||||
auto profiles = settings.childGroups();
|
auto profiles = settings.childGroups();
|
||||||
|
@ -312,7 +311,7 @@ void LauncherWindow::readInitialInformation() {
|
||||||
readGameVersion();
|
readGameVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherWindow::readWineInfo(ProfileSettings& profile) {
|
void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
switch(profile.wineVersion) {
|
switch(profile.wineVersion) {
|
||||||
case 0: // system wine
|
case 0: // system wine
|
||||||
|
@ -339,15 +338,14 @@ void LauncherWindow::readWineInfo(ProfileSettings& profile) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherWindow::readGameVersion() {
|
void LauncherCore::readGameVersion() {
|
||||||
for(auto& profile : profileSettings) {
|
for(auto& profile : profileSettings) {
|
||||||
profile.bootVersion = readVersion(profile.gamePath + "/boot/ffxivboot.ver");
|
profile.bootVersion = readVersion(profile.gamePath + "/boot/ffxivboot.ver");
|
||||||
profile.gameVersion = readVersion(profile.gamePath + "/game/ffxivgame.ver");
|
profile.gameVersion = readVersion(profile.gamePath + "/game/ffxivgame.ver");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherWindow::LauncherWindow(QWidget* parent) :
|
LauncherCore::LauncherCore() : settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::applicationName()) {
|
||||||
QMainWindow(parent), settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::applicationName()) {
|
|
||||||
mgr = new QNetworkAccessManager();
|
mgr = new QNetworkAccessManager();
|
||||||
sapphireLauncher = new SapphireLauncher(*this);
|
sapphireLauncher = new SapphireLauncher(*this);
|
||||||
squareLauncher = new SquareLauncher(*this);
|
squareLauncher = new SquareLauncher(*this);
|
||||||
|
@ -355,152 +353,17 @@ LauncherWindow::LauncherWindow(QWidget* parent) :
|
||||||
assetUpdater = new AssetUpdater(*this);
|
assetUpdater = new AssetUpdater(*this);
|
||||||
|
|
||||||
readInitialInformation();
|
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 LauncherCore::getProfile(int index) const {
|
||||||
|
|
||||||
ProfileSettings LauncherWindow::currentProfile() const {
|
|
||||||
return getProfile(profileSelect->currentIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfileSettings& LauncherWindow::currentProfile() {
|
|
||||||
return getProfile(profileSelect->currentIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfileSettings LauncherWindow::getProfile(int index) const {
|
|
||||||
return profileSettings[index];
|
return profileSettings[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileSettings& LauncherWindow::getProfile(int index) {
|
ProfileSettings& LauncherCore::getProfile(int index) {
|
||||||
return profileSettings[index];
|
return profileSettings[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
int LauncherWindow::getProfileIndex(QString name) {
|
int LauncherCore::getProfileIndex(QString name) {
|
||||||
for(int i = 0; i < profileSettings.size(); i++) {
|
for(int i = 0; i < profileSettings.size(); i++) {
|
||||||
if(profileSettings[i].name == name)
|
if(profileSettings[i].name == name)
|
||||||
return i;
|
return i;
|
||||||
|
@ -509,7 +372,7 @@ int LauncherWindow::getProfileIndex(QString name) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QString> LauncherWindow::profileList() const {
|
QList<QString> LauncherCore::profileList() const {
|
||||||
QList<QString> list;
|
QList<QString> list;
|
||||||
for(auto profile : profileSettings) {
|
for(auto profile : profileSettings) {
|
||||||
list.append(profile.name);
|
list.append(profile.name);
|
||||||
|
@ -518,7 +381,7 @@ QList<QString> LauncherWindow::profileList() const {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LauncherWindow::addProfile() {
|
int LauncherCore::addProfile() {
|
||||||
ProfileSettings newProfile;
|
ProfileSettings newProfile;
|
||||||
newProfile.uuid = QUuid::createUuid();
|
newProfile.uuid = QUuid::createUuid();
|
||||||
newProfile.name = "New Profile";
|
newProfile.name = "New Profile";
|
||||||
|
@ -530,7 +393,7 @@ int LauncherWindow::addProfile() {
|
||||||
return profileSettings.size() - 1;
|
return profileSettings.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LauncherWindow::deleteProfile(QString name) {
|
int LauncherCore::deleteProfile(QString name) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(int i = 0; i < profileSettings.size(); i++) {
|
for(int i = 0; i < profileSettings.size(); i++) {
|
||||||
if(profileSettings[i].name == name)
|
if(profileSettings[i].name == name)
|
||||||
|
@ -547,7 +410,7 @@ int LauncherWindow::deleteProfile(QString name) {
|
||||||
return index - 1;
|
return index - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherWindow::saveSettings() {
|
void LauncherCore::saveSettings() {
|
||||||
settings.setValue("defaultProfile", defaultProfileIndex);
|
settings.setValue("defaultProfile", defaultProfileIndex);
|
||||||
|
|
||||||
for(int i = 0; i < profileSettings.size(); i++) {
|
for(int i = 0; i < profileSettings.size(); i++) {
|
||||||
|
@ -582,52 +445,4 @@ void LauncherWindow::saveSettings() {
|
||||||
|
|
||||||
settings.endGroup();
|
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 <QNetworkAccessManager>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QComboBox>
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
|
@ -45,6 +42,8 @@ struct ProfileSettings {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoginInformation {
|
struct LoginInformation {
|
||||||
|
ProfileSettings* settings = nullptr;
|
||||||
|
|
||||||
QString username, password, oneTimePassword;
|
QString username, password, oneTimePassword;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,18 +56,13 @@ struct LoginAuth {
|
||||||
QString lobbyhost, frontierHost;
|
QString lobbyhost, frontierHost;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LauncherWindow : public QMainWindow {
|
class LauncherCore : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit LauncherWindow(QWidget* parent = nullptr);
|
LauncherCore();
|
||||||
|
|
||||||
~LauncherWindow() override;
|
|
||||||
|
|
||||||
QNetworkAccessManager* mgr;
|
QNetworkAccessManager* mgr;
|
||||||
|
|
||||||
ProfileSettings currentProfile() const;
|
|
||||||
ProfileSettings& currentProfile();
|
|
||||||
|
|
||||||
ProfileSettings getProfile(int index) const;
|
ProfileSettings getProfile(int index) const;
|
||||||
ProfileSettings& getProfile(int index);
|
ProfileSettings& getProfile(int index);
|
||||||
|
|
||||||
|
@ -77,9 +71,9 @@ public:
|
||||||
int addProfile();
|
int addProfile();
|
||||||
int deleteProfile(QString name);
|
int deleteProfile(QString name);
|
||||||
|
|
||||||
void launchGame(const LoginAuth auth);
|
void launchGame(const ProfileSettings& settings, const LoginAuth auth);
|
||||||
void launchExecutable(QStringList args);
|
void launchExecutable(const ProfileSettings& settings, QStringList args);
|
||||||
void launchExecutable(QProcess* process, QStringList args);
|
void launchExecutable(const ProfileSettings& settings, QProcess* process, QStringList args);
|
||||||
void buildRequest(QNetworkRequest& request);
|
void buildRequest(QNetworkRequest& request);
|
||||||
void setSSL(QNetworkRequest& request);
|
void setSSL(QNetworkRequest& request);
|
||||||
QString readVersion(QString path);
|
QString readVersion(QString path);
|
||||||
|
@ -90,26 +84,15 @@ public:
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
public slots:
|
|
||||||
void reloadControls();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void settingsChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool currentlyReloadingControls = false;
|
|
||||||
|
|
||||||
SapphireLauncher* sapphireLauncher;
|
SapphireLauncher* sapphireLauncher;
|
||||||
SquareBoot* squareBoot;
|
SquareBoot* squareBoot;
|
||||||
SquareLauncher* squareLauncher;
|
SquareLauncher* squareLauncher;
|
||||||
AssetUpdater* assetUpdater;
|
AssetUpdater* assetUpdater;
|
||||||
|
|
||||||
QComboBox* profileSelect;
|
|
||||||
QLineEdit* usernameEdit, *passwordEdit;
|
|
||||||
QLineEdit* otpEdit;
|
|
||||||
QCheckBox* rememberUsernameBox, *rememberPasswordBox;
|
|
||||||
QPushButton* registerButton;
|
|
||||||
|
|
||||||
QVector<ProfileSettings> profileSettings;
|
|
||||||
int defaultProfileIndex = 0;
|
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 <QApplication>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
@ -13,7 +16,15 @@ int main(int argc, char* argv[]) {
|
||||||
QCoreApplication::setApplicationName("xivlauncher-debug");
|
QCoreApplication::setApplicationName("xivlauncher-debug");
|
||||||
#endif
|
#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();
|
w.show();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QNetworkReply>
|
#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.frontierHost = document["frontierHost"].toString();
|
||||||
auth.region = 3;
|
auth.region = 3;
|
||||||
|
|
||||||
window.launchGame(auth);
|
window.launchGame(*info.settings, auth);
|
||||||
} else {
|
} else {
|
||||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Invalid username/password.");
|
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Invalid username/password.");
|
||||||
messageBox->show();
|
messageBox->show();
|
||||||
|
@ -64,6 +64,6 @@ void SapphireLauncher::registerAccount(QString lobbyUrl, const LoginInformation&
|
||||||
auth.frontierHost = document["frontierHost"].toString();
|
auth.frontierHost = document["frontierHost"].toString();
|
||||||
auth.region = 3;
|
auth.region = 3;
|
||||||
|
|
||||||
window.launchGame(auth);
|
window.launchGame(*info.settings, auth);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "xivlauncher.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
class SapphireLauncher : QObject {
|
class SapphireLauncher : QObject {
|
||||||
public:
|
public:
|
||||||
SapphireLauncher(LauncherWindow& window);
|
SapphireLauncher(LauncherCore& window);
|
||||||
|
|
||||||
void login(QString lobbyUrl, const LoginInformation& info);
|
void login(QString lobbyUrl, const LoginInformation& info);
|
||||||
void registerAccount(QString lobbyUrl, const LoginInformation& info);
|
void registerAccount(QString lobbyUrl, const LoginInformation& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LauncherWindow& window;
|
LauncherCore& window;
|
||||||
};
|
};
|
|
@ -11,9 +11,10 @@
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QGridLayout>
|
#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");
|
setWindowTitle("Settings");
|
||||||
setWindowModality(Qt::WindowModality::ApplicationModal);
|
setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||||
|
|
||||||
|
@ -30,17 +31,17 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
|
|
||||||
auto addProfileButton = new QPushButton("Add Profile");
|
auto addProfileButton = new QPushButton("Add Profile");
|
||||||
connect(addProfileButton, &QPushButton::pressed, [=] {
|
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);
|
mainLayout->addWidget(addProfileButton, 2, 0);
|
||||||
|
|
||||||
deleteProfileButton = new QPushButton("Delete Profile");
|
deleteProfileButton = new QPushButton("Delete Profile");
|
||||||
connect(deleteProfileButton, &QPushButton::pressed, [=] {
|
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);
|
mainLayout->addWidget(deleteProfileButton, 3, 0);
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
getCurrentProfile().name = nameEdit->text();
|
getCurrentProfile().name = nameEdit->text();
|
||||||
|
|
||||||
reloadControls();
|
reloadControls();
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
mainLayout->addWidget(nameEdit, 0, 1);
|
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) {
|
connect(directXCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||||
getCurrentProfile().useDX9 = directXCombo->currentIndex() == 1;
|
getCurrentProfile().useDX9 = directXCombo->currentIndex() == 1;
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
|
||||||
currentGameDirectory = new QLabel(window.currentProfile().gamePath);
|
currentGameDirectory = new QLabel();
|
||||||
currentGameDirectory->setWordWrap(true);
|
currentGameDirectory->setWordWrap(true);
|
||||||
gameBoxLayout->addRow("Game Directory", currentGameDirectory);
|
gameBoxLayout->addRow("Game Directory", currentGameDirectory);
|
||||||
|
|
||||||
|
@ -78,9 +79,9 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
getCurrentProfile().gamePath = QFileDialog::getExistingDirectory(this, "Open Game Directory");
|
getCurrentProfile().gamePath = QFileDialog::getExistingDirectory(this, "Open Game Directory");
|
||||||
|
|
||||||
this->reloadControls();
|
this->reloadControls();
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
|
|
||||||
this->window.readGameVersion();
|
this->core.readGameVersion();
|
||||||
});
|
});
|
||||||
gameBoxLayout->addWidget(selectDirectoryButton);
|
gameBoxLayout->addWidget(selectDirectoryButton);
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(encryptArgumentsBox, &QCheckBox::stateChanged, [=](int) {
|
connect(encryptArgumentsBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().encryptArguments = encryptArgumentsBox->isChecked();
|
getCurrentProfile().encryptArguments = encryptArgumentsBox->isChecked();
|
||||||
|
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
loginBoxLayout->addRow("Encrypt Game Arguments", encryptArgumentsBox);
|
loginBoxLayout->addRow("Encrypt Game Arguments", encryptArgumentsBox);
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(enableDalamudBox, &QCheckBox::stateChanged, [=](int) {
|
connect(enableDalamudBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().enableDalamud = enableDalamudBox->isChecked();
|
getCurrentProfile().enableDalamud = enableDalamudBox->isChecked();
|
||||||
|
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
loginBoxLayout->addRow("Enable Dalamud Injection", enableDalamudBox);
|
loginBoxLayout->addRow("Enable Dalamud Injection", enableDalamudBox);
|
||||||
|
|
||||||
|
@ -120,8 +121,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
getCurrentProfile().isSapphire = index == 1;
|
getCurrentProfile().isSapphire = index == 1;
|
||||||
|
|
||||||
reloadControls();
|
reloadControls();
|
||||||
this->window.reloadControls();
|
this->core.saveSettings();
|
||||||
this->window.saveSettings();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
loginBoxLayout->addRow("Server Lobby", serverType);
|
loginBoxLayout->addRow("Server Lobby", serverType);
|
||||||
|
@ -129,7 +129,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
lobbyServerURL = new QLineEdit();
|
lobbyServerURL = new QLineEdit();
|
||||||
connect(lobbyServerURL, &QLineEdit::editingFinished, [=] {
|
connect(lobbyServerURL, &QLineEdit::editingFinished, [=] {
|
||||||
getCurrentProfile().lobbyURL = lobbyServerURL->text();
|
getCurrentProfile().lobbyURL = lobbyServerURL->text();
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
loginBoxLayout->addRow("Lobby URL", lobbyServerURL);
|
loginBoxLayout->addRow("Lobby URL", lobbyServerURL);
|
||||||
|
|
||||||
|
@ -137,8 +137,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) {
|
connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().rememberUsername = rememberUsernameBox->isChecked();
|
getCurrentProfile().rememberUsername = rememberUsernameBox->isChecked();
|
||||||
|
|
||||||
this->window.reloadControls();
|
this->core.saveSettings();
|
||||||
this->window.saveSettings();
|
|
||||||
});
|
});
|
||||||
loginBoxLayout->addRow("Remember Username?", rememberUsernameBox);
|
loginBoxLayout->addRow("Remember Username?", rememberUsernameBox);
|
||||||
|
|
||||||
|
@ -146,8 +145,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) {
|
connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().rememberPassword = rememberPasswordBox->isChecked();
|
getCurrentProfile().rememberPassword = rememberPasswordBox->isChecked();
|
||||||
|
|
||||||
this->window.reloadControls();
|
this->core.saveSettings();
|
||||||
this->window.saveSettings();
|
|
||||||
});
|
});
|
||||||
loginBoxLayout->addRow("Remember Password?", rememberPasswordBox);
|
loginBoxLayout->addRow("Remember Password?", rememberPasswordBox);
|
||||||
|
|
||||||
|
@ -163,7 +161,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
infoLabel->setWordWrap(true);
|
infoLabel->setWordWrap(true);
|
||||||
wineBoxLayout->addWidget(infoLabel);
|
wineBoxLayout->addWidget(infoLabel);
|
||||||
|
|
||||||
winePathLabel = new QLabel(window.currentProfile().winePath);
|
winePathLabel = new QLabel();
|
||||||
winePathLabel->setWordWrap(true);
|
winePathLabel->setWordWrap(true);
|
||||||
wineBoxLayout->addRow("Wine Executable", winePathLabel);
|
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) {
|
connect(wineVersionCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [this](int index) {
|
||||||
getCurrentProfile().wineVersion = index;
|
getCurrentProfile().wineVersion = index;
|
||||||
|
|
||||||
this->window.readWineInfo(getCurrentProfile());
|
this->core.readWineInfo(getCurrentProfile());
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
this->reloadControls();
|
this->reloadControls();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(selectWineButton, &QPushButton::pressed, [this] {
|
connect(selectWineButton, &QPushButton::pressed, [this] {
|
||||||
getCurrentProfile().winePath = QFileDialog::getOpenFileName(this, "Open Wine Executable");
|
getCurrentProfile().winePath = QFileDialog::getOpenFileName(this, "Open Wine Executable");
|
||||||
|
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
this->reloadControls();
|
this->reloadControls();
|
||||||
});
|
});
|
||||||
|
|
||||||
winePrefixDirectory = new QLabel(window.currentProfile().winePrefixPath);
|
winePrefixDirectory = new QLabel();
|
||||||
winePrefixDirectory->setWordWrap(true);
|
winePrefixDirectory->setWordWrap(true);
|
||||||
wineBoxLayout->addRow("Wine Prefix", winePrefixDirectory);
|
wineBoxLayout->addRow("Wine Prefix", winePrefixDirectory);
|
||||||
|
|
||||||
|
@ -204,7 +202,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(selectPrefixButton, &QPushButton::pressed, [this] {
|
connect(selectPrefixButton, &QPushButton::pressed, [this] {
|
||||||
getCurrentProfile().winePrefixPath = QFileDialog::getExistingDirectory(this, "Open Wine Prefix");
|
getCurrentProfile().winePrefixPath = QFileDialog::getExistingDirectory(this, "Open Wine Prefix");
|
||||||
|
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
this->reloadControls();
|
this->reloadControls();
|
||||||
});
|
});
|
||||||
wineBoxLayout->addWidget(selectPrefixButton);
|
wineBoxLayout->addWidget(selectPrefixButton);
|
||||||
|
@ -216,12 +214,11 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
wineBoxLayout->addWidget(openPrefixButton);
|
wineBoxLayout->addWidget(openPrefixButton);
|
||||||
|
|
||||||
auto enableDXVKhud = new QCheckBox("Enable DXVK HUD");
|
auto enableDXVKhud = new QCheckBox("Enable DXVK HUD");
|
||||||
enableDXVKhud->setChecked(window.currentProfile().enableDXVKhud);
|
|
||||||
wineBoxLayout->addWidget(enableDXVKhud);
|
wineBoxLayout->addWidget(enableDXVKhud);
|
||||||
|
|
||||||
connect(enableDXVKhud, &QCheckBox::stateChanged, [this](int state) {
|
connect(enableDXVKhud, &QCheckBox::stateChanged, [this](int state) {
|
||||||
this->window.currentProfile().enableDXVKhud = state;
|
getCurrentProfile().enableDXVKhud = state;
|
||||||
this->window.settings.setValue("enableDXVKhud", static_cast<bool>(state));
|
this->core.settings.setValue("enableDXVKhud", static_cast<bool>(state));
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -237,7 +234,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(useEsync, &QCheckBox::stateChanged, [this](int state) {
|
connect(useEsync, &QCheckBox::stateChanged, [this](int state) {
|
||||||
getCurrentProfile().useEsync = state;
|
getCurrentProfile().useEsync = state;
|
||||||
|
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
|
||||||
useGamescope = new QCheckBox("Use Gamescope");
|
useGamescope = new QCheckBox("Use Gamescope");
|
||||||
|
@ -251,7 +248,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(useGamescope, &QCheckBox::stateChanged, [this](int state) {
|
connect(useGamescope, &QCheckBox::stateChanged, [this](int state) {
|
||||||
getCurrentProfile().useGamescope = state;
|
getCurrentProfile().useGamescope = state;
|
||||||
|
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
|
||||||
useGamemode = new QCheckBox("Use Gamemode");
|
useGamemode = new QCheckBox("Use Gamemode");
|
||||||
|
@ -265,7 +262,7 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, QWidget* parent) : window
|
||||||
connect(useGamemode, &QCheckBox::stateChanged, [this](int state) {
|
connect(useGamemode, &QCheckBox::stateChanged, [this](int state) {
|
||||||
getCurrentProfile().useGamemode = state;
|
getCurrentProfile().useGamemode = state;
|
||||||
|
|
||||||
this->window.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -282,15 +279,15 @@ void SettingsWindow::reloadControls() {
|
||||||
|
|
||||||
profileWidget->clear();
|
profileWidget->clear();
|
||||||
|
|
||||||
for(auto profile : window.profileList()) {
|
for(const auto& profile : core.profileList()) {
|
||||||
profileWidget->addItem(profile);
|
profileWidget->addItem(profile);
|
||||||
}
|
}
|
||||||
profileWidget->setCurrentRow(oldRow);
|
profileWidget->setCurrentRow(oldRow);
|
||||||
|
|
||||||
// deleting the main profile is unsupported behavior
|
// 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);
|
nameEdit->setText(profile.name);
|
||||||
|
|
||||||
// game
|
// game
|
||||||
|
@ -325,7 +322,7 @@ void SettingsWindow::reloadControls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileSettings& SettingsWindow::getCurrentProfile() {
|
ProfileSettings& SettingsWindow::getCurrentProfile() {
|
||||||
return this->window.getProfile(profileWidget->currentRow());
|
return this->core.getProfile(profileWidget->currentRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsWindow::openPath(const QString path) {
|
void SettingsWindow::openPath(const QString path) {
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
|
class LauncherCore;
|
||||||
class LauncherWindow;
|
class LauncherWindow;
|
||||||
struct ProfileSettings;
|
struct ProfileSettings;
|
||||||
|
|
||||||
class SettingsWindow : public QWidget {
|
class SettingsWindow : public QWidget {
|
||||||
public:
|
public:
|
||||||
SettingsWindow(LauncherWindow& window, QWidget* parent = nullptr);
|
SettingsWindow(LauncherWindow& window, LauncherCore& core, QWidget* parent = nullptr);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void reloadControls();
|
void reloadControls();
|
||||||
|
@ -48,4 +49,5 @@ private:
|
||||||
bool currentlyReloadingControls = false;
|
bool currentlyReloadingControls = false;
|
||||||
|
|
||||||
LauncherWindow& window;
|
LauncherWindow& window;
|
||||||
|
LauncherCore& core;
|
||||||
};
|
};
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "squarelauncher.h"
|
#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;
|
QUrl url;
|
||||||
url.setScheme("http");
|
url.setScheme("http");
|
||||||
url.setHost("patch-bootver.ffxiv.com");
|
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);
|
url.setQuery(query);
|
||||||
|
|
||||||
auto request = QNetworkRequest(url);
|
auto request = QNetworkRequest(url);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xivlauncher.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
class SquareLauncher;
|
class SquareLauncher;
|
||||||
|
|
||||||
class SquareBoot : public QObject {
|
class SquareBoot : public QObject {
|
||||||
public:
|
public:
|
||||||
SquareBoot(LauncherWindow& window, SquareLauncher& launcher);
|
SquareBoot(LauncherCore& window, SquareLauncher& launcher);
|
||||||
|
|
||||||
void bootCheck(LoginInformation& info);
|
void bootCheck(LoginInformation& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LauncherWindow& window;
|
LauncherCore& window;
|
||||||
SquareLauncher& launcher;
|
SquareLauncher& launcher;
|
||||||
};
|
};
|
|
@ -6,9 +6,9 @@
|
||||||
#include <QRegularExpressionMatch>
|
#include <QRegularExpressionMatch>
|
||||||
#include <QMessageBox>
|
#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.region = parts[5].toInt();
|
||||||
auth.maxExpansion = parts[13].toInt();
|
auth.maxExpansion = parts[13].toInt();
|
||||||
|
|
||||||
readExpansionVersions(auth.maxExpansion);
|
readExpansionVersions(info, auth.maxExpansion);
|
||||||
|
|
||||||
registerSession(info);
|
registerSession(info);
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
||||||
QUrl url;
|
QUrl url;
|
||||||
url.setScheme("https");
|
url.setScheme("https");
|
||||||
url.setHost("patch-gamever.ffxiv.com");
|
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);
|
auto request = QNetworkRequest(url);
|
||||||
window.setSSL(request);
|
window.setSSL(request);
|
||||||
|
@ -111,7 +111,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
||||||
request.setRawHeader("User-Agent", "FFXIV PATCH CLIENT");
|
request.setRawHeader("User-Agent", "FFXIV PATCH CLIENT");
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
|
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++)
|
for(int i = 0; i < expansionVersions.size(); i++)
|
||||||
report += QString("\nex%1\t%2").arg(QString::number(i + 1), expansionVersions[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")) {
|
if(reply->rawHeaderList().contains("X-Patch-Unique-Id")) {
|
||||||
auth.SID = reply->rawHeader("X-Patch-Unique-Id");
|
auth.SID = reply->rawHeader("X-Patch-Unique-Id");
|
||||||
|
|
||||||
window.launchGame(auth);
|
window.launchGame(*info.settings, auth);
|
||||||
} else {
|
} 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.");
|
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();
|
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 =
|
const QList<QString> fileList =
|
||||||
{
|
{
|
||||||
"ffxivboot.exe",
|
"ffxivboot.exe",
|
||||||
|
@ -142,7 +142,7 @@ QString SquareLauncher::getBootHash() {
|
||||||
|
|
||||||
QString result;
|
QString result;
|
||||||
for (int i = 0; i < fileList.count(); i++) {
|
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)
|
if (i != fileList.length() - 1)
|
||||||
result += ",";
|
result += ",";
|
||||||
|
@ -151,9 +151,9 @@ QString SquareLauncher::getBootHash() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SquareLauncher::readExpansionVersions(int max) {
|
void SquareLauncher::readExpansionVersions(const LoginInformation& info, int max) {
|
||||||
expansionVersions.clear();
|
expansionVersions.clear();
|
||||||
|
|
||||||
for(int i = 0; i < max; i++)
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "xivlauncher.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
class SquareLauncher : public QObject {
|
class SquareLauncher : public QObject {
|
||||||
public:
|
public:
|
||||||
SquareLauncher(LauncherWindow& window);
|
SquareLauncher(LauncherCore& window);
|
||||||
|
|
||||||
void getStored(const LoginInformation& info);
|
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);
|
void registerSession(const LoginInformation& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString getBootHash();
|
QString getBootHash(const LoginInformation& info);
|
||||||
void readExpansionVersions(int max);
|
void readExpansionVersions(const LoginInformation& info, int max);
|
||||||
|
|
||||||
QString stored, SID;
|
QString stored, SID;
|
||||||
LoginAuth auth;
|
LoginAuth auth;
|
||||||
|
|
||||||
LauncherWindow& window;
|
LauncherCore& window;
|
||||||
|
|
||||||
QList<QString> expansionVersions;
|
QList<QString> expansionVersions;
|
||||||
};
|
};
|
Loading…
Add table
Reference in a new issue