Table of Contents

FishMMO — Introduction

FishMMO is a multiplayer online game framework built on Unity, FishNet, and a custom WebTransport (QUIC/HTTP3) networking stack. It provides a complete server-authoritative MMO architecture with:

  • Client: Unity-based game client with launcher, auto-updater, and WebTransport networking
  • Login Server: SRP-6a zero-knowledge password authentication with TOTP two-factor auth
  • World Server: Player management, world state, and cross-scene coordination
  • Scene Server: Per-zone/scene gameplay logic and entity simulation. Hosts any number of scene instances — multiple instances of one open-world scene are channels, and instanced content (dungeons) is a private instance per character or party. A scene server is not owned by a world server; it pulls from one global pending-scene queue and may host scenes for several at once.
  • Web Servers: IPFetch (server discovery), Patcher (auto-update), WebGL (browser client hosting)
  • Database: PostgreSQL via Entity Framework Core with Npgsql provider and pgBouncer connection pooling
  • Reverse Proxy: NGINX with L4 UDP stream forwarding for game traffic and L7 HTTPS for API/WebGL

Architecture

See the Connection Pipeline for the complete end-to-end connection flow from client launch through authentication to gameplay.

Key Design Decisions

Decision Rationale
WebTransport (QUIC) for all platforms Unified transport; no TCP fallback, no WebSocket shim
NGINX L4 UDP stream proxy Zero-copy packet forwarding; no TLS termination at proxy
Each game server terminates its own TLS End-to-end encrypted; NGINX never sees plaintext game data
SRP-6a + X25519 ECDH Zero-knowledge password proof; forward secrecy for session keys
HMAC-signed auth tokens Stateless World/Scene server auth; no LoginServer dependency after login
No server-to-server character handover Every scene transfer releases the character, routes the client back through the World server, and re-claims it at the destination. One code path for teleports, channel switches, dungeon entry and reconnects — and a database-backed session claim, rather than trust between servers, decides who owns a character
Scene instances identified by database row, not process handle A scene-manager handle is only unique inside the process that allocated it, so it cannot name an instance across servers
Server lifecycle controlled through the database, not the process locked and shutdown_at_utc on the world and scene server rows are the authority; each process reads its own row back on every heartbeat and adopts it. One in-game /admin command therefore reaches servers the player is not connected to, and any other tool that can write those rows controls the servers identically

Repository Structure

  • FishMMO-Unity/ — Unity project (client + server game code)
  • FishMMO-Auth/ — Shared authentication library (SRP, token, crypto)
  • FishMMO-Database/ — Database layer (EF Core + Npgsql entities and services)
  • FishMMO-WebTransport/ — C++ msquic wrapper for QUIC/WebTransport
  • FishMMO-WebServers/ — ASP.NET Core web servers (IPFetch, Patcher, WebGL)
  • FishMMO-Setup/ — Deployment configuration (nginx, systemd, config files)
  • FishMMO-SharedUtility/ — Cross-cutting utility library
  • FishMMO-Dependencies/ — NuGet package aggregation for Unity compatibility