using System.Collections.Generic; using System.Linq; using UnityEngine; public class StatRegistry : MonoBehaviour { [Header("Auto-Discovery Settings")] [SerializeField] private string statDefinitionsResourcesPath = "StatDefinitions"; [SerializeField] private bool autoRefreshInEditor = true; [Header("Loaded Stats (Read-Only)")] [SerializeField] private StatDefinition[] allStats = new StatDefinition[0]; // Singleton instance private static StatRegistry _instance; public static StatRegistry Instance { get { if (_instance == null) { _instance = FindObjectOfType(); if (_instance == null) { GameObject registryGO = new GameObject("StatRegistry"); _instance = registryGO.AddComponent(); DontDestroyOnLoad(registryGO); } } return _instance; } } // Dictionary for fast lookups private Dictionary statLookup; private bool isInitialized = false; private void Awake() { // Singleton enforcement if (_instance != null && _instance != this) { Destroy(gameObject); return; } _instance = this; DontDestroyOnLoad(gameObject); Initialize(); } [ContextMenu("Refresh Stat Definitions")] public void RefreshStatDefinitions() { LoadAllStatDefinitions(); BuildLookupDictionary(); Debug.Log($"StatRegistry: Loaded {allStats.Length} stat definitions from Resources/{statDefinitionsResourcesPath}"); } private void Initialize() { if (isInitialized) return; RefreshStatDefinitions(); isInitialized = true; } private void LoadAllStatDefinitions() { // Load all StatDefinition assets from the specified Resources folder StatDefinition[] loadedStats = Resources.LoadAll(statDefinitionsResourcesPath); // Validate for duplicate keys var duplicateKeys = loadedStats .GroupBy(stat => stat.StatKey) .Where(g => g.Count() > 1) .Select(g => g.Key); if (duplicateKeys.Any()) { Debug.LogError($"StatRegistry: Duplicate stat keys found: {string.Join(", ", duplicateKeys)}"); } // Filter out any with empty keys allStats = loadedStats .Where(stat => !string.IsNullOrEmpty(stat.StatKey)) .ToArray(); // Sort alphabetically for consistent ordering System.Array.Sort(allStats, (a, b) => string.Compare(a.StatKey, b.StatKey, System.StringComparison.OrdinalIgnoreCase)); } private void BuildLookupDictionary() { statLookup = new Dictionary(); foreach (var stat in allStats) { if (!statLookup.ContainsKey(stat.StatKey)) { statLookup[stat.StatKey] = stat; } else { Debug.LogWarning($"StatRegistry: Duplicate stat key '{stat.StatKey}' ignored for asset '{stat.name}'"); } } } // Public API methods public StatDefinition GetStat(string statKey) { if (!isInitialized) Initialize(); return statLookup.TryGetValue(statKey, out StatDefinition stat) ? stat : null; } public StatDefinition[] GetAllStats() { if (!isInitialized) Initialize(); return allStats; } public StatDefinition[] GetStatsByCategory(StatCategory category) { if (!isInitialized) Initialize(); return allStats.Where(stat => stat.Category == category).ToArray(); } public StatDefinition[] GetItemRollableStats() { if (!isInitialized) Initialize(); return allStats.Where(stat => stat.CanRollOnItems).ToArray(); } public StatDefinition[] GetPrimaryStats() { if (!isInitialized) Initialize(); return allStats.Where(stat => stat.IsPrimary).ToArray(); } public StatDefinition[] GetUIVisibleStats() { if (!isInitialized) Initialize(); return allStats.Where(stat => stat.ShowInUI).ToArray(); } public bool HasStat(string statKey) { if (!isInitialized) Initialize(); return statLookup.ContainsKey(statKey); } public int GetStatCount() { if (!isInitialized) Initialize(); return allStats.Length; } // Debug/Editor methods public void LogAllStats() { if (!isInitialized) Initialize(); Debug.Log($"=== StatRegistry Contents ({allStats.Length} stats) ==="); foreach (var category in System.Enum.GetValues(typeof(StatCategory)).Cast()) { var statsInCategory = GetStatsByCategory(category); if (statsInCategory.Length > 0) { Debug.Log($"{category}: {string.Join(", ", statsInCategory.Select(s => s.StatKey))}"); } } } #if UNITY_EDITOR private void OnValidate() { // Auto-refresh in editor when settings change if (autoRefreshInEditor && Application.isPlaying) { RefreshStatDefinitions(); } } #endif }