diff --git a/src/views/ChengduGamePage.vue b/src/views/ChengduGamePage.vue index 6ee8074..45d38dd 100644 --- a/src/views/ChengduGamePage.vue +++ b/src/views/ChengduGamePage.vue @@ -83,7 +83,7 @@ const startGamePending = ref(false) const dingQuePending = ref(false) let clockTimer: number | null = null let unsubscribe: (() => void) | null = null -let pendingRoomInfoRequest = false +let needsInitialRoomInfo = false const menuOpen = ref(false) const isTrustMode = ref(false) @@ -352,7 +352,7 @@ const showDingQueChooser = computed(() => { return false } - if (gameStore.phase === 'waiting' || gameStore.phase === 'settlement') { + if (gameStore.phase === 'settlement') { return false } @@ -568,18 +568,14 @@ function requestRoomInfo(): void { const routeRoomId = typeof route.params.roomId === 'string' ? route.params.roomId : '' const roomId = routeRoomId || gameStore.roomId || activeRoom.value?.roomId || '' if (!roomId) { - pendingRoomInfoRequest = true - wsMessages.value.push('[client] get_room_info pending: missing roomId') return } if (wsStatus.value !== 'connected') { - pendingRoomInfoRequest = true - wsMessages.value.push(`[client] get_room_info pending: ws=${wsStatus.value}`) return } - pendingRoomInfoRequest = false + needsInitialRoomInfo = false wsMessages.value.push(`[client] get_room_info ${roomId}`) sendWsMessage({ type: 'get_room_info', @@ -920,7 +916,7 @@ const wallSeats = computed>(() => { left: emptyWallSeat(), } - if (gameStore.phase === 'waiting') { + if (gameStore.phase === 'waiting' && myHandTiles.value.length === 0) { return emptyState } @@ -1249,6 +1245,59 @@ function handleReadyStateResponse(message: unknown): void { } } +function handlePlayerDingQueResponse(message: unknown): void { + if (!message || typeof message !== 'object') { + return + } + + const source = message as Record + if (typeof source.type !== 'string') { + return + } + + if (normalizeWsType(source.type) !== 'PLAYER_DING_QUE') { + return + } + + const payload = asRecord(source.payload) + if (!payload) { + return + } + + const roomId = + readString(payload, 'room_id', 'roomId') || + readString(source, 'roomId') + if (roomId && roomId !== gameStore.roomId) { + return + } + + const userId = + readString(payload, 'user_id', 'userId', 'player_id', 'playerId') || + readString(source, 'target') + const suit = readString(payload, 'suit', 'Suit') + + if (!userId || !suit) { + return + } + + const player = gameStore.players[userId] + if (player) { + player.missingSuit = suit + } + + const room = activeRoom.value + if (room && room.roomId === (roomId || gameStore.roomId)) { + const roomPlayer = room.players.find((item) => item.playerId === userId) + if (roomPlayer) { + roomPlayer.missingSuit = suit + } + } + + if (userId === loggedInUserId.value) { + dingQuePending.value = false + } +} + function logoutToLogin(): void { clearAuth() auth.value = null @@ -1558,18 +1607,20 @@ function hydrateFromActiveRoom(routeRoomId: string): void { onMounted(() => { const routeRoomId = typeof route.params.roomId === 'string' ? route.params.roomId : '' - pendingRoomInfoRequest = true + needsInitialRoomInfo = true void ensureCurrentUserLoaded().finally(() => { hydrateFromActiveRoom(routeRoomId) if (routeRoomId) { gameStore.roomId = routeRoomId } - requestRoomInfo() + if (wsStatus.value === 'connected' && needsInitialRoomInfo) { + requestRoomInfo() + } }) const handler = (status: WsStatus) => { wsStatus.value = status - if (status === 'connected' && pendingRoomInfoRequest) { + if (status === 'connected' && needsInitialRoomInfo) { requestRoomInfo() } } @@ -1580,6 +1631,7 @@ onMounted(() => { handleRoomInfoResponse(msg) handlePlayerHandResponse(msg) handleReadyStateResponse(msg) + handlePlayerDingQueResponse(msg) const gameAction = toGameAction(msg) if (gameAction) { dispatchGameAction(gameAction)