From 5b0f9f3763e4ef8879e629db27c0d6cbdb06c151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=94=E9=A6=99=E4=B8=B8=E5=AD=90?= <15518898337@163.com> Date: Thu, 21 May 2026 23:34:07 +0800 Subject: [PATCH] feat: add wooden fish play template --- .hermes/shared-memory/decision-log.md | 24 + .hermes/shared-memory/pitfalls.md | 10 +- .hermes/shared-memory/project-overview.md | 1 + CONTEXT.md | 22 + ...€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md | 348 +++++ ...„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md | 39 +- ...玩法创作】平å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md | 20 + .../shared/src/contracts/creationAudio.ts | 7 +- packages/shared/src/contracts/index.ts | 1 + packages/shared/src/contracts/woodenFish.ts | 195 +++ public/wooden-fish/default-hit-object.png | Bin 0 -> 575719 bytes server-rs/Cargo.lock | 10 + server-rs/Cargo.toml | 2 + server-rs/crates/api-server/src/app.rs | 1 + server-rs/crates/api-server/src/main.rs | 1 + .../api-server/src/match3d/item_assets.rs | 4 +- server-rs/crates/api-server/src/modules.rs | 1 + .../api-server/src/modules/wooden_fish.rs | 80 ++ server-rs/crates/api-server/src/state.rs | 4 +- .../src/vector_engine_audio_generation.rs | 79 +- .../crates/api-server/src/wooden_fish.rs | 1107 +++++++++++++++ .../crates/module-jump-hop/src/application.rs | 8 +- .../crates/module-runtime/src/application.rs | 11 + server-rs/crates/module-runtime/src/lib.rs | 19 + .../crates/module-wooden-fish/Cargo.toml | 13 + .../module-wooden-fish/src/application.rs | 4 + .../crates/module-wooden-fish/src/commands.rs | 8 + .../crates/module-wooden-fish/src/domain.rs | 281 ++++ .../crates/module-wooden-fish/src/errors.rs | 23 + .../crates/module-wooden-fish/src/events.rs | 25 + .../crates/module-wooden-fish/src/lib.rs | 11 + server-rs/crates/platform-oss/src/lib.rs | 17 +- .../shared-contracts/src/creation_audio.rs | 17 + server-rs/crates/shared-contracts/src/lib.rs | 1 + .../shared-contracts/src/wooden_fish.rs | 485 +++++++ server-rs/crates/shared-logging/src/lib.rs | 19 +- server-rs/crates/spacetime-client/Cargo.toml | 1 + .../crates/spacetime-client/src/jump_hop.rs | 212 ++- server-rs/crates/spacetime-client/src/lib.rs | 34 +- .../crates/spacetime-client/src/mapper.rs | 40 +- .../spacetime-client/src/mapper/jump_hop.rs | 16 +- .../src/mapper/wooden_fish.rs | 237 ++++ .../spacetime-client/src/module_bindings.rs | 232 ++++ .../checkpoint_wooden_fish_run_procedure.rs | 59 + .../compile_wooden_fish_draft_procedure.rs | 59 + ...ate_wooden_fish_agent_session_procedure.rs | 59 + .../finish_wooden_fish_run_procedure.rs | 59 + ..._custom_world_agent_operation_procedure.rs | 1 - ...get_wooden_fish_agent_session_procedure.rs | 59 + .../get_wooden_fish_run_procedure.rs | 59 + .../get_wooden_fish_work_profile_procedure.rs | 59 + .../list_wooden_fish_works_procedure.rs | 59 + .../publish_wooden_fish_work_procedure.rs | 59 + .../start_wooden_fish_run_procedure.rs | 59 + .../update_wooden_fish_work_procedure.rs | 59 + ...en_fish_agent_session_create_input_type.rs | 22 + ...ooden_fish_agent_session_get_input_type.rs | 16 + ...ish_agent_session_procedure_result_type.rs | 19 + .../wooden_fish_agent_session_row_type.rs | 81 ++ ...wooden_fish_agent_session_snapshot_type.rs | 27 + .../wooden_fish_agent_session_table.rs | 165 +++ .../wooden_fish_audio_asset_snapshot_type.rs | 21 + ...ooden_fish_creator_config_snapshot_type.rs | 21 + .../wooden_fish_draft_compile_input_type.rs | 30 + .../wooden_fish_draft_snapshot_type.rs | 31 + .../wooden_fish_event_row_type.rs | 71 + .../wooden_fish_event_table.rs | 161 +++ .../wooden_fish_gallery_card_view_row_type.rs | 76 + .../wooden_fish_gallery_card_view_table.rs | 121 ++ .../wooden_fish_gallery_view_row_type.rs | 109 ++ .../wooden_fish_gallery_view_table.rs | 116 ++ .../wooden_fish_image_asset_snapshot_type.rs | 22 + .../wooden_fish_run_checkpoint_input_type.rs | 20 + .../wooden_fish_run_finish_input_type.rs | 20 + .../wooden_fish_run_get_input_type.rs | 16 + .../wooden_fish_run_procedure_result_type.rs | 19 + .../wooden_fish_run_snapshot_type.rs | 26 + .../wooden_fish_run_start_input_type.rs | 19 + .../wooden_fish_run_status_type.rs | 18 + .../wooden_fish_runtime_run_row_type.rs | 86 ++ .../wooden_fish_runtime_run_table.rs | 162 +++ .../wooden_fish_word_counter_type.rs | 16 + .../wooden_fish_work_get_input_type.rs | 16 + .../wooden_fish_work_procedure_result_type.rs | 19 + .../wooden_fish_work_profile_row_type.rs | 130 ++ .../wooden_fish_work_profile_table.rs | 162 +++ .../wooden_fish_work_publish_input_type.rs | 17 + .../wooden_fish_work_snapshot_type.rs | 38 + .../wooden_fish_work_update_input_type.rs | 28 + .../wooden_fish_works_list_input_type.rs | 16 + ...wooden_fish_works_procedure_result_type.rs | 19 + .../crates/spacetime-client/src/telemetry.rs | 4 +- .../spacetime-client/src/wooden_fish.rs | 1031 ++++++++++++++ server-rs/crates/spacetime-module/Cargo.toml | 1 + server-rs/crates/spacetime-module/src/lib.rs | 5 +- .../crates/spacetime-module/src/migration.rs | 7 + .../src/runtime/creation_entry_config.rs | 29 + .../spacetime-module/src/wooden_fish.rs | 1228 +++++++++++++++++ .../src/wooden_fish/tables.rs | 85 ++ .../spacetime-module/src/wooden_fish/types.rs | 254 ++++ .../PlatformEntryCreationTypeModal.test.tsx | 64 + .../PlatformEntryCreationTypeModal.tsx | 5 + .../PlatformEntryFlowShellImpl.tsx | 750 +++++++++- .../platform-entry/platformEntryTypes.ts | 4 + src/components/rpg-entry/RpgEntryHomeView.tsx | 42 +- .../rpgEntryWorldPresentation.test.ts | 30 + .../rpg-entry/rpgEntryWorldPresentation.ts | 83 ++ .../WoodenFishWorkspace.test.tsx | 25 + .../WoodenFishWorkspace.tsx | 534 +++++++ .../WoodenFishResultView.tsx | 206 +++ .../WoodenFishRuntimeShell.tsx | 384 ++++++ .../woodenFishRuntimeModel.test.ts | 71 + .../woodenFishRuntimeModel.ts | 97 ++ src/routing/appPageRoutes.test.ts | 18 + src/routing/appPageRoutes.ts | 4 + .../miniGameDraftGenerationProgress.test.ts | 50 + .../miniGameDraftGenerationProgress.ts | 128 +- src/services/publicWorkCode.test.ts | 24 + src/services/publicWorkCode.ts | 21 + src/services/wooden-fish/woodenFishClient.ts | 274 ++++ .../wooden-fish/woodenFishDefaults.ts | 5 + 121 files changed, 11580 insertions(+), 159 deletions(-) create mode 100644 docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md create mode 100644 packages/shared/src/contracts/woodenFish.ts create mode 100644 public/wooden-fish/default-hit-object.png create mode 100644 server-rs/crates/api-server/src/modules/wooden_fish.rs create mode 100644 server-rs/crates/api-server/src/wooden_fish.rs create mode 100644 server-rs/crates/module-wooden-fish/Cargo.toml create mode 100644 server-rs/crates/module-wooden-fish/src/application.rs create mode 100644 server-rs/crates/module-wooden-fish/src/commands.rs create mode 100644 server-rs/crates/module-wooden-fish/src/domain.rs create mode 100644 server-rs/crates/module-wooden-fish/src/errors.rs create mode 100644 server-rs/crates/module-wooden-fish/src/events.rs create mode 100644 server-rs/crates/module-wooden-fish/src/lib.rs create mode 100644 server-rs/crates/shared-contracts/src/wooden_fish.rs create mode 100644 server-rs/crates/spacetime-client/src/mapper/wooden_fish.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/checkpoint_wooden_fish_run_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/compile_wooden_fish_draft_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/create_wooden_fish_agent_session_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/finish_wooden_fish_run_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_agent_session_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_run_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_work_profile_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/list_wooden_fish_works_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/publish_wooden_fish_work_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/start_wooden_fish_run_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/update_wooden_fish_work_procedure.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_create_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_get_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_procedure_result_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_row_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_snapshot_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_table.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_audio_asset_snapshot_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_creator_config_snapshot_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_compile_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_snapshot_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_row_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_table.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_row_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_table.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_row_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_table.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_image_asset_snapshot_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_checkpoint_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_finish_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_get_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_procedure_result_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_snapshot_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_start_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_status_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_row_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_table.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_word_counter_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_get_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_procedure_result_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_row_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_table.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_publish_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_snapshot_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_update_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_list_input_type.rs create mode 100644 server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_procedure_result_type.rs create mode 100644 server-rs/crates/spacetime-client/src/wooden_fish.rs create mode 100644 server-rs/crates/spacetime-module/src/wooden_fish.rs create mode 100644 server-rs/crates/spacetime-module/src/wooden_fish/tables.rs create mode 100644 server-rs/crates/spacetime-module/src/wooden_fish/types.rs create mode 100644 src/components/platform-entry/PlatformEntryCreationTypeModal.test.tsx create mode 100644 src/components/wooden-fish-creation/WoodenFishWorkspace.test.tsx create mode 100644 src/components/wooden-fish-creation/WoodenFishWorkspace.tsx create mode 100644 src/components/wooden-fish-result/WoodenFishResultView.tsx create mode 100644 src/components/wooden-fish-runtime/WoodenFishRuntimeShell.tsx create mode 100644 src/components/wooden-fish-runtime/woodenFishRuntimeModel.test.ts create mode 100644 src/components/wooden-fish-runtime/woodenFishRuntimeModel.ts create mode 100644 src/services/publicWorkCode.test.ts create mode 100644 src/services/wooden-fish/woodenFishClient.ts create mode 100644 src/services/wooden-fish/woodenFishDefaults.ts diff --git a/.hermes/shared-memory/decision-log.md b/.hermes/shared-memory/decision-log.md index d6e0a5a1..924b7785 100644 --- a/.hermes/shared-memory/decision-log.md +++ b/.hermes/shared-memory/decision-log.md @@ -113,6 +113,30 @@ - éªŒè¯æ–¹å¼ï¼šæ–°å¢žçŽ©æ³• PRD 必须显å¼å£°æ˜Žå•图资产槽ä½å’Œç³»åˆ—ç´ ææ§½ä½ï¼›æ–°å¢žå·¥ä½œå°æµ‹è¯•确认没有默认èŠå¤©å¼ Agent 输入;skill 通过 `quick_validate.py`。 - å…³è”æ–‡æ¡£ï¼š`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`ã€`.codex/skills/genarrative-play-type-integration/SKILL.md`ã€`.hermes/skills/genarrative-play-type-integration/SKILL.md`。 +## 2026-05-20 敲木鱼玩法按完整平å°çºµåˆ‡æŽ¥å…¥ + +- 背景:敲木鱼玩法需è¦å¯¹é½æ‹¼å›¾ / 跳一跳的创作闭环,ä¸èƒ½åšæˆå­¤ç«‹ demo 或å‰ç«¯æœ¬åœ°è®¡æ•°å·¥å…·ã€‚ +- 决策:新增 `wooden-fish` çŽ©æ³•ï¼Œé‡‡ç”¨è¡¨å• / 图片输入工作å°ã€å•图敲击物资产槽ä½ã€æ•²å‡»éŸ³æ•ˆèµ„产槽ä½å’Œæœ€å¤š 8 æ¡é£˜å­—é…置;公开作å“å·å‰ç¼€ä¸º `WF-*`ï¼›è¿è¡Œæ€åªåœ¨å•次 run å†…ç´¯è®¡æ€»æ•²å‡»æ¬¡æ•°å’Œè¯æ¡è®¡æ•°ã€‚åŽç«¯æ–°å¢žç‹¬ç«‹ `module-wooden-fish`ã€shared contractsã€SpacetimeDB `wooden_fish_*` 表 / public viewsã€`spacetime-client` facade å’Œ `/api/creation/wooden-fish/*`ã€`/api/runtime/wooden-fish/*` 路由,å‰ç«¯æŽ¥å…¥å¹³å°å…¥å£ã€ç”Ÿæˆé¡µã€ç»“果页ã€è¿è¡Œæ€ã€å…¬å¼€è¯¦æƒ…和推è试玩。 +- å½±å“范围:`CONTEXT.md`ã€`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`ã€`docs/ã€åŽç«¯æž¶æž„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md`ã€`packages/shared/src/contracts/woodenFish.ts`ã€`server-rs/crates/shared-contracts/src/wooden_fish.rs`ã€`server-rs/crates/module-wooden-fish/`ã€`server-rs/crates/spacetime-module/src/wooden_fish*`ã€`server-rs/crates/spacetime-client/src/wooden_fish.rs`ã€`src/components/wooden-fish-*`。 +- éªŒè¯æ–¹å¼ï¼šæ‰§è¡Œæ•²æœ¨é±¼å¥‘约 / module / facade / runtime model / platform entry å®šå‘æµ‹è¯•ã€`npm run typecheck`ã€`npm run check:encoding`ã€`npm run check:spacetime-schema`ã€`cargo check -p api-server --manifest-path server-rs\Cargo.toml`,本地 smoke 使用 mock 短信é…ç½®åŽæ£€æŸ¥ `/healthz`。 +- å…³è”æ–‡æ¡£ï¼š`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`ã€`docs/ã€åŽç«¯æž¶æž„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md`。 + +## 2026-05-21 敲木鱼敲击音效å¤ç”¨é€šç”¨ Vidu 音效链路 + +- 背景:敲木鱼创作需è¦é€šè¿‡â€œæ•²å‡»éŸ³æ•ˆâ€æè¿°ç”ŸæˆçœŸå®žçŸ­éŸ³é¢‘,ä¸èƒ½ç»§ç»­ç”± `spacetime-client` åˆæˆ `/generated-wooden-fish-assets/...` å‡è·¯å¾„ï¼›åŒæ—¶æ‹¼å›¾å’ŒæŠ“大鹅音频生æˆå…¥å£ä»éœ€ä¿æŒå…³é—­ã€‚ +- 决策:通用 `/api/creation/audio/sound-effect` æäº¤ Vidu 音效任务;`/api/creation/audio/sound-effect/{task_id}/asset` åªå¯¹æœ¨é±¼ `hit_sound` ç›®æ ‡å¼€æ”¾ï¼Œå®ŒæˆæŸ¥è¯¢ã€ä¸‹è½½ã€OSS ç§æœ‰å¯¹è±¡ã€`asset_object` å’Œ entity binding 写入。木鱼 `compile-draft` / `generate-hit-sound` 在 `api-server` 内å¤ç”¨åŒä¸€ helper 生æˆå¹¶æ³¨å…¥ `hitSoundAsset`,`spacetime-client` 缺少真实 `hitSoundAsset` æ—¶æ‹’ç»ç¼–译。拼图和抓大鹅相关目标继续返回 `410 Gone`。 +- å½±å“范围:`server-rs/crates/api-server/src/vector_engine_audio_generation.rs`ã€`server-rs/crates/api-server/src/wooden_fish.rs`ã€`server-rs/crates/spacetime-client/src/wooden_fish.rs`ã€`shared-contracts` / `packages/shared` çš„ `creationAudio` å¥‘çº¦ã€æ•²æœ¨é±¼ PRD 与平å°é“¾è·¯æ–‡æ¡£ã€‚ +- éªŒè¯æ–¹å¼ï¼šæ‰§è¡Œ `cargo test -p shared-contracts creation_audio --manifest-path server-rs\Cargo.toml`ã€`cargo test -p spacetime-client wooden_fish --manifest-path server-rs\Cargo.toml`ã€`cargo test -p api-server wooden_fish --manifest-path server-rs\Cargo.toml`ã€`cargo test -p api-server disabled_creation_audio_targets_return_gone_except_wooden_fish_sound_effects --manifest-path server-rs\Cargo.toml`ã€`npm run typecheck`ã€`npm run check:encoding`,本地 smoke 检查 `/healthz`;真实生æˆéœ€åŒæ—¶é…ç½® VectorEngine 与 OSS AccessKey。 +- å…³è”æ–‡æ¡£ï¼š`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`ã€`docs/ã€åŽç«¯æž¶æž„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md`。 + +## 2026-05-21 æ•²æœ¨é±¼é»˜è®¤æ•²å‡»ç‰©ä½¿ç”¨å†…ç½®é€æ˜Ž PNG + +- 背景:默认敲木鱼图案若继续用“木鱼â€å…³é”®è¯ä¸´æ—¶ç”Ÿæˆï¼Œimage2 容易语义化é‡ç”»å¹¶æ”¹å˜ç”¨æˆ·è®¤å¯çš„原始造型。 +- 决策:默认模æ¿ä½¿ç”¨å†…ç½®èµ„æº `/wooden-fish/default-hit-object.png` 写回 `bundled-default` 敲击物资产;仅当用户输入自定义关键è¯ã€ä¸Šä¼ å‚考图或主动é‡ç”Ÿæˆæ•²å‡»ç‰©æ—¶ï¼Œæ‰èµ° image2 -> OSS -> asset object -> entity binding 链路。创作入å£å¡ç‰‡ã€ç»“果页ã€è¿è¡Œæ€å’Œå…¬å¼€åˆ—表兜底统一使用该 PNG。 +- å½±å“范围:敲木鱼工作å°é»˜è®¤æç¤ºè¯ã€api-server 木鱼默认资产编排ã€åˆ›ä½œå…¥å£ç§å­ä¸Žè¿ç§»ã€å¹³å°å…¬å¼€å¡ç‰‡å…œåº•ã€PRD 与平å°é“¾è·¯æ–‡æ¡£ã€‚ +- éªŒè¯æ–¹å¼ï¼šé»˜è®¤ `compile-draft` 返回的 `hitObjectAsset.generationProvider` 应为 `bundled-default` 且 `imageSrc=/wooden-fish/default-hit-object.png`ï¼›è‡ªå®šä¹‰å…³é”®è¯æˆ–å‚考图ä»èµ° image2ï¼›å‰ç«¯é™æ€èµ„æºå¯é€šè¿‡ Vite 直接访问。 +- å…³è”æ–‡æ¡£ï¼š`docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 + ## 2026-05-19 系列素æ n*n 图集抽为 api-server é€šç”¨æ¨¡å— - èƒŒæ™¯ï¼šæŠ“å¤§é¹…ç‰©å“ sheet å·²åŒ…å« prompt 组装ã€å›ºå®šç½‘格切图ã€ç»¿å¹• / è¿‘ç™½åº•é€æ˜ŽåŒ–ã€åˆ‡ç‰‡ PNG æŒä¹…化和 prompt 追踪;继续留在 Match3D ç§æœ‰æ¨¡å—会让跳一跳ã€åŽç»­åœ°å— / é“具类玩法é‡å¤å¤åˆ¶åŒä¸€å¥—算法和 OSS 元数æ®å£å¾„。 diff --git a/.hermes/shared-memory/pitfalls.md b/.hermes/shared-memory/pitfalls.md index 01c35907..163fa7cf 100644 --- a/.hermes/shared-memory/pitfalls.md +++ b/.hermes/shared-memory/pitfalls.md @@ -179,6 +179,14 @@ - 验è¯ï¼šæ‰§è¡Œ `node scripts/generate-edutainment-tv-map-concepts.mjs --dry-run`ï¼Œè¾“å‡ºåº”åªæ˜¾ç¤º `imageReferenceCount: 1`,ä¸å‡ºçŽ°å®Œæ•´ base64。 - å…³è”:`scripts/generate-edutainment-tv-map-concepts.mjs`ã€`docs/design/ã€å‰ç«¯ä½“验】寓教于ä¹ç”µè§†ç«¯ä¹å›­åœ°å›¾å…¥å£æ¦‚念图-2026-05-18.md`。 +## 生æˆå›¾èµ„产ä¸èƒ½åªæ‹¼ generated legacy path + +- 现象:结果页或è¿è¡Œæ€æ‹¿åˆ° `/generated-*-assets/.../image.png` åŽå›¾ç‰‡ä¸æ˜¾ç¤ºï¼›å‰ç«¯ `ResolvedAssetImage` 会先调用 `/api/assets/read-url?legacyPublicPath=...`,但æ¢ç­¾åŽçš„ OSS URL 仿Œ‡å‘ä¸å­˜åœ¨å¯¹è±¡ã€‚ +- 原因:åŽç«¯åªå†™äº†çœ‹èµ·æ¥åƒç”Ÿæˆå›¾çš„ legacy path,没有真正调用 image2ã€ä¸Šä¼  OSSã€ç™»è®° `asset_object` 并绑定实体。`/api/assets/read-url` åªè´Ÿè´£ç­¾å读å–,ä¸ä¼šå‡­ç©ºç”Ÿæˆæˆ–补写对象。 +- 处ç†ï¼šçŽ©æ³•ç”Ÿæˆé“¾è·¯å¿…须在 `api-server` 完æˆå¤–部副作用:调用 VectorEngine `gpt-image-2-all`,用 `GeneratedImageAssetAdapter` 准备 `PutObject`,上传 OSS ç§æœ‰å¯¹è±¡ï¼Œè°ƒç”¨ `confirm_asset_object` å’Œ `bind_asset_object_to_entity`ï¼Œå†æŠŠè¿”å›žçš„ `legacyPublicPath` 写入玩法 profile。 +- 验è¯ï¼š`cargo check -p api-server --manifest-path server-rs/Cargo.toml`;契约测试应断言å‰ç«¯ JSON 自带的 `hitObjectAsset` 会被忽略,spacetime-client å®šå‘æµ‹è¯•应断言缺少æœåŠ¡ç«¯æ³¨å…¥çš„çœŸå®ž `hitObjectAsset` æ—¶ä¸èƒ½ç¼–译;æµè§ˆå™¨ Network 中 generated 图片应先æ¢ç­¾ï¼Œç­¾å URL 指å‘已存在对象。 +- å…³è”:`server-rs/crates/api-server/src/wooden_fish.rs`ã€`server-rs/crates/spacetime-client/src/wooden_fish.rs`ã€`src/components/ResolvedAssetImage.tsx`ã€`src/services/assetReadUrlService.ts`。 + ## 忘记密ç åŽä»æç¤ºæ‰‹æœºå·æˆ–密ç é”™è¯¯å…ˆæŸ¥è®¤è¯å¿«ç…§åŒæ­¥ - 现象:用户通过“忘记密ç â€é‡è®¾å¯†ç åŽï¼ŒæŽ¥å£è¿”回æˆåŠŸæˆ–é¡µé¢è¿›å…¥ç™»å½•æ€ï¼Œä½†å†æ¬¡ä½¿ç”¨æ–°å¯†ç ç™»å½•ä»æç¤ºâ€œæ‰‹æœºå·æˆ–密ç é”™è¯¯â€ï¼›é‡å¯åŽè¿˜å¯èƒ½å‡ºçް `Bearer JWT 版本已失效`,日志里的 token version 与本地快照ä¸ä¸€è‡´ã€‚ @@ -558,7 +566,7 @@ - 现象:登录弹窗å¯ä»¥è¿›å…¥çŸ­ä¿¡é¡µç­¾ï¼Œä½†ç‚¹å‡»â€œèŽ·å–验è¯ç â€åŽï¼Œæ‰‹æœºæ²¡æœ‰æ”¶åˆ°çŸ­ä¿¡ã€‚ - 原因:本地 `.env.local` 里如果是 `SMS_AUTH_PROVIDER="mock"`,åŽç«¯ä¸ä¼šå‘真实短信,åªä¼šè¿”回固定 mock 验è¯ç ï¼›çœŸå®žé˜¿é‡Œäº‘é“¾è·¯å·²ç»æ”¹ä¸ºæ™®é€šçŸ­ä¿¡ `SendSms`,验è¯ç ç”±å½“å‰ `api-server` 进程本地生æˆã€å“ˆå¸Œå­˜å‚¨å’Œæ ¡éªŒï¼Œæ—§ `SendSmsVerifyCode` / `CheckSmsVerifyCode` 托管验è¯ç å‚æ•°ä¸å†å‚与真实校验。若接å£ç›´æŽ¥è¿”回“手机å·ç™»å½•暂未å¯ç”¨â€ï¼Œè¯´æ˜Žå½“å‰è¿è¡Œä¸­çš„ `api-server` 进程内 `sms_auth_enabled=false`:常è§åŽŸå› æ˜¯ä¿®æ”¹ `.env.local` åŽæ²¡æœ‰é‡å¯åŽç«¯ï¼Œæˆ–外层 shell å·²ç»è®¾ç½®äº†éžç©º `SMS_AUTH_ENABLED` 导致 dotenv ä¸è¦†ç›–。历å²ä¸Š cmd 里 `set SMS_AUTH_ENABLED="true"` 会把引å·ä¹Ÿä¼ è¿›è¿›ç¨‹ï¼ŒRust bool è§£æžå¤±è´¥åŽä¿æŒé»˜è®¤ false。 -- 处ç†ï¼šçœŸå®žçŸ­ä¿¡è”调时把 `.env.local` çš„ `SMS_AUTH_ENABLED=true`ã€`SMS_AUTH_PROVIDER=aliyun` æ˜¾å¼æ‰“开,并确认 `ALIYUN_SMS_ENDPOINT=dysmsapi.aliyuncs.com`ã€`ALIYUN_SMS_SIGN_NAME=北京亓盒网络科技`ã€`ALIYUN_SMS_TEMPLATE_CODE=SMS_506245486`ã€`ALIYUN_SMS_TEMPLATE_PARAM_KEY=code` åŽé‡å¯ `api-server`ï¼›å¦‚æžœåªæƒ³éªŒè¯ UI 和账å·é“¾è·¯ï¼Œåˆ™ä¿ç•™ `mock` 并使用 `SMS_AUTH_MOCK_VERIFY_CODE`。Shell 临时覆盖时 PowerShell 用 `$env:SMS_AUTH_ENABLED="true"`,cmd 用 `set SMS_AUTH_ENABLED=true`,ä¸è¦æŠŠå¼•å·ä½œä¸ºå€¼çš„一部分。`api-server` é‡å¯ä¼šæ¸…掉未校验的本地验è¯ç ã€‚ +- 处ç†ï¼šçœŸå®žçŸ­ä¿¡è”调时把 `.env.local` çš„ `SMS_AUTH_ENABLED=true`ã€`SMS_AUTH_PROVIDER=aliyun` æ˜¾å¼æ‰“开,并确认 `ALIYUN_SMS_ENDPOINT=dysmsapi.aliyuncs.com`ã€`ALIYUN_SMS_SIGN_NAME=北京亓盒网络科技`ã€`ALIYUN_SMS_TEMPLATE_CODE=SMS_506245486`ã€`ALIYUN_SMS_TEMPLATE_PARAM_KEY=code` åŽé‡å¯ `api-server`ï¼›å¦‚æžœåªæƒ³éªŒè¯ UIã€è´¦å·é“¾è·¯æˆ– `/healthz`,则ä¿ç•™ / 切æ¢ä¸º `mock` 并使用 `SMS_AUTH_MOCK_VERIFY_CODE`ã€‚æ³¨æ„ `npm run dev:api-server` 会先åˆå¹¶ `.env.local`,且 `SMS_AUTH_ENABLED`ã€`SMS_AUTH_PROVIDER`ã€`SMS_AUTH_MOCK_VERIFY_CODE` 属于å…许本地文件覆盖的键;如果 `.env.local` å†™ç€ `SMS_AUTH_PROVIDER=aliyun` 但没有 `ALIYUN_SMS_ACCESS_KEY_*`,å•纯在 PowerShell 里临时设置 mock ä»å¯èƒ½è¢«è¦†ç›–,health smoke 会在å¯åŠ¨é˜¶æ®µæŠ¥â€œé˜¿é‡Œäº‘çŸ­ä¿¡ AccessKey 未é…ç½®â€ã€‚䏿”¹ `.env.local` 的临时 smoke å¯ä»¥ç›´æŽ¥è¿è¡Œ `cargo run -p api-server --manifest-path server-rs\Cargo.toml` 并在åŒä¸€ shell 中显å¼è®¾ç½® `SMS_AUTH_PROVIDER=mock`ã€`GENARRATIVE_API_HOST`ã€`GENARRATIVE_API_PORT`ã€`GENARRATIVE_SPACETIME_SERVER_URL`ã€`GENARRATIVE_SPACETIME_DATABASE`。Shell 临时覆盖时 PowerShell 用 `$env:SMS_AUTH_ENABLED="true"`,cmd 用 `set SMS_AUTH_ENABLED=true`,ä¸è¦æŠŠå¼•å·ä½œä¸ºå€¼çš„一部分。`api-server` é‡å¯ä¼šæ¸…掉未校验的本地验è¯ç ã€‚ - 验è¯ï¼šåˆ†åˆ«è¯·æ±‚æµè§ˆå™¨åŸŸåå’Œ Rust API 直连的 `/api/auth/login-options`,都应返回 `["phone","password"]`ï¼›`api-server` 日志里 `provider=aliyun` æ‰è¯´æ˜ŽçœŸå®žçŸ­ä¿¡é“¾è·¯å·²ç”Ÿæ•ˆã€‚需è¦ç›´æŽ¥ç¡®è®¤å¹³å°å±‚真实调用阿里云时,é…ç½® `ALIYUN_SMS_ACCESS_KEY_ID`ã€`ALIYUN_SMS_ACCESS_KEY_SECRET` å’Œ `ALIYUN_SMS_REAL_TEST_PHONE_NUMBER` åŽæ‰‹åŠ¨æ‰§è¡Œ `cargo test -p platform-auth --manifest-path server-rs/Cargo.toml aliyun_send_sms_real_provider_sends_verify_code -- --ignored --nocapture`。 - å…³è”:`server-rs/crates/api-server/src/config.rs`ã€`scripts/dev-utils.mjs`ã€`docs/technical/AUTH_LOGIN_OPTIONS_DESIGN_2026-04-21.md`ã€`docs/technical/PHONE_SMS_REAL_PROVIDER_MANUAL_VERIFICATION_RUNBOOK_2026-04-23.md`。 diff --git a/.hermes/shared-memory/project-overview.md b/.hermes/shared-memory/project-overview.md index 040d5771..45ffc1e4 100644 --- a/.hermes/shared-memory/project-overview.md +++ b/.hermes/shared-memory/project-overview.md @@ -10,6 +10,7 @@ Genarrative / 陶泥儿是一个 AI åŽŸç”Ÿäº’åŠ¨å†…å®¹ä¸Žå°æ¸¸æˆå¹³å°ï¼ŒæŠŠ A - RPG / 自定义世界创作与è¿è¡Œæ—¶ã€‚ - 拼图玩法创作ã€è‰ç¨¿ã€å‘布ã€è¿è¡Œæ€å’ŒæŽ’行榜。 +- 敲木鱼玩法创作ã€è‰ç¨¿ã€å‘布ã€è¿è¡Œæ€ã€å…¬å¼€è¯¦æƒ…和分享ç ã€‚ - 抓大鹅 Match3D 创作ã€2D 多视角素æç”Ÿæˆã€å‘布和è¿è¡Œæ€ã€‚ - 大鱼åƒå°é±¼ã€æ–¹æ´žæŒ‘战ã€è§†è§‰å°è¯´ã€æ±ªæ±ªå£°æµªå’Œå„¿ç«¥å‘寓教于ä¹çŽ©æ³•ã€‚ - è´¦å·ã€çŸ­ä¿¡ / å¯†ç  / 微信登录ã€ä¸ªäººèµ„æ–™ã€ä»»åŠ¡ã€é’±åŒ…ã€é‚€è¯·ç ã€å……值ã€åé¦ˆã€æ³•律信æ¯å’ŒåŽå°ç®¡ç†ã€‚ diff --git a/CONTEXT.md b/CONTEXT.md index 2937f24b..c431cb69 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -18,6 +18,28 @@ _Avoid_: 为æ¯ä¸ªçŽ©æ³•å•ç‹¬å‘æ˜Žç´ ææµæ°´çº¿ã€æŠŠç³»åˆ—ç´ æå»ºæ¨¡æˆ ## Language +### Wooden Fish + +**敲木鱼**: +è½»é‡ç‚¹å‡»åž‹äº’åŠ¨çŽ©æ³•ï¼ŒçŽ©å®¶åœ¨å•æ¬¡è¿è¡Œä¸­ç‚¹å‡»éžåŠŸèƒ½åŒºæ•²å‡»ä¸­å¤®ç‰©å“ï¼Œè§¦å‘æ•²å‡»éŸ³æ•ˆã€æ•²å‡»åŠ¨ç”»ã€éšæœºé£˜å­—å’Œæœ¬æ¬¡è¿è¡Œå†…çš„è¯æ¡è®¡æ•°ã€‚ +_Avoid_: é•¿æœŸåŠŸå¾·è´¦æœ¬ã€æŽ’è¡Œæ¦œçŽ©æ³•ã€å…¨å±€è´¦æˆ·ç´¯è®¡ + +**敲击物图案**: +敲木鱼作å“中被玩家点击敲击的å•张物å“图案;默认模æ¿ä½¿ç”¨å†…ç½®é€æ˜Ž PNG `/wooden-fish/default-hit-object.png`ï¼Œç”¨æˆ·è‡ªå®šä¹‰å…³é”®è¯æˆ–上传图时å†ä½¿ç”¨ image2 ç”Ÿæˆæœ€ç»ˆèµ„产,上传图åªä½œä¸º image2 å‚考。 +_Avoid_: 直接把上传图作为è¿è¡Œæ€ç´ æã€ç³»åˆ—ç´ æå›¾é›† + +**敲击音效**: +敲木鱼作å“ä¸­æ¯æ¬¡æœ‰æ•ˆæ•²å‡»æ’­æ”¾çš„短音频资产,å¯ç”±æè¿°ç”Ÿæˆã€æ–‡ä»¶ä¸Šä¼ æˆ–麦克风录制产生,最终统一写回作å“的敲击音效资产槽ä½ã€‚ +_Avoid_: 背景音ä¹ã€é•¿éŸ³é¢‘轨é“ã€è¿è¡Œæ€å®žæ—¶å½•音 + +**飘字**: +æ¯æ¬¡æœ‰æ•ˆæ•²å‡»åŽä»Žä½œå“é…置中等概率抽å–è¯æ¡ï¼Œå¹¶åœ¨æ•²å‡»ç‰©ä¸Šæ–¹ä»¥â€œè¯æ¡+1â€çŸ­æš‚漂浮显示的文本;é…置里åªä¿å­˜å¹¸è¿ã€å¥åº·ã€è´¢å¯Œã€å§»ç¼˜ã€å¹¸ç¦ã€äº‹ä¸šã€æˆåŠŸã€åŠŸå¾·ç­‰è¯æ¡å本身。 +_Avoid_: 带æƒé‡å¥–励ã€è´¦æˆ·å±žæ€§ã€å¯ç»“ç®—è´§å¸ + +**啿¬¡ run 计数**: +敲木鱼è¿è¡Œæ€åªåœ¨å½“å‰ run å†…ç´¯è®¡æ€»æ•²å‡»æ¬¡æ•°å’Œå·²å‡ºçŽ°é£˜å­—è¯æ¡è®¡æ•°ï¼Œrun 结æŸåŽä½œä¸ºæ‘˜è¦ä¿å­˜ï¼Œä¸å½¢æˆè´¦å·çº§é•¿æœŸè´¦æœ¬ã€‚ +_Avoid_: 用户永久功德值ã€è·¨ä½œå“ç´¯è®¡å€¼ã€æŽ’è¡Œæ¦œç§¯åˆ† + ### Bark Battle **汪汪声浪大作战**: diff --git a/docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md b/docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md new file mode 100644 index 00000000..fa7c4535 --- /dev/null +++ b/docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md @@ -0,0 +1,348 @@ +# æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿ PRD 2026-05-20 + +## 1. 目标 + +新增一个å¯åˆ›ä½œã€å¯è¯•玩ã€å¯å‘布的轻é‡ä¼‘闲玩法模æ¿ï¼š + +```text +敲木鱼 +``` + +æ¨¡æ¿æŒ‰å¹³å°æ–°å¢žçŽ©æ³• SOP 接入完整闭环: + +```text +åˆ›ä½œå…¥å£ -> å·¥ä½œå° -> 生æˆé¡µ -> 结果页 -> 试玩 -> å‘布 -> è¿è¡Œæ€ -> 公开详情/分享 +``` + +首版默认å±å¹•中央展示内置å¡é€šé€æ˜Žæ•²å‡»ç‰©å›¾æ¡ˆ `/wooden-fish/default-hit-object.png`。玩家点击è¿è¡Œæ€éžåŠŸèƒ½åŒºæ—¶è§¦å‘ä¸€æ¬¡æ•²å‡»ï¼šæ’­æ”¾æ•²å‡»éŸ³æ•ˆã€æ•²å‡»ç‰©å›¾æ¡ˆæ‰§è¡Œè¢«æ•²å‡»åŠ¨ç”»ï¼Œå¹¶åœ¨æ•²å‡»ç‰©ä¸Šæ–¹éšæœºé£˜å‡ºä¸€æ¡ç¥ç¦è¯ã€‚顶部计数器åªåœ¨æŸæ¡ç¥ç¦è¯é¦–次出现时创建,之åŽè¯¥è¯æ¯æ¬¡å‡ºçŽ°éƒ½ç´¯åŠ ã€‚è®¡æ•°ä»…å±žäºŽå½“å‰å•次 run,ä¸è¿›å…¥è´¦å·é•¿æœŸè´¦æœ¬ã€‚ + +## 2. 模æ¿å®šä½ + +æ¨¡æ¿ ID: + +```text +wooden-fish +``` + +用户展示å: + +```text +敲木鱼 +``` + +公开作å“å·å‰ç¼€ï¼š + +```text +WF-* +``` + +体验关键è¯ï¼š + +1. å•å±ç‚¹å‡»ï¼› +2. è½»é‡è§£åŽ‹ï¼› +3. 飘字å馈; +4. å•局累计; +5. å¯è‡ªå®šä¹‰æ•²å‡»ç‰©ã€æ•²å‡»éŸ³æ•ˆå’Œç¥ç¦è¯ã€‚ + +## 3. 与拼图创作æµç¨‹çš„å¤ç”¨è¾¹ç•Œ + +å¯ä»¥å¤ç”¨ï¼š + +1. 创作入å£é…ç½®ã€å…¥å£å¼€å…³å’Œä½œå“æž¶ï¼› +2. 表å•/图片输入工作å°ï¼› +3. 生æˆè¿‡ç¨‹é¡µå’Œç”Ÿæˆä¸­æ¢å¤ï¼› +4. 结果页的返回编辑ã€å±€éƒ¨é‡ç”Ÿæˆã€è¯•玩ã€å‘布; +5. 公开列表ã€å…¬å¼€è¯¦æƒ…ã€åˆ†äº«ç å’ŒæŽ¨èæµåˆ†å‘ï¼› +6. å¹³å°èµ„产对象ã€OSS ç§æœ‰è¯»å–æ¢ç­¾å’ŒéŸ³é¢‘资产æŒä¹…化能力。 + +ä¸å¤ç”¨ï¼š + +1. 拼图关å¡ã€æ£‹ç›˜ã€æ‹¼å—ã€æŽ’è¡Œæ¦œå’Œå…³å¡æŽ¨è¿›è¯­ä¹‰ï¼› +2. 跳一跳地å—图集和蓄力判定语义; +3. æŠ“å¤§é¹…ç‰©å“æ¶ˆé™¤ã€äº”视角图集和容器语义; +4. 任何长期功德账本ã€è´¦å·ç»´åº¦æŽ’行榜或全局累计。 + +## 4. åˆ›ä½œå·¥å…·å¹³å°æŽ¥å…¥å£°æ˜Ž + +- å·¥ä½œå°æ¨¡å¼ï¼šè¡¨å•/å›¾ç‰‡è¾“å…¥åˆ›ä½œå·¥ä½œå° +- åˆ›ä½œé“¾è·¯ï¼šå…¥å£ -> å·¥ä½œå° -> 生æˆé¡µ -> 结果页 -> 试玩 -> å‘布 -> è¿è¡Œæ€ +- å•图资产槽ä½ï¼š + - `slotId=hit-object` + - `slotType=hit-object-image` + - `slotName=敲击物图案` + - æç¤ºè¯æ¥æºï¼š`hitObjectPrompt` 与å¯é€‰ `hitObjectReferenceImageSrc` + - 写回字段:`hitObjectAsset` + - 是å¦å…许历å²å›¾ï¼šå…许 + - 是å¦å…许 AI é‡ç»˜ï¼šå…许;上传图åªä½œä¸º image2 å‚考,最终è¿è¡Œæ€åªæ¶ˆè´¹ image2 生æˆå›¾ +- ç³»åˆ—ç´ ææ§½ä½ï¼šæ— ï¼›é¦–ç‰ˆåªæœ‰å•图敲击物,ä¸ç”Ÿæˆå›¾é›† +- 音频资产槽ä½ï¼š + - `slotId=hit-sound` + - `slotType=hit-sound-audio` + - `slotName=敲击音效` + - æ¥æºï¼š`hitSoundPrompt` 生æˆï¼Œæˆ–上传/麦克风录制音频 + - 写回字段:`hitSoundAsset` + - æè¿°ç”Ÿæˆèƒ½åŠ›ï¼šå¤ç”¨é€šç”¨åˆ›ä½œéŸ³é¢‘æŽ¥å£ `/api/creation/audio/sound-effect` çš„ VectorEngine Vidu 音效生æˆä¸Ž OSS æŒä¹…化链路 +- API 命å空间: + - `/api/creation/wooden-fish/...` + - `/api/runtime/wooden-fish/...` +- 业务真相: + - åŽç«¯è£å†³å¹¶æŒä¹…化 sessionã€work profileã€å‘布状æ€ã€run 摘è¦å’Œå…¬å¼€æŠ•影; + - å‰ç«¯åªè´Ÿè´£ç‚¹å‡»ä½Žå»¶è¿Ÿè¡¨çްã€éŸ³é¢‘播放ã€åŠ¨ç”»ã€é£˜å­—渲染和定期 checkpoint。 +- 创作工具模å¼ä¾‹å¤–:无 +- 验è¯å‘½ä»¤ï¼š + - `npm run check:encoding` + - `npm run typecheck` + - `cargo test -p shared-contracts wooden_fish --manifest-path server-rs/Cargo.toml` + - `cargo test -p module-wooden-fish --manifest-path server-rs/Cargo.toml` + - `cargo check -p api-server --manifest-path server-rs/Cargo.toml` + - `npm run spacetime:generate` + - `npm run check:spacetime-schema` + - `npm run dev:api-server` åŽæ£€æŸ¥ `/healthz` + +## 5. 创作输入 + +å·¥ä½œå°æäº¤ç»“æž„åŒ– payloadï¼Œä¸æäº¤èŠå¤©æ¶ˆæ¯ã€‚ + +必填字段: + +1. `templateId = "wooden-fish"`ï¼› +2. `workTitle`ï¼šä½œå“æ ‡é¢˜ï¼› +3. `hitObjectPrompt`ï¼šç”¨æˆ·æƒ³æ•²çš„å¯¹è±¡å…³é”®è¯æˆ–æè¿°ï¼Œé»˜è®¤â€œé»˜è®¤æ•²å‡»ç‰©å›¾æ¡ˆï¼Œåœ†æ¶¦æœ¨è´¨è´¨æ„Ÿï¼Œé€æ˜ŽèƒŒæ™¯â€ï¼› +4. `floatingWords[]`:ç¥ç¦è¯ï¼Œæœ€å¤š 8 æ¡ï¼Œä¸å¡«æˆ–清空时使用默认ç¥ç¦è¯ã€‚ + +å¯é€‰å­—段: + +1. `workDescription`:作å“简介; +2. `themeTags[]`:最多 6 个标签; +3. `hitObjectReferenceImageSrc`:上传或历å²å›¾å¼•用,åªèƒ½ä½œä¸º image2 å‚考,ä¸å¯ç›´æŽ¥è¿›å…¥è¿è¡Œæ€ï¼› +4. `hitSoundPrompt`:生æˆéŸ³æ•ˆæè¿°ï¼› +5. `hitSoundAsset`:用户上传或录音产生的音频资产。 + +默认ç¥ç¦è¯ï¼š + +```text +å¹¸è¿ +å¥åº· +财富 +姻缘 +å¹¸ç¦ +事业 +æˆåŠŸ +功德 +``` + +`floatingWords[]` ä¿å­˜è¯æ¡å本身,ä¸ä¿å­˜ `+1` åŽç¼€ï¼›è¿è¡Œæ€æ¯æ¬¡æ•²å‡»æ—¶å†æŠŠé£˜å­—å±•ç¤ºä¸ºâ€œè¯æ¡+1â€ã€‚ + +## 6. 生æˆè§„则 + +### 6.1 敲击物图案 + +默认模æ¿åœ¨ç”¨æˆ·æœªè‡ªå®šä¹‰å…³é”®è¯ä¸”未上传å‚考图时,`compile-draft` ä½¿ç”¨å†…ç½®é€æ˜Ž PNG `/wooden-fish/default-hit-object.png` 写回 `hitObjectAsset`,`generationProvider="bundled-default"`。这张图æ¥è‡ª image2 对原始å‚考图的å¡é€šé£Žæ ¼åŒ–é‡ç»˜ï¼Œå›ºå®šä¸ºæ¨¡æ¿é»˜è®¤èµ„æºï¼Œé¿å…默认关键è¯åœ¨æ¯æ¬¡ç”Ÿæˆæ—¶æ”¹å˜é€ åž‹ã€‚ + +用户输入自定义关键è¯ã€ä¸Šä¼ å‚考图,或在结果页主动é‡ç”Ÿæˆæ•²å‡»ç‰©æ—¶ï¼Œ`compile-draft` 与 `regenerate-hit-object` å¿…é¡»ä¸ºæ•²å‡»ç‰©å›¾æ¡ˆç”Ÿæˆ image2 å•图资产,并由 `api-server` 注入写回 `hitObjectAsset`。å‰ç«¯ action 请求ä¸å¾—自带 `hitObjectAsset` 短路生æˆã€‚如果用户上传å‚考图,åŽç«¯åªèƒ½æŠŠè¯¥å›¾ä½œä¸º image2 å‚考图或编辑输入;è¿è¡Œæ€ä¸å¾—直接使用上传图。 + +è½åº“链路固定为:`api-server` 调用 VectorEngine `gpt-image-2-all` -> æœåŠ¡ç«¯ä¸Šä¼  OSS ç§æœ‰å¯¹è±¡ -> `confirm_asset_object` 登记资产对象 -> `bind_asset_object_to_entity` 绑定到 `entityKind='wooden_fish_work'`ã€`slot='hit_object'`ã€`assetKind='wooden_fish_hit_object'` -> 把 `legacyPublicPath` 写入 `hitObjectAsset.imageSrc`。ä¸å¾—åªæ‹¼ `/generated-wooden-fish-assets/...` å ä½è·¯å¾„ï¼›å‰ç«¯ä¼šå¯¹ generated legacy path èµ° `/api/assets/read-url` æ¢ç­¾ï¼ŒOSS 中没有真实对象时图片无法显示。 + +é»˜è®¤å›¾æ¡ˆè¦æ±‚: + +1. 中央主体使用 `/wooden-fish/default-hit-object.png`ï¼› +2. 逿˜ŽèƒŒæ™¯ï¼› +3. 适åˆç§»åŠ¨ç«¯å±…ä¸­å±•ç¤ºï¼› +4. ä¸åŒ…å« UIã€æŒ‰é’®ã€è¯´æ˜Žæ–‡å­—ã€æ°´å°æˆ–å“牌标识; +5. 图片主体需留出敲击动画缩放空间。 + +### 6.2 敲击音效 + +音效统一写回 `hitSoundAsset`。 + +ç”Ÿæˆæˆ–写回规则: + +1. è‹¥ payload 已包å«ä¸Šä¼ /录音音频资产,`compile-draft` 跳过音效生æˆï¼Œç›´æŽ¥æŒä¹…化该资产; +2. è‹¥ payload åªåŒ…å« `hitSoundPrompt`,`api-server` å¤ç”¨é€šç”¨åˆ›ä½œéŸ³é¢‘能力æäº¤ VectorEngine Vidu `sound_effect` 任务,轮询生æˆç»“果,下载音频,写入 OSS ç§æœ‰å¯¹è±¡ï¼Œç™»è®° `asset_object`,并绑定到 `entityKind='wooden_fish_work'`ã€`slot='hit_sound'`ã€`assetKind='wooden_fish_hit_sound'`ï¼Œæœ€åŽæ³¨å…¥ `hitSoundAsset`ï¼› +3. 若两者都没有,åŽç«¯ç”Ÿæˆé»˜è®¤â€œæ¸…脆短促木鱼敲击声â€ï¼› +4. 音效资产必须包å«å¯æ’­æ”¾åœ°å€ã€å¯¹è±¡é”®ã€asset object idã€æ¥æºå’Œå¯é€‰æ—¶é•¿ï¼› +5. 通用创作音频接å£å¯¹ `wooden_fish` çš„ `hit_sound` 目标ä¸å¾—返回 `410 Gone`,对应 `storagePrefix='wooden_fish_assets'`ï¼› +6. `spacetime-client` ä¸å¾—è‡ªè¡Œåˆæˆ `/generated-wooden-fish-assets/...` 音效å ä½è·¯å¾„,缺少真实 `hitSoundAsset` 时必须拒ç»ç¼–译。 + +### 6.3 å°é¢ + +首版å°é¢ä½¿ç”¨ `hitObjectAsset.imageSrc` 作为 `coverImageSrc`。ä¸å•独新增第三次图片生æˆã€‚ + +## 7. å¥‘çº¦è‰æ¡ˆ + +`WoodenFishDraft` 至少包å«ï¼š + +1. `templateId = "wooden-fish"`ï¼› +2. `templateName = "敲木鱼"`ï¼› +3. `profileId`ï¼› +4. `workTitle`ï¼› +5. `workDescription`ï¼› +6. `themeTags[]`ï¼› +7. `hitObjectPrompt`ï¼› +8. `hitObjectReferenceImageSrc`ï¼› +9. `hitSoundPrompt`ï¼› +10. `floatingWords[]`ï¼› +11. `hitObjectAsset`ï¼› +12. `hitSoundAsset`ï¼› +13. `coverImageSrc`ï¼› +14. `generationStatus`。 + +`WoodenFishImageAsset` 至少包å«ï¼š + +1. `assetId`ï¼› +2. `imageSrc`ï¼› +3. `imageObjectKey`ï¼› +4. `assetObjectId`ï¼› +5. `generationProvider`ï¼› +6. `prompt`ï¼› +7. `width`ï¼› +8. `height`。 + +`WoodenFishAudioAsset` 至少包å«ï¼š + +1. `assetId`ï¼› +2. `audioSrc`ï¼› +3. `audioObjectKey`ï¼› +4. `assetObjectId`ï¼› +5. `source = generated | uploaded | recorded | placeholder`ï¼› +6. `prompt`ï¼› +7. `durationMs`。 + +`WoodenFishRunSnapshot` 至少包å«ï¼š + +1. `runId`ï¼› +2. `profileId`ï¼› +3. `ownerUserId`ï¼› +4. `status = playing | finished`ï¼› +5. `totalTapCount`ï¼› +6. `wordCounters[]`ï¼› +7. `startedAtMs`ï¼› +8. `updatedAtMs`ï¼› +9. `finishedAtMs`。 + +## 8. API è‰æ¡ˆ + +HTTP 路由: + +```text +POST /api/creation/wooden-fish/sessions +GET /api/creation/wooden-fish/sessions/{sessionId} +POST /api/creation/wooden-fish/sessions/{sessionId}/actions +GET /api/creation/wooden-fish/works/{profileId} +POST /api/creation/wooden-fish/works/{profileId}/publish +GET /api/runtime/wooden-fish/works/{profileId} +POST /api/runtime/wooden-fish/runs +POST /api/runtime/wooden-fish/runs/{runId}/checkpoint +POST /api/runtime/wooden-fish/runs/{runId}/finish +GET /api/runtime/wooden-fish/gallery +GET /api/runtime/wooden-fish/gallery/{publicWorkCode} +``` + +动作类型: + +```text +compile-draft +regenerate-hit-object +generate-hit-sound +replace-hit-sound +update-work-meta +update-floating-words +publish +start-run +checkpoint +finish +``` + +`compile-draft` 是长耗时动作。å‰ç«¯è¿›å…¥ç”Ÿæˆé¡µåŽåº”å±•ç¤ºå¯æ¢å¤è¿›åº¦ï¼›å¦‚果请求失败,标记失败å‰å¿…é¡»å¤è¯» session,确认åŽç«¯æ˜¯å¦å·²ç»ç”Ÿæˆå¹¶å†™å›žè‰ç¨¿ã€‚ + +## 9. SpacetimeDB 表和 view + +新增表: + +1. `wooden_fish_agent_session`ï¼› +2. `wooden_fish_work_profile`ï¼› +3. `wooden_fish_runtime_run`ï¼› +4. `wooden_fish_event`。 + +新增 view: + +1. `wooden_fish_gallery_card_view`:公开列表å¡ç‰‡æŠ•å½±ï¼Œåªæš´éœ²å·²å‘布作å“ï¼› +2. `wooden_fish_gallery_view`:公开详情兼容投影,包å«å›¾æ¡ˆã€éŸ³æ•ˆå’Œç¥ç¦è¯é…置。 + +新增或调整表ã€procedureã€view åŽå¿…é¡»åŒæ­¥ `migration.rs`ã€åŽç«¯è¡¨ç›®å½•ã€ç”Ÿæˆ bindings,并执行 `npm run check:spacetime-schema`。 + +## 10. 结果页能力 + +结果页必须展示: + +1. ä½œå“æ ‡é¢˜å’Œç®€ä»‹ï¼› +2. 敲击物图案; +3. 敲击音效试å¬ï¼› +4. ç¥ç¦è¯é…置; +5. 标签; +6. 试玩; +7. å‘布; +8. 返回编辑。 + +结果页必须支æŒï¼š + +1. é‡ç”Ÿæˆæ•²å‡»ç‰©å›¾æ¡ˆï¼› +2. 生æˆã€ä¸Šä¼ æˆ–æ›¿æ¢æ•²å‡»éŸ³æ•ˆï¼› +3. 修改标题ã€ç®€ä»‹å’Œæ ‡ç­¾ï¼› +4. 修改ç¥ç¦è¯ï¼Œæœ€å¤š 8 æ¡ã€‚ + +图案é‡ç”Ÿæˆå’ŒéŸ³æ•ˆç”Ÿæˆæ˜¯ç‹¬ç«‹å±€éƒ¨ç”Ÿæˆæ€ï¼Œä¸å¾—æŠŠå·²æœ‰å¯æŸ¥çœ‹ç»“æžœé‡æ–°å˜æˆä¸å¯æ‰“开的全局生æˆä¸­ã€‚ + +## 11. è¿è¡Œæ€è§„则 + +è¿è¡Œæ€é‡‡ç”¨å…¨å±å•击模型。 + +功能区: + +1. 顶部计数器; +2. è®¾ç½®ã€æš‚åœã€è¿”回ã€å‘布分享等按钮; +3. ç»“æžœå¼¹å±‚å’ŒéŸ³é¢‘æŽˆæƒæç¤ºã€‚ + +点击规则: + +1. 点击éžåŠŸèƒ½åŒºæ‰ç®—一次敲击; +2. æ¯æ¬¡æ•²å‡»ç«‹å³æœ¬åœ°ç´¯åŠ  `totalTapCount`ï¼› +3. éšæœºç­‰æ¦‚率从 `floatingWords[]` 中å–ä¸€ä¸ªè¯æ¡ï¼› +4. è‹¥è¯æ¡é¦–次出现,顶部创建对应计数器; +5. åŽç»­åŒè¯æ¡å‡ºçŽ°æ—¶å¯¹åº”è®¡æ•°å™¨ +1ï¼› +6. 播放敲击音效; +7. 敲击物图案执行压缩ã€å›žå¼¹æˆ–轻微震动动画; +8. æœ¨é±¼ä¸Šæ–¹é£˜å‡ºâ€œè¯æ¡+1â€å¹¶æ·¡å‡ºã€‚ + +音频播放: + +1. å‰ç«¯ä½¿ç”¨å°å¤éŸ³æ± ï¼› +2. è®¾ç½®æœ€å°æ’­æ”¾é—´éš”,é¿å…æžç«¯è¿žç‚¹å¯¼è‡´æµè§ˆå™¨æŠ–动; +3. 点击计数ä¸èƒ½å› ä¸ºéŸ³é¢‘节æµè€Œä¸¢å¤±ï¼› +4. ç­¾å URL 未就绪时先é™éŸ³è¡¨çŽ°ï¼Œä¸è¯·æ±‚裸 generated ç§æœ‰è·¯å¾„。 + +åŽç«¯åªä¿å­˜ run 摘è¦ï¼Œä¸ä¿å­˜æ¯æ¬¡ç‚¹å‡»çš„完整明细;`checkpoint` å’Œ `finish` éƒ½å†™å…¥æ€»æ•²å‡»æ¬¡æ•°ä¸Žè¯æ¡è®¡æ•°å¿«ç…§ã€‚ + +## 12. 公开链路 + +å¹³å°é¦–页推èã€å‘现ã€å…¬å¼€è¯¦æƒ…ã€æœç´¢ã€å·²çŽ©ä½œå“和公开试玩统一按 `sourceType='wooden-fish'` 与 `WF-*` 公开作å“å·è¯†åˆ«æ•²æœ¨é±¼ä½œå“。 + +公开列表优先消费 `wooden_fish_gallery_card_view` 订阅缓存。公开详情如果å¡ç‰‡æ‘˜è¦ä¸è¶³ä»¥è¿›å…¥è¿è¡Œæ€ï¼Œå¿…须补读完整 work profile。 + +## 13. 验收 + +1. 创作入å£èƒ½çœ‹åˆ° `敲木鱼` 模æ¿ï¼› +2. 工作å°å¯ä»¥å¡«å†™æ•²å‡»ç‰©æè¿°ã€ä¸Šä¼ å‚考图ã€é…置音效和ç¥ç¦è¯ï¼› +3. æäº¤åŽç”Ÿæˆ image2 敲击物图案; +4. 上传图ä¸ä¼šç›´æŽ¥è¿›å…¥è¿è¡Œæ€ï¼› +5. 用户上传或录制音效时跳过音效生æˆå¹¶æŒä¹…化该资产; +6. 结果页能看到图案ã€è¯•å¬éŸ³æ•ˆã€ç¼–辑ç¥ç¦è¯å¹¶è¯•玩; +7. è¿è¡Œæ€åŠŸèƒ½åŒºç‚¹å‡»ä¸è§¦å‘敲击; +8. éžåŠŸèƒ½åŒºç‚¹å‡»ä¼šè®¡æ•°ã€æ’­æ”¾éŸ³æ•ˆã€æ’­æ”¾æ•²å‡»åŠ¨ç”»å¹¶é£˜å­—ï¼› +9. 顶部计数器åªåœ¨è¯æ¡é¦–次出现时创建; +10. 连点ä¸ä¸¢è®¡æ•°ï¼› +11. `checkpoint` å’Œ `finish` åªä¿å­˜å•次 run 摘è¦ï¼› +12. 作å“å¯ä»¥å‘布ã€è¿›å…¥å…¬å¼€åˆ—表和公开详情; +13. `WF-*` 公开作å“å·èƒ½è¿›å…¥åˆ†äº«å’Œè¿è¡Œæ€ï¼› +14. `npm run check:encoding` 通过; +15. schema å˜æ›´åŽ `npm run check:spacetime-schema` 通过。 diff --git a/docs/ã€åŽç«¯æž¶æž„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md b/docs/ã€åŽç«¯æž¶æž„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md index 5aace093..af9d5cb2 100644 --- a/docs/ã€åŽç«¯æž¶æž„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md +++ b/docs/ã€åŽç«¯æž¶æž„】server-rs与SpacetimeDBæ•°æ®å¥‘约-2026-05-15.md @@ -44,7 +44,7 @@ npm run check:server-rs-ddd `server-rs/crates/spacetime-client/src/mapper.rs` åªä½œä¸ºèšåˆå…¥å£ï¼Œè´Ÿè´£å£°æ˜Ž `src/mapper/` ä¸‹çš„é¢†åŸŸå­æ¨¡å—å¹¶ re-export 原有 record / mapper 能力;ä¸è¦åœ¨è¯¥æ–‡ä»¶ç»§ç»­å †å å¤§æ®µæ˜ å°„实现。 -当å‰å­æ¨¡å—按调用领域拆分:`assets.rs`ã€`auth.rs`ã€`runtime.rs`ã€`runtime_profile.rs`ã€`custom_world.rs`ã€`puzzle.rs`ã€`match3d.rs`ã€`square_hole.rs`ã€`visual_novel.rs`ã€`big_fish.rs`ã€`story.rs`ã€`ai.rs`ã€`bark_battle.rs`ã€`combat.rs`ã€`inventory.rs`ã€`npc.rs`ï¼Œè·¨é¢†åŸŸè½»é‡ helper 和共享 record 统一放在 `common.rs`ã€‚è¯¥æ‹†åˆ†åªæ”¹å˜ `spacetime-client` æ–‡ä»¶ç»„ç»‡ï¼Œä¸æ”¹å˜ SpacetimeDB schemaã€ç”Ÿæˆç»‘定ã€procedure result 契约或外部 DTOï¼›åŽç»­æ–°å¢ž mapper 时优先è½åˆ°å¯¹åº”é¢†åŸŸå­æ¨¡å—,ä¸å¾—釿–°å¼•入跨层 JSON 字符串兼容结构。 +当å‰å­æ¨¡å—按调用领域拆分:`assets.rs`ã€`auth.rs`ã€`runtime.rs`ã€`runtime_profile.rs`ã€`custom_world.rs`ã€`puzzle.rs`ã€`match3d.rs`ã€`jump_hop.rs`ã€`wooden_fish.rs`ã€`square_hole.rs`ã€`visual_novel.rs`ã€`big_fish.rs`ã€`story.rs`ã€`ai.rs`ã€`bark_battle.rs`ã€`combat.rs`ã€`inventory.rs`ã€`npc.rs`ï¼Œè·¨é¢†åŸŸè½»é‡ helper 和共享 record 统一放在 `common.rs`ã€‚è¯¥æ‹†åˆ†åªæ”¹å˜ `spacetime-client` æ–‡ä»¶ç»„ç»‡ï¼Œä¸æ”¹å˜ SpacetimeDB schemaã€ç”Ÿæˆç»‘定ã€procedure result 契约或外部 DTOï¼›åŽç»­æ–°å¢ž mapper 时优先è½åˆ°å¯¹åº”é¢†åŸŸå­æ¨¡å—,ä¸å¾—釿–°å¼•入跨层 JSON 字符串兼容结构。 ## API 路由分组 @@ -60,6 +60,7 @@ npm run check:server-rs-ddd - 自定义世界 / RPG:`/api/runtime/custom-world*`ã€`/api/story/*`ã€`/api/runtime/chat/*`。 - 拼图:`/api/runtime/puzzle/*`。 - 抓大鹅 Match3D:`/api/creation/match3d/*`ã€`/api/runtime/match3d/*`。 +- 敲木鱼:`/api/creation/wooden-fish/*`ã€`/api/runtime/wooden-fish/*`。 - 方洞挑战:`/api/creation/square-hole/*`ã€`/api/runtime/square-hole/*`。 - 视觉å°è¯´ï¼š`/api/creation/visual-novel/*`ã€`/api/runtime/visual-novel/*`。 - 大鱼åƒå°é±¼ï¼š`/api/runtime/big-fish/*`。 @@ -156,7 +157,7 @@ npm run check:server-rs-ddd - Match3D å°é¢å’Œ 9:16 纯背景:VectorEngine `/v1/images/generations`。 - Match3D 1:1 容器 UI:VectorEngine `/v1/images/edits` multipart å‚考图。 - Hyper3D / Rodin:åªä¿ç•™åŽç«¯å®‰å…¨ä»£ç†å’Œæ—§æ•°æ®å…¼å®¹ï¼›æ–° Match3D è‰ç¨¿å’Œæ‰¹é‡æ–°å¢žä¸å†ç”Ÿæˆ GLB。 -- 音频:视觉å°è¯´ä¸“用音频路由ä¿ç•™ï¼›æ‹¼å›¾å’ŒæŠ“大鹅生æˆå…¥å£æš‚时关闭,通用 `/api/creation/audio/*` 对相关目标返回 `410 Gone`。 +- 音频:视觉å°è¯´ä¸“用音频路由ä¿ç•™ï¼›æ‹¼å›¾å’ŒæŠ“大鹅生æˆå…¥å£æš‚时关闭,通用 `/api/creation/audio/*` 对相关目标返回 `410 Gone`;敲木鱼 `hit_sound` 目标例外开放,å¤ç”¨ VectorEngine Vidu 音效生æˆã€OSS ç§æœ‰å¯¹è±¡ã€`asset_object` å’Œ entity binding 链路,目标字段固定为 `entityKind='wooden_fish_work'`ã€`slot='hit_sound'`ã€`assetKind='wooden_fish_hit_sound'`ã€`storagePrefix='wooden_fish_assets'`。 - OSSï¼šç§æœ‰ generated legacy path 进入æµè§ˆå™¨å‰å¿…须通过 `/api/assets/read-url` æ¢ç­¾ï¼›ä¸è¦è£¸è¯·æ±‚ `/generated-*`。 ## SpacetimeDB 表目录 @@ -396,6 +397,40 @@ npm run check:server-rs-ddd - æºç ï¼š`server-rs/crates/spacetime-module/src/jump_hop.rs` - 说明:跳一跳公开详情兼容投影,包å«ä½œå“ã€è·¯å¾„和素æå­—段;公开列表主路径优先使用 `jump_hop_gallery_card_view`。 +### `wooden_fish_agent_session` + +- Rust 结构体:`WoodenFishAgentSessionRow` +- æºç ï¼š`server-rs/crates/spacetime-module/src/wooden_fish/tables.rs` + +### `wooden_fish_event` + +- Rust 结构体:`WoodenFishEventRow` +- æºç ï¼š`server-rs/crates/spacetime-module/src/wooden_fish/tables.rs` + +### `wooden_fish_runtime_run` + +- Rust 结构体:`WoodenFishRuntimeRunRow` +- æºç ï¼š`server-rs/crates/spacetime-module/src/wooden_fish/tables.rs` + +### `wooden_fish_work_profile` + +- Rust 结构体:`WoodenFishWorkProfileRow` +- æºç ï¼š`server-rs/crates/spacetime-module/src/wooden_fish/tables.rs` + +### SpacetimeDB view:`wooden_fish_gallery_card_view` + +- Rust view:`wooden_fish_gallery_card_view` +- 返回类型:`Vec` +- æºç ï¼š`server-rs/crates/spacetime-module/src/wooden_fish.rs` +- 说明:敲木鱼公开广场列表å¡ç‰‡æŠ•å½±ï¼Œåªæš´éœ² `publication_status = published` 的作å“å¡ç‰‡å­—段;`api-server` çš„ `spacetime-client` 长期订阅 `SELECT * FROM wooden_fish_gallery_card_view` åŽï¼Œä»Žæœ¬åœ° cache 构造敲木鱼公开列表å“应。个人作å“列表ã€è¯¦æƒ…ã€å‘布和è¿è¡Œæ€ä»æŒ‰ procedure 路径处ç†ã€‚ + +### SpacetimeDB view:`wooden_fish_gallery_view` + +- Rust view:`wooden_fish_gallery_view` +- 返回类型:`Vec` +- æºç ï¼š`server-rs/crates/spacetime-module/src/wooden_fish.rs` +- è¯´æ˜Žï¼šæ•²æœ¨é±¼å…¬å¼€è¯¦æƒ…å…¼å®¹æŠ•å½±ï¼ŒåŒ…å«æ•²å‡»ç‰©å›¾æ¡ˆã€æ•²å‡»éŸ³æ•ˆå’Œé£˜å­—é…置;公开列表主路径优先使用 `wooden_fish_gallery_card_view`。 + ### `match3d_agent_message` - Rust 结构体:`Match3DAgentMessageRow` diff --git a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md index 06f781e9..6d35324e 100644 --- a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md +++ b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md @@ -87,6 +87,26 @@ å¹³å°é¦–页推èã€ç²¾é€‰ã€æœ€æ–°ã€å…¬å¼€è¯¦æƒ…ã€æœç´¢ã€å·²çŽ©ä½œå“和公开试玩统一按 `sourceType='jump-hop'` 与 `JH-*` 公开作å“å·è¯†åˆ«è·³ä¸€è·³ä½œå“ï¼›ä»Žå…¬å¼€è¯¦æƒ…æˆ–æŽ¨èæµå¯åЍè¿è¡Œæ€æ—¶ï¼Œè‹¥å¡ç‰‡æ‘˜è¦ä¸è¶³ä»¥æºå¸¦è§’色图ã€åœ°å—图集和路径é…置,必须先补读完整 work profile å†ä¼ å…¥è¿è¡Œæ€ã€‚ +## 敲木鱼 + +对外å称:`敲木鱼`。工程域:`wooden-fish`。PRD è§ `docs/prd/ã€çŽ©æ³•åˆ›ä½œã€‘æ•²æœ¨é±¼çŽ©æ³•æ¨¡æ¿PRD-2026-05-20.md`。 + +首版定ä½ä¸ºå•å±ç‚¹å‡»è§£åŽ‹æ¨¡æ¿ï¼Œé“¾è·¯å¯¹é½æ‹¼å›¾çš„创作闭环: + +```text +åˆ›ä½œå…¥å£ -> å·¥ä½œå° -> 生æˆè¿‡ç¨‹é¡µ -> 结果页 -> 试玩 -> å‘布 -> è¿è¡Œæ€ +``` + +创作输入固定为: + +1. `敲什么`:å•图资产槽ä½ã€‚默认模æ¿ä½¿ç”¨å†…ç½®é€æ˜Ž PNG `/wooden-fish/default-hit-object.png` 作为 `bundled-default` 敲击物资产,é¿å…默认关键è¯è¢«é‡æ–°è¯­ä¹‰åŒ–æ”¹å½¢ï¼›ç”¨æˆ·è¾“å…¥è‡ªå®šä¹‰å…³é”®è¯æˆ–上传å‚考图时,åŽç«¯å¿…须使用 image2 ç”Ÿæˆæœ€ç»ˆæ•²å‡»ç‰©å›¾æ¡ˆï¼Œä¸Šä¼ å›¾åªä½œä¸ºå‚考,ä¸ç›´æŽ¥è¿›å…¥è¿è¡Œæ€ã€‚自定义 `compile-draft` / `regenerate-hit-object` å¿…é¡»å®Œæˆ image2 -> OSS ç§æœ‰å¯¹è±¡ -> asset object 登记和绑定åŽï¼Œå†ç”± `api-server` 注入真实 `hitObjectAsset.imageSrc`,ä¸èƒ½åªå†™ `/generated-wooden-fish-assets/...` å ä½è·¯å¾„,也ä¸èƒ½æŽ¥å—å‰ç«¯è¯·æ±‚自带的 `hitObjectAsset` 短路生æˆã€‚ +2. `敲击音效`:音频资产槽ä½ï¼Œæ”¯æŒæè¿°ç”Ÿæˆã€ä¸Šä¼ å’Œéº¦å…‹é£Žå½•制,统一写回 `hitSoundAsset`。æè¿°ç”Ÿæˆå¤ç”¨é€šç”¨ `/api/creation/audio/sound-effect` çš„ VectorEngine Vidu 音效生æˆã€ä¸‹è½½ã€OSS ç§æœ‰å¯¹è±¡ã€asset object 登记和 entity binding 链路;木鱼目标固定为 `entityKind='wooden_fish_work'`ã€`slot='hit_sound'`ã€`assetKind='wooden_fish_hit_sound'`ã€`storagePrefix='wooden_fish_assets'`,ä¸å¾—å†è¿”回 `410 Gone`,也ä¸å¾—ç”± `spacetime-client` åˆæˆå‡éŸ³é¢‘路径。 +3. `功德有什么`:最多 8 æ¡é£˜å­—,默认 `幸è¿ã€å¥åº·ã€è´¢å¯Œã€å§»ç¼˜ã€å¹¸ç¦ã€äº‹ä¸šã€æˆåŠŸã€åŠŸå¾·`;创作æ€åªä¿å­˜è¯æ¡å,è¿è¡Œæ€é£˜å­—展示时å†è¿½åŠ  `+1`。 + +è¿è¡Œæ€è§„则真相以åŽç«¯ run 摘è¦ä¸ºå‡†ï¼Œå‰ç«¯åªåšç‚¹å‡»ä½Žå»¶è¿Ÿè¡¨çŽ°ã€æ•²å‡»åŠ¨ç”»ã€éŸ³é¢‘æ’­æ”¾å’Œé£˜å­—æ¸²æŸ“ã€‚æ¯æ¬¡éžåŠŸèƒ½åŒºç‚¹å‡»åœ¨å½“å‰ run 内累计 `totalTapCount` å’Œ `wordCounters`;计数ä¸è¿›å…¥è´¦å·é•¿æœŸè´¦æœ¬ï¼Œä¸åšæŽ’è¡Œæ¦œã€‚é¡¶éƒ¨è®¡æ•°å™¨ä»…åœ¨è¯æ¡é¦–次出现时创建,åŽç»­åŒè¯æ¡ç»§ç»­ç´¯åŠ ã€‚ + +å¹³å°é¦–页推èã€ç²¾é€‰ã€æœ€æ–°ã€å…¬å¼€è¯¦æƒ…ã€æœç´¢ã€å·²çŽ©ä½œå“和公开试玩统一按 `sourceType='wooden-fish'` 与 `WF-*` 公开作å“å·è¯†åˆ«æ•²æœ¨é±¼ä½œå“;公开列表应走 `wooden_fish_gallery_card_view` 订阅缓存,公开详情或è¿è¡Œæ€å¯åŠ¨æ—¶å¡ç‰‡æ‘˜è¦ä¸è¶³åˆ™è¡¥è¯»å®Œæ•´ work profile。 + ## 抓大鹅 Match3D 对外å称:`抓大鹅`。工程域:`match3d`。 diff --git a/packages/shared/src/contracts/creationAudio.ts b/packages/shared/src/contracts/creationAudio.ts index e1ad6cc3..5b820f56 100644 --- a/packages/shared/src/contracts/creationAudio.ts +++ b/packages/shared/src/contracts/creationAudio.ts @@ -39,7 +39,12 @@ export interface PublishGeneratedAudioAssetRequest { slot: string; assetKind: string; profileId?: string | null; - storagePrefix?: 'puzzle_assets' | 'match3d_assets' | 'custom_world_scenes' | null; + storagePrefix?: + | 'puzzle_assets' + | 'match3d_assets' + | 'wooden_fish_assets' + | 'custom_world_scenes' + | null; } export interface GeneratedAudioAssetResponse { diff --git a/packages/shared/src/contracts/index.ts b/packages/shared/src/contracts/index.ts index 8f8b20e8..49f37d51 100644 --- a/packages/shared/src/contracts/index.ts +++ b/packages/shared/src/contracts/index.ts @@ -5,3 +5,4 @@ export type * from './jumpHop'; export type * from './puzzleCreativeTemplate'; export type * from './visualNovel'; export type * from './barkBattle'; +export type * from './woodenFish'; diff --git a/packages/shared/src/contracts/woodenFish.ts b/packages/shared/src/contracts/woodenFish.ts new file mode 100644 index 00000000..e1026579 --- /dev/null +++ b/packages/shared/src/contracts/woodenFish.ts @@ -0,0 +1,195 @@ +export type WoodenFishGenerationStatus = + | 'draft' + | 'generating' + | 'ready' + | 'failed'; + +export type WoodenFishActionType = + | 'compile-draft' + | 'regenerate-hit-object' + | 'generate-hit-sound' + | 'replace-hit-sound' + | 'update-work-meta' + | 'update-floating-words'; + +export type WoodenFishRunStatus = 'playing' | 'finished'; + +export interface WoodenFishImageAsset { + assetId: string; + imageSrc: string; + imageObjectKey: string; + assetObjectId: string; + generationProvider: string; + prompt: string; + width: number; + height: number; +} + +export interface WoodenFishAudioAsset { + assetId: string; + audioSrc: string; + audioObjectKey: string; + assetObjectId: string; + source: string; + prompt?: string | null; + durationMs?: number | null; +} + +export interface WoodenFishWorkspaceCreateRequest { + templateId: string; + workTitle: string; + workDescription: string; + themeTags: string[]; + hitObjectPrompt: string; + hitObjectReferenceImageSrc?: string | null; + hitSoundPrompt?: string | null; + hitSoundAsset?: WoodenFishAudioAsset | null; + floatingWords: string[]; +} + +export interface WoodenFishActionRequest { + actionType: WoodenFishActionType; + profileId?: string | null; + workTitle?: string | null; + workDescription?: string | null; + themeTags?: string[] | null; + hitObjectPrompt?: string | null; + hitObjectReferenceImageSrc?: string | null; + hitSoundPrompt?: string | null; + hitSoundAsset?: WoodenFishAudioAsset | null; + floatingWords?: string[] | null; +} + +export interface WoodenFishWordCounter { + text: string; + count: number; +} + +export interface WoodenFishDraftResponse { + templateId: string; + templateName: string; + profileId: string | null; + workTitle: string; + workDescription: string; + themeTags: string[]; + hitObjectPrompt: string; + hitObjectReferenceImageSrc: string | null; + hitSoundPrompt: string | null; + floatingWords: string[]; + hitObjectAsset: WoodenFishImageAsset | null; + hitSoundAsset: WoodenFishAudioAsset | null; + coverImageSrc: string | null; + generationStatus: WoodenFishGenerationStatus; +} + +export interface WoodenFishSessionSnapshotResponse { + sessionId: string; + ownerUserId: string; + status: WoodenFishGenerationStatus; + draft: WoodenFishDraftResponse | null; + createdAt: string; + updatedAt: string; +} + +export interface WoodenFishSessionResponse { + session: WoodenFishSessionSnapshotResponse; +} + +export interface WoodenFishActionResponse { + actionType: WoodenFishActionType; + session: WoodenFishSessionSnapshotResponse; + work: WoodenFishWorkProfileResponse | null; +} + +export interface WoodenFishWorkSummaryResponse { + runtimeKind: 'wooden-fish'; + workId: string; + profileId: string; + ownerUserId: string; + sourceSessionId: string | null; + workTitle: string; + workDescription: string; + themeTags: string[]; + coverImageSrc: string | null; + publicationStatus: string; + playCount: number; + updatedAt: string; + publishedAt: string | null; + publishReady: boolean; + generationStatus: WoodenFishGenerationStatus; +} + +export interface WoodenFishWorkProfileResponse { + summary: WoodenFishWorkSummaryResponse; + draft: WoodenFishDraftResponse; + hitObjectAsset: WoodenFishImageAsset; + hitSoundAsset: WoodenFishAudioAsset; + floatingWords: string[]; +} + +export interface WoodenFishWorkDetailResponse { + item: WoodenFishWorkProfileResponse; +} + +export interface WoodenFishWorkMutationResponse { + item: WoodenFishWorkProfileResponse; +} + +export interface WoodenFishGalleryCardResponse { + publicWorkCode: string; + workId: string; + profileId: string; + ownerUserId: string; + authorDisplayName: string; + workTitle: string; + workDescription: string; + coverImageSrc: string | null; + themeTags: string[]; + publicationStatus: string; + playCount: number; + updatedAt: string; + publishedAt: string | null; + generationStatus: WoodenFishGenerationStatus; +} + +export interface WoodenFishGalleryResponse { + items: WoodenFishGalleryCardResponse[]; + hasMore: boolean; + nextCursor: string | null; +} + +export interface WoodenFishGalleryDetailResponse { + item: WoodenFishWorkProfileResponse; +} + +export interface WoodenFishRuntimeRunSnapshotResponse { + runId: string; + profileId: string; + ownerUserId: string; + status: WoodenFishRunStatus; + totalTapCount: number; + wordCounters: WoodenFishWordCounter[]; + startedAtMs: number; + updatedAtMs: number; + finishedAtMs: number | null; +} + +export interface WoodenFishRunResponse { + run: WoodenFishRuntimeRunSnapshotResponse; +} + +export interface WoodenFishStartRunRequest { + profileId: string; +} + +export interface WoodenFishCheckpointRunRequest { + totalTapCount: number; + wordCounters: WoodenFishWordCounter[]; + clientEventId: string; +} + +export interface WoodenFishFinishRunRequest { + totalTapCount: number; + wordCounters: WoodenFishWordCounter[]; + clientEventId: string; +} diff --git a/public/wooden-fish/default-hit-object.png b/public/wooden-fish/default-hit-object.png new file mode 100644 index 0000000000000000000000000000000000000000..44a6002c4a4f491dd6ef38d19fd5c6472742206c GIT binary patch literal 575719 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≀5a$frMQh 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

*TNjiVkBX{USFaxBKBF2r*6YFk@ZE56<)K(pT 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%0Aa+>QnA-u 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 literal 0 HcmV?d00001 diff --git a/server-rs/Cargo.lock b/server-rs/Cargo.lock index 6cb28534..ff327c57 100644 --- a/server-rs/Cargo.lock +++ b/server-rs/Cargo.lock @@ -1947,6 +1947,14 @@ dependencies = [ "spacetimedb", ] +[[package]] +name = "module-wooden-fish" +version = "0.1.0" +dependencies = [ + "serde", + "spacetimedb", +] + [[package]] name = "moxcms" version = "0.8.1" @@ -3278,6 +3286,7 @@ dependencies = [ "module-square-hole", "module-story", "module-visual-novel", + "module-wooden-fish", "opentelemetry", "serde", "serde_json", @@ -3311,6 +3320,7 @@ dependencies = [ "module-runtime-item", "module-square-hole", "module-story", + "module-wooden-fish", "serde", "serde_json", "sha2", diff --git a/server-rs/Cargo.toml b/server-rs/Cargo.toml index 1531dfc3..577c61bd 100644 --- a/server-rs/Cargo.toml +++ b/server-rs/Cargo.toml @@ -18,6 +18,7 @@ members = [ "crates/module-inventory", "crates/module-custom-world", "crates/module-jump-hop", + "crates/module-wooden-fish", "crates/module-match3d", "crates/module-npc", "crates/module-puzzle", @@ -59,6 +60,7 @@ module-creative-agent = { path = "crates/module-creative-agent", default-feature module-custom-world = { path = "crates/module-custom-world", default-features = false } module-inventory = { path = "crates/module-inventory", default-features = false } module-jump-hop = { path = "crates/module-jump-hop", default-features = false } +module-wooden-fish = { path = "crates/module-wooden-fish", default-features = false } module-match3d = { path = "crates/module-match3d", default-features = false } module-npc = { path = "crates/module-npc", default-features = false } module-progression = { path = "crates/module-progression", default-features = false } diff --git a/server-rs/crates/api-server/src/app.rs b/server-rs/crates/api-server/src/app.rs index d540f418..2b3458e1 100644 --- a/server-rs/crates/api-server/src/app.rs +++ b/server-rs/crates/api-server/src/app.rs @@ -60,6 +60,7 @@ pub fn build_router(state: AppState) -> Router { .merge(modules::match3d::router(state.clone())) .merge(modules::square_hole::router(state.clone())) .merge(modules::jump_hop::router(state.clone())) + .merge(modules::wooden_fish::router(state.clone())) .merge(modules::puzzle::router(state.clone())) .merge(visual_novel_router(state.clone())) .route( diff --git a/server-rs/crates/api-server/src/main.rs b/server-rs/crates/api-server/src/main.rs index 674e51c0..61bfce45 100644 --- a/server-rs/crates/api-server/src/main.rs +++ b/server-rs/crates/api-server/src/main.rs @@ -89,6 +89,7 @@ mod volcengine_speech; mod wechat_auth; mod wechat_pay; mod wechat_provider; +mod wooden_fish; mod work_author; mod work_play_tracking; diff --git a/server-rs/crates/api-server/src/match3d/item_assets.rs b/server-rs/crates/api-server/src/match3d/item_assets.rs index 87f86542..51c270ed 100644 --- a/server-rs/crates/api-server/src/match3d/item_assets.rs +++ b/server-rs/crates/api-server/src/match3d/item_assets.rs @@ -1,12 +1,12 @@ use super::*; +#[cfg(test)] +use crate::generated_asset_sheets::crop_generated_asset_sheet_view_edge_matte; use crate::generated_asset_sheets::{ GeneratedAssetSheetPersistInput, GeneratedAssetSheetPersistPrompt, GeneratedAssetSheetPromptInput, GeneratedAssetSheetSliceImage, build_generated_asset_sheet_prompt, persist_generated_asset_sheet_bytes, slice_generated_asset_sheet, }; -#[cfg(test)] -use crate::generated_asset_sheets::crop_generated_asset_sheet_view_edge_matte; pub(super) async fn generate_match3d_item_assets( state: &AppState, diff --git a/server-rs/crates/api-server/src/modules.rs b/server-rs/crates/api-server/src/modules.rs index a86abae9..d890a36f 100644 --- a/server-rs/crates/api-server/src/modules.rs +++ b/server-rs/crates/api-server/src/modules.rs @@ -14,3 +14,4 @@ pub mod profile; pub mod puzzle; pub mod square_hole; pub mod story; +pub mod wooden_fish; diff --git a/server-rs/crates/api-server/src/modules/wooden_fish.rs b/server-rs/crates/api-server/src/modules/wooden_fish.rs new file mode 100644 index 00000000..f9ad51a3 --- /dev/null +++ b/server-rs/crates/api-server/src/modules/wooden_fish.rs @@ -0,0 +1,80 @@ +use axum::{ + Router, middleware, + routing::{get, post}, +}; + +use crate::{ + auth::require_bearer_auth, + state::AppState, + wooden_fish::{ + checkpoint_wooden_fish_run, create_wooden_fish_session, execute_wooden_fish_action, + finish_wooden_fish_run, get_wooden_fish_gallery_detail, get_wooden_fish_runtime_work, + get_wooden_fish_session, list_wooden_fish_gallery, publish_wooden_fish_work, + start_wooden_fish_run, + }, +}; + +pub fn router(state: AppState) -> Router { + Router::new() + .route( + "/api/creation/wooden-fish/sessions", + post(create_wooden_fish_session).route_layer(middleware::from_fn_with_state( + state.clone(), + require_bearer_auth, + )), + ) + .route( + "/api/creation/wooden-fish/sessions/{session_id}", + get(get_wooden_fish_session).route_layer(middleware::from_fn_with_state( + state.clone(), + require_bearer_auth, + )), + ) + .route( + "/api/creation/wooden-fish/sessions/{session_id}/actions", + post(execute_wooden_fish_action).route_layer(middleware::from_fn_with_state( + state.clone(), + require_bearer_auth, + )), + ) + .route( + "/api/creation/wooden-fish/works/{profile_id}/publish", + post(publish_wooden_fish_work).route_layer(middleware::from_fn_with_state( + state.clone(), + require_bearer_auth, + )), + ) + .route( + "/api/runtime/wooden-fish/works/{profile_id}", + get(get_wooden_fish_runtime_work), + ) + .route( + "/api/runtime/wooden-fish/runs", + post(start_wooden_fish_run).route_layer(middleware::from_fn_with_state( + state.clone(), + require_bearer_auth, + )), + ) + .route( + "/api/runtime/wooden-fish/runs/{run_id}/checkpoint", + post(checkpoint_wooden_fish_run).route_layer(middleware::from_fn_with_state( + state.clone(), + require_bearer_auth, + )), + ) + .route( + "/api/runtime/wooden-fish/runs/{run_id}/finish", + post(finish_wooden_fish_run).route_layer(middleware::from_fn_with_state( + state.clone(), + require_bearer_auth, + )), + ) + .route( + "/api/runtime/wooden-fish/gallery", + get(list_wooden_fish_gallery), + ) + .route( + "/api/runtime/wooden-fish/gallery/{public_work_code}", + get(get_wooden_fish_gallery_detail), + ) +} diff --git a/server-rs/crates/api-server/src/state.rs b/server-rs/crates/api-server/src/state.rs index 02f8dcd0..a86348b6 100644 --- a/server-rs/crates/api-server/src/state.rs +++ b/server-rs/crates/api-server/src/state.rs @@ -1258,9 +1258,7 @@ fn build_admin_runtime( #[cfg(debug_assertions)] fn is_missing_creation_entry_config_procedure(error: &SpacetimeClientError) -> bool { match error { - SpacetimeClientError::Procedure(message) => { - message.contains("No such procedure") - } + SpacetimeClientError::Procedure(message) => message.contains("No such procedure"), _ => false, } } diff --git a/server-rs/crates/api-server/src/vector_engine_audio_generation.rs b/server-rs/crates/api-server/src/vector_engine_audio_generation.rs index d5708bf3..04e51f6e 100644 --- a/server-rs/crates/api-server/src/vector_engine_audio_generation.rs +++ b/server-rs/crates/api-server/src/vector_engine_audio_generation.rs @@ -233,13 +233,15 @@ pub async fn create_visual_novel_sound_effect_task( } pub async fn create_sound_effect_task( - State(_state): State, + State(state): State, axum::extract::Extension(request_context): axum::extract::Extension, payload: Result, JsonRejection>, ) -> Result, Response> { - let _ = parse_json_payload(&request_context, payload)?; - Err(creation_audio_generation_disabled_error() - .into_response_with_context(Some(&request_context))) + let Json(payload) = parse_json_payload(&request_context, payload)?; + create_sound_effect_task_response(&state, payload.prompt, payload.duration, payload.seed) + .await + .map(|task| json_success_body(Some(&request_context), task)) + .map_err(|error| error.into_response_with_context(Some(&request_context))) } pub(crate) async fn generate_sound_effect_asset_for_creation( @@ -518,15 +520,25 @@ pub async fn publish_background_music_asset( } pub async fn publish_sound_effect_asset( - State(_state): State, - Path(_task_id): Path, + State(state): State, + Path(task_id): Path, axum::extract::Extension(request_context): axum::extract::Extension, - axum::extract::Extension(_authenticated): axum::extract::Extension, + axum::extract::Extension(authenticated): axum::extract::Extension, payload: Result, JsonRejection>, ) -> Result, Response> { let payload = parse_json_payload(&request_context, payload)?.0; - Err(creation_audio_generation_disabled_error_for_target(payload) - .into_response_with_context(Some(&request_context))) + let target = build_creation_audio_target(payload, AudioAssetSlot::SoundEffect) + .map_err(|error| error.into_response_with_context(Some(&request_context)))?; + publish_generated_audio_asset( + &state, + authenticated.claims().user_id(), + task_id, + AudioAssetSlot::SoundEffect, + target, + ) + .await + .map(|payload| json_success_body(Some(&request_context), payload)) + .map_err(|error| error.into_response_with_context(Some(&request_context))) } async fn publish_generated_audio_asset( @@ -860,10 +872,36 @@ fn build_visual_novel_audio_target( }) } +fn build_creation_audio_target( + payload: creation_audio::PublishGeneratedAudioAssetRequest, + slot: AudioAssetSlot, +) -> Result { + if matches!(slot, AudioAssetSlot::SoundEffect) + && payload.entity_kind.trim() == "wooden_fish_work" + && payload.slot.trim() == "hit_sound" + && payload.asset_kind.trim() == "wooden_fish_hit_sound" + && payload.storage_prefix + == Some(creation_audio::CreationAudioStoragePrefix::WoodenFishAssets) + { + let entity_id = normalize_limited_text(&payload.entity_id, "entityId", 160)?; + return Ok(AudioAssetBindingTarget { + storage_scope: payload.entity_kind.trim().to_string(), + entity_kind: payload.entity_kind.trim().to_string(), + entity_id, + slot: payload.slot.trim().to_string(), + asset_kind: payload.asset_kind.trim().to_string(), + profile_id: normalize_optional_text(payload.profile_id.as_deref()), + storage_prefix: LegacyAssetPrefix::WoodenFishAssets, + }); + } + + Err(creation_audio_generation_disabled_error_for_target(payload)) +} + fn creation_audio_generation_disabled_error() -> AppError { AppError::from_status(StatusCode::GONE).with_details(json!({ "provider": VECTOR_ENGINE_PROVIDER, - "message": "拼图与抓大鹅音频生æˆå…¥å£å·²ä¸´æ—¶å…³é—­", + "message": "当å‰åˆ›ä½œéŸ³é¢‘目标未开放", })) } @@ -872,8 +910,9 @@ fn creation_audio_generation_disabled_error_for_target( ) -> AppError { creation_audio_generation_disabled_error().with_details(json!({ "provider": VECTOR_ENGINE_PROVIDER, - "message": "拼图与抓大鹅音频生æˆå…¥å£å·²ä¸´æ—¶å…³é—­", + "message": "当å‰åˆ›ä½œéŸ³é¢‘目标未开放", "entityKind": payload.entity_kind.trim(), + "slot": payload.slot.trim(), })) } @@ -1434,7 +1473,7 @@ mod tests { } #[test] - fn disabled_creation_audio_targets_return_gone() { + fn disabled_creation_audio_targets_return_gone_except_wooden_fish_sound_effects() { let payload = creation_audio::PublishGeneratedAudioAssetRequest { entity_kind: "puzzle_work".to_string(), entity_id: "puzzle-profile-1".to_string(), @@ -1467,6 +1506,22 @@ mod tests { }; let error = creation_audio_generation_disabled_error_for_target(payload); assert_eq!(error.status_code(), StatusCode::GONE); + + let payload = creation_audio::PublishGeneratedAudioAssetRequest { + entity_kind: "wooden_fish_work".to_string(), + entity_id: "wooden-fish-profile-1".to_string(), + slot: "hit_sound".to_string(), + asset_kind: "wooden_fish_hit_sound".to_string(), + profile_id: Some("wooden-fish-profile-1".to_string()), + storage_prefix: Some(creation_audio::CreationAudioStoragePrefix::WoodenFishAssets), + }; + let target = build_creation_audio_target(payload, AudioAssetSlot::SoundEffect) + .expect("wooden fish hit sound target should be enabled"); + + assert_eq!(target.entity_kind, "wooden_fish_work"); + assert_eq!(target.slot, "hit_sound"); + assert_eq!(target.storage_prefix, LegacyAssetPrefix::WoodenFishAssets); + assert_eq!(target.storage_scope, "wooden_fish_work"); } #[test] diff --git a/server-rs/crates/api-server/src/wooden_fish.rs b/server-rs/crates/api-server/src/wooden_fish.rs new file mode 100644 index 00000000..b0072a5b --- /dev/null +++ b/server-rs/crates/api-server/src/wooden_fish.rs @@ -0,0 +1,1107 @@ +use std::{ + collections::BTreeMap, + time::{SystemTime, UNIX_EPOCH}, +}; + +use axum::{ + Json, + extract::{Extension, Path, State, rejection::JsonRejection}, + http::{HeaderName, StatusCode, header}, + response::Response, +}; +use module_assets::{ + AssetObjectAccessPolicy, AssetObjectFieldError, build_asset_entity_binding_input, + build_asset_object_upsert_input, generate_asset_binding_id, generate_asset_object_id, +}; +use platform_oss::{LegacyAssetPrefix, OssHeadObjectRequest, OssObjectAccess}; +use serde_json::{Value, json}; +use shared_contracts::wooden_fish::{ + WoodenFishActionRequest, WoodenFishAudioAsset, WoodenFishCheckpointRunRequest, + WoodenFishDraftResponse, WoodenFishFinishRunRequest, WoodenFishGalleryDetailResponse, + WoodenFishGenerationStatus, WoodenFishImageAsset, WoodenFishRunResponse, + WoodenFishSessionResponse, WoodenFishSessionSnapshotResponse, WoodenFishStartRunRequest, + WoodenFishWorkDetailResponse, WoodenFishWorkMutationResponse, WoodenFishWorkspaceCreateRequest, +}; +use shared_kernel::{build_prefixed_uuid_id, format_timestamp_micros}; +use spacetime_client::SpacetimeClientError; + +use crate::generated_image_assets::{ + GeneratedImageAssetAdapter, GeneratedImageAssetDataUrl, + adapter::GeneratedImageAssetAdapterMetadata, adapter::GeneratedImageAssetPersistInput, + normalize_generated_image_asset_mime, +}; +use crate::{ + api_response::json_success_body, + auth::AuthenticatedAccessToken, + http_error::AppError, + openai_image_generation::{ + DownloadedOpenAiImage, build_openai_image_http_client, create_openai_image_generation, + require_openai_image_settings, + }, + platform_errors::map_oss_error, + request_context::RequestContext, + state::AppState, + vector_engine_audio_generation::{ + GeneratedCreationAudioTarget, generate_sound_effect_asset_for_creation, + }, +}; + +const WOODEN_FISH_PROVIDER: &str = "wooden-fish"; +const WOODEN_FISH_CREATION_PROVIDER: &str = "wooden-fish-creation"; +const WOODEN_FISH_RUNTIME_PROVIDER: &str = "wooden-fish-runtime"; +const WOODEN_FISH_TEMPLATE_ID: &str = "wooden-fish"; +const WOODEN_FISH_TEMPLATE_NAME: &str = "敲木鱼"; +const DEFAULT_HIT_OBJECT_PROMPT: &str = "é»˜è®¤æ•²å‡»ç‰©å›¾æ¡ˆï¼Œåœ†æ¶¦æœ¨è´¨è´¨æ„Ÿï¼Œé€æ˜ŽèƒŒæ™¯"; +const DEFAULT_HIT_SOUND_PROMPT: &str = "清脆短促的木鱼敲击声"; +const DEFAULT_HIT_OBJECT_ASSET_ID: &str = "wooden-fish-default-hit-object"; +const DEFAULT_HIT_OBJECT_IMAGE_SRC: &str = "/wooden-fish/default-hit-object.png"; +const WOODEN_FISH_ENTITY_KIND: &str = "wooden_fish_work"; +const WOODEN_FISH_HIT_OBJECT_SLOT: &str = "hit_object"; +const WOODEN_FISH_HIT_OBJECT_ASSET_KIND: &str = "wooden_fish_hit_object"; +const WOODEN_FISH_HIT_SOUND_SLOT: &str = "hit_sound"; +const WOODEN_FISH_HIT_SOUND_ASSET_KIND: &str = "wooden_fish_hit_sound"; +const WOODEN_FISH_HIT_SOUND_DURATION_SECONDS: u8 = 3; + +pub async fn create_wooden_fish_session( + State(state): State, + Extension(request_context): Extension, + Extension(authenticated): Extension, + payload: Result, JsonRejection>, +) -> Result, Response> { + let Json(payload) = wooden_fish_json(payload, &request_context, WOODEN_FISH_CREATION_PROVIDER)?; + validate_workspace_request(&request_context, &payload)?; + + let owner_user_id = authenticated.claims().user_id().to_string(); + let session_id = build_prefixed_uuid_id("wooden-fish-session-"); + let now = current_utc_micros(); + let draft = build_wooden_fish_draft(&payload); + let session = WoodenFishSessionSnapshotResponse { + session_id, + owner_user_id, + status: WoodenFishGenerationStatus::Draft, + draft: Some(draft), + created_at: format_timestamp_micros(now), + updated_at: format_timestamp_micros(now), + }; + + Ok(json_success_body( + Some(&request_context), + WoodenFishSessionResponse { + session: state + .spacetime_client() + .create_wooden_fish_session(session) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_CREATION_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?, + }, + )) +} + +pub async fn get_wooden_fish_session( + State(state): State, + Path(session_id): Path, + Extension(request_context): Extension, + Extension(authenticated): Extension, +) -> Result, Response> { + ensure_non_empty(&request_context, &session_id, "sessionId")?; + let owner_user_id = authenticated.claims().user_id().to_string(); + let session = state + .spacetime_client() + .get_wooden_fish_session(session_id, owner_user_id) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_CREATION_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body( + Some(&request_context), + WoodenFishSessionResponse { session }, + )) +} + +pub async fn execute_wooden_fish_action( + State(state): State, + Path(session_id): Path, + Extension(request_context): Extension, + Extension(authenticated): Extension, + payload: Result, JsonRejection>, +) -> Result, Response> { + ensure_non_empty(&request_context, &session_id, "sessionId")?; + let Json(mut payload) = + wooden_fish_json(payload, &request_context, WOODEN_FISH_CREATION_PROVIDER)?; + let owner_user_id = authenticated.claims().user_id().to_string(); + maybe_generate_hit_object_asset( + &state, + &request_context, + &session_id, + owner_user_id.as_str(), + &mut payload, + ) + .await?; + maybe_generate_hit_sound_asset( + &state, + &request_context, + &session_id, + owner_user_id.as_str(), + &mut payload, + ) + .await?; + let response = state + .spacetime_client() + .execute_wooden_fish_action(session_id, owner_user_id, payload) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_CREATION_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body(Some(&request_context), response)) +} + +pub async fn publish_wooden_fish_work( + State(state): State, + Path(profile_id): Path, + Extension(request_context): Extension, + Extension(authenticated): Extension, +) -> Result, Response> { + ensure_non_empty(&request_context, &profile_id, "profileId")?; + let work = state + .spacetime_client() + .publish_wooden_fish_work(profile_id, authenticated.claims().user_id().to_string()) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_CREATION_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body( + Some(&request_context), + WoodenFishWorkMutationResponse { item: work }, + )) +} + +pub async fn get_wooden_fish_runtime_work( + State(state): State, + Path(profile_id): Path, + Extension(request_context): Extension, +) -> Result, Response> { + ensure_non_empty(&request_context, &profile_id, "profileId")?; + let work = state + .spacetime_client() + .get_wooden_fish_runtime_work(profile_id) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_RUNTIME_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body( + Some(&request_context), + WoodenFishWorkDetailResponse { item: work }, + )) +} + +pub async fn start_wooden_fish_run( + State(state): State, + Extension(request_context): Extension, + Extension(authenticated): Extension, + payload: Result, JsonRejection>, +) -> Result, Response> { + let Json(payload) = wooden_fish_json(payload, &request_context, WOODEN_FISH_RUNTIME_PROVIDER)?; + ensure_non_empty(&request_context, &payload.profile_id, "profileId")?; + let run = state + .spacetime_client() + .start_wooden_fish_run(payload, authenticated.claims().user_id().to_string()) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_RUNTIME_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body( + Some(&request_context), + WoodenFishRunResponse { run }, + )) +} + +pub async fn checkpoint_wooden_fish_run( + State(state): State, + Path(run_id): Path, + Extension(request_context): Extension, + Extension(authenticated): Extension, + payload: Result, JsonRejection>, +) -> Result, Response> { + ensure_non_empty(&request_context, &run_id, "runId")?; + let Json(payload) = wooden_fish_json(payload, &request_context, WOODEN_FISH_RUNTIME_PROVIDER)?; + let run = state + .spacetime_client() + .checkpoint_wooden_fish_run( + run_id, + authenticated.claims().user_id().to_string(), + payload, + ) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_RUNTIME_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body( + Some(&request_context), + WoodenFishRunResponse { run }, + )) +} + +pub async fn finish_wooden_fish_run( + State(state): State, + Path(run_id): Path, + Extension(request_context): Extension, + Extension(authenticated): Extension, + payload: Result, JsonRejection>, +) -> Result, Response> { + ensure_non_empty(&request_context, &run_id, "runId")?; + let Json(payload) = wooden_fish_json(payload, &request_context, WOODEN_FISH_RUNTIME_PROVIDER)?; + let run = state + .spacetime_client() + .finish_wooden_fish_run( + run_id, + authenticated.claims().user_id().to_string(), + payload, + ) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_RUNTIME_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body( + Some(&request_context), + WoodenFishRunResponse { run }, + )) +} + +pub async fn list_wooden_fish_gallery( + State(state): State, + Extension(request_context): Extension, +) -> Result, Response> { + let gallery = state + .spacetime_client() + .list_wooden_fish_gallery() + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_RUNTIME_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body(Some(&request_context), gallery)) +} + +pub async fn get_wooden_fish_gallery_detail( + State(state): State, + Path(public_work_code): Path, + Extension(request_context): Extension, +) -> Result, Response> { + ensure_non_empty(&request_context, &public_work_code, "publicWorkCode")?; + let work = state + .spacetime_client() + .get_wooden_fish_gallery_detail(public_work_code) + .await + .map_err(|error| { + wooden_fish_error_response( + &request_context, + WOODEN_FISH_RUNTIME_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + + Ok(json_success_body( + Some(&request_context), + WoodenFishGalleryDetailResponse { item: work }, + )) +} + +fn build_wooden_fish_draft(payload: &WoodenFishWorkspaceCreateRequest) -> WoodenFishDraftResponse { + WoodenFishDraftResponse { + template_id: WOODEN_FISH_TEMPLATE_ID.to_string(), + template_name: WOODEN_FISH_TEMPLATE_NAME.to_string(), + profile_id: None, + work_title: payload.work_title.trim().to_string(), + work_description: payload.work_description.trim().to_string(), + theme_tags: normalize_tags(payload.theme_tags.clone()), + hit_object_prompt: clean_string(&payload.hit_object_prompt, DEFAULT_HIT_OBJECT_PROMPT), + hit_object_reference_image_src: payload + .hit_object_reference_image_src + .as_ref() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()), + hit_sound_prompt: payload + .hit_sound_prompt + .as_ref() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .or_else(|| Some(DEFAULT_HIT_SOUND_PROMPT.to_string())), + floating_words: normalize_floating_words(payload.floating_words.clone()), + hit_object_asset: None, + hit_sound_asset: payload.hit_sound_asset.clone(), + cover_image_src: None, + generation_status: WoodenFishGenerationStatus::Draft, + } +} + +fn validate_workspace_request( + request_context: &RequestContext, + payload: &WoodenFishWorkspaceCreateRequest, +) -> Result<(), Response> { + ensure_non_empty(request_context, &payload.work_title, "workTitle")?; + if payload.template_id.trim() != WOODEN_FISH_TEMPLATE_ID { + return Err(wooden_fish_error_response( + request_context, + WOODEN_FISH_CREATION_PROVIDER, + AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({ + "provider": WOODEN_FISH_PROVIDER, + "message": "templateId 必须为 wooden-fish", + })), + )); + } + Ok(()) +} + +async fn maybe_generate_hit_object_asset( + state: &AppState, + request_context: &RequestContext, + session_id: &str, + owner_user_id: &str, + payload: &mut WoodenFishActionRequest, +) -> Result<(), Response> { + if !matches!( + payload.action_type, + shared_contracts::wooden_fish::WoodenFishActionType::CompileDraft + | shared_contracts::wooden_fish::WoodenFishActionType::RegenerateHitObject + ) { + return Ok(()); + } + if payload.hit_object_asset.is_some() { + return Ok(()); + } + + let profile_id = + resolve_hit_object_profile_id(state, request_context, session_id, owner_user_id, payload) + .await?; + payload.profile_id = Some(profile_id.clone()); + let prompt = payload + .hit_object_prompt + .as_deref() + .map(|value| clean_string(value, DEFAULT_HIT_OBJECT_PROMPT)) + .filter(|value| !value.trim().is_empty()) + .unwrap_or_else(|| DEFAULT_HIT_OBJECT_PROMPT.to_string()); + let reference_images = payload + .hit_object_reference_image_src + .as_deref() + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(|value| vec![value.to_string()]) + .unwrap_or_default(); + + if reference_images.is_empty() && is_default_hit_object_prompt(prompt.as_str()) { + payload.hit_object_asset = Some(default_wooden_fish_hit_object_asset()); + return Ok(()); + } + + let asset = generate_wooden_fish_hit_object_asset( + state, + owner_user_id, + session_id, + profile_id.as_str(), + prompt.as_str(), + reference_images.as_slice(), + ) + .await + .map_err(|error| { + wooden_fish_error_response(request_context, WOODEN_FISH_CREATION_PROVIDER, error) + })?; + payload.hit_object_asset = Some(asset); + Ok(()) +} + +fn default_wooden_fish_hit_object_asset() -> WoodenFishImageAsset { + WoodenFishImageAsset { + asset_id: DEFAULT_HIT_OBJECT_ASSET_ID.to_string(), + image_src: DEFAULT_HIT_OBJECT_IMAGE_SRC.to_string(), + image_object_key: "public/wooden-fish/default-hit-object.png".to_string(), + asset_object_id: DEFAULT_HIT_OBJECT_ASSET_ID.to_string(), + generation_provider: "bundled-default".to_string(), + prompt: DEFAULT_HIT_OBJECT_PROMPT.to_string(), + width: 1024, + height: 1024, + } +} + +fn is_default_hit_object_prompt(prompt: &str) -> bool { + let normalized = normalize_hit_object_prompt_for_default_match(prompt); + normalized.is_empty() + || normalized + == normalize_hit_object_prompt_for_default_match(DEFAULT_HIT_OBJECT_PROMPT) + || normalized + == normalize_hit_object_prompt_for_default_match("å¡é€šæœ¨é±¼ï¼Œåœ†æ¶¦å¯çˆ±ï¼Œé€æ˜ŽèƒŒæ™¯") + || normalized + == normalize_hit_object_prompt_for_default_match("å¡é€šæœ¨é±¼ï¼Œé€æ˜ŽèƒŒæ™¯ï¼Œå±…中,圆润å¯çˆ±") + || normalized == normalize_hit_object_prompt_for_default_match("å¡é€šæœ¨é±¼") +} + +fn normalize_hit_object_prompt_for_default_match(prompt: &str) -> String { + prompt + .chars() + .filter(|ch| !ch.is_whitespace() && !matches!(ch, ',' | ',' | '。' | '.')) + .collect::() +} + +async fn resolve_hit_object_profile_id( + state: &AppState, + request_context: &RequestContext, + session_id: &str, + owner_user_id: &str, + payload: &WoodenFishActionRequest, +) -> Result { + if let Some(profile_id) = payload + .profile_id + .as_ref() + .map(|value| value.trim()) + .filter(|value| !value.is_empty()) + { + return Ok(profile_id.to_string()); + } + if matches!( + payload.action_type, + shared_contracts::wooden_fish::WoodenFishActionType::CompileDraft + ) { + return Ok(build_prefixed_uuid_id("wooden-fish-profile-")); + } + + let session = state + .spacetime_client() + .get_wooden_fish_session(session_id.to_string(), owner_user_id.to_string()) + .await + .map_err(|error| { + wooden_fish_error_response( + request_context, + WOODEN_FISH_CREATION_PROVIDER, + map_wooden_fish_client_error(error), + ) + })?; + session + .draft + .and_then(|draft| draft.profile_id) + .filter(|value| !value.trim().is_empty()) + .ok_or_else(|| { + wooden_fish_error_response( + request_context, + WOODEN_FISH_CREATION_PROVIDER, + AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({ + "provider": WOODEN_FISH_PROVIDER, + "message": "wooden-fish action 需è¦å…ˆå®Œæˆ compile-draft", + })), + ) + }) +} + +async fn maybe_generate_hit_sound_asset( + state: &AppState, + request_context: &RequestContext, + session_id: &str, + owner_user_id: &str, + payload: &mut WoodenFishActionRequest, +) -> Result<(), Response> { + if !matches!( + payload.action_type, + shared_contracts::wooden_fish::WoodenFishActionType::CompileDraft + | shared_contracts::wooden_fish::WoodenFishActionType::GenerateHitSound + ) { + return Ok(()); + } + if matches!( + payload.action_type, + shared_contracts::wooden_fish::WoodenFishActionType::CompileDraft + ) && payload.hit_sound_asset.is_some() + { + return Ok(()); + } + + let profile_id = + resolve_hit_object_profile_id(state, request_context, session_id, owner_user_id, payload) + .await?; + payload.profile_id = Some(profile_id.clone()); + let prompt = payload + .hit_sound_prompt + .as_deref() + .map(|value| clean_string(value, DEFAULT_HIT_SOUND_PROMPT)) + .filter(|value| !value.trim().is_empty()) + .unwrap_or_else(|| DEFAULT_HIT_SOUND_PROMPT.to_string()); + + let asset = generate_wooden_fish_hit_sound_asset( + state, + owner_user_id, + profile_id.as_str(), + prompt.as_str(), + ) + .await + .map_err(|error| { + wooden_fish_error_response(request_context, WOODEN_FISH_CREATION_PROVIDER, error) + })?; + payload.hit_sound_asset = Some(asset); + Ok(()) +} + +async fn generate_wooden_fish_hit_sound_asset( + state: &AppState, + owner_user_id: &str, + profile_id: &str, + prompt: &str, +) -> Result { + let final_prompt = build_wooden_fish_hit_sound_prompt(prompt); + let generated = generate_sound_effect_asset_for_creation( + state, + owner_user_id, + final_prompt.clone(), + Some(WOODEN_FISH_HIT_SOUND_DURATION_SECONDS), + None, + GeneratedCreationAudioTarget { + entity_kind: WOODEN_FISH_ENTITY_KIND.to_string(), + entity_id: profile_id.to_string(), + slot: WOODEN_FISH_HIT_SOUND_SLOT.to_string(), + asset_kind: WOODEN_FISH_HIT_SOUND_ASSET_KIND.to_string(), + profile_id: Some(profile_id.to_string()), + storage_prefix: LegacyAssetPrefix::WoodenFishAssets, + }, + ) + .await?; + map_generated_creation_audio_to_wooden_fish_asset( + profile_id, + final_prompt.as_str(), + generated, + WOODEN_FISH_HIT_SOUND_DURATION_SECONDS, + ) +} + +fn build_wooden_fish_hit_sound_prompt(prompt: &str) -> String { + format!( + "为敲木鱼玩法生æˆä¸€æ¬¡ç‚¹å‡»è§¦å‘的短促敲击音效:{}ã€‚è¦æ±‚ï¼šå¹²å‡€ã€æ¸…è„†ã€æ— æ—‹å¾‹ã€æ— çŽ¯å¢ƒå™ªå£°ã€æ— è¯­éŸ³ã€æ— æ–‡å­—æç¤ºéŸ³ï¼Œé€‚åˆé«˜é¢‘点击时å åŠ æ’­æ”¾ã€‚", + clean_string(prompt, DEFAULT_HIT_SOUND_PROMPT) + ) +} + +fn map_generated_creation_audio_to_wooden_fish_asset( + profile_id: &str, + prompt: &str, + asset: shared_contracts::creation_audio::CreationAudioAsset, + duration_seconds: u8, +) -> Result { + let asset_object_id = asset + .asset_object_id + .filter(|value| !value.trim().is_empty()) + .ok_or_else(|| { + AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({ + "provider": "vector-engine", + "message": "敲木鱼音效生æˆå®Œæˆä½†ç¼ºå°‘资产对象 ID", + })) + })?; + let audio_object_key = asset.audio_src.trim().trim_start_matches('/').to_string(); + if audio_object_key.is_empty() { + return Err( + AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({ + "provider": "vector-engine", + "message": "敲木鱼音效生æˆå®Œæˆä½†ç¼ºå°‘音频地å€", + })), + ); + } + + Ok(WoodenFishAudioAsset { + asset_id: format!("{profile_id}-hit-sound-{}", asset.task_id), + audio_src: asset.audio_src, + audio_object_key, + asset_object_id, + source: "generated".to_string(), + prompt: asset.prompt.or_else(|| Some(prompt.to_string())), + duration_ms: Some(u32::from(duration_seconds) * 1_000), + }) +} + +async fn generate_wooden_fish_hit_object_asset( + state: &AppState, + owner_user_id: &str, + session_id: &str, + profile_id: &str, + prompt: &str, + reference_images: &[String], +) -> Result { + let settings = require_openai_image_settings(state)?; + let http_client = build_openai_image_http_client(&settings)?; + let final_prompt = build_wooden_fish_hit_object_prompt(prompt); + let generated = create_openai_image_generation( + &http_client, + &settings, + final_prompt.as_str(), + Some(build_wooden_fish_hit_object_negative_prompt().as_str()), + "1024x1024", + 1, + reference_images, + "ç”Ÿæˆæ•²æœ¨é±¼æ•²å‡»ç‰©å›¾æ¡ˆå¤±è´¥", + ) + .await?; + let task_id = generated.task_id.clone(); + let image = generated.images.into_iter().next().ok_or_else(|| { + AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({ + "provider": "vector-engine", + "message": "ç”Ÿæˆæ•²æœ¨é±¼æ•²å‡»ç‰©å›¾æ¡ˆå¤±è´¥ï¼šä¸Šæ¸¸æœªè¿”回图片", + })) + })?; + let generated_at_micros = current_utc_micros(); + let persisted = persist_wooden_fish_hit_object_asset( + state, + owner_user_id, + session_id, + profile_id, + task_id.as_str(), + &final_prompt, + image, + generated_at_micros, + ) + .await?; + + Ok(persisted) +} + +fn build_wooden_fish_hit_object_prompt(prompt: &str) -> String { + format!( + "请使用 gpt-image-2 生æˆä¸€ä¸ªé€‚åˆç‚¹å‡»æ•²å‡»çŽ©æ³•çš„å•个物å“图案:{}。画é¢è¦æ±‚:å•个主体,å¡é€šæ’ç”»é£Žæ ¼ï¼Œé€æ˜Žæˆ–纯净浅色背景,居中构图,圆润å¯çˆ±ï¼Œè¾¹ç¼˜æ¸…晰,适åˆç§»åŠ¨ç«¯å±å¹•中央展示和点击动画缩放。ä¸è¦åŒ…嫿–‡å­—ã€æŒ‰é’®ã€UIã€è¾¹æ¡†ã€æ°´å°ã€å“牌标识或人物手部。", + clean_string(prompt, DEFAULT_HIT_OBJECT_PROMPT) + ) +} + +fn build_wooden_fish_hit_object_negative_prompt() -> String { + "ä¸è¦ç”Ÿæˆæ–‡å­—ã€Logoã€æ°´å°ã€æŒ‰é’®ã€ç•Œé¢æˆªå›¾ã€å¤æ‚背景ã€å¤šä¸ªä¸»ä½“ã€çœŸå®žæ‘„å½±è´¨æ„Ÿã€ææ€–æˆ–è¡€è…¥å…ƒç´ ã€‚" + .to_string() +} + +async fn persist_wooden_fish_hit_object_asset( + state: &AppState, + owner_user_id: &str, + session_id: &str, + profile_id: &str, + task_id: &str, + prompt: &str, + image: DownloadedOpenAiImage, + generated_at_micros: i64, +) -> Result { + let oss_client = state.oss_client().ok_or_else(|| { + AppError::from_status(StatusCode::SERVICE_UNAVAILABLE).with_details(json!({ + "provider": "aliyun-oss", + "reason": "OSS 未完æˆçŽ¯å¢ƒå˜é‡é…ç½®", + })) + })?; + let http_client = reqwest::Client::new(); + let prepared = + GeneratedImageAssetAdapter::prepare_put_object(GeneratedImageAssetPersistInput { + prefix: LegacyAssetPrefix::WoodenFishAssets, + path_segments: vec![ + sanitize_wooden_fish_asset_segment(session_id, "session"), + sanitize_wooden_fish_asset_segment(profile_id, "profile"), + WOODEN_FISH_HIT_OBJECT_SLOT.to_string(), + format!("asset-{generated_at_micros}"), + ], + file_stem: "image".to_string(), + image: GeneratedImageAssetDataUrl { + format: normalize_generated_image_asset_mime(image.mime_type.as_str()), + bytes: image.bytes, + }, + access: OssObjectAccess::Private, + metadata: GeneratedImageAssetAdapterMetadata { + asset_kind: Some(WOODEN_FISH_HIT_OBJECT_ASSET_KIND.to_string()), + owner_user_id: Some(owner_user_id.to_string()), + entity_kind: Some(WOODEN_FISH_ENTITY_KIND.to_string()), + entity_id: Some(profile_id.to_string()), + slot: Some(WOODEN_FISH_HIT_OBJECT_SLOT.to_string()), + provider: Some("image2".to_string()), + task_id: Some(task_id.to_string()), + }, + extra_metadata: BTreeMap::from([ + ("profile_id".to_string(), profile_id.to_string()), + ("session_id".to_string(), session_id.to_string()), + ]), + }) + .map_err(map_wooden_fish_generated_image_asset_error)?; + let persisted_mime_type = prepared.format.mime_type.clone(); + let put_result = oss_client + .put_object(&http_client, prepared.request) + .await + .map_err(map_wooden_fish_asset_oss_error)?; + let head = oss_client + .head_object( + &http_client, + OssHeadObjectRequest { + object_key: put_result.object_key.clone(), + }, + ) + .await + .map_err(map_wooden_fish_asset_oss_error)?; + let asset_object = state + .spacetime_client() + .confirm_asset_object( + build_asset_object_upsert_input( + generate_asset_object_id(generated_at_micros), + head.bucket, + head.object_key.clone(), + AssetObjectAccessPolicy::Private, + head.content_type.or(Some(persisted_mime_type)), + head.content_length, + head.etag, + WOODEN_FISH_HIT_OBJECT_ASSET_KIND.to_string(), + Some(task_id.to_string()), + Some(owner_user_id.to_string()), + Some(profile_id.to_string()), + Some(profile_id.to_string()), + generated_at_micros, + ) + .map_err(map_wooden_fish_asset_field_error)?, + ) + .await + .map_err(|error| { + AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({ + "provider": "spacetimedb", + "message": error.to_string(), + })) + })?; + if let Err(error) = state + .spacetime_client() + .bind_asset_object_to_entity( + build_asset_entity_binding_input( + generate_asset_binding_id(generated_at_micros), + asset_object.asset_object_id.clone(), + WOODEN_FISH_ENTITY_KIND.to_string(), + profile_id.to_string(), + WOODEN_FISH_HIT_OBJECT_SLOT.to_string(), + WOODEN_FISH_HIT_OBJECT_ASSET_KIND.to_string(), + Some(owner_user_id.to_string()), + Some(profile_id.to_string()), + generated_at_micros, + ) + .map_err(map_wooden_fish_asset_field_error)?, + ) + .await + { + tracing::warn!( + provider = "spacetimedb", + owner_user_id, + session_id, + profile_id, + error = %error, + "敲木鱼图片资产绑定失败,历å²ç´ æç´¢å¼•å¯èƒ½ç¼ºå°‘绑定记录" + ); + } + + Ok(WoodenFishImageAsset { + asset_id: format!("{profile_id}-hit-object-{generated_at_micros}"), + image_src: put_result.legacy_public_path, + image_object_key: head.object_key, + asset_object_id: asset_object.asset_object_id, + generation_provider: "image2".to_string(), + prompt: prompt.to_string(), + width: 1024, + height: 1024, + }) +} + +fn map_wooden_fish_generated_image_asset_error( + error: crate::generated_image_assets::helpers::GeneratedImageAssetHelperError, +) -> AppError { + AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR).with_details(json!({ + "provider": "generated-image-assets", + "message": format!("准备敲木鱼图片资产上传请求失败:{error:?}"), + })) +} + +fn map_wooden_fish_asset_oss_error(error: platform_oss::OssError) -> AppError { + map_oss_error(error, "aliyun-oss") +} + +fn map_wooden_fish_asset_field_error(error: AssetObjectFieldError) -> AppError { + AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR).with_details(json!({ + "provider": "wooden-fish-assets", + "message": error.to_string(), + })) +} + +fn sanitize_wooden_fish_asset_segment(value: &str, fallback: &str) -> String { + let sanitized = value + .trim() + .chars() + .map(|ch| { + if ch.is_ascii_alphanumeric() || ('\u{4e00}'..='\u{9fff}').contains(&ch) { + ch + } else { + '-' + } + }) + .collect::() + .trim_matches('-') + .to_string(); + if sanitized.is_empty() { + fallback.to_string() + } else { + sanitized + } +} + +fn ensure_non_empty( + request_context: &RequestContext, + value: &str, + field: &str, +) -> Result<(), Response> { + if value.trim().is_empty() { + return Err(wooden_fish_error_response( + request_context, + WOODEN_FISH_PROVIDER, + AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({ + "provider": WOODEN_FISH_PROVIDER, + "field": field, + "message": format!("{field} ä¸èƒ½ä¸ºç©º"), + })), + )); + } + Ok(()) +} + +fn clean_string(value: &str, fallback: &str) -> String { + let value = value.trim(); + if value.is_empty() { + fallback.to_string() + } else { + value.to_string() + } +} + +fn normalize_tags(tags: Vec) -> Vec { + let mut normalized = Vec::new(); + for tag in tags { + let tag = tag.trim(); + if tag.is_empty() || normalized.iter().any(|item| item == tag) { + continue; + } + normalized.push(tag.to_string()); + if normalized.len() >= 6 { + break; + } + } + normalized +} + +fn normalize_floating_words(words: Vec) -> Vec { + let mut normalized = Vec::new(); + for word in words { + let word = normalize_floating_word(&word); + if word.is_empty() || normalized.iter().any(|item| item == &word) { + continue; + } + normalized.push(word); + if normalized.len() >= 8 { + break; + } + } + if normalized.is_empty() { + vec![ + "幸è¿".to_string(), + "å¥åº·".to_string(), + "财富".to_string(), + "姻缘".to_string(), + "幸ç¦".to_string(), + "事业".to_string(), + "æˆåŠŸ".to_string(), + "功德".to_string(), + ] + } else { + normalized + } +} + +fn normalize_floating_word(word: &str) -> String { + word.trim() + .trim_end_matches(|ch: char| ch == '1' || ch.is_whitespace()) + .trim_end_matches(['+', '+']) + .trim() + .to_string() +} + +fn wooden_fish_json( + payload: Result, JsonRejection>, + request_context: &RequestContext, + provider: &str, +) -> Result, Response> { + payload.map_err(|error| { + wooden_fish_error_response( + request_context, + provider, + AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({ + "provider": provider, + "message": error.to_string(), + })), + ) + }) +} + +fn map_wooden_fish_client_error(error: SpacetimeClientError) -> AppError { + let status = match &error { + SpacetimeClientError::Runtime(_) => StatusCode::BAD_REQUEST, + SpacetimeClientError::Procedure(message) + if message.contains("ä¸å­˜åœ¨") + || message.contains("not found") + || message.contains("does not exist") => + { + StatusCode::NOT_FOUND + } + SpacetimeClientError::Procedure(message) + if message.contains("å‘布需è¦") + || message.contains("ä¸èƒ½ä¸ºç©º") + || message.contains("å¿…é¡»") => + { + StatusCode::BAD_REQUEST + } + _ => StatusCode::BAD_GATEWAY, + }; + + AppError::from_status(status).with_details(json!({ + "provider": "spacetimedb", + "message": error.to_string(), + })) +} + +fn wooden_fish_error_response( + request_context: &RequestContext, + provider: &str, + error: AppError, +) -> Response { + let mut response = error.into_response_with_context(Some(request_context)); + response.headers_mut().insert( + HeaderName::from_static("x-genarrative-provider"), + header::HeaderValue::from_str(provider) + .unwrap_or_else(|_| header::HeaderValue::from_static("wooden-fish")), + ); + response +} + +fn current_utc_micros() -> i64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|duration| duration.as_micros().min(i64::MAX as u128) as i64) + .unwrap_or(0) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn wooden_fish_hit_object_prompt_keeps_user_object_and_image2_constraints() { + let prompt = build_wooden_fish_hit_object_prompt("èµ›åšèŽ²èŠ±æœ¨é±¼"); + + assert!(prompt.contains("èµ›åšèŽ²èŠ±æœ¨é±¼")); + assert!(prompt.contains("gpt-image-2")); + assert!(prompt.contains("å•个主体")); + assert!(prompt.contains("ä¸è¦åŒ…嫿–‡å­—")); + } + + #[test] + fn wooden_fish_default_hit_object_uses_bundled_asset() { + let asset = default_wooden_fish_hit_object_asset(); + + assert_eq!(asset.asset_id, DEFAULT_HIT_OBJECT_ASSET_ID); + assert_eq!(asset.image_src, DEFAULT_HIT_OBJECT_IMAGE_SRC); + assert_eq!(asset.generation_provider, "bundled-default"); + assert_eq!(asset.width, 1024); + assert_eq!(asset.height, 1024); + } + + #[test] + fn wooden_fish_default_prompt_matches_legacy_defaults() { + assert!(is_default_hit_object_prompt(DEFAULT_HIT_OBJECT_PROMPT)); + assert!(is_default_hit_object_prompt("å¡é€šæœ¨é±¼ï¼Œåœ†æ¶¦å¯çˆ±ï¼Œé€æ˜ŽèƒŒæ™¯")); + assert!(is_default_hit_object_prompt("å¡é€šæœ¨é±¼ï¼Œé€æ˜ŽèƒŒæ™¯ï¼Œå±…中,圆润å¯çˆ±")); + assert!(is_default_hit_object_prompt("å¡é€šæœ¨é±¼")); + assert!(!is_default_hit_object_prompt("èµ›åšèŽ²èŠ±æœ¨é±¼")); + } + + #[test] + fn wooden_fish_asset_segment_sanitizes_for_oss_object_key() { + assert_eq!( + sanitize_wooden_fish_asset_segment("wooden-fish/profile:1", "fallback"), + "wooden-fish-profile-1" + ); + assert_eq!( + sanitize_wooden_fish_asset_segment(" ", "fallback"), + "fallback" + ); + } + + #[test] + fn wooden_fish_audio_asset_maps_from_generated_sound_effect() { + let asset = shared_contracts::creation_audio::CreationAudioAsset { + task_id: "task-hit-sound-1".to_string(), + provider: "vector-engine-vidu".to_string(), + asset_object_id: Some("assetobj-hit-sound-1".to_string()), + asset_kind: Some(WOODEN_FISH_HIT_SOUND_ASSET_KIND.to_string()), + audio_src: "/generated-wooden-fish-assets/wooden-fish-profile-1/hit-sound.mp3" + .to_string(), + prompt: Some("清脆木鱼声".to_string()), + title: None, + updated_at: None, + }; + + let mapped = map_generated_creation_audio_to_wooden_fish_asset( + "wooden-fish-profile-1", + "清脆木鱼声", + asset, + WOODEN_FISH_HIT_SOUND_DURATION_SECONDS, + ) + .expect("generated sound effect should map to wooden fish audio asset"); + + assert_eq!( + mapped.asset_id, + "wooden-fish-profile-1-hit-sound-task-hit-sound-1" + ); + assert_eq!( + mapped.audio_object_key, + "generated-wooden-fish-assets/wooden-fish-profile-1/hit-sound.mp3" + ); + assert_eq!(mapped.asset_object_id, "assetobj-hit-sound-1"); + assert_eq!(mapped.source, "generated"); + assert_eq!(mapped.duration_ms, Some(3_000)); + } +} diff --git a/server-rs/crates/module-jump-hop/src/application.rs b/server-rs/crates/module-jump-hop/src/application.rs index 3521c13a..e7f835bf 100644 --- a/server-rs/crates/module-jump-hop/src/application.rs +++ b/server-rs/crates/module-jump-hop/src/application.rs @@ -348,15 +348,15 @@ mod tests { assert_eq!(perfect.status, JumpHopRunStatus::Playing); assert_eq!(perfect.current_platform_index, 1); - let hit = apply_jump(&run, perfect_charge.saturating_add(80), 200) - .expect("jump should resolve"); + let hit = + apply_jump(&run, perfect_charge.saturating_add(80), 200).expect("jump should resolve"); assert_eq!( hit.last_jump.as_ref().unwrap().result, JumpHopJumpResultKind::Hit ); - let miss = apply_jump(&run, perfect_charge.saturating_add(900), 200) - .expect("jump should resolve"); + let miss = + apply_jump(&run, perfect_charge.saturating_add(900), 200).expect("jump should resolve"); assert_eq!(miss.status, JumpHopRunStatus::Failed); assert_eq!( miss.last_jump.as_ref().unwrap().result, diff --git a/server-rs/crates/module-runtime/src/application.rs b/server-rs/crates/module-runtime/src/application.rs index 7cf2a293..5d6a6475 100644 --- a/server-rs/crates/module-runtime/src/application.rs +++ b/server-rs/crates/module-runtime/src/application.rs @@ -105,6 +105,17 @@ pub fn default_creation_entry_type_snapshots( 45, updated_at_micros, ), + build_default_creation_entry_type_snapshot( + "wooden-fish", + "敲木鱼", + "点击祈ç¦è½»çŽ©æ³•", + "å¯åˆ›å»º", + "/wooden-fish/default-hit-object.png", + true, + true, + 47, + updated_at_micros, + ), build_default_creation_entry_type_snapshot( "square-hole", "方洞", diff --git a/server-rs/crates/module-runtime/src/lib.rs b/server-rs/crates/module-runtime/src/lib.rs index caad0895..892c9ade 100644 --- a/server-rs/crates/module-runtime/src/lib.rs +++ b/server-rs/crates/module-runtime/src/lib.rs @@ -251,6 +251,25 @@ mod tests { assert_eq!(bark_battle.sort_order, 85); } + #[test] + fn default_creation_entry_types_include_wooden_fish() { + let configs = default_creation_entry_type_snapshots(1); + let wooden_fish = configs + .iter() + .find(|item| item.id == "wooden-fish") + .expect("wooden-fish creation entry should be seeded"); + + assert_eq!(wooden_fish.title, "敲木鱼"); + assert!(wooden_fish.visible); + assert!(wooden_fish.open); + assert_eq!(wooden_fish.badge, "å¯åˆ›å»º"); + assert_eq!(wooden_fish.sort_order, 47); + assert_eq!( + wooden_fish.image_src, + "/wooden-fish/default-hit-object.png" + ); + } + #[test] fn normalized_clamps_music_volume_into_valid_range() { let low = RuntimeSettings::normalized(-1.0, RuntimePlatformTheme::Light); diff --git a/server-rs/crates/module-wooden-fish/Cargo.toml b/server-rs/crates/module-wooden-fish/Cargo.toml new file mode 100644 index 00000000..30e0fd30 --- /dev/null +++ b/server-rs/crates/module-wooden-fish/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "module-wooden-fish" +edition.workspace = true +version.workspace = true +license.workspace = true + +[features] +default = [] +spacetime-types = ["dep:spacetimedb"] + +[dependencies] +serde = { workspace = true } +spacetimedb = { workspace = true, optional = true } diff --git a/server-rs/crates/module-wooden-fish/src/application.rs b/server-rs/crates/module-wooden-fish/src/application.rs new file mode 100644 index 00000000..419f58b5 --- /dev/null +++ b/server-rs/crates/module-wooden-fish/src/application.rs @@ -0,0 +1,4 @@ +pub use crate::domain::{ + apply_run_checkpoint, default_floating_words, finish_run, normalize_floating_words, + normalize_word_counters, +}; diff --git a/server-rs/crates/module-wooden-fish/src/commands.rs b/server-rs/crates/module-wooden-fish/src/commands.rs new file mode 100644 index 00000000..f361ad29 --- /dev/null +++ b/server-rs/crates/module-wooden-fish/src/commands.rs @@ -0,0 +1,8 @@ +pub fn normalize_wooden_fish_prompt(value: &str, fallback: &str) -> String { + let value = value.trim(); + if value.is_empty() { + fallback.to_string() + } else { + value.to_string() + } +} diff --git a/server-rs/crates/module-wooden-fish/src/domain.rs b/server-rs/crates/module-wooden-fish/src/domain.rs new file mode 100644 index 00000000..1dc4e5fe --- /dev/null +++ b/server-rs/crates/module-wooden-fish/src/domain.rs @@ -0,0 +1,281 @@ +use serde::{Deserialize, Serialize}; +#[cfg(feature = "spacetime-types")] +use spacetimedb::SpacetimeType; + +pub const WOODEN_FISH_SESSION_ID_PREFIX: &str = "wooden-fish-session-"; +pub const WOODEN_FISH_PROFILE_ID_PREFIX: &str = "wooden-fish-profile-"; +pub const WOODEN_FISH_WORK_ID_PREFIX: &str = "wooden-fish-work-"; +pub const WOODEN_FISH_RUN_ID_PREFIX: &str = "wooden-fish-run-"; + +pub const DEFAULT_FLOATING_WORDS: [&str; 8] = [ + "幸è¿", "å¥åº·", "财富", "姻缘", "幸ç¦", "事业", "æˆåŠŸ", "功德", +]; + +#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum WoodenFishRunStatus { + Playing, + Finished, +} + +#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct WoodenFishWordCounter { + pub text: String, + pub count: u32, +} + +#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct WoodenFishRunSnapshot { + pub run_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub status: WoodenFishRunStatus, + pub total_tap_count: u32, + pub word_counters: Vec, + pub started_at_ms: u64, + pub updated_at_ms: u64, + pub finished_at_ms: Option, +} + +pub fn default_floating_words() -> Vec { + DEFAULT_FLOATING_WORDS + .iter() + .map(|value| (*value).to_string()) + .collect() +} + +pub fn normalize_floating_words(words: &[String]) -> Vec { + let mut normalized: Vec = Vec::new(); + for word in words { + let value = normalize_floating_word(word); + if !value.is_empty() && !normalized.iter().any(|item| item == &value) { + normalized.push(value); + } + if normalized.len() == 8 { + break; + } + } + if normalized.is_empty() { + default_floating_words() + } else { + normalized + } +} + +fn normalize_floating_word(word: &str) -> String { + word.trim() + .trim_end_matches(|ch: char| ch == '1' || ch.is_whitespace()) + .trim_end_matches(['+', '+']) + .trim() + .to_string() +} + +pub fn apply_run_checkpoint( + current: &WoodenFishRunSnapshot, + total_tap_count: u32, + word_counters: Vec, + updated_at_ms: u64, +) -> WoodenFishRunSnapshot { + WoodenFishRunSnapshot { + total_tap_count, + word_counters: normalize_word_counters(word_counters), + updated_at_ms, + ..current.clone() + } +} + +pub fn finish_run( + current: &WoodenFishRunSnapshot, + total_tap_count: u32, + word_counters: Vec, + finished_at_ms: u64, +) -> WoodenFishRunSnapshot { + WoodenFishRunSnapshot { + status: WoodenFishRunStatus::Finished, + total_tap_count, + word_counters: normalize_word_counters(word_counters), + updated_at_ms: finished_at_ms, + finished_at_ms: Some(finished_at_ms), + ..current.clone() + } +} + +pub fn normalize_word_counters(counters: Vec) -> Vec { + let mut normalized: Vec = Vec::new(); + for counter in counters { + let text = normalize_floating_word(&counter.text); + if text.is_empty() || counter.count == 0 { + continue; + } + if let Some(existing) = normalized.iter_mut().find(|item| item.text == text) { + existing.count = existing.count.saturating_add(counter.count); + } else { + normalized.push(WoodenFishWordCounter { + text, + count: counter.count, + }); + } + if normalized.len() == 8 { + break; + } + } + normalized +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn floating_words_default_to_eight_blessing_entries() { + assert_eq!( + default_floating_words(), + vec![ + "幸è¿".to_string(), + "å¥åº·".to_string(), + "财富".to_string(), + "姻缘".to_string(), + "幸ç¦".to_string(), + "事业".to_string(), + "æˆåŠŸ".to_string(), + "功德".to_string(), + ] + ); + } + + #[test] + fn floating_words_are_trimmed_deduped_and_capped_at_eight() { + let words = vec![ + " 幸è¿+1 ".to_string(), + "幸è¿".to_string(), + "å¥åº·".to_string(), + "财富".to_string(), + "姻缘".to_string(), + "幸ç¦".to_string(), + "事业".to_string(), + "æˆåŠŸ".to_string(), + "功德".to_string(), + "å¿«ä¹".to_string(), + ]; + + assert_eq!(normalize_floating_words(&words).len(), 8); + assert_eq!(normalize_floating_words(&words)[0], "幸è¿"); + assert_eq!(normalize_floating_words(&words)[7], "功德"); + } + + #[test] + fn checkpoint_replaces_single_run_counter_snapshot() { + let current = WoodenFishRunSnapshot { + run_id: "wooden-fish-run-1".to_string(), + profile_id: "wooden-fish-profile-1".to_string(), + owner_user_id: "user-1".to_string(), + status: WoodenFishRunStatus::Playing, + total_tap_count: 0, + word_counters: Vec::new(), + started_at_ms: 100, + updated_at_ms: 100, + finished_at_ms: None, + }; + + let next = apply_run_checkpoint( + ¤t, + 2, + vec![WoodenFishWordCounter { + text: "功德".to_string(), + count: 2, + }], + 160, + ); + + assert_eq!(next.total_tap_count, 2); + assert_eq!(next.word_counters[0].text, "功德"); + assert_eq!(next.updated_at_ms, 160); + assert_eq!(next.started_at_ms, 100); + } + + #[test] + fn word_counters_are_trimmed_deduped_and_capped_at_eight() { + let counters = vec![ + WoodenFishWordCounter { + text: " 幸è¿+1 ".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "幸è¿+1".to_string(), + count: 2, + }, + WoodenFishWordCounter { + text: "å¥åº·+1".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "财富+1".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "姻缘+1".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "幸ç¦+1".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "事业+1".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "æˆåŠŸ+1".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "功德+1".to_string(), + count: 1, + }, + WoodenFishWordCounter { + text: "å¿«ä¹+1".to_string(), + count: 1, + }, + ]; + + let normalized = normalize_word_counters(counters); + + assert_eq!(normalized.len(), 8); + assert_eq!(normalized[0].text, "幸è¿"); + assert_eq!(normalized[0].count, 3); + assert_eq!(normalized[7].text, "功德"); + } + + #[test] + fn finish_run_sets_status_and_finished_timestamp() { + let current = WoodenFishRunSnapshot { + run_id: "wooden-fish-run-1".to_string(), + profile_id: "wooden-fish-profile-1".to_string(), + owner_user_id: "user-1".to_string(), + status: WoodenFishRunStatus::Playing, + total_tap_count: 3, + word_counters: Vec::new(), + started_at_ms: 100, + updated_at_ms: 130, + finished_at_ms: None, + }; + + let next = finish_run( + ¤t, + 4, + vec![WoodenFishWordCounter { + text: "å¥åº·".to_string(), + count: 4, + }], + 220, + ); + + assert_eq!(next.status, WoodenFishRunStatus::Finished); + assert_eq!(next.total_tap_count, 4); + assert_eq!(next.updated_at_ms, 220); + assert_eq!(next.finished_at_ms, Some(220)); + assert_eq!(next.word_counters[0].text, "å¥åº·"); + } +} diff --git a/server-rs/crates/module-wooden-fish/src/errors.rs b/server-rs/crates/module-wooden-fish/src/errors.rs new file mode 100644 index 00000000..e7d4ff72 --- /dev/null +++ b/server-rs/crates/module-wooden-fish/src/errors.rs @@ -0,0 +1,23 @@ +use std::fmt::{self, Display}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum WoodenFishError { + MissingRunId, + MissingProfileId, + MissingOwnerUserId, + RunNotPlaying, +} + +impl Display for WoodenFishError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let message = match self { + Self::MissingRunId => "缺少 runId", + Self::MissingProfileId => "缺少 profileId", + Self::MissingOwnerUserId => "owner_user_id 缺失", + Self::RunNotPlaying => "当å‰è¿è¡Œæ€ä¸æ˜¯ playing", + }; + write!(f, "{message}") + } +} + +impl std::error::Error for WoodenFishError {} diff --git a/server-rs/crates/module-wooden-fish/src/events.rs b/server-rs/crates/module-wooden-fish/src/events.rs new file mode 100644 index 00000000..ae4f1a49 --- /dev/null +++ b/server-rs/crates/module-wooden-fish/src/events.rs @@ -0,0 +1,25 @@ +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum WoodenFishDomainEvent { + DraftCompiled { + profile_id: String, + owner_user_id: String, + occurred_at_micros: i64, + }, + WorkPublished { + profile_id: String, + owner_user_id: String, + occurred_at_micros: i64, + }, + RunCheckpointed { + run_id: String, + owner_user_id: String, + total_tap_count: u32, + occurred_at_micros: i64, + }, + RunFinished { + run_id: String, + owner_user_id: String, + total_tap_count: u32, + occurred_at_micros: i64, + }, +} diff --git a/server-rs/crates/module-wooden-fish/src/lib.rs b/server-rs/crates/module-wooden-fish/src/lib.rs new file mode 100644 index 00000000..6acdc7c7 --- /dev/null +++ b/server-rs/crates/module-wooden-fish/src/lib.rs @@ -0,0 +1,11 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + +pub use application::*; +pub use commands::*; +pub use domain::*; +pub use errors::*; +pub use events::*; diff --git a/server-rs/crates/platform-oss/src/lib.rs b/server-rs/crates/platform-oss/src/lib.rs index 61a4f301..8a00d7a6 100644 --- a/server-rs/crates/platform-oss/src/lib.rs +++ b/server-rs/crates/platform-oss/src/lib.rs @@ -20,12 +20,13 @@ const OSS_V4_REQUEST: &str = "aliyun_v4_request"; const OSS_V4_SERVICE: &str = "oss"; const OSS_UNSIGNED_PAYLOAD: &str = "UNSIGNED-PAYLOAD"; -pub const LEGACY_PUBLIC_PREFIXES: [&str; 10] = [ +pub const LEGACY_PUBLIC_PREFIXES: [&str; 11] = [ "generated-character-drafts", "generated-characters", "generated-animations", "generated-big-fish-assets", "generated-square-hole-assets", + "generated-wooden-fish-assets", "generated-match3d-assets", "generated-puzzle-assets", "generated-custom-world-scenes", @@ -47,6 +48,7 @@ pub enum LegacyAssetPrefix { Animations, BigFishAssets, SquareHoleAssets, + WoodenFishAssets, Match3DAssets, PuzzleAssets, CustomWorldScenes, @@ -234,6 +236,7 @@ impl LegacyAssetPrefix { "generated-animations" => Some(Self::Animations), "generated-big-fish-assets" => Some(Self::BigFishAssets), "generated-square-hole-assets" => Some(Self::SquareHoleAssets), + "generated-wooden-fish-assets" => Some(Self::WoodenFishAssets), "generated-match3d-assets" => Some(Self::Match3DAssets), "generated-puzzle-assets" => Some(Self::PuzzleAssets), "generated-custom-world-scenes" => Some(Self::CustomWorldScenes), @@ -250,6 +253,7 @@ impl LegacyAssetPrefix { Self::Animations => "generated-animations", Self::BigFishAssets => "generated-big-fish-assets", Self::SquareHoleAssets => "generated-square-hole-assets", + Self::WoodenFishAssets => "generated-wooden-fish-assets", Self::Match3DAssets => "generated-match3d-assets", Self::PuzzleAssets => "generated-puzzle-assets", Self::CustomWorldScenes => "generated-custom-world-scenes", @@ -1313,8 +1317,13 @@ mod tests { LegacyAssetPrefix::parse("/generated-match3d-assets/*"), Some(LegacyAssetPrefix::Match3DAssets) ); + assert_eq!( + LegacyAssetPrefix::parse("/generated-wooden-fish-assets/*"), + Some(LegacyAssetPrefix::WoodenFishAssets) + ); assert!(LEGACY_PUBLIC_PREFIXES.contains(&"generated-puzzle-assets")); assert!(LEGACY_PUBLIC_PREFIXES.contains(&"generated-match3d-assets")); + assert!(LEGACY_PUBLIC_PREFIXES.contains(&"generated-wooden-fish-assets")); assert_eq!(LegacyAssetPrefix::parse("unknown"), None); } @@ -1554,6 +1563,12 @@ mod tests { ), Some(LegacyAssetPrefix::CustomWorldScenes) ); + assert_eq!( + LegacyAssetPrefix::from_object_key( + "generated-wooden-fish-assets/session/profile/hit_object/asset/image.png" + ), + Some(LegacyAssetPrefix::WoodenFishAssets) + ); assert_eq!( LegacyAssetPrefix::from_object_key("workflow-cache/demo.json"), None diff --git a/server-rs/crates/shared-contracts/src/creation_audio.rs b/server-rs/crates/shared-contracts/src/creation_audio.rs index 21d37478..f6a3ca41 100644 --- a/server-rs/crates/shared-contracts/src/creation_audio.rs +++ b/server-rs/crates/shared-contracts/src/creation_audio.rs @@ -61,6 +61,7 @@ pub enum CreationAudioStoragePrefix { PuzzleAssets, #[serde(rename = "match3d_assets")] Match3DAssets, + WoodenFishAssets, CustomWorldScenes, } @@ -125,4 +126,20 @@ mod tests { assert_eq!(payload["taskId"], json!("task-1")); assert_eq!(payload["audioSrc"], json!("/generated-puzzle-assets/a.mp3")); } + + #[test] + fn creation_audio_contracts_support_wooden_fish_storage_prefix() { + let request = PublishGeneratedAudioAssetRequest { + entity_kind: "wooden_fish_work".to_string(), + entity_id: "wooden-fish-profile-1".to_string(), + slot: "hit_sound".to_string(), + asset_kind: "wooden_fish_hit_sound".to_string(), + profile_id: Some("wooden-fish-profile-1".to_string()), + storage_prefix: Some(CreationAudioStoragePrefix::WoodenFishAssets), + }; + + let payload = serde_json::to_value(request).expect("request should serialize"); + + assert_eq!(payload["storagePrefix"], json!("wooden_fish_assets")); + } } diff --git a/server-rs/crates/shared-contracts/src/lib.rs b/server-rs/crates/shared-contracts/src/lib.rs index 5324480d..ea60bfe9 100644 --- a/server-rs/crates/shared-contracts/src/lib.rs +++ b/server-rs/crates/shared-contracts/src/lib.rs @@ -29,3 +29,4 @@ pub mod square_hole_runtime; pub mod square_hole_works; pub mod story; pub mod visual_novel; +pub mod wooden_fish; diff --git a/server-rs/crates/shared-contracts/src/wooden_fish.rs b/server-rs/crates/shared-contracts/src/wooden_fish.rs new file mode 100644 index 00000000..105d11b1 --- /dev/null +++ b/server-rs/crates/shared-contracts/src/wooden_fish.rs @@ -0,0 +1,485 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum WoodenFishGenerationStatus { + Draft, + Generating, + Ready, + Failed, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum WoodenFishActionType { + CompileDraft, + RegenerateHitObject, + GenerateHitSound, + ReplaceHitSound, + UpdateWorkMeta, + UpdateFloatingWords, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum WoodenFishRunStatus { + Playing, + Finished, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishImageAsset { + pub asset_id: String, + pub image_src: String, + pub image_object_key: String, + pub asset_object_id: String, + pub generation_provider: String, + pub prompt: String, + pub width: u32, + pub height: u32, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishAudioAsset { + pub asset_id: String, + pub audio_src: String, + pub audio_object_key: String, + pub asset_object_id: String, + pub source: String, + #[serde(default)] + pub prompt: Option, + #[serde(default)] + pub duration_ms: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishWorkspaceCreateRequest { + pub template_id: String, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + #[serde(default)] + pub hit_object_reference_image_src: Option, + #[serde(default)] + pub hit_sound_prompt: Option, + #[serde(default)] + pub hit_sound_asset: Option, + pub floating_words: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishActionRequest { + pub action_type: WoodenFishActionType, + #[serde(default, skip_deserializing)] + pub profile_id: Option, + #[serde(default)] + pub work_title: Option, + #[serde(default)] + pub work_description: Option, + #[serde(default)] + pub theme_tags: Option>, + #[serde(default)] + pub hit_object_prompt: Option, + #[serde(default)] + pub hit_object_reference_image_src: Option, + #[serde(default, skip_deserializing)] + pub hit_object_asset: Option, + #[serde(default)] + pub hit_sound_prompt: Option, + #[serde(default)] + pub hit_sound_asset: Option, + #[serde(default)] + pub floating_words: Option>, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishWordCounter { + pub text: String, + pub count: u32, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishDraftResponse { + pub template_id: String, + pub template_name: String, + #[serde(default)] + pub profile_id: Option, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + #[serde(default)] + pub hit_object_reference_image_src: Option, + #[serde(default)] + pub hit_sound_prompt: Option, + pub floating_words: Vec, + #[serde(default)] + pub hit_object_asset: Option, + #[serde(default)] + pub hit_sound_asset: Option, + #[serde(default)] + pub cover_image_src: Option, + pub generation_status: WoodenFishGenerationStatus, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishSessionSnapshotResponse { + pub session_id: String, + pub owner_user_id: String, + pub status: WoodenFishGenerationStatus, + #[serde(default)] + pub draft: Option, + pub created_at: String, + pub updated_at: String, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishSessionResponse { + pub session: WoodenFishSessionSnapshotResponse, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishActionResponse { + pub action_type: WoodenFishActionType, + pub session: WoodenFishSessionSnapshotResponse, + #[serde(default)] + pub work: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishWorkSummaryResponse { + pub runtime_kind: String, + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + #[serde(default)] + pub source_session_id: Option, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + #[serde(default)] + pub cover_image_src: Option, + pub publication_status: String, + pub play_count: u32, + pub updated_at: String, + #[serde(default)] + pub published_at: Option, + pub publish_ready: bool, + pub generation_status: WoodenFishGenerationStatus, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishWorkProfileResponse { + pub summary: WoodenFishWorkSummaryResponse, + pub draft: WoodenFishDraftResponse, + pub hit_object_asset: WoodenFishImageAsset, + pub hit_sound_asset: WoodenFishAudioAsset, + pub floating_words: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishWorkDetailResponse { + pub item: WoodenFishWorkProfileResponse, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishWorkMutationResponse { + pub item: WoodenFishWorkProfileResponse, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishGalleryCardResponse { + pub public_work_code: String, + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + #[serde(default)] + pub cover_image_src: Option, + pub theme_tags: Vec, + pub publication_status: String, + pub play_count: u32, + pub updated_at: String, + #[serde(default)] + pub published_at: Option, + pub generation_status: WoodenFishGenerationStatus, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishGalleryResponse { + pub items: Vec, + pub has_more: bool, + #[serde(default)] + pub next_cursor: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishGalleryDetailResponse { + pub item: WoodenFishWorkProfileResponse, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishRuntimeRunSnapshotResponse { + pub run_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub status: WoodenFishRunStatus, + pub total_tap_count: u32, + pub word_counters: Vec, + pub started_at_ms: u64, + pub updated_at_ms: u64, + #[serde(default)] + pub finished_at_ms: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishRunResponse { + pub run: WoodenFishRuntimeRunSnapshotResponse, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishStartRunRequest { + pub profile_id: String, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishCheckpointRunRequest { + pub total_tap_count: u32, + pub word_counters: Vec, + pub client_event_id: String, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishFinishRunRequest { + pub total_tap_count: u32, + pub word_counters: Vec, + pub client_event_id: String, +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + #[test] + fn wooden_fish_workspace_request_uses_camel_case_and_default_words() { + let payload = serde_json::to_value(WoodenFishWorkspaceCreateRequest { + template_id: "wooden-fish".to_string(), + work_title: "今日敲木鱼".to_string(), + work_description: "è½»æ¾æ•²å‡»".to_string(), + theme_tags: vec!["休闲".to_string()], + hit_object_prompt: "å¡é€šæœ¨é±¼".to_string(), + hit_object_reference_image_src: None, + hit_sound_prompt: Some("清脆木鱼声".to_string()), + hit_sound_asset: None, + floating_words: vec![ + "幸è¿".to_string(), + "å¥åº·".to_string(), + "财富".to_string(), + "姻缘".to_string(), + "幸ç¦".to_string(), + "事业".to_string(), + "æˆåŠŸ".to_string(), + "功德".to_string(), + ], + }) + .expect("payload should serialize"); + + assert_eq!(payload["templateId"], json!("wooden-fish")); + assert_eq!(payload["hitObjectPrompt"], json!("å¡é€šæœ¨é±¼")); + assert_eq!(payload["hitSoundPrompt"], json!("清脆木鱼声")); + assert_eq!(payload["floatingWords"][7], json!("功德")); + } + + #[test] + fn wooden_fish_runtime_snapshot_counts_words_inside_one_run() { + let payload = serde_json::to_value(WoodenFishRuntimeRunSnapshotResponse { + run_id: "wooden-fish-run-1".to_string(), + profile_id: "wooden-fish-profile-1".to_string(), + owner_user_id: "user-1".to_string(), + status: WoodenFishRunStatus::Playing, + total_tap_count: 3, + word_counters: vec![ + WoodenFishWordCounter { + text: "幸è¿".to_string(), + count: 2, + }, + WoodenFishWordCounter { + text: "功德".to_string(), + count: 1, + }, + ], + started_at_ms: 100, + updated_at_ms: 130, + finished_at_ms: None, + }) + .expect("payload should serialize"); + + assert_eq!(payload["status"], json!("playing")); + assert_eq!(payload["totalTapCount"], json!(3)); + assert_eq!(payload["wordCounters"][0]["text"], json!("幸è¿")); + } + + #[test] + fn wooden_fish_action_request_serializes_audio_and_image_fields() { + let payload = serde_json::to_value(WoodenFishActionRequest { + action_type: WoodenFishActionType::ReplaceHitSound, + profile_id: Some("wooden-fish-profile-1".to_string()), + work_title: None, + work_description: None, + theme_tags: None, + hit_object_prompt: Some("å¡é€šé“œé’¹".to_string()), + hit_object_reference_image_src: Some("/uploads/reference.png".to_string()), + hit_object_asset: Some(WoodenFishImageAsset { + asset_id: "image-1".to_string(), + image_src: "/generated-wooden-fish-assets/profile/hit-object/image.png".to_string(), + image_object_key: "generated-wooden-fish-assets/profile/hit-object/image.png" + .to_string(), + asset_object_id: "image-object-1".to_string(), + generation_provider: "image2".to_string(), + prompt: "å¡é€šé“œé’¹".to_string(), + width: 1024, + height: 1024, + }), + hit_sound_prompt: Some("短促木鱼声".to_string()), + hit_sound_asset: Some(WoodenFishAudioAsset { + asset_id: "sound-1".to_string(), + audio_src: "/generated/wooden-fish.mp3".to_string(), + audio_object_key: "generated/wooden-fish.mp3".to_string(), + asset_object_id: "asset-object-1".to_string(), + source: "upload".to_string(), + prompt: None, + duration_ms: Some(800), + }), + floating_words: Some(vec!["功德".to_string()]), + }) + .expect("payload should serialize"); + + assert_eq!(payload["actionType"], json!("replace-hit-sound")); + assert_eq!(payload["profileId"], json!("wooden-fish-profile-1")); + assert_eq!(payload["hitObjectPrompt"], json!("å¡é€šé“œé’¹")); + assert_eq!( + payload["hitObjectAsset"]["imageObjectKey"], + json!("generated-wooden-fish-assets/profile/hit-object/image.png") + ); + assert_eq!(payload["hitSoundAsset"]["source"], json!("upload")); + assert_eq!(payload["hitSoundAsset"]["durationMs"], json!(800)); + } + + #[test] + fn wooden_fish_action_request_ignores_client_hit_object_asset() { + let payload = serde_json::from_value::(json!({ + "actionType": "compile-draft", + "hitObjectPrompt": "å¡é€šé“œé’¹", + "hitObjectAsset": { + "assetId": "client-image", + "imageSrc": "/generated-wooden-fish-assets/client/image.png", + "imageObjectKey": "generated-wooden-fish-assets/client/image.png", + "assetObjectId": "client-asset-object", + "generationProvider": "client", + "prompt": "跳过生æˆ", + "width": 1024, + "height": 1024 + } + })) + .expect("payload should deserialize"); + + assert_eq!(payload.action_type, WoodenFishActionType::CompileDraft); + assert_eq!(payload.hit_object_prompt.as_deref(), Some("å¡é€šé“œé’¹")); + assert_eq!(payload.hit_object_asset, None); + } + + #[test] + fn wooden_fish_work_profile_keeps_summary_and_runtime_assets() { + let image = WoodenFishImageAsset { + asset_id: "image-1".to_string(), + image_src: "/generated/wooden-fish.png".to_string(), + image_object_key: "generated/wooden-fish.png".to_string(), + asset_object_id: "image-object-1".to_string(), + generation_provider: "image2".to_string(), + prompt: "å¡é€šæœ¨é±¼".to_string(), + width: 1024, + height: 1024, + }; + let audio = WoodenFishAudioAsset { + asset_id: "sound-1".to_string(), + audio_src: "/generated/wooden-fish.mp3".to_string(), + audio_object_key: "generated/wooden-fish.mp3".to_string(), + asset_object_id: "sound-object-1".to_string(), + source: "generated".to_string(), + prompt: Some("清脆木鱼".to_string()), + duration_ms: Some(600), + }; + let profile = WoodenFishWorkProfileResponse { + summary: WoodenFishWorkSummaryResponse { + runtime_kind: "wooden-fish".to_string(), + work_id: "wooden-fish-profile-1".to_string(), + profile_id: "wooden-fish-profile-1".to_string(), + owner_user_id: "user-1".to_string(), + source_session_id: Some("wooden-fish-session-1".to_string()), + work_title: "敲木鱼".to_string(), + work_description: String::new(), + theme_tags: vec!["休闲".to_string()], + cover_image_src: Some(image.image_src.clone()), + publication_status: "draft".to_string(), + play_count: 0, + updated_at: "2026-05-20T00:00:00Z".to_string(), + published_at: None, + publish_ready: true, + generation_status: WoodenFishGenerationStatus::Ready, + }, + draft: WoodenFishDraftResponse { + template_id: "wooden-fish".to_string(), + template_name: "敲木鱼".to_string(), + profile_id: Some("wooden-fish-profile-1".to_string()), + work_title: "敲木鱼".to_string(), + work_description: String::new(), + theme_tags: vec!["休闲".to_string()], + hit_object_prompt: "å¡é€šæœ¨é±¼".to_string(), + hit_object_reference_image_src: None, + hit_sound_prompt: Some("清脆木鱼".to_string()), + floating_words: vec!["功德".to_string()], + hit_object_asset: Some(image.clone()), + hit_sound_asset: Some(audio.clone()), + cover_image_src: Some(image.image_src.clone()), + generation_status: WoodenFishGenerationStatus::Ready, + }, + hit_object_asset: image, + hit_sound_asset: audio, + floating_words: vec!["功德".to_string()], + }; + + let payload = serde_json::to_value(profile).expect("profile should serialize"); + + assert_eq!(payload["summary"]["runtimeKind"], json!("wooden-fish")); + assert_eq!( + payload["hitObjectAsset"]["generationProvider"], + json!("image2") + ); + assert_eq!(payload["hitSoundAsset"]["source"], json!("generated")); + } +} diff --git a/server-rs/crates/shared-logging/src/lib.rs b/server-rs/crates/shared-logging/src/lib.rs index ad77a6fb..6ab9470d 100644 --- a/server-rs/crates/shared-logging/src/lib.rs +++ b/server-rs/crates/shared-logging/src/lib.rs @@ -4,10 +4,7 @@ use opentelemetry::{KeyValue, global, trace::TracerProvider}; use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; use opentelemetry_otlp::WithExportConfig; use opentelemetry_sdk::{ - Resource, - logs::SdkLoggerProvider, - metrics::SdkMeterProvider, - trace::SdkTracerProvider, + Resource, logs::SdkLoggerProvider, metrics::SdkMeterProvider, trace::SdkTracerProvider, }; use tracing::warn; use tracing_subscriber::{ @@ -54,9 +51,7 @@ pub fn init_tracing(default_filter: &str, otel_config: OtelConfig) -> Result<(), tracing_opentelemetry::layer() .with_tracer(otel.tracer_provider.tracer("genarrative-api")), ) - .with( - OpenTelemetryTracingBridge::new(&otel.logger_provider).with_filter(LevelFilter::INFO), - ) + .with(OpenTelemetryTracingBridge::new(&otel.logger_provider).with_filter(LevelFilter::INFO)) .try_init() .map_err(|error| io::Error::other(format!("åˆå§‹åŒ– tracing subscriber 失败:{error}"))) } @@ -127,10 +122,12 @@ fn build_otel_pipeline() -> Option { .with_periodic_exporter(metric_exporter) .build(); let logger_provider = SdkLoggerProvider::builder() - .with_resource(Resource::builder() - .with_service_name(read_env_or_default("OTEL_SERVICE_NAME", "genarrative-api")) - .with_attribute(KeyValue::new("service.namespace", "genarrative")) - .build()) + .with_resource( + Resource::builder() + .with_service_name(read_env_or_default("OTEL_SERVICE_NAME", "genarrative-api")) + .with_attribute(KeyValue::new("service.namespace", "genarrative")) + .build(), + ) .with_batch_exporter(log_exporter) .build(); diff --git a/server-rs/crates/spacetime-client/Cargo.toml b/server-rs/crates/spacetime-client/Cargo.toml index 95c172ef..fcb0c9ce 100644 --- a/server-rs/crates/spacetime-client/Cargo.toml +++ b/server-rs/crates/spacetime-client/Cargo.toml @@ -12,6 +12,7 @@ module-combat = { workspace = true } module-custom-world = { workspace = true } module-inventory = { workspace = true } module-jump-hop = { workspace = true } +module-wooden-fish = { workspace = true } module-match3d = { workspace = true } module-npc = { workspace = true } module-puzzle = { workspace = true } diff --git a/server-rs/crates/spacetime-client/src/jump_hop.rs b/server-rs/crates/spacetime-client/src/jump_hop.rs index 1b22eddf..7d798b88 100644 --- a/server-rs/crates/spacetime-client/src/jump_hop.rs +++ b/server-rs/crates/spacetime-client/src/jump_hop.rs @@ -5,11 +5,11 @@ use crate::mapper::{ map_jump_hop_works_procedure_result, }; use shared_contracts::jump_hop::{ - JumpHopActionRequest, JumpHopActionResponse, JumpHopActionType, JumpHopCharacterAsset, JumpHopDifficulty, - JumpHopDraftResponse, JumpHopGalleryResponse, JumpHopGenerationStatus, JumpHopJumpRequest, - JumpHopRestartRunRequest, JumpHopRuntimeRunSnapshotResponse, JumpHopSessionSnapshotResponse, - JumpHopStartRunRequest, JumpHopStylePreset, JumpHopTileAsset, JumpHopTileType, - JumpHopWorkProfileResponse, + JumpHopActionRequest, JumpHopActionResponse, JumpHopActionType, JumpHopCharacterAsset, + JumpHopDifficulty, JumpHopDraftResponse, JumpHopGalleryResponse, JumpHopGenerationStatus, + JumpHopJumpRequest, JumpHopRestartRunRequest, JumpHopRuntimeRunSnapshotResponse, + JumpHopSessionSnapshotResponse, JumpHopStartRunRequest, JumpHopStylePreset, JumpHopTileAsset, + JumpHopTileType, JumpHopWorkProfileResponse, }; use shared_kernel::build_prefixed_uuid_id; @@ -21,10 +21,9 @@ impl SpacetimeClient { &self, session: JumpHopSessionSnapshotResponse, ) -> Result { - let draft = session - .draft - .clone() - .ok_or_else(|| SpacetimeClientError::validation_failed("jump-hop session 缺少 draft"))?; + let draft = session.draft.clone().ok_or_else(|| { + SpacetimeClientError::validation_failed("jump-hop session 缺少 draft") + })?; let theme_tags_json = Some(json_string(&draft.theme_tags)?); let config_json = Some(build_config_json(&draft)?); let work_title = draft.work_title.clone(); @@ -164,15 +163,14 @@ impl SpacetimeClient { procedure_input: JumpHopWorkUpdateInput, ) -> Result { self.call_after_connect("update_jump_hop_work", move |connection, sender| { - connection.procedures().update_jump_hop_work_then( - procedure_input, - move |_, result| { + connection + .procedures() + .update_jump_hop_work_then(procedure_input, move |_, result| { let mapped = result .map_err(SpacetimeClientError::from_sdk_error) .and_then(map_jump_hop_work_procedure_result); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -212,15 +210,14 @@ impl SpacetimeClient { }; self.call_after_connect("list_jump_hop_works", move |connection, sender| { - connection.procedures().list_jump_hop_works_then( - procedure_input, - move |_, result| { + connection + .procedures() + .list_jump_hop_works_then(procedure_input, move |_, result| { let mapped = result .map_err(SpacetimeClientError::from_sdk_error) .and_then(map_jump_hop_works_procedure_result); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -229,7 +226,8 @@ impl SpacetimeClient { &self, profile_id: String, ) -> Result { - self.get_jump_hop_work_profile(profile_id, String::new()).await + self.get_jump_hop_work_profile(profile_id, String::new()) + .await } pub async fn start_jump_hop_run( @@ -253,15 +251,14 @@ impl SpacetimeClient { procedure_input: JumpHopRunStartInput, ) -> Result { self.call_after_connect("start_jump_hop_run", move |connection, sender| { - connection.procedures().start_jump_hop_run_then( - procedure_input, - move |_, result| { + connection + .procedures() + .start_jump_hop_run_then(procedure_input, move |_, result| { let mapped = result .map_err(SpacetimeClientError::from_sdk_error) .and_then(map_jump_hop_run_procedure_result); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -277,15 +274,14 @@ impl SpacetimeClient { }; self.call_after_connect("get_jump_hop_run", move |connection, sender| { - connection.procedures().get_jump_hop_run_then( - procedure_input, - move |_, result| { + connection + .procedures() + .get_jump_hop_run_then(procedure_input, move |_, result| { let mapped = result .map_err(SpacetimeClientError::from_sdk_error) .and_then(map_jump_hop_run_procedure_result); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -305,15 +301,14 @@ impl SpacetimeClient { }; self.call_after_connect("jump_hop_jump", move |connection, sender| { - connection.procedures().jump_hop_jump_then( - procedure_input, - move |_, result| { + connection + .procedures() + .jump_hop_jump_then(procedure_input, move |_, result| { let mapped = result .map_err(SpacetimeClientError::from_sdk_error) .and_then(map_jump_hop_run_procedure_result); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -333,15 +328,14 @@ impl SpacetimeClient { }; self.call_after_connect("restart_jump_hop_run", move |connection, sender| { - connection.procedures().restart_jump_hop_run_then( - procedure_input, - move |_, result| { + connection + .procedures() + .restart_jump_hop_run_then(procedure_input, move |_, result| { let mapped = result .map_err(SpacetimeClientError::from_sdk_error) .and_then(map_jump_hop_run_procedure_result); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -430,16 +424,16 @@ fn build_jump_hop_action_plan( JumpHopAssetRefresh::Preserve, now_micros, )?), - JumpHopActionType::RegenerateCharacter => JumpHopActionProcedure::Compile( - build_compile_input( + JumpHopActionType::RegenerateCharacter => { + JumpHopActionProcedure::Compile(build_compile_input( current, owner_user_id, &profile_id, &mut draft, JumpHopAssetRefresh::Character, now_micros, - )?, - ), + )?) + } JumpHopActionType::RegenerateTiles => JumpHopActionProcedure::Compile(build_compile_input( current, owner_user_id, @@ -472,7 +466,11 @@ fn merge_action_into_draft( scope, JumpHopDraftMergeScope::CompileDraft | JumpHopDraftMergeScope::UpdateWorkMeta ) { - if let Some(value) = payload.work_title.as_ref().filter(|value| !value.trim().is_empty()) { + if let Some(value) = payload + .work_title + .as_ref() + .filter(|value| !value.trim().is_empty()) + { draft.work_title = value.trim().to_string(); } if let Some(value) = payload.work_description.as_ref() { @@ -523,7 +521,9 @@ fn merge_action_into_draft( draft.tile_prompt = value.trim().to_string(); } if draft.work_title.trim().is_empty() { - return Err(SpacetimeClientError::validation_failed("jump-hop work_title ä¸èƒ½ä¸ºç©º")); + return Err(SpacetimeClientError::validation_failed( + "jump-hop work_title ä¸èƒ½ä¸ºç©º", + )); } Ok(draft) } @@ -762,7 +762,9 @@ fn ensure_tile_assets( .map(|(index, tile_type)| JumpHopTileAsset { tile_type, image_src: format!("/generated-jump-hop-assets/{profile_id}/tiles/{index}{suffix}.png"), - image_object_key: format!("generated-jump-hop-assets/{profile_id}/tiles/{index}{suffix}.png"), + image_object_key: format!( + "generated-jump-hop-assets/{profile_id}/tiles/{index}{suffix}.png" + ), asset_object_id: format!("{profile_id}-tile-{index}{suffix}-object"), source_atlas_cell: format!("cell-{index}{suffix}"), visual_width: 256, @@ -788,7 +790,9 @@ fn resolve_cover_composite( { return Some(value.to_string()); } - let suffix = asset_revision_suffix((!matches!(refresh, JumpHopAssetRefresh::Preserve)).then_some(now_micros)); + let suffix = asset_revision_suffix( + (!matches!(refresh, JumpHopAssetRefresh::Preserve)).then_some(now_micros), + ); Some(format!( "/generated-jump-hop-assets/{profile_id}/cover-composite{suffix}.png" )) @@ -850,9 +854,27 @@ mod tests { assert_eq!(input.session_id, SESSION_ID); assert_eq!(input.owner_user_id, OWNER_USER_ID); assert_eq!(input.generation_status.as_deref(), Some("ready")); - assert!(input.character_asset_json.as_deref().unwrap_or("").contains("-character")); - assert!(input.tile_atlas_asset_json.as_deref().unwrap_or("").contains("-tile-atlas")); - assert!(input.tile_assets_json.as_deref().unwrap_or("").contains("tile-0-object")); + assert!( + input + .character_asset_json + .as_deref() + .unwrap_or("") + .contains("-character") + ); + assert!( + input + .tile_atlas_asset_json + .as_deref() + .unwrap_or("") + .contains("-tile-atlas") + ); + assert!( + input + .tile_assets_json + .as_deref() + .unwrap_or("") + .contains("tile-0-object") + ); assert_eq!(draft.generation_status, JumpHopGenerationStatus::Ready); } @@ -869,10 +891,34 @@ mod tests { let JumpHopActionProcedure::Compile(input) = plan else { panic!("regenerate-character should call compile_jump_hop_draft"); }; - assert!(!input.character_asset_json.as_deref().unwrap_or("").contains("old-character")); - assert!(input.character_asset_json.as_deref().unwrap_or("").contains(&NOW_MICROS.to_string())); - assert!(input.tile_atlas_asset_json.as_deref().unwrap_or("").contains("old-tile-atlas")); - assert!(input.tile_assets_json.as_deref().unwrap_or("").contains("old-normal-tile")); + assert!( + !input + .character_asset_json + .as_deref() + .unwrap_or("") + .contains("old-character") + ); + assert!( + input + .character_asset_json + .as_deref() + .unwrap_or("") + .contains(&NOW_MICROS.to_string()) + ); + assert!( + input + .tile_atlas_asset_json + .as_deref() + .unwrap_or("") + .contains("old-tile-atlas") + ); + assert!( + input + .tile_assets_json + .as_deref() + .unwrap_or("") + .contains("old-normal-tile") + ); } #[test] @@ -888,11 +934,41 @@ mod tests { let JumpHopActionProcedure::Compile(input) = plan else { panic!("regenerate-tiles should call compile_jump_hop_draft"); }; - assert!(input.character_asset_json.as_deref().unwrap_or("").contains("old-character")); - assert!(!input.tile_atlas_asset_json.as_deref().unwrap_or("").contains("old-tile-atlas")); - assert!(!input.tile_assets_json.as_deref().unwrap_or("").contains("old-normal-tile")); - assert!(input.tile_atlas_asset_json.as_deref().unwrap_or("").contains(&NOW_MICROS.to_string())); - assert!(input.tile_assets_json.as_deref().unwrap_or("").contains(&NOW_MICROS.to_string())); + assert!( + input + .character_asset_json + .as_deref() + .unwrap_or("") + .contains("old-character") + ); + assert!( + !input + .tile_atlas_asset_json + .as_deref() + .unwrap_or("") + .contains("old-tile-atlas") + ); + assert!( + !input + .tile_assets_json + .as_deref() + .unwrap_or("") + .contains("old-normal-tile") + ); + assert!( + input + .tile_atlas_asset_json + .as_deref() + .unwrap_or("") + .contains(&NOW_MICROS.to_string()) + ); + assert!( + input + .tile_assets_json + .as_deref() + .unwrap_or("") + .contains(&NOW_MICROS.to_string()) + ); } #[test] @@ -934,8 +1010,20 @@ mod tests { }; assert_eq!(input.difficulty.as_deref(), Some("challenge")); assert!(input.style_preset.is_none()); - assert_eq!(draft.character_asset.as_ref().map(|asset| asset.asset_id.as_str()), Some("old-character")); - assert_eq!(draft.tile_assets.first().map(|asset| asset.asset_object_id.as_str()), Some("old-normal-tile-object")); + assert_eq!( + draft + .character_asset + .as_ref() + .map(|asset| asset.asset_id.as_str()), + Some("old-character") + ); + assert_eq!( + draft + .tile_assets + .first() + .map(|asset| asset.asset_object_id.as_str()), + Some("old-normal-tile-object") + ); } fn action(action_type: JumpHopActionType) -> JumpHopActionRequest { diff --git a/server-rs/crates/spacetime-client/src/lib.rs b/server-rs/crates/spacetime-client/src/lib.rs index 26ff1ad9..87faa017 100644 --- a/server-rs/crates/spacetime-client/src/lib.rs +++ b/server-rs/crates/spacetime-client/src/lib.rs @@ -30,16 +30,8 @@ pub use mapper::{ CustomWorldPublishGateRecord, CustomWorldPublishWorldRecord, CustomWorldPublishWorldRecordInput, CustomWorldPublishedProfileCompileRecord, CustomWorldResultPreviewBlockerRecord, CustomWorldSupportedActionRecord, - CustomWorldWorkSummaryRecord, Match3DAgentMessageFinalizeRecordInput, - Match3DAgentMessageRecord, Match3DAgentMessageSubmitRecordInput, - Match3DAgentSessionCreateRecordInput, Match3DAgentSessionRecord, Match3DAnchorItemRecord, - Match3DAnchorPackRecord, Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput, - Match3DCreatorConfigRecord, Match3DItemSnapshotRecord, Match3DResultDraftRecord, - Match3DRunClickRecordInput, Match3DRunRecord, Match3DRunRestartRecordInput, - Match3DRunStartRecordInput, Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput, - Match3DTraySlotRecord, Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput, - JumpHopActionRequest, JumpHopActionResponse, JumpHopActionType, JumpHopCharacterAsset, - JumpHopDifficulty, JumpHopDraftResponse, JumpHopGalleryCardResponse, + CustomWorldWorkSummaryRecord, JumpHopActionRequest, JumpHopActionResponse, JumpHopActionType, + JumpHopCharacterAsset, JumpHopDifficulty, JumpHopDraftResponse, JumpHopGalleryCardResponse, JumpHopGalleryDetailResponse, JumpHopGalleryResponse, JumpHopGenerationStatus, JumpHopJumpRequest, JumpHopJumpResponse, JumpHopJumpResult, JumpHopLastJump, JumpHopPath, JumpHopPlatform, JumpHopRestartRunRequest, JumpHopRunResponse, JumpHopRunStatus, @@ -47,7 +39,14 @@ pub use mapper::{ JumpHopSessionSnapshotResponse, JumpHopStartRunRequest, JumpHopStylePreset, JumpHopTileAsset, JumpHopTileType, JumpHopWorkDetailResponse, JumpHopWorkMutationResponse, JumpHopWorkProfileResponse, JumpHopWorkSummaryResponse, JumpHopWorksResponse, - JumpHopWorkspaceCreateRequest, + JumpHopWorkspaceCreateRequest, Match3DAgentMessageFinalizeRecordInput, + Match3DAgentMessageRecord, Match3DAgentMessageSubmitRecordInput, + Match3DAgentSessionCreateRecordInput, Match3DAgentSessionRecord, Match3DAnchorItemRecord, + Match3DAnchorPackRecord, Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput, + Match3DCreatorConfigRecord, Match3DItemSnapshotRecord, Match3DResultDraftRecord, + Match3DRunClickRecordInput, Match3DRunRecord, Match3DRunRestartRecordInput, + Match3DRunStartRecordInput, Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput, + Match3DTraySlotRecord, Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput, NpcBattleInteractionRecord, NpcInteractionRecord, NpcStateRecord, PuzzleAgentMessageFinalizeRecordInput, PuzzleAgentMessageRecord, PuzzleAgentMessageSubmitRecordInput, PuzzleAgentSessionCreateRecordInput, @@ -80,7 +79,15 @@ pub use mapper::{ VisualNovelHistoryEntryRecordInput, VisualNovelRunRecord, VisualNovelRunSnapshotRecordInput, VisualNovelRunStartRecordInput, VisualNovelRuntimeEventRecord, VisualNovelRuntimeEventRecordInput, VisualNovelWorkCompileRecordInput, - VisualNovelWorkProfileRecord, VisualNovelWorkUpdateRecordInput, + VisualNovelWorkProfileRecord, VisualNovelWorkUpdateRecordInput, WoodenFishActionRequest, + WoodenFishActionResponse, WoodenFishActionType, WoodenFishAudioAsset, + WoodenFishCheckpointRunRequest, WoodenFishDraftResponse, WoodenFishFinishRunRequest, + WoodenFishGalleryCardResponse, WoodenFishGalleryDetailResponse, WoodenFishGalleryResponse, + WoodenFishGenerationStatus, WoodenFishImageAsset, WoodenFishRunResponse, WoodenFishRunStatus, + WoodenFishRuntimeRunSnapshotResponse, WoodenFishSessionResponse, + WoodenFishSessionSnapshotResponse, WoodenFishStartRunRequest, WoodenFishWordCounter, + WoodenFishWorkDetailResponse, WoodenFishWorkMutationResponse, WoodenFishWorkProfileResponse, + WoodenFishWorkSummaryResponse, WoodenFishWorkspaceCreateRequest, }; pub mod ai; @@ -105,6 +112,7 @@ pub mod square_hole; pub mod story; pub mod story_runtime; pub mod visual_novel; +pub mod wooden_fish; use std::{ collections::HashMap, @@ -563,6 +571,7 @@ impl SpacetimeClient { for query in [ "SELECT * FROM puzzle_gallery_card_view", "SELECT * FROM jump_hop_gallery_card_view", + "SELECT * FROM wooden_fish_gallery_card_view", "SELECT * FROM custom_world_gallery_entry", "SELECT * FROM match_3_d_gallery_view", "SELECT * FROM square_hole_gallery_view", @@ -578,6 +587,7 @@ impl SpacetimeClient { for query in [ "SELECT * FROM public_work_play_daily_stat WHERE source_type = 'puzzle'", "SELECT * FROM public_work_play_daily_stat WHERE source_type = 'jump-hop'", + "SELECT * FROM public_work_play_daily_stat WHERE source_type = 'wooden-fish'", "SELECT * FROM public_work_play_daily_stat WHERE source_type = 'custom-world'", "SELECT * FROM public_work_play_daily_stat WHERE source_type = 'match3d'", "SELECT * FROM public_work_play_daily_stat WHERE source_type = 'square-hole'", diff --git a/server-rs/crates/spacetime-client/src/mapper.rs b/server-rs/crates/spacetime-client/src/mapper.rs index 23ce69a8..34d50960 100644 --- a/server-rs/crates/spacetime-client/src/mapper.rs +++ b/server-rs/crates/spacetime-client/src/mapper.rs @@ -18,6 +18,7 @@ mod runtime_profile; mod square_hole; mod story; mod visual_novel; +mod wooden_fish; pub use self::ai::{ AiResultReferenceRecord, AiTaskMutationRecord, AiTaskRecord, AiTaskStageRecord, @@ -36,18 +37,6 @@ pub use self::combat::{ BarkBattleDraftConfigRecord, BarkBattleRunRecord, BarkBattleRuntimeConfigRecord, ResolveCombatActionRecord, }; -pub use self::jump_hop::{ - JumpHopActionRequest, JumpHopActionResponse, JumpHopActionType, JumpHopCharacterAsset, - JumpHopDifficulty, JumpHopDraftResponse, JumpHopGalleryCardResponse, - JumpHopGalleryDetailResponse, JumpHopGalleryResponse, JumpHopGenerationStatus, - JumpHopJumpRequest, JumpHopJumpResponse, JumpHopJumpResult, JumpHopLastJump, JumpHopPath, - JumpHopPlatform, JumpHopRestartRunRequest, JumpHopRunResponse, JumpHopRunStatus, - JumpHopRuntimeRunSnapshotResponse, JumpHopScoring, JumpHopSessionResponse, - JumpHopSessionSnapshotResponse, JumpHopStartRunRequest, JumpHopStylePreset, JumpHopTileAsset, - JumpHopTileType, JumpHopWorkDetailResponse, JumpHopWorkMutationResponse, - JumpHopWorkProfileResponse, JumpHopWorkSummaryResponse, JumpHopWorksResponse, - JumpHopWorkspaceCreateRequest, -}; pub use self::common::{ BigFishAgentMessageRecord, BigFishAnchorItemRecord, BigFishAnchorPackRecord, BigFishBackgroundBlueprintRecord, BigFishDraftCompileRecordInput, @@ -77,6 +66,18 @@ pub use self::common::{ VisualNovelRunSnapshotRecordInput, VisualNovelRunStartRecordInput, VisualNovelWorkCompileRecordInput, }; +pub use self::jump_hop::{ + JumpHopActionRequest, JumpHopActionResponse, JumpHopActionType, JumpHopCharacterAsset, + JumpHopDifficulty, JumpHopDraftResponse, JumpHopGalleryCardResponse, + JumpHopGalleryDetailResponse, JumpHopGalleryResponse, JumpHopGenerationStatus, + JumpHopJumpRequest, JumpHopJumpResponse, JumpHopJumpResult, JumpHopLastJump, JumpHopPath, + JumpHopPlatform, JumpHopRestartRunRequest, JumpHopRunResponse, JumpHopRunStatus, + JumpHopRuntimeRunSnapshotResponse, JumpHopScoring, JumpHopSessionResponse, + JumpHopSessionSnapshotResponse, JumpHopStartRunRequest, JumpHopStylePreset, JumpHopTileAsset, + JumpHopTileType, JumpHopWorkDetailResponse, JumpHopWorkMutationResponse, + JumpHopWorkProfileResponse, JumpHopWorkSummaryResponse, JumpHopWorksResponse, + JumpHopWorkspaceCreateRequest, +}; pub use self::match3d::{ Match3DAgentMessageFinalizeRecordInput, Match3DAgentMessageRecord, Match3DAgentMessageSubmitRecordInput, Match3DAgentSessionCreateRecordInput, @@ -118,6 +119,16 @@ pub use self::runtime_profile::{ SquareHoleDropConfirmationRecord, SquareHoleDropFeedbackRecord, SquareHoleRunRecord, }; pub use self::story::{VisualNovelRuntimeEventRecord, VisualNovelRuntimeEventRecordInput}; +pub use self::wooden_fish::{ + WoodenFishActionRequest, WoodenFishActionResponse, WoodenFishActionType, WoodenFishAudioAsset, + WoodenFishCheckpointRunRequest, WoodenFishDraftResponse, WoodenFishFinishRunRequest, + WoodenFishGalleryCardResponse, WoodenFishGalleryDetailResponse, WoodenFishGalleryResponse, + WoodenFishGenerationStatus, WoodenFishImageAsset, WoodenFishRunResponse, WoodenFishRunStatus, + WoodenFishRuntimeRunSnapshotResponse, WoodenFishSessionResponse, + WoodenFishSessionSnapshotResponse, WoodenFishStartRunRequest, WoodenFishWordCounter, + WoodenFishWorkDetailResponse, WoodenFishWorkMutationResponse, WoodenFishWorkProfileResponse, + WoodenFishWorkSummaryResponse, WoodenFishWorkspaceCreateRequest, +}; pub(crate) use self::ai::map_ai_task_procedure_result; pub(crate) use self::assets::{map_entity_binding_procedure_result, map_procedure_result}; @@ -220,3 +231,8 @@ pub(crate) use self::visual_novel::{ map_visual_novel_runtime_event_procedure_result, map_visual_novel_work_procedure_result, map_visual_novel_works_procedure_result, }; +pub(crate) use self::wooden_fish::{ + map_wooden_fish_agent_session_procedure_result, map_wooden_fish_gallery_card_view_row, + map_wooden_fish_run_procedure_result, map_wooden_fish_work_procedure_result, + map_wooden_fish_works_procedure_result, +}; diff --git a/server-rs/crates/spacetime-client/src/mapper/jump_hop.rs b/server-rs/crates/spacetime-client/src/mapper/jump_hop.rs index e5716a14..a2384840 100644 --- a/server-rs/crates/spacetime-client/src/mapper/jump_hop.rs +++ b/server-rs/crates/spacetime-client/src/mapper/jump_hop.rs @@ -161,7 +161,11 @@ fn map_jump_hop_work_snapshot( path: map_jump_hop_path(snapshot.path), character_asset, tile_atlas_asset, - tile_assets: snapshot.tile_assets.into_iter().map(map_tile_asset).collect(), + tile_assets: snapshot + .tile_assets + .into_iter() + .map(map_tile_asset) + .collect(), }) } @@ -180,7 +184,11 @@ fn map_jump_hop_draft_snapshot(snapshot: JumpHopDraftSnapshot) -> JumpHopDraftRe end_mood_prompt: snapshot.end_mood_prompt, character_asset: snapshot.character_asset.map(map_character_asset), tile_atlas_asset: snapshot.tile_atlas_asset.map(map_character_asset), - tile_assets: snapshot.tile_assets.into_iter().map(map_tile_asset).collect(), + tile_assets: snapshot + .tile_assets + .into_iter() + .map(map_tile_asset) + .collect(), path: snapshot.path.map(map_jump_hop_path), cover_composite: snapshot.cover_composite, generation_status: parse_generation_status(&snapshot.generation_status), @@ -268,7 +276,9 @@ fn map_jump_hop_run_snapshot(snapshot: JumpHopRunSnapshot) -> JumpHopRuntimeRunS crate::module_bindings::JumpHopJumpResultKind::Miss => JumpHopJumpResult::Miss, crate::module_bindings::JumpHopJumpResultKind::Hit => JumpHopJumpResult::Hit, crate::module_bindings::JumpHopJumpResultKind::Finish => JumpHopJumpResult::Finish, - crate::module_bindings::JumpHopJumpResultKind::Perfect => JumpHopJumpResult::Perfect, + crate::module_bindings::JumpHopJumpResultKind::Perfect => { + JumpHopJumpResult::Perfect + } }, }), started_at_ms: snapshot.started_at_ms, diff --git a/server-rs/crates/spacetime-client/src/mapper/wooden_fish.rs b/server-rs/crates/spacetime-client/src/mapper/wooden_fish.rs new file mode 100644 index 00000000..80beca4c --- /dev/null +++ b/server-rs/crates/spacetime-client/src/mapper/wooden_fish.rs @@ -0,0 +1,237 @@ +use super::*; +pub use shared_contracts::wooden_fish::{ + WoodenFishActionRequest, WoodenFishActionResponse, WoodenFishActionType, WoodenFishAudioAsset, + WoodenFishCheckpointRunRequest, WoodenFishDraftResponse, WoodenFishFinishRunRequest, + WoodenFishGalleryCardResponse, WoodenFishGalleryDetailResponse, WoodenFishGalleryResponse, + WoodenFishGenerationStatus, WoodenFishImageAsset, WoodenFishRunResponse, WoodenFishRunStatus, + WoodenFishRuntimeRunSnapshotResponse, WoodenFishSessionResponse, + WoodenFishSessionSnapshotResponse, WoodenFishStartRunRequest, WoodenFishWordCounter, + WoodenFishWorkDetailResponse, WoodenFishWorkMutationResponse, WoodenFishWorkProfileResponse, + WoodenFishWorkSummaryResponse, WoodenFishWorkspaceCreateRequest, +}; + +pub(crate) fn map_wooden_fish_agent_session_procedure_result( + result: WoodenFishAgentSessionProcedureResult, +) -> Result { + if !result.ok { + return Err(SpacetimeClientError::procedure_failed(result.error_message)); + } + let session = result + .session + .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish agent session å¿«ç…§"))?; + Ok(map_wooden_fish_session_snapshot(session)) +} + +pub(crate) fn map_wooden_fish_work_procedure_result( + result: WoodenFishWorkProcedureResult, +) -> Result { + if !result.ok { + return Err(SpacetimeClientError::procedure_failed(result.error_message)); + } + let work = result + .work + .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish work å¿«ç…§"))?; + map_wooden_fish_work_snapshot(work) +} + +pub(crate) fn map_wooden_fish_works_procedure_result( + result: WoodenFishWorksProcedureResult, +) -> Result, SpacetimeClientError> { + if !result.ok { + return Err(SpacetimeClientError::procedure_failed(result.error_message)); + } + result + .items + .into_iter() + .map(map_wooden_fish_work_snapshot) + .collect() +} + +pub(crate) fn map_wooden_fish_run_procedure_result( + result: WoodenFishRunProcedureResult, +) -> Result { + if !result.ok { + return Err(SpacetimeClientError::procedure_failed(result.error_message)); + } + let run = result + .run + .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish run å¿«ç…§"))?; + Ok(map_wooden_fish_run_snapshot(run)) +} + +pub(crate) fn map_wooden_fish_gallery_card_view_row( + row: WoodenFishGalleryCardViewRow, +) -> WoodenFishGalleryCardResponse { + WoodenFishGalleryCardResponse { + public_work_code: row.public_work_code, + work_id: row.work_id, + profile_id: row.profile_id, + owner_user_id: row.owner_user_id, + author_display_name: row.author_display_name, + work_title: row.work_title, + work_description: row.work_description, + cover_image_src: empty_string_to_none(row.cover_image_src), + theme_tags: row.theme_tags, + publication_status: normalize_publication_status(&row.publication_status).to_string(), + play_count: row.play_count, + updated_at: format_timestamp_micros(row.updated_at_micros), + published_at: row.published_at_micros.map(format_timestamp_micros), + generation_status: parse_generation_status(&row.generation_status), + } +} + +fn map_wooden_fish_session_snapshot( + snapshot: WoodenFishAgentSessionSnapshot, +) -> WoodenFishSessionSnapshotResponse { + WoodenFishSessionSnapshotResponse { + session_id: snapshot.session_id, + owner_user_id: snapshot.owner_user_id, + status: snapshot + .draft + .as_ref() + .map(|draft| parse_generation_status(&draft.generation_status)) + .unwrap_or(WoodenFishGenerationStatus::Draft), + draft: snapshot.draft.map(map_wooden_fish_draft_snapshot), + created_at: format_timestamp_micros(snapshot.created_at_micros), + updated_at: format_timestamp_micros(snapshot.updated_at_micros), + } +} + +fn map_wooden_fish_work_snapshot( + snapshot: WoodenFishWorkSnapshot, +) -> Result { + let draft = WoodenFishDraftResponse { + template_id: "wooden-fish".to_string(), + template_name: "敲木鱼".to_string(), + profile_id: Some(snapshot.profile_id.clone()), + work_title: snapshot.work_title.clone(), + work_description: snapshot.work_description.clone(), + theme_tags: snapshot.theme_tags.clone(), + hit_object_prompt: snapshot.hit_object_prompt.clone(), + hit_object_reference_image_src: snapshot.hit_object_reference_image_src.clone(), + hit_sound_prompt: snapshot.hit_sound_prompt.clone(), + floating_words: snapshot.floating_words.clone(), + hit_object_asset: snapshot.hit_object_asset.clone().map(map_image_asset), + hit_sound_asset: snapshot.hit_sound_asset.clone().map(map_audio_asset), + cover_image_src: empty_string_to_none(snapshot.cover_image_src.clone()), + generation_status: parse_generation_status(&snapshot.generation_status), + }; + let hit_object_asset = draft + .hit_object_asset + .clone() + .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish hit object asset"))?; + let hit_sound_asset = draft + .hit_sound_asset + .clone() + .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish hit sound asset"))?; + Ok(WoodenFishWorkProfileResponse { + summary: WoodenFishWorkSummaryResponse { + runtime_kind: "wooden-fish".to_string(), + work_id: snapshot.work_id, + profile_id: snapshot.profile_id, + owner_user_id: snapshot.owner_user_id, + source_session_id: empty_string_to_none(snapshot.source_session_id), + work_title: snapshot.work_title, + work_description: snapshot.work_description, + theme_tags: snapshot.theme_tags, + cover_image_src: empty_string_to_none(snapshot.cover_image_src), + publication_status: normalize_publication_status(&snapshot.publication_status) + .to_string(), + play_count: snapshot.play_count, + updated_at: format_timestamp_micros(snapshot.updated_at_micros), + published_at: snapshot.published_at_micros.map(format_timestamp_micros), + publish_ready: snapshot.publish_ready, + generation_status: parse_generation_status(&snapshot.generation_status), + }, + draft, + hit_object_asset, + hit_sound_asset, + floating_words: snapshot.floating_words, + }) +} + +fn map_wooden_fish_draft_snapshot(snapshot: WoodenFishDraftSnapshot) -> WoodenFishDraftResponse { + WoodenFishDraftResponse { + template_id: snapshot.template_id, + template_name: snapshot.template_name, + profile_id: snapshot.profile_id, + work_title: snapshot.work_title, + work_description: snapshot.work_description, + theme_tags: snapshot.theme_tags, + hit_object_prompt: snapshot.hit_object_prompt, + hit_object_reference_image_src: snapshot.hit_object_reference_image_src, + hit_sound_prompt: snapshot.hit_sound_prompt, + floating_words: snapshot.floating_words, + hit_object_asset: snapshot.hit_object_asset.map(map_image_asset), + hit_sound_asset: snapshot.hit_sound_asset.map(map_audio_asset), + cover_image_src: snapshot.cover_image_src, + generation_status: parse_generation_status(&snapshot.generation_status), + } +} + +fn map_image_asset(snapshot: WoodenFishImageAssetSnapshot) -> WoodenFishImageAsset { + WoodenFishImageAsset { + asset_id: snapshot.asset_id, + image_src: snapshot.image_src, + image_object_key: snapshot.image_object_key, + asset_object_id: snapshot.asset_object_id, + generation_provider: snapshot.generation_provider, + prompt: snapshot.prompt, + width: snapshot.width, + height: snapshot.height, + } +} + +fn map_audio_asset(snapshot: WoodenFishAudioAssetSnapshot) -> WoodenFishAudioAsset { + WoodenFishAudioAsset { + asset_id: snapshot.asset_id, + audio_src: snapshot.audio_src, + audio_object_key: snapshot.audio_object_key, + asset_object_id: snapshot.asset_object_id, + source: snapshot.source, + prompt: snapshot.prompt, + duration_ms: snapshot.duration_ms, + } +} + +fn map_wooden_fish_run_snapshot( + snapshot: crate::module_bindings::WoodenFishRunSnapshot, +) -> WoodenFishRuntimeRunSnapshotResponse { + WoodenFishRuntimeRunSnapshotResponse { + run_id: snapshot.run_id, + profile_id: snapshot.profile_id, + owner_user_id: snapshot.owner_user_id, + status: match snapshot.status { + crate::module_bindings::WoodenFishRunStatus::Playing => WoodenFishRunStatus::Playing, + crate::module_bindings::WoodenFishRunStatus::Finished => WoodenFishRunStatus::Finished, + }, + total_tap_count: snapshot.total_tap_count, + word_counters: snapshot + .word_counters + .into_iter() + .map(|counter| WoodenFishWordCounter { + text: counter.text, + count: counter.count, + }) + .collect(), + started_at_ms: snapshot.started_at_ms, + updated_at_ms: snapshot.updated_at_ms, + finished_at_ms: snapshot.finished_at_ms, + } +} + +fn parse_generation_status(value: &str) -> WoodenFishGenerationStatus { + match value { + "generating" => WoodenFishGenerationStatus::Generating, + "ready" => WoodenFishGenerationStatus::Ready, + "failed" => WoodenFishGenerationStatus::Failed, + _ => WoodenFishGenerationStatus::Draft, + } +} + +fn normalize_publication_status(value: &str) -> &str { + match value { + "Published" | "published" => "published", + _ => "draft", + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings.rs b/server-rs/crates/spacetime-client/src/module_bindings.rs index 5b6a593d..b5adca82 100644 --- a/server-rs/crates/spacetime-client/src/module_bindings.rs +++ b/server-rs/crates/spacetime-client/src/module_bindings.rs @@ -191,6 +191,7 @@ pub mod chapter_progression_procedure_result_type; pub mod chapter_progression_snapshot_type; pub mod chapter_progression_table; pub mod chapter_progression_type; +pub mod checkpoint_wooden_fish_run_procedure; pub mod claim_profile_task_reward_and_return_procedure; pub mod claim_puzzle_work_point_incentive_procedure; pub mod clear_database_migration_import_chunks_procedure; @@ -204,6 +205,7 @@ pub mod compile_match_3_d_draft_procedure; pub mod compile_puzzle_agent_draft_procedure; pub mod compile_square_hole_draft_procedure; pub mod compile_visual_novel_work_profile_procedure; +pub mod compile_wooden_fish_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; @@ -225,6 +227,7 @@ pub mod create_profile_recharge_order_and_return_procedure; pub mod create_puzzle_agent_session_procedure; pub mod create_square_hole_agent_session_procedure; pub mod create_visual_novel_agent_session_procedure; +pub mod create_wooden_fish_agent_session_procedure; pub mod creation_entry_config_procedure_result_type; pub mod creation_entry_config_snapshot_type; pub mod creation_entry_config_table; @@ -336,6 +339,7 @@ pub mod finalize_visual_novel_agent_message_turn_procedure; pub mod finish_bark_battle_run_procedure; pub mod finish_match_3_d_time_up_procedure; pub mod finish_square_hole_time_up_procedure; +pub mod finish_wooden_fish_run_procedure; pub mod generate_big_fish_asset_procedure; pub mod get_auth_store_snapshot_procedure; pub mod get_bark_battle_run_procedure; @@ -378,6 +382,9 @@ pub mod get_story_session_state_procedure; pub mod get_visual_novel_agent_session_procedure; pub mod get_visual_novel_run_procedure; pub mod get_visual_novel_work_detail_procedure; +pub mod get_wooden_fish_agent_session_procedure; +pub mod get_wooden_fish_run_procedure; +pub mod get_wooden_fish_work_profile_procedure; pub mod grant_inventory_item_input_type; pub mod grant_new_user_registration_wallet_reward_procedure; pub mod grant_player_progression_experience_and_return_procedure; @@ -456,6 +463,7 @@ pub mod list_puzzle_works_procedure; pub mod list_square_hole_works_procedure; pub mod list_visual_novel_runtime_history_procedure; pub mod list_visual_novel_works_procedure; +pub mod list_wooden_fish_works_procedure; pub mod mark_profile_recharge_order_paid_and_return_procedure; pub mod match_3_d_agent_message_finalize_input_type; pub mod match_3_d_agent_message_row_type; @@ -562,6 +570,7 @@ pub mod publish_match_3_d_work_procedure; pub mod publish_puzzle_work_procedure; pub mod publish_square_hole_work_procedure; pub mod publish_visual_novel_work_procedure; +pub mod publish_wooden_fish_work_procedure; pub mod put_database_migration_import_chunk_procedure; pub mod puzzle_agent_message_finalize_input_type; pub mod puzzle_agent_message_kind_type; @@ -876,6 +885,7 @@ pub mod start_match_3_d_run_procedure; pub mod start_puzzle_run_procedure; pub mod start_square_hole_run_procedure; pub mod start_visual_novel_run_procedure; +pub mod start_wooden_fish_run_procedure; pub mod stop_match_3_d_run_procedure; pub mod stop_square_hole_run_procedure; pub mod story_continue_input_type; @@ -922,6 +932,7 @@ pub mod update_puzzle_run_pause_procedure; pub mod update_puzzle_work_procedure; pub mod update_square_hole_work_procedure; pub mod update_visual_novel_work_procedure; +pub mod update_wooden_fish_work_procedure; pub mod upsert_auth_store_snapshot_procedure; pub mod upsert_chapter_progression_and_return_procedure; pub mod upsert_chapter_progression_reducer; @@ -984,6 +995,42 @@ pub mod visual_novel_work_snapshot_type; pub mod visual_novel_work_update_input_type; pub mod visual_novel_works_list_input_type; pub mod visual_novel_works_procedure_result_type; +pub mod wooden_fish_agent_session_create_input_type; +pub mod wooden_fish_agent_session_get_input_type; +pub mod wooden_fish_agent_session_procedure_result_type; +pub mod wooden_fish_agent_session_row_type; +pub mod wooden_fish_agent_session_snapshot_type; +pub mod wooden_fish_agent_session_table; +pub mod wooden_fish_audio_asset_snapshot_type; +pub mod wooden_fish_creator_config_snapshot_type; +pub mod wooden_fish_draft_compile_input_type; +pub mod wooden_fish_draft_snapshot_type; +pub mod wooden_fish_event_row_type; +pub mod wooden_fish_event_table; +pub mod wooden_fish_gallery_card_view_row_type; +pub mod wooden_fish_gallery_card_view_table; +pub mod wooden_fish_gallery_view_row_type; +pub mod wooden_fish_gallery_view_table; +pub mod wooden_fish_image_asset_snapshot_type; +pub mod wooden_fish_run_checkpoint_input_type; +pub mod wooden_fish_run_finish_input_type; +pub mod wooden_fish_run_get_input_type; +pub mod wooden_fish_run_procedure_result_type; +pub mod wooden_fish_run_snapshot_type; +pub mod wooden_fish_run_start_input_type; +pub mod wooden_fish_run_status_type; +pub mod wooden_fish_runtime_run_row_type; +pub mod wooden_fish_runtime_run_table; +pub mod wooden_fish_word_counter_type; +pub mod wooden_fish_work_get_input_type; +pub mod wooden_fish_work_procedure_result_type; +pub mod wooden_fish_work_profile_row_type; +pub mod wooden_fish_work_profile_table; +pub mod wooden_fish_work_publish_input_type; +pub mod wooden_fish_work_snapshot_type; +pub mod wooden_fish_work_update_input_type; +pub mod wooden_fish_works_list_input_type; +pub mod wooden_fish_works_procedure_result_type; pub use accept_quest_reducer::accept_quest; pub use acknowledge_quest_completion_reducer::acknowledge_quest_completion; @@ -1170,6 +1217,7 @@ pub use chapter_progression_procedure_result_type::ChapterProgressionProcedureRe pub use chapter_progression_snapshot_type::ChapterProgressionSnapshot; pub use chapter_progression_table::*; pub use chapter_progression_type::ChapterProgression; +pub use checkpoint_wooden_fish_run_procedure::checkpoint_wooden_fish_run; pub use claim_profile_task_reward_and_return_procedure::claim_profile_task_reward_and_return; pub use claim_puzzle_work_point_incentive_procedure::claim_puzzle_work_point_incentive; pub use clear_database_migration_import_chunks_procedure::clear_database_migration_import_chunks; @@ -1183,6 +1231,7 @@ pub use compile_match_3_d_draft_procedure::compile_match_3_d_draft; pub use compile_puzzle_agent_draft_procedure::compile_puzzle_agent_draft; pub use compile_square_hole_draft_procedure::compile_square_hole_draft; pub use compile_visual_novel_work_profile_procedure::compile_visual_novel_work_profile; +pub use compile_wooden_fish_draft_procedure::compile_wooden_fish_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; @@ -1204,6 +1253,7 @@ pub use create_profile_recharge_order_and_return_procedure::create_profile_recha pub use create_puzzle_agent_session_procedure::create_puzzle_agent_session; pub use create_square_hole_agent_session_procedure::create_square_hole_agent_session; pub use create_visual_novel_agent_session_procedure::create_visual_novel_agent_session; +pub use create_wooden_fish_agent_session_procedure::create_wooden_fish_agent_session; pub use creation_entry_config_procedure_result_type::CreationEntryConfigProcedureResult; pub use creation_entry_config_snapshot_type::CreationEntryConfigSnapshot; pub use creation_entry_config_table::*; @@ -1315,6 +1365,7 @@ pub use finalize_visual_novel_agent_message_turn_procedure::finalize_visual_nove pub use finish_bark_battle_run_procedure::finish_bark_battle_run; pub use finish_match_3_d_time_up_procedure::finish_match_3_d_time_up; pub use finish_square_hole_time_up_procedure::finish_square_hole_time_up; +pub use finish_wooden_fish_run_procedure::finish_wooden_fish_run; pub use generate_big_fish_asset_procedure::generate_big_fish_asset; pub use get_auth_store_snapshot_procedure::get_auth_store_snapshot; pub use get_bark_battle_run_procedure::get_bark_battle_run; @@ -1357,6 +1408,9 @@ pub use get_story_session_state_procedure::get_story_session_state; pub use get_visual_novel_agent_session_procedure::get_visual_novel_agent_session; pub use get_visual_novel_run_procedure::get_visual_novel_run; pub use get_visual_novel_work_detail_procedure::get_visual_novel_work_detail; +pub use get_wooden_fish_agent_session_procedure::get_wooden_fish_agent_session; +pub use get_wooden_fish_run_procedure::get_wooden_fish_run; +pub use get_wooden_fish_work_profile_procedure::get_wooden_fish_work_profile; pub use grant_inventory_item_input_type::GrantInventoryItemInput; pub use grant_new_user_registration_wallet_reward_procedure::grant_new_user_registration_wallet_reward; pub use grant_player_progression_experience_and_return_procedure::grant_player_progression_experience_and_return; @@ -1435,6 +1489,7 @@ pub use list_puzzle_works_procedure::list_puzzle_works; pub use list_square_hole_works_procedure::list_square_hole_works; pub use list_visual_novel_runtime_history_procedure::list_visual_novel_runtime_history; pub use list_visual_novel_works_procedure::list_visual_novel_works; +pub use list_wooden_fish_works_procedure::list_wooden_fish_works; pub use mark_profile_recharge_order_paid_and_return_procedure::mark_profile_recharge_order_paid_and_return; pub use match_3_d_agent_message_finalize_input_type::Match3DAgentMessageFinalizeInput; pub use match_3_d_agent_message_row_type::Match3DAgentMessageRow; @@ -1541,6 +1596,7 @@ pub use publish_match_3_d_work_procedure::publish_match_3_d_work; pub use publish_puzzle_work_procedure::publish_puzzle_work; pub use publish_square_hole_work_procedure::publish_square_hole_work; pub use publish_visual_novel_work_procedure::publish_visual_novel_work; +pub use publish_wooden_fish_work_procedure::publish_wooden_fish_work; pub use put_database_migration_import_chunk_procedure::put_database_migration_import_chunk; pub use puzzle_agent_message_finalize_input_type::PuzzleAgentMessageFinalizeInput; pub use puzzle_agent_message_kind_type::PuzzleAgentMessageKind; @@ -1855,6 +1911,7 @@ pub use start_match_3_d_run_procedure::start_match_3_d_run; pub use start_puzzle_run_procedure::start_puzzle_run; pub use start_square_hole_run_procedure::start_square_hole_run; pub use start_visual_novel_run_procedure::start_visual_novel_run; +pub use start_wooden_fish_run_procedure::start_wooden_fish_run; pub use stop_match_3_d_run_procedure::stop_match_3_d_run; pub use stop_square_hole_run_procedure::stop_square_hole_run; pub use story_continue_input_type::StoryContinueInput; @@ -1901,6 +1958,7 @@ pub use update_puzzle_run_pause_procedure::update_puzzle_run_pause; pub use update_puzzle_work_procedure::update_puzzle_work; pub use update_square_hole_work_procedure::update_square_hole_work; pub use update_visual_novel_work_procedure::update_visual_novel_work; +pub use update_wooden_fish_work_procedure::update_wooden_fish_work; pub use upsert_auth_store_snapshot_procedure::upsert_auth_store_snapshot; pub use upsert_chapter_progression_and_return_procedure::upsert_chapter_progression_and_return; pub use upsert_chapter_progression_reducer::upsert_chapter_progression; @@ -1963,6 +2021,42 @@ pub use visual_novel_work_snapshot_type::VisualNovelWorkSnapshot; pub use visual_novel_work_update_input_type::VisualNovelWorkUpdateInput; pub use visual_novel_works_list_input_type::VisualNovelWorksListInput; pub use visual_novel_works_procedure_result_type::VisualNovelWorksProcedureResult; +pub use wooden_fish_agent_session_create_input_type::WoodenFishAgentSessionCreateInput; +pub use wooden_fish_agent_session_get_input_type::WoodenFishAgentSessionGetInput; +pub use wooden_fish_agent_session_procedure_result_type::WoodenFishAgentSessionProcedureResult; +pub use wooden_fish_agent_session_row_type::WoodenFishAgentSessionRow; +pub use wooden_fish_agent_session_snapshot_type::WoodenFishAgentSessionSnapshot; +pub use wooden_fish_agent_session_table::*; +pub use wooden_fish_audio_asset_snapshot_type::WoodenFishAudioAssetSnapshot; +pub use wooden_fish_creator_config_snapshot_type::WoodenFishCreatorConfigSnapshot; +pub use wooden_fish_draft_compile_input_type::WoodenFishDraftCompileInput; +pub use wooden_fish_draft_snapshot_type::WoodenFishDraftSnapshot; +pub use wooden_fish_event_row_type::WoodenFishEventRow; +pub use wooden_fish_event_table::*; +pub use wooden_fish_gallery_card_view_row_type::WoodenFishGalleryCardViewRow; +pub use wooden_fish_gallery_card_view_table::*; +pub use wooden_fish_gallery_view_row_type::WoodenFishGalleryViewRow; +pub use wooden_fish_gallery_view_table::*; +pub use wooden_fish_image_asset_snapshot_type::WoodenFishImageAssetSnapshot; +pub use wooden_fish_run_checkpoint_input_type::WoodenFishRunCheckpointInput; +pub use wooden_fish_run_finish_input_type::WoodenFishRunFinishInput; +pub use wooden_fish_run_get_input_type::WoodenFishRunGetInput; +pub use wooden_fish_run_procedure_result_type::WoodenFishRunProcedureResult; +pub use wooden_fish_run_snapshot_type::WoodenFishRunSnapshot; +pub use wooden_fish_run_start_input_type::WoodenFishRunStartInput; +pub use wooden_fish_run_status_type::WoodenFishRunStatus; +pub use wooden_fish_runtime_run_row_type::WoodenFishRuntimeRunRow; +pub use wooden_fish_runtime_run_table::*; +pub use wooden_fish_word_counter_type::WoodenFishWordCounter; +pub use wooden_fish_work_get_input_type::WoodenFishWorkGetInput; +pub use wooden_fish_work_procedure_result_type::WoodenFishWorkProcedureResult; +pub use wooden_fish_work_profile_row_type::WoodenFishWorkProfileRow; +pub use wooden_fish_work_profile_table::*; +pub use wooden_fish_work_publish_input_type::WoodenFishWorkPublishInput; +pub use wooden_fish_work_snapshot_type::WoodenFishWorkSnapshot; +pub use wooden_fish_work_update_input_type::WoodenFishWorkUpdateInput; +pub use wooden_fish_works_list_input_type::WoodenFishWorksListInput; +pub use wooden_fish_works_procedure_result_type::WoodenFishWorksProcedureResult; #[derive(Clone, PartialEq, Debug)] @@ -2337,6 +2431,12 @@ pub struct DbUpdate { visual_novel_runtime_history_entry: __sdk::TableUpdate, visual_novel_runtime_run: __sdk::TableUpdate, visual_novel_work_profile: __sdk::TableUpdate, + wooden_fish_agent_session: __sdk::TableUpdate, + wooden_fish_event: __sdk::TableUpdate, + wooden_fish_gallery_card_view: __sdk::TableUpdate, + wooden_fish_gallery_view: __sdk::TableUpdate, + wooden_fish_runtime_run: __sdk::TableUpdate, + wooden_fish_work_profile: __sdk::TableUpdate, } impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate { @@ -2660,6 +2760,24 @@ impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate { "visual_novel_work_profile" => db_update.visual_novel_work_profile.append( visual_novel_work_profile_table::parse_table_update(table_update)?, ), + "wooden_fish_agent_session" => db_update.wooden_fish_agent_session.append( + wooden_fish_agent_session_table::parse_table_update(table_update)?, + ), + "wooden_fish_event" => db_update + .wooden_fish_event + .append(wooden_fish_event_table::parse_table_update(table_update)?), + "wooden_fish_gallery_card_view" => db_update.wooden_fish_gallery_card_view.append( + wooden_fish_gallery_card_view_table::parse_table_update(table_update)?, + ), + "wooden_fish_gallery_view" => db_update.wooden_fish_gallery_view.append( + wooden_fish_gallery_view_table::parse_table_update(table_update)?, + ), + "wooden_fish_runtime_run" => db_update.wooden_fish_runtime_run.append( + wooden_fish_runtime_run_table::parse_table_update(table_update)?, + ), + "wooden_fish_work_profile" => db_update.wooden_fish_work_profile.append( + wooden_fish_work_profile_table::parse_table_update(table_update)?, + ), unknown => { return Err(__sdk::InternalError::unknown_name( @@ -3159,6 +3277,27 @@ impl __sdk::DbUpdate for DbUpdate { &self.visual_novel_work_profile, ) .with_updates_by_pk(|row| &row.profile_id); + diff.wooden_fish_agent_session = cache + .apply_diff_to_table::( + "wooden_fish_agent_session", + &self.wooden_fish_agent_session, + ) + .with_updates_by_pk(|row| &row.session_id); + diff.wooden_fish_event = cache + .apply_diff_to_table::("wooden_fish_event", &self.wooden_fish_event) + .with_updates_by_pk(|row| &row.event_id); + diff.wooden_fish_runtime_run = cache + .apply_diff_to_table::( + "wooden_fish_runtime_run", + &self.wooden_fish_runtime_run, + ) + .with_updates_by_pk(|row| &row.run_id); + diff.wooden_fish_work_profile = cache + .apply_diff_to_table::( + "wooden_fish_work_profile", + &self.wooden_fish_work_profile, + ) + .with_updates_by_pk(|row| &row.profile_id); diff.big_fish_gallery_view = cache.apply_diff_to_table::( "big_fish_gallery_view", &self.big_fish_gallery_view, @@ -3191,6 +3330,15 @@ impl __sdk::DbUpdate for DbUpdate { "visual_novel_gallery_view", &self.visual_novel_gallery_view, ); + diff.wooden_fish_gallery_card_view = cache + .apply_diff_to_table::( + "wooden_fish_gallery_card_view", + &self.wooden_fish_gallery_card_view, + ); + diff.wooden_fish_gallery_view = cache.apply_diff_to_table::( + "wooden_fish_gallery_view", + &self.wooden_fish_gallery_view, + ); diff } @@ -3501,6 +3649,24 @@ impl __sdk::DbUpdate for DbUpdate { "visual_novel_work_profile" => db_update .visual_novel_work_profile .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), + "wooden_fish_agent_session" => db_update + .wooden_fish_agent_session + .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), + "wooden_fish_event" => db_update + .wooden_fish_event + .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), + "wooden_fish_gallery_card_view" => db_update + .wooden_fish_gallery_card_view + .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), + "wooden_fish_gallery_view" => db_update + .wooden_fish_gallery_view + .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), + "wooden_fish_runtime_run" => db_update + .wooden_fish_runtime_run + .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), + "wooden_fish_work_profile" => db_update + .wooden_fish_work_profile + .append(__sdk::parse_row_list_as_inserts(table_rows.rows)?), unknown => { return Err( __sdk::InternalError::unknown_name("table", unknown, "QueryRows").into(), @@ -3817,6 +3983,24 @@ impl __sdk::DbUpdate for DbUpdate { "visual_novel_work_profile" => db_update .visual_novel_work_profile .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), + "wooden_fish_agent_session" => db_update + .wooden_fish_agent_session + .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), + "wooden_fish_event" => db_update + .wooden_fish_event + .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), + "wooden_fish_gallery_card_view" => db_update + .wooden_fish_gallery_card_view + .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), + "wooden_fish_gallery_view" => db_update + .wooden_fish_gallery_view + .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), + "wooden_fish_runtime_run" => db_update + .wooden_fish_runtime_run + .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), + "wooden_fish_work_profile" => db_update + .wooden_fish_work_profile + .append(__sdk::parse_row_list_as_deletes(table_rows.rows)?), unknown => { return Err( __sdk::InternalError::unknown_name("table", unknown, "QueryRows").into(), @@ -3936,6 +4120,12 @@ pub struct AppliedDiff<'r> { __sdk::TableAppliedDiff<'r, VisualNovelRuntimeHistoryEntryRow>, visual_novel_runtime_run: __sdk::TableAppliedDiff<'r, VisualNovelRuntimeRunRow>, visual_novel_work_profile: __sdk::TableAppliedDiff<'r, VisualNovelWorkProfileRow>, + wooden_fish_agent_session: __sdk::TableAppliedDiff<'r, WoodenFishAgentSessionRow>, + wooden_fish_event: __sdk::TableAppliedDiff<'r, WoodenFishEventRow>, + wooden_fish_gallery_card_view: __sdk::TableAppliedDiff<'r, WoodenFishGalleryCardViewRow>, + wooden_fish_gallery_view: __sdk::TableAppliedDiff<'r, WoodenFishGalleryViewRow>, + wooden_fish_runtime_run: __sdk::TableAppliedDiff<'r, WoodenFishRuntimeRunRow>, + wooden_fish_work_profile: __sdk::TableAppliedDiff<'r, WoodenFishWorkProfileRow>, __unused: std::marker::PhantomData<&'r ()>, } @@ -4434,6 +4624,36 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> { &self.visual_novel_work_profile, event, ); + callbacks.invoke_table_row_callbacks::( + "wooden_fish_agent_session", + &self.wooden_fish_agent_session, + event, + ); + callbacks.invoke_table_row_callbacks::( + "wooden_fish_event", + &self.wooden_fish_event, + event, + ); + callbacks.invoke_table_row_callbacks::( + "wooden_fish_gallery_card_view", + &self.wooden_fish_gallery_card_view, + event, + ); + callbacks.invoke_table_row_callbacks::( + "wooden_fish_gallery_view", + &self.wooden_fish_gallery_view, + event, + ); + callbacks.invoke_table_row_callbacks::( + "wooden_fish_runtime_run", + &self.wooden_fish_runtime_run, + event, + ); + callbacks.invoke_table_row_callbacks::( + "wooden_fish_work_profile", + &self.wooden_fish_work_profile, + event, + ); } } @@ -5195,6 +5415,12 @@ impl __sdk::SpacetimeModule for RemoteModule { visual_novel_runtime_history_entry_table::register_table(client_cache); visual_novel_runtime_run_table::register_table(client_cache); visual_novel_work_profile_table::register_table(client_cache); + wooden_fish_agent_session_table::register_table(client_cache); + wooden_fish_event_table::register_table(client_cache); + wooden_fish_gallery_card_view_table::register_table(client_cache); + wooden_fish_gallery_view_table::register_table(client_cache); + wooden_fish_runtime_run_table::register_table(client_cache); + wooden_fish_work_profile_table::register_table(client_cache); } const ALL_TABLE_NAMES: &'static [&'static str] = &[ "ai_result_reference", @@ -5298,5 +5524,11 @@ impl __sdk::SpacetimeModule for RemoteModule { "visual_novel_runtime_history_entry", "visual_novel_runtime_run", "visual_novel_work_profile", + "wooden_fish_agent_session", + "wooden_fish_event", + "wooden_fish_gallery_card_view", + "wooden_fish_gallery_view", + "wooden_fish_runtime_run", + "wooden_fish_work_profile", ]; } diff --git a/server-rs/crates/spacetime-client/src/module_bindings/checkpoint_wooden_fish_run_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/checkpoint_wooden_fish_run_procedure.rs new file mode 100644 index 00000000..5bd5a45c --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/checkpoint_wooden_fish_run_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_run_checkpoint_input_type::WoodenFishRunCheckpointInput; +use super::wooden_fish_run_procedure_result_type::WoodenFishRunProcedureResult; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct CheckpointWoodenFishRunArgs { + pub input: WoodenFishRunCheckpointInput, +} + +impl __sdk::InModule for CheckpointWoodenFishRunArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `checkpoint_wooden_fish_run`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait checkpoint_wooden_fish_run { + fn checkpoint_wooden_fish_run(&self, input: WoodenFishRunCheckpointInput) { + self.checkpoint_wooden_fish_run_then(input, |_, _| {}); + } + + fn checkpoint_wooden_fish_run_then( + &self, + input: WoodenFishRunCheckpointInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl checkpoint_wooden_fish_run for super::RemoteProcedures { + fn checkpoint_wooden_fish_run_then( + &self, + input: WoodenFishRunCheckpointInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishRunProcedureResult>( + "checkpoint_wooden_fish_run", + CheckpointWoodenFishRunArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/compile_wooden_fish_draft_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/compile_wooden_fish_draft_procedure.rs new file mode 100644 index 00000000..61c7b013 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/compile_wooden_fish_draft_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_agent_session_procedure_result_type::WoodenFishAgentSessionProcedureResult; +use super::wooden_fish_draft_compile_input_type::WoodenFishDraftCompileInput; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct CompileWoodenFishDraftArgs { + pub input: WoodenFishDraftCompileInput, +} + +impl __sdk::InModule for CompileWoodenFishDraftArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `compile_wooden_fish_draft`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait compile_wooden_fish_draft { + fn compile_wooden_fish_draft(&self, input: WoodenFishDraftCompileInput) { + self.compile_wooden_fish_draft_then(input, |_, _| {}); + } + + fn compile_wooden_fish_draft_then( + &self, + input: WoodenFishDraftCompileInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl compile_wooden_fish_draft for super::RemoteProcedures { + fn compile_wooden_fish_draft_then( + &self, + input: WoodenFishDraftCompileInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishAgentSessionProcedureResult>( + "compile_wooden_fish_draft", + CompileWoodenFishDraftArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/create_wooden_fish_agent_session_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/create_wooden_fish_agent_session_procedure.rs new file mode 100644 index 00000000..ec6bec0d --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/create_wooden_fish_agent_session_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_agent_session_create_input_type::WoodenFishAgentSessionCreateInput; +use super::wooden_fish_agent_session_procedure_result_type::WoodenFishAgentSessionProcedureResult; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct CreateWoodenFishAgentSessionArgs { + pub input: WoodenFishAgentSessionCreateInput, +} + +impl __sdk::InModule for CreateWoodenFishAgentSessionArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `create_wooden_fish_agent_session`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait create_wooden_fish_agent_session { + fn create_wooden_fish_agent_session(&self, input: WoodenFishAgentSessionCreateInput) { + self.create_wooden_fish_agent_session_then(input, |_, _| {}); + } + + fn create_wooden_fish_agent_session_then( + &self, + input: WoodenFishAgentSessionCreateInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl create_wooden_fish_agent_session for super::RemoteProcedures { + fn create_wooden_fish_agent_session_then( + &self, + input: WoodenFishAgentSessionCreateInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishAgentSessionProcedureResult>( + "create_wooden_fish_agent_session", + CreateWoodenFishAgentSessionArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/finish_wooden_fish_run_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/finish_wooden_fish_run_procedure.rs new file mode 100644 index 00000000..30e452e1 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/finish_wooden_fish_run_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_run_finish_input_type::WoodenFishRunFinishInput; +use super::wooden_fish_run_procedure_result_type::WoodenFishRunProcedureResult; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct FinishWoodenFishRunArgs { + pub input: WoodenFishRunFinishInput, +} + +impl __sdk::InModule for FinishWoodenFishRunArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `finish_wooden_fish_run`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait finish_wooden_fish_run { + fn finish_wooden_fish_run(&self, input: WoodenFishRunFinishInput) { + self.finish_wooden_fish_run_then(input, |_, _| {}); + } + + fn finish_wooden_fish_run_then( + &self, + input: WoodenFishRunFinishInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl finish_wooden_fish_run for super::RemoteProcedures { + fn finish_wooden_fish_run_then( + &self, + input: WoodenFishRunFinishInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishRunProcedureResult>( + "finish_wooden_fish_run", + FinishWoodenFishRunArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/get_custom_world_agent_operation_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/get_custom_world_agent_operation_procedure.rs index b4d81a52..cce1dbb5 100644 --- a/server-rs/crates/spacetime-client/src/module_bindings/get_custom_world_agent_operation_procedure.rs +++ b/server-rs/crates/spacetime-client/src/module_bindings/get_custom_world_agent_operation_procedure.rs @@ -1,4 +1,3 @@ - // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. diff --git a/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_agent_session_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_agent_session_procedure.rs new file mode 100644 index 00000000..e0b80d0e --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_agent_session_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_agent_session_get_input_type::WoodenFishAgentSessionGetInput; +use super::wooden_fish_agent_session_procedure_result_type::WoodenFishAgentSessionProcedureResult; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct GetWoodenFishAgentSessionArgs { + pub input: WoodenFishAgentSessionGetInput, +} + +impl __sdk::InModule for GetWoodenFishAgentSessionArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `get_wooden_fish_agent_session`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait get_wooden_fish_agent_session { + fn get_wooden_fish_agent_session(&self, input: WoodenFishAgentSessionGetInput) { + self.get_wooden_fish_agent_session_then(input, |_, _| {}); + } + + fn get_wooden_fish_agent_session_then( + &self, + input: WoodenFishAgentSessionGetInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl get_wooden_fish_agent_session for super::RemoteProcedures { + fn get_wooden_fish_agent_session_then( + &self, + input: WoodenFishAgentSessionGetInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishAgentSessionProcedureResult>( + "get_wooden_fish_agent_session", + GetWoodenFishAgentSessionArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_run_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_run_procedure.rs new file mode 100644 index 00000000..8a0e145a --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_run_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_run_get_input_type::WoodenFishRunGetInput; +use super::wooden_fish_run_procedure_result_type::WoodenFishRunProcedureResult; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct GetWoodenFishRunArgs { + pub input: WoodenFishRunGetInput, +} + +impl __sdk::InModule for GetWoodenFishRunArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `get_wooden_fish_run`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait get_wooden_fish_run { + fn get_wooden_fish_run(&self, input: WoodenFishRunGetInput) { + self.get_wooden_fish_run_then(input, |_, _| {}); + } + + fn get_wooden_fish_run_then( + &self, + input: WoodenFishRunGetInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl get_wooden_fish_run for super::RemoteProcedures { + fn get_wooden_fish_run_then( + &self, + input: WoodenFishRunGetInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishRunProcedureResult>( + "get_wooden_fish_run", + GetWoodenFishRunArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_work_profile_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_work_profile_procedure.rs new file mode 100644 index 00000000..44f67362 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/get_wooden_fish_work_profile_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_work_get_input_type::WoodenFishWorkGetInput; +use super::wooden_fish_work_procedure_result_type::WoodenFishWorkProcedureResult; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct GetWoodenFishWorkProfileArgs { + pub input: WoodenFishWorkGetInput, +} + +impl __sdk::InModule for GetWoodenFishWorkProfileArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `get_wooden_fish_work_profile`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait get_wooden_fish_work_profile { + fn get_wooden_fish_work_profile(&self, input: WoodenFishWorkGetInput) { + self.get_wooden_fish_work_profile_then(input, |_, _| {}); + } + + fn get_wooden_fish_work_profile_then( + &self, + input: WoodenFishWorkGetInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl get_wooden_fish_work_profile for super::RemoteProcedures { + fn get_wooden_fish_work_profile_then( + &self, + input: WoodenFishWorkGetInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishWorkProcedureResult>( + "get_wooden_fish_work_profile", + GetWoodenFishWorkProfileArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/list_wooden_fish_works_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/list_wooden_fish_works_procedure.rs new file mode 100644 index 00000000..d449ff80 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/list_wooden_fish_works_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_works_list_input_type::WoodenFishWorksListInput; +use super::wooden_fish_works_procedure_result_type::WoodenFishWorksProcedureResult; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct ListWoodenFishWorksArgs { + pub input: WoodenFishWorksListInput, +} + +impl __sdk::InModule for ListWoodenFishWorksArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `list_wooden_fish_works`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait list_wooden_fish_works { + fn list_wooden_fish_works(&self, input: WoodenFishWorksListInput) { + self.list_wooden_fish_works_then(input, |_, _| {}); + } + + fn list_wooden_fish_works_then( + &self, + input: WoodenFishWorksListInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl list_wooden_fish_works for super::RemoteProcedures { + fn list_wooden_fish_works_then( + &self, + input: WoodenFishWorksListInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishWorksProcedureResult>( + "list_wooden_fish_works", + ListWoodenFishWorksArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/publish_wooden_fish_work_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/publish_wooden_fish_work_procedure.rs new file mode 100644 index 00000000..f370ace6 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/publish_wooden_fish_work_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_work_procedure_result_type::WoodenFishWorkProcedureResult; +use super::wooden_fish_work_publish_input_type::WoodenFishWorkPublishInput; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct PublishWoodenFishWorkArgs { + pub input: WoodenFishWorkPublishInput, +} + +impl __sdk::InModule for PublishWoodenFishWorkArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `publish_wooden_fish_work`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait publish_wooden_fish_work { + fn publish_wooden_fish_work(&self, input: WoodenFishWorkPublishInput) { + self.publish_wooden_fish_work_then(input, |_, _| {}); + } + + fn publish_wooden_fish_work_then( + &self, + input: WoodenFishWorkPublishInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl publish_wooden_fish_work for super::RemoteProcedures { + fn publish_wooden_fish_work_then( + &self, + input: WoodenFishWorkPublishInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishWorkProcedureResult>( + "publish_wooden_fish_work", + PublishWoodenFishWorkArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/start_wooden_fish_run_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/start_wooden_fish_run_procedure.rs new file mode 100644 index 00000000..daf6358e --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/start_wooden_fish_run_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_run_procedure_result_type::WoodenFishRunProcedureResult; +use super::wooden_fish_run_start_input_type::WoodenFishRunStartInput; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct StartWoodenFishRunArgs { + pub input: WoodenFishRunStartInput, +} + +impl __sdk::InModule for StartWoodenFishRunArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `start_wooden_fish_run`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait start_wooden_fish_run { + fn start_wooden_fish_run(&self, input: WoodenFishRunStartInput) { + self.start_wooden_fish_run_then(input, |_, _| {}); + } + + fn start_wooden_fish_run_then( + &self, + input: WoodenFishRunStartInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl start_wooden_fish_run for super::RemoteProcedures { + fn start_wooden_fish_run_then( + &self, + input: WoodenFishRunStartInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishRunProcedureResult>( + "start_wooden_fish_run", + StartWoodenFishRunArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/update_wooden_fish_work_procedure.rs b/server-rs/crates/spacetime-client/src/module_bindings/update_wooden_fish_work_procedure.rs new file mode 100644 index 00000000..31785275 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/update_wooden_fish_work_procedure.rs @@ -0,0 +1,59 @@ +// 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::wooden_fish_work_procedure_result_type::WoodenFishWorkProcedureResult; +use super::wooden_fish_work_update_input_type::WoodenFishWorkUpdateInput; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +struct UpdateWoodenFishWorkArgs { + pub input: WoodenFishWorkUpdateInput, +} + +impl __sdk::InModule for UpdateWoodenFishWorkArgs { + type Module = super::RemoteModule; +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the procedure `update_wooden_fish_work`. +/// +/// Implemented for [`super::RemoteProcedures`]. +pub trait update_wooden_fish_work { + fn update_wooden_fish_work(&self, input: WoodenFishWorkUpdateInput) { + self.update_wooden_fish_work_then(input, |_, _| {}); + } + + fn update_wooden_fish_work_then( + &self, + input: WoodenFishWorkUpdateInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ); +} + +impl update_wooden_fish_work for super::RemoteProcedures { + fn update_wooden_fish_work_then( + &self, + input: WoodenFishWorkUpdateInput, + + __callback: impl FnOnce( + &super::ProcedureEventContext, + Result, + ) + Send + + 'static, + ) { + self.imp + .invoke_procedure_with_callback::<_, WoodenFishWorkProcedureResult>( + "update_wooden_fish_work", + UpdateWoodenFishWorkArgs { input }, + __callback, + ); + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_create_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_create_input_type.rs new file mode 100644 index 00000000..1ad698a2 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_create_input_type.rs @@ -0,0 +1,22 @@ +// 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 WoodenFishAgentSessionCreateInput { + pub session_id: String, + pub owner_user_id: String, + pub work_title: String, + pub work_description: String, + pub theme_tags_json: Option, + pub config_json: Option, + pub draft_json: Option, + pub created_at_micros: i64, +} + +impl __sdk::InModule for WoodenFishAgentSessionCreateInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_get_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_get_input_type.rs new file mode 100644 index 00000000..62f4469b --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_get_input_type.rs @@ -0,0 +1,16 @@ +// 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 WoodenFishAgentSessionGetInput { + pub session_id: String, + pub owner_user_id: String, +} + +impl __sdk::InModule for WoodenFishAgentSessionGetInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_procedure_result_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_procedure_result_type.rs new file mode 100644 index 00000000..e89fc3a6 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_procedure_result_type.rs @@ -0,0 +1,19 @@ +// 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::wooden_fish_agent_session_snapshot_type::WoodenFishAgentSessionSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishAgentSessionProcedureResult { + pub ok: bool, + pub session: Option, + pub error_message: Option, +} + +impl __sdk::InModule for WoodenFishAgentSessionProcedureResult { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_row_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_row_type.rs new file mode 100644 index 00000000..8f918cdf --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_row_type.rs @@ -0,0 +1,81 @@ +// 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 WoodenFishAgentSessionRow { + pub session_id: String, + pub owner_user_id: String, + pub current_turn: u32, + pub progress_percent: u32, + pub stage: String, + pub config_json: String, + pub draft_json: String, + pub published_profile_id: String, + pub created_at: __sdk::Timestamp, + pub updated_at: __sdk::Timestamp, +} + +impl __sdk::InModule for WoodenFishAgentSessionRow { + type Module = super::RemoteModule; +} + +/// Column accessor struct for the table `WoodenFishAgentSessionRow`. +/// +/// Provides typed access to columns for query building. +pub struct WoodenFishAgentSessionRowCols { + pub session_id: __sdk::__query_builder::Col, + pub owner_user_id: __sdk::__query_builder::Col, + pub current_turn: __sdk::__query_builder::Col, + pub progress_percent: __sdk::__query_builder::Col, + pub stage: __sdk::__query_builder::Col, + pub config_json: __sdk::__query_builder::Col, + pub draft_json: __sdk::__query_builder::Col, + pub published_profile_id: __sdk::__query_builder::Col, + pub created_at: __sdk::__query_builder::Col, + pub updated_at: __sdk::__query_builder::Col, +} + +impl __sdk::__query_builder::HasCols for WoodenFishAgentSessionRow { + type Cols = WoodenFishAgentSessionRowCols; + fn cols(table_name: &'static str) -> Self::Cols { + WoodenFishAgentSessionRowCols { + session_id: __sdk::__query_builder::Col::new(table_name, "session_id"), + owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"), + 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"), + config_json: __sdk::__query_builder::Col::new(table_name, "config_json"), + draft_json: __sdk::__query_builder::Col::new(table_name, "draft_json"), + published_profile_id: __sdk::__query_builder::Col::new( + table_name, + "published_profile_id", + ), + 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 `WoodenFishAgentSessionRow`. +/// +/// Provides typed access to indexed columns for query building. +pub struct WoodenFishAgentSessionRowIxCols { + pub owner_user_id: __sdk::__query_builder::IxCol, + pub session_id: __sdk::__query_builder::IxCol, +} + +impl __sdk::__query_builder::HasIxCols for WoodenFishAgentSessionRow { + type IxCols = WoodenFishAgentSessionRowIxCols; + fn ix_cols(table_name: &'static str) -> Self::IxCols { + WoodenFishAgentSessionRowIxCols { + 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 WoodenFishAgentSessionRow {} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_snapshot_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_snapshot_type.rs new file mode 100644 index 00000000..f4526483 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_snapshot_type.rs @@ -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::wooden_fish_creator_config_snapshot_type::WoodenFishCreatorConfigSnapshot; +use super::wooden_fish_draft_snapshot_type::WoodenFishDraftSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishAgentSessionSnapshot { + pub session_id: String, + pub owner_user_id: String, + pub current_turn: u32, + pub progress_percent: u32, + pub stage: String, + pub config: WoodenFishCreatorConfigSnapshot, + pub draft: Option, + pub published_profile_id: Option, + pub created_at_micros: i64, + pub updated_at_micros: i64, +} + +impl __sdk::InModule for WoodenFishAgentSessionSnapshot { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_table.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_table.rs new file mode 100644 index 00000000..68f2e484 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_agent_session_table.rs @@ -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 super::wooden_fish_agent_session_row_type::WoodenFishAgentSessionRow; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `wooden_fish_agent_session`. +/// +/// Obtain a handle from the [`WoodenFishAgentSessionTableAccess::wooden_fish_agent_session`] method on [`super::RemoteTables`], +/// like `ctx.db.wooden_fish_agent_session()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_agent_session().on_insert(...)`. +pub struct WoodenFishAgentSessionTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `wooden_fish_agent_session`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait WoodenFishAgentSessionTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`WoodenFishAgentSessionTableHandle`], which mediates access to the table `wooden_fish_agent_session`. + fn wooden_fish_agent_session(&self) -> WoodenFishAgentSessionTableHandle<'_>; +} + +impl WoodenFishAgentSessionTableAccess for super::RemoteTables { + fn wooden_fish_agent_session(&self) -> WoodenFishAgentSessionTableHandle<'_> { + WoodenFishAgentSessionTableHandle { + imp: self + .imp + .get_table::("wooden_fish_agent_session"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct WoodenFishAgentSessionInsertCallbackId(__sdk::CallbackId); +pub struct WoodenFishAgentSessionDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for WoodenFishAgentSessionTableHandle<'ctx> { + type Row = WoodenFishAgentSessionRow; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = WoodenFishAgentSessionInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishAgentSessionInsertCallbackId { + WoodenFishAgentSessionInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: WoodenFishAgentSessionInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = WoodenFishAgentSessionDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishAgentSessionDeleteCallbackId { + WoodenFishAgentSessionDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: WoodenFishAgentSessionDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +pub struct WoodenFishAgentSessionUpdateCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::TableWithPrimaryKey for WoodenFishAgentSessionTableHandle<'ctx> { + type UpdateCallbackId = WoodenFishAgentSessionUpdateCallbackId; + + fn on_update( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, + ) -> WoodenFishAgentSessionUpdateCallbackId { + WoodenFishAgentSessionUpdateCallbackId(self.imp.on_update(Box::new(callback))) + } + + fn remove_on_update(&self, callback: WoodenFishAgentSessionUpdateCallbackId) { + self.imp.remove_on_update(callback.0) + } +} + +/// Access to the `session_id` unique index on the table `wooden_fish_agent_session`, +/// which allows point queries on the field of the same name +/// via the [`WoodenFishAgentSessionSessionIdUnique::find`] method. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_agent_session().session_id().find(...)`. +pub struct WoodenFishAgentSessionSessionIdUnique<'ctx> { + imp: __sdk::UniqueConstraintHandle, + phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +impl<'ctx> WoodenFishAgentSessionTableHandle<'ctx> { + /// Get a handle on the `session_id` unique index on the table `wooden_fish_agent_session`. + pub fn session_id(&self) -> WoodenFishAgentSessionSessionIdUnique<'ctx> { + WoodenFishAgentSessionSessionIdUnique { + imp: self.imp.get_unique_constraint::("session_id"), + phantom: std::marker::PhantomData, + } + } +} + +impl<'ctx> WoodenFishAgentSessionSessionIdUnique<'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 { + self.imp.find(col_val) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = + client_cache.get_or_make_table::("wooden_fish_agent_session"); + _table.add_unique_constraint::("session_id", |row| &row.session_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + +#[allow(non_camel_case_types)] +/// Extension trait for query builder access to the table `WoodenFishAgentSessionRow`. +/// +/// Implemented for [`__sdk::QueryTableAccessor`]. +pub trait wooden_fish_agent_sessionQueryTableAccess { + #[allow(non_snake_case)] + /// Get a query builder for the table `WoodenFishAgentSessionRow`. + fn wooden_fish_agent_session(&self) + -> __sdk::__query_builder::Table; +} + +impl wooden_fish_agent_sessionQueryTableAccess for __sdk::QueryTableAccessor { + fn wooden_fish_agent_session( + &self, + ) -> __sdk::__query_builder::Table { + __sdk::__query_builder::Table::new("wooden_fish_agent_session") + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_audio_asset_snapshot_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_audio_asset_snapshot_type.rs new file mode 100644 index 00000000..9fb39b2d --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_audio_asset_snapshot_type.rs @@ -0,0 +1,21 @@ +// 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 WoodenFishAudioAssetSnapshot { + pub asset_id: String, + pub audio_src: String, + pub audio_object_key: String, + pub asset_object_id: String, + pub source: String, + pub prompt: Option, + pub duration_ms: Option, +} + +impl __sdk::InModule for WoodenFishAudioAssetSnapshot { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_creator_config_snapshot_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_creator_config_snapshot_type.rs new file mode 100644 index 00000000..e54b4b3a --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_creator_config_snapshot_type.rs @@ -0,0 +1,21 @@ +// 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 WoodenFishCreatorConfigSnapshot { + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub floating_words: Vec, +} + +impl __sdk::InModule for WoodenFishCreatorConfigSnapshot { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_compile_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_compile_input_type.rs new file mode 100644 index 00000000..d88914d6 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_compile_input_type.rs @@ -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 WoodenFishDraftCompileInput { + pub session_id: String, + pub owner_user_id: String, + pub profile_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub theme_tags_json: Option, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset_json: Option, + pub hit_sound_asset_json: Option, + pub floating_words_json: Option, + pub cover_image_src: Option, + pub generation_status: Option, + pub compiled_at_micros: i64, +} + +impl __sdk::InModule for WoodenFishDraftCompileInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_snapshot_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_snapshot_type.rs new file mode 100644 index 00000000..f5f93b09 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_draft_snapshot_type.rs @@ -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}; + +use super::wooden_fish_audio_asset_snapshot_type::WoodenFishAudioAssetSnapshot; +use super::wooden_fish_image_asset_snapshot_type::WoodenFishImageAssetSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishDraftSnapshot { + pub template_id: String, + pub template_name: String, + pub profile_id: Option, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub floating_words: Vec, + pub hit_object_asset: Option, + pub hit_sound_asset: Option, + pub cover_image_src: Option, + pub generation_status: String, +} + +impl __sdk::InModule for WoodenFishDraftSnapshot { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_row_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_row_type.rs new file mode 100644 index 00000000..9b000003 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_row_type.rs @@ -0,0 +1,71 @@ +// 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 WoodenFishEventRow { + pub event_id: String, + pub owner_user_id: String, + pub profile_id: String, + pub run_id: String, + pub event_type: String, + pub result: String, + pub occurred_at: __sdk::Timestamp, +} + +impl __sdk::InModule for WoodenFishEventRow { + type Module = super::RemoteModule; +} + +/// Column accessor struct for the table `WoodenFishEventRow`. +/// +/// Provides typed access to columns for query building. +pub struct WoodenFishEventRowCols { + pub event_id: __sdk::__query_builder::Col, + pub owner_user_id: __sdk::__query_builder::Col, + pub profile_id: __sdk::__query_builder::Col, + pub run_id: __sdk::__query_builder::Col, + pub event_type: __sdk::__query_builder::Col, + pub result: __sdk::__query_builder::Col, + pub occurred_at: __sdk::__query_builder::Col, +} + +impl __sdk::__query_builder::HasCols for WoodenFishEventRow { + type Cols = WoodenFishEventRowCols; + fn cols(table_name: &'static str) -> Self::Cols { + WoodenFishEventRowCols { + event_id: __sdk::__query_builder::Col::new(table_name, "event_id"), + owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"), + profile_id: __sdk::__query_builder::Col::new(table_name, "profile_id"), + run_id: __sdk::__query_builder::Col::new(table_name, "run_id"), + event_type: __sdk::__query_builder::Col::new(table_name, "event_type"), + result: __sdk::__query_builder::Col::new(table_name, "result"), + occurred_at: __sdk::__query_builder::Col::new(table_name, "occurred_at"), + } + } +} + +/// Indexed column accessor struct for the table `WoodenFishEventRow`. +/// +/// Provides typed access to indexed columns for query building. +pub struct WoodenFishEventRowIxCols { + pub event_id: __sdk::__query_builder::IxCol, + pub profile_id: __sdk::__query_builder::IxCol, + pub run_id: __sdk::__query_builder::IxCol, +} + +impl __sdk::__query_builder::HasIxCols for WoodenFishEventRow { + type IxCols = WoodenFishEventRowIxCols; + fn ix_cols(table_name: &'static str) -> Self::IxCols { + WoodenFishEventRowIxCols { + event_id: __sdk::__query_builder::IxCol::new(table_name, "event_id"), + profile_id: __sdk::__query_builder::IxCol::new(table_name, "profile_id"), + run_id: __sdk::__query_builder::IxCol::new(table_name, "run_id"), + } + } +} + +impl __sdk::__query_builder::CanBeLookupTable for WoodenFishEventRow {} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_table.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_table.rs new file mode 100644 index 00000000..ba0e979d --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_event_table.rs @@ -0,0 +1,161 @@ +// 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 super::wooden_fish_event_row_type::WoodenFishEventRow; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `wooden_fish_event`. +/// +/// Obtain a handle from the [`WoodenFishEventTableAccess::wooden_fish_event`] method on [`super::RemoteTables`], +/// like `ctx.db.wooden_fish_event()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_event().on_insert(...)`. +pub struct WoodenFishEventTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `wooden_fish_event`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait WoodenFishEventTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`WoodenFishEventTableHandle`], which mediates access to the table `wooden_fish_event`. + fn wooden_fish_event(&self) -> WoodenFishEventTableHandle<'_>; +} + +impl WoodenFishEventTableAccess for super::RemoteTables { + fn wooden_fish_event(&self) -> WoodenFishEventTableHandle<'_> { + WoodenFishEventTableHandle { + imp: self + .imp + .get_table::("wooden_fish_event"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct WoodenFishEventInsertCallbackId(__sdk::CallbackId); +pub struct WoodenFishEventDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for WoodenFishEventTableHandle<'ctx> { + type Row = WoodenFishEventRow; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = WoodenFishEventInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishEventInsertCallbackId { + WoodenFishEventInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: WoodenFishEventInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = WoodenFishEventDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishEventDeleteCallbackId { + WoodenFishEventDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: WoodenFishEventDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +pub struct WoodenFishEventUpdateCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::TableWithPrimaryKey for WoodenFishEventTableHandle<'ctx> { + type UpdateCallbackId = WoodenFishEventUpdateCallbackId; + + fn on_update( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, + ) -> WoodenFishEventUpdateCallbackId { + WoodenFishEventUpdateCallbackId(self.imp.on_update(Box::new(callback))) + } + + fn remove_on_update(&self, callback: WoodenFishEventUpdateCallbackId) { + self.imp.remove_on_update(callback.0) + } +} + +/// Access to the `event_id` unique index on the table `wooden_fish_event`, +/// which allows point queries on the field of the same name +/// via the [`WoodenFishEventEventIdUnique::find`] method. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_event().event_id().find(...)`. +pub struct WoodenFishEventEventIdUnique<'ctx> { + imp: __sdk::UniqueConstraintHandle, + phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +impl<'ctx> WoodenFishEventTableHandle<'ctx> { + /// Get a handle on the `event_id` unique index on the table `wooden_fish_event`. + pub fn event_id(&self) -> WoodenFishEventEventIdUnique<'ctx> { + WoodenFishEventEventIdUnique { + imp: self.imp.get_unique_constraint::("event_id"), + phantom: std::marker::PhantomData, + } + } +} + +impl<'ctx> WoodenFishEventEventIdUnique<'ctx> { + /// Find the subscribed row whose `event_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 { + self.imp.find(col_val) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("wooden_fish_event"); + _table.add_unique_constraint::("event_id", |row| &row.event_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + +#[allow(non_camel_case_types)] +/// Extension trait for query builder access to the table `WoodenFishEventRow`. +/// +/// Implemented for [`__sdk::QueryTableAccessor`]. +pub trait wooden_fish_eventQueryTableAccess { + #[allow(non_snake_case)] + /// Get a query builder for the table `WoodenFishEventRow`. + fn wooden_fish_event(&self) -> __sdk::__query_builder::Table; +} + +impl wooden_fish_eventQueryTableAccess for __sdk::QueryTableAccessor { + fn wooden_fish_event(&self) -> __sdk::__query_builder::Table { + __sdk::__query_builder::Table::new("wooden_fish_event") + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_row_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_row_type.rs new file mode 100644 index 00000000..a11abdbb --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_row_type.rs @@ -0,0 +1,76 @@ +// 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 WoodenFishGalleryCardViewRow { + pub public_work_code: String, + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub cover_image_src: String, + pub theme_tags: Vec, + pub publication_status: String, + pub play_count: u32, + pub updated_at_micros: i64, + pub published_at_micros: Option, + pub generation_status: String, +} + +impl __sdk::InModule for WoodenFishGalleryCardViewRow { + type Module = super::RemoteModule; +} + +/// Column accessor struct for the table `WoodenFishGalleryCardViewRow`. +/// +/// Provides typed access to columns for query building. +pub struct WoodenFishGalleryCardViewRowCols { + pub public_work_code: __sdk::__query_builder::Col, + pub work_id: __sdk::__query_builder::Col, + pub profile_id: __sdk::__query_builder::Col, + pub owner_user_id: __sdk::__query_builder::Col, + pub author_display_name: __sdk::__query_builder::Col, + pub work_title: __sdk::__query_builder::Col, + pub work_description: __sdk::__query_builder::Col, + pub cover_image_src: __sdk::__query_builder::Col, + pub theme_tags: __sdk::__query_builder::Col>, + pub publication_status: __sdk::__query_builder::Col, + pub play_count: __sdk::__query_builder::Col, + pub updated_at_micros: __sdk::__query_builder::Col, + pub published_at_micros: __sdk::__query_builder::Col>, + pub generation_status: __sdk::__query_builder::Col, +} + +impl __sdk::__query_builder::HasCols for WoodenFishGalleryCardViewRow { + type Cols = WoodenFishGalleryCardViewRowCols; + fn cols(table_name: &'static str) -> Self::Cols { + WoodenFishGalleryCardViewRowCols { + public_work_code: __sdk::__query_builder::Col::new(table_name, "public_work_code"), + work_id: __sdk::__query_builder::Col::new(table_name, "work_id"), + profile_id: __sdk::__query_builder::Col::new(table_name, "profile_id"), + owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"), + author_display_name: __sdk::__query_builder::Col::new( + table_name, + "author_display_name", + ), + work_title: __sdk::__query_builder::Col::new(table_name, "work_title"), + work_description: __sdk::__query_builder::Col::new(table_name, "work_description"), + cover_image_src: __sdk::__query_builder::Col::new(table_name, "cover_image_src"), + theme_tags: __sdk::__query_builder::Col::new(table_name, "theme_tags"), + publication_status: __sdk::__query_builder::Col::new(table_name, "publication_status"), + play_count: __sdk::__query_builder::Col::new(table_name, "play_count"), + updated_at_micros: __sdk::__query_builder::Col::new(table_name, "updated_at_micros"), + published_at_micros: __sdk::__query_builder::Col::new( + table_name, + "published_at_micros", + ), + generation_status: __sdk::__query_builder::Col::new(table_name, "generation_status"), + } + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_table.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_table.rs new file mode 100644 index 00000000..d64eab80 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_card_view_table.rs @@ -0,0 +1,121 @@ +// 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 super::wooden_fish_gallery_card_view_row_type::WoodenFishGalleryCardViewRow; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `wooden_fish_gallery_card_view`. +/// +/// Obtain a handle from the [`WoodenFishGalleryCardViewTableAccess::wooden_fish_gallery_card_view`] method on [`super::RemoteTables`], +/// like `ctx.db.wooden_fish_gallery_card_view()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_gallery_card_view().on_insert(...)`. +pub struct WoodenFishGalleryCardViewTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `wooden_fish_gallery_card_view`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait WoodenFishGalleryCardViewTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`WoodenFishGalleryCardViewTableHandle`], which mediates access to the table `wooden_fish_gallery_card_view`. + fn wooden_fish_gallery_card_view(&self) -> WoodenFishGalleryCardViewTableHandle<'_>; +} + +impl WoodenFishGalleryCardViewTableAccess for super::RemoteTables { + fn wooden_fish_gallery_card_view(&self) -> WoodenFishGalleryCardViewTableHandle<'_> { + WoodenFishGalleryCardViewTableHandle { + imp: self + .imp + .get_table::("wooden_fish_gallery_card_view"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct WoodenFishGalleryCardViewInsertCallbackId(__sdk::CallbackId); +pub struct WoodenFishGalleryCardViewDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for WoodenFishGalleryCardViewTableHandle<'ctx> { + type Row = WoodenFishGalleryCardViewRow; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = WoodenFishGalleryCardViewInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishGalleryCardViewInsertCallbackId { + WoodenFishGalleryCardViewInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: WoodenFishGalleryCardViewInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = WoodenFishGalleryCardViewDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishGalleryCardViewDeleteCallbackId { + WoodenFishGalleryCardViewDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: WoodenFishGalleryCardViewDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache + .get_or_make_table::("wooden_fish_gallery_card_view"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse( + "TableUpdate", + "TableUpdate", + ) + .with_cause(e) + .into() + }) +} + +#[allow(non_camel_case_types)] +/// Extension trait for query builder access to the table `WoodenFishGalleryCardViewRow`. +/// +/// Implemented for [`__sdk::QueryTableAccessor`]. +pub trait wooden_fish_gallery_card_viewQueryTableAccess { + #[allow(non_snake_case)] + /// Get a query builder for the table `WoodenFishGalleryCardViewRow`. + fn wooden_fish_gallery_card_view( + &self, + ) -> __sdk::__query_builder::Table; +} + +impl wooden_fish_gallery_card_viewQueryTableAccess for __sdk::QueryTableAccessor { + fn wooden_fish_gallery_card_view( + &self, + ) -> __sdk::__query_builder::Table { + __sdk::__query_builder::Table::new("wooden_fish_gallery_card_view") + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_row_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_row_type.rs new file mode 100644 index 00000000..d3d7b30f --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_row_type.rs @@ -0,0 +1,109 @@ +// 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::wooden_fish_audio_asset_snapshot_type::WoodenFishAudioAssetSnapshot; +use super::wooden_fish_image_asset_snapshot_type::WoodenFishImageAssetSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishGalleryViewRow { + pub public_work_code: String, + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub source_session_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset: Option, + pub hit_sound_asset: Option, + pub floating_words: Vec, + pub cover_image_src: String, + pub publication_status: String, + pub publish_ready: bool, + pub play_count: u32, + pub generation_status: String, + pub updated_at_micros: i64, + pub published_at_micros: Option, +} + +impl __sdk::InModule for WoodenFishGalleryViewRow { + type Module = super::RemoteModule; +} + +/// Column accessor struct for the table `WoodenFishGalleryViewRow`. +/// +/// Provides typed access to columns for query building. +pub struct WoodenFishGalleryViewRowCols { + pub public_work_code: __sdk::__query_builder::Col, + pub work_id: __sdk::__query_builder::Col, + pub profile_id: __sdk::__query_builder::Col, + pub owner_user_id: __sdk::__query_builder::Col, + pub source_session_id: __sdk::__query_builder::Col, + pub author_display_name: __sdk::__query_builder::Col, + pub work_title: __sdk::__query_builder::Col, + pub work_description: __sdk::__query_builder::Col, + pub theme_tags: __sdk::__query_builder::Col>, + pub hit_object_prompt: __sdk::__query_builder::Col, + pub hit_object_reference_image_src: + __sdk::__query_builder::Col>, + pub hit_sound_prompt: __sdk::__query_builder::Col>, + pub hit_object_asset: + __sdk::__query_builder::Col>, + pub hit_sound_asset: + __sdk::__query_builder::Col>, + pub floating_words: __sdk::__query_builder::Col>, + pub cover_image_src: __sdk::__query_builder::Col, + pub publication_status: __sdk::__query_builder::Col, + pub publish_ready: __sdk::__query_builder::Col, + pub play_count: __sdk::__query_builder::Col, + pub generation_status: __sdk::__query_builder::Col, + pub updated_at_micros: __sdk::__query_builder::Col, + pub published_at_micros: __sdk::__query_builder::Col>, +} + +impl __sdk::__query_builder::HasCols for WoodenFishGalleryViewRow { + type Cols = WoodenFishGalleryViewRowCols; + fn cols(table_name: &'static str) -> Self::Cols { + WoodenFishGalleryViewRowCols { + public_work_code: __sdk::__query_builder::Col::new(table_name, "public_work_code"), + work_id: __sdk::__query_builder::Col::new(table_name, "work_id"), + profile_id: __sdk::__query_builder::Col::new(table_name, "profile_id"), + owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"), + source_session_id: __sdk::__query_builder::Col::new(table_name, "source_session_id"), + author_display_name: __sdk::__query_builder::Col::new( + table_name, + "author_display_name", + ), + work_title: __sdk::__query_builder::Col::new(table_name, "work_title"), + work_description: __sdk::__query_builder::Col::new(table_name, "work_description"), + theme_tags: __sdk::__query_builder::Col::new(table_name, "theme_tags"), + hit_object_prompt: __sdk::__query_builder::Col::new(table_name, "hit_object_prompt"), + hit_object_reference_image_src: __sdk::__query_builder::Col::new( + table_name, + "hit_object_reference_image_src", + ), + hit_sound_prompt: __sdk::__query_builder::Col::new(table_name, "hit_sound_prompt"), + hit_object_asset: __sdk::__query_builder::Col::new(table_name, "hit_object_asset"), + hit_sound_asset: __sdk::__query_builder::Col::new(table_name, "hit_sound_asset"), + floating_words: __sdk::__query_builder::Col::new(table_name, "floating_words"), + cover_image_src: __sdk::__query_builder::Col::new(table_name, "cover_image_src"), + publication_status: __sdk::__query_builder::Col::new(table_name, "publication_status"), + publish_ready: __sdk::__query_builder::Col::new(table_name, "publish_ready"), + play_count: __sdk::__query_builder::Col::new(table_name, "play_count"), + generation_status: __sdk::__query_builder::Col::new(table_name, "generation_status"), + updated_at_micros: __sdk::__query_builder::Col::new(table_name, "updated_at_micros"), + published_at_micros: __sdk::__query_builder::Col::new( + table_name, + "published_at_micros", + ), + } + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_table.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_table.rs new file mode 100644 index 00000000..e4a91629 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_gallery_view_table.rs @@ -0,0 +1,116 @@ +// 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 super::wooden_fish_audio_asset_snapshot_type::WoodenFishAudioAssetSnapshot; +use super::wooden_fish_gallery_view_row_type::WoodenFishGalleryViewRow; +use super::wooden_fish_image_asset_snapshot_type::WoodenFishImageAssetSnapshot; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `wooden_fish_gallery_view`. +/// +/// Obtain a handle from the [`WoodenFishGalleryViewTableAccess::wooden_fish_gallery_view`] method on [`super::RemoteTables`], +/// like `ctx.db.wooden_fish_gallery_view()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_gallery_view().on_insert(...)`. +pub struct WoodenFishGalleryViewTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `wooden_fish_gallery_view`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait WoodenFishGalleryViewTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`WoodenFishGalleryViewTableHandle`], which mediates access to the table `wooden_fish_gallery_view`. + fn wooden_fish_gallery_view(&self) -> WoodenFishGalleryViewTableHandle<'_>; +} + +impl WoodenFishGalleryViewTableAccess for super::RemoteTables { + fn wooden_fish_gallery_view(&self) -> WoodenFishGalleryViewTableHandle<'_> { + WoodenFishGalleryViewTableHandle { + imp: self + .imp + .get_table::("wooden_fish_gallery_view"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct WoodenFishGalleryViewInsertCallbackId(__sdk::CallbackId); +pub struct WoodenFishGalleryViewDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for WoodenFishGalleryViewTableHandle<'ctx> { + type Row = WoodenFishGalleryViewRow; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = WoodenFishGalleryViewInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishGalleryViewInsertCallbackId { + WoodenFishGalleryViewInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: WoodenFishGalleryViewInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = WoodenFishGalleryViewDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishGalleryViewDeleteCallbackId { + WoodenFishGalleryViewDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: WoodenFishGalleryViewDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = + client_cache.get_or_make_table::("wooden_fish_gallery_view"); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + +#[allow(non_camel_case_types)] +/// Extension trait for query builder access to the table `WoodenFishGalleryViewRow`. +/// +/// Implemented for [`__sdk::QueryTableAccessor`]. +pub trait wooden_fish_gallery_viewQueryTableAccess { + #[allow(non_snake_case)] + /// Get a query builder for the table `WoodenFishGalleryViewRow`. + fn wooden_fish_gallery_view(&self) -> __sdk::__query_builder::Table; +} + +impl wooden_fish_gallery_viewQueryTableAccess for __sdk::QueryTableAccessor { + fn wooden_fish_gallery_view(&self) -> __sdk::__query_builder::Table { + __sdk::__query_builder::Table::new("wooden_fish_gallery_view") + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_image_asset_snapshot_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_image_asset_snapshot_type.rs new file mode 100644 index 00000000..52f28559 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_image_asset_snapshot_type.rs @@ -0,0 +1,22 @@ +// 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 WoodenFishImageAssetSnapshot { + pub asset_id: String, + pub image_src: String, + pub image_object_key: String, + pub asset_object_id: String, + pub generation_provider: String, + pub prompt: String, + pub width: u32, + pub height: u32, +} + +impl __sdk::InModule for WoodenFishImageAssetSnapshot { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_checkpoint_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_checkpoint_input_type.rs new file mode 100644 index 00000000..0a3f0a16 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_checkpoint_input_type.rs @@ -0,0 +1,20 @@ +// 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 WoodenFishRunCheckpointInput { + pub run_id: String, + pub owner_user_id: String, + pub total_tap_count: u32, + pub word_counters_json: String, + pub client_event_id: String, + pub checkpoint_at_ms: i64, +} + +impl __sdk::InModule for WoodenFishRunCheckpointInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_finish_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_finish_input_type.rs new file mode 100644 index 00000000..a968b5ce --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_finish_input_type.rs @@ -0,0 +1,20 @@ +// 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 WoodenFishRunFinishInput { + pub run_id: String, + pub owner_user_id: String, + pub total_tap_count: u32, + pub word_counters_json: String, + pub client_event_id: String, + pub finished_at_ms: i64, +} + +impl __sdk::InModule for WoodenFishRunFinishInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_get_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_get_input_type.rs new file mode 100644 index 00000000..0b20556e --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_get_input_type.rs @@ -0,0 +1,16 @@ +// 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 WoodenFishRunGetInput { + pub run_id: String, + pub owner_user_id: String, +} + +impl __sdk::InModule for WoodenFishRunGetInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_procedure_result_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_procedure_result_type.rs new file mode 100644 index 00000000..21212b17 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_procedure_result_type.rs @@ -0,0 +1,19 @@ +// 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::wooden_fish_run_snapshot_type::WoodenFishRunSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishRunProcedureResult { + pub ok: bool, + pub run: Option, + pub error_message: Option, +} + +impl __sdk::InModule for WoodenFishRunProcedureResult { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_snapshot_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_snapshot_type.rs new file mode 100644 index 00000000..dfd085ac --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_snapshot_type.rs @@ -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::wooden_fish_run_status_type::WoodenFishRunStatus; +use super::wooden_fish_word_counter_type::WoodenFishWordCounter; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishRunSnapshot { + pub run_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub status: WoodenFishRunStatus, + pub total_tap_count: u32, + pub word_counters: Vec, + pub started_at_ms: u64, + pub updated_at_ms: u64, + pub finished_at_ms: Option, +} + +impl __sdk::InModule for WoodenFishRunSnapshot { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_start_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_start_input_type.rs new file mode 100644 index 00000000..c9f55321 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_start_input_type.rs @@ -0,0 +1,19 @@ +// 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 WoodenFishRunStartInput { + pub run_id: String, + pub owner_user_id: String, + pub profile_id: String, + pub client_event_id: String, + pub started_at_ms: i64, +} + +impl __sdk::InModule for WoodenFishRunStartInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_status_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_status_type.rs new file mode 100644 index 00000000..1b48ba39 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_run_status_type.rs @@ -0,0 +1,18 @@ +// 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 WoodenFishRunStatus { + Playing, + + Finished, +} + +impl __sdk::InModule for WoodenFishRunStatus { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_row_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_row_type.rs new file mode 100644 index 00000000..8c12c1e5 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_row_type.rs @@ -0,0 +1,86 @@ +// 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 WoodenFishRuntimeRunRow { + pub run_id: String, + pub owner_user_id: String, + pub profile_id: String, + pub status: String, + pub total_tap_count: u32, + pub word_counters_json: String, + pub started_at_ms: i64, + pub updated_at_ms: i64, + pub finished_at_ms: i64, + pub snapshot_json: String, + pub created_at: __sdk::Timestamp, + pub updated_at: __sdk::Timestamp, +} + +impl __sdk::InModule for WoodenFishRuntimeRunRow { + type Module = super::RemoteModule; +} + +/// Column accessor struct for the table `WoodenFishRuntimeRunRow`. +/// +/// Provides typed access to columns for query building. +pub struct WoodenFishRuntimeRunRowCols { + pub run_id: __sdk::__query_builder::Col, + pub owner_user_id: __sdk::__query_builder::Col, + pub profile_id: __sdk::__query_builder::Col, + pub status: __sdk::__query_builder::Col, + pub total_tap_count: __sdk::__query_builder::Col, + pub word_counters_json: __sdk::__query_builder::Col, + pub started_at_ms: __sdk::__query_builder::Col, + pub updated_at_ms: __sdk::__query_builder::Col, + pub finished_at_ms: __sdk::__query_builder::Col, + pub snapshot_json: __sdk::__query_builder::Col, + pub created_at: __sdk::__query_builder::Col, + pub updated_at: __sdk::__query_builder::Col, +} + +impl __sdk::__query_builder::HasCols for WoodenFishRuntimeRunRow { + type Cols = WoodenFishRuntimeRunRowCols; + fn cols(table_name: &'static str) -> Self::Cols { + WoodenFishRuntimeRunRowCols { + run_id: __sdk::__query_builder::Col::new(table_name, "run_id"), + owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"), + profile_id: __sdk::__query_builder::Col::new(table_name, "profile_id"), + status: __sdk::__query_builder::Col::new(table_name, "status"), + total_tap_count: __sdk::__query_builder::Col::new(table_name, "total_tap_count"), + word_counters_json: __sdk::__query_builder::Col::new(table_name, "word_counters_json"), + started_at_ms: __sdk::__query_builder::Col::new(table_name, "started_at_ms"), + updated_at_ms: __sdk::__query_builder::Col::new(table_name, "updated_at_ms"), + finished_at_ms: __sdk::__query_builder::Col::new(table_name, "finished_at_ms"), + snapshot_json: __sdk::__query_builder::Col::new(table_name, "snapshot_json"), + 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 `WoodenFishRuntimeRunRow`. +/// +/// Provides typed access to indexed columns for query building. +pub struct WoodenFishRuntimeRunRowIxCols { + pub owner_user_id: __sdk::__query_builder::IxCol, + pub profile_id: __sdk::__query_builder::IxCol, + pub run_id: __sdk::__query_builder::IxCol, +} + +impl __sdk::__query_builder::HasIxCols for WoodenFishRuntimeRunRow { + type IxCols = WoodenFishRuntimeRunRowIxCols; + fn ix_cols(table_name: &'static str) -> Self::IxCols { + WoodenFishRuntimeRunRowIxCols { + owner_user_id: __sdk::__query_builder::IxCol::new(table_name, "owner_user_id"), + profile_id: __sdk::__query_builder::IxCol::new(table_name, "profile_id"), + run_id: __sdk::__query_builder::IxCol::new(table_name, "run_id"), + } + } +} + +impl __sdk::__query_builder::CanBeLookupTable for WoodenFishRuntimeRunRow {} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_table.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_table.rs new file mode 100644 index 00000000..f09d3b6e --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_runtime_run_table.rs @@ -0,0 +1,162 @@ +// 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 super::wooden_fish_runtime_run_row_type::WoodenFishRuntimeRunRow; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `wooden_fish_runtime_run`. +/// +/// Obtain a handle from the [`WoodenFishRuntimeRunTableAccess::wooden_fish_runtime_run`] method on [`super::RemoteTables`], +/// like `ctx.db.wooden_fish_runtime_run()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_runtime_run().on_insert(...)`. +pub struct WoodenFishRuntimeRunTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `wooden_fish_runtime_run`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait WoodenFishRuntimeRunTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`WoodenFishRuntimeRunTableHandle`], which mediates access to the table `wooden_fish_runtime_run`. + fn wooden_fish_runtime_run(&self) -> WoodenFishRuntimeRunTableHandle<'_>; +} + +impl WoodenFishRuntimeRunTableAccess for super::RemoteTables { + fn wooden_fish_runtime_run(&self) -> WoodenFishRuntimeRunTableHandle<'_> { + WoodenFishRuntimeRunTableHandle { + imp: self + .imp + .get_table::("wooden_fish_runtime_run"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct WoodenFishRuntimeRunInsertCallbackId(__sdk::CallbackId); +pub struct WoodenFishRuntimeRunDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for WoodenFishRuntimeRunTableHandle<'ctx> { + type Row = WoodenFishRuntimeRunRow; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = WoodenFishRuntimeRunInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishRuntimeRunInsertCallbackId { + WoodenFishRuntimeRunInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: WoodenFishRuntimeRunInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = WoodenFishRuntimeRunDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishRuntimeRunDeleteCallbackId { + WoodenFishRuntimeRunDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: WoodenFishRuntimeRunDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +pub struct WoodenFishRuntimeRunUpdateCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::TableWithPrimaryKey for WoodenFishRuntimeRunTableHandle<'ctx> { + type UpdateCallbackId = WoodenFishRuntimeRunUpdateCallbackId; + + fn on_update( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, + ) -> WoodenFishRuntimeRunUpdateCallbackId { + WoodenFishRuntimeRunUpdateCallbackId(self.imp.on_update(Box::new(callback))) + } + + fn remove_on_update(&self, callback: WoodenFishRuntimeRunUpdateCallbackId) { + self.imp.remove_on_update(callback.0) + } +} + +/// Access to the `run_id` unique index on the table `wooden_fish_runtime_run`, +/// which allows point queries on the field of the same name +/// via the [`WoodenFishRuntimeRunRunIdUnique::find`] method. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_runtime_run().run_id().find(...)`. +pub struct WoodenFishRuntimeRunRunIdUnique<'ctx> { + imp: __sdk::UniqueConstraintHandle, + phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +impl<'ctx> WoodenFishRuntimeRunTableHandle<'ctx> { + /// Get a handle on the `run_id` unique index on the table `wooden_fish_runtime_run`. + pub fn run_id(&self) -> WoodenFishRuntimeRunRunIdUnique<'ctx> { + WoodenFishRuntimeRunRunIdUnique { + imp: self.imp.get_unique_constraint::("run_id"), + phantom: std::marker::PhantomData, + } + } +} + +impl<'ctx> WoodenFishRuntimeRunRunIdUnique<'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 { + self.imp.find(col_val) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = + client_cache.get_or_make_table::("wooden_fish_runtime_run"); + _table.add_unique_constraint::("run_id", |row| &row.run_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + +#[allow(non_camel_case_types)] +/// Extension trait for query builder access to the table `WoodenFishRuntimeRunRow`. +/// +/// Implemented for [`__sdk::QueryTableAccessor`]. +pub trait wooden_fish_runtime_runQueryTableAccess { + #[allow(non_snake_case)] + /// Get a query builder for the table `WoodenFishRuntimeRunRow`. + fn wooden_fish_runtime_run(&self) -> __sdk::__query_builder::Table; +} + +impl wooden_fish_runtime_runQueryTableAccess for __sdk::QueryTableAccessor { + fn wooden_fish_runtime_run(&self) -> __sdk::__query_builder::Table { + __sdk::__query_builder::Table::new("wooden_fish_runtime_run") + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_word_counter_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_word_counter_type.rs new file mode 100644 index 00000000..217899f1 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_word_counter_type.rs @@ -0,0 +1,16 @@ +// 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 WoodenFishWordCounter { + pub text: String, + pub count: u32, +} + +impl __sdk::InModule for WoodenFishWordCounter { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_get_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_get_input_type.rs new file mode 100644 index 00000000..9867cb79 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_get_input_type.rs @@ -0,0 +1,16 @@ +// 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 WoodenFishWorkGetInput { + pub profile_id: String, + pub owner_user_id: String, +} + +impl __sdk::InModule for WoodenFishWorkGetInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_procedure_result_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_procedure_result_type.rs new file mode 100644 index 00000000..bebf287c --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_procedure_result_type.rs @@ -0,0 +1,19 @@ +// 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::wooden_fish_work_snapshot_type::WoodenFishWorkSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishWorkProcedureResult { + pub ok: bool, + pub work: Option, + pub error_message: Option, +} + +impl __sdk::InModule for WoodenFishWorkProcedureResult { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_row_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_row_type.rs new file mode 100644 index 00000000..5e692843 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_row_type.rs @@ -0,0 +1,130 @@ +// 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 WoodenFishWorkProfileRow { + pub profile_id: String, + pub work_id: String, + pub owner_user_id: String, + pub source_session_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub theme_tags_json: String, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: String, + pub hit_sound_prompt: String, + pub hit_object_asset_json: String, + pub hit_sound_asset_json: String, + pub floating_words_json: String, + pub cover_image_src: String, + pub generation_status: String, + pub publication_status: String, + pub play_count: u32, + pub updated_at: __sdk::Timestamp, + pub published_at: Option<__sdk::Timestamp>, +} + +impl __sdk::InModule for WoodenFishWorkProfileRow { + type Module = super::RemoteModule; +} + +/// Column accessor struct for the table `WoodenFishWorkProfileRow`. +/// +/// Provides typed access to columns for query building. +pub struct WoodenFishWorkProfileRowCols { + pub profile_id: __sdk::__query_builder::Col, + pub work_id: __sdk::__query_builder::Col, + pub owner_user_id: __sdk::__query_builder::Col, + pub source_session_id: __sdk::__query_builder::Col, + pub author_display_name: __sdk::__query_builder::Col, + pub work_title: __sdk::__query_builder::Col, + pub work_description: __sdk::__query_builder::Col, + pub theme_tags_json: __sdk::__query_builder::Col, + pub hit_object_prompt: __sdk::__query_builder::Col, + pub hit_object_reference_image_src: + __sdk::__query_builder::Col, + pub hit_sound_prompt: __sdk::__query_builder::Col, + pub hit_object_asset_json: __sdk::__query_builder::Col, + pub hit_sound_asset_json: __sdk::__query_builder::Col, + pub floating_words_json: __sdk::__query_builder::Col, + pub cover_image_src: __sdk::__query_builder::Col, + pub generation_status: __sdk::__query_builder::Col, + pub publication_status: __sdk::__query_builder::Col, + pub play_count: __sdk::__query_builder::Col, + pub updated_at: __sdk::__query_builder::Col, + pub published_at: + __sdk::__query_builder::Col>, +} + +impl __sdk::__query_builder::HasCols for WoodenFishWorkProfileRow { + type Cols = WoodenFishWorkProfileRowCols; + fn cols(table_name: &'static str) -> Self::Cols { + WoodenFishWorkProfileRowCols { + profile_id: __sdk::__query_builder::Col::new(table_name, "profile_id"), + work_id: __sdk::__query_builder::Col::new(table_name, "work_id"), + owner_user_id: __sdk::__query_builder::Col::new(table_name, "owner_user_id"), + source_session_id: __sdk::__query_builder::Col::new(table_name, "source_session_id"), + author_display_name: __sdk::__query_builder::Col::new( + table_name, + "author_display_name", + ), + work_title: __sdk::__query_builder::Col::new(table_name, "work_title"), + work_description: __sdk::__query_builder::Col::new(table_name, "work_description"), + theme_tags_json: __sdk::__query_builder::Col::new(table_name, "theme_tags_json"), + hit_object_prompt: __sdk::__query_builder::Col::new(table_name, "hit_object_prompt"), + hit_object_reference_image_src: __sdk::__query_builder::Col::new( + table_name, + "hit_object_reference_image_src", + ), + hit_sound_prompt: __sdk::__query_builder::Col::new(table_name, "hit_sound_prompt"), + hit_object_asset_json: __sdk::__query_builder::Col::new( + table_name, + "hit_object_asset_json", + ), + hit_sound_asset_json: __sdk::__query_builder::Col::new( + table_name, + "hit_sound_asset_json", + ), + floating_words_json: __sdk::__query_builder::Col::new( + table_name, + "floating_words_json", + ), + cover_image_src: __sdk::__query_builder::Col::new(table_name, "cover_image_src"), + generation_status: __sdk::__query_builder::Col::new(table_name, "generation_status"), + publication_status: __sdk::__query_builder::Col::new(table_name, "publication_status"), + play_count: __sdk::__query_builder::Col::new(table_name, "play_count"), + updated_at: __sdk::__query_builder::Col::new(table_name, "updated_at"), + published_at: __sdk::__query_builder::Col::new(table_name, "published_at"), + } + } +} + +/// Indexed column accessor struct for the table `WoodenFishWorkProfileRow`. +/// +/// Provides typed access to indexed columns for query building. +pub struct WoodenFishWorkProfileRowIxCols { + pub owner_user_id: __sdk::__query_builder::IxCol, + pub profile_id: __sdk::__query_builder::IxCol, + pub publication_status: __sdk::__query_builder::IxCol, +} + +impl __sdk::__query_builder::HasIxCols for WoodenFishWorkProfileRow { + type IxCols = WoodenFishWorkProfileRowIxCols; + fn ix_cols(table_name: &'static str) -> Self::IxCols { + WoodenFishWorkProfileRowIxCols { + owner_user_id: __sdk::__query_builder::IxCol::new(table_name, "owner_user_id"), + profile_id: __sdk::__query_builder::IxCol::new(table_name, "profile_id"), + publication_status: __sdk::__query_builder::IxCol::new( + table_name, + "publication_status", + ), + } + } +} + +impl __sdk::__query_builder::CanBeLookupTable for WoodenFishWorkProfileRow {} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_table.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_table.rs new file mode 100644 index 00000000..6815f169 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_profile_table.rs @@ -0,0 +1,162 @@ +// 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 super::wooden_fish_work_profile_row_type::WoodenFishWorkProfileRow; +use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws}; + +/// Table handle for the table `wooden_fish_work_profile`. +/// +/// Obtain a handle from the [`WoodenFishWorkProfileTableAccess::wooden_fish_work_profile`] method on [`super::RemoteTables`], +/// like `ctx.db.wooden_fish_work_profile()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_work_profile().on_insert(...)`. +pub struct WoodenFishWorkProfileTableHandle<'ctx> { + imp: __sdk::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `wooden_fish_work_profile`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait WoodenFishWorkProfileTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`WoodenFishWorkProfileTableHandle`], which mediates access to the table `wooden_fish_work_profile`. + fn wooden_fish_work_profile(&self) -> WoodenFishWorkProfileTableHandle<'_>; +} + +impl WoodenFishWorkProfileTableAccess for super::RemoteTables { + fn wooden_fish_work_profile(&self) -> WoodenFishWorkProfileTableHandle<'_> { + WoodenFishWorkProfileTableHandle { + imp: self + .imp + .get_table::("wooden_fish_work_profile"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct WoodenFishWorkProfileInsertCallbackId(__sdk::CallbackId); +pub struct WoodenFishWorkProfileDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::Table for WoodenFishWorkProfileTableHandle<'ctx> { + type Row = WoodenFishWorkProfileRow; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = WoodenFishWorkProfileInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishWorkProfileInsertCallbackId { + WoodenFishWorkProfileInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: WoodenFishWorkProfileInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = WoodenFishWorkProfileDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> WoodenFishWorkProfileDeleteCallbackId { + WoodenFishWorkProfileDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: WoodenFishWorkProfileDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +pub struct WoodenFishWorkProfileUpdateCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::TableWithPrimaryKey for WoodenFishWorkProfileTableHandle<'ctx> { + type UpdateCallbackId = WoodenFishWorkProfileUpdateCallbackId; + + fn on_update( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, + ) -> WoodenFishWorkProfileUpdateCallbackId { + WoodenFishWorkProfileUpdateCallbackId(self.imp.on_update(Box::new(callback))) + } + + fn remove_on_update(&self, callback: WoodenFishWorkProfileUpdateCallbackId) { + self.imp.remove_on_update(callback.0) + } +} + +/// Access to the `profile_id` unique index on the table `wooden_fish_work_profile`, +/// which allows point queries on the field of the same name +/// via the [`WoodenFishWorkProfileProfileIdUnique::find`] method. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.wooden_fish_work_profile().profile_id().find(...)`. +pub struct WoodenFishWorkProfileProfileIdUnique<'ctx> { + imp: __sdk::UniqueConstraintHandle, + phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +impl<'ctx> WoodenFishWorkProfileTableHandle<'ctx> { + /// Get a handle on the `profile_id` unique index on the table `wooden_fish_work_profile`. + pub fn profile_id(&self) -> WoodenFishWorkProfileProfileIdUnique<'ctx> { + WoodenFishWorkProfileProfileIdUnique { + imp: self.imp.get_unique_constraint::("profile_id"), + phantom: std::marker::PhantomData, + } + } +} + +impl<'ctx> WoodenFishWorkProfileProfileIdUnique<'ctx> { + /// Find the subscribed row whose `profile_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 { + self.imp.find(col_val) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = + client_cache.get_or_make_table::("wooden_fish_work_profile"); + _table.add_unique_constraint::("profile_id", |row| &row.profile_id); +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::v2::TableUpdate, +) -> __sdk::Result<__sdk::TableUpdate> { + __sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| { + __sdk::InternalError::failed_parse("TableUpdate", "TableUpdate") + .with_cause(e) + .into() + }) +} + +#[allow(non_camel_case_types)] +/// Extension trait for query builder access to the table `WoodenFishWorkProfileRow`. +/// +/// Implemented for [`__sdk::QueryTableAccessor`]. +pub trait wooden_fish_work_profileQueryTableAccess { + #[allow(non_snake_case)] + /// Get a query builder for the table `WoodenFishWorkProfileRow`. + fn wooden_fish_work_profile(&self) -> __sdk::__query_builder::Table; +} + +impl wooden_fish_work_profileQueryTableAccess for __sdk::QueryTableAccessor { + fn wooden_fish_work_profile(&self) -> __sdk::__query_builder::Table { + __sdk::__query_builder::Table::new("wooden_fish_work_profile") + } +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_publish_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_publish_input_type.rs new file mode 100644 index 00000000..f9920f38 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_publish_input_type.rs @@ -0,0 +1,17 @@ +// 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 WoodenFishWorkPublishInput { + pub profile_id: String, + pub owner_user_id: String, + pub published_at_micros: i64, +} + +impl __sdk::InModule for WoodenFishWorkPublishInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_snapshot_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_snapshot_type.rs new file mode 100644 index 00000000..7c173133 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_snapshot_type.rs @@ -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::wooden_fish_audio_asset_snapshot_type::WoodenFishAudioAssetSnapshot; +use super::wooden_fish_image_asset_snapshot_type::WoodenFishImageAssetSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishWorkSnapshot { + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub source_session_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset: Option, + pub hit_sound_asset: Option, + pub floating_words: Vec, + pub cover_image_src: String, + pub publication_status: String, + pub publish_ready: bool, + pub play_count: u32, + pub generation_status: String, + pub updated_at_micros: i64, + pub published_at_micros: Option, +} + +impl __sdk::InModule for WoodenFishWorkSnapshot { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_update_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_update_input_type.rs new file mode 100644 index 00000000..2981f8e3 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_work_update_input_type.rs @@ -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 WoodenFishWorkUpdateInput { + pub profile_id: String, + pub owner_user_id: String, + pub work_title: String, + pub work_description: String, + pub theme_tags_json: String, + pub hit_object_prompt: Option, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset_json: Option, + pub hit_sound_asset_json: Option, + pub floating_words_json: Option, + pub cover_image_src: Option, + pub generation_status: Option, + pub updated_at_micros: i64, +} + +impl __sdk::InModule for WoodenFishWorkUpdateInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_list_input_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_list_input_type.rs new file mode 100644 index 00000000..0571854e --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_list_input_type.rs @@ -0,0 +1,16 @@ +// 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 WoodenFishWorksListInput { + pub owner_user_id: String, + pub published_only: bool, +} + +impl __sdk::InModule for WoodenFishWorksListInput { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_procedure_result_type.rs b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_procedure_result_type.rs new file mode 100644 index 00000000..bb2a8498 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/module_bindings/wooden_fish_works_procedure_result_type.rs @@ -0,0 +1,19 @@ +// 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::wooden_fish_work_snapshot_type::WoodenFishWorkSnapshot; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct WoodenFishWorksProcedureResult { + pub ok: bool, + pub items: Vec, + pub error_message: Option, +} + +impl __sdk::InModule for WoodenFishWorksProcedureResult { + type Module = super::RemoteModule; +} diff --git a/server-rs/crates/spacetime-client/src/telemetry.rs b/server-rs/crates/spacetime-client/src/telemetry.rs index c89e0f19..d75fc4a1 100644 --- a/server-rs/crates/spacetime-client/src/telemetry.rs +++ b/server-rs/crates/spacetime-client/src/telemetry.rs @@ -81,7 +81,9 @@ fn spacetime_metrics() -> &'static SpacetimeMetrics { read_duration_ms: meter .f64_histogram("genarrative.spacetime.read.duration_ms") .with_unit("ms") - .with_description("SpacetimeDB local subscription cache read duration in milliseconds") + .with_description( + "SpacetimeDB local subscription cache read duration in milliseconds", + ) .build(), } }) diff --git a/server-rs/crates/spacetime-client/src/wooden_fish.rs b/server-rs/crates/spacetime-client/src/wooden_fish.rs new file mode 100644 index 00000000..9297a163 --- /dev/null +++ b/server-rs/crates/spacetime-client/src/wooden_fish.rs @@ -0,0 +1,1031 @@ +use super::*; +use crate::mapper::{ + map_wooden_fish_agent_session_procedure_result, map_wooden_fish_gallery_card_view_row, + map_wooden_fish_run_procedure_result, map_wooden_fish_work_procedure_result, + map_wooden_fish_works_procedure_result, +}; +use shared_contracts::wooden_fish::{ + WoodenFishActionRequest, WoodenFishActionResponse, WoodenFishActionType, + WoodenFishCheckpointRunRequest, WoodenFishDraftResponse, WoodenFishFinishRunRequest, + WoodenFishGalleryResponse, WoodenFishGenerationStatus, WoodenFishRuntimeRunSnapshotResponse, + WoodenFishSessionSnapshotResponse, WoodenFishStartRunRequest, WoodenFishWorkProfileResponse, +}; +use shared_kernel::build_prefixed_uuid_id; + +const WOODEN_FISH_TEMPLATE_ID: &str = "wooden-fish"; +const WOODEN_FISH_TEMPLATE_NAME: &str = "敲木鱼"; +const DEFAULT_HIT_OBJECT_PROMPT: &str = "é»˜è®¤æ•²å‡»ç‰©å›¾æ¡ˆï¼Œåœ†æ¶¦æœ¨è´¨è´¨æ„Ÿï¼Œé€æ˜ŽèƒŒæ™¯"; +const DEFAULT_HIT_SOUND_PROMPT: &str = "清脆短促的木鱼敲击声"; + +impl SpacetimeClient { + pub async fn create_wooden_fish_session( + &self, + session: WoodenFishSessionSnapshotResponse, + ) -> Result { + let draft = session.draft.clone().ok_or_else(|| { + SpacetimeClientError::validation_failed("wooden-fish session 缺少 draft") + })?; + let theme_tags_json = Some(json_string(&draft.theme_tags)?); + let config_json = Some(build_config_json(&draft)?); + let draft_json = Some(json_string(&draft)?); + let procedure_input = WoodenFishAgentSessionCreateInput { + session_id: session.session_id, + owner_user_id: session.owner_user_id, + work_title: draft.work_title, + work_description: draft.work_description, + theme_tags_json, + config_json, + draft_json, + created_at_micros: current_unix_micros(), + }; + + self.call_after_connect( + "create_wooden_fish_agent_session", + move |connection, sender| { + connection + .procedures() + .create_wooden_fish_agent_session_then(procedure_input, move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_agent_session_procedure_result); + send_once(&sender, mapped); + }); + }, + ) + .await + } + + pub async fn get_wooden_fish_session( + &self, + session_id: String, + owner_user_id: String, + ) -> Result { + let procedure_input = WoodenFishAgentSessionGetInput { + session_id, + owner_user_id, + }; + + self.call_after_connect( + "get_wooden_fish_agent_session", + move |connection, sender| { + connection.procedures().get_wooden_fish_agent_session_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_agent_session_procedure_result); + send_once(&sender, mapped); + }, + ); + }, + ) + .await + } + + pub async fn execute_wooden_fish_action( + &self, + session_id: String, + owner_user_id: String, + payload: WoodenFishActionRequest, + ) -> Result { + let current = self + .get_wooden_fish_session(session_id.clone(), owner_user_id.clone()) + .await?; + let (procedure, _) = build_wooden_fish_action_plan( + ¤t, + &owner_user_id, + &payload, + current_unix_micros(), + )?; + let (session, work) = match procedure { + WoodenFishActionProcedure::Compile(input) => { + let profile_id = input.profile_id.clone(); + let session = self.compile_wooden_fish_draft(input).await?; + let work = self + .get_wooden_fish_work_profile(profile_id, owner_user_id) + .await + .ok(); + (session, work) + } + WoodenFishActionProcedure::Update(input) => { + let work = self.update_wooden_fish_work(input).await?; + let session = apply_wooden_fish_work_to_session(current, &work); + (session, Some(work)) + } + }; + + Ok(WoodenFishActionResponse { + action_type: payload.action_type, + session, + work, + }) + } + + pub async fn compile_wooden_fish_draft( + &self, + procedure_input: WoodenFishDraftCompileInput, + ) -> Result { + self.call_after_connect("compile_wooden_fish_draft", move |connection, sender| { + connection.procedures().compile_wooden_fish_draft_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_agent_session_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn get_wooden_fish_work_profile( + &self, + profile_id: String, + owner_user_id: String, + ) -> Result { + let procedure_input = WoodenFishWorkGetInput { + profile_id, + owner_user_id, + }; + + self.call_after_connect("get_wooden_fish_work_profile", move |connection, sender| { + connection.procedures().get_wooden_fish_work_profile_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_work_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn update_wooden_fish_work( + &self, + procedure_input: WoodenFishWorkUpdateInput, + ) -> Result { + self.call_after_connect("update_wooden_fish_work", move |connection, sender| { + connection.procedures().update_wooden_fish_work_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_work_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn publish_wooden_fish_work( + &self, + profile_id: String, + owner_user_id: String, + ) -> Result { + let procedure_input = WoodenFishWorkPublishInput { + profile_id, + owner_user_id, + published_at_micros: current_unix_micros(), + }; + + self.call_after_connect("publish_wooden_fish_work", move |connection, sender| { + connection.procedures().publish_wooden_fish_work_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_work_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn list_wooden_fish_works( + &self, + owner_user_id: String, + ) -> Result, SpacetimeClientError> { + let procedure_input = WoodenFishWorksListInput { + owner_user_id, + published_only: false, + }; + + self.call_after_connect("list_wooden_fish_works", move |connection, sender| { + connection.procedures().list_wooden_fish_works_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_works_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn get_wooden_fish_runtime_work( + &self, + profile_id: String, + ) -> Result { + self.get_wooden_fish_work_profile(profile_id, String::new()) + .await + } + + pub async fn start_wooden_fish_run( + &self, + payload: WoodenFishStartRunRequest, + owner_user_id: String, + ) -> Result { + let run_id = build_prefixed_uuid_id("wooden-fish-run-"); + let procedure_input = WoodenFishRunStartInput { + client_event_id: format!("{run_id}:start"), + run_id, + owner_user_id, + profile_id: payload.profile_id, + started_at_ms: current_unix_micros().div_euclid(1000), + }; + self.start_wooden_fish_run_with_input(procedure_input).await + } + + pub async fn start_wooden_fish_run_with_input( + &self, + procedure_input: WoodenFishRunStartInput, + ) -> Result { + self.call_after_connect("start_wooden_fish_run", move |connection, sender| { + connection.procedures().start_wooden_fish_run_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_run_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn checkpoint_wooden_fish_run( + &self, + run_id: String, + owner_user_id: String, + payload: WoodenFishCheckpointRunRequest, + ) -> Result { + let procedure_input = WoodenFishRunCheckpointInput { + run_id, + owner_user_id, + total_tap_count: payload.total_tap_count, + word_counters_json: json_string(&payload.word_counters)?, + client_event_id: payload.client_event_id, + checkpoint_at_ms: current_unix_micros().div_euclid(1000), + }; + + self.call_after_connect("checkpoint_wooden_fish_run", move |connection, sender| { + connection.procedures().checkpoint_wooden_fish_run_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_run_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn finish_wooden_fish_run( + &self, + run_id: String, + owner_user_id: String, + payload: WoodenFishFinishRunRequest, + ) -> Result { + let procedure_input = WoodenFishRunFinishInput { + run_id, + owner_user_id, + total_tap_count: payload.total_tap_count, + word_counters_json: json_string(&payload.word_counters)?, + client_event_id: payload.client_event_id, + finished_at_ms: current_unix_micros().div_euclid(1000), + }; + + self.call_after_connect("finish_wooden_fish_run", move |connection, sender| { + connection.procedures().finish_wooden_fish_run_then( + procedure_input, + move |_, result| { + let mapped = result + .map_err(SpacetimeClientError::from_sdk_error) + .and_then(map_wooden_fish_run_procedure_result); + send_once(&sender, mapped); + }, + ); + }) + .await + } + + pub async fn list_wooden_fish_gallery( + &self, + ) -> Result { + self.read_after_connect("list_wooden_fish_gallery", move |connection| { + let mut items = connection + .db() + .wooden_fish_gallery_card_view() + .iter() + .collect::>(); + items.sort_by(|left, right| { + right + .updated_at_micros + .cmp(&left.updated_at_micros) + .then_with(|| left.profile_id.cmp(&right.profile_id)) + }); + + Ok(WoodenFishGalleryResponse { + items: items + .into_iter() + .map(map_wooden_fish_gallery_card_view_row) + .collect(), + has_more: false, + next_cursor: None, + }) + }) + .await + } + + pub async fn get_wooden_fish_gallery_detail( + &self, + public_work_code: String, + ) -> Result { + let normalized_code = public_work_code.trim().to_string(); + if normalized_code.is_empty() { + return Err(SpacetimeClientError::validation_failed( + "wooden-fish public_work_code ä¸èƒ½ä¸ºç©º", + )); + } + + let profile_id = self + .read_after_connect("resolve_wooden_fish_gallery_detail", move |connection| { + connection + .db() + .wooden_fish_gallery_card_view() + .iter() + .find(|row| { + row.public_work_code.eq_ignore_ascii_case(&normalized_code) + || row.profile_id == normalized_code + }) + .map(|row| row.profile_id) + .ok_or_else(|| { + SpacetimeClientError::procedure_failed(Some( + "敲木鱼公开作å“ä¸å­˜åœ¨".to_string(), + )) + }) + }) + .await?; + + self.get_wooden_fish_work_profile(profile_id, String::new()) + .await + } +} + +enum WoodenFishActionProcedure { + Compile(WoodenFishDraftCompileInput), + Update(WoodenFishWorkUpdateInput), +} + +#[derive(Clone, Copy)] +enum WoodenFishDraftMergeScope { + CompileDraft, + RegenerateHitObject, + GenerateHitSound, + ReplaceHitSound, + UpdateWorkMeta, + UpdateFloatingWords, +} + +#[derive(Clone, Copy)] +enum WoodenFishAssetRefresh { + Preserve, + HitObject, + HitSound, +} + +fn build_wooden_fish_action_plan( + current: &WoodenFishSessionSnapshotResponse, + owner_user_id: &str, + payload: &WoodenFishActionRequest, + now_micros: i64, +) -> Result<(WoodenFishActionProcedure, WoodenFishDraftResponse), SpacetimeClientError> { + let scope = match payload.action_type { + WoodenFishActionType::CompileDraft => WoodenFishDraftMergeScope::CompileDraft, + WoodenFishActionType::RegenerateHitObject => WoodenFishDraftMergeScope::RegenerateHitObject, + WoodenFishActionType::GenerateHitSound => WoodenFishDraftMergeScope::GenerateHitSound, + WoodenFishActionType::ReplaceHitSound => WoodenFishDraftMergeScope::ReplaceHitSound, + WoodenFishActionType::UpdateWorkMeta => WoodenFishDraftMergeScope::UpdateWorkMeta, + WoodenFishActionType::UpdateFloatingWords => WoodenFishDraftMergeScope::UpdateFloatingWords, + }; + let mut draft = merge_action_into_draft(current.draft.clone(), payload, scope)?; + let profile_id = resolve_wooden_fish_profile_id( + &draft, + &payload.action_type, + payload.profile_id.as_deref(), + )?; + draft.profile_id = Some(profile_id.clone()); + + let procedure = match payload.action_type { + WoodenFishActionType::CompileDraft => { + WoodenFishActionProcedure::Compile(build_compile_input( + current, + owner_user_id, + &profile_id, + &mut draft, + WoodenFishAssetRefresh::Preserve, + now_micros, + )?) + } + WoodenFishActionType::RegenerateHitObject => { + WoodenFishActionProcedure::Compile(build_compile_input( + current, + owner_user_id, + &profile_id, + &mut draft, + WoodenFishAssetRefresh::HitObject, + now_micros, + )?) + } + WoodenFishActionType::GenerateHitSound => { + WoodenFishActionProcedure::Compile(build_compile_input( + current, + owner_user_id, + &profile_id, + &mut draft, + WoodenFishAssetRefresh::HitSound, + now_micros, + )?) + } + WoodenFishActionType::ReplaceHitSound => WoodenFishActionProcedure::Update( + build_update_input(owner_user_id, &profile_id, &draft, true, now_micros)?, + ), + WoodenFishActionType::UpdateWorkMeta | WoodenFishActionType::UpdateFloatingWords => { + WoodenFishActionProcedure::Update(build_update_input( + owner_user_id, + &profile_id, + &draft, + false, + now_micros, + )?) + } + }; + + Ok((procedure, draft)) +} + +fn merge_action_into_draft( + draft: Option, + payload: &WoodenFishActionRequest, + scope: WoodenFishDraftMergeScope, +) -> Result { + let mut draft = draft.unwrap_or_else(default_draft); + if matches!( + scope, + WoodenFishDraftMergeScope::CompileDraft | WoodenFishDraftMergeScope::UpdateWorkMeta + ) { + if let Some(value) = payload + .work_title + .as_ref() + .filter(|value| !value.trim().is_empty()) + { + draft.work_title = value.trim().to_string(); + } + if let Some(value) = payload.work_description.as_ref() { + draft.work_description = value.trim().to_string(); + } + if let Some(value) = payload.theme_tags.clone() { + draft.theme_tags = normalize_tags(value); + } + } + if matches!( + scope, + WoodenFishDraftMergeScope::CompileDraft | WoodenFishDraftMergeScope::RegenerateHitObject + ) { + if let Some(value) = payload + .hit_object_prompt + .as_ref() + .filter(|value| !value.trim().is_empty()) + { + draft.hit_object_prompt = value.trim().to_string(); + } + if payload.hit_object_reference_image_src.is_some() { + draft.hit_object_reference_image_src = payload + .hit_object_reference_image_src + .as_ref() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()); + } + if let Some(asset) = payload.hit_object_asset.clone() { + draft.hit_object_asset = Some(asset); + } + } + if matches!( + scope, + WoodenFishDraftMergeScope::CompileDraft + | WoodenFishDraftMergeScope::GenerateHitSound + | WoodenFishDraftMergeScope::ReplaceHitSound + ) { + if let Some(value) = payload + .hit_sound_prompt + .as_ref() + .filter(|value| !value.trim().is_empty()) + { + draft.hit_sound_prompt = Some(value.trim().to_string()); + } + } + if matches!(scope, WoodenFishDraftMergeScope::GenerateHitSound) { + draft.hit_sound_asset = payload.hit_sound_asset.clone(); + } else if matches!( + scope, + WoodenFishDraftMergeScope::CompileDraft | WoodenFishDraftMergeScope::ReplaceHitSound + ) && let Some(asset) = payload.hit_sound_asset.clone() + { + draft.hit_sound_asset = Some(asset); + } + if matches!( + scope, + WoodenFishDraftMergeScope::CompileDraft | WoodenFishDraftMergeScope::UpdateFloatingWords + ) && let Some(words) = payload.floating_words.clone() + { + draft.floating_words = normalize_floating_words(words); + } + if draft.work_title.trim().is_empty() { + return Err(SpacetimeClientError::validation_failed( + "wooden-fish work_title ä¸èƒ½ä¸ºç©º", + )); + } + if draft.hit_object_prompt.trim().is_empty() { + draft.hit_object_prompt = DEFAULT_HIT_OBJECT_PROMPT.to_string(); + } + if draft.hit_object_asset.is_some() + && matches!(scope, WoodenFishDraftMergeScope::RegenerateHitObject) + && payload.hit_object_asset.is_none() + { + draft.hit_object_asset = None; + } + if draft.floating_words.is_empty() { + draft.floating_words = default_floating_words(); + } + Ok(draft) +} + +fn build_compile_input( + current: &WoodenFishSessionSnapshotResponse, + owner_user_id: &str, + profile_id: &str, + draft: &mut WoodenFishDraftResponse, + refresh: WoodenFishAssetRefresh, + now_micros: i64, +) -> Result { + let _refresh = refresh; + let hit_object_asset = draft.hit_object_asset.clone().ok_or_else(|| { + SpacetimeClientError::validation_failed("wooden fish hit object asset 缺少真实生æˆèµ„产") + })?; + draft.hit_object_asset = Some(hit_object_asset); + draft.cover_image_src = draft + .hit_object_asset + .as_ref() + .map(|asset| asset.image_src.clone()); + draft.generation_status = WoodenFishGenerationStatus::Ready; + + let hit_object_asset = draft + .hit_object_asset + .clone() + .ok_or_else(|| SpacetimeClientError::missing_snapshot("wooden fish hit object asset"))?; + let hit_sound_asset = draft.hit_sound_asset.clone().ok_or_else(|| { + SpacetimeClientError::validation_failed("wooden fish hit sound asset 缺少真实生æˆèµ„产") + })?; + + Ok(WoodenFishDraftCompileInput { + session_id: current.session_id.clone(), + owner_user_id: owner_user_id.to_string(), + profile_id: profile_id.to_string(), + author_display_name: "敲木鱼玩家".to_string(), + work_title: draft.work_title.clone(), + work_description: draft.work_description.clone(), + theme_tags_json: Some(json_string(&draft.theme_tags)?), + hit_object_prompt: draft.hit_object_prompt.clone(), + hit_object_reference_image_src: draft.hit_object_reference_image_src.clone(), + hit_sound_prompt: draft.hit_sound_prompt.clone(), + hit_object_asset_json: Some(json_string(&hit_object_asset)?), + hit_sound_asset_json: Some(json_string(&hit_sound_asset)?), + floating_words_json: Some(json_string(&draft.floating_words)?), + cover_image_src: draft.cover_image_src.clone(), + generation_status: Some("ready".to_string()), + compiled_at_micros: now_micros, + }) +} + +fn build_update_input( + owner_user_id: &str, + profile_id: &str, + draft: &WoodenFishDraftResponse, + include_hit_sound_asset: bool, + now_micros: i64, +) -> Result { + Ok(WoodenFishWorkUpdateInput { + profile_id: profile_id.to_string(), + owner_user_id: owner_user_id.to_string(), + work_title: draft.work_title.clone(), + work_description: draft.work_description.clone(), + theme_tags_json: json_string(&draft.theme_tags)?, + hit_object_prompt: Some(draft.hit_object_prompt.clone()), + hit_object_reference_image_src: draft.hit_object_reference_image_src.clone(), + hit_sound_prompt: draft.hit_sound_prompt.clone(), + hit_object_asset_json: None, + hit_sound_asset_json: if include_hit_sound_asset { + draft + .hit_sound_asset + .as_ref() + .map(json_string) + .transpose()? + } else { + None + }, + floating_words_json: Some(json_string(&draft.floating_words)?), + cover_image_src: draft.cover_image_src.clone(), + generation_status: None, + updated_at_micros: now_micros, + }) +} + +fn resolve_wooden_fish_profile_id( + draft: &WoodenFishDraftResponse, + action_type: &WoodenFishActionType, + requested_profile_id: Option<&str>, +) -> Result { + if let Some(profile_id) = requested_profile_id + .map(str::trim) + .filter(|value| !value.is_empty()) + { + return Ok(profile_id.to_string()); + } + if let Some(profile_id) = draft + .profile_id + .as_ref() + .map(|value| value.trim()) + .filter(|value| !value.is_empty()) + { + return Ok(profile_id.to_string()); + } + if matches!(action_type, WoodenFishActionType::CompileDraft) { + return Ok(build_prefixed_uuid_id("wooden-fish-profile-")); + } + Err(SpacetimeClientError::validation_failed( + "wooden-fish action 需è¦å…ˆå®Œæˆ compile-draft", + )) +} + +fn apply_wooden_fish_work_to_session( + mut session: WoodenFishSessionSnapshotResponse, + work: &WoodenFishWorkProfileResponse, +) -> WoodenFishSessionSnapshotResponse { + session.status = work.draft.generation_status.clone(); + session.draft = Some(work.draft.clone()); + session.updated_at = work.summary.updated_at.clone(); + session +} + +fn default_draft() -> WoodenFishDraftResponse { + WoodenFishDraftResponse { + template_id: WOODEN_FISH_TEMPLATE_ID.to_string(), + template_name: WOODEN_FISH_TEMPLATE_NAME.to_string(), + profile_id: None, + work_title: WOODEN_FISH_TEMPLATE_NAME.to_string(), + work_description: String::new(), + theme_tags: vec!["休闲".to_string()], + hit_object_prompt: DEFAULT_HIT_OBJECT_PROMPT.to_string(), + hit_object_reference_image_src: None, + hit_sound_prompt: Some(DEFAULT_HIT_SOUND_PROMPT.to_string()), + floating_words: default_floating_words(), + hit_object_asset: None, + hit_sound_asset: None, + cover_image_src: None, + generation_status: WoodenFishGenerationStatus::Draft, + } +} + +fn build_config_json(draft: &WoodenFishDraftResponse) -> Result { + serde_json::to_string(&serde_json::json!({ + "workTitle": draft.work_title, + "workDescription": draft.work_description, + "themeTags": draft.theme_tags, + "hitObjectPrompt": draft.hit_object_prompt, + "hitObjectReferenceImageSrc": draft.hit_object_reference_image_src, + "hitSoundPrompt": draft.hit_sound_prompt, + "floatingWords": draft.floating_words, + })) + .map_err(SpacetimeClientError::validation_failed) +} + +fn normalize_tags(tags: Vec) -> Vec { + tags.into_iter() + .map(|tag| tag.trim().to_string()) + .filter(|tag| !tag.is_empty()) + .take(8) + .collect() +} + +fn default_floating_words() -> Vec { + vec![ + "幸è¿".to_string(), + "å¥åº·".to_string(), + "财富".to_string(), + "姻缘".to_string(), + "幸ç¦".to_string(), + "事业".to_string(), + "æˆåŠŸ".to_string(), + "功德".to_string(), + ] +} + +fn normalize_floating_words(words: Vec) -> Vec { + let mut normalized = Vec::new(); + for word in words { + let word = normalize_floating_word(&word); + if word.is_empty() || normalized.iter().any(|item| item == &word) { + continue; + } + normalized.push(word); + if normalized.len() >= 8 { + break; + } + } + if normalized.is_empty() { + default_floating_words() + } else { + normalized + } +} + +fn normalize_floating_word(word: &str) -> String { + word.trim() + .trim_end_matches(|ch: char| ch == '1' || ch.is_whitespace()) + .trim_end_matches(['+', '+']) + .trim() + .to_string() +} + +fn json_string(value: &T) -> Result { + serde_json::to_string(value).map_err(SpacetimeClientError::validation_failed) +} + +#[cfg(test)] +mod tests { + use super::*; + use shared_contracts::wooden_fish::WoodenFishAudioAsset; + + const SESSION_ID: &str = "wooden-fish-session-test"; + const OWNER_USER_ID: &str = "user-test"; + const PROFILE_ID: &str = "wooden-fish-profile-test"; + const NOW_MICROS: i64 = 1_763_456_789_000_000; + + #[test] + fn wooden_fish_action_compile_draft_builds_compile_input_with_assets() { + let session = session_with_draft(draft_without_assets()); + let mut payload = action(WoodenFishActionType::CompileDraft); + payload.hit_object_asset = Some(generated_hit_object_asset("generated-compile-object")); + payload.hit_sound_asset = Some(generated_hit_sound_asset("generated-compile-sound")); + + let (plan, draft) = + build_wooden_fish_action_plan(&session, OWNER_USER_ID, &payload, NOW_MICROS) + .expect("compile-draft should build plan"); + + let WoodenFishActionProcedure::Compile(input) = plan else { + panic!("compile-draft should call compile_wooden_fish_draft"); + }; + assert_eq!(input.session_id, SESSION_ID); + assert_eq!(input.owner_user_id, OWNER_USER_ID); + assert_eq!(input.generation_status.as_deref(), Some("ready")); + assert!( + input + .hit_object_asset_json + .as_deref() + .unwrap_or("") + .contains("generated-compile-object") + ); + assert!( + input + .hit_sound_asset_json + .as_deref() + .unwrap_or("") + .contains("generated-compile-sound") + ); + assert_eq!(draft.generation_status, WoodenFishGenerationStatus::Ready); + } + + #[test] + fn wooden_fish_compile_requires_real_hit_sound_asset_from_api_server() { + let session = session_with_draft(draft_without_assets()); + let mut payload = action(WoodenFishActionType::CompileDraft); + payload.hit_object_asset = Some(generated_hit_object_asset("generated-compile-object")); + + let error = + match build_wooden_fish_action_plan(&session, OWNER_USER_ID, &payload, NOW_MICROS) { + Ok(_) => panic!("compile-draft should not synthesize fake hit sound assets"), + Err(error) => error, + }; + + assert!( + error + .to_string() + .contains("hit sound asset 缺少真实生æˆèµ„产") + ); + } + + #[test] + fn wooden_fish_action_regenerate_hit_object_replaces_only_object_asset() { + let session = session_with_draft(draft_with_assets()); + let mut payload = action(WoodenFishActionType::RegenerateHitObject); + payload.hit_object_prompt = Some("新的敲击物".to_string()); + payload.hit_object_asset = Some(generated_hit_object_asset("generated-object")); + + let (plan, _draft) = + build_wooden_fish_action_plan(&session, OWNER_USER_ID, &payload, NOW_MICROS) + .expect("regenerate-hit-object should build plan"); + + let WoodenFishActionProcedure::Compile(input) = plan else { + panic!("regenerate-hit-object should call compile_wooden_fish_draft"); + }; + assert!( + !input + .hit_object_asset_json + .as_deref() + .unwrap_or("") + .contains("old-object") + ); + assert!( + input + .hit_object_asset_json + .as_deref() + .unwrap_or("") + .contains("real-profile") + ); + assert!( + !input + .hit_object_asset_json + .as_deref() + .unwrap_or("") + .contains(&NOW_MICROS.to_string()) + ); + assert!( + input + .hit_sound_asset_json + .as_deref() + .unwrap_or("") + .contains("old-sound") + ); + } + + #[test] + fn wooden_fish_action_update_floating_words_builds_update_input() { + let session = session_with_draft(draft_with_assets()); + let mut payload = action(WoodenFishActionType::UpdateFloatingWords); + payload.floating_words = Some(vec![ + " 功德+1 ".to_string(), + "功德+1".to_string(), + "å¥åº·+1".to_string(), + ]); + + let (plan, draft) = + build_wooden_fish_action_plan(&session, OWNER_USER_ID, &payload, NOW_MICROS) + .expect("update-floating-words should build plan"); + + let WoodenFishActionProcedure::Update(input) = plan else { + panic!("update-floating-words should call update_wooden_fish_work"); + }; + assert_eq!(input.profile_id, PROFILE_ID); + assert!(input.hit_sound_asset_json.is_none()); + assert_eq!( + draft.floating_words, + vec!["功德".to_string(), "å¥åº·".to_string()] + ); + assert!( + input + .floating_words_json + .as_deref() + .unwrap_or("") + .contains("å¥åº·") + ); + } + + fn action(action_type: WoodenFishActionType) -> WoodenFishActionRequest { + WoodenFishActionRequest { + action_type, + profile_id: None, + work_title: None, + work_description: None, + theme_tags: None, + hit_object_prompt: None, + hit_object_reference_image_src: None, + hit_object_asset: None, + hit_sound_prompt: None, + hit_sound_asset: None, + floating_words: None, + } + } + + fn session_with_draft(draft: WoodenFishDraftResponse) -> WoodenFishSessionSnapshotResponse { + WoodenFishSessionSnapshotResponse { + session_id: SESSION_ID.to_string(), + owner_user_id: OWNER_USER_ID.to_string(), + status: draft.generation_status.clone(), + draft: Some(draft), + created_at: "2026-05-20T00:00:00Z".to_string(), + updated_at: "2026-05-20T00:00:00Z".to_string(), + } + } + + fn draft_without_assets() -> WoodenFishDraftResponse { + WoodenFishDraftResponse { + profile_id: None, + ..base_draft() + } + } + + fn generated_hit_object_asset(asset_id: &str) -> WoodenFishImageAsset { + WoodenFishImageAsset { + asset_id: asset_id.to_string(), + image_src: "/generated-wooden-fish-assets/real-profile/hit-object/image.png" + .to_string(), + image_object_key: "generated-wooden-fish-assets/real-profile/hit-object/image.png" + .to_string(), + asset_object_id: format!("{asset_id}-asset"), + generation_provider: "image2".to_string(), + prompt: "新的敲击物".to_string(), + width: 1024, + height: 1024, + } + } + + fn generated_hit_sound_asset(asset_id: &str) -> WoodenFishAudioAsset { + WoodenFishAudioAsset { + asset_id: asset_id.to_string(), + audio_src: "/generated-wooden-fish-assets/real-profile/hit-sound/sound.mp3".to_string(), + audio_object_key: "generated-wooden-fish-assets/real-profile/hit-sound/sound.mp3" + .to_string(), + asset_object_id: format!("{asset_id}-asset"), + source: "generated".to_string(), + prompt: Some("新的木鱼音效".to_string()), + duration_ms: Some(3000), + } + } + + fn draft_with_assets() -> WoodenFishDraftResponse { + WoodenFishDraftResponse { + profile_id: Some(PROFILE_ID.to_string()), + hit_object_asset: Some(WoodenFishImageAsset { + asset_id: "old-object".to_string(), + image_src: "/generated-wooden-fish-assets/old-object.png".to_string(), + image_object_key: "generated-wooden-fish-assets/old-object.png".to_string(), + asset_object_id: "old-object-asset".to_string(), + generation_provider: "image2".to_string(), + prompt: "旧敲击物".to_string(), + width: 1024, + height: 1024, + }), + hit_sound_asset: Some(WoodenFishAudioAsset { + asset_id: "old-sound".to_string(), + audio_src: "/generated-wooden-fish-assets/old-sound.mp3".to_string(), + audio_object_key: "generated-wooden-fish-assets/old-sound.mp3".to_string(), + asset_object_id: "old-sound-asset".to_string(), + source: "generated".to_string(), + prompt: Some("旧音效".to_string()), + duration_ms: Some(700), + }), + cover_image_src: Some("/generated-wooden-fish-assets/old-object.png".to_string()), + generation_status: WoodenFishGenerationStatus::Ready, + ..base_draft() + } + } + + fn base_draft() -> WoodenFishDraftResponse { + WoodenFishDraftResponse { + template_id: WOODEN_FISH_TEMPLATE_ID.to_string(), + template_name: WOODEN_FISH_TEMPLATE_NAME.to_string(), + profile_id: None, + work_title: "旧标题".to_string(), + work_description: "æ—§æè¿°".to_string(), + theme_tags: vec!["旧标签".to_string()], + hit_object_prompt: "旧敲击物".to_string(), + hit_object_reference_image_src: None, + hit_sound_prompt: Some("旧音效".to_string()), + floating_words: default_floating_words(), + hit_object_asset: None, + hit_sound_asset: None, + cover_image_src: None, + generation_status: WoodenFishGenerationStatus::Draft, + } + } +} diff --git a/server-rs/crates/spacetime-module/Cargo.toml b/server-rs/crates/spacetime-module/Cargo.toml index 16ff92e2..a418c2ad 100644 --- a/server-rs/crates/spacetime-module/Cargo.toml +++ b/server-rs/crates/spacetime-module/Cargo.toml @@ -19,6 +19,7 @@ module-combat = { workspace = true, features = ["spacetime-types"] } module-inventory = { workspace = true, features = ["spacetime-types"] } module-custom-world = { workspace = true, features = ["spacetime-types"] } module-jump-hop = { workspace = true, features = ["spacetime-types"] } +module-wooden-fish = { workspace = true, features = ["spacetime-types"] } module-match3d = { workspace = true } module-npc = { workspace = true, features = ["spacetime-types"] } module-puzzle = { workspace = true, features = ["spacetime-types"] } diff --git a/server-rs/crates/spacetime-module/src/lib.rs b/server-rs/crates/spacetime-module/src/lib.rs index b89390a4..adaeb114 100644 --- a/server-rs/crates/spacetime-module/src/lib.rs +++ b/server-rs/crates/spacetime-module/src/lib.rs @@ -1,4 +1,4 @@ -// 中文注释:SpacetimeDB 绑定生æˆä¾èµ–根模å—继续公开 re-export å„领域类型; +// 中文注释:SpacetimeDB 绑定生æˆä¾èµ–根模å—继续公开 re-export å„领域类型; // 少数领域 helper åŒååªå½±å“ value namespace 导出,ä¸å½±å“ table / reducer 类型。 #![allow(ambiguous_glob_reexports)] @@ -15,6 +15,7 @@ pub use module_quest::*; pub use module_runtime::*; pub use module_runtime_item::*; pub use module_story::*; +pub use module_wooden_fish::*; pub(crate) use serde_json::{Map as JsonMap, Value as JsonValue, json}; pub(crate) use shared_kernel::format_timestamp_micros; @@ -37,6 +38,7 @@ mod puzzle; mod runtime; mod square_hole; mod visual_novel; +mod wooden_fish; pub use ai::*; pub use asset_metadata::*; @@ -53,3 +55,4 @@ pub use migration::*; pub use runtime::*; pub use square_hole::*; pub use visual_novel::*; +pub use wooden_fish::*; diff --git a/server-rs/crates/spacetime-module/src/migration.rs b/server-rs/crates/spacetime-module/src/migration.rs index d12566c6..4b630149 100644 --- a/server-rs/crates/spacetime-module/src/migration.rs +++ b/server-rs/crates/spacetime-module/src/migration.rs @@ -26,6 +26,9 @@ use crate::square_hole::tables::{ square_hole_agent_message, square_hole_agent_session, square_hole_runtime_run, square_hole_work_profile, }; +use crate::wooden_fish::tables::{ + wooden_fish_agent_session, wooden_fish_event, wooden_fish_runtime_run, wooden_fish_work_profile, +}; use crate::{ visual_novel_agent_message, visual_novel_agent_session, visual_novel_runtime_event, visual_novel_runtime_history_entry, visual_novel_runtime_run, visual_novel_work_profile, @@ -241,6 +244,10 @@ macro_rules! migration_tables { jump_hop_work_profile, jump_hop_runtime_run, jump_hop_event, + wooden_fish_agent_session, + wooden_fish_work_profile, + wooden_fish_runtime_run, + wooden_fish_event, square_hole_agent_session, square_hole_agent_message, square_hole_work_profile, diff --git a/server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs b/server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs index 77ed87e7..d754501d 100644 --- a/server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs +++ b/server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs @@ -192,6 +192,7 @@ fn seed_creation_entry_config_if_missing(ctx: &ReducerContext) { }, ); migrate_baby_object_match_entry_from_old_coming_soon_default(ctx, now); + migrate_wooden_fish_entry_from_old_puzzle_image_default(ctx, now); } fn migrate_visual_novel_entry_from_old_visible_default(ctx: &ReducerContext, now: Timestamp) { @@ -296,6 +297,34 @@ fn migrate_baby_object_match_entry_from_old_coming_soon_default( }); } +fn migrate_wooden_fish_entry_from_old_puzzle_image_default(ctx: &ReducerContext, now: Timestamp) { + let id = "wooden-fish".to_string(); + let Some(row) = ctx.db.creation_entry_type_config().id().find(&id) else { + return; + }; + + // ä¸­æ–‡æ³¨é‡Šï¼šåªæ›¿æ¢æ•²æœ¨é±¼æ—§é»˜è®¤å…¥å£å›¾ï¼Œä¸è¦†ç›–åŽå°æ‰‹åŠ¨è®¾ç½®è¿‡çš„å…¶å®ƒå±•ç¤ºä¿¡æ¯ã€‚ + let still_old_puzzle_image_default = row.title == "敲木鱼" + && row.subtitle == "点击祈ç¦è½»çŽ©æ³•" + && row.badge == "å¯åˆ›å»º" + && row.image_src == "/creation-type-references/puzzle.webp" + && row.visible + && row.open + && row.sort_order == 47; + if !still_old_puzzle_image_default { + return; + } + + ctx.db + .creation_entry_type_config() + .id() + .update(CreationEntryTypeConfig { + image_src: "/wooden-fish/default-hit-object.png".to_string(), + updated_at: now, + ..row + }); +} + fn default_creation_entry_type_configs(now: Timestamp) -> Vec { module_runtime::default_creation_entry_type_snapshots(now.to_micros_since_unix_epoch()) .into_iter() diff --git a/server-rs/crates/spacetime-module/src/wooden_fish.rs b/server-rs/crates/spacetime-module/src/wooden_fish.rs new file mode 100644 index 00000000..7808ce6a --- /dev/null +++ b/server-rs/crates/spacetime-module/src/wooden_fish.rs @@ -0,0 +1,1228 @@ +pub(crate) mod tables; +mod types; + +pub use tables::*; +pub use types::*; + +use crate::{ProcedureContext, ReducerContext, SpacetimeType, Table, Timestamp}; +use module_wooden_fish::{ + WoodenFishRunSnapshot, WoodenFishRunStatus, WoodenFishWordCounter, apply_run_checkpoint, + default_floating_words, finish_run, normalize_floating_words, normalize_word_counters, +}; +use serde::Serialize; +use serde::de::DeserializeOwned; +use spacetimedb::AnonymousViewContext; + +#[spacetimedb::view(accessor = wooden_fish_gallery_view, public)] +pub fn wooden_fish_gallery_view(ctx: &AnonymousViewContext) -> Vec { + let mut items = ctx + .db + .wooden_fish_work_profile() + .by_wooden_fish_work_publication_status() + .filter(WOODEN_FISH_PUBLICATION_PUBLISHED) + .filter_map(|row| match build_gallery_view_row(&row) { + Ok(item) => Some(item), + Err(error) => { + log::warn!( + "敲木鱼公开广场 view 跳过æŸåçš„ä½œå“æŠ•å½± profile_id={}: {}", + row.profile_id, + error + ); + None + } + }) + .collect::>(); + items.sort_by(|left, right| { + right + .updated_at_micros + .cmp(&left.updated_at_micros) + .then_with(|| left.profile_id.cmp(&right.profile_id)) + }); + items +} + +#[spacetimedb::view(accessor = wooden_fish_gallery_card_view, public)] +pub fn wooden_fish_gallery_card_view( + ctx: &AnonymousViewContext, +) -> Vec { + wooden_fish_gallery_view(ctx) + .into_iter() + .map(|row| WoodenFishGalleryCardViewRow { + public_work_code: row.public_work_code, + work_id: row.work_id, + profile_id: row.profile_id, + owner_user_id: row.owner_user_id, + author_display_name: row.author_display_name, + work_title: row.work_title, + work_description: row.work_description, + cover_image_src: row.cover_image_src, + theme_tags: row.theme_tags, + publication_status: row.publication_status, + play_count: row.play_count, + updated_at_micros: row.updated_at_micros, + published_at_micros: row.published_at_micros, + generation_status: row.generation_status, + }) + .collect() +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishGalleryViewRow { + pub public_work_code: String, + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub source_session_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset: Option, + pub hit_sound_asset: Option, + pub floating_words: Vec, + pub cover_image_src: String, + pub publication_status: String, + pub publish_ready: bool, + pub play_count: u32, + pub generation_status: String, + pub updated_at_micros: i64, + pub published_at_micros: Option, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishGalleryCardViewRow { + pub public_work_code: String, + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub cover_image_src: String, + pub theme_tags: Vec, + pub publication_status: String, + pub play_count: u32, + pub updated_at_micros: i64, + pub published_at_micros: Option, + pub generation_status: String, +} + +#[spacetimedb::procedure] +pub fn create_wooden_fish_agent_session( + ctx: &mut ProcedureContext, + input: WoodenFishAgentSessionCreateInput, +) -> WoodenFishAgentSessionProcedureResult { + match ctx.try_with_tx(|tx| create_wooden_fish_agent_session_tx(tx, input.clone())) { + Ok(session) => session_result(session), + Err(message) => session_error(message), + } +} + +#[spacetimedb::procedure] +pub fn get_wooden_fish_agent_session( + ctx: &mut ProcedureContext, + input: WoodenFishAgentSessionGetInput, +) -> WoodenFishAgentSessionProcedureResult { + match ctx.try_with_tx(|tx| get_wooden_fish_agent_session_tx(tx, input.clone())) { + Ok(session) => session_result(session), + Err(message) => session_error(message), + } +} + +#[spacetimedb::procedure] +pub fn compile_wooden_fish_draft( + ctx: &mut ProcedureContext, + input: WoodenFishDraftCompileInput, +) -> WoodenFishAgentSessionProcedureResult { + match ctx.try_with_tx(|tx| compile_wooden_fish_draft_tx(tx, input.clone())) { + Ok(session) => session_result(session), + Err(message) => session_error(message), + } +} + +#[spacetimedb::procedure] +pub fn get_wooden_fish_work_profile( + ctx: &mut ProcedureContext, + input: WoodenFishWorkGetInput, +) -> WoodenFishWorkProcedureResult { + match ctx.try_with_tx(|tx| get_wooden_fish_work_profile_tx(tx, input.clone())) { + Ok(work) => work_result(work), + Err(message) => work_error(message), + } +} + +#[spacetimedb::procedure] +pub fn update_wooden_fish_work( + ctx: &mut ProcedureContext, + input: WoodenFishWorkUpdateInput, +) -> WoodenFishWorkProcedureResult { + match ctx.try_with_tx(|tx| update_wooden_fish_work_tx(tx, input.clone())) { + Ok(work) => work_result(work), + Err(message) => work_error(message), + } +} + +#[spacetimedb::procedure] +pub fn publish_wooden_fish_work( + ctx: &mut ProcedureContext, + input: WoodenFishWorkPublishInput, +) -> WoodenFishWorkProcedureResult { + match ctx.try_with_tx(|tx| publish_wooden_fish_work_tx(tx, input.clone())) { + Ok(work) => work_result(work), + Err(message) => work_error(message), + } +} + +#[spacetimedb::procedure] +pub fn list_wooden_fish_works( + ctx: &mut ProcedureContext, + input: WoodenFishWorksListInput, +) -> WoodenFishWorksProcedureResult { + match ctx.try_with_tx(|tx| list_wooden_fish_works_tx(tx, input.clone())) { + Ok(items) => WoodenFishWorksProcedureResult { + ok: true, + items, + error_message: None, + }, + Err(message) => WoodenFishWorksProcedureResult { + ok: false, + items: Vec::new(), + error_message: Some(message), + }, + } +} + +#[spacetimedb::procedure] +pub fn start_wooden_fish_run( + ctx: &mut ProcedureContext, + input: WoodenFishRunStartInput, +) -> WoodenFishRunProcedureResult { + match ctx.try_with_tx(|tx| start_wooden_fish_run_tx(tx, input.clone())) { + Ok(run) => run_result(run), + Err(message) => run_error(message), + } +} + +#[spacetimedb::procedure] +pub fn get_wooden_fish_run( + ctx: &mut ProcedureContext, + input: WoodenFishRunGetInput, +) -> WoodenFishRunProcedureResult { + match ctx.try_with_tx(|tx| get_wooden_fish_run_tx(tx, input.clone())) { + Ok(run) => run_result(run), + Err(message) => run_error(message), + } +} + +#[spacetimedb::procedure] +pub fn checkpoint_wooden_fish_run( + ctx: &mut ProcedureContext, + input: WoodenFishRunCheckpointInput, +) -> WoodenFishRunProcedureResult { + match ctx.try_with_tx(|tx| checkpoint_wooden_fish_run_tx(tx, input.clone())) { + Ok(run) => run_result(run), + Err(message) => run_error(message), + } +} + +#[spacetimedb::procedure] +pub fn finish_wooden_fish_run( + ctx: &mut ProcedureContext, + input: WoodenFishRunFinishInput, +) -> WoodenFishRunProcedureResult { + match ctx.try_with_tx(|tx| finish_wooden_fish_run_tx(tx, input.clone())) { + Ok(run) => run_result(run), + Err(message) => run_error(message), + } +} + +fn create_wooden_fish_agent_session_tx( + ctx: &ReducerContext, + input: WoodenFishAgentSessionCreateInput, +) -> Result { + require_non_empty(&input.session_id, "wooden_fish session_id")?; + require_non_empty(&input.owner_user_id, "wooden_fish owner_user_id")?; + if ctx + .db + .wooden_fish_agent_session() + .session_id() + .find(&input.session_id) + .is_some() + { + return Err("wooden_fish_agent_session.session_id 已存在".to_string()); + } + + let created_at = Timestamp::from_micros_since_unix_epoch(input.created_at_micros); + let config = input + .config_json + .as_deref() + .map(parse_config) + .transpose()? + .unwrap_or_else(|| default_config_from_input(&input)); + let draft = input + .draft_json + .as_deref() + .map(parse_json) + .transpose()? + .unwrap_or_else(|| draft_from_config(&config, None, WOODEN_FISH_GENERATION_DRAFT)); + + ctx.db + .wooden_fish_agent_session() + .insert(WoodenFishAgentSessionRow { + session_id: input.session_id.clone(), + owner_user_id: input.owner_user_id.clone(), + current_turn: 0, + progress_percent: 0, + stage: WOODEN_FISH_STAGE_COLLECTING.to_string(), + config_json: to_json_string(&config), + draft_json: to_json_string(&draft), + published_profile_id: String::new(), + created_at, + updated_at: created_at, + }); + + get_wooden_fish_agent_session_tx( + ctx, + WoodenFishAgentSessionGetInput { + session_id: input.session_id, + owner_user_id: input.owner_user_id, + }, + ) +} + +fn get_wooden_fish_agent_session_tx( + ctx: &ReducerContext, + input: WoodenFishAgentSessionGetInput, +) -> Result { + let row = find_owned_session(ctx, &input.session_id, &input.owner_user_id)?; + build_session_snapshot(&row) +} + +fn compile_wooden_fish_draft_tx( + ctx: &ReducerContext, + input: WoodenFishDraftCompileInput, +) -> Result { + require_non_empty(&input.profile_id, "wooden_fish profile_id")?; + let session = find_owned_session(ctx, &input.session_id, &input.owner_user_id)?; + let tags = parse_tags(input.theme_tags_json.as_deref().unwrap_or("[]"))?; + let floating_words = match input + .floating_words_json + .as_deref() + .map(parse_json::>) + .transpose()? + { + Some(words) => normalize_floating_words(&words), + None => default_floating_words(), + }; + let hit_object_asset = input + .hit_object_asset_json + .as_deref() + .map(parse_json) + .transpose()?; + let hit_sound_asset = input + .hit_sound_asset_json + .as_deref() + .map(parse_json) + .transpose()?; + let cover_image_src = input + .cover_image_src + .as_deref() + .and_then(clean_optional) + .or_else(|| { + hit_object_asset + .as_ref() + .map(|asset: &WoodenFishImageAssetSnapshot| asset.image_src.clone()) + }); + let draft = WoodenFishDraftSnapshot { + template_id: WOODEN_FISH_TEMPLATE_ID.to_string(), + template_name: WOODEN_FISH_TEMPLATE_NAME.to_string(), + profile_id: Some(input.profile_id.clone()), + work_title: clean_string(&input.work_title, WOODEN_FISH_TEMPLATE_NAME), + work_description: input.work_description.trim().to_string(), + theme_tags: tags.clone(), + hit_object_prompt: clean_string( + &input.hit_object_prompt, + "é»˜è®¤æ•²å‡»ç‰©å›¾æ¡ˆï¼Œåœ†æ¶¦æœ¨è´¨è´¨æ„Ÿï¼Œé€æ˜ŽèƒŒæ™¯", + ), + hit_object_reference_image_src: input + .hit_object_reference_image_src + .as_deref() + .and_then(clean_optional), + hit_sound_prompt: input.hit_sound_prompt.as_deref().and_then(clean_optional), + floating_words: floating_words.clone(), + hit_object_asset: hit_object_asset.clone(), + hit_sound_asset: hit_sound_asset.clone(), + cover_image_src: cover_image_src.clone(), + generation_status: input + .generation_status + .clone() + .unwrap_or_else(|| WOODEN_FISH_GENERATION_READY.to_string()), + }; + let compiled_at = Timestamp::from_micros_since_unix_epoch(input.compiled_at_micros); + let row = WoodenFishWorkProfileRow { + profile_id: input.profile_id.clone(), + work_id: input.profile_id.clone(), + owner_user_id: input.owner_user_id.clone(), + source_session_id: input.session_id.clone(), + author_display_name: clean_string(&input.author_display_name, "敲木鱼玩家"), + work_title: draft.work_title.clone(), + work_description: draft.work_description.clone(), + theme_tags_json: to_json_string(&tags), + hit_object_prompt: draft.hit_object_prompt.clone(), + hit_object_reference_image_src: draft + .hit_object_reference_image_src + .clone() + .unwrap_or_default(), + hit_sound_prompt: draft.hit_sound_prompt.clone().unwrap_or_default(), + hit_object_asset_json: hit_object_asset + .as_ref() + .map(to_json_string) + .unwrap_or_default(), + hit_sound_asset_json: hit_sound_asset + .as_ref() + .map(to_json_string) + .unwrap_or_default(), + floating_words_json: to_json_string(&floating_words), + cover_image_src: cover_image_src.unwrap_or_default(), + generation_status: draft.generation_status.clone(), + publication_status: WOODEN_FISH_PUBLICATION_DRAFT.to_string(), + play_count: 0, + updated_at: compiled_at, + published_at: None, + }; + upsert_work(ctx, row); + let config = config_from_draft(&draft); + replace_session( + ctx, + &session, + WoodenFishAgentSessionRow { + progress_percent: 100, + stage: WOODEN_FISH_STAGE_DRAFT_COMPILED.to_string(), + config_json: to_json_string(&config), + draft_json: to_json_string(&draft), + published_profile_id: input.profile_id, + updated_at: compiled_at, + ..clone_session(&session) + }, + ); + + get_wooden_fish_agent_session_tx( + ctx, + WoodenFishAgentSessionGetInput { + session_id: input.session_id, + owner_user_id: input.owner_user_id, + }, + ) +} + +fn get_wooden_fish_work_profile_tx( + ctx: &ReducerContext, + input: WoodenFishWorkGetInput, +) -> Result { + let row = find_work(ctx, &input.profile_id)?; + if !input.owner_user_id.trim().is_empty() && row.owner_user_id != input.owner_user_id { + return Err("æ— æƒè®¿é—®è¯¥ wooden_fish work".to_string()); + } + build_work_snapshot(&row) +} + +fn update_wooden_fish_work_tx( + ctx: &ReducerContext, + input: WoodenFishWorkUpdateInput, +) -> Result { + let row = find_owned_work(ctx, &input.profile_id, &input.owner_user_id)?; + let updated_at = Timestamp::from_micros_since_unix_epoch(input.updated_at_micros); + let mut next = clone_work(&row); + next.work_title = clean_string(&input.work_title, &row.work_title); + next.work_description = input.work_description.trim().to_string(); + next.theme_tags_json = input.theme_tags_json.clone(); + if let Some(value) = input.hit_object_prompt.as_deref().and_then(clean_optional) { + next.hit_object_prompt = value; + } + if let Some(value) = input + .hit_object_reference_image_src + .as_deref() + .and_then(clean_optional) + { + next.hit_object_reference_image_src = value; + } + if let Some(value) = input.hit_sound_prompt.as_deref().and_then(clean_optional) { + next.hit_sound_prompt = value; + } + if let Some(value) = input + .hit_object_asset_json + .as_deref() + .and_then(clean_optional) + { + let asset = parse_json::(&value)?; + next.hit_object_asset_json = to_json_string(&asset); + next.cover_image_src = asset.image_src; + } + if let Some(value) = input + .hit_sound_asset_json + .as_deref() + .and_then(clean_optional) + { + let asset = parse_json::(&value)?; + next.hit_sound_asset_json = to_json_string(&asset); + } + if let Some(value) = input + .floating_words_json + .as_deref() + .and_then(clean_optional) + { + let words = parse_json::>(&value)?; + next.floating_words_json = to_json_string(&normalize_floating_words(&words)); + } + if let Some(value) = input.cover_image_src.as_deref().and_then(clean_optional) { + next.cover_image_src = value; + } + if let Some(value) = input.generation_status.as_deref().and_then(clean_optional) { + next.generation_status = value; + } + next.updated_at = updated_at; + replace_work(ctx, &row, next); + let updated = find_work(ctx, &row.profile_id)?; + sync_session_from_work_update(ctx, &updated, updated_at)?; + build_work_snapshot(&updated) +} + +fn publish_wooden_fish_work_tx( + ctx: &ReducerContext, + input: WoodenFishWorkPublishInput, +) -> Result { + let row = find_owned_work(ctx, &input.profile_id, &input.owner_user_id)?; + if !is_publish_ready(&row) { + return Err("å‘布需è¦å®Œæ•´çš„æ•²å‡»ç‰©å›¾æ¡ˆã€æ•²å‡»éŸ³æ•ˆå’Œé£˜å­—é…ç½®".to_string()); + } + let published_at = Timestamp::from_micros_since_unix_epoch(input.published_at_micros); + replace_work( + ctx, + &row, + WoodenFishWorkProfileRow { + publication_status: WOODEN_FISH_PUBLICATION_PUBLISHED.to_string(), + updated_at: published_at, + published_at: Some(published_at), + ..clone_work(&row) + }, + ); + if let Some(session) = ctx + .db + .wooden_fish_agent_session() + .session_id() + .find(&row.source_session_id) + { + replace_session( + ctx, + &session, + WoodenFishAgentSessionRow { + stage: WOODEN_FISH_STAGE_PUBLISHED.to_string(), + updated_at: published_at, + ..clone_session(&session) + }, + ); + } + let updated = find_work(ctx, &row.profile_id)?; + build_work_snapshot(&updated) +} + +fn list_wooden_fish_works_tx( + ctx: &ReducerContext, + input: WoodenFishWorksListInput, +) -> Result, String> { + let mut rows = if input.owner_user_id.trim().is_empty() { + ctx.db.wooden_fish_work_profile().iter().collect::>() + } else { + ctx.db + .wooden_fish_work_profile() + .by_wooden_fish_work_owner_user_id() + .filter(input.owner_user_id.as_str()) + .collect::>() + }; + if input.published_only { + rows.retain(|row| row.publication_status == WOODEN_FISH_PUBLICATION_PUBLISHED); + } + rows.sort_by(|left, right| { + right + .updated_at + .cmp(&left.updated_at) + .then_with(|| left.profile_id.cmp(&right.profile_id)) + }); + rows.into_iter() + .map(|row| build_work_snapshot(&row)) + .collect() +} + +fn start_wooden_fish_run_tx( + ctx: &ReducerContext, + input: WoodenFishRunStartInput, +) -> Result { + require_non_empty(&input.run_id, "wooden_fish run_id")?; + let work = find_work(ctx, &input.profile_id)?; + if !is_publish_ready(&work) { + return Err("敲木鱼è¿è¡Œæ€éœ€è¦å®Œæ•´ä½œå“é…ç½®".to_string()); + } + let snapshot = WoodenFishRunSnapshot { + run_id: input.run_id.clone(), + profile_id: input.profile_id.clone(), + owner_user_id: input.owner_user_id.clone(), + status: WoodenFishRunStatus::Playing, + total_tap_count: 0, + word_counters: Vec::new(), + started_at_ms: input.started_at_ms.max(0) as u64, + updated_at_ms: input.started_at_ms.max(0) as u64, + finished_at_ms: None, + }; + upsert_run(ctx, &snapshot, input.started_at_ms); + increment_work_play_count(ctx, &work, input.started_at_ms); + insert_event( + ctx, + input.client_event_id, + input.owner_user_id, + input.profile_id, + input.run_id, + WOODEN_FISH_EVENT_RUN_STARTED, + None, + input.started_at_ms, + ); + Ok(snapshot) +} + +fn get_wooden_fish_run_tx( + ctx: &ReducerContext, + input: WoodenFishRunGetInput, +) -> Result { + let row = find_owned_run(ctx, &input.run_id, &input.owner_user_id)?; + parse_json(&row.snapshot_json) +} + +fn checkpoint_wooden_fish_run_tx( + ctx: &ReducerContext, + input: WoodenFishRunCheckpointInput, +) -> Result { + let row = find_owned_run(ctx, &input.run_id, &input.owner_user_id)?; + let current = parse_json::(&row.snapshot_json)?; + if current.status == WoodenFishRunStatus::Finished { + return Err("wooden_fish run 已结æŸï¼Œä¸èƒ½ checkpoint".to_string()); + } + let counters = parse_json::>(&input.word_counters_json)?; + let next = apply_run_checkpoint( + ¤t, + input.total_tap_count, + normalize_word_counters(counters), + input.checkpoint_at_ms.max(0) as u64, + ); + replace_run(ctx, &row, &next, input.checkpoint_at_ms); + insert_event( + ctx, + input.client_event_id, + input.owner_user_id, + next.profile_id.clone(), + input.run_id, + WOODEN_FISH_EVENT_RUN_CHECKPOINT, + Some(next.total_tap_count.to_string()), + input.checkpoint_at_ms, + ); + Ok(next) +} + +fn finish_wooden_fish_run_tx( + ctx: &ReducerContext, + input: WoodenFishRunFinishInput, +) -> Result { + let row = find_owned_run(ctx, &input.run_id, &input.owner_user_id)?; + let current = parse_json::(&row.snapshot_json)?; + let counters = parse_json::>(&input.word_counters_json)?; + let next = finish_run( + ¤t, + input.total_tap_count, + normalize_word_counters(counters), + input.finished_at_ms.max(0) as u64, + ); + replace_run(ctx, &row, &next, input.finished_at_ms); + insert_event( + ctx, + input.client_event_id, + input.owner_user_id, + next.profile_id.clone(), + input.run_id, + WOODEN_FISH_EVENT_RUN_FINISHED, + Some(next.total_tap_count.to_string()), + input.finished_at_ms, + ); + Ok(next) +} + +fn build_gallery_view_row( + row: &WoodenFishWorkProfileRow, +) -> Result { + let work = build_work_snapshot(row)?; + Ok(WoodenFishGalleryViewRow { + public_work_code: build_wooden_fish_public_work_code(&work.profile_id), + work_id: work.work_id, + profile_id: work.profile_id, + owner_user_id: work.owner_user_id, + source_session_id: work.source_session_id, + author_display_name: work.author_display_name, + work_title: work.work_title, + work_description: work.work_description, + theme_tags: work.theme_tags, + hit_object_prompt: work.hit_object_prompt, + hit_object_reference_image_src: work.hit_object_reference_image_src, + hit_sound_prompt: work.hit_sound_prompt, + hit_object_asset: work.hit_object_asset, + hit_sound_asset: work.hit_sound_asset, + floating_words: work.floating_words, + cover_image_src: work.cover_image_src, + publication_status: work.publication_status, + publish_ready: work.publish_ready, + play_count: work.play_count, + generation_status: work.generation_status, + updated_at_micros: work.updated_at_micros, + published_at_micros: work.published_at_micros, + }) +} + +fn build_session_snapshot( + row: &WoodenFishAgentSessionRow, +) -> Result { + Ok(WoodenFishAgentSessionSnapshot { + session_id: row.session_id.clone(), + owner_user_id: row.owner_user_id.clone(), + current_turn: row.current_turn, + progress_percent: row.progress_percent, + stage: row.stage.clone(), + config: parse_config(&row.config_json)?, + draft: clean_optional(&row.draft_json) + .map(|value| parse_json(&value)) + .transpose()?, + published_profile_id: clean_optional(&row.published_profile_id), + created_at_micros: row.created_at.to_micros_since_unix_epoch(), + updated_at_micros: row.updated_at.to_micros_since_unix_epoch(), + }) +} + +fn build_work_snapshot(row: &WoodenFishWorkProfileRow) -> Result { + Ok(WoodenFishWorkSnapshot { + work_id: row.work_id.clone(), + profile_id: row.profile_id.clone(), + owner_user_id: row.owner_user_id.clone(), + source_session_id: row.source_session_id.clone(), + author_display_name: row.author_display_name.clone(), + work_title: row.work_title.clone(), + work_description: row.work_description.clone(), + theme_tags: parse_tags(&row.theme_tags_json)?, + hit_object_prompt: row.hit_object_prompt.clone(), + hit_object_reference_image_src: clean_optional(&row.hit_object_reference_image_src), + hit_sound_prompt: clean_optional(&row.hit_sound_prompt), + hit_object_asset: clean_optional(&row.hit_object_asset_json) + .map(|value| parse_json(&value)) + .transpose()?, + hit_sound_asset: clean_optional(&row.hit_sound_asset_json) + .map(|value| parse_json(&value)) + .transpose()?, + floating_words: normalize_floating_words(&parse_json_or_default::>( + &row.floating_words_json, + )), + cover_image_src: row.cover_image_src.clone(), + publication_status: row.publication_status.clone(), + publish_ready: is_publish_ready(row), + play_count: row.play_count, + generation_status: row.generation_status.clone(), + updated_at_micros: row.updated_at.to_micros_since_unix_epoch(), + published_at_micros: row + .published_at + .map(|value| value.to_micros_since_unix_epoch()), + }) +} + +fn sync_session_from_work_update( + ctx: &ReducerContext, + work: &WoodenFishWorkProfileRow, + updated_at: Timestamp, +) -> Result<(), String> { + let Some(session) = ctx + .db + .wooden_fish_agent_session() + .session_id() + .find(&work.source_session_id) + else { + return Ok(()); + }; + + let snapshot = build_work_snapshot(work)?; + let draft = draft_from_work_snapshot(&snapshot); + let config = config_from_draft(&draft); + replace_session( + ctx, + &session, + WoodenFishAgentSessionRow { + config_json: to_json_string(&config), + draft_json: to_json_string(&draft), + updated_at, + ..clone_session(&session) + }, + ); + Ok(()) +} + +fn find_owned_session( + ctx: &ReducerContext, + session_id: &str, + owner_user_id: &str, +) -> Result { + let row = ctx + .db + .wooden_fish_agent_session() + .session_id() + .find(&session_id.to_string()) + .ok_or_else(|| "wooden_fish_agent_session ä¸å­˜åœ¨".to_string())?; + if row.owner_user_id != owner_user_id { + return Err("æ— æƒè®¿é—®è¯¥ wooden_fish session".to_string()); + } + Ok(row) +} + +fn find_work(ctx: &ReducerContext, profile_id: &str) -> Result { + ctx.db + .wooden_fish_work_profile() + .profile_id() + .find(&profile_id.to_string()) + .ok_or_else(|| "wooden_fish_work_profile ä¸å­˜åœ¨".to_string()) +} + +fn find_owned_work( + ctx: &ReducerContext, + profile_id: &str, + owner_user_id: &str, +) -> Result { + let row = find_work(ctx, profile_id)?; + if row.owner_user_id != owner_user_id { + return Err("æ— æƒè®¿é—®è¯¥ wooden_fish work".to_string()); + } + Ok(row) +} + +fn find_owned_run( + ctx: &ReducerContext, + run_id: &str, + owner_user_id: &str, +) -> Result { + let row = ctx + .db + .wooden_fish_runtime_run() + .run_id() + .find(&run_id.to_string()) + .ok_or_else(|| "wooden_fish_runtime_run ä¸å­˜åœ¨".to_string())?; + if row.owner_user_id != owner_user_id { + return Err("æ— æƒè®¿é—®è¯¥ wooden_fish run".to_string()); + } + Ok(row) +} + +fn upsert_work(ctx: &ReducerContext, row: WoodenFishWorkProfileRow) { + if let Some(old) = ctx + .db + .wooden_fish_work_profile() + .profile_id() + .find(&row.profile_id) + { + ctx.db.wooden_fish_work_profile().delete(old); + } + ctx.db.wooden_fish_work_profile().insert(row); +} + +fn replace_work( + ctx: &ReducerContext, + old: &WoodenFishWorkProfileRow, + next: WoodenFishWorkProfileRow, +) { + ctx.db.wooden_fish_work_profile().delete(clone_work(old)); + ctx.db.wooden_fish_work_profile().insert(next); +} + +fn replace_session( + ctx: &ReducerContext, + old: &WoodenFishAgentSessionRow, + next: WoodenFishAgentSessionRow, +) { + ctx.db + .wooden_fish_agent_session() + .delete(clone_session(old)); + ctx.db.wooden_fish_agent_session().insert(next); +} + +fn upsert_run(ctx: &ReducerContext, snapshot: &WoodenFishRunSnapshot, updated_at_ms: i64) { + if let Some(old) = ctx + .db + .wooden_fish_runtime_run() + .run_id() + .find(&snapshot.run_id) + { + ctx.db.wooden_fish_runtime_run().delete(old); + } + let created_at = Timestamp::from_micros_since_unix_epoch(updated_at_ms.saturating_mul(1000)); + ctx.db + .wooden_fish_runtime_run() + .insert(run_row_from_snapshot(snapshot, created_at, created_at)); +} + +fn replace_run( + ctx: &ReducerContext, + old: &WoodenFishRuntimeRunRow, + snapshot: &WoodenFishRunSnapshot, + updated_at_ms: i64, +) { + ctx.db.wooden_fish_runtime_run().delete(clone_run(old)); + ctx.db + .wooden_fish_runtime_run() + .insert(run_row_from_snapshot( + snapshot, + old.created_at, + Timestamp::from_micros_since_unix_epoch(updated_at_ms.saturating_mul(1000)), + )); +} + +fn run_row_from_snapshot( + snapshot: &WoodenFishRunSnapshot, + created_at: Timestamp, + updated_at: Timestamp, +) -> WoodenFishRuntimeRunRow { + WoodenFishRuntimeRunRow { + run_id: snapshot.run_id.clone(), + owner_user_id: snapshot.owner_user_id.clone(), + profile_id: snapshot.profile_id.clone(), + status: run_status_as_str(snapshot.status).to_string(), + total_tap_count: snapshot.total_tap_count, + word_counters_json: to_json_string(&snapshot.word_counters), + started_at_ms: snapshot.started_at_ms as i64, + updated_at_ms: snapshot.updated_at_ms as i64, + finished_at_ms: snapshot + .finished_at_ms + .map(|value| value as i64) + .unwrap_or(0), + snapshot_json: to_json_string(snapshot), + created_at, + updated_at, + } +} + +fn increment_work_play_count( + ctx: &ReducerContext, + row: &WoodenFishWorkProfileRow, + played_at_ms: i64, +) { + replace_work( + ctx, + row, + WoodenFishWorkProfileRow { + play_count: row.play_count.saturating_add(1), + updated_at: Timestamp::from_micros_since_unix_epoch(played_at_ms.saturating_mul(1000)), + ..clone_work(row) + }, + ); +} + +fn insert_event( + ctx: &ReducerContext, + event_id: String, + owner_user_id: String, + profile_id: String, + run_id: String, + event_type: &str, + result: Option, + occurred_at_ms: i64, +) { + let event_id = clean_optional(&event_id).unwrap_or_else(|| { + format!( + "wooden-fish-event-{}-{}-{}", + run_id, event_type, occurred_at_ms + ) + }); + if ctx + .db + .wooden_fish_event() + .event_id() + .find(&event_id) + .is_some() + { + return; + } + ctx.db.wooden_fish_event().insert(WoodenFishEventRow { + event_id, + owner_user_id, + profile_id, + run_id, + event_type: event_type.to_string(), + result: result.unwrap_or_default(), + occurred_at: Timestamp::from_micros_since_unix_epoch(occurred_at_ms.saturating_mul(1000)), + }); +} + +fn is_publish_ready(row: &WoodenFishWorkProfileRow) -> bool { + !row.work_title.trim().is_empty() + && !row.hit_object_asset_json.trim().is_empty() + && !row.hit_sound_asset_json.trim().is_empty() + && !row.floating_words_json.trim().is_empty() + && row.generation_status == WOODEN_FISH_GENERATION_READY +} + +fn default_config_from_input( + input: &WoodenFishAgentSessionCreateInput, +) -> WoodenFishCreatorConfigSnapshot { + WoodenFishCreatorConfigSnapshot { + work_title: clean_string(&input.work_title, WOODEN_FISH_TEMPLATE_NAME), + work_description: input.work_description.trim().to_string(), + theme_tags: parse_tags(input.theme_tags_json.as_deref().unwrap_or("[]")) + .unwrap_or_default(), + hit_object_prompt: "é»˜è®¤æ•²å‡»ç‰©å›¾æ¡ˆï¼Œåœ†æ¶¦æœ¨è´¨è´¨æ„Ÿï¼Œé€æ˜ŽèƒŒæ™¯".to_string(), + hit_object_reference_image_src: None, + hit_sound_prompt: Some("清脆短促的木鱼敲击声".to_string()), + floating_words: default_floating_words(), + } +} + +fn draft_from_config( + config: &WoodenFishCreatorConfigSnapshot, + profile_id: Option, + generation_status: &str, +) -> WoodenFishDraftSnapshot { + WoodenFishDraftSnapshot { + template_id: WOODEN_FISH_TEMPLATE_ID.to_string(), + template_name: WOODEN_FISH_TEMPLATE_NAME.to_string(), + profile_id, + work_title: config.work_title.clone(), + work_description: config.work_description.clone(), + theme_tags: config.theme_tags.clone(), + hit_object_prompt: config.hit_object_prompt.clone(), + hit_object_reference_image_src: config.hit_object_reference_image_src.clone(), + hit_sound_prompt: config.hit_sound_prompt.clone(), + floating_words: normalize_floating_words(&config.floating_words), + hit_object_asset: None, + hit_sound_asset: None, + cover_image_src: None, + generation_status: generation_status.to_string(), + } +} + +fn draft_from_work_snapshot(work: &WoodenFishWorkSnapshot) -> WoodenFishDraftSnapshot { + WoodenFishDraftSnapshot { + template_id: WOODEN_FISH_TEMPLATE_ID.to_string(), + template_name: WOODEN_FISH_TEMPLATE_NAME.to_string(), + profile_id: Some(work.profile_id.clone()), + work_title: work.work_title.clone(), + work_description: work.work_description.clone(), + theme_tags: work.theme_tags.clone(), + hit_object_prompt: work.hit_object_prompt.clone(), + hit_object_reference_image_src: work.hit_object_reference_image_src.clone(), + hit_sound_prompt: work.hit_sound_prompt.clone(), + floating_words: work.floating_words.clone(), + hit_object_asset: work.hit_object_asset.clone(), + hit_sound_asset: work.hit_sound_asset.clone(), + cover_image_src: clean_optional(&work.cover_image_src), + generation_status: work.generation_status.clone(), + } +} + +fn config_from_draft(draft: &WoodenFishDraftSnapshot) -> WoodenFishCreatorConfigSnapshot { + WoodenFishCreatorConfigSnapshot { + work_title: draft.work_title.clone(), + work_description: draft.work_description.clone(), + theme_tags: draft.theme_tags.clone(), + hit_object_prompt: draft.hit_object_prompt.clone(), + hit_object_reference_image_src: draft.hit_object_reference_image_src.clone(), + hit_sound_prompt: draft.hit_sound_prompt.clone(), + floating_words: normalize_floating_words(&draft.floating_words), + } +} + +fn build_wooden_fish_public_work_code(profile_id: &str) -> String { + let normalized = profile_id + .chars() + .filter(|character| character.is_ascii_alphanumeric()) + .flat_map(|character| character.to_uppercase()) + .collect::(); + let fallback = if normalized.is_empty() { + "00000000".to_string() + } else { + normalized + }; + let suffix = if fallback.len() > 8 { + fallback[fallback.len() - 8..].to_string() + } else { + format!("{fallback:0>8}") + }; + format!("WF-{suffix}") +} + +fn run_status_as_str(status: WoodenFishRunStatus) -> &'static str { + match status { + WoodenFishRunStatus::Playing => "playing", + WoodenFishRunStatus::Finished => "finished", + } +} + +fn require_non_empty(value: &str, label: &str) -> Result<(), String> { + if value.trim().is_empty() { + Err(format!("{label} ä¸èƒ½ä¸ºç©º")) + } else { + Ok(()) + } +} + +fn clean_optional(value: &str) -> Option { + let value = value.trim(); + if value.is_empty() { + None + } else { + Some(value.to_string()) + } +} + +fn clean_string(value: &str, fallback: &str) -> String { + clean_optional(value).unwrap_or_else(|| fallback.to_string()) +} + +fn parse_config(value: &str) -> Result { + parse_json(value) +} + +fn parse_tags(value: &str) -> Result, String> { + Ok(parse_json_or_default::>(value) + .into_iter() + .map(|tag| tag.trim().to_string()) + .filter(|tag| !tag.is_empty()) + .take(8) + .collect()) +} + +fn parse_json(value: &str) -> Result +where + T: DeserializeOwned, +{ + serde_json::from_str(value).map_err(|error| error.to_string()) +} + +fn parse_json_or_default(value: &str) -> T +where + T: DeserializeOwned + Default, +{ + serde_json::from_str(value).unwrap_or_default() +} + +fn to_json_string(value: &T) -> String +where + T: Serialize, +{ + serde_json::to_string(value).unwrap_or_else(|_| "{}".to_string()) +} + +fn session_result( + session: WoodenFishAgentSessionSnapshot, +) -> WoodenFishAgentSessionProcedureResult { + WoodenFishAgentSessionProcedureResult { + ok: true, + session: Some(session), + error_message: None, + } +} + +fn session_error(message: String) -> WoodenFishAgentSessionProcedureResult { + WoodenFishAgentSessionProcedureResult { + ok: false, + session: None, + error_message: Some(message), + } +} + +fn work_result(work: WoodenFishWorkSnapshot) -> WoodenFishWorkProcedureResult { + WoodenFishWorkProcedureResult { + ok: true, + work: Some(work), + error_message: None, + } +} + +fn work_error(message: String) -> WoodenFishWorkProcedureResult { + WoodenFishWorkProcedureResult { + ok: false, + work: None, + error_message: Some(message), + } +} + +fn run_result(run: WoodenFishRunSnapshot) -> WoodenFishRunProcedureResult { + WoodenFishRunProcedureResult { + ok: true, + run: Some(run), + error_message: None, + } +} + +fn run_error(message: String) -> WoodenFishRunProcedureResult { + WoodenFishRunProcedureResult { + ok: false, + run: None, + error_message: Some(message), + } +} + +fn clone_session(row: &WoodenFishAgentSessionRow) -> WoodenFishAgentSessionRow { + WoodenFishAgentSessionRow { + session_id: row.session_id.clone(), + owner_user_id: row.owner_user_id.clone(), + current_turn: row.current_turn, + progress_percent: row.progress_percent, + stage: row.stage.clone(), + config_json: row.config_json.clone(), + draft_json: row.draft_json.clone(), + published_profile_id: row.published_profile_id.clone(), + created_at: row.created_at, + updated_at: row.updated_at, + } +} + +fn clone_work(row: &WoodenFishWorkProfileRow) -> WoodenFishWorkProfileRow { + WoodenFishWorkProfileRow { + profile_id: row.profile_id.clone(), + work_id: row.work_id.clone(), + owner_user_id: row.owner_user_id.clone(), + source_session_id: row.source_session_id.clone(), + author_display_name: row.author_display_name.clone(), + work_title: row.work_title.clone(), + work_description: row.work_description.clone(), + theme_tags_json: row.theme_tags_json.clone(), + hit_object_prompt: row.hit_object_prompt.clone(), + hit_object_reference_image_src: row.hit_object_reference_image_src.clone(), + hit_sound_prompt: row.hit_sound_prompt.clone(), + hit_object_asset_json: row.hit_object_asset_json.clone(), + hit_sound_asset_json: row.hit_sound_asset_json.clone(), + floating_words_json: row.floating_words_json.clone(), + cover_image_src: row.cover_image_src.clone(), + generation_status: row.generation_status.clone(), + publication_status: row.publication_status.clone(), + play_count: row.play_count, + updated_at: row.updated_at, + published_at: row.published_at, + } +} + +fn clone_run(row: &WoodenFishRuntimeRunRow) -> WoodenFishRuntimeRunRow { + WoodenFishRuntimeRunRow { + run_id: row.run_id.clone(), + owner_user_id: row.owner_user_id.clone(), + profile_id: row.profile_id.clone(), + status: row.status.clone(), + total_tap_count: row.total_tap_count, + word_counters_json: row.word_counters_json.clone(), + started_at_ms: row.started_at_ms, + updated_at_ms: row.updated_at_ms, + finished_at_ms: row.finished_at_ms, + snapshot_json: row.snapshot_json.clone(), + created_at: row.created_at, + updated_at: row.updated_at, + } +} diff --git a/server-rs/crates/spacetime-module/src/wooden_fish/tables.rs b/server-rs/crates/spacetime-module/src/wooden_fish/tables.rs new file mode 100644 index 00000000..e7f84193 --- /dev/null +++ b/server-rs/crates/spacetime-module/src/wooden_fish/tables.rs @@ -0,0 +1,85 @@ +use crate::*; + +#[spacetimedb::table( + accessor = wooden_fish_agent_session, + index(accessor = by_wooden_fish_agent_session_owner_user_id, btree(columns = [owner_user_id])) +)] +pub struct WoodenFishAgentSessionRow { + #[primary_key] + pub(crate) session_id: String, + pub(crate) owner_user_id: String, + pub(crate) current_turn: u32, + pub(crate) progress_percent: u32, + pub(crate) stage: String, + pub(crate) config_json: String, + pub(crate) draft_json: String, + pub(crate) published_profile_id: String, + pub(crate) created_at: Timestamp, + pub(crate) updated_at: Timestamp, +} + +#[spacetimedb::table( + accessor = wooden_fish_work_profile, + index(accessor = by_wooden_fish_work_owner_user_id, btree(columns = [owner_user_id])), + index(accessor = by_wooden_fish_work_publication_status, btree(columns = [publication_status])) +)] +pub struct WoodenFishWorkProfileRow { + #[primary_key] + pub(crate) profile_id: String, + pub(crate) work_id: String, + pub(crate) owner_user_id: String, + pub(crate) source_session_id: String, + pub(crate) author_display_name: String, + pub(crate) work_title: String, + pub(crate) work_description: String, + pub(crate) theme_tags_json: String, + pub(crate) hit_object_prompt: String, + pub(crate) hit_object_reference_image_src: String, + pub(crate) hit_sound_prompt: String, + pub(crate) hit_object_asset_json: String, + pub(crate) hit_sound_asset_json: String, + pub(crate) floating_words_json: String, + pub(crate) cover_image_src: String, + pub(crate) generation_status: String, + pub(crate) publication_status: String, + pub(crate) play_count: u32, + pub(crate) updated_at: Timestamp, + pub(crate) published_at: Option, +} + +#[spacetimedb::table( + accessor = wooden_fish_runtime_run, + index(accessor = by_wooden_fish_run_owner_user_id, btree(columns = [owner_user_id])), + index(accessor = by_wooden_fish_run_profile_id, btree(columns = [profile_id])) +)] +pub struct WoodenFishRuntimeRunRow { + #[primary_key] + pub(crate) run_id: String, + pub(crate) owner_user_id: String, + pub(crate) profile_id: String, + pub(crate) status: String, + pub(crate) total_tap_count: u32, + pub(crate) word_counters_json: String, + pub(crate) started_at_ms: i64, + pub(crate) updated_at_ms: i64, + pub(crate) finished_at_ms: i64, + pub(crate) snapshot_json: String, + pub(crate) created_at: Timestamp, + pub(crate) updated_at: Timestamp, +} + +#[spacetimedb::table( + accessor = wooden_fish_event, + index(accessor = by_wooden_fish_event_profile_id, btree(columns = [profile_id])), + index(accessor = by_wooden_fish_event_run_id, btree(columns = [run_id])) +)] +pub struct WoodenFishEventRow { + #[primary_key] + pub(crate) event_id: String, + pub(crate) owner_user_id: String, + pub(crate) profile_id: String, + pub(crate) run_id: String, + pub(crate) event_type: String, + pub(crate) result: String, + pub(crate) occurred_at: Timestamp, +} diff --git a/server-rs/crates/spacetime-module/src/wooden_fish/types.rs b/server-rs/crates/spacetime-module/src/wooden_fish/types.rs new file mode 100644 index 00000000..8b8ea2ea --- /dev/null +++ b/server-rs/crates/spacetime-module/src/wooden_fish/types.rs @@ -0,0 +1,254 @@ +use crate::*; +use serde::{Deserialize, Serialize}; + +pub const WOODEN_FISH_TEMPLATE_ID: &str = "wooden-fish"; +pub const WOODEN_FISH_TEMPLATE_NAME: &str = "敲木鱼"; +pub const WOODEN_FISH_STAGE_COLLECTING: &str = "Collecting"; +pub const WOODEN_FISH_STAGE_DRAFT_COMPILED: &str = "DraftCompiled"; +pub const WOODEN_FISH_STAGE_PUBLISHED: &str = "Published"; +pub const WOODEN_FISH_PUBLICATION_DRAFT: &str = "Draft"; +pub const WOODEN_FISH_PUBLICATION_PUBLISHED: &str = "Published"; +pub const WOODEN_FISH_GENERATION_DRAFT: &str = "draft"; +pub const WOODEN_FISH_GENERATION_READY: &str = "ready"; +pub const WOODEN_FISH_EVENT_RUN_STARTED: &str = "run-started"; +pub const WOODEN_FISH_EVENT_RUN_CHECKPOINT: &str = "checkpoint"; +pub const WOODEN_FISH_EVENT_RUN_FINISHED: &str = "finish"; + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishAgentSessionCreateInput { + pub session_id: String, + pub owner_user_id: String, + pub work_title: String, + pub work_description: String, + pub theme_tags_json: Option, + pub config_json: Option, + pub draft_json: Option, + pub created_at_micros: i64, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishAgentSessionGetInput { + pub session_id: String, + pub owner_user_id: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishDraftCompileInput { + pub session_id: String, + pub owner_user_id: String, + pub profile_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub theme_tags_json: Option, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset_json: Option, + pub hit_sound_asset_json: Option, + pub floating_words_json: Option, + pub cover_image_src: Option, + pub generation_status: Option, + pub compiled_at_micros: i64, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishWorkUpdateInput { + pub profile_id: String, + pub owner_user_id: String, + pub work_title: String, + pub work_description: String, + pub theme_tags_json: String, + pub hit_object_prompt: Option, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset_json: Option, + pub hit_sound_asset_json: Option, + pub floating_words_json: Option, + pub cover_image_src: Option, + pub generation_status: Option, + pub updated_at_micros: i64, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishWorkPublishInput { + pub profile_id: String, + pub owner_user_id: String, + pub published_at_micros: i64, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishWorksListInput { + pub owner_user_id: String, + pub published_only: bool, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishWorkGetInput { + pub profile_id: String, + pub owner_user_id: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishRunStartInput { + pub run_id: String, + pub owner_user_id: String, + pub profile_id: String, + pub client_event_id: String, + pub started_at_ms: i64, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishRunGetInput { + pub run_id: String, + pub owner_user_id: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishRunCheckpointInput { + pub run_id: String, + pub owner_user_id: String, + pub total_tap_count: u32, + pub word_counters_json: String, + pub client_event_id: String, + pub checkpoint_at_ms: i64, +} + +#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)] +pub struct WoodenFishRunFinishInput { + pub run_id: String, + pub owner_user_id: String, + pub total_tap_count: u32, + pub word_counters_json: String, + pub client_event_id: String, + pub finished_at_ms: i64, +} + +#[derive(Clone, Debug, PartialEq, SpacetimeType)] +pub struct WoodenFishAgentSessionProcedureResult { + pub ok: bool, + pub session: Option, + pub error_message: Option, +} + +#[derive(Clone, Debug, PartialEq, SpacetimeType)] +pub struct WoodenFishWorkProcedureResult { + pub ok: bool, + pub work: Option, + pub error_message: Option, +} + +#[derive(Clone, Debug, PartialEq, SpacetimeType)] +pub struct WoodenFishWorksProcedureResult { + pub ok: bool, + pub items: Vec, + pub error_message: Option, +} + +#[derive(Clone, Debug, PartialEq, SpacetimeType)] +pub struct WoodenFishRunProcedureResult { + pub ok: bool, + pub run: Option, + pub error_message: Option, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishCreatorConfigSnapshot { + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + #[serde(default)] + pub hit_object_reference_image_src: Option, + #[serde(default)] + pub hit_sound_prompt: Option, + pub floating_words: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishImageAssetSnapshot { + pub asset_id: String, + pub image_src: String, + pub image_object_key: String, + pub asset_object_id: String, + pub generation_provider: String, + pub prompt: String, + pub width: u32, + pub height: u32, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishAudioAssetSnapshot { + pub asset_id: String, + pub audio_src: String, + pub audio_object_key: String, + pub asset_object_id: String, + pub source: String, + #[serde(default)] + pub prompt: Option, + #[serde(default)] + pub duration_ms: Option, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishDraftSnapshot { + pub template_id: String, + pub template_name: String, + pub profile_id: Option, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub floating_words: Vec, + pub hit_object_asset: Option, + pub hit_sound_asset: Option, + pub cover_image_src: Option, + pub generation_status: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishAgentSessionSnapshot { + pub session_id: String, + pub owner_user_id: String, + pub current_turn: u32, + pub progress_percent: u32, + pub stage: String, + pub config: WoodenFishCreatorConfigSnapshot, + pub draft: Option, + pub published_profile_id: Option, + pub created_at_micros: i64, + pub updated_at_micros: i64, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)] +#[serde(rename_all = "camelCase")] +pub struct WoodenFishWorkSnapshot { + pub work_id: String, + pub profile_id: String, + pub owner_user_id: String, + pub source_session_id: String, + pub author_display_name: String, + pub work_title: String, + pub work_description: String, + pub theme_tags: Vec, + pub hit_object_prompt: String, + pub hit_object_reference_image_src: Option, + pub hit_sound_prompt: Option, + pub hit_object_asset: Option, + pub hit_sound_asset: Option, + pub floating_words: Vec, + pub cover_image_src: String, + pub publication_status: String, + pub publish_ready: bool, + pub play_count: u32, + pub generation_status: String, + pub updated_at_micros: i64, + pub published_at_micros: Option, +} diff --git a/src/components/platform-entry/PlatformEntryCreationTypeModal.test.tsx b/src/components/platform-entry/PlatformEntryCreationTypeModal.test.tsx new file mode 100644 index 00000000..16e1b08e --- /dev/null +++ b/src/components/platform-entry/PlatformEntryCreationTypeModal.test.tsx @@ -0,0 +1,64 @@ +/* @vitest-environment jsdom */ + +import { fireEvent, render, screen } from '@testing-library/react'; +import { expect, test, vi } from 'vitest'; + +import type { CreationEntryConfig } from '../../services/creationEntryConfigService'; +import { PlatformEntryCreationTypeModal } from './PlatformEntryCreationTypeModal'; +import { derivePlatformCreationTypes } from './platformEntryCreationTypes'; + +const entryConfig = { + startCard: { + title: '新建作å“', + description: '', + idleBadge: '模æ¿', + busyBadge: 'å¼€å¯ä¸­', + }, + typeModal: { + title: '选择创作类型', + description: '', + }, + creationTypes: [ + { + id: 'wooden-fish', + title: '敲木鱼', + subtitle: '轻点积累功德', + badge: 'å¯åˆ›å»º', + imageSrc: '/creation-type-references/puzzle.webp', + visible: true, + open: true, + sortOrder: 10, + updatedAtMicros: 1, + }, + ], +} satisfies CreationEntryConfig; + +test('dispatches wooden fish creation type selection', () => { + const onSelectWoodenFish = vi.fn(); + + render( + {}} + onSelectRpg={() => {}} + onSelectBigFish={() => {}} + onSelectMatch3D={() => {}} + onSelectSquareHole={() => {}} + onSelectJumpHop={() => {}} + onSelectWoodenFish={onSelectWoodenFish} + onSelectPuzzle={() => {}} + onSelectCreativeAgent={() => {}} + onSelectBarkBattle={() => {}} + onSelectVisualNovel={() => {}} + onSelectBabyObjectMatch={() => {}} + />, + ); + + fireEvent.click(screen.getByRole('button', { name: /敲木鱼/u })); + + expect(onSelectWoodenFish).toHaveBeenCalledTimes(1); +}); diff --git a/src/components/platform-entry/PlatformEntryCreationTypeModal.tsx b/src/components/platform-entry/PlatformEntryCreationTypeModal.tsx index aa08bce6..8d6698aa 100644 --- a/src/components/platform-entry/PlatformEntryCreationTypeModal.tsx +++ b/src/components/platform-entry/PlatformEntryCreationTypeModal.tsx @@ -19,6 +19,7 @@ export interface PlatformEntryCreationTypeModalProps { onSelectMatch3D: () => void; onSelectSquareHole: () => void; onSelectJumpHop: () => void; + onSelectWoodenFish: () => void; onSelectPuzzle: () => void; onSelectCreativeAgent: () => void; onSelectBarkBattle: () => void; @@ -102,6 +103,7 @@ export function PlatformEntryCreationTypeModal({ onSelectMatch3D, onSelectSquareHole, onSelectJumpHop, + onSelectWoodenFish, onSelectPuzzle, onSelectCreativeAgent, onSelectBarkBattle, @@ -147,6 +149,9 @@ export function PlatformEntryCreationTypeModal({ if (item.id === 'jump-hop') { onSelectJumpHop(); } + if (item.id === 'wooden-fish') { + onSelectWoodenFish(); + } if (item.id === 'puzzle') { onSelectPuzzle(); } diff --git a/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx b/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx index eb79ef81..91954cb6 100644 --- a/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx +++ b/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx @@ -168,10 +168,10 @@ import { } from '../../services/edutainment-baby-object'; import { jumpHopClient, + type JumpHopGalleryCardResponse, type JumpHopRunResponse, type JumpHopSessionResponse, type JumpHopSessionSnapshotResponse, - type JumpHopGalleryCardResponse, type JumpHopWorkProfileResponse, type JumpHopWorkspaceCreateRequest, } from '../../services/jump-hop/jumpHopClient'; @@ -197,6 +197,7 @@ import { buildMiniGameDraftGenerationProgress, buildPuzzleGenerationAnchorEntries, buildSquareHoleGenerationAnchorEntries, + buildWoodenFishGenerationAnchorEntries, createMiniGameDraftGenerationState, type MiniGameDraftGenerationKind, type MiniGameDraftGenerationState, @@ -210,6 +211,7 @@ import { buildPuzzlePublicWorkCode, buildSquareHolePublicWorkCode, buildVisualNovelPublicWorkCode, + buildWoodenFishPublicWorkCode, isSameBabyObjectMatchPublicWorkCode, isSameBigFishPublicWorkCode, isSameJumpHopPublicWorkCode, @@ -217,6 +219,7 @@ import { isSamePuzzlePublicWorkCode, isSameSquareHolePublicWorkCode, isSameVisualNovelPublicWorkCode, + isSameWoodenFishPublicWorkCode, } from '../../services/publicWorkCode'; import { createPuzzleAgentSession, @@ -306,6 +309,15 @@ import { publishVisualNovelWork, updateVisualNovelWork, } from '../../services/visual-novel-works'; +import { + woodenFishClient, + type WoodenFishGalleryCardResponse, + type WoodenFishRunResponse, + type WoodenFishSessionResponse, + type WoodenFishSessionSnapshotResponse, + type WoodenFishWorkProfileResponse, + type WoodenFishWorkspaceCreateRequest, +} from '../../services/wooden-fish/woodenFishClient'; import type { CustomWorldProfile } from '../../types'; import { useAuthUi } from '../auth/AuthUiContext'; import { PublishShareModal } from '../common/PublishShareModal'; @@ -325,6 +337,7 @@ import { isPuzzleGalleryEntry, isSquareHoleGalleryEntry, isVisualNovelGalleryEntry, + isWoodenFishGalleryEntry, mapBabyObjectMatchDraftToPlatformGalleryCard, mapBigFishWorkToPlatformGalleryCard, mapJumpHopWorkToPlatformGalleryCard, @@ -332,6 +345,7 @@ import { mapPuzzleWorkToPlatformGalleryCard, mapSquareHoleWorkToPlatformGalleryCard, mapVisualNovelWorkToPlatformGalleryCard, + mapWoodenFishWorkToPlatformGalleryCard, type PlatformPublicGalleryCard, } from '../rpg-entry/rpgEntryWorldPresentation'; import { useRpgCreationAgentOperationPolling } from '../rpg-entry/useRpgCreationAgentOperationPolling'; @@ -439,6 +453,7 @@ type RecommendRuntimeKind = | 'match3d' | 'puzzle' | 'square-hole' + | 'wooden-fish' | 'visual-novel' | 'rpg'; type SquareHoleRuntimeReturnStage = @@ -455,6 +470,10 @@ type BabyObjectMatchRuntimeReturnStage = | 'work-detail' | 'platform'; type JumpHopRuntimeReturnStage = 'jump-hop-result' | 'work-detail' | 'platform'; +type WoodenFishRuntimeReturnStage = + | 'wooden-fish-result' + | 'work-detail' + | 'platform'; type VisualNovelEntryGenerationPhase = 'generating' | 'ready' | 'failed'; type BabyObjectMatchGenerationPhase = 'generating' | 'ready' | 'failed'; @@ -467,6 +486,7 @@ type RecommendRuntimeState = { puzzleRun: PuzzleRunSnapshot | null; squareHoleRun: SquareHoleRunSnapshot | null; visualNovelRun: VisualNovelRunSnapshot | null; + woodenFishRun: WoodenFishRunResponse['run'] | null; }; type PuzzleSaveArchiveState = { @@ -525,15 +545,17 @@ function getPlatformPublicGalleryEntryKey(entry: PlatformPublicGalleryCard) { ? 'puzzle' : isJumpHopGalleryEntry(entry) ? 'jump-hop' - : isMatch3DGalleryEntry(entry) - ? 'match3d' - : isSquareHoleGalleryEntry(entry) - ? 'square-hole' - : isVisualNovelGalleryEntry(entry) - ? 'visual-novel' - : isEdutainmentGalleryEntry(entry) - ? `edutainment:${entry.templateId}` - : 'rpg'; + : isWoodenFishGalleryEntry(entry) + ? 'wooden-fish' + : isMatch3DGalleryEntry(entry) + ? 'match3d' + : isSquareHoleGalleryEntry(entry) + ? 'square-hole' + : isVisualNovelGalleryEntry(entry) + ? 'visual-novel' + : isEdutainmentGalleryEntry(entry) + ? `edutainment:${entry.templateId}` + : 'rpg'; return `${kind}:${entry.ownerUserId}:${entry.profileId}`; } @@ -552,6 +574,10 @@ function getPlatformRecommendRuntimeKind( return 'jump-hop'; } + if (isWoodenFishGalleryEntry(entry)) { + return 'wooden-fish'; + } + if (isMatch3DGalleryEntry(entry)) { return 'match3d'; } @@ -586,6 +612,9 @@ function isRecommendRuntimeReadyForEntry( if (expectedKind === 'jump-hop') { return Boolean(state.jumpHopRun); } + if (expectedKind === 'wooden-fish') { + return Boolean(state.woodenFishRun); + } if (expectedKind === 'match3d') { return Boolean(state.match3dRun); } @@ -692,6 +721,12 @@ function mapJumpHopWorkToPublicWorkDetail( return mapJumpHopWorkToPlatformGalleryCard(item); } +function mapWoodenFishWorkToPublicWorkDetail( + item: WoodenFishGalleryCardResponse | WoodenFishWorkProfileResponse, +): PlatformPublicGalleryCard { + return mapWoodenFishWorkToPlatformGalleryCard(item); +} + function mapVisualNovelWorkDetailToSession( work: VisualNovelWorkDetail, ): VisualNovelAgentSessionSnapshot { @@ -2150,6 +2185,27 @@ const JumpHopRuntimeShell = lazy(async () => { }; }); +const WoodenFishWorkspace = lazy(async () => { + const module = await import('../wooden-fish-creation/WoodenFishWorkspace'); + return { + default: module.WoodenFishWorkspace, + }; +}); + +const WoodenFishResultView = lazy(async () => { + const module = await import('../wooden-fish-result/WoodenFishResultView'); + return { + default: module.WoodenFishResultView, + }; +}); + +const WoodenFishRuntimeShell = lazy(async () => { + const module = await import('../wooden-fish-runtime/WoodenFishRuntimeShell'); + return { + default: module.WoodenFishRuntimeShell, + }; +}); + const BarkBattleConfigEditor = lazy(async () => { const module = await import('../bark-battle-creation/BarkBattleConfigEditor'); return { @@ -2400,6 +2456,22 @@ export function PlatformEntryFlowShellImpl({ useState(null); const [jumpHopError, setJumpHopError] = useState(null); const [isJumpHopBusy, setIsJumpHopBusy] = useState(false); + const [woodenFishSession, setWoodenFishSession] = + useState(null); + const [woodenFishRun, setWoodenFishRun] = useState< + WoodenFishRunResponse['run'] | null + >(null); + const [woodenFishWork, setWoodenFishWork] = + useState(null); + const [woodenFishGalleryEntries, setWoodenFishGalleryEntries] = useState< + WoodenFishGalleryCardResponse[] + >([]); + const [woodenFishRuntimeReturnStage, setWoodenFishRuntimeReturnStage] = + useState('wooden-fish-result'); + const [woodenFishGenerationState, setWoodenFishGenerationState] = + useState(null); + const [woodenFishError, setWoodenFishError] = useState(null); + const [isWoodenFishBusy, setIsWoodenFishBusy] = useState(false); const [barkBattlePublishedConfig, setBarkBattlePublishedConfig] = useState(null); const [barkBattleError, setBarkBattleError] = useState(null); @@ -3031,6 +3103,17 @@ export function PlatformEntryFlowShellImpl({ } }, []); + const refreshWoodenFishGallery = useCallback(async () => { + try { + const galleryResponse = await woodenFishClient.listGallery(); + setWoodenFishGalleryEntries(galleryResponse.items); + return galleryResponse.items; + } catch { + setWoodenFishGalleryEntries([]); + return []; + } + }, []); + const refreshPuzzleShelf = useCallback(async () => { setIsPuzzleLoadingLibrary(true); @@ -3353,6 +3436,9 @@ export function PlatformEntryFlowShellImpl({ const jumpHopPublicEntries = jumpHopGalleryEntries.map( mapJumpHopWorkToPlatformGalleryCard, ); + const woodenFishPublicEntries = woodenFishGalleryEntries.map( + mapWoodenFishWorkToPlatformGalleryCard, + ); const visualNovelPublicEntries = visualNovelGalleryEntries.map( mapVisualNovelWorkToPlatformGalleryCard, ); @@ -3364,6 +3450,7 @@ export function PlatformEntryFlowShellImpl({ ...puzzlePublicEntries, ...squareHolePublicEntries, ...jumpHopPublicEntries, + ...woodenFishPublicEntries, ...(isVisualNovelCreationOpen ? visualNovelPublicEntries : []), ...babyObjectMatchPublicEntries, ], @@ -3380,6 +3467,7 @@ export function PlatformEntryFlowShellImpl({ puzzleGalleryEntries, squareHoleGalleryEntries, visualNovelGalleryEntries, + woodenFishGalleryEntries, ]); const latestGalleryEntries = useMemo( () => @@ -3392,6 +3480,9 @@ export function PlatformEntryFlowShellImpl({ ...match3dGalleryEntries.map(mapMatch3DWorkToPublicWorkDetail), ...puzzleGalleryEntries.map(mapPuzzleWorkToPlatformGalleryCard), ...jumpHopGalleryEntries.map(mapJumpHopWorkToPlatformGalleryCard), + ...woodenFishGalleryEntries.map( + mapWoodenFishWorkToPlatformGalleryCard, + ), ...squareHoleGalleryEntries.map( mapSquareHoleWorkToPlatformGalleryCard, ), @@ -3419,6 +3510,7 @@ export function PlatformEntryFlowShellImpl({ puzzleGalleryEntries, squareHoleGalleryEntries, visualNovelGalleryEntries, + woodenFishGalleryEntries, ], ); const recommendRuntimeEntries = useMemo(() => { @@ -5748,6 +5840,18 @@ export function PlatformEntryFlowShellImpl({ return; } + if (type === 'wooden-fish') { + enterCreateTab(); + setShowCreationTypeModal(false); + setActiveCreationFormType('wooden-fish'); + setWoodenFishError(null); + setWoodenFishSession(null); + setWoodenFishWork(null); + setWoodenFishRun(null); + setWoodenFishGenerationState(null); + return; + } + if (type === 'puzzle') { enterCreateTab(); setShowCreationTypeModal(false); @@ -5804,6 +5908,11 @@ export function PlatformEntryFlowShellImpl({ setJumpHopRun, setJumpHopSession, setJumpHopWork, + setWoodenFishError, + setWoodenFishGenerationState, + setWoodenFishRun, + setWoodenFishSession, + setWoodenFishWork, setVisualNovelError, ], ); @@ -5843,6 +5952,16 @@ export function PlatformEntryFlowShellImpl({ setSelectionStage('platform'); }, [setSelectionStage]); + const leaveWoodenFishFlow = useCallback(() => { + setWoodenFishRun(null); + setWoodenFishWork(null); + setWoodenFishRuntimeReturnStage('wooden-fish-result'); + setWoodenFishGenerationState(null); + setWoodenFishSession(null); + setWoodenFishError(null); + setSelectionStage('platform'); + }, [setSelectionStage]); + const createReadyJumpHopGenerationState = useCallback( (state: MiniGameDraftGenerationState) => resolveFinishedMiniGameDraftGenerationState(state, 'ready', { @@ -5852,6 +5971,15 @@ export function PlatformEntryFlowShellImpl({ [], ); + const createReadyWoodenFishGenerationState = useCallback( + (state: MiniGameDraftGenerationState) => + resolveFinishedMiniGameDraftGenerationState(state, 'ready', { + completedAssetCount: 2, + totalAssetCount: 2, + }), + [], + ); + const leaveBarkBattleFlow = useCallback(() => { setBarkBattlePublishedConfig(null); setBarkBattleError(null); @@ -6844,6 +6972,325 @@ export function PlatformEntryFlowShellImpl({ [jumpHopRun?.runId], ); + const compileWoodenFishSession = useCallback( + async ( + created: WoodenFishSessionResponse, + payload?: WoodenFishWorkspaceCreateRequest, + ) => { + const generationState = createMiniGameDraftGenerationState('wooden-fish'); + setWoodenFishError(null); + setWoodenFishSession(created.session); + setWoodenFishWork(null); + setWoodenFishRun(null); + setWoodenFishGenerationState(generationState); + setIsWoodenFishBusy(true); + setSelectionStage('wooden-fish-generating'); + + try { + const response = await woodenFishClient.executeAction( + created.session.sessionId, + { + actionType: 'compile-draft', + workTitle: payload?.workTitle ?? created.session.draft?.workTitle, + workDescription: + payload?.workDescription ?? + created.session.draft?.workDescription, + themeTags: payload?.themeTags ?? created.session.draft?.themeTags, + hitObjectPrompt: + payload?.hitObjectPrompt ?? + created.session.draft?.hitObjectPrompt, + hitObjectReferenceImageSrc: + payload?.hitObjectReferenceImageSrc ?? + created.session.draft?.hitObjectReferenceImageSrc, + hitSoundPrompt: + payload?.hitSoundPrompt ?? created.session.draft?.hitSoundPrompt, + hitSoundAsset: + payload?.hitSoundAsset ?? created.session.draft?.hitSoundAsset, + floatingWords: + payload?.floatingWords ?? created.session.draft?.floatingWords, + }, + ); + setWoodenFishSession(response.session); + setWoodenFishWork(response.work ?? null); + setWoodenFishGenerationState( + createReadyWoodenFishGenerationState(generationState), + ); + setSelectionStage('wooden-fish-result'); + } catch (error) { + const errorMessage = resolveRpgCreationErrorMessage( + error, + 'ç”Ÿæˆæ•²æœ¨é±¼è‰ç¨¿å¤±è´¥ã€‚', + ); + setWoodenFishError(errorMessage); + setWoodenFishGenerationState( + resolveFinishedMiniGameDraftGenerationState( + generationState, + 'failed', + { error: errorMessage }, + ), + ); + try { + const latest = await woodenFishClient.getSession( + created.session.sessionId, + ); + setWoodenFishSession(latest.session); + setWoodenFishWork(null); + } catch { + setWoodenFishSession(created.session); + setWoodenFishWork(null); + } + } finally { + setIsWoodenFishBusy(false); + } + }, + [createReadyWoodenFishGenerationState, setSelectionStage], + ); + + const retryWoodenFishDraftGeneration = useCallback(() => { + if (!woodenFishSession) { + setSelectionStage('wooden-fish-workspace'); + return; + } + + void compileWoodenFishSession({ session: woodenFishSession }); + }, [compileWoodenFishSession, setSelectionStage, woodenFishSession]); + + const regenerateWoodenFishAsset = useCallback( + async (actionType: 'regenerate-hit-object' | 'generate-hit-sound') => { + if (!woodenFishSession?.sessionId) { + setSelectionStage('wooden-fish-workspace'); + return; + } + + const generationState = createMiniGameDraftGenerationState('wooden-fish'); + setWoodenFishError(null); + setWoodenFishGenerationState(generationState); + setIsWoodenFishBusy(true); + setSelectionStage('wooden-fish-generating'); + try { + const response = await woodenFishClient.executeAction( + woodenFishSession.sessionId, + { + actionType, + workTitle: woodenFishSession.draft?.workTitle, + workDescription: woodenFishSession.draft?.workDescription, + themeTags: woodenFishSession.draft?.themeTags, + hitObjectPrompt: woodenFishSession.draft?.hitObjectPrompt, + hitObjectReferenceImageSrc: + woodenFishSession.draft?.hitObjectReferenceImageSrc, + hitSoundPrompt: woodenFishSession.draft?.hitSoundPrompt, + hitSoundAsset: woodenFishSession.draft?.hitSoundAsset, + floatingWords: woodenFishSession.draft?.floatingWords, + }, + ); + setWoodenFishSession(response.session); + setWoodenFishWork(response.work ?? woodenFishWork); + setWoodenFishGenerationState( + createReadyWoodenFishGenerationState(generationState), + ); + setSelectionStage('wooden-fish-result'); + } catch (error) { + const errorMessage = resolveRpgCreationErrorMessage( + error, + actionType === 'regenerate-hit-object' + ? '釿–°ç”Ÿæˆæ•²å‡»ç‰©å›¾æ¡ˆå¤±è´¥ã€‚' + : 'ç”Ÿæˆæ•²å‡»éŸ³æ•ˆå¤±è´¥ã€‚', + ); + setWoodenFishError(errorMessage); + setWoodenFishGenerationState( + resolveFinishedMiniGameDraftGenerationState( + generationState, + 'failed', + { error: errorMessage }, + ), + ); + } finally { + setIsWoodenFishBusy(false); + } + }, + [ + createReadyWoodenFishGenerationState, + setSelectionStage, + woodenFishSession?.draft, + woodenFishSession?.sessionId, + woodenFishWork, + ], + ); + + const publishWoodenFishDraft = useCallback(async () => { + const profileId = woodenFishWork?.summary.profileId?.trim(); + if (!profileId) { + setWoodenFishError('敲木鱼è‰ç¨¿å°šæœªç”Ÿæˆå¯å‘布作å“。'); + setSelectionStage('wooden-fish-result'); + return; + } + + setIsWoodenFishBusy(true); + setWoodenFishError(null); + try { + const response = await woodenFishClient.publishWork(profileId); + setWoodenFishWork(response.item); + openPublishShareModal({ + title: response.item.summary.workTitle || '敲木鱼', + publicWorkCode: buildWoodenFishPublicWorkCode( + response.item.summary.profileId, + ), + stage: 'work-detail', + }); + } catch (error) { + setWoodenFishError( + resolveRpgCreationErrorMessage(error, 'å‘布敲木鱼作å“失败。'), + ); + setSelectionStage('wooden-fish-result'); + } finally { + setIsWoodenFishBusy(false); + } + }, [ + openPublishShareModal, + setSelectionStage, + woodenFishWork?.summary.profileId, + ]); + + const startWoodenFishTestRunFromProfile = useCallback(async () => { + const profileId = woodenFishWork?.summary.profileId?.trim(); + if (!profileId) { + setWoodenFishError('敲木鱼è‰ç¨¿å°šæœªç”Ÿæˆå¯è¯•玩作å“。'); + setSelectionStage('wooden-fish-result'); + return; + } + + setIsWoodenFishBusy(true); + setWoodenFishError(null); + setWoodenFishRuntimeReturnStage('wooden-fish-result'); + try { + const response = await woodenFishClient.startRun(profileId); + setWoodenFishRun(response.run); + setSelectionStage('wooden-fish-runtime'); + } catch (error) { + setWoodenFishError( + error instanceof Error ? error.message : 'å¯åŠ¨æ•²æœ¨é±¼è¯•çŽ©å¤±è´¥ã€‚', + ); + setSelectionStage('wooden-fish-result'); + } finally { + setIsWoodenFishBusy(false); + } + }, [setSelectionStage, woodenFishWork?.summary.profileId]); + + const startWoodenFishRunFromProfile = useCallback( + async ( + profileId: string, + options: { + embedded?: boolean; + returnStage?: 'work-detail' | 'platform'; + } = {}, + ) => { + const normalizedProfileId = profileId.trim(); + if (!normalizedProfileId) { + setWoodenFishError('当剿•²æœ¨é±¼ä½œå“ä¿¡æ¯ä¸å®Œæ•´ï¼Œæš‚时无法进入玩法。'); + return false; + } + + setIsWoodenFishBusy(true); + setWoodenFishError(null); + setWoodenFishRuntimeReturnStage(options.returnStage ?? 'work-detail'); + try { + const [detail, runResponse] = await Promise.all([ + woodenFishClient.getWorkDetail(normalizedProfileId).catch(() => null), + woodenFishClient.startRun(normalizedProfileId), + ]); + if (detail?.item) { + setWoodenFishWork(detail.item); + } + setWoodenFishRun(runResponse.run); + if (!options.embedded) { + setSelectionStage('wooden-fish-runtime'); + pushAppHistoryPath( + buildPublicWorkStagePath( + 'wooden-fish-runtime', + buildWoodenFishPublicWorkCode(normalizedProfileId), + ), + ); + } + return true; + } catch (error) { + setWoodenFishError( + resolveRpgCreationErrorMessage(error, 'å¯åŠ¨æ•²æœ¨é±¼çŽ©æ³•å¤±è´¥ã€‚'), + ); + return false; + } finally { + setIsWoodenFishBusy(false); + } + }, + [setSelectionStage], + ); + + const restartWoodenFishRuntimeRun = useCallback(async () => { + const profileId = + woodenFishRun?.profileId?.trim() ?? + woodenFishWork?.summary.profileId?.trim(); + if (!profileId) { + await startWoodenFishTestRunFromProfile(); + return; + } + + setIsWoodenFishBusy(true); + setWoodenFishError(null); + try { + const response = await woodenFishClient.startRun(profileId); + setWoodenFishRun(response.run); + } catch (error) { + setWoodenFishError( + resolveRpgCreationErrorMessage(error, '釿–°å¼€å§‹æ•²æœ¨é±¼å¤±è´¥ã€‚'), + ); + } finally { + setIsWoodenFishBusy(false); + } + }, [ + startWoodenFishTestRunFromProfile, + woodenFishRun?.profileId, + woodenFishWork?.summary.profileId, + ]); + + const checkpointWoodenFishRuntimeRun = useCallback( + async (payload: { + totalTapCount: number; + wordCounters: WoodenFishRunResponse['run']['wordCounters']; + }) => { + const runId = woodenFishRun?.runId; + if (!runId) { + return; + } + const response = await woodenFishClient.checkpointRun(runId, payload); + setWoodenFishRun(response.run); + }, + [woodenFishRun?.runId], + ); + + const finishWoodenFishRuntimeRun = useCallback( + async (payload: { + totalTapCount: number; + wordCounters: WoodenFishRunResponse['run']['wordCounters']; + }) => { + const runId = woodenFishRun?.runId; + if (!runId) { + return; + } + setIsWoodenFishBusy(true); + setWoodenFishError(null); + try { + const response = await woodenFishClient.finishRun(runId, payload); + setWoodenFishRun(response.run); + } catch (error) { + setWoodenFishError( + resolveRpgCreationErrorMessage(error, 'ç»“æŸæ•²æœ¨é±¼å¤±è´¥ã€‚'), + ); + } finally { + setIsWoodenFishBusy(false); + } + }, + [woodenFishRun?.runId], + ); + const executePuzzleAction = puzzleFlow.executeAction; const executePuzzleBackgroundAction = useCallback( @@ -9089,6 +9536,28 @@ export function PlatformEntryFlowShellImpl({ [openPublicWorkDetail, setJumpHopError, setSelectionStage], ); + const openWoodenFishPublicWorkDetail = useCallback( + async (profileId: string) => { + setIsPublicWorkDetailBusy(true); + setWoodenFishError(null); + setPublicWorkDetailError(null); + setSelectionStage('work-detail'); + + try { + const detail = await woodenFishClient.getWorkDetail(profileId); + setWoodenFishWork(detail.item); + openPublicWorkDetail(mapWoodenFishWorkToPublicWorkDetail(detail.item)); + } catch (error) { + setPublicWorkDetailError( + resolveRpgCreationErrorMessage(error, 'è¯»å–æ•²æœ¨é±¼è¯¦æƒ…失败。'), + ); + } finally { + setIsPublicWorkDetailBusy(false); + } + }, + [openPublicWorkDetail, setSelectionStage], + ); + const openPublicGalleryDetail = useCallback( (entry: PlatformPublicGalleryCard) => { if (isBigFishGalleryEntry(entry)) { @@ -9118,6 +9587,11 @@ export function PlatformEntryFlowShellImpl({ return; } + if (isWoodenFishGalleryEntry(entry)) { + void openWoodenFishPublicWorkDetail(entry.profileId); + return; + } + if (isVisualNovelGalleryEntry(entry)) { void openVisualNovelPublicWorkDetail(entry.profileId); return; @@ -9134,6 +9608,7 @@ export function PlatformEntryFlowShellImpl({ openPuzzlePublicWorkDetail, openPublicWorkDetail, openJumpHopPublicWorkDetail, + openWoodenFishPublicWorkDetail, openRpgPublicWorkDetail, openVisualNovelPublicWorkDetail, platformBootstrap.platformTab, @@ -9815,6 +10290,14 @@ export function PlatformEntryFlowShellImpl({ return; } + if (isWoodenFishGalleryEntry(selectedPublicWorkDetail)) { + setPublicWorkDetailError(null); + void startWoodenFishRunFromProfile(selectedPublicWorkDetail.profileId, { + returnStage: 'work-detail', + }); + return; + } + if (isMatch3DGalleryEntry(selectedPublicWorkDetail)) { const work = mapPublicWorkDetailToMatch3DWork(selectedPublicWorkDetail); if (!work) { @@ -9900,6 +10383,7 @@ export function PlatformEntryFlowShellImpl({ selectedPublicWorkDetail, startBigFishRunFromWork, startJumpHopRunFromProfile, + startWoodenFishRunFromProfile, startPuzzleRunFromProfile, startMatch3DRunFromProfile, startSquareHoleRunFromProfile, @@ -9959,6 +10443,11 @@ export function PlatformEntryFlowShellImpl({ embedded: true, returnStage: 'platform', }); + } else if (isWoodenFishGalleryEntry(entry)) { + started = await startWoodenFishRunFromProfile(entry.profileId, { + embedded: true, + returnStage: 'platform', + }); } else if (isMatch3DGalleryEntry(entry)) { const work = mapPublicWorkDetailToMatch3DWork(entry); if (!work) { @@ -10037,6 +10526,7 @@ export function PlatformEntryFlowShellImpl({ setSquareHoleError, startBigFishRunFromWork, startJumpHopRunFromProfile, + startWoodenFishRunFromProfile, startMatch3DRunFromProfile, startPuzzleRunFromProfile, startSquareHoleRunFromProfile, @@ -10285,6 +10775,25 @@ export function PlatformEntryFlowShellImpl({ ); } + if (activeRecommendRuntimeKind === 'wooden-fish') { + return ( + { + setActiveRecommendRuntimeKind(null); + }} + onRestart={() => { + void restartWoodenFishRuntimeRun(); + }} + onCheckpoint={checkpointWoodenFishRuntimeRun} + onFinish={finishWoodenFishRuntimeRun} + /> + ); + } + if (activeRecommendRuntimeKind === 'square-hole') { return ( { @@ -10487,6 +11003,7 @@ export function PlatformEntryFlowShellImpl({ puzzleRun, squareHoleRun, visualNovelRun, + woodenFishRun, }); if ( (activeRecommendEntry !== null && isActiveRecommendRuntimeReady) || @@ -10518,6 +11035,7 @@ export function PlatformEntryFlowShellImpl({ selectionStage, squareHoleRun, visualNovelRun, + woodenFishRun, ]); const remixPublicWork = useCallback( @@ -10586,6 +11104,12 @@ export function PlatformEntryFlowShellImpl({ return; } + if (isWoodenFishGalleryEntry(entry)) { + setPublicWorkDetailError('æ•²æœ¨é±¼ä½œå“æ”¹é€ å°†åœ¨åŽç»­ç‰ˆæœ¬å¼€æ”¾ã€‚'); + setIsPublicWorkDetailBusy(false); + return; + } + if (isVisualNovelGalleryEntry(entry)) { setPublicWorkDetailError('视觉å°è¯´ä½œå“改造将在åŽç»­ç‰ˆæœ¬å¼€æ”¾ã€‚'); setIsPublicWorkDetailBusy(false); @@ -10701,6 +11225,11 @@ export function PlatformEntryFlowShellImpl({ return; } + if (isWoodenFishGalleryEntry(entry)) { + setPublicWorkDetailError('è¿™ä»½æ•²æœ¨é±¼ä½œå“æš‚æ—¶è¯·ä»Žä½œå“架编辑。'); + return; + } + if (isVisualNovelGalleryEntry(entry)) { const matchedWork = visualNovelWorks.find( (work) => work.profileId === entry.profileId, @@ -10787,6 +11316,7 @@ export function PlatformEntryFlowShellImpl({ const shouldSearchBigFishFirst = upperKeyword.startsWith('BF'); const shouldSearchBabyObjectFirst = upperKeyword.startsWith('BO'); const shouldSearchJumpHopFirst = upperKeyword.startsWith('JH'); + const shouldSearchWoodenFishFirst = upperKeyword.startsWith('WF'); const shouldSearchMatch3DFirst = upperKeyword.startsWith('M3'); const shouldSearchPuzzleFirst = upperKeyword.startsWith('PZ'); const shouldSearchSquareHoleFirst = upperKeyword.startsWith('SH'); @@ -10796,6 +11326,7 @@ export function PlatformEntryFlowShellImpl({ !shouldSearchBabyObjectFirst && !shouldSearchBigFishFirst && !shouldSearchJumpHopFirst && + !shouldSearchWoodenFishFirst && !shouldSearchMatch3DFirst && !shouldSearchPuzzleFirst && !shouldSearchSquareHoleFirst && @@ -10808,6 +11339,7 @@ export function PlatformEntryFlowShellImpl({ !shouldSearchBigFishFirst && !shouldSearchBabyObjectFirst && !shouldSearchJumpHopFirst && + !shouldSearchWoodenFishFirst && !shouldSearchMatch3DFirst && !shouldSearchPuzzleFirst && !shouldSearchSquareHoleFirst && @@ -10904,6 +11436,25 @@ export function PlatformEntryFlowShellImpl({ openPublicWorkDetail(mapJumpHopWorkToPublicWorkDetail(matchedEntry)); }; + const tryOpenWoodenFishGalleryEntry = async () => { + const entries = + woodenFishGalleryEntries.length > 0 + ? woodenFishGalleryEntries + : await refreshWoodenFishGallery(); + const matchedEntry = entries.find((entry) => { + const detailEntry = mapWoodenFishWorkToPublicWorkDetail(entry); + return ( + canExposePublicWork(detailEntry) && + isSameWoodenFishPublicWorkCode(normalizedKeyword, entry.profileId) + ); + }); + + if (!matchedEntry) { + throw new Error('未找到敲木鱼作å“。'); + } + + openPublicWorkDetail(mapWoodenFishWorkToPublicWorkDetail(matchedEntry)); + }; const tryOpenMatch3DGalleryEntry = async () => { const entries = match3dGalleryEntries.length > 0 @@ -11011,6 +11562,11 @@ export function PlatformEntryFlowShellImpl({ return; } + if (shouldSearchWoodenFishFirst) { + await tryOpenWoodenFishGalleryEntry(); + return; + } + if (shouldSearchBabyObjectFirst) { await tryOpenBabyObjectMatchGalleryEntry(); return; @@ -11093,6 +11649,7 @@ export function PlatformEntryFlowShellImpl({ puzzleGalleryEntries, refreshBigFishGallery, refreshJumpHopGallery, + refreshWoodenFishGallery, refreshPuzzleGallery, refreshSquareHoleGallery, refreshVisualNovelGallery, @@ -11102,6 +11659,7 @@ export function PlatformEntryFlowShellImpl({ setPuzzleError, setSelectionStage, visualNovelGalleryEntries, + woodenFishGalleryEntries, ], ); @@ -11176,6 +11734,19 @@ export function PlatformEntryFlowShellImpl({ return; } + if ( + worldType === 'wooden-fish' || + worldType === 'wooden_fish' || + work.worldKey.startsWith('wooden-fish:') + ) { + const profileId = + work.profileId ?? work.worldKey.replace(/^wooden-fish:/u, ''); + if (profileId) { + void openWoodenFishPublicWorkDetail(profileId); + } + return; + } + if ( worldType === 'big_fish' || worldType === 'big-fish' || @@ -11257,6 +11828,7 @@ export function PlatformEntryFlowShellImpl({ openPuzzlePublicWorkDetail, openPublicWorkDetail, openJumpHopPublicWorkDetail, + openWoodenFishPublicWorkDetail, openRpgPublicWorkDetail, openSquareHolePublicWorkDetail, refreshBigFishGallery, @@ -11284,6 +11856,7 @@ export function PlatformEntryFlowShellImpl({ void refreshBigFishGallery(); } void refreshJumpHopGallery(); + void refreshWoodenFishGallery(); void refreshMatch3DGallery(); void refreshPuzzleGallery(); if (isSquareHoleCreationVisible) { @@ -11299,6 +11872,7 @@ export function PlatformEntryFlowShellImpl({ isVisualNovelCreationOpen, refreshBigFishGallery, refreshJumpHopGallery, + refreshWoodenFishGallery, refreshMatch3DGallery, refreshPuzzleGallery, refreshSquareHoleGallery, @@ -11409,6 +11983,7 @@ export function PlatformEntryFlowShellImpl({ setPuzzleError(null); setVisualNovelError(null); setBabyObjectMatchError(null); + setWoodenFishError(null); void platformBootstrap.refreshCustomWorldWorks().catch((error) => { platformBootstrap.setPlatformError( resolveRpgCreationErrorMessage(error, '读å–创作作å“列表失败。'), @@ -11433,6 +12008,7 @@ export function PlatformEntryFlowShellImpl({ bigFishError ?? match3dError ?? (isSquareHoleCreationVisible ? squareHoleError : null) ?? + woodenFishError ?? puzzleCreationError ?? puzzleError ?? (isVisualNovelCreationOpen ? visualNovelError : null) ?? @@ -11446,6 +12022,7 @@ export function PlatformEntryFlowShellImpl({ isBigFishBusy || isMatch3DBusy || (isSquareHoleCreationVisible && isSquareHoleBusy) || + isWoodenFishBusy || isPuzzleBusy || (isVisualNovelCreationOpen && isVisualNovelBusy) || (isVisualNovelCreationOpen && isVisualNovelStreamingReply) || @@ -11718,6 +12295,19 @@ export function PlatformEntryFlowShellImpl({ }} /> + ) : activeCreationFormType === 'wooden-fish' ? ( + } + > + { + void compileWoodenFishSession(result, payload); + }} + /> + ) : ( } @@ -11821,7 +12411,8 @@ export function PlatformEntryFlowShellImpl({ isPuzzleBusy || isMatch3DBusy || isSquareHoleBusy || - isVisualNovelBusy + isVisualNovelBusy || + isWoodenFishBusy } recommendRuntimeError={activeRecommendRuntimeError} onSelectNextRecommendEntry={() => @@ -12973,6 +13564,137 @@ export function PlatformEntryFlowShellImpl({ )} + {selectionStage === 'wooden-fish-workspace' && ( + + } + > + { + void compileWoodenFishSession(result, payload); + }} + /> + + + )} + + {selectionStage === 'wooden-fish-generating' && ( + + } + > + { + setSelectionStage('wooden-fish-workspace'); + }} + onRetry={retryWoodenFishDraftGeneration} + onInterrupt={undefined} + backLabel="返回创作中心" + settingActionLabel={null} + retryLabel="釿–°ç”Ÿæˆè‰ç¨¿" + settingTitle="当剿•²æœ¨é±¼ä¿¡æ¯" + settingDescription={null} + progressTitle="敲木鱼è‰ç¨¿ç”Ÿæˆè¿›åº¦" + activeBadgeLabel="ç´ æç”Ÿæˆä¸­" + pausedBadgeLabel="ç´ æç”Ÿæˆå·²æš‚åœ" + idleBadgeLabel="等待返回工作区" + /> + + + )} + + {selectionStage === 'wooden-fish-result' && + woodenFishSession?.draft && ( + + } + > + { + setSelectionStage('wooden-fish-workspace'); + }} + onStartTestRun={startWoodenFishTestRunFromProfile} + onPublish={publishWoodenFishDraft} + onRegenerateHitObject={() => { + void regenerateWoodenFishAsset('regenerate-hit-object'); + }} + onGenerateHitSound={() => { + void regenerateWoodenFishAsset('generate-hit-sound'); + }} + /> + + + )} + + {selectionStage === 'wooden-fish-runtime' && ( + + } + > + { + setSelectionStage(woodenFishRuntimeReturnStage); + }} + onRestart={() => { + void restartWoodenFishRuntimeRun(); + }} + onCheckpoint={checkpointWoodenFishRuntimeRun} + onFinish={finishWoodenFishRuntimeRun} + /> + + + )} + {selectionStage === 'creative-agent-workspace' && ( { handleCreationHubCreateType('jump-hop'); }} + onSelectWoodenFish={() => { + handleCreationHubCreateType('wooden-fish'); + }} onSelectCreativeAgent={() => { runProtectedAction(() => { void openCreativeAgentWorkspace(); diff --git a/src/components/platform-entry/platformEntryTypes.ts b/src/components/platform-entry/platformEntryTypes.ts index 938c1f5a..67c426c4 100644 --- a/src/components/platform-entry/platformEntryTypes.ts +++ b/src/components/platform-entry/platformEntryTypes.ts @@ -36,6 +36,10 @@ export type SelectionStage = | 'jump-hop-result' | 'jump-hop-runtime' | 'jump-hop-gallery-detail' + | 'wooden-fish-workspace' + | 'wooden-fish-generating' + | 'wooden-fish-result' + | 'wooden-fish-runtime' | 'bark-battle-runtime' | 'creative-agent-workspace' | 'visual-novel-agent-workspace' diff --git a/src/components/rpg-entry/RpgEntryHomeView.tsx b/src/components/rpg-entry/RpgEntryHomeView.tsx index 782ddf4e..36684ae9 100644 --- a/src/components/rpg-entry/RpgEntryHomeView.tsx +++ b/src/components/rpg-entry/RpgEntryHomeView.tsx @@ -133,6 +133,7 @@ import { isPuzzleGalleryEntry, isSquareHoleGalleryEntry, isVisualNovelGalleryEntry, + isWoodenFishGalleryEntry, type PlatformPublicGalleryCard, type PlatformWorldCardLike, resolvePlatformPublicWorkCode, @@ -1843,22 +1844,31 @@ async function getPublicWorkAuthorSummary( } function describePublicGalleryCardKind(entry: PlatformPublicGalleryCard) { - const kind = isBigFishGalleryEntry(entry) - ? '大鱼' - : isPuzzleGalleryEntry(entry) - ? '拼图' - : isMatch3DGalleryEntry(entry) - ? '抓鹅' - : isSquareHoleGalleryEntry(entry) - ? '方洞' - : isJumpHopGalleryEntry(entry) - ? '跳一跳' - : isVisualNovelGalleryEntry(entry) - ? '视觉' - : isEdutainmentGalleryEntry(entry) - ? entry.templateName - : describePlatformThemeLabel(entry.themeMode); - return formatPlatformWorkDisplayTag(kind); + if (isBigFishGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag('大鱼'); + } + if (isPuzzleGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag('拼图'); + } + if (isMatch3DGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag('抓鹅'); + } + if (isSquareHoleGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag('方洞'); + } + if (isJumpHopGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag('跳一跳'); + } + if (isWoodenFishGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag('敲木鱼'); + } + if (isVisualNovelGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag('视觉'); + } + if (isEdutainmentGalleryEntry(entry)) { + return formatPlatformWorkDisplayTag(entry.templateName); + } + return formatPlatformWorkDisplayTag(describePlatformThemeLabel(entry.themeMode)); } function getPublicAuthorAvatarLabel(authorDisplayName: string) { diff --git a/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts b/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts index 8abc1fe3..07f7d1c1 100644 --- a/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts +++ b/src/components/rpg-entry/rpgEntryWorldPresentation.test.ts @@ -10,8 +10,10 @@ import { formatPlatformWorldTime, isEdutainmentGalleryEntry, isVisualNovelGalleryEntry, + isWoodenFishGalleryEntry, mapBabyObjectMatchDraftToPlatformGalleryCard, mapVisualNovelWorkToPlatformGalleryCard, + mapWoodenFishWorkToPlatformGalleryCard, type PlatformEdutainmentGalleryCard, type PlatformPuzzleGalleryCard, resolvePlatformPublicWorkCode, @@ -165,6 +167,34 @@ test('maps visual novel work to platform gallery card with VN public code', () = expect(buildPlatformWorldDisplayTags(card, 2)).toEqual(['悬疑', '列车']); }); +test('maps wooden fish work to platform gallery card with WF public code', () => { + const card = mapWoodenFishWorkToPlatformGalleryCard({ + publicWorkCode: '', + workId: 'wooden-fish-work-1', + profileId: 'wooden-fish-profile-12345678', + ownerUserId: 'user-1', + authorDisplayName: '玩家', + workTitle: 'æ¯æ—¥ä¸€æ•²', + workDescription: '敲一下,好事å‘生。', + coverImageSrc: '/generated-wooden-fish-assets/profile/hit-object.png', + themeTags: [], + publicationStatus: 'published', + playCount: 12, + updatedAt: '2026-05-20T00:00:00.000Z', + publishedAt: '2026-05-20T00:00:00.000Z', + generationStatus: 'ready', + }); + + expect(isWoodenFishGalleryEntry(card)).toBe(true); + expect(card.sourceType).toBe('wooden-fish'); + expect(card.publicWorkCode).toBe('WF-12345678'); + expect(resolvePlatformPublicWorkCode(card)).toBe('WF-12345678'); + expect(resolvePlatformWorldFallbackCoverImage(card)).toBe( + '/wooden-fish/default-hit-object.png', + ); + expect(buildPlatformWorldDisplayTags(card, 2)).toEqual(['敲木鱼']); +}); + test('keeps baby object match public card code and template label intact', () => { const card: PlatformEdutainmentGalleryCard = { sourceType: 'edutainment', diff --git a/src/components/rpg-entry/rpgEntryWorldPresentation.ts b/src/components/rpg-entry/rpgEntryWorldPresentation.ts index 48871876..621703dd 100644 --- a/src/components/rpg-entry/rpgEntryWorldPresentation.ts +++ b/src/components/rpg-entry/rpgEntryWorldPresentation.ts @@ -22,6 +22,10 @@ import type { SquareHoleWorkSummary, } from '../../../packages/shared/src/contracts/squareHoleWorks'; import type { VisualNovelWorkSummary } from '../../../packages/shared/src/contracts/visualNovel'; +import type { + WoodenFishGalleryCardResponse, + WoodenFishWorkProfileResponse, +} from '../../../packages/shared/src/contracts/woodenFish'; import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets'; import { resolveCustomWorldCampSceneImage } from '../../data/customWorldVisuals'; import { @@ -32,7 +36,9 @@ import { buildPuzzlePublicWorkCode, buildSquareHolePublicWorkCode, buildVisualNovelPublicWorkCode, + buildWoodenFishPublicWorkCode, } from '../../services/publicWorkCode'; +import { WOODEN_FISH_DEFAULT_HIT_OBJECT_SRC } from '../../services/wooden-fish/woodenFishDefaults'; import type { CustomWorldProfile } from '../../types'; export const PLATFORM_WORK_NAME_DISPLAY_LIMIT = 8; @@ -48,6 +54,7 @@ export type PlatformWorldCardLike = | PlatformSquareHoleGalleryCard | PlatformPuzzleGalleryCard | PlatformJumpHopGalleryCard + | PlatformWoodenFishGalleryCard | PlatformVisualNovelGalleryCard | PlatformEdutainmentGalleryCard; @@ -202,6 +209,28 @@ export type PlatformJumpHopGalleryCard = { stylePreset?: string; }; +export type PlatformWoodenFishGalleryCard = { + sourceType: 'wooden-fish'; + workId: string; + profileId: string; + sourceSessionId?: string | null; + publicWorkCode: string; + ownerUserId: string; + authorDisplayName: string; + worldName: string; + subtitle: string; + summaryText: string; + coverImageSrc: string | null; + themeTags: string[]; + playCount?: number; + remixCount?: number; + likeCount?: number; + recentPlayCount7d?: number; + visibility: 'published'; + publishedAt: string | null; + updatedAt: string; +}; + export type PlatformEdutainmentGalleryCard = { sourceType: 'edutainment'; templateId: typeof EDUTAINMENT_BABY_OBJECT_MATCH_TEMPLATE_ID; @@ -233,6 +262,7 @@ export type PlatformPublicGalleryCard = | PlatformSquareHoleGalleryCard | PlatformPuzzleGalleryCard | PlatformJumpHopGalleryCard + | PlatformWoodenFishGalleryCard | PlatformVisualNovelGalleryCard | PlatformEdutainmentGalleryCard; @@ -278,6 +308,12 @@ export function isJumpHopGalleryEntry( return 'sourceType' in entry && entry.sourceType === 'jump-hop'; } +export function isWoodenFishGalleryEntry( + entry: PlatformWorldCardLike, +): entry is PlatformWoodenFishGalleryCard { + return 'sourceType' in entry && entry.sourceType === 'wooden-fish'; +} + export function isEdutainmentGalleryEntry( entry: PlatformWorldCardLike, ): entry is PlatformEdutainmentGalleryCard { @@ -472,6 +508,39 @@ export function mapJumpHopWorkToPlatformGalleryCard( }; } +export function mapWoodenFishWorkToPlatformGalleryCard( + work: WoodenFishGalleryCardResponse | WoodenFishWorkProfileResponse, +): PlatformWoodenFishGalleryCard { + const summary = 'summary' in work ? work.summary : work; + + return { + sourceType: 'wooden-fish', + workId: summary.workId, + profileId: summary.profileId, + sourceSessionId: + 'sourceSessionId' in summary ? (summary.sourceSessionId ?? null) : null, + publicWorkCode: + 'publicWorkCode' in summary && summary.publicWorkCode.trim() + ? summary.publicWorkCode + : buildWoodenFishPublicWorkCode(summary.profileId), + ownerUserId: summary.ownerUserId, + authorDisplayName: + 'authorDisplayName' in summary ? summary.authorDisplayName : '玩家', + worldName: summary.workTitle, + subtitle: '敲木鱼', + summaryText: summary.workDescription, + coverImageSrc: summary.coverImageSrc ?? null, + themeTags: summary.themeTags.length > 0 ? summary.themeTags : ['敲木鱼'], + playCount: summary.playCount ?? 0, + remixCount: 0, + likeCount: 0, + recentPlayCount7d: 0, + visibility: 'published', + publishedAt: summary.publishedAt ?? null, + updatedAt: summary.updatedAt, + }; +} + export function mapBabyObjectMatchDraftToPlatformGalleryCard( draft: BabyObjectMatchDraft, ): PlatformEdutainmentGalleryCard { @@ -553,6 +622,10 @@ export function resolvePlatformWorldFallbackCoverImage( return '/creation-type-references/jump-hop.webp'; } + if (isWoodenFishGalleryEntry(entry)) { + return WOODEN_FISH_DEFAULT_HIT_OBJECT_SRC; + } + if (isBigFishGalleryEntry(entry)) { return '/creation-type-references/big-fish.webp'; } @@ -722,6 +795,12 @@ export function buildPlatformWorldTags(entry: PlatformWorldCardLike) { : ['跳一跳']; } + if (isWoodenFishGalleryEntry(entry)) { + return entry.themeTags.length > 0 + ? entry.themeTags.slice(0, 3) + : ['敲木鱼']; + } + if (isEdutainmentGalleryEntry(entry)) { return entry.themeTags.length > 0 ? entry.themeTags.slice(0, 3) @@ -818,6 +897,10 @@ export function resolvePlatformPublicWorkCode( return entry.publicWorkCode; } + if (isWoodenFishGalleryEntry(entry)) { + return entry.publicWorkCode; + } + if (isEdutainmentGalleryEntry(entry)) { return entry.publicWorkCode; } diff --git a/src/components/wooden-fish-creation/WoodenFishWorkspace.test.tsx b/src/components/wooden-fish-creation/WoodenFishWorkspace.test.tsx new file mode 100644 index 00000000..600f5708 --- /dev/null +++ b/src/components/wooden-fish-creation/WoodenFishWorkspace.test.tsx @@ -0,0 +1,25 @@ +/* @vitest-environment jsdom */ + +import { render, screen, within } from '@testing-library/react'; +import { expect, test } from 'vitest'; + +import { WoodenFishWorkspace } from './WoodenFishWorkspace'; + +test('åŠŸå¾·æœ‰ä»€ä¹ˆé»˜è®¤åªæ˜¾ç¤ºåŸºç¡€è¯æ¡ï¼Œä¸æ˜¾ç¤ºè¿è¡Œæ€ +1 åŽç¼€', () => { + render( + {}} + onSubmitted={() => {}} + />, + ); + + const sectionTitle = screen.getByText('功德有什么'); + const section = sectionTitle.closest('section'); + + expect(section).not.toBeNull(); + expect(within(section as HTMLElement).getByDisplayValue('幸è¿')).toBeTruthy(); + expect(within(section as HTMLElement).getByDisplayValue('å¥åº·')).toBeTruthy(); + expect(within(section as HTMLElement).getByDisplayValue('财富')).toBeTruthy(); + expect(within(section as HTMLElement).queryByDisplayValue('幸è¿+1')).toBeNull(); + expect(within(section as HTMLElement).queryByDisplayValue('功德+1')).toBeNull(); +}); diff --git a/src/components/wooden-fish-creation/WoodenFishWorkspace.tsx b/src/components/wooden-fish-creation/WoodenFishWorkspace.tsx new file mode 100644 index 00000000..8a863496 --- /dev/null +++ b/src/components/wooden-fish-creation/WoodenFishWorkspace.tsx @@ -0,0 +1,534 @@ +import { + ArrowLeft, + Loader2, + Mic, + Pause, + Send, + Upload, +} from 'lucide-react'; +import { useMemo, useRef, useState } from 'react'; + +import type { + WoodenFishAudioAsset, + WoodenFishSessionResponse, + WoodenFishWorkspaceCreateRequest, +} from '../../../packages/shared/src/contracts/woodenFish'; +import { readPuzzleReferenceImageAsDataUrl } from '../../services/puzzleReferenceImage'; +import { woodenFishClient } from '../../services/wooden-fish/woodenFishClient'; +import { WOODEN_FISH_DEFAULT_HIT_OBJECT_PROMPT } from '../../services/wooden-fish/woodenFishDefaults'; +import { CreativeImageInputPanel } from '../common/CreativeImageInputPanel'; + +type WoodenFishWorkspaceProps = { + isBusy?: boolean; + error?: string | null; + onBack: () => void; + onSubmitted: ( + result: WoodenFishSessionResponse, + payload: WoodenFishWorkspaceCreateRequest, + ) => void; +}; + +type WoodenFishWorkspaceFormState = { + workTitle: string; + workDescription: string; + themeTags: string; + hitObjectPrompt: string; + hitObjectReferenceImageSrc: string; + hitSoundPrompt: string; + hitSoundAsset: WoodenFishAudioAsset | null; + floatingWords: string[]; +}; + +const DEFAULT_FLOATING_WORDS = [ + '幸è¿', + 'å¥åº·', + '财富', + '姻缘', + '幸ç¦', + '事业', + 'æˆåŠŸ', + '功德', +]; + +const DEFAULT_FORM_STATE: WoodenFishWorkspaceFormState = { + workTitle: '今日敲木鱼', + workDescription: '', + themeTags: '敲木鱼 解压', + hitObjectPrompt: WOODEN_FISH_DEFAULT_HIT_OBJECT_PROMPT, + hitObjectReferenceImageSrc: '', + hitSoundPrompt: '清脆短促的木鱼敲击声', + hitSoundAsset: null, + floatingWords: DEFAULT_FLOATING_WORDS, +}; + +function splitTags(value: string) { + return value + .split(/[,,ã€\s]+/u) + .map((item) => item.trim()) + .filter(Boolean) + .slice(0, 6); +} + +function normalizeFloatingWords(words: string[]) { + const seen = new Set(); + const normalized: string[] = []; + for (const word of words) { + const trimmed = word.trim().replace(/[++]\s*1$/u, '').trim(); + if (!trimmed || seen.has(trimmed)) { + continue; + } + seen.add(trimmed); + normalized.push(trimmed); + if (normalized.length >= 8) { + break; + } + } + return normalized.length > 0 ? normalized : DEFAULT_FLOATING_WORDS; +} + +function readAudioFileAsAsset(file: File, source: 'uploaded' | 'recorded') { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onerror = () => reject(new Error('音频读å–失败,请é‡è¯•。')); + reader.onload = () => { + if (typeof reader.result !== 'string') { + reject(new Error('音频读å–失败,请é‡è¯•。')); + return; + } + resolve({ + assetId: `local-${source}-${Date.now()}`, + audioSrc: reader.result, + audioObjectKey: '', + assetObjectId: '', + source, + prompt: file.name, + durationMs: null, + }); + }; + reader.readAsDataURL(file); + }); +} + +function WoodenFishAudioInputPanel({ + disabled, + prompt, + asset, + onPromptChange, + onAssetChange, + onError, +}: { + disabled: boolean; + prompt: string; + asset: WoodenFishAudioAsset | null; + onPromptChange: (value: string) => void; + onAssetChange: (asset: WoodenFishAudioAsset | null) => void; + onError: (message: string | null) => void; +}) { + const [isRecording, setIsRecording] = useState(false); + const recorderRef = useRef(null); + const chunksRef = useRef([]); + + const startRecording = async () => { + if (disabled || isRecording) { + return; + } + + try { + if ( + typeof navigator === 'undefined' || + !navigator.mediaDevices?.getUserMedia || + typeof MediaRecorder === 'undefined' + ) { + throw new Error('当剿µè§ˆå™¨ä¸æ”¯æŒå½•音。'); + } + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + const recorder = new MediaRecorder(stream); + chunksRef.current = []; + recorder.ondataavailable = (event) => { + if (event.data.size > 0) { + chunksRef.current.push(event.data); + } + }; + recorder.onstop = () => { + const blob = new Blob(chunksRef.current, { + type: recorder.mimeType || 'audio/webm', + }); + stream.getTracks().forEach((track) => track.stop()); + const file = new File([blob], `wooden-fish-hit-${Date.now()}.webm`, { + type: blob.type, + }); + void readAudioFileAsAsset(file, 'recorded') + .then(onAssetChange) + .catch((caughtError) => { + onError( + caughtError instanceof Error + ? caughtError.message + : '录音ä¿å­˜å¤±è´¥ã€‚', + ); + }); + }; + recorderRef.current = recorder; + recorder.start(); + setIsRecording(true); + onError(null); + } catch (caughtError) { + onError( + caughtError instanceof Error ? caughtError.message : '录音å¯åŠ¨å¤±è´¥ã€‚', + ); + } + }; + + const stopRecording = () => { + recorderRef.current?.stop(); + recorderRef.current = null; + setIsRecording(false); + }; + + return ( +
+
+
+ 敲击音效 +
+ {asset ? ( + + ) : null} +
+