extends SceneTree
## Gate: a null field in the daemon's identity reply never becomes the text
## "<null>" in presence (hyper-games #89 §3.4 / defect 8).
##
## presence.gd stored identity fields with str(): str(null) is "<null>", so
## - displayName: null -> presence entry {"name": "<null>"}, shown as a name;
## - memberId: null -> _my_member_id "<null>", which passes the `== ""`
## guard, and the game announces itself under presence:<null>.
## keet-core leaves an unnamed profile's displayName unset/null, which is every
## fresh identity.
##
## Run with no daemon: HYPERTPS_DAEMON_TCP=127.0.0.1:1.
var ok := true
var _frames := 0
func _p(c: bool, m: String) -> void:
print(("ok " if c else "FAIL: ") + m)
if not c:
ok = false
func _process(_delta: float) -> bool:
# Presence wires itself up with call_deferred; give it a frame.
_frames += 1
if _frames < 3:
return false
_run()
print("GATE presence_null_identity: %s" % ("PASS" if ok else "FAIL"))
quit(0 if ok else 1)
return true
func _run() -> void:
var pr: Node = root.get_node_or_null("Presence")
_p(pr != null, "Presence autoload present")
if pr == null:
return
pr._on_identity_loaded({"memberId": "m1abcdef", "displayName": null, "username": null})
_p(pr._my_member_id == "m1abcdef", "memberId kept (got %s)" % pr._my_member_id)
_p(pr._my_display_name == "", "null displayName/username -> no name, not \"<null>\" (got '%s')" % pr._my_display_name)
pr._on_identity_loaded({"memberId": "m2abcdef", "displayName": null, "username": "fleeky1"})
_p(pr._my_display_name == "fleeky1", "null displayName falls back to username (got '%s')" % pr._my_display_name)
pr._on_identity_loaded({"memberId": null, "displayName": "clode"})
_p(pr._my_member_id == "", "null memberId -> empty, so nothing is announced under presence:<null> (got '%s')" % pr._my_member_id)