feat(client): upgrade protocol decoder and GameState for v2 snapshot
Server shipped ObserverSnapshot v2 with game_time, player_facing, visible_tiles (with visibility sectors), and per-entity visibility. Protocol decoder was silently ignoring these fields. Now extracts all v2 data with null defaults for backward compatibility. GameState gains game_time, player_facing, visibility_sectors vars. Derives visible_positions from visible_tiles when present (for real server mode). Test snapshot updated with v2 fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,9 @@ class_name Protocol
|
||||
# -- Decode: bytes from server → GDScript types --------------------------------
|
||||
|
||||
## Decode an ObserverSnapshot from MessagePack bytes.
|
||||
## Returns { "tick": int, "entities": Array[Dictionary] } or null on error.
|
||||
## Returns decoded snapshot Dictionary or null on error.
|
||||
## v2 fields (version, game_time, player_facing, visible_tiles) default to null/empty
|
||||
## when decoding v1 snapshots for backward compatibility.
|
||||
static func decode_snapshot(bytes: PackedByteArray) -> Variant:
|
||||
var result = Messagepack.decode(bytes)
|
||||
if result.status != null:
|
||||
@@ -41,10 +43,41 @@ static func decode_snapshot(bytes: PackedByteArray) -> Variant:
|
||||
# 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/game-minute per D-031).
|
||||
var tick: int = raw["tick"]
|
||||
|
||||
# v2 fields — optional for backward compatibility
|
||||
var version: Variant = raw.get("version")
|
||||
var game_time: Variant = raw.get("game_time")
|
||||
|
||||
# player_facing: FacingDirection is a unit enum → bare string in rmp_serde
|
||||
var player_facing: Variant = null
|
||||
var raw_facing: Variant = raw.get("player_facing")
|
||||
if raw_facing is String:
|
||||
player_facing = raw_facing
|
||||
|
||||
# visible_tiles: Array of {x, y, z, visibility}
|
||||
var visible_tiles: Array = []
|
||||
var raw_vtiles: Variant = raw.get("visible_tiles")
|
||||
if raw_vtiles is Array:
|
||||
for raw_tile in raw_vtiles:
|
||||
if raw_tile is Dictionary and raw_tile.has("x") and raw_tile.has("y") and raw_tile.has("z"):
|
||||
var tile_entry := {
|
||||
"x": int(raw_tile["x"]),
|
||||
"y": int(raw_tile["y"]),
|
||||
"z": int(raw_tile["z"]),
|
||||
}
|
||||
var vis: Variant = raw_tile.get("visibility")
|
||||
if vis is String:
|
||||
tile_entry["visibility"] = vis
|
||||
visible_tiles.append(tile_entry)
|
||||
|
||||
return {
|
||||
"tick": tick,
|
||||
"entities": entities,
|
||||
"decode_errors": dropped,
|
||||
"version": version,
|
||||
"game_time": game_time,
|
||||
"player_facing": player_facing,
|
||||
"visible_tiles": visible_tiles,
|
||||
}
|
||||
|
||||
|
||||
@@ -56,12 +89,20 @@ static func _decode_entity(raw: Dictionary) -> Variant:
|
||||
return null
|
||||
|
||||
var entity_id: int = raw["entity_id"]
|
||||
|
||||
# v2: visibility sector (Forward/Peripheral). null for v1 entities.
|
||||
var visibility: Variant = null
|
||||
var raw_vis: Variant = raw.get("visibility")
|
||||
if raw_vis is String:
|
||||
visibility = raw_vis
|
||||
|
||||
return {
|
||||
"entity_id": entity_id,
|
||||
"x": float(raw["x"]),
|
||||
"y": float(raw["y"]),
|
||||
"z": int(raw["z"]),
|
||||
"kind": _decode_enum_variant(raw["kind"]),
|
||||
"visibility": visibility,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user