feat(simulation): add NPC name masking with role labels and color index

Server-side infrastructure for information asymmetry in dialogue.
NPCs display role labels (Worker, Supervisor, Patron) instead of
real names until the player explicitly learns them via KG lookup.
NpcColorIndex (stable_id % 8) persists across name reveal.

ConversationEvent and DialogueResponseEvent carry display names +
color indices on the wire with serde(default) for compat.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-21 13:42:59 +01:00
co-authored by Claude Opus 4.6
parent 82e58559ba
commit 28e7e6d9ad
12 changed files with 446 additions and 63 deletions
+2
View File
@@ -363,6 +363,8 @@ mod tests {
line_id: "line_test".into(),
text: "Welcome to the docks.".into(),
speaker_entity_id: 100,
speaker_color_index: 0,
speaker_name: "Dock Worker".into(),
});
let text = format_snapshot_text(&snap);
assert!(text.contains("Dialogue: [npc:100] \"Welcome to the docks.\""));
+9
View File
@@ -358,6 +358,9 @@ pub enum PlayerAction {
ToggleStanceUp,
/// Move one step down the stance ladder (toward Crouch) per D-053
ToggleStanceDown,
/// Update player facing without movement (D-054). Client sends when
/// the player turns in place (e.g. mouse aim, turn keys).
SetFacing { facing: String },
/// Teleport player to the Gauntlet hub spawn point (#491).
/// Clears dialogue, monologue, and interaction buffers.
/// Rejected with a log warning on non-Gauntlet maps.
@@ -500,6 +503,12 @@ pub struct DialogueResponseEvent {
pub text: String,
/// Wire-format entity identifier of the speaking NPC
pub speaker_entity_id: u64,
/// Color index (0-7) for the speaker's dialogue box header.
#[serde(default)]
pub speaker_color_index: u8,
/// Display name of the speaker (real name if known to player, else role label).
#[serde(default)]
pub speaker_name: String,
}
/// Snapshot buffer resource for staging outgoing ObserverSnapshots