Files
youle_framework/docs/client/development-guide/红线速查.md
T
2026-08-19 08:14:48 +08:00

54 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端 · 一页纸分层模型与红线速查
> 本文是前端开发**必须常驻在手边**的那一页:分层模型 + 红线清单。
> 它由 `CLAUDE.md` 通过 `@import` 常驻每次会话上下文;**红线以本文为权威**。
> 文档导航、阅读顺序、各篇主题见 [README](./README.md);红线的完整细节见 [05-开发规范与红线.md](./05-开发规范与红线.md)。
---
## 一页纸:前端分层模型
```
gameabc.min.js(引擎,js/vendor,第三方)
▲
GameABCUtils(core,唯一直接调引擎原生 API 的模块)
▲
SpriteManager(core,业务级精灵 API:ID 校验 + 单位换算) EventBus / AnimationManager / AudioManager / SpineMgr(system)
▲ ▲
BaseComponent / UIManager(ui,组件化与场景) ← gameabc-framework(游戏中立,可复用)
══════════════════════════════════════════════════════════════════════════
01_SubGame/codes(子游戏实例,单向依赖框架;内部结构由子游戏自行组织)
shared 前后端共享算法(与服务端同源,脚本同步,只读)
══════════════════════════════════════════════════════════════════════════
旧受限对接层(平台入口,尽量不改)
00/01/02_SubGame_*.js → Game_Modify.StartWar / Reconnect / _ReceiveData / appStart
```
- **框架(gameabc-framework)**:游戏中立,提供精灵/组件/事件/动画/音频/Spine 通用能力,可被任何子游戏复用。
- **子游戏(01_SubGame/codes)**:单向依赖框架,在其内部自由组织实现(目录/文件命名由子游戏自定,仅 `shared/` 为只读同步副本)。
- **旧受限对接层**:平台框架的固定入口(`Game_Modify.*`),把平台事件转交给新架构,**尽量不改**(详见 01/04)。
---
## 红线速查(详见 05)
- **可编辑范围**:前端平台代码 `js/00_Surface/` 禁改;受限接口文件 `01_SubGame/00_/01_/02_SubGame_*.js` 不新增接口、尽量不改;其余在 `gameabc-framework/`、`01_SubGame/codes/` 内开发。
- **严格 ES5**:用 `var`/`function`/`Object.create`,禁 `let`/`const`/箭头/模板串/`class`。
- **框架游戏中立**:`gameabc-framework/` 内**不得**出现任何具体玩法逻辑或专属常量;玩法专属的事件/资源/配置一律定义在子游戏侧(如玩法事件在子游戏的事件常量文件里追加到 `EventBus.Events`)。
- **精灵只走 SpriteManager**:UI 代码**禁止**直接调 `GameABCUtils` 或引擎原生 API;ID 必须落在规定范围(精灵 1001–3000、群组 ≥201、图层 101–200/弹窗 301–400,另有 501–600、701+ 备用段,框架保留 1–1000 及 3001+ 等交替段)。
- **常量集中、禁硬编码**:UI 代码**禁止任何硬编码 id / 裸值**——精灵 ID / 群组 ID / 图层 ID / 图片资源 ID / 声音 ID / Spine 资源 / 坐标尺寸 / 动画时长 / 事件名 一律定义在对应常量文件、只引用常量。
- **服务端权威、前端只展示**:核心运算与胜负裁定以服务端为准、数据以服务端为权威;前端只做界面展示与玩家交互,本地数据仅为渲染副本,不做权威计算。
- **数据驱动、前端无对局状态机**:阶段、轮次/控制权、可用操作、倒计时、分数、按钮该不该出现,一律**读服务端下发的权威字段**渲染;**禁止**前端自建状态机、由本地规则推导「现在轮到谁/进入哪个阶段/显示哪些按钮」,**禁止**用本地定时器自行推进阶段或自判超时(超时与托管由服务端驱动,倒计时前端只做插值显示)。包里没有的状态是**服务端漏发**,修在服务端发包处,前端不推、不补、不猜(详见 05 §6.1)。
- **视图 = f(服务端快照)**:`this.data` 只是服务端状态的镜像,**不得存在只活在前端、服务端不知道的对局态**。判据:任意时刻丢弃 `this.data`、仅凭最近一次服务端快照重画,界面必须完全一致——做不到即"前端私存了状态"或"服务端漏发了字段",都要修。只有不影响裁定的纯表现态(选中高亮、按下反馈、滚动位置、动画进度)可只存在于前端(详见 05 §6.2–6.3)。
- **请求包只带「意图」**:发包只带「做什么 + 目标标识」(操作类型、牌 `uniqueId`、`choiceIndex`),**禁止**回传前端算出的结论(分数/番数、"我胡了"之类判定、结算结果、阶段推进指令);前端 `shared/` 的计算只用于本地提示与预校验,结果不回传(详见 04 §1)。**前端能自己推出来的东西,就是玩家能改的东西**——这是防作弊的根本。
- **组件走 BaseComponent**:UI 组件继承 `BaseComponent`,事件用 `this.addEventListener` 注册(`destroy()` 自动清理,防泄漏);动态精灵/定时器在 `onDestroy` 清理。
- **组件数据自持 + set-refresh**:组件自有数据集中 `this.data`;每个 UI/零件有 `setXxx`(只写数据)/`refreshXxx`(只据数据画)对,组件有总 `refresh()` 可据数据重建界面。
- **UI 组件专职自己的界面**:每个界面的数据与渲染只由其对应 UI 组件实现;别的模块要改/刷该界面一律**调该组件的公开接口**(`setXxx`/`refreshXxx`/语义方法),**禁止**在别处重复实现重叠或类似的界面数据/渲染逻辑。
- **显隐走 `showXxx`/`hideXxx`**:UI 组件/零件的精灵、群组显隐必须由组件暴露的 `showXxx`/`hideXxx` 接口控制;**禁止**别处直接用其精灵 ID/群组 ID 去 `SpriteManager.show/hide` 控显隐。
- **发包只请求、收包才表现(悲观 UI / 输入-渲染解耦)**:用户点击**只发请求包**,对局状态界面(提示/按钮/控制权/倒计时/落牌/阶段)一律**收到服务端结果或推送包后**才更新,点击时不做乐观预测;收包处理器**触发源无关**(数据从包字段读,不依赖点击时的本地变量),故真人操作与 **AI 托管/他人广播共用同一更新路径、对前端透明**——挂在「点击」而非「收包」会导致 AI 托管时界面卡死(详见 04 §5)。**受控例外**:本玩家点击的**响应/掷骰交互按钮**(碰/杠/过/胡、手动掷骰按钮)的隐藏允许乐观清除(兼作防连点+即时反馈),前提是**服务端合法性验证 + 收包侧兜底(AI 托管一致)**,见 04 §5.6 与服务端 04 §8;其余提示/控制权/倒计时/落牌仍严格收包驱动。
- **数据优先、表现延后**:收到推送先 `setXxx` 写数据、再播动画;动画的开始/结束/出错回调里**只刷界面、不写核心数据**。即使动画缺失/卡住/出错,数据、逻辑、界面仍正确、互不影响。
- **重连即重画(断线重连 + 硬刷新都要处理)**:重连/页面重载的本质是**恢复数据 → 调各 UI 组件 set-refresh 恢复数据与界面状态**,复用同一条重画路径,不为重连单写一套渲染(详见 04 §3.3、05 §6)。
- **成败只认 `data.success`**:前端一律 `if (!data.success)` 判成败,**不**用 `status`/`code`,**不**写 `status` 兼容兜底。
- **收发包走统一通道**:发包经统一发送封装(底层 `RpcHelper` 自动注入平台字段),收包统一分发(一 rpc 一处理器);业务逻辑放处理器,**不**写进 `Game_Modify.*`。
- **shared 只读**:`01_SubGame/codes/shared/` 是服务端 `shared/` 的同步副本,**不在前端改**,改服务端权威源后跑同步脚本。