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:
@@ -107,7 +107,7 @@ export const privateHandoutSchema = z.object({
|
||||
});
|
||||
export type PrivateHandout = z.infer<typeof privateHandoutSchema>;
|
||||
|
||||
export const rosterEntrySchema = z.object({ playerId: z.string(), name: z.string() });
|
||||
export const rosterEntrySchema = z.object({ playerId: z.string(), name: z.string(), character: z.string().optional() });
|
||||
export type RosterEntry = z.infer<typeof rosterEntrySchema>;
|
||||
|
||||
// ---- messages ----
|
||||
@@ -129,6 +129,8 @@ export const clientMessageSchema = z.discriminatedUnion('t', [
|
||||
z.object({ t: z.literal('privateState'), gmSecret: z.string(), targetPlayerId: z.string(), handout: privateHandoutSchema.nullable() }),
|
||||
// chat: table message (no `to`) or whisper. GM `to` = target playerId; player `to` set = whisper to GM.
|
||||
z.object({ t: z.literal('chat'), body: z.string().min(1).max(2000), to: z.string().optional() }),
|
||||
// a player sets their display name (shown in the roster + chat)
|
||||
z.object({ t: z.literal('setName'), name: z.string().max(40) }),
|
||||
]);
|
||||
export type ClientMessage = z.infer<typeof clientMessageSchema>;
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ function connect(): void {
|
||||
for (const [id, dataUrl] of sentImages) send({ t: 'image', gmSecret, id, dataUrl });
|
||||
} else if (msg.t === 'joined') {
|
||||
session.set({ role: 'player', status: 'connected', roomId: msg.roomId, error: null });
|
||||
const guestName = useSessionStore.getState().guestName.trim();
|
||||
if (guestName) send({ t: 'setName', name: guestName });
|
||||
} else if (msg.t === 'snapshot') {
|
||||
usePlayerSessionStore.getState().setSnapshot(msg.snapshot);
|
||||
// fetch the map image if we don't have it cached
|
||||
@@ -171,6 +173,11 @@ export function broadcastGmRoll(label: string, expression: string, total: number
|
||||
}
|
||||
}
|
||||
|
||||
/** Player: set/update the display name shown in the roster + chat. */
|
||||
export function sendSetName(name: string): void {
|
||||
if (useSessionStore.getState().role === 'player') send({ t: 'setName', name });
|
||||
}
|
||||
|
||||
/** Send a chat message. `to` set = whisper (GM → that playerId; player → the GM). */
|
||||
export function sendChat(body: string, to?: string): void {
|
||||
const text = body.trim();
|
||||
|
||||
Reference in New Issue
Block a user