前后端分工与多人云存档 · 2026-09-18
玩家体验优先:移动、输入反馈、镜头、动画和声音在前端即时执行;云端负责持久化、权限与必要的共享状态协调。正常移动不等待网络确认。
本文同时包含代码现状和设计方向,两者分别标注。多人和云存档是目标,具体同步协议、运行部署方式及共享世界规则尚未定稿。
版本与适用范围
- 当前实现依据游戏仓库
NevaMind-AI/remaining-time的dev提交fd06e631fcb49a47a6c6c2f030d1e6d4fbb7b5d0,适用于房间世界和酒馆本地模式。 - Agent 对照依据
feat/agentic提交a4e35e4b69d81dbf30a6b3d8464768e4266927d2,该分支的能力不代表已经接入上述本地模式。 - 这是代码阅读与设计记录,没有生产网络延迟、并发容量或帧率实测结果。后续实现可能调整本文的规划部分。
- 既有字段结构、内容组织与本地存储格式见世界架构 · 2026-09-15。该快照保留原版本依据。
当前实现:游戏在哪里运行
仓库有本地游戏与 Convex AI Town 两条入口。
| 启动命令 | 内容 | 游戏后端 |
|---|---|---|
just dev / npm run play:local | 当前房间世界,从 404 开始 | 不连接 Convex |
just dev-tavern / npm run play:tavern | 酒馆内容与玩法 | 不连接 Convex |
just dev-convex / npm run dev | Convex AI Town 模式 | 连接 Convex |
just dev 与 npm run dev 对应不同模式。本地模式由 src/lib/localMode.ts 识别,src/main.tsx 绕过 Convex Provider,src/App.tsx 加载 LocalGame。
| 功能 | 当前执行与保存位置 |
|---|---|
| 玩家移动、碰撞、场景切换 | 浏览器中的 MemoryWorld |
| 剧情选项、任务、交易、NPC 日程、服务与音乐练习 | 浏览器执行规则,具体能力由内容包启用 |
| 模拟时间、剧情时间、时间余额 | 浏览器计算,LocalGame 驱动推进 |
| 当前世界状态 | 浏览器内存 |
| 命令与状态记录 | 浏览器生成并暂存在内存,再写本地存档 |
| 自动存档 | 玩家设备上、当前网站来源下的浏览器私有文件系统 OPFS |
| 回放、校验、快照恢复 | 浏览器执行 |
| 剧本、地图、图片、音频 | 从静态资源服务加载到浏览器 |
prototype/world.ts 提供 execute() 和 advance();LocalGame 在浏览器里创建它的实例。规则模块本身主要不依赖浏览器,但当前执行位置是前端。
src/lib/autosaves.ts 使用 navigator.storage.getDirectory() 保存文件。当前房间与酒馆的存档分别使用本地目录;没有云端上传或跨设备同步。资产和内容的 HTTP 下载也不涉及服务端玩法计算。
仓库的 convex/ 已包含数据库、服务端世界循环、输入队列、LLM 对话与记忆代码。它们服务于 Convex 模式;启动一个 Convex 服务不会自动让本地游戏使用它。
设计方向:按体验和状态职责划分
目标是支持多用户、云存档,并保留即时操作体验。表中的“云端确认”指需要持久化或协调的事实,不要求界面为每次操作等待网络返回。
| 功能 | 前端职责 | 服务端职责 | 分工与延迟要求 |
|---|---|---|---|
| 身份与世界访问权限 | 登录与选择世界界面 | 认证、授权、校验操作角色 | 权限由服务端确认 |
| 玩家移动 | 即时执行移动,处理本地碰撞和操作手感 | 接收移动信息,做必要校验,协调共享位置与记录 | 前端执行;同步异步进行,正常移动不等待确认 |
| 动态门禁、多人占位 | 使用已同步状态响应,处理冲突反馈 | 协调冲突并返回结果 | 冲突修正方式待定,要避免频繁拉回角色 |
| 其他玩家和 NPC 的移动显示 | 平滑插值、播放动作 | 提供共享位置或路线更新 | 前端展示;允许受控的展示延后 |
| 镜头、缩放、悬停、选中、菜单 | 即时处理 | 通常无须参与 | 前端 |
| 动画、音效、音乐、粒子 | 即时播放与混音 | 必要时同步动作或曲目起点 | 前端;按键音效不等待网络 |
| 音乐练习 | 采集本地输入时刻,实时反馈与评分显示 | 校验并保存需要共享的成绩与奖励 | 不能直接用服务端收包时间代替按键发生时间 |
| 余额、库存、物品归属、交易 | 展示状态和操作反馈 | 校验并原子提交共享交易,保证重试不重复扣款 | 服务端确认正式收支;界面立即反馈处理状态 |
| 固定剧本文本、对白排版 | 缓存、展示与打字效果 | 提供内容版本和有权限访问的内容 | 文本可两边读取,展示优先本地 |
| 任务和剧情效果 | 即时展示、可运行本地条件预判 | 协调涉及共享事实、奖励和持久化的提交 | 计算位置可按场景选择,同一事实需明确提交归属 |
| NPC 日程、营业、服务 | 展示,也可承担独立世界的规则计算 | 共享世界中的一致推进与冲突协调 | 共享世界由统一运行入口推进;独立局的执行位置待定 |
| 寻路 | 玩家本地寻路、路线预览 | 共享 NPC 寻路或路线校验 | 算法可两边复用,按延迟与负载选择 |
| 游戏时间 | 平滑显示,消费统一的时间推进结果 | 保存时间基准,协调共享世界的推进、暂停与跳时 | 每局只有一个明确的推进权;部署位置按模式确定 |
| Agent / LLM | 展示等待或流式文本 | 密钥、模型调用、额度、结果校验与提交 | 服务端调用,生成期间不阻塞普通移动 |
| 随机结果 | 视觉随机;可执行受约束的本地玩法计算 | 确认需共享的随机事实并记录 | 玩法随机必须可重现,视觉随机无需逐项保存 |
| 云存档 | 本地缓存、保存进度与断线提示 | 持久化、版本管理、访问控制、恢复 | 云端保存正式副本;未确认上传时明确显示未同步 |
| Record | 可采集本地输入与移动轨迹 | 保存正式事件顺序、提交结果、时间与外部输出 | 采集可分布,正式记录必须可关联并恢复 |
| Replay | 本地播放、拖动、调速 | 授权、提供数据、必要时验证 | 执行可两边做,交互播放器优先前端 |
| 从记录点续玩 | 选择时间点并加载 | 恢复或分支、隔离旧异步操作、持久化新进度 | 独立局与共享世界采用不同恢复规则 |
| 资产加载 | 按需加载、解码、缓存 | 静态托管与 CDN | 不经过世界状态同步接口;按实际加载瓶颈优化 |
| 用户偏好 | 音量、画质、快捷键立即生效 | 可选的跨设备同步 | 两边都可以,保存异步进行 |
| 埋点 | 帧率、资源加载、输入到画面的耗时 | 排队、存储、模拟、模型耗时 | 两端通过请求或操作 ID 关联 |
前端可立即执行本地操作,云端也可以校验并记录结果。需要避免的是两个执行者同时独立改写同一个共享事实。共享余额、门状态、物品归属等必须约定提交入口;存储在云端本身不要求所有计算迁到服务端。
移动与共享交互的边界
移动操作先在本机执行并呈现,再异步发送需要同步的信息。应选择输入批次、位置采样或路线中的合适形式,频率依据实际手感、带宽和记录需求确定。
动态门状态、多人抢占同一资源等情况可能需要协调。购买、领取唯一物品等结果以协调后的提交为准,界面及时说明处理中或失败;网络等待不应冻结镜头、声音和普通操作。
同步修正不得重复触发任务、发奖、存档或音效。前端显示、本地计算和正式效果提交需要有清晰边界。移动校验、断网可继续范围、冲突修正和记录精度仍需通过小场景确定。
多用户的两种模式
已确定需要多用户与云端存储;是否允许多个玩家同时影响同一个世界,仍需明确。
| 行为 | 各用户独立一局 | 多玩家共享同一世界 |
|---|---|---|
| 状态归属 | 一局可保持单玩家状态 | 区分玩家位置、背包、余额与世界公共状态 |
| 切后台、打开菜单 | 可暂停自己的局 | 通常只停止个人输入,世界继续 |
| 睡觉、等待到明早 | 可推进自己的剧情时间 | 需要共同跳时规则,或只改变个人活动状态 |
| 读档、任意时刻续玩 | 按当前存档规则恢复并处理后续记录 | 需要授权恢复整个世界,或创建独立分支 |
| 断线恢复 | 对齐该局的云端保存位置 | 还需处理离线期间其他玩家改变的世界 |
| 性能重点 | 实例数量、存储、Agent 成本 | 另有同步广播、资源竞争和共享模拟负载 |
时间、Agent 与记录的共同边界
统一推进权,保留不同时间含义
| 时间 | 单位与用途 |
|---|---|
| 模拟时间 | 毫秒,移动与活动进度 |
| 剧情时间 | 秒,昼夜、营业、日程和等待 |
| 时间余额 | 秒,玩家可以消费或获得的资源 |
| 现实时间 | 网络、LLM 超时与运行观测 |
| 前端表现时间 | 动画与插值,不单独产生共享剧情事实 |
暂停、恢复、调速和等待必须有明确语义并进入记录。Agent 的超时或后台扫描可使用现实时间,其结果按正式事件顺序生效。各系统消费同一局的时间规则。
Agent 与规则协作
Agent 可以生成对白、行为意图和剧情提议;rule 可以承担稳定条件、资源约束和既有玩法计算。具体剧情由谁推进,可在编排和调试中逐段决定。
合并时先明确每个共享字段的写入归属。模型返回时,世界可能已变化:需要校验相关版本、操作是否仍有效、目标是否仍可用。一次交易或交互中必须一起成功的修改,应一起提交。模型生成结果、提交成功、玩家已经看到结果是不同的阶段。
agentic 对照版本已有输入序号、step 边界、可保存的随机状态、文字状态与 Langfuse 追踪。部分决策回调会检查操作 ID,但实体状态写入仍需补齐相关版本或过期校验。这些能力接入本地游戏时需要逐项适配。
完整记录与回放
正式记录至少需要覆盖:
- 初始状态、内容与规则版本,以及恢复点。
- 玩家操作、实际生效顺序、必要的移动记录、推进边界、暂停和跳时。
- 已接受的 Agent/God 输出、随机结果或随机状态、成功和拒绝结果。
- 对话正文、文字状态与引用内容,关联其出现或生效的位置。
- 续玩所需的去重信息、待完成操作及相关记忆。
回放使用已记录的模型输出。续玩时读取所选时刻的状态,隔离原时间线尚未返回的操作;之后的新生成进入新进度。
agentic 的 messages 和 interactionTurns 独立保存正文,仅有 inputs 与 steps 不足以还原完整对话。我们已有的本地播放器可以复用,但尚未实现上述跨模式回放。
世界事件回放重现正式事实;如果还需要逐帧还原某位玩家当时看到的预测和修正过程,则需要额外记录客户端表现信息。首版回放精度必须在实现前约定。
Convex:技术栈、能力边界与迁移
以下判断以本文所列游戏提交及 2026-09-18 查阅的官方文档为依据。平台配额可能随版本、云服务方案与自托管配置变化;未进行容量或延迟压测。
两边使用的语言与框架
| 部分 | 当前技术栈 |
|---|---|
| 前端 | TypeScript / TSX、React 18、PixiJS 7、Vite 4 |
| 现有 Convex 后端与 Agent 业务 | TypeScript;Query 读取、Mutation 事务写入、Action 执行外部调用 |
| LLM 接入 | 后端通过 HTTP 请求模型接口,Agent 分支增加 Langfuse 追踪 |
| 本地玩法核心 | TypeScript 的 MemoryWorld 及配套规则模块 |
Agent 分支没有另设 Python 业务后端。两边的集成主要涉及状态结构、执行位置与提交协议,语言本身不是障碍。Convex 默认运行时与普通 Node.js 进程不同;使用 Node.js 专属库时,可将合适的 Action 放入 Node.js 运行时。
流式输出
Convex 支持 HTTP 流式响应,也支持将文本增量分批持久化后通过查询订阅分发,后者方便多客户端读取与断线重连,但会增加写入与订阅工作量,需要合批和节流。
Agent 分支的 convex/util/llm.ts 已有读取模型流的分支;已核对的主要决策与交互调用仍等待完整文本后解析、提交。模型流式输出、后端读取和前端逐段展示是三个环节,普通 Action 调用不会自动把返回值变成前端可消费的 token 流。官方 Agent 组件提供流式能力,但本分支使用自编 Agent 逻辑,不能将官方组件能力视为本分支已完成的接入。
对白可以逐段显示;改变任务、门状态、余额等效果,需在结果完整并经过校验后提交。生成期间普通移动继续即时响应。
平台约束与游戏影响
| 方面 | 能力与约束 | 对项目的影响 |
|---|---|---|
| 实时通信 | 自带实时查询订阅,连接由平台管理 | 状态同步方便;自定义移动消息合批、按附近玩家广播、二进制协议与拥塞策略需要另行设计,不能把订阅 API 当作任意 socket 服务 |
| 世界生命周期 | 函数有执行期限,不应依赖永久存活的内存实例 | 长时间模拟需要加载、推进、保存和再次调度;精细控制常驻房间与调度时适配成本较高 |
| 外部调用与事务 | LLM 请求在 Action,原子写入在 Mutation | 生成与提交分开,必须检查过期结果、重复操作和部分失败 |
| 运行环境 | 默认受约束的 JS 运行时;Node.js 仅用于相应 Action | 不是所有 npm 库都能在 Query、Mutation 或 HTTP Action 中直接运行 |
| 数据模型 | 文档数据库 API、索引与事务边界由平台定义 | 查询、数据拆分和以后迁移需适配;不是直接使用通用 SQL 的业务接口 |
| 并发写入 | 乐观并发控制,冲突可能触发重试 | 同一世界文档被大量操作更新时会形成热点,需要拆分数据或调整提交方式 |
| 大小与执行限额 | 官方当前列出单文档 1 MiB,以及事务、执行时间、内存和并发等限额 | 世界与录像需拆分,长任务需有恢复点;实际限额按部署版本和配置核对 |
| 部署 | 支持云服务与自托管 | 自托管增加部署控制权和运维责任,仍保留 Convex 的函数与数据库编程模型 |
| 成本 | 云端调用、数据库、带宽等受计费与配额影响;自托管消耗自己的资源 | 高频写入、文本流和持续世界需要实测,不能只按玩家数量估算 |
| 迁移耦合 | ctx.db、生成 API、订阅 Hooks 和调度接口属于 Convex | 接入越深,需要替换的基础设施连接代码越多 |
Agent 分支当前约每秒提交一批世界状态,这是 Game.stepDuration 的实现参数,不是 Convex 强制的一秒更新下限。降低间隔会改变调用、写入和订阅负载,是否改善体验需要实测。
当前 Game.saveDiff() 按 step 替换包含 players、agents、conversations、entities 等集合的世界文档。随着内容和用户增加,文档体积、共享写入竞争及订阅重算值得关注;这是数据建模与平台边界共同产生的问题。更换数据库后,也应避免让所有高频操作争用同一份大对象。
仓库的 docker-compose.yml 已提供自托管 Convex 镜像配置。这说明存在自托管路径,不代表当前生产部署状态。云服务的套餐配额与自托管可调配置需分别核对。
接入与替换的工作量
| 部分 | 复用与改造判断 |
|---|---|
| 本地移动、渲染、音效、规则与回放核心 | 多数不依赖 Convex,可继续复用 |
| 提示词、模型输出解析、文字状态解析 | 多数是普通 TS 逻辑;调整调用上下文 |
| LLM HTTP 请求与追踪 | 可保留主要逻辑;适配配置与任务入口 |
| 世界加载、数据表、索引查询、ID 和事务提交 | 明显依赖 Convex,需要替换存储层与一致性机制 |
| 实时查询、输入确认与前端订阅 | 需要适配新请求和推送协议 |
| scheduler、cron、后台 Agent 操作 | 需要补齐持久任务、去重、重试和重启恢复 |
| 已有世界、记忆与日志 | 是否迁移及迁移量取决于保留需求,目前未评估 |
仅用 Convex 保存个人云存档,接入范围较集中;接入共享世界和 Agent,还涉及状态归属、异步确认、时间协调和完整记录。当前本地调用立即返回结果,不能将所有操作机械替换为等待网络返回的调用。
替换 Convex 时,难点主要是接回它已经提供的事务、调度和实时更新能力。一次世界推进涉及状态、记录和待执行任务,必须避免只保存了其中一部分,也要防止重启后重复推进同一局。
如果决定更换,宜先明确目标后端并稳定操作 ID、状态版本、时间单位、同步消息和记录协议,再接入云存档与 Agent。TypeScript / Node.js 服务、PostgreSQL 和按需的 WebSocket 是可评估的替代组合,尚未选定。初期可在一个后端项目中实现运行与任务处理,持久化和恢复语义仍需具备。
云存档、普通状态同步、Agent 对话及流式文本都在 Convex 的能力范围内。平台选择应主要衡量多人实时通信、长期模拟、数据布局和运维控制需求,以及团队自行维护这些能力的成本。
官方参考:流式输出、运行环境、HTTP Actions、平台限制、乐观并发控制、自托管。
改造范围与实施顺序
| 工作 | 可复用基础 | 范围判断 |
|---|---|---|
| 云存档 | 本地事件、快照、恢复和版本检查 | 中等:增加云端归属、提交、同步与恢复 |
| 移动异步同步 | 当前即时移动、碰撞和表现 | 中等偏大:补同步、冲突处理,保持本地手感 |
| UI 连接共享结果 | 当前命令与反馈逻辑 | 中等:区分即时响应、等待确认和已保存 |
| 时间协调 | 已有时间计算与推进函数 | 中等:明确暂停、等待与多人语义 |
| Agent 接入 | 两边的命令、异步生成与记录基础 | 中等:补结果协议、版本校验和关联 |
| 回放与续玩 | 已有本地播放器、逐事件比对和快照恢复 | 可复用:补齐云端、Agent 与移动记录 |
| 共享多人玩法 | 当前主要是单玩家状态 | 较大:划分个人与公共状态,调整玩法调用 |
这些是基于代码结构的定性判断,不是排期承诺。MemoryWorld 集中了规则逻辑,值得继续复用;当前 LocalGame 同时承担输入、时间驱动、状态读取和存档,需要拆清边界。当前 State.player、balance、背包、对话和任务等多为单份,若采用共享多人模式,改造范围会进一步增加。
建议先接通一间房、一个 NPC、一个交互物件和一段任务:前端即时移动,异步同步,云端保存,Agent 结果提交,断线恢复,以及完整回放。共享多人确定后,在这个场景尽早放入两个客户端验证冲突。
验收时分别观察正常移动、弱网、断线、过期 Agent 结果和恢复续玩;不要用平均请求耗时替代操作手感。随后再扩展交易、日程、服务和音乐玩法。
观测与待定事项
现有 Agent 分支已提供部分生成耗时、重试、token 用量和状态审计。还需关联前端与云端观测:
| 观测 | 用途 |
|---|---|
| 输入到首次画面反馈 | 判断即时体验是否达标 |
| 发出、收到、确认、同步到其他玩家的耗时 | 分离网络与排队延迟 |
| 移动修正次数与幅度 | 判断同步是否破坏手感 |
| 云存档未同步时长、恢复失败率 | 判断持久化体验 |
| LLM 生成时长、过期结果比例、调用成本 | 判断 Agent 的实际作用与开销 |
| 帧率、首屏资源量、切场景加载耗时 | 定位渲染与资产瓶颈 |
尚待决定:共享世界模式、移动同步协议与校验边界、断网行为、个人与世界时间规则、回放精度、事件与快照保留策略。具体频率、压缩格式和部署规模在测量后确定。
源码入口
以下路径相对于上述游戏仓库版本;游戏源码的访问权限与公共文档站独立。
| 路径 | 核对内容 |
|---|---|
justfile、package.json | 启动模式 |
src/lib/localMode.ts、src/main.tsx、src/App.tsx | 前后端入口选择 |
src/components/LocalGame.tsx | 本地输入、时间推进、状态展示 |
prototype/world.ts、prototype/entities.ts | 世界状态、命令与规则执行 |
prototype/replay.ts、src/lib/autosaves.ts | 本地回放、恢复与 OPFS 存储 |
convex/aiTown/game.ts、convex/engine/abstractGame.ts | Convex 世界循环与提交;Agent 版本增加记录能力 |
convex/aiTown/entityInputs.ts、convex/agent/interact.ts(Agent 分支) | 文字状态、物件交互与异步结果 |
convex/aiTown/agent.ts、convex/prose/schema.ts(Agent 分支) | 对话正文与记录关联 |