P14d: guest display names for players
- Players set a display name in the session panel ("Your name"); it persists
(sessionStore.guestName) and is sent via a new `setName` message on join + edit.
- Server stores the name per connection and uses it in the roster + chat; the roster
entry now also carries the player's character, so the GM sees "Alice · Lia".
- Realtime e2e: a player names themselves and the GM's roster/share update to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+17
-4
@@ -54,7 +54,7 @@ function timingEqual(a: string, b: string): boolean {
|
||||
export class RoomHub {
|
||||
private rooms = new Map<string, Room>();
|
||||
private byCode = new Map<string, string>();
|
||||
private conns = new Map<Sender, { roomId: string; role: 'gm' | 'player'; playerId: string }>();
|
||||
private conns = new Map<Sender, { roomId: string; role: 'gm' | 'player'; playerId: string; name?: string }>();
|
||||
constructor(private now: () => number = () => Date.now()) {}
|
||||
|
||||
private mintJoinCode(): string {
|
||||
@@ -175,20 +175,33 @@ export class RoomHub {
|
||||
|
||||
/** Tell everyone (GM + players) the current roster: the GM (if present) + players. */
|
||||
private sendRoster(room: Room): void {
|
||||
const players: { playerId: string; name: string }[] = [];
|
||||
const players: { playerId: string; name: string; character?: string }[] = [];
|
||||
if (room.gm) players.push({ playerId: 'gm', name: 'GM' });
|
||||
const seen = new Set<string>();
|
||||
for (const s of room.players) {
|
||||
const conn = this.conns.get(s);
|
||||
if (!conn || seen.has(conn.playerId)) continue;
|
||||
seen.add(conn.playerId);
|
||||
players.push({ playerId: conn.playerId, name: room.seats.get(conn.playerId)?.name ?? `Player ${conn.playerId.slice(0, 4)}` });
|
||||
const seatName = room.seats.get(conn.playerId)?.name;
|
||||
const name = conn.name ?? seatName ?? `Player ${conn.playerId.slice(0, 4)}`;
|
||||
players.push({ playerId: conn.playerId, name, ...(conn.name && seatName ? { character: seatName } : {}) });
|
||||
}
|
||||
const msg = { t: 'roster', players } as const;
|
||||
room.gm?.send(msg);
|
||||
for (const p of room.players) p.send(msg);
|
||||
}
|
||||
|
||||
/** A player sets their display name (roster + chat). */
|
||||
setName(socket: Sender, name: string): void {
|
||||
const conn = this.conns.get(socket);
|
||||
const room = conn ? this.rooms.get(conn.roomId) : undefined;
|
||||
if (!conn || conn.role !== 'player' || !room) return;
|
||||
const trimmed = name.trim().slice(0, 40);
|
||||
if (trimmed) conn.name = trimmed; else delete conn.name;
|
||||
room.lastActivity = this.now();
|
||||
this.sendRoster(room);
|
||||
}
|
||||
|
||||
/** A seated player edits their own sheet; the diff is forwarded to the GM only. */
|
||||
playerPatch(socket: Sender, characterId: string, diff: PartialCharacterDiff): void {
|
||||
const conn = this.conns.get(socket);
|
||||
@@ -237,7 +250,7 @@ export class RoomHub {
|
||||
for (const p of room.players) p.send(msg);
|
||||
}
|
||||
} else {
|
||||
const from = room.seats.get(conn.playerId)?.name ?? `Player ${conn.playerId.slice(0, 4)}`;
|
||||
const from = conn.name ?? room.seats.get(conn.playerId)?.name ?? `Player ${conn.playerId.slice(0, 4)}`;
|
||||
if (to) {
|
||||
room.gm?.send({ t: 'chat', from, body, scope: 'whisper' });
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user