Files
zeling_v2/Assets/_Game/Scripts/World/Map/MapManager.cs

108 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using BaseGames.Core;
using BaseGames.Core.Events;
using BaseGames.Core.Save;
namespace BaseGames.World.Map
{
/// <summary>
/// 运行时地图管理器(架构 15_MapShopModule §1.2)。
/// 挂在 Persistent 场景 [GameManagers] 下,通过事件驱动记录已探索/已完整地图的房间。
/// 实现 ISaveable 持久化探索进度。
/// </summary>
[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<string> _exploredRooms = new();
private HashSet<string> _mappedRooms = new();
private string _currentRegionId;
private readonly CompositeDisposable _subs = new();
private void Awake()
{
if (ServiceLocator.GetOrDefault<IMapService>() != null) { Destroy(gameObject); return; }
ServiceLocator.Register<IMapService>(this);
}
private void OnEnable()
{
_onRoomEntered?.Subscribe(OnRoomEntered).AddTo(_subs);
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Register(this);
}
private void OnDisable()
{
_subs.Clear();
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Unregister(this);
}
// ── ISaveable ─────────────────────────────────────────────────────────
public void OnSave(SaveData data)
{
data.Map.ExploredRooms ??= new List<string>();
data.Map.ExploredRooms.Clear();
data.Map.ExploredRooms.AddRange(_exploredRooms);
data.Map.MappedRooms ??= new List<string>();
data.Map.MappedRooms.Clear();
data.Map.MappedRooms.AddRange(_mappedRooms);
}
public void OnLoad(SaveData data)
{
_exploredRooms = new HashSet<string>(data.Map.ExploredRooms ?? new System.Collections.Generic.List<string>());
_mappedRooms = new HashSet<string>(data.Map.MappedRooms ?? new System.Collections.Generic.List<string>());
}
// ── 事件驱动房间发现 ──────────────────────────────────────────────────
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);
}
}
/// <summary>标记为已完整获取地图信息(购买 MapFragment SO 触发)。</summary>
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<IMapService>(this);
}
}
}