extends SceneTree
## Gate: in-game chat shows the sender's keet name (hyper-games #89 §3.4).
##
## keet-daemon's `read` returns messages FLAT: {memberId, name, text, …}
## (router.js _read: `name: nameMap[memberId] || memberId.slice(0, 8)`). The
## overlay looked for msg.sender.displayName / .username, found neither, and
## printed "?" for EVERY received line.
##
## It also echoed its own sends optimistically under a hard-coded "Player"
## default, and the poll then showed the real message a second time: KeetChat's
## dedup only knows ids it has POLLED, and the optimistic line has none.
##
## Run with no daemon: HYPERTPS_DAEMON_TCP=127.0.0.1:1 makes KeetService's
## client fail to connect harmlessly instead of talking to whatever daemon
## happens to be on this machine.
var ok := true
var _ran := false
func _p(c: bool, m: String) -> void:
print(("ok " if c else "FAIL: ") + m)
if not c:
ok = false
func _process(_delta: float) -> bool:
if _ran:
return true
_ran = true
_run()
print("GATE chat_names: %s" % ("PASS" if ok else "FAIL"))
quit(0 if ok else 1)
return true
func _last_line(log: RichTextLabel) -> String:
var lines := log.get_parsed_text().strip_edges().split("\n")
return lines[lines.size() - 1] if lines.size() > 0 else ""
func _run() -> void:
var scene := load("res://packs/keet_chat/chat_overlay.tscn") as PackedScene
_p(scene != null, "chat overlay scene loads")
if scene == null:
return
var overlay: Node = scene.instantiate()
root.add_child(overlay)
var log: RichTextLabel = overlay.get_node("ChatPanel/VBox/ChatLog")
# 1. The daemon's shape: a flat name.
overlay._append_msg({"memberId": "q1w2e3r4t5y6", "name": "clode", "text": "hi"})
_p(_last_line(log) == "clode: hi", "daemon message shows its sender name (got %s)" % _last_line(log))
# 2. A member with no keet name: a short anon label, never "?" or "Player".
overlay._append_msg({"memberId": "abcd1234efgh5678", "name": null, "text": "yo"})
_p(_last_line(log) == "anon-abcd: yo", "nameless member shows anon-<4> (got %s)" % _last_line(log))
# 2b. Today's daemon fills a missing name with memberId.slice(0, 8). That is a
# key fragment, not a name, and must render as anon too.
overlay._append_msg({"memberId": "wxyz98765432", "name": "wxyz9876", "text": "yo2"})
_p(_last_line(log) == "anon-wxyz: yo2", "id-prefix placeholder shows anon-<4> (got %s)" % _last_line(log))
# 3. Sending does not echo optimistically: the polled copy is the only copy.
var input: LineEdit = overlay.get_node("ChatPanel/VBox/InputRow/MessageInput")
input.text = "hello-from-me"
overlay._send()
_p(not log.get_parsed_text().contains("hello-from-me"), "send adds no optimistic line (it would be shown twice)")
# 4. The hard-coded default is gone everywhere in this view.
_p(not log.get_parsed_text().contains("Player"), "no \"Player\" anywhere in the chat log")
overlay.queue_free()