二七王:S-7 明牌条件按手册定案,服务端无需改动

结论:按 design §9.3——任一玩家报无主后,三家都显示「明牌」按钮,
且整个出牌阶段随时可查、不限次数。判定依据是「场上有人报无主」而非
「自己报无主」,报无主那位和另外两位一样能看。

此前我把前端条件收紧成「自己是无主玩家」,比手册严格,反而与服务端
have_baofu() 的受理条件对不上。现改回:

- 前端清单 §1.7 D-6、§2.6 底栏按钮、§0.0 对照表、baozhu 字段说明统一为
  「可查牌 + 出牌阶段 + baozhu==1 → 三家都显示」。
- design §9.3 第 3 条补一句消歧:明确「为这三个人都出现」、判定依据是
  场上有人报无主、且不限次数随时可查。原文靠「同时」承接上一条的
  「为全体三人」,容易读漏。
- protocol 的术语表与 mingpai 受理条件说明同步加注。

服务端与协议本来就是手册口径,无代码改动。此前记的「有主牌玩家伪造请求
也能拿到明牌数据」这一泄露担忧不成立——按手册他本就有权查看,服务端受理
是正确行为。

验收清单增至 18 条,新增一条专门钉住「三家都显示,不是只给自己无主那家」。
至此 §7.5 服务端待补项 7 条全部处理完毕,服务端侧无遗留。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-26 08:03:08 +08:00
co-authored by Claude Opus 5
parent 9ea6bfa14d
commit 796503153d
3 changed files with 19 additions and 26 deletions
+16 -23
View File
@@ -70,7 +70,7 @@
| --- | --- | --- | --- | --- | --- |
| **亮牌** | 庄家 → 两个闲家 | **具体牌面**(庄家全部固定主牌) | 庄家埋牌后固定主牌达门槛(design §8.2) | 遮罩面板,同明牌版式(§1.6) | `liangpai.cards` |
| **余主公示** | 全体 → 全体 | **只有数量**(剩余主牌数、主对数) | 任一玩家报无主(design §9) | 他家头像下 `主N` `对N` 角标(§2.5) | `seatlist[seat][4]`、`baozhu` |
| **明牌** | 他家 → 请求者 | **具体牌面** | 可查牌 + 无主,点按钮(design §9) | 遮罩面板(§1.7 D-6) | `mingpai.others[].zhucards` |
| **明牌** | 他家 → 请求者 | **具体牌面** | 可查牌 + **场上有人报无主**,三家均可点、随时可查(design §9) | 遮罩面板(§1.7 D-6) | `mingpai.others[].zhucards` |
| **开底** | 桌面 → 所有玩家 | **具体牌面**(8 张底牌) | 70 分坐庄,**摸底之前** 3 秒(design §4) | 复用底牌区翻牌(§1.4 D-2) | `ancard3s` + `bottomcards` |
一句话记:**只有「余主公示」是统计类(给数字),「亮牌」「明牌」「开底」都给具体牌面**——区别在给谁的牌:亮牌给庄家自己的、明牌给他家的、开底给桌上那 8 张。
@@ -660,7 +660,7 @@ EQW_RoomOptions = {
| `flower` / `count` | 本轮首出花色与张数,供本地跟牌提示 |
| `nextseat` / `countdown` | 倒计时移到下一家 |
| `seatlist` | **仅可查牌模式**:三家牌况,用于 §2.2 的 `主N` / `对N` 角标 |
| `baozhu` | 是否已有玩家**报无主**:= 1 时显示各家主牌数/对数,并让底栏 `明牌` 按钮可用 |
| `baozhu` | 是否已有**任一**玩家**报无主**:= 1 时触发余主公示(各家主牌数/对数),并让**三家**的底栏 `明牌` 按钮可用 |
| `cardsinhand` | **仅出牌者本人有**:出牌后剩余手牌,据此重画手牌区 |
**收 `chupai2` / `chupai3`**:字段类似,`chupai3` 额外带 `maxseat`(本轮谁最大)与 `grade`(本轮闲家得分,仅闲家有得分时才有)。
@@ -715,8 +715,8 @@ EQW_RoomOptions = {
**明牌**(design §9.3):
- **按钮显示条件(D-6 已定)**:**勾选了可查牌模式 + 自己是「无主玩家」**(自己的主牌已出空)时才显示 `明牌` 按钮。
> ⚠️ 这比 design §9 更严格,且与服务端当前校验不一致,见 §7.5 **S-7**。design 原文是「一旦有玩家的主牌全部打空……界面上会出现一个『明牌』按钮」,读作**全体三人**都出现;服务端 `mingpai` 的受理条件也是 `have_baofu()`(任一玩家报无主)。按新规则则应改成「**请求者本人**无主」。
- **按钮显示条件(D-6 已定,按 design 手册)**:**可查牌模式 + 出牌阶段 + 已有任一玩家报无主**(`baozhu == 1`)→ **三家都显示** `明牌` 按钮,且**可随时查看**、不限次数。
> 判定的是「场上**有人**报无主」,不是「**自己**报无主」——报无主的那位自己也能看。与 design §9.3「一旦有玩家的主牌全部打空……为**全体三人**(含刚刚报无主的这位玩家自己)显示……同时界面上会出现一个『明牌』按钮」一致,也与服务端 `mingpai` 的受理条件 `have_baofu()` 一致。
- 点击 → 发 `mingpai { seat }` → 收 `mingpai { seat, others: [{seat, zhucards}] }` → 弹出面板展示另两家全部未出主牌的**具体牌面**。
- **再点一次取消是纯前端开关**,不再请求服务端(协议 §13.6)。
- **展示形式(D-6 已定)**:**照 `冲关牌型显示.png` 那一套**——半透黑遮罩 + 两家各一排牌(`CARD_FACE_L`、`fan` 重叠排列),点遮罩关闭。与冲关牌型叠加层是同一种版式,可复用同一套渲染逻辑,仅数据源与座位数不同(明牌是**另两家**,冲关牌型是**三家**)。
@@ -982,7 +982,7 @@ y≈648–720 深色条。左侧头像/昵称/分数由平台渲染(§0.2)
| --- | --- | --- |
| `上一轮` | **上一轮**所有人出的牌 | 可查牌 + 出牌阶段 + 已打过至少一轮 |
| `出牌历史` | 所有人**出过的全部牌** | 可查牌 + 出牌阶段 |
| `明牌` | 另两家手中全部主牌的具体牌面 | 可查牌 + 出牌阶段 + **已报无主** |
| `明牌` | 另两家手中全部未出主牌的具体牌面 | 可查牌 + 出牌阶段 + **场上已有人报无主**(`baozhu==1`)→ **三家都显示** |
| **`扣底`** | **埋牌底牌**:庄家埋下的 8 张 | **仅庄家** + 已埋牌之后 |
| **`底牌`**(**查底牌**) | **底牌**:发牌时没发给玩家、留在桌面的 8 张 | 庄家全程;闲家仅**开底**过的局(70 分坐庄)(S-3) |
@@ -1742,7 +1742,7 @@ codes/config/
## 7. 待补充清单
> **状态汇总**(2026-08-26):设计稿只剩 **D-8**(判定结果文字)。
> **§7.5 服务端待补项**:S-1…S-6 已完成,**只剩 S-7**(明牌按钮条件与服务端校验不一致,有泄露口子)。
> **§7.5 服务端待补项 7 条已全部处理完毕**(S-1/S-2/S-4/S-6 有代码改动,S-3/S-5/S-7 为定论或文档同步)。**服务端侧无遗留**。
### 7.1 待出设计稿的界面
@@ -1756,7 +1756,7 @@ codes/config/
| ~~D-3~~ | 甩错提示 | ✅ 定稿:桌面中央深色半透条 **`强甩失败`**(`强甩失败提示.png`),**不做收回动画**,直接落下那张被强制打出的最小主牌 |
| ~~D-4~~ | 报无主 | ✅ 定稿:**不做全场提示**。只让他家 `主N`/`对N` 角标出现;自己的主牌统计条本来就常显(§2.5) |
| ~~D-5~~ | 踩 / 没分 / 有分 | ✅ 定稿:底栏三按钮(占庄标区)+ 3×2 六帧气泡 |
| ~~D-6~~ | 明牌面板 | ✅ 定稿:版式照 `冲关牌型显示.png`(遮罩 + 每家一排牌)。**按钮显示条件收紧为「可查牌 + 自己是无主玩家」** → 见 **S-7** |
| ~~D-6~~ | 明牌面板 | ✅ 定稿:版式照 `冲关牌型显示.png`(遮罩 + 每家一排牌)。按钮条件**按 design 手册**:可查牌 + 已有任一玩家报无主 → 三家都显示、可随时查看 |
| ~~D-7~~ | 出牌历史面板 | ✅ 定稿:版式同上。**不按轮次**,按玩家聚合、用主牌序排序。前端摊平 `pushlist` 即可,无需改服务端 |
| ~~D-9~~ | 大局总结算 | ✅ 定稿:`大局结算.png`,玩家栏用精灵复制(§5.7a)。**四项分数协议缺** → 见 **S-6** |
| ~~D-10~~ | 解散结算 | ✅ 复用 D-9 面板;投票界面平台全包(Layer 420) |
@@ -1843,6 +1843,7 @@ codes/config/
| 15 | 自己发的提示本地回显后,收到失败回包时能撤掉 | §1.7 |
| 16 | 自己的主牌统计条**有手牌时常显**、不受查牌模式与报无主影响;他家 `主N`/`对N` 角标只在「可查牌 + 已报无主」时出现 | §2.5 |
| 17 | 出牌历史**按玩家聚合 + 主牌序排序**,不是按轮次分组 | §1.7 D-7 |
| 18 | `明牌` 按钮在「场上**有人**报无主」时**三家都显示**(含报无主那家自己),不是只给自己无主的那家 | §1.7 D-6 |
### 7.4 开发前置条件
@@ -1987,27 +1988,19 @@ data.bottom.cards // 结算包
> 面板上「基础分」取 `grade_jf_total`、「总得分」取 `score`。参考图里这两行数值相同、且与右侧大字对不上,是填充假数据所致,不作依据(§0.5)。
#### S-7 · 明牌按钮的显示条件与服务端校验不一致(新增,⚠️ 与 design 冲突)
#### S-7 · 明牌按钮的显示条件 —— ✅ 已定论:按手册,服务端无需改动(2026-08-26)
**需求(D-6)**:`明牌` 按钮在**「勾选可查牌 + 自己是无主玩家」**时才显示。
**结论:按 design §9.3 手册办**——**任一玩家报无主后,三家都显示 `明牌` 按钮,且可随时查看。**
**冲突**:
| 来源 | 现在的规定 |
| 项 | 取值 |
| --- | --- |
| design §9.3 | 「一旦有玩家的主牌全部打空……**为全体三人**(含刚刚报无主的这位玩家自己)显示另外两家的主牌数量……**同时界面上会出现一个「明牌」按钮**」——读作三人都出现 |
| 协议 / 服务端 | `mingpai` 的受理条件是 `have_baofu()`(**任一**玩家报无主);`chupai` 包的 `baozhu` 字段也是「是否**已有玩家**报无主」 |
| 新需求 | **请求者本人**无主才给看 |
| 显示条件 | 可查牌模式 **+** 出牌阶段 **+** `baozhu == 1`(**任一**玩家主牌出空) |
| 谁能看 | **全体三人**,包括刚刚报无主的那位自己 |
| 次数 | **不限**,随时可点开、可关闭 |
**需要定**:
**服务端无需改动**——`mingpai` 现有的受理条件 `have_baofu()`(任一玩家报无主)**正好就是这条规则**,与 design §9.3 一致。此前我把前端条件收紧成「自己是无主玩家」,比手册严格,反而与服务端校验对不上;现已改回。
| 方案 | 做法 |
| --- | --- |
| **(a) 只改前端**(最小改动) | 服务端不动,前端按「自己无主」控制按钮显隐。缺点:服务端仍会受理非无主玩家的 `mingpai` 请求,规则靠前端自觉——**违反「服务器权威」红线**,不推荐 |
| **(b) 前后端一起改**(推荐) | 服务端 `mingpai` 的受理条件由 `have_baofu()` 改为「请求者本人 `seatlist[seat][4][0] == 0`」,前端同步;并**同步修订 design §9.3** 的措辞 |
| **(c) 维持 design** | 放弃新需求,仍按「任一玩家报无主 → 三人都能明牌」 |
**在确认前前端按 (b) 的显隐规则实现**(更严格、不会越权),但**服务端校验尚未改**——即当前状态下,一个有主牌的玩家若伪造请求仍能拿到明牌数据。**这是个真实的信息泄露口子,选定方案后要尽快补上。**
> 之前记录的「有主牌的玩家伪造请求也能拿到明牌数据」这一泄露担忧**不成立**:按手册他本来就有权查看,服务端受理是正确行为,不是校验缺失。
---