# 子游戏创建房间接入 返回[接入指南](README.md)。本章对应原工程的“创建页面选择玩法 → create_room → 进入房间”流程。 ## 1. 平台与子游戏的职责 子游戏负责创建页面布局、选项状态、房卡展示、已有配置回显、roomtype 编码和校验。平台负责弹窗生命周期、忙碌状态、统一发包、身份与设备环境注入、响应分发和房间进入。 创建页面只调用 `context.submit(roomtype)`,不自行拼接 agentid/playerid/gameid/ip/location,不直接创建 WebSocket,不自行调用 create_room RPC。 平台将 roomtype 作为不透明配置保存和转发。它会验证可用的数据形态,但不会把所有游戏限制成字符串、数组或同一长度。当前模板使用数组,二七王新请求使用 11 位字符串。禁止对通用 roomtype 使用 String()/JSON.stringify() 进行协议类型转换。 ## 2. 页面契约 接口定义:[create-room-page.ts](../sdk/contracts.md)。引擎组件基类:[CreateRoomPage.ts](../sdk/contracts.md)。 ```ts interface CreateRoomPageContext { readonly previousRoomtype: unknown; submit(roomtype: Roomtype): void; cancel(): void; reportError(message: string): void; } interface CreateRoomPagePort { open(context: CreateRoomPageContext): void; setBusy(busy: boolean): void; close(): void; } ``` 该代码用于说明现有契约;实际开发应直接 import SDK 类型,不复制一份接口到子游戏。 自己的组件应继承 CreateRoomPage,并挂在创建 prefab 的根节点。现有参考: - [ErqiwangCreateRoomView.ts](../sdk/contracts.md) - [TemplateCreateRoomView.ts](../sdk/contracts.md) ### open(context) 1. 先清理前一次打开遗留的监听和 context。 2. 验证必要的编辑器绑定完整,缺少控件时显式报错。 3. 由本游戏规则对象解释 previousRoomtype,恢复 UI 选中状态。 4. 绑定选项、提交和取消操作,保存解除监听的函数。 5. 更新消费展示和按钮状态。 `previousRoomtype === null` 表示没有历史配置,子游戏规则来源可以在此定义自己的首次创建默认值。已有但非法的历史配置不应悄悄替换为默认值;应明确暴露或实现有协议依据的版本迁移。 当前平台从 localStorage 的 `tsgame_roomtype_` 读取历史 JSON 的 data,交给页面。页面不必重新读取本地存储,也不要按另一套 key 再维护一份历史。 ### setBusy(busy) 平台请求期间禁用提交和会改变 roomtype 的选项,避免双击重复创建。取消/关闭策略按业务处理;二七王当前保留关闭入口。忙碌状态由平台驱动,不能以固定延时假装请求结束。 ### close() / onDestroy() 解除所有事件、清空 context,重复调用安全。组件 onDestroy 调用 close。异步回调应检查 context 或会话是否仍有效,关闭后不能继续 submit。 `context.reportError` 当前进入控制台诊断,不是给玩家看的提示接口。编码错误、缺少组件、堆栈等不得通过 Layer612_Tips 展示。 ## 3. roomtype 放在独立规则对象中 建议将规则逻辑放在本游戏的 room-rules.ts,页面只负责从控件调用 select/build。规则对象应能在不启动 Cocos 的情况下测试: - 无历史时的明确默认值。 - 合法历史的解析和回显。 - 非法值拒绝。 - UI 选项到线协议字段的映射。 - 房卡文案所需计算;最终扣卡仍以服务器为准。 - 新请求编码,以及服务器回包/重连输入的解析。 **请求编码与历史解析不一定采用相同的严格程度。** 必须以真实协议和服务端行为为依据,不能为了让旧数据通过而在平台增加通用兜底。 ## 4. 二七王的具体参考 [ErqiwangRoomRules](../sdk/contracts.md) 将 UI 顺序映射到服务器位序。UI 顺序与线协议顺序不同,不可直接拼接各 Toggle 的排列顺序。 当前创建页面需要在编辑器序列化: - 3 个 ToggleContainer。 - 8 个 Toggle,以及对应 8 个选项 Label。 - 1 个提交 Button、2 个关闭/取消 Button。 - 1 个费用 Label。 前三组选项是局数、扣卡方式、查牌设置;后两个独立选项是傍王和爬坡。准确的位定义见[二七王玩法协议](../../subgames/erqiwang/protocol/packet_protocol.md),本指南不另维护一份位索引常量。 当前 build() 新请求输出:**11 位字符串,前 5 位为 0/1,后 6 位为 0**。例如所有开关取 0 时是字符串 `"00000000000"`。此例不是平台默认配置,也不能转换成数字 0。 已有/回包配置解析当前允许至少 5 位、前 5 位为 0/1的字符串;新请求仍固定输出 11 位。二七王座位数由自己的 resolveSeatCount 返回 3,平台不内置该人数。 ## 5. 完整提交与响应链 ```text 大厅打开创建弹窗 → 从 SubgameAssets.createRoom 实例化 prefab → 根节点取得 CreateRoomPage 组件 → page.open(context),回显 previousRoomtype → 点击创建:本游戏 rules.build() → context.submit(roomtype) → 平台请求管理与 PlatformRuntime.createRoom → 既有 agent/create_room RPC → 服务器响应 → RuntimeSession 解析公共响应 → 本游戏 resolveSeatCount(真实 roomtype) → 平台提交房间状态,进入房间会话并挂载视图 ``` 发包信封保持 `app: youle`、`route: agent`、`rpc: create_room`。data 中的身份字段、ip、location 由平台按既有契约提供,roomtype 原样采用子游戏生成值。通用协议入口见[agent 协议 create_room](../protocol/02-协议-agent路由.md)。该文档早期数组描述针对模板,不代表二七王也应发送数组。 发送成功不代表创建成功。必须等待服务器返回:拒绝响应走平台业务拒绝流程;成功响应才进入房间。页面不要在点击提交时直接切换到房间场景。 ## 6. 房间视图与重连接续 创建 prefab、房间 prefab 是不同资源。除了创建页面,还要完成应用注册中的工厂和 roomViewClass,在本游戏定义中声明 room 路径,在 SubgameAssets 保留公共 roomScene 绑定。 房间状态/准备/退出通过公共能力接口;玩法消息通过本游戏 GameModule;登录发现已有房间时,deskinfo 必须由本游戏 restore 解释。只验证 create_room 正常,不足以证明重连已接通。 不要在创建页面 open 中建立房间模块、订阅房间消息或提前发送准备指令;该页面处于入房之前。 ## 7. 推荐验证顺序 1. 纯规则测试:选项组合、历史恢复、边界值、非法输入。 2. 实际 prefab:字段绑定完整,重复打开关闭无重复监听,费用显示正确。 3. 实际按钮提交:截获 context.submit 参数,确认类型与完整 roomtype 内容。二七王可覆盖全部 32 种开关组合。 4. 平台出包:核对最终 agent/create_room 的类型和字段,不能只看规则单测。 5. 成功与拒绝:忙碌状态正确释放,拒绝不进入房间,连续点击不重复发包。 6. 房间接续:创建、加入、退出重进、登录重连、已有牌局 deskinfo 恢复。 7. 资源释放:弹窗关闭及场景销毁后无事件、计时器和迟到提交。 实际服务器操作会创建房间或改变玩家状态,应使用明确的测试账号;纯规则和 prefab 验证可以通过注入 submit 回调完成,不需要真实发包。