namespace BaseGames.World.Map { /// /// IMapService 无状态扩展方法,集中可复用的查询逻辑。 /// MapPanel、MinimapHUD 等所有消费方均调用此处,避免分散的重复实现。 /// /// RegionNameEntry 字典构建与解析逻辑(BuildRegionDict / ResolveRegionDisplayName) /// 也集中在此,供 RegionNameDisplay 和 MapProgressDisplay 共享,消除 DRY 违反。 /// /// public static class MapServiceExtensions { /// /// 将 RegionNameEntry 数组构建为 O(1) 查询字典。 /// RegionNameDisplay / MapProgressDisplay 共享此实现,避免重复代码。 /// public static System.Collections.Generic.Dictionary BuildRegionDict( RegionNameEntry[] entries) { var dict = new System.Collections.Generic.Dictionary(); if (entries == null) return dict; foreach (var e in entries) if (!string.IsNullOrEmpty(e.RegionId)) dict[e.RegionId] = e; return dict; } /// /// 将 regionId 解析为玩家可读的显示名。 /// 优先读 LocKey,其次 DisplayName,最后回退到 regionId 本身。 /// public static string ResolveRegionDisplayName( System.Collections.Generic.Dictionary dict, string regionId) { if (dict != null && dict.TryGetValue(regionId, out var e)) return e.GetDisplayName(); return regionId; } /// /// 根据探索状态推导房间三级可见性(Explored > Mapped > Unknown)。 /// public static RoomVisibility GetVisibility(this IMapService svc, string roomId) { if (svc == null) return RoomVisibility.Unknown; if (svc.IsExplored(roomId)) return RoomVisibility.Explored; if (svc.IsMapped(roomId)) return RoomVisibility.Mapped; return RoomVisibility.Unknown; } /// /// 在指定世界坐标处创建地图标记。 /// 通过 将世界坐标转换为 /// 房间 ID 和归一化位置;坐标不在任何已知房间内时返回 null。 /// public static BaseGames.Core.Save.MapPin CreatePinAtWorldPos( this IPinService pinSvc, IPlayerPositionProvider playerProvider, UnityEngine.Vector3 worldPos, BaseGames.Core.Save.PinType type = BaseGames.Core.Save.PinType.Marker, string note = "") { if (pinSvc == null || playerProvider == null) return null; if (!playerProvider.TryGetRoomAtWorldPos(worldPos, out var roomId, out var normPos)) return null; return pinSvc.CreatePin(roomId, normPos.x, normPos.y, type, note); } } }