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.
This commit is contained in:
Matt Sijbers
2026-05-05 00:19:05 +01:00
commit a1331212cb
99 changed files with 12640 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace ModpackLauncher.Services;
public static class SystemInfo
{
private const long DefaultFallbackKB = 8L * 1024 * 1024; // assume 8 GB if detection fails
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetPhysicallyInstalledSystemMemory(out long memoryInKilobytes);
/// <summary>Total physically installed system RAM in megabytes.</summary>
public static int TotalPhysicalMemoryMB
{
get
{
try
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (GetPhysicallyInstalledSystemMemory(out var kb))
return (int)(kb / 1024);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// Read MemTotal from /proc/meminfo
foreach (var line in File.ReadAllLines("/proc/meminfo"))
{
if (line.StartsWith("MemTotal:", StringComparison.Ordinal))
{
var parts = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length >= 2 && long.TryParse(parts[1], out var memKb))
return (int)(memKb / 1024);
}
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// GC heap-size hint; not perfect but a reasonable fallback for macOS.
var gcInfo = GC.GetGCMemoryInfo();
if (gcInfo.TotalAvailableMemoryBytes > 0)
return (int)(gcInfo.TotalAvailableMemoryBytes / (1024 * 1024));
}
}
catch
{
// Fall through to default
}
return (int)(DefaultFallbackKB / 1024);
}
}
/// <summary>Recommended max user-allocatable RAM (leaves headroom for OS + other apps).</summary>
public static int SafeMaxAllocationMB
{
get
{
var total = TotalPhysicalMemoryMB;
// Leave at least 4 GB for OS + browser + Discord + everything else.
var headroom = total >= 32 * 1024 ? 6 * 1024 : 4 * 1024;
return Math.Max(2048, total - headroom);
}
}
}