UnoActions
UNO 插件自定义的 Action 类型与工厂函数。
概述
UNO 插件在引擎通用 Action(PLAY_CARD / DRAW_CARD / END_TURN / PASS)之外,新增两个专属 Action:
| Action 类型 | 常量 | 用途 |
|---|---|---|
CHOOSE_COLOR | CHOOSE_COLOR_ACTION | 玩家为刚打出的 Wild 牌指定颜色 |
UNO_FLIP_INITIAL | UNO_FLIP_INITIAL_ACTION | 游戏开始时翻出初始弃牌 |
UNO 还复用引擎内置的 PLAY_CARD_ACTION / DRAW_CARD_ACTION / END_TURN_ACTION,由 UnoPlugin 注册对应的 ActionHandler。
常量
| 名称 | 类型 | 值 |
|---|---|---|
CHOOSE_COLOR_ACTION | 'CHOOSE_COLOR' (as const) | 玩家选色 Action 类型 |
UNO_FLIP_INITIAL_ACTION | 'UNO_FLIP_INITIAL' (as const) | 翻初始弃牌 Action 类型 |
类型
ChooseColorPayload
ts
interface ChooseColorPayload {
color: UnoColorChoice
}CHOOSE_COLOR 的负载:玩家选择的颜色(必须是实色 red / yellow / green / blue,不能是 'wild')。
ChooseColorAction
ts
type ChooseColorAction = Action<typeof CHOOSE_COLOR_ACTION, ChooseColorPayload>UnoFlipInitialAction
ts
type UnoFlipInitialAction = Action<typeof UNO_FLIP_INITIAL_ACTION, Record<string, never>>无负载、无发起玩家的系统动作。
工厂函数
createChooseColorAction()
ts
function createChooseColorAction(
playerId: string,
color: UnoColorChoice
): ChooseColorAction创建 CHOOSE_COLOR Action。
参数
| 名称 | 类型 | 说明 |
|---|---|---|
playerId | string | 指定颜色的玩家 ID(即刚打出 Wild 牌的玩家) |
color | UnoColorChoice | 玩家选择的目标颜色 |
返回值
ChooseColorAction
示例
ts
import { createChooseColorAction } from 'decklet/uno'
const action = createChooseColorAction('p1', 'red')
// { type: 'CHOOSE_COLOR', playerId: 'p1', payload: { color: 'red' } }createUnoFlipInitialAction()
ts
function createUnoFlipInitialAction(): UnoFlipInitialAction创建 UNO_FLIP_INITIAL Action。
参数
无。
返回值
UnoFlipInitialAction:无 playerId、无有效 payload 的系统动作。
行为
由 handleGameStarted 在发完初始手牌后派发,从牌堆顶翻牌直到出现数字牌,该数字牌作为初始弃牌并决定起始颜色;非数字牌通过"移到弃牌堆再移回牌堆底部"的往返轮转至牌堆底,避免功能牌 / Wild 牌成为起始弃牌。
示例
ts
import { createUnoFlipInitialAction } from 'decklet/uno'
const action = createUnoFlipInitialAction()
// { type: 'UNO_FLIP_INITIAL', payload: {} }UNO 复用的基础 Action
UNO 出牌、抽牌、结束回合均通过引擎通用 Action 完成,由 UnoPlugin.actions 注册对应 ActionHandler:
| Action 类型 | 常量 | UNO 中的用途 | 工厂函数 |
|---|---|---|---|
PLAY_CARD | PLAY_CARD_ACTION | 玩家出一张牌到弃牌堆 | createPlayCardAction(playerId, cardIds) |
DRAW_CARD | DRAW_CARD_ACTION | 玩家从牌堆抽牌(初始发牌、罚抽、无牌可出时抽牌) | createDrawCardAction(playerId, count) |
END_TURN | END_TURN_ACTION | 结束当前玩家回合,推进到下家 | createEndTurnAction(playerId) |
PASS | PASS_ACTION | 玩家主动过牌(UNO 一般通过抽牌代替) | createPassAction(playerId) |
PLAY_CARD 在 UNO 中的特殊行为
UnoPlugin 注册的 playCardHandler(ActionHandler<PlayCardAction>):
- 校验
playerId与cardIds(恰一张),取出卡牌并移入 弃牌堆。 - 发出引擎通用
CARD_PLAYED与 UNO 专属UNO_CARD_PLAYED事件。 - 实色牌额外更新
UNO_VAR_CURRENT_COLOR并发出UNO_COLOR_CHANGED(reason='play');Wild 牌不在此更新颜色,留待CHOOSE_COLOR处理。
回合推进与胜负判定不在该 handler 完成,而是交由 handleCardPlayed 在 CARD_PLAYED 事件回调中根据卡牌类型派发对应 Effect。
示例:完整出牌 + 选色流程
ts
import {
GameEngine,
TurnPlugin,
DrawPlugin,
createPlayCardAction,
createDrawCardAction,
createEndTurnAction
} from 'decklet'
import {
UnoPlugin,
createChooseColorAction,
CHOOSE_COLOR_ACTION,
UNO_VAR_PENDING_COLOR,
isPendingColorChoice
} from 'decklet/uno'
const engine = new GameEngine()
engine.use(TurnPlugin).use(DrawPlugin).use(UnoPlugin)
engine.createGame({
players: [
{ id: 'p1', name: 'Alice', seat: 1 },
{ id: 'p2', name: 'Bob', seat: 2 }
]
})
engine.start()
const state = engine.getState()
const currentId = state.currentPlayerId!
// 1) 出一张 Wild 牌
const wildCardId = /* 当前玩家手中的 wild 牌 id */ '<wildCardId>'
engine.dispatch(createPlayCardAction(currentId, [wildCardId]))
// 2) 此时 isPendingColorChoice === true,需提交 CHOOSE_COLOR
if (isPendingColorChoice(engine.getState())) {
engine.dispatch(createChooseColorAction(currentId, 'red'))
}
// 3) 选色完成后,handleColorChosen 自动派发 END_TURN 推进回合
console.log('next player:', engine.getState().currentPlayerId)注意事项
CHOOSE_COLOR_ACTION仅在UNO_VAR_PENDING_COLOR === true时合法(由chooseColorValidRule校验)。UNO_FLIP_INITIAL_ACTION是系统动作,由插件内部派发,外部通常不需要直接调用。payload.color必须是UnoColorChoice(实色),不能传'wild'——isUnoColorChoice类型守卫会拒绝。