多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using BaseGames.Core.Save;
using UnityEngine;
namespace BaseGames.World
{
/// <summary>世界对象的分类枚举,作为 WorldStateRegistry 的泛化 key。</summary>
public enum WorldObjectCategory
{
Collectible,
SavePoint,
Door,
Destroyed,
Flag,
}
/// <summary>
/// 运行时世界状态缓存。ScriptableObject通过 [SerializeField] 注入各组件。
/// SaveManager.SaveAsync 调用 GetAllFlags()
/// SaveManager.LoadAsync 调用 LoadFromSave(data.World)。
/// </summary>
[CreateAssetMenu(menuName = "World/WorldStateRegistry")]
public class WorldStateRegistry : ScriptableObject
{
// ── 统一状态字典 ─────────────────────────────────────────────────────
private readonly Dictionary<WorldObjectCategory, HashSet<string>> _states = new();
/// <summary>
/// 状态变更时广播:(类别, id)。UI / 测试代码可订阅此事件做响应式刷新。
/// </summary>
public event Action<WorldObjectCategory, string> OnStateChanged;
/// <summary>
/// Editor 重新进入 Play Mode 时 ScriptableObject 保留上一次运行的状态,
/// OnEnable 在域重载Domain Reload和每次 Play 开始时都会调用,确保状态干净。
/// </summary>
private void OnEnable() => _states.Clear();
// ── 泛化 API ─────────────────────────────────────────────────────────
/// <summary>检查指定类别中 id 是否已标记。</summary>
public bool IsMarked(WorldObjectCategory category, string id)
=> _states.TryGetValue(category, out var set) && set.Contains(id);
/// <summary>标记指定类别中的 id幂等。</summary>
public void Mark(WorldObjectCategory category, string id)
{
if (!_states.TryGetValue(category, out var set))
{
set = new HashSet<string>();
_states[category] = set;
}
if (set.Add(id))
OnStateChanged?.Invoke(category, id);
}
// ── 语义化具名 API泛化方法快捷方式───────────────────────────────
public bool IsCollected(string id) => IsMarked(WorldObjectCategory.Collectible, id);
public void MarkCollected(string id) => Mark(WorldObjectCategory.Collectible, id);
public bool IsSavePointActivated(string id) => IsMarked(WorldObjectCategory.SavePoint, id);
public void MarkSavePointActivated(string id) => Mark(WorldObjectCategory.SavePoint, id);
public bool IsDestroyed(string id) => IsMarked(WorldObjectCategory.Destroyed, id);
public void MarkDestroyed(string id) => Mark(WorldObjectCategory.Destroyed, id);
public bool IsDoorOpened(string id) => IsMarked(WorldObjectCategory.Door, id);
public void MarkDoorOpened(string id) => Mark(WorldObjectCategory.Door, id);
public bool HasFlag(string key) => IsMarked(WorldObjectCategory.Flag, key);
public void SetFlag(string key) => Mark(WorldObjectCategory.Flag, key);
public void ClearFlag(string key)
{
if (_states.TryGetValue(WorldObjectCategory.Flag, out var set) && set.Remove(key))
OnStateChanged?.Invoke(WorldObjectCategory.Flag, key);
}
// ── Persistence ───────────────────────────────────────────────────────
/// <summary>从存档数据恢复全部状态。由 SaveManager.LoadAsync 调用。</summary>
public void LoadFromSave(WorldSaveData data)
{
_states.Clear();
if (data == null) return;
foreach (var id in data.CollectedIds) Mark(WorldObjectCategory.Collectible, id);
foreach (var id in data.ActivatedSavePoints) Mark(WorldObjectCategory.SavePoint, id);
foreach (var id in data.OpenedDoors) Mark(WorldObjectCategory.Door, id);
foreach (var id in data.DestroyedObjectIds) Mark(WorldObjectCategory.Destroyed, id);
if (data.Switches != null)
foreach (var kv in data.Switches)
if (kv.Value) Mark(WorldObjectCategory.Flag, kv.Key);
}
/// <summary>获取所有通用标记,供 SaveManager 持久化。</summary>
public HashSet<string> GetAllFlags()
{
if (_states.TryGetValue(WorldObjectCategory.Flag, out var flags))
return new HashSet<string>(flags);
return new HashSet<string>();
}
/// <summary>获取所有已摧毁对象 ID供 SaveManager 持久化。</summary>
public HashSet<string> GetAllDestroyedIds()
{
if (_states.TryGetValue(WorldObjectCategory.Destroyed, out var set))
return new HashSet<string>(set);
return new HashSet<string>();
}
/// <summary>重置所有状态(开始新游戏时调用)。</summary>
public void Reset() => _states.Clear();
}
}