Skip to content

Repository files navigation

Avalon.Server

.NET CI Pipeline

Official server-side solution for the Avalon ARPG: API, authentication, world simulation, networking, persistence, telemetry, and extensibility frameworks.

High-Level Overview

Avalon is split into bounded components that can scale and evolve independently:

  • Public REST API (account + meta operations)
  • Real‑time Auth server (login / token / world selection)
  • Real‑time World server (simulation, state replication, gameplay logic)
  • Shared foundational libraries (domain model, networking, value objects, metrics, configuration)
  • Infrastructure services (Redis, Postgres)
  • Tooling (migrations, benchmarking, scripting, migration console)

Communication paths:

  • Clients → API (HTTPS + JWT) for out‑of‑band operations (account, web UX, management)
  • Game Client → Auth Server (custom TCP packet protocol) for authentication & world ticket exchange
  • Auth Server ↔ Redis (session, ephemeral keys, pub/sub)
  • World Server ↔ Redis (cross‑node coordination, session/materialized view, pub/sub)
  • World Server ↔ Databases (persistent character/world state)
  • API ↔ Databases (account + world metadata) & Redis (caching, notifications)

Solution Structure (Key Projects)

Server layer:

Project Role
src/Server/Avalon Aspire host for all server components
src/Server/Avalon.Api ASP.NET Core REST API; OpenAPI generation; JWT issuance; JSON serialization
src/Server/Avalon.Server.Auth Hosted service wrapping AuthServer (packet dispatcher, login flow, MFA)
src/Server/Avalon.Server.World Hosted service running the simulation loop (maps, entities, spells, spawning)
src/Server/Avalon.World Core world implementation (maps, grid, entities, spells, sessions, connections)
src/Server/Avalon.World.Public Public abstractions (interfaces) consumed by other layers
src/Server/Avalon.World.Scripts / .Abstractions Scripting system boundary for gameplay extensions
src/Server/Avalon.Infrastructure Redis replicated cache, MFA hashing, config binding, helper services
src/Server/Avalon.Database.* EF Core contexts and repositories (Auth, Character, World) + migrations
src/Server/Avalon.Hosting Uniform host bootstrap (AvalonHostBuilder): converters, telemetry, configuration
src/Server/Avalon.ServiceDefaults Shared service registration (logging, OpenTelemetry, resiliency, service discovery)
src/Server/Avalon.PluginFramework Foundation for dynamic plugin loading (future roadmap)

Shared libraries:

Project Role
src/Shared/Avalon.Common ValueObject<T>, common utilities, JSON converters
src/Shared/Avalon.Domain Rich domain model (Auth, Accounts, Devices, Worlds, etc.)
src/Shared/Avalon.Configuration Strongly typed configuration objects
src/Shared/Avalon.Network.* Custom packet protocol, attributes, base handlers, contracts
src/Shared/Avalon.Metrics OpenTelemetry integration points

Tooling & Tests:

Project Role
tools/Avalon.Benchmarking Micro-benchmarks for performance-sensitive components
tests/Avalon.Shared.UnitTests Unit tests for shared libraries
tests/Avalon.Server.Auth.UnitTests Unit tests for authentication server components
tests/Avalon.Server.World.UnitTests Unit tests for world server and simulation logic
tests/Avalon.Api.UnitTests Unit tests for the REST API

Core Cross-Cutting Concepts

Value Objects

ValueObject<TValue> in Avalon.Common wraps primitives like AccountId and WorldId for strong typing. They serialize to their underlying primitive via custom System.Text.Json converters and appear as scalars in OpenAPI through a custom schema transformer. See → ValueObject — OpenAPI Integration

OpenAPI & Scalar UI

The API exposes an interactive Scalar UI at /scalar and raw schema at /openapi/v1.json, built on Microsoft.AspNetCore.OpenApi. A custom schema transformer produces clean scalar definitions for value object types. See → ValueObject — OpenAPI Integration

Authentication & Security

JWT issuance and validation, MFA (Otp.NET) with Redis-backed ephemeral secrets, BCrypt password hashing, refresh tokens, and session tracking in AuthDb. See → Security — Session Management

Networking

Custom TCP layer (Avalon.Network.Tcp) with Protobuf-net serialization and reflection-based packet handler registration. Auth and World servers share packet abstractions via Avalon.Network.Packets. See → Networking — Packet Protocol

Caching & Pub/Sub

Redis (via IReplicatedCache) manages ephemeral session keys, MFA secrets, world exchange tokens, and cross-service pub/sub events. See → Redis Cache Keys

Persistence

Postgres via Npgsql EF Core with three distinct DbContexts (AuthDbContext, CharacterDbContext, WorldDbContext) for separation of concerns and independent scaling. Design-time factories enable dotnet ef without a running host.

Telemetry & Logging

Serilog for structured logging; OpenTelemetry instrumentation covers HTTP, EF Core, Redis, and runtime metrics. See → Configuration Reference

World Simulation

WorldServer hosted service runs the tick loop at ~60 Hz. Each MapInstance manages entities, spell queues, creature AI, and state broadcast. See → Spell System · Creature System · Architecture — Startup Flow

Scripting & Extensibility

Avalon.World.Scripts.Abstractions isolates contracts for externally defined gameplay logic. Future dynamic loading planned via PluginFramework.

Running Locally

Prerequisites: .NET 10 SDK, Docker (for infra services).

  1. Start infra (Redis + PostgreSQL):
    docker compose up -d
    Optionally add Redis Insight for a GUI over Redis:
    docker compose -f docker-compose.yml -f docker-compose.tools.yml up -d
  2. Run the API — migrations are applied automatically on startup:
    dotnet run --project src/Server/Avalon.Api
  3. Run Auth Server:
    dotnet run --project src/Server/Avalon.Server.Auth
  4. Run World Server:
    dotnet run --project src/Server/Avalon.Server.World
  5. Open API docs: https://localhost:<port>/scalar (Scalar UI) or /openapi/v1.json

Migrations Workflow

Note: During early development, Avalon.Api is used as the EF design-time startup project and applies migrations automatically on startup. Migration generation and execution will be decoupled as the project matures.

Generate a migration:

dotnet ef migrations add <Name> \
  --project src/Server/Avalon.Database.Auth \
  --startup-project src/Server/Avalon.Api \
  --context AuthDbContext

Replace Auth / AuthDbContext with Character / CharacterDbContext or World / WorldDbContext as needed.

Testing

dotnet test

Run a specific project: dotnet test tests/Avalon.Server.Auth.UnitTests

Benchmarking

dotnet run -c Release --project tools/Avalon.Benchmarking

Use to regress-check simulation hot paths.

Feature Documentation

Document Description
Networking — Packet Protocol Header fields, auth lifecycle, world handoff, Redis patterns, failure modes
Networking — Graceful Shutdown Connection lifecycle, SDisconnectPacket schema, shutdown sequences
Security — Session Management Auth flow, world key CSPRNG, bearer token validation, duplicate session guard
Architecture — Startup Flow Bootstrap sequence for API, Auth Server, and World Server
Map Generation Chunk authoring, town + procedural pipelines, end-to-end Unity → bake → playable, troubleshooting
Instanced Map System Instance lifecycle: town routing, normal map re-entry, expiry, transitions, logout
ValueObject — OpenAPI Integration Schema transformer pattern, registration, and shape transformation
Configuration Reference All appsettings.json keys, validation rules, environment override guidance
Redis Cache Keys All Redis key patterns and pub/sub channels: purpose, TTL, writer/consumer
Spell System Spell lifecycle, power cost deduction, AoE targeting, creature spell support
Creature System Creature lifecycle, AI scripting, XP rewards, respawn/remove timers
Character Login Flow World-select → spawn sequence, inventory on login, instance ID design
Architecture Decisions ADRs: World/Auth DB decoupling, chat command handler pattern, specializations

For the full list of pending work items see TODO.md.

Roadmap

  • Plugin hot-reload & isolation boundaries
  • Horizontal world shard scaling (multi-process coordination via Redis pub/sub)
  • Observability dashboards (Grafana / Prometheus integration)
  • More test coverage (property-based / fuzzing for packet protocol)
  • Rate limiting & advanced DDoS mitigation

License

MIT (see repository root). Some vendor components (DotRecast, Raylib bindings) under their respective licenses.

Contributing

See CONTRIBUTING.md for setup, extension patterns, and PR guidelines.

Releases

Packages

Used by

Contributors

Languages