refactor(game): 重构游戏状态管理和WebSocket通信

- 定义统一的游戏动作类型GameAction替代原有发送函数
- 创建游戏状态管理store使用Pinia进行状态管理
- 实现游戏状态分发器处理各种游戏事件
- 重构WebSocket处理器支持多处理器注册
- 重命名状态类型文件统一使用State后缀
- 添加ACTION游戏阶段处理操作窗口逻辑
- 集成Pinia依赖管理应用状态
This commit is contained in:
2026-03-25 15:19:28 +08:00
parent 4a9b2f2db2
commit 2737971608
17 changed files with 334 additions and 178 deletions

105
src/store/gameStore.ts Normal file
View File

@@ -0,0 +1,105 @@
import { defineStore } from 'pinia'
import {
GAME_PHASE,
type GameState,
type PendingClaimState,
} from '../types/state'
import type { Tile } from '../types/tile'
export const useGameStore = defineStore('game', {
state: (): GameState => ({
roomId: '',
phase: GAME_PHASE.WAITING,
dealerIndex: 0,
currentTurn: 0,
players: {},
remainingTiles: 0,
pendingClaim: undefined,
winners: [],
scores: {},
}),
actions: {
// 初始化
initGame(data: GameState) {
Object.assign(this, data)
},
// 摸牌
onDrawTile(data: { playerId: string; tile: Tile }) {
const player = this.players[data.playerId]
if (!player) return
// 只更新自己的手牌
if (player.playerId === this.getMyPlayerId()) {
player.handTiles.push(data.tile)
}
// 剩余牌数减少
this.remainingTiles = Math.max(0, this.remainingTiles - 1)
// 更新回合seatIndex
this.currentTurn = player.seatIndex
// 清除操作窗口
this.pendingClaim = undefined
// 进入出牌阶段
this.phase = GAME_PHASE.PLAYING
},
// 出牌
onPlayTile(data: {
playerId: string
tile: Tile
nextSeat: number
}) {
const player = this.players[data.playerId]
if (!player) return
// 如果是自己,移除手牌
if (player.playerId === this.getMyPlayerId()) {
const index = player.handTiles.findIndex(
(t) => t.id === data.tile.id
)
if (index !== -1) {
player.handTiles.splice(index, 1)
}
}
// 加入出牌区
player.discardTiles.push(data.tile)
// 更新回合
this.currentTurn = data.nextSeat
// 等待其他玩家响应
this.phase = GAME_PHASE.ACTION
},
// 触发操作窗口(碰/杠/胡)
onPendingClaim(data: PendingClaimState) {
this.pendingClaim = data
this.phase = GAME_PHASE.ACTION
},
// 清理操作窗口
clearPendingClaim() {
this.pendingClaim = undefined
this.phase = GAME_PHASE.PLAYING
},
// 获取当前玩家ID后续建议放到 userStore
getMyPlayerId(): string {
return Object.keys(this.players)[0] || ''
},
},
})