diff --git a/launcher/config.kcfg b/launcher/config.kcfg
index 07abb68..683a5b6 100644
--- a/launcher/config.kcfg
+++ b/launcher/config.kcfg
@@ -20,5 +20,14 @@ SPDX-License-Identifier: CC0-1.0
false
+
+ goatcorp.github.io
+
+
+ ffxiv.com
+
+
+ square-enix.com
+
diff --git a/launcher/include/assetupdater.h b/launcher/include/assetupdater.h
index 5bc4f27..42f12d1 100644
--- a/launcher/include/assetupdater.h
+++ b/launcher/include/assetupdater.h
@@ -29,6 +29,10 @@ signals:
void finishedUpdating();
private:
+ QUrl dalamudVersionManifestUrl(Profile::DalamudChannel channel) const;
+ QUrl dalamudLatestPackageUrl(Profile::DalamudChannel channel) const;
+ QUrl dalamudAssetManifestUrl() const;
+
LauncherCore &launcher;
Profile::DalamudChannel chosenChannel;
diff --git a/launcher/include/launchercore.h b/launcher/include/launchercore.h
index bade3b3..94429ff 100755
--- a/launcher/include/launchercore.h
+++ b/launcher/include/launchercore.h
@@ -64,6 +64,9 @@ class LauncherCore : public QObject
Q_PROPERTY(bool closeWhenLaunched READ closeWhenLaunched WRITE setCloseWhenLaunched NOTIFY closeWhenLaunchedChanged)
Q_PROPERTY(bool showNews READ showNews WRITE setShowNews NOTIFY showNewsChanged)
Q_PROPERTY(bool keepPatches READ keepPatches WRITE setKeepPatches NOTIFY keepPatchesChanged)
+ Q_PROPERTY(QString dalamudDistribServer READ dalamudDistribServer WRITE setDalamudDistribServer NOTIFY dalamudDistribServerChanged)
+ Q_PROPERTY(QString squareEnixServer READ squareEnixServer WRITE setSquareEnixServer NOTIFY squareEnixServerChanged)
+ Q_PROPERTY(QString squareEnixLoginServer READ squareEnixLoginServer WRITE setSquareEnixLoginServer NOTIFY squareEnixLoginServerChanged)
Q_PROPERTY(Headline *headline READ headline NOTIFY newsChanged)
public:
@@ -124,6 +127,15 @@ public:
bool keepPatches() const;
void setKeepPatches(bool value);
+ QString dalamudDistribServer() const;
+ void setDalamudDistribServer(const QString &value);
+
+ QString squareEnixServer() const;
+ void setSquareEnixServer(const QString &value);
+
+ QString squareEnixLoginServer() const;
+ void setSquareEnixLoginServer(const QString &value);
+
int defaultProfileIndex = 0;
bool m_isSteam = false;
@@ -152,6 +164,9 @@ signals:
void closeWhenLaunchedChanged();
void showNewsChanged();
void keepPatchesChanged();
+ void dalamudDistribServerChanged();
+ void squareEnixServerChanged();
+ void squareEnixLoginServerChanged();
void loginError(QString message);
void stageChanged(QString message);
void stageIndeterminate();
diff --git a/launcher/src/assetupdater.cpp b/launcher/src/assetupdater.cpp
index b1071be..347ea3c 100644
--- a/launcher/src/assetupdater.cpp
+++ b/launcher/src/assetupdater.cpp
@@ -11,22 +11,9 @@
#include
-const QString baseGoatDomain = "https://goatcorp.github.io";
-
-const QString baseDalamudDistribution = baseGoatDomain + "/dalamud-distrib/";
-const QString dalamudLatestPackageURL = baseDalamudDistribution + "%1latest.zip";
-const QString dalamudVersionManifestURL = baseDalamudDistribution + "%1version";
-
-const QString baseDalamudAssetDistribution = baseGoatDomain + "/DalamudAssets";
-const QString dalamudAssetManifestURL = baseDalamudAssetDistribution + "/asset.json";
-
const QString dotnetRuntimePackageURL = "https://dotnetcli.azureedge.net/dotnet/Runtime/%1/dotnet-runtime-%1-win-x64.zip";
const QString dotnetDesktopPackageURL = "https://dotnetcli.azureedge.net/dotnet/WindowsDesktop/%1/windowsdesktop-runtime-%1-win-x64.zip";
-QMap channelToDistribPrefix = {{Profile::DalamudChannel::Stable, "/"},
- {Profile::DalamudChannel::Staging, "stg/"},
- {Profile::DalamudChannel::Net5, "net5/"}};
-
AssetUpdater::AssetUpdater(Profile &profile, LauncherCore &launcher, QObject *parent)
: QObject(parent)
, launcher(launcher)
@@ -74,7 +61,7 @@ void AssetUpdater::update()
dalamudAssetNeededFilenames.append("dummy");
// first we want to fetch the list of assets required
- QNetworkRequest request(dalamudAssetManifestURL);
+ QNetworkRequest request(dalamudAssetManifestUrl());
auto reply = launcher.mgr->get(request);
connect(reply, &QNetworkReply::finished, [reply, this] {
@@ -97,7 +84,7 @@ void AssetUpdater::update()
// dalamud injector / net runtime
// they're all updated in unison, so there's no reason to have multiple checks
{
- QNetworkRequest request(dalamudVersionManifestURL.arg(channelToDistribPrefix[m_profile.dalamudChannel()]));
+ QNetworkRequest request(dalamudVersionManifestUrl(m_profile.dalamudChannel()));
chosenChannel = m_profile.dalamudChannel();
@@ -260,7 +247,7 @@ void AssetUpdater::checkIfCheckingIsDone()
needsDalamudInstall = true;
- QNetworkRequest request(dalamudLatestPackageURL.arg(channelToDistribPrefix[chosenChannel]));
+ QNetworkRequest request(dalamudLatestPackageUrl(chosenChannel));
auto reply = launcher.mgr->get(request);
connect(reply, &QNetworkReply::finished, [this, reply] {
@@ -330,3 +317,37 @@ void AssetUpdater::checkIfCheckingIsDone()
checkIfFinished();
}
}
+
+static const QMap channelToDistribPrefix = {{Profile::DalamudChannel::Stable, "/"},
+ {Profile::DalamudChannel::Staging, "stg/"},
+ {Profile::DalamudChannel::Net5, "net5/"}};
+
+QUrl AssetUpdater::dalamudVersionManifestUrl(const Profile::DalamudChannel channel) const
+{
+ QUrl url;
+ url.setScheme("https");
+ url.setHost(launcher.dalamudDistribServer());
+ url.setPath(QStringLiteral("/dalamud-distrib/%1version").arg(channelToDistribPrefix[channel]));
+
+ return url;
+}
+
+QUrl AssetUpdater::dalamudLatestPackageUrl(Profile::DalamudChannel channel) const
+{
+ QUrl url;
+ url.setScheme("https");
+ url.setHost(launcher.dalamudDistribServer());
+ url.setPath(QStringLiteral("/dalamud-distrib/%1latest.zip").arg(channelToDistribPrefix[channel]));
+
+ return url;
+}
+
+QUrl AssetUpdater::dalamudAssetManifestUrl() const
+{
+ QUrl url;
+ url.setScheme("https");
+ url.setHost(launcher.dalamudDistribServer());
+ url.setPath(QStringLiteral("/DalamudAssets/asset.json"));
+
+ return url;
+}
diff --git a/launcher/src/launchercore.cpp b/launcher/src/launchercore.cpp
index 0483df1..a95dc28 100755
--- a/launcher/src/launchercore.cpp
+++ b/launcher/src/launchercore.cpp
@@ -107,17 +107,26 @@ void LauncherCore::beginDalamudGame(const QString &gameExecutablePath, const Pro
const QDir dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
const QDir configDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
const QDir stateDir = Utility::stateDirectory();
+ const QDir dalamudDir = dataDir.absoluteFilePath("dalamud");
+
+ const QDir dalamudConfigDir = configDir.absoluteFilePath("dalamud");
+ const QDir userDalamudConfigDir = dalamudConfigDir.absoluteFilePath(profile.account()->uuid());
+
+ const QDir dalamudBasePluginDir = dalamudDir.absoluteFilePath("plugins");
+ const QDir dalamudUserPluginDir = dalamudBasePluginDir.absoluteFilePath(profile.account()->uuid());
+
+ // Some really dumb plugins check for "installedPlugins" in their assembly directory FOR SOME REASON
+ // so we need to match typical XIVQuickLauncher behavior here. Why? I have no clue.
+ const QDir dalamudPluginDir = dalamudUserPluginDir.absoluteFilePath("installedPlugins");
const QString logDir = stateDir.absoluteFilePath("logs");
if (!QDir().exists(logDir))
QDir().mkpath(logDir);
- const QDir dalamudDir = dataDir.absoluteFilePath("dalamud");
const QDir dalamudRuntimeDir = dalamudDir.absoluteFilePath("runtime");
const QDir dalamudAssetDir = dalamudDir.absoluteFilePath("assets");
- const QDir dalamudConfigPath = configDir.absoluteFilePath("dalamud-config.json");
- const QDir dalamudPluginDir = dalamudDir.absoluteFilePath("plugins");
+ const QDir dalamudConfigPath = userDalamudConfigDir.absoluteFilePath("dalamud-config.json");
const QDir dalamudInstallDir = dalamudDir.absoluteFilePath(profile.dalamudChannelName());
const QString dalamudInjector = dalamudInstallDir.absoluteFilePath("Dalamud.Injector.exe");
@@ -145,7 +154,6 @@ void LauncherCore::beginDalamudGame(const QString &gameExecutablePath, const Pro
"-m",
"inject",
"--game=" + Utility::toWindowsPath(gameExecutablePath),
- "--dalamud-working-directory=" + Utility::toWindowsPath(dalamudDir),
"--dalamud-configuration-path=" + Utility::toWindowsPath(dalamudConfigPath),
"--dalamud-plugin-directory=" + Utility::toWindowsPath(dalamudPluginDir),
"--dalamud-asset-directory=" + Utility::toWindowsPath(dalamudAssetDir),
@@ -465,6 +473,48 @@ void LauncherCore::setKeepPatches(const bool value)
}
}
+QString LauncherCore::dalamudDistribServer() const
+{
+ return Config::dalamudDistribServer();
+}
+
+void LauncherCore::setDalamudDistribServer(const QString &value)
+{
+ if (value != Config::dalamudDistribServer()) {
+ Config::setDalamudDistribServer(value);
+ Config::self()->save();
+ Q_EMIT dalamudDistribServerChanged();
+ }
+}
+
+QString LauncherCore::squareEnixServer() const
+{
+ return Config::squareEnixServer();
+}
+
+void LauncherCore::setSquareEnixServer(const QString &value)
+{
+ if (value != Config::squareEnixServer()) {
+ Config::setSquareEnixServer(value);
+ Config::self()->save();
+ Q_EMIT squareEnixServerChanged();
+ }
+}
+
+QString LauncherCore::squareEnixLoginServer() const
+{
+ return Config::squareEnixLoginServer();
+}
+
+void LauncherCore::setSquareEnixLoginServer(const QString &value)
+{
+ if (value != Config::squareEnixLoginServer()) {
+ Config::setSquareEnixLoginServer(value);
+ Config::self()->save();
+ Q_EMIT squareEnixLoginServerChanged();
+ }
+}
+
void LauncherCore::refreshNews()
{
QUrlQuery query;
@@ -473,7 +523,7 @@ void LauncherCore::refreshNews()
QUrl url;
url.setScheme("https");
- url.setHost("frontier.ffxiv.com");
+ url.setHost(QStringLiteral("frontier.%1").arg(squareEnixServer()));
url.setPath("/news/headline.json");
url.setQuery(query);
diff --git a/launcher/src/profile.cpp b/launcher/src/profile.cpp
index 70a2edd..229f2ad 100644
--- a/launcher/src/profile.cpp
+++ b/launcher/src/profile.cpp
@@ -21,12 +21,18 @@ Profile::Profile(LauncherCore &launcher, const QString &key, QObject *parent)
readGameVersion();
readWineInfo();
- const QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
+ const QDir dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
- const bool hasDalamud = QFile::exists(dataDir + "/Dalamud");
- if (hasDalamud) {
- if (QFile::exists(dataDir + "/Dalamud/Dalamud.deps.json")) {
- QFile depsJson(dataDir + "/Dalamud/Dalamud.deps.json");
+ const QDir dalamudDir = dataDir.absoluteFilePath("dalamud");
+
+ if (dalamudDir.exists()) {
+ const QDir dalamudInstallDir = dalamudDir.absoluteFilePath(dalamudChannelName());
+ const QDir dalamudAssetsDir = dalamudDir.absoluteFilePath("assets");
+ const QDir dalamudRuntimeDir = dalamudDir.absoluteFilePath("runtime");
+
+ const QString dalamudDepsJson = dalamudInstallDir.absoluteFilePath("Dalamud.deps.json");
+ if (QFile::exists(dalamudDepsJson)) {
+ QFile depsJson(dalamudDepsJson);
depsJson.open(QFile::ReadOnly);
QJsonDocument doc = QJsonDocument::fromJson(depsJson.readAll());
@@ -40,15 +46,17 @@ Profile::Profile(LauncherCore &launcher, const QString &key, QObject *parent)
dalamudVersion = versionString.remove("Dalamud/");
}
- if (QFile::exists(dataDir + "/DalamudAssets/asset.ver")) {
- QFile assetJson(dataDir + "/DalamudAssets/asset.ver");
+ const QString dalamudAssetsVer = dalamudAssetsDir.absoluteFilePath("asset.ver");
+ if (QFile::exists(dalamudAssetsVer)) {
+ QFile assetJson(dalamudAssetsVer);
assetJson.open(QFile::ReadOnly | QFile::Text);
dalamudAssetVersion = QString(assetJson.readAll()).toInt();
}
- if (QFile::exists(dataDir + "/DalamudRuntime/runtime.ver")) {
- QFile runtimeVer(dataDir + "/DalamudRuntime/runtime.ver");
+ const QString dalamudRuntimeVer = dalamudRuntimeDir.absoluteFilePath("runtime.ver");
+ if (QFile::exists(dalamudRuntimeVer)) {
+ QFile runtimeVer(dalamudRuntimeVer);
runtimeVer.open(QFile::ReadOnly | QFile::Text);
runtimeVersion = QString(runtimeVer.readAll());
diff --git a/launcher/src/squareboot.cpp b/launcher/src/squareboot.cpp
index e75c424..5e6bd28 100644
--- a/launcher/src/squareboot.cpp
+++ b/launcher/src/squareboot.cpp
@@ -38,7 +38,7 @@ void SquareBoot::bootCheck(const LoginInformation &info)
QUrl url;
url.setScheme("http");
- url.setHost("patch-bootver.ffxiv.com");
+ url.setHost(QStringLiteral("patch-bootver.%1").arg(window.squareEnixServer()));
url.setPath(QString("/http/win32/ffxivneo_release_boot/%1").arg(info.profile->bootVersion));
url.setQuery(query);
@@ -49,7 +49,7 @@ void SquareBoot::bootCheck(const LoginInformation &info)
request.setRawHeader("User-Agent", "FFXIV PATCH CLIENT");
}
- request.setRawHeader("Host", "patch-bootver.ffxiv.com");
+ request.setRawHeader("Host", QStringLiteral("patch-bootver.%1").arg(window.squareEnixServer()).toUtf8());
auto reply = window.mgr->get(request);
connect(reply, &QNetworkReply::finished, [this, reply] {
@@ -64,7 +64,10 @@ void SquareBoot::checkGateStatus(LoginInformation *info)
Q_EMIT window.stageChanged(i18n("Checking gate..."));
qDebug() << "Checking gate...";
- QUrl url("https://frontier.ffxiv.com/worldStatus/gate_status.json");
+ QUrl url;
+ url.setScheme("https");
+ url.setHost(QStringLiteral("frontier.%1").arg(window.squareEnixServer()));
+ url.setPath("/worldStatus/gate_status.json");
url.setQuery(QString::number(QDateTime::currentMSecsSinceEpoch()));
QNetworkRequest request(url);
diff --git a/launcher/src/squarelauncher.cpp b/launcher/src/squarelauncher.cpp
index bfaee19..25180c8 100644
--- a/launcher/src/squarelauncher.cpp
+++ b/launcher/src/squarelauncher.cpp
@@ -53,7 +53,10 @@ void SquareLauncher::getStored(const LoginInformation &info)
query.addQueryItem("ticket_size", "1");
}
- QUrl url("https://ffxiv-login.square-enix.com/oauth/ffxivarr/login/top");
+ QUrl url;
+ url.setScheme("https");
+ url.setHost(QStringLiteral("ffxiv-login.%1").arg(window.squareEnixLoginServer()));
+ url.setPath("/oauth/ffxivarr/login/top");
url.setQuery(query);
auto request = QNetworkRequest(url);
@@ -98,7 +101,12 @@ void SquareLauncher::login(const LoginInformation &info, const QUrl &referer)
postData.addQueryItem("password", info.password);
postData.addQueryItem("otppw", info.oneTimePassword);
- QNetworkRequest request(QUrl("https://ffxiv-login.square-enix.com/oauth/ffxivarr/login/login.send"));
+ QUrl url;
+ url.setScheme("https");
+ url.setHost(QStringLiteral("ffxiv-login.%1").arg(window.squareEnixLoginServer()));
+ url.setPath("/oauth/ffxivarr/login/login.send");
+
+ QNetworkRequest request(url);
window.buildRequest(*info.profile, request);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setRawHeader("Referer", referer.toEncoded());
@@ -149,7 +157,7 @@ void SquareLauncher::registerSession(const LoginInformation &info)
{
QUrl url;
url.setScheme("https");
- url.setHost("patch-gamever.ffxiv.com");
+ url.setHost(QStringLiteral("patch-gamever.%1").arg(window.squareEnixServer()));
url.setPath(QString("/http/win32/ffxivneo_release_game/%1/%2").arg(info.profile->repositories.repositories[0].version, SID));
auto request = QNetworkRequest(url);
diff --git a/launcher/ui/Settings/DeveloperSettings.qml b/launcher/ui/Settings/DeveloperSettings.qml
index 59aa3d6..d6efd20 100644
--- a/launcher/ui/Settings/DeveloperSettings.qml
+++ b/launcher/ui/Settings/DeveloperSettings.qml
@@ -31,6 +31,24 @@ Kirigami.ScrollablePage {
checked: LauncherCore.keepPatches
onCheckedChanged: LauncherCore.keepPatches = checked
}
+
+ MobileForm.FormTextFieldDelegate {
+ label: i18n("Dalamud Distribution Server")
+ text: LauncherCore.dalamudDistribServer
+ onTextChanged: LauncherCore.dalamudDistribServer = text
+ }
+
+ MobileForm.FormTextFieldDelegate {
+ label: i18n("SE Main Server")
+ text: LauncherCore.squareEnixServer
+ onTextChanged: LauncherCore.squareEnixServer = text
+ }
+
+ MobileForm.FormTextFieldDelegate {
+ label: i18n("SE Login Server")
+ text: LauncherCore.squareEnixLoginServer
+ onTextChanged: LauncherCore.squareEnixLoginServer = text
+ }
}
}
}