- CLAUDE.md:编号 01→05/04 修正为 01→06/04,补三套文档优先级
(硬红线以 dev-guide 为准)与「编号↔主题」对照表
- client README 阅读顺序表补上遗漏的 06 子游戏接入模式与Hooks外置
- 修正 README 及正文交叉链接的旧路径(server/docs、client/docs、
docs/engineering → docs/{server,client,games/engineering},
相对层级 ../../../ → ../../),共 7 处
- engineering 文档移除对已删除路径(docs/architecture、
.github/copilot/skills)的引用,改为通用表述
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.3 KiB
9.3 KiB
05 · 开发规范与红线
本篇汇总前端必须遵守的工程纪律,是代码审查清单的来源。改任何代码前按相关条目自检。前面 01–04 是“怎么做”,本篇是“不许怎么做 / 必须怎么做”。
1. 可编辑范围
| 区域 | 可改性 |
|---|---|
js/vendor/、js/00_Surface/ |
禁改(第三方/平台代码) |
01_SubGame/00_SubGame_Config.js |
仅可改值:只给已有 Game_Config.* 配置项赋值;禁止新增/删除/改名/改结构定义(三文件中唯一子游戏可碰者,且仅限改值)。详见 06 |
01_SubGame/01_SubGame_modify.js |
受限:仅顶部「配置区」填值(Type_*/CreateRoomData/combat/game_config/roomDes);转发壳/平台接口不碰、不新增,业务走子游戏实现层。详见 06 |
01_SubGame/02_SubGame_Input.js |
不碰:框架维护的平台接口骨架/转发壳,不改、不新增接口、不写业务。详见 06 |
js/gameabc-framework/ |
可改,但须保持游戏中立(见 §3) |
01_SubGame/codes/(除 shared/) |
子游戏自由开发区 |
01_SubGame/codes/shared/ |
只读:服务端 shared/ 的同步副本,改服务端权威源再同步(见 §7) |
新增前后端交互一律走服务端 mod.js 的 rpc 机制 + 前端统一发包/收包封装,不在受限文件新增接口。
2. 语言标准:严格 ES5
- 用
var/function;对象继承用Object.create(Base)+ 在init内重声明实例属性。 - 禁
let/const、箭头函数、模板字符串、解构、默认参数、展开、class、for...of。 - 跨文件按全局名引用(各文件
var X = ...暴露全局,index.html顺序加载);新增文件必须在index.html插到依赖之后、使用者之前。
3. 框架游戏中立
gameabc-framework/ 是给任意子游戏复用的通用框架,不得渗入任何具体玩法:
- 禁止在框架内出现玩法逻辑、玩法专属常量(牌型、动作、玩法事件名等)。
- 玩法专属内容一律定义在子游戏侧:
- 玩法事件 → 子游戏事件常量文件,追加到
EventBus.Events; - 音效映射 → 子游戏音效资源常量 + 游戏音频管理;
- Spine 动作 → 子游戏 Spine 动作配置;
- 资源/布局 → 子游戏精灵结构/图片资源/布局常量。
- 玩法事件 → 子游戏事件常量文件,追加到
- 违例信号:框架文件里出现
mahjong:、牌型、吃碰杠胡等具体玩法字样(注释举例除外,且举例应尽量中立)。
范例:本仓库把框架
EventBus.js内所有预定义事件常量清空(只留空容器EventBus.Events={}),全部事件(通用语义 + 玩法专属)改由子游戏的事件常量文件定义;并把通用的精灵事件控制器从子游戏抽到框架system/SpriteEventController.js、剥离其中的玩法标记耦合为「全局 draw 钩子」;把UIManager的全局 UI(Loading/Message/Confirm)从「主动读子游戏精灵常量」改为「由子游戏init(config)注入」。新玩法照此扩展,框架零改动。
4. 渲染与常量
- 精灵只走
SpriteManager:UI 代码禁止直接调GameABCUtils/引擎原生 API。 - ID 守范围:精灵 1001–3000、群组 ≥201、普通图层 101–200、弹窗图层 301–400(另有 501–600、701+ 备用段);框架保留 1–1000 及 3001+(精灵)等交替段,不可占用;ID 必须与编辑器一致,不编造。
- 检查返回值:
SpriteManager.*返回false即 ID/范围有误,及时暴露。 - 常量集中、禁硬编码:精灵 ID / 图片资源 ID / 坐标尺寸 / 动画时长帧数 / 音效 ID / 事件名,一律定义在对应常量文件,业务代码只引用:
- 精灵结构 → 精灵结构常量(主界面/弹窗分文件)
- 图片资源 → 图片资源常量
- 布局坐标 → 布局常量
- 动画参数 → 动画配置
- 音效 ID → 音效资源常量
- 事件名 →
EventBus.Events(专属在子游戏事件常量文件) - 整合入口 → 精灵常量整合入口(最后加载)
5. UI 组件生命周期与内存安全
- 组件继承
BaseComponent,在init内重声明实例属性、建精灵、注册事件。 - 事件用
this.addEventListener订阅(destroy()自动off),禁裸EventBus.on(会泄漏)。 - 销毁用
destroy()而非只hide();在onDestroy清理定时器、动态复制精灵、Spine 回调登记。 - 动态列表用
DynamicSpriteList并在销毁时list.destroy(),避免复制精灵残留。
6. 数据权威、组件数据与表现延后
- 服务端权威:所有核心运算与胜负裁定以服务端为准、数据以服务端为权威;前端只做界面展示与玩家交互,本地数据仅为「渲染副本」,不做权威计算。
- 组件数据自持 + set-refresh:组件(及其下每个「零件 UI」)的自有数据集中在
this.data,不散落各处;每个 UI 都有setXxx(只写数据)/refreshXxx(只据数据画界面)成对方法,组件另有总refresh()据this.data重建整块界面(见 02)。 - 收包节奏:先
setXxx写数据 →(必要时refresh刷静态界面)→ 再播动画 → 动画回调里只刷新界面;动画的开始/结束/出错等生命周期回调里绝不设置核心数据,动画期间不改数据。 - 重画随时可用:任何时候调
refresh都能据this.data重建正确界面(网页刷新/断线重连/切 app 复用同一路径,不为重连单写一套渲染)。 - 动画是体验层:开发阶段可先不做动画只保证静态界面正确;即使动画缺失/卡住/播错,数据、逻辑与界面仍正确、互不影响。
7. 成败标志与收发包
- 成败只认
data.success:if (!data.success)判失败;禁用status/code判成败、禁status兼容兜底。个别嵌套场景按该推送契约取success所在字段,语义不变。 - 发包走语义化发包封装/
RpcHelper(自动注入平台字段),收包统一分发(一 rpc 一处理器)。 - 业务逻辑放 controllers/managers,不写进受限
Game_Modify.*。
8. shared 同步
shared/是子游戏自己的游戏逻辑,与平台无关:存放本玩法前后端必须算出完全一致的纯逻辑(胡牌/听牌/比精/牌型/计分/规则常量等),前端用于即时表现与预校验,服务端做权威裁定。它不是平台代码,平台既不提供也不感知。01_SubGame/codes/shared/是服务端server/<游戏容器目录>/<游戏>/shared/的同步副本,前端只读(脚本生成)。- 改共享算法只改服务端权威源,再运行同步脚本覆盖前端副本;禁止直接编辑前端
codes/shared/。 - 逻辑同源不改变数据权威:前端
shared/算的是表现/预判,最终以服务端为准(数据优先、表现延后,见 §6)。详见服务端docs/server/development-guide/04 §8。
9. 模块职责边界
- 一个职能只在一个模块实现,其他模块调用而非重造:渲染找
SpriteManager、动画找AnimationManager(及游戏动画封装)、音频找游戏音频管理、Spine 找SpineMgr(及 Spine 回调分发)、发包找语义化发包封装、收包分发找收包分发器。 - 写代码前先问“这段属于谁的职责”,属于别人就调用它,不在本模块复制一份近似实现。
10. 测试纪律
- 测试用于验证业务正确性;失败先裁定根因归属(业务缺陷 vs 测试脚本缺陷),禁止 skip/软化断言/吞异常掩盖。
- 业务缺陷修业务并单独提交;脚本缺陷修置场并保持硬断言。
shared/算法变更应在 Node 跑相应单测验证(前后端同源)。
11. 审查速查表
| 维度 | 红线 |
|---|---|
| 范围 | vendor/00_Surface 禁改;受限文件不新增接口;shared 只读 |
| 语言 | 严格 ES5;新文件插对加载顺序 |
| 框架中立 | 框架无玩法逻辑/专属常量;专属内容归子游戏 |
| 渲染 | 只走 SpriteManager;ID 守范围、不编造;查返回值 |
| 常量 | 精灵/资源/坐标/动画/音效/事件全集中,禁硬编码裸值 |
| 组件 | 继承 BaseComponent;事件 addEventListener;destroy 清动态精灵/定时器 |
| 数据 | 服务端权威(核心运算/裁定在服务端);组件自有数据集中 this.data;每个 UI/零件有 set/refresh 对、组件有总 refresh |
| 节奏 | 先写数据后表现;动画回调只刷界面、不写核心数据;重画可随时据数据还原界面 |
| 成败 | 只认 data.success,禁 status 兜底 |
| 收发包 | 发走语义化发包封装、收走收包分发器;业务不进 Game_Modify |
| 职责 | 一职能一模块,调用不重造 |
至此,从架构与环境(01)、渲染与组件(02)、表现系统(03)、网络与启动(04)到工程红线(05),构成一套完整的前端子游戏开发指导。回到 README 查看导航与分层模型。