86 lines
2.3 KiB
GDScript
86 lines
2.3 KiB
GDScript
extends Node
|
|
|
|
## NEO-25: fetches `GET /game/world/interactables`; exposes descriptor rows for world build and
|
|
## 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
|