using System; using System.Collections.Generic; using UnityEngine; namespace Jovian.EncounterSystem { [CreateAssetMenu(fileName = "EncounterTable", menuName = "Jovian/Encounter System/Encounter Table", order = 1)] public class EncounterTable : ScriptableObject { public string id; public List encounters; private Dictionary idCache; /// O(1) lookup by . Used by . /// Call if you mutate the list at runtime. public IEncounter Resolve(string internalId) { if(string.IsNullOrEmpty(internalId) || encounters == null || encounters.Count == 0) { return null; } EnsureCache(); return idCache.GetValueOrDefault(internalId); } /// Force the id lookup cache to rebuild on next use. public void InvalidateCache() { idCache = null; } private void EnsureCache() { if(idCache != null) { return; } idCache = new Dictionary(encounters?.Count ?? 0); if(encounters == null) { return; } for(var i = 0; i < encounters.Count; i++) { var encounter = encounters[i]; var internalId = encounter?.EncounterDefinition?.internalId; if(!string.IsNullOrEmpty(internalId)) { idCache[internalId] = encounter; } } } #if UNITY_EDITOR // Unity's inspector "+" duplicates the previous list element, including nested internalId // GUIDs. Regenerate any duplicates so every encounter carries a unique internalId. private void OnValidate() { InvalidateCache(); if(encounters == null) { return; } var seen = new HashSet(encounters.Count); var changed = false; for(int i = 0; i < encounters.Count; i++) { var encounter = encounters[i]; if(encounter?.EncounterDefinition == null) { continue; } var entryId = encounter.EncounterDefinition.internalId; if(string.IsNullOrEmpty(entryId) || !seen.Add(entryId)) { encounter.EncounterDefinition.internalId = Guid.NewGuid().ToString(); seen.Add(encounter.EncounterDefinition.internalId); changed = true; } } if(changed) { UnityEditor.EditorUtility.SetDirty(this); } } #endif } }