using System.Collections.Generic;
using UnityEngine;
namespace BaseGames.World.Map
{
///
/// 全局区域注册表 SO。
///
/// 设计原则: 是房间归属的单一权威来源。
/// 本 SO 持有所有 资产引用,运行时从
/// 惰性构建 SceneName → Region 缓存,
/// 消除了原 RegionDefinitionSO.roomSceneNames 与 MapRoomDataSO.RegionId 的双重冗余。
///
/// 资产路径:Assets/_Game/Data/Map/RegionRegistry.asset
///
[CreateAssetMenu(menuName = "BaseGames/Map/RegionRegistry", fileName = "RegionRegistry")]
public class RegionRegistrySO : ScriptableObject
{
[Tooltip("项目中所有 RegionDefinitionSO 资产。新增区域 SO 时同步添加到此数组。")]
[SerializeField] private RegionDefinitionSO[] _regions;
[Tooltip("地图数据库,用于从 MapRoomDataSO.RegionId 构建 SceneName → Region 缓存(单一权威来源)。")]
[SerializeField] private MapDatabaseSO _mapDatabase;
private Dictionary _regionById;
private Dictionary _sceneToRegion;
/// 根据场景名(MapRoomDataSO.RoomId)查找所属区域;未找到返回 null。
public RegionDefinitionSO FindBySceneName(string sceneName)
{
if (string.IsNullOrEmpty(sceneName)) return null;
BuildCacheIfNeeded();
_sceneToRegion.TryGetValue(sceneName, out var region);
return region;
}
/// 根据 regionId 直接查找;未找到返回 null。
public RegionDefinitionSO FindById(string regionId)
{
if (string.IsNullOrEmpty(regionId)) return null;
BuildCacheIfNeeded();
_regionById.TryGetValue(regionId, out var region);
return region;
}
private void BuildCacheIfNeeded()
{
if (_sceneToRegion != null) return;
// Step 1: regionId → RegionDefinitionSO
_regionById = new Dictionary(System.StringComparer.OrdinalIgnoreCase);
if (_regions != null)
foreach (var r in _regions)
if (r != null && !string.IsNullOrEmpty(r.regionId))
_regionById[r.regionId] = r;
// Step 2: sceneName → RegionDefinitionSO,以 MapRoomDataSO.RegionId 为权威来源
_sceneToRegion = new Dictionary(System.StringComparer.OrdinalIgnoreCase);
if (_mapDatabase?.AllRooms == null) return;
foreach (var room in _mapDatabase.AllRooms)
{
if (room == null || string.IsNullOrEmpty(room.RoomId) || string.IsNullOrEmpty(room.RegionId))
continue;
if (_regionById.TryGetValue(room.RegionId, out var def))
_sceneToRegion[room.RoomId] = def;
}
}
private void OnValidate()
{
_sceneToRegion = null;
_regionById = null;
}
}
}