diff --git a/src/server/main.py b/src/server/main.py index 1964b32..9e3e7f1 100644 --- a/src/server/main.py +++ b/src/server/main.py @@ -167,21 +167,55 @@ async def game_loop(): # 执行一步 events = await sim.step() + # 找出新诞生的角色 ID + newly_born_ids = set() + for e in events: + if "晋升为修士" in e.content and e.related_avatars: + newly_born_ids.update(e.related_avatars) + + avatar_updates = [] + + # 为了避免重复发送大量数据,我们区分处理: + # - 新角色:发送完整数据 + # - 旧角色:只发送位置 (x, y)(限制数量) + + # 1. 发送新角色的完整信息 + for aid in newly_born_ids: + a = world.avatar_manager.avatars.get(aid) + if a: + avatar_updates.append({ + "id": str(a.id), + "name": a.name, + "x": int(getattr(a, "pos_x", 0)), + "y": int(getattr(a, "pos_y", 0)), + "gender": a.gender.value, # 使用 value (male/female) 而不是 str (中文) + "pic_id": (hash(a.id) % 15) + 1, + "action": getattr(a, "current_action", {}).get("name", "发呆") if hasattr(a, "current_action") and a.current_action else "发呆" + }) + + # 2. 常规位置更新(暂时只发前 50 个旧角色,减少数据量) + limit = 50 + count = 0 + for a in world.avatar_manager.avatars.values(): + # 如果是新角色,已经在上面处理过了,跳过 + if a.id in newly_born_ids: + continue + + if count < limit: + avatar_updates.append({ + "id": str(a.id), + "x": int(getattr(a, "pos_x", 0)), + "y": int(getattr(a, "pos_y", 0)) + }) + count += 1 + # 构造广播数据包 state = { "type": "tick", "year": int(world.month_stamp.get_year()), "month": world.month_stamp.get_month().value, "events": serialize_events_for_client(events), - # 暂时只发前 50 个角色的位置更新,减少数据量 - "avatars": [ - { - "id": str(a.id), - "x": int(getattr(a, "pos_x", 0)), - "y": int(getattr(a, "pos_y", 0)) - } - for a in list(world.avatar_manager.avatars.values())[:50] - ] + "avatars": avatar_updates } await manager.broadcast(state) except Exception as e: diff --git a/static/config.yml b/static/config.yml index 2a814d3..a03698f 100644 --- a/static/config.yml +++ b/static/config.yml @@ -18,8 +18,8 @@ ai: max_parse_retries: 3 game: - init_npc_num: 6 - sect_num: 2 # init_npc_num大于sect_num时,会随机选择sect_num个宗门 + init_npc_num: 12 + sect_num: 3 # init_npc_num大于sect_num时,会随机选择sect_num个宗门 npc_birth_rate_per_month: 0.01 fortune_probability: 0.005 diff --git a/static/templates/ai.txt b/static/templates/ai.txt index 30e1a96..a3238aa 100644 --- a/static/templates/ai.txt +++ b/static/templates/ai.txt @@ -10,7 +10,7 @@ 格式为: {{ AvatarName: {{ - "avatar_thinking": ... // 从角色角度,以第一人称视角,描述想法 + "avatar_thinking": ... // 从角色角度,以第一人称视角,简单清晰的描述想法 "short_term_objective": ..., // 角色接下来一段时间的短期目标 "action_name_params_pairs": list[Tuple[action_name, action_params]] // 一次性决定未来的3~8个动作,按顺序执行 }} diff --git a/web/src/stores/world.ts b/web/src/stores/world.ts index c1baa22..3f24e00 100644 --- a/web/src/stores/world.ts +++ b/web/src/stores/world.ts @@ -43,9 +43,15 @@ export const useWorldStore = defineStore('world', () => { // Merge next.set(av.id, { ...existing, ...av } as AvatarSummary); changed = true; + } else { + // New Avatar? Only insert if it has enough info (at least name) + // This handles newly born avatars sent by backend + if (av.name) { + next.set(av.id, av as AvatarSummary); + changed = true; + } } - // Else: ignore. Do NOT insert new avatars from tick updates, - // as tick data is incomplete (position only) and might be from a stale game state (Race Condition). + // Else: ignore. Do NOT insert new avatars from tick updates unless they have full info. } if (changed) {