mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
fix(multiplayer): stop recovery after completion
This commit is contained in:
@@ -465,7 +465,7 @@ func _set_websocket_status(status: String) -> void:
|
||||
_websocket_status = status
|
||||
websocket_status_changed.emit(status)
|
||||
if status == "CONNECTED":
|
||||
if not state.ticket_id.is_empty() and state.phase not in [MatchmakingState.CANCELLED, MatchmakingState.EXPIRED, MatchmakingState.FAILED, MatchmakingState.LIVE]:
|
||||
if not state.ticket_id.is_empty() and state.phase not in [MatchmakingState.CANCELLED, MatchmakingState.EXPIRED, MatchmakingState.FAILED, MatchmakingState.LIVE, MatchmakingState.COMPLETED]:
|
||||
var resource_id := state.proposal_id if not state.proposal_id.is_empty() else state.ticket_id
|
||||
if _operation.is_empty():
|
||||
_run_resync(resource_id)
|
||||
|
||||
@@ -5,14 +5,15 @@ const MatchmakingState = preload("res://scripts/matchmaking_state.gd")
|
||||
|
||||
|
||||
func test_every_backend_phase_has_a_nonempty_user_message() -> void:
|
||||
for phase in [MatchmakingState.IDLE, MatchmakingState.QUEUED, MatchmakingState.PROPOSED, MatchmakingState.ALLOCATING, MatchmakingState.PROCESS_READY, MatchmakingState.ASSIGNMENT_READY, MatchmakingState.CONNECTING, MatchmakingState.LIVE, MatchmakingState.CANCELLED, MatchmakingState.EXPIRED, MatchmakingState.FAILED]:
|
||||
for phase in [MatchmakingState.IDLE, MatchmakingState.QUEUED, MatchmakingState.PROPOSED, MatchmakingState.ACCEPTED, MatchmakingState.ALLOCATING, MatchmakingState.PROCESS_READY, MatchmakingState.ASSIGNMENT_READY, MatchmakingState.ASSIGNED, MatchmakingState.CONNECTING, MatchmakingState.LIVE, MatchmakingState.RESULT_PENDING, MatchmakingState.COMPLETED, MatchmakingState.CANCELLED, MatchmakingState.EXPIRED, MatchmakingState.FAILED]:
|
||||
assert_true(not Matchmaking.phase_label(phase).is_empty(), "phase %s has visible copy" % phase)
|
||||
|
||||
|
||||
func test_terminal_state_policy_does_not_leave_cancel_or_proposal_actions_enabled() -> void:
|
||||
for phase in [MatchmakingState.CANCELLED, MatchmakingState.EXPIRED, MatchmakingState.FAILED, MatchmakingState.LIVE]:
|
||||
for phase in [MatchmakingState.CANCELLED, MatchmakingState.EXPIRED, MatchmakingState.FAILED, MatchmakingState.LIVE, MatchmakingState.COMPLETED]:
|
||||
assert_true(Matchmaking._is_terminal(phase), "phase %s is terminal" % phase)
|
||||
assert_true(not Matchmaking._is_terminal(MatchmakingState.QUEUED), "queued search remains active")
|
||||
assert_true(not Matchmaking._is_terminal(MatchmakingState.PROPOSED), "proposal remains actionable")
|
||||
assert_true(Matchmaking._can_start_new_search(MatchmakingState.FAILED), "failed search can be retried")
|
||||
assert_true(not Matchmaking._can_start_new_search(MatchmakingState.LIVE), "live match cannot start a second search")
|
||||
assert_true(Matchmaking._can_start_new_search(MatchmakingState.COMPLETED), "completed match can start a new search")
|
||||
|
||||
@@ -1540,3 +1540,5 @@ The Godot queue projection now includes the contract's `ACCEPTED` ticket phase.
|
||||
The queue projection now also accepts the contract's post-allocation/result states (`ASSIGNED`, `RESULT_PENDING`, and `COMPLETED`). These states remain visible, cannot issue queue cancellation, and completed matches return the search action to a valid new-search state; adversarial lifecycle and WebSocket vocabulary tests cover them.
|
||||
|
||||
Client ticket updates now enforce the versioned legal transition graph as well as revision ordering. Same-state heartbeat revisions remain valid, while higher-revision jumps and rewinds request authoritative recovery without mutating the visible phase; adversarial tests cover both boundaries.
|
||||
|
||||
Reconnect recovery now treats `COMPLETED` as terminal, avoiding a needless queue read after a finished match. UI policy tests cover the complete expanded lifecycle, including the completed-to-new-search boundary.
|
||||
|
||||
Reference in New Issue
Block a user