# Netcode, Authority & Determinism

V5 is one UE5 open-world universe split into six ruleset cells — a 1947-noir
**Urban** cell, a Prohibition-era **Period** cell, an 1899 **Frontier**, a
Witcher-flavoured **Hunter** cell, a hard-SF **Sci-Fi** cell, and the cross-cell
**Mind Palace** — and like its V4 sibling it refuses to pick one netcode for all
of them. A 30-player Urban free-roam is server-authoritative with
lag-compensated hit validation; a Period mission is single-player and never
opens a socket; a Sci-Fi capital-ship raid wants a 60 Hz server tick and 12 km
of relevancy; a Sci-Fi ship duel or Urban deathmatch wants 8-frame rollback
prediction so your own ship answers the stick without waiting a round-trip. The
single most consequential networking decision in V5 is therefore the same one V4
made: **each cell picks the netcode posture that fits its loop.**

All of those postures are expressed in one Unreal C++ module — **`V5Netcode`**
(`V5/ue/Source/V5Netcode/`, three `.cpp` / three `.h` plus `V5Netcode.Build.cs`)
— but, and this is the load-bearing honesty of the page, they are expressed as
**deterministic library functions, not a running net stack.** The module
compiles on the on-box engine: the build tree carries seven `V5Netcode/*.o`
objects under
`V5/ue/Intermediate/Build/Linux/x64/UnrealEditor/Development/V5Netcode/`, and
the dedicated-server and arcade-cabinet targets carry their own copies. The one
place V5 genuinely touches Unreal's net path is elsewhere — the replicated
Gameplay-Ability-System attribute sets in `V5Gameplay`, covered below. This page
is the architecture-side companion for V5's per-cell netcode, server authority,
lag compensation, rollback prediction and determinism, part of the
**Multiplayer, Modes & World Simulation** group; the orientation hub is
[../V5_ARCHITECTURE.md](../V5_ARCHITECTURE.md).

## What ships, honestly

Five plain claims, so the rest of the page reads at face value.

- **The netcode logic is real, deterministic-by-construction, and tested.**
  `V5Netcode` is a set of thirteen `UBlueprintFunctionLibrary` classes (config
  builders, an actor-priority classifier, a lag-comp rewind selector, a
  host-election scorer, a rollback-span evaluator, a seeded PRNG, a bandwidth
  grader, a soak grader). Two automation specs —
  **`V5.Netcode.SystemsAndTargets`** and **`V5.Netcode.SoakSimulation`**
  (`V5NetcodeTests.cpp`) — drive these statics and assert _computed_ values, and
  both reported `Result={Success}` in the on-box run logged at
  `Saved/Logs/AutomationFull.log` (2026-06-13), inside a 304-test V5 suite.
- **This is a deterministic library, not a wired net driver.** There is no
  `FSocket`, `ISocketSubsystem`, no `UReplicationGraph`, no
  `UFUNCTION(Server/ Client/NetMulticast)` RPC, and no Iris API symbols anywhere
  in the module. `V5Netcode.Build.cs` declares only `Core`, `CoreUObject`,
  `Engine` and `V5Core` (`:9–17`) — it does not even depend on `Iris`,
  `OnlineSubsystem`, `ReplicationGraph` or `NetworkPrediction`. When
  `BuildIrisConfig` sets `NetDriverName = FName("IrisNetDriverV2")`
  (`V5NetcodeSystems.cpp:42`), that is the _name_ of the driver V5 intends to
  bind, carried in a plain config struct — not a call into a live Iris runtime.
- **The real engine-networking integration is the replicated GAS attribute
  sets.** `V5Gameplay` declares **44 server-authoritative
  `FGameplayAttributeData` fields** across four `UAttributeSet` subclasses, each
  `ReplicatedUsing = OnRep_*` with `REPNOTIFY_Always` and server-side clamping
  in `PostGameplayEffectExecute` (`V5AttributeSets.cpp`). That is genuine
  replication metadata — but **no actor, pawn or `PlayerState` in the tree
  mounts a replicated `AbilitySystemComponent` that owns these sets, and nothing
  sets `bReplicates`** (outside the gameplay-effect tests, the only
  `AbilitySystemComponent` reference in `V5/ue/Source` is the `#include` in
  `V5AttributeSets.h:3`; `V5GameplayEffectTests.cpp` is the other). The
  attributes are replication-_ready_, not replicating.
- **No build target enforces strict floating-point or a determinism flag.**
  `V5.Target.cs`, `V5DedicatedServer.Target.cs` and `V5ListenServer.Target.cs`
  set none of `/fp:strict`, `DETERMINISM`, or a `V5_STRICT_FP` define — unlike
  V2 (`V2_STRICT_FP=1`). The monolith's "fp-strict in deterministic paths" is
  _not_ realized in build config. V5's determinism instead rests on a seeded
  integer PRNG and integer frame arithmetic, described honestly below.
- **`RunSoakSimulation` is a closed-form grader, not a packet simulation.** It
  maps a `(packet-loss, RTT, duration)` tuple to a quality grade and
  recovery/validation counts by deterministic arithmetic
  (`V5NetcodeSystems.cpp:287`) — there is no datagram-level loss model behind
  the name. It is honest about its own arithmetic and tested as such.

These are honest altitude statements, not disparagement: every line cited
compiles, is UHT-processed, and is exercised by a passing spec. V5's netcode
simply sits one rung lower than V2's full rollback engine or V4's lockstep
subsystem — it is the _policy and math_ layer, with the wire binding deferred.

## The per-cell netcode model

The architecture monolith's promise — "combat authority is per-cell" — resolves
to four concrete postures, selected by cell and mode:

| Cell / mode                         | Strategy                       | Authority                  | Determinism posture                |
| ----------------------------------- | ------------------------------ | -------------------------- | ---------------------------------- |
| Urban / Frontier / Hunter (open)    | Iris client-server + AOI       | Server (lag-comp hit-reg)  | Server-authoritative, float OK     |
| Sci-Fi capital raid                 | Iris client-server, 60 Hz tick | Server                     | Server-authoritative, float OK     |
| Sci-Fi ship duel / Urban deathmatch | 8-frame rollback prediction    | Predict-and-confirm        | Seeded xoshiro256+, integer frames |
| Period (single-player)              | Local, no session              | Client-local               | Seeded, opt-in replay              |
| Mind Palace                         | Client-authoritative + sync    | Client-local, cloud-merged | n/a (deduction graph)              |

The selector is `BuildIrisConfig(Cell, bCapitalRaid)`
(`V5NetcodeSystems.cpp:39`): Iris is enabled for every cell _except_ Period and
Mind Palace (`bUseIris = Cell != Period && Cell != MindPalace`, `:43`), the
client input rate is pinned at 60 Hz, and the server tick is **60 Hz for a
capital raid or any Sci-Fi session, else 30 Hz** (`:45`). Server-authoritative
damage rides on the same flag (`bServerAuthoritativeDamage = bUseIris`, `:46`),
so a single-player Period mission is `bUseIris=false` and never claims server
authority it has no server to enforce.

```mermaid
flowchart TD
    M[Session opens: which cell + mode?] --> Q{BuildIrisConfig}
    Q -->|Period / Mind Palace| LO[bUseIris=false · local, no socket]
    Q -->|Urban / Frontier / Hunter| CS[Iris client-server · 30 Hz tick]
    Q -->|Sci-Fi capital raid| HF[Iris client-server · 60 Hz tick]
    Q -->|Sci-Fi duel / Urban deathmatch| RB[8-frame rollback prediction]
    CS --> AOI[AOI relevancy + priority tiers]
    HF --> AOI
    AOI --> AUTH[Server authority: replicated GAS attrs + PostGE clamp]
    AUTH --> LC[Lag-comp rewind: half-RTT, 200 ms window]
    RB --> EV[EvaluateRollback: span = current - max&#40;confirmed, mismatch&#41;]
    EV --> W{span within 8 frames?}
    W -->|yes| OK[resimulate predicted frames]
    W -->|no| DROP[flagged out-of-window]
    LO --> PR[seeded xoshiro256+ drives all gameplay RNG]
    OK --> PR
```

## Iris replication, AOI streaming and priority tiers

For the open-world cells V5 partitions relevancy by an area-of-interest profile
and a three-tier priority scheme — both pure functions over plain data.

`BuildAOIProfile(Cell)` (`V5NetcodeSystems.cpp:50`) returns the per-cell radius,
player cap and tick: **Urban 300 m / 30 players / 30 Hz** (the `default` arm,
`:77`), **Frontier 500 m / 7 / 30 Hz** (`:56`), **Sci-Fi 12 000 m / 10 / 60 Hz**
(`:61` — the 12 km the monolith promises for void combat), **Hunter 400 m / 4 /
30 Hz** (`:66`), and **Period / Mind Palace 0 m / 1 player / 0 Hz** (`:71`, i.e.
offline). The `V5.Netcode.SystemsAndTargets` spec pins three of these exactly
(Urban 300, Frontier 500, Sci-Fi 12 000).

`ClassifyActor(Input)` (`:86`) is the relevancy band budgeter. A player-or-owned
pawn, a mission-critical actor, or anything within **40 m** is **Critical** at
30 Hz; a vehicle-in-encounter or anything within **180 m** is **Important** at
12 Hz; everything else is **Background**, at 2 Hz or **0.5 Hz** for a
schedule-only NPC (`:99–103`). A schedule-only NPC beyond **600 m** stops
replicating entirely (`bReplicate`, `:104`) — the monolith's "distant
schedule-only NPC" tier made concrete. The bandwidth side is
`EvaluateBudget(Input)` (`:212`), which sums the three tiers, checks them
against the **64 kbps average / 256 kbps burst** budget (constants `:7–8`) the
monolith states, and on overflow throttles **Background first, then Important**
(`:218– 228`) — never Critical. The spec drives a 70 kbps over-budget input and
asserts Background lands in `ThrottledTiers` first.

### Server authority: the replicated GAS attribute sets

This is where V5 actually meets Unreal's replication system, and it lives in
`V5Gameplay`, not `V5Netcode`. Four `UAttributeSet` subclasses —
`UV5_AttributeSet_Combat` (14 attrs), `_Honor` (9), `_Ship` (11) and `_Vehicle`
(10) — declare every replicated stat via the `V5_REPLICATE_ATTRIBUTE` macro,
which expands to
`DOREPLIFETIME_CONDITION_NOTIFY(..., COND_None, REPNOTIFY_Always)`
(`V5AttributeSets.cpp:12`), and register them in `GetLifetimeReplicatedProps`
(Combat at `:57`). Authority is enforced **server-side after every gameplay
effect**: `PostGameplayEffectExecute` clamps Health to MaxHealth, Stamina to
MaxStamina, Toxicity, Mana, ship Hull/Reactor and vehicle Fuel into range
(`:94–103`, `:229–234`, `:287–290`), so a client cannot drive an attribute out
of bounds — the server re-clamps on its own copy before the `OnRep_*` notify
fans the value back out. `V5Gameplay.Build.cs` declares the real
`GameplayAbilities` and `GameplayTags` modules, and these attribute sets and
their `V5.Gameplay.GE.ReplicationMetadata` spec are documented in detail in
[./gas-animation-input.md](./gas-animation-input.md). The honest caveat from the
top still holds: the metadata is correct and compiled, but no replicated ASC
mounts it in-tree, so nothing pushes these bytes at runtime _yet_ — the binding
sits behind the same boundary as the `V5Netcode` library.

### Lag-compensated hit validation

`RewindForHitValidation(History, CurrentServerTime, RoundTripMs)`
(`V5NetcodeSystems.cpp:108`) is the server's "rewind the target to where the
shooter saw it" guard. It clamps the RTT into the **200 ms history window**
(constant `V5LagCompWindowMs`, `:5`; exposed via `GetHistoryWindowMs`, `:133`),
rewinds to `CurrentServerTime − RTT × 0.0005` — i.e. **half the round-trip**,
the one-way latency, in seconds (`:112`) — and floors that at the oldest
retained sample (`:113–117`). It then scans the sample ring for the entry
**nearest** the rewind time by absolute delta and reports `bCanRewind` only when
history is non-empty _and_ the best match is inside the 200 ms window
(`:119–129`). Worth labeling precisely: this is **nearest-sample selection, not
interpolation between two bracketing samples** (V4's lag-comp interpolates; V5's
snaps to the closest recorded pose). The spec builds a ten-sample 33 ms history
and confirms a 200 ms RTT shot rewinds inside the window.

## Rollback-emulated prediction (the Sci-Fi duel cell)

For tight twitch PvP — the Sci-Fi ship duel and Urban deathmatch — V5 predicts
forward and rolls back on a remote-input mismatch. The decision logic is
`EvaluateRollback(CurrentFrame, LastConfirmedFrame, MismatchFrame, bRemoteInputMismatch)`
(`V5NetcodeSystems.cpp:160`). When the prediction held
(`!bRemoteInputMismatch`), it early-outs with `bWithinEightFrameWindow=true` and
zero rollback (`:163–167`) — a correctly predicted frame costs nothing, exactly
the property that keeps a clean connection at zero rewinds. On a mismatch it
computes `RollbackStart = max(LastConfirmedFrame, MismatchFrame)`, sets
`RollbackFrames = max(0, CurrentFrame − RollbackStart)`, mirrors that into
`ResimulatedFrames`, and grades it against the **8-frame window** (constant
`V5RollbackWindowFrames`, `:6`; check at `:172`). The spec proves the
arithmetic: `EvaluateRollback(120, 113, 114, true)` rolls back to frame 114 and
reports **6 resimulated frames, within window**.

The honest distinction from V2 matters here. V2 ships a full rollback _engine_ —
`FV2SimWorld` with `CaptureSnapshot`/`RestoreSnapshot`/`StepFrame`, an 8 KB
snapshot budget, a chained state hash and a golden-replay corpus. V5's
`EvaluateRollback` is a **span-and-window evaluator**: it decides _how many
frames a rollback would cover and whether that fits the budget_, but the
snapshot/restore/replay machinery it would gate is not in this module. The
monolith's behavioural rules — visuals snap for one frame, physics-particles and
audio do _not_ replay, torpedo trajectories are deterministic and need no
rollback — describe the intended cosmetics layer that consumes this decision;
the decision itself is what `V5Netcode` provides and tests.

## Determinism: the seeded PRNG and what it guarantees

V5's determinism backbone is a single, real, named algorithm. `UV5_Net_PRNG`
implements **xoshiro256+**: `Seed(MatchSeed)` expands a 64-bit match seed into
the 256-bit state with four `SplitMix64` draws (`:176–185`, the standard
`0x9E3779B97F4A7C15` increment and the two mix constants, `:25–31`) — the
seeding procedure the xoshiro authors prescribe — and `Next(State)` returns
`s0 + s3` as the output, then advances the state with the canonical
xor/shift/rotl-45 transition (`:187–209`). The unit float is taken from the
**top 24 bits** of the output (`(Value >> 40) & 0xFFFFFF`, `:204`), which is
correct practice for the `+` scrambler whose low bits have weak linear
complexity. Because the state is integer and the transition is fixed, the stream
is bit-identical across machines from the same seed — the spec asserts both
`Seed(12345)` states and their first `Next` values are equal.

Two honest qualifications keep this from over-claiming. **First, this is the
whole determinism story in-code.** There is no chained state-hash desync
detector (V4's `ComputeDeterministicHash`), no RNG-consumption-order audit (V4's
`ValidateRngConsumptionOrder`), no `StableNameHash`, and no replay serializer or
golden corpus (V2's `GoldenReplayCorpus`). Cross-machine determinism is asserted
for the _PRNG_ and the _integer frame arithmetic_, not for a full gameplay sim.
**Second, the monolith's two stronger claims are unbacked by this tree:**
"fp-strict in deterministic paths" sets no compiler flag in any target, and the
"opt-in save-replay with full input stream + initial seed" has no serializer
here. The float-math open-world paths are safe precisely because they are
server-reconciled, never cross-machine lockstep — V5, like V4, deliberately
abandoned deterministic lockstep for the Urban heist in favour of
client-server + lag-comp (per the monolith), so it never depends on
bit-identical float replay across peers.

## Sessions, host migration, dedicated servers and LAN

`V5Netcode` also carries the session-shape layer. `UV5_Net_DedicatedServer` and
`UV5_Net_ListenServer` build target profiles — dedicated on **port 7777, 30
players** (`:232`), listen on **7778, 6 players** (`:243`), both
`bServerAuthoritative=true` — matching the `V5DedicatedServer`/`V5ListenServer`
build targets, which both compile (their intermediate trees exist alongside the
editor's). `ElectNewHost(Candidates, PreviousHost)` (`:138`) is the 2-second
host-migration rule: it scores each connected, non-previous-host peer by
**`UploadKbps × 0.7 − PingMs × 2.0`** (`HostScore`, `:33–36`), picks the
highest, estimates a completion time clamped to `[0.6 s, 2.0 s]` from ping and
upload headroom (`:153`), and reports `bWithinTwoSecondCap` (`:156`). The spec
elects a 5 Mbps/38 ms peer over a disconnected old host and confirms the
sub-two-second swap. `UV5_Net_LAN::BuildLANAdvertisement` (`:254`) mints an
offline-capable LAN session (`bRequiresOnlineServices=false`), and
`UV5_Net_ServerBrowser::FilterRooms` (`:266`) filters private rooms by
cell/mode/region/password/ping and **sorts the survivors by ascending ping**
(`:280–283`).

The choice of _which_ cells may even cross platforms is policy data in
`V5/crossplay/crossplay-progression-policy.json`: crossplay is on by default
across **9 platforms**, but the Sci-Fi `mode.scifi.spaceship-pvp` carries a
documented opt-out with
`consoleInputParityReason: "spaceship_pvp_high_precision_input"` — the one cell
on the rollback path is also the one allowed to fence console players off for
input-parity fairness. That file, the canonical-account ledger and the
progression merge policies belong to the online/persistence layer and are
detailed in
[./persistence-online-and-crossplay.md](./persistence-online-and-crossplay.md).

## How it connects

The netcode module is consumed, not standalone. The GameFeatures mode plugins
that select an Iris profile and an AOI band per session — and the
World-Partition grid those relevancy radii stream against — are detailed in
[./modes-streaming-procgen.md](./modes-streaming-procgen.md); the per-cell
server ticks here are the same ticks the streaming budget plans around. The
server-authoritative replication of _non-combat_ state — guard suspicion, honor,
bounty and wanted level, distinct from the rollback path — is the AI side of the
same client-server backbone and lives in
[./perception-crowd-and-morality.md](./perception-crowd-and-morality.md), whose
morality attributes mount on the very `UV5_AttributeSet_Honor` set this page
shows replicating. The dedicated-server backend, matchmaking, anti-cheat,
canonical-account crossplay and save-sync that the target profiles and session
shapes feed into are covered in
[./persistence-online-and-crossplay.md](./persistence-online-and-crossplay.md).
The attribute-set field definitions, clamps and GAS replication metadata are in
[./gas-animation-input.md](./gas-animation-input.md). The orientation hub is
[../V5_ARCHITECTURE.md](../V5_ARCHITECTURE.md).

## Related

- [Modes, Streaming & Procgen](./modes-streaming-procgen.md) — the mode plugins
  that pick an Iris profile and the World-Partition grid the AOI radii stream on
- [Perception, Crowd & the Morality System](./perception-crowd-and-morality.md)
  — server-authoritative suspicion, honor, bounty and wanted state, the
  non-rollback authority path
- [Persistence, Online & Crossplay](./persistence-online-and-crossplay.md) — the
  online services backend, dedicated-server backbone, anti-cheat and the
  canonical-account crossplay policy
- [GAS, Animation & Input](./gas-animation-input.md) — the four `UAttributeSet`
  subclasses, their 44 replicated fields and server-side clamps
- The orientation hub: [../V5_ARCHITECTURE.md](../V5_ARCHITECTURE.md)
