using System; using System.Collections.Generic; using BaseGames.Core.Save; using UnityEngine; namespace BaseGames.World { /// 世界对象的分类枚举,作为 WorldStateRegistry 的泛化 key。 public enum WorldObjectCategory { Collectible, SavePoint, Door, Destroyed, Flag, } /// /// 运行时世界状态缓存。ScriptableObject,通过 [SerializeField] 注入各组件。 /// SaveManager.SaveAsync 调用 GetAllFlags(); /// SaveManager.LoadAsync 调用 LoadFromSave(data.World)。 /// [CreateAssetMenu(menuName = "BaseGames/World/WorldStateRegistry")] public class WorldStateRegistry : ScriptableObject { // ── 统一状态字典 ───────────────────────────────────────────────────── private readonly Dictionary> _states = new(); /// /// 状态变更时广播:(类别, id)。UI / 测试代码可订阅此事件做响应式刷新。 /// public event Action OnStateChanged; /// /// Editor 重新进入 Play Mode 时 ScriptableObject 保留上一次运行的状态, /// OnEnable 在域重载(Domain Reload)和每次 Play 开始时都会调用,确保状态干净。 /// private void OnEnable() => _states.Clear(); // ── 泛化 API ───────────────────────────────────────────────────────── /// 检查指定类别中 id 是否已标记。 public bool IsMarked(WorldObjectCategory category, string id) => _states.TryGetValue(category, out var set) && set.Contains(id); /// 标记指定类别中的 id(幂等)。 public void Mark(WorldObjectCategory category, string id) { if (!_states.TryGetValue(category, out var set)) { set = new HashSet(); _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 ─────────────────────────────────────────────────────── /// 从存档数据恢复全部状态。由 SaveManager.LoadAsync 调用。 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); } /// 获取所有通用标记,供 SaveManager 持久化。 public HashSet GetAllFlags() { if (_states.TryGetValue(WorldObjectCategory.Flag, out var flags)) return new HashSet(flags); return new HashSet(); } /// 获取所有已摧毁对象 ID,供 SaveManager 持久化。 public HashSet GetAllDestroyedIds() { if (_states.TryGetValue(WorldObjectCategory.Destroyed, out var set)) return new HashSet(set); return new HashSet(); } /// 重置所有状态(开始新游戏时调用)。 public void Reset() => _states.Clear(); } }