From 3b772da73c2d9158523286429dc791814481370c Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 18 May 2026 15:18:31 -0700 Subject: [PATCH] Add multiplayer latency test plan --- AGRARIAN_DEVELOPMENT_ROADMAP.md | 4 +- Docs/MultiplayerNetworkingDesign.md | 8 +++ Docs/Ops/MultiplayerLatencyTestPlan.md | 69 +++++++++++++++++++++++ Scripts/LatencyTestProfiles-Windows.bat | 27 +++++++++ Scripts/verify_basic_latency_testing.py | 73 +++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 Docs/Ops/MultiplayerLatencyTestPlan.md create mode 100644 Scripts/LatencyTestProfiles-Windows.bat create mode 100644 Scripts/verify_basic_latency_testing.py diff --git a/AGRARIAN_DEVELOPMENT_ROADMAP.md b/AGRARIAN_DEVELOPMENT_ROADMAP.md index b74f1fe..bf67746 100644 --- a/AGRARIAN_DEVELOPMENT_ROADMAP.md +++ b/AGRARIAN_DEVELOPMENT_ROADMAP.md @@ -722,7 +722,9 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe pickups, resources, campfires, shelters, wildlife, water sources, weather exposure zones, and wildlife spawn managers, with the matching relevancy strategy documented for Ground Zero multiplayer tests. -- [ ] Add basic latency testing. +- [x] Add basic latency testing. Added an MVP latency test plan with clean LAN, + mild WAN, and rough WAN Unreal packet-simulation profiles plus a Windows + helper script for the test console commands. - [ ] Add disconnect/reconnect handling. ## 0.1.M Persistence MVP diff --git a/Docs/MultiplayerNetworkingDesign.md b/Docs/MultiplayerNetworkingDesign.md index a7bb388..bd589eb 100644 --- a/Docs/MultiplayerNetworkingDesign.md +++ b/Docs/MultiplayerNetworkingDesign.md @@ -245,10 +245,18 @@ MVP target: - normal gathering/crafting/building should feel acceptable under LAN and typical residential broadband latency; +- clean LAN profile uses 0ms artificial lag and 0% packet loss; +- mild WAN profile uses 80ms lag, 20ms variance, and 1% packet loss; +- rough WAN profile uses 160ms lag, 40ms variance, and 3% packet loss; - survival stat updates can tolerate low-frequency replication; - inventory/crafting feedback should feel responsive enough to test the loop; - combat and precision movement prediction are not the first MVP focus. +`Docs/Ops/MultiplayerLatencyTestPlan.md` is the 0.1.L latency gate. It uses +Unreal packet simulation commands and two packaged clients to check resource +depletion, item drops, fire/shelter replication, wildlife state, and server +travel under repeatable profiles. + Initial latency testing should cover: - join and spawn; diff --git a/Docs/Ops/MultiplayerLatencyTestPlan.md b/Docs/Ops/MultiplayerLatencyTestPlan.md new file mode 100644 index 0000000..155a347 --- /dev/null +++ b/Docs/Ops/MultiplayerLatencyTestPlan.md @@ -0,0 +1,69 @@ +# Agrarian Multiplayer Latency Test Plan + +This is the MVP latency test gate for 0.1.L. It is intentionally small and +repeatable so the first two-player tests can find obvious replication and +interaction problems before dedicated-server hosting is stable. + +## Scope + +Run these tests against the current Ground Zero map: + +```text +/Game/Agrarian/Maps/L_GroundZeroTerrain_Test +``` + +The test can use either: + +- listen server while dedicated-server packaging is blocked; +- Linux dedicated server at `play.agrariangame.com:7777` once the gameplay VM is + available. + +## Network Profiles + +Use Unreal packet simulation console variables on the client being tested: + +| Profile | Commands | +| --- | --- | +| Clean LAN | `Net PktLag=0`, `Net PktLoss=0` | +| Mild WAN | `Net PktLag=80`, `Net PktLagVariance=20`, `Net PktLoss=1` | +| Rough WAN | `Net PktLag=160`, `Net PktLagVariance=40`, `Net PktLoss=3` | + +Reset after testing: + +```text +Net PktLag=0 +Net PktLagVariance=0 +Net PktLoss=0 +``` + +## Smoke Steps + +For each profile: + +1. Start a listen server or dedicated server on the Ground Zero map. +2. Connect two packaged Windows clients. +3. Confirm both clients see the same world time and weather. +4. Gather from a resource node on client A and confirm depletion on client B. +5. Drop an item on client A and confirm client B sees the pickup only when + nearby. +6. Place or interact with a campfire/shelter and confirm replicated state. +7. Damage/harvest wildlife if available and confirm state replication. +8. Trigger `AgrarianServerTravel GroundZero` and confirm clients return to the + Ground Zero map. +9. Record visible hitching, missed interactions, delayed stat updates, or + disconnects. + +## Pass Criteria + +- Both clients remain connected through the clean LAN and mild WAN profiles. +- Core interactions eventually reconcile under rough WAN conditions. +- No client can create authoritative inventory, survival, resource, fire, + shelter, or wildlife state locally. +- Any failure is reproducible with the profile, map, client build, server build, + and logs recorded. + +## Helper Script + +`Scripts/LatencyTestProfiles-Windows.bat` prints the console commands for each +profile and the reset command. It does not automate a full playthrough; the MVP +gate still requires human observation until gameplay automation matures. diff --git a/Scripts/LatencyTestProfiles-Windows.bat b/Scripts/LatencyTestProfiles-Windows.bat new file mode 100644 index 0000000..b90ef54 --- /dev/null +++ b/Scripts/LatencyTestProfiles-Windows.bat @@ -0,0 +1,27 @@ +@echo off +setlocal + +echo Agrarian MVP latency test profiles +echo. +echo Clean LAN: +echo Net PktLag=0 +echo Net PktLagVariance=0 +echo Net PktLoss=0 +echo. +echo Mild WAN: +echo Net PktLag=80 +echo Net PktLagVariance=20 +echo Net PktLoss=1 +echo. +echo Rough WAN: +echo Net PktLag=160 +echo Net PktLagVariance=40 +echo Net PktLoss=3 +echo. +echo Reset: +echo Net PktLag=0 +echo Net PktLagVariance=0 +echo Net PktLoss=0 +echo. +echo Run these in the client console while connected to the Ground Zero server. +exit /b 0 diff --git a/Scripts/verify_basic_latency_testing.py b/Scripts/verify_basic_latency_testing.py new file mode 100644 index 0000000..db866a1 --- /dev/null +++ b/Scripts/verify_basic_latency_testing.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +"""Validate MVP latency testing plan and helper script.""" + +from pathlib import Path +import sys + +ROOT = Path(__file__).resolve().parents[1] + + +def read(relative_path: str) -> str: + path = ROOT / relative_path + if not path.exists(): + raise AssertionError(f"Missing required file: {relative_path}") + return path.read_text(encoding="utf-8") + + +def require(content: str, needle: str, context: str) -> None: + if needle not in content: + raise AssertionError(f"Missing {needle!r} in {context}") + + +def main() -> int: + errors: list[str] = [] + checks = { + "Docs/Ops/MultiplayerLatencyTestPlan.md": [ + "Clean LAN", + "Mild WAN", + "Rough WAN", + "Net PktLag=80", + "Net PktLag=160", + "Net PktLoss=3", + "AgrarianServerTravel GroundZero", + "play.agrariangame.com:7777", + ], + "Scripts/LatencyTestProfiles-Windows.bat": [ + "Net PktLag=0", + "Net PktLagVariance=20", + "Net PktLoss=1", + "Net PktLagVariance=40", + "Net PktLoss=3", + ], + "Docs/MultiplayerNetworkingDesign.md": [ + "mild WAN profile", + "rough WAN profile", + "Docs/Ops/MultiplayerLatencyTestPlan.md", + "Unreal packet simulation", + ], + "AGRARIAN_DEVELOPMENT_ROADMAP.md": [ + "[x] Add basic latency testing.", + "clean LAN", + "rough WAN", + ], + } + + for relative_path, needles in checks.items(): + try: + content = read(relative_path) + for needle in needles: + require(content, needle, relative_path) + except AssertionError as exc: + errors.append(str(exc)) + + if errors: + for error in errors: + print(f"ERROR: {error}", file=sys.stderr) + return 1 + + print("PASS: MVP latency testing plan and helper script are present.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())