Merge branch 'main' into xzhseh/sqlite-event-manager

This commit is contained in:
Zihao Xu
2026-01-07 20:05:02 -08:00
committed by GitHub
74 changed files with 1754 additions and 806 deletions

View File

@@ -41,7 +41,7 @@ class AvatarLoadMixin:
from src.classes.age import Age
from src.classes.hp import HP
from src.classes.technique import techniques_by_id
from src.classes.item import items_by_id
from src.classes.material import materials_by_id
from src.classes.weapon import weapons_by_id
from src.classes.auxiliary import auxiliaries_by_id
from src.classes.sect import sects_by_id
@@ -92,13 +92,13 @@ class AvatarLoadMixin:
# 设置物品与资源
avatar.magic_stone = MagicStone(data.get("magic_stone", 0))
# 重建items
items_dict = data.get("items", {})
avatar.items = {}
for item_id_str, quantity in items_dict.items():
item_id = int(item_id_str)
if item_id in items_by_id:
avatar.items[items_by_id[item_id]] = quantity
# 重建materials (兼容旧档 items)
materials_dict = data.get("materials") or data.get("items") or {}
avatar.materials = {}
for mat_id_str, quantity in materials_dict.items():
mat_id = int(mat_id_str)
if mat_id in materials_by_id:
avatar.materials[materials_by_id[mat_id]] = quantity
# 重建weapon
# 使用copy而非deepcopy避免潜在的递归引用导致的崩溃且性能更好

View File

@@ -8,7 +8,7 @@
加载流程(两阶段):
1. 第一阶段加载所有Avatar对象relations留空
- 通过AvatarLoadMixin.from_save_dict反序列化
- 配表对象Technique, Item通过id从全局字典获取
- 配表对象Technique, Material通过id从全局字典获取
2. 第二阶段重建Avatar之间的relations网络
- 必须在所有Avatar加载完成后才能建立引用关系
@@ -123,12 +123,7 @@ def load_game(save_path: Optional[Path] = None) -> Tuple["World", "Simulator", L
avatar.relations[other_avatar] = relation
# 将所有avatar添加到world
# 根据生死状态分流
for avatar in all_avatars.values():
if avatar.is_dead:
world.avatar_manager.dead_avatars[avatar.id] = avatar
else:
world.avatar_manager.avatars[avatar.id] = avatar
world.avatar_manager.avatars = all_avatars
# 恢复洞府主人关系
cultivate_regions_hosts = world_data.get("cultivate_regions_hosts", {})

View File

@@ -507,6 +507,15 @@ class AvatarFactory:
if levels[a] < levels[b] + MASTER_LEVEL_MIN_DIFF:
levels[a] = min(LEVEL_MAX, levels[b] + MASTER_LEVEL_MIN_DIFF + random.randint(0, MASTER_LEVEL_EXTRA_MAX))
# 确保年龄不超过境界寿命上限,避免角色一出生就老死
# 放在所有关系调整之后,因为关系调整可能会修改年龄和等级
for i in range(n):
realm = CultivationProgress(levels[i]).realm
max_lifespan = Age.REALM_LIFESPAN.get(realm, 100)
if ages[i] >= max_lifespan:
# 将年龄限制为寿命上限的 80%-95%,保留一定的生存空间
ages[i] = int(max_lifespan * random.uniform(0.8, 0.95))
avatars_by_index: list[Avatar] = [None] * n # type: ignore
avatars_by_id: dict[str, Avatar] = {}

View File

@@ -4,9 +4,9 @@ Avatar存档序列化Mixin
将Avatar的序列化逻辑从avatar.py分离出来保持核心类的清晰性。
存档策略:
- 引用对象Technique, Item保存id加载时从全局字典获取
- 引用对象Technique, Material保存id加载时从全局字典获取
- relations转换为dict[str, str]avatar_id -> relation_value
- items转换为dict[int, int]item_id -> quantity
- materials转换为dict[int, int]material_id -> quantity
- current_action保存动作类名和参数
- weapon/auxiliary需要深拷贝因为special_data是实例特有的
"""
@@ -30,10 +30,10 @@ class AvatarSaveMixin:
for other, relation in self.relations.items()
}
# 序列化items: dict[Item, int] -> dict[int, int]
items_dict = {
item.id: quantity
for item, quantity in self.items.items()
# 序列化materials: dict[Material, int] -> dict[int, int]
materials_dict = {
material.id: quantity
for material, quantity in self.materials.items()
}
# 序列化current_action
@@ -75,7 +75,7 @@ class AvatarSaveMixin:
# 物品与资源
"magic_stone": self.magic_stone.value,
"items": items_dict,
"materials": materials_dict,
"weapon_id": self.weapon.id if self.weapon else None,
"weapon_special_data": self.weapon.special_data if self.weapon else {},
"weapon_proficiency": self.weapon_proficiency,