2025archived

Chronos

Unreal Engine 5.4 · C++ · Steam OnlineSubsystem · C# · WPF · MVVM

Overview

A game and its self-updating launcher, built back to back in one four-day sprint.

Chronos is a game and its launcher, two repos built as one product. The game: a third-person multiplayer project in Unreal Engine 5.4 where two players meet in a Steam lobby and seamless-travel into a hand-built terrain map. The launcher: a WPF app that keeps itself current on every machine it lands on, checking a version manifest and installing its own updates.

Both halves went up in the same four-day stretch of February 2025, the game across three days and the launcher on the fourth. The idea was distribution: edit the game, share the launcher, and everyone holding it gets the newest version. Unreal's multiplayer workflows and the install-and-update lifecycle each got learned once, properly, so neither has to be improvised later.

How does the game's multiplayer work?

A Steam lobby and a seamless hop. Hosting and joining run through the MultiplayerSessions plugin, which follows Stephen Ulibarri's course design, with a session subsystem handling create, find, join and destroy around the Steam online subsystem. The travel logic is deliberately tiny: the lobby game mode counts players in PostLogin, and at two it switches on seamless travel and moves everyone to HighRollers, a hand-built terrain map with a 537 KB heightmap and dozens of meshes sculpted in the editor's modeling tools. The game module is 229 lines of C++; Lumen, virtual shadow maps and World Partition carry the look.

How do you build that in three days?

One system per day, and the commit log reads as the curriculum: character and movement, then sessions and seamless travel, then the HighRollers map, then animations. The sprint's last commit landed at 3:27 AM, named "Animations?", question mark included. Focus does the rest: 14 C++ files for the game, everything heavy living in the engine where it is already solved.

Why does a learning project ship with a launcher?

Because the plan was distribution, and distribution means updates: edit the game, share one launcher, and every copy pulls the newest version on its own. So the launcher landed the day after the game's last commit, the whole app in a single commit: a .NET 8 WPF application with hand-rolled MVVM, custom window chrome, themed views and zero NuGet packages.

How does the launcher update itself?

A running app can't overwrite its own installed files, so the launcher hands that job to its own installer: it compares the installed version.txt against the manifest on the web host, and on a difference it downloads the newest MSI and setup over HTTPS into %TEMP% and runs the setup. The installer side is a Visual Studio setup project: an x64 MSI into Program Files under the ChronosLTD name, desktop and Start Menu shortcuts, a .NET runtime check, and previous versions upgraded automatically.

Field notes

  • 14 C++ files, 784 lines in the game; the travel trigger is one PostLogin check that moves the lobby to HighRollers at two players.
  • 7 commits across the three-day game sprint, February 9-11, 2025; the last one, "Animations?", landed at 3:27 AM.
  • HighRollers is hand-built in the editor: a 537 KB heightmap, modeling-tool meshes under _GENERATED/, World Partition with 179 external actors, Lumen and virtual shadow maps on top.
  • 416 assets, 7 maps, and a session subsystem with custom multicast delegates, LAN fallback and match-type filtering around the Steam online subsystem.
  • Launcher: 15 C# files, 567 lines, plus 784 lines of XAML; zero NuGet packages, MVVM hand-rolled down to a 16-line ObservableObject.
  • The entire launcher landed in one commit: 50 files, February 12, 2025, the day after the game's last commit.
  • Update chain: version.txt manifest compared over HTTPS, the launcher's own MSI and setup downloaded into %TEMP%, the setup executed. A running app delegates the overwrite to its own installer.
  • Installer: an x64 MSI into Program Files\ChronosLTD with desktop and Start Menu shortcuts, a .NET runtime launch condition, and automatic upgrade of previous versions.

Source

github.com/notdezzi/ChronosV2