Project

Catan

Full-stack digital Settlers of Catan: one C# rules engine driving Blazor WebAssembly, MAUI Hybrid, and a SignalR multiplayer server, with dual SVG and Three.js boards.

2026Coming soon

A from-scratch digital adaptation of Settlers of Catan, built as an end-to-end .NET 10 solution. It runs as a Blazor WebAssembly web app, a MAUI Blazor Hybrid desktop/mobile app (Windows, macOS, Android, iOS), and a standalone ASP.NET Core multiplayer server — all sharing a single rules engine and UI component library.

Catan 3D board renderer

Architecture

The codebase is structured as eight projects with strict layering:

  • A transport- and UI-agnostic GameCore library that owns all game rules — board generation, turn state machine, building/trade/robber/development-card managers, victory calculator
  • A shared protocol layer of typed commands and events
  • A Razor component library consumed by both the WebAssembly host and the MAUI WebView host
  • A thin SignalR server that acts as a pure transport — every inbound message is unwrapped by a hub filter and dispatched through MediatR to handlers that live alongside the rules engine
Catan architecture overview

Dual board renderers

The board is rendered two ways:

  • A 2D SVG implementation for fast first paint and accessibility
  • A full Three.js scene (~2k+ lines of JS across ~20 modular renderers — tiles, props, harbors, robber, pieces, highlights, animations, camera) interop'd from Blazor for a 3D view with seeded procedural terrain, hit-testing, and animated state changes

Game state is JSON-serialized through custom converters for hex coordinates, vertex/edge IDs, resource bundles, and polymorphic buildings, and survives round-trips between server, clients, and persisted snapshots.

Real-time multiplayer

A single /hubs/catan SignalR endpoint with an envelope protocol — typed commands (CreateLobbyCommand, RollDiceCommand, ProposeTradeCommand, etc.) and events (DiceRolled, BuildingPlaced, TradeProposed, …) are deserialized by a hub filter, routed via MediatR to handlers, and rebroadcast to lobby/game groups managed by dedicated group services.

The same handler infrastructure runs in-process inside the MAUI host for offline single-device "hot-seat" play with no server required.

Composition and testing

Cross-cutting concerns are wired with Autofac modules (GameModule, ClientModule, UIModule, ServerModule) so each host composes only the services it needs. The test project covers ~52 files of unit, integration, and end-to-end tests — including SignalR end-to-end tests that exercise the real hub, real MediatR pipeline, and real serialization stack.

Highlights

  • One rules engine, five hosts. The same GameCore assembly drives single-player MAUI, hot-seat play, WebAssembly multiplayer, the SignalR server, and tests.
  • Transport-agnostic protocol. Commands and events are plain C# records dispatched by MediatR; SignalR is a thin envelope on top, so the rules engine doesn't know it's networked.
  • Dual renderers. A 2D SVG board and a modular Three.js scene (camera controller, animation manager, hit-target builder, mesh factories, prop factory, etc.) share the same hex-coordinate math.
  • Hot-seat and online from the same code path. The MAUI build skips the server entirely and runs the multiplayer service in-process for local pass-and-play.

Tech stack

  • .NET 10, C# 13 — strict-null, signed assemblies
  • Blazor WebAssembly + MAUI Blazor Hybrid (Windows / macOS / Android / iOS / Web)
  • ASP.NET Core + SignalR (Newtonsoft.Json protocol, custom envelope hub filter)
  • MediatR for command/event dispatch shared across in-process and networked play
  • Autofac for modular DI across five hosts
  • Three.js for 3D board rendering, SVG for 2D fallback, JS interop from Blazor
  • xUnit for unit / integration / end-to-end test layers
  • .NET 10
  • C# 13
  • Blazor WebAssembly
  • MAUI Blazor Hybrid
  • ASP.NET Core
  • SignalR
  • MediatR
  • Autofac
  • Three.js
  • SVG
  • xUnit