feat: integrate room framework and isolated subgame bundles

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.
This commit is contained in:
2026-09-09 03:13:18 +08:00
parent a7ec8aa6a7
commit 35216f75e7
1028 changed files with 835556 additions and 21415 deletions
@@ -0,0 +1,20 @@
# 构建指南
返回[框架目录](../README.md)。本目录专门说明如何选择子游戏、配置版本、预览和导出 Web 包。
## 推荐阅读顺序
1. [单游戏构建操作](single-game-build.md):二七王与模板的完整构建步骤、Bundle 勾选、切换游戏、配置复用、产物检查和排错。
2. [版本配置与身份来源](version-and-build.md):XML 字段、网页与原生身份、版本包、构建扩展和发布环境限制。
3. [旧构建目录与脚手架说明](legacy-project-layout.md):识别旧独立工程流程,避免使用错误的构建命令。
4. 新接入游戏先完成[子游戏接入指南](../integration/README.md)和[创建房间接入](../integration/create-room.md)。
## 当前构建流程
保存启动场景中的 gameKey → 核对游戏入口、版本 XML 和 Bundle 元数据 → 构建面板仅保留公共包与目标游戏包 → 使用独立输出目录构建 → 检查代码、资源、XML → 通过 HTTP 运行导出网页。
本目录说明的是同一个 YouleNexus 工程内选择一款子游戏。切换现有游戏不修改框架代码、框架资源或引擎源码,也不依赖构建后删除其他游戏目录。
## 当前边界
已支持按 gameKey 动态加载游戏入口与私有 prefab,以及自动输出原生兼容 XML。构建时在 Bundle 列表保留公共 resources、目标游戏和目标版本包;当前还未自动同步 gameKey 与构建勾选项。正式发布环境注入仍待完善。
@@ -0,0 +1,29 @@
# 旧独立子工程目录的作用与迁移
返回[构建指南](README.md)。当前操作见[单游戏构建](single-game-build.md)。旧目录核查与迁移日期:2026-09-08。
## 原来作用
顶层 cocoscreator_projects/games 是旧“每款游戏单独 Cocos 工程”脚手架预留的目录,与当前 YouleNexus/assets/games 完全不同。
旧 new-game 脚本会复制工程种子到该目录,创建 assets/game 代码骨架,并通过 assets/framework junction 共享宿主框架;setup-links 重建链接;build-game 将独立工程实体化到临时构建工作区,再调用 Cocos CLI。check-skin、check-cocos-version、bump-cocos 也保留对该旧目录的支持。
当前 Bundle 入口、运行时与 version.xml 构建扩展都使用 YouleNexus 内的子游戏,不依赖这个顶层目录。
## 实际内容与处理
删除前逐项核查:只有 .gitkeep 和三份二七王文档,无 package.json、assets、游戏代码、资源或 reparse/junction 链接。因此它实际上没有可构建的独立子工程。
三份文档已逐文件校验后迁入当前文档树:
- [创建房间接入](../../subgames/erqiwang/create-room-integration.md)
- [玩法设计](../../subgames/erqiwang/design/design.md)
- [玩法协议](../../subgames/erqiwang/protocol/packet_protocol.md)
迁移后删除 .gitkeep,再确认无遗留文件,删除空旧目录。真正使用的 YouleNexus/assets/games 未删除或移动。
## 剩余旧工具
本次没有删除旧脚手架脚本、模板或测试,也没有把它们冒充成当前架构的工具。旧 new-game 命令仍可能重新创建顶层目录,不能用于新接入;旧 build-game 也不是当前单工程选择构建入口。
当前操作以[单游戏构建](single-game-build.md)为准。是否整体移除旧脚手架及相关 npm 入口属于后续工具清理,不影响当前同工程构建。
@@ -0,0 +1,153 @@
# 单游戏构建操作
返回[构建目录](README.md)。关联文档:[版本配置](version-and-build.md)、[子游戏接入](../integration/README.md)。核对日期:2026-09-09,Cocos Creator 3.8.8。
## 1. 当前能力与边界
一个 YouleNexus 工程可以包含多个子游戏。公共 app/framework/scripts 不静态导入具体子游戏,启动时按 `gameKey` 加载目标游戏 Bundle 的入口,并加载该游戏的创建页面和房间 prefab。
构建时使用 Creator 自身的 Bundle 选择能力,使未选游戏的代码和资源不进入产物。不修改引擎源码,不先构建全部游戏再手动删除。
**目前需要配合完成两项选择:保存启动场景的 gameKey;在构建面板勾选对应的 Bundle。两者尚未自动同步。** 修改 gameKey 不会自动改变构建面板,导入构建配置也不会修改场景 gameKey。
当前真实验收范围是二七王 Web Mobile:产物无模板游戏实现及私有资源,导出网页进入登录页,二七王创建页与房间 prefab 可实例化,XML 版本正确。此结果不代表完整牌局、服务器重连或原生壳已重新验收。模板的同类步骤如下,但不能将独立实验工程的双向验证当作两款正式游戏均已完成导出运行验收。
## 2. 一次性资源准备
以下位置均以 YouleNexus 工程为基准。资源元数据、prefab 和场景使用编辑器配置;AI 操作走 Cocos MCP,不手改序列化文件。
公共 `assets/resources` 包名为 `resources`,当前优先级 8,包含 `dev-config` 等公共运行资源。它不是任何一款子游戏的私有目录,当前开发构建必须保留。
二七王的配置:
- 游戏目录:`assets/games/erqiwang`;包名 `game-erqiwang`;优先级 **1**。
- 版本目录:`assets/games/erqiwang/resources`;包名 `version-erqiwang`;优先级 **2**。
- 入口类名:`GameEntry_erqiwang`;static definition 提供本游戏定义。
- 版本资源:`assets/games/erqiwang/resources/erqiwang/version.xml`。
模板的配置:
- 游戏目录:`assets/games/template`;包名 `game-Game_Surface_3`;优先级 **1**。
- 版本目录:`assets/games/template/resources`;包名 `version-Game_Surface_3`;优先级 **2**。
- 入口类名:`GameEntry_Game_Surface_3`。
- 版本资源:`assets/games/template/resources/Game_Surface_3/version.xml`。
**版本包优先级必须高于游戏根包。** 两者相同时,嵌套 XML 可能被父包收走,产生“版本包存在,但包内没有 version”的错误。修正元数据归属,不增加另一条运行时加载路径。
新增或移动脚本后,确认编辑器完成导入,资源数据库能查到脚本且已生成 `.meta`。磁盘上存在 GameEntry.ts,并不等于构建已能包含它。
## 3. 构建二七王 Web Mobile
1. 打开 YouleNexus 的 `assets/scenes/PlatformStartup.scene`。
2. 找到 `SubgameAssets`,设置 `gameKey = erqiwang`,保留公共 `roomScene = TemplateRoom.scene`,保存场景。不要再绑定 createRoom、room;这两个 prefab 由目标入口自动加载。
3. 核对二七王 XML;版本字段与原生读取约定见[版本配置](version-and-build.md)。
4. 在项目扩展管理中启用 **Youle Version Manifest**。
5. 打开“项目 → 构建发布”,选择 **Web Mobile**,启动场景选择 **PlatformStartup**。
6. 参与构建的场景包含 PlatformStartup、PlatformLoading、PlatformLogin、PlatformLobby、TemplateRoom。TemplateRoom 是公共空白承载场景,名称包含 Template 不代表打入模板玩法。
7. 在 Bundles 取消全选,选择 `resources`、`game-erqiwang`、`version-erqiwang`。`main`、`internal` 为正常构建自动保留的公共包。排除 `game-Game_Surface_3`、`version-Game_Surface_3` 以及所有其他游戏的包。
8. 当前工程采用 debug/local 配置,保留 Debug。取消 Debug 不会自动切换生产配置,详见[开发与发布环境](version-and-build.md#6-开发构建与正式发布的区别)。
9. 使用新的独立输出目录,例如 `build/erqiwang-web-check`。在未验证跨游戏增量清理前,不把另一款游戏的旧产物目录直接用作发布目录。
10. 执行构建。构建期间不要修改启动场景、XML 和相关 Bundle 元数据。
11. 确认构建成功,且日志出现 `[youle-version-manifest] erqiwang: .../version.xml`。然后执行下文产物检查与 HTTP 运行验证。
无需更改 defaults.ts、公共注册表、框架 prefab 或引擎安装目录。
## 4. 切换到模板或新增游戏
构建模板时,把启动场景 `gameKey` 改为 **Game_Surface_3** 并保存;保留公共场景与 `resources`,选择 `game-Game_Surface_3` 和 `version-Game_Surface_3`,排除二七王两个包,使用新的模板输出目录。
模板目录名是 template,但 gameKey 是 Game_Surface_3。不要把目录名直接当作 gameKey;游戏入口名、Bundle 名和版本资源路径必须一致。
新游戏先按[接入指南](../integration/README.md)在自己的目录中提供定义、入口、prefab 和 XML。完成后,构建步骤相同:选择 `<gameKey>`,保留 `game-<gameKey>`、`version-<gameKey>` 及公共包,排除所有其他游戏包。构建选择属于应用配置,不是在框架代码中增加游戏分支。
## 5. 保存与复用构建配置
在构建面板配置好平台、场景、Bundle 和输出位置后,使用 **Export** 保存配置;以后用 **Import** 恢复。建议每款游戏保留独立的构建配置,使用时仍核对启动场景已保存的 gameKey。
下列仅展示二七王配置的 Bundle 部分,**不是完整可导入文件**;其余字段由当前 Creator 构建面板导出,不手工拼凑启动场景 UUID。
```json
{
"bundleConfigs": [
{"root": "db://assets/resources", "name": "resources", "output": true},
{"root": "db://assets/games/erqiwang", "name": "game-erqiwang", "output": true},
{"root": "db://assets/games/erqiwang/resources", "name": "version-erqiwang", "output": true},
{"root": "db://assets/games/template", "name": "game-Game_Surface_3", "output": false},
{"root": "db://assets/games/template/resources", "name": "version-Game_Surface_3", "output": false}
]
}
```
`root` 使用 **db:// 资源目录路径,不使用 UUID**。构建工具应在提交构建任务时提供选择结果;当前版本 XML 扩展不负责修改 Bundle 勾选项,也不保证发现所有代码或资源泄漏。
当前 `npm run build-game` 对应旧的独立子工程实体化脚本,不是上述同工程 Bundle 构建的一键入口。参见[历史脚手架说明](legacy-project-layout.md)。
## 6. 检查实际产物
二七王构建的关键目录应为:
```text
<输出目录>/
index.html
version.xml
assets/
internal/
main/
resources/
game-erqiwang/
version-erqiwang/
src/
settings.json
```
还会有引擎代码、样式等公共文件。检查以下内容:
- `assets` 不存在 game-Game_Surface_3、version-Game_Surface_3 或其他未选游戏目录。
- `src/settings.json` 的 assets.projectBundles 只列出当前公共包与二七王两个包;数组顺序不是验收条件。
- 检查所有生成 JS,不能出现 createTemplateGame、TemplateCreateRoomView、TemplateRoomView、GameEntry_Game_Surface_3 等模板实现。仅删除 Bundle 文件夹不能清除已混入公共脚本的代码。
- 版本包的资源路径包含 `erqiwang/version`,不能只检查版本包文件夹是否存在。
- 输出根目录 version.xml 与源 XML 字节或 SHA256 一致。保持原生兼容文件名,不改成 gameKey.xml。
在 cocoscreator_projects 目录使用 PowerShell 检查某次输出,按实际目录修改第一行:
```powershell
$webOutput = Resolve-Path 'YouleNexus/build/erqiwang-web-check'
Get-ChildItem (Join-Path $webOutput 'assets') -Directory | Select-Object -ExpandProperty Name
$settings = Get-Content (Join-Path $webOutput 'src/settings.json') -Raw | ConvertFrom-Json
$settings.assets.projectBundles
Get-FileHash 'YouleNexus/assets/games/erqiwang/resources/erqiwang/version.xml'
Get-FileHash (Join-Path $webOutput 'version.xml')
rg -n 'createTemplateGame|TemplateCreateRoomView|TemplateRoomView|GameEntry_Game_Surface_3' $webOutput -g '*.js'
```
最后一条没有匹配时,rg 返回码为 1,表示未检出这些标记。标记扫描只是辅助检查,不代替依赖边界和实际运行验证。
## 7. 运行与回归验证
通过 HTTP 服务或 Creator 构建预览打开导出目录,不用 file:// 双击 index.html。查看浏览器 Network 和控制台:
1. 只请求公共包、game-erqiwang、version-erqiwang,没有未选游戏包请求或 404。
2. 进入登录页,版本来自目标 XML,启动没有 terminal/fatal 错误。
3. 成功登录后,验证创建页与房间视图是二七王;验证创建房间、服务器拒绝和重连等真实业务路径。这一步需要测试账号与运行中的服务器,本次解耦验证没有代替完整牌局回归。
源码检查从 cocoscreator_projects 运行:
```powershell
node scripts/check-import-boundaries.mjs
node scripts/check-room-assets.mjs
node --experimental-transform-types --test framework-tests/architecture/subgame-entry.test.ts
node --test scripts/test/version-manifest-build.test.mjs
node node_modules/typescript/bin/tsc -p tsconfig.framework.json --noEmit
```
类型和源码测试通过不等于产物通过;正式发布以本次实际生成的目录和运行结果为准。
## 8. 常见故障
- **Missing subgame entry**:核对 gameKey、入口 ccclass 名、游戏包勾选及 GameEntry.ts 的编辑器导入状态。不要添加模板回退入口。
- **Load assets/game-.../index.js failed**:检查目标游戏包是否进入构建、部署路径是否完整;若只在编辑器场景进程发生,用浏览器预览或导出包确认,不能直接当成浏览器运行结果。
- **Bundle version-... doesn't contain .../version**:检查嵌套包优先级,确认 XML 实际归属版本包,而非父游戏包。
- **本地配置读取失败,dev-config 路径不能解析**:检查公共 resources 是否被排除,同时核对当前是否采用 debug/local 配置。
- **旧游戏仍进入产物**:检查 Bundle 是否全选、公共代码是否静态导入游戏、公共 prefab/场景是否引用私有游戏脚本或资源,以及输出目录是否来自旧构建。
- **切换 gameKey 后仍请求旧游戏**:保存真正用于构建的启动场景,重新构建;检查浏览器缓存或部署缓存,不能只改编辑器中未保存的 Inspector。
- **输出缺少根 version.xml**:确认项目扩展启用并完成构建,查看具体扩展错误。扩展失败的产物不要通过手动补文件冒充成功。
@@ -0,0 +1,95 @@
# 版本配置与身份来源
返回[构建目录](README.md)。具体操作见[单游戏构建](single-game-build.md)。本文维护版本字段、身份来源及 XML 构建扩展的职责。
## 1. version.xml 是身份和版本唯一配置文件
源文件在各子游戏目录中:二七王为 `assets/games/erqiwang/resources/erqiwang/version.xml`,模板为 `assets/games/template/resources/Game_Surface_3/version.xml`。路径相对于 YouleNexus,本文不复制第二份配置。
结构保持原生既有格式:XML 声明、game 根节点,以及 agent/game/channel/version 子节点。
- agent@id:网页默认 agentid。
- channel@id:网页默认 channelid。
- 子节点 game@id:服务器 gameid。
- version@value:数值 versionCode,发送到登录包的 version 字段。
- version@name:字符串展示版本 version,登录页显示为 v 加该字符串。
- agent/game/channel 的 name 属性保留供原生读取,必须显式提供。
网页和构建共用这一份源 XML。构建出的副本由工具产生,不手工维护,不反向当作源码编辑。
不要把展示字符串(例如 1.8)作为登录数值版本发送。通用协议部分早期类型描述与真实登录校验存在历史差异,数值约定及实包依据见[数据结构说明](../protocol/04-数据结构.md)。
## 2. 网页与原生身份来源
网页预览从选中游戏的 XML 生成启动身份。原生环境 agentid/channelid/marketid 继续通过既有 settings/uAgent_3 接口读取,缺失时显式报错;gameid 与版本仍来自 XML。
原 XML 没有 marketid。网页的唯一 marketid 配置在应用层 `build-identity.ts` 的 WEB_MARKET_ID,当前为 4。不要为此擅自改变原生 XML 格式。
现有启动解析器仍支持显式 URL agentid/channelid/marketid/version 调试覆盖;gameid 不接受 URL 覆盖。普通预览不传身份参数即可使用 XML。URL version 如使用,含义是数值协议版本,而不是展示版本。
当前 XML 保留当前开发注册身份和 versionCode=1;展示版本二七王为 1.8、模板为 1.1。正式部署要在这份源 XML 中核对真实发布身份与版本,不照搬旧工程过期注册值。
## 3. 版本资源包设置
每个游戏的 resources 文件夹在编辑器中配置 Asset Bundle:
版本 Bundle 优先级为 2,游戏根目录 `game-<gameKey>` Bundle 优先级为 1。不要使用相同优先级,否则嵌套 XML 可能归入父包,版本包变为空包。
- 二七王目录 `assets/games/erqiwang/resources`:bundleName 为 `version-erqiwang`。
- 模板目录 `assets/games/template/resources`:bundleName 为 `version-Game_Surface_3`。
运行时加载 `version-<gameKey>`,再加载包内 `<gameKey>/version` TextAsset。嵌套的 resources 目录不会自动进入全局 resources 包,必须完成上述配置。文件扩展名仍是 .xml,加载路径不带扩展名。
game-config.ts 只定位资源,不保存第二份 gameid 或版本。包名、路径和已保存的场景 gameKey 不一致时应修正来源,不能通过运行时备用路径掩盖。
## 4. 构建操作入口
按[单游戏构建操作](single-game-build.md)选择 gameKey、场景和 Bundle,并校验实际输出。游戏包与版本包必须配对选择,同时保留公共 resources。
Web Mobile 已做真实构建验证;Web Desktop 注册同一 hook 并通过接口测试,但不把这一点当作所有平台都完成了真实验收。
## 5. 构建扩展做了什么
项目扩展名为 **Youle Version Manifest**,实现目录为 `extensions/youle-version-manifest`。新编辑器环境需要确认已启用。
扩展读取构建任务真正的 startScene,而不是猜测当前编辑器正在显示哪个场景。它查找场景中唯一且启用的 SubgameAssets,然后在各游戏目录中查找唯一 `resources/<gameKey>/version.xml`。
构建前验证 XML、版本资源包元数据并保留快照。构建后验证启动场景未变、所选版本 bundle 确实包含在产物、源 XML/场景/元数据未变,再把 XML 字节原样写到实际输出根目录。
无效 XML、重复来源、磁盘场景中的无效选择、缺失所选版本 bundle、构建中来源变化都会阻止构建。扩展只读取已保存场景,不能替用户保存或识别 Inspector 中尚未保存的游戏切换。
扩展不会自动勾选游戏包、自动排除其他游戏、检查版本包内所有资源路径或扫描所有生成代码。看到 XML 发布成功日志,仍需完成单游戏产物检查。失败产物不能当成可发布结果。
## 6. 开发构建与正式发布的区别
当前 `profiles.ts` 是 debug、本地配置、连接本机 127.0.0.1:3088。刚构建出的包不会因为 Cocos 取消 Debug 就自动切换正式服务器;本地配置加载器也不允许在非调试构建使用本地配置。工程的脚本 loose 设置保持 false,避免对标准集合遍历产生不正确的降级编译结果。
目前环境配置仍位于框架历史 profiles.ts,这是尚未完成的应用层配置迁移,不符合未来“发布时无需修改框架”的完整目标。不要把修改它当作每个子游戏接入的步骤。正式发布前,需要完成应用发布环境注入或作为独立框架任务迁移这处配置,并验证 remote/release 的真实来源。
## 7. 当前限制与后续构建方向
- gameKey 选择游戏入口和私有 prefab;roomScene 保持公共承载场景绑定。
- XML 选择和根目录输出已经自动化。
- 公共应用层已解除具体游戏静态导入。构建需显式保留公共 resources、目标游戏和目标版本 Bundle;gameKey 尚未自动同步构建面板勾选项。
- 原有仓库 `scripts/build-game.mjs` 使用另外的子工程实体化流程,不是当前 YouleNexus 同工程游戏选择的一键入口;不要直接把它当成这里的构建命令。
- 未来统一构建入口应在应用/工具层完成选择、资源装配、环境注入与产物裁剪,并验证导出包仅含目标游戏,不随游戏切换修改框架。
## 8. 验证命令与常见故障
从 cocoscreator_projects 目录运行:
```powershell
node scripts/check-import-boundaries.mjs
node scripts/check-room-assets.mjs
node --test scripts/test/version-manifest-build.test.mjs
node node_modules/typescript/bin/tsc -p tsconfig.framework.json --noEmit
```
引擎运行验证脚本 `verify-version-xml-preview.mjs` 需通过 Cocos MCP 在 Game View 上下文执行,不能直接在普通 Node 中运行。它会尝试加载两款游戏,适用于包含两款游戏资源的开发预览,不适用于已排除其他游戏的单游戏发布包。单游戏产物按[导出运行验证](single-game-build.md#7-运行与回归验证)检查。
- `Missing subgame entry`:目标 Bundle 未注册 GameEntry_<gameKey>。
- `Cannot load version-...`:版本目录未设为对应 bundle,或构建排除了它。
- `Version resource does not match selected game`:game-config 中的路径与 gameKey 不一致。
- 根目录没有 XML:确认构建扩展已启用、所选启动场景正确,并查看构建日志;不要手动复制文件后掩盖失败。
- 切换游戏仍出现旧创建页面:检查本游戏 definition.resources 与 gameKey。
- 登录包的版本错误:核对 XML value 及是否传了 URL version 调试参数,不把 XML name 发给服务器。