mirror of
https://github.com/redstrate/Astra.git
synced 2025-04-21 20:27:45 +00:00
Reformat code
This commit is contained in:
parent
bbdb78f2a8
commit
5a96467f14
36 changed files with 598 additions and 606 deletions
|
@ -31,4 +31,3 @@ AllowShortFunctionsOnASingleLine: 'Empty'
|
||||||
AllowShortLambdasOnASingleLine: 'Empty'
|
AllowShortLambdasOnASingleLine: 'Empty'
|
||||||
AllowShortLoopsOnASingleLine: 'false'
|
AllowShortLoopsOnASingleLine: 'false'
|
||||||
SeparateDefinitionBlocks : 'Always'
|
SeparateDefinitionBlocks : 'Always'
|
||||||
...
|
|
|
@ -10,24 +10,24 @@ option(ENABLE_WATCHDOG "Build with Tesseract support (needed for Watchdog)" OFF)
|
||||||
option(USE_OWN_LIBRARIES "Build with own libraries" OFF)
|
option(USE_OWN_LIBRARIES "Build with own libraries" OFF)
|
||||||
option(BUILD_FLATPAK "Build with Flatpak support in mind" OFF)
|
option(BUILD_FLATPAK "Build with Flatpak support in mind" OFF)
|
||||||
|
|
||||||
if(ENABLE_WATCHDOG)
|
if (ENABLE_WATCHDOG)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_search_module(TESSERACT REQUIRED tesseract)
|
pkg_search_module(TESSERACT REQUIRED tesseract)
|
||||||
pkg_search_module(LEPTONICA REQUIRED lept)
|
pkg_search_module(LEPTONICA REQUIRED lept)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
if(NOT USE_OWN_LIBRARIES)
|
if (NOT USE_OWN_LIBRARIES)
|
||||||
find_package(Qt5Keychain QUIET)
|
find_package(Qt5Keychain QUIET)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if(TARGET Qt5Keychain::Qt5Keychain)
|
if (TARGET Qt5Keychain::Qt5Keychain)
|
||||||
message("Using system library for Qt5 Keychain")
|
message("Using system library for Qt5 Keychain")
|
||||||
|
|
||||||
set(LIBRARIES Qt5Keychain::Qt5Keychain ${LIBRARIES})
|
set(LIBRARIES Qt5Keychain::Qt5Keychain ${LIBRARIES})
|
||||||
set(KEYCHAIN_INCLUDE_DIRS ${QTKEYCHAIN_INCLUDE_DIRS}/qt5keychain) # this is to be consistent with the built-in lib?
|
set(KEYCHAIN_INCLUDE_DIRS ${QTKEYCHAIN_INCLUDE_DIRS}/qt5keychain) # this is to be consistent with the built-in lib?
|
||||||
else()
|
else ()
|
||||||
message("Using downloaded qtkeychain")
|
message("Using downloaded qtkeychain")
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
|
@ -45,17 +45,17 @@ else()
|
||||||
set(KEYCHAIN_INCLUDE_DIRS
|
set(KEYCHAIN_INCLUDE_DIRS
|
||||||
${CMAKE_BINARY_DIR}/_deps/qtkeychain-src
|
${CMAKE_BINARY_DIR}/_deps/qtkeychain-src
|
||||||
${CMAKE_BINARY_DIR}/_deps/qtkeychain-build)
|
${CMAKE_BINARY_DIR}/_deps/qtkeychain-build)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if(NOT USE_OWN_LIBRARIES)
|
if (NOT USE_OWN_LIBRARIES)
|
||||||
find_package(QuaZip-Qt5 QUIET)
|
find_package(QuaZip-Qt5 QUIET)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if(TARGET QuaZip::QuaZip)
|
if (TARGET QuaZip::QuaZip)
|
||||||
message("Using system library for Quazip")
|
message("Using system library for Quazip")
|
||||||
|
|
||||||
set(LIBRARIES QuaZip::QuaZip ${LIBRARIES})
|
set(LIBRARIES QuaZip::QuaZip ${LIBRARIES})
|
||||||
else()
|
else ()
|
||||||
message("Using downloaded quazip")
|
message("Using downloaded quazip")
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
|
@ -71,17 +71,17 @@ else()
|
||||||
|
|
||||||
set(LIBRARIES QuaZip ${LIBRARIES})
|
set(LIBRARIES QuaZip ${LIBRARIES})
|
||||||
set(QUAZIP_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/_deps/quazip-src/quazip)
|
set(QUAZIP_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/_deps/quazip-src/quazip)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if(NOT USE_OWN_LIBRARIES)
|
if (NOT USE_OWN_LIBRARIES)
|
||||||
find_package(fmt QUIET)
|
find_package(fmt QUIET)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if(TARGET fmt::fmt)
|
if (TARGET fmt::fmt)
|
||||||
message("Using system library for fmt")
|
message("Using system library for fmt")
|
||||||
|
|
||||||
set(LIBRARIES fmt::fmt ${LIBRARIES})
|
set(LIBRARIES fmt::fmt ${LIBRARIES})
|
||||||
else()
|
else ()
|
||||||
message("Using downloaded fmt")
|
message("Using downloaded fmt")
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
|
@ -95,11 +95,11 @@ else()
|
||||||
FetchContent_MakeAvailable(fmt)
|
FetchContent_MakeAvailable(fmt)
|
||||||
|
|
||||||
set(LIBRARIES fmt::fmt ${LIBRARIES})
|
set(LIBRARIES fmt::fmt ${LIBRARIES})
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
add_subdirectory(external)
|
add_subdirectory(external)
|
||||||
|
|
||||||
if(ENABLE_WATCHDOG)
|
if (ENABLE_WATCHDOG)
|
||||||
set(LIBRARIES ${LIBRARIES} ${TESSERACT_LIBRARIES} ${LEPTONICA_LIBRARIES})
|
set(LIBRARIES ${LIBRARIES} ${TESSERACT_LIBRARIES} ${LEPTONICA_LIBRARIES})
|
||||||
|
|
||||||
set(SRC ${SRC}
|
set(SRC ${SRC}
|
||||||
|
@ -107,13 +107,13 @@ if(ENABLE_WATCHDOG)
|
||||||
src/watchdog.cpp
|
src/watchdog.cpp
|
||||||
include/gameparser.h
|
include/gameparser.h
|
||||||
src/gameparser.cpp)
|
src/gameparser.cpp)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if(ENABLE_WATCHDOG)
|
if (ENABLE_WATCHDOG)
|
||||||
set(LIBRARIES ${LIBRARIES}
|
set(LIBRARIES ${LIBRARIES}
|
||||||
X11
|
X11
|
||||||
Xcomposite
|
Xcomposite
|
||||||
Xrender)
|
Xrender)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
add_subdirectory(launcher)
|
add_subdirectory(launcher)
|
|
@ -23,14 +23,14 @@ STRING(REPLACE "\"" "\"\"" LICENSE_TXT ${LICENSE_TXT})
|
||||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/../cmake/license.h.in
|
configure_file(${CMAKE_CURRENT_LIST_DIR}/../cmake/license.h.in
|
||||||
${CMAKE_BINARY_DIR}/license.h)
|
${CMAKE_BINARY_DIR}/license.h)
|
||||||
|
|
||||||
if(BUILD_FLATPAK)
|
if (BUILD_FLATPAK)
|
||||||
target_compile_definitions(astra PRIVATE FLATPAK)
|
target_compile_definitions(astra PRIVATE FLATPAK)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
install(TARGETS astra
|
install(TARGETS astra
|
||||||
DESTINATION "${INSTALL_BIN_PATH}")
|
DESTINATION "${INSTALL_BIN_PATH}")
|
||||||
|
|
||||||
if(WIN32)
|
if (WIN32)
|
||||||
get_target_property(QMAKE_EXE Qt5::qmake IMPORTED_LOCATION)
|
get_target_property(QMAKE_EXE Qt5::qmake IMPORTED_LOCATION)
|
||||||
get_filename_component(QT_BIN_DIR "${QMAKE_EXE}" DIRECTORY)
|
get_filename_component(QT_BIN_DIR "${QMAKE_EXE}" DIRECTORY)
|
||||||
|
|
||||||
|
@ -42,4 +42,4 @@ if(WIN32)
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND "${WINDEPLOYQT_ENV_SETUP}" && "${WINDEPLOYQT_EXECUTABLE}" \"$<TARGET_FILE:astra>\"
|
COMMAND "${WINDEPLOYQT_ENV_SETUP}" && "${WINDEPLOYQT_EXECUTABLE}" \"$<TARGET_FILE:astra>\"
|
||||||
)
|
)
|
||||||
endif()
|
endif ()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QCommandLineParser>
|
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The CLI interface for Astra, driven primarily by the command-line.
|
* The CLI interface for Astra, driven primarily by the command-line.
|
||||||
|
@ -13,6 +13,11 @@ public:
|
||||||
bool parse(QCommandLineParser& parser, LauncherCore& core);
|
bool parse(QCommandLineParser& parser, LauncherCore& core);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QCommandLineOption profileOption = {"default-profile", "Profile to use for default profile and autologin.", "profile"};
|
QCommandLineOption profileOption = {
|
||||||
QCommandLineOption autologinOption = {"autologin", "Auto-login with the default profile. This requires the profile to have remember username/password enabled!"};
|
"default-profile",
|
||||||
|
"Profile to use for default profile and autologin.",
|
||||||
|
"profile"};
|
||||||
|
QCommandLineOption autologinOption = {
|
||||||
|
"autologin",
|
||||||
|
"Auto-login with the default profile. This requires the profile to have remember username/password enabled!"};
|
||||||
};
|
};
|
|
@ -1,27 +1,27 @@
|
||||||
#include <keychain.h>
|
|
||||||
#include "cmdinterface.h"
|
#include "cmdinterface.h"
|
||||||
#include "squareboot.h"
|
|
||||||
#include "sapphirelauncher.h"
|
#include "sapphirelauncher.h"
|
||||||
|
#include "squareboot.h"
|
||||||
|
#include <keychain.h>
|
||||||
|
|
||||||
CMDInterface::CMDInterface(QCommandLineParser &parser) {
|
CMDInterface::CMDInterface(QCommandLineParser& parser) {
|
||||||
parser.addOption(autologinOption);
|
parser.addOption(autologinOption);
|
||||||
parser.addOption(profileOption);
|
parser.addOption(profileOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMDInterface::parse(QCommandLineParser &parser, LauncherCore &core) {
|
bool CMDInterface::parse(QCommandLineParser& parser, LauncherCore& core) {
|
||||||
if(parser.isSet(profileOption)) {
|
if (parser.isSet(profileOption)) {
|
||||||
core.defaultProfileIndex = core.getProfileIndex(parser.value(profileOption));
|
core.defaultProfileIndex = core.getProfileIndex(parser.value(profileOption));
|
||||||
|
|
||||||
if(core.defaultProfileIndex == -1) {
|
if (core.defaultProfileIndex == -1) {
|
||||||
qInfo() << "The profile \"" << parser.value(profileOption) << "\" does not exist!";
|
qInfo() << "The profile \"" << parser.value(profileOption) << "\" does not exist!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parser.isSet(autologinOption)) {
|
if (parser.isSet(autologinOption)) {
|
||||||
auto& profile = core.getProfile(core.defaultProfileIndex);
|
auto& profile = core.getProfile(core.defaultProfileIndex);
|
||||||
|
|
||||||
if(!profile.rememberUsername || !profile.rememberPassword) {
|
if (!profile.rememberUsername || !profile.rememberPassword) {
|
||||||
qInfo() << "Profile does not have a username and/or password saved, autologin disabled.";
|
qInfo() << "Profile does not have a username and/or password saved, autologin disabled.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -34,7 +34,8 @@ bool CMDInterface::parse(QCommandLineParser &parser, LauncherCore &core) {
|
||||||
usernameJob->setKey(profile.name + "-username");
|
usernameJob->setKey(profile.name + "-username");
|
||||||
usernameJob->start();
|
usernameJob->start();
|
||||||
|
|
||||||
core.connect(usernameJob, &QKeychain::ReadPasswordJob::finished, [loop, usernameJob, &username](QKeychain::Job* j) {
|
core.connect(
|
||||||
|
usernameJob, &QKeychain::ReadPasswordJob::finished, [loop, usernameJob, &username](QKeychain::Job* j) {
|
||||||
username = usernameJob->textData();
|
username = usernameJob->textData();
|
||||||
loop->quit();
|
loop->quit();
|
||||||
});
|
});
|
||||||
|
@ -45,7 +46,8 @@ bool CMDInterface::parse(QCommandLineParser &parser, LauncherCore &core) {
|
||||||
passwordJob->setKey(profile.name + "-password");
|
passwordJob->setKey(profile.name + "-password");
|
||||||
passwordJob->start();
|
passwordJob->start();
|
||||||
|
|
||||||
core.connect(passwordJob, &QKeychain::ReadPasswordJob::finished, [loop, passwordJob, &password](QKeychain::Job* j) {
|
core.connect(
|
||||||
|
passwordJob, &QKeychain::ReadPasswordJob::finished, [loop, passwordJob, &password](QKeychain::Job* j) {
|
||||||
password = passwordJob->textData();
|
password = passwordJob->textData();
|
||||||
loop->quit();
|
loop->quit();
|
||||||
});
|
});
|
||||||
|
@ -57,7 +59,7 @@ bool CMDInterface::parse(QCommandLineParser &parser, LauncherCore &core) {
|
||||||
info->username = username;
|
info->username = username;
|
||||||
info->password = password;
|
info->password = password;
|
||||||
|
|
||||||
if(profile.isSapphire) {
|
if (profile.isSapphire) {
|
||||||
core.sapphireLauncher->login(profile.lobbyURL, *info);
|
core.sapphireLauncher->login(profile.lobbyURL, *info);
|
||||||
} else {
|
} else {
|
||||||
core.squareBoot->bootCheck(*info);
|
core.squareBoot->bootCheck(*info);
|
||||||
|
|
|
@ -21,7 +21,7 @@ set(SRC
|
||||||
src/squarelauncher.cpp
|
src/squarelauncher.cpp
|
||||||
src/patcher.cpp)
|
src/patcher.cpp)
|
||||||
|
|
||||||
if(ENABLE_WATCHDOG)
|
if (ENABLE_WATCHDOG)
|
||||||
set(HEADERS ${HEADERS}
|
set(HEADERS ${HEADERS}
|
||||||
include/gameparser.h
|
include/gameparser.h
|
||||||
include/watchdog.h)
|
include/watchdog.h)
|
||||||
|
@ -29,7 +29,7 @@ if(ENABLE_WATCHDOG)
|
||||||
set(SRC ${SRC}
|
set(SRC ${SRC}
|
||||||
src/gameparser.cpp
|
src/gameparser.cpp
|
||||||
src/watchdog.cpp)
|
src/watchdog.cpp)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
add_library(astra_core STATIC ${HEADERS} ${SRC})
|
add_library(astra_core STATIC ${HEADERS} ${SRC})
|
||||||
target_include_directories(astra_core PUBLIC
|
target_include_directories(astra_core PUBLIC
|
||||||
|
@ -48,8 +48,8 @@ target_link_libraries(astra_core PUBLIC
|
||||||
PRIVATE
|
PRIVATE
|
||||||
astra_desktop) # desktop is currently required by the core, to be fixed/removed later
|
astra_desktop) # desktop is currently required by the core, to be fixed/removed later
|
||||||
|
|
||||||
if(ENABLE_WATCHDOG)
|
if (ENABLE_WATCHDOG)
|
||||||
target_include_directories(astra_core PUBLIC ${TESSERACT_INCLUDE_DIRS} ${LEPTONICA_INCLUDE_DIRS})
|
target_include_directories(astra_core PUBLIC ${TESSERACT_INCLUDE_DIRS} ${LEPTONICA_INCLUDE_DIRS})
|
||||||
|
|
||||||
target_compile_definitions(astra_core PUBLIC ENABLE_WATCHDOG)
|
target_compile_definitions(astra_core PUBLIC ENABLE_WATCHDOG)
|
||||||
endif()
|
endif ()
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
#include <physis.hpp>
|
#include <physis.hpp>
|
||||||
|
|
||||||
// from xivdev
|
// from xivdev
|
||||||
static char ChecksumTable[] = {
|
static char ChecksumTable[] = {'f', 'X', '1', 'p', 'G', 't', 'd', 'S', '5', 'C', 'A', 'P', '4', '_', 'V', 'L'};
|
||||||
'f', 'X', '1', 'p', 'G', 't', 'd', 'S',
|
|
||||||
'5', 'C', 'A', 'P', '4', '_', 'V', 'L'
|
|
||||||
};
|
|
||||||
|
|
||||||
inline char GetChecksum(unsigned int key) {
|
inline char GetChecksum(unsigned int key) {
|
||||||
auto value = key & 0x000F0000;
|
auto value = key & 0x000F0000;
|
||||||
|
@ -31,13 +28,13 @@ inline QString encryptGameArg(QString arg) {
|
||||||
|
|
||||||
QByteArray toEncrypt = (QString(" /T =%1").arg(ticks) + arg).toUtf8();
|
QByteArray toEncrypt = (QString(" /T =%1").arg(ticks) + arg).toUtf8();
|
||||||
|
|
||||||
physis_blowfish_encrypt(blowfish,
|
physis_blowfish_encrypt(
|
||||||
reinterpret_cast<uint8_t*>(toEncrypt.data()), toEncrypt.size(), &out_data, &out_size);
|
blowfish, reinterpret_cast<uint8_t*>(toEncrypt.data()), toEncrypt.size(), &out_data, &out_size);
|
||||||
|
|
||||||
QByteArray encryptedArg = QByteArray::fromRawData(
|
QByteArray encryptedArg = QByteArray::fromRawData(reinterpret_cast<const char*>(out_data), out_size);
|
||||||
reinterpret_cast<const char*>(out_data), out_size);
|
|
||||||
|
|
||||||
QString base64 = encryptedArg.toBase64(QByteArray::Base64Option::Base64UrlEncoding | QByteArray::Base64Option::OmitTrailingEquals);
|
QString base64 = encryptedArg.toBase64(
|
||||||
|
QByteArray::Base64Option::Base64UrlEncoding | QByteArray::Base64Option::OmitTrailingEquals);
|
||||||
char checksum = GetChecksum(key);
|
char checksum = GetChecksum(key);
|
||||||
|
|
||||||
return QString("//**sqex0003%1%2**//").arg(base64, QString(checksum));
|
return QString("//**sqex0003%1%2**//").arg(base64, QString(checksum));
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <tesseract/baseapi.h>
|
|
||||||
#include <leptonica/allheaders.h>
|
#include <leptonica/allheaders.h>
|
||||||
|
#include <tesseract/baseapi.h>
|
||||||
|
|
||||||
enum class ScreenState {
|
enum class ScreenState {
|
||||||
Splash,
|
Splash,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
struct News {
|
struct News {
|
||||||
QDateTime date;
|
QDateTime date;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QProcess>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <QProcess>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QtQml>
|
#include <QtQml>
|
||||||
|
|
||||||
#include "squareboot.h"
|
#include "squareboot.h"
|
||||||
|
@ -162,7 +162,12 @@ public:
|
||||||
/*
|
/*
|
||||||
* This just wraps it in wine if needed.
|
* This just wraps it in wine if needed.
|
||||||
*/
|
*/
|
||||||
void launchExecutable(const ProfileSettings& settings, QProcess* process, QStringList args, bool isGame, bool needsRegistrySetup);
|
void launchExecutable(
|
||||||
|
const ProfileSettings& settings,
|
||||||
|
QProcess* process,
|
||||||
|
QStringList args,
|
||||||
|
bool isGame,
|
||||||
|
bool needsRegistrySetup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Launches an external tool. Gamescope for example is intentionally excluded.
|
* Launches an external tool. Gamescope for example is intentionally excluded.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QProgressDialog>
|
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QString>
|
||||||
#include <physis.hpp>
|
#include <physis.hpp>
|
||||||
|
|
||||||
// General-purpose patcher routine. It opens a nice dialog box, handles downloading
|
// General-purpose patcher routine. It opens a nice dialog box, handles downloading
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
#include "gameparser.h"
|
#include "gameparser.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
|
|
|
@ -2,6 +2,4 @@
|
||||||
|
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
void installDXVK(LauncherCore& launcher, ProfileSettings& profile, std::function<void()> returnFunc) {
|
void installDXVK(LauncherCore& launcher, ProfileSettings& profile, std::function<void()> returnFunc) {}
|
||||||
|
|
||||||
}
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include "encryptedarg.h"
|
#include "encryptedarg.h"
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
#include <sys/sysctl.h>
|
#include <mach/mach_time.h>
|
||||||
#include <mach/mach_time.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
|
@ -16,7 +16,7 @@ uint32_t TickCount() {
|
||||||
mach_timebase_info(&timebase);
|
mach_timebase_info(&timebase);
|
||||||
|
|
||||||
auto machtime = mach_continuous_time();
|
auto machtime = mach_continuous_time();
|
||||||
auto numer = uint64_t (timebase.numer);
|
auto numer = uint64_t(timebase.numer);
|
||||||
auto denom = uint64_t(timebase.denom);
|
auto denom = uint64_t(timebase.denom);
|
||||||
auto monotonic_time = machtime * numer / denom / 100;
|
auto monotonic_time = machtime * numer / denom / 100;
|
||||||
return monotonic_time / 10000;
|
return monotonic_time / 10000;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "gameinstaller.h"
|
#include "gameinstaller.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QFile>
|
|
||||||
#include <physis.hpp>
|
#include <physis.hpp>
|
||||||
|
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
|
@ -17,15 +17,15 @@ void installGame(LauncherCore& launcher, ProfileSettings& profile, std::function
|
||||||
|
|
||||||
auto reply = launcher.mgr->get(request);
|
auto reply = launcher.mgr->get(request);
|
||||||
launcher.connect(reply, &QNetworkReply::finished, [reply, installDirectory, returnFunc] {
|
launcher.connect(reply, &QNetworkReply::finished, [reply, installDirectory, returnFunc] {
|
||||||
QString dataDir =
|
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||||
QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
|
||||||
|
|
||||||
QFile file(dataDir + "/ffxivsetup.exe");
|
QFile file(dataDir + "/ffxivsetup.exe");
|
||||||
file.open(QIODevice::WriteOnly);
|
file.open(QIODevice::WriteOnly);
|
||||||
file.write(reply->readAll());
|
file.write(reply->readAll());
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
physis_install_game(installDirectory.toStdString().c_str(), (dataDir + "/ffxivsetup.exe").toStdString().c_str());
|
physis_install_game(
|
||||||
|
installDirectory.toStdString().c_str(), (dataDir + "/ffxivsetup.exe").toStdString().c_str());
|
||||||
|
|
||||||
qDebug() << "Done installing to " << installDirectory << "!";
|
qDebug() << "Done installing to " << installDirectory << "!";
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "gameparser.h"
|
#include "gameparser.h"
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QBuffer>
|
|
||||||
|
|
||||||
GameParser::GameParser() {
|
GameParser::GameParser() {
|
||||||
api = new tesseract::TessBaseAPI();
|
api = new tesseract::TessBaseAPI();
|
||||||
|
@ -25,7 +25,7 @@ GameParseResult GameParser::parseImage(QImage img) {
|
||||||
img = img.convertToFormat(QImage::Format_Grayscale8);
|
img = img.convertToFormat(QImage::Format_Grayscale8);
|
||||||
img.save(&buf, "PNG", 100);
|
img.save(&buf, "PNG", 100);
|
||||||
|
|
||||||
Pix* image = pixReadMem((const l_uint8 *) buf.data().data(), buf.size());
|
Pix* image = pixReadMem((const l_uint8*)buf.data().data(), buf.size());
|
||||||
api->SetImage(image);
|
api->SetImage(image);
|
||||||
api->SetSourceResolution(300);
|
api->SetSourceResolution(300);
|
||||||
|
|
||||||
|
@ -38,35 +38,35 @@ GameParseResult GameParser::parseImage(QImage img) {
|
||||||
const bool hasConnectingToData = text.contains("Connecting to data center");
|
const bool hasConnectingToData = text.contains("Connecting to data center");
|
||||||
const bool worldTotallyFull = text.contains("3001");
|
const bool worldTotallyFull = text.contains("3001");
|
||||||
|
|
||||||
if(hasLobbyErrorText) {
|
if (hasLobbyErrorText) {
|
||||||
qDebug() << "LOBBY ERROR";
|
qDebug() << "LOBBY ERROR";
|
||||||
|
|
||||||
return {ScreenState::LobbyError, -1};
|
return {ScreenState::LobbyError, -1};
|
||||||
} else {
|
} else {
|
||||||
if(worldTotallyFull) {
|
if (worldTotallyFull) {
|
||||||
qDebug() << "TOTALLY FULL WORLD (CLOSED BY SQENIX)";
|
qDebug() << "TOTALLY FULL WORLD (CLOSED BY SQENIX)";
|
||||||
|
|
||||||
return {ScreenState::WorldFull, -1};
|
return {ScreenState::WorldFull, -1};
|
||||||
} else {
|
} else {
|
||||||
if(hasConnectingToData) {
|
if (hasConnectingToData) {
|
||||||
qDebug() << "CONNECTING TO DATA CENTER";
|
qDebug() << "CONNECTING TO DATA CENTER";
|
||||||
|
|
||||||
return {ScreenState::ConnectingToDataCenter, -1};
|
return {ScreenState::ConnectingToDataCenter, -1};
|
||||||
} else {
|
} else {
|
||||||
if(hasWorldFullText) {
|
if (hasWorldFullText) {
|
||||||
qDebug() << "FULL WORLD";
|
qDebug() << "FULL WORLD";
|
||||||
|
|
||||||
// attempt to extract number of players in queue
|
// attempt to extract number of players in queue
|
||||||
QRegularExpression exp("(?:Players in queue: )([\\d|,]*)");
|
QRegularExpression exp("(?:Players in queue: )([\\d|,]*)");
|
||||||
|
|
||||||
auto match = exp.match(text);
|
auto match = exp.match(text);
|
||||||
if(match.isValid()) {
|
if (match.isValid()) {
|
||||||
return {ScreenState::InLoginQueue, match.captured(1).remove(',').toInt()};
|
return {ScreenState::InLoginQueue, match.captured(1).remove(',').toInt()};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {ScreenState::InLoginQueue, -1};
|
return {ScreenState::InLoginQueue, -1};
|
||||||
} else {
|
} else {
|
||||||
if(hasCONFIGURATIONText) {
|
if (hasCONFIGURATIONText) {
|
||||||
qDebug() << "TITLE SCREEN";
|
qDebug() << "TITLE SCREEN";
|
||||||
return {ScreenState::EnteredTitleScreen, -1};
|
return {ScreenState::EnteredTitleScreen, -1};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include "headline.h"
|
#include "headline.h"
|
||||||
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QNetworkReply>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ void getHeadline(LauncherCore& core, std::function<void(Headline)> return_func)
|
||||||
url.setPath("/news/headline.json");
|
url.setPath("/news/headline.json");
|
||||||
url.setQuery(query);
|
url.setQuery(query);
|
||||||
|
|
||||||
auto request = QNetworkRequest(QString("%1&%2").arg(url.toString(), QString::number(QDateTime::currentMSecsSinceEpoch())));
|
auto request =
|
||||||
|
QNetworkRequest(QString("%1&%2").arg(url.toString(), QString::number(QDateTime::currentMSecsSinceEpoch())));
|
||||||
|
|
||||||
// TODO: really?
|
// TODO: really?
|
||||||
core.buildRequest(core.getProfile(core.defaultProfileIndex), request);
|
core.buildRequest(core.getProfile(core.defaultProfileIndex), request);
|
||||||
|
@ -29,7 +30,11 @@ void getHeadline(LauncherCore& core, std::function<void(Headline)> return_func)
|
||||||
qInfo() << request.url();
|
qInfo() << request.url();
|
||||||
request.setRawHeader("Accept", "application/json, text/plain, */*");
|
request.setRawHeader("Accept", "application/json, text/plain, */*");
|
||||||
request.setRawHeader("Origin", "https://launcher.finalfantasyxiv.com");
|
request.setRawHeader("Origin", "https://launcher.finalfantasyxiv.com");
|
||||||
request.setRawHeader("Referer", QString("https://launcher.finalfantasyxiv.com/v600/index.html?rc_lang=%1&time=%2").arg("en-us", QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd-HH")).toUtf8());
|
request.setRawHeader(
|
||||||
|
"Referer",
|
||||||
|
QString("https://launcher.finalfantasyxiv.com/v600/index.html?rc_lang=%1&time=%2")
|
||||||
|
.arg("en-us", QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd-HH"))
|
||||||
|
.toUtf8());
|
||||||
|
|
||||||
auto reply = core.mgr->get(request);
|
auto reply = core.mgr->get(request);
|
||||||
core.connect(reply, &QNetworkReply::finished, [=] {
|
core.connect(reply, &QNetworkReply::finished, [=] {
|
||||||
|
@ -44,7 +49,7 @@ void getHeadline(LauncherCore& core, std::function<void(Headline)> return_func)
|
||||||
news.tag = object["tag"].toString();
|
news.tag = object["tag"].toString();
|
||||||
news.title = object["title"].toString();
|
news.title = object["title"].toString();
|
||||||
|
|
||||||
if(object["url"].toString().isEmpty()) {
|
if (object["url"].toString().isEmpty()) {
|
||||||
news.url = QUrl(QString("https://na.finalfantasyxiv.com/lodestone/news/detail/%1").arg(news.id));
|
news.url = QUrl(QString("https://na.finalfantasyxiv.com/lodestone/news/detail/%1").arg(news.id));
|
||||||
} else {
|
} else {
|
||||||
news.url = QUrl(object["url"].toString());
|
news.url = QUrl(object["url"].toString());
|
||||||
|
@ -53,7 +58,7 @@ void getHeadline(LauncherCore& core, std::function<void(Headline)> return_func)
|
||||||
return news;
|
return news;
|
||||||
};
|
};
|
||||||
|
|
||||||
for(auto bannerObject : document.object()["banner"].toArray()) {
|
for (auto bannerObject : document.object()["banner"].toArray()) {
|
||||||
Banner banner;
|
Banner banner;
|
||||||
banner.link = QUrl(bannerObject.toObject()["link"].toString());
|
banner.link = QUrl(bannerObject.toObject()["link"].toString());
|
||||||
banner.bannerImage = QUrl(bannerObject.toObject()["lsb_banner"].toString());
|
banner.bannerImage = QUrl(bannerObject.toObject()["lsb_banner"].toString());
|
||||||
|
@ -61,17 +66,17 @@ void getHeadline(LauncherCore& core, std::function<void(Headline)> return_func)
|
||||||
headline.banner.push_back(banner);
|
headline.banner.push_back(banner);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto newsObject : document.object()["news"].toArray()) {
|
for (auto newsObject : document.object()["news"].toArray()) {
|
||||||
auto news = parseNews(newsObject.toObject());
|
auto news = parseNews(newsObject.toObject());
|
||||||
headline.news.push_back(news);
|
headline.news.push_back(news);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto pinnedObject : document.object()["pinned"].toArray()) {
|
for (auto pinnedObject : document.object()["pinned"].toArray()) {
|
||||||
auto pinned = parseNews(pinnedObject.toObject());
|
auto pinned = parseNews(pinnedObject.toObject());
|
||||||
headline.pinned.push_back(pinned);
|
headline.pinned.push_back(pinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto pinnedObject : document.object()["topics"].toArray()) {
|
for (auto pinnedObject : document.object()["topics"].toArray()) {
|
||||||
auto pinned = parseNews(pinnedObject.toObject());
|
auto pinned = parseNews(pinnedObject.toObject());
|
||||||
headline.topics.push_back(pinned);
|
headline.topics.push_back(pinned);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
#include <QPushButton>
|
#include <QCheckBox>
|
||||||
#include <QProcess>
|
#include <QComboBox>
|
||||||
#include <QNetworkAccessManager>
|
#include <QCoreApplication>
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QCheckBox>
|
#include <QJsonObject>
|
||||||
#include <keychain.h>
|
#include <QLineEdit>
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QCoreApplication>
|
#include <QMessageBox>
|
||||||
#include <QStandardPaths>
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QRegularExpressionMatch>
|
#include <QRegularExpressionMatch>
|
||||||
#include <algorithm>
|
#include <QStandardPaths>
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <keychain.h>
|
||||||
|
|
||||||
#include "launchercore.h"
|
|
||||||
#include "sapphirelauncher.h"
|
|
||||||
#include "squarelauncher.h"
|
|
||||||
#include "squareboot.h"
|
|
||||||
#include "settingswindow.h"
|
|
||||||
#include "assetupdater.h"
|
#include "assetupdater.h"
|
||||||
#include "encryptedarg.h"
|
#include "encryptedarg.h"
|
||||||
|
#include "launchercore.h"
|
||||||
|
#include "sapphirelauncher.h"
|
||||||
|
#include "settingswindow.h"
|
||||||
|
#include "squareboot.h"
|
||||||
|
#include "squarelauncher.h"
|
||||||
|
|
||||||
#ifdef ENABLE_WATCHDOG
|
#ifdef ENABLE_WATCHDOG
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void LauncherCore::setSSL(QNetworkRequest& request) {
|
void LauncherCore::setSSL(QNetworkRequest& request) {
|
||||||
|
@ -43,15 +43,18 @@ void LauncherCore::setSSL(QNetworkRequest& request) {
|
||||||
void LauncherCore::buildRequest(const ProfileSettings& settings, QNetworkRequest& request) {
|
void LauncherCore::buildRequest(const ProfileSettings& settings, QNetworkRequest& request) {
|
||||||
setSSL(request);
|
setSSL(request);
|
||||||
|
|
||||||
if(settings.license == GameLicense::macOS) {
|
if (settings.license == GameLicense::macOS) {
|
||||||
request.setHeader(QNetworkRequest::UserAgentHeader, "macSQEXAuthor/2.0.0(MacOSX; ja-jp)");
|
request.setHeader(QNetworkRequest::UserAgentHeader, "macSQEXAuthor/2.0.0(MacOSX; ja-jp)");
|
||||||
} else {
|
} else {
|
||||||
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())));
|
||||||
}
|
}
|
||||||
|
|
||||||
request.setRawHeader("Accept",
|
request.setRawHeader(
|
||||||
"image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*");
|
"Accept",
|
||||||
|
"image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, "
|
||||||
|
"application/x-ms-xbap, */*");
|
||||||
request.setRawHeader("Accept-Encoding", "gzip, deflate");
|
request.setRawHeader("Accept-Encoding", "gzip, deflate");
|
||||||
request.setRawHeader("Accept-Language", "en-us");
|
request.setRawHeader("Accept-Language", "en-us");
|
||||||
}
|
}
|
||||||
|
@ -61,13 +64,13 @@ void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth au
|
||||||
|
|
||||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
|
|
||||||
if(profile.dalamud.enabled) {
|
if (profile.dalamud.enabled) {
|
||||||
arguments.push_back(dataDir + "/NativeLauncher.exe");
|
arguments.push_back(dataDir + "/NativeLauncher.exe");
|
||||||
arguments.push_back("5248"); // TODO: make port configurable/random
|
arguments.push_back("5248"); // TODO: make port configurable/random
|
||||||
}
|
}
|
||||||
|
|
||||||
// now for the actual game...
|
// now for the actual game...
|
||||||
if(profile.useDX9) {
|
if (profile.useDX9) {
|
||||||
arguments.push_back(profile.gamePath + "\\game\\ffxiv.exe");
|
arguments.push_back(profile.gamePath + "\\game\\ffxiv.exe");
|
||||||
} else {
|
} else {
|
||||||
arguments.push_back(profile.gamePath + "\\game\\ffxiv_dx11.exe");
|
arguments.push_back(profile.gamePath + "\\game\\ffxiv_dx11.exe");
|
||||||
|
@ -87,9 +90,9 @@ void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth au
|
||||||
gameArgs.push_back({"language", QString::number(profile.language)});
|
gameArgs.push_back({"language", QString::number(profile.language)});
|
||||||
gameArgs.push_back({"ver", profile.repositories.repositories[0].version});
|
gameArgs.push_back({"ver", profile.repositories.repositories[0].version});
|
||||||
|
|
||||||
if(!auth.lobbyhost.isEmpty()) {
|
if (!auth.lobbyhost.isEmpty()) {
|
||||||
gameArgs.push_back({"DEV.GMServerHost", auth.frontierHost});
|
gameArgs.push_back({"DEV.GMServerHost", auth.frontierHost});
|
||||||
for(int i = 1; i < 9; i++) {
|
for (int i = 1; i < 9; i++) {
|
||||||
gameArgs.push_back({QString("DEV.LobbyHost0%1").arg(QString::number(i)), auth.lobbyhost});
|
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)});
|
gameArgs.push_back({QString("DEV.LobbyPort0%1").arg(QString::number(i)), QString::number(54994)});
|
||||||
}
|
}
|
||||||
|
@ -99,16 +102,15 @@ void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth au
|
||||||
|
|
||||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
|
|
||||||
if(profile.license == GameLicense::WindowsSteam) {
|
if (profile.license == GameLicense::WindowsSteam) {
|
||||||
gameArgs.push_back({"IsSteam", "1"});
|
gameArgs.push_back({"IsSteam", "1"});
|
||||||
env.insert("IS_FFXIV_LAUNCH_FROM_STEAM", QString::number(1));
|
env.insert("IS_FFXIV_LAUNCH_FROM_STEAM", QString::number(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(profile.dalamud.enabled) {
|
if (profile.dalamud.enabled) {
|
||||||
// TODO: this depends on the default wine Z: path existing, which may not
|
// TODO: this depends on the default wine Z: path existing, which may not
|
||||||
// always the case.
|
// always the case.
|
||||||
env.insert("DALAMUD_RUNTIME",
|
env.insert("DALAMUD_RUNTIME", "Z:" + dataDir.replace('/', '\\') + "\\DalamudRuntime");
|
||||||
"Z:" + dataDir.replace('/', '\\') + "\\DalamudRuntime");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gameProcess->setProcessEnvironment(env);
|
gameProcess->setProcessEnvironment(env);
|
||||||
|
@ -118,17 +120,17 @@ void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth au
|
||||||
const QString argFormat = profile.encryptArguments ? " /%1 =%2" : " %1=%2";
|
const QString argFormat = profile.encryptArguments ? " /%1 =%2" : " %1=%2";
|
||||||
|
|
||||||
QString argJoined;
|
QString argJoined;
|
||||||
for(const auto& arg : gameArgs) {
|
for (const auto& arg : gameArgs) {
|
||||||
argJoined += argFormat.arg(arg.key, arg.value);
|
argJoined += argFormat.arg(arg.key, arg.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(profile.encryptArguments) {
|
if (profile.encryptArguments) {
|
||||||
arguments.append(encryptGameArg(argJoined));
|
arguments.append(encryptGameArg(argJoined));
|
||||||
} else {
|
} else {
|
||||||
arguments.append(argJoined);
|
arguments.append(argJoined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(profile.dalamud.enabled) {
|
if (profile.dalamud.enabled) {
|
||||||
auto socket = new QTcpServer();
|
auto socket = new QTcpServer();
|
||||||
|
|
||||||
connect(socket, &QTcpServer::newConnection, [this, &profile, socket] {
|
connect(socket, &QTcpServer::newConnection, [this, &profile, socket] {
|
||||||
|
@ -139,7 +141,7 @@ void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth au
|
||||||
bool success;
|
bool success;
|
||||||
int exitCode = output.toInt(&success, 10);
|
int exitCode = output.toInt(&success, 10);
|
||||||
|
|
||||||
if(exitCode != -1 && success) {
|
if (exitCode != -1 && success) {
|
||||||
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
dataDir = "Z:" + dataDir.replace('/', '\\');
|
dataDir = "Z:" + dataDir.replace('/', '\\');
|
||||||
|
|
||||||
|
@ -169,7 +171,12 @@ void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth au
|
||||||
|
|
||||||
auto list = dalamudProcess->processEnvironment().toStringList();
|
auto list = dalamudProcess->processEnvironment().toStringList();
|
||||||
|
|
||||||
launchExecutable(profile, dalamudProcess, {dataDir + "/Dalamud/" + "Dalamud.Injector.exe", QString::number(exitCode), argsEncoded}, false, true);
|
launchExecutable(
|
||||||
|
profile,
|
||||||
|
dalamudProcess,
|
||||||
|
{dataDir + "/Dalamud/" + "Dalamud.Injector.exe", QString::number(exitCode), argsEncoded},
|
||||||
|
false,
|
||||||
|
true);
|
||||||
|
|
||||||
connection->close();
|
connection->close();
|
||||||
socket->close();
|
socket->close();
|
||||||
|
@ -180,7 +187,11 @@ void LauncherCore::launchGame(const ProfileSettings& profile, const LoginAuth au
|
||||||
socket->listen(QHostAddress::Any, 5248);
|
socket->listen(QHostAddress::Any, 5248);
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(gameProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [this](int code, QProcess::ExitStatus status) {
|
connect(
|
||||||
|
gameProcess,
|
||||||
|
qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
|
||||||
|
this,
|
||||||
|
[this](int code, QProcess::ExitStatus status) {
|
||||||
gameClosed();
|
gameClosed();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -209,13 +220,18 @@ void LauncherCore::launchGameExecutable(const ProfileSettings& profile, QProcess
|
||||||
launchExecutable(profile, process, arguments, true, true);
|
launchExecutable(profile, process, arguments, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherCore::launchExecutable(const ProfileSettings& profile, QProcess* process, const QStringList args, bool isGame, bool needsRegistrySetup) {
|
void LauncherCore::launchExecutable(
|
||||||
|
const ProfileSettings& profile,
|
||||||
|
QProcess* process,
|
||||||
|
const QStringList args,
|
||||||
|
bool isGame,
|
||||||
|
bool needsRegistrySetup) {
|
||||||
QList<QString> arguments;
|
QList<QString> arguments;
|
||||||
auto env = process->processEnvironment();
|
auto env = process->processEnvironment();
|
||||||
|
|
||||||
if(needsRegistrySetup) {
|
if (needsRegistrySetup) {
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
||||||
if(profile.license == GameLicense::macOS) {
|
if (profile.license == GameLicense::macOS) {
|
||||||
addRegistryKey(profile, "HKEY_CURRENT_USER\\Software\\Wine", "HideWineExports", "0");
|
addRegistryKey(profile, "HKEY_CURRENT_USER\\Software\\Wine", "HideWineExports", "0");
|
||||||
} else {
|
} else {
|
||||||
addRegistryKey(profile, "HKEY_CURRENT_USER\\Software\\Wine", "HideWineExports", "1");
|
addRegistryKey(profile, "HKEY_CURRENT_USER\\Software\\Wine", "HideWineExports", "1");
|
||||||
|
@ -235,16 +251,13 @@ void LauncherCore::launchExecutable(const ProfileSettings& profile, QProcess* pr
|
||||||
arguments.push_back("-b");
|
arguments.push_back("-b");
|
||||||
|
|
||||||
if (profile.gamescope.width > 0)
|
if (profile.gamescope.width > 0)
|
||||||
arguments.push_back("-w " +
|
arguments.push_back("-w " + QString::number(profile.gamescope.width));
|
||||||
QString::number(profile.gamescope.width));
|
|
||||||
|
|
||||||
if (profile.gamescope.height > 0)
|
if (profile.gamescope.height > 0)
|
||||||
arguments.push_back("-h " +
|
arguments.push_back("-h " + QString::number(profile.gamescope.height));
|
||||||
QString::number(profile.gamescope.height));
|
|
||||||
|
|
||||||
if (profile.gamescope.refreshRate > 0)
|
if (profile.gamescope.refreshRate > 0)
|
||||||
arguments.push_back(
|
arguments.push_back("-r " + QString::number(profile.gamescope.refreshRate));
|
||||||
"-r " + QString::number(profile.gamescope.refreshRate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile.useGamemode)
|
if (profile.useGamemode)
|
||||||
|
@ -253,7 +266,7 @@ void LauncherCore::launchExecutable(const ProfileSettings& profile, QProcess* pr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
if(profile.useEsync) {
|
if (profile.useEsync) {
|
||||||
env.insert("WINEESYNC", QString::number(1));
|
env.insert("WINEESYNC", QString::number(1));
|
||||||
env.insert("WINEFSYNC", QString::number(1));
|
env.insert("WINEFSYNC", QString::number(1));
|
||||||
env.insert("WINEFSYNC_FUTEX2", QString::number(1));
|
env.insert("WINEFSYNC_FUTEX2", QString::number(1));
|
||||||
|
@ -264,9 +277,10 @@ void LauncherCore::launchExecutable(const ProfileSettings& profile, QProcess* pr
|
||||||
env.insert("WINEPREFIX", profile.winePrefixPath);
|
env.insert("WINEPREFIX", profile.winePrefixPath);
|
||||||
|
|
||||||
// XIV on Mac bundle their own Wine install directory, complete with libs etc
|
// XIV on Mac bundle their own Wine install directory, complete with libs etc
|
||||||
if(profile.wineType == WineType::XIVOnMac) {
|
if (profile.wineType == WineType::XIVOnMac) {
|
||||||
// TODO: don't hardcode this
|
// TODO: don't hardcode this
|
||||||
QString xivLibPath = "/Applications/XIV on Mac.app/Contents/Resources/wine/lib:/Applications/XIV on Mac.app/Contents/Resources/MoltenVK/modern";
|
QString xivLibPath = "/Applications/XIV on Mac.app/Contents/Resources/wine/lib:/Applications/XIV on "
|
||||||
|
"Mac.app/Contents/Resources/MoltenVK/modern";
|
||||||
|
|
||||||
env.insert("DYLD_FALLBACK_LIBRARY_PATH", xivLibPath);
|
env.insert("DYLD_FALLBACK_LIBRARY_PATH", xivLibPath);
|
||||||
env.insert("DYLD_VERSIONED_LIBRARY_PATH", xivLibPath);
|
env.insert("DYLD_VERSIONED_LIBRARY_PATH", xivLibPath);
|
||||||
|
@ -276,10 +290,10 @@ void LauncherCore::launchExecutable(const ProfileSettings& profile, QProcess* pr
|
||||||
env.insert("MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", "1");
|
env.insert("MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FLATPAK)
|
#if defined(FLATPAK)
|
||||||
arguments.push_back("flatpak-spawn");
|
arguments.push_back("flatpak-spawn");
|
||||||
arguments.push_back("--host");
|
arguments.push_back("--host");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
arguments.push_back(profile.winePath);
|
arguments.push_back(profile.winePath);
|
||||||
#endif
|
#endif
|
||||||
|
@ -317,8 +331,7 @@ void LauncherCore::readInitialInformation() {
|
||||||
gamescopeAvailable = checkIfInPath("gamescope");
|
gamescopeAvailable = checkIfInPath("gamescope");
|
||||||
gamemodeAvailable = checkIfInPath("gamemoderun");
|
gamemodeAvailable = checkIfInPath("gamemoderun");
|
||||||
|
|
||||||
const QString dataDir =
|
const QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
|
||||||
|
|
||||||
const bool hasDalamud = QFile::exists(dataDir + "/Dalamud");
|
const bool hasDalamud = QFile::exists(dataDir + "/Dalamud");
|
||||||
if (hasDalamud) {
|
if (hasDalamud) {
|
||||||
|
@ -328,33 +341,25 @@ void LauncherCore::readInitialInformation() {
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(depsJson.readAll());
|
QJsonDocument doc = QJsonDocument::fromJson(depsJson.readAll());
|
||||||
|
|
||||||
QString versionString;
|
QString versionString;
|
||||||
if(doc["targets"].toObject().contains(".NETCoreApp,Version=v5.0")) {
|
if (doc["targets"].toObject().contains(".NETCoreApp,Version=v5.0")) {
|
||||||
versionString =
|
versionString =
|
||||||
doc["targets"]
|
doc["targets"].toObject()[".NETCoreApp,Version=v5.0"].toObject().keys().filter("Dalamud")[0];
|
||||||
.toObject()[".NETCoreApp,Version=v5.0"]
|
|
||||||
.toObject()
|
|
||||||
.keys()
|
|
||||||
.filter("Dalamud")[0];
|
|
||||||
} else {
|
} else {
|
||||||
versionString =
|
versionString =
|
||||||
doc["targets"]
|
doc["targets"].toObject()[".NETCoreApp,Version=v6.0"].toObject().keys().filter("Dalamud")[0];
|
||||||
.toObject()[".NETCoreApp,Version=v6.0"]
|
|
||||||
.toObject()
|
|
||||||
.keys()
|
|
||||||
.filter("Dalamud")[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dalamudVersion = versionString.remove("Dalamud/");
|
dalamudVersion = versionString.remove("Dalamud/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(QFile::exists(dataDir + "/DalamudAssets/asset.ver")) {
|
if (QFile::exists(dataDir + "/DalamudAssets/asset.ver")) {
|
||||||
QFile assetJson(dataDir + "/DalamudAssets/asset.ver");
|
QFile assetJson(dataDir + "/DalamudAssets/asset.ver");
|
||||||
assetJson.open(QFile::ReadOnly | QFile::Text);
|
assetJson.open(QFile::ReadOnly | QFile::Text);
|
||||||
|
|
||||||
dalamudAssetVersion = QString(assetJson.readAll()).toInt();
|
dalamudAssetVersion = QString(assetJson.readAll()).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(QFile::exists(dataDir + "/DalamudRuntime/runtime.ver")) {
|
if (QFile::exists(dataDir + "/DalamudRuntime/runtime.ver")) {
|
||||||
QFile runtimeVer(dataDir + "/DalamudRuntime/runtime.ver");
|
QFile runtimeVer(dataDir + "/DalamudRuntime/runtime.ver");
|
||||||
runtimeVer.open(QFile::ReadOnly | QFile::Text);
|
runtimeVer.open(QFile::ReadOnly | QFile::Text);
|
||||||
|
|
||||||
|
@ -362,7 +367,7 @@ void LauncherCore::readInitialInformation() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(QFile::exists(dataDir + "/nativelauncher.ver")) {
|
if (QFile::exists(dataDir + "/nativelauncher.ver")) {
|
||||||
QFile nativeVer(dataDir + "/nativelauncher.ver");
|
QFile nativeVer(dataDir + "/nativelauncher.ver");
|
||||||
nativeVer.open(QFile::ReadOnly | QFile::Text);
|
nativeVer.open(QFile::ReadOnly | QFile::Text);
|
||||||
|
|
||||||
|
@ -372,12 +377,12 @@ void LauncherCore::readInitialInformation() {
|
||||||
auto profiles = settings.childGroups();
|
auto profiles = settings.childGroups();
|
||||||
|
|
||||||
// create the Default profile if it doesnt exist
|
// create the Default profile if it doesnt exist
|
||||||
if(profiles.empty())
|
if (profiles.empty())
|
||||||
profiles.append(QUuid::createUuid().toString(QUuid::StringFormat::WithoutBraces));
|
profiles.append(QUuid::createUuid().toString(QUuid::StringFormat::WithoutBraces));
|
||||||
|
|
||||||
profileSettings.resize(profiles.size());
|
profileSettings.resize(profiles.size());
|
||||||
|
|
||||||
for(const auto& uuid : profiles) {
|
for (const auto& uuid : profiles) {
|
||||||
ProfileSettings* profile = new ProfileSettings();
|
ProfileSettings* profile = new ProfileSettings();
|
||||||
profile->uuid = QUuid(uuid);
|
profile->uuid = QUuid(uuid);
|
||||||
|
|
||||||
|
@ -385,19 +390,22 @@ void LauncherCore::readInitialInformation() {
|
||||||
|
|
||||||
profile->name = settings.value("name", "Default").toString();
|
profile->name = settings.value("name", "Default").toString();
|
||||||
|
|
||||||
if(settings.contains("gamePath") && settings.value("gamePath").canConvert<QString>() && !settings.value("gamePath").toString().isEmpty()) {
|
if (settings.contains("gamePath") && settings.value("gamePath").canConvert<QString>() &&
|
||||||
|
!settings.value("gamePath").toString().isEmpty()) {
|
||||||
profile->gamePath = settings.value("gamePath").toString();
|
profile->gamePath = settings.value("gamePath").toString();
|
||||||
} else {
|
} else {
|
||||||
profile->gamePath = getDefaultGamePath();
|
profile->gamePath = getDefaultGamePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(settings.contains("winePrefixPath") && settings.value("winePrefixPath").canConvert<QString>() && !settings.value("winePrefixPath").toString().isEmpty()) {
|
if (settings.contains("winePrefixPath") && settings.value("winePrefixPath").canConvert<QString>() &&
|
||||||
|
!settings.value("winePrefixPath").toString().isEmpty()) {
|
||||||
profile->winePrefixPath = settings.value("winePrefixPath").toString();
|
profile->winePrefixPath = settings.value("winePrefixPath").toString();
|
||||||
} else {
|
} else {
|
||||||
profile->winePrefixPath = getDefaultWinePrefixPath();
|
profile->winePrefixPath = getDefaultWinePrefixPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(settings.contains("winePath") && settings.value("winePath").canConvert<QString>() && !settings.value("winePath").toString().isEmpty()) {
|
if (settings.contains("winePath") && settings.value("winePath").canConvert<QString>() &&
|
||||||
|
!settings.value("winePath").toString().isEmpty()) {
|
||||||
profile->winePath = settings.value("winePath").toString();
|
profile->winePath = settings.value("winePath").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,10 +429,10 @@ void LauncherCore::readInitialInformation() {
|
||||||
|
|
||||||
readWineInfo(*profile);
|
readWineInfo(*profile);
|
||||||
|
|
||||||
if(gamescopeAvailable)
|
if (gamescopeAvailable)
|
||||||
profile->useGamescope = settings.value("useGamescope", defaultSettings.useGamescope).toBool();
|
profile->useGamescope = settings.value("useGamescope", defaultSettings.useGamescope).toBool();
|
||||||
|
|
||||||
if(gamemodeAvailable)
|
if (gamemodeAvailable)
|
||||||
profile->useGamemode = settings.value("useGamemode", defaultSettings.useGamemode).toBool();
|
profile->useGamemode = settings.value("useGamemode", defaultSettings.useGamemode).toBool();
|
||||||
|
|
||||||
profile->enableDXVKhud = settings.value("enableDXVKhud", defaultSettings.enableDXVKhud).toBool();
|
profile->enableDXVKhud = settings.value("enableDXVKhud", defaultSettings.enableDXVKhud).toBool();
|
||||||
|
@ -432,14 +440,18 @@ void LauncherCore::readInitialInformation() {
|
||||||
profile->enableWatchdog = settings.value("enableWatchdog", defaultSettings.enableWatchdog).toBool();
|
profile->enableWatchdog = settings.value("enableWatchdog", defaultSettings.enableWatchdog).toBool();
|
||||||
|
|
||||||
// gamescope
|
// gamescope
|
||||||
profile->gamescope.borderless = settings.value("gamescopeBorderless", defaultSettings.gamescope.borderless).toBool();
|
profile->gamescope.borderless =
|
||||||
|
settings.value("gamescopeBorderless", defaultSettings.gamescope.borderless).toBool();
|
||||||
profile->gamescope.width = settings.value("gamescopeWidth", defaultSettings.gamescope.width).toInt();
|
profile->gamescope.width = settings.value("gamescopeWidth", defaultSettings.gamescope.width).toInt();
|
||||||
profile->gamescope.height = settings.value("gamescopeHeight", defaultSettings.gamescope.height).toInt();
|
profile->gamescope.height = settings.value("gamescopeHeight", defaultSettings.gamescope.height).toInt();
|
||||||
profile->gamescope.refreshRate = settings.value("gamescopeRefreshRate", defaultSettings.gamescope.refreshRate).toInt();
|
profile->gamescope.refreshRate =
|
||||||
|
settings.value("gamescopeRefreshRate", defaultSettings.gamescope.refreshRate).toInt();
|
||||||
|
|
||||||
profile->dalamud.enabled = settings.value("enableDalamud", defaultSettings.dalamud.enabled).toBool();
|
profile->dalamud.enabled = settings.value("enableDalamud", defaultSettings.dalamud.enabled).toBool();
|
||||||
profile->dalamud.optOutOfMbCollection = settings.value("dalamudOptOut", defaultSettings.dalamud.optOutOfMbCollection).toBool();
|
profile->dalamud.optOutOfMbCollection =
|
||||||
profile->dalamud.channel = (DalamudChannel)settings.value("dalamudChannel", (int)defaultSettings.dalamud.channel).toInt();
|
settings.value("dalamudOptOut", defaultSettings.dalamud.optOutOfMbCollection).toBool();
|
||||||
|
profile->dalamud.channel =
|
||||||
|
(DalamudChannel)settings.value("dalamudChannel", (int)defaultSettings.dalamud.channel).toInt();
|
||||||
|
|
||||||
profileSettings[settings.value("index").toInt()] = profile;
|
profileSettings[settings.value("index").toInt()] = profile;
|
||||||
|
|
||||||
|
@ -451,7 +463,7 @@ void LauncherCore::readInitialInformation() {
|
||||||
|
|
||||||
void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
switch(profile.wineType) {
|
switch (profile.wineType) {
|
||||||
case WineType::System: // system wine
|
case WineType::System: // system wine
|
||||||
profile.winePath = "/usr/local/bin/wine64";
|
profile.winePath = "/usr/local/bin/wine64";
|
||||||
break;
|
break;
|
||||||
|
@ -459,7 +471,8 @@ void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
||||||
profile.winePath = profile.winePath;
|
profile.winePath = profile.winePath;
|
||||||
break;
|
break;
|
||||||
case WineType::Builtin: // ffxiv built-in (for mac users)
|
case WineType::Builtin: // ffxiv built-in (for mac users)
|
||||||
profile.winePath = "/Applications/FINAL FANTASY XIV ONLINE.app/Contents/SharedSupport/finalfantasyxiv/FINAL FANTASY XIV ONLINE/wine";
|
profile.winePath = "/Applications/FINAL FANTASY XIV "
|
||||||
|
"ONLINE.app/Contents/SharedSupport/finalfantasyxiv/FINAL FANTASY XIV ONLINE/wine";
|
||||||
break;
|
break;
|
||||||
case WineType::XIVOnMac:
|
case WineType::XIVOnMac:
|
||||||
profile.winePath = "/Applications/XIV on Mac.app/Contents/Resources/wine/bin/wine64";
|
profile.winePath = "/Applications/XIV on Mac.app/Contents/Resources/wine/bin/wine64";
|
||||||
|
@ -468,7 +481,7 @@ void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
switch(profile.wineType) {
|
switch (profile.wineType) {
|
||||||
case WineType::System: // system wine (should be in $PATH)
|
case WineType::System: // system wine (should be in $PATH)
|
||||||
profile.winePath = "/usr/bin/wine";
|
profile.winePath = "/usr/bin/wine";
|
||||||
break;
|
break;
|
||||||
|
@ -493,7 +506,7 @@ void LauncherCore::readWineInfo(ProfileSettings& profile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherCore::readGameVersion() {
|
void LauncherCore::readGameVersion() {
|
||||||
for(auto& profile : profileSettings) {
|
for (auto& profile : profileSettings) {
|
||||||
profile->gameData = physis_gamedata_initialize((profile->gamePath + "/game").toStdString().c_str());
|
profile->gameData = physis_gamedata_initialize((profile->gamePath + "/game").toStdString().c_str());
|
||||||
profile->bootData = physis_bootdata_initialize((profile->gamePath + "/boot").toStdString().c_str());
|
profile->bootData = physis_bootdata_initialize((profile->gamePath + "/boot").toStdString().c_str());
|
||||||
|
|
||||||
|
@ -504,7 +517,8 @@ void LauncherCore::readGameVersion() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherCore::LauncherCore() : settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::applicationName()) {
|
LauncherCore::LauncherCore()
|
||||||
|
: 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);
|
||||||
|
@ -523,8 +537,8 @@ ProfileSettings& LauncherCore::getProfile(int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int LauncherCore::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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +547,7 @@ int LauncherCore::getProfileIndex(QString name) {
|
||||||
|
|
||||||
QList<QString> LauncherCore::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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,8 +573,8 @@ int LauncherCore::addProfile() {
|
||||||
|
|
||||||
int LauncherCore::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)
|
||||||
index = i;
|
index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +594,7 @@ void LauncherCore::saveSettings() {
|
||||||
settings.setValue("showBanners", appSettings.showBanners);
|
settings.setValue("showBanners", appSettings.showBanners);
|
||||||
settings.setValue("showNewsList", appSettings.showNewsList);
|
settings.setValue("showNewsList", appSettings.showNewsList);
|
||||||
|
|
||||||
for(int i = 0; i < profileSettings.size(); i++) {
|
for (int i = 0; i < profileSettings.size(); i++) {
|
||||||
const auto& profile = profileSettings[i];
|
const auto& profile = profileSettings[i];
|
||||||
|
|
||||||
settings.beginGroup(profile->uuid.toString(QUuid::StringFormat::WithoutBraces));
|
settings.beginGroup(profile->uuid.toString(QUuid::StringFormat::WithoutBraces));
|
||||||
|
@ -663,7 +677,9 @@ QString LauncherCore::getDefaultGamePath() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
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";
|
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";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
|
@ -671,19 +687,18 @@ QString LauncherCore::getDefaultGamePath() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherCore::addRegistryKey(const ProfileSettings& settings,
|
void LauncherCore::addRegistryKey(const ProfileSettings& settings, QString key, QString value, QString data) {
|
||||||
QString key, QString value, QString data) {
|
|
||||||
auto process = new QProcess(this);
|
auto process = new QProcess(this);
|
||||||
process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
|
process->setProcessEnvironment(QProcessEnvironment::systemEnvironment());
|
||||||
launchExecutable(settings, process, {"reg", "add", key, "/v", value, "/d", data, "/f" }, false, false);
|
launchExecutable(settings, process, {"reg", "add", key, "/v", value, "/d", data, "/f"}, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherCore::readGameData(ProfileSettings& profile) {
|
void LauncherCore::readGameData(ProfileSettings& profile) {
|
||||||
EXH* exh = physis_gamedata_read_excel_sheet_header(profile.gameData, "ExVersion");
|
EXH* exh = physis_gamedata_read_excel_sheet_header(profile.gameData, "ExVersion");
|
||||||
if(exh != nullptr) {
|
if (exh != nullptr) {
|
||||||
physis_EXD exd = physis_gamedata_read_excel_sheet(profile.gameData, "ExVersion", exh, Language::English, 0);
|
physis_EXD exd = physis_gamedata_read_excel_sheet(profile.gameData, "ExVersion", exh, Language::English, 0);
|
||||||
|
|
||||||
for(int i = 0; i < exd.row_count; i++) {
|
for (int i = 0; i < exd.row_count; i++) {
|
||||||
expansionNames.push_back(exd.row_data[i].column_data[0].string._0);
|
expansionNames.push_back(exd.row_data[i].column_data[0].string._0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <physis.hpp>
|
#include <physis.hpp>
|
||||||
#include <QDir>
|
|
||||||
|
|
||||||
Patcher::Patcher(QString baseDirectory, BootData* boot_data) : boot_data(boot_data), baseDirectory(baseDirectory) {
|
Patcher::Patcher(QString baseDirectory, BootData* boot_data) : boot_data(boot_data), baseDirectory(baseDirectory) {
|
||||||
dialog = new QProgressDialog();
|
dialog = new QProgressDialog();
|
||||||
|
@ -21,12 +21,12 @@ Patcher::Patcher(QString baseDirectory, GameData* game_data) : game_data(game_da
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patcher::processPatchList(QNetworkAccessManager& mgr, QString patchList) {
|
void Patcher::processPatchList(QNetworkAccessManager& mgr, QString patchList) {
|
||||||
if(patchList.isEmpty()) {
|
if (patchList.isEmpty()) {
|
||||||
dialog->hide();
|
dialog->hide();
|
||||||
|
|
||||||
emit done();
|
emit done();
|
||||||
} else {
|
} else {
|
||||||
if(isBoot()) {
|
if (isBoot()) {
|
||||||
dialog->setLabelText("Updating the FINAL FANTASY XIV Updater/Launcher version.");
|
dialog->setLabelText("Updating the FINAL FANTASY XIV Updater/Launcher version.");
|
||||||
} else {
|
} else {
|
||||||
dialog->setLabelText("Updating the FINAL FANTASY XIV Game version.");
|
dialog->setLabelText("Updating the FINAL FANTASY XIV Game version.");
|
||||||
|
@ -36,7 +36,7 @@ void Patcher::processPatchList(QNetworkAccessManager& mgr, QString patchList) {
|
||||||
|
|
||||||
remainingPatches = parts.size() - 7;
|
remainingPatches = parts.size() - 7;
|
||||||
|
|
||||||
for(int i = 5; i < parts.size() - 2; i++) {
|
for (int i = 5; i < parts.size() - 2; i++) {
|
||||||
const QStringList patchParts = parts[i].split("\t");
|
const QStringList patchParts = parts[i].split("\t");
|
||||||
|
|
||||||
const int length = patchParts[0].toInt();
|
const int length = patchParts[0].toInt();
|
||||||
|
@ -56,10 +56,12 @@ void Patcher::processPatchList(QNetworkAccessManager& mgr, QString patchList) {
|
||||||
auto url_parts = url.split('/');
|
auto url_parts = url.split('/');
|
||||||
repository = url_parts[url_parts.size() - 3];
|
repository = url_parts[url_parts.size() - 3];
|
||||||
|
|
||||||
if(isBoot()) {
|
if (isBoot()) {
|
||||||
dialog->setLabelText("Updating the FINAL FANTASY XIV Updater/Launcher version.\nDownloading ffxivboot - " + version);
|
dialog->setLabelText(
|
||||||
|
"Updating the FINAL FANTASY XIV Updater/Launcher version.\nDownloading ffxivboot - " + version);
|
||||||
} else {
|
} else {
|
||||||
dialog->setLabelText("Updating the FINAL FANTASY XIV Game version.\nDownloading " + repository + " - " + version);
|
dialog->setLabelText(
|
||||||
|
"Updating the FINAL FANTASY XIV Game version.\nDownloading " + repository + " - " + version);
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog->setMinimum(0);
|
dialog->setMinimum(0);
|
||||||
|
@ -68,10 +70,10 @@ void Patcher::processPatchList(QNetworkAccessManager& mgr, QString patchList) {
|
||||||
const QString patchesDir =
|
const QString patchesDir =
|
||||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/patches/" + repository;
|
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/patches/" + repository;
|
||||||
|
|
||||||
if(!QDir().exists(patchesDir))
|
if (!QDir().exists(patchesDir))
|
||||||
QDir().mkdir(patchesDir);
|
QDir().mkdir(patchesDir);
|
||||||
|
|
||||||
if(!QFile::exists(patchesDir + "/" + name + ".patch")) {
|
if (!QFile::exists(patchesDir + "/" + name + ".patch")) {
|
||||||
QNetworkRequest patchRequest(url);
|
QNetworkRequest patchRequest(url);
|
||||||
auto patchReply = mgr.get(patchRequest);
|
auto patchReply = mgr.get(patchRequest);
|
||||||
connect(patchReply, &QNetworkReply::downloadProgress, [=](int recieved, int total) {
|
connect(patchReply, &QNetworkReply::downloadProgress, [=](int recieved, int total) {
|
||||||
|
@ -102,7 +104,7 @@ void Patcher::processPatchList(QNetworkAccessManager& mgr, QString patchList) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patcher::checkIfDone() {
|
void Patcher::checkIfDone() {
|
||||||
if(remainingPatches <= 0) {
|
if (remainingPatches <= 0) {
|
||||||
for (auto patch : patchQueue) {
|
for (auto patch : patchQueue) {
|
||||||
processPatch(patch);
|
processPatch(patch);
|
||||||
}
|
}
|
||||||
|
@ -116,17 +118,17 @@ void Patcher::checkIfDone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patcher::processPatch(QueuedPatch patch) {
|
void Patcher::processPatch(QueuedPatch patch) {
|
||||||
if(isBoot()) {
|
if (isBoot()) {
|
||||||
physis_bootdata_apply_patch(boot_data, patch.path.toStdString().c_str());
|
physis_bootdata_apply_patch(boot_data, patch.path.toStdString().c_str());
|
||||||
} else {
|
} else {
|
||||||
physis_gamedata_apply_patch(game_data, patch.path.toStdString().c_str());
|
physis_gamedata_apply_patch(game_data, patch.path.toStdString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString verFilePath;
|
QString verFilePath;
|
||||||
if(isBoot()) {
|
if (isBoot()) {
|
||||||
verFilePath = baseDirectory + "/ffxivboot.ver";
|
verFilePath = baseDirectory + "/ffxivboot.ver";
|
||||||
} else {
|
} else {
|
||||||
if(patch.repository == "game") {
|
if (patch.repository == "game") {
|
||||||
verFilePath = baseDirectory + "/ffxivgame.ver";
|
verFilePath = baseDirectory + "/ffxivgame.ver";
|
||||||
} else {
|
} else {
|
||||||
verFilePath = baseDirectory + "/sqpack/" + patch.repository + "/" + patch.repository + ".ver";
|
verFilePath = baseDirectory + "/sqpack/" + patch.repository + "/" + patch.repository + ".ver";
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
#include "sapphirelauncher.h"
|
#include "sapphirelauncher.h"
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
|
||||||
SapphireLauncher::SapphireLauncher(LauncherCore& window) : window(window), QObject(&window) {
|
SapphireLauncher::SapphireLauncher(LauncherCore& window) : window(window), QObject(&window) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SapphireLauncher::login(QString lobbyUrl, const LoginInformation& info) {
|
void SapphireLauncher::login(QString lobbyUrl, const LoginInformation& info) {
|
||||||
QJsonObject data {
|
QJsonObject data{{"username", info.username}, {"pass", info.password}};
|
||||||
{"username", info.username},
|
|
||||||
{"pass", info.password}
|
|
||||||
};
|
|
||||||
|
|
||||||
QUrl url;
|
QUrl url;
|
||||||
url.setScheme("http");
|
url.setScheme("http");
|
||||||
|
@ -21,12 +16,12 @@ void SapphireLauncher::login(QString lobbyUrl, const LoginInformation& info) {
|
||||||
url.setPath("/sapphire-api/lobby/login");
|
url.setPath("/sapphire-api/lobby/login");
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
auto reply = window.mgr->post(request, QJsonDocument(data).toJson(QJsonDocument::JsonFormat::Compact));
|
auto reply = window.mgr->post(request, QJsonDocument(data).toJson(QJsonDocument::JsonFormat::Compact));
|
||||||
connect(reply, &QNetworkReply::finished, [&] {
|
connect(reply, &QNetworkReply::finished, [&] {
|
||||||
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
if(!document.isEmpty()) {
|
if (!document.isEmpty()) {
|
||||||
LoginAuth auth;
|
LoginAuth auth;
|
||||||
auth.SID = document["sId"].toString();
|
auth.SID = document["sId"].toString();
|
||||||
auth.lobbyhost = document["lobbyHost"].toString();
|
auth.lobbyhost = document["lobbyHost"].toString();
|
||||||
|
@ -35,24 +30,22 @@ void SapphireLauncher::login(QString lobbyUrl, const LoginInformation& info) {
|
||||||
|
|
||||||
window.launchGame(*info.settings, 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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SapphireLauncher::registerAccount(QString lobbyUrl, const LoginInformation& info) {
|
void SapphireLauncher::registerAccount(QString lobbyUrl, const LoginInformation& info) {
|
||||||
QJsonObject data {
|
QJsonObject data{{"username", info.username}, {"pass", info.password}};
|
||||||
{"username", info.username},
|
|
||||||
{"pass", info.password}
|
|
||||||
};
|
|
||||||
QUrl url;
|
QUrl url;
|
||||||
url.setScheme("http");
|
url.setScheme("http");
|
||||||
url.setHost(lobbyUrl);
|
url.setHost(lobbyUrl);
|
||||||
url.setPath("/sapphire-api/lobby/createAccount");
|
url.setPath("/sapphire-api/lobby/createAccount");
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
auto reply = window.mgr->post(request, QJsonDocument(data).toJson(QJsonDocument::JsonFormat::Compact));
|
auto reply = window.mgr->post(request, QJsonDocument(data).toJson(QJsonDocument::JsonFormat::Compact));
|
||||||
connect(reply, &QNetworkReply::finished, [&] {
|
connect(reply, &QNetworkReply::finished, [&] {
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
#include "squareboot.h"
|
#include "squareboot.h"
|
||||||
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <physis.hpp>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
#include <physis.hpp>
|
||||||
|
|
||||||
#include "squarelauncher.h"
|
#include "squarelauncher.h"
|
||||||
|
|
||||||
SquareBoot::SquareBoot(LauncherCore& window, SquareLauncher& launcher) : window(window), launcher(launcher), QObject(&window) {
|
SquareBoot::SquareBoot(LauncherCore& window, SquareLauncher& launcher)
|
||||||
|
: window(window), launcher(launcher), QObject(&window) {}
|
||||||
}
|
|
||||||
|
|
||||||
void SquareBoot::bootCheck(const LoginInformation& info) {
|
void SquareBoot::bootCheck(const LoginInformation& info) {
|
||||||
patcher = new Patcher(info.settings->gamePath + "/boot", info.settings->bootData);
|
patcher = new Patcher(info.settings->gamePath + "/boot", info.settings->bootData);
|
||||||
|
@ -34,7 +33,7 @@ void SquareBoot::bootCheck(const LoginInformation& info) {
|
||||||
url.setQuery(query);
|
url.setQuery(query);
|
||||||
|
|
||||||
auto request = QNetworkRequest(url);
|
auto request = QNetworkRequest(url);
|
||||||
if(info.settings->license == GameLicense::macOS) {
|
if (info.settings->license == GameLicense::macOS) {
|
||||||
request.setRawHeader("User-Agent", "FFXIV-MAC PATCH CLIENT");
|
request.setRawHeader("User-Agent", "FFXIV-MAC PATCH CLIENT");
|
||||||
} else {
|
} else {
|
||||||
request.setRawHeader("User-Agent", "FFXIV PATCH CLIENT");
|
request.setRawHeader("User-Agent", "FFXIV PATCH CLIENT");
|
||||||
|
@ -69,19 +68,21 @@ void SquareBoot::checkGateStatus(LoginInformation* info) {
|
||||||
// I happen to run into this issue often, if I start the launcher really quickly after bootup
|
// I happen to run into this issue often, if I start the launcher really quickly after bootup
|
||||||
// it's possible to actually check this quicker than the network is actually available,
|
// it's possible to actually check this quicker than the network is actually available,
|
||||||
// causing the launcher to be stuck in "maintenace mode". so if that happens, we try to rerun this logic.
|
// causing the launcher to be stuck in "maintenace mode". so if that happens, we try to rerun this logic.
|
||||||
// TODO: this selection of errors is currently guesswork, i'm assuming one of these will fit the bill of "internet is unavailable" in
|
// TODO: this selection of errors is currently guesswork, i'm assuming one of these will fit the bill of
|
||||||
// some way.
|
// "internet is unavailable" in some way.
|
||||||
if(reply->error() == QNetworkReply::HostNotFoundError || reply->error() == QNetworkReply::TimeoutError || reply->error() == QNetworkReply::UnknownServerError)
|
if (reply->error() == QNetworkReply::HostNotFoundError || reply->error() == QNetworkReply::TimeoutError ||
|
||||||
|
reply->error() == QNetworkReply::UnknownServerError)
|
||||||
checkGateStatus(info);
|
checkGateStatus(info);
|
||||||
|
|
||||||
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
|
||||||
|
|
||||||
const bool isGateOpen = !document.isEmpty() && document.object()["status"].toInt() != 0;
|
const bool isGateOpen = !document.isEmpty() && document.object()["status"].toInt() != 0;
|
||||||
|
|
||||||
if(isGateOpen) {
|
if (isGateOpen) {
|
||||||
bootCheck(*info);
|
bootCheck(*info);
|
||||||
} else {
|
} else {
|
||||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical,
|
auto messageBox = new QMessageBox(
|
||||||
|
QMessageBox::Icon::Critical,
|
||||||
"Failed to Login",
|
"Failed to Login",
|
||||||
"The login gate is closed, the game may be under maintenance.");
|
"The login gate is closed, the game may be under maintenance.");
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,22 @@
|
||||||
#include "squarelauncher.h"
|
#include "squarelauncher.h"
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QRegularExpressionMatch>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QNetworkReply>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QDesktopServices>
|
#include <QRegularExpressionMatch>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
#ifdef ENABLE_WATCHDOG
|
#ifdef ENABLE_WATCHDOG
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SquareLauncher::SquareLauncher(LauncherCore& window) : window(window), QObject(&window) {
|
SquareLauncher::SquareLauncher(LauncherCore& window) : window(window), QObject(&window) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QString getFileHash(QString file) {
|
QString getFileHash(QString file) {
|
||||||
auto f = QFile(file);
|
auto f = QFile(file);
|
||||||
|
@ -42,7 +40,7 @@ void SquareLauncher::getStored(const LoginInformation& info) {
|
||||||
query.addQueryItem("isnew", "1");
|
query.addQueryItem("isnew", "1");
|
||||||
query.addQueryItem("launchver", "3");
|
query.addQueryItem("launchver", "3");
|
||||||
|
|
||||||
if(info.settings->license == GameLicense::WindowsSteam) {
|
if (info.settings->license == GameLicense::WindowsSteam) {
|
||||||
query.addQueryItem("issteam", "1");
|
query.addQueryItem("issteam", "1");
|
||||||
|
|
||||||
// TODO: get steam ticket information from steam api
|
// TODO: get steam ticket information from steam api
|
||||||
|
@ -62,14 +60,17 @@ void SquareLauncher::getStored(const LoginInformation& info) {
|
||||||
auto str = QString(reply->readAll());
|
auto str = QString(reply->readAll());
|
||||||
|
|
||||||
// fetches Steam username
|
// fetches Steam username
|
||||||
if(info.settings->license == GameLicense::WindowsSteam) {
|
if (info.settings->license == GameLicense::WindowsSteam) {
|
||||||
QRegularExpression re(R"lit(<input name=""sqexid"" type=""hidden"" value=""(?<sqexid>.*)""\/>)lit");
|
QRegularExpression re(R"lit(<input name=""sqexid"" type=""hidden"" value=""(?<sqexid>.*)""\/>)lit");
|
||||||
QRegularExpressionMatch match = re.match(str);
|
QRegularExpressionMatch match = re.match(str);
|
||||||
|
|
||||||
if(match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
username = match.captured(1);
|
username = match.captured(1);
|
||||||
} else {
|
} else {
|
||||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Could not get Steam username, have you attached your account?");
|
auto messageBox = new QMessageBox(
|
||||||
|
QMessageBox::Icon::Critical,
|
||||||
|
"Failed to Login",
|
||||||
|
"Could not get Steam username, have you attached your account?");
|
||||||
messageBox->show();
|
messageBox->show();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,7 +83,10 @@ void SquareLauncher::getStored(const LoginInformation& info) {
|
||||||
stored = match.captured(1);
|
stored = match.captured(1);
|
||||||
login(info, url);
|
login(info, url);
|
||||||
} else {
|
} else {
|
||||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Failed to contact SE servers. They may be in maintenance.");
|
auto messageBox = new QMessageBox(
|
||||||
|
QMessageBox::Icon::Critical,
|
||||||
|
"Failed to Login",
|
||||||
|
"Failed to contact SE servers. They may be in maintenance.");
|
||||||
messageBox->show();
|
messageBox->show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -97,7 +101,7 @@ void SquareLauncher::login(const LoginInformation& info, const QUrl referer) {
|
||||||
|
|
||||||
QNetworkRequest request(QUrl("https://ffxiv-login.square-enix.com/oauth/ffxivarr/login/login.send"));
|
QNetworkRequest request(QUrl("https://ffxiv-login.square-enix.com/oauth/ffxivarr/login/login.send"));
|
||||||
window.buildRequest(*info.settings, request);
|
window.buildRequest(*info.settings, request);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
request.setRawHeader("Referer", referer.toEncoded());
|
request.setRawHeader("Referer", referer.toEncoded());
|
||||||
request.setRawHeader("Cache-Control", "no-cache");
|
request.setRawHeader("Cache-Control", "no-cache");
|
||||||
|
|
||||||
|
@ -107,14 +111,18 @@ void SquareLauncher::login(const LoginInformation& info, const QUrl referer) {
|
||||||
|
|
||||||
QRegularExpression re(R"lit(window.external.user\("login=auth,ok,(?<launchParams>.*)\);)lit");
|
QRegularExpression re(R"lit(window.external.user\("login=auth,ok,(?<launchParams>.*)\);)lit");
|
||||||
QRegularExpressionMatch match = re.match(str);
|
QRegularExpressionMatch match = re.match(str);
|
||||||
if(match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
const auto parts = match.captured(1).split(',');
|
const auto parts = match.captured(1).split(',');
|
||||||
|
|
||||||
const bool terms = parts[3] == "1";
|
const bool terms = parts[3] == "1";
|
||||||
const bool playable = parts[9] == "1";
|
const bool playable = parts[9] == "1";
|
||||||
|
|
||||||
if(!playable) {
|
if (!playable) {
|
||||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Your game is unplayable. Please check that you have the right license selected, and a subscription to play.");
|
auto messageBox = new QMessageBox(
|
||||||
|
QMessageBox::Icon::Critical,
|
||||||
|
"Failed to Login",
|
||||||
|
"Your game is unplayable. Please check that you have the right license selected, and a "
|
||||||
|
"subscription to play.");
|
||||||
|
|
||||||
auto launcherButton = messageBox->addButton("Open Mog Station", QMessageBox::HelpRole);
|
auto launcherButton = messageBox->addButton("Open Mog Station", QMessageBox::HelpRole);
|
||||||
connect(launcherButton, &QPushButton::clicked, [=] {
|
connect(launcherButton, &QPushButton::clicked, [=] {
|
||||||
|
@ -128,8 +136,11 @@ void SquareLauncher::login(const LoginInformation& info, const QUrl referer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!terms) {
|
if (!terms) {
|
||||||
auto messageBox = new QMessageBox(QMessageBox::Icon::Critical, "Failed to Login", "Your game is unplayable. You need to accept the terms of service from the official launcher.");
|
auto messageBox = new QMessageBox(
|
||||||
|
QMessageBox::Icon::Critical,
|
||||||
|
"Failed to Login",
|
||||||
|
"Your game is unplayable. You need to accept the terms of service from the official launcher.");
|
||||||
window.addUpdateButtons(*info.settings, *messageBox);
|
window.addUpdateButtons(*info.settings, *messageBox);
|
||||||
|
|
||||||
messageBox->show();
|
messageBox->show();
|
||||||
|
@ -161,20 +172,21 @@ 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(info.settings->repositories.repositories[0].version, SID));
|
url.setPath(QString("/http/win32/ffxivneo_release_game/%1/%2")
|
||||||
|
.arg(info.settings->repositories.repositories[0].version, SID));
|
||||||
|
|
||||||
auto request = QNetworkRequest(url);
|
auto request = QNetworkRequest(url);
|
||||||
window.setSSL(request);
|
window.setSSL(request);
|
||||||
request.setRawHeader("X-Hash-Check", "enabled");
|
request.setRawHeader("X-Hash-Check", "enabled");
|
||||||
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 = QString("%1=%2").arg(info.settings->bootVersion, getBootHash(info));
|
QString report = QString("%1=%2").arg(info.settings->bootVersion, getBootHash(info));
|
||||||
|
|
||||||
for(int i = 1; i < auth.maxExpansion + 1; i++) {
|
for (int i = 1; i < auth.maxExpansion + 1; i++) {
|
||||||
if(i <= info.settings->repositories.repositories_count) {
|
if (i <= info.settings->repositories.repositories_count) {
|
||||||
report += QString("\nex%1\t%2")
|
report +=
|
||||||
.arg(QString::number(i), info.settings->repositories.repositories[i].version);
|
QString("\nex%1\t%2").arg(QString::number(i), info.settings->repositories.repositories[i].version);
|
||||||
} else {
|
} else {
|
||||||
report += QString("\nex%1\t2012.01.01.0000.0000").arg(QString::number(i));
|
report += QString("\nex%1\t2012.01.01.0000.0000").arg(QString::number(i));
|
||||||
}
|
}
|
||||||
|
@ -182,7 +194,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
||||||
|
|
||||||
auto reply = window.mgr->post(request, report.toUtf8());
|
auto reply = window.mgr->post(request, report.toUtf8());
|
||||||
connect(reply, &QNetworkReply::finished, [=, &info] {
|
connect(reply, &QNetworkReply::finished, [=, &info] {
|
||||||
if(reply->rawHeaderList().contains("X-Patch-Unique-Id")) {
|
if (reply->rawHeaderList().contains("X-Patch-Unique-Id")) {
|
||||||
QString body = reply->readAll();
|
QString body = reply->readAll();
|
||||||
|
|
||||||
patcher = new Patcher(info.settings->gamePath + "/game", info.settings->gameData);
|
patcher = new Patcher(info.settings->gamePath + "/game", info.settings->gameData);
|
||||||
|
@ -192,7 +204,7 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
||||||
auth.SID = reply->rawHeader("X-Patch-Unique-Id");
|
auth.SID = reply->rawHeader("X-Patch-Unique-Id");
|
||||||
|
|
||||||
#ifdef ENABLE_WATCHDOG
|
#ifdef ENABLE_WATCHDOG
|
||||||
if(info.settings->enableWatchdog) {
|
if (info.settings->enableWatchdog) {
|
||||||
window.watchdog->launchGame(*info.settings, auth);
|
window.watchdog->launchGame(*info.settings, auth);
|
||||||
} else {
|
} else {
|
||||||
window.launchGame(*info.settings, auth);
|
window.launchGame(*info.settings, auth);
|
||||||
|
@ -204,7 +216,10 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
||||||
|
|
||||||
patcher->processPatchList(*window.mgr, body);
|
patcher->processPatchList(*window.mgr, body);
|
||||||
} 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.");
|
||||||
window.addUpdateButtons(*info.settings, *messageBox);
|
window.addUpdateButtons(*info.settings, *messageBox);
|
||||||
|
|
||||||
messageBox->show();
|
messageBox->show();
|
||||||
|
@ -213,15 +228,13 @@ void SquareLauncher::registerSession(const LoginInformation& info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SquareLauncher::getBootHash(const LoginInformation& info) {
|
QString SquareLauncher::getBootHash(const LoginInformation& info) {
|
||||||
const QList<QString> fileList =
|
const QList<QString> fileList = {
|
||||||
{
|
|
||||||
"ffxivboot.exe",
|
"ffxivboot.exe",
|
||||||
"ffxivboot64.exe",
|
"ffxivboot64.exe",
|
||||||
"ffxivlauncher.exe",
|
"ffxivlauncher.exe",
|
||||||
"ffxivlauncher64.exe",
|
"ffxivlauncher64.exe",
|
||||||
"ffxivupdater.exe",
|
"ffxivupdater.exe",
|
||||||
"ffxivupdater64.exe"
|
"ffxivupdater64.exe"};
|
||||||
};
|
|
||||||
|
|
||||||
QString result;
|
QString result;
|
||||||
for (int i = 0; i < fileList.count(); i++) {
|
for (int i = 0; i < fileList.count(); i++) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QScreen>
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
@ -13,34 +13,33 @@
|
||||||
// from https://github.com/adobe/webkit/blob/master/Source/WebCore/plugins/qt/QtX11ImageConversion.cpp
|
// from https://github.com/adobe/webkit/blob/master/Source/WebCore/plugins/qt/QtX11ImageConversion.cpp
|
||||||
// code is licensed under GPLv2
|
// code is licensed under GPLv2
|
||||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
|
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
|
||||||
QImage qimageFromXImage(XImage *xi) {
|
QImage qimageFromXImage(XImage* xi) {
|
||||||
QImage::Format format = QImage::Format_ARGB32_Premultiplied;
|
QImage::Format format = QImage::Format_ARGB32_Premultiplied;
|
||||||
if (xi->depth == 24)
|
if (xi->depth == 24)
|
||||||
format = QImage::Format_RGB32;
|
format = QImage::Format_RGB32;
|
||||||
else if (xi->depth == 16)
|
else if (xi->depth == 16)
|
||||||
format = QImage::Format_RGB16;
|
format = QImage::Format_RGB16;
|
||||||
|
|
||||||
QImage image = QImage(reinterpret_cast<uchar *>(xi->data), xi->width, xi->height, xi->bytes_per_line,
|
QImage image = QImage(reinterpret_cast<uchar*>(xi->data), xi->width, xi->height, xi->bytes_per_line, format).copy();
|
||||||
format).copy();
|
|
||||||
|
|
||||||
// we may have to swap the byte order
|
// we may have to swap the byte order
|
||||||
if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
|
if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst) ||
|
||||||
|| (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) {
|
(QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) {
|
||||||
|
|
||||||
for (int i = 0; i < image.height(); i++) {
|
for (int i = 0; i < image.height(); i++) {
|
||||||
if (xi->depth == 16) {
|
if (xi->depth == 16) {
|
||||||
ushort *p = reinterpret_cast<ushort *>(image.scanLine(i));
|
ushort* p = reinterpret_cast<ushort*>(image.scanLine(i));
|
||||||
ushort *end = p + image.width();
|
ushort* end = p + image.width();
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
*p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
|
*p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint *p = reinterpret_cast<uint *>(image.scanLine(i));
|
uint* p = reinterpret_cast<uint*>(image.scanLine(i));
|
||||||
uint *end = p + image.width();
|
uint* end = p + image.width();
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
*p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
|
*p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) | ((*p >> 8) & 0x0000ff00) |
|
||||||
| ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
|
((*p >> 24) & 0x000000ff);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +48,7 @@ QImage qimageFromXImage(XImage *xi) {
|
||||||
|
|
||||||
// fix-up alpha channel
|
// fix-up alpha channel
|
||||||
if (format == QImage::Format_RGB32) {
|
if (format == QImage::Format_RGB32) {
|
||||||
QRgb *p = reinterpret_cast<QRgb *>(image.bits());
|
QRgb* p = reinterpret_cast<QRgb*>(image.bits());
|
||||||
for (int y = 0; y < xi->height; ++y) {
|
for (int y = 0; y < xi->height; ++y) {
|
||||||
for (int x = 0; x < xi->width; ++x)
|
for (int x = 0; x < xi->width; ++x)
|
||||||
p[x] |= 0xff000000;
|
p[x] |= 0xff000000;
|
||||||
|
@ -60,8 +59,8 @@ QImage qimageFromXImage(XImage *xi) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Watchdog::launchGame(const ProfileSettings &settings, LoginAuth auth) {
|
void Watchdog::launchGame(const ProfileSettings& settings, LoginAuth auth) {
|
||||||
if(icon == nullptr) {
|
if (icon == nullptr) {
|
||||||
icon = new QSystemTrayIcon();
|
icon = new QSystemTrayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +83,7 @@ void Watchdog::launchGame(const ProfileSettings &settings, LoginAuth auth) {
|
||||||
|
|
||||||
core.launchGame(settings, auth);
|
core.launchGame(settings, auth);
|
||||||
|
|
||||||
if(parser == nullptr) {
|
if (parser == nullptr) {
|
||||||
parser = std::make_unique<GameParser>();
|
parser = std::make_unique<GameParser>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +91,9 @@ void Watchdog::launchGame(const ProfileSettings &settings, LoginAuth auth) {
|
||||||
if (processWindowId == -1) {
|
if (processWindowId == -1) {
|
||||||
auto xdoProcess = new QProcess();
|
auto xdoProcess = new QProcess();
|
||||||
|
|
||||||
connect(xdoProcess, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
connect(
|
||||||
|
xdoProcess,
|
||||||
|
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
[=](int, QProcess::ExitStatus) {
|
[=](int, QProcess::ExitStatus) {
|
||||||
QString output = xdoProcess->readAllStandardOutput();
|
QString output = xdoProcess->readAllStandardOutput();
|
||||||
qDebug() << "Found XIV Window: " << output.toInt();
|
qDebug() << "Found XIV Window: " << output.toInt();
|
||||||
|
@ -123,8 +124,7 @@ void Watchdog::launchGame(const ProfileSettings &settings, LoginAuth auth) {
|
||||||
XRenderPictureAttributes pa;
|
XRenderPictureAttributes pa;
|
||||||
pa.subwindow_mode = IncludeInferiors;
|
pa.subwindow_mode = IncludeInferiors;
|
||||||
|
|
||||||
Picture picture = XRenderCreatePicture(display, processWindowId, format,
|
Picture picture = XRenderCreatePicture(display, processWindowId, format, CPSubwindowMode, &pa);
|
||||||
CPSubwindowMode, &pa);
|
|
||||||
XFlush(display); // TODO: does this actually make a difference?
|
XFlush(display); // TODO: does this actually make a difference?
|
||||||
|
|
||||||
XImage* image = XGetImage(display, processWindowId, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
|
XImage* image = XGetImage(display, processWindowId, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
|
||||||
|
@ -134,33 +134,30 @@ void Watchdog::launchGame(const ProfileSettings &settings, LoginAuth auth) {
|
||||||
auto result = parser->parseImage(qimageFromXImage(image));
|
auto result = parser->parseImage(qimageFromXImage(image));
|
||||||
if (result != lastResult) {
|
if (result != lastResult) {
|
||||||
// skip OCR errors (TODO: should be handled by GameParser itself)
|
// skip OCR errors (TODO: should be handled by GameParser itself)
|
||||||
if(result.state == ScreenState::InLoginQueue && result.playersInQueue == 0)
|
if (result.state == ScreenState::InLoginQueue && result.playersInQueue == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (result.state) {
|
switch (result.state) {
|
||||||
case ScreenState::InLoginQueue: {
|
case ScreenState::InLoginQueue: {
|
||||||
icon->showMessage("Watchdog",
|
icon->showMessage(
|
||||||
QString("You are now at position %1 (moved %2 spots)").arg(
|
"Watchdog",
|
||||||
result.playersInQueue).arg(
|
QString("You are now at position %1 (moved %2 spots)")
|
||||||
lastResult.playersInQueue - result.playersInQueue));
|
.arg(result.playersInQueue)
|
||||||
|
.arg(lastResult.playersInQueue - result.playersInQueue));
|
||||||
|
|
||||||
icon->setToolTip(QString("Queue Status (%1)").arg(result.playersInQueue));
|
icon->setToolTip(QString("Queue Status (%1)").arg(result.playersInQueue));
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
case ScreenState::LobbyError: {
|
case ScreenState::LobbyError: {
|
||||||
// TODO: kill game?
|
// TODO: kill game?
|
||||||
icon->showMessage("Watchdog", "You have been disconnected due to a lobby error.");
|
icon->showMessage("Watchdog", "You have been disconnected due to a lobby error.");
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
case ScreenState::ConnectingToDataCenter: {
|
case ScreenState::ConnectingToDataCenter: {
|
||||||
icon->showMessage("Watchdog",
|
icon->showMessage(
|
||||||
"You are in the process of being connected to the data center.");
|
"Watchdog", "You are in the process of being connected to the data center.");
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
case ScreenState::WorldFull: {
|
case ScreenState::WorldFull: {
|
||||||
icon->showMessage("Watchdog", "You have been disconnected due to a lobby error.");
|
icon->showMessage("Watchdog", "You have been disconnected due to a lobby error.");
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastResult = result;
|
lastResult = result;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QTemporaryDir>
|
|
||||||
#include <QProgressDialog>
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ public:
|
||||||
void setUrl(QUrl url);
|
void setUrl(QUrl url);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUrl url;
|
QUrl url;
|
||||||
};
|
};
|
|
@ -1,11 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QDialog>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QListWidget>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
class LauncherCore;
|
class LauncherCore;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QPushButton>
|
#include <QComboBox>
|
||||||
#include <QTreeWidget>
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
#include <QTreeWidget>
|
||||||
|
|
||||||
#include "launchercore.h"
|
|
||||||
#include "headline.h"
|
#include "headline.h"
|
||||||
|
#include "launchercore.h"
|
||||||
|
|
||||||
class LauncherWindow : public QMainWindow {
|
class LauncherWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -51,10 +51,10 @@ private:
|
||||||
QAction* openGameDir;
|
QAction* openGameDir;
|
||||||
|
|
||||||
QComboBox* profileSelect;
|
QComboBox* profileSelect;
|
||||||
QLineEdit* usernameEdit, *passwordEdit;
|
QLineEdit *usernameEdit, *passwordEdit;
|
||||||
QLineEdit* otpEdit;
|
QLineEdit* otpEdit;
|
||||||
QCheckBox* rememberUsernameBox, *rememberPasswordBox;
|
QCheckBox *rememberUsernameBox, *rememberPasswordBox;
|
||||||
QPushButton* loginButton, *registerButton;
|
QPushButton *loginButton, *registerButton;
|
||||||
|
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
|
#if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
|
||||||
QAction* wineCfg;
|
QAction* wineCfg;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QLabel>
|
#include <QComboBox>
|
||||||
#include <QPushButton>
|
#include <QDialog>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
class LauncherCore;
|
class LauncherCore;
|
||||||
class LauncherWindow;
|
class LauncherWindow;
|
||||||
|
@ -54,14 +54,14 @@ private:
|
||||||
QPushButton* configureGamescopeButton;
|
QPushButton* configureGamescopeButton;
|
||||||
QLabel* wineVersionLabel;
|
QLabel* wineVersionLabel;
|
||||||
|
|
||||||
QCheckBox* useGamescope, *useEsync, *useGamemode;
|
QCheckBox *useGamescope, *useEsync, *useGamemode;
|
||||||
QCheckBox* enableWatchdog;
|
QCheckBox* enableWatchdog;
|
||||||
|
|
||||||
// login
|
// login
|
||||||
QCheckBox* encryptArgumentsBox = nullptr;
|
QCheckBox* encryptArgumentsBox = nullptr;
|
||||||
QComboBox* serverType = nullptr;
|
QComboBox* serverType = nullptr;
|
||||||
QLineEdit* lobbyServerURL = nullptr;
|
QLineEdit* lobbyServerURL = nullptr;
|
||||||
QCheckBox* rememberUsernameBox = nullptr, *rememberPasswordBox = nullptr;
|
QCheckBox *rememberUsernameBox = nullptr, *rememberPasswordBox = nullptr;
|
||||||
QComboBox* gameLicenseBox = nullptr;
|
QComboBox* gameLicenseBox = nullptr;
|
||||||
QCheckBox* freeTrialBox = nullptr;
|
QCheckBox* freeTrialBox = nullptr;
|
||||||
QCheckBox* useOneTimePassword = nullptr;
|
QCheckBox* useOneTimePassword = nullptr;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include "aboutwindow.h"
|
#include "aboutwindow.h"
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QTabWidget>
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
|
#include <QTabWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "license.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "license.h"
|
||||||
|
|
||||||
AboutWindow::AboutWindow(QWidget* widget) : QDialog(widget) {
|
AboutWindow::AboutWindow(QWidget* widget) : QDialog(widget) {
|
||||||
setWindowTitle("About");
|
setWindowTitle("About");
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include "assetupdater.h"
|
#include "assetupdater.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QJsonArray>
|
|
||||||
|
|
||||||
#include <JlCompress.h>
|
#include <JlCompress.h>
|
||||||
|
|
||||||
|
@ -20,10 +20,8 @@ const QString dalamudVersionManifestURL = baseDalamudDistribution + "%1version";
|
||||||
const QString baseDalamudAssetDistribution = baseGoatDomain + "/DalamudAssets";
|
const QString baseDalamudAssetDistribution = baseGoatDomain + "/DalamudAssets";
|
||||||
const QString dalamudAssetManifestURL = baseDalamudAssetDistribution + "/asset.json";
|
const QString dalamudAssetManifestURL = baseDalamudAssetDistribution + "/asset.json";
|
||||||
|
|
||||||
const QString baseNativeLauncherDistribution =
|
const QString baseNativeLauncherDistribution = "https://xiv.zone/astra-distrib/nativelauncher";
|
||||||
"https://xiv.zone/astra-distrib/nativelauncher";
|
const QString nativeLauncherLatestPackageURL = baseNativeLauncherDistribution + "/NativeLauncher.exe";
|
||||||
const QString nativeLauncherLatestPackageURL =
|
|
||||||
baseNativeLauncherDistribution + "/NativeLauncher.exe";
|
|
||||||
const QString nativeLauncherVersionManifestURL = baseNativeLauncherDistribution + "/version";
|
const QString nativeLauncherVersionManifestURL = baseNativeLauncherDistribution + "/version";
|
||||||
|
|
||||||
const QString dotnetRuntimePackageURL =
|
const QString dotnetRuntimePackageURL =
|
||||||
|
@ -34,22 +32,20 @@ const QString dotnetDesktopPackageURL =
|
||||||
QMap<DalamudChannel, QString> channelToDistribPrefix = {
|
QMap<DalamudChannel, QString> channelToDistribPrefix = {
|
||||||
{DalamudChannel::Stable, "/"},
|
{DalamudChannel::Stable, "/"},
|
||||||
{DalamudChannel::Staging, "stg/"},
|
{DalamudChannel::Staging, "stg/"},
|
||||||
{DalamudChannel::Net5, "net5/"}
|
{DalamudChannel::Net5, "net5/"}};
|
||||||
};
|
|
||||||
|
|
||||||
AssetUpdater::AssetUpdater(LauncherCore& launcher) : launcher(launcher), QObject(&launcher) {
|
AssetUpdater::AssetUpdater(LauncherCore& launcher) : launcher(launcher), QObject(&launcher) {
|
||||||
launcher.mgr->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
launcher.mgr->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||||
|
|
||||||
dataDir =
|
dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
|
||||||
|
|
||||||
if(!QDir().exists(dataDir))
|
if (!QDir().exists(dataDir))
|
||||||
QDir().mkdir(dataDir);
|
QDir().mkdir(dataDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetUpdater::update(const ProfileSettings& profile) {
|
void AssetUpdater::update(const ProfileSettings& profile) {
|
||||||
// non-dalamud users can bypass this process since it's not needed
|
// non-dalamud users can bypass this process since it's not needed
|
||||||
if(!profile.dalamud.enabled) {
|
if (!profile.dalamud.enabled) {
|
||||||
finishedUpdating();
|
finishedUpdating();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -146,12 +142,10 @@ void AssetUpdater::update(const ProfileSettings& profile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetUpdater::beginInstall() {
|
void AssetUpdater::beginInstall() {
|
||||||
if(needsDalamudInstall) {
|
if (needsDalamudInstall) {
|
||||||
bool success = !JlCompress::extractDir(tempDir.path() + "/latest.zip",
|
bool success = !JlCompress::extractDir(tempDir.path() + "/latest.zip", dataDir + "/Dalamud").empty();
|
||||||
dataDir + "/Dalamud")
|
|
||||||
.empty();
|
|
||||||
|
|
||||||
if(!success) {
|
if (!success) {
|
||||||
// TODO: handle failure here
|
// TODO: handle failure here
|
||||||
qInfo() << "Failed to install Dalamud!";
|
qInfo() << "Failed to install Dalamud!";
|
||||||
} else {
|
} else {
|
||||||
|
@ -159,16 +153,15 @@ void AssetUpdater::beginInstall() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(needsNativeInstall) {
|
if (needsNativeInstall) {
|
||||||
qInfo() << "Installing native launcher...";
|
qInfo() << "Installing native launcher...";
|
||||||
|
|
||||||
if(QFile::exists(dataDir + "/NativeLauncher.exe"))
|
if (QFile::exists(dataDir + "/NativeLauncher.exe"))
|
||||||
QFile::remove(dataDir + "/NativeLauncher.exe");
|
QFile::remove(dataDir + "/NativeLauncher.exe");
|
||||||
|
|
||||||
bool success = QFile::copy(tempDir.path() + "/NativeLauncher.exe",
|
bool success = QFile::copy(tempDir.path() + "/NativeLauncher.exe", dataDir + "/NativeLauncher.exe");
|
||||||
dataDir + "/NativeLauncher.exe");
|
|
||||||
|
|
||||||
if(!success) {
|
if (!success) {
|
||||||
qInfo() << "Failed to install native launcher!";
|
qInfo() << "Failed to install native launcher!";
|
||||||
} else {
|
} else {
|
||||||
QFile file(dataDir + "/nativelauncher.ver");
|
QFile file(dataDir + "/nativelauncher.ver");
|
||||||
|
@ -180,16 +173,13 @@ void AssetUpdater::beginInstall() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(needsRuntimeInstall) {
|
if (needsRuntimeInstall) {
|
||||||
bool success = !JlCompress::extractDir(tempDir.path() + "/dotnet-core.zip",
|
bool success =
|
||||||
dataDir + "/DalamudRuntime")
|
!JlCompress::extractDir(tempDir.path() + "/dotnet-core.zip", dataDir + "/DalamudRuntime").empty();
|
||||||
.empty();
|
|
||||||
|
|
||||||
success |= !JlCompress::extractDir(tempDir.path() + "/dotnet-desktop.zip",
|
success |= !JlCompress::extractDir(tempDir.path() + "/dotnet-desktop.zip", dataDir + "/DalamudRuntime").empty();
|
||||||
dataDir + "/DalamudRuntime")
|
|
||||||
.empty();
|
|
||||||
|
|
||||||
if(!success) {
|
if (!success) {
|
||||||
qInfo() << "Failed to install dotnet!";
|
qInfo() << "Failed to install dotnet!";
|
||||||
} else {
|
} else {
|
||||||
QFile file(dataDir + "/DalamudRuntime/runtime.ver");
|
QFile file(dataDir + "/DalamudRuntime/runtime.ver");
|
||||||
|
@ -205,10 +195,10 @@ void AssetUpdater::beginInstall() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetUpdater::checkIfDalamudAssetsDone() {
|
void AssetUpdater::checkIfDalamudAssetsDone() {
|
||||||
if(dialog->wasCanceled())
|
if (dialog->wasCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(dalamudAssetNeededFilenames.empty()) {
|
if (dalamudAssetNeededFilenames.empty()) {
|
||||||
qInfo() << "Finished downloading Dalamud assets.";
|
qInfo() << "Finished downloading Dalamud assets.";
|
||||||
|
|
||||||
launcher.dalamudAssetVersion = remoteDalamudAssetVersion;
|
launcher.dalamudAssetVersion = remoteDalamudAssetVersion;
|
||||||
|
@ -223,14 +213,11 @@ void AssetUpdater::checkIfDalamudAssetsDone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetUpdater::checkIfFinished() {
|
void AssetUpdater::checkIfFinished() {
|
||||||
if(dialog->wasCanceled())
|
if (dialog->wasCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (doneDownloadingDalamud &&
|
if (doneDownloadingDalamud && doneDownloadingNativelauncher && doneDownloadingRuntimeCore &&
|
||||||
doneDownloadingNativelauncher &&
|
doneDownloadingRuntimeDesktop && dalamudAssetNeededFilenames.empty()) {
|
||||||
doneDownloadingRuntimeCore &&
|
|
||||||
doneDownloadingRuntimeDesktop &&
|
|
||||||
dalamudAssetNeededFilenames.empty()) {
|
|
||||||
if (needsRuntimeInstall || needsNativeInstall || needsDalamudInstall) {
|
if (needsRuntimeInstall || needsNativeInstall || needsDalamudInstall) {
|
||||||
beginInstall();
|
beginInstall();
|
||||||
} else {
|
} else {
|
||||||
|
@ -243,10 +230,11 @@ void AssetUpdater::checkIfFinished() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetUpdater::checkIfCheckingIsDone() {
|
void AssetUpdater::checkIfCheckingIsDone() {
|
||||||
if(dialog->wasCanceled())
|
if (dialog->wasCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(remoteDalamudVersion.isEmpty() || remoteRuntimeVersion.isEmpty() || remoteDalamudAssetVersion == -1 || remoteNativeLauncherVersion.isEmpty()) {
|
if (remoteDalamudVersion.isEmpty() || remoteRuntimeVersion.isEmpty() || remoteDalamudAssetVersion == -1 ||
|
||||||
|
remoteNativeLauncherVersion.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +244,7 @@ void AssetUpdater::checkIfCheckingIsDone() {
|
||||||
dialog->setLabelText("Starting update...");
|
dialog->setLabelText("Starting update...");
|
||||||
|
|
||||||
// dalamud injector / net runtime
|
// dalamud injector / net runtime
|
||||||
if(launcher.runtimeVersion != remoteRuntimeVersion) {
|
if (launcher.runtimeVersion != remoteRuntimeVersion) {
|
||||||
needsRuntimeInstall = true;
|
needsRuntimeInstall = true;
|
||||||
|
|
||||||
// core
|
// core
|
||||||
|
@ -308,7 +296,7 @@ void AssetUpdater::checkIfCheckingIsDone() {
|
||||||
checkIfFinished();
|
checkIfFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(remoteDalamudVersion != launcher.dalamudVersion) {
|
if (remoteDalamudVersion != launcher.dalamudVersion) {
|
||||||
qInfo() << "Downloading Dalamud...";
|
qInfo() << "Downloading Dalamud...";
|
||||||
|
|
||||||
needsDalamudInstall = true;
|
needsDalamudInstall = true;
|
||||||
|
@ -342,14 +330,14 @@ void AssetUpdater::checkIfCheckingIsDone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// dalamud assets
|
// dalamud assets
|
||||||
if(remoteDalamudAssetVersion != launcher.dalamudAssetVersion) {
|
if (remoteDalamudAssetVersion != launcher.dalamudAssetVersion) {
|
||||||
qInfo() << "Dalamud assets out of date.";
|
qInfo() << "Dalamud assets out of date.";
|
||||||
|
|
||||||
dialog->setLabelText("Updating Dalamud assets...");
|
dialog->setLabelText("Updating Dalamud assets...");
|
||||||
|
|
||||||
dalamudAssetNeededFilenames.clear();
|
dalamudAssetNeededFilenames.clear();
|
||||||
|
|
||||||
for(auto assetObject : remoteDalamudAssetArray) {
|
for (auto assetObject : remoteDalamudAssetArray) {
|
||||||
{
|
{
|
||||||
dalamudAssetNeededFilenames.append(assetObject.toObject()["FileName"].toString());
|
dalamudAssetNeededFilenames.append(assetObject.toObject()["FileName"].toString());
|
||||||
|
|
||||||
|
@ -364,7 +352,7 @@ void AssetUpdater::checkIfCheckingIsDone() {
|
||||||
const QList<QString> dirPath = fileName.left(fileName.lastIndexOf("/")).split('/');
|
const QList<QString> dirPath = fileName.left(fileName.lastIndexOf("/")).split('/');
|
||||||
|
|
||||||
QString build = dataDir + "/DalamudAssets/";
|
QString build = dataDir + "/DalamudAssets/";
|
||||||
for(auto dir : dirPath) {
|
for (auto dir : dirPath) {
|
||||||
if (!QDir().exists(build + dir))
|
if (!QDir().exists(build + dir))
|
||||||
QDir().mkdir(build + dir);
|
QDir().mkdir(build + dir);
|
||||||
|
|
||||||
|
@ -389,7 +377,7 @@ void AssetUpdater::checkIfCheckingIsDone() {
|
||||||
checkIfFinished();
|
checkIfFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(remoteNativeLauncherVersion != launcher.nativeLauncherVersion) {
|
if (remoteNativeLauncherVersion != launcher.nativeLauncherVersion) {
|
||||||
qInfo() << "Native launcher out of date.";
|
qInfo() << "Native launcher out of date.";
|
||||||
|
|
||||||
dialog->setLabelText("Updating native launcher...");
|
dialog->setLabelText("Updating native launcher...");
|
||||||
|
|
|
@ -7,14 +7,16 @@ DesktopInterface::DesktopInterface(LauncherCore& core) {
|
||||||
|
|
||||||
auto& defaultProfile = core.getProfile(core.defaultProfileIndex);
|
auto& defaultProfile = core.getProfile(core.defaultProfileIndex);
|
||||||
|
|
||||||
if(!defaultProfile.isGameInstalled()) {
|
if (!defaultProfile.isGameInstalled()) {
|
||||||
auto messageBox = new QMessageBox(window);
|
auto messageBox = new QMessageBox(window);
|
||||||
messageBox->setIcon(QMessageBox::Icon::Question);
|
messageBox->setIcon(QMessageBox::Icon::Question);
|
||||||
messageBox->setText("No Game Found");
|
messageBox->setText("No Game Found");
|
||||||
messageBox->setInformativeText("FFXIV is not installed. Would you like to install it now?");
|
messageBox->setInformativeText("FFXIV is not installed. Would you like to install it now?");
|
||||||
|
|
||||||
QString detailedText = QString("Astra will install FFXIV for you at '%1'").arg(core.getProfile(core.defaultProfileIndex).gamePath);
|
QString detailedText =
|
||||||
detailedText.append("\n\nIf you do not wish to install it to this location, please set it in your default profile first.");
|
QString("Astra will install FFXIV for you at '%1'").arg(core.getProfile(core.defaultProfileIndex).gamePath);
|
||||||
|
detailedText.append(
|
||||||
|
"\n\nIf you do not wish to install it to this location, please set it in your default profile first.");
|
||||||
|
|
||||||
messageBox->setDetailedText(detailedText);
|
messageBox->setDetailedText(detailedText);
|
||||||
messageBox->setWindowModality(Qt::WindowModal);
|
messageBox->setWindowModality(Qt::WindowModal);
|
||||||
|
@ -35,7 +37,7 @@ DesktopInterface::DesktopInterface(LauncherCore& core) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
||||||
if(!defaultProfile.isWineInstalled()) {
|
if (!defaultProfile.isWineInstalled()) {
|
||||||
auto messageBox = new QMessageBox(window);
|
auto messageBox = new QMessageBox(window);
|
||||||
messageBox->setIcon(QMessageBox::Icon::Critical);
|
messageBox->setIcon(QMessageBox::Icon::Critical);
|
||||||
messageBox->setText("No Wine Found");
|
messageBox->setText("No Wine Found");
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
#include "gamescopesettingswindow.h"
|
#include "gamescopesettingswindow.h"
|
||||||
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QGridLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
|
#include <QLabel>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QGridLayout>
|
#include <QPushButton>
|
||||||
#include <QToolTip>
|
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
#include <QToolTip>
|
||||||
|
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
#include "launcherwindow.h"
|
#include "launcherwindow.h"
|
||||||
|
|
||||||
GamescopeSettingsWindow::GamescopeSettingsWindow(ProfileSettings& settings, LauncherCore& core, QWidget* parent) : QDialog(parent) {
|
GamescopeSettingsWindow::GamescopeSettingsWindow(ProfileSettings& settings, LauncherCore& core, QWidget* parent)
|
||||||
|
: QDialog(parent) {
|
||||||
setWindowTitle("Gamescope Settings");
|
setWindowTitle("Gamescope Settings");
|
||||||
setWindowModality(Qt::WindowModality::ApplicationModal);
|
setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
#include "launcherwindow.h"
|
#include "launcherwindow.h"
|
||||||
|
|
||||||
#include <QMenuBar>
|
|
||||||
#include <keychain.h>
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QTreeWidgetItem>
|
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QTimer>
|
#include <QFormLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QMenuBar>
|
||||||
|
#include <QNetworkReply>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QTreeWidgetItem>
|
||||||
|
#include <keychain.h>
|
||||||
|
|
||||||
|
#include "aboutwindow.h"
|
||||||
|
#include "assetupdater.h"
|
||||||
|
#include "bannerwidget.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "encryptedarg.h"
|
||||||
|
#include "gameinstaller.h"
|
||||||
|
#include "headline.h"
|
||||||
|
#include "sapphirelauncher.h"
|
||||||
#include "settingswindow.h"
|
#include "settingswindow.h"
|
||||||
#include "squareboot.h"
|
#include "squareboot.h"
|
||||||
#include "squarelauncher.h"
|
#include "squarelauncher.h"
|
||||||
#include "sapphirelauncher.h"
|
|
||||||
#include "assetupdater.h"
|
|
||||||
#include "headline.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "aboutwindow.h"
|
|
||||||
#include "gameinstaller.h"
|
|
||||||
#include "bannerwidget.h"
|
|
||||||
#include "encryptedarg.h"
|
|
||||||
|
|
||||||
LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindow(parent), core(core) {
|
LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindow(parent), core(core) {
|
||||||
setWindowTitle("Astra");
|
setWindowTitle("Astra");
|
||||||
|
@ -66,23 +66,26 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
QString fileName = fi.fileName();
|
QString fileName = fi.fileName();
|
||||||
|
|
||||||
// FIXME: is there no easier way to filter out these in Qt?
|
// FIXME: is there no easier way to filter out these in Qt?
|
||||||
if(fi.fileName() != "Public" && fi.fileName() != "." && fi.fileName() != "..") {
|
if (fi.fileName() != "Public" && fi.fileName() != "." && fi.fileName() != "..") {
|
||||||
userPath = fileName;
|
userPath = fileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments.push_back({"UserPath", QString(R"(C:\Users\%1\Documents\My Games\FINAL FANTASY XIV - A Realm Reborn)").arg(userPath)});
|
arguments.push_back(
|
||||||
|
{"UserPath",
|
||||||
|
QString(R"(C:\Users\%1\Documents\My Games\FINAL FANTASY XIV - A Realm Reborn)").arg(userPath)});
|
||||||
|
|
||||||
const QString argFormat = " /%1 =%2";
|
const QString argFormat = " /%1 =%2";
|
||||||
|
|
||||||
QString argJoined;
|
QString argJoined;
|
||||||
for(auto& arg : arguments) {
|
for (auto& arg : arguments) {
|
||||||
argJoined += argFormat.arg(arg.key, arg.value.replace(" ", " "));
|
argJoined += argFormat.arg(arg.key, arg.value.replace(" ", " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString finalArg = encryptGameArg(argJoined);
|
QString finalArg = encryptGameArg(argJoined);
|
||||||
|
|
||||||
this->core.launchExecutable(currentProfile(), {currentProfile().gamePath + "/boot/ffxivlauncher64.exe", finalArg});
|
this->core.launchExecutable(
|
||||||
|
currentProfile(), {currentProfile().gamePath + "/boot/ffxivlauncher64.exe", finalArg});
|
||||||
});
|
});
|
||||||
|
|
||||||
launchSysInfo = toolsMenu->addAction("Open System Info...");
|
launchSysInfo = toolsMenu->addAction("Open System Info...");
|
||||||
|
@ -116,7 +119,8 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
messageBox->setInformativeText("FFXIV will be installed to your selected game directory.");
|
messageBox->setInformativeText("FFXIV will be installed to your selected game directory.");
|
||||||
|
|
||||||
QString detailedText = QString("Astra will install FFXIV for you at '%1'").arg(this->currentProfile().gamePath);
|
QString detailedText = QString("Astra will install FFXIV for you at '%1'").arg(this->currentProfile().gamePath);
|
||||||
detailedText.append("\n\nIf you do not wish to install it to this location, please change your profile settings.");
|
detailedText.append(
|
||||||
|
"\n\nIf you do not wish to install it to this location, please change your profile settings.");
|
||||||
|
|
||||||
messageBox->setDetailedText(detailedText);
|
messageBox->setDetailedText(detailedText);
|
||||||
messageBox->setWindowModality(Qt::WindowModal);
|
messageBox->setWindowModality(Qt::WindowModal);
|
||||||
|
@ -127,7 +131,6 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
this->core.readGameVersion();
|
this->core.readGameVersion();
|
||||||
|
|
||||||
messageBox->close();
|
messageBox->close();
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -212,7 +215,7 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
layout->addLayout(loginLayout, 0, 1, 1, 1);
|
layout->addLayout(loginLayout, 0, 1, 1, 1);
|
||||||
|
|
||||||
profileSelect = new QComboBox();
|
profileSelect = new QComboBox();
|
||||||
connect(profileSelect, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
connect(profileSelect, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||||
reloadControls();
|
reloadControls();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -244,12 +247,12 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
registerButton = new QPushButton("Register");
|
registerButton = new QPushButton("Register");
|
||||||
|
|
||||||
connect(otpEdit, &QLineEdit::returnPressed, [this] {
|
connect(otpEdit, &QLineEdit::returnPressed, [this] {
|
||||||
if(loginButton->isEnabled())
|
if (loginButton->isEnabled())
|
||||||
this->core.assetUpdater->update(currentProfile());
|
this->core.assetUpdater->update(currentProfile());
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(passwordEdit, &QLineEdit::returnPressed, [this] {
|
connect(passwordEdit, &QLineEdit::returnPressed, [this] {
|
||||||
if(loginButton->isEnabled())
|
if (loginButton->isEnabled())
|
||||||
this->core.assetUpdater->update(currentProfile());
|
this->core.assetUpdater->update(currentProfile());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -267,7 +270,7 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
info->oneTimePassword = otpEdit->text();
|
info->oneTimePassword = otpEdit->text();
|
||||||
|
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
if(currentProfile().rememberUsername) {
|
if (currentProfile().rememberUsername) {
|
||||||
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
||||||
job->setTextData(usernameEdit->text());
|
job->setTextData(usernameEdit->text());
|
||||||
job->setKey(currentProfile().name + "-username");
|
job->setKey(currentProfile().name + "-username");
|
||||||
|
@ -276,7 +279,7 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
if(currentProfile().rememberPassword) {
|
if (currentProfile().rememberPassword) {
|
||||||
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
auto job = new QKeychain::WritePasswordJob("LauncherWindow");
|
||||||
job->setTextData(passwordEdit->text());
|
job->setTextData(passwordEdit->text());
|
||||||
job->setKey(currentProfile().name + "-password");
|
job->setKey(currentProfile().name + "-password");
|
||||||
|
@ -284,7 +287,7 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(currentProfile().isSapphire) {
|
if (currentProfile().isSapphire) {
|
||||||
this->core.sapphireLauncher->login(currentProfile().lobbyURL, *info);
|
this->core.sapphireLauncher->login(currentProfile().lobbyURL, *info);
|
||||||
} else {
|
} else {
|
||||||
this->core.squareBoot->checkGateStatus(info);
|
this->core.squareBoot->checkGateStatus(info);
|
||||||
|
@ -297,7 +300,7 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(registerButton, &QPushButton::released, [=] {
|
connect(registerButton, &QPushButton::released, [=] {
|
||||||
if(currentProfile().isSapphire) {
|
if (currentProfile().isSapphire) {
|
||||||
auto& profile = currentProfile();
|
auto& profile = currentProfile();
|
||||||
|
|
||||||
LoginInformation info;
|
LoginInformation info;
|
||||||
|
@ -311,16 +314,16 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&core, &LauncherCore::successfulLaunch, [&] {
|
connect(&core, &LauncherCore::successfulLaunch, [&] {
|
||||||
if(core.appSettings.closeWhenLaunched)
|
if (core.appSettings.closeWhenLaunched)
|
||||||
hide();
|
hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&core, &LauncherCore::gameClosed, [&] {
|
connect(&core, &LauncherCore::gameClosed, [&] {
|
||||||
if(core.appSettings.closeWhenLaunched)
|
if (core.appSettings.closeWhenLaunched)
|
||||||
QCoreApplication::quit();
|
QCoreApplication::quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
getHeadline(core,[&](Headline headline) {
|
getHeadline(core, [&](Headline headline) {
|
||||||
this->headline = headline;
|
this->headline = headline;
|
||||||
reloadNews();
|
reloadNews();
|
||||||
});
|
});
|
||||||
|
@ -333,7 +336,7 @@ ProfileSettings& LauncherWindow::currentProfile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherWindow::reloadControls() {
|
void LauncherWindow::reloadControls() {
|
||||||
if(currentlyReloadingControls)
|
if (currentlyReloadingControls)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currentlyReloadingControls = true;
|
currentlyReloadingControls = true;
|
||||||
|
@ -342,19 +345,19 @@ void LauncherWindow::reloadControls() {
|
||||||
|
|
||||||
profileSelect->clear();
|
profileSelect->clear();
|
||||||
|
|
||||||
for(const auto& profile : core.profileList()) {
|
for (const auto& profile : core.profileList()) {
|
||||||
profileSelect->addItem(profile);
|
profileSelect->addItem(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
profileSelect->setCurrentIndex(oldIndex);
|
profileSelect->setCurrentIndex(oldIndex);
|
||||||
|
|
||||||
if(profileSelect->currentIndex() == -1) {
|
if (profileSelect->currentIndex() == -1) {
|
||||||
profileSelect->setCurrentIndex(core.defaultProfileIndex);
|
profileSelect->setCurrentIndex(core.defaultProfileIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
rememberUsernameBox->setChecked(currentProfile().rememberUsername);
|
rememberUsernameBox->setChecked(currentProfile().rememberUsername);
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
if(currentProfile().rememberUsername) {
|
if (currentProfile().rememberUsername) {
|
||||||
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
||||||
job->setKey(currentProfile().name + "-username");
|
job->setKey(currentProfile().name + "-username");
|
||||||
job->start();
|
job->start();
|
||||||
|
@ -367,7 +370,7 @@ void LauncherWindow::reloadControls() {
|
||||||
|
|
||||||
rememberPasswordBox->setChecked(currentProfile().rememberPassword);
|
rememberPasswordBox->setChecked(currentProfile().rememberPassword);
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
if(currentProfile().rememberPassword) {
|
if (currentProfile().rememberPassword) {
|
||||||
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
auto job = new QKeychain::ReadPasswordJob("LauncherWindow");
|
||||||
job->setKey(currentProfile().name + "-password");
|
job->setKey(currentProfile().name + "-password");
|
||||||
job->start();
|
job->start();
|
||||||
|
@ -379,25 +382,25 @@ void LauncherWindow::reloadControls() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool canLogin = true;
|
bool canLogin = true;
|
||||||
if(currentProfile().isSapphire) {
|
if (currentProfile().isSapphire) {
|
||||||
if(currentProfile().lobbyURL.isEmpty()) {
|
if (currentProfile().lobbyURL.isEmpty()) {
|
||||||
loginButton->setText("Login (Lobby URL is invalid)");
|
loginButton->setText("Login (Lobby URL is invalid)");
|
||||||
canLogin = false;
|
canLogin = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
||||||
if(!currentProfile().isWineInstalled()) {
|
if (!currentProfile().isWineInstalled()) {
|
||||||
loginButton->setText("Login (Wine is not installed)");
|
loginButton->setText("Login (Wine is not installed)");
|
||||||
canLogin = false;
|
canLogin = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(!currentProfile().isGameInstalled()) {
|
if (!currentProfile().isGameInstalled()) {
|
||||||
loginButton->setText("Login (Game is not installed)");
|
loginButton->setText("Login (Game is not installed)");
|
||||||
canLogin = false;
|
canLogin = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(canLogin)
|
if (canLogin)
|
||||||
loginButton->setText("Login");
|
loginButton->setText("Login");
|
||||||
|
|
||||||
launchOfficial->setEnabled(currentProfile().isGameInstalled());
|
launchOfficial->setEnabled(currentProfile().isGameInstalled());
|
||||||
|
@ -415,13 +418,13 @@ void LauncherWindow::reloadControls() {
|
||||||
newsListView->hide();
|
newsListView->hide();
|
||||||
|
|
||||||
auto field = loginLayout->labelForField(otpEdit);
|
auto field = loginLayout->labelForField(otpEdit);
|
||||||
if(field != nullptr)
|
if (field != nullptr)
|
||||||
field->deleteLater();
|
field->deleteLater();
|
||||||
|
|
||||||
loginLayout->takeRow(otpEdit);
|
loginLayout->takeRow(otpEdit);
|
||||||
otpEdit->hide();
|
otpEdit->hide();
|
||||||
|
|
||||||
if(currentProfile().useOneTimePassword && !currentProfile().isSapphire) {
|
if (currentProfile().useOneTimePassword && !currentProfile().isSapphire) {
|
||||||
loginLayout->addRow("One-Time Password", otpEdit);
|
loginLayout->addRow("One-Time Password", otpEdit);
|
||||||
otpEdit->show();
|
otpEdit->show();
|
||||||
}
|
}
|
||||||
|
@ -434,7 +437,7 @@ void LauncherWindow::reloadControls() {
|
||||||
loginLayout->takeRow(registerButton);
|
loginLayout->takeRow(registerButton);
|
||||||
registerButton->hide();
|
registerButton->hide();
|
||||||
|
|
||||||
if(currentProfile().isSapphire) {
|
if (currentProfile().isSapphire) {
|
||||||
loginLayout->addRow(registerButton);
|
loginLayout->addRow(registerButton);
|
||||||
registerButton->show();
|
registerButton->show();
|
||||||
}
|
}
|
||||||
|
@ -445,20 +448,20 @@ void LauncherWindow::reloadControls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherWindow::reloadNews() {
|
void LauncherWindow::reloadNews() {
|
||||||
if(core.appSettings.showBanners || core.appSettings.showNewsList) {
|
if (core.appSettings.showBanners || core.appSettings.showNewsList) {
|
||||||
for(auto widget : bannerWidgets) {
|
for (auto widget : bannerWidgets) {
|
||||||
bannerLayout->removeWidget(widget);
|
bannerLayout->removeWidget(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
bannerWidgets.clear();
|
bannerWidgets.clear();
|
||||||
|
|
||||||
int totalRow = 0;
|
int totalRow = 0;
|
||||||
if(core.appSettings.showBanners) {
|
if (core.appSettings.showBanners) {
|
||||||
bannerScrollArea->show();
|
bannerScrollArea->show();
|
||||||
layout->addWidget(bannerScrollArea, totalRow++, 0);
|
layout->addWidget(bannerScrollArea, totalRow++, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(core.appSettings.showNewsList) {
|
if (core.appSettings.showNewsList) {
|
||||||
newsListView->show();
|
newsListView->show();
|
||||||
layout->addWidget(newsListView, totalRow++, 0);
|
layout->addWidget(newsListView, totalRow++, 0);
|
||||||
}
|
}
|
||||||
|
@ -466,8 +469,8 @@ void LauncherWindow::reloadNews() {
|
||||||
newsListView->clear();
|
newsListView->clear();
|
||||||
|
|
||||||
if (!headline.banner.empty()) {
|
if (!headline.banner.empty()) {
|
||||||
if(core.appSettings.showBanners) {
|
if (core.appSettings.showBanners) {
|
||||||
for(auto banner : headline.banner) {
|
for (auto banner : headline.banner) {
|
||||||
auto request = QNetworkRequest(banner.bannerImage);
|
auto request = QNetworkRequest(banner.bannerImage);
|
||||||
core.buildRequest(currentProfile(), request);
|
core.buildRequest(currentProfile(), request);
|
||||||
|
|
||||||
|
@ -485,68 +488,58 @@ void LauncherWindow::reloadNews() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bannerTimer == nullptr) {
|
if (bannerTimer == nullptr) {
|
||||||
bannerTimer = new QTimer();
|
bannerTimer = new QTimer();
|
||||||
connect(bannerTimer, &QTimer::timeout, this, [=] {
|
connect(bannerTimer, &QTimer::timeout, this, [=] {
|
||||||
if (currentBanner >= headline.banner.size())
|
if (currentBanner >= headline.banner.size())
|
||||||
currentBanner = 0;
|
currentBanner = 0;
|
||||||
|
|
||||||
bannerScrollArea->ensureVisible(
|
bannerScrollArea->ensureVisible(640 * (currentBanner + 1), 0, 0, 0);
|
||||||
640 * (currentBanner + 1), 0, 0, 0);
|
|
||||||
|
|
||||||
currentBanner++;
|
currentBanner++;
|
||||||
});
|
});
|
||||||
bannerTimer->start(5000);
|
bannerTimer->start(5000);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(bannerTimer != nullptr) {
|
if (bannerTimer != nullptr) {
|
||||||
bannerTimer->stop();
|
bannerTimer->stop();
|
||||||
bannerTimer->deleteLater();
|
bannerTimer->deleteLater();
|
||||||
bannerTimer = nullptr;
|
bannerTimer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(core.appSettings.showNewsList) {
|
if (core.appSettings.showNewsList) {
|
||||||
QTreeWidgetItem* newsItem = new QTreeWidgetItem(
|
QTreeWidgetItem* newsItem = new QTreeWidgetItem((QTreeWidgetItem*)nullptr, QStringList("News"));
|
||||||
(QTreeWidgetItem*)nullptr, QStringList("News"));
|
|
||||||
for (auto news : headline.news) {
|
for (auto news : headline.news) {
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||||
item->setText(0, news.title);
|
item->setText(0, news.title);
|
||||||
item->setText(1, QLocale().toString(
|
item->setText(1, QLocale().toString(news.date, QLocale::ShortFormat));
|
||||||
news.date, QLocale::ShortFormat));
|
|
||||||
item->setData(0, Qt::UserRole, news.url);
|
item->setData(0, Qt::UserRole, news.url);
|
||||||
|
|
||||||
newsItem->addChild(item);
|
newsItem->addChild(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* pinnedItem = new QTreeWidgetItem(
|
QTreeWidgetItem* pinnedItem = new QTreeWidgetItem((QTreeWidgetItem*)nullptr, QStringList("Pinned"));
|
||||||
(QTreeWidgetItem*)nullptr, QStringList("Pinned"));
|
|
||||||
for (auto pinned : headline.pinned) {
|
for (auto pinned : headline.pinned) {
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||||
item->setText(0, pinned.title);
|
item->setText(0, pinned.title);
|
||||||
item->setText(1,
|
item->setText(1, QLocale().toString(pinned.date, QLocale::ShortFormat));
|
||||||
QLocale().toString(pinned.date,
|
|
||||||
QLocale::ShortFormat));
|
|
||||||
item->setData(0, Qt::UserRole, pinned.url);
|
item->setData(0, Qt::UserRole, pinned.url);
|
||||||
|
|
||||||
pinnedItem->addChild(item);
|
pinnedItem->addChild(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* topicsItem = new QTreeWidgetItem(
|
QTreeWidgetItem* topicsItem = new QTreeWidgetItem((QTreeWidgetItem*)nullptr, QStringList("Topics"));
|
||||||
(QTreeWidgetItem*)nullptr, QStringList("Topics"));
|
|
||||||
for (auto news : headline.topics) {
|
for (auto news : headline.topics) {
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||||
item->setText(0, news.title);
|
item->setText(0, news.title);
|
||||||
item->setText(1, QLocale().toString(
|
item->setText(1, QLocale().toString(news.date, QLocale::ShortFormat));
|
||||||
news.date, QLocale::ShortFormat));
|
|
||||||
item->setData(0, Qt::UserRole, news.url);
|
item->setData(0, Qt::UserRole, news.url);
|
||||||
|
|
||||||
topicsItem->addChild(item);
|
topicsItem->addChild(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
newsListView->insertTopLevelItems(
|
newsListView->insertTopLevelItems(0, QList<QTreeWidgetItem*>({newsItem, pinnedItem, topicsItem}));
|
||||||
0, QList<QTreeWidgetItem*>(
|
|
||||||
{newsItem, pinnedItem, topicsItem}));
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
newsListView->expandItem(newsListView->topLevelItem(i));
|
newsListView->expandItem(newsListView->topLevelItem(i));
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
#include "settingswindow.h"
|
#include "settingswindow.h"
|
||||||
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QGridLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
|
#include <QLabel>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QGridLayout>
|
#include <QPushButton>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
|
|
||||||
|
#include "gamescopesettingswindow.h"
|
||||||
#include "launchercore.h"
|
#include "launchercore.h"
|
||||||
#include "launcherwindow.h"
|
#include "launcherwindow.h"
|
||||||
#include "gamescopesettingswindow.h"
|
|
||||||
|
|
||||||
SettingsWindow::SettingsWindow(int defaultTab, LauncherWindow& window, LauncherCore& core, QWidget* parent) : core(core), window(window), QDialog(parent) {
|
SettingsWindow::SettingsWindow(int defaultTab, LauncherWindow& window, LauncherCore& core, QWidget* parent)
|
||||||
|
: core(core), window(window), QDialog(parent) {
|
||||||
setWindowTitle("Settings");
|
setWindowTitle("Settings");
|
||||||
setWindowModality(Qt::WindowModality::ApplicationModal);
|
setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||||
|
|
||||||
|
@ -76,8 +77,7 @@ SettingsWindow::SettingsWindow(int defaultTab, LauncherWindow& window, LauncherC
|
||||||
profileWidget->addItem("INVALID *DEBUG*");
|
profileWidget->addItem("INVALID *DEBUG*");
|
||||||
profileWidget->setCurrentRow(0);
|
profileWidget->setCurrentRow(0);
|
||||||
|
|
||||||
connect(profileWidget, &QListWidget::currentRowChanged, this,
|
connect(profileWidget, &QListWidget::currentRowChanged, this, &SettingsWindow::reloadControls);
|
||||||
&SettingsWindow::reloadControls);
|
|
||||||
|
|
||||||
profileLayout->addWidget(profileWidget, 0, 0, 3, 1);
|
profileLayout->addWidget(profileWidget, 0, 0, 3, 1);
|
||||||
|
|
||||||
|
@ -91,8 +91,7 @@ SettingsWindow::SettingsWindow(int defaultTab, LauncherWindow& window, LauncherC
|
||||||
|
|
||||||
deleteProfileButton = new QPushButton("Delete Profile");
|
deleteProfileButton = new QPushButton("Delete Profile");
|
||||||
connect(deleteProfileButton, &QPushButton::pressed, [=] {
|
connect(deleteProfileButton, &QPushButton::pressed, [=] {
|
||||||
profileWidget->setCurrentRow(
|
profileWidget->setCurrentRow(this->core.deleteProfile(getCurrentProfile().name));
|
||||||
this->core.deleteProfile(getCurrentProfile().name));
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
@ -168,7 +167,7 @@ SettingsWindow::SettingsWindow(int defaultTab, LauncherWindow& window, LauncherC
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsWindow::reloadControls() {
|
void SettingsWindow::reloadControls() {
|
||||||
if(currentlyReloadingControls)
|
if (currentlyReloadingControls)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currentlyReloadingControls = true;
|
currentlyReloadingControls = true;
|
||||||
|
@ -177,7 +176,7 @@ void SettingsWindow::reloadControls() {
|
||||||
|
|
||||||
profileWidget->clear();
|
profileWidget->clear();
|
||||||
|
|
||||||
for(const auto& profile : core.profileList()) {
|
for (const auto& profile : core.profileList()) {
|
||||||
profileWidget->addItem(profile);
|
profileWidget->addItem(profile);
|
||||||
}
|
}
|
||||||
profileWidget->setCurrentRow(oldRow);
|
profileWidget->setCurrentRow(oldRow);
|
||||||
|
@ -196,7 +195,7 @@ void SettingsWindow::reloadControls() {
|
||||||
directXCombo->setCurrentIndex(profile.useDX9 ? 1 : 0);
|
directXCombo->setCurrentIndex(profile.useDX9 ? 1 : 0);
|
||||||
currentGameDirectory->setText(profile.gamePath);
|
currentGameDirectory->setText(profile.gamePath);
|
||||||
|
|
||||||
if(!profile.isGameInstalled()) {
|
if (!profile.isGameInstalled()) {
|
||||||
expansionVersionLabel->setText("No game installed.");
|
expansionVersionLabel->setText("No game installed.");
|
||||||
} else {
|
} else {
|
||||||
QString expacString;
|
QString expacString;
|
||||||
|
@ -204,9 +203,9 @@ void SettingsWindow::reloadControls() {
|
||||||
expacString += "Boot";
|
expacString += "Boot";
|
||||||
expacString += QString(" (%1)\n").arg(profile.bootVersion);
|
expacString += QString(" (%1)\n").arg(profile.bootVersion);
|
||||||
|
|
||||||
for(int i = 0; i < profile.repositories.repositories_count; i++) {
|
for (int i = 0; i < profile.repositories.repositories_count; i++) {
|
||||||
QString expansionName = "Unknown Expansion";
|
QString expansionName = "Unknown Expansion";
|
||||||
if(i < core.expansionNames.size()) {
|
if (i < core.expansionNames.size()) {
|
||||||
expansionName = core.expansionNames[i];
|
expansionName = core.expansionNames[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +218,7 @@ void SettingsWindow::reloadControls() {
|
||||||
|
|
||||||
// wine
|
// wine
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
|
||||||
if(!profile.isWineInstalled()) {
|
if (!profile.isWineInstalled()) {
|
||||||
wineVersionLabel->setText("Wine is not installed.");
|
wineVersionLabel->setText("Wine is not installed.");
|
||||||
} else {
|
} else {
|
||||||
wineVersionLabel->setText(profile.wineVersion);
|
wineVersionLabel->setText(profile.wineVersion);
|
||||||
|
@ -250,7 +249,7 @@ void SettingsWindow::reloadControls() {
|
||||||
encryptArgumentsBox->setChecked(profile.encryptArguments);
|
encryptArgumentsBox->setChecked(profile.encryptArguments);
|
||||||
serverType->setCurrentIndex(profile.isSapphire ? 1 : 0);
|
serverType->setCurrentIndex(profile.isSapphire ? 1 : 0);
|
||||||
lobbyServerURL->setEnabled(profile.isSapphire);
|
lobbyServerURL->setEnabled(profile.isSapphire);
|
||||||
if(profile.isSapphire) {
|
if (profile.isSapphire) {
|
||||||
lobbyServerURL->setText(profile.lobbyURL);
|
lobbyServerURL->setText(profile.lobbyURL);
|
||||||
lobbyServerURL->setPlaceholderText("Required...");
|
lobbyServerURL->setPlaceholderText("Required...");
|
||||||
} else {
|
} else {
|
||||||
|
@ -260,7 +259,7 @@ void SettingsWindow::reloadControls() {
|
||||||
rememberPasswordBox->setChecked(profile.rememberPassword);
|
rememberPasswordBox->setChecked(profile.rememberPassword);
|
||||||
useOneTimePassword->setChecked(profile.useOneTimePassword);
|
useOneTimePassword->setChecked(profile.useOneTimePassword);
|
||||||
useOneTimePassword->setEnabled(!profile.isSapphire);
|
useOneTimePassword->setEnabled(!profile.isSapphire);
|
||||||
if(!useOneTimePassword->isEnabled()) {
|
if (!useOneTimePassword->isEnabled()) {
|
||||||
useOneTimePassword->setToolTip("OTP is not supported by Sapphire servers.");
|
useOneTimePassword->setToolTip("OTP is not supported by Sapphire servers.");
|
||||||
} else {
|
} else {
|
||||||
useOneTimePassword->setToolTip("");
|
useOneTimePassword->setToolTip("");
|
||||||
|
@ -268,7 +267,7 @@ void SettingsWindow::reloadControls() {
|
||||||
|
|
||||||
gameLicenseBox->setCurrentIndex((int)profile.license);
|
gameLicenseBox->setCurrentIndex((int)profile.license);
|
||||||
gameLicenseBox->setEnabled(!profile.isSapphire);
|
gameLicenseBox->setEnabled(!profile.isSapphire);
|
||||||
if(!gameLicenseBox->isEnabled()) {
|
if (!gameLicenseBox->isEnabled()) {
|
||||||
gameLicenseBox->setToolTip("Game licenses only matter when logging into the official Square Enix servers.");
|
gameLicenseBox->setToolTip("Game licenses only matter when logging into the official Square Enix servers.");
|
||||||
} else {
|
} else {
|
||||||
gameLicenseBox->setToolTip("");
|
gameLicenseBox->setToolTip("");
|
||||||
|
@ -278,19 +277,19 @@ void SettingsWindow::reloadControls() {
|
||||||
|
|
||||||
// dalamud
|
// dalamud
|
||||||
enableDalamudBox->setChecked(profile.dalamud.enabled);
|
enableDalamudBox->setChecked(profile.dalamud.enabled);
|
||||||
if(core.dalamudVersion.isEmpty()) {
|
if (core.dalamudVersion.isEmpty()) {
|
||||||
dalamudVersionLabel->setText("Dalamud is not installed.");
|
dalamudVersionLabel->setText("Dalamud is not installed.");
|
||||||
} else {
|
} else {
|
||||||
dalamudVersionLabel->setText(core.dalamudVersion);
|
dalamudVersionLabel->setText(core.dalamudVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(core.dalamudAssetVersion == -1) {
|
if (core.dalamudAssetVersion == -1) {
|
||||||
dalamudAssetVersionLabel->setText("Dalamud assets are not installed.");
|
dalamudAssetVersionLabel->setText("Dalamud assets are not installed.");
|
||||||
} else {
|
} else {
|
||||||
dalamudAssetVersionLabel->setText(QString::number(core.dalamudAssetVersion));
|
dalamudAssetVersionLabel->setText(QString::number(core.dalamudAssetVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(core.nativeLauncherVersion.isEmpty()) {
|
if (core.nativeLauncherVersion.isEmpty()) {
|
||||||
nativeLauncherVersionLabel->setText("Native launcher is not installed.");
|
nativeLauncherVersionLabel->setText("Native launcher is not installed.");
|
||||||
} else {
|
} else {
|
||||||
nativeLauncherVersionLabel->setText(core.nativeLauncherVersion);
|
nativeLauncherVersionLabel->setText(core.nativeLauncherVersion);
|
||||||
|
@ -314,12 +313,8 @@ void SettingsWindow::setupGameTab(QFormLayout& layout) {
|
||||||
directXCombo->addItem("DirectX 9");
|
directXCombo->addItem("DirectX 9");
|
||||||
layout.addRow("DirectX Version", directXCombo);
|
layout.addRow("DirectX Version", directXCombo);
|
||||||
|
|
||||||
connect(directXCombo,
|
connect(directXCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||||
static_cast<void (QComboBox::*)(int)>(
|
getCurrentProfile().useDX9 = directXCombo->currentIndex() == 1;
|
||||||
&QComboBox::currentIndexChanged),
|
|
||||||
[=](int index) {
|
|
||||||
getCurrentProfile().useDX9 =
|
|
||||||
directXCombo->currentIndex() == 1;
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -334,8 +329,7 @@ void SettingsWindow::setupGameTab(QFormLayout& layout) {
|
||||||
|
|
||||||
auto selectDirectoryButton = new QPushButton("Select Game Directory");
|
auto selectDirectoryButton = new QPushButton("Select Game Directory");
|
||||||
connect(selectDirectoryButton, &QPushButton::pressed, [this] {
|
connect(selectDirectoryButton, &QPushButton::pressed, [this] {
|
||||||
getCurrentProfile().gamePath =
|
getCurrentProfile().gamePath = QFileDialog::getExistingDirectory(this, "Open Game Directory");
|
||||||
QFileDialog::getExistingDirectory(this, "Open Game Directory");
|
|
||||||
|
|
||||||
this->reloadControls();
|
this->reloadControls();
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
|
@ -345,8 +339,9 @@ void SettingsWindow::setupGameTab(QFormLayout& layout) {
|
||||||
gameDirButtonLayout->addWidget(selectDirectoryButton);
|
gameDirButtonLayout->addWidget(selectDirectoryButton);
|
||||||
|
|
||||||
gameDirectoryButton = new QPushButton("Open Game Directory");
|
gameDirectoryButton = new QPushButton("Open Game Directory");
|
||||||
connect(gameDirectoryButton, &QPushButton::pressed,
|
connect(gameDirectoryButton, &QPushButton::pressed, [this] {
|
||||||
[this] { window.openPath(getCurrentProfile().gamePath); });
|
window.openPath(getCurrentProfile().gamePath);
|
||||||
|
});
|
||||||
gameDirButtonLayout->addWidget(gameDirectoryButton);
|
gameDirButtonLayout->addWidget(gameDirectoryButton);
|
||||||
|
|
||||||
#ifdef ENABLE_WATCHDOG
|
#ifdef ENABLE_WATCHDOG
|
||||||
|
@ -370,8 +365,7 @@ void SettingsWindow::setupGameTab(QFormLayout& layout) {
|
||||||
void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
||||||
encryptArgumentsBox = new QCheckBox();
|
encryptArgumentsBox = new QCheckBox();
|
||||||
connect(encryptArgumentsBox, &QCheckBox::stateChanged, [=](int) {
|
connect(encryptArgumentsBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().encryptArguments =
|
getCurrentProfile().encryptArguments = encryptArgumentsBox->isChecked();
|
||||||
encryptArgumentsBox->isChecked();
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
@ -381,10 +375,7 @@ void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
||||||
serverType->insertItem(0, "Square Enix");
|
serverType->insertItem(0, "Square Enix");
|
||||||
serverType->insertItem(1, "Sapphire");
|
serverType->insertItem(1, "Sapphire");
|
||||||
|
|
||||||
connect(serverType,
|
connect(serverType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||||
static_cast<void (QComboBox::*)(int)>(
|
|
||||||
&QComboBox::currentIndexChanged),
|
|
||||||
[=](int index) {
|
|
||||||
getCurrentProfile().isSapphire = index == 1;
|
getCurrentProfile().isSapphire = index == 1;
|
||||||
|
|
||||||
reloadControls();
|
reloadControls();
|
||||||
|
@ -405,10 +396,7 @@ void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
||||||
gameLicenseBox->insertItem(1, "Windows (Steam)");
|
gameLicenseBox->insertItem(1, "Windows (Steam)");
|
||||||
gameLicenseBox->insertItem(2, "macOS");
|
gameLicenseBox->insertItem(2, "macOS");
|
||||||
|
|
||||||
connect(gameLicenseBox,
|
connect(gameLicenseBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||||
static_cast<void (QComboBox::*)(int)>(
|
|
||||||
&QComboBox::currentIndexChanged),
|
|
||||||
[=](int index) {
|
|
||||||
getCurrentProfile().license = (GameLicense)index;
|
getCurrentProfile().license = (GameLicense)index;
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
|
@ -418,8 +406,7 @@ void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
||||||
|
|
||||||
freeTrialBox = new QCheckBox();
|
freeTrialBox = new QCheckBox();
|
||||||
connect(freeTrialBox, &QCheckBox::stateChanged, [=](int) {
|
connect(freeTrialBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().isFreeTrial =
|
getCurrentProfile().isFreeTrial = freeTrialBox->isChecked();
|
||||||
freeTrialBox->isChecked();
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
@ -427,8 +414,7 @@ void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
||||||
|
|
||||||
rememberUsernameBox = new QCheckBox();
|
rememberUsernameBox = new QCheckBox();
|
||||||
connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) {
|
connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().rememberUsername =
|
getCurrentProfile().rememberUsername = rememberUsernameBox->isChecked();
|
||||||
rememberUsernameBox->isChecked();
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
@ -436,8 +422,7 @@ void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
||||||
|
|
||||||
rememberPasswordBox = new QCheckBox();
|
rememberPasswordBox = new QCheckBox();
|
||||||
connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) {
|
connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().rememberPassword =
|
getCurrentProfile().rememberPassword = rememberPasswordBox->isChecked();
|
||||||
rememberPasswordBox->isChecked();
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
});
|
});
|
||||||
|
@ -445,8 +430,7 @@ void SettingsWindow::setupLoginTab(QFormLayout& layout) {
|
||||||
|
|
||||||
useOneTimePassword = new QCheckBox();
|
useOneTimePassword = new QCheckBox();
|
||||||
connect(useOneTimePassword, &QCheckBox::stateChanged, [=](int) {
|
connect(useOneTimePassword, &QCheckBox::stateChanged, [=](int) {
|
||||||
getCurrentProfile().useOneTimePassword =
|
getCurrentProfile().useOneTimePassword = useOneTimePassword->isChecked();
|
||||||
useOneTimePassword->isChecked();
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
this->window.reloadControls();
|
this->window.reloadControls();
|
||||||
|
@ -462,30 +446,27 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
|
|
||||||
wineTypeCombo = new QComboBox();
|
wineTypeCombo = new QComboBox();
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
wineTypeCombo->insertItem(2, "FFXIV for Mac (Official)");
|
wineTypeCombo->insertItem(2, "FFXIV for Mac (Official)");
|
||||||
wineTypeCombo->insertItem(3, "XIV on Mac");
|
wineTypeCombo->insertItem(3, "XIV on Mac");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wineTypeCombo->insertItem(0, "System Wine");
|
wineTypeCombo->insertItem(0, "System Wine");
|
||||||
|
|
||||||
// custom wine selection is broken under flatpak
|
// custom wine selection is broken under flatpak
|
||||||
#ifndef FLATPAK
|
#ifndef FLATPAK
|
||||||
wineTypeCombo->insertItem(1, "Custom Wine");
|
wineTypeCombo->insertItem(1, "Custom Wine");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
layout.addWidget(wineTypeCombo);
|
layout.addWidget(wineTypeCombo);
|
||||||
|
|
||||||
selectWineButton = new QPushButton("Select Wine Executable");
|
selectWineButton = new QPushButton("Select Wine Executable");
|
||||||
|
|
||||||
#ifndef FLATPAK
|
#ifndef FLATPAK
|
||||||
layout.addWidget(selectWineButton);
|
layout.addWidget(selectWineButton);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(wineTypeCombo,
|
connect(wineTypeCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [this](int index) {
|
||||||
static_cast<void (QComboBox::*)(int)>(
|
|
||||||
&QComboBox::currentIndexChanged),
|
|
||||||
[this](int index) {
|
|
||||||
getCurrentProfile().wineType = (WineType)index;
|
getCurrentProfile().wineType = (WineType)index;
|
||||||
|
|
||||||
this->core.readWineInfo(getCurrentProfile());
|
this->core.readWineInfo(getCurrentProfile());
|
||||||
|
@ -494,8 +475,7 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(selectWineButton, &QPushButton::pressed, [this] {
|
connect(selectWineButton, &QPushButton::pressed, [this] {
|
||||||
getCurrentProfile().winePath =
|
getCurrentProfile().winePath = QFileDialog::getOpenFileName(this, "Open Wine Executable");
|
||||||
QFileDialog::getOpenFileName(this, "Open Wine Executable");
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
this->reloadControls();
|
this->reloadControls();
|
||||||
|
@ -503,10 +483,10 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
|
|
||||||
// wine version is reported incorrectly under flatpak too
|
// wine version is reported incorrectly under flatpak too
|
||||||
wineVersionLabel = new QLabel();
|
wineVersionLabel = new QLabel();
|
||||||
#ifndef FLATPAK
|
#ifndef FLATPAK
|
||||||
wineVersionLabel->setTextInteractionFlags(Qt::TextInteractionFlag::TextSelectableByMouse);
|
wineVersionLabel->setTextInteractionFlags(Qt::TextInteractionFlag::TextSelectableByMouse);
|
||||||
layout.addRow("Wine Version", wineVersionLabel);
|
layout.addRow("Wine Version", wineVersionLabel);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
winePrefixDirectory = new QLabel();
|
winePrefixDirectory = new QLabel();
|
||||||
winePrefixDirectory->setTextInteractionFlags(Qt::TextInteractionFlag::TextSelectableByMouse);
|
winePrefixDirectory->setTextInteractionFlags(Qt::TextInteractionFlag::TextSelectableByMouse);
|
||||||
|
@ -519,8 +499,7 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
|
|
||||||
auto selectPrefixButton = new QPushButton("Select Wine Prefix");
|
auto selectPrefixButton = new QPushButton("Select Wine Prefix");
|
||||||
connect(selectPrefixButton, &QPushButton::pressed, [this] {
|
connect(selectPrefixButton, &QPushButton::pressed, [this] {
|
||||||
getCurrentProfile().winePrefixPath =
|
getCurrentProfile().winePrefixPath = QFileDialog::getExistingDirectory(this, "Open Wine Prefix");
|
||||||
QFileDialog::getExistingDirectory(this, "Open Wine Prefix");
|
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
this->reloadControls();
|
this->reloadControls();
|
||||||
|
@ -528,8 +507,9 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
winePrefixButtonLayout->addWidget(selectPrefixButton);
|
winePrefixButtonLayout->addWidget(selectPrefixButton);
|
||||||
|
|
||||||
auto openPrefixButton = new QPushButton("Open Wine Prefix");
|
auto openPrefixButton = new QPushButton("Open Wine Prefix");
|
||||||
connect(openPrefixButton, &QPushButton::pressed,
|
connect(openPrefixButton, &QPushButton::pressed, [this] {
|
||||||
[this] { window.openPath(getCurrentProfile().winePrefixPath); });
|
window.openPath(getCurrentProfile().winePrefixPath);
|
||||||
|
});
|
||||||
winePrefixButtonLayout->addWidget(openPrefixButton);
|
winePrefixButtonLayout->addWidget(openPrefixButton);
|
||||||
|
|
||||||
auto enableDXVKhud = new QCheckBox("Enable DXVK HUD");
|
auto enableDXVKhud = new QCheckBox("Enable DXVK HUD");
|
||||||
|
@ -537,17 +517,16 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
|
|
||||||
connect(enableDXVKhud, &QCheckBox::stateChanged, [this](int state) {
|
connect(enableDXVKhud, &QCheckBox::stateChanged, [this](int state) {
|
||||||
getCurrentProfile().enableDXVKhud = state;
|
getCurrentProfile().enableDXVKhud = state;
|
||||||
this->core.settings.setValue("enableDXVKhud",
|
this->core.settings.setValue("enableDXVKhud", static_cast<bool>(state));
|
||||||
static_cast<bool>(state));
|
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
useEsync = new QCheckBox(
|
useEsync = new QCheckBox("Use Better Sync Primitives (Esync, Fsync, and Futex2)");
|
||||||
"Use Better Sync Primitives (Esync, Fsync, and Futex2)");
|
|
||||||
layout.addWidget(useEsync);
|
layout.addWidget(useEsync);
|
||||||
|
|
||||||
useEsync->setToolTip("This may improve game performance, but requires a Wine and kernel with the patches included.");
|
useEsync->setToolTip(
|
||||||
|
"This may improve game performance, but requires a Wine and kernel with the patches included.");
|
||||||
|
|
||||||
connect(useEsync, &QCheckBox::stateChanged, [this](int state) {
|
connect(useEsync, &QCheckBox::stateChanged, [this](int state) {
|
||||||
getCurrentProfile().useEsync = state;
|
getCurrentProfile().useEsync = state;
|
||||||
|
@ -558,7 +537,9 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
useGamescope = new QCheckBox("Use Gamescope");
|
useGamescope = new QCheckBox("Use Gamescope");
|
||||||
layout.addWidget(useGamescope);
|
layout.addWidget(useGamescope);
|
||||||
|
|
||||||
useGamescope->setToolTip("Use the micro-compositor compositor that uses Wayland and XWayland to create a nested session.\nIf you primarily use fullscreen mode, this may improve input handling especially on Wayland.");
|
useGamescope->setToolTip(
|
||||||
|
"Use the micro-compositor compositor that uses Wayland and XWayland to create a nested session.\nIf you "
|
||||||
|
"primarily use fullscreen mode, this may improve input handling especially on Wayland.");
|
||||||
|
|
||||||
auto gamescopeButtonLayout = new QHBoxLayout();
|
auto gamescopeButtonLayout = new QHBoxLayout();
|
||||||
auto gamescopeButtonContainer = new QWidget();
|
auto gamescopeButtonContainer = new QWidget();
|
||||||
|
@ -567,8 +548,7 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
|
|
||||||
configureGamescopeButton = new QPushButton("Configure...");
|
configureGamescopeButton = new QPushButton("Configure...");
|
||||||
connect(configureGamescopeButton, &QPushButton::pressed, [&] {
|
connect(configureGamescopeButton, &QPushButton::pressed, [&] {
|
||||||
auto gamescopeSettingsWindow = new GamescopeSettingsWindow(
|
auto gamescopeSettingsWindow = new GamescopeSettingsWindow(getCurrentProfile(), this->core, this);
|
||||||
getCurrentProfile(), this->core, this);
|
|
||||||
gamescopeSettingsWindow->show();
|
gamescopeSettingsWindow->show();
|
||||||
});
|
});
|
||||||
gamescopeButtonLayout->addWidget(configureGamescopeButton);
|
gamescopeButtonLayout->addWidget(configureGamescopeButton);
|
||||||
|
@ -583,7 +563,8 @@ void SettingsWindow::setupWineTab(QFormLayout& layout) {
|
||||||
useGamemode = new QCheckBox("Use GameMode");
|
useGamemode = new QCheckBox("Use GameMode");
|
||||||
layout.addWidget(useGamemode);
|
layout.addWidget(useGamemode);
|
||||||
|
|
||||||
useGamemode->setToolTip("A special game performance enhancer, which automatically tunes your CPU scheduler among other things. This may improve game performance.");
|
useGamemode->setToolTip("A special game performance enhancer, which automatically tunes your CPU scheduler among "
|
||||||
|
"other things. This may improve game performance.");
|
||||||
|
|
||||||
connect(useGamemode, &QCheckBox::stateChanged, [this](int state) {
|
connect(useGamemode, &QCheckBox::stateChanged, [this](int state) {
|
||||||
getCurrentProfile().useGamemode = state;
|
getCurrentProfile().useGamemode = state;
|
||||||
|
@ -615,10 +596,7 @@ void SettingsWindow::setupDalamudTab(QFormLayout& layout) {
|
||||||
dalamudChannel->insertItem(1, "Staging");
|
dalamudChannel->insertItem(1, "Staging");
|
||||||
dalamudChannel->insertItem(2, ".NET 5");
|
dalamudChannel->insertItem(2, ".NET 5");
|
||||||
|
|
||||||
connect(dalamudChannel,
|
connect(dalamudChannel, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||||
static_cast<void (QComboBox::*)(int)>(
|
|
||||||
&QComboBox::currentIndexChanged),
|
|
||||||
[=](int index) {
|
|
||||||
getCurrentProfile().dalamud.channel = (DalamudChannel)index;
|
getCurrentProfile().dalamud.channel = (DalamudChannel)index;
|
||||||
|
|
||||||
this->core.saveSettings();
|
this->core.saveSettings();
|
||||||
|
@ -639,6 +617,4 @@ void SettingsWindow::setupDalamudTab(QFormLayout& layout) {
|
||||||
layout.addRow("Native Launcher Version", nativeLauncherVersionLabel);
|
layout.addRow("Native Launcher Version", nativeLauncherVersionLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsWindow::setupAccountsTab(QFormLayout& layout) {
|
void SettingsWindow::setupAccountsTab(QFormLayout& layout) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <keychain.h>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <keychain.h>
|
||||||
#include <physis.hpp>
|
#include <physis.hpp>
|
||||||
|
|
||||||
#include "../launcher/tablet/include/tabletinterface.h"
|
#include "../launcher/tablet/include/tabletinterface.h"
|
||||||
|
@ -53,19 +53,19 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
if(parser.isSet(versionOption)) {
|
if (parser.isSet(versionOption)) {
|
||||||
parser.showVersion();
|
parser.showVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parser.isSet(helpOption)) {
|
if (parser.isSet(helpOption)) {
|
||||||
parser.showHelp();
|
parser.showHelp();
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherCore c;
|
LauncherCore c;
|
||||||
if(parser.isSet(tabletOption)) {
|
if (parser.isSet(tabletOption)) {
|
||||||
std::make_unique<TabletInterface>(c);
|
std::make_unique<TabletInterface>(c);
|
||||||
} else if(parser.isSet(cliOption)) {
|
} else if (parser.isSet(cliOption)) {
|
||||||
if(!cmd->parse(parser, c))
|
if (!cmd->parse(parser, c))
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
std::make_unique<DesktopInterface>(c);
|
std::make_unique<DesktopInterface>(c);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include "tabletinterface.h"
|
#include "tabletinterface.h"
|
||||||
|
|
||||||
#include <QQuickView>
|
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
#include <QQuickView>
|
||||||
|
|
||||||
TabletInterface::TabletInterface(LauncherCore &core) {
|
TabletInterface::TabletInterface(LauncherCore& core) {
|
||||||
qmlRegisterType<ProfileSettings>("Astra", 1, 0, "ProfileSettings");
|
qmlRegisterType<ProfileSettings>("Astra", 1, 0, "ProfileSettings");
|
||||||
qmlRegisterType<LoginInformation>("Astra", 1, 0, "LoginInformation");
|
qmlRegisterType<LoginInformation>("Astra", 1, 0, "LoginInformation");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue