update manager — design #2

Closed
opened 2026-04-14 10:37:12 +02:00 by jann · 0 comments
Member

Assignment

Design an update manager for the Metin2 client.

Decisions baked into the design

  • A) Single entry point: player runs Metin2Launcher.exe, it owns update + launch.
  • B) Publishing: manual make-release.sh in v1, move to Gitea Actions in v2 once the flow is proven.
  • C) Base install is large (~4.3 GB), shipped out-of-band; the update channel only carries patches and the launcher itself.
  • D) Release cadence: potentially daily, which is why the storage layer is content-addressed so unchanged files are not re-downloaded.

Proposed architecture

  • Server: static files under updates.jakubkadlec.dev/, served by the existing Caddy on the VPS. Content-addressed blobs at files/<hash[0:2]>/<hash>, current manifest at manifest.json, detached Ed25519 signature at manifest.json.sig.
  • Manifest: JSON with per-file sha256, sortable version string YYYY.MM.DD-N, launcher called out separately.
  • Launcher: small C# .NET 8 single-file exe. Fetches manifest, verifies signature against compiled-in public key, downloads missing / changed blobs with HTTP Range resume, atomic move into place via MoveFileEx, self-updates via rename-before-replace, launches Metin2.exe. Offline fallback: if server is unreachable, launch the game with whatever is local.
  • Trust: Ed25519 keypair, private key on release machine only, public key compiled into the launcher. Key rotation via overlap-period launcher releases.

Deliverables in the PR

See PR #2 (to be linked) for:

  • docs/update-manager.md — full design (21 KB)
  • docs/update-manifest.md — manifest schema + canonical JSON rules
  • docs/examples/manifest-example.json — small synthetic example
  • scripts/make-manifest.py — working manifest generator, excludes runtime noise, tested against our current client folder (54k files, ~3.3 GB)

The design doc has a full implementation plan table (~10 working days to MVP) and a failure-modes table.

Not in this PR

  • The launcher itself (next PR, claude/update-launcher)
  • make-release.sh (follows the launcher)
  • Caddy config for updates.jakubkadlec.dev (operator task, separate issue)
  • Signing key generation / key custody runbook (security task, separate issue)

Open questions I left for the team

  • Launcher UI scope (bare progress bar vs. richer news/changelog)
  • Launcher localization (ship own locale vs. reuse game's locale.pck)
  • Optional analytics (off by default, opt-in)

Happy to adjust any of this before implementing the launcher. Review welcome.

## Assignment Design an update manager for the Metin2 client. ## Decisions baked into the design - **A) Single entry point:** player runs `Metin2Launcher.exe`, it owns update + launch. - **B) Publishing:** manual `make-release.sh` in v1, move to Gitea Actions in v2 once the flow is proven. - **C) Base install is large** (~4.3 GB), shipped out-of-band; the update channel only carries patches and the launcher itself. - **D) Release cadence:** potentially daily, which is why the storage layer is content-addressed so unchanged files are not re-downloaded. ## Proposed architecture - **Server:** static files under `updates.jakubkadlec.dev/`, served by the existing Caddy on the VPS. Content-addressed blobs at `files/<hash[0:2]>/<hash>`, current manifest at `manifest.json`, detached Ed25519 signature at `manifest.json.sig`. - **Manifest:** JSON with per-file sha256, sortable version string `YYYY.MM.DD-N`, launcher called out separately. - **Launcher:** small C# .NET 8 single-file exe. Fetches manifest, verifies signature against compiled-in public key, downloads missing / changed blobs with HTTP Range resume, atomic move into place via `MoveFileEx`, self-updates via rename-before-replace, launches `Metin2.exe`. Offline fallback: if server is unreachable, launch the game with whatever is local. - **Trust:** Ed25519 keypair, private key on release machine only, public key compiled into the launcher. Key rotation via overlap-period launcher releases. ## Deliverables in the PR See PR #2 (to be linked) for: - `docs/update-manager.md` — full design (21 KB) - `docs/update-manifest.md` — manifest schema + canonical JSON rules - `docs/examples/manifest-example.json` — small synthetic example - `scripts/make-manifest.py` — working manifest generator, excludes runtime noise, tested against our current client folder (54k files, ~3.3 GB) The design doc has a full implementation plan table (~10 working days to MVP) and a failure-modes table. ## Not in this PR - The launcher itself (next PR, `claude/update-launcher`) - `make-release.sh` (follows the launcher) - Caddy config for `updates.jakubkadlec.dev` (operator task, separate issue) - Signing key generation / key custody runbook (security task, separate issue) ## Open questions I left for the team - Launcher UI scope (bare progress bar vs. richer news/changelog) - Launcher localization (ship own locale vs. reuse game's `locale.pck`) - Optional analytics (off by default, opt-in) Happy to adjust any of this before implementing the launcher. Review welcome.
jakub closed this issue 2026-04-14 11:54:43 +02:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: metin-server/m2dev-client#2