Files
Genarrative/docs/technical/RPG_RUNTIME_POST_BATTLE_BACKEND_MIGRATION_2026-04-28.md
2026-04-28 19:36:39 +08:00

4.7 KiB
Raw Permalink Blame History

RPG 运行时战斗后处理后端迁移落地方案2026-04-28

目标

本方案承接 docs/audits/engineering/RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_AUDIT_2026-04-28.md 的 4.5 项,专门收口三类仍由前端补真相的逻辑:

  1. 战斗胜利 / 切磋完成后的正式 GameState 清理。
  2. 玩家死亡后的复活场景、血蓝恢复与首场景 act 状态。
  3. 战斗结束后章节 act 推进与 currentStory.deferredOptions 编排。

边界

后端负责:

  1. 根据 battle resolver 的 outcome 决定 victoryspar_completedefeatescaped 的最终状态。
  2. 写回 inBattlecurrentEncountersceneHostileNpcscurrentNpcBattleOutcomeplayerHpplayerManastoryEngineMemory.currentSceneActState
  3. 为死亡复活构造回到首场景的快照,并恢复 playerHp = playerMaxHpplayerMana = playerMaxMana
  4. 为胜利 / 切磋完成构造只含 story_continue_adventure 的当前 story并把真实后续 options 放入 deferredOptions
  5. 在最后一幕或无需等待继续按钮时直接返回场景旅行 / 常规 fallback options。

前端只负责:

  1. 播放 presentation.battle 对应动画。
  2. 使用 response.snapshot.gameStateresponse.snapshot.currentStory 渲染。
  3. 不再调用 buildPostBattleVictoryStatebuildPostBattleVictoryStorybuildRevivedFirstSceneStatebuildDeathStory 作为服务端动作后的正式状态。

后端落点

  1. server-rs/crates/module-runtime-story-compat/src/post_battle.rs
    • 增加纯 JSON helper迁移战斗后状态、复活和 scene act 推进。
  2. server-rs/crates/api-server/src/runtime_story/compat.rs
    • resolve_battle_action 之后、生成 AI fallback 之前统一调用 post-battle finalizer。
  3. server-rs/crates/api-server/src/runtime_story/compat/presentation.rs
    • 复用现有 option / current story 构造函数。
  4. packages/shared/src/contracts/rpgRuntimeStoryState.ts
    • battle outcome 增加 defeat,避免前端类型层把失败误判成非战斗终局。

落地补充

  1. 后端 post-battle finalizer 在 resolve_battle_action 之后、LLM fallback 之前执行,终局战斗不再生成额外 AI 文本。
  2. 胜利 / 切磋完成会清理战斗态并推进当前场景 act非最后一幕只展示 story_continue_adventure,真实后续动作写入 deferredOptions
  3. 败北复活会先写回首场景、回满血蓝、重置首场景 act再基于复活后的场景重新生成 deferredOptions,避免沿用战斗前旧场景选项。
  4. story engine 投影额外接收 battle outcome只有 victory / spar_complete 会记录胜利信号,defeat 不会被“战斗态从 true 变 false”误判成胜利。
  5. 前端 runServerRuntimeChoiceAction 的服务端路径不再调用 postBattleFlow 构造正式状态;死亡动画仍可短暂播放,但最终 GameState/currentStory 只采用后端 hydrated snapshot。

本轮收口记录

  1. choiceActions.ts 删除 shouldResolveCombatChoiceLocally(...)battle_* / inventory_use 不再因战斗可见态回落到本地 continuation。
  2. storyChoiceContinuation.tsbattle_* / inventory_use 以及被分类为 battle / escape 的动作加硬保护,误入时不会裁决掉落、复活、任务推进或战后 story。
  3. storyChoiceRuntime.ts 删除本地敌对 NPC 战斗奖励 helper前端不再调用 rollHostileNpcLoot(...)addInventoryItems(...) 生成正式战利品。
  4. 删除 postBattleFlow.ts 与其测试,前端不再保留死亡复活、胜利后 story、deferred options、章节推进的正式构造函数。
  5. choiceActions.test.ts 覆盖 battle_use_skill、stale battle_attack_basicinventory_use 全部进入后端 resolverstoryChoiceRuntime.test.ts 继续覆盖服务端胜利 / 失败 snapshot 被直接采用。

验收

  1. Rust 单测覆盖:
    • 服务端 battle victory 返回后,currentEncounter = nullinBattle = falsecurrentStory.options = [story_continue_adventure]deferredOptions 存在。
    • 服务端 battle defeat 返回后,玩家复活到首场景,playerHp/playerMana 回满,currentStory 为死亡复活故事。
  2. 前端单测覆盖:
    • runServerRuntimeChoiceActionvictorydefeat 都直接采用服务端 snapshot/story不再本地构造 post battle / revive 状态。
  3. 搜索确认 src/hooks/rpg-runtime-story 不再出现 shouldResolveCombatChoiceLocallybuildPostBattleVictory*buildRevivedFirstSceneStatebuildDeathStorybuildHostileNpcBattleReward
  4. Rust 单测覆盖:
    • story engine 对 defeat outcome 不写入 win_battle 信号和敌压 mutation。