marli-UpdateModNightcoop.psm1

#region Private Hilfsfunktionen
function Remove-NightCoopTempItem {
    param([string]$Path)
    if (Test-Path -LiteralPath $Path) {
        Remove-Item -LiteralPath $Path -Recurse -Force
    }
}

function Get-NightCoopSteamGamePath {
    param([string]$GameFolder)

    $steamPath = (Get-ItemProperty 'HKLM:\SOFTWARE\WOW6432Node\Valve\Steam' -ErrorAction SilentlyContinue).InstallPath
    if (-not $steamPath) {
        $steamPath = (Get-ItemProperty 'HKCU:\Software\Valve\Steam' -ErrorAction SilentlyContinue).SteamPath
    }
    if (-not $steamPath) { return $null }

    # Alle Steam-Bibliotheken sammeln (Spiel kann auf einem anderen Laufwerk liegen)
    $libraries = @($steamPath)
    $vdf = Join-Path $steamPath 'steamapps\libraryfolders.vdf'
    if (Test-Path -LiteralPath $vdf) {
        foreach ($match in (Select-String -LiteralPath $vdf -Pattern '"path"\s+"([^"]+)"')) {
            $libraries += ($match.Matches[0].Groups[1].Value -replace '\\\\', '\')
        }
    }

    foreach ($lib in ($libraries | Select-Object -Unique)) {
        $candidate = Join-Path $lib "steamapps\common\$GameFolder"
        if (Test-Path -LiteralPath $candidate) { return $candidate }
    }
    return $null
}

function ConvertTo-NightCoopVersion {
    param([string]$Text)
    $clean = ($Text -replace '[^\d\.]', '').Trim('.')
    $v = $null
    if ([version]::TryParse($clean, [ref]$v)) { return $v }
    return $null
}
#endregion

function Update-NightCoopMod {
<#
.SYNOPSIS
    Aktualisiert die Cyberpunk-2077-Mod NightCoop auf die neueste Version.
 
.DESCRIPTION
    Sucht Cyberpunk 2077 in allen Steam-Bibliotheken, vergleicht die installierte
    NightCoop-Version mit der Online-Version von nightcoop.net und installiert
    bei Bedarf das Update (Download, Entpacken, Kopieren ins Spielverzeichnis).
 
.PARAMETER Force
    Installiert ohne Rückfrage, wenn ein Update verfügbar ist.
 
.EXAMPLE
    Update-NightCoopMod
 
.EXAMPLE
    marli-UpdateModNightcoop -Force
 
.NOTES
    Autor: Marco Lippert
#>

    [CmdletBinding()]
    param(
        [switch]$Force
    )

    $ErrorActionPreference = 'Stop'
    $ProgressPreference    = 'SilentlyContinue'   # macht Invoke-WebRequest in PS 5.1 deutlich schneller
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

    $tempRoot = Join-Path $env:TEMP 'NightCoopUpdate'

    try {
        #region Pfade
        $gamePath = Get-NightCoopSteamGamePath -GameFolder 'Cyberpunk 2077'
        if (-not $gamePath) { throw 'Cyberpunk 2077 wurde in keiner Steam-Bibliothek gefunden.' }

        $modPath     = Join-Path $gamePath 'red4ext\plugins\NightCoop'
        $versionFile = Join-Path $modPath 'version.txt'
        $zipFile     = Join-Path $tempRoot 'NightCoop_update.zip'
        $expandPath  = Join-Path $tempRoot 'expand'
        #endregion

        #region Lokale Version
        $versionLocal = 'nicht installiert'
        if (Test-Path -LiteralPath $versionFile) {
            $versionLocal = (Get-Content -LiteralPath $versionFile -Raw).Trim()
        }
        #endregion

        #region Online-Version
        $baseUri       = 'https://nightcoop.net'
        $release       = Invoke-RestMethod -Uri "$baseUri/releases.json" -UseBasicParsing
        $versionOnline = [string]$release.latest

        $entry = $release.releases | Where-Object { $_.version -eq $versionOnline } | Select-Object -First 1
        if (-not $entry) { throw "Version $versionOnline wurde in releases.json nicht gefunden." }

        $fileUrl = [string](@($entry.files.url)[0])
        if ($fileUrl -notmatch '^https?://') { $fileUrl = $baseUri + '/' + $fileUrl.TrimStart('/') }
        #endregion

        #region Versionen vergleichen
        $vLocal  = ConvertTo-NightCoopVersion $versionLocal
        $vOnline = ConvertTo-NightCoopVersion $versionOnline
        if ($vLocal -and $vOnline) { $updateNeeded = $vOnline -gt $vLocal }
        else                       { $updateNeeded = $versionLocal -ne $versionOnline }

        if (-not $updateNeeded) {
            Write-Host "Kein Update verfügbar. Installiert: $versionLocal" -ForegroundColor Green
            return
        }

        Write-Host 'Neues Update verfügbar!' -ForegroundColor Yellow
        Write-Host 'Installierte Version: ' -NoNewline; Write-Host $versionLocal  -ForegroundColor Green
        Write-Host 'Neue verfügbare Version: ' -NoNewline; Write-Host $versionOnline -ForegroundColor Green

        if (-not $Force) {
            $answer = Read-Host 'Neue Version installieren? (j)a / (n)ein'
            if ($answer -notmatch '^j') {
                Write-Host 'Abgebrochen.'
                return
            }
        }
        #endregion

        #region Installation
        if (Get-Process -Name 'Cyberpunk2077' -ErrorAction SilentlyContinue) {
            throw 'Cyberpunk 2077 läuft noch. Bitte zuerst beenden.'
        }

        Remove-NightCoopTempItem $tempRoot
        New-Item -Path $tempRoot -ItemType Directory -Force | Out-Null

        Write-Host 'Lade Update herunter...'
        Invoke-WebRequest -Uri $fileUrl -OutFile $zipFile -UseBasicParsing
        Unblock-File -LiteralPath $zipFile

        Write-Host 'Entpacke...'
        Expand-Archive -LiteralPath $zipFile -DestinationPath $expandPath -Force

        Write-Host 'Kopiere Dateien ins Spielverzeichnis...'
        foreach ($file in (Get-ChildItem -LiteralPath $expandPath -Recurse -File)) {
            $relative  = $file.FullName.Substring($expandPath.Length).TrimStart('\')
            $target    = Join-Path $gamePath $relative
            $targetDir = Split-Path $target -Parent
            if (-not (Test-Path -LiteralPath $targetDir)) {
                New-Item -Path $targetDir -ItemType Directory -Force | Out-Null
            }
            Copy-Item -LiteralPath $file.FullName -Destination $target -Force
        }

        if (-not (Test-Path -LiteralPath $modPath)) {
            New-Item -Path $modPath -ItemType Directory -Force | Out-Null
        }
        Set-Content -LiteralPath $versionFile -Value $versionOnline -Force

        Write-Host "Update auf Version $versionOnline erfolgreich installiert." -ForegroundColor Green
        #endregion
    }
    catch {
        Write-Host "Fehler: $($_.Exception.Message)" -ForegroundColor Red
    }
    finally {
        Write-Host 'Bereinige temporäre Dateien...'
        Remove-NightCoopTempItem $tempRoot
    }
}

# Alter Name bleibt nutzbar
New-Alias -Name 'marli-UpdateModNightcoop' -Value 'Update-NightCoopMod' -Force

Export-ModuleMember -Function 'Update-NightCoopMod' -Alias 'marli-UpdateModNightcoop'