using Map; using System; using System.Collections.Generic; using System.Linq; using Base; using Data; using Managers; using UnityEngine; using Utils; /// /// Program 类作为单例模式的核心管理器,负责维护和管理游戏或应用中的维度(Dimension)实例和焦点状态。 /// 它提供了维度注册、注销、获取以及焦点维度设置的功能。 /// public class Program : Singleton { // 当前角色定义 public CharacterDef CurrentCharacter { get;private set; } // 指示是否需要加载数据的标志,例如在游戏启动或场景切换时。 private bool _needLoad = true; /// /// 指示是否需要加载数据的标志,例如在游戏启动或场景切换时。 /// public bool NeedLoad { get => _needLoad; set { if (value) { CurrentCharacter = null; } _needLoad = value; } } public bool OnPlay => CurrentCharacter != null; /// /// 当前聚焦的实体对象。 /// 变更为属性,并私有化setter,确保通过 SetFocusedEntity 方法集中管理其更新和事件触发。 /// public Entity.Entity FocusedEntity => FocusedDimension?.focusEntity; /// /// 当焦点实体发生变化时触发的事件。 /// 事件参数为新的焦点 Entity 实例,如果焦点被清除则为 null。 /// public event Action OnFocusedEntityChanged; /// /// 当前活跃焦点的维度唯一标识符,可能为空。 /// 变更为属性,并私有化setter,确保通过 SetFocusedDimension 方法集中管理其更新。 /// public string FocusedDimensionId { get; private set; } = null; /// /// 当前聚焦的维度对象实例。当 不为空时,此属性指向对应的维度实例。 /// public Dimension FocusedDimension { get; private set; } /// /// 维护所有已注册的维度实例的字典,键是维度的唯一标识符 (ID)。 /// private readonly Dictionary _registeredDimensions = new Dictionary(); /// /// 获取所有已注册的维度。返回一个只读字典副本,防止外部直接修改。 /// public IReadOnlyDictionary RegisteredDimensions => _registeredDimensions; /// /// 当焦点维度发生变化时触发的事件。 /// 事件参数为新的焦点 Dimension 实例,如果焦点被清除则为 null。 /// public event Action OnFocusedDimensionChanged; /// /// 获取已注册维度的数量。 /// public int DimensionCount => _registeredDimensions.Count; /// /// 获取所有已注册维度的ID数组。 /// public string[] Dimensions => _registeredDimensions.Keys.ToArray(); public bool CanOpenRightMenu => Setting.Instance.CurrentSettings.developerMode && !OnPlay; public bool CanMoveCamera => CanOpenRightMenu; /// /// 注册一个维度实例到 Program。 /// /// 要注册的维度实例。 public void RegisterDimension(Dimension dimension) { if (dimension == null) { Debug.LogError("[Program] 尝试注册一个空的维度。"); return; } var id = dimension.DimensionId; if (string.IsNullOrEmpty(id)) { Debug.LogError($"[Program] 尝试注册一个ID为空的维度: {dimension.name}"); return; } if (!_registeredDimensions.TryAdd(id, dimension)) { Debug.LogWarning($"[Program] ID为 '{id}' 的维度已注册。跳过重复注册 {dimension.name}。"); return; } // 如果注册的维度恰好是当前 focusedDimensionId,SetFocusedDimension(id) 将负责更新 FocusedDimension 并触发事件。 // 并且,由于SetFocusedDimension会清空FocusedEntity,这也符合新维度的行为。 if (FocusedDimensionId == id) { SetFocusedDimension(id); } } /// /// 从 Program 注销一个维度实例。 /// /// 要注销的维度实例。 public void UnregisterDimension(Dimension dimension) { if (dimension == null) { Debug.LogWarning("[Program] 尝试注销一个空的维度。"); return; } var id = dimension.DimensionId; if (_registeredDimensions.Remove(id)) { // 如果注销的维度是当前焦点维度,则调用 SetFocusedDimension(null) 清除焦点并触发事件。 if (FocusedDimensionId == id) { SetFocusedDimension(null); // 清除焦点 } } else { Debug.LogWarning($"[Program] 尝试注销ID为 '{id}' 的维度,但未在已注册列表中找到。"); } } /// /// 根据ID获取一个已注册的维度。 /// /// 维度的唯一标识符。 /// 对应的Dimension实例,如果未找到则返回null。 public Dimension GetDimension(string dimensionId) { if (dimensionId == null) return null; _registeredDimensions.TryGetValue(dimensionId, out var dimension); return dimension; } /// /// 设置当前聚焦的维度。 /// 这是更改焦点维度的唯一官方入口。 /// /// 要设置为焦点的维度的唯一标识符。如果传入null或空字符串,将清除当前焦点维度。 public void SetFocusedDimension(string dimensionId) { // 确定新的焦点维度及其ID Dimension newFocusedDimension = null; // 默认为清除焦点 string newFocusedDimensionId = null; if (!string.IsNullOrEmpty(dimensionId)) { if (_registeredDimensions.TryGetValue(dimensionId, out var foundDimension)) { newFocusedDimensionId = dimensionId; newFocusedDimension = foundDimension; } else { // 如果尝试设置未注册的维度,警告并直接返回,不改变当前焦点状态。 Debug.LogWarning($"[Program] 尝试设置焦点到未注册的维度ID: '{dimensionId}'。焦点未改变。"); return; } } // 如果 dimensionId 为 null 或空, newFocusedDimension 和 newFocusedDimensionId 将保持为 null,表示清除焦点。 // 检查是否实际发生变化 if (FocusedDimensionId == newFocusedDimensionId && FocusedDimension == newFocusedDimension) { return; } if (FocusedEntity) { FocusedEntity.PlayerControlled = false; } // 更新内部状态 FocusedDimensionId = newFocusedDimensionId; FocusedDimension = newFocusedDimension; // 确保功能一致性:当维度焦点改变(或被清除)时,任何实体焦点也应被清除。 SetFocusedEntity(null); // 触发事件 OnFocusedDimensionChanged?.Invoke(FocusedDimension); } /// /// 设置当前聚焦的实体。 /// 这是更改焦点实体的唯一官方入口,并会在实体改变时触发 OnFocusedEntityChanged 事件。 /// /// 要设置为焦点的实体实例。如果传入null,将清除当前焦点实体。 public void SetFocusedEntity(Entity.Entity entity) { // 检查是否实际发生变化 if (FocusedEntity == entity || !FocusedDimension) { return; } FocusedDimension.focusEntity = entity; // 触发事件,将新的焦点实体(或 null)作为参数传递。 OnFocusedEntityChanged?.Invoke(FocusedEntity); } public void PlayGame(CharacterDef character) { CurrentCharacter = character; if (character == null) return; var pos = CameraControl.CameraControl.Instance.Position; var player = EntityManager.Instance.GenerateEntity(FocusedDimensionId, character, new Vector3(pos.x, pos.y)); if(!player) return; player.entity.PlayerControlled = true; } }