2e1b58bada
添加游戏设计文档、技术架构文档、数值经济文档等内容 新增Mermaid图表文件描述系统架构和流程 包含README说明文档结构和阅读顺序
155 lines
4.5 KiB
Markdown
155 lines
4.5 KiB
Markdown
# 09 存档与后端
|
||
|
||
本文档定义新项目的存档模型与后端接口。目标:稳定、可迁移、可扩展、可观测。即使是单机为主,也建议提供云端存档能力以支持跨设备与版本兼容。
|
||
|
||
## 9.1 存档设计目标
|
||
|
||
- 数据完整:可恢复到任意一个确定状态
|
||
- 可迁移:版本升级可做增量迁移
|
||
- 可校验:避免异常/作弊数据导致崩档
|
||
- 可压缩:存档体积可控,读写快速
|
||
|
||
## 9.2 存档分层与结构
|
||
|
||
存档建议由三部分组成:
|
||
|
||
- `meta`:版本、时间戳、校验、内容包版本
|
||
- `player`:玩家状态与资产
|
||
- `world`:世界状态(时间、地点资源、灾害、标记)
|
||
|
||
```json
|
||
{
|
||
"meta": {
|
||
"saveVersion": 3,
|
||
"contentVersion": {"base": "1.0.0", "packs": {"event_pack_01": "1.0.0"}},
|
||
"createdAt": 1730000000000,
|
||
"updatedAt": 1730001234000,
|
||
"checksum": "sha256:..."
|
||
},
|
||
"player": {
|
||
"name": "Player",
|
||
"placeId": "home",
|
||
"stats": {"life": 80, "hunger": 40, "thirst": 60, "energy": 30, "san": 50, "radiation": 10},
|
||
"attributes": {"str": 4, "agi": 5, "int": 6, "per": 5, "luck": 3},
|
||
"inventory": [{"itemId": "water_purified", "count": 2, "durability": null}],
|
||
"equipment": {"weapon": "knife_01", "body": "jacket_01"},
|
||
"buffs": [{"buffId": "infection_1", "startedAt": 1730000500000, "stacks": 1}],
|
||
"quests": {"active": ["q_main_01"], "completed": ["q_tutorial_01"]}
|
||
},
|
||
"world": {
|
||
"time": {"baseTime": 0, "minutesFromStart": 1234},
|
||
"flags": {"met_trader": true},
|
||
"places": {
|
||
"ruins_store": {
|
||
"heat": 3,
|
||
"resourceStock": {"water_dirty": 0, "scrap_metal": 2},
|
||
"lastRefreshAt": 1730001200000
|
||
}
|
||
},
|
||
"disaster": {"activeId": "sandstorm", "endsAt": 1730003000000}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 9.3 存档写入策略
|
||
|
||
- 自动存档触发点(建议):
|
||
- 回到基地
|
||
- 完成任务步骤
|
||
- 战斗结束
|
||
- 灾害开始/结束
|
||
- 重要事件选择后
|
||
- 快速保存:
|
||
- UI 提供手动保存按钮
|
||
- 保存期间不阻塞主线程(使用异步/worker)
|
||
- 防止坏档:
|
||
- 写入采用“双缓冲”:先写临时,再替换正式
|
||
- 写入失败保留上一份
|
||
|
||
## 9.4 存档校验与迁移
|
||
|
||
### 9.4.1 校验(客户端与服务端)
|
||
|
||
- Schema 校验:字段类型、必填字段、范围
|
||
- 引用校验:itemId/placeId/questId 必须存在于内容库
|
||
- 数值校验:状态上下限、背包容量、堆叠上限
|
||
|
||
### 9.4.2 迁移(SaveVersion)
|
||
|
||
- 每次内容/结构变化提升 `saveVersion`
|
||
- 迁移必须是纯函数:`migrate(save_vN) -> save_vN+1`
|
||
- 迁移记录:
|
||
- 变更点
|
||
- 默认值策略
|
||
- 兼容策略(删字段/改名/拆分)
|
||
|
||
## 9.5 后端能力范围(建议)
|
||
|
||
后端建议至少提供:
|
||
|
||
- 账号与鉴权(匿名账号也可)
|
||
- 云端存档 CRUD
|
||
- 内容包版本与更新清单(可选)
|
||
- 运行日志/错误上报(可选)
|
||
|
||
## 9.6 API 约定(REST 示例)
|
||
|
||
### 9.6.1 鉴权
|
||
|
||
- 登录(匿名/设备绑定):
|
||
- `POST /api/v1/auth/anonymous`
|
||
- 返回 `accessToken/refreshToken`
|
||
- 请求头:
|
||
- `Authorization: Bearer <accessToken>`
|
||
|
||
### 9.6.2 存档接口
|
||
|
||
- 列表:
|
||
- `GET /api/v1/saves`
|
||
- 读取:
|
||
- `GET /api/v1/saves/{slotId}`
|
||
- 写入(覆盖):
|
||
- `PUT /api/v1/saves/{slotId}`
|
||
- Body:完整存档 JSON
|
||
- 服务端校验通过后写入
|
||
- 删除:
|
||
- `DELETE /api/v1/saves/{slotId}`
|
||
|
||
### 9.6.3 并发与冲突
|
||
|
||
使用乐观锁:
|
||
|
||
- 存档 meta 带 `etag` 或 `rev`
|
||
- 更新时带 `If-Match: <etag>`
|
||
- 冲突返回 409,客户端提示“本地与云端不一致”
|
||
|
||
## 9.7 速率限制与滥用防护
|
||
|
||
- 写入频率限制:例如每分钟最多 10 次
|
||
- 存档大小限制:例如 1MB
|
||
- 结构化错误码,避免泄漏服务端信息
|
||
|
||
## 9.8 旧版 PHP 存档参考(当前仓库)
|
||
|
||
当前仓库包含简单的 PHP+MySQL 存档端点:
|
||
|
||
- [save.php](file:///Users/virtheart/Documents/CloneProjects/TinyWaste/save.php):按 `key/data/overwrite` 写入 `record(key,data)`,并校验 `data` 是 JSON
|
||
- [load.php](file:///Users/virtheart/Documents/CloneProjects/TinyWaste/load.php):按 `key` 读取
|
||
|
||
新项目不建议继续沿用 SAE 环境变量模式与弱协议,建议升级为标准鉴权、版本控制与迁移机制。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as Client
|
||
participant API as Save API
|
||
participant DB as Database
|
||
C->>API: PUT /saves/{slotId} (save, If-Match)
|
||
API->>API: 校验Schema/引用/数值
|
||
API->>DB: 写入(事务)
|
||
DB-->>API: ok
|
||
API-->>C: 200 (new etag)
|
||
```
|
||
|
||
对应源文件:[save-flow.mmd](./diagrams/save-flow.mmd)
|
||
|