OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / addons / keet_social / keet_names.gd

51 lines · gd ref:
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"))