using UnityEngine;
using UnityEngine.SceneManagement;
using BaseGames.Core.Events;
using BaseGames.Core.Save;
namespace BaseGames.Core
{
///
/// 在 Awake 时(最早执行)向 ServiceLocator 注册所有服务。
/// 挂载在 Persistent 场景的根 GameObject 上。
///
[DefaultExecutionOrder(-2000)]
public class GameServiceRegistrar : MonoBehaviour
{
[SerializeField] private DeathRespawnService _deathRespawnService;
[SerializeField] private SceneService _sceneService;
[SerializeField] private EventChannelRegistry _eventChannelRegistry;
[SerializeField] private SaveManager _saveManager;
///
/// Persistent 场景中唯一保留的主 AudioListener(通常挂在主相机上)。
/// 在 Inspector 中绑定后可完全跳过 Awake 时的 FindObjectsOfType 全场景扫描。
/// 未绑定时自动执行运行时扫描。
///
[SerializeField] private AudioListener _primaryListener;
private bool _audioListenerFixLogged;
private void Awake()
{
// 若 Inspector 已绑定主 AudioListener,直接使用,跳过全场景扫描
if (_primaryListener != null)
DisableDuplicateListenersInCurrentScenes();
else
EnsureSingleAudioListener(); // 未绑定时回退:全量扫描并自动缓存
SceneManager.sceneLoaded += OnSceneLoaded;
// 注册 NullAudioService 作为兜底;AudioManager.Awake 后会用真实实现覆盖
ServiceLocator.RegisterIfAbsent(new NullAudioService());
if (_deathRespawnService)
ServiceLocator.Register(_deathRespawnService);
if (_sceneService)
ServiceLocator.Register(_sceneService);
if (_eventChannelRegistry)
ServiceLocator.Register(_eventChannelRegistry);
if (_saveManager)
ServiceLocator.Register(new SaveServiceAdapter(_saveManager));
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (_primaryListener != null)
{
// 仅扫描新加载场景的根节点,避免 FindObjectsOfType 全场景遍历
int disabled = 0;
foreach (var root in scene.GetRootGameObjects())
foreach (var al in root.GetComponentsInChildren(true))
{
if (al == _primaryListener || !al.enabled) continue;
al.enabled = false;
disabled++;
}
if (disabled > 0)
Debug.LogWarning($"[GameServiceRegistrar] Scene '{scene.name}' 中禁用了 {disabled} 个多余的 AudioListener。");
}
else
{
// 首次加载时 _primaryListener 可能尚未缓存,回退到全量扫描
EnsureSingleAudioListener();
}
}
///
/// 当 Inspector 已预绑定 _primaryListener 时,无需全场景扫描。
/// 仅遍历当前已加载场景的根节点,禁用多余的 AudioListener。
///
private void DisableDuplicateListenersInCurrentScenes()
{
int sceneCount = SceneManager.sceneCount;
int disabled = 0;
for (int s = 0; s < sceneCount; s++)
{
Scene scene = SceneManager.GetSceneAt(s);
if (!scene.isLoaded) continue;
foreach (var root in scene.GetRootGameObjects())
foreach (var al in root.GetComponentsInChildren(true))
{
if (al == _primaryListener || !al.enabled) continue;
al.enabled = false;
disabled++;
}
}
if (disabled > 0 && !_audioListenerFixLogged)
{
Debug.LogWarning($"[GameServiceRegistrar] Disabled {disabled} duplicate AudioListener(s). Primary: '{_primaryListener.gameObject.name}'.");
_audioListenerFixLogged = true;
}
}
private void EnsureSingleAudioListener()
{
AudioListener[] listeners = FindObjectsOfType(true); AudioListener primary = null;
int enabledCount = 0;
for (int i = 0; i < listeners.Length; i++)
{
AudioListener listener = listeners[i];
if (listener == null || !listener.enabled || !listener.gameObject.activeInHierarchy)
continue;
enabledCount++;
if (primary == null)
primary = listener;
if (listener.gameObject.scene.name == "Persistent")
primary = listener;
}
if (enabledCount <= 1 || primary == null)
{
_primaryListener = primary; // 缓存(含 enabledCount==1 时的单个监听器)
return;
}
int disabled = 0;
for (int i = 0; i < listeners.Length; i++)
{
AudioListener listener = listeners[i];
if (listener == null || listener == primary)
continue;
if (!listener.enabled || !listener.gameObject.activeInHierarchy)
continue;
listener.enabled = false;
disabled++;
}
_primaryListener = primary; // 缓存主监听器
if (disabled > 0 && !_audioListenerFixLogged)
{
Debug.LogWarning($"[GameServiceRegistrar] Found {enabledCount} active AudioListeners. Kept '{primary.gameObject.name}' and disabled {disabled} duplicate listener(s).");
_audioListenerFixLogged = true;
}
}
}
///
/// 将 SaveManager 适配为 ISaveService。
/// 由于 BaseGames.Core.Save 与 BaseGames.Core 存在循环依赖风险,
/// SaveManager 不直接声明实现 ISaveService;由此 Adapter 桥接,
/// 保持 Core → Core.Save 的单向依赖方向不变。
///
internal sealed class SaveServiceAdapter : ISaveService
{
private readonly BaseGames.Core.Save.SaveManager _save;
internal SaveServiceAdapter(BaseGames.Core.Save.SaveManager save) => _save = save;
// ── I/O 操作 ──────────────────────────────────────────────────────
public System.Threading.Tasks.Task SaveAsync(int slot) => _save.SaveAsync(slot);
public System.Threading.Tasks.Task LoadAsync(int slot) => _save.LoadAsync(slot);
public void QuickSave() => _save.QuickSave();
public void QuickLoad() => _save.QuickLoad();
public System.Threading.Tasks.Task QuickLoadAsync() => _save.LoadAsync(BaseGames.Core.Save.SaveManager.QuickSaveSlot);
public bool HasSave(int slot) => _save.SlotExists(slot);
public int ActiveSlot => _save.CurrentSlot;
public System.Threading.Tasks.Task DeleteSlotAsync(int slot) => _save.DeleteSlotAsync(slot);
// ── 存档点 ────────────────────────────────────────────────────────
public string LastCheckpointScene => _save.LastCheckpointScene;
public string LastCheckpointSpawnId => _save.LastCheckpointSpawnId;
// ── 世界状态查询 ──────────────────────────────────────────────────
public bool IsWorldCollected(string id) => _save.IsWorldCollected(id);
public bool IsDoorOpened(string id) => _save.IsDoorOpened(id);
public bool IsBossDefeated(string bossId) => _save.IsBossDefeated(bossId);
public int GetPlayerMaxHP() => _save.GetPlayerMaxHP();
public bool IsFirstClear(string challengeId) => _save.IsFirstClear(challengeId);
// ── 世界标志 & 事件链 ─────────────────────────────────────────────
public bool GetFlag(string flagId) => _save.GetFlag(flagId);
public void SetFlag(string flagId, bool value) => _save.SetFlag(flagId, value);
public System.Collections.Generic.IEnumerable GetCompletedChains() => _save.GetCompletedChains();
public void SetChainCompleted(string chainId) => _save.SetChainCompleted(chainId);
}
}