diff --git a/web-client/src/scenes/boot-scene.js b/web-client/src/scenes/boot-scene.js index b785535..0b36493 100644 --- a/web-client/src/scenes/boot-scene.js +++ b/web-client/src/scenes/boot-scene.js @@ -24,9 +24,14 @@ export class BootScene extends Phaser.Scene { // Connect to server connectionService.connect(); - // Transition to menu once server prompts for nickname - eventBus.on(ClientEventCode.NICKNAME_SET, () => { + // Transition to menu once server prompts for nickname. Server emits + // NICKNAME_SET both as the initial prompt AND on validation rejection, + // so unsubscribe after the first hit — otherwise later rejections would + // bounce the scene back to MenuScene (restart loop). + const onPrompt = () => { + eventBus.off(ClientEventCode.NICKNAME_SET, onPrompt); this.scene.start('MenuScene'); - }); + }; + eventBus.on(ClientEventCode.NICKNAME_SET, onPrompt); } } diff --git a/web-client/src/ui/menu-ui.js b/web-client/src/ui/menu-ui.js index 9df56dc..4af666f 100644 --- a/web-client/src/ui/menu-ui.js +++ b/web-client/src/ui/menu-ui.js @@ -7,6 +7,7 @@ import { connectionService } from '../services/connection-service.js'; import { eventBus } from '../services/event-bus.js'; import { gameState } from '../services/game-state-service.js'; import { ServerEventCode, ClientEventCode } from '../config/protocol-constants.js'; +import { showToast } from './game-ui.js'; const overlay = () => document.getElementById('ui-overlay'); @@ -178,3 +179,14 @@ eventBus.on(ClientEventCode.ROOM_CREATE_SUCCESS, (data) => { }); eventBus.on(ClientEventCode.CLIENT_EXIT, showLobby); eventBus.on(ClientEventCode.CLIENT_KICK, showLobby); + +// Server emits NICKNAME_SET as rejection when the submitted nickname fails +// length validation (payload: { invalidLength: N }). Surface it as a toast +// and clear the optimistically-stored local nickname so we don't drift. +eventBus.on(ClientEventCode.NICKNAME_SET, (data) => { + if (data && typeof data === 'object' && 'invalidLength' in data) { + showToast(`Nickname must be 1–10 characters (got ${data.invalidLength})`, 'error'); + gameState.nickname = ''; + showNicknameScreen(); + } +});