feat(client): enforce PROTOCOL_VERSION check in snapshot decode

Client now rejects snapshots where version != PROTOCOL_VERSION (4).
Returns null with error log on mismatch. Test snapshot updated to
use Protocol.PROTOCOL_VERSION and v4 game_time format (tick_rate
replaces paused field).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-12 23:32:49 +01:00
co-authored by Claude Opus 4.6
parent 18d8253bfe
commit c05ff7b063
2 changed files with 13 additions and 4 deletions
+2 -2
View File
@@ -296,12 +296,12 @@ func _test_snapshot() -> Dictionary:
return {
"tick": _test_tick,
"version": 2,
"version": Protocol.PROTOCOL_VERSION,
"game_time": {
"day": 0,
"time_of_day": _test_tick * 10,
"day_phase": "Morning",
"paused": false,
"tick_rate": "Full",
},
"player_facing": _test_facing,
"entities": entities,
+11 -2
View File
@@ -9,6 +9,10 @@ class_name Protocol
## Unit enum variants (no data) → bare strings ("MoveNorth", "Npc")
## Data enum variants → single-element maps ({"UsePerceptionMode": "thermal"})
## Protocol version — must match server PROTOCOL_VERSION in bridge/types.rs.
## Reject snapshots where version != this value.
const PROTOCOL_VERSION: int = 4
# -- Decode: bytes from server → GDScript types --------------------------------
@@ -27,6 +31,12 @@ static func decode_snapshot(bytes: PackedByteArray) -> Variant:
push_error("Protocol: snapshot missing required fields")
return null
# Version check: reject snapshots from incompatible server
var version: Variant = raw.get("version")
if version != PROTOCOL_VERSION:
push_error("Protocol: version mismatch (got %s, expected %s). Server and client are out of sync." % [version, PROTOCOL_VERSION])
return null
var entities: Array[Dictionary] = []
var raw_entities: Array = raw["entities"]
var dropped := 0
@@ -44,8 +54,7 @@ static func decode_snapshot(bytes: PackedByteArray) -> Variant:
# in any realistic scenario (would require ~29 billion years at 10 ticks/game-minute per D-031).
var tick: int = raw["tick"]
# v2 fields — optional for backward compatibility
var version: Variant = raw.get("version")
# version already checked above; game_time for HUD display
var game_time: Variant = raw.get("game_time")
# player_facing: FacingDirection is a unit enum → bare string in rmp_serde