A turn-based tactical RPG in the style of Dofus, written from scratch: a Godot 4 C# client for Windows, macOS and Linux, rules shared with an ASP.NET Core server for accounts and characters, a launcher in Rust.
In progressSprint S45-S60+S64-S219 · 728 points
In short, no jargonfor non-developersRead the summaryClose
What it is
A turn-based combat video game on a board seen at an angle, like Dofus: you create your character, walk around a town and talk to its people.
What it is for
A real game to download, with its installer, player accounts and a server, built to grow: monsters, landscapes, then multiplayer.
What it shows
Running a large video game project, from its rules to its distribution, in C# and Rust.
The launcher (Rust, Tauri) signs the player in, compares the installed game with the server's manifest (size and SHA-256 of every file), downloads only what changed, resumes a cut download, checks every file, then starts the game with the token.
The desktop game (Godot 4, C#) only draws: login screen, village, fight. Everything a click can do lives in Rpg.Client, a library without an engine tested with xUnit, which the game replays itself in the CI (self-tests).
Rpg.Core holds the rules and the data (spells, classes, monsters, maps, village, dialogues): the same library serves the game, the server and the simulator, so a recorded fight replays identically everywhere, on all three systems.
The server (ASP.NET Core) handles accounts and characters (JWT, hashed passwords, rate limit, EF Core and PostgreSQL), checks every request with the rules of Rpg.Core, and serves the game's files to the launcher.
Rpg.Sim, the command-line simulator, has the AI play thousands of times: it is what balanced the classes and the monsters.
A look at the fight
The desktop client, in Godot 4 and C#: a diamond board seen at an angle, animated characters (Kenney's free 3D models), and the rules of sprint 45, without a single extra rule in the client.
A 36-second video, without sound, recorded by the game itself: a training fight where the AI also plays the heroine. She walks up to the orc and the poacher and strikes them up close; hit points drop above their heads, the log on the left tells every blow, and she wins narrowly in round six, with 6 HP out of 60.The launcher (Rust, Tauri): it updates the game by itself when it opens, file by file; "Sign in" starts the game; the name and the password can be remembered (the password in the system's credential store). Windows, macOS and Linux packages made by the CI, unsigned.After the launcher, as in the games of the genre: the server choice (straight through while there is only one, Osméria), then the characters as cards (portrait, class, level), up to five per account. Accounts and characters live on the server (ASP.NET Core, PostgreSQL).Creating one's character: class (with its twenty spells, by level), woman or man then one of six looks, outfit, hair and skin colours, height and build, on Kenney's free models; each swatch shows the colour it will give this model. The server checks every value.The welcome town: you walk with a click, talk to three inhabitants (dialogues with choices, described in data), the east gate leads to a training fight, the west road to Clairval Woods; the server keeps where the character stands.A level-3 zone, twice the size of the village: the camera follows the player, zooms with the wheel and turns a quarter with Q and E; the green ring leads to the next zone, and the server keeps the zone and the cell one stands on.The world map (M key): each zone in its place, with its level, joined to its neighbours; the zones and their links are described in data and checked by the tests.The characteristics sheet: Vitality, Earth, Water, Fire, Air, each in its colour; the points put in and those of the equipment, what each total gives (10 points = +2 damage in the element, and nothing else); a value to type, MIN, MAX, and everything taken back at any time.Spells: the class's twenty-four, four per element and eight neutral, each with its icon on its element's colour, locked until their level; the card gives normal and critical damage with the character's characteristics and equipment, and what the next rank gives.Gearing up: the character surrounded by its fourteen slots, the inventory in tabs and a grid, a search; the icons are drawn by the game (the shape says the slot, the colour the characteristic). A sample inventory of a level-10 guard; in the game, the server keeps what each fight leaves.Moving: the reachable cells, the path, and the deck of twelve spells in two rows (keys 1 to 6 and Ctrl+1 to 6).Aiming: the spell's range, the line of sight, the target and the damage to expect, critical hits included; at the top, the timeline of the next turns.
Pictures taken by the game itself (option --screenshot), in a virtual screen, with Mesa's software OpenGL renderer.
Spell icons: game-icons.net, under the CC BY 3.0 licence, by Lorc, Delapouite and Sbed (background removed, set on the element's colour).
To run it at home (.NET 10 SDK and Godot 4.7 .NET):
cd projects/rpg
dotnet run --project src/Rpg.Sim -- --simulate 100 --lang en # AI fights, in the terminal
docker compose up --build rpg-api # the accounts and characters server, on port 8002
dotnet build godot/Rpg.Godot.csproj
godot --path godot -- --lang en # the game ("Play offline" without a server)
Ready-to-run builds (Windows, macOS, Linux, unsigned), made by the CI, which plays a whole fight in them, kept 14 days: artifacts of the rpg workflow
Tech stack
Godot 4
C#
.NET
ASP.NET Core
EF Core
PostgreSQL
JWT
Rust
Tauri
xUnit
Docker
Who does what
Godot 4
The desktop client: isometric maps, combat, character creation, town and NPCs, exported for Windows, Linux and macOS by CI.
C#
The game rules (grid, action and movement points, line of sight, spells, AI) in a deterministic library, shared by the client and the server.
.NET
The common platform of the client, the rules and the server.
ASP.NET Core
The accounts and characters server, which validates every character created.
EF Core
Database access and its migrations.
PostgreSQL
Accounts, characters and their progress.
JWT
The login tokens, shared by the launcher and the game.
Rust
The launcher: login, checking and downloading only the changed files.
Tauri
The launcher's interface and its packages for the three systems.
xUnit
Tests of the rules (paths, line of sight, replayed fights) and of the server, on a real PostgreSQL database.
Docker
The server and its database, started by docker compose.
Definition of Done
Code reviewed, diff by diff
Unit and integration tests green
Green CI on Linux, Windows and macOS when compiled