diff --git a/README.md b/README.md index 77fc109..a15f4aa 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ plugins! * Encrypted Arguments: Game arguments are encrypted out of the box, and is as secure as other launchers. * Secure Password Storage: Login information is encrypted using your system keychain and is never stored plain-text. * Game Patching Support: Can patch the game without the need to boot into the official launcher. -* Alternative Server Support: Can log into Sapphire servers and use alternative domains. +* Alternative Server Support: Can use alternative servers in case the official ones ever disappear. **Note:** Steam-linked Square Enix accounts are not currently supported. You will have to use the official launcher or XIVLauncher.Core. diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 45be751..7226594 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -49,7 +49,6 @@ target_sources(astra_static PRIVATE include/launchercore.h include/patcher.h include/processlogger.h - include/sapphirelogin.h include/squareenixlogin.h include/steamapi.h @@ -70,7 +69,6 @@ target_sources(astra_static PRIVATE src/utility.cpp src/patcher.cpp src/processlogger.cpp - src/sapphirelogin.cpp src/squareenixlogin.cpp src/steamapi.cpp) target_include_directories(astra_static PUBLIC include) @@ -156,7 +154,6 @@ qt_target_qml_sources(astra_static ui/Settings/SettingsPage.qml ui/Settings/SyncSettings.qml ui/Setup/AccountSetup.qml - ui/Setup/AddSapphire.qml ui/Setup/AddSquareEnix.qml ui/Setup/BenchmarkInstallProgress.qml ui/Setup/ExistingSetup.qml diff --git a/launcher/accountconfig.kcfg b/launcher/accountconfig.kcfg index 4d39c23..3d2dea6 100644 --- a/launcher/accountconfig.kcfg +++ b/launcher/accountconfig.kcfg @@ -36,9 +36,6 @@ SPDX-License-Identifier: CC0-1.0 - - false - false diff --git a/launcher/include/accountmanager.h b/launcher/include/accountmanager.h index 3603a2f..8a81428 100644 --- a/launcher/include/accountmanager.h +++ b/launcher/include/accountmanager.h @@ -29,7 +29,6 @@ public: [[nodiscard]] QHash roleNames() const override; Q_INVOKABLE Account *createSquareEnixAccount(const QString &username, int licenseType, bool isFreeTrial); - Q_INVOKABLE Account *createSapphireAccount(const QString &lobbyUrl, const QString &username); [[nodiscard]] Account *getByUuid(const QString &uuid) const; @@ -48,4 +47,4 @@ private: void insertAccount(Account *account); QList m_accounts; -}; \ No newline at end of file +}; diff --git a/launcher/include/launchercore.h b/launcher/include/launchercore.h index b4ad25d..99c06d1 100755 --- a/launcher/include/launchercore.h +++ b/launcher/include/launchercore.h @@ -14,7 +14,6 @@ #include "profilemanager.h" #include "steamapi.h" -class SapphireLogin; class SquareEnixLogin; class AssetUpdater; class GameInstaller; @@ -82,7 +81,7 @@ public: /// Initializes the Steamworks API. void initializeSteam(); - /// Begins the login process, and may call SquareBoot or SapphireLauncher depending on the profile type. + /// Begins the login process. /// It's designed to be opaque as possible to the caller. /// \note The login process is asynchronous. Q_INVOKABLE void login(Profile *profile, const QString &username, const QString &password, const QString &oneTimePassword); @@ -185,7 +184,6 @@ private: ProfileManager *m_profileManager = nullptr; AccountManager *m_accountManager = nullptr; - SapphireLogin *m_sapphireLogin = nullptr; SquareEnixLogin *m_squareEnixLogin = nullptr; QNetworkAccessManager *m_mgr = nullptr; diff --git a/launcher/include/sapphirelogin.h b/launcher/include/sapphirelogin.h deleted file mode 100644 index 4e785a2..0000000 --- a/launcher/include/sapphirelogin.h +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Joshua Goins -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "launchercore.h" - -class SapphireLogin : QObject -{ -public: - explicit SapphireLogin(LauncherCore &window, QObject *parent = nullptr); - - /// Begins the login process for Sapphire servers - /// \param lobbyUrl The URL to the Sapphire lobby server - /// \param info The required login information - QCoro::Task> login(const QString &lobbyUrl, const LoginInformation &info); - - void registerAccount(const QString &lobbyUrl, const LoginInformation &info); - -private: - LauncherCore &m_launcher; -}; \ No newline at end of file diff --git a/launcher/src/accountmanager.cpp b/launcher/src/accountmanager.cpp index 14a64e2..7138819 100644 --- a/launcher/src/accountmanager.cpp +++ b/launcher/src/accountmanager.cpp @@ -58,7 +58,6 @@ QHash AccountManager::roleNames() const Account *AccountManager::createSquareEnixAccount(const QString &username, const int licenseType, const bool isFreeTrial) { const auto account = new Account(QUuid::createUuid().toString(), this); - account->config()->setIsSapphire(false); account->config()->setLicense(static_cast(licenseType)); account->config()->setIsFreeTrial(isFreeTrial); account->config()->setName(username); @@ -68,18 +67,6 @@ Account *AccountManager::createSquareEnixAccount(const QString &username, const return account; } -Account *AccountManager::createSapphireAccount(const QString &lobbyUrl, const QString &username) -{ - const auto account = new Account(QUuid::createUuid().toString(), this); - account->config()->setIsSapphire(true); - account->config()->setName(username); - account->config()->setLobbyHost(lobbyUrl); - - insertAccount(account); - - return account; -} - Account *AccountManager::getByUuid(const QString &uuid) const { for (const auto &account : m_accounts) { diff --git a/launcher/src/launchercore.cpp b/launcher/src/launchercore.cpp index 85950d7..b9fe382 100755 --- a/launcher/src/launchercore.cpp +++ b/launcher/src/launchercore.cpp @@ -20,7 +20,6 @@ #include "gamerunner.h" #include "launchercore.h" #include "profileconfig.h" -#include "sapphirelogin.h" #include "squareenixlogin.h" #include "utility.h" @@ -42,7 +41,6 @@ LauncherCore::LauncherCore() { m_config = new Config(KSharedConfig::openConfig(QStringLiteral("astrarc"), KConfig::SimpleConfig, QStandardPaths::AppConfigLocation), this); m_mgr = new QNetworkAccessManager(this); - m_sapphireLogin = new SapphireLogin(*this, this); m_squareEnixLogin = new SquareEnixLogin(*this, this); m_profileManager = new ProfileManager(this); m_accountManager = new AccountManager(this); @@ -470,11 +468,7 @@ QCoro::Task<> LauncherCore::beginLogin(LoginInformation &info) std::optional auth; if (!info.profile->config()->isBenchmark()) { - if (info.profile->account()->config()->isSapphire()) { - auth = co_await m_sapphireLogin->login(info.profile->account()->config()->lobbyHost(), info); - } else { - auth = co_await m_squareEnixLogin->login(&info); - } + auth = co_await m_squareEnixLogin->login(&info); } const auto assetUpdater = new AssetUpdater(*info.profile, *this, this); diff --git a/launcher/src/sapphirelogin.cpp b/launcher/src/sapphirelogin.cpp deleted file mode 100644 index de0a524..0000000 --- a/launcher/src/sapphirelogin.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Joshua Goins -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "sapphirelogin.h" -#include "utility.h" - -#include -#include -#include -#include -#include - -using namespace Qt::StringLiterals; - -SapphireLogin::SapphireLogin(LauncherCore &window, QObject *parent) - : QObject(parent) - , m_launcher(window) -{ -} - -QCoro::Task> SapphireLogin::login(const QString &lobbyUrl, const LoginInformation &info) -{ - const QJsonObject data{{QStringLiteral("username"), info.username}, {QStringLiteral("pass"), info.password}}; - - const QUrl url(lobbyUrl + QStringLiteral("/sapphire-api/lobby/login")); - - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/x-www-form-urlencoded")); - Utility::printRequest(QStringLiteral("POST"), request); - - const auto reply = m_launcher.mgr()->post(request, QJsonDocument(data).toJson(QJsonDocument::JsonFormat::Compact)); - co_await reply; - - if (reply->error() != QNetworkReply::NetworkError::NoError) { - Q_EMIT m_launcher.loginError(i18n("Could not contact lobby server.\n\n%1", reply->errorString())); - co_return std::nullopt; - } - - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - if (!document.isEmpty()) { - LoginAuth auth; - auth.SID = document["sId"_L1].toString(); - auth.lobbyHost = document["lobbyHost"_L1].toString(); - auth.frontierHost = document["frontierHost"_L1].toString(); - auth.lobbyHostPort = 54994; // TODO: where did this come from? - auth.region = 3; - - co_return auth; - } else { - Q_EMIT m_launcher.loginError(i18n("Invalid username or password.")); - co_return std::nullopt; - } -} - -void SapphireLogin::registerAccount(const QString &lobbyUrl, const LoginInformation &info) -{ - const QJsonObject data{{QStringLiteral("username"), info.username}, {QStringLiteral("pass"), info.password}}; - const QUrl url(lobbyUrl + QStringLiteral("/sapphire-api/lobby/createAccount")); - - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/x-www-form-urlencoded")); - - Utility::printRequest(QStringLiteral("POST"), request); - - const auto reply = m_launcher.mgr()->post(request, QJsonDocument(data).toJson(QJsonDocument::JsonFormat::Compact)); - connect(reply, &QNetworkReply::finished, [&] { - const QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); - - LoginAuth auth; - auth.SID = document["sId"_L1].toString(); - auth.lobbyHost = document["lobbyHost"_L1].toString(); - auth.frontierHost = document["frontierHost"_L1].toString(); - auth.region = 3; - - // m_launcher.launchGame(*info.profile, auth); - }); -} diff --git a/launcher/ui/Pages/LoginPage.qml b/launcher/ui/Pages/LoginPage.qml index a7a797e..6faa527 100644 --- a/launcher/ui/Pages/LoginPage.qml +++ b/launcher/ui/Pages/LoginPage.qml @@ -214,7 +214,7 @@ QQC2.Control { FormCard.FormTextFieldDelegate { id: usernameField - label: LauncherCore.currentProfile.account.config.isSapphire ? i18n("Username") : i18n("Square Enix ID") + label: i18n("Square Enix ID") text: LauncherCore.currentProfile.account.config.name enabled: false @@ -230,7 +230,7 @@ QQC2.Control { FormCard.FormPasswordFieldDelegate { id: passwordField - label: LauncherCore.currentProfile.account.config.isSapphire ? i18n("Password") : i18n("Square Enix Password") + label: i18n("Square Enix Password") focus: true onAccepted: { if (otpField.visible) { @@ -281,7 +281,6 @@ QQC2.Control { FormCard.FormDelegateSeparator { above: loginButton below: forgotPasswordButton - visible: !LauncherCore.currentProfile.account.config.isSapphire } FormCard.FormButtonDelegate { @@ -289,7 +288,6 @@ QQC2.Control { text: i18n("Forgot ID or Password") icon.name: "question-symbolic" - visible: !LauncherCore.currentProfile.account.config.isSapphire onClicked: applicationWindow().openUrl('https://secure.square-enix.com/account/app/svc/reminder') } } @@ -325,7 +323,6 @@ QQC2.Control { FormCard.FormLinkDelegate { text: i18nc("@action:button", "The Lodestone") icon.name: "internet-services-symbolic" - visible: !LauncherCore.currentProfile.account.config.isSapphire // TODO: how do we link to a "worldwide" lodestone, if that even exists? url: 'https://na.finalfantasyxiv.com/lodestone/' onClicked: applicationWindow().openUrl(url) @@ -336,7 +333,6 @@ QQC2.Control { FormCard.FormLinkDelegate { text: i18nc("@action:button", "Mog Station") icon.name: "internet-services-symbolic" - visible: !LauncherCore.currentProfile.account.config.isSapphire url: 'https://secure.square-enix.com/account/app/svc/mogstation/' onClicked: applicationWindow().openUrl(url) } diff --git a/launcher/ui/Settings/AccountSettings.qml b/launcher/ui/Settings/AccountSettings.qml index 8bb20d9..d60747d 100644 --- a/launcher/ui/Settings/AccountSettings.qml +++ b/launcher/ui/Settings/AccountSettings.qml @@ -77,20 +77,6 @@ FormCard.FormCardPage { FormCard.FormDelegateSeparator { above: usernameDelegate - below: accountTypeDelegate - } - - FormCard.FormComboBoxDelegate { - id: accountTypeDelegate - - text: i18n("Account type") - model: ["Square Enix", "Sapphire"] - currentIndex: page.account.config.isSapphire ? 1 : 0 - onCurrentIndexChanged: page.account.config.isSapphire = (currentIndex === 1) - } - - FormCard.FormDelegateSeparator { - above: accountTypeDelegate below: languageDelegate } @@ -106,7 +92,7 @@ FormCard.FormCardPage { } FormCard.FormCard { - visible: accountAction.checked && !page.account.config.isSapphire + visible: accountAction.checked Layout.fillWidth: true Layout.topMargin: Kirigami.Units.largeSpacing * 4 @@ -178,23 +164,6 @@ FormCard.FormCardPage { } } - FormCard.FormCard { - visible: accountAction.checked && page.account.config.isSapphire - - Layout.fillWidth: true - Layout.topMargin: Kirigami.Units.largeSpacing * 4 - - FormCard.FormTextFieldDelegate { - id: lobbyURLDelegate - - label: i18n("Lobby URL") - text: page.account.config.lobbyUrl - onTextChanged: page.account.config.lobbyUrl = text - visible: page.account.config.isSapphire - placeholderText: "neolobby0X.ffxiv.com" - } - } - FormCard.FormCard { visible: loginAction.checked @@ -224,7 +193,6 @@ FormCard.FormCardPage { checked: page.account.config.rememberOTP onCheckedChanged: page.account.config.rememberOTP = checked enabled: page.account.config.useOTP - visible: !page.account.config.isSapphire } FormCard.FormDelegateSeparator { diff --git a/launcher/ui/Settings/AccountsPage.qml b/launcher/ui/Settings/AccountsPage.qml index 99d63c6..b38279f 100644 --- a/launcher/ui/Settings/AccountsPage.qml +++ b/launcher/ui/Settings/AccountsPage.qml @@ -22,15 +22,7 @@ FormCard.FormCardPage { Kirigami.Action { text: i18n("Add Account…") icon.name: "list-add-symbolic" - - Kirigami.Action { - text: i18n("Square Enix") - onTriggered: root.Window.window.pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "AddSquareEnix")) - } - Kirigami.Action { - text: i18n("Sapphire") - onTriggered: root.Window.window.pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "AddSapphire")) - } + onTriggered: root.Window.window.pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "AddSquareEnix")) } ] @@ -53,7 +45,7 @@ FormCard.FormCardPage { FormCard.FormButtonDelegate { text: layout.account.config.name - description: layout.account.config.isSapphire ? i18n("Sapphire") : i18n("Square Enix") + description: i18n("Square Enix") leading: Components.Avatar { diff --git a/launcher/ui/Setup/AccountSetup.qml b/launcher/ui/Setup/AccountSetup.qml index c218465..b7ca6e9 100644 --- a/launcher/ui/Setup/AccountSetup.qml +++ b/launcher/ui/Setup/AccountSetup.qml @@ -74,21 +74,5 @@ FormCard.FormCardPage { profile: page.profile }) } - - FormCard.FormDelegateSeparator { - above: addSquareEnixButton - below: addSapphireButton - } - - FormCard.FormButtonDelegate { - id: addSapphireButton - - text: i18n("Sapphire Account…") - description: i18n("Only for Sapphire servers, don't select this if unless you need to connect to one.") - icon.name: "list-add-symbolic" - onClicked: page.Window.window.pageStack.layers.push(Qt.createComponent("zone.xiv.astra", "AddSapphire"), { - profile: page.profile - }) - } } } diff --git a/launcher/ui/Setup/AddSapphire.qml b/launcher/ui/Setup/AddSapphire.qml deleted file mode 100644 index b35d8ce..0000000 --- a/launcher/ui/Setup/AddSapphire.qml +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Joshua Goins -// SPDX-License-Identifier: GPL-3.0-or-later - -import QtQuick -import QtQuick.Layouts -import QtQuick.Window - -import org.kde.kirigami as Kirigami -import org.kde.kirigamiaddons.formcard as FormCard - -import zone.xiv.astra - -FormCard.FormCardPage { - id: page - - property var profile - - title: i18n("Add Sapphire Account") - - readonly property bool isValid: usernameField.text.length !== 0 && lobbyUrlField.text.length !== 0 - - FormCard.FormCard { - Layout.topMargin: Kirigami.Units.largeSpacing - Layout.fillWidth: true - - FormCard.FormTextDelegate { - id: helpTextDelegate - description: i18n("The password will be entered on the login page. A username will be associated with this account but can always be changed later.") - } - - FormCard.FormDelegateSeparator { - above: helpTextDelegate - below: usernameField - } - - FormCard.FormTextFieldDelegate { - id: usernameField - label: i18n("Username") - } - - FormCard.FormDelegateSeparator { - above: usernameField - below: lobbyUrlField - } - - FormCard.FormTextFieldDelegate { - id: lobbyUrlField - label: i18n("Lobby URL") - } - - FormCard.FormDelegateSeparator { - above: lobbyUrlField - below: buttonDelegate - } - - FormCard.FormButtonDelegate { - id: buttonDelegate - text: i18n("Add Account") - icon.name: "list-add-symbolic" - enabled: page.isValid - onClicked: { - let account = LauncherCore.accountManager.createSapphireAccount(lobbyUrlField.text, usernameField.text) - if (page.profile) { - page.profile.account = account - applicationWindow().checkSetup() - } else { - page.Window.window.pageStack.layers.pop() - } - } - } - } -} \ No newline at end of file