fix(multiplayer): enforce client state transitions

This commit is contained in:
Josh Creek
2026-09-01 21:57:13 +01:00
parent 30a5a89164
commit 0f1864f8bc
3 changed files with 43 additions and 2 deletions
+20
View File
@@ -74,6 +74,8 @@ func apply_ticket_update(update: Dictionary) -> bool:
var incoming_state := String(update["state"])
if not _is_ticket_state(incoming_state):
return _request_resync(self.ticket_id)
if not _is_legal_ticket_transition(phase, incoming_state):
return _request_resync(self.ticket_id)
revision = incoming_revision
phase = incoming_state
if update.has("playlist"):
@@ -248,5 +250,23 @@ func _is_ticket_state(value: String) -> bool:
return value in [QUEUED, PROPOSED, ACCEPTED, ALLOCATING, PROCESS_READY, ASSIGNMENT_READY, ASSIGNED, CONNECTING, LIVE, RESULT_PENDING, COMPLETED, CANCELLED, EXPIRED, FAILED]
func _is_legal_ticket_transition(from: String, to: String) -> bool:
if from == to:
return true
var transitions := {
QUEUED: [PROPOSED, CANCELLED, EXPIRED],
PROPOSED: [QUEUED, ACCEPTED, CANCELLED, EXPIRED],
ACCEPTED: [QUEUED, ALLOCATING, CANCELLED, FAILED],
ALLOCATING: [PROCESS_READY, FAILED, CANCELLED],
PROCESS_READY: [ASSIGNMENT_READY, FAILED, CANCELLED],
ASSIGNMENT_READY: [ASSIGNED, FAILED, CANCELLED],
ASSIGNED: [CONNECTING, FAILED, CANCELLED],
CONNECTING: [LIVE, FAILED, EXPIRED],
LIVE: [RESULT_PENDING, FAILED],
RESULT_PENDING: [COMPLETED, FAILED],
}
return transitions.has(from) and to in transitions[from]
func _has_string(value: Dictionary, key: String) -> bool:
return value.has(key) and value[key] is String and not String(value[key]).is_empty()