# framework — 框架真源(唯一权威副本) 各子游戏工程的 `assets/framework` 是指向**本目录**的 junction(见 `scripts/setup-links.mjs`)。 协议相关实现以 `docs/protocol/` 为权威,远程配置与原生接口也必须复刻原工程。服务器、配置服务和原生侧均零改动。 ## 现代运行时的唯一组合路径 ```text game CompositionRoot -> bootstrapPlatform(single GameEntry) game implementation -> framework/sdk only WireClient -> PlatformRuntime -> Router exactly once PlatformStore -> selectors -> GameHost/UI read-only consumers ``` 这里的 `bootstrapPlatform(single GameEntry)` 是组合设计记号,当前没有同名函数。 已实现的构造入口是 `new PlatformRuntime(options)`:`gameEntry` 由构建期固定提供一个, `resolveRuntimeConfig` 使用 `config/runtime-config.ts` 的解析器, `createWireClient(config)` 用最终 `config.servers` 构造 `WireClient`,注入实际 Transport 工厂。 组合方还提供 `ScenePort`、资源加载、最短展示等待和登录设备快照能力,然后调用 `start()`; 界面取得账号后显式调用 `login(account)`,socket open 本身不会发送登录。 `integration/platform-vertical-slice.test.ts` 展示了这一组合的完整无界面回放。 Runtime 内部创建唯一 Router、RuntimeSession、PlatformStore、平台命令和 GameSessionHost。 游戏实现只通过 `framework/sdk/index.ts` 导入公开契约;该入口只重导出 `sdk/contracts`, 不再公开旧 Store、EventBus 或任意路由发包能力。SDK contracts 不导入内部框架模块或 `cc`; SDK runtime 也不导入框架实现层,平台适配由 `platform/game-host-adapter.ts` 承担。 不提供 GameRegistry、运行时 API 协商、多个游戏的包、游戏直接访问 Store/EventBus 的路径。 每次房间会话创建新的 GameModule 和 Host lease,旧 lease 不能读取或操纵新房间。 平台先原子提交房间和玩家快照,再创建游戏、发布平台事件;truthy `deskinfo` 在房间场景就绪后 按原对象引用交给 `restore`,不进入 PlatformStore,falsey/缺失值不触发恢复。 连接事件也提交到同一个 Store;重连只更换 app 连接状态,保留 room/players 引用。 切服先发送原始 `connect_*server` 信封,进房成功再原子标记已登录;普通重连才重新发送已保存的登录信封。 登录、进房的非零 `state` 通过必需的 `ScenePort.showServerDenial({ rpc, state, data })` 报告;`data` 保留服务器原对象,消费方依据 `showerror`、`error`、`roomcode` 等原字段处理。 这类结果不提交成功状态、不关闭连接,调用方可重试;成功回包缺少必需字段仍是显式错误。 `GameEntry.resolveSeatCount` 只接收真实房间的 `roomtype`,预检只检查该方法存在; GameHost 在进房边界验证返回值是正整数并与服务器座位数组长度相同。 `assertGameContract(entry, samples)` 的每个样本由游戏提供 `roomtype`、`expectedSeatCount` 和对应的 `makeHost` 工厂,不要求游戏支持框架虚构的房间配置。 远程地址唯一取自 `data.urlserver`。配置请求使用空 body 的 POST,沿用无条件 `?` 缓存参数拼接。 原生 settings 方法名称、调用次序和 WVJB 初始化/handler 名称由 `config/sources`、 `adapters/native` 实现,`framework-tests/config` 与 `framework-tests/native` 验证。 ## 仍被 Cocos 脚本使用的兼容隔离区 以下是 `LEGACY_RUNTIME` 的完整文件清单,路径相对本目录;现代框架文件禁止直接或传递依赖它们: - `net/net-client.ts` - `platform/session.ts` - `platform/startup.ts` - `platform/room-rpc-bus.ts` - `platform/readonly.ts` - `platform/stores/app-store.ts` - `platform/stores/player-store.ts` - `platform/stores/room-store.ts` - `platform/stores/types.ts` - `protocol/room-handlers.ts` 当前 `YouleNexus/assets/scripts/LoginFlow.ts`、`RoomEventProbe.ts`、`RoomSceneStart.ts` 仍直接引用上述兼容文件。因此它们继续保留;阶段 3 必须由 Presenter 和真正的游戏 Composition Root 接管这些脚本的调用后,阶段 6 才能删除兼容区。当前无界面现代回放通过,不表示 Cocos UI 已接入现代运行时。 保留的兼容逻辑测试(相对 `framework-tests/`)是 `net/net-client.test.ts`、 `platform/app-store.test.ts`、`platform/player-store.test.ts`、`platform/room-store.test.ts`、 `platform/session.test.ts`、`platform/startup.test.ts`、`platform/room-rpc-bus.test.ts`、 `protocol/room-handlers.test.ts`。它们测试旧脚本仍需使用的行为,不属于现代运行时的依赖图。 旧 SDK 的完整标识符盘点仅允许 `architecture/import-boundaries.test.mjs` 中的负例, 以及 `protocol/room-handlers.ts` 内一处历史说明。名称子串 `requireActiveGame` 是现代处理器的局部状态检查方法, 不是已移除的旧类型;自动盘点按完整标识符匹配。 `scripts/check-import-boundaries.mjs` 不再给 SDK 入口任何内部依赖豁免,也不给旧活动游戏文件名称检查豁免。 `framework-tests/architecture/import-boundaries.test.mjs` 对全部现代框架 TypeScript 文件检查传递依赖, 并验证重导出、别名、动态导入、CommonJS 和 import type 的负例;无法静态判断的传递加载直接拒绝。 阶段 3 的 Presenter/Composition Root 接管、theme/Prefab binding、首个真实子游戏迁移及 ZIP 发布均属于后续独立计划。 本次逻辑验收不改动 Cocos 序列化资源或现有 UI 迁移产物。