From 796503153d0d2b061d1ce9a9b5be7e16f22924c5 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Wed, 26 Aug 2026 08:03:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8C=E4=B8=83=E7=8E=8B=EF=BC=9AS-7=20?= =?UTF-8?q?=E6=98=8E=E7=89=8C=E6=9D=A1=E4=BB=B6=E6=8C=89=E6=89=8B=E5=86=8C?= =?UTF-8?q?=E5=AE=9A=E6=A1=88=EF=BC=8C=E6=9C=8D=E5=8A=A1=E7=AB=AF=E6=97=A0?= =?UTF-8?q?=E9=9C=80=E6=94=B9=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 结论:按 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) --- docs_dev/二七王-UI资源与精灵清单.md | 39 ++++++++----------- server/games/erqiwang/docs/design/design.md | 2 +- .../erqiwang/docs/protocol/packet_protocol.md | 4 +- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/docs_dev/二七王-UI资源与精灵清单.md b/docs_dev/二七王-UI资源与精灵清单.md index 2a1b21c..aaf4d0d 100644 --- a/docs_dev/二七王-UI资源与精灵清单.md +++ b/docs_dev/二七王-UI资源与精灵清单.md @@ -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) 的显隐规则实现**(更严格、不会越权),但**服务端校验尚未改**——即当前状态下,一个有主牌的玩家若伪造请求仍能拿到明牌数据。**这是个真实的信息泄露口子,选定方案后要尽快补上。** +> 之前记录的「有主牌的玩家伪造请求也能拿到明牌数据」这一泄露担忧**不成立**:按手册他本来就有权查看,服务端受理是正确行为,不是校验缺失。 --- diff --git a/server/games/erqiwang/docs/design/design.md b/server/games/erqiwang/docs/design/design.md index 01e7a49..43a9e4a 100644 --- a/server/games/erqiwang/docs/design/design.md +++ b/server/games/erqiwang/docs/design/design.md @@ -677,7 +677,7 @@ A - K - Q - J - 10 - 9 - 8 - 6 - 5 - **可查牌模式**(四项功能全部提供): 1. **出牌历史**:当前牌局中,所有玩家已经打出的牌(含之前每一轮打出、已被收走的牌),任何时候都可以回看。 2. **余主公示**:一旦有玩家的主牌全部打空(即 5.4.2 节所说的"报无主"状态;"主牌"指大王、小王、所有花色的 2、所有花色的 7,以及主花色的其余普通牌,见第 3 节),系统就为**全体三人**(含刚刚报无主的这位玩家自己)显示另外两家各自的主牌数量、以及这些主牌里有多少对子。**只给数量、不给具体牌面**——要看具体牌面是下一条的"明牌"。 - 3. 同时界面上会出现一个"明牌"按钮:点击后可以查看另外两家手中全部主牌的**具体牌面**(不只是数量 / 对子结构),再点一次取消查看、恢复隐藏。 + 3. **明牌**:同时**为这三个人都**出现一个"明牌"按钮——判定依据是「**场上有人**报无主」,不是「**自己**报无主」,所以报无主的那位和另外两位一样都能点。点击后可以查看另外两家手中全部主牌的**具体牌面**(不只是数量 / 对子结构),再点一次取消查看、恢复隐藏;**不限次数,整个出牌阶段随时可查**。 4. 庄家若触发了 8.2 节的"亮牌要求",两个闲家可以看到**庄家全部固定主牌的具体牌面**(见 8.2 节)。 - **不可查牌模式**:以上四项**一项都不提供**—— diff --git a/server/games/erqiwang/docs/protocol/packet_protocol.md b/server/games/erqiwang/docs/protocol/packet_protocol.md index 7b2888d..fefaa9e 100644 --- a/server/games/erqiwang/docs/protocol/packet_protocol.md +++ b/server/games/erqiwang/docs/protocol/packet_protocol.md @@ -31,7 +31,7 @@ | --- | --- | --- | --- | --- | | **亮牌** | 庄家 → 两个闲家 | **具体牌面**(庄家全部固定主牌) | 庄家埋牌后固定主牌达门槛(design §8.2) | `liangpai.cards` | | **余主公示** | 全体 → 全体 | **只有数量**(剩余主牌数、主对数) | 任一玩家报无主(design §9) | `seatlist[seat][4]`、`baozhu` | -| **明牌** | 他家 → 请求者 | **具体牌面**(他家全部未出主牌) | 可查牌 + 报无主,主动点击(design §9) | `mingpai.others[].zhucards` | +| **明牌** | 他家 → 请求者 | **具体牌面**(他家全部未出主牌) | 可查牌 + **任一**玩家报无主 → **三家均可点、随时可查**(design §9) | `mingpai.others[].zhucards` | | **开底** | 桌面 → 所有玩家 | **具体牌面**(8 张底牌) | 70 分坐庄,**摸底之前** 3 秒(design §4) | `ancard3s` + `bottomcards` | 一句话记:**只有「余主公示」是统计类(给数字),「亮牌」「明牌」「开底」都给具体牌面**——区别在给谁的牌:亮牌给庄家自己的、明牌给他家的、开底给桌上那 8 张。 @@ -341,7 +341,7 @@ 发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:mingpai -查看另外两家手中全部主牌的具体牌面(design §9)。服务端仅在**可查牌模式、出牌阶段(step5)、且已有玩家报无主**(`have_baofu()`)时受理;不满足时按 0.2 回 `mingpai` 失败包(不查牌 / 未报无主 → `RULE`,非出牌阶段 → `STEP`)。 +查看另外两家手中全部主牌的具体牌面(design §9)。服务端仅在**可查牌模式、出牌阶段(step5)、且已有【任一】玩家报无主**(`have_baofu()`)时受理——注意判定的是「场上有人报无主」而非「请求者本人报无主」,报无主那位与另外两位同样有权查看(design §9.3);不满足时按 0.2 回 `mingpai` 失败包(不查牌 / 未报无主 → `RULE`,非出牌阶段 → `STEP`)。 | 参数名 | 类型 | 说明 | | --- | --- | --- |