ModernWormfare — Async PvP Test

Automated Playwright run · 2026-07-22 · 2-player async turn-batch · dev server on :5080

Overview

Date: 2026-07-22

Mode: Async (turn-batch PvP) — client records a whole turn, server simulates deterministically, broadcasts a replay, persists the turn

Players: net (host, Cow race, admin) vs guest (Rocket race)

Map: Islands

Server: dev server ./dev.sh on http://localhost:5080 (no sudo)

Tester: automated via Playwright (headless Chromium, 2 browser tabs)

Game ID: 8e05ad7a-5ee0-4737-9394-b440597e1a57

Match flow exercised

1. Lobby (create + join)→ 2. Loadout (buy + ready)→ 3. Begin Match→ 4. Record turn→ 5. Submit batch→ 6. Replay→ 7. Undo / Commit→ next unit

Screenshots

Home
1. Home — three entry points (Single Player, Async, Sync)
Lobby create
2. Host creates an Async game (name: net, Cow, Islands)
Lobby join
3. Second player (guest, Rocket) joins the open game
Loadout host
4. Host loadout — Shotgun + Cluster Grenade + Ninja Rope (4597cr)
Loadout guest
5. Guest loadout — Sniper + Banana Bomb + Teleport (4487cr)
Game start
6. Match begins — net's turn, unit 1/3, recording armed
Turn 1 aim
7. Turn 1 — Rocket aimed at 45°, power 530, recording 16k+ ticks
Turn 2 recording
8. Turn 2 — Shotgun selected, recording continues (unit 2/3)
Turn passed to guest
9. Turn rotated to guest (unit 1/3) — host now "Waiting"
Guest turn
10. Guest's perspective — their loadout, their funds, recording armed
Admin toolbar
11. Admin toolbar (Undo / Commit) visible only to player "net"
Admin undo
12. Admin Undo clicked — last turn rolled back (success=True)
Replay playing
13. Replay playing back after a committed turn (⏳ status)
Game state
14. Post-commit game state — next unit armed for recording

Report

Environment: .NET 10.0.301, dev server on port 5080, zero sudo. Two independent browser tabs simulated two human players on separate SignalR connections.

Features exercised

1. Lobby create + join — PASS

2. Loadout + economy (two players) — PASS

3. Turn recording + batch submission — PASS (caveat: issue #1)

#PlayerUnitWeaponTicksAccepted
1net1/3Rocket3350✓
2net2/3Shotgun4463✓
3net3/3Cluster Grenade5929✓
4guest1/3Sniper484✓
5guest2/3Banana Bomb2763✓
6guest3/3Rocket153✓

4. Turn rotation across players — PASS

5. Admin undo / commit moderation — PASS

6. Per-player state isolation — PASS

Known issues found

1. Large turn batches exceed the 2 MiB SignalR limit NOTE / robustness FIXED

Three submissions were rejected because the serialized TurnActionBatch exceeded SignalR's MaximumReceiveMessageSize (2 MiB, set in Program.cs):

AttemptTicksResult
1st26176Connection closed — message size exceeded
2nd21403Connection closed — message size exceeded
3rd8998Connection closed — message size exceeded

Successful batches ranged 153–5929 ticks. Recording accumulates one tick per animation frame (~60 Hz), so a turn held open ~2.5 min (idle aiming / slow interaction) produces ~9000 ticks and trips the limit.

Fix: Added MaxRecordedTicks = 5000 cap in MultiplayerGame.razor.cs. The client auto-submits when the cap is reached (~83s at 60 FPS), keeping the batch under ~1.5 MiB. Regression test in TurnRecordingCapTests.

2. Loadout roster funds display lag MINOR FIXED

The shared "Players" roster panel sometimes showed a player's pre-purchase funds for a beat after buying. Cosmetic sync-timing issue, not a data bug.

Fix: BuyItemAsync, SellItemAsync, and ReorderLoadoutAsync in Loadout.razor.cs now call StateHasChanged() immediately after the hub call completes.

3. Client recording state not cleared after admin undo MINOR FIXED

After Undo Turn, the server rolled back the turn but the client kept showing 🎮 RECORDING with a stale tick count.

Fix: Added AdminActionDto to GameDtos.cs, wired an OnAdminAction event in GameHubConnection.cs, and registered a handler in MultiplayerGame.razor.cs that clears _turnTicks and re-arms recording on undo. Regression test in TurnRecordingCapTests.

Conclusion

The async PvP loop works end-to-end: lobby → loadout → turn recording → batch submission → deterministic replay → turn rotation across both players → admin undo/commit. All three issues found in this run have been fixed: the turn-batch size cap prevents SignalR disconnects, admin undo now clears client recording state, and loadout purchases update the display immediately.