Cat
This commit is contained in:
parent
7b7424eea1
commit
570c704427
1 changed files with 135 additions and 28 deletions
|
|
@ -27,7 +27,6 @@ function Wait-ConsolePause {
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-DazedPatcherBannerGlyphs {
|
function Get-DazedPatcherBannerGlyphs {
|
||||||
# Fixed 7 rows × 8 cols per glyph (monospace). Letters only; words built separately.
|
|
||||||
return @{
|
return @{
|
||||||
'A' = @(' ', ' AAA ', ' A A ', ' AAAAA ', ' A A ', ' A A ', ' ')
|
'A' = @(' ', ' AAA ', ' A A ', ' AAAAA ', ' A A ', ' A A ', ' ')
|
||||||
'C' = @(' ', ' CCCC ', ' C ', ' C ', ' C ', ' CCCC ', ' ')
|
'C' = @(' ', ' CCCC ', ' C ', ' C ', ' C ', ' CCCC ', ' ')
|
||||||
|
|
@ -46,7 +45,6 @@ function Build-AsciiWordLines {
|
||||||
[Parameter(Mandatory = $true)][string]$Word,
|
[Parameter(Mandatory = $true)][string]$Word,
|
||||||
[hashtable]$Glyphs
|
[hashtable]$Glyphs
|
||||||
)
|
)
|
||||||
# Force array: pipeline assignment can otherwise collapse to a scalar and break glyph lookup.
|
|
||||||
$letters = @(
|
$letters = @(
|
||||||
$Word.ToUpperInvariant().ToCharArray() | ForEach-Object { [string]$_ }
|
$Word.ToUpperInvariant().ToCharArray() | ForEach-Object { [string]$_ }
|
||||||
)
|
)
|
||||||
|
|
@ -78,11 +76,10 @@ function ConvertTo-LineStringArray {
|
||||||
|
|
||||||
function Pad-LineBlockToHeight {
|
function Pad-LineBlockToHeight {
|
||||||
param(
|
param(
|
||||||
# Untyped: PS may wrongly coerce to '' before binding [string[]]; normalize ourselves.
|
[Parameter(Mandatory = $true, Position = 0)][object]$Rows,
|
||||||
[Parameter(Mandatory = $true, Position = 0)][object]$PatchVerticalRows,
|
|
||||||
[Parameter(Mandatory = $true, Position = 1)][int]$TargetHeight
|
[Parameter(Mandatory = $true, Position = 1)][int]$TargetHeight
|
||||||
)
|
)
|
||||||
[string[]]$lines = ConvertTo-LineStringArray -Value $PatchVerticalRows
|
[string[]]$lines = ConvertTo-LineStringArray -Value $Rows
|
||||||
if ($lines.Count -eq 0 -and $TargetHeight -gt 0) {
|
if ($lines.Count -eq 0 -and $TargetHeight -gt 0) {
|
||||||
$blank = New-Object string[] $TargetHeight
|
$blank = New-Object string[] $TargetHeight
|
||||||
for ($i = 0; $i -lt $TargetHeight; $i++) { $blank[$i] = '' }
|
for ($i = 0; $i -lt $TargetHeight; $i++) { $blank[$i] = '' }
|
||||||
|
|
@ -102,7 +99,7 @@ function Pad-LineBlockToHeight {
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-EmbeddedIconAsciiCatLines {
|
function Get-EmbeddedIconAsciiCatLines {
|
||||||
# Generated from assets/icon.png; rerun generate_icon_ascii.ps1 and paste here if the icon changes.
|
# Refresh via generate_icon_ascii.ps1 when assets/icon.png changes.
|
||||||
$raw = @'
|
$raw = @'
|
||||||
# %#
|
# %#
|
||||||
%:.-@ #..=
|
%:.-@ #..=
|
||||||
|
|
@ -137,8 +134,7 @@ function Get-EmbeddedIconAsciiCatLines {
|
||||||
+..............................:=#
|
+..............................:=#
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%@
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%@
|
||||||
'@
|
'@
|
||||||
[string[]]$split = @($raw -split '\r?\n')
|
return [string[]]@($raw -split '\r?\n')
|
||||||
return [string[]]$split
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Write-AsciiHeader {
|
function Write-AsciiHeader {
|
||||||
|
|
@ -156,8 +152,8 @@ function Write-AsciiHeader {
|
||||||
$catLines = @(Get-EmbeddedIconAsciiCatLines)
|
$catLines = @(Get-EmbeddedIconAsciiCatLines)
|
||||||
|
|
||||||
$targetH = [Math]::Max($titleRows.Count, $catLines.Count)
|
$targetH = [Math]::Max($titleRows.Count, $catLines.Count)
|
||||||
$titlePadded = Pad-LineBlockToHeight -PatchVerticalRows $titleRows -TargetHeight $targetH
|
$titlePadded = Pad-LineBlockToHeight -Rows $titleRows -TargetHeight $targetH
|
||||||
$catPadded = Pad-LineBlockToHeight -PatchVerticalRows $catLines -TargetHeight $targetH
|
$catPadded = Pad-LineBlockToHeight -Rows $catLines -TargetHeight $targetH
|
||||||
|
|
||||||
$titleWidth = 0
|
$titleWidth = 0
|
||||||
foreach ($ln in $titlePadded) {
|
foreach ($ln in $titlePadded) {
|
||||||
|
|
@ -344,7 +340,7 @@ function Get-InvalidZipDownloadHint {
|
||||||
$parts = [System.Collections.Generic.List[string]]::new()
|
$parts = [System.Collections.Generic.List[string]]::new()
|
||||||
$parts.Add("File size: $len bytes.")
|
$parts.Add("File size: $len bytes.")
|
||||||
if ($len -eq 0) {
|
if ($len -eq 0) {
|
||||||
$parts.Add('Download was empty.')
|
$parts.Add('Empty file often means the window was closed during download, the connection dropped, or security software blocked the file. Run again and let it finish.')
|
||||||
return ($parts -join ' ')
|
return ($parts -join ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -387,7 +383,67 @@ function Get-InvalidZipDownloadHint {
|
||||||
return ($parts -join ' ')
|
return ($parts -join ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
function Download-WithIwrSpeedProgress {
|
$script:GameUpdateConsoleCloseHelperLoaded = $false
|
||||||
|
function Initialize-GameUpdateConsoleCloseHelper {
|
||||||
|
if ($script:GameUpdateConsoleCloseHelperLoaded) { return }
|
||||||
|
$script:GameUpdateConsoleCloseHelperLoaded = $true
|
||||||
|
$script:GameUpdateConsoleCloseHelperWorks = $false
|
||||||
|
if ($env:OS -ne 'Windows_NT') { return }
|
||||||
|
|
||||||
|
try {
|
||||||
|
Add-Type -TypeDefinition @'
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace GameUpdate {
|
||||||
|
public static class ConsoleCloseHelper {
|
||||||
|
private static HandlerRoutine _handler;
|
||||||
|
|
||||||
|
public static void Register() {
|
||||||
|
_handler = Handle;
|
||||||
|
SetConsoleCtrlHandler(_handler, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Unregister() {
|
||||||
|
if (_handler != null) {
|
||||||
|
SetConsoleCtrlHandler(_handler, false);
|
||||||
|
_handler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool Handle(uint ctrlType) {
|
||||||
|
const uint CTRL_CLOSE_EVENT = 2;
|
||||||
|
const uint CTRL_LOGOFF_EVENT = 5;
|
||||||
|
const uint CTRL_SHUTDOWN_EVENT = 6;
|
||||||
|
if (ctrlType != CTRL_CLOSE_EVENT && ctrlType != CTRL_LOGOFF_EVENT && ctrlType != CTRL_SHUTDOWN_EVENT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
string path = Environment.GetEnvironmentVariable("GAMEUPDATE_REPO_ZIP_PATH");
|
||||||
|
if (!string.IsNullOrEmpty(path) && File.Exists(path)) {
|
||||||
|
File.Delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate bool HandlerRoutine(uint ctrlType);
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll", SetLastError = true)]
|
||||||
|
private static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'@ -ErrorAction Stop
|
||||||
|
$script:GameUpdateConsoleCloseHelperWorks = $true
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$script:GameUpdateConsoleCloseHelperWorks = $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-PatchArchiveDownload {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)][string]$Url,
|
[Parameter(Mandatory = $true)][string]$Url,
|
||||||
[Parameter(Mandatory = $true)][string]$OutFile,
|
[Parameter(Mandatory = $true)][string]$OutFile,
|
||||||
|
|
@ -398,13 +454,37 @@ function Download-WithIwrSpeedProgress {
|
||||||
Remove-Item -LiteralPath $OutFile -Force
|
Remove-Item -LiteralPath $OutFile -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$outFull = [System.IO.Path]::GetFullPath($OutFile)
|
||||||
|
Initialize-GameUpdateConsoleCloseHelper
|
||||||
|
|
||||||
$prevPref = $ProgressPreference
|
$prevPref = $ProgressPreference
|
||||||
|
$completed = $false
|
||||||
|
$registeredCloseHandler = $false
|
||||||
try {
|
try {
|
||||||
|
if ($script:GameUpdateConsoleCloseHelperWorks) {
|
||||||
|
$env:GAMEUPDATE_REPO_ZIP_PATH = $outFull
|
||||||
|
[GameUpdate.ConsoleCloseHelper]::Register()
|
||||||
|
$registeredCloseHandler = $true
|
||||||
|
}
|
||||||
|
|
||||||
$ProgressPreference = 'Continue'
|
$ProgressPreference = 'Continue'
|
||||||
Invoke-WebRequest -Uri $Url -OutFile $OutFile -Headers $Headers -UseBasicParsing
|
Invoke-WebRequest -Uri $Url -OutFile $OutFile -Headers $Headers -UseBasicParsing
|
||||||
|
$completed = $true
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
$ProgressPreference = $prevPref
|
$ProgressPreference = $prevPref
|
||||||
|
|
||||||
|
if ($registeredCloseHandler) {
|
||||||
|
try {
|
||||||
|
[GameUpdate.ConsoleCloseHelper]::Unregister()
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
Remove-Item env:GAMEUPDATE_REPO_ZIP_PATH -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $completed -and (Test-Path -LiteralPath $OutFile)) {
|
||||||
|
Remove-FileOrDirectoryViaCmd -LiteralPath $OutFile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,47 +548,64 @@ function Invoke-PatchDownloadExtract {
|
||||||
return 10
|
return 10
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host 'Downloading patch...'
|
$zipPath = Join-Path $Root ('dazedmtl_patch_' + [Guid]::NewGuid().ToString('N') + '.zip')
|
||||||
$zipPath = Join-Path $PWD.Path 'repo.zip'
|
Write-Host ('Downloading patch... ' + $zipPath)
|
||||||
$stage = Join-Path ([IO.Path]::GetTempPath()) ('gu_' + [Guid]::NewGuid().ToString('N'))
|
$stage = Join-Path ([IO.Path]::GetTempPath()) ('gu_' + [Guid]::NewGuid().ToString('N'))
|
||||||
$archiveSha = [uri]::EscapeDataString($latestSha)
|
$archiveSha = [uri]::EscapeDataString($latestSha)
|
||||||
$archiveUrl = "https://gitgud.io/api/v4/projects/$id/repository/archive.zip?sha=$archiveSha"
|
$archiveUrl = "https://gitgud.io/api/v4/projects/$id/repository/archive.zip?sha=$archiveSha"
|
||||||
|
|
||||||
$dlSw = [System.Diagnostics.Stopwatch]::StartNew()
|
$dlSw = [System.Diagnostics.Stopwatch]::StartNew()
|
||||||
Invoke-WithRetry -Name 'Download archive with Invoke-WebRequest' -Attempts $dlAttempts -Action {
|
Invoke-WithRetry -Name 'Download archive with Invoke-WebRequest' -Attempts $dlAttempts -Action {
|
||||||
Download-WithIwrSpeedProgress -Url $archiveUrl -OutFile $zipPath -Headers $headers
|
Invoke-PatchArchiveDownload -Url $archiveUrl -OutFile $zipPath -Headers $headers
|
||||||
} | Out-Null
|
} | Out-Null
|
||||||
$dlSw.Stop()
|
$dlSw.Stop()
|
||||||
$bytes = (Get-Item -LiteralPath $zipPath).Length
|
$bytes = (Get-Item -LiteralPath $zipPath).Length
|
||||||
|
if ($bytes -eq 0) {
|
||||||
|
$hint = Get-InvalidZipDownloadHint -LiteralPath $zipPath
|
||||||
|
Remove-DownloadedRepoZip -LiteralPath $zipPath
|
||||||
|
throw "PATCH_ERR:ZIP:Download is empty (0 bytes). $hint"
|
||||||
|
}
|
||||||
|
|
||||||
$secs = [Math]::Max($dlSw.Elapsed.TotalSeconds, 0.001)
|
$secs = [Math]::Max($dlSw.Elapsed.TotalSeconds, 0.001)
|
||||||
$mbps = ($bytes / 1MB) / $secs
|
$mbps = ($bytes / 1MB) / $secs
|
||||||
Write-Host ("Download complete via iwr: {0:N1} MB in {1:N1}s ({2:N1} MB/s)" -f ($bytes / 1MB), $secs, $mbps)
|
Write-Host ("Download complete: {0:N1} MB in {1:N1}s ({2:N1} MB/s)" -f ($bytes / 1MB), $secs, $mbps)
|
||||||
|
|
||||||
|
$zipHeaderBad = $false
|
||||||
|
$zipHeaderHint = ''
|
||||||
$fs = [System.IO.File]::OpenRead($zipPath)
|
$fs = [System.IO.File]::OpenRead($zipPath)
|
||||||
try {
|
try {
|
||||||
$hdr = New-Object byte[] 4
|
$hdr = New-Object byte[] 4
|
||||||
if ($fs.Read($hdr, 0, 4) -lt 4 -or $hdr[0] -ne 0x50 -or $hdr[1] -ne 0x4B) {
|
if ($fs.Read($hdr, 0, 4) -lt 4 -or $hdr[0] -ne 0x50 -or $hdr[1] -ne 0x4B) {
|
||||||
$hint = Get-InvalidZipDownloadHint -LiteralPath $zipPath
|
$zipHeaderBad = $true
|
||||||
throw "PATCH_ERR:ZIP:Download is not a valid ZIP (missing PK header). $hint"
|
$zipHeaderHint = Get-InvalidZipDownloadHint -LiteralPath $zipPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
$fs.Dispose()
|
$fs.Dispose()
|
||||||
}
|
}
|
||||||
|
if ($zipHeaderBad) {
|
||||||
|
Remove-DownloadedRepoZip -LiteralPath $zipPath
|
||||||
|
throw "PATCH_ERR:ZIP:Download is not a valid ZIP (missing PK header). $zipHeaderHint"
|
||||||
|
}
|
||||||
|
|
||||||
if (Test-Path -LiteralPath $stage) {
|
if (Test-Path -LiteralPath $stage) {
|
||||||
Remove-FileOrDirectoryViaCmd -LiteralPath $stage
|
Remove-FileOrDirectoryViaCmd -LiteralPath $stage
|
||||||
}
|
}
|
||||||
New-Item -ItemType Directory -Path $stage | Out-Null
|
New-Item -ItemType Directory -Path $stage | Out-Null
|
||||||
try {
|
try {
|
||||||
Expand-Archive -LiteralPath $zipPath -DestinationPath $stage -Force
|
try {
|
||||||
$dirs = @(Get-ChildItem -LiteralPath $stage -Directory)
|
Expand-Archive -LiteralPath $zipPath -DestinationPath $stage -Force
|
||||||
if ($dirs.Count -ne 1) {
|
$dirs = @(Get-ChildItem -LiteralPath $stage -Directory)
|
||||||
throw ('PATCH_ERR:ZIP:Expected one root folder in archive, found {0}.' -f $dirs.Count)
|
if ($dirs.Count -ne 1) {
|
||||||
|
throw ('PATCH_ERR:ZIP:Expected one root folder in archive, found {0}.' -f $dirs.Count)
|
||||||
|
}
|
||||||
|
Copy-Item -Path (Join-Path $dirs[0].FullName '*') -Destination $PWD.Path -Recurse -Force
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (Test-Path -LiteralPath $zipPath) {
|
||||||
|
Remove-DownloadedRepoZip -LiteralPath $zipPath
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Copy-Item -Path (Join-Path $dirs[0].FullName '*') -Destination $PWD.Path -Recurse -Force
|
|
||||||
Write-Host 'Removing downloaded archive (repo.zip)...'
|
|
||||||
Remove-DownloadedRepoZip -LiteralPath $zipPath
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (Test-Path -LiteralPath $stage) {
|
if (Test-Path -LiteralPath $stage) {
|
||||||
|
|
@ -558,13 +655,24 @@ function Invoke-SrpgPostApply {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Remove-StalePatchZipArtifactsInGameRoot {
|
||||||
|
param([Parameter(Mandatory = $true)][string]$Root)
|
||||||
|
if (-not (Test-Path -LiteralPath $Root)) { return }
|
||||||
|
Get-ChildItem -LiteralPath $Root -Filter 'dazedmtl_patch_*.zip' -File -ErrorAction SilentlyContinue |
|
||||||
|
ForEach-Object {
|
||||||
|
Remove-FileOrDirectoryViaCmd -LiteralPath $_.FullName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Remove-PatchTempArtifacts {
|
function Remove-PatchTempArtifacts {
|
||||||
param([string]$Root)
|
param([string]$Root)
|
||||||
$zipPath = Join-Path $Root 'repo.zip'
|
$zipPath = Join-Path $Root 'repo.zip'
|
||||||
$legacyTmp = Join-Path $Root '_patch_extract_tmp'
|
$legacyTmp = Join-Path $Root '_patch_extract_tmp'
|
||||||
|
|
||||||
|
Remove-StalePatchZipArtifactsInGameRoot -Root $Root
|
||||||
|
|
||||||
if (Test-Path -LiteralPath $zipPath) {
|
if (Test-Path -LiteralPath $zipPath) {
|
||||||
Write-Host ' Removing repo.zip - large files can sit here for minutes if antivirus is scanning.'
|
Write-Host ' Removing repo.zip...'
|
||||||
Remove-FileOrDirectoryViaCmd -LiteralPath $zipPath
|
Remove-FileOrDirectoryViaCmd -LiteralPath $zipPath
|
||||||
}
|
}
|
||||||
if (Test-Path -LiteralPath $legacyTmp) {
|
if (Test-Path -LiteralPath $legacyTmp) {
|
||||||
|
|
@ -582,7 +690,7 @@ try {
|
||||||
|
|
||||||
Write-AsciiHeader
|
Write-AsciiHeader
|
||||||
|
|
||||||
Write-Host "Root: $GameRoot"
|
Remove-StalePatchZipArtifactsInGameRoot -Root $GameRoot
|
||||||
|
|
||||||
$configPath = Join-Path $PatchBundleRoot 'patch-config.txt'
|
$configPath = Join-Path $PatchBundleRoot 'patch-config.txt'
|
||||||
if (-not (Test-Path -LiteralPath $configPath)) {
|
if (-not (Test-Path -LiteralPath $configPath)) {
|
||||||
|
|
@ -610,7 +718,6 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host ('Pulling patch from https://gitgud.io/{0}/{1} (branch: {2})' -f $cfg.username, $cfg.repo, $cfg.branch)
|
Write-Host ('Pulling patch from https://gitgud.io/{0}/{1} (branch: {2})' -f $cfg.username, $cfg.repo, $cfg.branch)
|
||||||
Write-Host ''
|
|
||||||
|
|
||||||
Invoke-SrpgPreSetup -Root $GameRoot
|
Invoke-SrpgPreSetup -Root $GameRoot
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue