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

285 lines
8.9 KiB
HTML

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Brass &amp; Sigil Launcher -- Matt Sijbers</title>
<meta name="description" content="A private custom Minecraft Java Edition launcher for the Brass & Sigil modpack -- built in C# / .NET 8 / Avalonia." />
<link rel="icon" href="/images/favicon-light.ico" media="(prefers-color-scheme: light)" type="image/x-icon" />
<link rel="icon" href="/images/favicon-dark.ico" media="(prefers-color-scheme: dark)" type="image/x-icon" />
<link rel="stylesheet" href="css/matt.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" />
<style>
html, body {
background: var(--color-primary-darker-10);
overflow: auto;
height: auto;
min-height: 100vh;
max-height: none;
}
.page-wrap {
max-width: 900px;
margin: 0 auto;
padding: clamp(20px, 5vw, 60px) clamp(16px, 5vw, 32px) 80px;
}
.back-link {
display: inline-flex;
align-items: center;
gap: 8px;
margin-bottom: 24px;
font-size: 0.95em;
}
.hero {
padding: clamp(20px, 4vw, 36px);
margin-bottom: 24px;
}
.hero h1 {
font-size: clamp(1.6em, 6vw, 2.6em);
text-transform: uppercase;
margin: 0 0 8px;
}
.hero .subtitle {
color: var(--color-secondary-text);
font-size: clamp(0.9em, 3vw, 1.1em);
margin: 0;
}
.tag-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 18px;
}
.tag {
background: var(--color-primary-darker-20);
color: var(--color-primary-text);
padding: 6px 12px;
border-radius: 999px;
font-size: 0.85em;
font-weight: 500;
}
.action-row {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 22px;
}
.action-btn {
display: inline-flex;
align-items: center;
gap: 8px;
background: var(--color-accent);
color: #fff !important;
padding: 10px 18px;
border-radius: 8px;
font-weight: 600;
font-size: 0.95em;
text-decoration: none;
transition: background 0.15s linear, transform 0.1s linear;
}
.action-btn:hover {
background: var(--color-accent-lighter-10);
transform: translateY(-1px);
}
.action-btn.secondary {
background: var(--color-primary-darker-20);
color: var(--color-primary-text) !important;
}
.action-btn.secondary:hover {
background: var(--color-primary-darker-30);
}
.whitelist-note {
margin: 18px 0 0;
padding: 10px 14px;
background: var(--color-primary-darker-10);
border-left: 3px solid var(--color-accent);
border-radius: 6px;
color: var(--color-secondary-text);
font-size: 0.9em;
line-height: 1.45;
}
.whitelist-note i { color: var(--color-accent); margin-right: 6px; }
.section {
padding: clamp(18px, 3.5vw, 28px);
margin-bottom: 18px;
}
.section h2 {
margin-top: 0;
margin-bottom: 12px;
}
.section p {
line-height: 1.55;
color: var(--color-primary-text);
}
.facts {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
margin-top: 8px;
}
.fact {
background: var(--color-primary-darker-10);
border-radius: 12px;
padding: 14px 18px;
}
.fact .label {
font-size: 0.78em;
color: var(--color-secondary-text);
text-transform: uppercase;
letter-spacing: 0.05em;
margin: 0 0 4px;
}
.fact .value {
font-family: "Ubuntu", sans-serif;
font-weight: 500;
color: var(--color-primary-text);
margin: 0;
}
@media (max-width: 540px) {
.facts { grid-template-columns: 1fr; }
}
ul.feature-list {
padding-left: 1.25em;
margin: 4px 0 0;
}
ul.feature-list li {
color: var(--color-primary-text);
line-height: 1.5;
margin: 4px 0;
}
footer.page-footer {
color: var(--color-secondary-text);
font-size: 0.85em;
text-align: center;
margin-top: 40px;
}
</style>
</head>
<body>
<div class="page-wrap">
<a href="/matt#projects" class="back-link"><i class="fa fa-arrow-left"></i> Back to portfolio</a>
<div class="bevel hero">
<h1>Brass &amp; Sigil Launcher</h1>
<p class="subtitle">A private custom Minecraft Java Edition launcher for a small friend group.</p>
<div class="tag-row">
<span class="tag">C# / .NET 8</span>
<span class="tag">Avalonia</span>
<span class="tag">CmlLib.Core</span>
<span class="tag">Single-file Windows</span>
<span class="tag">Private project</span>
</div>
<div class="action-row">
<a class="action-btn" href="/pack/BrassAndSigil-Launcher.exe">
<i class="fa fa-download"></i> Download launcher
</a>
<a class="action-btn secondary" href="https://sijbers.uk:8443/projects/BS/repos/brass-and-sigil-launcher/browse"
target="_blank" rel="noopener noreferrer">
<i class="fa fa-code"></i> View source code
</a>
<a class="action-btn secondary" href="/matt#projects">
<i class="fa fa-user"></i> Developer portfolio
</a>
</div>
<p class="whitelist-note">
<i class="fa fa-info-circle"></i>
You'll need to be whitelisted on the server to actually join &mdash; message Matt with your Minecraft username.
</p>
</div>
<div class="bevel section">
<h2>About the project</h2>
<p>
Brass &amp; Sigil is a private Minecraft modpack centred on the Create mod, aeronautics, tech and magic mods,
with Distant Horizons for far-render exploration. This launcher is the desktop client built specifically
to distribute the pack to a small friend group (under 50 players, no public release).
</p>
<p>
The launcher is a native Windows application written in C# on .NET 8, using the Avalonia UI framework.
It ships as a single self-contained executable so friends can just download and run it &mdash; no installer,
no .NET runtime to install, no separate config files.
</p>
</div>
<div class="bevel section">
<h2>What it does</h2>
<ul class="feature-list">
<li>Fetches a JSON manifest from a self-hosted server and syncs the modpack files (mods, configs, resourcepacks) to the player's local install directory, using SHA-1 hashing so only changed files are downloaded.</li>
<li>Authenticates the player with their own personal Microsoft account via the standard MSAL OAuth flow, so only legitimate Minecraft Java Edition owners can sign in.</li>
<li>Installs the right Minecraft version and Forge loader, then launches the game with the configured memory and the player's session.</li>
<li>Auto-updates the modpack on every launch when the manifest changes &mdash; players never have to manually install or update mods.</li>
</ul>
</div>
<div class="bevel section">
<h2>Technical details</h2>
<div class="facts">
<div class="fact">
<p class="label">Language</p>
<p class="value">C# (.NET 8)</p>
</div>
<div class="fact">
<p class="label">UI Framework</p>
<p class="value">Avalonia 12</p>
</div>
<div class="fact">
<p class="label">Minecraft auth</p>
<p class="value">CmlLib.Core.Auth.Microsoft</p>
</div>
<div class="fact">
<p class="label">Game launching</p>
<p class="value">CmlLib.Core 4.x + Forge installer</p>
</div>
<div class="fact">
<p class="label">Distribution</p>
<p class="value">Single-file self-contained .exe</p>
</div>
<div class="fact">
<p class="label">Audience</p>
<p class="value">Private friend group (&lt; 50)</p>
</div>
</div>
</div>
<div class="bevel section">
<h2>Privacy &amp; data</h2>
<p>
The launcher does not collect, store, or transmit any user data beyond what the standard Microsoft and
Minecraft authentication flows require. Auth tokens are cached locally on the player's machine via the
MSAL token cache &mdash; no telemetry, no analytics, no third-party services beyond Microsoft and Mojang.
</p>
<p>
The modpack manifest and mod files are served from a self-hosted Linux server that I personally operate.
</p>
</div>
<div class="bevel section">
<h2>Status</h2>
<p>
Active development. The launcher is functional end-to-end (manifest sync, Microsoft auth, Forge install,
game launch) and is currently being prepared for distribution to a small group of friends.
</p>
<p>
Source code is publicly available, MIT-licensed, on my self-hosted Bitbucket:
<a href="https://sijbers.uk:8443/projects/BS/repos/brass-and-sigil-launcher/browse"
target="_blank" rel="noopener noreferrer">sijbers.uk:8443/.../brass-and-sigil-launcher</a>.
</p>
</div>
<div class="bevel section" style="text-align: center; font-size: 0.85em;">
<p style="margin: 0; color: var(--color-secondary-text); letter-spacing: 0.04em;">
NOT AN OFFICIAL MINECRAFT PRODUCT. NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT.
</p>
</div>
<footer class="page-footer">
Brass &amp; Sigil Launcher &mdash; a private project by <a href="/matt">Matt Sijbers</a>.
</footer>
</div>
</body>
</html>