C# port of DistrictServer (DistrictServerCSharp/) — full reimplementation, status + verification
This issue documents a complete C# (.NET 8) reimplementation of DistrictServer.cpp (~14k lines → ~40 modular service files) that has been developed in parallel with the C++ tree. It is informational / a proposal for discussion — the C++ DistrictServer/ remains the protocol oracle and the rollback path.
What it is
A wire-identical port of the C++ district server, structured by responsibility (modern C# idioms, no global mutable state):
Handshake/ — AUTH/USES/WELCOME/JOIN/ANS, channel-sequencing, binary NMT control
WorldControl/ — world registration + character handoffs
Core/ — reliable TX queue + retry/ACK, transport-state tracking, packet diagnostics
Gri/, Streaming/, SpawnZone/ — GRI match-start, level-streaming plan, spawn-zone markers/selection
Pawn/ — ACK-gated pawn bootstrap + possession, remote-pawn multiplayer + dead-peer lifecycle
Packages/ — cooked-package net-index resolver (parses cooked .u packages directly)
Controller/ — controller field decoding, customisation replicator request dispatch
Protocol/, Bits/, Crypto/, Net/ — UE3 wire layer, bit primitives, XTEA/BTEA, UDP listener
Port status (drift-gated)
Tools/check_port_sync.py inventories every C++ function and asserts it has a C# home:
- DistrictServer.cpp: 175 functions — 175 mapped / 0 not-ported / 0 unmapped (complete)
- ApbUdp.cpp wire layer covered by a file map; the only intentionally-unported items are dead
Unreal.cpp (not in the C++ build, zero callers) and 3 zero-caller raw-float helpers
Verification
dotnet build -c Release — 0 warnings / 0 errors
--selftest — byte-identical wire output vs the C++ self-test vectors
--drive (two-player) — full join path: AUTH → WELCOME → JOIN → 371 spawn-zone → district-enter answer → pawn-open → all 8 ACK-gated possession stages, remote pawns on both viewers, and the customisation transfer driven to ClientNotifyTransferComplete
--resolver-check — parses a real cooked APBGame.u and reproduces the live C++ net indices exactly (controller 12426, holdable 15985→47088, storage 25478→56581)
Tools/check_port_sync.py (default + --all) and Tools/check_deploy_sync.py — both green
Deploy state
The C# port is currently the deployed live district server in the local stack (Social 6969 / Financial 6970 / Waterfront 6971, world control 2108; win-x64 apphost, sha 526e3d64…, boot 2026-08-17 13:31). It is not yet committed to git — the DistrictServerCSharp/ tree is untracked, so nothing here is a merge request yet.
What is NOT yet proven
- A live-client smoke test: the deployed C# port has not yet been validated end-to-end against the real 1.1 client (all current verification is in-process/simulated). This is the last open verification gap.
Proposed path to a PR (for discussion)
- Commit
DistrictServerCSharp/ (+ the Tools/check_port_sync.py / check_deploy_sync.py gates) to a feature branch on the fork with incremental, reviewable history.
- Run a live-client smoke test against the deployed C# port and capture the milestones.
- Open a PR with the full diff + verification summary, keeping the C++ tree as the oracle for review.
Happy to restructure, split into smaller PRs, or adjust the architecture based on maintainer feedback before anything is merged.
C# port of DistrictServer (
DistrictServerCSharp/) — full reimplementation, status + verificationThis issue documents a complete C# (.NET 8) reimplementation of
DistrictServer.cpp(~14k lines → ~40 modular service files) that has been developed in parallel with the C++ tree. It is informational / a proposal for discussion — the C++DistrictServer/remains the protocol oracle and the rollback path.What it is
A wire-identical port of the C++ district server, structured by responsibility (modern C# idioms, no global mutable state):
Handshake/— AUTH/USES/WELCOME/JOIN/ANS, channel-sequencing, binary NMT controlWorldControl/— world registration + character handoffsCore/— reliable TX queue + retry/ACK, transport-state tracking, packet diagnosticsGri/,Streaming/,SpawnZone/— GRI match-start, level-streaming plan, spawn-zone markers/selectionPawn/— ACK-gated pawn bootstrap + possession, remote-pawn multiplayer + dead-peer lifecyclePackages/— cooked-package net-index resolver (parses cooked .u packages directly)Controller/— controller field decoding, customisation replicator request dispatchProtocol/,Bits/,Crypto/,Net/— UE3 wire layer, bit primitives, XTEA/BTEA, UDP listenerPort status (drift-gated)
Tools/check_port_sync.pyinventories every C++ function and asserts it has a C# home:Unreal.cpp(not in the C++ build, zero callers) and 3 zero-caller raw-float helpersVerification
dotnet build -c Release— 0 warnings / 0 errors--selftest— byte-identical wire output vs the C++ self-test vectors--drive(two-player) — full join path: AUTH → WELCOME → JOIN → 371 spawn-zone → district-enter answer → pawn-open → all 8 ACK-gated possession stages, remote pawns on both viewers, and the customisation transfer driven toClientNotifyTransferComplete--resolver-check— parses a real cookedAPBGame.uand reproduces the live C++ net indices exactly (controller 12426, holdable 15985→47088, storage 25478→56581)Tools/check_port_sync.py(default +--all) andTools/check_deploy_sync.py— both greenDeploy state
The C# port is currently the deployed live district server in the local stack (Social 6969 / Financial 6970 / Waterfront 6971, world control 2108; win-x64 apphost, sha
526e3d64…, boot 2026-08-17 13:31). It is not yet committed to git — theDistrictServerCSharp/tree is untracked, so nothing here is a merge request yet.What is NOT yet proven
Proposed path to a PR (for discussion)
DistrictServerCSharp/(+ theTools/check_port_sync.py/check_deploy_sync.pygates) to a feature branch on the fork with incremental, reviewable history.Happy to restructure, split into smaller PRs, or adjust the architecture based on maintainer feedback before anything is merged.