This is the repository for Yandols' Bachelor's Degree Final Year Project Game (2019). Game created in Construct 2 and Launcher/Updater is created with AHK.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ResistanceSaga/Launcher/rs-updater.ahk

373 lines
14 KiB

; /* ------------------------------------------------------------ */
; Script Name : Singularity Updater (For Resistance Saga)
; Version : 3.0.4.5142
; Author : Yandols Z'eon X
; Supported Platforms : Any 64-bit system
; /* ------------------------------------------------------------ */
#Include lib\ssdp-i.ahk
#Include lib\hashvalidate.ahk
#SingleInstance Ignore
#NoEnv
#NoTrayIcon
; #Warn ;-- Enable to display some debug information.
SendMode Input
SetWorkingDir %A_ScriptDir%
;; ----------------------------------
;; Configuration Section -- Start
ProductName = Resistance Saga
ProductProcessName = rs-Launcher.exe
AppName = Singularity Updater
AppAuth = Yandols Zeon X
UpdaterInternalName = Singularity Updater
UpdaterInternalVersion = 3.0.4.5142
UpdaterProcessName = rs-Updater.exe
UpdaterHost = https://kin.yandols.xyz
UpdaterRemoteConfig = rs-fyp.ini
UpdaterServerKeyprint = f3e371ec28b221c0ff46b45f44e1e647
CacheDir = %A_Temp%
CachedPatchName = rs-gameupdate-package.vi
ConfigFileName = csu-resistancesaga-2.vs
AliasFileName = csu-multiupdate0.vs
LauncherAlias = CSU_
VersionAlias = 3045141_
;; Configuration Section -- End
;; Anything beyond this line should only need to be changed whenever things like libraries are updated and parameters need to be recoded.
;; ----------------------------------
;; De-instancer for after program self-updating is completed.
IfExist, %A_ScriptDir%\%LauncherAlias%_patchrstats.vs
{
goto PostUpdateCompletion
return
}
;; De-instancer (Compatibility Fix for updating from Pre-3.0.4 updater).
IfExist, %A_ScriptDir%\PatchrCompletionNotice.vs
{
CompatibilityFixMode = 1
goto PostUpdateCompletion
return
}
;; ----------------------------------
;; Instance the updater in cache folder to allow self-updating of the updater.
If A_IsCompiled = 1
{
If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName%
{
;Msgbox, 0, Debug Notice, Running in local directory
FileCopy, %UpdaterProcessName%, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName%, 1
FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
FileInstall, lib\UnFurl3.exe, %A_Temp%\FurlPatcher.exe, 1
Run, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName% %1%, %A_ScriptDir%, UseErrorLevel
If ErrorLevel
ExitApp
ExitApp
}
If A_ScriptName = %LauncherAlias%%VersionAlias%%UpdaterProcessName%
{
;Msgbox, 0, Debug Notice, Running in alias directory
FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName%
}
}
;; Added testing environment compatibility to speed up uncompiled testing
Else If A_IsCompiled != 1
{
;Msgbox, 0, Debug Notice, Running in local directory (uncompiled)
;FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
;FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
;FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName%
AliasWorkingDir = %A_ScriptDir%
}
;; ----------------------------------
;; Check if /forceupdate paramter is passed.
If 1 = /forceupdate
goto ForceUpdate
;; ----------------------------------
;; Normal operations - Update Prompt
gosub ReadPatchFile
If ExtUpdateNotice = true
{
If ReleaseDate != null
NewUpdateMessage = An update for %ProductName% is available`, would you like to download the new update? `n`nThe latest version is %VersionToUse%, released %ReleaseDate%
else
NewUpdateMessage = An update for %ProductName% is available`, would you like to download the new update? `n`nThe latest version is %VersionToUse%
}
else
NewUpdateMessage = An update for %ProductName% is available`, would you like to download the new update?
Msgbox, 68, %AppName%, %NewUpdateMessage%
IfMsgbox, Yes
goto TaskUpdater
else
ExitApp
return
return
;; ----------------------------------
;; Commence Downloader and Patcher Subroutines
TaskUpdater:
Process, Close, %ProductProcessName% ; Specific to RS only. Remove line here for other apps.
If DownloadType = SingleFile
ThePatchFile = %UpdaterHost%/%File%
Else If DownloadType = URL
ThePatchFile = %URL%
Else
ThePatchFile = %UpdaterHost%/%File%
DownloadFile(ThePatchFile, CachedPatchName, True, True)
sleep 500 ; Prevents thread overload
Gui, Destroy ; Redundancy Backup
Progress, Off ; Redundancy Backup
fileToValidate := CachedPatchName
LocalPatchHash := HashFile(fileToValidate,2)
If LocalPatchHash != %FileHash%
goto PatchValidationFailed
sleep 250 ; Prevents thread overload
Gui, Destroy ; Redundancy Backup
Progress, Off ; Redundancy Backup
;Msgbox, 4, %AppName%, Patch file successfully downloaded`, install now? ;`n`nLocal Hash: %LocalPatchHash%`nRemote Hash: %FileHash%
Msgbox, 0, %AppName%, Patch file successfully downloaded. Installation will now proceed. , 3
;; ----------------------------------
;; Handles Installing the downloaded patch.
;; Added in 5142 and removed Yes or No prompt since pressing No will always make the patch redownload again anyways.
TaskInstallPatch:
sleep 500 ; Prevents thread overload
Process, Close, %ProductProcessName%
sleep 100 ; Prevents thread overload
IfExist, patched.log
FileDelete, patched.log
IfExist, patcherbat.bat
FileDelete, patcherbat.bat
FileInstall, lib\UnFurl3.exe, FurlPatcher.exe, 1
FileAppend, FurlPatcher.exe x -y "%CachedPatchName%" "%AliasWorkingDir%" >patched.log, patcherbat.bat
FileSetAttrib, +R+H+S, FurlPatcher.exe
FileSetAttrib, +R+H+S, patcherbat.bat
RunWait, patcherbat.bat,, Hide UseErrorLevel
;RunWait, FurlPatcher.exe x -y "%CachedPatchName%" >patched.log,, UseErrorLevel
If ErrorLevel
{
If ErrorLevel = 2
Msgbox, 16, %AppName%, A fatal error has occured. Try rebooting your computer and try again.`n[Error Code: %ErrorLevel%]
Else If ErrorLevel = 3
Msgbox, 16, %AppName%, Patching has failed due to invalid checksum, the internal data is damaged. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%]
Else If ErrorLevel = 6
Msgbox, 16, %AppName%, Patching has failed due to one or more required files are locked by other processes such as anti-virus software. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%]
Else If ErrorLevel = 7
Msgbox, 16, %AppName%, Patching has failed. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%]
Else If ErrorLevel = 8
Msgbox, 16, %AppName%, A memory leak has been detected, patching has been aborted. Please reboot your computer and try again.`n[Error Code: %ErrorLevel%]
Else If ErrorLevel = 9
Msgbox, 16, %AppName%, Patching has failed partially. The updater was not able to instance itself and is most likely not able to replace one or more needed files. Try running the updater again with administrator privileges.`n[Error Code: %ErrorLevel%]
Else If ErrorLevel = 10
Msgbox, 16, %AppName%, Patching has failed. The downloaded patch file seems to have disappeared. Try running the updater again with administrator privileges.`n[Error Code: %ErrorLevel%]
Else If ErrorLevel = 11
Msgbox, 16, %AppName%, Patching has failed. The downloaded patch file is not a %ProductName% patch. Please contact the author to have this fixed asap.`n[Error Code: %ErrorLevel%]
Else
Msgbox, 16, %AppName%, Patching has failed. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%]
DontDeleteLogFile = 1
PatchHasFailed = 1
}
sleep 100 ; Prevents thread overload
FileSetAttrib, -R-S, FurlPatcher.exe
FileSetAttrib, -R-S, patcherbat.bat
FileDelete, FurlPatcher.exe
FileDelete, patcherbat.bat
FileDelete, %CachedPatchName%
If DontDeleteLogFile != 1
FileDelete, patched.log
If PatchHasFailed = 1
ExitApp
FileAppend, STATUS_COMPLETED, %AliasWorkingDir%\%LauncherAlias%_patchrstats.vs
FileSetAttrib, +H+S, %LauncherAlias%_patchrstats.vs
sleep 150 ; Prevents thread overload
Run, %AliasWorkingDir%\%UpdaterProcessName%,, UseErrorLevel
If ErrorLevel
{
Msgbox, 16, %AppName%, Failed to switch instances. This may be caused by an invalid or failed update attempt.
ExitApp
}
; ;If PatchHasFailed != 1
; ;Msgbox, 64, %AppName%, Patching completed. You are now running on the latest version of %ProductName%!
ExitApp
return
;; ----------------------------------
;; Error handling when downloaded patch file's hash does not match remote hash file
PatchValidationFailed:
sleep 100 ; Prevents thread overload
Msgbox, 16, %AppName%, Warning: Patch file validation has failed! The file that was downloaded may be corrupted, please try running the updater again. If problem persists, please contact the author to have this fixed asap.
ExitApp
return
;; ----------------------------------
;; De-instancing handler and post update completion notice.
PostUpdateCompletion:
If CompatibilityFixMode = 1
{
;IniRead, VersionToUse, %CacheDir%/clayupdate-rmtclock.vc, SingularityUpdater, VersionToUse, null
FileSetAttrib, -R+H+S, PatchrCompletionNotice.vs
sleep 100 ; Prevents thread overload
}
IniRead, VersionToUse, %CacheDir%/%ConfigFileName%, SingularityUpdater, VersionToUse, null
FileSetAttrib, -R+H+S, %LauncherAlias%_patchrstats.vs
sleep 100 ; Prevents thread overload
Msgbox, 64, %AppName%, Patching completed. Your version of %ProductName% has been updated to version %VersionToUse%!
FileSetAttrib, -R-S, FurlPatcher.exe
FileSetAttrib, -R-S, patcherbat.bat
FileDelete, FurlPatcher.exe
FileDelete, patcherbat.bat
FileDelete, %CachedPatchName%
FileDelete, %AliasFileName%
FileDelete, %LauncherAlias%_patchrstats.vs
If DontDeleteLogFile != 1
FileDelete, patched.log
FileDelete, %LauncherAlias%%VersionAlias%%AliasFileName%
FileDelete, %LauncherAlias%%VersionAlias%%UpdaterProcessName%
If CompatibilityFixMode = 1
{
FileDelete, %CachedPatchName%
FileDelete, %AliasFileName%
FileDelete, PatchrCmd.vs
FileDelete, PatchrCompletionNotice.vs
FileDelete, %LauncherAlias%%VersionAlias%PatchrCmd.vs
FileDelete, %LauncherAlias%%VersionAlias%teal-updater.exe
}
Run, %A_ScriptDir%\%ProductProcessName%, UseErrorLevel
ExitApp
return
;; ----------------------------------
;; Force Update Handler (Specific to RS only but may be adapted into main SU)
ForceUpdate:
IsForceUpdating = 1
If A_IsCompiled = 1
{
If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName%
{
; Running in local directory
FileCopy, %UpdaterProcessName%, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName%, 1
FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
FileInstall, lib\UnFurl3.exe, %A_Temp%\FurlPatcher.exe, 1
Run, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName%, %A_ScriptDir%, UseErrorLevel
If ErrorLevel
ExitApp
ExitApp
}
If A_ScriptName = %LauncherAlias%%VersionAlias%%UpdaterProcessName%
{
; Running in alias directory
FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName%
}
}
;; Added testing environment compatibility to speed up uncompiled testing
Else If A_IsCompiled != 1
AliasWorkingDir = %A_ScriptDir%
gosub ReadPatchFile
goto TaskUpdater
Return
;; ----------------------------------
;; Read the patch info downloaded from the remote config file
ReadPatchFile:
;; Always force redownload the remote config file
IfExist, %CacheDir%/%ConfigFileName%
FileDelete, %CacheDir%/%ConfigFileName%
UrlDownloadToFile, %UpdaterHost%/%UpdaterRemoteConfig%, %CacheDir%/%ConfigFileName%
;; Read Remote Config File
IniRead, RetailVersion, %CacheDir%/%ConfigFileName%, SingularityUpdater, RetailVersion, null
IniRead, VersionToUse, %CacheDir%/%ConfigFileName%, SingularityUpdater, VersionToUse, null
IniRead, ReleaseDate, %CacheDir%/%ConfigFileName%, SingularityUpdater, ReleaseDate, null
IniRead, ExtUpdateNotice, %CacheDir%/%ConfigFileName%, SingularityUpdater, ExtUpdateNotice, false
IniRead, OCVersion, %CacheDir%/%ConfigFileName%, SingularityUpdater, OCVersion, 0
IniRead, Identifier, %CacheDir%/%ConfigFileName%, SingularityUpdater, Identifier, 0
IniRead, Keyprint, %CacheDir%/%ConfigFileName%, SingularityUpdater, Keyprint, 0
IniRead, Optimization, %CacheDir%/%ConfigFileName%, SingularityUpdater, Optimization, null
IniRead, DownloadType, %CacheDir%/%ConfigFileName%, SingularityUpdater, DownloadType, SingleFile
IniRead, File, %CacheDir%/%ConfigFileName%, SingularityUpdater, File, null
IniRead, URL, %CacheDir%/%ConfigFileName%, SingularityUpdater, URL, null
IniRead, FileHash, %CacheDir%/%ConfigFileName%, SingularityUpdater, FileHash, 0
;; Make sure the remote config file is the correct one by validating keyprint.
If Keyprint != %UpdaterServerKeyprint%
{
Msgbox, 16, %AppName%, Patch server authentication failed.
ExitApp
}
;; Make Forced Updating stop the thread here so that the prompts don't show up.
If IsForceUpdating = 1
{
If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName%
{
FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
Return
}
Return
}
;; Do not prompt a download if existing version is the same as latest [Compiled Version]
If A_IsCompiled = 1
{
If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName%
{
;Msgbox, 0, Debug Notice, Running in local directory
FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName%
;FileGetVersion, ExistingVersion, %ProductProcessName%
FileRead, ExistingVersion, win64\rversion.txt
If ExistingVersion = %VersionToUse%
{
Msgbox, 64, %AppName%, You already have the latest version currently available.
ExitApp
}
return
}
If A_ScriptName = %LauncherAlias%%VersionAlias%%UpdaterProcessName%
{
;Msgbox, 0, Debug Notice, Running in alias directory
FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName%
;FileGetVersion, ExistingVersion, %AliasWorkingDir%\%ProductProcessName%
FileRead, ExistingVersion, %AliasWorkingDir%\win64\rversion.txt
If CSU_NewVersion != %ProductVer%
If ExistingVersion = %VersionToUse%
{
Msgbox, 64, %AppName%, You already have the latest version currently available.
ExitApp
}
return
}
}
;; Do not prompt a download if existing version is the same as latest [Uncompiled Version]
;FileGetVersion, ExistingVersion, %ProductProcessName%
FileRead, ExistingVersion, win64\rversion.txt
If ExistingVersion = %VersionToUse%
{
Msgbox, 64, %AppName%, You already have the latest version currently available.
ExitApp
}
return
;; ----------------------------------
;; Nullify Progress Window Standard Closure Calls
GuiClose:
GuiExit:
return