feat: integrate platform room entry, UI migration and erqiwang documentation
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# Room entry template implementation
|
||||
|
||||
Spec: ../specs/2026-09-07-room-entry-template-design.md (approved).
|
||||
|
||||
Constraints: server zero changes; opaque subgame-owned roomtype; no serialized asset text edits; preserve working tree; main checkout branch; no automatic commits.
|
||||
|
||||
## Task 1: platform create-room lifecycle
|
||||
Implement exact create_room request and independent response parsing, state construction traced to Desk.create_room, runtime command/session routing and room scene handoff. Test precise fields, denial, duplicate outcomes and module lifecycle. Own framework protocol/platform files and corresponding tests. Do not edit Startup or UI. Expose runtime.createRoom({roomtype,location,ip}). Existing self_join_room remains compatible. Report source evidence and API changes.
|
||||
|
||||
## Task 2: template entry and room UI
|
||||
Implement pre-room page contract and template rules adapter; JoinRoom input and template create page components with source behavior. Wire LobbyAssets, lobby panel, Startup and usable template room shell through existing GameHost. Use Cocos editor for prefab references/components. No invented gameplay. Test source keypad and exact template array, roomtype validation and host disposal.
|
||||
|
||||
## Task 3: integration verification
|
||||
Run framework tests, strict Cocos typecheck, import boundaries, local fixture preview for keypad/create options/wait/close and successful room handoff/exit. Review combined feature against spec. Document actual server test limitations.
|
||||
|
||||
## Progress / rulings
|
||||
- Initial: no implementation yet. Existing working tree snapshot stored in YouleNexus/temp/room-entry-baseline.
|
||||
- Task 1 produces createRoom consumed by Task 2; no shared edits beyond read-only imports. Task 3 consumes both. Each task matches the approved spec.
|
||||
- Ruling: use the main checkout branch and preserve dirty state, as required by repository/user preference; no worktree or automatic commit.
|
||||
- Task 1: complete. Separate create parser/store/session/command paths and numeric join; 223 combined targeted tests pass after review correction for immutable resolver input.
|
||||
- Task 2: complete. Serialized page controls, subgame CreateRoomPage contract, template entry/room shell, Startup and lobby wiring. Source template capacity is 10 via Desk.Create and Game_Config.Max.PlayerCnt; no roomtype index inference.
|
||||
- Task 3: complete. Cocos 30 checks pass, both strict typechecks and import boundaries pass. Full suite 770/775; five existing login path/channel fixture failures documented in integration report. Reviewed protocol and integration fixes; no remaining scoped findings.
|
||||
- Ruling: closed pages cancel callbacks and loading but cannot cancel a server request already sent. The platform continues to accept authoritative success replies; no invented correlation IDs or cancellation RPCs.
|
||||
@@ -0,0 +1,30 @@
|
||||
# 邀请码接线验证
|
||||
|
||||
分支:`codex/invite-code-wiring`。
|
||||
|
||||
## 行为与来源
|
||||
|
||||
- `Layer8_Notice/Spirit235` 沿用更多菜单显隐规则;点击发送 `agent/get_player_invitecode`,字段仅为 `agentid/playerid/unionid/openid`,收到响应后打开 `Layer16_Bind`。
|
||||
- `Spirit365` 原生 EditBox:450×60、20 号字,保留前导零,不限制六位长度。`Spirit366` 粘贴剔除非数字;settings 无参数调用,WVJB 传空字符串并使用回调。纯浏览器调用 Clipboard API,失败显式提示。
|
||||
- `Spirit367` 关闭弹窗并发送 `agent/binding_invitecode`,字段仅为 `agentid/playerid/invitecode`。成功才更新玩家邀请码,显示服务器 `error` 提示;已绑定隐藏输入、粘贴、提交并显示绑定码。`Spirit362` 关闭。
|
||||
- 身份来源遵循登录模式:非设备登录来自授权账号,设备登录来自回包;重连保留该来源,unionid 保持 string/number 原类型。
|
||||
- 查询/提交等待期间抑制重复请求,超时和断线释放等待状态;迟到粘贴不会影响已关闭弹窗。
|
||||
- 序列化资源仅经 Cocos MCP、引擎序列化和 asset-db 保存。输入文本采用 EditBox 需要的左上锚点;已绑定文本采用左锚点,左距 403 对应源工程 x=243 加 1600/1280 画布差的一半。
|
||||
|
||||
权威依据:`docs/protocol/02-协议-agent路由.md` 邀请码章节、`04-数据结构.md` 登录身份说明;原工程 `11_GameUI.js` 的 235/362/366/367 分支和 OpenBind,`06_Player.js` 绑定响应,`05_Func.js` 粘贴接口,`save/Layer00016.xml` 输入尺寸。
|
||||
|
||||
## 验证
|
||||
|
||||
- 233 项相关回归通过(platform 全部测试、platform-handlers、lobby-menu、invite-clipboard)。覆盖两种登录模式、数字 unionid、重连、准确出包、失败状态不覆盖和数据非法时不提交。
|
||||
- Cocos Game View 中运行 `cocoscreator_projects/scripts/verify-invite-preview.mjs`,29 项断言通过:实际 prefab、Runtime/Router/Store/UI 全链路,记录出包并注入响应。包括输入、粘贴、重复点击、成功/失败提示、反复打开、已绑定状态、文字边界和断线。
|
||||
- 未绑定及已绑定截图已人工检查:`YouleNexus/temp/mcp-captures/invite-full.png`、`invite-bound.png`。
|
||||
- prefab 的 5 个资源引用全部有效;导入边界检查通过。
|
||||
- 框架类型检查通过,命令附加 `--lib es2022,dom`;Cocos 脚本类型检查附加 `--ignoreDeprecations 6.0 --skipLibCheck --lib es2022,dom --types node --strictNullChecks` 后通过。未修改现有 tsconfig;原始配置存在旧库目标/引擎声明兼容问题。
|
||||
|
||||
预览使用隔离记录端口,没有向真实账号提交绑定。原生桥参数由自动测试验证,尚未进行手机真机剪贴板验收。
|
||||
|
||||
## 联调修正:字符串 state 导致断线
|
||||
|
||||
用户实际绑定时收到字符串 `state`,初版 `requireInteger(raw.state)` 拒绝字符串,沿 Router → PlatformRuntime fatal 路径主动关闭连接。原工程的 `state == 0` 支持字符串状态;初版数字回包测试漏掉了这类实际数据。
|
||||
|
||||
修复限定在 `applyInviteBinding` 的协议入口:整数型字符串先归一化,再校验整数;未改变共享校验器和服务器。新增完整运行时回归覆盖 `0/"0"/1/"1"/-1/"-1"`,断言显示服务器反馈、连接关闭次数保持 0、继续查询可用。空串、null、boolean、非数字和小数字符串仍作为非法状态拒绝,且不提交状态。预览脚本也已改用字符串成功/失败响应。
|
||||
@@ -0,0 +1,10 @@
|
||||
# Layer9_Feedback 最后两个分组拆分
|
||||
|
||||
- `assets/framework/ui/prefabs/widgets/RedeemCode.prefab`:只包含 group-74,保留当前兑换码输入、粘贴、兑换、遮罩关闭逻辑。
|
||||
- `assets/framework/ui/prefabs/widgets/QrCode.prefab`:只包含 group-42,保留二维码加载、分享、遮罩关闭及图片资源释放逻辑。
|
||||
- `LobbyAssets.redeemCode`、`LobbyAssets.qrCode` 已在 PlatformStartup.scene 中指定对应资源。
|
||||
- 已删除不再使用的 `Layer9_Feedback.prefab` 及 meta,并移除共享 `notices` 资源字段。公告数据模型中的 notices 数据字段仍然保留。
|
||||
|
||||
15 项兑换码/二维码 Game View 检查通过,使用本地粘贴、图片回调、兑换和分享测试替身,没有实际兑换或原生分享。房间列表 18 项、公告 43 项回归检查通过。2 项分享模型测试、严格类型检查和导入边界检查通过;两个 prefab 共 11 个引用均有效。
|
||||
|
||||
可复用脚本:`cocoscreator_projects/scripts/verify-feedback-split-preview.mjs`。序列化资源均通过编辑器 API 操作。
|
||||
@@ -0,0 +1,20 @@
|
||||
# 公告独立 prefab 与原生选项卡
|
||||
|
||||
`assets/framework/ui/prefabs/widgets/NoticeBoard.prefab` 单独承载 `group-12`,原 `Layer9_Feedback.prefab` 保留反馈、二维码、房间列表三个分组。`PlatformStartup.scene` 的 `LobbyAssets.noticeBoard` 已引用新资源;其他入口继续使用原 `notices` 引用。
|
||||
|
||||
在新 prefab 的 `group-12/NoticeTabs` 中配置:
|
||||
|
||||
- `ToggleContainer`:禁止全部取消,三个 Toggle 直接作为子节点。
|
||||
- 纵向 `Layout`:自动排列三个高度 92 的选项,隐藏项不占位。
|
||||
- `NoticeTabsView`:指定三个 Toggle、背景及标题 Sprite,以及各自正常/选中 SpriteFrame。
|
||||
- 每项分别组合原 `Spirit570/573`、`Spirit571/574`、`Spirit572/575`,统一点击区域,保留美术资源。背景使用 `00216_2/00216_1`;标题正常/选中使用 `00217_1/2`、`00217_3/4`、`00217_5/6`,与原工程相同。
|
||||
|
||||
公告入口默认选择第一页,后两页沿用原有内容可见性规则。Toggle 事件驱动原公告文字/图片显示逻辑,关闭时释放监听,重新打开重置选择。
|
||||
|
||||
验证:37 项 Game View 检查通过,覆盖三页互斥与图片状态、隐藏中间项、回调释放、内容切换、关闭与重新打开、启动场景引用和原分组保留;9 项相关单元测试、严格类型检查、导入边界检查通过。新旧 prefab 共 40 个引用全部有效。已检查实际渲染;点击验证采用 Cocos 原生 Button 事件驱动 Toggle,并非物理鼠标实点。
|
||||
|
||||
可复用脚本:`cocoscreator_projects/scripts/verify-notice-tabs-preview.mjs`。本次资源均通过编辑器 API 保存。
|
||||
|
||||
后续点击范围修正:打开公告时,为通知背景、通知标题、通知标题内容添加 BlockInputEvents,防止点击穿透到遮罩。只有遮罩和通知关闭按钮负责退出。新增 Cocos 坐标触摸命中测试,覆盖背景空白、标题、正文、选项卡不关闭,关闭按钮和遮罩关闭;现共 43 项检查通过,严格类型检查通过。
|
||||
|
||||
收尾时,旧 prefab 编辑视图仍显示拆分前的分组,已在该视图移除 group-12;随后 `save_current_scene` 同步调用未返回,已停止等待。上述磁盘资源保存和验证在此之前均已完成,编辑视图是否同步完成未确认,可重新打开 NoticeBoard.prefab 查看新资源。
|
||||
@@ -0,0 +1,35 @@
|
||||
# 大厅、通知和设置的可选动画
|
||||
|
||||
## 配置方法
|
||||
|
||||
在 Cocos Creator 中打开对应 prefab,选择目标节点。
|
||||
|
||||
- 大厅和通知节点已经挂好 `Animation` 与 `OptionalUiAnimation`。把制作好的片段拖到 `Animation` 的 **Default Clip**,片段的 **Wrap Mode** 决定单次或循环播放。保持 **Play On Load** 关闭,由组件在节点显示时播放、隐藏时停止,再显示时重新开始。未指定 Default Clip 时保持原来的静态表现。
|
||||
- 设置开关已经挂好 `Animation` 与 `OptionalSwitchAnimation`。把片段分别拖到后者的 **开启片段**、**关闭片段**。两个字段各自可空;缺少该方向的片段时立即切换图片。开关过渡只播一次,完成、隐藏或被反向切换时,状态图片服从最新开关状态。
|
||||
- 片段以当前节点为绑定根。Sprite 换帧轨道绑定当前节点的 `cc.Sprite.spriteFrame`。制作位移等轨道时,要考虑节点现有 Widget 对布局的约束。
|
||||
|
||||
## 已配置范围
|
||||
|
||||
- `Layer4_MainMenu`:Spirit479、Spirit3120、Spirit76、Spirit11、Spirit12、Spirit14、Spirit17、Spirit13、Spirit7。
|
||||
- `Layer8_Notice`:Spirit3121、Spirit3017、Spirit5、Spirit235、Spirit604、Spirit3057、Spirit15。
|
||||
- `Layer609_Setting`:音乐底、音效底、Spirit357、Spirit388。
|
||||
|
||||
Spirit479 已指定 `assets/framework/ui/animations/AnnouncementHorn.anim`:沿用原有两张喇叭图片,2 秒循环,在 0.5 秒切到第二张、1 秒切回第一张。`AnnouncementView` 继续负责公告文字移动,喇叭换帧由片段负责。
|
||||
|
||||
其余节点暂未制作或指定新片段,保持当前表现。音乐和音效已接入状态切换动画;Spirit357、Spirit388 仍保留“原生震动与语音开关尚未接入”的提示,仅预留动画组件。以后业务接通时,由状态拥有方调用 `setState(on, stateFrame, animate)`;初始化用 `animate=false`,用户切换用 `true`。
|
||||
|
||||
## 验证
|
||||
|
||||
`cocoscreator_projects/scripts/verify-optional-animation-preview.mjs` 在 Cocos Game View 中执行,使用真实 Animation 组件和独立测试节点,检查资源接线、无片段静态表现、显隐重播、喇叭帧序列、开关中断及实际音乐/音效点击与再次打开。测试使用独立的存储键并在结束时恢复。
|
||||
|
||||
三个 prefab 通过 Cocos MCP 序列化及 asset-db 保存,原节点 prefab fileId、布局和原有组件属性保留;新组件获得独立 fileId。
|
||||
|
||||
2026-09-07 验证结果:Game View 44 项检查通过,期间无警告或错误;三个 prefab 的资源引用检查通过,缺失引用为 0;公告、大厅菜单和登录动画的 10 项既有测试通过,导入边界检查通过。
|
||||
|
||||
工程脚本严格类型检查通过,命令在 `cocoscreator_projects` 执行:
|
||||
|
||||
```powershell
|
||||
node node_modules/typescript/bin/tsc -p YouleNexus/tsconfig.json --noEmit --ignoreDeprecations 6.0 --skipLibCheck --lib ES2022,DOM --types node --strict
|
||||
```
|
||||
|
||||
原始检查入口仍有环境限制:Cocos 内置旧版 TypeScript 不支持工程使用的新语法;未加上述库选项的检查还会报告引擎声明及标准库版本问题。本次未修改这些全局配置。
|
||||
@@ -0,0 +1,12 @@
|
||||
# 我的开房列表拆分
|
||||
|
||||
- `assets/framework/ui/prefabs/widgets/OwnedRoomList.prefab` 独立承载原 `group-98`,已绑定 `LobbyAssets.ownedRoomList`。
|
||||
- `assets/framework/ui/prefabs/widgets/OwnerRoomItem.prefab` 从用户整理的条目创建,保留背景与数字图片。条目内部坐标改为相对条目中心,房间号数字容器使用横向 Layout。
|
||||
- 列表背景保持用户调整后的 280×530 尺寸和位置。其下 `RoomScrollView` 使用 Mask、纵向 ScrollView;边距左/右 8、上 55、下 10。`Content` 使用纵向 Layout,间距 5;条目尺寸 264×80。
|
||||
- 根节点 `OwnerRoomListView` 已指定条目 prefab、Content 和 ScrollView。数字图片仍由现有 `LobbyAssets.ownedRoomDigits` 提供。
|
||||
- 取消显示前五条的截断,按既有 OwnedRoomHistory 顺序显示全部记录。条目点击继续调用原 joinOwned,拖动不触发加入;背景阻止穿透,遮罩负责关闭。重新打开回到顶部。
|
||||
- 空列表明确清空高度并暂停 Layout,重新加入条目恢复布局,避免引擎在零条目时计算出负间距高度。
|
||||
|
||||
验证:18 项房间列表 Game View 检查通过(包括坐标拖动、滚到底部点击最后一条、遮罩关闭、空列表与重新填充),43 项公告回归检查通过。原房间历史生命周期单元测试、严格类型检查和导入边界检查通过。新 prefab 缺失引用为 0;已检查实际渲染。
|
||||
|
||||
预览脚本:`cocoscreator_projects/scripts/verify-owner-room-preview.mjs`。序列化资源通过 Cocos 编辑器 API 创建和保存,服务器协议与数据来源未改。
|
||||
@@ -0,0 +1,28 @@
|
||||
# 资料列表与实名认证接线
|
||||
|
||||
## 资料列表
|
||||
|
||||
`Layer17_PlayerInfo` 保留调整后的精灵层级。`InfoText` 作为可滚动视口,`Content` 使用纵向 Layout,根据显示的数据实例化 `PlayerInfoTextItem.prefab`。文字自动换行并调整行高,删除项目后不留空行;签名背景作为最后一项随文字增高,内容超出视口时可以滚动。
|
||||
|
||||
- 字体、颜色、行宽:在 `assets/framework/ui/prefabs/widgets/PlayerInfoTextItem.prefab` 的 Label 中配置,沿用原文字样式。
|
||||
- 项目间距:在 `Layer17_PlayerInfo/InfoText/Content` 对应节点的 Layout 配置(实际位于 group-18 下),当前 `spacingY=14`。
|
||||
- 签名背景:最小高度 79,文字上下内边距 10。
|
||||
- 根节点 `ProfileInfoListView` 已指定文本 prefab、认证 prefab、容器、滚动组件和签名引用。
|
||||
- `lobby-panel.ts` 提供有序文字数组;新增或移除显示字段不需要手工摆放坐标。
|
||||
|
||||
## 实名认证
|
||||
|
||||
`Spirit484` 打开 `Layer18_Auth`;姓名、身份证输入框,`Spirit493` 提交,以及 `Spirit485` 退出已接通。背景启用拦截,输入框支持身份证末位 X,重新打开时清空输入。
|
||||
|
||||
严格沿用原工程 `03_Banwords.js` 的本地姓名长度、身份证地址/日期范围/校验位规则及提示文案。原工程没有服务器身份核验请求,本次也不产生该请求、不保存身份证信息;“认证成功!”仅表示通过原工程的本地校验。
|
||||
|
||||
## 验证
|
||||
|
||||
- Game View 中 37 项检查通过,覆盖动态行数、换行、签名增高、滚动回缩、实际 LobbyPanel 接线、输入错误提示、提交和退出事件。
|
||||
- 12 项相关单元测试通过,包括与原始 IDValidator 对照的校验测试。
|
||||
- Cocos 工程严格类型检查、导入边界检查通过;三个 prefab 的缺失引用均为 0。
|
||||
- 已检查资料页、认证页实际渲染,修正 EditBox 文字垂直偏移,并通过原生输入验证中文姓名及含 X 的身份证文本。
|
||||
- Electron 鼠标模拟未进入 Game View 的 Cocos 输入系统,因此鼠标实点退出未验证;退出按钮事件接线已通过运行时检查。
|
||||
- 核对任务开始时的文件哈希,既有改动中仅预定的 Layer17 prefab 与 lobby-panel.ts 发生变化,其余保留。
|
||||
|
||||
可复用预览检查脚本:`cocoscreator_projects/scripts/verify-profile-preview.mjs`。所有序列化资源均通过 Cocos 编辑器 API 创建和保存。
|
||||
@@ -0,0 +1,35 @@
|
||||
# 模板房间接入验收
|
||||
|
||||
依据:已确认的 `2026-09-07-room-entry-template-design.md`。分支 `codex/room-entry-template`;未提交或合并。服务器零改动。
|
||||
|
||||
## 已接入
|
||||
|
||||
- Layer15_JoinRoom:0–9、删除、重输、粘贴、短号确认、6 位自动提交。显示保留前导零,出站房号按原模板为 number。复用 00046 BitmapFont;原有 Sprite 数字槽改为 Label。
|
||||
- Layer27_CreateRoom:根节点挂 TemplateCreateRoomView,使用两个 Cocos ToggleContainer。选择与上次 roomtype 的读取遵循原模板;创建按钮仍发原源码固定数组。重新对齐选项、标签和关闭按钮,面板背景阻止点击穿透。
|
||||
- create_room 请求、独立创建回包解析和权威房间状态建立;创建回包不要求 players。创建成功的自己资料来自已登录玩家,不向原始回包添加虚构字段。
|
||||
- 平台与子游戏双向调用沿用 GameEntry / GameModule / GameHost:成功提交状态后挂载模块,房间视图消费快照,准备/退出经受限 host 发回平台。替换原登录专用拒绝房间入口。
|
||||
- 请求防重复、15 秒超时、错误与断线结束等待;断线关闭房间页并使迟到剪贴板回调失效。关闭页不能撤销已经发往服务器的请求,迟到成功仍由平台按服务器状态进入房间。
|
||||
- 原样传递 join/login 的 deskinfo。解析人数前传给子游戏的是不可变 roomtype 副本,防止污染服务器原始数据。
|
||||
|
||||
## 子游戏如何换创建页
|
||||
|
||||
1. 在自己的 prefab 根节点挂继承 `assets/scripts/platform-login/CreateRoomPage.ts` 的脚本,实现 `open(context)`、`setBusy(busy)`、`close()`。
|
||||
2. 子游戏自行管理选项、布局、校验和异步回调,调用 `context.submit(roomtype)` 提交已经验证的数组,调用 `context.cancel()` 关闭。
|
||||
3. 在 PlatformStartup 场景的 SubgameAssets.createRoom 指定该 prefab。平台不访问其 group/Spirit 节点。
|
||||
4. 子游戏的 GameEntry 提供实际 route、resolveSeatCount 和 GameModule。本次模板注册放在 Startup 的组合入口;不把模板的示例规则作为其他游戏的默认值。
|
||||
|
||||
模板的 Desk.Create 在没有 getMaxPlayerCount 钩子时明确采用 Game_Config.Max.PlayerCnt=10。本次 TemplateRoomRules 保留该容量;其他游戏必须用自己的真实人数规则。模板没有玩法网络实现,`Game_Surface_3` 模块标识不是任何具体游戏服务器路由的认证结果。TemplateRoom.prefab 是房间接管演示页,不是已完成的牌桌玩法。
|
||||
|
||||
## 验证结果
|
||||
|
||||
- 223 项房间相关平台/协议/模型测试通过。
|
||||
- Cocos Game View 30 项检查通过:真实坐标点击键盘、数字显示、删除/粘贴、ToggleContainer(再次点击选中项保持选中)、防重复、迟到回调取消、超时、创建拒绝、创建成功真实加载 TemplateRoom 场景、准备/退出 GameHost、重复成功不重挂、加入成功及 deskinfo 原样恢复。脚本:`cocoscreator_projects/scripts/verify-room-entry-preview.mjs`。实际 socket 在测试前停止,测试回包与出站捕获仅在本地运行。
|
||||
- Cocos 与 framework 两个严格 TypeScript 检查通过(ES2022/DOM,TypeScript 6);import boundaries 通过。
|
||||
- 三个 prefab 共 55 个资源引用校验,无缺失;截图检查创建页和加入页布局。
|
||||
- 全量 775 项测试:770 通过,5 失败。3 项旧迁移测试仍读取已在本任务前移走的 Login_Layer.prefab;2 项账号/登录策略测试硬编码旧 agentid/channelid,与本任务前已调整的 defaults 配置不一致。未为测试改回用户的配置或资源名称。
|
||||
- 基线哈希核对:原有序列化资源仅 PlatformStartup.scene、Layer15_JoinRoom.prefab、Layer27_CreateRoom.prefab 变化。其余原有 scene/prefab/anim/meta 保持基线。
|
||||
- 协议审查发现的可变数组问题、集成审查发现的断线剪贴板问题均已修复并复核。
|
||||
|
||||
未进行实际服务器创建/加入联调,未实现具体子游戏的规则解释、玩法消息或牌桌操作。本次确认的是模板页面与平台房间交接边界。
|
||||
|
||||
截图:`cocoscreator_projects/YouleNexus/temp/mcp-captures/room-create.png`、`room-join.png`。
|
||||
@@ -0,0 +1,45 @@
|
||||
# Room protocol implementation — 2026-09-07
|
||||
|
||||
Implemented Task 1 of the approved room-entry template plan. No server, SDK, Startup, UI, or serialized asset changes were made by this task. Existing dirty work was preserved; no commits were made.
|
||||
|
||||
## Source evidence
|
||||
|
||||
- `docs/protocol/02-协议-agent路由.md`, create_room / self_join_room: outbound agent route and exact identity, roomtype, IP and location fields.
|
||||
- `projects/Game_Surface_3/js/00_Surface/09_Net.js:104-119`: create request adds C_Player.ip / addr; response calls Desk.create_room, ends loading and calls the subgame hook.
|
||||
- `projects/Game_Surface_3/js/00_Surface/07_Desk.js:456-536`: create success does not consume players; sets local seat, resets isprepare, seats C_Player, then displays the room. Failure only displays the server error when requested.
|
||||
- `07_Desk.js:149-156`: Desk.Init starts stage, needprepare and infinite at zero; create response overrides the latter two only when present. These defaults are owned by the create parser, not guessed downstream.
|
||||
- `06_Player.js:19,69,279-285`: new/local player online state is zero and SetDeskInfo copies it. Created-room canonical self profile comes from the login player, with preparation reset.
|
||||
- `12_Logic.js:1024-1055`: keypad join submits Number(RoomCode). Numeric roomcode is now preserved by the join request builder while existing string callers remain unchanged.
|
||||
|
||||
## API and state
|
||||
|
||||
- `PlatformRuntime.createRoom({roomtype, location, ip})` delegates to `PlatformCommands`, requires authenticated lobby state and an open wire, sends exactly app/route/rpc plus agentid/playerid/gameid/roomtype/ip/location.
|
||||
- Reuses the existing defensive roomtype clone to reject non-JSON values without inspecting subgame array indices or rewriting rules.
|
||||
- Independent `parseCreateRoomResponse` accepts successful create data without players and retains raw data unchanged. `PlatformStore.createRoom` constructs canonical seats from `GameEntry.resolveSeatCount`, places the login player at the server seat, and never manufactures wire players or other raw fields.
|
||||
- Create denial retains state and reports `ServerDenial.rpc='create_room'`. Successful create opens the leased GameModule, publishes room.entered, and shows the room. The original create path has no deskinfo restoration; join/login restoration behavior is preserved.
|
||||
- Duplicate create success for the active room and duplicate join success during the active joined session do not reattach or restore a module. Login/switch/exit cleanup resets join deduplication.
|
||||
- Runtime join/create scene handoff checks that canonical room state is inside; denied lobby join cannot attempt to show an inactive module.
|
||||
|
||||
## Verification
|
||||
|
||||
- Red tests observed missing create command/session methods and duplicate join state/module replacement before implementation.
|
||||
- 180 tests passed: platform commands, runtime-session, runtime, and all protocol test files, using `node --experimental-transform-types --test`.
|
||||
- 37 platform-store tests passed separately.
|
||||
- `node cocoscreator_projects/scripts/check-import-boundaries.mjs`: OK.
|
||||
- New runtime end-to-end fixture verifies exact create RPC, denial with no module/scene, successful ten-seat entry, duplicate reply with one scene activation/module attachment, and module disposal on stop.
|
||||
- Framework tsc was attempted with `cocoscreator_projects/node_modules/typescript/bin/tsc`. No new protocol/platform implementation errors; the combined tree currently has pre-existing runtime test Array.at library errors and concurrent template UI/test type errors. Parent owns combined typecheck resolution.
|
||||
- Outputs: `cocoscreator_projects/YouleNexus/temp/room-protocol-tests.txt` and `room-protocol-store-tests.txt`.
|
||||
|
||||
## Integration boundaries
|
||||
|
||||
Parent owns page waits, repeated submit prevention, timeout/disconnect/close cleanup and user error display. Runtime has no invented request correlation ID. Real server interoperability and Cocos visual acceptance were not performed by this task. Generic startup GameEntry validation already probes and disposes a module; tests distinguish that existing startup probe from actual room entry attachment.
|
||||
|
||||
## Review follow-up: immutable resolver boundary
|
||||
|
||||
Confirmed the initial create-room path passed `parsed.room.roomtype` directly to the subgame seat resolver before canonical state construction. A resolver could mutate the inbound array or its nested objects, changing server data before commit.
|
||||
|
||||
`RuntimeSession.handleCreateRoom` now uses the existing `cloneAndFreezeRoomtype` rules before calling `resolveSeatCount`. The resolver receives a deeply immutable owned copy; raw response data remains untouched. The store still independently constructs canonical state using the original parsed response, with no fabricated input fields.
|
||||
|
||||
Two regressions attempted top-level and nested mutation. Both failed before the fix because no exception occurred. After the fix, both throw TypeError; the raw array and nested object remain unchanged and unfrozen, the prior store root remains identical, no module opens and no partial room state is committed. Re-reviewed create denial, invalid seat count, room command fields, duplicate response handling and scene ordering; existing targeted tests remain green.
|
||||
|
||||
Verification: 149 tests passed across runtime-session, runtime, commands and platform-store. Framework tsc reports only the previously communicated runtime Array.at and concurrent template-game test errors, with no error in this change. Parent edits preserved.
|
||||
@@ -0,0 +1,36 @@
|
||||
# 模板创建与加入房间接入设计
|
||||
|
||||
## 已确认依据
|
||||
|
||||
以 `projects/Game_Surface_3` 为迁移来源。平台不得定义、解释或改写具体玩法的 roomtype;它的生成、业务校验、人数解析属于子游戏。通用页面黑盒改造继续搁置,仅创建房间页采用可替换页面契约。
|
||||
|
||||
## 职责边界
|
||||
|
||||
1. 平台加入页:Layer15_JoinRoom 的数字输入、删除、清空、提交、关闭与等待显示。输入限制和提交时机逐项对照原模板。
|
||||
2. 子游戏创建页:Layer27_CreateRoom 作为模板默认实现,封装自己的节点、布局、选项与交互。平台仅调用页面生命周期和状态接口,接收提交与取消操作,不依赖该页 group/Spirit 路径。
|
||||
3. 子游戏规则适配:由独立的进房前适配对象提供创建页资源和生成配置的能力;内部房间规则模型不进入平台。提交给平台的是已经由子游戏验证的原始 roomtype 数组。平台只检查传输层结构,不补规则默认值。
|
||||
4. 平台房间命令:按 docs/protocol/02 的 create_room、self_join_room 契约,补齐已有权威来源的身份、IP、定位字段,管理重复请求、失败、连接状态和页面生命周期。
|
||||
5. 进房后模块:沿用 GameEntry / GameModule / GameHost 边界,由平台提交房间状态并分发生命周期事件。创建页不能为了显示选项而提前实例化对局 GameModule。
|
||||
|
||||
## 模板兼容要求
|
||||
|
||||
原模板 `01_SubGame_modify.js` 的创建按钮当前发送固定示例数组,而非根据 Type_1/Type_2 选择生成数组。迁移保留这一事实,示例只放在模板适配层,不推导未知索引、不作为其他子游戏的缺省规则。子游戏替换创建页和规则适配后,自行提供完整配置。
|
||||
|
||||
原模板对局钩子多数为空。本次提供平台房间进入及子游戏接管边界、模板实现和验证,不声称已经实现任何具体玩法。不得继续使用会拒绝所有房间操作的 createLoginStageGameEntry 作为最终房间入口。
|
||||
|
||||
## 回包与生命周期
|
||||
|
||||
- 创建成功与加入成功分别解析。创建回包不能直接套用要求 players 数组的现有加入解析器;公共房间状态的建立须逐项追溯原 Desk.create_room 与登录玩家状态,不伪造服务器字段。
|
||||
- 失败不进入房间,不创建对局模块,页面按原流程结束等待并显示错误。
|
||||
- 成功更新权威状态后,再进入房间表现并通知子游戏;避免重复回包导致重复挂载。
|
||||
- deskinfo 原样交给子游戏恢复,平台不解释其玩法内容。保留原工程恢复时机。
|
||||
- 子游戏经受限 GameHost 发起平台动作;平台事件和状态快照是反向通知路径,不共享可变全局对象。
|
||||
- 页面关闭、切场景、断线和退出时,解绑输入、取消页面等待与异步显示回调。
|
||||
|
||||
## 工作范围与验证
|
||||
|
||||
先完成模板创建/加入 UI 与进房前契约,再补平台创建请求/回包、模板 GameEntry 和房间接管;每一段都须可单独测试。已有 SDK、房间状态与座位组件先核对再复用,不另建第二套状态系统。
|
||||
|
||||
验证包含:原模板输入行为与选项行为;精确出站字段及 roomtype 不变;创建成功、加入成功、拒绝、重复提交、超时/断线、恢复、退出;模块生命周期;真实 Cocos prefab 引用、数字键盘、创建页操作、关闭与等待状态。协议验证使用本地测试数据,实际服务器联调结果单独报告。
|
||||
|
||||
所有 prefab/scene/meta 通过 Cocos MCP 编辑器操作;主检出分支工作,保留用户现有资源调整,不自动 stash。
|
||||
Reference in New Issue
Block a user