Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions installer/windows/Language Files/EnglishExtra.nsh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup will guide you through the
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nThis path does not have Geometry Dash installed!"
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "This path has other mods installed!$\r$\nThey will be overwritten by Geode. (the dll trademark)"
${LangFileString} GEODE_TEXT_REGISTER_FILETYPE "Register .geode filetype"

; uninstaller

Expand Down
36 changes: 36 additions & 0 deletions installer/windows/installer.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,12 @@ SectionGroup "Geode"
Section "Loader" LOADER_SECTION
SetOutPath $INSTDIR

!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
!define env_hkcu 'HKCU "Environment"'

WriteRegExpandStr ${env_hkcu} "GEODE_GD_PATH" "$INSTDIR"
System::Call 'user32::SendMessageTimeoutA(i0xffff,i0x1a,i0, t"Environment",i2,i5000,i0)i'

File ${BINDIR}\Geode.dll
File ${BINDIR}\Geode.pdb
File ${BINDIR}\GeodeUpdater.exe
Expand All @@ -480,6 +486,32 @@ SectionGroup "Geode"
WriteUninstaller "GeodeUninstaller.exe"
SectionEnd

Section "Register .geode Filetype" FILETYPE_SECTION
SectionGetFlags ${FILETYPE_SECTION} $0
IntOp $0 $0 & ${SF_SELECTED}
StrCmp $0 0 done

; Extract the ICO to a known path
SetOutPath "$INSTDIR\geode"
File /oname=logo_inst.ico "Graphics\logo_inst.ico"
File /oname=installmods.ps1 "installmods.ps1"

; Register .geode extension
WriteRegStr HKCU "Software\Classes\.geode" "" "GeodeFile"
WriteRegStr HKCU "Software\Classes\GeodeFile" "" "Geode Mod"
WriteRegStr HKCU "Software\Classes\GeodeFile\DefaultIcon" "" "$INSTDIR\geode\logo_inst.ico,0"
WriteRegStr HKCU "Software\Classes\GeodeFile\shell" "" "open"
WriteRegStr HKCU "Software\Classes\GeodeFile\shell\open\command" "" \
'powershell.exe -ExecutionPolicy Bypass -File "$INSTDIR\geode\installmods.ps1" "%1"'

; Refresh icon cache
System::Call 'shell32::SHChangeNotify(i0x8000000,i0x0,p0,p0)'

SetOutPath "$INSTDIR"

done:
SectionEnd

Section "Resources"
CreateDirectory $INSTDIR\geode\resources\geode.loader
SetOutPath $INSTDIR\geode\resources\geode.loader
Expand Down Expand Up @@ -545,6 +577,10 @@ Section "Uninstall"
Delete $INSTDIR\GeodeUpdater.exe
Delete $INSTDIR\XInput1_4.dll

; Remove the .geode filetype registry keys
DeleteRegKey HKCU "Software\Classes\.geode"
DeleteRegKey HKCU "Software\Classes\GeodeFile"

# default value of DATA is an empty string
# if DATA is empty, keep user data
# otherwise, delete the entire geode and DATA\geode\mods dirs
Expand Down
110 changes: 110 additions & 0 deletions installer/windows/installmods.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
param (
[Parameter(Mandatory=$true, ValueFromRemainingArguments=$true)]
[string[]]$ModFiles
)

if (-not $env:GEODE_GD_PATH) {
Write-Error "GEODE_GD_PATH environment variable is not set."
exit
}

$GEODE_GD_PATH = $env:GEODE_GD_PATH
$MODS_PATH = Join-Path $GEODE_GD_PATH "geode\mods"
$InstalledMods = @{}
$InstalledOrDownloaded = @{}

function Show-InstalledModsMessage {
param([hashtable]$Mods)
Add-Type -AssemblyName System.Windows.Forms
if ($Mods.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show(
"No new mods were installed.",
"Geode Mod Installer",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
)
} else {
$msg = "Installed mods:`n`n"
foreach ($mod in $Mods.Keys) {
$msg += "- $mod`n"
}
[System.Windows.Forms.MessageBox]::Show(
$msg,
"Geode Mod Installer",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
)
}
}

function Extract-Mod {
param([string]$Source, [string]$Destination)
if (Test-Path $Destination) { Remove-Item -Recurse -Force $Destination }
try {
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($Source, $Destination)
return $true
} catch {
Write-Error ("Failed to extract {0}: {1}" -f $Source, $_)
return $false
}
}

function Install-Mod {
param([string]$ModFilePath)

$ModName = [System.IO.Path]::GetFileNameWithoutExtension($ModFilePath)
if ($InstalledOrDownloaded.ContainsKey($ModName)) { return }

$TempDir = Join-Path $env:TEMP "temp_$ModName"
if (-not (Extract-Mod -Source $ModFilePath -Destination $TempDir)) { return }

$DestModPath = Join-Path $MODS_PATH ([System.IO.Path]::GetFileName($ModFilePath))
Copy-Item -Path $ModFilePath -Destination $DestModPath -Force

$InstalledMods[$ModName] = $true
$InstalledOrDownloaded[$ModName] = $true

$ModJsonPath = Join-Path $TempDir "mod.json"
if (Test-Path $ModJsonPath) {
$ModJson = Get-Content $ModJsonPath -Raw | ConvertFrom-Json
if ($ModJson.PSObject.Properties.Name -contains "dependencies" -and $ModJson.dependencies) {
Write-Host "Installing dependencies - Mod versions may be incompatible with the mod."
foreach ($dep in $ModJson.dependencies.PSObject.Properties) {
$depId = $dep.Name
$depValue = $dep.Value

if ($depValue -is [PSCustomObject] -and $depValue.importance -eq "suggested") {
Write-Host "Skipping suggested dependency $depId"
continue
}

$DepModPath = Join-Path $MODS_PATH "$depId.geode"
if ($InstalledOrDownloaded.ContainsKey($depId) -or (Test-Path $DepModPath)) { continue }

Write-Host "Downloading latest dependency $depId..."
try {
$TempDepPath = Join-Path $env:TEMP "$depId.geode"
Invoke-WebRequest -Uri "https://api.geode-sdk.org/v1/mods/$depId/versions/latest/download" -OutFile $TempDepPath -UseBasicParsing
Install-Mod -ModFilePath $TempDepPath
} catch {
Write-Warning ("Failed to download or install dependency {0}: {1}" -f $depId, $_)
}
}
}
}

if (Test-Path $TempDir) { Remove-Item -Recurse -Force $TempDir }
}

if (-not (Test-Path $MODS_PATH)) { New-Item -ItemType Directory -Path $MODS_PATH | Out-Null }

foreach ($modFile in $ModFiles) {
if (Test-Path $modFile) {
Install-Mod -ModFilePath (Resolve-Path $modFile)
} else {
Write-Warning "$modFile does not exist."
}
}

Show-InstalledModsMessage -Mods $InstalledMods
Loading