From e1268e7cceeca1d3821c7ec86b96ac4c7cfc3e53 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Tue, 14 Apr 2026 11:13:03 +0200 Subject: [PATCH] launcher: document build, run, and placeholder key in readme --- README.md | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 404b602..e853415 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,88 @@ # metin-launcher -Self-updating launcher for the Metin2 client (dev repo) \ No newline at end of file +Self-updating launcher for the Metin2 client. + +This is the single entry point the player runs. It fetches a signed manifest from +`updates.jakubkadlec.dev`, verifies an Ed25519 signature against a compiled-in +public key, reconciles the local client against the manifest by sha256, downloads +anything that differs from a content-addressed blob store (with HTTP Range resume), +applies updates atomically, hands launcher self-update off to Velopack, and then +starts `Metin2.exe`. If the update server is unreachable the launcher falls back +to launching whatever the player already has. + +Architecture and failure modes live in the client repo under +`docs/update-manager.md` and `docs/update-manifest.md`. This project implements +those specs in C# .NET 8; it does not own the spec. + +## Build + +``` +dotnet build Launcher.sln -c Release +dotnet test +``` + +Tests are xUnit and run on Linux. A local `HttpListener` stands in for the blob +server in `BlobDownloaderTests`. + +## Publish (Windows single-file) + +``` +dotnet publish src/Metin2Launcher/Metin2Launcher.csproj \ + -c Release -r win-x64 --self-contained \ + -p:PublishSingleFile=true +``` + +The CI hasn't been wired yet; the MVP only requires the build to succeed. + +## Run + +Drop `Metin2Launcher.exe` next to `Metin2.exe` in the client install directory +and run it. On first launch it will: + +1. fetch `https://updates.jakubkadlec.dev/manifest.json` + `.sig` +2. verify the signature against the compiled-in public key +3. hash every file listed in the manifest, download anything that doesn't match + into `.updates/staging/`, then atomically move each one into place +4. check for a Velopack launcher update against the feed at + `https://updates.jakubkadlec.dev/launcher` (skipped cleanly on non-installed + dev builds) +5. start `Metin2.exe` + +A log is written to both stdout and `/.updates/launcher.log`. On a plain +`dotnet run` (no client root yet), the log falls back to +`%LOCALAPPDATA%/Metin2Launcher/launcher.log` on Windows or +`$XDG_DATA_HOME/Metin2Launcher/launcher.log` on Linux. + +## Project layout + +``` +src/Metin2Launcher/ + Program.cs orchestration + Velopack bootstrap + game launch + Config/LauncherConfig.cs hardcoded URLs, timeouts, public key + Manifest/ DTOs, HTTP loader, Ed25519 verifier + Transfer/ streaming sha256, Range-resume blob downloader + Apply/ atomic staging -> final move + GameLaunch/ CreateProcess wrapper + Logging/ hand-rolled file + stdout logger +tests/Metin2Launcher.Tests/ +``` + +## Dependencies + +- **NSec.Cryptography** — libsodium-backed Ed25519 (.NET 8 BCL does not have it). +- **Velopack** — launcher self-update. Only used for the launcher binary itself; + game assets (~4 GB) are handled by our own patcher code. +- **xunit / xunit.runner.visualstudio** — tests. + +## PLACEHOLDER public key + +`LauncherConfig.PublicKeyHex` currently contains a **test-only** Ed25519 public +key generated locally during MVP scaffolding: + +``` +a8619c11348cb26cdcad9467c5dd44e3fcb40017e9fbcf225ac76ad824422c46 +``` + +This MUST be replaced with the real production signing key before the first +public release. The private half of this placeholder was used only to prove +signature wiring works; it is not tied to any real release.