# Online Services, Network Quality & Tournaments

```mermaid
sequenceDiagram
  actor Player
  participant Client
  participant Matchmaking
  participant Quality as Network quality
  participant Authority as Match authority
  participant Tournament
  Player->>Client: Queue with mode ruleset region and party
  Client->>Matchmaking: Auth entitlement build and preferences
  Matchmaking->>Quality: Evaluate peers route latency and integrity
  Quality-->>Client: Transport authority and compatibility decision
  Client->>Authority: Join signed match configuration
  Authority-->>Tournament: Replay hash and result receipt
  Tournament-->>Player: Bracket advancement broadcast and dispute state
```

Finding peers, selecting transport, admitting a compatible match, validating the
result, and advancing a bracket are independently observable steps. A
client-reported win never settles a tournament by itself.

A competitive fighting game makes one promise that is really three: that you can
_find_ a match, that the match runs on netcode worthy of the inputs you put into
it, and that when the bracket starts the result is real. This page is the
player-facing tour of the systems that keep all three — V2's **online services**
backbone (the auth, party, matchmaking, replay, and moderation plumbing every
menu sits on top of), the **network-quality** surfaces that decide how a match
is transported and where you can play it (rollback selection, the pre-match
handshake, LAN mode, the dedicated server browser, and private rooms), and the
**in-game tournament** stack that lets a TO run an entire event — bracket,
broadcast, and verified results — from inside the client. It deliberately stops
at two seams handled by siblings: the seasonal ranked ladder, the Crown pro
circuit, and local/online co-op live in
[Ranked, the Esports Circuit & Local Co-op](./ranked-esports-circuit-and-local-coop.md),
and the store, season pass, and companion app live in
[Live Service, DLC, Battle Pass & Companion](./live-service-dlc-battle-pass-and-companion.md).
The deep engine treatment of the backbone and competitive integrity is the
architecture companion,
[../architecture/online-backbone-and-competitive-integrity.md](../architecture/online-backbone-and-competitive-integrity.md).
For the full feature scope this slots into, start at the hub:
[../V2_features.md](../V2_features.md).

## What ships, honestly

The split here is sharp and worth stating up front. The **client-side online
surface is real, shipped Unreal C++**, and it is large.
`V2/ue/Source/V2OnlineServices` is a `UGameInstanceSubsystem`
(`V2OnlineServicesSubsystem.h`, ~2,500 lines) over a typed contract
(`V2OnlineServicesTypes.h`, ~26,700 lines) and a Blueprint library
(`V2OnlineServicesBlueprintLibrary.h`, ~2,900 lines), with `~25,400` lines of
type implementation in `V2OnlineServicesTypes.cpp`. Every feature on this page
is a validated `USTRUCT` with a real `IsValid…` predicate and, where it does
work, a real algorithm — the server-browser filter, the network-quality grading,
the tournament feature-set completeness gate. The single automation spec
`V2Tests/Automation/OnlineServices.Module.spec.cpp` is **5,044 lines carrying
737** `TestTrue`/`TestEqual`/`TestFalse`/`TestNotNull` assertions over that
surface, ~129 of them touching the network-quality, server-browser, LAN, room,
spectator, and tournament types specifically. The **service tier is real
TypeScript** too: `apps/v2/` holds **91** packages, including
`nous-anti-cheat-classifiers`, whose `buildV2NousAntiCheatClassifierSuite`
carries the same rollback-safety constant
(`V2_NOUS_ANTI_CHEAT_CLASSIFIERS_ROLLBACK_POLICY`) the architecture page
describes.

Four honest qualifications. **First**, the subsystem is a _typed client
abstraction with validation and local query logic_ — it is not a running cloud
fleet. The fleet-management, autoscaling, canary, DDoS, and SLO machinery
(matchmaking p50 ≤ 12 s / p99 ≤ 35 s at 5× launch concurrency, auth p99 ≤ 200
ms, ≥ 99.9% per-region availability) are _designed contracts and operational
targets_, represented in-engine as validated config/state snapshots, not a
server this header boots. **Second**, the wire contract to that backend — the
gRPC package the monolith specifies under `libs/proto/v2/online/` — **does not
exist in the tree** (confirmed: no such path), so the proto method signatures
are the designed contract, not generated stubs. **Third**, the kernel anti-cheat
client specified at `V2/ue/Plugins/V2AntiCheat/` **is not present** (the shipped
plugins are `V2AICommentary`, `V2AdaptiveAI`, `V2AssetLinter`, plus the
Bellona/V2 editor helpers) — so EAC/BattlEye is a plan, while the _server-side_
integrity check is the part that is architecturally real because it rides the
deterministic sim. **Fourth**, ranked/matchmaking tuning is baked into the C++
defaults rather than data: `V2/balance/online/` currently holds only
`world-boss-community-raid.json`. Where prose and code disagree, the code is the
authority.

## The online backbone, from the player's seat

Press _Online_ and you are talking to one gateway that fronts auth, friends,
presence, parties (≤ 8), matchmaking, lobbies, ranked, the replay cloud, and the
store — the engine never branches on platform, because Sony NP, Microsoft Live,
and the Switch SDK are reached through shims behind the same subsystem interface
over an Epic Online Services baseline. A session is a short-lived JWT (15 min)
plus a rotating 30-day refresh token, so a sign-in survives a console sleep
without re-prompting. Matchmaking is per-mode — Casual, Ranked, Tournament,
Crew, Royal Rumble lobby — and each ticket carries a Glicko-2 / TrueSkill2 skill
estimate, region weighting, a ping cap that widens the longer you wait, and
role-preference balancing for tag and 4-player. Replays are first-class: every
match is stored as re-simulatable inputs you can share by code, pull from a
cloud library, or download locally, and the same file doubles as the _ghost_
data the Ghost Battle and master-training modes consume.

The integrity story is where the backbone earns its keep, and the load-bearing
line of defense is the one that is _real today_. Because a V2 match runs on a
deterministic, integer-frame simulator, the server can do what most fighting
games cannot: **re-simulate a match from its inputs and compare the result
hash.** That check is a shipped type — `FV2ReplayDeterminismGateResult`
(`V2OnlineServicesTypes.h:12063`) carries the `InputStreamHash`, `RngSeed`,
`ClientOutcomeHash`, and `ServerOutcomeHash`, and its `ShouldBlockRankedWrite()`
predicate refuses to commit a ranked result when `bOutcomeDiverged` is set. The
gate result is then embedded directly in the match row: `FV2RankedMatchRecord`
(`:12111`) holds both the determinism gate _and_ the network-quality handshake
as required fields, so a ranked match cannot be written without both having been
evaluated. The other anti-cheat layers — kernel client drivers, ML smurf /
win-trading / coordinated-throw / geo-anomaly classifiers — are real-as-designed
but governed by an honest rule: classifier output **prioritizes human review and
never issues automatic discipline**, and discipline/appeals route out to the
shared Themis/Kuanyin trust-and-safety plane rather than living in V2.

## Network quality: how a match picks its netcode

A 1v1 match does not assume good conditions; it measures them first. The
**pre-match handshake** samples RTT, jitter, and packet loss on both ends, and
the result is the shipped `FV2NetworkQualityHandshakeResult`
(`V2OnlineServicesTypes.h:12022`), built by `BuildNetworkQualityHandshake` with
`bRunsBeforeRankedMatchStart`, `bMeasuresBothSides`, and
`bStampedIntoMatchRecord` all true. The per-side `FV2NetworkQualityMeasurement`
(`:11993`) carries a real threshold, not a vibe: `IsPoorQuality()`
(`V2OnlineServicesTypes.cpp:12532`) returns true when
`RttMs >= 150 || JitterMs >= 30 || PacketLossPercent >= 3.0`. From the two
measurements the handshake resolves a grade — `EV2OnlineNetworkQualityGrade` is
`{ Good, Fair, Poor }` (`:384`) — and the transport mode follows from it
(`EV2NetworkQualityTransportMode { Rollback, Delay, Hybrid }`, `:169`): a _Good_
read runs full rollback at 60 Hz with the engine's ≤ 8-frame budget, a _Fair_
read runs the hybrid of rollback plus a small input-delay buffer, and RTT > 150
ms or sustained rollback pressure runs delay-based netcode.

The honest part is the _out_. `IsDeclinable()`
(`V2OnlineServicesTypes.cpp:12581`) returns true when the player is allowed to
decline _and_ the grade is Poor or either side reads poor — and per the feature
contract, declining a degraded rollback match in ranked converts it to a
**no-contest rather than forcing a bad fight**. The handshake also surfaces
connection hygiene the platform exposes: `RequiresWirelessWarning()` flags Wi-Fi
and `RequiresMobileHotspotWarning()` flags MobileHotspot / Cellular4G /
Cellular5G off the `EV2NetworkConnectionType` enum (`:373`), and those bubble up
to the match record as the `bLastRankedNetworkWirelessWarning` /
`…MobileWarning` snapshot fields. A per-account network-reliability score feeds
the ops dashboard from these stamps over time.

### LAN tournament mode

For a venue with no internet to trust, V2 ships a LAN path that stands entirely
on its own. `FV2LanTournamentModeConfig` (`V2OnlineServicesTypes.h:11675`) does
**UDP-broadcast peer discovery** on port `36666` with `bNoInternetRequired`,
keeps a `bLanOnlyRankingLedger` strictly separate from the online ladder, still
`bCapturesReplays` and `bPreservesPerMatchRuleSheet`, and auto-enables when the
client sees a registered venue SSID — the default catalog
(`BuildDefaultNetworkQualityOnlineCatalog`,
`V2OnlineServicesBlueprintLibrary.cpp:9651`) ships three: `EVO-Stage-LAN`,
`CPT-Arena-Admin`, `Oshun-TO-Offline`. `IsValidConfig`
(`V2OnlineServicesTypes.cpp:11731`) is a real gate: it fails the config unless
the SSID list is non-empty and every one of those guarantees holds.

### The dedicated server browser

The server browser is primarily a PC surface (and console where TRC permits) and
runs on real query logic, not a mock list. A host's listing is an
`FV2ServerBrowserEntry` (`:24109`); a search is an `FV2ServerBrowserQuery`
(`:24071`, default `MaxPingMs = 120`), and the match is decided by
`FV2ServerBrowserEntry::MatchesQuery` (`V2OnlineServicesTypes.cpp:23112`) — a
genuine multi-clause filter that rejects a server on visibility, dedicated-only,
healthy-only, join-in-progress, game-mode, region, platform, a
`PingMs > MaxPingMs` cap, _and_ requires
`OpenPlayerSlots >= MinOpenPlayerSlots`. The Blueprint library's
`QueryServerBrowser` runs that filter over the directory and then **sorts the
survivors by ascending ping**, while the subsystem's
`QueryServerBrowserDirectory` fails loud — "directory must be refreshed before
query" — rather than return a stale or empty list silently. The host-side config
(`FV2DedicatedServerBrowserConfig`, `:11710`) covers what you'd expect a host to
control — ruleset, stipulation, fighter restriction, password, AFK-kick,
rotating maps, kick/ban/mute moderation, chat-log audit, and a server reputation
rating — plus a bring-your-own-dedicated-server path and a `MaxBrowserLatencyMs`
ceiling of 250. Listings are typed by `EV2DedicatedServerListingKind`
(`{ Official, BringYourOwnServer, CommunityLeague }`, `:177`).

### Custom rooms & private lobbies

`FV2CustomRoomConfig` (`:11757`) is the private-lobby contract, and its
validators are strict by design. `HasRequiredModes()`
(`V2OnlineServicesTypes.cpp:11781`) demands all six `EV2CustomRoomMode` values —
`OneVOne`, `TwoVTwo`, `FourCorner`, `Tournament`, `BattleRoyal`, `RoyalRumble`
(`:185`) — and `HasRequiredRotationPolicies()` demands all three of
`EV2RoomQueueRotationPolicy { WinnersStayOn, LosersRotateOut, RandomizedSeating }`
(`:196`). A room seats up to **16 participants and 8 spectators** (both
clamp-enforced in the property metadata), gates on an optional password, lets
the host force a specific transport (`bHostCanForceRollbackDelayHybrid`), runs a
who-plays-next queue, and — the nice touch — enables a `bSpectatorMiniLab` so a
waiting player drills in a practice space instead of idling. Above the room sits
`FV2CrossServerTournamentConfig` (`:11803`) for events that span regional
servers with a unified bracket and an anti-stream-snipe start delay, and a
region pool (`FV2RegionMatchmakingPoolConfig`) the default catalog seeds with
nine regions: NA, EU, JP, KR, LATAM, SEA, India, MENA, Oceania.

## In-game tournaments & broadcast

V2's tournament stack is a single typed bundle, `FV2EsportsTournamentFeatureSet`
(`V2OnlineServicesTypes.h:7913`), and the subsystem's
`ConfigureEsportsTournamentFeatures` will **only accept it if it is complete**:
`IsCompleteFeatureSet` (`V2OnlineServicesTypes.cpp`) validates all ten
sub-configs — spectator policy, admin event config, broadcast control surface,
the tournament-edition rule snapshot, the Crown ranking config, the
streamer-mode profile, coach/speedrun configs, the caster API contract, and the
pro-ghost catalog — and short-circuits to `false` with a precise reason on the
first one that fails. There is no half-configured tournament.

A TO with a badge account drives `FV2TournamentAdminEventConfig` (`:7433`): it
builds any of the five `EV2TournamentBracketFormat` values —
`SingleElimination`, `DoubleElimination`, `RoundRobin`, `Swiss`, `Gsl` (`:1589`)
— assigns seeds, schedules matches, drives a broadcast run-of-show, and
auto-reports results, with DQ, a no-show timeout (default 300 s, clamped
30–1800), and round-extension override as TO controls. **Tournament Edition** is
the lockdown: `FV2TournamentEditionRuleSnapshot` (`:7557`) forces classic
controls only, default stages and costumes only, no Mercy/Friendship/Babality, a
forced P1-left/P2-right side, and a locked finisher policy — and critically it
carries a `RulesHash` and `ReplayHeaderId`, so the exact conditions a match was
played under are **stamped into every replay header and auditable forever**.

Spectating and casting are real policy, not a toggle.
`FV2EsportsSpectatorPolicy` (`:7383`) is validated by `IsValidPolicy`
(`V2OnlineServicesTypes.cpp`) to allow **exactly 8 in-match observers** with a
chat throttle and a configurable anti-leak delay (default 120 s), and it
_requires_ the overlay, drawing tools, freeze-frame, slow-mo, name plates, score
overlay, director-cam, scriptable cuts, picture-in-picture, and side-by-side
stick cam all be present. The caster-facing `FV2BroadcastControlSurface`
(`:7499`) is a manual control surface that toggles HUD elements, supports a
configurable broadcast delay and a stream-lag injector, outputs to OBS / NDI /
Spout / a browser source / a JSON WebSocket (`EV2BroadcastOutputIntegration`),
and points third-party overlay developers at a documented public SDK schema
(`apps/v2/web/dev-portal/caster-api/schema.json`).

The two ends — playing and ranking — are joined by **result integrity that a
client cannot forge**. Results are server-authoritative: the design _pulls_
results from Start.gg / Challonge / Battlefy / Tournament.app and
cryptographically verifies each against the replay hash before it counts toward
Crown Points, and the `FV2CrownProTourRankingConfig` (`:7628`) holds the
approved-tournament and third-party-integration allowlists, a
`QualificationCutoff` of 32 for the Grand Final, and read-only third-party API
display. The same machinery makes **Battle Hub Crown Tournaments** possible
inside the client — a public bracket, auto-progression, a per-match side-stream,
and a public leaderboard — so a player enters a real bracket without ever
leaving the game. Streamer Mode (`FV2StreamerModePrivacyProfile`) rounds it out:
it hides handles and region, renders the opponent as "Opponent," defaults voice
off, auto-enables stream-safe music, and exposes an anti-stream-snipe delay
between 60 and 300 seconds.

## How it connects

The online subsystem is the seam every networked surface in V2 runs through, but
it deliberately hands off two large neighbors. The **seasonal ranked ladder, the
Crown pro circuit, and split-screen / online co-op** are the player-facing focus
of
[Ranked, the Esports Circuit & Local Co-op](./ranked-esports-circuit-and-local-coop.md);
the **store, season pass, player compensation, and companion app** that share
this same backbone are in
[Live Service, DLC, Battle Pass & Companion](./live-service-dlc-battle-pass-and-companion.md).
For the engine-side treatment — the EOS abstraction, the matchmaking SLO
contract, the event-bus topics, the replay-hash re-simulation pipeline, and the
cross-play / cross-progression policy model — read the architecture companion,
[../architecture/online-backbone-and-competitive-integrity.md](../architecture/online-backbone-and-competitive-integrity.md).

## Related

- The feature hub: [../V2_features.md](../V2_features.md)
- [Ranked, the Esports Circuit & Local Co-op](./ranked-esports-circuit-and-local-coop.md)
  — the seasonal ladder, Crown pro tour, and couch/online co-op
- [Live Service, DLC, Battle Pass & Companion](./live-service-dlc-battle-pass-and-companion.md)
  — the store and live-ops services that share the backbone
- Architecture companion:
  [../architecture/online-backbone-and-competitive-integrity.md](../architecture/online-backbone-and-competitive-integrity.md)
  — the backbone, anti-cheat, and cross-play/cross-progression model
