☰
OpenFootManager 足球经理存档系统终极指南:SQLite 每档一库设计与迁移、校验机制全解析
2026/10/15 15:25:21 网站建设 项目流程

【免费下载链接】openfootmanager

An open source soccer/football manager game

项目地址:https://gitcode.com/gh_mirrors/op/openfootmanager
点击查看免费下载

OpenFootManager 是一款开源足球经理游戏(soccer/football manager),由 Rust + Tauri + React 构建。它的存档系统采用「每个存档一个 SQLite 数据库文件」的设计,配合 6 个版本化迁移、SHA-256 校验和与可自动重建的save_index.json索引,保证老玩家升级不丢档、损坏文件不崩游戏。本文带你完整看懂这套机制背后的设计与实现。

🎯 为什么要"每档一库"?告别 JSON 大杂烩

早期版本的存档方式很简单:单个saves.db文件里,把整个游戏状态序列化成一个 JSON 文本列存起来。问题也很明显:

  • 没有结构校验,JSON 一损坏整个存档直接报废;
  • 没有校验和,无法判断文件是否被篡改或写坏;
  • 没有迁移机制,字段一加,老档就读不出来了。

新设计(见 docs/SAVE_SYSTEM_DESIGN.md)把思路整个翻转:每个存档会话拥有独立的.db文件,内部是清晰的关系型表结构。一个档坏了,只影响一个档;列表页不需要打开任何数据库;升级时靠迁移脚本平滑过渡。

📁 存档目录结构:N 个 .db 文件 + 一份 save_index.json

Linux 下所有存档都放在应用数据目录里,结构一目了然:

~/.local/share/com.openfootmanager/ ├── saves/ │ ├── <uuid1>.db # 存档 1:独立的 SQLite 文件 │ ├── <uuid2>.db # 存档 2 │ └── ... ├── save_index.json # 全部存档的清单(索引) ├── settings.json # 应用设置 ├── databases/ # 用户导入的世界数据库 └── saves.db.migrated # 旧版存档文件(迁移后改名保留)

save_index.json是全部存档的"目录页",每条记录包含存档名、经理名、库文件名和 SHA-256 校验和等元数据:

{ "version": 1, "saves": [ { "id": "uuid-1", "name": "John's Career", "manager_name": "John Smith", "db_filename": "uuid-1.db", "checksum": "sha256hex...", "created_at": "2026-03-05T18:00:00Z", "last_played_at": "2026-03-05T19:30:00Z" } ] }

这个设计带来一个很实际的收益:列出存档时只读这份小 JSON,完全不打开数据库,存档再多也秒开。索引的读写与重建逻辑集中在 src-tauri/crates/db/src/save_index.rs。

🗂️ 每个存档库里的 12 张核心表

打开任意一个<uuid>.db,你会看到 12 张表(由 src-tauri/crates/db/src/sql/v001_initial_schema.sql 定义):

表名存放内容
game_meta存档元信息:存档名、开始/当前日期、经理 ID 等
managers经理资料、声望、满意度、生涯数据
teams球队:财务、战术、训练设置、阵容等
players球员:能力值、状态、伤病、合同、数据
staff教练组人员及其能力
league/fixtures/standings联赛、赛程与积分排名
messages/news收件箱消息与新闻
board_objectives董事会目标
scouting_assignments球探任务

值得一提的是混合存储策略:球员能力值、近期状态、生涯记录这类结构复杂的嵌套数据,仍以 JSON 形式存在 TEXT 列里(如players.attributes、teams.form)。核心关系用真正的表格表达,嵌套细节用 JSON 兜底——既保留了查询能力,又避免了过度拆表,是关系型存档里很实用的折中。

🚀 数据库迁移机制:6 个迁移如何保证旧档不断档

每个存档库的表结构由 src-tauri/crates/db/src/migrations.rs 统一管理,基于rusqlite_migration实现,目前共 6 个迁移:

版本迁移文件作用
V1v001_initial_schema.sql初始 schema:全部 12 张游戏实体表
V2v002_training_groups.sql每队训练分组
V3v003_alternate_positions.sql球员副位置
V4v004_natural_position.sql球员天然/首选位置
V5v005_player_training_focus.sql按球员的训练专注度覆盖
V6v006_team_match_roles.sql球队比赛角色默认值

关键保障有三点:

  1. 打开即迁移:src-tauri/crates/db/src/game_database.rs 中GameDatabase::open打开任何存档库时都会执行to_latest,老档被读入的瞬间就自动升级到最新结构;
  2. 幂等可重放:迁移已经应用过再执行一遍是空操作,重复读档不会产生副作用(有专门的测试覆盖);
  3. 版本可校验:rusqlite_migration会把已应用的迁移数写入 SQLite 的user_version,validate_schema()用它和MIGRATION_COUNT比对,不一致就判定为"Schema version mismatch"。

🔍 校验机制:SHA-256 校验和 + 索引重建自救

保存时算校验和。每次保存(create_save/save_game),src-tauri/crates/db/src/save_manager.rs 会先写完全部实体表,再对整个.db文件计算 SHA-256,把 64 位十六进制摘要写回save_index.json。数据一变,摘要必变——测试里专门验证了"游戏推进 7 天后 checksum 不同"。

索引丢失时自动重建。如果save_index.json不在了,启动流程会扫描saves/目录里的每个.db文件:逐个打开、校验 schema 版本、读取game_meta提取元数据、重算校验和,最后重建并写回索引。

损坏文件不会让游戏崩掉。无法打开、schema 版本不符、或缺少game_meta的文件,会被标记为Invalid { filename, reason },记录 warn 日志并在界面里显示为损坏——其余正常存档照常列出和读取。这就是"每档一库"隔离性的直接回报。

🕰️ 老版本 saves.db 自动迁移:升级不丢档

如果你从使用旧版 JSON 大杂烩存档的时代升级过来,src-tauri/crates/db/src/legacy_migration.rs 会在启动时接管:

  1. 检测应用数据目录里是否存在saves.db;
  2. 打开旧库,按最近游玩时间倒序取出全部存档行(id / name / manager_name / game_data / created_at / last_played_at);
  3. 每行的game_dataJSON 反序列化成Game,走标准的SaveManager::create_save写入独立的新.db;
  4. 全部处理完成后,把saves.db改名为saves.db.migrated防止重复迁移,并生成新的save_index.json。

单条存档 JSON 损坏只会把该条标记为Failed(附原因),不阻断其他存档的迁移——坏档隔离,好档照迁。

💾 一次"保存"与"读档"背后的数据流

  • 保存:内存中的Game→ 逐个 upsert 写入 12 张表 → 关闭连接 → 计算.db的 SHA-256 → 更新save_index.json;
  • 读档:按 id 从索引查到文件名 → 打开对应.db→ 自动迁移到最新 schema → 逐表读回组装成Game放入内存状态;
  • 从已有存档开新局:new_game_from_save会剥掉消息、新闻、球探任务、董事会目标等"局内数据",重置时钟回赛季开始、清空玩家赛季数据与球队赛季财务,保留世界与阵容——相当于"继承班底,重开一局"。

🧭 关键文件导航(想深入源码从这里开始)

  • 存档总设计文档:docs/SAVE_SYSTEM_DESIGN.md
  • 存档编排(创建/保存/读取/删除):src-tauri/crates/db/src/save_manager.rs
  • 索引与校验和:src-tauri/crates/db/src/save_index.rs
  • 数据库打开与 schema 校验:src-tauri/crates/db/src/game_database.rs
  • 迁移定义(6 个版本):src-tauri/crates/db/src/migrations.rs
  • 旧版 saves.db 迁移:src-tauri/crates/db/src/legacy_migration.rs
  • 仓库整体架构:docs/ARCHITECTURE.md

小结:OpenFootManager 的存档系统用"每档一库 + 版本化迁移 + SHA-256 校验 + 可重建索引"四件套,把最让人头疼的存档损坏与版本升级问题变成了可预期、可自愈的工程行为。理解了这套设计,你也能把它当作其他桌面游戏做持久层的参考模板。

【免费下载链接】openfootmanager

An open source soccer/football manager game

项目地址:https://gitcode.com/gh_mirrors/op/openfootmanager
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询