2021-11-01 09:54:58 -04:00
# include <QPushButton>
# include <QProcess>
# include <QNetworkAccessManager>
# include <QNetworkReply>
# include <QUrlQuery>
# include <QDir>
# include <QFormLayout>
# include <QLineEdit>
# include <QRegularExpression>
# include <QComboBox>
# include <QJsonObject>
# include <QJsonDocument>
# include <QCheckBox>
# include <keychain.h>
# include <QMessageBox>
2021-11-01 13:14:00 -04:00
# include <QMenuBar>
2021-11-01 09:54:58 -04:00
2021-11-09 15:02:17 -05:00
# if defined(Q_OS_MAC)
# include <sys/sysctl.h>
# include <mach/mach_time.h>
# endif
2021-11-09 20:57:10 -05:00
# if defined(Q_OS_WIN)
# include <windows.h>
# endif
2021-11-01 09:54:58 -04:00
# include "xivlauncher.h"
# include "sapphirelauncher.h"
# include "squarelauncher.h"
# include "squareboot.h"
2021-11-01 13:14:00 -04:00
# include "settingswindow.h"
2021-11-09 15:02:17 -05:00
# include "blowfish.h"
2021-11-01 09:54:58 -04:00
void LauncherWindow : : setSSL ( QNetworkRequest & request ) {
QSslConfiguration config ;
config . setProtocol ( QSsl : : AnyProtocol ) ;
config . setPeerVerifyMode ( QSslSocket : : VerifyNone ) ;
request . setSslConfiguration ( config ) ;
}
void LauncherWindow : : buildRequest ( QNetworkRequest & request ) {
setSSL ( request ) ;
request . setHeader ( QNetworkRequest : : UserAgentHeader ,
QString ( " SQEXAuthor/2.0.0(Windows 6.2; ja-jp; %1) " ) . arg ( QSysInfo : : bootUniqueId ( ) ) ) ;
request . setRawHeader ( " 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-Language " , " en-us " ) ;
}
2021-11-09 15:02:17 -05:00
// from xivdev
char ChecksumTable [ ] = {
' f ' , ' X ' , ' 1 ' , ' p ' , ' G ' , ' t ' , ' d ' , ' S ' ,
' 5 ' , ' C ' , ' A ' , ' P ' , ' 4 ' , ' _ ' , ' V ' , ' L '
} ;
char GetChecksum ( unsigned int key ) {
auto value = key & 0x000F0000 ;
return ChecksumTable [ value > > 16 ] ;
}
# if defined(Q_OS_MAC)
// this is pretty much what wine does :-0
uint32_t TickCount ( ) {
struct mach_timebase_info convfact ;
mach_timebase_info ( & convfact ) ;
return mach_absolute_time ( ) * convfact . numer / convfact . denom / 100 ;
}
# endif
2021-11-09 20:59:39 -05:00
# if defined(Q_OS_LINUX)
uint32_t TickCount ( ) {
struct timespec ts ;
clock_gettime ( CLOCK_MONOTONIC , & ts ) ;
return ( ts . tv_sec * 1000 + ts . tv_nsec / 1000000 ) ;
}
# endif
2021-11-09 20:57:10 -05:00
# if defined(Q_OS_WIN)
uint32_t TickCount ( ) {
return GetTickCount ( ) ;
}
# endif
2021-11-09 15:02:17 -05:00
QString encryptGameArg ( QString arg ) {
2021-11-09 20:57:10 -05:00
unsigned int rawTicks = TickCount ( ) ;
2021-11-09 15:02:17 -05:00
qDebug ( ) < < " raw tick count: " < < rawTicks ;
unsigned int ticks = rawTicks & 0xFFFFFFFFu ;
qDebug ( ) < < " ticks: " < < ticks ;
unsigned int u = ticks & 0xFFFF0000u ;
qDebug ( ) < < " key: " < < u ;
2021-11-09 20:57:10 -05:00
char buffer [ 9 ] = { } ;
sprintf ( buffer , " %08x " , u ) ;
2021-11-09 15:02:17 -05:00
2021-11-09 20:57:10 -05:00
Blowfish session ( QByteArray ( buffer , 8 ) ) ;
QByteArray encryptedArg = session . Encrypt ( ( QString ( " /T =%1 " ) . arg ( ticks ) + arg ) . toUtf8 ( ) ) ;
2021-11-09 15:02:17 -05:00
2021-11-09 20:57:10 -05:00
QString base64 = encryptedArg . toBase64 ( QByteArray : : Base64Option : : Base64UrlEncoding | QByteArray : : Base64Option : : OmitTrailingEquals ) ;
2021-11-09 15:02:17 -05:00
qDebug ( ) < < " base64: " < < encryptedArg . toBase64 ( ) ;
2021-11-09 20:57:10 -05:00
session . Decrypt ( encryptedArg ) ;
qDebug ( ) < < " decryption attempt: " < < encryptedArg ;
2021-11-09 15:02:17 -05:00
char checksum = GetChecksum ( u ) ;
2021-11-09 20:57:10 -05:00
qDebug ( ) < < checksum ;
2021-11-09 15:02:17 -05:00
2021-11-09 20:57:10 -05:00
auto a = QString ( " //**sqex0003%1%2**// " ) . arg ( base64 , QString ( checksum ) ) ;
qDebug ( ) < < a ;
return a ;
2021-11-09 15:02:17 -05:00
}
2021-11-02 08:36:30 -04:00
void LauncherWindow : : launchGame ( const LoginAuth auth ) {
QList < QString > arguments ;
// now for the actual game...
2021-11-09 11:03:44 -05:00
if ( currentProfile ( ) . useDX9 ) {
arguments . push_back ( currentProfile ( ) . gamePath + " \\ game \\ ffxiv.exe " ) ;
2021-11-02 08:49:06 -04:00
} else {
2021-11-09 11:03:44 -05:00
arguments . push_back ( currentProfile ( ) . gamePath + " \\ game \\ ffxiv_dx11.exe " ) ;
2021-11-02 08:49:06 -04:00
}
2021-11-09 21:26:16 -05:00
struct Argument {
QString key , value ;
} ;
2021-11-02 08:36:30 -04:00
2021-11-09 21:26:16 -05:00
QList < Argument > gameArgs ;
gameArgs . push_back ( { " DEV.DataPathType " , QString : : number ( 1 ) } ) ;
gameArgs . push_back ( { " DEV.UseSqPack " , QString : : number ( 1 ) } ) ;
gameArgs . push_back ( { " DEV.MaxEntitledExpansionID " , QString : : number ( auth . maxExpansion ) } ) ;
gameArgs . push_back ( { " DEV.TestSID " , auth . SID } ) ;
gameArgs . push_back ( { " SYS.Region " , QString : : number ( auth . region ) } ) ;
gameArgs . push_back ( { " language " , QString : : number ( currentProfile ( ) . language ) } ) ;
gameArgs . push_back ( { " ver " , currentProfile ( ) . gameVersion } ) ;
2021-11-02 08:36:30 -04:00
if ( ! auth . lobbyhost . isEmpty ( ) ) {
2021-11-09 21:26:16 -05:00
gameArgs . push_back ( { " DEV.GMServerHost " , auth . frontierHost } ) ;
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.LobbyPort0%1 " ) . arg ( QString : : number ( i ) ) , QString : : number ( 54994 ) } ) ;
}
2021-11-02 08:36:30 -04:00
}
2021-11-09 21:13:21 -05:00
if ( currentProfile ( ) . encryptArguments ) {
2021-11-09 15:02:17 -05:00
QString argJoined ;
2021-11-09 21:26:16 -05:00
for ( auto arg : gameArgs ) {
argJoined + = QString ( " /%1 =%2 " ) . arg ( arg . key , arg . value ) ;
}
2021-11-09 15:02:17 -05:00
auto earg = encryptGameArg ( argJoined ) ;
2021-11-09 21:26:16 -05:00
arguments . append ( earg ) ;
launchExecutable ( arguments ) ;
2021-11-09 15:02:17 -05:00
} else {
2021-11-09 21:26:16 -05:00
for ( auto arg : gameArgs ) {
arguments . push_back ( QString ( " %1=%2 " ) . arg ( arg . key , arg . value ) ) ;
}
2021-11-09 15:02:17 -05:00
launchExecutable ( arguments ) ;
}
2021-11-02 08:36:30 -04:00
}
void LauncherWindow : : launchExecutable ( const QStringList args ) {
2021-11-01 09:54:58 -04:00
auto process = new QProcess ( this ) ;
process - > setProcessChannelMode ( QProcess : : ForwardedChannels ) ;
2021-11-01 14:35:32 -04:00
QList < QString > arguments ;
2021-11-02 20:04:53 -04:00
QStringList env = QProcess : : systemEnvironment ( ) ;
2021-11-01 09:54:58 -04:00
# if defined(Q_OS_LINUX)
2021-11-09 11:03:44 -05:00
if ( currentProfile ( ) . useGamescope ) {
2021-11-01 14:35:32 -04:00
arguments . push_back ( " gamescope " ) ;
arguments . push_back ( " -f " ) ;
arguments . push_back ( " -b " ) ;
}
2021-11-01 09:54:58 -04:00
2021-11-09 11:03:44 -05:00
if ( currentProfile ( ) . useGamemode )
2021-11-01 14:35:32 -04:00
arguments . push_back ( " gamemoderun " ) ;
2021-11-01 09:54:58 -04:00
2021-11-09 11:03:44 -05:00
if ( currentProfile ( ) . useEsync ) {
2021-11-01 14:35:32 -04:00
env < < " WINEESYNC=1 " ;
2021-11-01 09:54:58 -04:00
}
2021-11-03 06:18:31 -04:00
# endif
2021-11-01 09:54:58 -04:00
2021-11-03 06:31:02 -04:00
# if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
2021-11-09 11:03:44 -05:00
env < < " WINEPREFIX= " + currentProfile ( ) . winePrefixPath ;
2021-11-01 14:35:32 -04:00
2021-11-09 11:03:44 -05:00
if ( currentProfile ( ) . enableDXVKhud )
2021-11-03 06:18:31 -04:00
env < < " DXVK_HUD=full " ;
2021-11-09 11:03:44 -05:00
arguments . push_back ( currentProfile ( ) . winePath ) ;
2021-11-03 06:31:02 -04:00
# endif
2021-11-02 08:36:30 -04:00
arguments . append ( args ) ;
2021-11-01 09:54:58 -04:00
2021-11-01 14:35:32 -04:00
auto executable = arguments [ 0 ] ;
arguments . removeFirst ( ) ;
2021-11-03 06:18:31 -04:00
2021-11-09 11:03:44 -05:00
process - > setWorkingDirectory ( currentProfile ( ) . gamePath + " /game/ " ) ;
2021-11-03 06:18:31 -04:00
process - > setEnvironment ( env ) ;
2021-11-01 14:35:32 -04:00
process - > start ( executable , arguments ) ;
2021-11-01 09:54:58 -04:00
}
QString LauncherWindow : : readVersion ( QString path ) {
QFile file ( path ) ;
file . open ( QFile : : OpenModeFlag : : ReadOnly ) ;
return file . readAll ( ) ;
}
void LauncherWindow : : readInitialInformation ( ) {
2021-11-09 12:25:54 -05:00
defaultProfileIndex = settings . value ( " defaultProfile " , 0 ) . toInt ( ) ;
2021-11-09 11:25:15 -05:00
auto profiles = settings . childGroups ( ) ;
// create the Default profile if it doesnt exist
if ( profiles . empty ( ) )
2021-11-09 13:26:59 -05:00
profiles . append ( QUuid : : createUuid ( ) . toString ( QUuid : : StringFormat : : WithoutBraces ) ) ;
2021-11-09 11:25:15 -05:00
2021-11-09 13:24:38 -05:00
profileSettings . resize ( profiles . size ( ) ) ;
for ( const auto & uuid : profiles ) {
2021-11-09 11:25:15 -05:00
ProfileSettings profile ;
2021-11-09 13:24:38 -05:00
profile . uuid = QUuid ( uuid ) ;
settings . beginGroup ( uuid ) ;
2021-11-09 11:25:15 -05:00
2021-11-09 13:26:59 -05:00
profile . name = settings . value ( " name " , " Default " ) . toString ( ) ;
2021-11-09 11:25:15 -05:00
2021-11-09 13:04:22 -05:00
profile . wineVersion = settings . value ( " wineVersion " , 0 ) . toInt ( ) ;
2021-11-03 06:18:31 -04:00
# if defined(Q_OS_MAC)
2021-11-09 13:04:22 -05:00
switch ( profile . wineVersion ) {
2021-11-03 06:18:31 -04:00
case 0 : // system wine
2021-11-09 11:25:15 -05:00
profile . winePath = " /usr/local/bin/wine64 " ;
2021-11-03 06:18:31 -04:00
break ;
case 1 : // custom path
2021-11-09 11:25:15 -05:00
profile . winePath = settings . value ( " winePath " ) . toString ( ) ;
2021-11-03 06:18:31 -04:00
break ;
case 2 : // ffxiv built-in (for mac users)
2021-11-09 11:25:15 -05:00
profile . winePath = " /Applications/FINAL FANTASY XIV ONLINE.app/Contents/SharedSupport/finalfantasyxiv/FINAL FANTASY XIV ONLINE/wine " ;
2021-11-03 06:18:31 -04:00
break ;
}
# endif
# if defined(Q_OS_LINUX)
2021-11-09 13:04:22 -05:00
switch ( profile . wineVersion ) {
2021-11-09 11:25:15 -05:00
case 0 : // system wine (should be in $PATH)
profile . winePath = " wine " ;
break ;
case 1 : // custom pth
profile . winePath = settings . value ( " winePath " ) . toString ( ) ;
break ;
}
2021-11-03 06:18:31 -04:00
# endif
2021-11-09 11:25:15 -05:00
if ( settings . contains ( " gamePath " ) & & settings . value ( " gamePath " ) . canConvert < QString > ( ) & & ! settings . value ( " gamePath " ) . toString ( ) . isEmpty ( ) ) {
profile . gamePath = settings . value ( " gamePath " ) . toString ( ) ;
} else {
2021-11-01 09:54:58 -04:00
# if defined(Q_OS_WIN)
2021-11-09 11:25:15 -05:00
profile . gamePath = " C: \\ Program Files (x86) \\ SquareEnix \\ FINAL FANTASY XIV - A Realm Reborn " ;
2021-11-01 09:54:58 -04:00
# endif
# if defined(Q_OS_MACOS)
2021-11-09 11:25:15 -05:00
profile . gamePath = 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 " ;
2021-11-01 09:54:58 -04:00
# endif
# if defined(Q_OS_LINUX)
2021-11-09 11:25:15 -05:00
profile . gamePath = QDir : : homePath ( ) + " /.wine/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn " ;
2021-11-01 09:54:58 -04:00
# endif
2021-11-09 11:25:15 -05:00
}
2021-11-01 09:54:58 -04:00
2021-11-09 13:04:22 -05:00
if ( settings . contains ( " winePrefixPath " ) & & settings . value ( " winePrefixPath " ) . canConvert < QString > ( ) & & ! settings . value ( " winePrefixPath " ) . toString ( ) . isEmpty ( ) ) {
profile . winePrefixPath = settings . value ( " winePrefixPath " ) . toString ( ) ;
2021-11-09 11:25:15 -05:00
} else {
2021-11-03 06:31:02 -04:00
# if defined(Q_OS_MACOS)
2021-11-09 11:25:15 -05:00
profile . winePrefixPath = QDir : : homePath ( ) + " /Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy " ;
2021-11-03 06:31:02 -04:00
# endif
# if defined(Q_OS_LINUX)
2021-11-09 11:25:15 -05:00
profile . winePrefixPath = QDir : : homePath ( ) + " /.wine " ;
2021-11-03 06:31:02 -04:00
# endif
2021-11-09 11:25:15 -05:00
}
2021-11-09 21:13:21 -05:00
// login
profile . encryptArguments = settings . value ( " encryptArguments " , false ) . toBool ( ) ;
2021-11-09 12:40:44 -05:00
profile . isSapphire = settings . value ( " isSapphire " , false ) . toBool ( ) ;
2021-11-09 12:50:37 -05:00
profile . lobbyURL = settings . value ( " lobbyURL " , " " ) . toString ( ) ;
2021-11-09 12:32:18 -05:00
profile . rememberUsername = settings . value ( " rememberUsername " , false ) . toBool ( ) ;
profile . rememberPassword = settings . value ( " rememberPassword " , false ) . toBool ( ) ;
2021-11-09 12:16:14 -05:00
profile . useDX9 = settings . value ( " useDX9 " , false ) . toBool ( ) ;
2021-11-09 11:25:15 -05:00
profile . useEsync = settings . value ( " useEsync " , false ) . toBool ( ) ;
profile . useGamemode = settings . value ( " useGamemode " , false ) . toBool ( ) ;
profile . useGamescope = settings . value ( " useGamescope " , false ) . toBool ( ) ;
profile . enableDXVKhud = settings . value ( " enableDXVKhud " , false ) . toBool ( ) ;
2021-11-03 06:31:02 -04:00
2021-11-09 13:24:38 -05:00
profileSettings [ settings . value ( " index " ) . toInt ( ) ] = profile ;
2021-11-02 08:50:14 -04:00
2021-11-09 13:24:38 -05:00
settings . endGroup ( ) ;
2021-11-09 11:25:15 -05:00
}
2021-11-09 13:11:21 -05:00
readGameVersion ( ) ;
}
void LauncherWindow : : readGameVersion ( ) {
for ( auto & profile : profileSettings ) {
profile . bootVersion = readVersion ( profile . gamePath + " /boot/ffxivboot.ver " ) ;
profile . gameVersion = readVersion ( profile . gamePath + " /game/ffxivgame.ver " ) ;
}
2021-11-01 09:54:58 -04:00
}
LauncherWindow : : LauncherWindow ( QWidget * parent ) :
QMainWindow ( parent ) {
mgr = new QNetworkAccessManager ( ) ;
sapphireLauncher = new SapphireLauncher ( * this ) ;
squareLauncher = new SquareLauncher ( * this ) ;
squareBoot = new SquareBoot ( * this , * squareLauncher ) ;
2021-11-09 11:25:15 -05:00
readInitialInformation ( ) ;
2021-11-09 11:03:44 -05:00
2021-11-01 13:14:00 -04:00
QMenu * fileMenu = menuBar ( ) - > addMenu ( " File " ) ;
2021-11-01 13:22:27 -04:00
// sorry linux users, for some reason my global menu does not like qt6 apps right now
# if defined(Q_OS_LINUX)
menuBar ( ) - > setNativeMenuBar ( false ) ;
# endif
2021-11-01 13:14:00 -04:00
QAction * settingsAction = fileMenu - > addAction ( " Settings... " ) ;
connect ( settingsAction , & QAction : : triggered , [ = ] {
auto window = new SettingsWindow ( * this ) ;
2021-11-09 11:44:27 -05:00
connect ( this , & LauncherWindow : : settingsChanged , window , & SettingsWindow : : reloadControls ) ;
2021-11-01 13:14:00 -04:00
window - > show ( ) ;
} ) ;
2021-11-02 08:36:30 -04:00
QMenu * toolsMenu = menuBar ( ) - > addMenu ( " Tools " ) ;
QAction * launchOfficial = toolsMenu - > addAction ( " Launch Official Client... " ) ;
connect ( launchOfficial , & QAction : : triggered , [ = ] {
2021-11-09 11:03:44 -05:00
launchExecutable ( { currentProfile ( ) . gamePath + " /boot/ffxivboot64.exe " } ) ;
2021-11-02 08:36:30 -04:00
} ) ;
2021-11-02 08:38:04 -04:00
QAction * launchSysInfo = toolsMenu - > addAction ( " Launch System Info... " ) ;
connect ( launchSysInfo , & QAction : : triggered , [ = ] {
2021-11-09 11:03:44 -05:00
launchExecutable ( { currentProfile ( ) . gamePath + " /boot/ffxivsysinfo64.exe " } ) ;
2021-11-02 08:38:04 -04:00
} ) ;
2021-11-02 08:39:52 -04:00
QAction * launchCfgBackup = toolsMenu - > addAction ( " Launch Config Backup... " ) ;
connect ( launchCfgBackup , & QAction : : triggered , [ = ] {
2021-11-09 11:03:44 -05:00
launchExecutable ( { currentProfile ( ) . gamePath + " /boot/ffxivconfig64.exe " } ) ;
2021-11-02 08:39:52 -04:00
} ) ;
2021-11-02 14:59:05 -04:00
# if defined(Q_OS_MAC) || defined(Q_OS_LINUX)
QMenu * wineMenu = toolsMenu - > addMenu ( " Wine " ) ;
QAction * wineCfg = wineMenu - > addAction ( " winecfg " ) ;
connect ( wineCfg , & QAction : : triggered , [ = ] {
launchExecutable ( { " winecfg.exe " } ) ;
} ) ;
QAction * controlPanel = wineMenu - > addAction ( " Control Panel " ) ;
connect ( controlPanel , & QAction : : triggered , [ = ] {
launchExecutable ( { " control.exe " } ) ;
} ) ;
# endif
2021-11-01 09:54:58 -04:00
auto layout = new QFormLayout ( ) ;
2021-11-09 12:25:54 -05:00
profileSelect = new QComboBox ( ) ;
2021-11-09 12:36:09 -05:00
connect ( profileSelect , & QComboBox : : currentIndexChanged , [ = ] ( int index ) {
reloadControls ( ) ;
} ) ;
2021-11-09 12:25:54 -05:00
2021-11-09 10:37:48 -05:00
layout - > addRow ( " Profile " , profileSelect ) ;
2021-11-09 12:25:54 -05:00
usernameEdit = new QLineEdit ( ) ;
2021-11-01 09:54:58 -04:00
layout - > addRow ( " Username " , usernameEdit ) ;
2021-11-09 12:25:54 -05:00
rememberUsernameBox = new QCheckBox ( ) ;
2021-11-09 12:32:18 -05:00
connect ( rememberUsernameBox , & QCheckBox : : stateChanged , [ = ] ( int ) {
currentProfile ( ) . rememberUsername = rememberUsernameBox - > isChecked ( ) ;
saveSettings ( ) ;
} ) ;
2021-11-01 09:54:58 -04:00
layout - > addRow ( " Remember Username? " , rememberUsernameBox ) ;
2021-11-09 12:25:54 -05:00
passwordEdit = new QLineEdit ( ) ;
2021-11-01 09:54:58 -04:00
passwordEdit - > setEchoMode ( QLineEdit : : EchoMode : : Password ) ;
layout - > addRow ( " Password " , passwordEdit ) ;
2021-11-09 12:25:54 -05:00
rememberPasswordBox = new QCheckBox ( ) ;
2021-11-09 12:32:18 -05:00
connect ( rememberPasswordBox , & QCheckBox : : stateChanged , [ = ] ( int ) {
currentProfile ( ) . rememberPassword = rememberPasswordBox - > isChecked ( ) ;
saveSettings ( ) ;
} ) ;
2021-11-01 09:54:58 -04:00
layout - > addRow ( " Remember Password? " , rememberPasswordBox ) ;
2021-11-09 12:25:54 -05:00
otpEdit = new QLineEdit ( ) ;
2021-11-01 09:54:58 -04:00
layout - > addRow ( " One-Time Password " , otpEdit ) ;
auto loginButton = new QPushButton ( " Login " ) ;
layout - > addRow ( loginButton ) ;
2021-11-09 12:25:54 -05:00
registerButton = new QPushButton ( " Register " ) ;
2021-11-01 09:54:58 -04:00
layout - > addRow ( registerButton ) ;
auto emptyWidget = new QWidget ( ) ;
emptyWidget - > setLayout ( layout ) ;
setCentralWidget ( emptyWidget ) ;
connect ( loginButton , & QPushButton : : released , [ = ] {
auto info = LoginInformation { usernameEdit - > text ( ) , passwordEdit - > text ( ) , otpEdit - > text ( ) } ;
2021-11-09 11:25:15 -05:00
if ( currentProfile ( ) . rememberUsername ) {
2021-11-01 09:54:58 -04:00
auto job = new QKeychain : : WritePasswordJob ( " LauncherWindow " ) ;
job - > setTextData ( usernameEdit - > text ( ) ) ;
2021-11-09 13:29:44 -05:00
job - > setKey ( currentProfile ( ) . name + " -username " ) ;
2021-11-01 09:54:58 -04:00
job - > start ( ) ;
}
2021-11-09 11:25:15 -05:00
if ( currentProfile ( ) . rememberPassword ) {
2021-11-01 09:54:58 -04:00
auto job = new QKeychain : : WritePasswordJob ( " LauncherWindow " ) ;
job - > setTextData ( passwordEdit - > text ( ) ) ;
2021-11-09 13:29:44 -05:00
job - > setKey ( currentProfile ( ) . name + " -password " ) ;
2021-11-01 09:54:58 -04:00
job - > start ( ) ;
}
2021-11-09 11:25:15 -05:00
if ( currentProfile ( ) . isSapphire ) {
sapphireLauncher - > login ( currentProfile ( ) . lobbyURL , info ) ;
} else {
2021-11-01 09:54:58 -04:00
squareBoot - > bootCheck ( info ) ;
2021-11-09 11:25:15 -05:00
}
2021-11-01 09:54:58 -04:00
} ) ;
2021-11-09 11:25:15 -05:00
connect ( registerButton , & QPushButton : : released , [ = ] {
if ( currentProfile ( ) . isSapphire ) {
2021-11-01 09:54:58 -04:00
auto info = LoginInformation { usernameEdit - > text ( ) , passwordEdit - > text ( ) , otpEdit - > text ( ) } ;
2021-11-09 11:25:15 -05:00
sapphireLauncher - > registerAccount ( currentProfile ( ) . lobbyURL , info ) ;
2021-11-01 09:54:58 -04:00
}
2021-11-09 11:25:15 -05:00
} ) ;
2021-11-09 12:25:54 -05:00
reloadControls ( ) ;
2021-11-01 09:54:58 -04:00
}
LauncherWindow : : ~ LauncherWindow ( ) = default ;
2021-11-09 11:03:44 -05:00
ProfileSettings LauncherWindow : : currentProfile ( ) const {
2021-11-09 12:25:54 -05:00
return getProfile ( profileSelect - > currentIndex ( ) ) ;
2021-11-09 11:03:44 -05:00
}
ProfileSettings & LauncherWindow : : currentProfile ( ) {
2021-11-09 12:25:54 -05:00
return getProfile ( profileSelect - > currentIndex ( ) ) ;
2021-11-09 12:06:30 -05:00
}
ProfileSettings LauncherWindow : : getProfile ( int index ) const {
return profileSettings [ index ] ;
}
ProfileSettings & LauncherWindow : : getProfile ( int index ) {
return profileSettings [ index ] ;
2021-11-09 11:03:44 -05:00
}
2021-11-09 11:25:15 -05:00
int LauncherWindow : : getProfileIndex ( QString name ) {
for ( int i = 0 ; i < profileSettings . size ( ) ; i + + ) {
if ( profileSettings [ i ] . name = = name )
return i ;
2021-11-09 11:03:44 -05:00
}
2021-11-09 11:25:15 -05:00
return - 1 ;
2021-11-09 11:03:44 -05:00
}
QList < QString > LauncherWindow : : profileList ( ) const {
QList < QString > list ;
for ( auto profile : profileSettings ) {
2021-11-09 11:25:15 -05:00
list . append ( profile . name ) ;
2021-11-09 11:03:44 -05:00
}
return list ;
2021-11-09 11:44:27 -05:00
}
int LauncherWindow : : addProfile ( ) {
ProfileSettings newProfile ;
2021-11-09 13:24:38 -05:00
newProfile . uuid = QUuid : : createUuid ( ) ;
2021-11-09 11:44:27 -05:00
newProfile . name = " New Profile " ;
profileSettings . append ( newProfile ) ;
settingsChanged ( ) ;
return profileSettings . size ( ) - 1 ;
2021-11-09 12:16:14 -05:00
}
2021-11-09 13:44:37 -05:00
int LauncherWindow : : deleteProfile ( QString name ) {
int index = 0 ;
for ( int i = 0 ; i < profileSettings . size ( ) ; i + + ) {
if ( profileSettings [ i ] . name = = name )
index = i ;
}
// remove group so it doesnt stay
settings . beginGroup ( profileSettings [ index ] . uuid . toString ( QUuid : : StringFormat : : WithoutBraces ) ) ;
settings . remove ( " " ) ;
settings . endGroup ( ) ;
profileSettings . removeAt ( index ) ;
return index - 1 ;
}
2021-11-09 12:16:14 -05:00
void LauncherWindow : : saveSettings ( ) {
2021-11-09 13:24:38 -05:00
settings . setValue ( " defaultProfile " , defaultProfileIndex ) ;
for ( int i = 0 ; i < profileSettings . size ( ) ; i + + ) {
const auto & profile = profileSettings [ i ] ;
2021-11-09 13:26:59 -05:00
settings . beginGroup ( profile . uuid . toString ( QUuid : : StringFormat : : WithoutBraces ) ) ;
2021-11-09 13:24:38 -05:00
settings . setValue ( " name " , profile . name ) ;
settings . setValue ( " index " , i ) ;
2021-11-09 12:16:14 -05:00
2021-11-09 13:04:22 -05:00
// game
2021-11-09 12:16:14 -05:00
settings . setValue ( " useDX9 " , profile . useDX9 ) ;
2021-11-09 12:46:27 -05:00
settings . setValue ( " gamePath " , profile . gamePath ) ;
2021-11-09 12:40:44 -05:00
2021-11-09 13:04:22 -05:00
// wine
settings . setValue ( " wineVersion " , profile . wineVersion ) ;
settings . setValue ( " winePath " , profile . winePath ) ;
settings . setValue ( " winePrefixPath " , profile . winePrefixPath ) ;
2021-11-09 13:08:25 -05:00
settings . setValue ( " useEsync " , profile . useEsync ) ;
settings . setValue ( " useGamescope " , profile . useGamescope ) ;
settings . setValue ( " useGamemode " , profile . useGamemode ) ;
2021-11-09 13:04:22 -05:00
// login
2021-11-09 21:13:21 -05:00
settings . setValue ( " encryptArguments " , profile . encryptArguments ) ;
2021-11-09 12:40:44 -05:00
settings . setValue ( " isSapphire " , profile . isSapphire ) ;
2021-11-09 12:50:37 -05:00
settings . setValue ( " lobbyURL " , profile . lobbyURL ) ;
2021-11-09 12:32:18 -05:00
settings . setValue ( " rememberUsername " , profile . rememberUsername ) ;
settings . setValue ( " rememberPassword " , profile . rememberPassword ) ;
2021-11-09 12:16:14 -05:00
settings . endGroup ( ) ;
}
2021-11-09 12:25:54 -05:00
}
void LauncherWindow : : reloadControls ( ) {
2021-11-09 12:36:09 -05:00
if ( currentlyReloadingControls )
return ;
currentlyReloadingControls = true ;
const int oldIndex = profileSelect - > currentIndex ( ) ;
2021-11-09 12:25:54 -05:00
profileSelect - > clear ( ) ;
for ( const auto & profile : profileList ( ) ) {
profileSelect - > addItem ( profile ) ;
}
2021-11-09 12:36:09 -05:00
profileSelect - > setCurrentIndex ( oldIndex ) ;
2021-11-09 12:25:54 -05:00
if ( profileSelect - > currentIndex ( ) = = - 1 ) {
profileSelect - > setCurrentIndex ( defaultProfileIndex ) ;
}
rememberUsernameBox - > setChecked ( currentProfile ( ) . rememberUsername ) ;
if ( currentProfile ( ) . rememberUsername ) {
auto job = new QKeychain : : ReadPasswordJob ( " LauncherWindow " ) ;
2021-11-09 12:33:20 -05:00
job - > setKey ( currentProfile ( ) . name + " -username " ) ;
2021-11-09 12:25:54 -05:00
job - > start ( ) ;
connect ( job , & QKeychain : : ReadPasswordJob : : finished , [ = ] ( QKeychain : : Job * j ) {
usernameEdit - > setText ( job - > textData ( ) ) ;
} ) ;
}
rememberPasswordBox - > setChecked ( currentProfile ( ) . rememberPassword ) ;
if ( currentProfile ( ) . rememberPassword ) {
auto job = new QKeychain : : ReadPasswordJob ( " LauncherWindow " ) ;
2021-11-09 12:33:20 -05:00
job - > setKey ( currentProfile ( ) . name + " -password " ) ;
2021-11-09 12:25:54 -05:00
job - > start ( ) ;
connect ( job , & QKeychain : : ReadPasswordJob : : finished , [ = ] ( QKeychain : : Job * j ) {
passwordEdit - > setText ( job - > textData ( ) ) ;
} ) ;
}
registerButton - > setEnabled ( currentProfile ( ) . isSapphire ) ;
otpEdit - > setEnabled ( ! currentProfile ( ) . isSapphire ) ;
2021-11-09 12:36:09 -05:00
currentlyReloadingControls = false ;
2021-11-09 11:03:44 -05:00
}