Complete room UI and protocol integration, move game definitions and resources behind bundle entries, publish authoritative version XML, and document single-game builds. Include all current resource changes and experiment artifacts.
16 KiB
原接口迁移清单与子游戏接入契约
版本:1.1 · 2026-09-08 · 状态:已落地 API 与兼容边界见第 7 节及实施记录。前文保留原接口迁移目标。
主文档:房间平台架构设计。本清单基于原工程 Input/Output 文件及其调用点,区分“保留业务能力”与“保留旧调用方式”。默认不保留全局 Game_Modify、Utl、Desk、C_Player 接口。
1. 迁移规则
- 保留:协议语义、原始载荷、来源定义的顺序、玩家可观察的正确结果。
- 改造:直接读写全局状态、精灵编号、跨层调用、手工拼公共身份、全局输入回调。
- 分离:在线与回放、局内分数与账户资产、请求与确认、状态重绘与一次性业务副作用。
- 不照搬:示例默认值、空钩子掩盖未接入、吞异常、以显示状态判断业务阶段。
- 必需项缺失在装配时失败;可选项必须声明“未提供”的行为,不能通过任意 fallback 冒充支持。
2. Input:平台通知游戏
源码:02_SubGame_Input.js。
2.1 房间进入与游戏协议
StartWar(_msg) → started 输入。保留触发 sourceRpc 和原整包;包括 self_makewar、makewar、加入/准备附带 deskwar,不仅监听单个 rpc。
_ReceiveData(_msg) → game-message 输入。游戏自己的协议适配器校验 rpc/payload,平台只校验路由归属与传输外层。
createRoom(roomtype,infinite)、onCreateRoom(data) → created 成功输入的游戏适配。旧包装层可能在失败后仍调用钩子,必须记录并改为明确的结果/成功边界,禁止把失败视为建房成功。
myJoinRoom(_msg) → joined 输入及对应 waiting/snapshot/started 分支。不能因为有快照而省略主动加入语义。
Reconnect(deskinfo) → login-restored 输入;ReconnectNoMakewar 虽未在此文件声明,但在 Desk.login 调用,应纳入 login-waiting 契约。
DeskInfo(deskinfo) → joined-snapshot。与登录重连区分,游戏可以映射到共享内部还原函数,但平台不得强迫两者等同。
onCreateDesk(roomtype) → 游戏初始化/规则预检。座位规则可以先运行,任何需要 View 的工作移到挂载就绪后。
2.2 玩家与公共状态
playerJoinRoom、playerLeaveRoom、playerOffline、playerOnline、onReady、changeSeat → 类型明确的公共成员输入,始终使用服务器座位。
myExitRoom、breakRoom → 保留服务端确认的自身离开原因,在旧上下文仍可读取的收尾阶段通知,然后统一释放。游戏不能在通知中再次发送同一退出命令。
playerphonestate → 设备/玩家通话状态能力输入。旧参数 0/1 的实际语义以 Desk.call_phone/hangup_phone 为准,不照抄注释中的歧义文本。
2.3 视图生命周期
onEnterMainScene → View 挂载就绪后的明确通知;不通过读取精灵可见性判断。
onExitMainScene、closeGameScene、stopAllSounds → 由 scope 组织的停止/卸载/音频释放。音频使用房间或游戏专属 owner,不误停应用其他声音。
updateScene → 从现有游戏状态重建展示。不会重新解释创建响应、再次发命令或再次产生分享/活动结果。
onMainMenuScene → 应用/大厅导航生命周期,非每房间 GameModel 必需能力。
2.4 结算与活动
Free → dissolution-settlement,区分普通投票确认与 freeNow。deskfree 内容由游戏解析。
onSurrender → 对应来源的业务结果输入,游戏解释;公共投降入口只负责协议封装和展示流程。
onEnterVideo → 可选回放能力,绑定独立 ReplayContext。
onCloseVip、getShareRoom → 大厅/房间列表功能的可选扩展,不强迫纯房间游戏实现。
2.5 同步规则与描述
getRoomInfo、getFullRoomInfo、getRoomTopDescAry → GameRoomDescription。返回标题、说明项等结构化内容,UI 决定换行和字体,不让游戏按“18/26 个字符”进行硬布局。
getRoomMode、getStarLimit、getLeaveLimit、getMult、getVideoByRoomType → 游戏规则/策略查询;不修改 roomtype、不发包、不写 UI。仅保留项目实际支持的功能,未提供时有明确的能力边界。
创建前的规则预览与入房后的权威公共回包不能混用:例如 roommode 已由服务端明确给出时,不用本地规则覆盖。
onGameConfig → 游戏配置生命周期。配置来源唯一,更新时有版本/替换语义,游戏不得自行从另一个 URL 再读一套。
2.6 用户输入与设备
calResult、onCheckInput → 对应具体输入请求的结果,不再使用全局回调入口。
shakeEvent → 平台设备意图适配。平台提供的“摇动开始”与开始按钮调用同一个 start 命令;游戏自定义摇动行为可以声明独立能力,不能复制公共身份拼包代码。
onLocationInfo → Location 能力的结果/订阅。浏览器替身数据的缺省由浏览器适配器明确定义,游戏不猜地址或坐标。
onOpenHelp(spid) → 帮助内容/页面能力,不暴露原精灵编号。
2.7 gameHallImport
appStart、jumpMenuScene、gameStart、setGameList、clearGameinfo、getWebdata、isInstalled、up_imgurl、getphoto 属于宿主/大厅适配。应与房间游戏 SDK 分开,不要求每个子游戏定义一套全局对象。
isInstalled 等示例固定返回值不能成为新实现的真实能力证明。
3. Output:游戏使用平台能力
源码:08_Utl_Output.js。按职责归属迁移,不按原函数顺序重新堆成大工具类。
3.1 身份、玩家和房间查询
涉及:getMyInfo、getGameID、getAgentID、getPlayeridBySeat、getNicknameBySeat、getSexBySeat、getMyPlayerid、getMySex、getRoomcode、getMySeat、getMyOpenid、getPlayerInfoBySeat、getPlayerList、getPlayerCnt、getPlayerReadyState、getBeanBySeat、getShortCode、getIsInfinite、getInfMode。
归属:RoomReadPort 的只读快照、必要身份投影和具名选择器。occupiedCount 与 seatCount 分开,空位有明确表示;缺失玩家不能返回 -1 后让 UI 猜测。
getMyOpenid 不应作为普通玩法的默认必需字段;确有原业务用途时,通过最小身份能力提供,不把完整登录响应暴露给所有游戏。
changeToStatus → 统一 seat mapper。服务端座位和显示座位可使用不同类型别名,减少混用,转换只在边界进行。
getOnState/isMainScene → 分别读取状态投影和生命周期,不能读取 UI 数组或 Node.active 来决定业务。
3.2 网络与房间命令
sendData → 当前游戏 route 绑定的 GameMessagePort。app/route 不由子游戏每次传入,rpc/data 仍由游戏定义。
sendExitRoom/sendChangeRoom/sendText/enterShareRoom/getShareRoom → 公共具名命令。平台负责身份和房间参数,调用方只提供真正变化的业务参数。
Exit → 不暴露为可任意清空平台状态的方法。区分请求退出、已确认的本地会话结束、结算返回大厅,由协调器内部执行。
openMatchUrl、getMathInfo/getIsMathInfo、getAdvanced/getPlayerAdvanced、openSnrOption、getRebateRange → 对应比赛、VIP/房间策略能力。不要混入通用游戏传输端口;不支持的模式明确标记。
3.3 状态修改与展示
setGrade → 游戏状态中的局内分数,经 GameRoomProjection/HUD 展示模型更新,布局由 View 负责。
changeBean → 先追踪调用源。若是玩法结算的相对得分,应写游戏投影;若是权威资产更新,走对应协议来源。禁止 initialBean + delta 直接覆盖平台账户余额。
setPlayerPrepare/setDeskStage/changePlayerState → 拆分公共协议事实、游戏阶段/参与状态、公共动作限制。必要映射显式声明,禁止通用 setter 任意修改平台状态。
closeMainSceneButton/closeInvitation/closeCommunication/updatePlayerInfoUI → 公共展示模型的状态或具名 UI 操作。业务长期显隐通过模型表达,短暂关闭模态框通过所有者句柄执行,不直接查找平台节点。
getExitVisible/getChangeVisible → RoomPolicy 派生值。命令执行时仍重新验证当前 scope 与策略,不能只靠按钮隐藏防止错误操作。
3.4 UI、资源和声音
openTips/openTips2/closeTips → 有所有者的提示能力,返回可关闭句柄;一个游戏不能关闭其他来源的提示。
Layer612_Tips 的内容仅面向玩家业务。reportError/catch/Error.message 不得直接转接提示端口;配置、协议、资源及代码异常写诊断日志,业务提示通过单独的 notify/showBusinessTip 入口。不能把技术异常转移到 Kick 等其他玩家面板。
startLoad/endLoad → 任务绑定的 loading 句柄或计数租约;并发两个任务时,一个结束不能关闭另一个的加载提示。
openInputPanel/closeInputPanel/openTextInput → 有请求 ID(仅本地)、明确结果和取消语义的输入能力。
getMultipleResult → 纯计算与倍率偏好读取分开;展示倍率选择交给 UI 端口,禁止计算函数暗改 GameData.OrgArr 或存储。
playMusic/playSound/stopMusic/stopSound → AudioPort。声音标识来自游戏资源定义,播放策略遵循平台设置,句柄受 scope 管理。
getHeadimgSrc/openInfo/openInfo1 → 头像资源租约和玩家资料能力;不返回 116+seat 这类精灵 ID。
setFontColor/convertNumberToImg/getNameImgFrame_1/getNameImgFrame_2 → 展示适配层。Cocos 文本使用 Label/BitmapFont,具体业务不依赖字符替换 b/c/d 或图集帧号。
getRoomCardName/getstarName → 平台展示配置投影,保留单一来源,不在游戏里重复定义。
3.5 持久化与工具
SetStorage、Config.pre_* → 存储命名空间与键定义集中管理;账户/游戏作用域明确,不能以当前全局身份拼出不确定的键。
SaveData/ReadData/checkKey/RemoveItemByKey/ClearStorage、setCookie/getCookie/delCookie → 存储适配器。游戏只获得自身命名空间,不能清空应用全部登录/平台数据。
saveRoomtype/getRoomtype/delRoomtype → 游戏配置历史能力;保存与读取不转换 roomtype,版本迁移由游戏负责。
saveGradeInfo/readGradeInfo → 战绩/回放数据仓储,不与房间临时模型混放;来源、保留上限与账号隔离必须明确。
clone/removeItemFromArray → 普通内部工具或删除;不作为平台业务 SDK。新架构使用明确的数据所有权与不可变更新,避免原 clone 破坏数组类型。
3.6 结算、分享和回放
onGameFinished → 拆为已解析的结算事实、游戏结果展示和显式分享请求;渲染函数重复调用不会重复分享。
typeForActivity → 可选活动能力的一次性业务通知,绑定结算来源;不能在重绘中调用。
gameOver/mainScene → 由明确结束原因、结算状态与导航结果驱动。结束一局不等于结束房间。
openVideo/closeVideo → ReplaySession,独立状态、时钟、玩家视角,不修改在线房间数据。
3.7 设备与宿主环境
getLocation/getPhoneInfo/gameCopytext/getAppService/closeWindow → 设备/宿主能力;浏览器和原生各自实现相同契约。
getGameConfig/getVersionState/getH5Version/getIsDebugger/getShowShare → 配置与能力投影。新游戏优先判断声明的能力,而非散布平台版本号分支;调试配置不进入玩法规则。
getPayCodeBySeat、支付/VIP/分享等与房间非核心功能相连的读取 → 在迁移对应模式时核对实际字段来源,不能为满足接口数量提前返回假值。
4. 新接口的使用约定
4.1 查询
一次业务处理读取同一 revision 的快照。对象只读,任何修改都不通过 getter 返回对象完成。需要最新状态时再次读取;异步回调读取前确认 scope 仍有效。
4.2 命令
具名命令检查:scope 有效、登录有效、房间身份匹配、当前策略允许、是否已有同类 pending。发送成功不代表业务确认。
服务器没有关联 ID 时不得虚构关联。对于同房间互斥操作采用本地串行 pending,收到对应合法回复或超时后解除。重连恢复以服务器状态为准,不自动重发非幂等命令。
4.3 UI 请求
type InputResult<T> =
| { kind: 'confirmed'; value: T }
| { kind: 'cancelled'; reason: 'user' | 'scope-ended' | 'replaced' };
输入请求在离房时必须结束。数值模式返回 number,允许前导零的文本模式返回 string,不能在平台随意转换。类型签名可按不同请求模式精确约束。
4.4 投影
游戏模型是事实来源,投影只负责提取公共 HUD 所需字段。投影更新不能反向产生同一输入事件,避免状态→事件→状态循环。
平台准备/资产信息与投影若冲突,优先按各字段定义的唯一来源处理,并报告不一致,不采用“最后写入者胜出”。
4.5 一次性事件
结算活动、音效、分享等与状态渲染分开。重连直接重建状态,不默认重放历史音效、公告或分享。哪些效果需要重放由具体玩法契约明确规定。
5. 接入交付清单
- 一个权威 GameDefinition,明确必需和可选能力。
- roomtype 编码/解析与规则测试,不要求平台理解格式。
- 一个游戏模型以及进入来源/游戏 rpc 到模型的映射。
- 创建页、房间 View 和资源定义;恰好一个页面契约实现。
- SDK 回归夹具:创建、加入、重连有/无快照、开战、结算、取消、退出。
- Cocos 实际创建按钮提交与 WebSocket 发包验证。
- 已实现/未实现能力清单,不以空处理器通过检查。
只增加游戏目录和应用注册项即可接入。若仍必须修改平台菜单脚本、公共协议路由或提供很多固定返回值,说明边界设计尚未达标。
6. 过渡期
旧接口兼容层仅用于逐条迁移现有游戏,不作为新 SDK 的正式表面。每项兼容入口必须有目标能力、测试和移除条件。
不要求一次迁移所有历史宿主/VIP/回放功能,但必须明确未支持范围。任何尚未找到调用源或协议依据的接口不得凭名称实现。
7. 本轮实际落地位置
- StartWar:
PlatformToGameEvent.room.started,保留完整 message/sourceRpc;线上 other_makewar 对应原 makewar 函数。原始游戏包由GameModule.handleGameMessage接收。 - createRoom/onCreateRoom、myJoinRoom、Reconnect/DeskInfo:
room.entered.entry的来源分支与兼容restore。开战优先于加入快照恢复。游戏自身牌桌显示仍未迁移。 - 房间查询、座位映射:
requireRoomCapabilities(host).room.getSnapshot / subscribe / seat。只读数据来自平台 Store。 - 准备、退出、申请解散:同一 room 端口的
prepare / requestExit / applyDissolution,公共身份与投影权限由 PlatformCommands 处理。自定义游戏包使用messages.send。 - 数字、数字文本、倍率:
ui.requestNumber / requestDigitText / requestMultiplier,返回 InputResult;本地取消、替换和 scope 结束均有结果。原回调式 Host 命令暂留兼容。 - loading、玩家业务提示:
ui.beginLoading / showBusinessTip返回{close()},通过真实 FeedbackPanels 仲裁所有者。技术错误不得传入这些接口。 - 资源生命周期:
scope.active / defer;底层 RoomScope 复用既有 Host 租约失效机制。取消先撤销能力,再逐项释放资源。 - 局内公共事实:
createGameRoomProjection的 owner 提交完整版本,GameModule 暴露 source;公共 render 第三个参数和命令权限读取同一来源。现有模板/二七王返回 null,未生成伪 phase 或局内分数。 - 头像、聊天:RoomUi 使用共享租约;RoomChatPanel 使用本地 ID 增量行和同帧合并。协议不增加消息 ID。
- 音频所有者接口:未提供,原生契约没有播放停止能力。原有 RoomVoiceAdapter 的语音功能保留;支付、分享、回放和其他未迁移 Output 接口继续按其原边界单独接入。
新游戏只需要自己的代码/资源、组合根注册,以及编辑器中对应的 SubgameAssets 资源配置。运行期不会预执行工厂来推断模块或资源;真实 open 时只创建一个模块并校验。