188 lines
5.3 KiB
C#
188 lines
5.3 KiB
C#
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<StatRegistry>();
|
|
if (_instance == null)
|
|
{
|
|
GameObject registryGO = new GameObject("StatRegistry");
|
|
_instance = registryGO.AddComponent<StatRegistry>();
|
|
DontDestroyOnLoad(registryGO);
|
|
}
|
|
}
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
// Dictionary for fast lookups
|
|
private Dictionary<string, StatDefinition> 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<StatDefinition>(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<string, StatDefinition>();
|
|
|
|
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<StatCategory>())
|
|
{
|
|
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
|
|
} |