谁最大、这墩闲家得几分是【一次性表现】(收牌动画、得分飘字),任何 deskinfo 都不下发它,
写进 GameState 就多出一处「只活在前端、服务端不知道」的对局态——出牌中途断线重连即归零,
违反红线「丢弃 this.data、仅凭最近一次服务端快照重画,界面必须一致」。
三处一起改,缺一不可:
- PlayHandler chupai3:删 result.chupai 写入,改随 EQW_TRICK_END 下发 {seat,cards,maxseat?,grade?};
aset.grade 的累加保留(它有服务端来源 PushCards.grade / chupai3.grade,是镜像量)
- ResultHandler:_apply 的 map 删掉 chupai。收尾墩不发 chupai3、整包换成 jiesuan,
不改这里则删 EXCLUDE 后必转红。收尾墩改为与 chupai3 走同一对事件、同一份载荷字段
(补 emit EQW_TRICK_END 并带上 grade),否则最后一墩的得分没有出口
- GameState:删掉 result.chupai 字段本身(声明 + reset),不留永远为 null 的死字段
test_consistency 的 EXCLUDE 随之删到只剩 table.ancard3s 一条,27 checks 仍全绿;
该条改注释标明「当前夹具(65 分坐庄、单局)无法触发,此条未经验证」,不假装它在守什么。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
42 lines
2.5 KiB
JavaScript
42 lines
2.5 KiB
JavaScript
///////////////////////////////////////////////////////////////
|
|
////////// EQW_Events: 玩法事件常量 ///////////////////////////
|
|
///////////////////////////////////////////////////////////////
|
|
// 前端红线:框架保持游戏中立,玩法专属事件由子游戏追加到 EventBus.Events。
|
|
//
|
|
// 【对局状态不进事件载荷】——凡是 GameState 里有的,订阅者一律从 EQW_GameState 读,
|
|
// 同一份数据不在事件载荷与状态里各存一份(SSOT)。
|
|
// 例外只有「一次性、不属于对局状态、deskinfo 也不下发」的信息,它们不该进 GameState
|
|
// (进了就会立刻制造一处增量/全量不一致),只能随事件载荷走:
|
|
// EQW_RPC_FAILED {rpc, errcode} 一次性错误信息
|
|
// EQW_CARD_PLAYED {order, seat, cards, count?, flower?, cardtype?, shuai?, shuaicuo?}
|
|
// 这一手的落牌信息(一次性表现)。带 ? 的键【缺字段不兜底】,
|
|
// 包里没有就不带;收尾轮由 jiesuan.chupai 带出时只有 {seat, cards, maxseat?}
|
|
var EQW_Events = EQW_Events || {
|
|
|
|
EQW_RESET: 'eqw.reset', //新一局发牌,全部清场
|
|
EQW_HAND_CHANGED: 'eqw.hand_changed', //自己手牌变化
|
|
EQW_CALL_CHANGED: 'eqw.call_changed', //叫分推进
|
|
EQW_BANKER_SET: 'eqw.banker_set', //上庄
|
|
EQW_MAIN_SET: 'eqw.main_set', //选主
|
|
EQW_BURY_DONE: 'eqw.bury_done', //埋牌完成
|
|
EQW_CARD_PLAYED: 'eqw.card_played', //有人出牌
|
|
EQW_TRICK_END: 'eqw.trick_end', //一墩结束;载荷 {seat,cards,maxseat[,grade]},不落 GameState
|
|
EQW_TURN_CHANGED: 'eqw.turn_changed', //控制权或倒计时变化
|
|
EQW_MINGPAI: 'eqw.mingpai', //收到明牌数据
|
|
EQW_TIP: 'eqw.tip', //收到对家提示
|
|
EQW_ASET_RESULT: 'eqw.aset_result', //小局结算
|
|
EQW_ACCOUNT_RESULT: 'eqw.account_result', //大局/解散结算
|
|
EQW_READY_CHANGED: 'eqw.ready_changed', //有人准备
|
|
EQW_RESYNC_ALL: 'eqw.resync_all', //重连/开局全量重画
|
|
EQW_RPC_FAILED: 'eqw.rpc_failed' //失败回包 {rpc, errcode}
|
|
};
|
|
|
|
//追加到框架事件总线的事件表(框架不认识玩法事件,由子游戏注册)
|
|
if (typeof EventBus !== 'undefined' && EventBus.Events) {
|
|
for (var _eqwEvtKey in EQW_Events) {
|
|
if (EQW_Events.hasOwnProperty(_eqwEvtKey)) {
|
|
EventBus.Events[_eqwEvtKey] = EQW_Events[_eqwEvtKey];
|
|
}
|
|
}
|
|
}
|