@cael.ai/game-kit
v0.1.31
Published
Cael game host SDK: protocol, pack zip, scene session, and authored-layer ports.
Readme
@cael.ai/game-kit
在 Babylon.js Editor 中接入玩法、Play 验证,并导出 zip。
安装发布到 npm 的包。玩家订阅 zip 内容包。不要用 file: 指向本地仓库。
1. 安装
npm install @cael.ai/game-kit使用场景或 React 壳时:
npm install react react-dom @babylonjs/core使用表单入口时安装 @rjsf/utils。
2. 编辑器插件
project.bjseditor:
{
"plugins": [{ "nameOrPath": "@cael.ai/game-kit/babylon-plugin" }]
}用 Babylon.js Editor 打开工程。布局中出现 Cael · Sidebar 和 Cael · Inspector。
3. 玩法宿主场景
- 新建或打开玩法宿主场景。不使用 Editor 自带的 example / 演示场景。
- 删除模板自带的
ground/box/sky/ 示例灯 / 示例相机。编辑导航使用 Editor preview 相机。 - 保存场景。
npm install 在工程根目录存在 project.bjseditor,且 src/scripts/cael-game-runtime.ts 不存在时,写入该文件。已存在则不覆盖。文件被删除后,插件再次执行同一安装脚本。不要手写该文件。
在 Editor 中:
- 图层面板选中 Scene 根。
- Inspector → Scripts → Add。
- 选择
scripts/cael-game-runtime.ts,保持 enabled。 - 移除 Editor 示例脚本(例如
scripts/box.ts)。 - 保存场景。
该脚本不静态 import kit 或项目玩法。一个项目只在一个玩法宿主场景上挂该脚本。
4. 场景与侧栏
| Scene 文件 | Cael · Sidebar 局面 / 表 | |---|---| | 地形、建筑、装饰、静态灯、环境 | 牌、可玩实例、玩法相机、玩法灯 |
静态节点在 Play 时留在同一 Scene。可玩的牌和玩法相机放在侧栏局面里。
5. 局面与资源
空局面使用 createEmptyGameShapeDocument(seed)(@cael.ai/game-kit/runtime),在侧栏填表、摆实例。
自带开局把局面 JSON 放在 fixtures/author-default-template.json。不使用 webpack import 加载该 JSON。没有该文件时 Play 使用空局面。
资源放在 public/game-assets/<目录名>/。Play 静态 Host 按目录扫描清单。
6. Play
点 Play 后:
- Scene 脚本
onStart同步创建相机cael-play-boot-camera。 - 插件生成
public/editor-play/runtime.js,并启动静态 Hosthttp://127.0.0.1:39471。runtime.js缺失、kit 版本变化,或cael.gameplayBoot/cael.editorPlayScene比该产物新时,插件重新构建。 - IIFE 在当前已打开的 Scene 上调用
bootGameHostSession。Stop 回到 edit,侧栏会话保留。
7. 玩法 boot
package.json:
{
"cael": {
"gameplayBoot": "src/lib/game/boot-gameplay.ts"
}
}该文件导出名称包含 boot 的函数。网页、Editor Play 和 zip 的 install() 调用同一函数。
7.1 配置表
功能表始终在侧栏。专属表写入 installGamePack 的 configAssetIds 后出现在侧栏。
import {
installGamePack,
listKitBaseConfigAssetIds,
} from "@cael.ai/game-kit/lib/game/game-type-profile"
import { GAME_CONFIG_ASSET_IDS } from "@cael.ai/game-kit/lib/game/game-asset-ids"
installGamePack("my-game", {
configAssetIds: [
...listKitBaseConfigAssetIds(),
GAME_CONFIG_ASSET_IDS.cardPacks,
],
})已安装的包要改专属表时,调用 registerGameTypeExclusiveConfigAssetIds。功能表和项目设置保留,专属表被替换。
已有协议表只把 id 写入档案。新的列结构在 boot 里 registerGameConfigTable:assetId、definitionKey、行的 zod schema。登记后,侧栏和 game_config_read / game_config_write 使用这张表。默认 agentReadable / agentWritable 为真;关闭时传入 capabilities。
import { z } from "zod"
import { registerGameConfigTable } from "@cael.ai/game-kit/lib/game/game-table-registry"
registerGameConfigTable({
assetId: "weather_table",
definitionKey: "weatherRules",
rowSchema: z.object({ id: z.string(), label: z.string() }),
})installGamePack 与 registerGameConfigTable 的调用顺序不限。未调用 installGamePack 时,该表不进入空项目侧栏。
7.2 读表
系统读取当帧传入的 definitions。协议内的表使用 definitions.cardPacks.rows。registerGameConfigTable 登记的表使用 readConfigTableRows(definitions, definitionKey)。表数据留在 definitions。运行时 LLM 读写同一份 definitions。
7.3 命令
在同一份档案里写 commandKinds(kind + 文案)。侧栏列出这些指令。
setGameProjectRuntimePort 提供 reduceGameCommand 与 listGameCommandSuggestions。执行使用 Intent system:在 boot 里调用 registerGameIntentSystems(@cael.ai/game-kit/lib/game/game-type-pipelines)。后注册的替换先注册的。档案未打开 Intent 管线时,这组 system 不挂上。
commandKinds 的 kind 与运行时命令的 type 都是字符串。新指令写入档案、运行端口和 Intent system。
7.4 声音与后处理
调用一次 registerGameHostPresentation(@cael.ai/game-kit/gameplay)。runRenderFrame 在场景上下文齐全时调用该口。宿主内不调用 bind、sync、unlock、dispose、syncFrame。
帧顺序:
bindSceneAudio:第一次,或资源缓存更换时。在此配置解析上下文,并按definitions预加载音效。syncAudioSettings:将definitions.projectSettings.audio应用到播放器。syncFrame({ advance: true }):推进依赖时间的后处理。stepSpatial:绘制前的项目空间步进。没有则省略。syncFrame({ advance: false }):用步进之后的局面投影后处理,不推进时间。- 第一次指针按下时,kit 调用
unlockAmbient。卸下 Scene host 时调用disposeAudio。
牌面、战斗等一次性音效在项目 system 里调用 gameAudioPlayer(@cael.ai/game-kit/components/game/game-audio-player)。
7.5 场景 system 与其它口
帧预算探针默认出现在监视里。项目阶段写在档案 customPerfMetricDefs,或用 registerGamePackCustomPerf 覆盖文案。采样打开时,用 measureCustomPerf(sessionKey, id, fn) 写入。id 为字符串。
在同一份 boot 里按需要注册:
| 口 | 作用 |
|---|---|
| setGameplayPipelineRegistrar | 向场景 pipeline 注册本项目的 Babylon system |
| registerGamePackSettingsSections | 项目设置表的分区。未登记时只有字体、主题、画质 |
| registerGameProjectFontDefaults | 项目字体。未登记时字体槽为 null |
| registerDefaultNineSlice | 默认九宫格。未登记时没有内置贴图 |
| setGameBoardSceneRootIds | 板场景根 id |
| setGameWorldMutationHooks | 生成、销毁等写入副作用 |
| setGameEcsWorldGameplayHooks | World 上的玩法读口 |
保存后点 Play。
8. Editor Play 场景投影
在 package.json 的 cael 中设置:
"editorPlayScene": "src/components/game/babylon/register-editor-play-scene.ts"该文件导出 registerProjectEditorPlayScene,调用一次 registerEditorPlaySceneHost(@cael.ai/game-kit/gameplay)。IIFE 先调用 gameplayBoot,再调用该函数。
向宿主提供 registry、场景 system、局内 HUD。帧循环、指针、相机关闭和监视由 kit 执行。
局内键盘与 HUD 的文件路径由项目决定,由 registerProjectEditorPlayScene 交给宿主。示例工程使用同目录的 editor-play-shell.ts。
gameplayBoot 与 pack 入口不 import 该登记文件和 HUD。无场景投影时不设置 editorPlayScene。
9. 导出
原创导出生成一个游戏 zip,以及每个资源挂载各自的资源 zip。游戏 zip 包含:
| 路径 | 内容 |
|---|---|
| manifest.json | 包身份、原创 / 二创;资源包记录 id / download / sha256 / bytes |
| game/template.json | 局面与配置表 |
| game/gameplay.js | 玩法制品,调用 gameplayBoot |
资源字节在 <挂载 id>.zip。同一批资源文件两次导出,资源 zip 的 SHA-256 不变。玩法经包内 install() 注入。zip 内不包含 .ts。
game/gameplay.js 由 scripts/build-gameplay-pack.mjs 编译。入口默认 src/gameplay/pack-entry.ts,该文件只调用 boot。其它入口路径设置 cael.gameplayPackEntry。cael.gameplayPackExport 要求制品中出现 function <导出名>(。
package.json:
{
"scripts": {
"build:gameplay-pack": "node ./node_modules/@cael.ai/game-kit/scripts/build-gameplay-pack.mjs"
}
}编辑器导出调用同一脚本。工程内不放置 scripts/build-gameplay-pack.mjs。
Author 工程提供:
| 路由 | 响应 |
|---|---|
| GET /api/author/gameplay-module | 已编译的 game/gameplay.js |
| GET /api/author/game-asset-roots | { roots: [{ bundleId, publicPath, displayName? }] } |
import { GamePackExportPanel } from "@cael.ai/game-kit/author"
<GamePackExportPanel sessionKey={sessionKey} />面板中的目录写入资源 zip。导出时选择保存目录,游戏 zip 与资源 zip 写入该目录。网页没有目录选择时逐个下载。只要字节时调用 assembleOriginalGamePackZip,其中 resourcePacks 为独立资源 zip。无面板时调用 downloadAuthorFullPackZip。
资源分包在面板中勾选。槽 id 写入后保持不变。局面引用 { mount, path, kind }。二创不重打父包的 game/gameplay.js 和父包资源。
10. 网页播放
网页 Author 与广场播放调用同一个 gameplayBoot,再调用 bootGameHostSession(@cael.ai/game-kit/runtime)。
网页场景组件在 boot 里用 setHostedGameScene 注册。
没有 Editor Scene 时,用 AuthoredScenePort(@cael.ai/game-kit/authoring)把导出的 .babylon 挂到播放器已有 Scene。Editor Play 使用已打开的 Scene。
常见问题
| 现象 | 处理 |
|---|---|
| 没有 Cael · Sidebar / Inspector | project.bjseditor 挂上 @cael.ai/game-kit/babylon-plugin 后重启 Editor |
| Play 黄条 plugin is not loaded | 同上 |
| Play 为空场景 | 脚本挂在 Scene 根 且 enabled。控制台查看 [cael-game-runtime] |
| No camera defined | Scene 根挂 cael-game-runtime |
| Could not resolve "@cael.ai/game-kit/..." | Scene 脚本改为 kit 写入的 cael-game-runtime.ts |
| Editor Play runtime is missing after build | 确认已安装 kit |
| 改了玩法但 Play 仍是旧制品 | 删除 public/editor-play/runtime.js 后再 Play |
License
MIT
