Files
brass-and-sigil/server/Program.cs
T
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

53 lines
1.7 KiB
C#

using BrassAndSigil.Server.Commands;
using Spectre.Console;
using Spectre.Console.Cli;
// Detect interactive double-click on Windows so we can hold the console open at exit
// (otherwise the window vanishes before the user can read errors).
var interactive = !Console.IsInputRedirected && OperatingSystem.IsWindows();
var app = new CommandApp<RunCommand>();
app.Configure(config =>
{
config.SetApplicationName("brass-sigil-server");
config.SetApplicationVersion("0.1.0");
config.AddCommand<InstallCommand>("install")
.WithDescription("Force a fresh setup: download mods + run the NeoForge installer.");
config.AddCommand<SyncCommand>("sync")
.WithDescription("Update mods to match the current manifest. Server should be stopped first.");
config.AddCommand<RunCommand>("run")
.WithDescription("Run the server daemon (auto-installs anything missing, then serves the web UI).")
.WithAlias("start");
config.AddCommand<CheckCommand>("check")
.WithDescription("Verify install: dependencies, EULA, manifest reachability.");
config.AddCommand<SetPasswordCommand>("set-password")
.WithDescription("Set or rotate the web panel admin password.");
});
int result;
try
{
result = await app.RunAsync(args);
}
catch (Exception ex)
{
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
result = 1;
}
// Hold the console open at exit only when an error occurred during interactive use.
// Successful daemon termination (Ctrl+C, /api/server/stop) closes cleanly.
if (interactive && result != 0)
{
AnsiConsole.MarkupLine("");
AnsiConsole.MarkupLine("[grey]Press any key to close...[/]");
Console.ReadKey(intercept: true);
}
return result;