Repository navigation
Repository layout
What's in the repository today: the files at its root, every project and what it depends on, the tests and the CI workflow. The server core's first stage, the pregame server, is built; its systems are on Host, Gateway, Owners, Persistence, Command layer and Harness, the codec on Codec, and the rest of the design on Server core design.
| File | Holds |
|---|---|
global.json |
The SDK pin, 10.0.400 with rollForward: latestPatch, and Microsoft Testing Platform as the test runner |
Directory.Build.props |
Nullable reference types on for every project; every warning an error; code-style rules run in the build; the analysis level pinned to 10-recommended
|
Directory.Build.targets |
The hot-path switch: a project that sets <HotPath>true</HotPath> gets the banned-API list and the hot-path rules as errors |
Directory.Packages.props |
Every package version, pinned exactly (central package management) |
nuget.config |
nuget.org as the only package source, mapped for every package |
.config/dotnet-tools.json |
The dotnet-ef tool, pinned, for writing migrations |
.editorconfig |
Formatting, style and naming rules, and every suppression with its reason |
.gitattributes |
* text=auto eol=crlf: text stored with LF, checked out with CRLF on every system |
.git-blame-ignore-revs |
Mechanical commits git blame skips: the line-ending normalization, the formatting pass, the renames to the code standard, and the wire models' neutral rename |
README.md, CONTRIBUTING.md, SECURITY.md, LICENSE
|
The front door, the contributor rules, how to report a security problem, the AGPL-3.0 |
| Folder | Holds |
|---|---|
Source/ |
Every project a server is built from, and the solution Source/NexusTomorrow.slnx
|
Tests/ |
One test project per project under test, and two that support them, NexusTomorrow.Testing and NexusTomorrow.Harness
|
Tools/ |
Tools for the repository itself: the protocol reference generator |
Build/HotPath/ |
The hot-path ban list (BannedSymbols.txt) and the rules it raises to errors (HotPath.globalconfig) |
.github/workflows/ |
The Tests workflow |
Every library targets net10.0, except the generator, which targets netstandard2.0 because the compiler loads it.
| Project | Holds | References | Nullable |
|---|---|---|---|
NexusTomorrow.Shared |
Factories, configuration binding, the update timer, shared extensions | On | |
NexusTomorrow.Cryptography |
SRP6 for the server and for headless clients, RC4, password and random helpers | On | |
NexusTomorrow.IO |
Readers for the client's area files; reader and writer for the server's map format, .nfmap
|
On | |
NexusTomorrow.Game.Static |
The game's enums and flags, one folder per system | On | |
NexusTomorrow.GameTable |
Typed loading of the client's game tables (.tbl) and text tables |
Game.Static, Shared
|
On |
NexusTomorrow.Network.Codec |
The bit reader and writer, the declaration attributes, the layout types and the layout tree with its text form, and the client facts table. Hot path | On | |
NexusTomorrow.Network.Codec.Generator |
The source generator that writes each declared type's reader, writer and layout, and its diagnostics NTC001 to NTC013
|
On | |
NexusTomorrow.Network |
The opcode list, exactly the client's 1,119 wire opcodes; the [WireMessage] attribute, and [Verified] with its Rung; the three messages both the auth and world servers use, ServerHello (0x0003), ClientEnvelope (0x0244) and NestedMessage (0x025C); NetworkGuid; and the network configuration |
Network.Codec, Shared; the generator |
On |
NexusTomorrow.Network.Sts |
Message models for the STS login protocol, in XML | On | |
NexusTomorrow.Network.Auth |
Message declarations for the auth server; the generated reader and writer are their only code |
Game.Static, Network; the generator |
On |
NexusTomorrow.Network.World |
Message declarations for the world server; the generated reader and writer are their only code |
Game.Static, Network; the generator |
On |
NexusTomorrow.Transport |
Frames, envelopes, the transport ping's opcodes and the packet cipher. Hot path | Network.Codec |
On |
NexusTomorrow.Gateway |
The three client listeners and their connections, sign-on, login and world; the message catalog, the opcode table and the decoder; rate and connection limits |
Transport, Network, Network.Auth, Network.World, Network.Sts, Cryptography, Owners, Persistence; ASP.NET Core |
On |
NexusTomorrow.Owners |
The owner base and its watchdog, and the account and realm owners |
GameTable, Network.Codec, Network, Network.Auth, Network.World, Persistence
|
On |
NexusTomorrow.Persistence |
The account, realm and ops schemas and their migrations, the write-behind queue, character id blocks and the account directory |
On | |
NexusTomorrow.Commands |
The command dispatcher, permissions, the audit, and the account and server commands, listed once for the server to register |
Cryptography, Owners, Persistence
|
On |
Every project builds with the analysers on, nullable reference types on and every warning as an error, and none opts out of any of them. Network, Network.Auth and Network.World run the generator, which writes each model's reader, writer and size, and one WireMessages registry per assembly with a factory per direction keyed by opcode. Nothing else in the tree reads or writes a message: the gateway reads and writes through those registries. The three also write their XML documentation, which the verification check reads.
| Project | Does | References |
|---|---|---|
NexusTomorrow.Server |
The one process: composition, settings checks, start-up and shutdown, the migrate verb and the console. Running a server has how to run it |
Gateway, Owners, Persistence, Commands; ASP.NET Core |
| Project | Does | References |
|---|---|---|
NexusTomorrow.MapGenerator |
Extracts the game tables and localization files from your client, and generates .nfmap map files from its area files |
GameTable, IO, Shared
|
NexusTomorrow.ClientConnector |
Starts your client with a server's address on its command line, from beside the client in its folder. Windows only | Shared |
How to run them is in the repository's README.md. Their output is built from your client and never goes in the repository.
One more sits under Tools/, since it serves the repository rather than a server:
| Project | Does | References |
|---|---|---|
NexusTomorrow.ProtocolReference |
Generates this wiki's reference pages: the message reference, an index by opcode and a page per area, from the declarations' generated registries and their XML documentation; the opcode table from the gateway's; and the commands from the server's command list. It reads no client files |
Network, Network.Auth, Network.World, Gateway, Commands
|
| Package | Used by |
|---|---|
Microsoft.Extensions.* (configuration, dependency injection, logging, options) |
Shared, Network, GameTable, MapGenerator, Owners, Persistence, Commands, the tests |
Microsoft.EntityFrameworkCore (with .Relational and .Design), Npgsql.EntityFrameworkCore.PostgreSQL, EFCore.NamingConventions
|
Persistence, and the test support library for its test databases |
Microsoft.Extensions.TimeProvider.Testing |
The harness and the tests that move a fake clock |
Microsoft.CodeAnalysis.CSharp, Microsoft.CodeAnalysis.Analyzers
|
The generator and its tests |
Microsoft.CodeAnalysis.BannedApiAnalyzers |
Every hot-path project, added by Directory.Build.targets
|
NLog |
Shared |
Newtonsoft.Json |
GameTable, ClientConnector
|
CommandLineParser |
MapGenerator |
Nexus.Archive |
MapGenerator, to read the client's archives |
xunit.v3.mtp-v2, Microsoft.Testing.Extensions.TrxReport
|
The tests |
| Project | Tests |
|---|---|
NexusTomorrow.Network.Codec.Tests |
The bit reader and writer against hand-derived bytes; strings and packed floats; generated code on test messages of every member shape; the facts check over every message Network, Network.Auth and Network.World declare, with each disagreement pinned; the verification check, which holds every declared message to its rung and the documentation it requires, with every message below Fields pinned; and the split gate, which fails a message at Fields that splits a value the client reads whole |
NexusTomorrow.Network.Codec.Generator.Tests |
Every diagnostic, and the source the generator emits |
NexusTomorrow.Cryptography.Tests |
The SRP6 session key is always 64 bytes; the client and server sides agree on the key and both proofs, and refuse a wrong password or a wrong server proof; RC4 against its published vector, in one go or in pieces |
NexusTomorrow.GameTable.Tests |
A missing or empty GameTablePath fails options validation, and a bound one passes |
NexusTomorrow.ClientConnector.Tests |
Reading the configuration throws, naming the key, when the host name or language is missing or empty, and returns both when they're set; the configuration is saved to and read from the given folder, never the current one; the 64-bit client is preferred when both are there |
NexusTomorrow.ProtocolReference.Tests |
The pages on test messages against hand-written pages; an unverified message shown as layout only; the index in opcode order; areas taken from the model folders, a world message outside an area refused; pages written as UTF-8 without a byte order mark, with LF line ends; a message page the set no longer has turned into a tombstone, an existing tombstone left byte for byte whatever its line ends, and a retired name that comes back written as a real page; the opcode table page, each row linked to its message and stopped by a row no client message declares, with every priority and action named; the commands page in name order with secrets marked and help listed once; and the walk, which turns every declared message into its page rows and requires them to reproduce its generated layout tree |
NexusTomorrow.Transport.Tests |
The packet cipher against known values, and its zero allocation; frames read whole, a byte at a time and two at once, and their length limits; envelopes and pings written and read |
NexusTomorrow.Gateway.Tests |
The catalog, the gate and the rate gate; login and connection limits; sign-on's reader, writer and state machine, unknown accounts, and nothing secret ever logged; the login and world connections, key switching, the outbound queue and disconnect grace |
NexusTomorrow.Owners.Tests |
The owner base and the watchdog; the account owner's tokens, session keys, suspensions and second logins; the realm owner's character-select rules, names and creation options |
NexusTomorrow.Persistence.Tests |
Migrations on an empty database; emails and live names unique in any case; the write-behind queue's order, retries and refusals; account and character work; id blocks; the account directory |
NexusTomorrow.Commands.Tests |
The dispatcher's checks, outcomes and audit, with secrets kept out; the line splitter; usage lines, which mark a secret only when asked; the account and server commands, and the list the server registers |
NexusTomorrow.Server.Tests |
Start-up refusals, listening and an orderly stop, the connection limit, settings checks that name a key never its value, migrate, the console and the watchdog service |
NexusTomorrow.Harness.Tests |
The pregame scenarios, on the harness |
747 tests in all, in 13 xUnit v3 test applications on Microsoft Testing Platform: 240 in the codec's, 132 in the gateway's, 88 in the owners', 64 in the generator's, 53 in the command layer's, 48 in the server's, 40 in persistence's, 28 in the transport's, 23 in the protocol reference's, 14 harness scenarios, and 17 in the other three. The facts check and the verification check, among the codec's tests, and the protocol reference's walk each cover every declared message. The database tests and the scenarios need PostgreSQL 18, as Running the tests says.
.github/workflows/test.yml, named Tests:
| Step | Does |
|---|---|
| Trigger |
workflow_dispatch only, with an optional args input passed to the test applications |
| Runner | ubuntu-24.04 |
| Permissions | contents: read |
| Checkout | Full history, so the commit check can see every commit since main; the token isn't kept in the checkout |
| Commit messages | Every commit in origin/main..HEAD: a blank second line, a headline of 72 characters or fewer, no full stop at its end |
| Em dashes | Fails on any em dash in a .cs or .md file, and lists where |
| Method words | Fails on any word in a .cs or .md file, other than CONTRIBUTING.md, that says how a client fact was found, and lists where |
| Set up .NET | Installs the SDK global.json asks for: the latest 10.0.4xx patch |
| Restore, build | Against Source/NexusTomorrow.slnx, in Debug |
| Format |
dotnet format Source/NexusTomorrow.slnx --verify-no-changes, after the build, because it loads the codec's generator from the build output |
| PostgreSQL | A postgres:18 service beside the job; a role that can create databases is made with a random password, and logins switch to passwords only |
| Test | Every test application, with a .trx report; the database tests and scenarios run against the service and fail rather than skip |
| Upload results | The test-results artifact, uploaded even when tests fail |
Every action is pinned to a full commit. Running the tests shows how to dispatch it.
- Every message, nested type and field carries a neutral name built from its opcode and position (
Client009A,Unknown0) until it's checked against the client. Pregame, world entry, movement and logout have been, and their messages carry the names the check gave them. The verification check pins the 1,066 messages not yet read to their fields as unverified. - Each world message sits in the folder of the client feature it serves, under
Message/Model/inNetwork.World: 49 areas, with structs used across areas inShared/. A message whose area isn't confirmed yet sits provisionally in the area of its old folder, or inUnsettled/when there's none, 127 of them. Pregame's also use theNetworkandNetwork.Authmodel folders. - The facts check pins 43 disagreements with the client's full layouts, each with its reason. The message audit settles them as it checks each feature area.
-
MapGeneratorandClientConnectorboth work against a real client since the nullable work changed how they read their settings.ClientConnectorsits in the client's folder and finds the client and itsconfig.jsonthere, whatever folder it's started from. - Permissions beyond the console's and the GM command definitions aren't here yet; roles and in-game commands come after the first stage.
- Selecting a character can't enter the world until the map side is built.
| Piece | Path |
|---|---|
| The solution | Source/NexusTomorrow.slnx |
| Projects | Source/NexusTomorrow.*/ |
| The codec | Source/NexusTomorrow.Network.Codec/ |
| The generator | Source/NexusTomorrow.Network.Codec.Generator/ |
| The client facts table | Source/NexusTomorrow.Network.Codec/Facts/wire-facts-16042.jsonl |
| The protocol reference generator | Tools/NexusTomorrow.ProtocolReference/ |
| The server and its default settings | Source/NexusTomorrow.Server/ |
| Test support |
Tests/NexusTomorrow.Testing/, Tests/NexusTomorrow.Harness/
|
The dotnet-ef tool pin |
.config/dotnet-tools.json |
| The hot-path switch and list |
Directory.Build.targets, Build/HotPath/
|
| Tests | Tests/NexusTomorrow.*.Tests/ |
| Package versions | Directory.Packages.props |
| The workflow | .github/workflows/test.yml |
Start here
How the server works
- Server core design
- Host
- Gateway
- Owners
- Persistence
- Command layer
- Harness
- Map scheduler design
- Timer wheel design
The protocol
Working on it