新规hook
This commit is contained in:
@@ -44,21 +44,8 @@
|
||||
|
||||
`00` 是平台配置项的**结构定义**文件,配置项的**集合与结构由平台/框架固定**。子游戏接入只做一件事:**把已有配置项的值改成本游戏需要的**。
|
||||
|
||||
✅ **允许(改值)**:
|
||||
```js
|
||||
Game_Config.Max.PlayerCnt = 4; // 改人数
|
||||
Game_Config.Share.title = "进贤麻将"; // 改分享标题
|
||||
Game_Config.Info.TextContent = ["你好","谢谢","快点","不要","加油","收到","稍等"]; // 改常用语的【值】
|
||||
Game_Config.Chat.ChatLoc = [[35,517],[1100,315]/* ... */]; // 改聊天气泡坐标【值】
|
||||
```
|
||||
|
||||
❌ **禁止(改定义 / 结构)**:
|
||||
```js
|
||||
Game_Config.Info.MyNewField = 1; // ✗ 新增配置项(增定义)
|
||||
delete Game_Config.Voice; // ✗ 删除配置项(删定义)
|
||||
Game_Config.Max = [4]; // ✗ 改变项的类型/结构
|
||||
// ✗ 重命名平台已定义的字段(如把 PlayerCnt 改成 playerCount)
|
||||
```
|
||||
- ✅ **允许(改值)**:给已有配置项赋值,如 `Game_Config.Max.PlayerCnt = 4;`、`Game_Config.Share.title = "进贤麻将";`、改 `Game_Config.Info.TextContent`(常用语)/`Game_Config.Chat.ChatLoc`(气泡坐标)等数组元素的【值】。
|
||||
- ❌ **禁止(改定义 / 结构)**:新增配置项(`Game_Config.Info.MyNewField = 1;`);删除配置项(`delete Game_Config.Voice;`);改变项的类型/结构(`Game_Config.Max = [4];`);重命名平台已定义字段(如 `PlayerCnt` → `playerCount`)。
|
||||
|
||||
> **为什么**:平台代码(`00_Surface/*`)按**固定字段名**读取 `Game_Config.*`。增 / 删 / 改名定义会让平台读到 `undefined` 或破坏约定,引发线上故障。**配置项的集合与结构是平台契约,只有「值」属于子游戏**。
|
||||
>
|
||||
@@ -75,19 +62,17 @@ Hooks 外置模式下,职责分为三层,单向向下:
|
||||
00_SubGame_Config.js 平台配置项结构 + 子游戏填【配置值】
|
||||
01_SubGame_modify.js 平台接口骨架,每个接口是固定【转发壳】
|
||||
02_SubGame_Input.js 平台接口骨架,每个接口是固定【转发壳】
|
||||
|
|
||||
| 转发壳查 SubGameHooks.X,存在则委托,不存在则平台默认(B类)/空操作(A类)
|
||||
v
|
||||
子游戏入口层(codes/,Hooks 外置新方案核心)
|
||||
SubGameHooks{} 全局对象,接口名与平台接口一一对应;子游戏只填需要的
|
||||
|
|
||||
| SubGameHooks.StartWar = function(_msg){ /* 委托子游戏的开局处理 */ };
|
||||
v
|
||||
子游戏实现层(codes/,已有)
|
||||
各消息处理器 / 收发包 / 战绩等业务模块 / UIManager 扩展 ...
|
||||
```
|
||||
|
||||
**数据流**:平台调 `Game_Modify.X(args)` → 转发壳查 `SubGameHooks.X` → 存在则委托子游戏实现并返回其结果;不存在则执行平台默认(B 类)或空操作(A 类)。
|
||||
**数据流**:平台调 `Game_Modify.X(args)` → 转发壳查 `SubGameHooks.X` → 存在则委托子游戏实现并返回其结果;不存在则执行空操作(A)/平台默认返回值(B)/模板默认 UI 渲染(D)。
|
||||
|
||||
**兼容性原因**:平台只认全局接口名,不关心实现在哪。老游戏不定义 `SubGameHooks`、三文件实心实现 → 照跑;新游戏用转发壳三文件 + `SubGameHooks` → 也跑。无需任何运行期判断。
|
||||
|
||||
@@ -108,7 +93,7 @@ Hooks 外置模式下,职责分为三层,单向向下:
|
||||
|
||||
1. **复制四个模板文件**到新游戏目录。
|
||||
2. **三个转发壳直接用,不改**:`00/01/02_SubGame_*.template.js` 复制后重命名,原样放入 `01_SubGame/`。
|
||||
3. **填充 SubGameHooks**:将 `SubGameHooks.template.js` 重命名为 `codes/SubGameHooks.js`,在其中实现本游戏需要的 hook(不需要的 hook 留空函数或删除,A 类无 hook 默认 no-op,B 类无 hook 返回平台默认值)。
|
||||
3. **填充 SubGameHooks**:将 `SubGameHooks.template.js` 重命名为 `codes/SubGameHooks.js`,在其中实现本游戏需要的 hook(不需要的 hook 留空函数或删除,A 类无 hook 默认 no-op,B 类无 hook 返回平台默认值,D 类无 hook 由模板渲染可变人数默认 UI)。
|
||||
4. **index.html 加载**:按既有顺序在原 `00_/01_/02_SubGame_*.js` 的位置加载新三文件,并在 `codes/` 相应位置加载 `SubGameHooks.js`(在其所依赖的 controllers/handlers 之后)。
|
||||
|
||||
### index.html 加载顺序要点
|
||||
@@ -123,7 +108,7 @@ Hooks 外置模式下,职责分为三层,单向向下:
|
||||
|
||||
## 4. 转发壳范式
|
||||
|
||||
转发壳按「无 hook 时的默认行为」分三类,必须**逐一覆盖全部 63 个接口**(见 §6)。
|
||||
转发壳按「无 hook 时的默认行为」分四类,必须**逐一覆盖全部平台接口**(见 §6)。
|
||||
|
||||
### A 类 — 纯子游戏行为(无 hook 即 no-op)
|
||||
|
||||
@@ -136,12 +121,6 @@ Game_Modify.StartWar = function (_msg) {
|
||||
return SubGameHooks.StartWar(_msg);
|
||||
}
|
||||
};
|
||||
|
||||
Game_Modify.Reconnect = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.Reconnect) {
|
||||
return SubGameHooks.Reconnect(_msg);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### B 类 — 有平台默认返回值(无 hook 即返回默认)
|
||||
@@ -156,37 +135,23 @@ Game_Modify.getMaxPlayerCount = function (roomtype) {
|
||||
}
|
||||
return (Game_Config.Max && Game_Config.Max.PlayerCnt) || 4;
|
||||
};
|
||||
|
||||
Game_Modify.getLeaveLimit = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getLeaveLimit) {
|
||||
return SubGameHooks.getLeaveLimit(roomtype);
|
||||
}
|
||||
return 10;
|
||||
};
|
||||
|
||||
gameHallImport.isInstalled = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.isInstalled) {
|
||||
return SubGameHooks.isInstalled();
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
```
|
||||
|
||||
`gameHallImport.*` 侧同理(如 `isInstalled` 无 hook 返回 `1`、`getLeaveLimit` 返回 `10`)。
|
||||
|
||||
### C 类 — 配置数据(不是 hook,留配置文件)
|
||||
|
||||
`Game_Config.*`(00 全部)与房型数据(`Game_Modify.Type_1/Type_2/CreateRoomData/game_config`、`Game_Modify.combat/roomDes`)属于**配置数据**而非行为接口,不进 `SubGameHooks`。
|
||||
|
||||
模板在 01 文件顶部设置「配置区」,由子游戏直接填值:
|
||||
模板在 01 文件顶部设置「配置区」,由子游戏直接填值(与转发壳接口段物理分开):`Game_Modify.combat/roomDes/Type_1/Type_2/CreateRoomData/game_config`。
|
||||
|
||||
```js
|
||||
// 01_SubGame_modify.js 顶部:配置区(子游戏填值,与转发壳接口段物理分开)
|
||||
Game_Modify.combat = null; // 战绩配置,子游戏按需赋值
|
||||
Game_Modify.roomDes = ''; // 房间描述
|
||||
Game_Modify.Type_1 = []; // 房型一级选项
|
||||
Game_Modify.Type_2 = []; // 房型二级选项
|
||||
Game_Modify.CreateRoomData = []; // 创建房间数据
|
||||
Game_Modify.game_config = {}; // 游戏配置
|
||||
```
|
||||
### D 类 — 模板默认 UI 渲染(可变人数)
|
||||
|
||||
少数 UI 接口无 hook 时,模板不止 no-op,而是提供一套**可变人数**的默认渲染(随房间 2/3/4 人自适应各玩家位):`updatePlayerInfoUI`(玩家头像/昵称/分数)、`ShowChat`(桌面文字聊天气泡)、`gameui_play_voice` / `gameui_stop_voice`(桌面语音气泡)。
|
||||
|
||||
- 渲染只用平台全局数据(`Desk`/`C_Player`/`Game_Config`),并一律经框架 `SpriteManager` 操作精灵,**不引用 codes、不直接调引擎原语**。
|
||||
- 座位→显示位的映射(2/3 人时精灵槽 ≠ 物理布局位)由内部助手统一解析,保证头像面板与聊天/语音气泡落在同一玩家位。
|
||||
- **布局配置挂在 `Game_Modify` 下**(01 配置区,与 C 类配置数据同处):玩家信息用 `Game_Modify.PLAYER_INFO_LAYOUT`、聊天/语音气泡用 `Game_Modify.BUBBLE_LAYOUT`;子游戏可调这些坐标,或用同名 hook 完全接管该 UI。
|
||||
|
||||
---
|
||||
|
||||
@@ -203,30 +168,22 @@ Game_Modify.game_config = {}; // 游戏配置
|
||||
|
||||
目前仅 `appStart` 存在此冲突。`gameHallImport` 侧所有同名接口均加 `hall` 前缀以区分。
|
||||
|
||||
```js
|
||||
// SubGameHooks.js 中的写法
|
||||
SubGameHooks.appStart = function () {
|
||||
// 对应 Game_Modify.appStart:委托子游戏的启动编排
|
||||
};
|
||||
|
||||
SubGameHooks.hallAppStart = function () {
|
||||
// 对应 gameHallImport.appStart(大厅启动):委托子游戏的大厅初始化
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 接口覆盖要求
|
||||
|
||||
转发壳必须**逐个覆盖全部平台接口**,遗漏会导致新游戏某平台调用落空(静默失败)。接口分三组,总计 **63 个**:
|
||||
转发壳必须**逐个覆盖全部平台接口**,遗漏会导致新游戏某平台调用落空(静默失败)。接口分组如下:
|
||||
|
||||
| 来源 | 数量 | 说明 |
|
||||
|------|------|------|
|
||||
| `gameHallImport.*` | 9 | 大厅相关;其中 `appStart` 对应 `SubGameHooks.hallAppStart`(加 `hall` 前缀) |
|
||||
| `Game_Modify.*`(事件/交互,01 段) | 9 | 精灵事件类默认 no-op,改用框架 `SpriteEventController` |
|
||||
| `Game_Modify.*`(生命周期/回调,02 段) | 45 | 多为 A 类 no-op,少量 B 类需给平台默认返回值 |
|
||||
| `Game_Modify.*`(桌面聊天/语音气泡) | 3 | `ShowChat` / `gameui_play_voice` / `gameui_stop_voice`;D 类,模板提供可变人数默认渲染 |
|
||||
|
||||
覆盖原则:**A 类无 hook 即 no-op;B 类无 hook 须返回有意义的平台默认值**(如玩家数、离开上限、房间文案等),而非静默返回 `undefined`。各接口的具体分类与默认值以平台接入 spec 为权威,接入时逐一核对。
|
||||
前三组共 63 项以平台接入 spec §9 为权威;桌面聊天/语音 3 项由本模板补充转发并提供可变人数默认。
|
||||
|
||||
覆盖原则:**A 类无 hook 即 no-op;B 类无 hook 须返回有意义的平台默认值**(如玩家数、离开上限、房间文案),**D 类无 hook 由模板按可变人数渲染默认 UI**(玩家信息/聊天/语音气泡,布局配置在 `Game_Modify`),均不应静默返回 `undefined`。各接口的具体分类与默认值以 spec 为权威,接入时逐一核对。
|
||||
|
||||
---
|
||||
|
||||
@@ -265,7 +222,7 @@ SubGameHooks.hallAppStart = function () {
|
||||
|
||||
| 验证项 | 方法 |
|
||||
|--------|------|
|
||||
| 接口不遗漏 | grep 对比三文件原定义与转发壳一一对应(63 个) |
|
||||
| 接口不遗漏 | grep 对比三文件原定义与转发壳一一对应(基础 63 项 + 桌面气泡 3 项) |
|
||||
| 签名不变 | 检查平台调用处参数与转发壳参数列表一致 |
|
||||
| 行为等价 | 逐接口黑盒测试(开局/重连/战绩/离开等主流程) |
|
||||
| 配置值完整 | `Game_Config.*` 与配置区数据均已保留 |
|
||||
@@ -284,7 +241,7 @@ SubGameHooks.hallAppStart = function () {
|
||||
| **配置值留配置文件** | `Game_Config.*` 和配置区数据(`Type_1/2/CreateRoomData` 等)不得塞进 `SubGameHooks`,保留在对应配置位置 |
|
||||
| **hook 签名必须与平台接口一致** | 平台按位置传参,转发壳以相同参数透传给 hook,hook 签名不得偏移 |
|
||||
| **二选一,不混用** | 同一接口不允许在三文件内联实现与 `SubGameHooks` 中同时存在 |
|
||||
| **转发壳必须全覆盖** | 转发壳须覆盖全部 63 个接口,遗漏会导致平台调用落空(静默失败) |
|
||||
| **转发壳必须全覆盖** | 转发壳须覆盖全部平台接口(基础 63 项 + 桌面聊天/语音气泡 3 项),遗漏会导致平台调用落空(静默失败) |
|
||||
| **严格 ES5** | `SubGameHooks.js` 与所有 codes 文件一律 ES5,禁 `let`/`const`/箭头函数等 |
|
||||
| **加载顺序正确** | `SubGameHooks.js` 须在其依赖的 controllers/handlers 之后、三文件之前加载 |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user