2022-08-15 11:14:37 -04:00
|
|
|
#include <QCheckBox>
|
|
|
|
#include <QComboBox>
|
|
|
|
#include <QCoreApplication>
|
2021-11-01 09:54:58 -04:00
|
|
|
#include <QDir>
|
|
|
|
#include <QFormLayout>
|
|
|
|
#include <QJsonDocument>
|
2022-08-15 11:14:37 -04:00
|
|
|
#include <QJsonObject>
|
|
|
|
#include <QLineEdit>
|
2021-11-01 13:14:00 -04:00
|
|
|
#include <QMenuBar>
|
2022-08-15 11:14:37 -04:00
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QNetworkAccessManager>
|
|
|
|
#include <QNetworkReply>
|
|
|
|
#include <QProcess>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QRegularExpression>
|
2021-11-23 14:37:37 -05:00
|
|
|
#include <QRegularExpressionMatch>
|
2022-08-15 11:14:37 -04:00
|
|
|
#include <QStandardPaths>
|
2022-04-06 13:18:40 -04:00
|
|
|
#include <QTcpServer>
|
2022-08-15 11:14:37 -04:00
|
|
|
#include <QUrlQuery>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <keychain.h>
|
2022-09-05 16:14:07 -04:00
|
|
|
#include <cotp.h>
|
2021-11-09 20:57:10 -05:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
#include "assetupdater.h"
|
|
|
|
#include "encryptedarg.h"
|
2021-11-23 15:34:23 -05:00
|
|
|
#include "launchercore.h"
|
2021-11-01 09:54:58 -04:00
|
|
|
#include "sapphirelauncher.h"
|
2022-08-15 11:14:37 -04:00
|
|
|
#include "squareboot.h"
|
|
|
|
#include "squarelauncher.h"
|
2022-01-27 09:25:23 -05:00
|
|
|
|
|
|
|
#ifdef ENABLE_WATCHDOG
|
2022-08-15 11:14:37 -04:00
|
|
|
#include "watchdog.h"
|
2022-01-27 09:25:23 -05:00
|
|
|
#endif
|
2021-11-01 09:54:58 -04:00
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
void LauncherCore::setSSL(QNetworkRequest& request) {
|
2021-11-01 09:54:58 -04:00
|
|
|
QSslConfiguration config;
|
|
|
|
config.setProtocol(QSsl::AnyProtocol);
|
|
|
|
config.setPeerVerifyMode(QSslSocket::VerifyNone);
|
|
|
|
|
|
|
|
request.setSslConfiguration(config);
|
|
|
|
}
|
|
|
|
|
2022-03-16 15:03:35 -04:00
|
|
|
void LauncherCore::buildRequest(const ProfileSettings& settings, QNetworkRequest& request) {
|
2021-11-01 09:54:58 -04:00
|
|
|
setSSL(request);
|
2022-03-16 15:03:35 -04:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (settings.license == GameLicense::macOS) {
|
2022-03-16 15:03:35 -04:00
|
|
|
request.setHeader(QNetworkRequest::UserAgentHeader, "macSQEXAuthor/2.0.0(MacOSX; ja-jp)");
|
|
|
|
} else {
|
2022-08-15 11:14:37 -04:00
|
|
|
request.setHeader(
|
|
|
|
QNetworkRequest::UserAgentHeader,
|
|
|
|
QString("SQEXAuthor/2.0.0(Windows 6.2; ja-jp; %1)").arg(QString(QSysInfo::bootUniqueId())));
|
2022-03-16 15:03:35 -04:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
request.setRawHeader(
|
|
|
|
"Accept",
|
|
|
|
"image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, "
|
|
|
|
"application/x-ms-xbap, */*");
|
2021-11-01 09:54:58 -04:00
|
|
|
request.setRawHeader("Accept-Encoding", "gzip, deflate");
|
|
|
|
request.setRawHeader("Accept-Language", "en-us");
|
|
|
|
}
|
|
|
|
|
2022-09-05 15:59:00 -04:00
|
|
|
void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth& auth) {
|
|
|
|
#ifdef ENABLE_WATCHDOG
|
|
|
|
if (info.settings->enableWatchdog) {
|
|
|
|
watchdog->launchGame(profile, auth);
|
|
|
|
} else {
|
|
|
|
beginGameExecutable(profile, auth);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
beginGameExecutable(profile, auth);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void LauncherCore::beginGameExecutable(const ProfileSettings& profile, const LoginAuth& auth) {
|
2022-09-05 16:51:46 -04:00
|
|
|
QString gameExectuable;
|
|
|
|
if(profile.useDX9) {
|
|
|
|
gameExectuable = profile.gamePath + "/game/ffxiv.exe";
|
|
|
|
} else {
|
|
|
|
gameExectuable = profile.gamePath + "/game/ffxiv_dx11.exe";
|
2021-11-23 14:37:37 -05:00
|
|
|
}
|
|
|
|
|
2022-09-05 16:51:46 -04:00
|
|
|
if(profile.dalamud.enabled) {
|
|
|
|
beginDalamudGame(gameExectuable, profile, auth);
|
2021-11-02 08:49:06 -04:00
|
|
|
} else {
|
2022-09-05 16:51:46 -04:00
|
|
|
beginVanillaGame(gameExectuable, profile, auth);
|
2021-11-02 08:49:06 -04:00
|
|
|
}
|
|
|
|
|
2022-09-05 16:51:46 -04:00
|
|
|
successfulLaunch();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LauncherCore::beginVanillaGame(const QString& gameExecutablePath, const ProfileSettings& profile, const LoginAuth& auth) {
|
|
|
|
auto gameProcess = new QProcess();
|
|
|
|
gameProcess->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
|
|
|
|
|
|
|
|
auto args = getGameArgs(profile, auth);
|
|
|
|
|
|
|
|
launchExecutable(
|
|
|
|
profile,
|
|
|
|
gameProcess,
|
|
|
|
{gameExecutablePath, args},
|
|
|
|
true,
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LauncherCore::beginDalamudGame(const QString& gameExecutablePath, const ProfileSettings& profile, const LoginAuth& auth) {
|
|
|
|
QString gamePath = gameExecutablePath;
|
|
|
|
gamePath = "Z:" + gamePath.replace('/', '\\');
|
|
|
|
|
|
|
|
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
|
|
|
dataDir = "Z:" + dataDir.replace('/', '\\');
|
|
|
|
|
|
|
|
auto dalamudProcess = new QProcess();
|
|
|
|
|
|
|
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
|
|
|
env.insert("DALAMUD_RUNTIME", dataDir + "\\DalamudRuntime");
|
|
|
|
|
|
|
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
|
|
|
env.insert("XL_WINEONLINUX", "true");
|
|
|
|
#endif
|
|
|
|
dalamudProcess->setProcessEnvironment(env);
|
|
|
|
|
|
|
|
auto args = getGameArgs(profile, auth);
|
|
|
|
|
|
|
|
launchExecutable(
|
|
|
|
profile,
|
|
|
|
dalamudProcess,
|
|
|
|
{dataDir + "/Dalamud/" + "Dalamud.Injector.exe", "launch", "-m", "inject",
|
|
|
|
"--game=" + gamePath,
|
|
|
|
"--dalamud-configuration-path=" + dataDir + "\\dalamudConfig.json",
|
|
|
|
"--dalamud-plugin-directory=" + dataDir + "\\installedPlugins",
|
|
|
|
"--dalamud-asset-directory=" + dataDir + "\\DalamudAssets",
|
|
|
|
"--dalamud-client-language=" + QString::number(profile.language),
|
|
|
|
"--", args},
|
|
|
|
true,
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString LauncherCore::getGameArgs(const ProfileSettings& profile, const LoginAuth& auth) {
|
2021-11-09 21:26:16 -05:00
|
|
|
struct Argument {
|
|
|
|
QString key, value;
|
|
|
|
};
|
2021-11-02 08:36:30 -04:00
|
|
|
|
2021-11-09 21:26:16 -05:00
|
|
|
QList<Argument> gameArgs;
|
|
|
|
gameArgs.push_back({"DEV.DataPathType", QString::number(1)});
|
|
|
|
gameArgs.push_back({"DEV.UseSqPack", QString::number(1)});
|
|
|
|
|
|
|
|
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)});
|
2021-11-23 15:34:23 -05:00
|
|
|
gameArgs.push_back({"language", QString::number(profile.language)});
|
2022-08-09 23:18:18 -04:00
|
|
|
gameArgs.push_back({"ver", profile.repositories.repositories[0].version});
|
2021-11-02 08:36:30 -04:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (!auth.lobbyhost.isEmpty()) {
|
2021-11-09 21:26:16 -05:00
|
|
|
gameArgs.push_back({"DEV.GMServerHost", auth.frontierHost});
|
2022-08-15 11:14:37 -04:00
|
|
|
for (int i = 1; i < 9; i++) {
|
2021-11-09 21:26:16 -05:00
|
|
|
gameArgs.push_back({QString("DEV.LobbyHost0%1").arg(QString::number(i)), auth.lobbyhost});
|
|
|
|
gameArgs.push_back({QString("DEV.LobbyPort0%1").arg(QString::number(i)), QString::number(54994)});
|
|
|
|
}
|
2021-11-02 08:36:30 -04:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (profile.license == GameLicense::WindowsSteam) {
|
2022-01-30 16:57:44 -05:00
|
|
|
gameArgs.push_back({"IsSteam", "1"});
|
2022-03-16 14:33:04 -04:00
|
|
|
}
|
2022-02-25 20:06:29 -05:00
|
|
|
|
2022-03-28 20:24:24 +08:00
|
|
|
const QString argFormat = profile.encryptArguments ? " /%1 =%2" : " %1=%2";
|
2021-11-09 15:02:17 -05:00
|
|
|
|
2022-01-27 11:12:23 -05:00
|
|
|
QString argJoined;
|
2022-08-15 11:14:37 -04:00
|
|
|
for (const auto& arg : gameArgs) {
|
2022-01-27 11:12:23 -05:00
|
|
|
argJoined += argFormat.arg(arg.key, arg.value);
|
|
|
|
}
|
2021-11-09 21:26:16 -05:00
|
|
|
|
2022-09-05 16:51:46 -04:00
|
|
|
return profile.encryptArguments ? encryptGameArg(argJoined) : argJoined;
|
2021-11-02 08:36:30 -04:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
void LauncherCore::launchExecutable(const ProfileSettings& profile, const QStringList args) {
|
2021-11-01 09:54:58 -04:00
|
|
|
auto process = new QProcess(this);
|
2022-02-25 20:20:52 -05:00
|
|
|
process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
|
2022-04-14 17:48:06 -04:00
|
|
|
launchExecutable(profile, process, args, true, true);
|
2022-04-09 17:53:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LauncherCore::launchExternalTool(const ProfileSettings& profile, const QStringList args) {
|
|
|
|
auto process = new QProcess(this);
|
|
|
|
process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
|
2022-04-14 17:48:06 -04:00
|
|
|
launchExecutable(profile, process, args, false, true);
|
2021-11-23 14:37:37 -05:00
|
|
|
}
|
2021-11-01 09:54:58 -04:00
|
|
|
|
2022-02-25 20:20:52 -05:00
|
|
|
void LauncherCore::launchGameExecutable(const ProfileSettings& profile, QProcess* process, const QStringList args) {
|
2021-11-01 14:35:32 -04:00
|
|
|
QList<QString> arguments;
|
2021-11-02 20:04:53 -04:00
|
|
|
|
2022-02-25 22:25:39 -05:00
|
|
|
arguments.append(args);
|
|
|
|
|
2022-04-14 17:48:06 -04:00
|
|
|
launchExecutable(profile, process, arguments, true, true);
|
2022-02-25 22:25:39 -05:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
void LauncherCore::launchExecutable(
|
|
|
|
const ProfileSettings& profile,
|
|
|
|
QProcess* process,
|
|
|
|
const QStringList args,
|
|
|
|
bool isGame,
|
|
|
|
bool needsRegistrySetup) {
|
2022-02-25 22:25:39 -05:00
|
|
|
QList<QString> arguments;
|
|
|
|
auto env = process->processEnvironment();
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (needsRegistrySetup) {
|
2022-04-14 17:48:06 -04:00
|
|
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
2022-08-15 11:14:37 -04:00
|
|
|
if (profile.license == GameLicense::macOS) {
|
2022-04-14 17:48:06 -04:00
|
|
|
addRegistryKey(profile, "HKEY_CURRENT_USER\\Software\\Wine", "HideWineExports", "0");
|
|
|
|
} else {
|
|
|
|
addRegistryKey(profile, "HKEY_CURRENT_USER\\Software\\Wine", "HideWineExports", "1");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:54:58 -04:00
|
|
|
#if defined(Q_OS_LINUX)
|
2022-04-09 17:53:43 -04:00
|
|
|
if (isGame) {
|
|
|
|
if (profile.useGamescope) {
|
|
|
|
arguments.push_back("gamescope");
|
2022-02-23 21:18:53 -05:00
|
|
|
|
2022-04-09 17:53:43 -04:00
|
|
|
if (profile.gamescope.fullscreen)
|
|
|
|
arguments.push_back("-f");
|
2022-02-23 21:18:53 -05:00
|
|
|
|
2022-04-09 17:53:43 -04:00
|
|
|
if (profile.gamescope.borderless)
|
|
|
|
arguments.push_back("-b");
|
2022-02-23 21:18:53 -05:00
|
|
|
|
2022-04-09 17:53:43 -04:00
|
|
|
if (profile.gamescope.width > 0)
|
2022-08-15 11:14:37 -04:00
|
|
|
arguments.push_back("-w " + QString::number(profile.gamescope.width));
|
2022-02-23 21:18:53 -05:00
|
|
|
|
2022-04-09 17:53:43 -04:00
|
|
|
if (profile.gamescope.height > 0)
|
2022-08-15 11:14:37 -04:00
|
|
|
arguments.push_back("-h " + QString::number(profile.gamescope.height));
|
2022-02-23 21:18:53 -05:00
|
|
|
|
2022-04-09 17:53:43 -04:00
|
|
|
if (profile.gamescope.refreshRate > 0)
|
2022-08-15 11:14:37 -04:00
|
|
|
arguments.push_back("-r " + QString::number(profile.gamescope.refreshRate));
|
2022-04-09 17:53:43 -04:00
|
|
|
}
|
2021-11-01 09:54:58 -04:00
|
|
|
|
2022-04-09 17:53:43 -04:00
|
|
|
if (profile.useGamemode)
|
|
|
|
arguments.push_back("gamemoderun");
|
|
|
|
}
|
2022-02-25 20:20:52 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Q_OS_LINUX)
|
2022-08-15 11:14:37 -04:00
|
|
|
if (profile.useEsync) {
|
2022-02-25 20:06:29 -05:00
|
|
|
env.insert("WINEESYNC", QString::number(1));
|
|
|
|
env.insert("WINEFSYNC", QString::number(1));
|
|
|
|
env.insert("WINEFSYNC_FUTEX2", QString::number(1));
|
2022-02-24 08:41:37 -05:00
|
|
|
}
|
2021-11-03 06:18:31 -04:00
|
|
|
#endif
|
2021-11-01 09:54:58 -04:00
|
|
|
|
2021-11-03 06:31:02 -04:00
|
|
|
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
|
2022-02-25 20:06:29 -05:00
|
|
|
env.insert("WINEPREFIX", profile.winePrefixPath);
|
2021-11-01 14:35:32 -04:00
|
|
|
|
2022-04-14 16:29:23 -04:00
|
|
|
// XIV on Mac bundle their own Wine install directory, complete with libs etc
|
2022-08-15 11:14:37 -04:00
|
|
|
if (profile.wineType == WineType::XIVOnMac) {
|
2022-04-14 16:29:23 -04:00
|
|
|
// TODO: don't hardcode this
|
2022-08-15 11:14:37 -04:00
|
|
|
QString xivLibPath = "/Applications/XIV on Mac.app/Contents/Resources/wine/lib:/Applications/XIV on "
|
|
|
|
"Mac.app/Contents/Resources/MoltenVK/modern";
|
2022-04-14 16:29:23 -04:00
|
|
|
|
|
|
|
env.insert("DYLD_FALLBACK_LIBRARY_PATH", xivLibPath);
|
2022-04-27 11:45:09 -04:00
|
|
|
env.insert("DYLD_VERSIONED_LIBRARY_PATH", xivLibPath);
|
|
|
|
env.insert("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1");
|
|
|
|
env.insert("MVK_CONFIG_RESUME_LOST_DEVICE", "1");
|
|
|
|
env.insert("MVK_ALLOW_METAL_FENCES", "1");
|
|
|
|
env.insert("MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", "1");
|
2022-04-14 16:29:23 -04:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
#if defined(FLATPAK)
|
2022-04-17 22:31:22 -04:00
|
|
|
arguments.push_back("flatpak-spawn");
|
|
|
|
arguments.push_back("--host");
|
2022-08-15 11:14:37 -04:00
|
|
|
#endif
|
2022-04-17 22:31:22 -04:00
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
arguments.push_back(profile.winePath);
|
2021-11-03 06:31:02 -04:00
|
|
|
#endif
|
|
|
|
|
2021-11-02 08:36:30 -04:00
|
|
|
arguments.append(args);
|
2021-11-01 09:54:58 -04:00
|
|
|
|
2021-11-01 14:35:32 -04:00
|
|
|
auto executable = arguments[0];
|
|
|
|
arguments.removeFirst();
|
2021-11-03 06:18:31 -04:00
|
|
|
|
2022-04-09 17:53:43 -04:00
|
|
|
if (isGame)
|
|
|
|
process->setWorkingDirectory(profile.gamePath + "/game/");
|
|
|
|
|
2022-02-25 20:06:29 -05:00
|
|
|
process->setProcessEnvironment(env);
|
2021-11-23 14:37:37 -05:00
|
|
|
|
2021-11-01 14:35:32 -04:00
|
|
|
process->start(executable, arguments);
|
2021-11-01 09:54:58 -04:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
void LauncherCore::readInitialInformation() {
|
2021-11-09 12:25:54 -05:00
|
|
|
defaultProfileIndex = settings.value("defaultProfile", 0).toInt();
|
|
|
|
|
2022-04-10 16:58:29 -04:00
|
|
|
auto defaultAppSettings = AppSettings();
|
|
|
|
appSettings.closeWhenLaunched = settings.value("closeWhenLaunched", defaultAppSettings.closeWhenLaunched).toBool();
|
|
|
|
appSettings.showBanners = settings.value("showBanners", defaultAppSettings.showBanners).toBool();
|
|
|
|
appSettings.showNewsList = settings.value("showNewsList", defaultAppSettings.showNewsList).toBool();
|
2022-02-24 09:10:00 -05:00
|
|
|
|
2022-02-24 08:35:31 -05:00
|
|
|
gamescopeAvailable = checkIfInPath("gamescope");
|
|
|
|
gamemodeAvailable = checkIfInPath("gamemoderun");
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
const QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
2022-02-25 22:25:21 -05:00
|
|
|
|
|
|
|
const bool hasDalamud = QFile::exists(dataDir + "/Dalamud");
|
|
|
|
if (hasDalamud) {
|
|
|
|
if (QFile::exists(dataDir + "/Dalamud/Dalamud.deps.json")) {
|
|
|
|
QFile depsJson(dataDir + "/Dalamud/Dalamud.deps.json");
|
|
|
|
depsJson.open(QFile::ReadOnly);
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(depsJson.readAll());
|
|
|
|
|
2022-04-13 10:45:00 -04:00
|
|
|
QString versionString;
|
2022-08-15 11:14:37 -04:00
|
|
|
if (doc["targets"].toObject().contains(".NETCoreApp,Version=v5.0")) {
|
2022-04-13 10:45:00 -04:00
|
|
|
versionString =
|
2022-08-15 11:14:37 -04:00
|
|
|
doc["targets"].toObject()[".NETCoreApp,Version=v5.0"].toObject().keys().filter("Dalamud")[0];
|
2022-04-13 10:45:00 -04:00
|
|
|
} else {
|
|
|
|
versionString =
|
2022-08-15 11:14:37 -04:00
|
|
|
doc["targets"].toObject()[".NETCoreApp,Version=v6.0"].toObject().keys().filter("Dalamud")[0];
|
2022-04-13 10:45:00 -04:00
|
|
|
}
|
|
|
|
|
2022-02-25 22:25:21 -05:00
|
|
|
dalamudVersion = versionString.remove("Dalamud/");
|
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (QFile::exists(dataDir + "/DalamudAssets/asset.ver")) {
|
2022-02-25 22:25:21 -05:00
|
|
|
QFile assetJson(dataDir + "/DalamudAssets/asset.ver");
|
|
|
|
assetJson.open(QFile::ReadOnly | QFile::Text);
|
|
|
|
|
|
|
|
dalamudAssetVersion = QString(assetJson.readAll()).toInt();
|
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (QFile::exists(dataDir + "/DalamudRuntime/runtime.ver")) {
|
2022-02-25 22:25:21 -05:00
|
|
|
QFile runtimeVer(dataDir + "/DalamudRuntime/runtime.ver");
|
|
|
|
runtimeVer.open(QFile::ReadOnly | QFile::Text);
|
|
|
|
|
|
|
|
runtimeVersion = QString(runtimeVer.readAll());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-09 11:25:15 -05:00
|
|
|
auto profiles = settings.childGroups();
|
|
|
|
|
|
|
|
// create the Default profile if it doesnt exist
|
2022-08-15 11:14:37 -04:00
|
|
|
if (profiles.empty())
|
2021-11-09 13:26:59 -05:00
|
|
|
profiles.append(QUuid::createUuid().toString(QUuid::StringFormat::WithoutBraces));
|
2021-11-09 11:25:15 -05:00
|
|
|
|
2021-11-09 13:24:38 -05:00
|
|
|
profileSettings.resize(profiles.size());
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
for (const auto& uuid : profiles) {
|
2022-06-08 13:55:15 -04:00
|
|
|
ProfileSettings* profile = new ProfileSettings();
|
|
|
|
profile->uuid = QUuid(uuid);
|
2021-11-09 13:24:38 -05:00
|
|
|
|
|
|
|
settings.beginGroup(uuid);
|
2021-11-09 11:25:15 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->name = settings.value("name", "Default").toString();
|
2021-11-09 11:25:15 -05:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (settings.contains("gamePath") && settings.value("gamePath").canConvert<QString>() &&
|
|
|
|
!settings.value("gamePath").toString().isEmpty()) {
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->gamePath = settings.value("gamePath").toString();
|
2021-11-09 11:25:15 -05:00
|
|
|
} else {
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->gamePath = getDefaultGamePath();
|
2021-11-09 11:25:15 -05:00
|
|
|
}
|
2021-11-01 09:54:58 -04:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (settings.contains("winePrefixPath") && settings.value("winePrefixPath").canConvert<QString>() &&
|
|
|
|
!settings.value("winePrefixPath").toString().isEmpty()) {
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->winePrefixPath = settings.value("winePrefixPath").toString();
|
2021-11-09 11:25:15 -05:00
|
|
|
} else {
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->winePrefixPath = getDefaultWinePrefixPath();
|
2021-11-09 11:25:15 -05:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (settings.contains("winePath") && settings.value("winePath").canConvert<QString>() &&
|
|
|
|
!settings.value("winePath").toString().isEmpty()) {
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->winePath = settings.value("winePath").toString();
|
2022-03-28 22:06:01 +08:00
|
|
|
}
|
|
|
|
|
2022-02-25 20:32:08 -05:00
|
|
|
ProfileSettings defaultSettings;
|
|
|
|
|
2021-11-09 21:13:21 -05:00
|
|
|
// login
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->encryptArguments = settings.value("encryptArguments", defaultSettings.encryptArguments).toBool();
|
|
|
|
profile->isSapphire = settings.value("isSapphire", defaultSettings.isSapphire).toBool();
|
|
|
|
profile->lobbyURL = settings.value("lobbyURL", defaultSettings.lobbyURL).toString();
|
|
|
|
profile->rememberUsername = settings.value("rememberUsername", defaultSettings.rememberUsername).toBool();
|
|
|
|
profile->rememberPassword = settings.value("rememberPassword", defaultSettings.rememberPassword).toBool();
|
2022-08-31 17:27:30 -04:00
|
|
|
profile->rememberOTPSecret = settings.value("rememberOTPSecret", defaultSettings.rememberOTPSecret).toBool();
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->useOneTimePassword = settings.value("useOneTimePassword", defaultSettings.useOneTimePassword).toBool();
|
|
|
|
profile->license = (GameLicense)settings.value("license", (int)defaultSettings.license).toInt();
|
|
|
|
profile->isFreeTrial = settings.value("isFreeTrial", defaultSettings.isFreeTrial).toBool();
|
2022-08-31 17:14:54 -04:00
|
|
|
profile->autoLogin = settings.value("autoLogin", defaultSettings.autoLogin).toBool();
|
2021-11-09 12:32:18 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->useDX9 = settings.value("useDX9", defaultSettings.useDX9).toBool();
|
2022-04-09 17:28:24 -04:00
|
|
|
|
|
|
|
// wine
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->wineType = (WineType)settings.value("wineType", (int)defaultSettings.wineType).toInt();
|
|
|
|
profile->useEsync = settings.value("useEsync", defaultSettings.useEsync).toBool();
|
2022-02-24 08:35:31 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
readWineInfo(*profile);
|
2022-04-14 16:29:23 -04:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (gamescopeAvailable)
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->useGamescope = settings.value("useGamescope", defaultSettings.useGamescope).toBool();
|
2022-02-24 08:35:31 -05:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
if (gamemodeAvailable)
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->useGamemode = settings.value("useGamemode", defaultSettings.useGamemode).toBool();
|
2022-02-24 08:35:31 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->enableDXVKhud = settings.value("enableDXVKhud", defaultSettings.enableDXVKhud).toBool();
|
2022-04-09 17:28:24 -04:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->enableWatchdog = settings.value("enableWatchdog", defaultSettings.enableWatchdog).toBool();
|
2021-11-03 06:31:02 -04:00
|
|
|
|
2022-02-23 21:18:53 -05:00
|
|
|
// gamescope
|
2022-08-15 11:14:37 -04:00
|
|
|
profile->gamescope.borderless =
|
|
|
|
settings.value("gamescopeBorderless", defaultSettings.gamescope.borderless).toBool();
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->gamescope.width = settings.value("gamescopeWidth", defaultSettings.gamescope.width).toInt();
|
|
|
|
profile->gamescope.height = settings.value("gamescopeHeight", defaultSettings.gamescope.height).toInt();
|
2022-08-15 11:14:37 -04:00
|
|
|
profile->gamescope.refreshRate =
|
|
|
|
settings.value("gamescopeRefreshRate", defaultSettings.gamescope.refreshRate).toInt();
|
2022-02-23 21:18:53 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
profile->dalamud.enabled = settings.value("enableDalamud", defaultSettings.dalamud.enabled).toBool();
|
2022-08-15 11:14:37 -04:00
|
|
|
profile->dalamud.optOutOfMbCollection =
|
|
|
|
settings.value("dalamudOptOut", defaultSettings.dalamud.optOutOfMbCollection).toBool();
|
|
|
|
profile->dalamud.channel =
|
|
|
|
(DalamudChannel)settings.value("dalamudChannel", (int)defaultSettings.dalamud.channel).toInt();
|
2021-11-23 14:37:37 -05:00
|
|
|
|
2021-11-09 13:24:38 -05:00
|
|
|
profileSettings[settings.value("index").toInt()] = profile;
|
2021-11-02 08:50:14 -04:00
|
|
|
|
2021-11-09 13:24:38 -05:00
|
|
|
settings.endGroup();
|
2021-11-09 11:25:15 -05:00
|
|
|
}
|
2021-11-09 13:11:21 -05:00
|
|
|
|
|
|
|
readGameVersion();
|
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
2021-11-10 04:30:01 -05:00
|
|
|
#if defined(Q_OS_MAC)
|
2022-08-15 11:14:37 -04:00
|
|
|
switch (profile.wineType) {
|
2022-04-09 17:28:24 -04:00
|
|
|
case WineType::System: // system wine
|
2021-11-10 04:30:01 -05:00
|
|
|
profile.winePath = "/usr/local/bin/wine64";
|
|
|
|
break;
|
2022-04-09 17:28:24 -04:00
|
|
|
case WineType::Custom: // custom path
|
2021-11-10 04:30:01 -05:00
|
|
|
profile.winePath = profile.winePath;
|
|
|
|
break;
|
2022-04-09 17:28:24 -04:00
|
|
|
case WineType::Builtin: // ffxiv built-in (for mac users)
|
2022-08-15 11:14:37 -04:00
|
|
|
profile.winePath = "/Applications/FINAL FANTASY XIV "
|
|
|
|
"ONLINE.app/Contents/SharedSupport/finalfantasyxiv/FINAL FANTASY XIV ONLINE/wine";
|
2021-11-10 04:30:01 -05:00
|
|
|
break;
|
2022-04-14 16:29:23 -04:00
|
|
|
case WineType::XIVOnMac:
|
|
|
|
profile.winePath = "/Applications/XIV on Mac.app/Contents/Resources/wine/bin/wine64";
|
|
|
|
break;
|
2021-11-10 04:30:01 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Q_OS_LINUX)
|
2022-08-15 11:14:37 -04:00
|
|
|
switch (profile.wineType) {
|
|
|
|
case WineType::System: // system wine (should be in $PATH)
|
|
|
|
profile.winePath = "/usr/bin/wine";
|
|
|
|
break;
|
|
|
|
case WineType::Custom: // custom pth
|
|
|
|
profile.winePath = profile.winePath;
|
|
|
|
break;
|
|
|
|
}
|
2021-11-10 04:30:01 -05:00
|
|
|
#endif
|
2022-04-09 17:28:24 -04:00
|
|
|
|
|
|
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
2022-07-21 21:38:26 -04:00
|
|
|
auto wineProcess = new QProcess(this);
|
2022-04-09 17:28:24 -04:00
|
|
|
wineProcess->setProcessChannelMode(QProcess::MergedChannels);
|
|
|
|
|
|
|
|
connect(wineProcess, &QProcess::readyRead, this, [wineProcess, &profile] {
|
|
|
|
profile.wineVersion = wineProcess->readAllStandardOutput().trimmed();
|
|
|
|
});
|
|
|
|
|
2022-04-17 22:31:22 -04:00
|
|
|
launchExecutable(profile, wineProcess, {"--version"}, false, false);
|
|
|
|
|
2022-04-09 17:28:24 -04:00
|
|
|
wineProcess->waitForFinished();
|
|
|
|
#endif
|
2021-11-10 04:30:01 -05:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
void LauncherCore::readGameVersion() {
|
2022-08-15 11:14:37 -04:00
|
|
|
for (auto& profile : profileSettings) {
|
2022-08-09 23:18:18 -04:00
|
|
|
profile->gameData = physis_gamedata_initialize((profile->gamePath + "/game").toStdString().c_str());
|
|
|
|
profile->bootData = physis_bootdata_initialize((profile->gamePath + "/boot").toStdString().c_str());
|
2021-12-02 15:02:59 -05:00
|
|
|
|
2022-08-09 23:18:18 -04:00
|
|
|
profile->repositories = physis_gamedata_get_repositories(profile->gameData);
|
|
|
|
profile->bootVersion = physis_bootdata_get_version(profile->bootData);
|
2022-05-09 15:04:56 -04:00
|
|
|
|
2022-08-09 23:18:18 -04:00
|
|
|
readGameData(*profile);
|
2021-11-09 13:11:21 -05:00
|
|
|
}
|
2021-11-01 09:54:58 -04:00
|
|
|
}
|
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
LauncherCore::LauncherCore()
|
|
|
|
: settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::applicationName()) {
|
2021-11-01 09:54:58 -04:00
|
|
|
mgr = new QNetworkAccessManager();
|
|
|
|
sapphireLauncher = new SapphireLauncher(*this);
|
|
|
|
squareLauncher = new SquareLauncher(*this);
|
|
|
|
squareBoot = new SquareBoot(*this, *squareLauncher);
|
2021-11-23 14:37:37 -05:00
|
|
|
assetUpdater = new AssetUpdater(*this);
|
2022-09-05 15:43:15 -04:00
|
|
|
steamApi = new SteamAPI();
|
2022-01-27 09:25:23 -05:00
|
|
|
|
|
|
|
#ifdef ENABLE_WATCHDOG
|
2021-12-06 21:15:31 -05:00
|
|
|
watchdog = new Watchdog(*this);
|
2022-01-27 09:25:23 -05:00
|
|
|
#endif
|
2021-11-01 09:54:58 -04:00
|
|
|
|
2021-11-09 11:25:15 -05:00
|
|
|
readInitialInformation();
|
2021-11-09 12:06:30 -05:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
ProfileSettings& LauncherCore::getProfile(int index) {
|
2022-06-08 13:55:15 -04:00
|
|
|
return *profileSettings[index];
|
2021-11-09 11:03:44 -05:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
int LauncherCore::getProfileIndex(QString name) {
|
2022-08-15 11:14:37 -04:00
|
|
|
for (int i = 0; i < profileSettings.size(); i++) {
|
|
|
|
if (profileSettings[i]->name == name)
|
2021-11-09 11:25:15 -05:00
|
|
|
return i;
|
2021-11-09 11:03:44 -05:00
|
|
|
}
|
2021-11-09 11:25:15 -05:00
|
|
|
|
|
|
|
return -1;
|
2021-11-09 11:03:44 -05:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
QList<QString> LauncherCore::profileList() const {
|
2021-11-09 11:03:44 -05:00
|
|
|
QList<QString> list;
|
2022-08-15 11:14:37 -04:00
|
|
|
for (auto profile : profileSettings) {
|
2022-06-08 13:55:15 -04:00
|
|
|
list.append(profile->name);
|
2021-11-09 11:03:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
2021-11-09 11:44:27 -05:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
int LauncherCore::addProfile() {
|
2022-06-08 13:55:15 -04:00
|
|
|
ProfileSettings* newProfile = new ProfileSettings();
|
|
|
|
newProfile->uuid = QUuid::createUuid();
|
|
|
|
newProfile->name = "New Profile";
|
2021-11-09 11:44:27 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
readWineInfo(*newProfile);
|
2022-02-25 20:37:38 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
newProfile->gamePath = getDefaultGamePath();
|
|
|
|
newProfile->winePrefixPath = getDefaultWinePrefixPath();
|
2022-02-25 20:37:38 -05:00
|
|
|
|
2021-11-09 11:44:27 -05:00
|
|
|
profileSettings.append(newProfile);
|
|
|
|
|
|
|
|
settingsChanged();
|
|
|
|
|
|
|
|
return profileSettings.size() - 1;
|
2021-11-09 12:16:14 -05:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
int LauncherCore::deleteProfile(QString name) {
|
2021-11-09 13:44:37 -05:00
|
|
|
int index = 0;
|
2022-08-15 11:14:37 -04:00
|
|
|
for (int i = 0; i < profileSettings.size(); i++) {
|
|
|
|
if (profileSettings[i]->name == name)
|
2021-11-09 13:44:37 -05:00
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove group so it doesnt stay
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.beginGroup(profileSettings[index]->uuid.toString(QUuid::StringFormat::WithoutBraces));
|
2021-11-09 13:44:37 -05:00
|
|
|
settings.remove("");
|
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
profileSettings.removeAt(index);
|
|
|
|
|
|
|
|
return index - 1;
|
|
|
|
}
|
|
|
|
|
2021-11-23 15:34:23 -05:00
|
|
|
void LauncherCore::saveSettings() {
|
2021-11-09 13:24:38 -05:00
|
|
|
settings.setValue("defaultProfile", defaultProfileIndex);
|
2022-02-24 09:10:00 -05:00
|
|
|
settings.setValue("closeWhenLaunched", appSettings.closeWhenLaunched);
|
2022-04-10 16:58:29 -04:00
|
|
|
settings.setValue("showBanners", appSettings.showBanners);
|
|
|
|
settings.setValue("showNewsList", appSettings.showNewsList);
|
2021-11-09 13:24:38 -05:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
for (int i = 0; i < profileSettings.size(); i++) {
|
2021-11-09 13:24:38 -05:00
|
|
|
const auto& profile = profileSettings[i];
|
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.beginGroup(profile->uuid.toString(QUuid::StringFormat::WithoutBraces));
|
2021-11-09 13:24:38 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.setValue("name", profile->name);
|
2021-11-09 13:24:38 -05:00
|
|
|
settings.setValue("index", i);
|
2021-11-09 12:16:14 -05:00
|
|
|
|
2021-11-09 13:04:22 -05:00
|
|
|
// game
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.setValue("useDX9", profile->useDX9);
|
|
|
|
settings.setValue("gamePath", profile->gamePath);
|
2021-11-09 12:40:44 -05:00
|
|
|
|
2021-11-09 13:04:22 -05:00
|
|
|
// wine
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.setValue("wineType", (int)profile->wineType);
|
|
|
|
settings.setValue("winePath", profile->winePath);
|
|
|
|
settings.setValue("winePrefixPath", profile->winePrefixPath);
|
2021-11-09 13:04:22 -05:00
|
|
|
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.setValue("useEsync", profile->useEsync);
|
|
|
|
settings.setValue("useGamescope", profile->useGamescope);
|
|
|
|
settings.setValue("useGamemode", profile->useGamemode);
|
2021-11-09 13:08:25 -05:00
|
|
|
|
2022-02-23 21:18:53 -05:00
|
|
|
// gamescope
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.setValue("gamescopeFullscreen", profile->gamescope.fullscreen);
|
|
|
|
settings.setValue("gamescopeBorderless", profile->gamescope.borderless);
|
|
|
|
settings.setValue("gamescopeWidth", profile->gamescope.width);
|
|
|
|
settings.setValue("gamescopeHeight", profile->gamescope.height);
|
|
|
|
settings.setValue("gamescopeRefreshRate", profile->gamescope.refreshRate);
|
2022-02-23 21:18:53 -05:00
|
|
|
|
2021-11-09 13:04:22 -05:00
|
|
|
// login
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.setValue("encryptArguments", profile->encryptArguments);
|
|
|
|
settings.setValue("isSapphire", profile->isSapphire);
|
|
|
|
settings.setValue("lobbyURL", profile->lobbyURL);
|
|
|
|
settings.setValue("rememberUsername", profile->rememberUsername);
|
|
|
|
settings.setValue("rememberPassword", profile->rememberPassword);
|
2022-08-31 17:27:30 -04:00
|
|
|
settings.setValue("rememberOTPSecret", profile->rememberOTPSecret);
|
2022-06-08 13:55:15 -04:00
|
|
|
settings.setValue("useOneTimePassword", profile->useOneTimePassword);
|
|
|
|
settings.setValue("license", (int)profile->license);
|
|
|
|
settings.setValue("isFreeTrial", profile->isFreeTrial);
|
2022-08-31 17:14:54 -04:00
|
|
|
settings.setValue("autoLogin", profile->autoLogin);
|
2022-06-08 13:55:15 -04:00
|
|
|
|
|
|
|
settings.setValue("enableDalamud", profile->dalamud.enabled);
|
|
|
|
settings.setValue("dalamudOptOut", profile->dalamud.optOutOfMbCollection);
|
|
|
|
settings.setValue("dalamudChannel", (int)profile->dalamud.channel);
|
|
|
|
settings.setValue("enableWatchdog", profile->enableWatchdog);
|
2021-11-23 14:37:37 -05:00
|
|
|
|
2021-11-09 12:16:14 -05:00
|
|
|
settings.endGroup();
|
|
|
|
}
|
2021-12-02 14:40:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void LauncherCore::addUpdateButtons(const ProfileSettings& settings, QMessageBox& messageBox) {
|
|
|
|
auto launcherButton = messageBox.addButton("Launch Official Launcher", QMessageBox::NoRole);
|
2022-06-08 13:55:15 -04:00
|
|
|
connect(launcherButton, &QPushButton::clicked, [&] {
|
2021-12-02 22:26:08 -05:00
|
|
|
launchExecutable(settings, {settings.gamePath + "/boot/ffxivboot.exe"});
|
2021-12-02 14:40:04 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
messageBox.addButton(QMessageBox::StandardButton::Ok);
|
2021-12-02 15:02:59 -05:00
|
|
|
}
|
|
|
|
|
2022-02-24 08:35:31 -05:00
|
|
|
bool LauncherCore::checkIfInPath(const QString program) {
|
|
|
|
// TODO: also check /usr/local/bin, /bin32 etc (basically read $PATH)
|
|
|
|
const QString directory = "/usr/bin";
|
|
|
|
|
|
|
|
QFileInfo fileInfo(directory + "/" + program);
|
|
|
|
|
|
|
|
return fileInfo.exists() && fileInfo.isFile();
|
2022-02-25 20:37:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
QString LauncherCore::getDefaultWinePrefixPath() {
|
|
|
|
#if defined(Q_OS_MACOS)
|
|
|
|
return QDir::homePath() + "/Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Q_OS_LINUX)
|
|
|
|
return QDir::homePath() + "/.wine";
|
|
|
|
#endif
|
2022-03-14 19:04:23 +00:00
|
|
|
|
|
|
|
return "";
|
2022-02-25 20:37:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
QString LauncherCore::getDefaultGamePath() {
|
|
|
|
#if defined(Q_OS_WIN)
|
|
|
|
return "C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Q_OS_MAC)
|
2022-08-15 11:14:37 -04:00
|
|
|
return QDir::homePath() +
|
|
|
|
"/Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program "
|
|
|
|
"Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn";
|
2022-02-25 20:37:38 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Q_OS_LINUX)
|
|
|
|
return QDir::homePath() + "/.wine/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn";
|
|
|
|
#endif
|
|
|
|
}
|
2022-04-14 17:48:06 -04:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
void LauncherCore::addRegistryKey(const ProfileSettings& settings, QString key, QString value, QString data) {
|
2022-04-14 17:48:06 -04:00
|
|
|
auto process = new QProcess(this);
|
|
|
|
process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
|
2022-08-15 11:14:37 -04:00
|
|
|
launchExecutable(settings, process, {"reg", "add", key, "/v", value, "/d", data, "/f"}, false, false);
|
2022-05-09 15:04:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LauncherCore::readGameData(ProfileSettings& profile) {
|
2022-08-09 22:44:10 -04:00
|
|
|
EXH* exh = physis_gamedata_read_excel_sheet_header(profile.gameData, "ExVersion");
|
2022-08-15 11:14:37 -04:00
|
|
|
if (exh != nullptr) {
|
2022-08-09 22:44:10 -04:00
|
|
|
physis_EXD exd = physis_gamedata_read_excel_sheet(profile.gameData, "ExVersion", exh, Language::English, 0);
|
2022-05-09 15:04:56 -04:00
|
|
|
|
2022-08-15 11:14:37 -04:00
|
|
|
for (int i = 0; i < exd.row_count; i++) {
|
2022-07-21 20:53:19 -04:00
|
|
|
expansionNames.push_back(exd.row_data[i].column_data[0].string._0);
|
2022-05-09 15:04:56 -04:00
|
|
|
}
|
2022-07-21 21:18:27 -04:00
|
|
|
|
|
|
|
physis_gamedata_free_sheet(exd);
|
|
|
|
physis_gamedata_free_sheet_header(exh);
|
2022-05-09 15:04:56 -04:00
|
|
|
}
|
|
|
|
}
|
2022-09-05 16:05:39 -04:00
|
|
|
|
|
|
|
void LauncherCore::login(LoginInformation& loginInformation) {
|
|
|
|
if (loginInformation.settings->isSapphire) {
|
|
|
|
sapphireLauncher->login(loginInformation.settings->lobbyURL, loginInformation);
|
|
|
|
} else {
|
|
|
|
squareBoot->checkGateStatus(&loginInformation);
|
|
|
|
}
|
|
|
|
}
|
2022-09-05 16:14:07 -04:00
|
|
|
|
|
|
|
bool LauncherCore::autoLogin(ProfileSettings& profile) {
|
|
|
|
auto loop = new QEventLoop();
|
|
|
|
|
|
|
|
QString username, password;
|
|
|
|
QString otpSecret;
|
|
|
|
|
|
|
|
auto usernameJob = new QKeychain::ReadPasswordJob("LauncherWindow");
|
|
|
|
usernameJob->setKey(profile.name + "-username");
|
|
|
|
usernameJob->start();
|
|
|
|
|
|
|
|
QObject::connect(
|
|
|
|
usernameJob, &QKeychain::ReadPasswordJob::finished, [loop, usernameJob, &username](QKeychain::Job* j) {
|
|
|
|
username = usernameJob->textData();
|
|
|
|
loop->quit();
|
|
|
|
});
|
|
|
|
|
|
|
|
loop->exec();
|
|
|
|
|
|
|
|
auto passwordJob = new QKeychain::ReadPasswordJob("LauncherWindow");
|
|
|
|
passwordJob->setKey(profile.name + "-password");
|
|
|
|
passwordJob->start();
|
|
|
|
|
|
|
|
QObject::connect(
|
|
|
|
passwordJob, &QKeychain::ReadPasswordJob::finished, [loop, passwordJob, &password](QKeychain::Job* j) {
|
|
|
|
password = passwordJob->textData();
|
|
|
|
loop->quit();
|
|
|
|
});
|
|
|
|
|
|
|
|
loop->exec();
|
|
|
|
|
|
|
|
// TODO: handle cases where the user doesn't want to store their OTP secret, so we have to manually prompt them
|
|
|
|
if(profile.useOneTimePassword && profile.rememberOTPSecret) {
|
|
|
|
auto otpJob = new QKeychain::ReadPasswordJob("LauncherWindow");
|
|
|
|
otpJob->setKey(profile.name + "-otpsecret");
|
|
|
|
otpJob->start();
|
|
|
|
|
|
|
|
QObject::connect(
|
|
|
|
otpJob, &QKeychain::ReadPasswordJob::finished, [loop, otpJob, &otpSecret](QKeychain::Job* j) {
|
|
|
|
otpSecret = otpJob->textData();
|
|
|
|
loop->quit();
|
|
|
|
});
|
|
|
|
|
|
|
|
loop->exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto info = new LoginInformation();
|
|
|
|
info->settings = &profile;
|
|
|
|
info->username = username;
|
|
|
|
info->password = password;
|
|
|
|
|
|
|
|
if(profile.useOneTimePassword && !profile.rememberOTPSecret)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(profile.useOneTimePassword && profile.rememberOTPSecret) {
|
|
|
|
// generate otp
|
|
|
|
char* totp = get_totp (otpSecret.toStdString().c_str(), 6, 30, SHA1, nullptr);
|
|
|
|
info->oneTimePassword = totp;
|
|
|
|
free (totp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: when login fails, we need some way to propagate this back? or not?
|
|
|
|
login(*info);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|