fix: integrate SQLite event storage into load/save system
- Fix load_game to use World.create_with_db() for SQLite event storage - Add get_events_db_path() to compute event database path from save path - Add JSON to SQLite migration for backward compatibility with old saves - Close old EventManager before loading new save to prevent connection leaks - Add events_db metadata to save file - Add comprehensive tests for database switching bug and save/load cycle
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
主要功能:
|
||||
- load_game: 从JSON文件加载游戏完整状态
|
||||
- get_events_db_path: 根据存档路径计算事件数据库路径
|
||||
- check_save_compatibility: 检查存档版本兼容性(当前未实现严格检查)
|
||||
|
||||
加载流程(两阶段):
|
||||
@@ -17,9 +18,12 @@
|
||||
- 无法重建的动作会被置为None
|
||||
- 不存在的Avatar引用会被忽略
|
||||
|
||||
事件存储:
|
||||
- 事件存储在 SQLite 数据库中({save_name}_events.db)
|
||||
- 旧存档的 JSON 事件会自动迁移到 SQLite
|
||||
|
||||
注意事项:
|
||||
- 读档后会重置前端UI状态(头像图像、插值等)
|
||||
- 事件历史完整恢复(受限于保存时的数量)
|
||||
- 地图从头重建(因为地图是固定的),但会恢复宗门总部位置
|
||||
"""
|
||||
import json
|
||||
@@ -37,6 +41,15 @@ from src.classes.relation import Relation
|
||||
from src.utils.config import CONFIG
|
||||
|
||||
|
||||
def get_events_db_path(save_path: Path) -> Path:
|
||||
"""
|
||||
根据存档路径计算事件数据库路径。
|
||||
|
||||
例如:save_20260105_1423.json -> save_20260105_1423_events.db
|
||||
"""
|
||||
return save_path.with_suffix("").with_name(save_path.stem + "_events.db")
|
||||
|
||||
|
||||
def load_game(save_path: Optional[Path] = None) -> Tuple["World", "Simulator", List["Sect"]]:
|
||||
"""
|
||||
从文件加载游戏状态
|
||||
@@ -85,8 +98,15 @@ def load_game(save_path: Optional[Path] = None) -> Tuple["World", "Simulator", L
|
||||
world_data = save_data.get("world", {})
|
||||
month_stamp = MonthStamp(world_data["month_stamp"])
|
||||
|
||||
# 重建World对象
|
||||
world = World(map=game_map, month_stamp=month_stamp)
|
||||
# 计算事件数据库路径。
|
||||
events_db_path = get_events_db_path(save_path)
|
||||
|
||||
# 重建World对象(使用 SQLite 事件存储)。
|
||||
world = World.create_with_db(
|
||||
map=game_map,
|
||||
month_stamp=month_stamp,
|
||||
events_db_path=events_db_path,
|
||||
)
|
||||
|
||||
# 重建天地灵机
|
||||
from src.classes.celestial_phenomenon import celestial_phenomena_by_id
|
||||
@@ -153,18 +173,26 @@ def load_game(save_path: Optional[Path] = None) -> Tuple["World", "Simulator", L
|
||||
if t_name in techniques_by_name:
|
||||
sect.techniques.append(techniques_by_name[t_name])
|
||||
|
||||
# 重建事件历史
|
||||
# 检查是否需要从 JSON 迁移事件(向后兼容旧存档)。
|
||||
db_event_count = world.event_manager.count()
|
||||
events_data = save_data.get("events", [])
|
||||
for event_data in events_data:
|
||||
event = Event.from_dict(event_data)
|
||||
world.event_manager.add_event(event)
|
||||
|
||||
|
||||
if db_event_count == 0 and len(events_data) > 0:
|
||||
# SQLite 数据库是空的,但 JSON 中有事件,执行迁移。
|
||||
print(f"正在从 JSON 迁移 {len(events_data)} 条事件到 SQLite...")
|
||||
for event_data in events_data:
|
||||
event = Event.from_dict(event_data)
|
||||
world.event_manager.add_event(event)
|
||||
print("事件迁移完成")
|
||||
else:
|
||||
print(f"已从 SQLite 加载 {db_event_count} 条事件")
|
||||
|
||||
# 重建Simulator
|
||||
simulator_data = save_data.get("simulator", {})
|
||||
simulator = Simulator(world)
|
||||
simulator.birth_rate = simulator_data.get("birth_rate", CONFIG.game.npc_birth_rate_per_month)
|
||||
|
||||
print(f"存档加载成功!共加载 {len(all_avatars)} 个角色,{len(events_data)} 条事件")
|
||||
print(f"存档加载成功!共加载 {len(all_avatars)} 个角色")
|
||||
return world, simulator, existed_sects
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user