Skip to content

Spectator mode — development status & next steps #5

Description

@Vmarcelo49

Status: Code complete, pending runtime validation

All 5 phases of the spectator mode plan () are implemented and wired end-to-end, but never validated at runtime (requires Wine + MBAACC.exe).

What's done (code-level)

Phase Description Status
1 Protocol — message added to protocol ✅ Complete
2 Host-side — ported from CCCaster, integrated into NetworkThread ✅ Complete
2.5 NetworkThread integration — CONNECT/DISCONNECT handlers, re-enabled ✅ Re-enabled ()
3 Client-side — receives + + and replays ✅ Complete
4 Launcher/GUI — and GUI Spectate button working ✅ Complete
5 Relay spectate — via relay server ✅ Complete

Where we stopped

The spectator code was fully implemented in commits and (2026-07-14/15), including re-enabling the two DISABLERS that were blocking it in the network thread. Build is clean (MinGW cross-compile, zero warnings/errors).

What's missing is runtime validation — the feature has never been tested with actual Wine + MBAACC.exe.

Runtime validation matrix (pending)

  1. Regression test: host + join via localhost — must still work end-to-end (critical: previously caused a Wine regression)
  2. Direct spectate: host + join + 3rd instance as spectator via — spectator should receive SpectateConfig + InitialGameState + BothInputs stream and replay the match
  3. Relay spectate: — spectator connects via relay, host identifies as spectator, replay works
  4. Spectator disconnect mid-match — host's SpectatorManager removes spectator via , no crash, no impact on ongoing match
  5. Opponent disconnect mid-match with spectator connected — spectator should also be disconnected or notified

Known minor pendings (non-blocking for basic spectate)

  • SpectatorManager::step() detects pending spectator timeout but only does _pending.erase(peer) — no enet_peer_disconnect_later call. Relies on spectator's own client-side timeout.
  • frameStepRerun not adapted for spectator — may work as-is (spectator has no local inputs to predict), but needs runtime confirmation.
  • getInput() dispatcher has no explicit SpectateNetplay path — returns 0 by default (correct for spectator), but unverified at runtime.
  • SyncHash received by spectator is intentionally discarded — no desync detection for spectators by design.

Next steps

References

  • Full plan: docs/spectator-plan.md
  • Threading prerequisite: docs/threading-migration.md (Layer 4 — complete)
  • Key commits: 027d9ee (initial implementation), 3fd525e (re-enablement)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions