Skip to content

Server architecture processes and projects

rebaserHEAD edited this page Oct 14, 2026 · 1 revision

reference, committed verified 2026-10-14 stable a4e75b18

The server's processes, their ports, databases and broker queues, how they're configured and started, and how the 44 projects in the solution are layered. How it all fits together is on Server architecture.

Processes

What runs

As declared by the Aspire host:

Aspire name Project Listens on Databases Broker queue Also needs
sts-server StsServer TCP 6600 Auth
auth-server AuthServer TCP 23115 Auth
world-server WorldServer TCP 24000, HTTP 5000 Auth, Character, World WorldServer_1 Tables, maps, scripts, Realm:RealmId
character-api API.Character HTTP 4000 Auth, Character
account-api API.Account HTTP 4001 Auth
chat-server Server.ChatServer Chat ChatServer Character API, tables
group-server Server.GroupServer Group GroupServer Character API
friendship-server Server.Friendship Friendship FriendshipServer Account API, Character API, tables
character-server Server.Character Query CharacterServer Character API
database-migrations Aspire.Database.Migrations All seven Runs once: migrations, a starter account, the world database import

Under Aspire, the three game ports bind to 127.0.0.1 on stable and to every interface upstream. The HTTP ports bind to localhost.

Start order

  1. The MySQL and RabbitMQ containers.
  2. database-migrations, to completion.
  3. Every server and API. The broker-only servers also wait for the Character API, and friendship-server for the Account API too. character-server waits for its database and the Character API, but not for the migrations.

Configuration

Each process reads <Name>.json from its own folder, then environment variables, which win. The Aspire host sets these per process:

Key Set from
Network:Host, Network:Port The host's TCP endpoint for that server
Database:<Name>:ConnectionString, Database:<Name>:Provider The MySQL container's database for that name
Network:Internal:Broker, Network:Internal:ConnectionString, Network:Internal:InputQueue The RabbitMQ container, and the queue in the table above
API:<Name>:Host The Character or Account API's address
Realm:RealmId 1, for the world server
urls The HTTP endpoint, for anything with a web host

Everything else, such as table and map paths, still comes from the JSON file.

Projects

Layers

Each layer depends only on the layers above it.

Layer Projects Holds
Leaves Game.Static, Shared, IO, Cryptography, Network.Sts Enums and flags; configuration and the world thread; file readers; SRP6; STS messages
Wire Network, Network.World, Network.Auth, Network.Internal Sessions, framing and the opcode list; client message models; auth messages; broker message contracts
Data GameTable, Database, Database.Auth, Database.Character, Database.World, Database.Chat, Database.Group, Database.Friendship, Database.Query Game table readers and row models; database contexts, models and migrations
Contracts Game.Abstract An interface for every game system
Script engine Script Compiling, loading, watching and binding scripts
Logic Game The implementations, one folder per system
Hosts WorldServer, AuthServer, StsServer, Server.*, API.* Composition, message handlers, GM commands
Content Script.Main, Script.Instance, Script.Alizar, Script.Olyssia, Script.Arcterra, Script.Farside, Script.Isigrol Content scripts
Tools MapGenerator, ClientConnector, Aspire.AppHost, Aspire.Database.Migrations Table and map extraction, client launching, orchestration, migrations

All project names start with NexusForever..

Where a question lands

Question Look in
What does this client packet look like? Source/NexusForever.Network.World/Message/Model/<Feature>/
What's its opcode? Source/NexusForever.Network/Message/GameMessageOpcode.cs
Who handles it? Source/NexusForever.WorldServer/Network/Message/Handler/
What crosses the broker? Source/NexusForever.Network.Internal/Message/, handled in Source/NexusForever.WorldServer/Network/Internal/Handler/ or the owning Server.* project
What is this enum value? Source/NexusForever.Game.Static/
What does this game table row hold? Source/NexusForever.GameTable/Model/
How does this system behave? Source/NexusForever.Game/<System>/, with its interface in Source/NexusForever.Game.Abstract/
What does this GM command do? Source/NexusForever.WorldServer/Command/
What's in this database table? Source/NexusForever.Database.<Name>/Model/, with migrations beside it

Stack

Piece Version
.NET and C# .NET 10, C# 14
Aspire hosting 13.4.6
EF Core 10.0.10, on Microting.EntityFrameworkCore.MySql 10.0.9
Rebus 8.9.2, with RabbitMQ or Azure Service Bus transports
Quartz 3.18.2
NLog 6.1.4
Nexus.Archive 1.0.1, for the client's index and archive files

Package versions are pinned centrally in Source/Directory.Packages.props. The solution has no test project.

Where the code lives

Piece Path
The deployment Source/NexusForever.Aspire.AppHost/Program.cs
How the host sets each process's keys Source/NexusForever.Aspire.AppHost/ResourceBuilderExtensions.cs
The solution Source/NexusForever.slnx
Package versions Source/Directory.Packages.props
Example configs Source/NexusForever.<Project>/<Name>.example.json

Clone this wiki locally