Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development Tools

Network Simulation

Inspired by Generals’ debug network simulation features, all NetworkModel implementations support artificial network condition injection:

#![allow(unused)]
fn main() {
/// Configurable network conditions for testing. Applied at the transport layer.
/// Only available in debug/development builds — compiled out of release.
pub struct NetworkSimConfig {
    pub latency_ms: u32,          // Artificial one-way latency added to each packet
    pub jitter_ms: u32,           // Random ± jitter on top of latency
    pub packet_loss_pct: f32,     // Percentage of packets silently dropped (0.0–100.0)
    pub corruption_pct: f32,      // Percentage of packets with random bit flips
    pub bandwidth_limit_kbps: Option<u32>,  // Throttle outgoing bandwidth
    pub duplicate_pct: f32,       // Percentage of packets sent twice
    pub reorder_pct: f32,         // Percentage of packets delivered out of order
}
}

This is invaluable for testing edge cases (desync under packet loss, adaptive run-ahead behavior, frame resend logic) without needing actual bad networks. Accessible via debug console or lobby settings in development builds.

Diagnostic Overlay

A real-time network health display (inspired by Quake 3’s lagometer) renders as a debug overlay in development builds:

  • Tick timing bar — shows how long each sim tick takes to process, with color coding (green = within budget, yellow = approaching limit, red = over budget)
  • Order delivery timeline — visualizes when each player’s orders arrive relative to the tick deadline. Highlights late arrivals and idle substitutions.
  • Sync health — shows RNG hash match/mismatch per sync frame. A red flash on mismatch gives immediate visual feedback during desync debugging.
  • Latency graph — per-player RTT history (rolling 60 ticks). Shows jitter, trends, and spikes.

The overlay is toggled via debug console (net_diag 1) and compiled out of release builds. It uses the same data already collected by NetworkDiagnostics — no additional overhead.

Netcode Parameter Philosophy (D060)

Netcode parameters are not like graphics settings. Graphics preferences are subjective; netcode parameters have objectively correct values — or correct adaptive algorithms. A cross-game survey (C&C Generals, StarCraft/BW, Spring Engine, 0 A.D., OpenTTD, Factorio, CS2, AoE II:DE, original Red Alert) confirms that games which expose fewer netcode controls and invest in automatic adaptation have fewer player complaints and better perceived netcode quality.

IC follows a three-tier exposure model:

TierPlayer-Facing ExamplesExposure
Tier 1: Lobby GUIGame speed (Slowest–Fastest)One setting. The only parameter where player preference is legitimate.
Tier 2: Consolenet.sync_frequency, net.show_diagnostics, net.desync_debug_level, net.simulate_latency/loss/jitterPower users only. Flagged DEV_ONLY or SERVER in the cvar system (D058).
Tier 3: Engine constantsTick rate (set by game speed preset; default Slower ≈15 tps), sub-tick ordering, adaptive run-ahead, timing feedback, stall policy (never stall), anti-lag-switch, visual predictionFixed. These are correct engineering solutions, not preferences.

Sub-tick ordering (D008) is always-on. Cost: ~4 bytes per order + one sort of typically ≤5 items per tick. The mechanism is automatic, but the outcome is player-facing — who wins the engineer race, who grabs the contested crate, whose attack resolves first. These moments define close games. Making it optional would require two sim code paths, a deterministic fallback that’s inherently unfair (player ID tiebreak), and a lobby setting nobody understands.

Adaptive run-ahead is always-on. Generals proved this over 20 years. Manual latency settings (StarCraft BW’s Low/High/Extra High) were necessary only because BW lacked adaptive run-ahead. IC’s adaptive system replaces the manual knob with a better automatic one.

Visual prediction is always-on. Factorio originally offered a “latency hiding” toggle. They removed it in 0.14.0 because always-on was always better — there was no situation where the player benefited from seeing raw lockstep delay.

Full rationale, cross-game evidence table, and alternatives considered: see decisions/09b/D060-netcode-params.md.