diff --git a/client/scripts/autoloads/sim_bridge.gd b/client/scripts/autoloads/sim_bridge.gd index 0154ac915..aa3794948 100644 --- a/client/scripts/autoloads/sim_bridge.gd +++ b/client/scripts/autoloads/sim_bridge.gd @@ -75,9 +75,13 @@ func poll_snapshot() -> Variant: return null # Called by transport layer (ticket #79) when raw bytes arrive from the server. +# Latest-wins semantics: newer snapshots replace unconsumed ones. This is correct +# for real-time rendering (stale frames are worthless). Upgrade to queue if needed. func receive_bytes(bytes: PackedByteArray) -> void: var snapshot = Protocol.decode_snapshot(bytes) if snapshot != null: + if _last_snapshot != null: + push_warning("SimBridge: overwriting unconsumed snapshot (tick %s replaced by %s)" % [_last_snapshot.tick, snapshot.tick]) _last_snapshot = snapshot # Drain the outbound buffer. Called by transport layer (ticket #79) to get encoded messages. diff --git a/client/scripts/protocol/protocol.gd b/client/scripts/protocol/protocol.gd index 8bfdfd8e2..be31cece7 100644 --- a/client/scripts/protocol/protocol.gd +++ b/client/scripts/protocol/protocol.gd @@ -26,17 +26,25 @@ static func decode_snapshot(bytes: PackedByteArray) -> Variant: return null var entities: Array[Dictionary] = [] - for raw_entity in raw["entities"]: + var raw_entities: Array = raw["entities"] + var dropped := 0 + for raw_entity in raw_entities: var entity = _decode_entity(raw_entity) if entity != null: entities.append(entity) + else: + dropped += 1 + + if dropped > 0: + push_error("Protocol: %d/%d entities failed to decode (D-010 information boundary violation)" % [dropped, raw_entities.size()]) # GDScript int is signed 64-bit. Rust tick is u64 but will not exceed 2^63 - # in any realistic scenario (would require ~29 billion years at 10 ticks/min). + # in any realistic scenario (would require ~29 billion years at 10 ticks/game-minute per D-031). var tick: int = raw["tick"] return { "tick": tick, "entities": entities, + "decode_errors": dropped, } diff --git a/client/tests/test_protocol.gd b/client/tests/test_protocol.gd index 1a87fbe5c..e574bf318 100644 --- a/client/tests/test_protocol.gd +++ b/client/tests/test_protocol.gd @@ -164,7 +164,6 @@ func test_decode_player_input_empty_bytes() -> void: assert_that(result).is_null() -func test_encode_returns_empty_on_failure() -> void: - # Verify that a valid encode produces non-empty bytes +func test_encode_produces_nonempty_bytes() -> void: var bytes = Protocol.encode_player_input(1, "MoveNorth") assert_that(bytes.size()).is_greater(0)