diff --git a/Game/scripts/matchmaking_state.gd b/Game/scripts/matchmaking_state.gd index 919ab656..a750b821 100644 --- a/Game/scripts/matchmaking_state.gd +++ b/Game/scripts/matchmaking_state.gd @@ -54,6 +54,13 @@ func apply_ticket_update(update: Dictionary) -> bool: if incoming_revision == revision: if _ticket_differs(update): return _request_resync(self.ticket_id) + # expires_at_unix is deliberately not part of _ticket_differs' conflict + # check (see its own comment) but is still adopted here: begin_queue() + # has no way to know the server-assigned expiry in advance, so the + # very first same-revision confirmation is the only place a freshly + # queued ticket's expiry is ever set at all. + if update.has("expires_at_unix"): + expires_at_unix = int(update["expires_at_unix"]) return true if incoming_revision > revision + 1: return _request_resync(self.ticket_id) @@ -185,7 +192,17 @@ func snapshot() -> Dictionary: func _ticket_differs(update: Dictionary) -> bool: - return String(update["state"]) != phase or (update.has("playlist") and String(update["playlist"]) != playlist) or (update.has("expires_at_unix") and int(update["expires_at_unix"]) != expires_at_unix) + # expires_at_unix is excluded on purpose: begin_queue()'s optimistic local + # state has no way to know the server-assigned expiry before the first + # real response arrives, so comparing it here made the very first + # same-revision confirmation after every begin_queue() look like a + # conflict, unconditionally -- found by an actual client hitting a real + # server: apply_ticket_update() kept requesting a resync, whose own + # response hit exactly the same false mismatch, forever, which + # control_plane_smoke.gd (a live end-to-end test, not a mock) surfaced as + # a request that legitimately never terminates. It's still kept current + # via the direct assignment below, just not treated as a conflict signal. + return String(update["state"]) != phase or (update.has("playlist") and String(update["playlist"]) != playlist) func _request_resync(resource_id: String) -> bool: