1
This commit is contained in:
@@ -17,6 +17,13 @@ VITE_SCENE_IMAGE_PROXY_BASE_URL="/api/custom-world/scene-image"
|
||||
NODE_SERVER_ADDR=":8081"
|
||||
NODE_SERVER_TARGET="http://127.0.0.1:8081"
|
||||
|
||||
# Rust api-server local target used by the Big Fish compatibility gateway in server-node.
|
||||
GENARRATIVE_API_PORT="3100"
|
||||
GENARRATIVE_API_TARGET="http://127.0.0.1:3100"
|
||||
GENARRATIVE_INTERNAL_API_SECRET="CHANGE_ME_FOR_PRODUCTION"
|
||||
GENARRATIVE_SPACETIME_SERVER_URL="http://127.0.0.1:3001"
|
||||
GENARRATIVE_SPACETIME_DATABASE="genarrative-dev"
|
||||
|
||||
# Local Caddy upstream target used for dist-based testing.
|
||||
CADDY_API_UPSTREAM="http://127.0.0.1:8081"
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
- UI设计需要兼顾网页端、移动端双端的使用体验,确保在不同设备上都能正常显示和操作,移动端优先考虑。
|
||||
- 不要在gitignore中添加.env.local文件。
|
||||
- 严格遵循简洁的代码风格
|
||||
- 前端只负责做表现,所有的逻辑、数据都放到Express后端进行运算和存储。
|
||||
- 前端只负责做表现,所有的逻辑、数据都放到后端工程,后端使用server-rs中用Rust+spacetimeDB的方案实现,禁止继续使用server-node(Express)和postgreSQL
|
||||
- 后端采用多crate设计
|
||||
- 请默认保持系统的简洁性,能复用、修改、扩展现有系统、页面就不新建新系统新页面。
|
||||
- 禁止将功能说明描述类的文本默认写入UI界面中。
|
||||
- prd文档中每个模块的描述要落地设计到可以精准编码到位,不能出现需求落地漂移。
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,273 @@
|
||||
# 大鱼吃小鱼玩法创作与运行态最小落地技术方案
|
||||
|
||||
日期:`2026-04-22`
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
本文件承接 PRD《AI 原生 Agent-First 大鱼吃小鱼玩法创作工具与玩法系统》,冻结本轮工程落地的最小完整闭环。
|
||||
|
||||
本轮目标不是抽象一个通用街机玩法引擎,而是在现有平台内新增一个独立 `big_fish` 玩法域,跑通:
|
||||
|
||||
1. 平台创作入口选择大鱼吃小鱼玩法
|
||||
2. Agent 会话创建、消息提交和 SSE 兼容返回
|
||||
3. 基于 4 个高杠杆锚点编译玩法草稿
|
||||
4. 结果页生成等级主图、等级动作、场地背景的正式资产槽位
|
||||
5. 发布校验
|
||||
6. 启动测试运行态
|
||||
7. 后端推进摇杆输入、刷怪、吞噬收编、三合一、屏外清理和胜负裁决
|
||||
|
||||
## 2. 本轮明确不做
|
||||
|
||||
1. 不接入真实图片 / 动作模型调用,只生成可预览的占位资产引用与冻结提示词快照。
|
||||
2. 不新增 WebSocket 依赖;首版运行态使用 `POST input + GET snapshot` 的有限 HTTP 辅助接口,后续再升级长连接。
|
||||
3. 不把 Big Fish 写回 `custom_world`、`rpgCreation` 或 RPG runtime 旧语义。
|
||||
4. 不新增作品市场、排行榜、复盘、局外成长、PvP。
|
||||
5. 不要求前端本地模拟真相;前端只渲染后端 snapshot。
|
||||
|
||||
## 3. Rust crate 边界
|
||||
|
||||
新增:
|
||||
|
||||
1. `server-rs/crates/module-big-fish`
|
||||
- 纯领域模型、输入校验、草稿编译、资产覆盖率、运行态规则推进。
|
||||
- 可开启 `spacetime-types` feature,为 `spacetime-module` 派生 SpacetimeDB 类型。
|
||||
|
||||
接入:
|
||||
|
||||
1. `server-rs/crates/spacetime-module`
|
||||
- 新增 Big Fish 表与 procedure。
|
||||
- 只存状态与结构化引用,不做 OSS / LLM 外部 IO。
|
||||
2. `server-rs/crates/spacetime-client`
|
||||
- 新增 Big Fish facade,隐藏 generated bindings。
|
||||
3. `server-rs/crates/shared-contracts`
|
||||
- 新增 HTTP DTO。
|
||||
4. `server-rs/crates/api-server`
|
||||
- 新增 `big_fish_creation.rs`、`big_fish_assets.rs`、`big_fish_runtime.rs` 或最小合并的 `big_fish.rs`。
|
||||
|
||||
## 4. SpacetimeDB 表
|
||||
|
||||
本轮只新增必要表,所有表主键使用 Axum 生成的显式业务 ID。
|
||||
|
||||
### 4.1 `big_fish_creation_session`
|
||||
|
||||
字段:
|
||||
|
||||
1. `session_id: String`
|
||||
2. `owner_user_id: String`
|
||||
3. `seed_text: String`
|
||||
4. `current_turn: u32`
|
||||
5. `progress_percent: u32`
|
||||
6. `stage: BigFishCreationStage`
|
||||
7. `anchor_pack_json: String`
|
||||
8. `draft_json: Option<String>`
|
||||
9. `asset_coverage_json: String`
|
||||
10. `last_assistant_reply: Option<String>`
|
||||
11. `publish_ready: bool`
|
||||
12. `created_at: Timestamp`
|
||||
13. `updated_at: Timestamp`
|
||||
|
||||
索引:
|
||||
|
||||
1. `by_big_fish_session_owner_user_id(owner_user_id)`
|
||||
|
||||
### 4.2 `big_fish_agent_message`
|
||||
|
||||
字段:
|
||||
|
||||
1. `message_id: String`
|
||||
2. `session_id: String`
|
||||
3. `role: BigFishAgentMessageRole`
|
||||
4. `kind: BigFishAgentMessageKind`
|
||||
5. `text: String`
|
||||
6. `created_at: Timestamp`
|
||||
|
||||
索引:
|
||||
|
||||
1. `by_big_fish_message_session_id(session_id)`
|
||||
|
||||
### 4.3 `big_fish_asset_slot`
|
||||
|
||||
字段:
|
||||
|
||||
1. `slot_id: String`
|
||||
2. `session_id: String`
|
||||
3. `asset_kind: BigFishAssetKind`
|
||||
4. `level: Option<u32>`
|
||||
5. `motion_key: Option<String>`
|
||||
6. `status: BigFishAssetStatus`
|
||||
7. `asset_url: Option<String>`
|
||||
8. `prompt_snapshot: String`
|
||||
9. `updated_at: Timestamp`
|
||||
|
||||
索引:
|
||||
|
||||
1. `by_big_fish_asset_session_id(session_id)`
|
||||
2. `by_big_fish_asset_slot(session_id, asset_kind, level, motion_key)`
|
||||
|
||||
### 4.4 `big_fish_runtime_run`
|
||||
|
||||
字段:
|
||||
|
||||
1. `run_id: String`
|
||||
2. `session_id: String`
|
||||
3. `owner_user_id: String`
|
||||
4. `status: BigFishRunStatus`
|
||||
5. `snapshot_json: String`
|
||||
6. `last_input_x: f32`
|
||||
7. `last_input_y: f32`
|
||||
8. `tick: u64`
|
||||
9. `created_at: Timestamp`
|
||||
10. `updated_at: Timestamp`
|
||||
|
||||
索引:
|
||||
|
||||
1. `by_big_fish_run_owner_user_id(owner_user_id)`
|
||||
2. `by_big_fish_run_session_id(session_id)`
|
||||
|
||||
## 5. SpacetimeDB procedure
|
||||
|
||||
本轮全部使用 procedure 同步返回快照,避免 Axum 额外拼读模型。
|
||||
|
||||
1. `create_big_fish_session(input) -> BigFishSessionProcedureResult`
|
||||
2. `get_big_fish_session(input) -> BigFishSessionProcedureResult`
|
||||
3. `submit_big_fish_message(input) -> BigFishSessionProcedureResult`
|
||||
4. `compile_big_fish_draft(input) -> BigFishSessionProcedureResult`
|
||||
5. `generate_big_fish_asset(input) -> BigFishSessionProcedureResult`
|
||||
6. `publish_big_fish_game(input) -> BigFishSessionProcedureResult`
|
||||
7. `start_big_fish_run(input) -> BigFishRunProcedureResult`
|
||||
8. `submit_big_fish_input(input) -> BigFishRunProcedureResult`
|
||||
9. `get_big_fish_run(input) -> BigFishRunProcedureResult`
|
||||
|
||||
说明:
|
||||
|
||||
1. `submit_big_fish_message` 只做 deterministic 锚点补全,不调用 LLM。
|
||||
2. `generate_big_fish_asset` 只写正式资产槽位和提示词快照,真实模型生成后续由 AI/OSS worker 替换。
|
||||
3. `submit_big_fish_input` 每次至少推进 1 个后端 tick,前端不能本地裁决。
|
||||
4. 运行态所有“持续时间”语义按真实秒数累计,前端即使摇杆静止也要持续以当前输入心跳驱动后端推进,避免刷怪与屏外 `3` 秒清理依赖手速或提交频率。
|
||||
|
||||
## 6. HTTP contract
|
||||
|
||||
所有接口挂在 `/api/runtime/big-fish/*`,全部需要 Bearer 鉴权。
|
||||
|
||||
开发态本地链路补充约定:
|
||||
|
||||
1. 浏览器仍只请求同源 `/api/runtime/big-fish/*`。
|
||||
2. `vite -> server-node:8081` 保持不变,由 `server-node` 先复用现有登录态完成 Bearer 校验。
|
||||
3. `server-node` 仅作为 Big Fish 兼容网关,把“已校验用户身份 + 原始请求体”转发到 Rust `api-server`。
|
||||
4. Rust `api-server` 继续作为 Big Fish 真相后端,正式处理会话、草稿、资产动作和运行态规则。
|
||||
5. 本地默认端口:
|
||||
- `vite`: `3000`
|
||||
- `server-node`: `8081`
|
||||
- Rust `api-server`: `3100`
|
||||
- `SpacetimeDB standalone`: `3001`
|
||||
6. `GENARRATIVE_SPACETIME_DATABASE` 本地开发优先跟随仓库根目录 `spacetime.local.json` 的 `database` 字段,避免 `api-server` 默认连到错误数据库名。
|
||||
- `.env.local` 或进程环境显式配置 `GENARRATIVE_SPACETIME_DATABASE` 时可覆盖本地配置。
|
||||
- `.env.example` 只提供示例默认值,不得压过 `spacetime.local.json`。
|
||||
|
||||
### 6.1 创作会话
|
||||
|
||||
1. `POST /api/runtime/big-fish/agent/sessions`
|
||||
2. `GET /api/runtime/big-fish/agent/sessions/{sessionId}`
|
||||
3. `POST /api/runtime/big-fish/agent/sessions/{sessionId}/messages/stream`
|
||||
4. `POST /api/runtime/big-fish/agent/sessions/{sessionId}/actions`
|
||||
|
||||
`messages/stream` 首版兼容当前前端 SSE 解析方式,只输出:
|
||||
|
||||
1. `reply_delta`
|
||||
2. `session`
|
||||
3. `done`
|
||||
4. `error`
|
||||
|
||||
`actions` 首版支持:
|
||||
|
||||
1. `big_fish_compile_draft`
|
||||
2. `big_fish_generate_level_main_image`
|
||||
3. `big_fish_generate_level_motion`
|
||||
4. `big_fish_generate_stage_background`
|
||||
5. `big_fish_publish_game`
|
||||
|
||||
### 6.2 运行态
|
||||
|
||||
1. `POST /api/runtime/big-fish/sessions/{sessionId}/runs`
|
||||
2. `GET /api/runtime/big-fish/runs/{runId}`
|
||||
3. `POST /api/runtime/big-fish/runs/{runId}/input`
|
||||
|
||||
`input` 请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"x": 0.4,
|
||||
"y": -0.2
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 运行态最小规则
|
||||
|
||||
后端推进规则固定:
|
||||
|
||||
1. 开局拥有 1 个 `level = 1` 己方实体。
|
||||
2. 开局视野内生成至少 2 个同级野生实体。
|
||||
3. 己方实体碰撞低于或等于自己等级的野生实体时收编。
|
||||
4. 高于己方等级的野生实体碰撞己方实体时吃掉该己方实体。
|
||||
5. 每次结算后从低等级开始做三合一连锁合成。
|
||||
6. 野生实体池围绕玩家最高己方等级维持低 1~2 级与高 1~2 级。
|
||||
7. 同等级、高 3 级及以上、低 3 级及以下的野生实体,屏外连续 3 秒后删除。
|
||||
8. 玩家首次拥有最高等级实体时立即胜利。
|
||||
9. 己方实体归零时失败。
|
||||
|
||||
## 8. 前端接入边界
|
||||
|
||||
新增目录:
|
||||
|
||||
1. `src/services/big-fish-creation/`
|
||||
2. `src/components/big-fish-creation/`
|
||||
3. `src/components/big-fish-result/`
|
||||
4. `src/components/big-fish-runtime/`
|
||||
|
||||
复用现有平台入口壳层,但入口脚本必须使用通用平台命名,禁止把 Big Fish 业务状态写进 `rpg-entry` 命名脚本:
|
||||
|
||||
1. 在 `src/components/platform-entry/PlatformEntryCreationTypeModal.tsx` 新增“大鱼吃小鱼”选项。
|
||||
2. 在 `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx` 中新增 Big Fish 专属 stage。
|
||||
3. Big Fish 不使用 `RpgCreationResultView`,使用 `BigFishResultView`。
|
||||
4. `src/components/rpg-entry/*` 只能保留兼容导出或 RPG 专属组件,不允许承载 Big Fish 业务分支。
|
||||
|
||||
前端只允许:
|
||||
|
||||
1. 展示会话、草稿、资产槽位、运行快照。
|
||||
2. 发送聊天、action 和摇杆输入。
|
||||
3. 根据后端 snapshot 渲染实体。
|
||||
|
||||
前端禁止:
|
||||
|
||||
1. 自行决定刷怪。
|
||||
2. 自行决定吞噬 / 合成 / 清理 / 胜负。
|
||||
|
||||
## 9. 本轮验收
|
||||
|
||||
完成后至少执行:
|
||||
|
||||
1. `cargo fmt -p module-big-fish -p shared-contracts -p spacetime-module -p spacetime-client -p api-server`
|
||||
2. `cargo check -p module-big-fish`
|
||||
3. `cargo check -p shared-contracts`
|
||||
4. `cargo check -p spacetime-module`
|
||||
5. `spacetime generate` 刷新 Rust bindings
|
||||
6. `cargo check -p spacetime-client`
|
||||
7. `cargo check -p api-server`
|
||||
8. 前端类型 / 构建检查
|
||||
9. `npm run check:encoding`
|
||||
|
||||
## 10. 本地开发补充
|
||||
|
||||
为避免再次出现 `POST /api/runtime/big-fish/agent/sessions` 命中旧 Node 后端 `404`,本轮额外冻结以下联调口径:
|
||||
|
||||
1. `npm run dev` 需要同时拉起:
|
||||
- `server-node`
|
||||
- Rust `api-server`
|
||||
- `vite`
|
||||
2. `server-node` 新增 Big Fish 专用兼容网关路由,不在 Node 内复制 Big Fish 玩法逻辑。
|
||||
3. Node -> Rust 转发使用内部桥接头:
|
||||
- `x-genarrative-authenticated-user-id`
|
||||
- `x-genarrative-internal-api-secret`
|
||||
4. Rust 侧只对带正确内部密钥的本地桥接请求接受该用户头,不对普通外部请求放开匿名身份伪造。
|
||||
|
||||
如检查发现本轮主链缺口,继续补齐;如已经满足上述验收,不继续扩展额外玩法能力。
|
||||
@@ -0,0 +1,384 @@
|
||||
# 拼图玩法创作与运行态最小落地技术方案
|
||||
|
||||
日期:`2026-04-22`
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
本文件承接 PRD《AI 原生拼图玩法创作工具与玩法系统》,冻结本轮拼图玩法在当前平台内的最小完整闭环。
|
||||
|
||||
本轮目标不是抽象一个通用拼图编辑器,也不是额外搭建一个脱离平台的新小游戏站点,而是在现有平台壳层内新增独立 `puzzle` 玩法域,跑通下面这条主链:
|
||||
|
||||
1. 平台创作入口选择拼图玩法
|
||||
2. Agent-first 对话收束 5 个高杠杆视觉锚点
|
||||
3. 编译结果页草稿
|
||||
4. 在结果页编辑关卡名、标签并生成候选拼图图片
|
||||
5. 发布作品进入拼图广场
|
||||
6. 玩家从广场进入第 1 关
|
||||
7. 后端初始化 `3x3 / 4x4` 棋盘
|
||||
8. 后端裁决交换、合并、拖动、拆分与通关
|
||||
9. 通关后根据“标签相似度 `70%` + 同作者 `30%`”推荐下一关
|
||||
|
||||
## 2. 本轮明确不做
|
||||
|
||||
1. 不做异形拼块、旋转拼块、道具、体力、倒计时。
|
||||
2. 不做新的平台站点或新的全局导航系统。
|
||||
3. 不做前端本地推荐、前端本地裁决、前端本地持久化真相。
|
||||
4. 不做复杂图片模型编排;首版图片生成沿用 `api-server` 的占位资产生成方式,保证完整链路可跑通。
|
||||
5. 不把拼图玩法继续挂在 `customWorld`、`rpgWorld` 或 RPG runtime 旧语义下。
|
||||
6. 不扩到拼图排行榜、社交评论、收藏、复盘系统。
|
||||
|
||||
## 3. 分层边界
|
||||
|
||||
### 3.1 前端
|
||||
|
||||
前端继续使用当前 `React + TypeScript + Vite` 平台壳层,只负责:
|
||||
|
||||
1. 展示拼图创作中心、Agent 工作区、结果页、广场、运行时画布。
|
||||
2. 发起聊天、结果页编辑、发布、开始游戏、交换与拖动请求。
|
||||
3. 基于后端快照渲染棋盘、HUD、选中态与合并反馈。
|
||||
|
||||
前端禁止:
|
||||
|
||||
1. 自行判断下一关推荐。
|
||||
2. 自行判断拼块是否应当合并。
|
||||
3. 自行判断合并块是否应当拆分。
|
||||
4. 自行判断通关。
|
||||
|
||||
### 3.2 Axum
|
||||
|
||||
`server-rs/crates/api-server` 负责:
|
||||
|
||||
1. 对外暴露 `/api/runtime/puzzle-*` HTTP 接口。
|
||||
2. 鉴权、请求上下文、错误 envelope。
|
||||
3. 结果页占位图片生成与静态资产落盘。
|
||||
4. 调用 `spacetime-client` 读写拼图玩法真相态。
|
||||
|
||||
### 3.3 SpacetimeDB
|
||||
|
||||
`server-rs/crates/spacetime-module` 负责:
|
||||
|
||||
1. 存储拼图 Agent session / message。
|
||||
2. 存储已发布拼图作品 profile。
|
||||
3. 存储拼图运行态 run snapshot。
|
||||
4. 通过 procedure 同步返回 session / works / gallery / runtime 快照。
|
||||
|
||||
### 3.4 纯领域 crate
|
||||
|
||||
新增 `server-rs/crates/module-puzzle`,承载:
|
||||
|
||||
1. 5 个锚点与会话阶段的纯领域模型。
|
||||
2. 草稿编译、标签规范化、发布校验。
|
||||
3. `3x3 / 4x4` 棋盘初始化。
|
||||
4. 交换、合并、拖动、拆分、通关与下一关推荐算法。
|
||||
|
||||
## 4. 共享契约
|
||||
|
||||
### 4.1 TypeScript shared contracts
|
||||
|
||||
在 `packages/shared/src/contracts/` 新增:
|
||||
|
||||
1. `puzzleAgentSession.ts`
|
||||
2. `puzzleAgentDraft.ts`
|
||||
3. `puzzleAgentActions.ts`
|
||||
4. `puzzleResultPreview.ts`
|
||||
5. `puzzleWorkSummary.ts`
|
||||
6. `puzzleRuntimeSession.ts`
|
||||
|
||||
这些文件分别承载:
|
||||
|
||||
1. Agent session / message / anchor pack
|
||||
2. 结果页草稿与候选图片
|
||||
3. Agent actions 与 works/gallery mutation request
|
||||
4. 结果页 publish gate / preview
|
||||
5. owner-only works 与 gallery card
|
||||
6. runtime run / board / swap / drag / next-level contract
|
||||
|
||||
### 4.2 Rust shared contracts
|
||||
|
||||
在 `server-rs/crates/shared-contracts/src/` 新增:
|
||||
|
||||
1. `puzzle_agent.rs`
|
||||
2. `puzzle_works.rs`
|
||||
3. `puzzle_gallery.rs`
|
||||
4. `puzzle_runtime.rs`
|
||||
|
||||
Rust DTO 只承载对前端公开的 HTTP contract,不直接泄露 `module-puzzle` 内部实现细节。
|
||||
|
||||
## 5. Spacetime 表与 procedure
|
||||
|
||||
本轮保持“最小闭环优先”,作品与运行时仍以结构化字段 + `snapshot_json` 组合持久化,不额外拆出更多高耦合表。
|
||||
|
||||
### 5.1 `puzzle_agent_session`
|
||||
|
||||
字段:
|
||||
|
||||
1. `session_id`
|
||||
2. `owner_user_id`
|
||||
3. `seed_text`
|
||||
4. `current_turn`
|
||||
5. `progress_percent`
|
||||
6. `stage`
|
||||
7. `anchor_pack_json`
|
||||
8. `draft_json`
|
||||
9. `last_assistant_reply`
|
||||
10. `published_profile_id`
|
||||
11. `created_at`
|
||||
12. `updated_at`
|
||||
|
||||
### 5.2 `puzzle_agent_message`
|
||||
|
||||
字段:
|
||||
|
||||
1. `message_id`
|
||||
2. `session_id`
|
||||
3. `role`
|
||||
4. `kind`
|
||||
5. `text`
|
||||
6. `created_at`
|
||||
|
||||
### 5.3 `puzzle_work_profile`
|
||||
|
||||
字段:
|
||||
|
||||
1. `profile_id`
|
||||
2. `owner_user_id`
|
||||
3. `source_session_id`
|
||||
4. `author_display_name`
|
||||
5. `level_name`
|
||||
6. `summary_text`
|
||||
7. `theme_tags_json`
|
||||
8. `cover_image_src`
|
||||
9. `cover_asset_id`
|
||||
10. `anchor_pack_json`
|
||||
11. `publication_status`
|
||||
12. `play_count`
|
||||
13. `updated_at`
|
||||
14. `published_at`
|
||||
|
||||
### 5.4 `puzzle_runtime_run`
|
||||
|
||||
字段:
|
||||
|
||||
1. `run_id`
|
||||
2. `owner_user_id`
|
||||
3. `entry_profile_id`
|
||||
4. `current_profile_id`
|
||||
5. `cleared_level_count`
|
||||
6. `current_level_index`
|
||||
7. `current_grid_size`
|
||||
8. `played_profile_ids_json`
|
||||
9. `previous_level_tags_json`
|
||||
10. `snapshot_json`
|
||||
11. `updated_at`
|
||||
12. `created_at`
|
||||
|
||||
### 5.5 Procedure
|
||||
|
||||
本轮全部使用 procedure 同步返回快照,避免 Axum 再次读 private table:
|
||||
|
||||
1. `create_puzzle_agent_session`
|
||||
2. `get_puzzle_agent_session`
|
||||
3. `submit_puzzle_agent_message`
|
||||
4. `compile_puzzle_agent_draft`
|
||||
5. `save_puzzle_generated_images`
|
||||
6. `select_puzzle_cover_image`
|
||||
7. `publish_puzzle_work`
|
||||
8. `list_puzzle_works`
|
||||
9. `get_puzzle_work_detail`
|
||||
10. `update_puzzle_work`
|
||||
11. `list_puzzle_gallery`
|
||||
12. `get_puzzle_gallery_detail`
|
||||
13. `start_puzzle_run`
|
||||
14. `get_puzzle_run`
|
||||
15. `swap_puzzle_pieces`
|
||||
16. `drag_puzzle_piece_or_group`
|
||||
17. `advance_puzzle_next_level`
|
||||
|
||||
## 6. 结果页图片生成策略
|
||||
|
||||
本轮不引入新的真实图像模型编排,而是复用 `api-server` 里已有的占位资产写盘模式:
|
||||
|
||||
1. 每次生成 2 张候选图。
|
||||
2. 候选图通过 `api-server` 写入 `public/generated-puzzle-covers/...`。
|
||||
3. Axum 把候选图 URL、assetId、prompt snapshot 回写到 Spacetime session draft。
|
||||
4. 创作者在结果页选择其中 1 张作为正式图。
|
||||
|
||||
这样可以保证:
|
||||
|
||||
1. 结果页图片生成、重生、应用正式图完整可用。
|
||||
2. 发布链有正式图片可校验。
|
||||
3. 不额外扩到模型供应商集成。
|
||||
|
||||
### 6.1 发布前编辑真相补充
|
||||
|
||||
结果页允许创作者在发布前直接编辑:
|
||||
|
||||
1. `关卡名`
|
||||
2. `摘要`
|
||||
3. `题材标签`
|
||||
|
||||
这 3 个字段不能只停留在前端临时态。
|
||||
|
||||
本轮冻结为:
|
||||
|
||||
1. `publish_puzzle_work` 允许直接携带 `levelName / summary / themeTags`
|
||||
2. `spacetime-module` 在发布事务内先把这些字段覆盖回 session draft 真相
|
||||
3. 覆盖后的 draft 再参与发布校验与 profile 持久化
|
||||
|
||||
这样可以避免额外新增一条“草稿轻量编辑 procedure”,同时确保结果页编辑内容会真实进入广场作品与后续运行时 HUD。
|
||||
|
||||
## 7. 运行态规则冻结
|
||||
|
||||
### 7.1 难度推进
|
||||
|
||||
```ts
|
||||
function resolvePuzzleGridSize(clearedLevelCount: number): 3 | 4 {
|
||||
return clearedLevelCount >= 3 ? 4 : 3;
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 棋盘初始化
|
||||
|
||||
1. 根据正式图片与网格规格生成 `pieceId -> correctRow/correctCol`。
|
||||
2. 随机打乱到非完成态。
|
||||
3. 生成初始 `mergedGroups = []`,再执行一次正确连接检查。
|
||||
|
||||
### 7.3 正确连接
|
||||
|
||||
若两个拼块在当前棋盘中四向相邻,且它们在原图上的正确位置也以同方向相邻,则视为正确连接。
|
||||
|
||||
所有正确连接链通过并查集合并为 `mergedGroup`。
|
||||
|
||||
### 7.4 拖动与拆分
|
||||
|
||||
1. 单块拖到单块位置:执行交换。
|
||||
2. 合并块拖到任意目标锚点:保持内部相对布局整体重排。
|
||||
3. 单块拖到合并块占据位置:先拆分目标合并块,再执行交换,最后重算合并。
|
||||
|
||||
### 7.5 通关
|
||||
|
||||
当所有拼块回到正确位置,或全盘只剩一个覆盖全部拼块的合并组时,标记当前关卡 `cleared`。
|
||||
|
||||
### 7.6 下一关推荐
|
||||
|
||||
固定公式:
|
||||
|
||||
```ts
|
||||
finalScore = tagSimilarityScore * 0.7 + sameAuthorScore * 0.3;
|
||||
```
|
||||
|
||||
标签相似度首版使用规范化标签集合的 Jaccard。
|
||||
|
||||
同分裁决顺序:
|
||||
|
||||
1. `tagSimilarityScore` 更高
|
||||
2. 当前 run 未出现过
|
||||
3. `play_count` 更低
|
||||
4. `updated_at` 更近
|
||||
|
||||
## 8. 前端接入
|
||||
|
||||
### 8.1 平台入口
|
||||
|
||||
只改现有平台壳层:
|
||||
|
||||
1. 在创作类型弹层新增“拼图玩法”。
|
||||
2. 新增拼图专属 stage,不改 RPG runtime 主链。
|
||||
|
||||
### 8.2 组件目录
|
||||
|
||||
新增:
|
||||
|
||||
1. `src/components/puzzle-agent/`
|
||||
2. `src/components/puzzle-result/`
|
||||
3. `src/components/puzzle-gallery/`
|
||||
4. `src/components/puzzle-runtime/`
|
||||
|
||||
### 8.3 服务目录
|
||||
|
||||
新增:
|
||||
|
||||
1. `src/services/puzzle-agent/`
|
||||
2. `src/services/puzzle-works/`
|
||||
3. `src/services/puzzle-gallery/`
|
||||
4. `src/services/puzzle-runtime/`
|
||||
|
||||
本轮全部走 HTTP facade,不引入新的前端 Spacetime 直连。
|
||||
|
||||
### 8.4 当前前端最小落地补充
|
||||
|
||||
当前实现固定走下面这条最小链路:
|
||||
|
||||
1. `PlatformEntryCreationTypeModal` 选择 `puzzle`
|
||||
2. `PuzzleAgentWorkspace` 收束锚点并触发 `compile_puzzle_draft`
|
||||
3. `PuzzleResultView` 编辑 `levelName / summary / themeTags`
|
||||
4. 图片生成通过独立 `PuzzleImageStudioModal` 触发,不在结果页内联堆叠
|
||||
5. 发布后跳转 `PuzzleGalleryDetailView`
|
||||
6. 从详情进入 `PuzzleRuntimeShell`
|
||||
|
||||
创作中心作品展示冻结为:
|
||||
|
||||
1. 拼图作品也是平台作品,和其他创作作品共用同一套列表项样式。
|
||||
2. 创作中心不再保留独立“拼图玩法作品模块”。
|
||||
3. 拼图作品仅通过 `拼图` 标签与题材标签区分,不额外拆出第二块作品区。
|
||||
4. 创作中心仍保留统一“新建作品”入口,由创建类型弹层继续分流到 RPG / 拼图玩法。
|
||||
|
||||
运行时前端表现冻结为:
|
||||
|
||||
1. 使用正式封面图按 `correctRow / correctCol` 做真实网格切片渲染
|
||||
2. 点击两块时仅前端维护轻量选中态,真正交换以后端返回快照为准
|
||||
3. 拖动统一采用 pointer 事件,兼顾网页端与移动端
|
||||
4. 不在前端计算合并、拆分、通关与下一关推荐
|
||||
|
||||
## 9. 验收与检查
|
||||
|
||||
完成后至少执行:
|
||||
|
||||
1. `npm run check:encoding`
|
||||
2. `npm run typecheck`
|
||||
3. `npm run test`
|
||||
4. `cargo check -p module-puzzle`
|
||||
5. `cargo check -p shared-contracts`
|
||||
6. `cargo check -p spacetime-module`
|
||||
7. `spacetime generate --no-config --lang rust --out-dir server-rs/crates/spacetime-client/src/module_bindings --module-path server-rs/crates/spacetime-module --include-private --yes`
|
||||
8. `cargo check -p spacetime-client`
|
||||
9. `cargo check -p api-server`
|
||||
|
||||
如果检查中发现拼图主链缺口,继续补齐;如果已经满足 PRD 主链和上述检查,不再追加额外玩法能力。
|
||||
|
||||
## 10. 2026-04-22 最终验收记录
|
||||
|
||||
本轮已按“最小完整闭环、禁止超出需求过度实现”完成拼图玩法主链落地,并补齐收尾检查。
|
||||
|
||||
### 10.1 已落地主链
|
||||
|
||||
1. 平台创作中心可选择 `puzzle` 玩法入口。
|
||||
2. `PuzzleAgentWorkspace` 已接入 Agent-first 锚点收束与草稿编译。
|
||||
3. `PuzzleResultView` 已支持最小结果页编辑与独立图片生成弹层。
|
||||
4. 发布后作品可进入拼图广场与详情页。
|
||||
5. `PuzzleRuntimeShell` 已按正式封面图真实切片渲染 `3x3 / 4x4` 关卡。
|
||||
6. 交换、拖动、拆分、合并、通关、下一关推荐真相全部以后端快照为准。
|
||||
|
||||
### 10.2 本轮额外修复的验收阻塞
|
||||
|
||||
在最终验收阶段,补齐了与拼图主链无直接业务耦合、但会阻塞仓库整体检查的基线问题:
|
||||
|
||||
1. `typecheck` 基线类型不兼容。
|
||||
2. `AccountModal` 测试 mock 字段落后于最新鉴权契约。
|
||||
3. `customWorld` 存档归一化中场景连接方向未收敛到强类型。
|
||||
4. 结果页生成资源在签名 URL 尚未返回时会短暂空白,已调整为先展示原路径占位,再异步替换签名读地址。
|
||||
|
||||
### 10.3 实际通过的检查
|
||||
|
||||
1. `npm run check:encoding`
|
||||
2. `npm run typecheck`
|
||||
3. `npm run test`
|
||||
4. `cargo check -p module-puzzle`
|
||||
5. `cargo check -p shared-contracts`
|
||||
6. `cargo check -p spacetime-module`
|
||||
7. `cargo check -p spacetime-client`
|
||||
8. `cargo check -p api-server`
|
||||
|
||||
### 10.4 冻结说明
|
||||
|
||||
截至本次验收,拼图玩法已满足 PRD 要求的最小产品闭环;未继续扩展排行榜、提示、体力、异形拼块、倒计时、前端本地裁决等超出本轮需求的能力。
|
||||
@@ -42,6 +42,9 @@
|
||||
- [SPACETIMEDB_CUSTOM_WORLD_AGENT_SESSION_STAGE6_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_SESSION_STAGE6_DESIGN_2026-04-22.md):冻结 `M5` Agent session create / snapshot 的最小 SpacetimeDB 与 Axum facade 闭环,明确本轮不迁移 LLM、SSE、卡片更新和完整 action registry。
|
||||
- [SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STAGE7_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STAGE7_DESIGN_2026-04-22.md):冻结 `M5` Agent `message submit / operation query` 的 deterministic 最小闭环,明确同步写入 user/assistant 消息、`process_message` operation 与 session 进度推进规则。
|
||||
- [SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STREAM_STAGE8_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_AGENT_MESSAGE_STREAM_STAGE8_DESIGN_2026-04-22.md):冻结 `M5` Agent `/messages/stream` 的最小兼容 SSE facade,明确复用 Stage 7 的同步写表逻辑,只输出当前前端真实消费的 `reply_delta / session / done / error` 事件。
|
||||
- [BIG_FISH_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-22.md](./BIG_FISH_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-22.md):冻结大鱼吃小鱼玩法本轮最小完整落地方案,明确 `module-big-fish`、SpacetimeDB 表 / procedure、Axum facade、前端接入和运行态规则边界。
|
||||
- [PUZZLE_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-22.md](./PUZZLE_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-22.md):冻结拼图玩法本轮最小完整落地方案,明确 `module-puzzle`、SpacetimeDB 表 / procedure、Axum facade、前端接入,以及交换 / 合并 / 拖动 / 拆分 / 下一关推荐边界。
|
||||
- [UNIFIED_CREATION_AGENT_CHAT_FRAMEWORK_2026-04-22.md](./UNIFIED_CREATION_AGENT_CHAT_FRAMEWORK_2026-04-22.md):冻结所有创作品类 Agent 聊天 UI 与对话进度管理统一框架,明确品类差异只保留锚点映射、提示词/话术和 action。
|
||||
- [SPACETIMEDB_CUSTOM_WORLD_LIBRARY_DETAIL_STAGE5_EXTENSION_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_LIBRARY_DETAIL_STAGE5_EXTENSION_DESIGN_2026-04-22.md):补齐 `M5` Stage 5 遗漏的 owner-only `GET /api/runtime/custom-world-library/:profileId` 设计,冻结单条 profile detail 的 SpacetimeDB procedure、client facade、404 语义与 Axum 路由扩展方式。
|
||||
- [SPACETIMEDB_CUSTOM_WORLD_WORKS_AND_AGENT_EXTENSION_STAGE9_DESIGN_2026-04-22.md](./SPACETIMEDB_CUSTOM_WORLD_WORKS_AND_AGENT_EXTENSION_STAGE9_DESIGN_2026-04-22.md):冻结 `M5` 剩余主链的 works、card detail、publish gate、supportedActions、action registry 与 AI/OSS 兼容路由边界,作为 Stage 9 到收口阶段的统一落地依据。
|
||||
- [M3_BROWSE_HISTORY_AXUM_SPACETIMEDB_DESIGN_2026-04-21.md](./M3_BROWSE_HISTORY_AXUM_SPACETIMEDB_DESIGN_2026-04-21.md):冻结 `M3` 第二批 `browse history` 纵向切片的 `user_browse_history` 表、双路径 facade、宽松归一化、去重排序规则与测试策略。
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
# 统一创作品类 Agent 对话框架技术方案
|
||||
|
||||
日期:`2026-04-22`
|
||||
|
||||
## 1. 目标
|
||||
|
||||
把平台内所有“先 Agent 聊天收束锚点,再生成结果页”的创作流程统一到一套前端框架:
|
||||
|
||||
1. UI 交互共用一套:标题区、返回、生成结果页按钮、锚点卡片、进度条、操作横幅、聊天气泡、推荐回复、输入框。
|
||||
2. 对话进度管理共用一套:进度归一化、忙碌态判断、SSE `reply_delta / session / error` 解析、操作状态展示。
|
||||
3. 品类差异只允许落在配置和后端领域逻辑:锚点列表、提示词/占位文案、生成结果页 action、快捷补全/总结话术、结果页与运行态。
|
||||
|
||||
## 2. 本轮范围
|
||||
|
||||
覆盖当前已接入平台入口的三条创作链:
|
||||
|
||||
1. RPG / Custom World Agent 创作。
|
||||
2. 大鱼吃小鱼 Agent 创作。
|
||||
3. 拼图 Agent 创作。
|
||||
|
||||
本轮不迁移结果页、运行态、发布、资产生成 UI;这些仍按各品类自己的页面承载。
|
||||
|
||||
## 3. 前端结构
|
||||
|
||||
新增目录:
|
||||
|
||||
```text
|
||||
src/components/creation-agent/
|
||||
├─ CreationAgentWorkspace.tsx
|
||||
└─ index.ts
|
||||
|
||||
src/services/creation-agent/
|
||||
├─ creationAgentProgress.ts
|
||||
├─ creationAgentSse.ts
|
||||
└─ index.ts
|
||||
```
|
||||
|
||||
### 3.1 `CreationAgentWorkspace`
|
||||
|
||||
统一组件只接收通用 view model:
|
||||
|
||||
1. `session`: `CreationAgentSessionView | null`
|
||||
2. `theme`: 品类主题色与背景 class
|
||||
3. `primaryAction`: 生成结果页按钮配置
|
||||
4. `progressActions`: 总结、补全等可选快捷动作
|
||||
5. `activeOperation`: 可选操作状态
|
||||
6. `streamingReplyText / isStreamingReply / isBusy / error`
|
||||
7. `onBack / onSubmitText / onPrimaryAction / onQuickAction`
|
||||
|
||||
组件内部只做表现,不读取任何 RPG、Big Fish、Puzzle 专属字段。
|
||||
|
||||
### 3.2 会话 view model
|
||||
|
||||
各品类工作区负责把自己的 session 映射成:
|
||||
|
||||
1. `title`
|
||||
2. `assistantSummary`
|
||||
3. `progressPercent`
|
||||
4. `currentTurn`
|
||||
5. `anchors: { key, label, value, status }[]`
|
||||
6. `messages: { id, role, kind, text, createdAt }[]`
|
||||
7. `recommendedReplies`
|
||||
|
||||
因此新增品类时只需要新增 mapper,不再复制聊天工作区。
|
||||
|
||||
### 3.3 进度管理
|
||||
|
||||
`creationAgentProgress.ts` 统一提供:
|
||||
|
||||
1. `normalizeCreationAgentProgress(progressPercent)`
|
||||
2. `isCreationAgentOperationBusy(operation)`
|
||||
3. `resolveCreationAgentProgressHint(progressPercent, copy?)`
|
||||
4. `resolveCreationAnchorStatusLabel(status)`
|
||||
5. `createCreationAgentClientMessageId(prefix)`
|
||||
|
||||
### 3.4 SSE 解析
|
||||
|
||||
`creationAgentSse.ts` 统一解析现有 SSE 事件:
|
||||
|
||||
1. `reply_delta`: 调用 `onUpdate(text)`
|
||||
2. `session`: 缓存最终 session
|
||||
3. `error`: 抛出后端错误
|
||||
4. 流结束后若没有 session,抛出品类传入的 incomplete message
|
||||
|
||||
各品类 client 只负责打开自己的 URL 和提供类型参数。
|
||||
|
||||
## 4. 品类差异边界
|
||||
|
||||
### 4.1 RPG / Custom World
|
||||
|
||||
保留差异:
|
||||
|
||||
1. 8 个 RPG 高杠杆锚点映射。
|
||||
2. 总结当前设定话术。
|
||||
3. 补全剩余设定话术。
|
||||
4. 生成结果页 action:`draft_foundation`。
|
||||
|
||||
### 4.2 大鱼吃小鱼
|
||||
|
||||
保留差异:
|
||||
|
||||
1. 4 个玩法锚点映射。
|
||||
2. 输入框占位提示。
|
||||
3. 生成结果页 action:`big_fish_compile_draft`。
|
||||
|
||||
### 4.3 拼图
|
||||
|
||||
保留差异:
|
||||
|
||||
1. 拼图视觉/题材锚点映射。
|
||||
2. 输入框占位提示。
|
||||
3. 生成结果页 action:`compile_puzzle_draft`。
|
||||
|
||||
## 5. 禁止事项
|
||||
|
||||
1. 禁止在统一组件中判断具体品类名称后写分支业务。
|
||||
2. 禁止把 Big Fish / Puzzle 的状态写入 RPG 命名脚本。
|
||||
3. 禁止把后端锚点收束、提示词生成或进度裁决搬到前端。
|
||||
4. 禁止为了统一 UI 改写结果页、运行态或发布流程。
|
||||
|
||||
## 6. 验收
|
||||
|
||||
1. 三个创作流程的 Agent 聊天区都通过 `CreationAgentWorkspace` 渲染。
|
||||
2. Big Fish 与 Puzzle 不再各自复制聊天 UI、锚点卡片、输入框和进度条。
|
||||
3. RPG / Custom World 保留原有“总结当前设定 / 补全剩余设定 / 生成游戏设定草稿”交互。
|
||||
4. 定向 TypeScript / ESLint / 编码检查通过。
|
||||
190
packages/shared/src/contracts/bigFish.ts
Normal file
190
packages/shared/src/contracts/bigFish.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* 大鱼吃小鱼玩法域前端共享契约。
|
||||
* 字段与 server-rs/shared-contracts/src/big_fish.rs 保持 camelCase 对齐。
|
||||
*/
|
||||
export type CreateBigFishSessionRequest = {
|
||||
seedText?: string;
|
||||
};
|
||||
|
||||
export type SendBigFishMessageRequest = {
|
||||
clientMessageId: string;
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type BigFishActionId =
|
||||
| 'big_fish_compile_draft'
|
||||
| 'big_fish_generate_level_main_image'
|
||||
| 'big_fish_generate_level_motion'
|
||||
| 'big_fish_generate_stage_background'
|
||||
| 'big_fish_publish_game';
|
||||
|
||||
export type ExecuteBigFishActionRequest = {
|
||||
action: BigFishActionId;
|
||||
level?: number;
|
||||
motionKey?: 'idle_float' | 'move_swim' | string;
|
||||
};
|
||||
|
||||
export type SubmitBigFishInputRequest = {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
export type BigFishAnchorStatus =
|
||||
| 'confirmed'
|
||||
| 'inferred'
|
||||
| 'missing'
|
||||
| 'locked'
|
||||
| string;
|
||||
|
||||
export type BigFishAnchorItemResponse = {
|
||||
key: string;
|
||||
label: string;
|
||||
value: string;
|
||||
status: BigFishAnchorStatus;
|
||||
};
|
||||
|
||||
export type BigFishAnchorPackResponse = {
|
||||
gameplayPromise: BigFishAnchorItemResponse;
|
||||
ecologyVisualTheme: BigFishAnchorItemResponse;
|
||||
growthLadder: BigFishAnchorItemResponse;
|
||||
riskTempo: BigFishAnchorItemResponse;
|
||||
};
|
||||
|
||||
export type BigFishLevelBlueprintResponse = {
|
||||
level: number;
|
||||
name: string;
|
||||
oneLineFantasy: string;
|
||||
silhouetteDirection: string;
|
||||
sizeRatio: number;
|
||||
visualPromptSeed: string;
|
||||
motionPromptSeed: string;
|
||||
mergeSourceLevel?: number | null;
|
||||
preyWindow: number[];
|
||||
threatWindow: number[];
|
||||
isFinalLevel: boolean;
|
||||
};
|
||||
|
||||
export type BigFishBackgroundBlueprintResponse = {
|
||||
theme: string;
|
||||
colorMood: string;
|
||||
foregroundHints: string;
|
||||
midgroundComposition: string;
|
||||
backgroundDepth: string;
|
||||
safePlayAreaHint: string;
|
||||
spawnEdgeHint: string;
|
||||
backgroundPromptSeed: string;
|
||||
};
|
||||
|
||||
export type BigFishRuntimeParamsResponse = {
|
||||
levelCount: number;
|
||||
mergeCountPerUpgrade: number;
|
||||
spawnTargetCount: number;
|
||||
leaderMoveSpeed: number;
|
||||
followerCatchUpSpeed: number;
|
||||
offscreenCullSeconds: number;
|
||||
preySpawnDeltaLevels: number[];
|
||||
threatSpawnDeltaLevels: number[];
|
||||
winLevel: number;
|
||||
};
|
||||
|
||||
export type BigFishGameDraftResponse = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
coreFun: string;
|
||||
ecologyTheme: string;
|
||||
levels: BigFishLevelBlueprintResponse[];
|
||||
background: BigFishBackgroundBlueprintResponse;
|
||||
runtimeParams: BigFishRuntimeParamsResponse;
|
||||
};
|
||||
|
||||
export type BigFishAgentMessageResponse = {
|
||||
id: string;
|
||||
role: 'user' | 'assistant' | string;
|
||||
kind: 'chat' | 'system' | 'warning' | string;
|
||||
text: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export type BigFishAssetKind =
|
||||
| 'level_main_image'
|
||||
| 'level_motion'
|
||||
| 'stage_background'
|
||||
| string;
|
||||
|
||||
export type BigFishAssetStatus = 'empty' | 'ready' | 'generating' | string;
|
||||
|
||||
export type BigFishAssetSlotResponse = {
|
||||
slotId: string;
|
||||
assetKind: BigFishAssetKind;
|
||||
level?: number | null;
|
||||
motionKey?: string | null;
|
||||
status: BigFishAssetStatus;
|
||||
assetUrl?: string | null;
|
||||
promptSnapshot: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type BigFishAssetCoverageResponse = {
|
||||
levelMainImageReadyCount: number;
|
||||
levelMotionReadyCount: number;
|
||||
backgroundReady: boolean;
|
||||
requiredLevelCount: number;
|
||||
publishReady: boolean;
|
||||
blockers: string[];
|
||||
};
|
||||
|
||||
export type BigFishSessionSnapshotResponse = {
|
||||
sessionId: string;
|
||||
currentTurn: number;
|
||||
progressPercent: number;
|
||||
stage: string;
|
||||
anchorPack: BigFishAnchorPackResponse;
|
||||
draft?: BigFishGameDraftResponse | null;
|
||||
assetSlots: BigFishAssetSlotResponse[];
|
||||
assetCoverage: BigFishAssetCoverageResponse;
|
||||
messages: BigFishAgentMessageResponse[];
|
||||
lastAssistantReply?: string | null;
|
||||
publishReady: boolean;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type BigFishSessionResponse = {
|
||||
session: BigFishSessionSnapshotResponse;
|
||||
};
|
||||
|
||||
export type BigFishActionResponse = {
|
||||
session: BigFishSessionSnapshotResponse;
|
||||
};
|
||||
|
||||
export type BigFishVector2Response = {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
export type BigFishRuntimeEntityResponse = {
|
||||
entityId: string;
|
||||
level: number;
|
||||
position: BigFishVector2Response;
|
||||
radius: number;
|
||||
offscreenSeconds: number;
|
||||
};
|
||||
|
||||
export type BigFishRuntimeSnapshotResponse = {
|
||||
runId: string;
|
||||
sessionId: string;
|
||||
status: 'running' | 'won' | 'failed' | string;
|
||||
tick: number;
|
||||
playerLevel: number;
|
||||
winLevel: number;
|
||||
leaderEntityId?: string | null;
|
||||
ownedEntities: BigFishRuntimeEntityResponse[];
|
||||
wildEntities: BigFishRuntimeEntityResponse[];
|
||||
cameraCenter: BigFishVector2Response;
|
||||
lastInput: BigFishVector2Response;
|
||||
eventLog: string[];
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type BigFishRunResponse = {
|
||||
run: BigFishRuntimeSnapshotResponse;
|
||||
};
|
||||
59
packages/shared/src/contracts/puzzleAgentActions.ts
Normal file
59
packages/shared/src/contracts/puzzleAgentActions.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
export type PuzzleAgentSuggestedActionType =
|
||||
| 'request_summary'
|
||||
| 'compile_puzzle_draft'
|
||||
| 'generate_puzzle_images'
|
||||
| 'publish_puzzle_work';
|
||||
|
||||
export interface PuzzleAgentSuggestedAction {
|
||||
id: string;
|
||||
actionType: PuzzleAgentSuggestedActionType;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export type PuzzleAgentActionType =
|
||||
| 'compile_puzzle_draft'
|
||||
| 'generate_puzzle_images'
|
||||
| 'select_puzzle_image'
|
||||
| 'publish_puzzle_work';
|
||||
|
||||
export type PuzzleAgentOperationType =
|
||||
| 'process_message'
|
||||
| PuzzleAgentActionType;
|
||||
|
||||
export type PuzzleAgentOperationStatus =
|
||||
| 'queued'
|
||||
| 'running'
|
||||
| 'completed'
|
||||
| 'failed';
|
||||
|
||||
export interface PuzzleAgentOperationRecord {
|
||||
operationId: string;
|
||||
type: PuzzleAgentOperationType;
|
||||
status: PuzzleAgentOperationStatus;
|
||||
phaseLabel: string;
|
||||
phaseDetail: string;
|
||||
progress: number;
|
||||
error?: string | null;
|
||||
}
|
||||
|
||||
export type PuzzleAgentActionRequest =
|
||||
| { action: 'compile_puzzle_draft' }
|
||||
| {
|
||||
action: 'generate_puzzle_images';
|
||||
promptText?: string | null;
|
||||
candidateCount?: number;
|
||||
}
|
||||
| {
|
||||
action: 'select_puzzle_image';
|
||||
candidateId: string;
|
||||
}
|
||||
| {
|
||||
action: 'publish_puzzle_work';
|
||||
levelName?: string;
|
||||
summary?: string;
|
||||
themeTags?: string[];
|
||||
};
|
||||
|
||||
export interface PuzzleAgentActionResponse {
|
||||
operation: PuzzleAgentOperationRecord;
|
||||
}
|
||||
58
packages/shared/src/contracts/puzzleAgentDraft.ts
Normal file
58
packages/shared/src/contracts/puzzleAgentDraft.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { JsonObject } from './common';
|
||||
|
||||
export type PuzzleAnchorStatus =
|
||||
| 'missing'
|
||||
| 'inferred'
|
||||
| 'confirmed'
|
||||
| 'locked';
|
||||
|
||||
export interface PuzzleAnchorItem {
|
||||
key: string;
|
||||
label: string;
|
||||
value: string;
|
||||
status: PuzzleAnchorStatus;
|
||||
}
|
||||
|
||||
export interface PuzzleAnchorPack {
|
||||
themePromise: PuzzleAnchorItem;
|
||||
visualSubject: PuzzleAnchorItem;
|
||||
visualMood: PuzzleAnchorItem;
|
||||
compositionHooks: PuzzleAnchorItem;
|
||||
tagsAndForbidden: PuzzleAnchorItem;
|
||||
}
|
||||
|
||||
export interface PuzzleCreatorIntent {
|
||||
sourceMode: 'agent_chat';
|
||||
rawMessagesSummary: string;
|
||||
themePromise: string;
|
||||
visualSubject: string;
|
||||
visualMood: string[];
|
||||
compositionHooks: string[];
|
||||
themeTags: string[];
|
||||
forbiddenDirectives: string[];
|
||||
}
|
||||
|
||||
export interface PuzzleGeneratedImageCandidate {
|
||||
candidateId: string;
|
||||
imageSrc: string;
|
||||
assetId: string;
|
||||
prompt: string;
|
||||
actualPrompt?: string | null;
|
||||
sourceType: 'generated' | 'uploaded';
|
||||
selected: boolean;
|
||||
}
|
||||
|
||||
export interface PuzzleResultDraft {
|
||||
levelName: string;
|
||||
summary: string;
|
||||
themeTags: string[];
|
||||
forbiddenDirectives: string[];
|
||||
creatorIntent: PuzzleCreatorIntent | null;
|
||||
anchorPack: PuzzleAnchorPack;
|
||||
candidates: PuzzleGeneratedImageCandidate[];
|
||||
selectedCandidateId: string | null;
|
||||
coverImageSrc: string | null;
|
||||
coverAssetId: string | null;
|
||||
generationStatus: 'idle' | 'generating' | 'ready';
|
||||
metadata?: JsonObject | null;
|
||||
}
|
||||
58
packages/shared/src/contracts/puzzleAgentSession.ts
Normal file
58
packages/shared/src/contracts/puzzleAgentSession.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { PuzzleAgentActionResponse, PuzzleAgentSuggestedAction } from './puzzleAgentActions';
|
||||
import type { PuzzleAnchorPack, PuzzleResultDraft } from './puzzleAgentDraft';
|
||||
import type { PuzzleResultPreviewEnvelope } from './puzzleResultPreview';
|
||||
|
||||
export type PuzzleAgentStage =
|
||||
| 'collecting_anchors'
|
||||
| 'draft_ready'
|
||||
| 'image_refining'
|
||||
| 'ready_to_publish'
|
||||
| 'published';
|
||||
|
||||
export type PuzzleAgentMessageRole = 'user' | 'assistant' | 'system';
|
||||
|
||||
export type PuzzleAgentMessageKind =
|
||||
| 'chat'
|
||||
| 'summary'
|
||||
| 'action_result'
|
||||
| 'warning';
|
||||
|
||||
export interface PuzzleAgentMessage {
|
||||
id: string;
|
||||
role: PuzzleAgentMessageRole;
|
||||
kind: PuzzleAgentMessageKind;
|
||||
text: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface PuzzleAgentSessionSnapshot {
|
||||
sessionId: string;
|
||||
currentTurn: number;
|
||||
progressPercent: number;
|
||||
stage: PuzzleAgentStage;
|
||||
anchorPack: PuzzleAnchorPack;
|
||||
draft: PuzzleResultDraft | null;
|
||||
messages: PuzzleAgentMessage[];
|
||||
lastAssistantReply: string | null;
|
||||
publishedProfileId: string | null;
|
||||
suggestedActions: PuzzleAgentSuggestedAction[];
|
||||
resultPreview: PuzzleResultPreviewEnvelope | null;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface CreatePuzzleAgentSessionRequest {
|
||||
seedText?: string;
|
||||
}
|
||||
|
||||
export interface CreatePuzzleAgentSessionResponse {
|
||||
session: PuzzleAgentSessionSnapshot;
|
||||
}
|
||||
|
||||
export interface SendPuzzleAgentMessageRequest {
|
||||
clientMessageId: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface SendPuzzleAgentMessageResponse extends PuzzleAgentActionResponse {
|
||||
session: PuzzleAgentSessionSnapshot;
|
||||
}
|
||||
21
packages/shared/src/contracts/puzzleResultPreview.ts
Normal file
21
packages/shared/src/contracts/puzzleResultPreview.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { PuzzleResultDraft } from './puzzleAgentDraft';
|
||||
|
||||
export interface PuzzleResultPreviewBlocker {
|
||||
id: string;
|
||||
code: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface PuzzleResultPreviewFinding {
|
||||
id: string;
|
||||
severity: 'info' | 'warning' | 'blocker';
|
||||
code: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface PuzzleResultPreviewEnvelope {
|
||||
draft: PuzzleResultDraft;
|
||||
blockers: PuzzleResultPreviewBlocker[];
|
||||
qualityFindings: PuzzleResultPreviewFinding[];
|
||||
publishReady: boolean;
|
||||
}
|
||||
74
packages/shared/src/contracts/puzzleRuntimeSession.ts
Normal file
74
packages/shared/src/contracts/puzzleRuntimeSession.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
export type PuzzleGridSize = 3 | 4;
|
||||
|
||||
export interface PuzzleCellPosition {
|
||||
row: number;
|
||||
col: number;
|
||||
}
|
||||
|
||||
export interface PuzzlePieceState {
|
||||
pieceId: string;
|
||||
correctRow: number;
|
||||
correctCol: number;
|
||||
currentRow: number;
|
||||
currentCol: number;
|
||||
mergedGroupId: string | null;
|
||||
}
|
||||
|
||||
export interface PuzzleMergedGroupState {
|
||||
groupId: string;
|
||||
pieceIds: string[];
|
||||
occupiedCells: PuzzleCellPosition[];
|
||||
}
|
||||
|
||||
export interface PuzzleBoardSnapshot {
|
||||
rows: number;
|
||||
cols: number;
|
||||
pieces: PuzzlePieceState[];
|
||||
mergedGroups: PuzzleMergedGroupState[];
|
||||
selectedPieceId: string | null;
|
||||
allTilesResolved: boolean;
|
||||
}
|
||||
|
||||
export interface PuzzleRuntimeLevelSnapshot {
|
||||
runId: string;
|
||||
levelIndex: number;
|
||||
gridSize: PuzzleGridSize;
|
||||
profileId: string;
|
||||
levelName: string;
|
||||
authorDisplayName: string;
|
||||
themeTags: string[];
|
||||
coverImageSrc: string | null;
|
||||
board: PuzzleBoardSnapshot;
|
||||
status: 'playing' | 'cleared';
|
||||
}
|
||||
|
||||
export interface PuzzleRunSnapshot {
|
||||
runId: string;
|
||||
entryProfileId: string;
|
||||
clearedLevelCount: number;
|
||||
currentLevelIndex: number;
|
||||
currentGridSize: PuzzleGridSize;
|
||||
playedProfileIds: string[];
|
||||
previousLevelTags: string[];
|
||||
currentLevel: PuzzleRuntimeLevelSnapshot | null;
|
||||
recommendedNextProfileId: string | null;
|
||||
}
|
||||
|
||||
export interface StartPuzzleRunRequest {
|
||||
profileId: string;
|
||||
}
|
||||
|
||||
export interface PuzzleRunResponse {
|
||||
run: PuzzleRunSnapshot;
|
||||
}
|
||||
|
||||
export interface SwapPuzzlePiecesRequest {
|
||||
firstPieceId: string;
|
||||
secondPieceId: string;
|
||||
}
|
||||
|
||||
export interface DragPuzzlePieceRequest {
|
||||
pieceId: string;
|
||||
targetRow: number;
|
||||
targetCol: number;
|
||||
}
|
||||
39
packages/shared/src/contracts/puzzleWorkSummary.ts
Normal file
39
packages/shared/src/contracts/puzzleWorkSummary.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { JsonObject } from './common';
|
||||
import type { PuzzleAnchorPack } from './puzzleAgentDraft';
|
||||
|
||||
export type PuzzleWorkPublicationStatus = 'draft' | 'published';
|
||||
|
||||
export interface PuzzleWorkSummary {
|
||||
workId: string;
|
||||
profileId: string;
|
||||
ownerUserId: string;
|
||||
sourceSessionId?: string | null;
|
||||
authorDisplayName: string;
|
||||
levelName: string;
|
||||
summary: string;
|
||||
themeTags: string[];
|
||||
coverImageSrc: string | null;
|
||||
coverAssetId?: string | null;
|
||||
publicationStatus: PuzzleWorkPublicationStatus;
|
||||
updatedAt: string;
|
||||
publishedAt: string | null;
|
||||
playCount: number;
|
||||
publishReady: boolean;
|
||||
}
|
||||
|
||||
export interface PuzzleWorkProfile extends PuzzleWorkSummary {
|
||||
anchorPack: PuzzleAnchorPack;
|
||||
metadata?: JsonObject | null;
|
||||
}
|
||||
|
||||
export interface PuzzleWorksResponse {
|
||||
items: PuzzleWorkSummary[];
|
||||
}
|
||||
|
||||
export interface PuzzleWorkDetailResponse {
|
||||
item: PuzzleWorkProfile;
|
||||
}
|
||||
|
||||
export interface PuzzleWorkMutationResponse {
|
||||
item: PuzzleWorkProfile;
|
||||
}
|
||||
@@ -579,7 +579,7 @@ export function createRpgAgentSessionFixture(): RpgAgentSessionSnapshot {
|
||||
lockState: {
|
||||
lockedCardIds: ['world-foundation'],
|
||||
},
|
||||
draftProfile,
|
||||
draftProfile: draftProfile as unknown as Record<string, unknown>,
|
||||
messages: [
|
||||
{
|
||||
id: 'message-1',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './assets/qwenSprite';
|
||||
export * from './contracts/auth';
|
||||
export type * from './contracts/bigFish';
|
||||
export * from './contracts/common';
|
||||
export type * from './contracts/customWorldAgent';
|
||||
export * from './contracts/rpgAgentActions';
|
||||
@@ -9,6 +10,12 @@ export * from './contracts/rpgAgentSession';
|
||||
export * from './contracts/rpgCreationFixtures';
|
||||
export * from './contracts/rpgCreationPreview';
|
||||
export * from './contracts/rpgCreationWorkSummary';
|
||||
export * from './contracts/puzzleAgentActions';
|
||||
export * from './contracts/puzzleAgentDraft';
|
||||
export * from './contracts/puzzleAgentSession';
|
||||
export * from './contracts/puzzleResultPreview';
|
||||
export * from './contracts/puzzleRuntimeSession';
|
||||
export * from './contracts/puzzleWorkSummary';
|
||||
export * from './contracts/rpgRuntimeChat';
|
||||
export * from './contracts/rpgRuntimeQuestAssist';
|
||||
export * from './contracts/rpgRuntimeStoryAction';
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import net from 'node:net';
|
||||
import path from 'node:path';
|
||||
import {spawn} from 'node:child_process';
|
||||
import {existsSync, readFileSync} from 'node:fs';
|
||||
import net from 'node:net';
|
||||
import path from 'node:path';
|
||||
import {fileURLToPath, pathToFileURL} from 'node:url';
|
||||
|
||||
const repoRoot = fileURLToPath(new URL('../', import.meta.url));
|
||||
const serverRoot = fileURLToPath(new URL('../server-node/', import.meta.url));
|
||||
const serverRsRoot = fileURLToPath(new URL('../server-rs/', import.meta.url));
|
||||
const viteCliPath = fileURLToPath(new URL('./vite-cli.mjs', import.meta.url));
|
||||
const serverTsxCliPath = fileURLToPath(
|
||||
new URL('../server-node/node_modules/tsx/dist/cli.mjs', import.meta.url),
|
||||
@@ -16,6 +17,8 @@ const serverTsxLoaderPath = fileURLToPath(
|
||||
const serverTsxLoaderUrl = pathToFileURL(serverTsxLoaderPath).href;
|
||||
const envExamplePath = fileURLToPath(new URL('../.env.example', import.meta.url));
|
||||
const envLocalPath = fileURLToPath(new URL('../.env.local', import.meta.url));
|
||||
const spacetimeConfigPath = fileURLToPath(new URL('../spacetime.json', import.meta.url));
|
||||
const spacetimeLocalConfigPath = fileURLToPath(new URL('../spacetime.local.json', import.meta.url));
|
||||
const bundledNodePath = fileURLToPath(
|
||||
new URL('../.tools/node-v22.22.2-win-x64/node.exe', import.meta.url),
|
||||
);
|
||||
@@ -25,6 +28,11 @@ const bundledNpmCliPath = fileURLToPath(
|
||||
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||
const DEFAULT_DEV_DATABASE_URL = 'postgresql://postgres:postgres@127.0.0.1:5432/genarrative';
|
||||
const DEV_MEMORY_DATABASE_URL = 'pg-mem://genarrative-dev';
|
||||
const DEFAULT_RUST_API_HOST = '127.0.0.1';
|
||||
const DEFAULT_RUST_API_PORT = '3100';
|
||||
const DEFAULT_SPACETIME_SERVER_URL = 'http://127.0.0.1:3001';
|
||||
const DEFAULT_SPACETIME_DATABASE = 'genarrative-dev';
|
||||
const DEFAULT_INTERNAL_API_SECRET = 'genarrative-dev-internal-bridge';
|
||||
|
||||
function parseEnvContents(contents) {
|
||||
return contents
|
||||
@@ -63,6 +71,18 @@ function readEnvFile(filePath) {
|
||||
return parseEnvContents(readFileSync(filePath, 'utf8'));
|
||||
}
|
||||
|
||||
function readJsonFile(filePath) {
|
||||
if (!existsSync(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(readFileSync(filePath, 'utf8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveDatabaseProbeTarget(databaseUrl) {
|
||||
const trimmed = databaseUrl.trim();
|
||||
if (!trimmed || !/^postgres(?:ql)?:\/\//u.test(trimmed)) {
|
||||
@@ -177,6 +197,8 @@ function prependEnvPath(envMap, nextEntry) {
|
||||
|
||||
const exampleEnv = readEnvFile(envExamplePath);
|
||||
const localEnv = readEnvFile(envLocalPath);
|
||||
const spacetimeConfig = readJsonFile(spacetimeConfigPath);
|
||||
const spacetimeLocalConfig = readJsonFile(spacetimeLocalConfigPath);
|
||||
|
||||
const mergedEnv = {
|
||||
...exampleEnv,
|
||||
@@ -196,6 +218,22 @@ mergedEnv.PROJECT_ROOT = mergedEnv.PROJECT_ROOT || repoRoot;
|
||||
mergedEnv.NODE_SERVER_ADDR = mergedEnv.NODE_SERVER_ADDR || ':8081';
|
||||
mergedEnv.NODE_SERVER_TARGET =
|
||||
mergedEnv.NODE_SERVER_TARGET || resolveServerTarget(mergedEnv.NODE_SERVER_ADDR);
|
||||
mergedEnv.GENARRATIVE_API_HOST =
|
||||
mergedEnv.GENARRATIVE_API_HOST || DEFAULT_RUST_API_HOST;
|
||||
mergedEnv.GENARRATIVE_API_PORT =
|
||||
mergedEnv.GENARRATIVE_API_PORT || DEFAULT_RUST_API_PORT;
|
||||
mergedEnv.GENARRATIVE_API_TARGET =
|
||||
mergedEnv.GENARRATIVE_API_TARGET ||
|
||||
`http://${mergedEnv.GENARRATIVE_API_HOST}:${mergedEnv.GENARRATIVE_API_PORT}`;
|
||||
mergedEnv.GENARRATIVE_INTERNAL_API_SECRET =
|
||||
mergedEnv.GENARRATIVE_INTERNAL_API_SECRET || DEFAULT_INTERNAL_API_SECRET;
|
||||
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL =
|
||||
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL || DEFAULT_SPACETIME_SERVER_URL;
|
||||
mergedEnv.GENARRATIVE_SPACETIME_DATABASE =
|
||||
mergedEnv.GENARRATIVE_SPACETIME_DATABASE ||
|
||||
spacetimeLocalConfig?.database ||
|
||||
spacetimeConfig?.database ||
|
||||
DEFAULT_SPACETIME_DATABASE;
|
||||
mergedEnv.DATABASE_URL =
|
||||
mergedEnv.DATABASE_URL || DEFAULT_DEV_DATABASE_URL;
|
||||
mergedEnv.VITE_DEV_HOST = mergedEnv.VITE_DEV_HOST || '127.0.0.1';
|
||||
@@ -205,9 +243,23 @@ mergedEnv.npm_config_scripts_prepend_node_path = 'true';
|
||||
const exampleDatabaseUrl = `${exampleEnv.DATABASE_URL || ''}`.trim();
|
||||
const localDatabaseUrl = `${localEnv.DATABASE_URL || ''}`.trim();
|
||||
const processDatabaseUrl = `${process.env.DATABASE_URL || ''}`.trim();
|
||||
const exampleSpacetimeDatabase = `${exampleEnv.GENARRATIVE_SPACETIME_DATABASE || ''}`.trim();
|
||||
const localSpacetimeDatabase = `${localEnv.GENARRATIVE_SPACETIME_DATABASE || ''}`.trim();
|
||||
const processSpacetimeDatabase = `${process.env.GENARRATIVE_SPACETIME_DATABASE || ''}`.trim();
|
||||
const hasExplicitDatabaseUrl =
|
||||
Boolean(processDatabaseUrl) ||
|
||||
(Boolean(localDatabaseUrl) && localDatabaseUrl !== exampleDatabaseUrl);
|
||||
const hasExplicitSpacetimeDatabase =
|
||||
Boolean(processSpacetimeDatabase) ||
|
||||
(Boolean(localSpacetimeDatabase) && localSpacetimeDatabase !== exampleSpacetimeDatabase);
|
||||
|
||||
// 本地开发默认跟随仓库当前的 Spacetime 数据库名,只有显式覆盖时才尊重环境变量。
|
||||
if (!hasExplicitSpacetimeDatabase) {
|
||||
mergedEnv.GENARRATIVE_SPACETIME_DATABASE =
|
||||
spacetimeLocalConfig?.database ||
|
||||
spacetimeConfig?.database ||
|
||||
DEFAULT_SPACETIME_DATABASE;
|
||||
}
|
||||
|
||||
if (!hasExplicitDatabaseUrl) {
|
||||
const databaseProbeTarget = resolveDatabaseProbeTarget(mergedEnv.DATABASE_URL);
|
||||
@@ -228,6 +280,14 @@ if (!hasExplicitDatabaseUrl) {
|
||||
console.log(`[dev:node] PROJECT_ROOT=${mergedEnv.PROJECT_ROOT}`);
|
||||
console.log(`[dev:node] NODE_SERVER_ADDR=${mergedEnv.NODE_SERVER_ADDR}`);
|
||||
console.log(`[dev:node] NODE_SERVER_TARGET=${mergedEnv.NODE_SERVER_TARGET}`);
|
||||
console.log(`[dev:node] GENARRATIVE_API_TARGET=${mergedEnv.GENARRATIVE_API_TARGET}`);
|
||||
console.log('[dev:node] GENARRATIVE_INTERNAL_API_SECRET=[configured]');
|
||||
console.log(
|
||||
`[dev:node] GENARRATIVE_SPACETIME_SERVER_URL=${mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL}`,
|
||||
);
|
||||
console.log(
|
||||
`[dev:node] GENARRATIVE_SPACETIME_DATABASE=${mergedEnv.GENARRATIVE_SPACETIME_DATABASE}`,
|
||||
);
|
||||
console.log(`[dev:node] DATABASE_URL=${redactDatabaseUrl(mergedEnv.DATABASE_URL)}`);
|
||||
console.log(`[dev:node] VITE_DEV_HOST=${mergedEnv.VITE_DEV_HOST}`);
|
||||
console.log(`[dev:node] NODE_RUNTIME=${runtimeNodePath}`);
|
||||
@@ -329,6 +389,38 @@ const serverProcess = existsSync(serverTsxLoaderPath)
|
||||
stdio: 'inherit',
|
||||
});
|
||||
|
||||
const rustApiProcess = process.platform === 'win32'
|
||||
? spawn(
|
||||
'powershell',
|
||||
[
|
||||
'-NoProfile',
|
||||
'-ExecutionPolicy',
|
||||
'Bypass',
|
||||
'-File',
|
||||
path.join(serverRsRoot, 'scripts', 'dev.ps1'),
|
||||
'-ApiHost',
|
||||
mergedEnv.GENARRATIVE_API_HOST,
|
||||
'-Port',
|
||||
mergedEnv.GENARRATIVE_API_PORT,
|
||||
],
|
||||
{
|
||||
cwd: repoRoot,
|
||||
env: mergedEnv,
|
||||
stdio: 'inherit',
|
||||
},
|
||||
)
|
||||
: spawn(
|
||||
'bash',
|
||||
[
|
||||
path.join(serverRsRoot, 'scripts', 'dev.sh'),
|
||||
],
|
||||
{
|
||||
cwd: repoRoot,
|
||||
env: mergedEnv,
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
|
||||
const viteProcess = spawn(
|
||||
runtimeNodePath,
|
||||
[viteCliPath, '--port=3000', `--host=${mergedEnv.VITE_DEV_HOST}`],
|
||||
@@ -340,6 +432,7 @@ const viteProcess = spawn(
|
||||
);
|
||||
|
||||
registerChild('node server', serverProcess, () => viteProcess);
|
||||
registerChild('rust api-server', rustApiProcess, () => viteProcess);
|
||||
registerChild('vite dev server', viteProcess, () => serverProcess);
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
|
||||
@@ -10,12 +10,14 @@ import { responseEnvelopeMiddleware } from './middleware/responseEnvelope.js';
|
||||
import { createCharacterAssetRoutes } from './modules/assets/characterAssetRoutes.js';
|
||||
import { createEditorRoutes } from './modules/editor/editorRoutes.js';
|
||||
import { createAuthRoutes } from './routes/authRoutes.js';
|
||||
import { createBigFishProxyRoutes } from './routes/bigFishProxyRoutes.js';
|
||||
import { createCustomWorldAgentRoutes } from './routes/customWorldAgent.js';
|
||||
import { createPuzzleProxyRoutes } from './routes/puzzleProxyRoutes.js';
|
||||
import { createRpgEntrySaveRoutes } from './routes/rpg-entry/rpgEntrySaveRoutes.js';
|
||||
import { createRpgWorldLibraryRoutes } from './routes/rpg-entry/rpgWorldLibraryRoutes.js';
|
||||
import { createRpgProfileRoutes } from './routes/rpg-profile/rpgProfileRoutes.js';
|
||||
import { createRpgRuntimeAiAssistRoutes } from './routes/rpg-runtime/rpgRuntimeAiAssistRoutes.js';
|
||||
import { createRpgRuntimeStoryRoutes } from './routes/rpg-runtime/rpgRuntimeStoryRoutes.js';
|
||||
import { createCustomWorldAgentRoutes } from './routes/customWorldAgent.js';
|
||||
|
||||
function matchesRoutePrefix(
|
||||
request: express.Request,
|
||||
@@ -212,6 +214,16 @@ export function createApp(context: AppContext) {
|
||||
withRouteMeta({ routeVersion: '2026-04-21', operation: 'rpg.creation.agent.api' }),
|
||||
createCustomWorldAgentRoutes(context),
|
||||
);
|
||||
app.use(
|
||||
'/api/runtime/big-fish',
|
||||
withRouteMeta({ routeVersion: '2026-04-22', operation: 'bigFish.runtime.proxy.api' }),
|
||||
createBigFishProxyRoutes(context),
|
||||
);
|
||||
app.use(
|
||||
'/api/runtime/puzzle',
|
||||
withRouteMeta({ routeVersion: '2026-04-22', operation: 'puzzle.runtime.proxy.api' }),
|
||||
createPuzzleProxyRoutes(context),
|
||||
);
|
||||
app.use(
|
||||
express.static(context.config.publicDir, {
|
||||
fallthrough: true,
|
||||
|
||||
329
server-node/src/routes/bigFishProxyRoutes.ts
Normal file
329
server-node/src/routes/bigFishProxyRoutes.ts
Normal file
@@ -0,0 +1,329 @@
|
||||
import { Readable } from 'node:stream';
|
||||
|
||||
import { type Request, type Response,Router } from 'express';
|
||||
|
||||
import type { AppContext } from '../context.js';
|
||||
import { badRequest, upstreamError } from '../errors.js';
|
||||
import {
|
||||
API_RESPONSE_ENVELOPE_HEADER,
|
||||
API_VERSION_HEADER,
|
||||
asyncHandler,
|
||||
prepareApiResponse,
|
||||
RESPONSE_TIME_HEADER,
|
||||
ROUTE_VERSION_HEADER,
|
||||
} from '../http.js';
|
||||
import { requireJwtAuth } from '../middleware/auth.js';
|
||||
import { routeMeta } from '../middleware/routeMeta.js';
|
||||
|
||||
const BIG_FISH_ROUTE_VERSION = '2026-04-22';
|
||||
const DEFAULT_RUST_API_TARGET = 'http://127.0.0.1:3100';
|
||||
const DEFAULT_INTERNAL_API_SECRET = 'genarrative-dev-internal-bridge';
|
||||
const INTERNAL_USER_HEADER = 'x-genarrative-authenticated-user-id';
|
||||
const INTERNAL_SECRET_HEADER = 'x-genarrative-internal-api-secret';
|
||||
|
||||
function resolveRustApiTarget(context: AppContext) {
|
||||
const configured =
|
||||
context.config.rawEnv.GENARRATIVE_API_TARGET?.trim() ||
|
||||
context.config.rawEnv.RUST_API_SERVER_TARGET?.trim() ||
|
||||
'';
|
||||
return configured || DEFAULT_RUST_API_TARGET;
|
||||
}
|
||||
|
||||
function resolveInternalApiSecret(context: AppContext) {
|
||||
return (
|
||||
context.config.rawEnv.GENARRATIVE_INTERNAL_API_SECRET?.trim() ||
|
||||
DEFAULT_INTERNAL_API_SECRET
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeRouteSuffix(path: string) {
|
||||
const normalized = path.startsWith('/') ? path : `/${path}`;
|
||||
return normalized.replace(/\/+$/u, '');
|
||||
}
|
||||
|
||||
function buildUpstreamUrl(context: AppContext, pathSuffix: string) {
|
||||
const baseUrl = resolveRustApiTarget(context).replace(/\/+$/u, '');
|
||||
return `${baseUrl}${normalizeRouteSuffix(pathSuffix)}`;
|
||||
}
|
||||
|
||||
function pickForwardHeaders(
|
||||
request: Request,
|
||||
context: AppContext,
|
||||
userId: string,
|
||||
) {
|
||||
const forwardedHeaders = new Headers();
|
||||
|
||||
const contentType = request.header('content-type')?.trim();
|
||||
if (contentType) {
|
||||
forwardedHeaders.set('content-type', contentType);
|
||||
}
|
||||
|
||||
const accept = request.header('accept')?.trim();
|
||||
if (accept) {
|
||||
forwardedHeaders.set('accept', accept);
|
||||
}
|
||||
|
||||
const requestId = request.requestId?.trim();
|
||||
if (requestId) {
|
||||
forwardedHeaders.set('x-request-id', requestId);
|
||||
}
|
||||
|
||||
const envelope = request.header(API_RESPONSE_ENVELOPE_HEADER)?.trim();
|
||||
if (envelope) {
|
||||
forwardedHeaders.set(API_RESPONSE_ENVELOPE_HEADER, envelope);
|
||||
}
|
||||
|
||||
forwardedHeaders.set(INTERNAL_USER_HEADER, userId);
|
||||
const internalSecret = resolveInternalApiSecret(context);
|
||||
if (internalSecret) {
|
||||
forwardedHeaders.set(INTERNAL_SECRET_HEADER, internalSecret);
|
||||
}
|
||||
return forwardedHeaders;
|
||||
}
|
||||
|
||||
function readBodyAllowed(method: string) {
|
||||
return !['GET', 'HEAD'].includes(method.toUpperCase());
|
||||
}
|
||||
|
||||
async function proxyBigFishRequest(params: {
|
||||
context: AppContext;
|
||||
request: Request;
|
||||
response: Response;
|
||||
pathSuffix: string;
|
||||
streamBody?: boolean;
|
||||
}) {
|
||||
const { context, request, response, pathSuffix, streamBody = false } = params;
|
||||
const userId = request.userId?.trim();
|
||||
if (!userId) {
|
||||
throw badRequest('缺少已认证用户上下文');
|
||||
}
|
||||
|
||||
const upstreamUrl = buildUpstreamUrl(context, pathSuffix);
|
||||
const method = request.method.toUpperCase();
|
||||
const body =
|
||||
readBodyAllowed(method) && request.body !== undefined
|
||||
? JSON.stringify(request.body)
|
||||
: undefined;
|
||||
|
||||
let upstreamResponse: globalThis.Response;
|
||||
try {
|
||||
upstreamResponse = await fetch(upstreamUrl, {
|
||||
method,
|
||||
// 这里显式转发“已通过 Node 校验的用户身份”,让 Big Fish 继续由 Rust 真相后端处理。
|
||||
headers: pickForwardHeaders(request, context, userId),
|
||||
body,
|
||||
});
|
||||
} catch (error) {
|
||||
request.log?.error(
|
||||
{
|
||||
err: error,
|
||||
user_id: userId,
|
||||
upstream_url: upstreamUrl,
|
||||
},
|
||||
'big fish upstream request failed',
|
||||
);
|
||||
throw upstreamError('大鱼吃小鱼后端暂时不可用');
|
||||
}
|
||||
|
||||
prepareApiResponse(request, response, {
|
||||
statusCode: upstreamResponse.status,
|
||||
headers: {
|
||||
'Content-Type':
|
||||
upstreamResponse.headers.get('content-type') ||
|
||||
'application/json; charset=utf-8',
|
||||
'Cache-Control':
|
||||
upstreamResponse.headers.get('cache-control') || 'no-cache',
|
||||
},
|
||||
routeMeta: {
|
||||
routeVersion: BIG_FISH_ROUTE_VERSION,
|
||||
},
|
||||
});
|
||||
|
||||
const upstreamRequestId = upstreamResponse.headers.get('x-request-id');
|
||||
if (upstreamRequestId) {
|
||||
response.setHeader('x-upstream-request-id', upstreamRequestId);
|
||||
}
|
||||
|
||||
const upstreamRouteVersion = upstreamResponse.headers.get(ROUTE_VERSION_HEADER);
|
||||
if (upstreamRouteVersion) {
|
||||
response.setHeader('x-upstream-route-version', upstreamRouteVersion);
|
||||
}
|
||||
|
||||
const upstreamApiVersion = upstreamResponse.headers.get(API_VERSION_HEADER);
|
||||
if (upstreamApiVersion) {
|
||||
response.setHeader('x-upstream-api-version', upstreamApiVersion);
|
||||
}
|
||||
|
||||
const upstreamLatency = upstreamResponse.headers.get(RESPONSE_TIME_HEADER);
|
||||
if (upstreamLatency) {
|
||||
response.setHeader('x-upstream-response-time-ms', upstreamLatency);
|
||||
}
|
||||
|
||||
if (streamBody) {
|
||||
if (!upstreamResponse.body) {
|
||||
throw upstreamError('大鱼吃小鱼流式响应不可用');
|
||||
}
|
||||
|
||||
response.flushHeaders?.();
|
||||
await Readable.fromWeb(upstreamResponse.body as never).pipe(response);
|
||||
return;
|
||||
}
|
||||
|
||||
response.end(await upstreamResponse.text());
|
||||
}
|
||||
|
||||
function readParam(value: string | string[] | undefined) {
|
||||
return Array.isArray(value) ? value[0]?.trim() || '' : value?.trim() || '';
|
||||
}
|
||||
|
||||
export function createBigFishProxyRoutes(context: AppContext) {
|
||||
const router = Router();
|
||||
const requireAuth = requireJwtAuth(context.config, context.userRepository);
|
||||
|
||||
router.use(requireAuth);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions',
|
||||
routeMeta({ operation: 'runtime.bigFish.createSession', routeVersion: BIG_FISH_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: '/api/runtime/big-fish/agent/sessions',
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/agent/sessions/:sessionId',
|
||||
routeMeta({ operation: 'runtime.bigFish.getSession', routeVersion: BIG_FISH_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/big-fish/agent/sessions/${encodeURIComponent(sessionId)}`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions/:sessionId/messages',
|
||||
routeMeta({ operation: 'runtime.bigFish.sendMessage', routeVersion: BIG_FISH_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/big-fish/agent/sessions/${encodeURIComponent(sessionId)}/messages`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions/:sessionId/messages/stream',
|
||||
routeMeta({
|
||||
operation: 'runtime.bigFish.streamMessage',
|
||||
routeVersion: BIG_FISH_ROUTE_VERSION,
|
||||
}),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/big-fish/agent/sessions/${encodeURIComponent(sessionId)}/messages/stream`,
|
||||
streamBody: true,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions/:sessionId/actions',
|
||||
routeMeta({ operation: 'runtime.bigFish.executeAction', routeVersion: BIG_FISH_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/big-fish/agent/sessions/${encodeURIComponent(sessionId)}/actions`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/sessions/:sessionId/runs',
|
||||
routeMeta({ operation: 'runtime.bigFish.startRun', routeVersion: BIG_FISH_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/big-fish/sessions/${encodeURIComponent(sessionId)}/runs`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/runs/:runId',
|
||||
routeMeta({ operation: 'runtime.bigFish.getRun', routeVersion: BIG_FISH_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const runId = readParam(request.params.runId);
|
||||
if (!runId) {
|
||||
throw badRequest('runId is required');
|
||||
}
|
||||
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/big-fish/runs/${encodeURIComponent(runId)}`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/runs/:runId/input',
|
||||
routeMeta({ operation: 'runtime.bigFish.submitInput', routeVersion: BIG_FISH_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const runId = readParam(request.params.runId);
|
||||
if (!runId) {
|
||||
throw badRequest('runId is required');
|
||||
}
|
||||
|
||||
await proxyBigFishRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/big-fish/runs/${encodeURIComponent(runId)}/input`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
return router;
|
||||
}
|
||||
439
server-node/src/routes/puzzleProxyRoutes.ts
Normal file
439
server-node/src/routes/puzzleProxyRoutes.ts
Normal file
@@ -0,0 +1,439 @@
|
||||
import { Readable } from 'node:stream';
|
||||
|
||||
import { type Request, type Response, Router } from 'express';
|
||||
|
||||
import type { AppContext } from '../context.js';
|
||||
import { badRequest, upstreamError } from '../errors.js';
|
||||
import {
|
||||
API_RESPONSE_ENVELOPE_HEADER,
|
||||
API_VERSION_HEADER,
|
||||
asyncHandler,
|
||||
prepareApiResponse,
|
||||
RESPONSE_TIME_HEADER,
|
||||
ROUTE_VERSION_HEADER,
|
||||
} from '../http.js';
|
||||
import { requireJwtAuth } from '../middleware/auth.js';
|
||||
import { routeMeta } from '../middleware/routeMeta.js';
|
||||
|
||||
const PUZZLE_ROUTE_VERSION = '2026-04-22';
|
||||
const DEFAULT_RUST_API_TARGET = 'http://127.0.0.1:3100';
|
||||
const DEFAULT_INTERNAL_API_SECRET = 'genarrative-dev-internal-bridge';
|
||||
const INTERNAL_USER_HEADER = 'x-genarrative-authenticated-user-id';
|
||||
const INTERNAL_SECRET_HEADER = 'x-genarrative-internal-api-secret';
|
||||
|
||||
function resolveRustApiTarget(context: AppContext) {
|
||||
const configured =
|
||||
context.config.rawEnv.GENARRATIVE_API_TARGET?.trim() ||
|
||||
context.config.rawEnv.RUST_API_SERVER_TARGET?.trim() ||
|
||||
'';
|
||||
return configured || DEFAULT_RUST_API_TARGET;
|
||||
}
|
||||
|
||||
function resolveInternalApiSecret(context: AppContext) {
|
||||
return (
|
||||
context.config.rawEnv.GENARRATIVE_INTERNAL_API_SECRET?.trim() ||
|
||||
DEFAULT_INTERNAL_API_SECRET
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeRouteSuffix(path: string) {
|
||||
const normalized = path.startsWith('/') ? path : `/${path}`;
|
||||
return normalized.replace(/\/+$/u, '');
|
||||
}
|
||||
|
||||
function buildUpstreamUrl(context: AppContext, pathSuffix: string) {
|
||||
const baseUrl = resolveRustApiTarget(context).replace(/\/+$/u, '');
|
||||
return `${baseUrl}${normalizeRouteSuffix(pathSuffix)}`;
|
||||
}
|
||||
|
||||
function pickForwardHeaders(
|
||||
request: Request,
|
||||
context: AppContext,
|
||||
userId: string,
|
||||
) {
|
||||
const forwardedHeaders = new Headers();
|
||||
|
||||
const contentType = request.header('content-type')?.trim();
|
||||
if (contentType) {
|
||||
forwardedHeaders.set('content-type', contentType);
|
||||
}
|
||||
|
||||
const accept = request.header('accept')?.trim();
|
||||
if (accept) {
|
||||
forwardedHeaders.set('accept', accept);
|
||||
}
|
||||
|
||||
const requestId = request.requestId?.trim();
|
||||
if (requestId) {
|
||||
forwardedHeaders.set('x-request-id', requestId);
|
||||
}
|
||||
|
||||
const envelope = request.header(API_RESPONSE_ENVELOPE_HEADER)?.trim();
|
||||
if (envelope) {
|
||||
forwardedHeaders.set(API_RESPONSE_ENVELOPE_HEADER, envelope);
|
||||
}
|
||||
|
||||
forwardedHeaders.set(INTERNAL_USER_HEADER, userId);
|
||||
const internalSecret = resolveInternalApiSecret(context);
|
||||
if (internalSecret) {
|
||||
forwardedHeaders.set(INTERNAL_SECRET_HEADER, internalSecret);
|
||||
}
|
||||
return forwardedHeaders;
|
||||
}
|
||||
|
||||
function readBodyAllowed(method: string) {
|
||||
return !['GET', 'HEAD'].includes(method.toUpperCase());
|
||||
}
|
||||
|
||||
async function proxyPuzzleRequest(params: {
|
||||
context: AppContext;
|
||||
request: Request;
|
||||
response: Response;
|
||||
pathSuffix: string;
|
||||
streamBody?: boolean;
|
||||
}) {
|
||||
const { context, request, response, pathSuffix, streamBody = false } = params;
|
||||
const userId = request.userId?.trim();
|
||||
if (!userId) {
|
||||
throw badRequest('缺少已认证用户上下文');
|
||||
}
|
||||
|
||||
const upstreamUrl = buildUpstreamUrl(context, pathSuffix);
|
||||
const method = request.method.toUpperCase();
|
||||
const body =
|
||||
readBodyAllowed(method) && request.body !== undefined
|
||||
? JSON.stringify(request.body)
|
||||
: undefined;
|
||||
|
||||
let upstreamResponse: globalThis.Response;
|
||||
try {
|
||||
upstreamResponse = await fetch(upstreamUrl, {
|
||||
method,
|
||||
headers: pickForwardHeaders(request, context, userId),
|
||||
body,
|
||||
});
|
||||
} catch (error) {
|
||||
request.log?.error(
|
||||
{
|
||||
err: error,
|
||||
user_id: userId,
|
||||
upstream_url: upstreamUrl,
|
||||
},
|
||||
'puzzle upstream request failed',
|
||||
);
|
||||
throw upstreamError('拼图后端暂时不可用');
|
||||
}
|
||||
|
||||
prepareApiResponse(request, response, {
|
||||
statusCode: upstreamResponse.status,
|
||||
headers: {
|
||||
'Content-Type':
|
||||
upstreamResponse.headers.get('content-type') ||
|
||||
'application/json; charset=utf-8',
|
||||
'Cache-Control':
|
||||
upstreamResponse.headers.get('cache-control') || 'no-cache',
|
||||
},
|
||||
routeMeta: {
|
||||
routeVersion: PUZZLE_ROUTE_VERSION,
|
||||
},
|
||||
});
|
||||
|
||||
const upstreamRequestId = upstreamResponse.headers.get('x-request-id');
|
||||
if (upstreamRequestId) {
|
||||
response.setHeader('x-upstream-request-id', upstreamRequestId);
|
||||
}
|
||||
|
||||
const upstreamRouteVersion = upstreamResponse.headers.get(ROUTE_VERSION_HEADER);
|
||||
if (upstreamRouteVersion) {
|
||||
response.setHeader('x-upstream-route-version', upstreamRouteVersion);
|
||||
}
|
||||
|
||||
const upstreamApiVersion = upstreamResponse.headers.get(API_VERSION_HEADER);
|
||||
if (upstreamApiVersion) {
|
||||
response.setHeader('x-upstream-api-version', upstreamApiVersion);
|
||||
}
|
||||
|
||||
const upstreamLatency = upstreamResponse.headers.get(RESPONSE_TIME_HEADER);
|
||||
if (upstreamLatency) {
|
||||
response.setHeader('x-upstream-response-time-ms', upstreamLatency);
|
||||
}
|
||||
|
||||
if (streamBody) {
|
||||
if (!upstreamResponse.body) {
|
||||
throw upstreamError('拼图流式响应不可用');
|
||||
}
|
||||
|
||||
response.flushHeaders?.();
|
||||
await Readable.fromWeb(upstreamResponse.body as never).pipe(response);
|
||||
return;
|
||||
}
|
||||
|
||||
response.end(await upstreamResponse.text());
|
||||
}
|
||||
|
||||
function readParam(value: string | string[] | undefined) {
|
||||
return Array.isArray(value) ? value[0]?.trim() || '' : value?.trim() || '';
|
||||
}
|
||||
|
||||
export function createPuzzleProxyRoutes(context: AppContext) {
|
||||
const router = Router();
|
||||
const requireAuth = requireJwtAuth(context.config, context.userRepository);
|
||||
|
||||
router.use(requireAuth);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions',
|
||||
routeMeta({ operation: 'runtime.puzzle.createSession', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: '/api/runtime/puzzle/agent/sessions',
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/agent/sessions/:sessionId',
|
||||
routeMeta({ operation: 'runtime.puzzle.getSession', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/agent/sessions/${encodeURIComponent(sessionId)}`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions/:sessionId/messages',
|
||||
routeMeta({ operation: 'runtime.puzzle.sendMessage', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/agent/sessions/${encodeURIComponent(sessionId)}/messages`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions/:sessionId/messages/stream',
|
||||
routeMeta({
|
||||
operation: 'runtime.puzzle.streamMessage',
|
||||
routeVersion: PUZZLE_ROUTE_VERSION,
|
||||
}),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/agent/sessions/${encodeURIComponent(sessionId)}/messages/stream`,
|
||||
streamBody: true,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/agent/sessions/:sessionId/actions',
|
||||
routeMeta({ operation: 'runtime.puzzle.executeAction', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = readParam(request.params.sessionId);
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/agent/sessions/${encodeURIComponent(sessionId)}/actions`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/works',
|
||||
routeMeta({ operation: 'runtime.puzzle.listWorks', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: '/api/runtime/puzzle/works',
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/works/:profileId',
|
||||
routeMeta({ operation: 'runtime.puzzle.getWorkDetail', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const profileId = readParam(request.params.profileId);
|
||||
if (!profileId) {
|
||||
throw badRequest('profileId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/works/${encodeURIComponent(profileId)}`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.put(
|
||||
'/works/:profileId',
|
||||
routeMeta({ operation: 'runtime.puzzle.updateWork', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const profileId = readParam(request.params.profileId);
|
||||
if (!profileId) {
|
||||
throw badRequest('profileId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/works/${encodeURIComponent(profileId)}`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/gallery',
|
||||
routeMeta({ operation: 'runtime.puzzle.listGallery', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: '/api/runtime/puzzle/gallery',
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/gallery/:profileId',
|
||||
routeMeta({ operation: 'runtime.puzzle.getGalleryDetail', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const profileId = readParam(request.params.profileId);
|
||||
if (!profileId) {
|
||||
throw badRequest('profileId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/gallery/${encodeURIComponent(profileId)}`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/runs',
|
||||
routeMeta({ operation: 'runtime.puzzle.startRun', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: '/api/runtime/puzzle/runs',
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/runs/:runId',
|
||||
routeMeta({ operation: 'runtime.puzzle.getRun', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const runId = readParam(request.params.runId);
|
||||
if (!runId) {
|
||||
throw badRequest('runId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/runs/${encodeURIComponent(runId)}`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/runs/:runId/swap',
|
||||
routeMeta({ operation: 'runtime.puzzle.swapPieces', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const runId = readParam(request.params.runId);
|
||||
if (!runId) {
|
||||
throw badRequest('runId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/runs/${encodeURIComponent(runId)}/swap`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/runs/:runId/drag',
|
||||
routeMeta({ operation: 'runtime.puzzle.dragPiece', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const runId = readParam(request.params.runId);
|
||||
if (!runId) {
|
||||
throw badRequest('runId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/runs/${encodeURIComponent(runId)}/drag`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/runs/:runId/next-level',
|
||||
routeMeta({ operation: 'runtime.puzzle.nextLevel', routeVersion: PUZZLE_ROUTE_VERSION }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const runId = readParam(request.params.runId);
|
||||
if (!runId) {
|
||||
throw badRequest('runId is required');
|
||||
}
|
||||
|
||||
await proxyPuzzleRequest({
|
||||
context,
|
||||
request,
|
||||
response,
|
||||
pathSuffix: `/api/runtime/puzzle/runs/${encodeURIComponent(runId)}/next-level`,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
return router;
|
||||
}
|
||||
26
server-rs/Cargo.lock
generated
26
server-rs/Cargo.lock
generated
@@ -78,6 +78,7 @@ dependencies = [
|
||||
"module-ai",
|
||||
"module-assets",
|
||||
"module-auth",
|
||||
"module-big-fish",
|
||||
"module-combat",
|
||||
"module-custom-world",
|
||||
"module-inventory",
|
||||
@@ -1425,6 +1426,16 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "module-big-fish"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shared-kernel",
|
||||
"spacetimedb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "module-combat"
|
||||
version = "0.1.0"
|
||||
@@ -1471,6 +1482,16 @@ dependencies = [
|
||||
"spacetimedb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "module-puzzle"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shared-kernel",
|
||||
"spacetimedb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "module-quest"
|
||||
version = "0.1.0"
|
||||
@@ -2487,10 +2508,12 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"module-ai",
|
||||
"module-assets",
|
||||
"module-big-fish",
|
||||
"module-combat",
|
||||
"module-custom-world",
|
||||
"module-inventory",
|
||||
"module-npc",
|
||||
"module-puzzle",
|
||||
"module-runtime",
|
||||
"module-runtime-item",
|
||||
"module-story",
|
||||
@@ -2507,15 +2530,18 @@ dependencies = [
|
||||
"log",
|
||||
"module-ai",
|
||||
"module-assets",
|
||||
"module-big-fish",
|
||||
"module-combat",
|
||||
"module-custom-world",
|
||||
"module-inventory",
|
||||
"module-npc",
|
||||
"module-progression",
|
||||
"module-puzzle",
|
||||
"module-quest",
|
||||
"module-runtime",
|
||||
"module-runtime-item",
|
||||
"module-story",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shared-kernel",
|
||||
"spacetimedb",
|
||||
|
||||
@@ -8,10 +8,12 @@ members = [
|
||||
"crates/module-ai",
|
||||
"crates/module-assets",
|
||||
"crates/module-auth",
|
||||
"crates/module-big-fish",
|
||||
"crates/module-combat",
|
||||
"crates/module-inventory",
|
||||
"crates/module-custom-world",
|
||||
"crates/module-npc",
|
||||
"crates/module-puzzle",
|
||||
"crates/module-progression",
|
||||
"crates/module-quest",
|
||||
"crates/module-runtime",
|
||||
|
||||
@@ -11,6 +11,7 @@ reqwest = { version = "0.12", default-features = false, features = ["json", "rus
|
||||
module-ai = { path = "../module-ai" }
|
||||
module-assets = { path = "../module-assets" }
|
||||
module-auth = { path = "../module-auth" }
|
||||
module-big-fish = { path = "../module-big-fish" }
|
||||
module-combat = { path = "../module-combat" }
|
||||
module-custom-world = { path = "../module-custom-world" }
|
||||
module-inventory = { path = "../module-inventory" }
|
||||
|
||||
@@ -24,6 +24,11 @@ use crate::{
|
||||
},
|
||||
auth_me::auth_me,
|
||||
auth_sessions::auth_sessions,
|
||||
big_fish::{
|
||||
create_big_fish_session, execute_big_fish_action, get_big_fish_run, get_big_fish_session,
|
||||
start_big_fish_run, stream_big_fish_message, submit_big_fish_input,
|
||||
submit_big_fish_message,
|
||||
},
|
||||
custom_world::{
|
||||
create_custom_world_agent_session, execute_custom_world_agent_action,
|
||||
get_custom_world_agent_card_detail,
|
||||
@@ -48,6 +53,13 @@ use crate::{
|
||||
logout_all::logout_all,
|
||||
password_entry::password_entry,
|
||||
phone_auth::{phone_login, send_phone_code},
|
||||
puzzle::{
|
||||
advance_puzzle_next_level, create_puzzle_agent_session, drag_puzzle_piece_or_group,
|
||||
execute_puzzle_agent_action, get_puzzle_agent_session, get_puzzle_gallery_detail,
|
||||
get_puzzle_run, get_puzzle_work_detail, get_puzzle_works, list_puzzle_gallery,
|
||||
put_puzzle_work, start_puzzle_run, stream_puzzle_agent_message,
|
||||
submit_puzzle_agent_message, swap_puzzle_pieces,
|
||||
},
|
||||
refresh_session::refresh_session,
|
||||
request_context::{attach_request_context, resolve_request_id},
|
||||
response_headers::propagate_request_id_header,
|
||||
@@ -348,6 +360,153 @@ pub fn build_router(state: AppState) -> Router {
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/agent/sessions",
|
||||
post(create_big_fish_session).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/agent/sessions/{session_id}",
|
||||
get(get_big_fish_session).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/agent/sessions/{session_id}/messages",
|
||||
post(submit_big_fish_message).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/agent/sessions/{session_id}/messages/stream",
|
||||
post(stream_big_fish_message).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/agent/sessions/{session_id}/actions",
|
||||
post(execute_big_fish_action).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/sessions/{session_id}/runs",
|
||||
post(start_big_fish_run).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/runs/{run_id}",
|
||||
get(get_big_fish_run).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/big-fish/runs/{run_id}/input",
|
||||
post(submit_big_fish_input).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/agent/sessions",
|
||||
post(create_puzzle_agent_session).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/agent/sessions/{session_id}",
|
||||
get(get_puzzle_agent_session).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/agent/sessions/{session_id}/messages",
|
||||
post(submit_puzzle_agent_message).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/agent/sessions/{session_id}/messages/stream",
|
||||
post(stream_puzzle_agent_message).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/agent/sessions/{session_id}/actions",
|
||||
post(execute_puzzle_agent_action).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/works",
|
||||
get(get_puzzle_works).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/works/{profile_id}",
|
||||
get(get_puzzle_work_detail)
|
||||
.put(put_puzzle_work)
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route("/api/runtime/puzzle/gallery", get(list_puzzle_gallery))
|
||||
.route(
|
||||
"/api/runtime/puzzle/gallery/{profile_id}",
|
||||
get(get_puzzle_gallery_detail),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/runs",
|
||||
post(start_puzzle_run).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/runs/{run_id}",
|
||||
get(get_puzzle_run).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/runs/{run_id}/swap",
|
||||
post(swap_puzzle_pieces).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/runs/{run_id}/drag",
|
||||
post(drag_puzzle_piece_or_group).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/puzzle/runs/{run_id}/next-level",
|
||||
post(advance_puzzle_next_level).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/custom-world/entity",
|
||||
post(generate_custom_world_entity).route_layer(middleware::from_fn_with_state(
|
||||
|
||||
@@ -8,8 +8,12 @@ use axum::{
|
||||
middleware::Next,
|
||||
response::Response,
|
||||
};
|
||||
use platform_auth::{AccessTokenClaims, read_refresh_session_token, verify_access_token};
|
||||
use platform_auth::{
|
||||
AccessTokenClaims, AuthProvider, BindingStatus, read_refresh_session_token,
|
||||
verify_access_token,
|
||||
};
|
||||
use serde_json::{Value, json};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
@@ -17,6 +21,9 @@ use crate::{
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
const INTERNAL_AUTH_USER_ID_HEADER: &str = "x-genarrative-authenticated-user-id";
|
||||
const INTERNAL_API_SECRET_HEADER: &str = "x-genarrative-internal-api-secret";
|
||||
|
||||
// 统一把已校验的 claims 写入 request extensions,避免后续 handler 再次重复解析 Bearer token。
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AuthenticatedAccessToken {
|
||||
@@ -53,6 +60,15 @@ pub async fn require_bearer_auth(
|
||||
mut request: Request,
|
||||
next: Next,
|
||||
) -> Result<Response, AppError> {
|
||||
if request.uri().path().starts_with("/api/runtime/big-fish/")
|
||||
&& let Some(claims) = try_build_internal_forwarded_claims(&state, request.headers())
|
||||
{
|
||||
request
|
||||
.extensions_mut()
|
||||
.insert(AuthenticatedAccessToken::new(claims));
|
||||
return Ok(next.run(request).await);
|
||||
}
|
||||
|
||||
let bearer_token = extract_bearer_token(request.headers())?;
|
||||
let request_id = request
|
||||
.extensions()
|
||||
@@ -172,13 +188,60 @@ fn extract_bearer_token(headers: &HeaderMap) -> Result<String, AppError> {
|
||||
Ok(token.to_string())
|
||||
}
|
||||
|
||||
fn try_build_internal_forwarded_claims(
|
||||
state: &AppState,
|
||||
headers: &HeaderMap,
|
||||
) -> Option<AccessTokenClaims> {
|
||||
let expected_secret = state.config.internal_api_secret.as_ref()?.trim();
|
||||
if expected_secret.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let provided_secret = headers
|
||||
.get(INTERNAL_API_SECRET_HEADER)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())?;
|
||||
if provided_secret != expected_secret {
|
||||
return None;
|
||||
}
|
||||
|
||||
let user_id = headers
|
||||
.get(INTERNAL_AUTH_USER_ID_HEADER)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())?
|
||||
.to_string();
|
||||
|
||||
// 这里的 claims 只服务于经 Node 已鉴权后的本地内部转发链路,避免在开发态复制整套账号仓储。
|
||||
AccessTokenClaims::from_input(
|
||||
platform_auth::AccessTokenClaimsInput {
|
||||
user_id: user_id.clone(),
|
||||
session_id: format!("internal-forwarded-{user_id}"),
|
||||
provider: AuthProvider::Password,
|
||||
roles: vec!["user".to_string()],
|
||||
token_version: 0,
|
||||
phone_verified: false,
|
||||
binding_status: BindingStatus::Active,
|
||||
display_name: None,
|
||||
},
|
||||
state.auth_jwt_config(),
|
||||
OffsetDateTime::now_utc(),
|
||||
)
|
||||
.ok()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{RefreshSessionToken, extract_bearer_token};
|
||||
use super::{
|
||||
INTERNAL_API_SECRET_HEADER, INTERNAL_AUTH_USER_ID_HEADER, RefreshSessionToken,
|
||||
extract_bearer_token, try_build_internal_forwarded_claims,
|
||||
};
|
||||
use axum::{
|
||||
http::{HeaderMap, HeaderValue, StatusCode, header::AUTHORIZATION},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use crate::{config::AppConfig, state::AppState};
|
||||
|
||||
#[test]
|
||||
fn extract_bearer_token_accepts_standard_header() {
|
||||
@@ -209,4 +272,26 @@ mod tests {
|
||||
|
||||
assert_eq!(token.token(), "refresh-token-01");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_forwarded_claims_require_matching_secret() {
|
||||
let mut config = AppConfig::default();
|
||||
config.internal_api_secret = Some("bridge-secret".to_string());
|
||||
let state = AppState::new(config).expect("state should build");
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
INTERNAL_AUTH_USER_ID_HEADER,
|
||||
HeaderValue::from_static("user_forwarded_01"),
|
||||
);
|
||||
headers.insert(
|
||||
INTERNAL_API_SECRET_HEADER,
|
||||
HeaderValue::from_static("bridge-secret"),
|
||||
);
|
||||
|
||||
let claims =
|
||||
try_build_internal_forwarded_claims(&state, &headers).expect("claims should resolve");
|
||||
|
||||
assert_eq!(claims.user_id(), "user_forwarded_01");
|
||||
assert_eq!(claims.token_version(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
653
server-rs/crates/api-server/src/big_fish.rs
Normal file
653
server-rs/crates/api-server/src/big_fish.rs
Normal file
@@ -0,0 +1,653 @@
|
||||
use axum::{
|
||||
Json,
|
||||
extract::{Extension, Path, State, rejection::JsonRejection},
|
||||
http::{HeaderName, StatusCode, header},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use serde_json::{Value, json};
|
||||
use shared_contracts::big_fish::{
|
||||
BigFishActionResponse, BigFishAgentMessageResponse, BigFishAnchorItemResponse,
|
||||
BigFishAnchorPackResponse, BigFishAssetCoverageResponse, BigFishAssetSlotResponse,
|
||||
BigFishBackgroundBlueprintResponse, BigFishGameDraftResponse, BigFishLevelBlueprintResponse,
|
||||
BigFishRuntimeEntityResponse, BigFishRuntimeParamsResponse, BigFishRuntimeSnapshotResponse,
|
||||
BigFishRunResponse, BigFishSessionResponse, BigFishSessionSnapshotResponse,
|
||||
BigFishVector2Response, CreateBigFishSessionRequest, ExecuteBigFishActionRequest,
|
||||
SendBigFishMessageRequest, SubmitBigFishInputRequest,
|
||||
};
|
||||
use shared_kernel::build_prefixed_uuid_id;
|
||||
use spacetime_client::{
|
||||
BigFishAgentMessageRecord, BigFishAnchorItemRecord, BigFishAnchorPackRecord,
|
||||
BigFishAssetCoverageRecord, BigFishAssetGenerateRecordInput, BigFishAssetSlotRecord,
|
||||
BigFishBackgroundBlueprintRecord, BigFishGameDraftRecord, BigFishLevelBlueprintRecord,
|
||||
BigFishMessageSubmitRecordInput, BigFishRunInputSubmitRecordInput, BigFishRunStartRecordInput,
|
||||
BigFishRuntimeEntityRecord, BigFishRuntimeParamsRecord, BigFishRuntimeRecord,
|
||||
BigFishSessionCreateRecordInput, BigFishSessionRecord, BigFishVector2Record,
|
||||
SpacetimeClientError,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
api_response::json_success_body, auth::AuthenticatedAccessToken, http_error::AppError,
|
||||
request_context::RequestContext, state::AppState,
|
||||
};
|
||||
|
||||
pub async fn create_big_fish_session(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<CreateBigFishSessionRequest>, JsonRejection>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let Json(payload) = payload.map_err(|error| {
|
||||
big_fish_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "big-fish",
|
||||
"message": error.body_text(),
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
|
||||
let seed_text = payload.seed_text.unwrap_or_default().trim().to_string();
|
||||
let session = state
|
||||
.spacetime_client()
|
||||
.create_big_fish_session(BigFishSessionCreateRecordInput {
|
||||
session_id: build_prefixed_uuid_id("big-fish-session-"),
|
||||
owner_user_id: authenticated.claims().user_id().to_string(),
|
||||
seed_text: seed_text.clone(),
|
||||
welcome_message_id: build_prefixed_uuid_id("big-fish-message-"),
|
||||
welcome_message_text: build_big_fish_welcome_text(&seed_text),
|
||||
created_at_micros: current_utc_micros(),
|
||||
})
|
||||
.await
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BigFishSessionResponse {
|
||||
session: map_big_fish_session_response(session),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn get_big_fish_session(
|
||||
State(state): State<AppState>,
|
||||
Path(session_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
ensure_non_empty(&request_context, &session_id, "sessionId")?;
|
||||
|
||||
let session = state
|
||||
.spacetime_client()
|
||||
.get_big_fish_session(session_id, authenticated.claims().user_id().to_string())
|
||||
.await
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BigFishSessionResponse {
|
||||
session: map_big_fish_session_response(session),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn submit_big_fish_message(
|
||||
State(state): State<AppState>,
|
||||
Path(session_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<SendBigFishMessageRequest>, JsonRejection>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let Json(payload) = payload.map_err(|error| {
|
||||
big_fish_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "big-fish",
|
||||
"message": error.body_text(),
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
ensure_non_empty(&request_context, &session_id, "sessionId")?;
|
||||
|
||||
let client_message_id = payload.client_message_id.trim().to_string();
|
||||
let message_text = payload.text.trim().to_string();
|
||||
if client_message_id.is_empty() || message_text.is_empty() {
|
||||
return Err(big_fish_bad_request(
|
||||
&request_context,
|
||||
"clientMessageId and text are required",
|
||||
));
|
||||
}
|
||||
|
||||
let session = state
|
||||
.spacetime_client()
|
||||
.submit_big_fish_message(BigFishMessageSubmitRecordInput {
|
||||
session_id,
|
||||
owner_user_id: authenticated.claims().user_id().to_string(),
|
||||
user_message_id: client_message_id,
|
||||
user_message_text: message_text,
|
||||
assistant_message_id: build_prefixed_uuid_id("big-fish-message-"),
|
||||
submitted_at_micros: current_utc_micros(),
|
||||
})
|
||||
.await
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BigFishSessionResponse {
|
||||
session: map_big_fish_session_response(session),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn stream_big_fish_message(
|
||||
State(state): State<AppState>,
|
||||
Path(session_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<SendBigFishMessageRequest>, JsonRejection>,
|
||||
) -> Result<Response, Response> {
|
||||
let Json(payload) = payload.map_err(|error| {
|
||||
big_fish_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "big-fish",
|
||||
"message": error.body_text(),
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
ensure_non_empty(&request_context, &session_id, "sessionId")?;
|
||||
|
||||
let owner_user_id = authenticated.claims().user_id().to_string();
|
||||
let session = state
|
||||
.spacetime_client()
|
||||
.submit_big_fish_message(BigFishMessageSubmitRecordInput {
|
||||
session_id,
|
||||
owner_user_id,
|
||||
user_message_id: payload.client_message_id.trim().to_string(),
|
||||
user_message_text: payload.text.trim().to_string(),
|
||||
assistant_message_id: build_prefixed_uuid_id("big-fish-message-"),
|
||||
submitted_at_micros: current_utc_micros(),
|
||||
})
|
||||
.await
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
let session_response = map_big_fish_session_response(session);
|
||||
let reply_text = session_response
|
||||
.last_assistant_reply
|
||||
.clone()
|
||||
.unwrap_or_else(|| "锚点已更新。".to_string());
|
||||
let mut sse_body = String::new();
|
||||
append_sse_event(&request_context, &mut sse_body, "reply_delta", &json!({ "text": reply_text }))?;
|
||||
append_sse_event(&request_context, &mut sse_body, "session", &json!({ "session": session_response }))?;
|
||||
append_sse_event(&request_context, &mut sse_body, "done", &json!({ "ok": true }))?;
|
||||
Ok(build_event_stream_response(sse_body))
|
||||
}
|
||||
|
||||
pub async fn execute_big_fish_action(
|
||||
State(state): State<AppState>,
|
||||
Path(session_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<ExecuteBigFishActionRequest>, JsonRejection>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let Json(payload) = payload.map_err(|error| {
|
||||
big_fish_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "big-fish",
|
||||
"message": error.body_text(),
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
ensure_non_empty(&request_context, &session_id, "sessionId")?;
|
||||
|
||||
let owner_user_id = authenticated.claims().user_id().to_string();
|
||||
let now = current_utc_micros();
|
||||
let session = match payload.action.trim() {
|
||||
"big_fish_compile_draft" => {
|
||||
state
|
||||
.spacetime_client()
|
||||
.compile_big_fish_draft(session_id, owner_user_id, now)
|
||||
.await
|
||||
}
|
||||
"big_fish_generate_level_main_image" => {
|
||||
state
|
||||
.spacetime_client()
|
||||
.generate_big_fish_asset(BigFishAssetGenerateRecordInput {
|
||||
session_id,
|
||||
owner_user_id,
|
||||
asset_kind: "level_main_image".to_string(),
|
||||
level: payload.level,
|
||||
motion_key: None,
|
||||
generated_at_micros: now,
|
||||
})
|
||||
.await
|
||||
}
|
||||
"big_fish_generate_level_motion" => {
|
||||
state
|
||||
.spacetime_client()
|
||||
.generate_big_fish_asset(BigFishAssetGenerateRecordInput {
|
||||
session_id,
|
||||
owner_user_id,
|
||||
asset_kind: "level_motion".to_string(),
|
||||
level: payload.level,
|
||||
motion_key: payload.motion_key,
|
||||
generated_at_micros: now,
|
||||
})
|
||||
.await
|
||||
}
|
||||
"big_fish_generate_stage_background" => {
|
||||
state
|
||||
.spacetime_client()
|
||||
.generate_big_fish_asset(BigFishAssetGenerateRecordInput {
|
||||
session_id,
|
||||
owner_user_id,
|
||||
asset_kind: "stage_background".to_string(),
|
||||
level: None,
|
||||
motion_key: None,
|
||||
generated_at_micros: now,
|
||||
})
|
||||
.await
|
||||
}
|
||||
"big_fish_publish_game" => {
|
||||
state
|
||||
.spacetime_client()
|
||||
.publish_big_fish_game(session_id, owner_user_id, now)
|
||||
.await
|
||||
}
|
||||
other => {
|
||||
return Err(big_fish_bad_request(
|
||||
&request_context,
|
||||
format!("action `{other}` is not supported").as_str(),
|
||||
));
|
||||
}
|
||||
}
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BigFishActionResponse {
|
||||
session: map_big_fish_session_response(session),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn start_big_fish_run(
|
||||
State(state): State<AppState>,
|
||||
Path(session_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
ensure_non_empty(&request_context, &session_id, "sessionId")?;
|
||||
|
||||
let run = state
|
||||
.spacetime_client()
|
||||
.start_big_fish_run(BigFishRunStartRecordInput {
|
||||
run_id: build_prefixed_uuid_id("big-fish-run-"),
|
||||
session_id,
|
||||
owner_user_id: authenticated.claims().user_id().to_string(),
|
||||
started_at_micros: current_utc_micros(),
|
||||
})
|
||||
.await
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BigFishRunResponse {
|
||||
run: map_big_fish_runtime_response(run),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn get_big_fish_run(
|
||||
State(state): State<AppState>,
|
||||
Path(run_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
ensure_non_empty(&request_context, &run_id, "runId")?;
|
||||
|
||||
let run = state
|
||||
.spacetime_client()
|
||||
.get_big_fish_run(run_id, authenticated.claims().user_id().to_string())
|
||||
.await
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BigFishRunResponse {
|
||||
run: map_big_fish_runtime_response(run),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn submit_big_fish_input(
|
||||
State(state): State<AppState>,
|
||||
Path(run_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<SubmitBigFishInputRequest>, JsonRejection>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let Json(payload) = payload.map_err(|error| {
|
||||
big_fish_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "big-fish",
|
||||
"message": error.body_text(),
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
ensure_non_empty(&request_context, &run_id, "runId")?;
|
||||
|
||||
let run = state
|
||||
.spacetime_client()
|
||||
.submit_big_fish_input(BigFishRunInputSubmitRecordInput {
|
||||
run_id,
|
||||
owner_user_id: authenticated.claims().user_id().to_string(),
|
||||
input_x: payload.x,
|
||||
input_y: payload.y,
|
||||
submitted_at_micros: current_utc_micros(),
|
||||
})
|
||||
.await
|
||||
.map_err(|error| big_fish_error_response(&request_context, map_big_fish_client_error(error)))?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BigFishRunResponse {
|
||||
run: map_big_fish_runtime_response(run),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
fn map_big_fish_session_response(session: BigFishSessionRecord) -> BigFishSessionSnapshotResponse {
|
||||
BigFishSessionSnapshotResponse {
|
||||
session_id: session.session_id,
|
||||
current_turn: session.current_turn,
|
||||
progress_percent: session.progress_percent,
|
||||
stage: session.stage,
|
||||
anchor_pack: map_big_fish_anchor_pack_response(session.anchor_pack),
|
||||
draft: session.draft.map(map_big_fish_draft_response),
|
||||
asset_slots: session
|
||||
.asset_slots
|
||||
.into_iter()
|
||||
.map(map_big_fish_asset_slot_response)
|
||||
.collect(),
|
||||
asset_coverage: map_big_fish_asset_coverage_response(session.asset_coverage),
|
||||
messages: session
|
||||
.messages
|
||||
.into_iter()
|
||||
.map(map_big_fish_agent_message_response)
|
||||
.collect(),
|
||||
last_assistant_reply: session.last_assistant_reply,
|
||||
publish_ready: session.publish_ready,
|
||||
updated_at: session.updated_at,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_anchor_pack_response(anchor_pack: BigFishAnchorPackRecord) -> BigFishAnchorPackResponse {
|
||||
BigFishAnchorPackResponse {
|
||||
gameplay_promise: map_big_fish_anchor_item_response(anchor_pack.gameplay_promise),
|
||||
ecology_visual_theme: map_big_fish_anchor_item_response(anchor_pack.ecology_visual_theme),
|
||||
growth_ladder: map_big_fish_anchor_item_response(anchor_pack.growth_ladder),
|
||||
risk_tempo: map_big_fish_anchor_item_response(anchor_pack.risk_tempo),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_anchor_item_response(anchor: BigFishAnchorItemRecord) -> BigFishAnchorItemResponse {
|
||||
BigFishAnchorItemResponse {
|
||||
key: anchor.key,
|
||||
label: anchor.label,
|
||||
value: anchor.value,
|
||||
status: anchor.status,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_draft_response(draft: BigFishGameDraftRecord) -> BigFishGameDraftResponse {
|
||||
BigFishGameDraftResponse {
|
||||
title: draft.title,
|
||||
subtitle: draft.subtitle,
|
||||
core_fun: draft.core_fun,
|
||||
ecology_theme: draft.ecology_theme,
|
||||
levels: draft
|
||||
.levels
|
||||
.into_iter()
|
||||
.map(map_big_fish_level_response)
|
||||
.collect(),
|
||||
background: map_big_fish_background_response(draft.background),
|
||||
runtime_params: map_big_fish_runtime_params_response(draft.runtime_params),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_level_response(level: BigFishLevelBlueprintRecord) -> BigFishLevelBlueprintResponse {
|
||||
BigFishLevelBlueprintResponse {
|
||||
level: level.level,
|
||||
name: level.name,
|
||||
one_line_fantasy: level.one_line_fantasy,
|
||||
silhouette_direction: level.silhouette_direction,
|
||||
size_ratio: level.size_ratio,
|
||||
visual_prompt_seed: level.visual_prompt_seed,
|
||||
motion_prompt_seed: level.motion_prompt_seed,
|
||||
merge_source_level: level.merge_source_level,
|
||||
prey_window: level.prey_window,
|
||||
threat_window: level.threat_window,
|
||||
is_final_level: level.is_final_level,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_background_response(
|
||||
background: BigFishBackgroundBlueprintRecord,
|
||||
) -> BigFishBackgroundBlueprintResponse {
|
||||
BigFishBackgroundBlueprintResponse {
|
||||
theme: background.theme,
|
||||
color_mood: background.color_mood,
|
||||
foreground_hints: background.foreground_hints,
|
||||
midground_composition: background.midground_composition,
|
||||
background_depth: background.background_depth,
|
||||
safe_play_area_hint: background.safe_play_area_hint,
|
||||
spawn_edge_hint: background.spawn_edge_hint,
|
||||
background_prompt_seed: background.background_prompt_seed,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_runtime_params_response(
|
||||
params: BigFishRuntimeParamsRecord,
|
||||
) -> BigFishRuntimeParamsResponse {
|
||||
BigFishRuntimeParamsResponse {
|
||||
level_count: params.level_count,
|
||||
merge_count_per_upgrade: params.merge_count_per_upgrade,
|
||||
spawn_target_count: params.spawn_target_count,
|
||||
leader_move_speed: params.leader_move_speed,
|
||||
follower_catch_up_speed: params.follower_catch_up_speed,
|
||||
offscreen_cull_seconds: params.offscreen_cull_seconds,
|
||||
prey_spawn_delta_levels: params.prey_spawn_delta_levels,
|
||||
threat_spawn_delta_levels: params.threat_spawn_delta_levels,
|
||||
win_level: params.win_level,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_asset_slot_response(slot: BigFishAssetSlotRecord) -> BigFishAssetSlotResponse {
|
||||
BigFishAssetSlotResponse {
|
||||
slot_id: slot.slot_id,
|
||||
asset_kind: slot.asset_kind,
|
||||
level: slot.level,
|
||||
motion_key: slot.motion_key,
|
||||
status: slot.status,
|
||||
asset_url: slot.asset_url,
|
||||
prompt_snapshot: slot.prompt_snapshot,
|
||||
updated_at: slot.updated_at,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_asset_coverage_response(
|
||||
coverage: BigFishAssetCoverageRecord,
|
||||
) -> BigFishAssetCoverageResponse {
|
||||
BigFishAssetCoverageResponse {
|
||||
level_main_image_ready_count: coverage.level_main_image_ready_count,
|
||||
level_motion_ready_count: coverage.level_motion_ready_count,
|
||||
background_ready: coverage.background_ready,
|
||||
required_level_count: coverage.required_level_count,
|
||||
publish_ready: coverage.publish_ready,
|
||||
blockers: coverage.blockers,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_agent_message_response(
|
||||
message: BigFishAgentMessageRecord,
|
||||
) -> BigFishAgentMessageResponse {
|
||||
BigFishAgentMessageResponse {
|
||||
id: message.message_id,
|
||||
role: message.role,
|
||||
kind: message.kind,
|
||||
text: message.text,
|
||||
created_at: message.created_at,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_runtime_response(run: BigFishRuntimeRecord) -> BigFishRuntimeSnapshotResponse {
|
||||
BigFishRuntimeSnapshotResponse {
|
||||
run_id: run.run_id,
|
||||
session_id: run.session_id,
|
||||
status: run.status,
|
||||
tick: run.tick,
|
||||
player_level: run.player_level,
|
||||
win_level: run.win_level,
|
||||
leader_entity_id: run.leader_entity_id,
|
||||
owned_entities: run
|
||||
.owned_entities
|
||||
.into_iter()
|
||||
.map(map_big_fish_entity_response)
|
||||
.collect(),
|
||||
wild_entities: run
|
||||
.wild_entities
|
||||
.into_iter()
|
||||
.map(map_big_fish_entity_response)
|
||||
.collect(),
|
||||
camera_center: map_big_fish_vector_response(run.camera_center),
|
||||
last_input: map_big_fish_vector_response(run.last_input),
|
||||
event_log: run.event_log,
|
||||
updated_at: run.updated_at,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_entity_response(entity: BigFishRuntimeEntityRecord) -> BigFishRuntimeEntityResponse {
|
||||
BigFishRuntimeEntityResponse {
|
||||
entity_id: entity.entity_id,
|
||||
level: entity.level,
|
||||
position: map_big_fish_vector_response(entity.position),
|
||||
radius: entity.radius,
|
||||
offscreen_seconds: entity.offscreen_seconds,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_big_fish_vector_response(vector: BigFishVector2Record) -> BigFishVector2Response {
|
||||
BigFishVector2Response {
|
||||
x: vector.x,
|
||||
y: vector.y,
|
||||
}
|
||||
}
|
||||
|
||||
fn build_big_fish_welcome_text(seed_text: &str) -> String {
|
||||
if seed_text.trim().is_empty() {
|
||||
return "我会先帮你确定大鱼吃小鱼的核心锚点。可以从主题生态、成长阶梯或风险节奏开始。".to_string();
|
||||
}
|
||||
"我已经收到你的玩法起点,会先把它整理成锚点并准备结果页草稿。".to_string()
|
||||
}
|
||||
|
||||
fn ensure_non_empty(
|
||||
request_context: &RequestContext,
|
||||
value: &str,
|
||||
field_name: &str,
|
||||
) -> Result<(), Response> {
|
||||
if value.trim().is_empty() {
|
||||
return Err(big_fish_bad_request(
|
||||
request_context,
|
||||
format!("{field_name} is required").as_str(),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn big_fish_bad_request(request_context: &RequestContext, message: &str) -> Response {
|
||||
big_fish_error_response(
|
||||
request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "big-fish",
|
||||
"message": message,
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
fn append_sse_event(
|
||||
request_context: &RequestContext,
|
||||
body: &mut String,
|
||||
event: &str,
|
||||
payload: &Value,
|
||||
) -> Result<(), Response> {
|
||||
let payload_text = serde_json::to_string(payload).map_err(|error| {
|
||||
big_fish_error_response(
|
||||
request_context,
|
||||
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR).with_details(json!({
|
||||
"provider": "big-fish",
|
||||
"message": format!("SSE payload 序列化失败:{error}"),
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
body.push_str("event: ");
|
||||
body.push_str(event);
|
||||
body.push('\n');
|
||||
body.push_str("data: ");
|
||||
body.push_str(&payload_text);
|
||||
body.push_str("\n\n");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_event_stream_response(body: String) -> Response {
|
||||
(
|
||||
[
|
||||
(header::CONTENT_TYPE, "text/event-stream; charset=utf-8"),
|
||||
(header::CACHE_CONTROL, "no-cache"),
|
||||
(HeaderName::from_static("x-accel-buffering"), "no"),
|
||||
],
|
||||
body,
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
|
||||
fn map_big_fish_client_error(error: SpacetimeClientError) -> AppError {
|
||||
let status = match &error {
|
||||
SpacetimeClientError::Procedure(message)
|
||||
if message.contains("big_fish_creation_session 不存在")
|
||||
|| message.contains("big_fish_runtime_run 不存在") =>
|
||||
{
|
||||
StatusCode::NOT_FOUND
|
||||
}
|
||||
SpacetimeClientError::Procedure(message)
|
||||
if message.contains("不能为空")
|
||||
|| message.contains("尚未编译")
|
||||
|| message.contains("不允许")
|
||||
|| message.contains("非法")
|
||||
|| message.contains("缺少") =>
|
||||
{
|
||||
StatusCode::BAD_REQUEST
|
||||
}
|
||||
SpacetimeClientError::Runtime(_) => StatusCode::BAD_REQUEST,
|
||||
_ => StatusCode::BAD_GATEWAY,
|
||||
};
|
||||
|
||||
AppError::from_status(status).with_details(json!({
|
||||
"provider": "spacetimedb",
|
||||
"message": error.to_string(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn big_fish_error_response(request_context: &RequestContext, error: AppError) -> Response {
|
||||
error.into_response_with_context(Some(request_context))
|
||||
}
|
||||
|
||||
fn current_utc_micros() -> i64 {
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
let duration = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("system clock should be after unix epoch");
|
||||
i64::try_from(duration.as_micros()).expect("current unix micros should fit in i64")
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use platform_llm::{
|
||||
};
|
||||
|
||||
const DEFAULT_LLM_MODEL: &str = "doubao-1-5-pro-32k-character-250715";
|
||||
const DEFAULT_INTERNAL_API_SECRET: &str = "genarrative-dev-internal-bridge";
|
||||
|
||||
// 集中管理 api-server 的启动配置,避免入口层直接散落环境变量解析逻辑。
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -13,6 +14,7 @@ pub struct AppConfig {
|
||||
pub bind_host: String,
|
||||
pub bind_port: u16,
|
||||
pub log_filter: String,
|
||||
pub internal_api_secret: Option<String>,
|
||||
pub jwt_issuer: String,
|
||||
pub jwt_secret: String,
|
||||
pub jwt_access_token_ttl_seconds: u64,
|
||||
@@ -62,6 +64,7 @@ impl Default for AppConfig {
|
||||
bind_host: "127.0.0.1".to_string(),
|
||||
bind_port: 3000,
|
||||
log_filter: "info,tower_http=info".to_string(),
|
||||
internal_api_secret: Some(DEFAULT_INTERNAL_API_SECRET.to_string()),
|
||||
jwt_issuer: "https://auth.genarrative.local".to_string(),
|
||||
jwt_secret: "genarrative-dev-secret".to_string(),
|
||||
jwt_access_token_ttl_seconds: 2 * 60 * 60,
|
||||
@@ -130,6 +133,9 @@ impl AppConfig {
|
||||
config.log_filter = log_filter;
|
||||
}
|
||||
|
||||
config.internal_api_secret =
|
||||
read_first_non_empty_env(&["GENARRATIVE_INTERNAL_API_SECRET"]);
|
||||
|
||||
if let Some(jwt_issuer) =
|
||||
read_first_non_empty_env(&["GENARRATIVE_JWT_ISSUER", "JWT_ISSUER"])
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ mod auth;
|
||||
mod auth_me;
|
||||
mod auth_session;
|
||||
mod auth_sessions;
|
||||
mod big_fish;
|
||||
mod config;
|
||||
mod custom_world;
|
||||
mod custom_world_ai;
|
||||
@@ -18,6 +19,7 @@ mod logout;
|
||||
mod logout_all;
|
||||
mod password_entry;
|
||||
mod phone_auth;
|
||||
mod puzzle;
|
||||
mod refresh_session;
|
||||
mod request_context;
|
||||
mod response_headers;
|
||||
|
||||
1394
server-rs/crates/api-server/src/puzzle.rs
Normal file
1394
server-rs/crates/api-server/src/puzzle.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
use axum::{
|
||||
Json,
|
||||
extract::{Extension, State},
|
||||
extract::{Extension, Path, State, rejection::JsonRejection},
|
||||
http::StatusCode,
|
||||
response::Response,
|
||||
};
|
||||
@@ -54,6 +54,91 @@ pub async fn resolve_runtime_story_state(
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn get_runtime_story_state(
|
||||
State(_state): State<AppState>,
|
||||
Path(session_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(_authenticated): Extension<AuthenticatedAccessToken>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let session_id = normalize_required_string(session_id.as_str()).ok_or_else(|| {
|
||||
runtime_story_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "runtime-story",
|
||||
"field": "sessionId",
|
||||
"message": "sessionId 不能为空",
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
build_runtime_story_state_response(&session_id, None, build_runtime_story_empty_snapshot(&session_id)),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn resolve_runtime_story_action(
|
||||
State(_state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(_authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<Value>, JsonRejection>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let payload = optional_runtime_story_payload(payload)?;
|
||||
let session_id = read_payload_session_id(&payload).ok_or_else(|| {
|
||||
runtime_story_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "runtime-story",
|
||||
"field": "sessionId",
|
||||
"message": "sessionId 不能为空",
|
||||
})),
|
||||
)
|
||||
})?;
|
||||
let client_version = read_u32_field(&payload, "clientVersion");
|
||||
let snapshot = read_payload_snapshot(&payload)
|
||||
.unwrap_or_else(|| build_runtime_story_empty_snapshot(&session_id));
|
||||
let mut response = build_runtime_story_state_response(&session_id, client_version, snapshot);
|
||||
response.presentation.action_text = read_runtime_story_action_text(&payload).unwrap_or_default();
|
||||
|
||||
Ok(json_success_body(Some(&request_context), response))
|
||||
}
|
||||
|
||||
pub async fn generate_runtime_story_initial(
|
||||
State(_state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(_authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<Value>, JsonRejection>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let payload = optional_runtime_story_payload(payload)?;
|
||||
let session_id = read_payload_session_id(&payload).unwrap_or_else(|| "runtime-main".to_string());
|
||||
let client_version = read_u32_field(&payload, "clientVersion");
|
||||
let snapshot = read_payload_snapshot(&payload)
|
||||
.unwrap_or_else(|| build_runtime_story_empty_snapshot(&session_id));
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
build_runtime_story_state_response(&session_id, client_version, snapshot),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn generate_runtime_story_continue(
|
||||
State(_state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(_authenticated): Extension<AuthenticatedAccessToken>,
|
||||
payload: Result<Json<Value>, JsonRejection>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let payload = optional_runtime_story_payload(payload)?;
|
||||
let session_id = read_payload_session_id(&payload).unwrap_or_else(|| "runtime-main".to_string());
|
||||
let client_version = read_u32_field(&payload, "clientVersion");
|
||||
let snapshot = read_payload_snapshot(&payload)
|
||||
.unwrap_or_else(|| build_runtime_story_empty_snapshot(&session_id));
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
build_runtime_story_state_response(&session_id, client_version, snapshot),
|
||||
))
|
||||
}
|
||||
|
||||
fn build_runtime_story_state_response(
|
||||
requested_session_id: &str,
|
||||
client_version: Option<u32>,
|
||||
@@ -107,6 +192,61 @@ fn build_runtime_story_state_response(
|
||||
}
|
||||
}
|
||||
|
||||
fn optional_runtime_story_payload(
|
||||
payload: Result<Json<Value>, JsonRejection>,
|
||||
) -> Result<Value, Response> {
|
||||
match payload {
|
||||
Ok(Json(value)) => Ok(value),
|
||||
Err(error) if error.status() == StatusCode::UNSUPPORTED_MEDIA_TYPE => Ok(json!({})),
|
||||
Err(error) if error.status() == StatusCode::BAD_REQUEST => Ok(json!({})),
|
||||
Err(error) => Err(AppError::from_status(StatusCode::BAD_REQUEST)
|
||||
.with_details(json!({
|
||||
"provider": "runtime-story",
|
||||
"message": error.body_text(),
|
||||
}))
|
||||
.into_response_with_context(None)),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_payload_session_id(payload: &Value) -> Option<String> {
|
||||
read_required_string_field(payload, "sessionId")
|
||||
.or_else(|| read_field(payload, "action").and_then(|action| read_required_string_field(action, "sessionId")))
|
||||
.or_else(|| read_field(payload, "snapshot").and_then(|snapshot| {
|
||||
read_object_field(snapshot, "gameState").and_then(read_runtime_session_id)
|
||||
}))
|
||||
}
|
||||
|
||||
fn read_payload_snapshot(payload: &Value) -> Option<RuntimeStorySnapshotPayload> {
|
||||
let snapshot = read_field(payload, "snapshot")?.clone();
|
||||
serde_json::from_value(snapshot).ok()
|
||||
}
|
||||
|
||||
fn read_runtime_story_action_text(payload: &Value) -> Option<String> {
|
||||
let action = read_field(payload, "action")?;
|
||||
read_optional_string_field(action, "functionId")
|
||||
.or_else(|| read_optional_string_field(action, "type"))
|
||||
}
|
||||
|
||||
fn build_runtime_story_empty_snapshot(session_id: &str) -> RuntimeStorySnapshotPayload {
|
||||
RuntimeStorySnapshotPayload {
|
||||
saved_at: time::OffsetDateTime::now_utc()
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.unwrap_or_else(|_| "1970-01-01T00:00:00Z".to_string()),
|
||||
bottom_tab: "adventure".to_string(),
|
||||
game_state: json!({
|
||||
"runtimeSessionId": session_id,
|
||||
"runtimeActionVersion": 0,
|
||||
"playerHp": 1,
|
||||
"playerMaxHp": 1,
|
||||
"playerMana": 0,
|
||||
"playerMaxMana": 1,
|
||||
"inBattle": false,
|
||||
"npcInteractionActive": false
|
||||
}),
|
||||
current_story: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn build_runtime_story_companions(game_state: &Value) -> Vec<RuntimeStoryCompanionViewModel> {
|
||||
read_array_field(game_state, "companions")
|
||||
.into_iter()
|
||||
|
||||
15
server-rs/crates/module-big-fish/Cargo.toml
Normal file
15
server-rs/crates/module-big-fish/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "module-big-fish"
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
spacetime-types = ["dep:spacetimedb"]
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
shared-kernel = { path = "../shared-kernel" }
|
||||
spacetimedb = { workspace = true, optional = true }
|
||||
1385
server-rs/crates/module-big-fish/src/lib.rs
Normal file
1385
server-rs/crates/module-big-fish/src/lib.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -153,6 +153,7 @@ pub enum CustomWorldFieldError {
|
||||
MissingMessageText,
|
||||
MissingOperationId,
|
||||
MissingPhaseLabel,
|
||||
MissingAction,
|
||||
InvalidProgressPercent,
|
||||
MissingCardId,
|
||||
MissingCardTitle,
|
||||
@@ -290,6 +291,7 @@ pub struct CustomWorldAgentSessionSnapshot {
|
||||
pub lock_state_json: Option<String>,
|
||||
pub draft_profile_json: Option<String>,
|
||||
pub last_assistant_reply: Option<String>,
|
||||
pub publish_gate_json: Option<String>,
|
||||
pub result_preview_json: Option<String>,
|
||||
pub pending_clarifications_json: String,
|
||||
pub quality_findings_json: String,
|
||||
@@ -297,6 +299,7 @@ pub struct CustomWorldAgentSessionSnapshot {
|
||||
pub recommended_replies_json: String,
|
||||
pub asset_coverage_json: String,
|
||||
pub checkpoints_json: String,
|
||||
pub supported_actions_json: String,
|
||||
pub messages: Vec<CustomWorldAgentMessageSnapshot>,
|
||||
pub draft_cards: Vec<CustomWorldDraftCardSnapshot>,
|
||||
pub operations: Vec<CustomWorldAgentOperationSnapshot>,
|
||||
@@ -425,6 +428,126 @@ pub struct CustomWorldAgentOperationProcedureResult {
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldWorksListInput {
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldPublishBlockerSnapshot {
|
||||
pub blocker_id: String,
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldPublishGateSnapshot {
|
||||
pub profile_id: String,
|
||||
pub blockers: Vec<CustomWorldPublishBlockerSnapshot>,
|
||||
pub blocker_count: u32,
|
||||
pub publish_ready: bool,
|
||||
pub can_enter_world: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldWorkSummarySnapshot {
|
||||
pub work_id: String,
|
||||
pub source_type: String,
|
||||
pub status: String,
|
||||
pub title: String,
|
||||
pub subtitle: String,
|
||||
pub summary: String,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub cover_render_mode: Option<String>,
|
||||
pub cover_character_image_srcs_json: String,
|
||||
pub updated_at_micros: i64,
|
||||
pub published_at_micros: Option<i64>,
|
||||
pub stage: Option<RpgAgentStage>,
|
||||
pub stage_label: Option<String>,
|
||||
pub playable_npc_count: u32,
|
||||
pub landmark_count: u32,
|
||||
pub role_visual_ready_count: Option<u32>,
|
||||
pub role_animation_ready_count: Option<u32>,
|
||||
pub role_asset_summary_label: Option<String>,
|
||||
pub session_id: Option<String>,
|
||||
pub profile_id: Option<String>,
|
||||
pub can_resume: bool,
|
||||
pub can_enter_world: bool,
|
||||
pub blocker_count: u32,
|
||||
pub publish_ready: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldWorksListResult {
|
||||
pub ok: bool,
|
||||
pub items: Vec<CustomWorldWorkSummarySnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldAgentCardDetailGetInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub card_id: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldDraftCardDetailSectionSnapshot {
|
||||
pub section_id: String,
|
||||
pub label: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldDraftCardDetailSnapshot {
|
||||
pub card_id: String,
|
||||
pub kind: RpgAgentDraftCardKind,
|
||||
pub title: String,
|
||||
pub sections: Vec<CustomWorldDraftCardDetailSectionSnapshot>,
|
||||
pub linked_ids_json: String,
|
||||
pub locked: bool,
|
||||
pub editable: bool,
|
||||
pub editable_section_ids_json: String,
|
||||
pub warning_messages_json: String,
|
||||
pub asset_status: Option<CustomWorldRoleAssetStatus>,
|
||||
pub asset_status_label: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldDraftCardDetailResult {
|
||||
pub ok: bool,
|
||||
pub card: Option<CustomWorldDraftCardDetailSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldAgentActionExecuteInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub operation_id: String,
|
||||
pub action: String,
|
||||
pub payload_json: Option<String>,
|
||||
pub submitted_at_micros: i64,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldAgentActionExecuteResult {
|
||||
pub ok: bool,
|
||||
pub operation: Option<CustomWorldAgentOperationSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CustomWorldPublishedProfileCompileInput {
|
||||
@@ -941,6 +1064,52 @@ pub fn validate_custom_world_agent_operation_get_input(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_custom_world_works_list_input(
|
||||
input: &CustomWorldWorksListInput,
|
||||
) -> Result<(), CustomWorldFieldError> {
|
||||
if input.owner_user_id.trim().is_empty() {
|
||||
return Err(CustomWorldFieldError::MissingOwnerUserId);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_custom_world_agent_card_detail_get_input(
|
||||
input: &CustomWorldAgentCardDetailGetInput,
|
||||
) -> Result<(), CustomWorldFieldError> {
|
||||
if input.session_id.trim().is_empty() {
|
||||
return Err(CustomWorldFieldError::MissingSessionId);
|
||||
}
|
||||
if input.owner_user_id.trim().is_empty() {
|
||||
return Err(CustomWorldFieldError::MissingOwnerUserId);
|
||||
}
|
||||
if input.card_id.trim().is_empty() {
|
||||
return Err(CustomWorldFieldError::MissingCardId);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_custom_world_agent_action_execute_input(
|
||||
input: &CustomWorldAgentActionExecuteInput,
|
||||
) -> Result<(), CustomWorldFieldError> {
|
||||
validate_custom_world_agent_operation_get_input(&CustomWorldAgentOperationGetInput {
|
||||
session_id: input.session_id.clone(),
|
||||
owner_user_id: input.owner_user_id.clone(),
|
||||
operation_id: input.operation_id.clone(),
|
||||
})?;
|
||||
if input.action.trim().is_empty() {
|
||||
return Err(CustomWorldFieldError::MissingAction);
|
||||
}
|
||||
if let Some(payload_json) = input.payload_json.as_deref() {
|
||||
if !payload_json.trim().is_empty() {
|
||||
ensure_json_object(payload_json)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_custom_world_agent_message_fields(
|
||||
message_id: &str,
|
||||
session_id: &str,
|
||||
@@ -1321,6 +1490,7 @@ impl fmt::Display for CustomWorldFieldError {
|
||||
Self::MissingPhaseLabel => {
|
||||
f.write_str("custom_world_agent_operation.phase_label 不能为空")
|
||||
}
|
||||
Self::MissingAction => f.write_str("custom_world_agent_action.action 不能为空"),
|
||||
Self::InvalidProgressPercent => f.write_str("progress 必须位于 0~100"),
|
||||
Self::MissingCardId => f.write_str("custom_world_draft_card.card_id 不能为空"),
|
||||
Self::MissingCardTitle => f.write_str("custom_world_draft_card.title 不能为空"),
|
||||
|
||||
15
server-rs/crates/module-puzzle/Cargo.toml
Normal file
15
server-rs/crates/module-puzzle/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "module-puzzle"
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
spacetime-types = ["dep:spacetimedb"]
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
shared-kernel = { path = "../shared-kernel" }
|
||||
spacetimedb = { workspace = true, optional = true }
|
||||
1538
server-rs/crates/module-puzzle/src/lib.rs
Normal file
1538
server-rs/crates/module-puzzle/src/lib.rs
Normal file
File diff suppressed because it is too large
Load Diff
238
server-rs/crates/shared-contracts/src/big_fish.rs
Normal file
238
server-rs/crates/shared-contracts/src/big_fish.rs
Normal file
@@ -0,0 +1,238 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateBigFishSessionRequest {
|
||||
#[serde(default)]
|
||||
pub seed_text: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SendBigFishMessageRequest {
|
||||
pub client_message_id: String,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecuteBigFishActionRequest {
|
||||
pub action: String,
|
||||
#[serde(default)]
|
||||
pub level: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub motion_key: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SubmitBigFishInputRequest {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishAnchorItemResponse {
|
||||
pub key: String,
|
||||
pub label: String,
|
||||
pub value: String,
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishAnchorPackResponse {
|
||||
pub gameplay_promise: BigFishAnchorItemResponse,
|
||||
pub ecology_visual_theme: BigFishAnchorItemResponse,
|
||||
pub growth_ladder: BigFishAnchorItemResponse,
|
||||
pub risk_tempo: BigFishAnchorItemResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishLevelBlueprintResponse {
|
||||
pub level: u32,
|
||||
pub name: String,
|
||||
pub one_line_fantasy: String,
|
||||
pub silhouette_direction: String,
|
||||
pub size_ratio: f32,
|
||||
pub visual_prompt_seed: String,
|
||||
pub motion_prompt_seed: String,
|
||||
pub merge_source_level: Option<u32>,
|
||||
pub prey_window: Vec<u32>,
|
||||
pub threat_window: Vec<u32>,
|
||||
pub is_final_level: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishBackgroundBlueprintResponse {
|
||||
pub theme: String,
|
||||
pub color_mood: String,
|
||||
pub foreground_hints: String,
|
||||
pub midground_composition: String,
|
||||
pub background_depth: String,
|
||||
pub safe_play_area_hint: String,
|
||||
pub spawn_edge_hint: String,
|
||||
pub background_prompt_seed: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishRuntimeParamsResponse {
|
||||
pub level_count: u32,
|
||||
pub merge_count_per_upgrade: u32,
|
||||
pub spawn_target_count: u32,
|
||||
pub leader_move_speed: f32,
|
||||
pub follower_catch_up_speed: f32,
|
||||
pub offscreen_cull_seconds: f32,
|
||||
pub prey_spawn_delta_levels: Vec<u32>,
|
||||
pub threat_spawn_delta_levels: Vec<u32>,
|
||||
pub win_level: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishGameDraftResponse {
|
||||
pub title: String,
|
||||
pub subtitle: String,
|
||||
pub core_fun: String,
|
||||
pub ecology_theme: String,
|
||||
pub levels: Vec<BigFishLevelBlueprintResponse>,
|
||||
pub background: BigFishBackgroundBlueprintResponse,
|
||||
pub runtime_params: BigFishRuntimeParamsResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishAgentMessageResponse {
|
||||
pub id: String,
|
||||
pub role: String,
|
||||
pub kind: String,
|
||||
pub text: String,
|
||||
pub created_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishAssetSlotResponse {
|
||||
pub slot_id: String,
|
||||
pub asset_kind: String,
|
||||
pub level: Option<u32>,
|
||||
pub motion_key: Option<String>,
|
||||
pub status: String,
|
||||
pub asset_url: Option<String>,
|
||||
pub prompt_snapshot: String,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishAssetCoverageResponse {
|
||||
pub level_main_image_ready_count: u32,
|
||||
pub level_motion_ready_count: u32,
|
||||
pub background_ready: bool,
|
||||
pub required_level_count: u32,
|
||||
pub publish_ready: bool,
|
||||
pub blockers: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishSessionSnapshotResponse {
|
||||
pub session_id: String,
|
||||
pub current_turn: u32,
|
||||
pub progress_percent: u32,
|
||||
pub stage: String,
|
||||
pub anchor_pack: BigFishAnchorPackResponse,
|
||||
pub draft: Option<BigFishGameDraftResponse>,
|
||||
pub asset_slots: Vec<BigFishAssetSlotResponse>,
|
||||
pub asset_coverage: BigFishAssetCoverageResponse,
|
||||
pub messages: Vec<BigFishAgentMessageResponse>,
|
||||
pub last_assistant_reply: Option<String>,
|
||||
pub publish_ready: bool,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishSessionResponse {
|
||||
pub session: BigFishSessionSnapshotResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishActionResponse {
|
||||
pub session: BigFishSessionSnapshotResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishVector2Response {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishRuntimeEntityResponse {
|
||||
pub entity_id: String,
|
||||
pub level: u32,
|
||||
pub position: BigFishVector2Response,
|
||||
pub radius: f32,
|
||||
pub offscreen_seconds: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishRuntimeSnapshotResponse {
|
||||
pub run_id: String,
|
||||
pub session_id: String,
|
||||
pub status: String,
|
||||
pub tick: u64,
|
||||
pub player_level: u32,
|
||||
pub win_level: u32,
|
||||
pub leader_entity_id: Option<String>,
|
||||
pub owned_entities: Vec<BigFishRuntimeEntityResponse>,
|
||||
pub wild_entities: Vec<BigFishRuntimeEntityResponse>,
|
||||
pub camera_center: BigFishVector2Response,
|
||||
pub last_input: BigFishVector2Response,
|
||||
pub event_log: Vec<String>,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BigFishRunResponse {
|
||||
pub run: BigFishRuntimeSnapshotResponse,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn big_fish_session_request_uses_camel_case() {
|
||||
let payload = serde_json::to_value(CreateBigFishSessionRequest {
|
||||
seed_text: Some("深海机械鱼".to_string()),
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload, json!({ "seedText": "深海机械鱼" }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn big_fish_action_request_uses_camel_case() {
|
||||
let payload = serde_json::to_value(ExecuteBigFishActionRequest {
|
||||
action: "big_fish_generate_level_motion".to_string(),
|
||||
level: Some(3),
|
||||
motion_key: Some("move_swim".to_string()),
|
||||
})
|
||||
.expect("payload should serialize");
|
||||
|
||||
assert_eq!(payload["motionKey"], json!("move_swim"));
|
||||
assert_eq!(payload["level"], json!(3));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,12 @@ pub mod ai;
|
||||
pub mod api;
|
||||
pub mod assets;
|
||||
pub mod auth;
|
||||
pub mod big_fish;
|
||||
pub mod llm;
|
||||
pub mod puzzle_agent;
|
||||
pub mod puzzle_gallery;
|
||||
pub mod puzzle_runtime;
|
||||
pub mod puzzle_works;
|
||||
pub mod runtime;
|
||||
pub mod runtime_story;
|
||||
pub mod story;
|
||||
|
||||
188
server-rs/crates/shared-contracts/src/puzzle_agent.rs
Normal file
188
server-rs/crates/shared-contracts/src/puzzle_agent.rs
Normal file
@@ -0,0 +1,188 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreatePuzzleAgentSessionRequest {
|
||||
#[serde(default)]
|
||||
pub seed_text: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SendPuzzleAgentMessageRequest {
|
||||
pub client_message_id: String,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecutePuzzleAgentActionRequest {
|
||||
pub action: String,
|
||||
#[serde(default)]
|
||||
pub prompt_text: Option<String>,
|
||||
#[serde(default)]
|
||||
pub candidate_count: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub candidate_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub level_name: Option<String>,
|
||||
#[serde(default)]
|
||||
pub summary: Option<String>,
|
||||
#[serde(default)]
|
||||
pub theme_tags: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAnchorItemResponse {
|
||||
pub key: String,
|
||||
pub label: String,
|
||||
pub value: String,
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAnchorPackResponse {
|
||||
pub theme_promise: PuzzleAnchorItemResponse,
|
||||
pub visual_subject: PuzzleAnchorItemResponse,
|
||||
pub visual_mood: PuzzleAnchorItemResponse,
|
||||
pub composition_hooks: PuzzleAnchorItemResponse,
|
||||
pub tags_and_forbidden: PuzzleAnchorItemResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleGeneratedImageCandidateResponse {
|
||||
pub candidate_id: String,
|
||||
pub image_src: String,
|
||||
pub asset_id: String,
|
||||
pub prompt: String,
|
||||
#[serde(default)]
|
||||
pub actual_prompt: Option<String>,
|
||||
pub source_type: String,
|
||||
pub selected: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleCreatorIntentResponse {
|
||||
pub source_mode: String,
|
||||
pub raw_messages_summary: String,
|
||||
pub theme_promise: String,
|
||||
pub visual_subject: String,
|
||||
pub visual_mood: Vec<String>,
|
||||
pub composition_hooks: Vec<String>,
|
||||
pub theme_tags: Vec<String>,
|
||||
pub forbidden_directives: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleResultDraftResponse {
|
||||
pub level_name: String,
|
||||
pub summary: String,
|
||||
pub theme_tags: Vec<String>,
|
||||
pub forbidden_directives: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub creator_intent: Option<PuzzleCreatorIntentResponse>,
|
||||
pub anchor_pack: PuzzleAnchorPackResponse,
|
||||
pub candidates: Vec<PuzzleGeneratedImageCandidateResponse>,
|
||||
#[serde(default)]
|
||||
pub selected_candidate_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub cover_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub cover_asset_id: Option<String>,
|
||||
pub generation_status: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAgentMessageResponse {
|
||||
pub id: String,
|
||||
pub role: String,
|
||||
pub kind: String,
|
||||
pub text: String,
|
||||
pub created_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAgentSuggestedActionResponse {
|
||||
pub id: String,
|
||||
pub action_type: String,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleResultPreviewBlockerResponse {
|
||||
pub id: String,
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleResultPreviewFindingResponse {
|
||||
pub id: String,
|
||||
pub severity: String,
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleResultPreviewEnvelopeResponse {
|
||||
pub draft: PuzzleResultDraftResponse,
|
||||
pub blockers: Vec<PuzzleResultPreviewBlockerResponse>,
|
||||
pub quality_findings: Vec<PuzzleResultPreviewFindingResponse>,
|
||||
pub publish_ready: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAgentSessionSnapshotResponse {
|
||||
pub session_id: String,
|
||||
pub current_turn: u32,
|
||||
pub progress_percent: u32,
|
||||
pub stage: String,
|
||||
pub anchor_pack: PuzzleAnchorPackResponse,
|
||||
#[serde(default)]
|
||||
pub draft: Option<PuzzleResultDraftResponse>,
|
||||
pub messages: Vec<PuzzleAgentMessageResponse>,
|
||||
#[serde(default)]
|
||||
pub last_assistant_reply: Option<String>,
|
||||
#[serde(default)]
|
||||
pub published_profile_id: Option<String>,
|
||||
pub suggested_actions: Vec<PuzzleAgentSuggestedActionResponse>,
|
||||
#[serde(default)]
|
||||
pub result_preview: Option<PuzzleResultPreviewEnvelopeResponse>,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAgentSessionResponse {
|
||||
pub session: PuzzleAgentSessionSnapshotResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAgentOperationResponse {
|
||||
pub operation_id: String,
|
||||
pub operation_type: String,
|
||||
pub status: String,
|
||||
pub phase_label: String,
|
||||
pub phase_detail: String,
|
||||
pub progress: u32,
|
||||
#[serde(default)]
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleAgentActionResponse {
|
||||
pub operation: PuzzleAgentOperationResponse,
|
||||
}
|
||||
15
server-rs/crates/shared-contracts/src/puzzle_gallery.rs
Normal file
15
server-rs/crates/shared-contracts/src/puzzle_gallery.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::puzzle_works::PuzzleWorkSummaryResponse;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleGalleryResponse {
|
||||
pub items: Vec<PuzzleWorkSummaryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleGalleryDetailResponse {
|
||||
pub item: PuzzleWorkSummaryResponse,
|
||||
}
|
||||
99
server-rs/crates/shared-contracts/src/puzzle_runtime.rs
Normal file
99
server-rs/crates/shared-contracts/src/puzzle_runtime.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StartPuzzleRunRequest {
|
||||
pub profile_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SwapPuzzlePiecesRequest {
|
||||
pub first_piece_id: String,
|
||||
pub second_piece_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DragPuzzlePieceRequest {
|
||||
pub piece_id: String,
|
||||
pub target_row: u32,
|
||||
pub target_col: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleCellPositionResponse {
|
||||
pub row: u32,
|
||||
pub col: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzlePieceStateResponse {
|
||||
pub piece_id: String,
|
||||
pub correct_row: u32,
|
||||
pub correct_col: u32,
|
||||
pub current_row: u32,
|
||||
pub current_col: u32,
|
||||
#[serde(default)]
|
||||
pub merged_group_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleMergedGroupStateResponse {
|
||||
pub group_id: String,
|
||||
pub piece_ids: Vec<String>,
|
||||
pub occupied_cells: Vec<PuzzleCellPositionResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleBoardSnapshotResponse {
|
||||
pub rows: u32,
|
||||
pub cols: u32,
|
||||
pub pieces: Vec<PuzzlePieceStateResponse>,
|
||||
pub merged_groups: Vec<PuzzleMergedGroupStateResponse>,
|
||||
#[serde(default)]
|
||||
pub selected_piece_id: Option<String>,
|
||||
pub all_tiles_resolved: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleRuntimeLevelSnapshotResponse {
|
||||
pub run_id: String,
|
||||
pub level_index: u32,
|
||||
pub grid_size: u32,
|
||||
pub profile_id: String,
|
||||
pub level_name: String,
|
||||
pub author_display_name: String,
|
||||
pub theme_tags: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub cover_image_src: Option<String>,
|
||||
pub board: PuzzleBoardSnapshotResponse,
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleRunSnapshotResponse {
|
||||
pub run_id: String,
|
||||
pub entry_profile_id: String,
|
||||
pub cleared_level_count: u32,
|
||||
pub current_level_index: u32,
|
||||
pub current_grid_size: u32,
|
||||
pub played_profile_ids: Vec<String>,
|
||||
pub previous_level_tags: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub current_level: Option<PuzzleRuntimeLevelSnapshotResponse>,
|
||||
#[serde(default)]
|
||||
pub recommended_next_profile_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleRunResponse {
|
||||
pub run: PuzzleRunSnapshotResponse,
|
||||
}
|
||||
65
server-rs/crates/shared-contracts/src/puzzle_works.rs
Normal file
65
server-rs/crates/shared-contracts/src/puzzle_works.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::puzzle_agent::PuzzleAnchorPackResponse;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PutPuzzleWorkRequest {
|
||||
pub level_name: String,
|
||||
pub summary: String,
|
||||
pub theme_tags: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub cover_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub cover_asset_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleWorkSummaryResponse {
|
||||
pub work_id: String,
|
||||
pub profile_id: String,
|
||||
pub owner_user_id: String,
|
||||
#[serde(default)]
|
||||
pub source_session_id: Option<String>,
|
||||
pub author_display_name: String,
|
||||
pub level_name: String,
|
||||
pub summary: String,
|
||||
pub theme_tags: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub cover_image_src: Option<String>,
|
||||
#[serde(default)]
|
||||
pub cover_asset_id: Option<String>,
|
||||
pub publication_status: String,
|
||||
pub updated_at: String,
|
||||
#[serde(default)]
|
||||
pub published_at: Option<String>,
|
||||
pub play_count: u32,
|
||||
pub publish_ready: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleWorkProfileResponse {
|
||||
#[serde(flatten)]
|
||||
pub summary: PuzzleWorkSummaryResponse,
|
||||
pub anchor_pack: PuzzleAnchorPackResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleWorksResponse {
|
||||
pub items: Vec<PuzzleWorkSummaryResponse>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleWorkDetailResponse {
|
||||
pub item: PuzzleWorkProfileResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PuzzleWorkMutationResponse {
|
||||
pub item: PuzzleWorkProfileResponse,
|
||||
}
|
||||
@@ -6,11 +6,13 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
module-ai = { path = "../module-ai" }
|
||||
module-big-fish = { path = "../module-big-fish" }
|
||||
module-custom-world = { path = "../module-custom-world" }
|
||||
module-assets = { path = "../module-assets" }
|
||||
module-combat = { path = "../module-combat" }
|
||||
module-inventory = { path = "../module-inventory" }
|
||||
module-npc = { path = "../module-npc" }
|
||||
module-puzzle = { path = "../module-puzzle" }
|
||||
module-runtime = { path = "../module-runtime" }
|
||||
module-runtime-item = { path = "../module-runtime-item" }
|
||||
module-story = { path = "../module-story" }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_run_next_level_input_type::PuzzleRunNextLevelInput;
|
||||
use super::puzzle_run_procedure_result_type::PuzzleRunProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct AdvancePuzzleNextLevelArgs {
|
||||
pub input: PuzzleRunNextLevelInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for AdvancePuzzleNextLevelArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `advance_puzzle_next_level`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait advance_puzzle_next_level {
|
||||
fn advance_puzzle_next_level(&self, input: PuzzleRunNextLevelInput,
|
||||
) {
|
||||
self.advance_puzzle_next_level_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn advance_puzzle_next_level_then(
|
||||
&self,
|
||||
input: PuzzleRunNextLevelInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl advance_puzzle_next_level for super::RemoteProcedures {
|
||||
fn advance_puzzle_next_level_then(
|
||||
&self,
|
||||
input: PuzzleRunNextLevelInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleRunProcedureResult>(
|
||||
"advance_puzzle_next_level",
|
||||
AdvancePuzzleNextLevelArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
#[derive(Copy, Eq, Hash)]
|
||||
pub enum BigFishAgentMessageKind {
|
||||
Chat,
|
||||
|
||||
Summary,
|
||||
|
||||
ActionResult,
|
||||
|
||||
Warning,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAgentMessageKind {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
#[derive(Copy, Eq, Hash)]
|
||||
pub enum BigFishAgentMessageRole {
|
||||
User,
|
||||
|
||||
Assistant,
|
||||
|
||||
System,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAgentMessageRole {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_agent_message_role_type::BigFishAgentMessageRole;
|
||||
use super::big_fish_agent_message_kind_type::BigFishAgentMessageKind;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAgentMessageSnapshot {
|
||||
pub message_id: String,
|
||||
pub session_id: String,
|
||||
pub role: BigFishAgentMessageRole,
|
||||
pub kind: BigFishAgentMessageKind,
|
||||
pub text: String,
|
||||
pub created_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAgentMessageSnapshot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
use super::big_fish_agent_message_type::BigFishAgentMessage;
|
||||
use super::big_fish_agent_message_role_type::BigFishAgentMessageRole;
|
||||
use super::big_fish_agent_message_kind_type::BigFishAgentMessageKind;
|
||||
|
||||
/// Table handle for the table `big_fish_agent_message`.
|
||||
///
|
||||
/// Obtain a handle from the [`BigFishAgentMessageTableAccess::big_fish_agent_message`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.big_fish_agent_message()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_agent_message().on_insert(...)`.
|
||||
pub struct BigFishAgentMessageTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<BigFishAgentMessage>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `big_fish_agent_message`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait BigFishAgentMessageTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`BigFishAgentMessageTableHandle`], which mediates access to the table `big_fish_agent_message`.
|
||||
fn big_fish_agent_message(&self) -> BigFishAgentMessageTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl BigFishAgentMessageTableAccess for super::RemoteTables {
|
||||
fn big_fish_agent_message(&self) -> BigFishAgentMessageTableHandle<'_> {
|
||||
BigFishAgentMessageTableHandle {
|
||||
imp: self.imp.get_table::<BigFishAgentMessage>("big_fish_agent_message"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishAgentMessageInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct BigFishAgentMessageDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::Table for BigFishAgentMessageTableHandle<'ctx> {
|
||||
type Row = BigFishAgentMessage;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 { self.imp.count() }
|
||||
fn iter(&self) -> impl Iterator<Item = BigFishAgentMessage> + '_ { self.imp.iter() }
|
||||
|
||||
type InsertCallbackId = BigFishAgentMessageInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishAgentMessageInsertCallbackId {
|
||||
BigFishAgentMessageInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: BigFishAgentMessageInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = BigFishAgentMessageDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishAgentMessageDeleteCallbackId {
|
||||
BigFishAgentMessageDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: BigFishAgentMessageDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishAgentMessageUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableWithPrimaryKey for BigFishAgentMessageTableHandle<'ctx> {
|
||||
type UpdateCallbackId = BigFishAgentMessageUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> BigFishAgentMessageUpdateCallbackId {
|
||||
BigFishAgentMessageUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: BigFishAgentMessageUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `message_id` unique index on the table `big_fish_agent_message`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`BigFishAgentMessageMessageIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_agent_message().message_id().find(...)`.
|
||||
pub struct BigFishAgentMessageMessageIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<BigFishAgentMessage, String>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishAgentMessageTableHandle<'ctx> {
|
||||
/// Get a handle on the `message_id` unique index on the table `big_fish_agent_message`.
|
||||
pub fn message_id(&self) -> BigFishAgentMessageMessageIdUnique<'ctx> {
|
||||
BigFishAgentMessageMessageIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<String>("message_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishAgentMessageMessageIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `message_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &String) -> Option<BigFishAgentMessage> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
|
||||
let _table = client_cache.get_or_make_table::<BigFishAgentMessage>("big_fish_agent_message");
|
||||
_table.add_unique_constraint::<String>("message_id", |row| &row.message_id);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<BigFishAgentMessage>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse(
|
||||
"TableUpdate<BigFishAgentMessage>",
|
||||
"TableUpdate",
|
||||
).with_cause(e).into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `BigFishAgentMessage`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait big_fish_agent_messageQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `BigFishAgentMessage`.
|
||||
fn big_fish_agent_message(&self) -> __sdk::__query_builder::Table<BigFishAgentMessage>;
|
||||
}
|
||||
|
||||
impl big_fish_agent_messageQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn big_fish_agent_message(&self) -> __sdk::__query_builder::Table<BigFishAgentMessage> {
|
||||
__sdk::__query_builder::Table::new("big_fish_agent_message")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_agent_message_role_type::BigFishAgentMessageRole;
|
||||
use super::big_fish_agent_message_kind_type::BigFishAgentMessageKind;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAgentMessage {
|
||||
pub message_id: String,
|
||||
pub session_id: String,
|
||||
pub role: BigFishAgentMessageRole,
|
||||
pub kind: BigFishAgentMessageKind,
|
||||
pub text: String,
|
||||
pub created_at: __sdk::Timestamp,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAgentMessage {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
|
||||
/// Column accessor struct for the table `BigFishAgentMessage`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct BigFishAgentMessageCols {
|
||||
pub message_id: __sdk::__query_builder::Col<BigFishAgentMessage, String>,
|
||||
pub session_id: __sdk::__query_builder::Col<BigFishAgentMessage, String>,
|
||||
pub role: __sdk::__query_builder::Col<BigFishAgentMessage, BigFishAgentMessageRole>,
|
||||
pub kind: __sdk::__query_builder::Col<BigFishAgentMessage, BigFishAgentMessageKind>,
|
||||
pub text: __sdk::__query_builder::Col<BigFishAgentMessage, String>,
|
||||
pub created_at: __sdk::__query_builder::Col<BigFishAgentMessage, __sdk::Timestamp>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for BigFishAgentMessage {
|
||||
type Cols = BigFishAgentMessageCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
BigFishAgentMessageCols {
|
||||
message_id: __sdk::__query_builder::Col::new(table_name, "message_id"),
|
||||
session_id: __sdk::__query_builder::Col::new(table_name, "session_id"),
|
||||
role: __sdk::__query_builder::Col::new(table_name, "role"),
|
||||
kind: __sdk::__query_builder::Col::new(table_name, "kind"),
|
||||
text: __sdk::__query_builder::Col::new(table_name, "text"),
|
||||
created_at: __sdk::__query_builder::Col::new(table_name, "created_at"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indexed column accessor struct for the table `BigFishAgentMessage`.
|
||||
///
|
||||
/// Provides typed access to indexed columns for query building.
|
||||
pub struct BigFishAgentMessageIxCols {
|
||||
pub message_id: __sdk::__query_builder::IxCol<BigFishAgentMessage, String>,
|
||||
pub session_id: __sdk::__query_builder::IxCol<BigFishAgentMessage, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasIxCols for BigFishAgentMessage {
|
||||
type IxCols = BigFishAgentMessageIxCols;
|
||||
fn ix_cols(table_name: &'static str) -> Self::IxCols {
|
||||
BigFishAgentMessageIxCols {
|
||||
message_id: __sdk::__query_builder::IxCol::new(table_name, "message_id"),
|
||||
session_id: __sdk::__query_builder::IxCol::new(table_name, "session_id"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::CanBeLookupTable for BigFishAgentMessage {}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_anchor_status_type::BigFishAnchorStatus;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAnchorItem {
|
||||
pub key: String,
|
||||
pub label: String,
|
||||
pub value: String,
|
||||
pub status: BigFishAnchorStatus,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAnchorItem {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_anchor_item_type::BigFishAnchorItem;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAnchorPack {
|
||||
pub gameplay_promise: BigFishAnchorItem,
|
||||
pub ecology_visual_theme: BigFishAnchorItem,
|
||||
pub growth_ladder: BigFishAnchorItem,
|
||||
pub risk_tempo: BigFishAnchorItem,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAnchorPack {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
#[derive(Copy, Eq, Hash)]
|
||||
pub enum BigFishAnchorStatus {
|
||||
Confirmed,
|
||||
|
||||
Inferred,
|
||||
|
||||
Missing,
|
||||
|
||||
Locked,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAnchorStatus {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAssetCoverage {
|
||||
pub level_main_image_ready_count: u32,
|
||||
pub level_motion_ready_count: u32,
|
||||
pub background_ready: bool,
|
||||
pub required_level_count: u32,
|
||||
pub publish_ready: bool,
|
||||
pub blockers: Vec::<String>,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAssetCoverage {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_asset_kind_type::BigFishAssetKind;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAssetGenerateInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub asset_kind: BigFishAssetKind,
|
||||
pub level: Option::<u32>,
|
||||
pub motion_key: Option::<String>,
|
||||
pub generated_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAssetGenerateInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
#[derive(Copy, Eq, Hash)]
|
||||
pub enum BigFishAssetKind {
|
||||
LevelMainImage,
|
||||
|
||||
LevelMotion,
|
||||
|
||||
StageBackground,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAssetKind {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_asset_kind_type::BigFishAssetKind;
|
||||
use super::big_fish_asset_status_type::BigFishAssetStatus;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAssetSlotSnapshot {
|
||||
pub slot_id: String,
|
||||
pub session_id: String,
|
||||
pub asset_kind: BigFishAssetKind,
|
||||
pub level: Option::<u32>,
|
||||
pub motion_key: Option::<String>,
|
||||
pub status: BigFishAssetStatus,
|
||||
pub asset_url: Option::<String>,
|
||||
pub prompt_snapshot: String,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAssetSlotSnapshot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
use super::big_fish_asset_slot_type::BigFishAssetSlot;
|
||||
use super::big_fish_asset_kind_type::BigFishAssetKind;
|
||||
use super::big_fish_asset_status_type::BigFishAssetStatus;
|
||||
|
||||
/// Table handle for the table `big_fish_asset_slot`.
|
||||
///
|
||||
/// Obtain a handle from the [`BigFishAssetSlotTableAccess::big_fish_asset_slot`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.big_fish_asset_slot()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_asset_slot().on_insert(...)`.
|
||||
pub struct BigFishAssetSlotTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<BigFishAssetSlot>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `big_fish_asset_slot`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait BigFishAssetSlotTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`BigFishAssetSlotTableHandle`], which mediates access to the table `big_fish_asset_slot`.
|
||||
fn big_fish_asset_slot(&self) -> BigFishAssetSlotTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl BigFishAssetSlotTableAccess for super::RemoteTables {
|
||||
fn big_fish_asset_slot(&self) -> BigFishAssetSlotTableHandle<'_> {
|
||||
BigFishAssetSlotTableHandle {
|
||||
imp: self.imp.get_table::<BigFishAssetSlot>("big_fish_asset_slot"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishAssetSlotInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct BigFishAssetSlotDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::Table for BigFishAssetSlotTableHandle<'ctx> {
|
||||
type Row = BigFishAssetSlot;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 { self.imp.count() }
|
||||
fn iter(&self) -> impl Iterator<Item = BigFishAssetSlot> + '_ { self.imp.iter() }
|
||||
|
||||
type InsertCallbackId = BigFishAssetSlotInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishAssetSlotInsertCallbackId {
|
||||
BigFishAssetSlotInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: BigFishAssetSlotInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = BigFishAssetSlotDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishAssetSlotDeleteCallbackId {
|
||||
BigFishAssetSlotDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: BigFishAssetSlotDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishAssetSlotUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableWithPrimaryKey for BigFishAssetSlotTableHandle<'ctx> {
|
||||
type UpdateCallbackId = BigFishAssetSlotUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> BigFishAssetSlotUpdateCallbackId {
|
||||
BigFishAssetSlotUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: BigFishAssetSlotUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `slot_id` unique index on the table `big_fish_asset_slot`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`BigFishAssetSlotSlotIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_asset_slot().slot_id().find(...)`.
|
||||
pub struct BigFishAssetSlotSlotIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<BigFishAssetSlot, String>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishAssetSlotTableHandle<'ctx> {
|
||||
/// Get a handle on the `slot_id` unique index on the table `big_fish_asset_slot`.
|
||||
pub fn slot_id(&self) -> BigFishAssetSlotSlotIdUnique<'ctx> {
|
||||
BigFishAssetSlotSlotIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<String>("slot_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishAssetSlotSlotIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `slot_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &String) -> Option<BigFishAssetSlot> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
|
||||
let _table = client_cache.get_or_make_table::<BigFishAssetSlot>("big_fish_asset_slot");
|
||||
_table.add_unique_constraint::<String>("slot_id", |row| &row.slot_id);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<BigFishAssetSlot>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse(
|
||||
"TableUpdate<BigFishAssetSlot>",
|
||||
"TableUpdate",
|
||||
).with_cause(e).into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `BigFishAssetSlot`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait big_fish_asset_slotQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `BigFishAssetSlot`.
|
||||
fn big_fish_asset_slot(&self) -> __sdk::__query_builder::Table<BigFishAssetSlot>;
|
||||
}
|
||||
|
||||
impl big_fish_asset_slotQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn big_fish_asset_slot(&self) -> __sdk::__query_builder::Table<BigFishAssetSlot> {
|
||||
__sdk::__query_builder::Table::new("big_fish_asset_slot")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_asset_kind_type::BigFishAssetKind;
|
||||
use super::big_fish_asset_status_type::BigFishAssetStatus;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishAssetSlot {
|
||||
pub slot_id: String,
|
||||
pub session_id: String,
|
||||
pub asset_kind: BigFishAssetKind,
|
||||
pub level: Option::<u32>,
|
||||
pub motion_key: Option::<String>,
|
||||
pub status: BigFishAssetStatus,
|
||||
pub asset_url: Option::<String>,
|
||||
pub prompt_snapshot: String,
|
||||
pub updated_at: __sdk::Timestamp,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAssetSlot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
|
||||
/// Column accessor struct for the table `BigFishAssetSlot`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct BigFishAssetSlotCols {
|
||||
pub slot_id: __sdk::__query_builder::Col<BigFishAssetSlot, String>,
|
||||
pub session_id: __sdk::__query_builder::Col<BigFishAssetSlot, String>,
|
||||
pub asset_kind: __sdk::__query_builder::Col<BigFishAssetSlot, BigFishAssetKind>,
|
||||
pub level: __sdk::__query_builder::Col<BigFishAssetSlot, Option::<u32>>,
|
||||
pub motion_key: __sdk::__query_builder::Col<BigFishAssetSlot, Option::<String>>,
|
||||
pub status: __sdk::__query_builder::Col<BigFishAssetSlot, BigFishAssetStatus>,
|
||||
pub asset_url: __sdk::__query_builder::Col<BigFishAssetSlot, Option::<String>>,
|
||||
pub prompt_snapshot: __sdk::__query_builder::Col<BigFishAssetSlot, String>,
|
||||
pub updated_at: __sdk::__query_builder::Col<BigFishAssetSlot, __sdk::Timestamp>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for BigFishAssetSlot {
|
||||
type Cols = BigFishAssetSlotCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
BigFishAssetSlotCols {
|
||||
slot_id: __sdk::__query_builder::Col::new(table_name, "slot_id"),
|
||||
session_id: __sdk::__query_builder::Col::new(table_name, "session_id"),
|
||||
asset_kind: __sdk::__query_builder::Col::new(table_name, "asset_kind"),
|
||||
level: __sdk::__query_builder::Col::new(table_name, "level"),
|
||||
motion_key: __sdk::__query_builder::Col::new(table_name, "motion_key"),
|
||||
status: __sdk::__query_builder::Col::new(table_name, "status"),
|
||||
asset_url: __sdk::__query_builder::Col::new(table_name, "asset_url"),
|
||||
prompt_snapshot: __sdk::__query_builder::Col::new(table_name, "prompt_snapshot"),
|
||||
updated_at: __sdk::__query_builder::Col::new(table_name, "updated_at"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indexed column accessor struct for the table `BigFishAssetSlot`.
|
||||
///
|
||||
/// Provides typed access to indexed columns for query building.
|
||||
pub struct BigFishAssetSlotIxCols {
|
||||
pub session_id: __sdk::__query_builder::IxCol<BigFishAssetSlot, String>,
|
||||
pub slot_id: __sdk::__query_builder::IxCol<BigFishAssetSlot, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasIxCols for BigFishAssetSlot {
|
||||
type IxCols = BigFishAssetSlotIxCols;
|
||||
fn ix_cols(table_name: &'static str) -> Self::IxCols {
|
||||
BigFishAssetSlotIxCols {
|
||||
session_id: __sdk::__query_builder::IxCol::new(table_name, "session_id"),
|
||||
slot_id: __sdk::__query_builder::IxCol::new(table_name, "slot_id"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::CanBeLookupTable for BigFishAssetSlot {}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
#[derive(Copy, Eq, Hash)]
|
||||
pub enum BigFishAssetStatus {
|
||||
Missing,
|
||||
|
||||
Ready,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishAssetStatus {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishBackgroundBlueprint {
|
||||
pub theme: String,
|
||||
pub color_mood: String,
|
||||
pub foreground_hints: String,
|
||||
pub midground_composition: String,
|
||||
pub background_depth: String,
|
||||
pub safe_play_area_hint: String,
|
||||
pub spawn_edge_hint: String,
|
||||
pub background_prompt_seed: String,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishBackgroundBlueprint {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
use super::big_fish_creation_session_type::BigFishCreationSession;
|
||||
use super::big_fish_creation_stage_type::BigFishCreationStage;
|
||||
|
||||
/// Table handle for the table `big_fish_creation_session`.
|
||||
///
|
||||
/// Obtain a handle from the [`BigFishCreationSessionTableAccess::big_fish_creation_session`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.big_fish_creation_session()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_creation_session().on_insert(...)`.
|
||||
pub struct BigFishCreationSessionTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<BigFishCreationSession>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `big_fish_creation_session`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait BigFishCreationSessionTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`BigFishCreationSessionTableHandle`], which mediates access to the table `big_fish_creation_session`.
|
||||
fn big_fish_creation_session(&self) -> BigFishCreationSessionTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl BigFishCreationSessionTableAccess for super::RemoteTables {
|
||||
fn big_fish_creation_session(&self) -> BigFishCreationSessionTableHandle<'_> {
|
||||
BigFishCreationSessionTableHandle {
|
||||
imp: self.imp.get_table::<BigFishCreationSession>("big_fish_creation_session"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishCreationSessionInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct BigFishCreationSessionDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::Table for BigFishCreationSessionTableHandle<'ctx> {
|
||||
type Row = BigFishCreationSession;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 { self.imp.count() }
|
||||
fn iter(&self) -> impl Iterator<Item = BigFishCreationSession> + '_ { self.imp.iter() }
|
||||
|
||||
type InsertCallbackId = BigFishCreationSessionInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishCreationSessionInsertCallbackId {
|
||||
BigFishCreationSessionInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: BigFishCreationSessionInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = BigFishCreationSessionDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishCreationSessionDeleteCallbackId {
|
||||
BigFishCreationSessionDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: BigFishCreationSessionDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishCreationSessionUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableWithPrimaryKey for BigFishCreationSessionTableHandle<'ctx> {
|
||||
type UpdateCallbackId = BigFishCreationSessionUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> BigFishCreationSessionUpdateCallbackId {
|
||||
BigFishCreationSessionUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: BigFishCreationSessionUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `session_id` unique index on the table `big_fish_creation_session`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`BigFishCreationSessionSessionIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_creation_session().session_id().find(...)`.
|
||||
pub struct BigFishCreationSessionSessionIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<BigFishCreationSession, String>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishCreationSessionTableHandle<'ctx> {
|
||||
/// Get a handle on the `session_id` unique index on the table `big_fish_creation_session`.
|
||||
pub fn session_id(&self) -> BigFishCreationSessionSessionIdUnique<'ctx> {
|
||||
BigFishCreationSessionSessionIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<String>("session_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishCreationSessionSessionIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `session_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &String) -> Option<BigFishCreationSession> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
|
||||
let _table = client_cache.get_or_make_table::<BigFishCreationSession>("big_fish_creation_session");
|
||||
_table.add_unique_constraint::<String>("session_id", |row| &row.session_id);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<BigFishCreationSession>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse(
|
||||
"TableUpdate<BigFishCreationSession>",
|
||||
"TableUpdate",
|
||||
).with_cause(e).into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `BigFishCreationSession`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait big_fish_creation_sessionQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `BigFishCreationSession`.
|
||||
fn big_fish_creation_session(&self) -> __sdk::__query_builder::Table<BigFishCreationSession>;
|
||||
}
|
||||
|
||||
impl big_fish_creation_sessionQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn big_fish_creation_session(&self) -> __sdk::__query_builder::Table<BigFishCreationSession> {
|
||||
__sdk::__query_builder::Table::new("big_fish_creation_session")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_creation_stage_type::BigFishCreationStage;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishCreationSession {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub seed_text: String,
|
||||
pub current_turn: u32,
|
||||
pub progress_percent: u32,
|
||||
pub stage: BigFishCreationStage,
|
||||
pub anchor_pack_json: String,
|
||||
pub draft_json: Option::<String>,
|
||||
pub asset_coverage_json: String,
|
||||
pub last_assistant_reply: Option::<String>,
|
||||
pub publish_ready: bool,
|
||||
pub created_at: __sdk::Timestamp,
|
||||
pub updated_at: __sdk::Timestamp,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishCreationSession {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
|
||||
/// Column accessor struct for the table `BigFishCreationSession`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct BigFishCreationSessionCols {
|
||||
pub session_id: __sdk::__query_builder::Col<BigFishCreationSession, String>,
|
||||
pub owner_user_id: __sdk::__query_builder::Col<BigFishCreationSession, String>,
|
||||
pub seed_text: __sdk::__query_builder::Col<BigFishCreationSession, String>,
|
||||
pub current_turn: __sdk::__query_builder::Col<BigFishCreationSession, u32>,
|
||||
pub progress_percent: __sdk::__query_builder::Col<BigFishCreationSession, u32>,
|
||||
pub stage: __sdk::__query_builder::Col<BigFishCreationSession, BigFishCreationStage>,
|
||||
pub anchor_pack_json: __sdk::__query_builder::Col<BigFishCreationSession, String>,
|
||||
pub draft_json: __sdk::__query_builder::Col<BigFishCreationSession, Option::<String>>,
|
||||
pub asset_coverage_json: __sdk::__query_builder::Col<BigFishCreationSession, String>,
|
||||
pub last_assistant_reply: __sdk::__query_builder::Col<BigFishCreationSession, Option::<String>>,
|
||||
pub publish_ready: __sdk::__query_builder::Col<BigFishCreationSession, bool>,
|
||||
pub created_at: __sdk::__query_builder::Col<BigFishCreationSession, __sdk::Timestamp>,
|
||||
pub updated_at: __sdk::__query_builder::Col<BigFishCreationSession, __sdk::Timestamp>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for BigFishCreationSession {
|
||||
type Cols = BigFishCreationSessionCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
BigFishCreationSessionCols {
|
||||
session_id: __sdk::__query_builder::Col::new(table_name, "session_id"),
|
||||
owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"),
|
||||
seed_text: __sdk::__query_builder::Col::new(table_name, "seed_text"),
|
||||
current_turn: __sdk::__query_builder::Col::new(table_name, "current_turn"),
|
||||
progress_percent: __sdk::__query_builder::Col::new(table_name, "progress_percent"),
|
||||
stage: __sdk::__query_builder::Col::new(table_name, "stage"),
|
||||
anchor_pack_json: __sdk::__query_builder::Col::new(table_name, "anchor_pack_json"),
|
||||
draft_json: __sdk::__query_builder::Col::new(table_name, "draft_json"),
|
||||
asset_coverage_json: __sdk::__query_builder::Col::new(table_name, "asset_coverage_json"),
|
||||
last_assistant_reply: __sdk::__query_builder::Col::new(table_name, "last_assistant_reply"),
|
||||
publish_ready: __sdk::__query_builder::Col::new(table_name, "publish_ready"),
|
||||
created_at: __sdk::__query_builder::Col::new(table_name, "created_at"),
|
||||
updated_at: __sdk::__query_builder::Col::new(table_name, "updated_at"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indexed column accessor struct for the table `BigFishCreationSession`.
|
||||
///
|
||||
/// Provides typed access to indexed columns for query building.
|
||||
pub struct BigFishCreationSessionIxCols {
|
||||
pub owner_user_id: __sdk::__query_builder::IxCol<BigFishCreationSession, String>,
|
||||
pub session_id: __sdk::__query_builder::IxCol<BigFishCreationSession, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasIxCols for BigFishCreationSession {
|
||||
type IxCols = BigFishCreationSessionIxCols;
|
||||
fn ix_cols(table_name: &'static str) -> Self::IxCols {
|
||||
BigFishCreationSessionIxCols {
|
||||
owner_user_id: __sdk::__query_builder::IxCol::new(table_name, "owner_user_id"),
|
||||
session_id: __sdk::__query_builder::IxCol::new(table_name, "session_id"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::CanBeLookupTable for BigFishCreationSession {}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
#[derive(Copy, Eq, Hash)]
|
||||
pub enum BigFishCreationStage {
|
||||
CollectingAnchors,
|
||||
|
||||
DraftReady,
|
||||
|
||||
AssetRefining,
|
||||
|
||||
ReadyToPublish,
|
||||
|
||||
Published,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishCreationStage {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishDraftCompileInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub compiled_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishDraftCompileInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_level_blueprint_type::BigFishLevelBlueprint;
|
||||
use super::big_fish_background_blueprint_type::BigFishBackgroundBlueprint;
|
||||
use super::big_fish_runtime_params_type::BigFishRuntimeParams;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishGameDraft {
|
||||
pub title: String,
|
||||
pub subtitle: String,
|
||||
pub core_fun: String,
|
||||
pub ecology_theme: String,
|
||||
pub levels: Vec::<BigFishLevelBlueprint>,
|
||||
pub background: BigFishBackgroundBlueprint,
|
||||
pub runtime_params: BigFishRuntimeParams,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishGameDraft {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishLevelBlueprint {
|
||||
pub level: u32,
|
||||
pub name: String,
|
||||
pub one_line_fantasy: String,
|
||||
pub silhouette_direction: String,
|
||||
pub size_ratio: f32,
|
||||
pub visual_prompt_seed: String,
|
||||
pub motion_prompt_seed: String,
|
||||
pub merge_source_level: Option::<u32>,
|
||||
pub prey_window: Vec::<u32>,
|
||||
pub threat_window: Vec::<u32>,
|
||||
pub is_final_level: bool,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishLevelBlueprint {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishMessageSubmitInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub user_message_id: String,
|
||||
pub user_message_text: String,
|
||||
pub assistant_message_id: String,
|
||||
pub submitted_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishMessageSubmitInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishPublishInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub published_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishPublishInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRunGetInput {
|
||||
pub run_id: String,
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRunGetInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRunInputSubmitInput {
|
||||
pub run_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub input_x: f32,
|
||||
pub input_y: f32,
|
||||
pub submitted_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRunInputSubmitInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_runtime_snapshot_type::BigFishRuntimeSnapshot;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRunProcedureResult {
|
||||
pub ok: bool,
|
||||
pub run: Option::<BigFishRuntimeSnapshot>,
|
||||
pub error_message: Option::<String>,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRunProcedureResult {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRunStartInput {
|
||||
pub run_id: String,
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub started_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRunStartInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
#[derive(Copy, Eq, Hash)]
|
||||
pub enum BigFishRunStatus {
|
||||
Running,
|
||||
|
||||
Won,
|
||||
|
||||
Failed,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRunStatus {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_vector_2_type::BigFishVector2;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRuntimeEntity {
|
||||
pub entity_id: String,
|
||||
pub level: u32,
|
||||
pub position: BigFishVector2,
|
||||
pub radius: f32,
|
||||
pub offscreen_seconds: f32,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRuntimeEntity {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRuntimeParams {
|
||||
pub level_count: u32,
|
||||
pub merge_count_per_upgrade: u32,
|
||||
pub spawn_target_count: u32,
|
||||
pub leader_move_speed: f32,
|
||||
pub follower_catch_up_speed: f32,
|
||||
pub offscreen_cull_seconds: f32,
|
||||
pub prey_spawn_delta_levels: Vec::<u32>,
|
||||
pub threat_spawn_delta_levels: Vec::<u32>,
|
||||
pub win_level: u32,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRuntimeParams {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
use super::big_fish_runtime_run_type::BigFishRuntimeRun;
|
||||
use super::big_fish_run_status_type::BigFishRunStatus;
|
||||
|
||||
/// Table handle for the table `big_fish_runtime_run`.
|
||||
///
|
||||
/// Obtain a handle from the [`BigFishRuntimeRunTableAccess::big_fish_runtime_run`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.big_fish_runtime_run()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_runtime_run().on_insert(...)`.
|
||||
pub struct BigFishRuntimeRunTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<BigFishRuntimeRun>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `big_fish_runtime_run`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait BigFishRuntimeRunTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`BigFishRuntimeRunTableHandle`], which mediates access to the table `big_fish_runtime_run`.
|
||||
fn big_fish_runtime_run(&self) -> BigFishRuntimeRunTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl BigFishRuntimeRunTableAccess for super::RemoteTables {
|
||||
fn big_fish_runtime_run(&self) -> BigFishRuntimeRunTableHandle<'_> {
|
||||
BigFishRuntimeRunTableHandle {
|
||||
imp: self.imp.get_table::<BigFishRuntimeRun>("big_fish_runtime_run"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishRuntimeRunInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct BigFishRuntimeRunDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::Table for BigFishRuntimeRunTableHandle<'ctx> {
|
||||
type Row = BigFishRuntimeRun;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 { self.imp.count() }
|
||||
fn iter(&self) -> impl Iterator<Item = BigFishRuntimeRun> + '_ { self.imp.iter() }
|
||||
|
||||
type InsertCallbackId = BigFishRuntimeRunInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishRuntimeRunInsertCallbackId {
|
||||
BigFishRuntimeRunInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: BigFishRuntimeRunInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = BigFishRuntimeRunDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> BigFishRuntimeRunDeleteCallbackId {
|
||||
BigFishRuntimeRunDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: BigFishRuntimeRunDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BigFishRuntimeRunUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableWithPrimaryKey for BigFishRuntimeRunTableHandle<'ctx> {
|
||||
type UpdateCallbackId = BigFishRuntimeRunUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> BigFishRuntimeRunUpdateCallbackId {
|
||||
BigFishRuntimeRunUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: BigFishRuntimeRunUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `run_id` unique index on the table `big_fish_runtime_run`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`BigFishRuntimeRunRunIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.big_fish_runtime_run().run_id().find(...)`.
|
||||
pub struct BigFishRuntimeRunRunIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<BigFishRuntimeRun, String>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishRuntimeRunTableHandle<'ctx> {
|
||||
/// Get a handle on the `run_id` unique index on the table `big_fish_runtime_run`.
|
||||
pub fn run_id(&self) -> BigFishRuntimeRunRunIdUnique<'ctx> {
|
||||
BigFishRuntimeRunRunIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<String>("run_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> BigFishRuntimeRunRunIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `run_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &String) -> Option<BigFishRuntimeRun> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
|
||||
let _table = client_cache.get_or_make_table::<BigFishRuntimeRun>("big_fish_runtime_run");
|
||||
_table.add_unique_constraint::<String>("run_id", |row| &row.run_id);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<BigFishRuntimeRun>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse(
|
||||
"TableUpdate<BigFishRuntimeRun>",
|
||||
"TableUpdate",
|
||||
).with_cause(e).into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `BigFishRuntimeRun`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait big_fish_runtime_runQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `BigFishRuntimeRun`.
|
||||
fn big_fish_runtime_run(&self) -> __sdk::__query_builder::Table<BigFishRuntimeRun>;
|
||||
}
|
||||
|
||||
impl big_fish_runtime_runQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn big_fish_runtime_run(&self) -> __sdk::__query_builder::Table<BigFishRuntimeRun> {
|
||||
__sdk::__query_builder::Table::new("big_fish_runtime_run")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_run_status_type::BigFishRunStatus;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRuntimeRun {
|
||||
pub run_id: String,
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub status: BigFishRunStatus,
|
||||
pub snapshot_json: String,
|
||||
pub last_input_x: f32,
|
||||
pub last_input_y: f32,
|
||||
pub tick: u64,
|
||||
pub created_at: __sdk::Timestamp,
|
||||
pub updated_at: __sdk::Timestamp,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRuntimeRun {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
|
||||
/// Column accessor struct for the table `BigFishRuntimeRun`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct BigFishRuntimeRunCols {
|
||||
pub run_id: __sdk::__query_builder::Col<BigFishRuntimeRun, String>,
|
||||
pub session_id: __sdk::__query_builder::Col<BigFishRuntimeRun, String>,
|
||||
pub owner_user_id: __sdk::__query_builder::Col<BigFishRuntimeRun, String>,
|
||||
pub status: __sdk::__query_builder::Col<BigFishRuntimeRun, BigFishRunStatus>,
|
||||
pub snapshot_json: __sdk::__query_builder::Col<BigFishRuntimeRun, String>,
|
||||
pub last_input_x: __sdk::__query_builder::Col<BigFishRuntimeRun, f32>,
|
||||
pub last_input_y: __sdk::__query_builder::Col<BigFishRuntimeRun, f32>,
|
||||
pub tick: __sdk::__query_builder::Col<BigFishRuntimeRun, u64>,
|
||||
pub created_at: __sdk::__query_builder::Col<BigFishRuntimeRun, __sdk::Timestamp>,
|
||||
pub updated_at: __sdk::__query_builder::Col<BigFishRuntimeRun, __sdk::Timestamp>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for BigFishRuntimeRun {
|
||||
type Cols = BigFishRuntimeRunCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
BigFishRuntimeRunCols {
|
||||
run_id: __sdk::__query_builder::Col::new(table_name, "run_id"),
|
||||
session_id: __sdk::__query_builder::Col::new(table_name, "session_id"),
|
||||
owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"),
|
||||
status: __sdk::__query_builder::Col::new(table_name, "status"),
|
||||
snapshot_json: __sdk::__query_builder::Col::new(table_name, "snapshot_json"),
|
||||
last_input_x: __sdk::__query_builder::Col::new(table_name, "last_input_x"),
|
||||
last_input_y: __sdk::__query_builder::Col::new(table_name, "last_input_y"),
|
||||
tick: __sdk::__query_builder::Col::new(table_name, "tick"),
|
||||
created_at: __sdk::__query_builder::Col::new(table_name, "created_at"),
|
||||
updated_at: __sdk::__query_builder::Col::new(table_name, "updated_at"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indexed column accessor struct for the table `BigFishRuntimeRun`.
|
||||
///
|
||||
/// Provides typed access to indexed columns for query building.
|
||||
pub struct BigFishRuntimeRunIxCols {
|
||||
pub owner_user_id: __sdk::__query_builder::IxCol<BigFishRuntimeRun, String>,
|
||||
pub run_id: __sdk::__query_builder::IxCol<BigFishRuntimeRun, String>,
|
||||
pub session_id: __sdk::__query_builder::IxCol<BigFishRuntimeRun, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasIxCols for BigFishRuntimeRun {
|
||||
type IxCols = BigFishRuntimeRunIxCols;
|
||||
fn ix_cols(table_name: &'static str) -> Self::IxCols {
|
||||
BigFishRuntimeRunIxCols {
|
||||
owner_user_id: __sdk::__query_builder::IxCol::new(table_name, "owner_user_id"),
|
||||
run_id: __sdk::__query_builder::IxCol::new(table_name, "run_id"),
|
||||
session_id: __sdk::__query_builder::IxCol::new(table_name, "session_id"),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::CanBeLookupTable for BigFishRuntimeRun {}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_run_status_type::BigFishRunStatus;
|
||||
use super::big_fish_runtime_entity_type::BigFishRuntimeEntity;
|
||||
use super::big_fish_vector_2_type::BigFishVector2;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishRuntimeSnapshot {
|
||||
pub run_id: String,
|
||||
pub session_id: String,
|
||||
pub status: BigFishRunStatus,
|
||||
pub tick: u64,
|
||||
pub player_level: u32,
|
||||
pub win_level: u32,
|
||||
pub leader_entity_id: Option::<String>,
|
||||
pub owned_entities: Vec::<BigFishRuntimeEntity>,
|
||||
pub wild_entities: Vec::<BigFishRuntimeEntity>,
|
||||
pub camera_center: BigFishVector2,
|
||||
pub last_input: BigFishVector2,
|
||||
pub event_log: Vec::<String>,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishRuntimeSnapshot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishSessionCreateInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub seed_text: String,
|
||||
pub welcome_message_id: String,
|
||||
pub welcome_message_text: String,
|
||||
pub created_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishSessionCreateInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishSessionGetInput {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishSessionGetInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_session_snapshot_type::BigFishSessionSnapshot;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishSessionProcedureResult {
|
||||
pub ok: bool,
|
||||
pub session: Option::<BigFishSessionSnapshot>,
|
||||
pub error_message: Option::<String>,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishSessionProcedureResult {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_creation_stage_type::BigFishCreationStage;
|
||||
use super::big_fish_anchor_pack_type::BigFishAnchorPack;
|
||||
use super::big_fish_game_draft_type::BigFishGameDraft;
|
||||
use super::big_fish_asset_slot_snapshot_type::BigFishAssetSlotSnapshot;
|
||||
use super::big_fish_asset_coverage_type::BigFishAssetCoverage;
|
||||
use super::big_fish_agent_message_snapshot_type::BigFishAgentMessageSnapshot;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishSessionSnapshot {
|
||||
pub session_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub seed_text: String,
|
||||
pub current_turn: u32,
|
||||
pub progress_percent: u32,
|
||||
pub stage: BigFishCreationStage,
|
||||
pub anchor_pack: BigFishAnchorPack,
|
||||
pub draft: Option::<BigFishGameDraft>,
|
||||
pub asset_slots: Vec::<BigFishAssetSlotSnapshot>,
|
||||
pub asset_coverage: BigFishAssetCoverage,
|
||||
pub messages: Vec::<BigFishAgentMessageSnapshot>,
|
||||
pub last_assistant_reply: Option::<String>,
|
||||
pub publish_ready: bool,
|
||||
pub created_at_micros: i64,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishSessionSnapshot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct BigFishVector2 {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for BigFishVector2 {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_draft_compile_input_type::BigFishDraftCompileInput;
|
||||
use super::big_fish_session_procedure_result_type::BigFishSessionProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct CompileBigFishDraftArgs {
|
||||
pub input: BigFishDraftCompileInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for CompileBigFishDraftArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `compile_big_fish_draft`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait compile_big_fish_draft {
|
||||
fn compile_big_fish_draft(&self, input: BigFishDraftCompileInput,
|
||||
) {
|
||||
self.compile_big_fish_draft_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn compile_big_fish_draft_then(
|
||||
&self,
|
||||
input: BigFishDraftCompileInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl compile_big_fish_draft for super::RemoteProcedures {
|
||||
fn compile_big_fish_draft_then(
|
||||
&self,
|
||||
input: BigFishDraftCompileInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, BigFishSessionProcedureResult>(
|
||||
"compile_big_fish_draft",
|
||||
CompileBigFishDraftArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_draft_compile_input_type::PuzzleDraftCompileInput;
|
||||
use super::puzzle_agent_session_procedure_result_type::PuzzleAgentSessionProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct CompilePuzzleAgentDraftArgs {
|
||||
pub input: PuzzleDraftCompileInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for CompilePuzzleAgentDraftArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `compile_puzzle_agent_draft`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait compile_puzzle_agent_draft {
|
||||
fn compile_puzzle_agent_draft(&self, input: PuzzleDraftCompileInput,
|
||||
) {
|
||||
self.compile_puzzle_agent_draft_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn compile_puzzle_agent_draft_then(
|
||||
&self,
|
||||
input: PuzzleDraftCompileInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleAgentSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl compile_puzzle_agent_draft for super::RemoteProcedures {
|
||||
fn compile_puzzle_agent_draft_then(
|
||||
&self,
|
||||
input: PuzzleDraftCompileInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleAgentSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleAgentSessionProcedureResult>(
|
||||
"compile_puzzle_agent_draft",
|
||||
CompilePuzzleAgentDraftArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_session_procedure_result_type::BigFishSessionProcedureResult;
|
||||
use super::big_fish_session_create_input_type::BigFishSessionCreateInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct CreateBigFishSessionArgs {
|
||||
pub input: BigFishSessionCreateInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for CreateBigFishSessionArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `create_big_fish_session`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait create_big_fish_session {
|
||||
fn create_big_fish_session(&self, input: BigFishSessionCreateInput,
|
||||
) {
|
||||
self.create_big_fish_session_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn create_big_fish_session_then(
|
||||
&self,
|
||||
input: BigFishSessionCreateInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl create_big_fish_session for super::RemoteProcedures {
|
||||
fn create_big_fish_session_then(
|
||||
&self,
|
||||
input: BigFishSessionCreateInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, BigFishSessionProcedureResult>(
|
||||
"create_big_fish_session",
|
||||
CreateBigFishSessionArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_agent_session_procedure_result_type::PuzzleAgentSessionProcedureResult;
|
||||
use super::puzzle_agent_session_create_input_type::PuzzleAgentSessionCreateInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct CreatePuzzleAgentSessionArgs {
|
||||
pub input: PuzzleAgentSessionCreateInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for CreatePuzzleAgentSessionArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `create_puzzle_agent_session`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait create_puzzle_agent_session {
|
||||
fn create_puzzle_agent_session(&self, input: PuzzleAgentSessionCreateInput,
|
||||
) {
|
||||
self.create_puzzle_agent_session_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn create_puzzle_agent_session_then(
|
||||
&self,
|
||||
input: PuzzleAgentSessionCreateInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleAgentSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl create_puzzle_agent_session for super::RemoteProcedures {
|
||||
fn create_puzzle_agent_session_then(
|
||||
&self,
|
||||
input: PuzzleAgentSessionCreateInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleAgentSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleAgentSessionProcedureResult>(
|
||||
"create_puzzle_agent_session",
|
||||
CreatePuzzleAgentSessionArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_run_procedure_result_type::PuzzleRunProcedureResult;
|
||||
use super::puzzle_run_drag_input_type::PuzzleRunDragInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct DragPuzzlePieceOrGroupArgs {
|
||||
pub input: PuzzleRunDragInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for DragPuzzlePieceOrGroupArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `drag_puzzle_piece_or_group`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait drag_puzzle_piece_or_group {
|
||||
fn drag_puzzle_piece_or_group(&self, input: PuzzleRunDragInput,
|
||||
) {
|
||||
self.drag_puzzle_piece_or_group_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn drag_puzzle_piece_or_group_then(
|
||||
&self,
|
||||
input: PuzzleRunDragInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl drag_puzzle_piece_or_group for super::RemoteProcedures {
|
||||
fn drag_puzzle_piece_or_group_then(
|
||||
&self,
|
||||
input: PuzzleRunDragInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleRunProcedureResult>(
|
||||
"drag_puzzle_piece_or_group",
|
||||
DragPuzzlePieceOrGroupArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_session_procedure_result_type::BigFishSessionProcedureResult;
|
||||
use super::big_fish_asset_generate_input_type::BigFishAssetGenerateInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct GenerateBigFishAssetArgs {
|
||||
pub input: BigFishAssetGenerateInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for GenerateBigFishAssetArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `generate_big_fish_asset`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait generate_big_fish_asset {
|
||||
fn generate_big_fish_asset(&self, input: BigFishAssetGenerateInput,
|
||||
) {
|
||||
self.generate_big_fish_asset_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn generate_big_fish_asset_then(
|
||||
&self,
|
||||
input: BigFishAssetGenerateInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl generate_big_fish_asset for super::RemoteProcedures {
|
||||
fn generate_big_fish_asset_then(
|
||||
&self,
|
||||
input: BigFishAssetGenerateInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, BigFishSessionProcedureResult>(
|
||||
"generate_big_fish_asset",
|
||||
GenerateBigFishAssetArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_run_get_input_type::BigFishRunGetInput;
|
||||
use super::big_fish_run_procedure_result_type::BigFishRunProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct GetBigFishRunArgs {
|
||||
pub input: BigFishRunGetInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for GetBigFishRunArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `get_big_fish_run`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait get_big_fish_run {
|
||||
fn get_big_fish_run(&self, input: BigFishRunGetInput,
|
||||
) {
|
||||
self.get_big_fish_run_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn get_big_fish_run_then(
|
||||
&self,
|
||||
input: BigFishRunGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl get_big_fish_run for super::RemoteProcedures {
|
||||
fn get_big_fish_run_then(
|
||||
&self,
|
||||
input: BigFishRunGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, BigFishRunProcedureResult>(
|
||||
"get_big_fish_run",
|
||||
GetBigFishRunArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_session_procedure_result_type::BigFishSessionProcedureResult;
|
||||
use super::big_fish_session_get_input_type::BigFishSessionGetInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct GetBigFishSessionArgs {
|
||||
pub input: BigFishSessionGetInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for GetBigFishSessionArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `get_big_fish_session`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait get_big_fish_session {
|
||||
fn get_big_fish_session(&self, input: BigFishSessionGetInput,
|
||||
) {
|
||||
self.get_big_fish_session_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn get_big_fish_session_then(
|
||||
&self,
|
||||
input: BigFishSessionGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl get_big_fish_session for super::RemoteProcedures {
|
||||
fn get_big_fish_session_then(
|
||||
&self,
|
||||
input: BigFishSessionGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, BigFishSessionProcedureResult>(
|
||||
"get_big_fish_session",
|
||||
GetBigFishSessionArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_agent_session_procedure_result_type::PuzzleAgentSessionProcedureResult;
|
||||
use super::puzzle_agent_session_get_input_type::PuzzleAgentSessionGetInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct GetPuzzleAgentSessionArgs {
|
||||
pub input: PuzzleAgentSessionGetInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for GetPuzzleAgentSessionArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `get_puzzle_agent_session`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait get_puzzle_agent_session {
|
||||
fn get_puzzle_agent_session(&self, input: PuzzleAgentSessionGetInput,
|
||||
) {
|
||||
self.get_puzzle_agent_session_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn get_puzzle_agent_session_then(
|
||||
&self,
|
||||
input: PuzzleAgentSessionGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleAgentSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl get_puzzle_agent_session for super::RemoteProcedures {
|
||||
fn get_puzzle_agent_session_then(
|
||||
&self,
|
||||
input: PuzzleAgentSessionGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleAgentSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleAgentSessionProcedureResult>(
|
||||
"get_puzzle_agent_session",
|
||||
GetPuzzleAgentSessionArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_work_get_input_type::PuzzleWorkGetInput;
|
||||
use super::puzzle_work_procedure_result_type::PuzzleWorkProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct GetPuzzleGalleryDetailArgs {
|
||||
pub input: PuzzleWorkGetInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for GetPuzzleGalleryDetailArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `get_puzzle_gallery_detail`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait get_puzzle_gallery_detail {
|
||||
fn get_puzzle_gallery_detail(&self, input: PuzzleWorkGetInput,
|
||||
) {
|
||||
self.get_puzzle_gallery_detail_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn get_puzzle_gallery_detail_then(
|
||||
&self,
|
||||
input: PuzzleWorkGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorkProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl get_puzzle_gallery_detail for super::RemoteProcedures {
|
||||
fn get_puzzle_gallery_detail_then(
|
||||
&self,
|
||||
input: PuzzleWorkGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorkProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleWorkProcedureResult>(
|
||||
"get_puzzle_gallery_detail",
|
||||
GetPuzzleGalleryDetailArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_run_procedure_result_type::PuzzleRunProcedureResult;
|
||||
use super::puzzle_run_get_input_type::PuzzleRunGetInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct GetPuzzleRunArgs {
|
||||
pub input: PuzzleRunGetInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for GetPuzzleRunArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `get_puzzle_run`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait get_puzzle_run {
|
||||
fn get_puzzle_run(&self, input: PuzzleRunGetInput,
|
||||
) {
|
||||
self.get_puzzle_run_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn get_puzzle_run_then(
|
||||
&self,
|
||||
input: PuzzleRunGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl get_puzzle_run for super::RemoteProcedures {
|
||||
fn get_puzzle_run_then(
|
||||
&self,
|
||||
input: PuzzleRunGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleRunProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleRunProcedureResult>(
|
||||
"get_puzzle_run",
|
||||
GetPuzzleRunArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_work_get_input_type::PuzzleWorkGetInput;
|
||||
use super::puzzle_work_procedure_result_type::PuzzleWorkProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct GetPuzzleWorkDetailArgs {
|
||||
pub input: PuzzleWorkGetInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for GetPuzzleWorkDetailArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `get_puzzle_work_detail`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait get_puzzle_work_detail {
|
||||
fn get_puzzle_work_detail(&self, input: PuzzleWorkGetInput,
|
||||
) {
|
||||
self.get_puzzle_work_detail_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn get_puzzle_work_detail_then(
|
||||
&self,
|
||||
input: PuzzleWorkGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorkProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl get_puzzle_work_detail for super::RemoteProcedures {
|
||||
fn get_puzzle_work_detail_then(
|
||||
&self,
|
||||
input: PuzzleWorkGetInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorkProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleWorkProcedureResult>(
|
||||
"get_puzzle_work_detail",
|
||||
GetPuzzleWorkDetailArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_works_procedure_result_type::PuzzleWorksProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct ListPuzzleGalleryArgs {
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for ListPuzzleGalleryArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `list_puzzle_gallery`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait list_puzzle_gallery {
|
||||
fn list_puzzle_gallery(&self, ) {
|
||||
self.list_puzzle_gallery_then( |_, _| {});
|
||||
}
|
||||
|
||||
fn list_puzzle_gallery_then(
|
||||
&self,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorksProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl list_puzzle_gallery for super::RemoteProcedures {
|
||||
fn list_puzzle_gallery_then(
|
||||
&self,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorksProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleWorksProcedureResult>(
|
||||
"list_puzzle_gallery",
|
||||
ListPuzzleGalleryArgs { },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::puzzle_works_procedure_result_type::PuzzleWorksProcedureResult;
|
||||
use super::puzzle_works_list_input_type::PuzzleWorksListInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct ListPuzzleWorksArgs {
|
||||
pub input: PuzzleWorksListInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for ListPuzzleWorksArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `list_puzzle_works`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait list_puzzle_works {
|
||||
fn list_puzzle_works(&self, input: PuzzleWorksListInput,
|
||||
) {
|
||||
self.list_puzzle_works_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn list_puzzle_works_then(
|
||||
&self,
|
||||
input: PuzzleWorksListInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorksProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl list_puzzle_works for super::RemoteProcedures {
|
||||
fn list_puzzle_works_then(
|
||||
&self,
|
||||
input: PuzzleWorksListInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<PuzzleWorksProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, PuzzleWorksProcedureResult>(
|
||||
"list_puzzle_works",
|
||||
ListPuzzleWorksArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,41 @@ pub mod battle_state_procedure_result_type;
|
||||
pub mod battle_state_query_input_type;
|
||||
pub mod battle_state_snapshot_type;
|
||||
pub mod battle_status_type;
|
||||
pub mod big_fish_agent_message_type;
|
||||
pub mod big_fish_agent_message_kind_type;
|
||||
pub mod big_fish_agent_message_role_type;
|
||||
pub mod big_fish_agent_message_snapshot_type;
|
||||
pub mod big_fish_anchor_item_type;
|
||||
pub mod big_fish_anchor_pack_type;
|
||||
pub mod big_fish_anchor_status_type;
|
||||
pub mod big_fish_asset_coverage_type;
|
||||
pub mod big_fish_asset_generate_input_type;
|
||||
pub mod big_fish_asset_kind_type;
|
||||
pub mod big_fish_asset_slot_type;
|
||||
pub mod big_fish_asset_slot_snapshot_type;
|
||||
pub mod big_fish_asset_status_type;
|
||||
pub mod big_fish_background_blueprint_type;
|
||||
pub mod big_fish_creation_session_type;
|
||||
pub mod big_fish_creation_stage_type;
|
||||
pub mod big_fish_draft_compile_input_type;
|
||||
pub mod big_fish_game_draft_type;
|
||||
pub mod big_fish_level_blueprint_type;
|
||||
pub mod big_fish_message_submit_input_type;
|
||||
pub mod big_fish_publish_input_type;
|
||||
pub mod big_fish_run_get_input_type;
|
||||
pub mod big_fish_run_input_submit_input_type;
|
||||
pub mod big_fish_run_procedure_result_type;
|
||||
pub mod big_fish_run_start_input_type;
|
||||
pub mod big_fish_run_status_type;
|
||||
pub mod big_fish_runtime_entity_type;
|
||||
pub mod big_fish_runtime_params_type;
|
||||
pub mod big_fish_runtime_run_type;
|
||||
pub mod big_fish_runtime_snapshot_type;
|
||||
pub mod big_fish_session_create_input_type;
|
||||
pub mod big_fish_session_get_input_type;
|
||||
pub mod big_fish_session_procedure_result_type;
|
||||
pub mod big_fish_session_snapshot_type;
|
||||
pub mod big_fish_vector_2_type;
|
||||
pub mod chapter_pace_band_type;
|
||||
pub mod chapter_progression_type;
|
||||
pub mod chapter_progression_get_input_type;
|
||||
@@ -142,6 +177,33 @@ pub mod profile_dashboard_state_type;
|
||||
pub mod profile_played_world_type;
|
||||
pub mod profile_save_archive_type;
|
||||
pub mod profile_wallet_ledger_type;
|
||||
pub mod puzzle_agent_message_kind_type;
|
||||
pub mod puzzle_agent_message_role_type;
|
||||
pub mod puzzle_agent_message_row_type;
|
||||
pub mod puzzle_agent_message_submit_input_type;
|
||||
pub mod puzzle_agent_session_create_input_type;
|
||||
pub mod puzzle_agent_session_get_input_type;
|
||||
pub mod puzzle_agent_session_procedure_result_type;
|
||||
pub mod puzzle_agent_session_row_type;
|
||||
pub mod puzzle_agent_stage_type;
|
||||
pub mod puzzle_draft_compile_input_type;
|
||||
pub mod puzzle_generated_images_save_input_type;
|
||||
pub mod puzzle_publication_status_type;
|
||||
pub mod puzzle_publish_input_type;
|
||||
pub mod puzzle_run_drag_input_type;
|
||||
pub mod puzzle_run_get_input_type;
|
||||
pub mod puzzle_run_next_level_input_type;
|
||||
pub mod puzzle_run_procedure_result_type;
|
||||
pub mod puzzle_run_start_input_type;
|
||||
pub mod puzzle_run_swap_input_type;
|
||||
pub mod puzzle_runtime_run_row_type;
|
||||
pub mod puzzle_select_cover_image_input_type;
|
||||
pub mod puzzle_work_get_input_type;
|
||||
pub mod puzzle_work_procedure_result_type;
|
||||
pub mod puzzle_work_profile_row_type;
|
||||
pub mod puzzle_work_upsert_input_type;
|
||||
pub mod puzzle_works_list_input_type;
|
||||
pub mod puzzle_works_procedure_result_type;
|
||||
pub mod quest_completion_ack_input_type;
|
||||
pub mod quest_hostile_npc_defeated_signal_type;
|
||||
pub mod quest_item_delivered_signal_type;
|
||||
@@ -271,6 +333,10 @@ pub mod ai_text_chunk_table;
|
||||
pub mod asset_entity_binding_table;
|
||||
pub mod asset_object_table;
|
||||
pub mod battle_state_table;
|
||||
pub mod big_fish_agent_message_table;
|
||||
pub mod big_fish_asset_slot_table;
|
||||
pub mod big_fish_creation_session_table;
|
||||
pub mod big_fish_runtime_run_table;
|
||||
pub mod chapter_progression_table;
|
||||
pub mod custom_world_agent_message_table;
|
||||
pub mod custom_world_agent_operation_table;
|
||||
@@ -286,6 +352,10 @@ pub mod profile_dashboard_state_table;
|
||||
pub mod profile_played_world_table;
|
||||
pub mod profile_save_archive_table;
|
||||
pub mod profile_wallet_ledger_table;
|
||||
pub mod puzzle_agent_message_table;
|
||||
pub mod puzzle_agent_session_table;
|
||||
pub mod puzzle_runtime_run_table;
|
||||
pub mod puzzle_work_profile_table;
|
||||
pub mod quest_log_table;
|
||||
pub mod quest_record_table;
|
||||
pub mod runtime_setting_table;
|
||||
@@ -294,6 +364,7 @@ pub mod story_event_table;
|
||||
pub mod story_session_table;
|
||||
pub mod treasure_record_table;
|
||||
pub mod user_browse_history_table;
|
||||
pub mod advance_puzzle_next_level_procedure;
|
||||
pub mod append_ai_text_chunk_and_return_procedure;
|
||||
pub mod apply_chapter_progression_ledger_entry_and_return_procedure;
|
||||
pub mod attach_ai_result_reference_and_return_procedure;
|
||||
@@ -301,18 +372,26 @@ pub mod begin_story_session_and_return_procedure;
|
||||
pub mod bind_asset_object_to_entity_and_return_procedure;
|
||||
pub mod cancel_ai_task_and_return_procedure;
|
||||
pub mod clear_platform_browse_history_and_return_procedure;
|
||||
pub mod compile_big_fish_draft_procedure;
|
||||
pub mod compile_custom_world_published_profile_procedure;
|
||||
pub mod compile_puzzle_agent_draft_procedure;
|
||||
pub mod complete_ai_stage_and_return_procedure;
|
||||
pub mod complete_ai_task_and_return_procedure;
|
||||
pub mod confirm_asset_object_and_return_procedure;
|
||||
pub mod continue_story_and_return_procedure;
|
||||
pub mod create_ai_task_and_return_procedure;
|
||||
pub mod create_battle_state_and_return_procedure;
|
||||
pub mod create_big_fish_session_procedure;
|
||||
pub mod create_custom_world_agent_session_procedure;
|
||||
pub mod create_puzzle_agent_session_procedure;
|
||||
pub mod delete_runtime_snapshot_and_return_procedure;
|
||||
pub mod drag_puzzle_piece_or_group_procedure;
|
||||
pub mod execute_custom_world_agent_action_procedure;
|
||||
pub mod fail_ai_task_and_return_procedure;
|
||||
pub mod generate_big_fish_asset_procedure;
|
||||
pub mod get_battle_state_procedure;
|
||||
pub mod get_big_fish_run_procedure;
|
||||
pub mod get_big_fish_session_procedure;
|
||||
pub mod get_chapter_progression_procedure;
|
||||
pub mod get_custom_world_agent_card_detail_procedure;
|
||||
pub mod get_custom_world_agent_operation_procedure;
|
||||
@@ -322,6 +401,10 @@ pub mod get_custom_world_library_detail_procedure;
|
||||
pub mod get_player_progression_or_default_procedure;
|
||||
pub mod get_profile_dashboard_procedure;
|
||||
pub mod get_profile_play_stats_procedure;
|
||||
pub mod get_puzzle_agent_session_procedure;
|
||||
pub mod get_puzzle_gallery_detail_procedure;
|
||||
pub mod get_puzzle_run_procedure;
|
||||
pub mod get_puzzle_work_detail_procedure;
|
||||
pub mod get_runtime_inventory_state_procedure;
|
||||
pub mod get_runtime_setting_or_default_procedure;
|
||||
pub mod get_runtime_snapshot_procedure;
|
||||
@@ -333,16 +416,29 @@ pub mod list_custom_world_works_procedure;
|
||||
pub mod list_platform_browse_history_procedure;
|
||||
pub mod list_profile_save_archives_procedure;
|
||||
pub mod list_profile_wallet_ledger_procedure;
|
||||
pub mod list_puzzle_gallery_procedure;
|
||||
pub mod list_puzzle_works_procedure;
|
||||
pub mod publish_big_fish_game_procedure;
|
||||
pub mod publish_custom_world_profile_and_return_procedure;
|
||||
pub mod publish_custom_world_world_procedure;
|
||||
pub mod publish_puzzle_work_procedure;
|
||||
pub mod resolve_combat_action_and_return_procedure;
|
||||
pub mod resolve_npc_battle_interaction_and_return_procedure;
|
||||
pub mod resolve_npc_interaction_and_return_procedure;
|
||||
pub mod resolve_npc_social_action_and_return_procedure;
|
||||
pub mod resolve_treasure_interaction_and_return_procedure;
|
||||
pub mod resume_profile_save_archive_and_return_procedure;
|
||||
pub mod save_puzzle_generated_images_procedure;
|
||||
pub mod select_puzzle_cover_image_procedure;
|
||||
pub mod start_big_fish_run_procedure;
|
||||
pub mod start_puzzle_run_procedure;
|
||||
pub mod submit_big_fish_input_procedure;
|
||||
pub mod submit_big_fish_message_procedure;
|
||||
pub mod submit_custom_world_agent_message_procedure;
|
||||
pub mod submit_puzzle_agent_message_procedure;
|
||||
pub mod swap_puzzle_pieces_procedure;
|
||||
pub mod unpublish_custom_world_profile_and_return_procedure;
|
||||
pub mod update_puzzle_work_procedure;
|
||||
pub mod upsert_chapter_progression_and_return_procedure;
|
||||
pub mod upsert_custom_world_profile_and_return_procedure;
|
||||
pub mod upsert_npc_state_and_return_procedure;
|
||||
@@ -390,6 +486,41 @@ pub use battle_state_procedure_result_type::BattleStateProcedureResult;
|
||||
pub use battle_state_query_input_type::BattleStateQueryInput;
|
||||
pub use battle_state_snapshot_type::BattleStateSnapshot;
|
||||
pub use battle_status_type::BattleStatus;
|
||||
pub use big_fish_agent_message_type::BigFishAgentMessage;
|
||||
pub use big_fish_agent_message_kind_type::BigFishAgentMessageKind;
|
||||
pub use big_fish_agent_message_role_type::BigFishAgentMessageRole;
|
||||
pub use big_fish_agent_message_snapshot_type::BigFishAgentMessageSnapshot;
|
||||
pub use big_fish_anchor_item_type::BigFishAnchorItem;
|
||||
pub use big_fish_anchor_pack_type::BigFishAnchorPack;
|
||||
pub use big_fish_anchor_status_type::BigFishAnchorStatus;
|
||||
pub use big_fish_asset_coverage_type::BigFishAssetCoverage;
|
||||
pub use big_fish_asset_generate_input_type::BigFishAssetGenerateInput;
|
||||
pub use big_fish_asset_kind_type::BigFishAssetKind;
|
||||
pub use big_fish_asset_slot_type::BigFishAssetSlot;
|
||||
pub use big_fish_asset_slot_snapshot_type::BigFishAssetSlotSnapshot;
|
||||
pub use big_fish_asset_status_type::BigFishAssetStatus;
|
||||
pub use big_fish_background_blueprint_type::BigFishBackgroundBlueprint;
|
||||
pub use big_fish_creation_session_type::BigFishCreationSession;
|
||||
pub use big_fish_creation_stage_type::BigFishCreationStage;
|
||||
pub use big_fish_draft_compile_input_type::BigFishDraftCompileInput;
|
||||
pub use big_fish_game_draft_type::BigFishGameDraft;
|
||||
pub use big_fish_level_blueprint_type::BigFishLevelBlueprint;
|
||||
pub use big_fish_message_submit_input_type::BigFishMessageSubmitInput;
|
||||
pub use big_fish_publish_input_type::BigFishPublishInput;
|
||||
pub use big_fish_run_get_input_type::BigFishRunGetInput;
|
||||
pub use big_fish_run_input_submit_input_type::BigFishRunInputSubmitInput;
|
||||
pub use big_fish_run_procedure_result_type::BigFishRunProcedureResult;
|
||||
pub use big_fish_run_start_input_type::BigFishRunStartInput;
|
||||
pub use big_fish_run_status_type::BigFishRunStatus;
|
||||
pub use big_fish_runtime_entity_type::BigFishRuntimeEntity;
|
||||
pub use big_fish_runtime_params_type::BigFishRuntimeParams;
|
||||
pub use big_fish_runtime_run_type::BigFishRuntimeRun;
|
||||
pub use big_fish_runtime_snapshot_type::BigFishRuntimeSnapshot;
|
||||
pub use big_fish_session_create_input_type::BigFishSessionCreateInput;
|
||||
pub use big_fish_session_get_input_type::BigFishSessionGetInput;
|
||||
pub use big_fish_session_procedure_result_type::BigFishSessionProcedureResult;
|
||||
pub use big_fish_session_snapshot_type::BigFishSessionSnapshot;
|
||||
pub use big_fish_vector_2_type::BigFishVector2;
|
||||
pub use chapter_pace_band_type::ChapterPaceBand;
|
||||
pub use chapter_progression_type::ChapterProgression;
|
||||
pub use chapter_progression_get_input_type::ChapterProgressionGetInput;
|
||||
@@ -481,6 +612,33 @@ pub use profile_dashboard_state_type::ProfileDashboardState;
|
||||
pub use profile_played_world_type::ProfilePlayedWorld;
|
||||
pub use profile_save_archive_type::ProfileSaveArchive;
|
||||
pub use profile_wallet_ledger_type::ProfileWalletLedger;
|
||||
pub use puzzle_agent_message_kind_type::PuzzleAgentMessageKind;
|
||||
pub use puzzle_agent_message_role_type::PuzzleAgentMessageRole;
|
||||
pub use puzzle_agent_message_row_type::PuzzleAgentMessageRow;
|
||||
pub use puzzle_agent_message_submit_input_type::PuzzleAgentMessageSubmitInput;
|
||||
pub use puzzle_agent_session_create_input_type::PuzzleAgentSessionCreateInput;
|
||||
pub use puzzle_agent_session_get_input_type::PuzzleAgentSessionGetInput;
|
||||
pub use puzzle_agent_session_procedure_result_type::PuzzleAgentSessionProcedureResult;
|
||||
pub use puzzle_agent_session_row_type::PuzzleAgentSessionRow;
|
||||
pub use puzzle_agent_stage_type::PuzzleAgentStage;
|
||||
pub use puzzle_draft_compile_input_type::PuzzleDraftCompileInput;
|
||||
pub use puzzle_generated_images_save_input_type::PuzzleGeneratedImagesSaveInput;
|
||||
pub use puzzle_publication_status_type::PuzzlePublicationStatus;
|
||||
pub use puzzle_publish_input_type::PuzzlePublishInput;
|
||||
pub use puzzle_run_drag_input_type::PuzzleRunDragInput;
|
||||
pub use puzzle_run_get_input_type::PuzzleRunGetInput;
|
||||
pub use puzzle_run_next_level_input_type::PuzzleRunNextLevelInput;
|
||||
pub use puzzle_run_procedure_result_type::PuzzleRunProcedureResult;
|
||||
pub use puzzle_run_start_input_type::PuzzleRunStartInput;
|
||||
pub use puzzle_run_swap_input_type::PuzzleRunSwapInput;
|
||||
pub use puzzle_runtime_run_row_type::PuzzleRuntimeRunRow;
|
||||
pub use puzzle_select_cover_image_input_type::PuzzleSelectCoverImageInput;
|
||||
pub use puzzle_work_get_input_type::PuzzleWorkGetInput;
|
||||
pub use puzzle_work_procedure_result_type::PuzzleWorkProcedureResult;
|
||||
pub use puzzle_work_profile_row_type::PuzzleWorkProfileRow;
|
||||
pub use puzzle_work_upsert_input_type::PuzzleWorkUpsertInput;
|
||||
pub use puzzle_works_list_input_type::PuzzleWorksListInput;
|
||||
pub use puzzle_works_procedure_result_type::PuzzleWorksProcedureResult;
|
||||
pub use quest_completion_ack_input_type::QuestCompletionAckInput;
|
||||
pub use quest_hostile_npc_defeated_signal_type::QuestHostileNpcDefeatedSignal;
|
||||
pub use quest_item_delivered_signal_type::QuestItemDeliveredSignal;
|
||||
@@ -586,6 +744,10 @@ pub use ai_text_chunk_table::*;
|
||||
pub use asset_entity_binding_table::*;
|
||||
pub use asset_object_table::*;
|
||||
pub use battle_state_table::*;
|
||||
pub use big_fish_agent_message_table::*;
|
||||
pub use big_fish_asset_slot_table::*;
|
||||
pub use big_fish_creation_session_table::*;
|
||||
pub use big_fish_runtime_run_table::*;
|
||||
pub use chapter_progression_table::*;
|
||||
pub use custom_world_agent_message_table::*;
|
||||
pub use custom_world_agent_operation_table::*;
|
||||
@@ -601,6 +763,10 @@ pub use profile_dashboard_state_table::*;
|
||||
pub use profile_played_world_table::*;
|
||||
pub use profile_save_archive_table::*;
|
||||
pub use profile_wallet_ledger_table::*;
|
||||
pub use puzzle_agent_message_table::*;
|
||||
pub use puzzle_agent_session_table::*;
|
||||
pub use puzzle_runtime_run_table::*;
|
||||
pub use puzzle_work_profile_table::*;
|
||||
pub use quest_log_table::*;
|
||||
pub use quest_record_table::*;
|
||||
pub use runtime_setting_table::*;
|
||||
@@ -633,6 +799,7 @@ pub use unpublish_custom_world_profile_reducer::unpublish_custom_world_profile;
|
||||
pub use upsert_chapter_progression_reducer::upsert_chapter_progression;
|
||||
pub use upsert_custom_world_profile_reducer::upsert_custom_world_profile;
|
||||
pub use upsert_npc_state_reducer::upsert_npc_state;
|
||||
pub use advance_puzzle_next_level_procedure::advance_puzzle_next_level;
|
||||
pub use append_ai_text_chunk_and_return_procedure::append_ai_text_chunk_and_return;
|
||||
pub use apply_chapter_progression_ledger_entry_and_return_procedure::apply_chapter_progression_ledger_entry_and_return;
|
||||
pub use attach_ai_result_reference_and_return_procedure::attach_ai_result_reference_and_return;
|
||||
@@ -640,18 +807,26 @@ pub use begin_story_session_and_return_procedure::begin_story_session_and_return
|
||||
pub use bind_asset_object_to_entity_and_return_procedure::bind_asset_object_to_entity_and_return;
|
||||
pub use cancel_ai_task_and_return_procedure::cancel_ai_task_and_return;
|
||||
pub use clear_platform_browse_history_and_return_procedure::clear_platform_browse_history_and_return;
|
||||
pub use compile_big_fish_draft_procedure::compile_big_fish_draft;
|
||||
pub use compile_custom_world_published_profile_procedure::compile_custom_world_published_profile;
|
||||
pub use compile_puzzle_agent_draft_procedure::compile_puzzle_agent_draft;
|
||||
pub use complete_ai_stage_and_return_procedure::complete_ai_stage_and_return;
|
||||
pub use complete_ai_task_and_return_procedure::complete_ai_task_and_return;
|
||||
pub use confirm_asset_object_and_return_procedure::confirm_asset_object_and_return;
|
||||
pub use continue_story_and_return_procedure::continue_story_and_return;
|
||||
pub use create_ai_task_and_return_procedure::create_ai_task_and_return;
|
||||
pub use create_battle_state_and_return_procedure::create_battle_state_and_return;
|
||||
pub use create_big_fish_session_procedure::create_big_fish_session;
|
||||
pub use create_custom_world_agent_session_procedure::create_custom_world_agent_session;
|
||||
pub use create_puzzle_agent_session_procedure::create_puzzle_agent_session;
|
||||
pub use delete_runtime_snapshot_and_return_procedure::delete_runtime_snapshot_and_return;
|
||||
pub use drag_puzzle_piece_or_group_procedure::drag_puzzle_piece_or_group;
|
||||
pub use execute_custom_world_agent_action_procedure::execute_custom_world_agent_action;
|
||||
pub use fail_ai_task_and_return_procedure::fail_ai_task_and_return;
|
||||
pub use generate_big_fish_asset_procedure::generate_big_fish_asset;
|
||||
pub use get_battle_state_procedure::get_battle_state;
|
||||
pub use get_big_fish_run_procedure::get_big_fish_run;
|
||||
pub use get_big_fish_session_procedure::get_big_fish_session;
|
||||
pub use get_chapter_progression_procedure::get_chapter_progression;
|
||||
pub use get_custom_world_agent_card_detail_procedure::get_custom_world_agent_card_detail;
|
||||
pub use get_custom_world_agent_operation_procedure::get_custom_world_agent_operation;
|
||||
@@ -661,6 +836,10 @@ pub use get_custom_world_library_detail_procedure::get_custom_world_library_deta
|
||||
pub use get_player_progression_or_default_procedure::get_player_progression_or_default;
|
||||
pub use get_profile_dashboard_procedure::get_profile_dashboard;
|
||||
pub use get_profile_play_stats_procedure::get_profile_play_stats;
|
||||
pub use get_puzzle_agent_session_procedure::get_puzzle_agent_session;
|
||||
pub use get_puzzle_gallery_detail_procedure::get_puzzle_gallery_detail;
|
||||
pub use get_puzzle_run_procedure::get_puzzle_run;
|
||||
pub use get_puzzle_work_detail_procedure::get_puzzle_work_detail;
|
||||
pub use get_runtime_inventory_state_procedure::get_runtime_inventory_state;
|
||||
pub use get_runtime_setting_or_default_procedure::get_runtime_setting_or_default;
|
||||
pub use get_runtime_snapshot_procedure::get_runtime_snapshot;
|
||||
@@ -672,16 +851,29 @@ pub use list_custom_world_works_procedure::list_custom_world_works;
|
||||
pub use list_platform_browse_history_procedure::list_platform_browse_history;
|
||||
pub use list_profile_save_archives_procedure::list_profile_save_archives;
|
||||
pub use list_profile_wallet_ledger_procedure::list_profile_wallet_ledger;
|
||||
pub use list_puzzle_gallery_procedure::list_puzzle_gallery;
|
||||
pub use list_puzzle_works_procedure::list_puzzle_works;
|
||||
pub use publish_big_fish_game_procedure::publish_big_fish_game;
|
||||
pub use publish_custom_world_profile_and_return_procedure::publish_custom_world_profile_and_return;
|
||||
pub use publish_custom_world_world_procedure::publish_custom_world_world;
|
||||
pub use publish_puzzle_work_procedure::publish_puzzle_work;
|
||||
pub use resolve_combat_action_and_return_procedure::resolve_combat_action_and_return;
|
||||
pub use resolve_npc_battle_interaction_and_return_procedure::resolve_npc_battle_interaction_and_return;
|
||||
pub use resolve_npc_interaction_and_return_procedure::resolve_npc_interaction_and_return;
|
||||
pub use resolve_npc_social_action_and_return_procedure::resolve_npc_social_action_and_return;
|
||||
pub use resolve_treasure_interaction_and_return_procedure::resolve_treasure_interaction_and_return;
|
||||
pub use resume_profile_save_archive_and_return_procedure::resume_profile_save_archive_and_return;
|
||||
pub use save_puzzle_generated_images_procedure::save_puzzle_generated_images;
|
||||
pub use select_puzzle_cover_image_procedure::select_puzzle_cover_image;
|
||||
pub use start_big_fish_run_procedure::start_big_fish_run;
|
||||
pub use start_puzzle_run_procedure::start_puzzle_run;
|
||||
pub use submit_big_fish_input_procedure::submit_big_fish_input;
|
||||
pub use submit_big_fish_message_procedure::submit_big_fish_message;
|
||||
pub use submit_custom_world_agent_message_procedure::submit_custom_world_agent_message;
|
||||
pub use submit_puzzle_agent_message_procedure::submit_puzzle_agent_message;
|
||||
pub use swap_puzzle_pieces_procedure::swap_puzzle_pieces;
|
||||
pub use unpublish_custom_world_profile_and_return_procedure::unpublish_custom_world_profile_and_return;
|
||||
pub use update_puzzle_work_procedure::update_puzzle_work;
|
||||
pub use upsert_chapter_progression_and_return_procedure::upsert_chapter_progression_and_return;
|
||||
pub use upsert_custom_world_profile_and_return_procedure::upsert_custom_world_profile_and_return;
|
||||
pub use upsert_npc_state_and_return_procedure::upsert_npc_state_and_return;
|
||||
@@ -945,6 +1137,10 @@ pub struct DbUpdate {
|
||||
asset_entity_binding: __sdk::TableUpdate<AssetEntityBinding>,
|
||||
asset_object: __sdk::TableUpdate<AssetObject>,
|
||||
battle_state: __sdk::TableUpdate<BattleState>,
|
||||
big_fish_agent_message: __sdk::TableUpdate<BigFishAgentMessage>,
|
||||
big_fish_asset_slot: __sdk::TableUpdate<BigFishAssetSlot>,
|
||||
big_fish_creation_session: __sdk::TableUpdate<BigFishCreationSession>,
|
||||
big_fish_runtime_run: __sdk::TableUpdate<BigFishRuntimeRun>,
|
||||
chapter_progression: __sdk::TableUpdate<ChapterProgression>,
|
||||
custom_world_agent_message: __sdk::TableUpdate<CustomWorldAgentMessage>,
|
||||
custom_world_agent_operation: __sdk::TableUpdate<CustomWorldAgentOperation>,
|
||||
@@ -960,6 +1156,10 @@ pub struct DbUpdate {
|
||||
profile_played_world: __sdk::TableUpdate<ProfilePlayedWorld>,
|
||||
profile_save_archive: __sdk::TableUpdate<ProfileSaveArchive>,
|
||||
profile_wallet_ledger: __sdk::TableUpdate<ProfileWalletLedger>,
|
||||
puzzle_agent_message: __sdk::TableUpdate<PuzzleAgentMessageRow>,
|
||||
puzzle_agent_session: __sdk::TableUpdate<PuzzleAgentSessionRow>,
|
||||
puzzle_runtime_run: __sdk::TableUpdate<PuzzleRuntimeRunRow>,
|
||||
puzzle_work_profile: __sdk::TableUpdate<PuzzleWorkProfileRow>,
|
||||
quest_log: __sdk::TableUpdate<QuestLog>,
|
||||
quest_record: __sdk::TableUpdate<QuestRecord>,
|
||||
runtime_setting: __sdk::TableUpdate<RuntimeSetting>,
|
||||
@@ -985,6 +1185,10 @@ impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate {
|
||||
"asset_entity_binding" => db_update.asset_entity_binding.append(asset_entity_binding_table::parse_table_update(table_update)?),
|
||||
"asset_object" => db_update.asset_object.append(asset_object_table::parse_table_update(table_update)?),
|
||||
"battle_state" => db_update.battle_state.append(battle_state_table::parse_table_update(table_update)?),
|
||||
"big_fish_agent_message" => db_update.big_fish_agent_message.append(big_fish_agent_message_table::parse_table_update(table_update)?),
|
||||
"big_fish_asset_slot" => db_update.big_fish_asset_slot.append(big_fish_asset_slot_table::parse_table_update(table_update)?),
|
||||
"big_fish_creation_session" => db_update.big_fish_creation_session.append(big_fish_creation_session_table::parse_table_update(table_update)?),
|
||||
"big_fish_runtime_run" => db_update.big_fish_runtime_run.append(big_fish_runtime_run_table::parse_table_update(table_update)?),
|
||||
"chapter_progression" => db_update.chapter_progression.append(chapter_progression_table::parse_table_update(table_update)?),
|
||||
"custom_world_agent_message" => db_update.custom_world_agent_message.append(custom_world_agent_message_table::parse_table_update(table_update)?),
|
||||
"custom_world_agent_operation" => db_update.custom_world_agent_operation.append(custom_world_agent_operation_table::parse_table_update(table_update)?),
|
||||
@@ -1000,6 +1204,10 @@ impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate {
|
||||
"profile_played_world" => db_update.profile_played_world.append(profile_played_world_table::parse_table_update(table_update)?),
|
||||
"profile_save_archive" => db_update.profile_save_archive.append(profile_save_archive_table::parse_table_update(table_update)?),
|
||||
"profile_wallet_ledger" => db_update.profile_wallet_ledger.append(profile_wallet_ledger_table::parse_table_update(table_update)?),
|
||||
"puzzle_agent_message" => db_update.puzzle_agent_message.append(puzzle_agent_message_table::parse_table_update(table_update)?),
|
||||
"puzzle_agent_session" => db_update.puzzle_agent_session.append(puzzle_agent_session_table::parse_table_update(table_update)?),
|
||||
"puzzle_runtime_run" => db_update.puzzle_runtime_run.append(puzzle_runtime_run_table::parse_table_update(table_update)?),
|
||||
"puzzle_work_profile" => db_update.puzzle_work_profile.append(puzzle_work_profile_table::parse_table_update(table_update)?),
|
||||
"quest_log" => db_update.quest_log.append(quest_log_table::parse_table_update(table_update)?),
|
||||
"quest_record" => db_update.quest_record.append(quest_record_table::parse_table_update(table_update)?),
|
||||
"runtime_setting" => db_update.runtime_setting.append(runtime_setting_table::parse_table_update(table_update)?),
|
||||
@@ -1037,6 +1245,10 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
diff.asset_entity_binding = cache.apply_diff_to_table::<AssetEntityBinding>("asset_entity_binding", &self.asset_entity_binding).with_updates_by_pk(|row| &row.binding_id);
|
||||
diff.asset_object = cache.apply_diff_to_table::<AssetObject>("asset_object", &self.asset_object).with_updates_by_pk(|row| &row.asset_object_id);
|
||||
diff.battle_state = cache.apply_diff_to_table::<BattleState>("battle_state", &self.battle_state).with_updates_by_pk(|row| &row.battle_state_id);
|
||||
diff.big_fish_agent_message = cache.apply_diff_to_table::<BigFishAgentMessage>("big_fish_agent_message", &self.big_fish_agent_message).with_updates_by_pk(|row| &row.message_id);
|
||||
diff.big_fish_asset_slot = cache.apply_diff_to_table::<BigFishAssetSlot>("big_fish_asset_slot", &self.big_fish_asset_slot).with_updates_by_pk(|row| &row.slot_id);
|
||||
diff.big_fish_creation_session = cache.apply_diff_to_table::<BigFishCreationSession>("big_fish_creation_session", &self.big_fish_creation_session).with_updates_by_pk(|row| &row.session_id);
|
||||
diff.big_fish_runtime_run = cache.apply_diff_to_table::<BigFishRuntimeRun>("big_fish_runtime_run", &self.big_fish_runtime_run).with_updates_by_pk(|row| &row.run_id);
|
||||
diff.chapter_progression = cache.apply_diff_to_table::<ChapterProgression>("chapter_progression", &self.chapter_progression).with_updates_by_pk(|row| &row.chapter_progression_id);
|
||||
diff.custom_world_agent_message = cache.apply_diff_to_table::<CustomWorldAgentMessage>("custom_world_agent_message", &self.custom_world_agent_message).with_updates_by_pk(|row| &row.message_id);
|
||||
diff.custom_world_agent_operation = cache.apply_diff_to_table::<CustomWorldAgentOperation>("custom_world_agent_operation", &self.custom_world_agent_operation).with_updates_by_pk(|row| &row.operation_id);
|
||||
@@ -1052,6 +1264,10 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
diff.profile_played_world = cache.apply_diff_to_table::<ProfilePlayedWorld>("profile_played_world", &self.profile_played_world).with_updates_by_pk(|row| &row.played_world_id);
|
||||
diff.profile_save_archive = cache.apply_diff_to_table::<ProfileSaveArchive>("profile_save_archive", &self.profile_save_archive).with_updates_by_pk(|row| &row.archive_id);
|
||||
diff.profile_wallet_ledger = cache.apply_diff_to_table::<ProfileWalletLedger>("profile_wallet_ledger", &self.profile_wallet_ledger).with_updates_by_pk(|row| &row.wallet_ledger_id);
|
||||
diff.puzzle_agent_message = cache.apply_diff_to_table::<PuzzleAgentMessageRow>("puzzle_agent_message", &self.puzzle_agent_message).with_updates_by_pk(|row| &row.message_id);
|
||||
diff.puzzle_agent_session = cache.apply_diff_to_table::<PuzzleAgentSessionRow>("puzzle_agent_session", &self.puzzle_agent_session).with_updates_by_pk(|row| &row.session_id);
|
||||
diff.puzzle_runtime_run = cache.apply_diff_to_table::<PuzzleRuntimeRunRow>("puzzle_runtime_run", &self.puzzle_runtime_run).with_updates_by_pk(|row| &row.run_id);
|
||||
diff.puzzle_work_profile = cache.apply_diff_to_table::<PuzzleWorkProfileRow>("puzzle_work_profile", &self.puzzle_work_profile).with_updates_by_pk(|row| &row.profile_id);
|
||||
diff.quest_log = cache.apply_diff_to_table::<QuestLog>("quest_log", &self.quest_log).with_updates_by_pk(|row| &row.log_id);
|
||||
diff.quest_record = cache.apply_diff_to_table::<QuestRecord>("quest_record", &self.quest_record).with_updates_by_pk(|row| &row.quest_id);
|
||||
diff.runtime_setting = cache.apply_diff_to_table::<RuntimeSetting>("runtime_setting", &self.runtime_setting).with_updates_by_pk(|row| &row.user_id);
|
||||
@@ -1074,6 +1290,10 @@ for table_rows in raw.tables {
|
||||
"asset_entity_binding" => db_update.asset_entity_binding.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"asset_object" => db_update.asset_object.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"battle_state" => db_update.battle_state.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"big_fish_agent_message" => db_update.big_fish_agent_message.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"big_fish_asset_slot" => db_update.big_fish_asset_slot.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"big_fish_creation_session" => db_update.big_fish_creation_session.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"big_fish_runtime_run" => db_update.big_fish_runtime_run.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"chapter_progression" => db_update.chapter_progression.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"custom_world_agent_message" => db_update.custom_world_agent_message.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"custom_world_agent_operation" => db_update.custom_world_agent_operation.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
@@ -1089,6 +1309,10 @@ for table_rows in raw.tables {
|
||||
"profile_played_world" => db_update.profile_played_world.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"profile_save_archive" => db_update.profile_save_archive.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"profile_wallet_ledger" => db_update.profile_wallet_ledger.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"puzzle_agent_message" => db_update.puzzle_agent_message.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"puzzle_agent_session" => db_update.puzzle_agent_session.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"puzzle_runtime_run" => db_update.puzzle_runtime_run.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"puzzle_work_profile" => db_update.puzzle_work_profile.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"quest_log" => db_update.quest_log.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"quest_record" => db_update.quest_record.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"runtime_setting" => db_update.runtime_setting.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
@@ -1111,6 +1335,10 @@ for table_rows in raw.tables {
|
||||
"asset_entity_binding" => db_update.asset_entity_binding.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"asset_object" => db_update.asset_object.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"battle_state" => db_update.battle_state.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"big_fish_agent_message" => db_update.big_fish_agent_message.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"big_fish_asset_slot" => db_update.big_fish_asset_slot.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"big_fish_creation_session" => db_update.big_fish_creation_session.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"big_fish_runtime_run" => db_update.big_fish_runtime_run.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"chapter_progression" => db_update.chapter_progression.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"custom_world_agent_message" => db_update.custom_world_agent_message.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"custom_world_agent_operation" => db_update.custom_world_agent_operation.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
@@ -1126,6 +1354,10 @@ for table_rows in raw.tables {
|
||||
"profile_played_world" => db_update.profile_played_world.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"profile_save_archive" => db_update.profile_save_archive.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"profile_wallet_ledger" => db_update.profile_wallet_ledger.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"puzzle_agent_message" => db_update.puzzle_agent_message.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"puzzle_agent_session" => db_update.puzzle_agent_session.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"puzzle_runtime_run" => db_update.puzzle_runtime_run.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"puzzle_work_profile" => db_update.puzzle_work_profile.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"quest_log" => db_update.quest_log.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"quest_record" => db_update.quest_record.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"runtime_setting" => db_update.runtime_setting.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
@@ -1150,6 +1382,10 @@ pub struct AppliedDiff<'r> {
|
||||
asset_entity_binding: __sdk::TableAppliedDiff<'r, AssetEntityBinding>,
|
||||
asset_object: __sdk::TableAppliedDiff<'r, AssetObject>,
|
||||
battle_state: __sdk::TableAppliedDiff<'r, BattleState>,
|
||||
big_fish_agent_message: __sdk::TableAppliedDiff<'r, BigFishAgentMessage>,
|
||||
big_fish_asset_slot: __sdk::TableAppliedDiff<'r, BigFishAssetSlot>,
|
||||
big_fish_creation_session: __sdk::TableAppliedDiff<'r, BigFishCreationSession>,
|
||||
big_fish_runtime_run: __sdk::TableAppliedDiff<'r, BigFishRuntimeRun>,
|
||||
chapter_progression: __sdk::TableAppliedDiff<'r, ChapterProgression>,
|
||||
custom_world_agent_message: __sdk::TableAppliedDiff<'r, CustomWorldAgentMessage>,
|
||||
custom_world_agent_operation: __sdk::TableAppliedDiff<'r, CustomWorldAgentOperation>,
|
||||
@@ -1165,6 +1401,10 @@ pub struct AppliedDiff<'r> {
|
||||
profile_played_world: __sdk::TableAppliedDiff<'r, ProfilePlayedWorld>,
|
||||
profile_save_archive: __sdk::TableAppliedDiff<'r, ProfileSaveArchive>,
|
||||
profile_wallet_ledger: __sdk::TableAppliedDiff<'r, ProfileWalletLedger>,
|
||||
puzzle_agent_message: __sdk::TableAppliedDiff<'r, PuzzleAgentMessageRow>,
|
||||
puzzle_agent_session: __sdk::TableAppliedDiff<'r, PuzzleAgentSessionRow>,
|
||||
puzzle_runtime_run: __sdk::TableAppliedDiff<'r, PuzzleRuntimeRunRow>,
|
||||
puzzle_work_profile: __sdk::TableAppliedDiff<'r, PuzzleWorkProfileRow>,
|
||||
quest_log: __sdk::TableAppliedDiff<'r, QuestLog>,
|
||||
quest_record: __sdk::TableAppliedDiff<'r, QuestRecord>,
|
||||
runtime_setting: __sdk::TableAppliedDiff<'r, RuntimeSetting>,
|
||||
@@ -1190,6 +1430,10 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
|
||||
callbacks.invoke_table_row_callbacks::<AssetEntityBinding>("asset_entity_binding", &self.asset_entity_binding, event);
|
||||
callbacks.invoke_table_row_callbacks::<AssetObject>("asset_object", &self.asset_object, event);
|
||||
callbacks.invoke_table_row_callbacks::<BattleState>("battle_state", &self.battle_state, event);
|
||||
callbacks.invoke_table_row_callbacks::<BigFishAgentMessage>("big_fish_agent_message", &self.big_fish_agent_message, event);
|
||||
callbacks.invoke_table_row_callbacks::<BigFishAssetSlot>("big_fish_asset_slot", &self.big_fish_asset_slot, event);
|
||||
callbacks.invoke_table_row_callbacks::<BigFishCreationSession>("big_fish_creation_session", &self.big_fish_creation_session, event);
|
||||
callbacks.invoke_table_row_callbacks::<BigFishRuntimeRun>("big_fish_runtime_run", &self.big_fish_runtime_run, event);
|
||||
callbacks.invoke_table_row_callbacks::<ChapterProgression>("chapter_progression", &self.chapter_progression, event);
|
||||
callbacks.invoke_table_row_callbacks::<CustomWorldAgentMessage>("custom_world_agent_message", &self.custom_world_agent_message, event);
|
||||
callbacks.invoke_table_row_callbacks::<CustomWorldAgentOperation>("custom_world_agent_operation", &self.custom_world_agent_operation, event);
|
||||
@@ -1205,6 +1449,10 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
|
||||
callbacks.invoke_table_row_callbacks::<ProfilePlayedWorld>("profile_played_world", &self.profile_played_world, event);
|
||||
callbacks.invoke_table_row_callbacks::<ProfileSaveArchive>("profile_save_archive", &self.profile_save_archive, event);
|
||||
callbacks.invoke_table_row_callbacks::<ProfileWalletLedger>("profile_wallet_ledger", &self.profile_wallet_ledger, event);
|
||||
callbacks.invoke_table_row_callbacks::<PuzzleAgentMessageRow>("puzzle_agent_message", &self.puzzle_agent_message, event);
|
||||
callbacks.invoke_table_row_callbacks::<PuzzleAgentSessionRow>("puzzle_agent_session", &self.puzzle_agent_session, event);
|
||||
callbacks.invoke_table_row_callbacks::<PuzzleRuntimeRunRow>("puzzle_runtime_run", &self.puzzle_runtime_run, event);
|
||||
callbacks.invoke_table_row_callbacks::<PuzzleWorkProfileRow>("puzzle_work_profile", &self.puzzle_work_profile, event);
|
||||
callbacks.invoke_table_row_callbacks::<QuestLog>("quest_log", &self.quest_log, event);
|
||||
callbacks.invoke_table_row_callbacks::<QuestRecord>("quest_record", &self.quest_record, event);
|
||||
callbacks.invoke_table_row_callbacks::<RuntimeSetting>("runtime_setting", &self.runtime_setting, event);
|
||||
@@ -1871,6 +2119,10 @@ fn register_tables(client_cache: &mut __sdk::ClientCache<Self>) {
|
||||
asset_entity_binding_table::register_table(client_cache);
|
||||
asset_object_table::register_table(client_cache);
|
||||
battle_state_table::register_table(client_cache);
|
||||
big_fish_agent_message_table::register_table(client_cache);
|
||||
big_fish_asset_slot_table::register_table(client_cache);
|
||||
big_fish_creation_session_table::register_table(client_cache);
|
||||
big_fish_runtime_run_table::register_table(client_cache);
|
||||
chapter_progression_table::register_table(client_cache);
|
||||
custom_world_agent_message_table::register_table(client_cache);
|
||||
custom_world_agent_operation_table::register_table(client_cache);
|
||||
@@ -1886,6 +2138,10 @@ fn register_tables(client_cache: &mut __sdk::ClientCache<Self>) {
|
||||
profile_played_world_table::register_table(client_cache);
|
||||
profile_save_archive_table::register_table(client_cache);
|
||||
profile_wallet_ledger_table::register_table(client_cache);
|
||||
puzzle_agent_message_table::register_table(client_cache);
|
||||
puzzle_agent_session_table::register_table(client_cache);
|
||||
puzzle_runtime_run_table::register_table(client_cache);
|
||||
puzzle_work_profile_table::register_table(client_cache);
|
||||
quest_log_table::register_table(client_cache);
|
||||
quest_record_table::register_table(client_cache);
|
||||
runtime_setting_table::register_table(client_cache);
|
||||
@@ -1903,6 +2159,10 @@ const ALL_TABLE_NAMES: &'static [&'static str] = &[
|
||||
"asset_entity_binding",
|
||||
"asset_object",
|
||||
"battle_state",
|
||||
"big_fish_agent_message",
|
||||
"big_fish_asset_slot",
|
||||
"big_fish_creation_session",
|
||||
"big_fish_runtime_run",
|
||||
"chapter_progression",
|
||||
"custom_world_agent_message",
|
||||
"custom_world_agent_operation",
|
||||
@@ -1918,6 +2178,10 @@ const ALL_TABLE_NAMES: &'static [&'static str] = &[
|
||||
"profile_played_world",
|
||||
"profile_save_archive",
|
||||
"profile_wallet_ledger",
|
||||
"puzzle_agent_message",
|
||||
"puzzle_agent_session",
|
||||
"puzzle_runtime_run",
|
||||
"puzzle_work_profile",
|
||||
"quest_log",
|
||||
"quest_record",
|
||||
"runtime_setting",
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::big_fish_session_procedure_result_type::BigFishSessionProcedureResult;
|
||||
use super::big_fish_publish_input_type::BigFishPublishInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct PublishBigFishGameArgs {
|
||||
pub input: BigFishPublishInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for PublishBigFishGameArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `publish_big_fish_game`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait publish_big_fish_game {
|
||||
fn publish_big_fish_game(&self, input: BigFishPublishInput,
|
||||
) {
|
||||
self.publish_big_fish_game_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn publish_big_fish_game_then(
|
||||
&self,
|
||||
input: BigFishPublishInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl publish_big_fish_game for super::RemoteProcedures {
|
||||
fn publish_big_fish_game_then(
|
||||
&self,
|
||||
input: BigFishPublishInput,
|
||||
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<BigFishSessionProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp.invoke_procedure_with_callback::<_, BigFishSessionProcedureResult>(
|
||||
"publish_big_fish_game",
|
||||
PublishBigFishGameArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user