Skip to content

数据储存

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_模块名称_类名称"的小写形式。
  • 脏标记机制:当数据被修改时,会将类标记为"脏",引擎销毁时会自动保存所有标记为"脏"的类数据。

工作原理

  1. 当使用@ServerDataStorage.AutoSave装饰器装饰一个类时,装饰器会替换该类的元类为AutoSaveMeta。
  2. AutoSaveMeta重写了__setattr__和__getattribute__方法,使得对类属性的访问实际上是对内部_autosave_前缀属性的访问。
  3. 当修改类属性时,会调用_autosave_write方法将修改存入内存并标记为需要保存。
  4. 游戏结束时,engineDestroy方法会自动保存所有被标记为"脏"的类数据。