using System.Collections.Generic; using System.Linq; using UnityEngine; using BaseGames.Core; using BaseGames.Core.Events; using BaseGames.Core.Save; namespace BaseGames.World.Map { /// /// 运行时地图管理器(架构 15_MapShopModule §1.2)。 /// 挂在 Persistent 场景 [GameManagers] 下,通过事件驱动记录已探索/已完整地图的房间。 /// 实现 ISaveable 持久化探索进度。 /// [DefaultExecutionOrder(-700)] public class MapManager : MonoBehaviour, ISaveable, IMapService { [SerializeField] private MapDatabaseSO _database; [Header("Event Channels")] [SerializeField] private StringEventChannelSO _onRoomEntered; // 订阅 EVT_RoomEntered [SerializeField] private StringEventChannelSO _onMapUpdated; // 发布:房间发现时 [SerializeField] private StringEventChannelSO _onRegionChanged; // 发布:玩家首次进入新区域时(EVT_RegionChanged) // 三级可见性: // Unknown → 未进入过(默认) // Explored → 进入过(显示轮廓/格子) // Mapped → 完整地图信息(购买 MapFragment 或存档点揭示) private HashSet _exploredRooms = new(); private HashSet _mappedRooms = new(); private string _currentRegionId; private readonly CompositeDisposable _subs = new(); private void Awake() { if (ServiceLocator.GetOrDefault() != null) { Destroy(gameObject); return; } ServiceLocator.Register(this); } private void OnEnable() { _onRoomEntered?.Subscribe(OnRoomEntered).AddTo(_subs); ServiceLocator.GetOrDefault()?.Register(this); } private void OnDisable() { _subs.Clear(); ServiceLocator.GetOrDefault()?.Unregister(this); } // ── ISaveable ───────────────────────────────────────────────────────── public void OnSave(SaveData data) { data.Map.ExploredRooms ??= new List(); data.Map.ExploredRooms.Clear(); data.Map.ExploredRooms.AddRange(_exploredRooms); data.Map.MappedRooms ??= new List(); data.Map.MappedRooms.Clear(); data.Map.MappedRooms.AddRange(_mappedRooms); } public void OnLoad(SaveData data) { _exploredRooms = new HashSet(data.Map.ExploredRooms ?? new System.Collections.Generic.List()); _mappedRooms = new HashSet(data.Map.MappedRooms ?? new System.Collections.Generic.List()); } // ── 事件驱动房间发现 ────────────────────────────────────────────────── private void OnRoomEntered(string roomId) { bool changed = _exploredRooms.Add(roomId); if (changed) _onMapUpdated?.Raise(roomId); // 区域变化检测:RegionId 非空且与上一次不同时广播 EVT_RegionChanged var regionId = _database?.GetRoom(roomId)?.RegionId; if (!string.IsNullOrEmpty(regionId) && regionId != _currentRegionId) { _currentRegionId = regionId; _onRegionChanged?.Raise(regionId); } } /// 标记为已完整获取地图信息(购买 MapFragment SO 触发)。 public void SetMapped(string roomId) { _exploredRooms.Add(roomId); if (_mappedRooms.Add(roomId)) _onMapUpdated?.Raise(roomId); } // ── 查询 API ────────────────────────────────────────────────────────── public bool IsExplored(string roomId) => _exploredRooms.Contains(roomId); public bool IsMapped(string roomId) => _mappedRooms.Contains(roomId); public string CurrentRegionId => _currentRegionId; public MapDatabaseSO Database => _database; private void OnDestroy() { ServiceLocator.Unregister(this); } } }