Files
Matt Sijbers a1331212cb Initial commit: Brass & Sigil monorepo
Self-hosted Minecraft modpack distribution + administration system.

- launcher/  Avalonia 12 desktop client; single-file win-x64 publish.
             Microsoft auth via XboxAuthNet, manifest+SHA-1 mod sync,
             portable install path, sidecar settings.
- server/    brass-sigil-server daemon (.NET 8, linux-x64). Wraps the
             MC subprocess, embedded Kestrel admin panel with cookie
             auth + rate limiting, RCON bridge, scheduled backups,
             BlueMap CLI integration with player markers + skin proxy,
             friend-side whitelist request flow, world wipe with seed
             selection (keep current / random / custom).
- pack/      pack.lock.json (Modrinth + manual CurseForge entries),
             data-only tweak source under tweaks/, build outputs in
             overrides/ (gitignored).
- scripts/   Build-Pack / Build-Tweaks / Update-Pack / Check-Updates
             plus Deploy-Brass.ps1 unified one-shot deploy with
             version-bump pre-flight and daemon-state detection.
2026-05-05 00:19:05 +01:00

99 lines
3.7 KiB
PowerShell

#requires -Version 5
# One-shot helper: produces a multi-resolution icon.ico from icon.png.
# Run only when the source icon changes; commit the resulting icon.ico.
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName PresentationCore
Add-Type -AssemblyName WindowsBase
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$srcPath = Join-Path $here 'icon.png'
$icoPath = Join-Path $here 'icon.ico'
if (-not (Test-Path $srcPath)) { throw "icon.png not found at $srcPath" }
# Detect if the file is actually a different format renamed to .png (e.g. WebP from AI tools).
# If so, transcode via WPF's WIC pipeline to a real PNG before feeding GDI+.
$head = [System.IO.File]::ReadAllBytes($srcPath)[0..3]
$isPng = $head[0] -eq 0x89 -and $head[1] -eq 0x50 -and $head[2] -eq 0x4E -and $head[3] -eq 0x47
if (-not $isPng) {
Write-Host "Source file is not a PNG (likely WebP from AI tool). Transcoding via WIC..."
$bytes = [System.IO.File]::ReadAllBytes($srcPath)
$stream = New-Object System.IO.MemoryStream(,$bytes)
$decoder = [System.Windows.Media.Imaging.BitmapDecoder]::Create(
$stream,
[System.Windows.Media.Imaging.BitmapCreateOptions]::PreservePixelFormat,
[System.Windows.Media.Imaging.BitmapCacheOption]::OnLoad)
$frame = $decoder.Frames[0]
# Force BGRA32 so GDI+ can later handle it cleanly with alpha
$converted = New-Object System.Windows.Media.Imaging.FormatConvertedBitmap(
$frame,
[System.Windows.Media.PixelFormats]::Bgra32,
$null,
0)
$encoder = New-Object System.Windows.Media.Imaging.PngBitmapEncoder
$encoder.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($converted))
$outStream = New-Object System.IO.MemoryStream
$encoder.Save($outStream)
[System.IO.File]::WriteAllBytes($srcPath, $outStream.ToArray())
$outStream.Dispose()
$stream.Dispose()
Write-Host "Transcoded to real PNG ($($outStream.Length) bytes)."
}
$sizes = 16, 32, 48, 64, 128, 256
$src = [System.Drawing.Image]::FromFile($srcPath)
$frames = @{}
foreach ($size in $sizes) {
$bmp = New-Object System.Drawing.Bitmap $size, $size, ([System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
$g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
$g.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
$g.DrawImage($src, 0, 0, $size, $size)
$g.Dispose()
$ms = New-Object System.IO.MemoryStream
$bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
$frames[$size] = $ms.ToArray()
$bmp.Dispose()
$ms.Dispose()
}
$out = New-Object System.IO.MemoryStream
$bw = New-Object System.IO.BinaryWriter($out)
# ICONDIR header
$bw.Write([UInt16]0)
$bw.Write([UInt16]1)
$bw.Write([UInt16]$sizes.Count)
$dataOffset = 6 + (16 * $sizes.Count)
foreach ($size in $sizes) {
$bytes = $frames[$size]
$w = if ($size -ge 256) { [byte]0 } else { [byte]$size }
$h = if ($size -ge 256) { [byte]0 } else { [byte]$size }
$bw.Write([byte]$w)
$bw.Write([byte]$h)
$bw.Write([byte]0)
$bw.Write([byte]0)
$bw.Write([UInt16]1)
$bw.Write([UInt16]32)
$bw.Write([UInt32]$bytes.Length)
$bw.Write([UInt32]$dataOffset)
$dataOffset += $bytes.Length
}
foreach ($size in $sizes) {
$bw.Write($frames[$size])
}
[System.IO.File]::WriteAllBytes($icoPath, $out.ToArray())
$bw.Dispose()
$out.Dispose()
$src.Dispose()
"Wrote: $icoPath ($((Get-Item $icoPath).Length) bytes, $($sizes.Count) sizes)"