neon-sprawl/client/scripts/interactables_catalog_clien...

85 lines
2.3 KiB
GDScript

extends Node
## NEO-25: fetches `GET /game/world/interactables` and exposes descriptor rows for world build + glow preview.
signal catalog_ready(descriptors: Array)
signal catalog_failed(reason: String)
@export var base_url: String = "http://127.0.0.1:5253"
var _http: HTTPRequest
var _busy: bool = false
func _ready() -> void:
_http = HTTPRequest.new()
add_child(_http)
_http.timeout = 30.0
_http.request_completed.connect(_on_request_completed)
func request_catalog() -> void:
if _busy:
return
_busy = true
var url := "%s/game/world/interactables" % _base_root()
var err: Error = _http.request(url)
if err != OK:
_busy = false
var msg := "InteractablesCatalogClient: GET failed to start (%s)" % err
push_error(msg)
catalog_failed.emit(msg)
func _base_root() -> String:
return base_url.strip_edges().rstrip("/")
func _on_request_completed(
_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray
) -> void:
_busy = false
var text := body.get_string_from_utf8()
if response_code != 200:
var msg := "InteractablesCatalogClient: HTTP %s body=%s" % [response_code, text]
push_error(msg)
catalog_failed.emit(msg)
return
var parsed: Variant = JSON.parse_string(text)
if not parsed is Dictionary:
var msg := "InteractablesCatalogClient: expected JSON object"
push_error(msg)
catalog_failed.emit(msg)
return
var root: Dictionary = parsed
var descriptors: Array = _parse_interactables_array(root)
if descriptors.is_empty():
var msg2 := "InteractablesCatalogClient: interactables missing or empty"
push_error(msg2)
catalog_failed.emit(msg2)
return
catalog_ready.emit(descriptors)
## Returns an [Array] of [Dictionary] rows: [code]interactableId[/code], [code]kind[/code],
## [code]anchor[/code] ([Dictionary] x,y,z), [code]interactionRadius[/code] ([float]).
static func parse_catalog_json(text: String) -> Array:
var parsed: Variant = JSON.parse_string(text)
if not parsed is Dictionary:
return []
return _parse_interactables_array(parsed)
static func _parse_interactables_array(root: Variant) -> Array:
if not root is Dictionary:
return []
var d: Dictionary = root
var raw: Variant = d.get("interactables", null)
if raw == null or not raw is Array:
return []
var out_arr: Array = []
for item in raw as Array:
if item is Dictionary:
out_arr.append(item)
return out_arr