extends RefCounted
## How a keet member's name is DISPLAYED in-game (hyper-games #89 §3.3/§3.4).
##
## keet has ONE name per identity — the private-profile displayName, which
## keet-core copies into every room's member record. So the game never invents
## a name. When a member genuinely has none, it shows a short label that is
## plainly not a name: "anon-" + the first 4 characters of the member id.
## Never "Player" (a hard-coded default that made every stranger look the
## same) and never a full key.
##
## Used via preload (no class_name), so it works without refreshing Godot's
## global class cache.
const ANON_PREFIX := "anon-"
## A usable name, or "" when the value is null / not a string / blank.
static func clean(name: Variant) -> String:
if name is String:
return (name as String).strip_edges()
if name is StringName:
return String(name).strip_edges()
return ""
## The label to show for a member: their keet name, else anon-<4 of member id>.
static func display(name: Variant, member_id: Variant) -> String:
var n := clean(name)
var id := clean(member_id)
# ⚠ keet-daemon's `read` and `members` still fill a missing name with the
# member id itself (`memberId.slice(0, 8)` / `memberId`). A "name" that is
# just a prefix of the member id is therefore NOT a name. (#89 §3.1 removes
# that on the daemon side; this keeps older daemons rendering correctly.)
if not n.is_empty() and not (not id.is_empty() and id.begins_with(n)):
return n
return ANON_PREFIX + (id.left(4) if not id.is_empty() else "????")
## The sender label for a chat message as keet-daemon's `read` returns it:
## FLAT {memberId, name, text}. Tolerates the older nested {sender:{displayName,
## username}} shape so a daemon on either side of that change still renders.
static func for_message(msg: Dictionary) -> String:
var name: Variant = msg.get("name")
if clean(name).is_empty():
var sender: Variant = msg.get("sender")
if sender is Dictionary:
name = sender.get("displayName")
if clean(name).is_empty():
name = sender.get("username")
return display(name, msg.get("memberId"))