数据储存
AutoSave 提供了一种封装,方便开发者构建自动存盘的数据类
python
from ..framework.utils.data_storage.server import *
# 示例
@ServerDataStorage.AutoSave(version=1)
class GameConfig(object):
max_players = 10
game_time = 300
difficulty = "normal"
# 读取数据
player_count = GameConfig.max_players # 自动从存储加载
# 修改数据
GameConfig.game_time = 600 # 写入内存,退出游戏时自动写入磁盘
# 手动保存(动态加入的方法,所以没有补全,但是可以使用)
GameConfig.saveData()高级用法:版本迁移
当您需要对数据结构进行更改时,可以使用版本迁移功能:
python
def v1_to_v2(old_data):
# 将旧数据迁移到新版本
return {
"max_players": old_data.get("max_players", 10),
"game_time": old_data.get("game_time", 300),
"difficulty": old_data.get("difficulty", "normal"),
"new_field": "新字段默认值" # 新增字段
}
# 使用迁移函数
@ServerDataStorage.AutoSave(version=2, migration={1: v1_to_v2})
class GameConfig(object):
max_players = 10
game_time = 300
difficulty = "normal"
new_field = "新字段默认值" # 新增字段向后兼容的数据存储
如果您希望保留旧版本数据,可以使用BackwardCompatibleAutoSave:
python
@ServerDataStorage.BackwardCompatibleAutoSave(version=2)
class GameConfig(object):
max_players = 10
game_time = 300
difficulty = "normal"
new_feature = True # 版本2新增字段
# 定义数据转换函数,可选
@staticmethod
def migrate_from_v1(old_data):
# 处理v1到v2的数据迁移
return {
"max_players": old_data.get("max_players", 10),
"game_time": old_data.get("game_time", 300),
"difficulty": old_data.get("difficulty", "normal"),
"new_feature": True
}
# 访问历史版本数据
v1_data = GameConfig.get_version_data(1)
# 手动保存所有版本数据
GameConfig.save_all_data()模块行为
- 版本控制:version是 int 类型,默认为1。当修改version为更大的数字,新版本将强制覆盖旧版本,旧数据(包括键和值)将被丢弃,除非使用migration或BackwardCompatibleAutoSave。
- 储存时机:当自定义数据类(例如GameConfig)被加载,将从磁盘中读取数据。当数据被修改时,不会立即保存,而是在游戏结束时或手动调用GameConfig.saveData()时保存。
- 缓存机制:维护一个 _cache,全局共享(您在同一脚本目录下,任何地方import GameConfig并访问数据,都会访问同一个_cache,有缓存期间所有访问将先访问内存,如果命中就return)。
- key生成机制:通过 _make_key 函数创建一个全局唯一的key,格式为"hf_autosave_模块名称_类名称"的小写形式。
- 脏标记机制:当数据被修改时,会将类标记为"脏",引擎销毁时会自动保存所有标记为"脏"的类数据。
工作原理
- 当使用@ServerDataStorage.AutoSave装饰器装饰一个类时,装饰器会替换该类的元类为AutoSaveMeta。
- AutoSaveMeta重写了__setattr__和__getattribute__方法,使得对类属性的访问实际上是对内部_autosave_前缀属性的访问。
- 当修改类属性时,会调用_autosave_write方法将修改存入内存并标记为需要保存。
- 游戏结束时,engineDestroy方法会自动保存所有被标记为"脏"的类数据。