Repository navigation
Description
Problem
OloEngine's networking subsystem contains ~20 replication/prediction/interest/lag-comp classes and a working GameNetworkingSockets transport — all unit-tested in isolation — but they are never assembled into a running server-authoritative loop. The pieces exist; the game does not.
Verified dead seams (grep + read, 2026-07-11):
NetworkManager::TickSnapshots()has zero call sites.NetworkThread::ThreadFunc(NetworkThread.cpp:78) only runs GNS callbacks + named-thread tasks. The header comment claiming it "invokes TickSnapshots()" is false. The server-side capture+delta+broadcast never runs.NetworkManager::SetActiveScene()is never called in production.OloServer/src/OloServerApp.cpploads a scene and ticksOnUpdateRuntimeFixed, but never registers it with networking.s_ActiveSceneis always null, soTickSnapshotswould early-out anyway.SnapshotInterpolator::Interpolate(scene, dt)is called only from tests. Received snapshots pile into the buffer and are never applied to the client ECS — remote entities never move.- Prediction/reconciliation never fires end-to-end. No
InputApplyCallbackis registered in production; the server never sendsInputAck, soClientPrediction::Reconcileis dead. RPCis a bareENetworkMessageTypeenum value (NetworkMessage.h:21). No registry, marshalling, authority routing, or script bindings exist (RegisterRPC/InvokeRPC/RpcDispatcher= no matches anywhere).- Interest management is wired only into the separate MMO
ZoneServer, not the core loop —TickSnapshotsbroadcasts one shared delta to all clients with no per-connection baseline or relevance culling. LagCompensatoris never invoked by the input/hit path (ServerInputHandler::ProcessInputdoes no rewind).EntitySpawn/EntityDespawnare enum tokens with no lifecycle replication — snapshots assume a static entity set; server-spawned entities never appear on clients.
No open GitHub issue tracks this.
Why it matters
The engine advertises networking (dedicated OloServer target, MMO/lobby/P2P classes, Lua Network.* table) but cannot run a single authoritative multiplayer match. This is the highest-decay area in the codebase: a large, well-tested stack that produces nothing playable because the last-mile assembly and several keystone systems (RPC, spawn/despawn, interest-scoped replication, lag-comp integration) were never built. Bringing it to life turns a dead stack into the engine's flagship differentiator.
What EXISTS today
- Transport:
NetworkServer/NetworkClient/NetworkConnection(GNS), live-tested bytests/Networking/NetworkIntegrationTest.cpp. - Replication:
EntitySnapshot(Capture/CaptureDelta/Apply),ComponentReplicator,ComponentInterpolationRegistry,SnapshotBuffer,SnapshotInterpolator. - Prediction:
ClientPrediction,ServerInputHandler,NetworkInputBuffer. - Lag comp:
LagCompensator(rewind primitive). - Interest:
NetworkInterestManager,SpatialGrid,NetworkPriorityQueue,RelevanceTier. - Components:
NetworkIdentityComponent+ENetworkAuthority{Server,Client,Shared}(Components.h:3509),NetworkInterestComponent,NetworkLODComponent. - Facade:
NetworkManager(server capture+broadcast inTickSnapshots,SendInput, reconcile handlers inConnect). - Lua:
Network.isServer/connect/startServer/…(LuaScriptGlue.cpp:2385).
Proposed approach
- Core loop driver — drive
TickSnapshots()from the NetworkThread (or a dedicated fixed-rate replication tick); register the active scene viaSetActiveScene()fromOloServerAppand the editor host; driveSnapshotInterpolator::Interpolate()per client frame. - Authoritative ECS replication + entity lifecycle — replicate spawn/despawn (wire the existing tokens), server-UUID→client-entity mapping, authority-gated writes.
- Client prediction + reconciliation end-to-end — real
InputApplyCallback, per-tick input sampling, serverInputAck, replay-on-divergence. - Registered RPC system — typed marshalling over
FArchive, authority routing (Server/Client/Multicast/target), reliability, dispatch over theRPCmessage type. - RPC script bindings —
RegisterRPC/InvokeRPCin Lua (LuaScriptGlue.cpp) and C# (ScriptGlue.cpp). - Interest-scoped core replication — per-connection scoping via
NetworkInterestManager/SpatialGrid/RelevanceTier+ per-client delta baselines. - Lag compensation integration — rewind to the client's RTT-adjusted tick before authoritative hit checks, then restore.
- Dedicated-server integration —
OloServerAppregisters its scene, spawns/despawns a player entity per connection, drives the replication tick. - Playable 2-client demo + functional tests — a
SandboxProjectscene running the full loop, plusFunctional-axis convergence/authority/RPC/interest/lag-comp tests.
Acceptance criteria
-
TickSnapshots()is driven andSetActiveScene()is wired from bothOloServerAppand the editor host; a connected client's remote entities move viaSnapshotInterpolator::Interpolate(). - Server spawns/despawns replicate to clients with a stable server-UUID→client-entity mapping; client writes to server-authoritative entities are rejected.
- Client prediction + server
InputAck+ reconciliation converge end-to-end (replay of unacknowledged inputs on divergence). - A registered RPC system marshals typed args, routes by authority (Server/Client/Multicast/target), and selects reliability — no longer a bare enum.
- RPCs are callable from Lua and C# scripts.
- The core replication loop scopes snapshots per connection with per-client baselines and relevance culling (not one shared broadcast).
-
LagCompensatoris invoked from the server input/hit path (rewind → check → restore). -
OloServerruns the full authoritative loop: player-per-connection lifecycle + replication tick. - A playable 2-client demo scene exists under
SandboxProject, plusFunctionaltests asserting cross-client convergence, authority rejection under the live loop, RPC round-trips, interest culling, and lag-comp hit registration.
capability: 5
craft: 4
stability: 2
decay: 5
effort: 13
confidence: 0.92
learning: 4
fun: 5
kano: delighter
blocked_by: []
blocks: []
Activity
coderabbitai commentedon Jul 11, 2026
🔗 Related PRs
#162 - Feature/networking [closed]
#334 - MCP: per-worktree discovery-file isolation + skill auto-attach (
#316… [merged]#382 - feat(network): spatial-grid prefilter + relevance evaluation for NetworkInterestManager [merged]
#561 - fix(networking): correct prediction/reconciliation and state-lifecycle bugs [merged]
#743 - feat(networking): assemble the server-authoritative multiplayer loop (
#636) [open]🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
drsnuggles8 commentedon Aug 3, 2026
Implemented in #743.
Acceptance criteria — evidence
SetActiveScene()wired fromOloServerAppand the editor host; remote entities move viaInterpolate()NetworkManager::Tick(dt)is the single game-thread entry point, called fromOloServerApp,OloRuntimeAppandEditorLayer(which registers only the Play scene, neverm_EditorScene).ServerAuthoritativeLoopTest.ClientInputMovesItsPawnOnTheServerAndOnTheOtherClientasserts client 1 sees client 0's pawn move — which travels through the interpolator.EntityLifecycle+NetworkSpawnRegistry.EachConnectionGetsAPawnThatBothClientsSee,DisconnectDespawnsThePawnOnTheRemainingClient,ClientOnlyDestroysEntitiesTheSpawnPathCreated,ServerRejectsInputForAServerAuthoritativeEntity, plus 10EntityLifecycleTestcodec cases.InputAck+ reconciliation converge end-to-endPredictionAndReconciliationConvergeOnTheServerPosition— asserts convergence, not merely "it moved".RpcRegistry/RpcDispatcher; 12RpcMarshallingTestcases + 4 live-loop RPC tests.OloServerruns the demo'sNetwork.useMovementInputand bothNetwork.registerRPCcalls at startup. C# surface (OloEngine.Network) compiles intoOloEngine-ScriptCore.dll.SnapshotAck).InterestScopingWithholdsADistantEntityplus its controlInterestScopingDisabledReplicatesEverything.LagCompensatorinvoked from the server pathServerReplicationDriver::PerformLagCompensatedCheckrewinds by half-RTT plus the client's render delay.LagCompensationRewindsToWhereTheClientSawTheWorldasserts the check saw the past and that the world was restored.OloServerruns the full loopFunctionaltestsSandboxProject/Assets/Scenes/NetworkDemo.olo+NetworkDemoController.lua;ServerAuthoritativeLoopTeststands up a real server and two real clients over loopback (15 cases).Test totals: 37 new networking tests pass; a 580-test regression sweep across networking, replication, components, MMO, lockstep, P2P and persistence is green (1 unrelated skip).
Honest caveats
Pre-existing bugs surfaced
Three were in code that had never executed — which is the pathology this issue was about:
NetworkClient::PollMessagesdispatched handlers inside its own mutex, so any handler that replied self-deadlocked.NetworkServer::PollMessagesalready deferred dispatch outside the lock and documents why.GetClientPingMsre-acquires the mutexForEachConnectionholds. Three shipped call sites had that shape — including the editor's Network Debug panel, so opening it against a live server froze the editor.OloServermounted noProject, so scene-referenced Lua never resolved: the dedicated server could host a world but run none of its server-side gameplay.Lessons captured in
docs/agent-rules/server-authoritative-networking-loop.md(and anmspdbsrvbuild-infra note inbuild-trees-and-windows-asan.md).test(networking): guard the C# binding surface against silent drift
fix(ci): UBSan enabled the whole `undefined` group, not its curated e…