diff --git a/Assets/_DDD/_Scripts/GameFramework/Localization/LocalizationManager.cs b/Assets/_DDD/_Scripts/GameFramework/Localization/LocalizationManager.cs index ec217c5c7..3e5b16402 100644 --- a/Assets/_DDD/_Scripts/GameFramework/Localization/LocalizationManager.cs +++ b/Assets/_DDD/_Scripts/GameFramework/Localization/LocalizationManager.cs @@ -97,7 +97,7 @@ public string GetString(string key) var entryRef = key; var locale = LocalizationSettings.SelectedLocale; - VariablesGroupAsset variables = SmartStringVariables.Instance.GetVariablesGroupAsset(); + VariablesGroupAsset variables = GameDataSo.instance.GameLocalizationData.SmartStringVariableGroup; if (variables != null) { _singleArgBuffer.Clear(); diff --git a/Assets/_DDD/_Scripts/GameFramework/Localization/SmartStringVariables.cs b/Assets/_DDD/_Scripts/GameFramework/Localization/SmartStringVariables.cs index 96b89641e..506679cb5 100644 --- a/Assets/_DDD/_Scripts/GameFramework/Localization/SmartStringVariables.cs +++ b/Assets/_DDD/_Scripts/GameFramework/Localization/SmartStringVariables.cs @@ -1,39 +1,128 @@ +using System; +using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Localization.SmartFormat.PersistentVariables; namespace DDD { - /// - /// Smart String 변수 전담 매니저. - /// - VariablesGroupAsset 안의 변수들을 생성/재사용하고 값만 갱신(무가비지). - /// - {day}, {playerName}, {money} 등 공용 Set API 제공. - /// - public class SmartStringVariables : Singleton, IManager + [Flags] + public enum SmartVariablesDomain : uint { - private VariablesGroupAsset _vars; - private GameStateSo _gameStateSo; + None = 0u, + RestaurantToday = 1u << 0, + ChecklistTargets = 1u << 1, + PlayerLevel = 1u << 2, + All = 0xFFFFFFFFu, + } - private const string VariablesGroupAssetKey = "SmartStringGroup"; - private const string Daykey = "day"; + public enum smartStringKey + { + None = 0, + Day, + AddedTodayFoodCount, + AddedTodayCookwareCount, + MatchedTodayMenuWithCookwareCount, + ChecklistFoodCount, + ChecklistCookwareCount, + ChecklistMatchedMenuWithCookwareCount, + } + + public class SmartStringVariables : Singleton, IManager, IEventHandler + { + private Dictionary _smartStringKeys = new() + { + {smartStringKey.Day, "day"}, + {smartStringKey.AddedTodayFoodCount, "addedTodayFoodCount"}, + {smartStringKey.AddedTodayCookwareCount, "addedTodayCookwareCount"}, + {smartStringKey.MatchedTodayMenuWithCookwareCount, "matchedTodayMenuWithCookwareCount"}, + {smartStringKey.ChecklistFoodCount, "checklistFoodCount"}, + {smartStringKey.ChecklistCookwareCount, "checklistCookwareCount"}, + {smartStringKey.ChecklistMatchedMenuWithCookwareCount, "checklistMatchedMenuWithCookwareCount"}, + }; + + private void OnDestroy() + { + EventBus.Unregister(this); + } public void PreInit() { } public async Task Init() { - _vars = await AssetManager.LoadAsset(VariablesGroupAssetKey); - Debug.Assert(_vars != null, "_variablesGroupAsset is null"); - - _gameStateSo = await AssetManager.LoadAsset(DataConstants.GameStateSo); - Debug.Assert(_gameStateSo != null, "_gameStateSo is null"); + var gameLevelStateSo = GameStateSo.instance.GameLevelStateSo; + var restaurantStateSo = RestaurantState.instance.ManagementState; // 예시: day 초기 세팅 (없으면 생성, 타입 다르면 교체) - Set(Daykey, _gameStateSo.GetCurrentLevel()); + Set(_smartStringKeys[smartStringKey.Day], gameLevelStateSo.Level); + Set(_smartStringKeys[smartStringKey.AddedTodayFoodCount], restaurantStateSo.AddedTodayFoodCount); + Set(_smartStringKeys[smartStringKey.AddedTodayCookwareCount], restaurantStateSo.AddedTodayCookwareCount); + Set(_smartStringKeys[smartStringKey.MatchedTodayMenuWithCookwareCount], restaurantStateSo.MatchedTodayMenuWithCookwareCount); + Set(_smartStringKeys[smartStringKey.ChecklistFoodCount], restaurantStateSo.ChecklistFoodCount); + Set(_smartStringKeys[smartStringKey.ChecklistCookwareCount], restaurantStateSo.ChecklistCookwareCount); + Set(_smartStringKeys[smartStringKey.ChecklistMatchedMenuWithCookwareCount], restaurantStateSo.ChecklistMatchedMenuWithCookwareCount); + + await Task.CompletedTask; } - public void PostInit() { } + public void PostInit() + { + // 도메인 단위 더티 이벤트를 구독하여 필요한 key만 갱신 + EventBus.Register(this); + } - public VariablesGroupAsset GetVariablesGroupAsset() => _vars; + private RestaurantManagementStateSo GetRestaurantState() => RestaurantState.instance.ManagementState; + + public void Invoke(SmartVariablesDirtyEvent evt) + { + var flags = evt.DomainFlags; + if (flags == SmartVariablesDomain.All) + { + RefreshAll(); + return; + } + if ((flags & SmartVariablesDomain.RestaurantToday) != 0) + { + RefreshTodayMenuCounts(); + } + if ((flags & SmartVariablesDomain.ChecklistTargets) != 0) + { + RefreshChecklistTargets(); + } + if ((flags & SmartVariablesDomain.PlayerLevel) != 0) + { + RefreshDay(); + } + } + + public void RefreshTodayMenuCounts() + { + var state = GetRestaurantState(); + Set(_smartStringKeys[smartStringKey.AddedTodayFoodCount], state.AddedTodayFoodCount); + Set(_smartStringKeys[smartStringKey.AddedTodayCookwareCount], state.AddedTodayCookwareCount); + Set(_smartStringKeys[smartStringKey.MatchedTodayMenuWithCookwareCount], state.MatchedTodayMenuWithCookwareCount); + } + + public void RefreshChecklistTargets() + { + var state = GetRestaurantState(); + Set(_smartStringKeys[smartStringKey.ChecklistFoodCount], state.ChecklistFoodCount); + Set(_smartStringKeys[smartStringKey.ChecklistCookwareCount], state.ChecklistCookwareCount); + Set(_smartStringKeys[smartStringKey.ChecklistMatchedMenuWithCookwareCount], state.ChecklistMatchedMenuWithCookwareCount); + } + + public void RefreshDay() + { + var gameLevelStateSo = GameStateSo.instance.GameLevelStateSo; + Set(_smartStringKeys[smartStringKey.Day], gameLevelStateSo.Level); + } + + public void RefreshAll() + { + RefreshDay(); + RefreshTodayMenuCounts(); + RefreshChecklistTargets(); + } // ---------- 공용 Set API (가비지 최소화) ---------- @@ -48,7 +137,7 @@ public void Set(string key, int value) public void Set(string key, float value) { var v = Ensure(key); - if (!Mathf.Approximately(v.Value, value)) v.Value = value; + if (Mathf.Approximately(v.Value, value) == false) v.Value = value; } /// bool 변수 세팅. {key} 로 접근. @@ -62,7 +151,7 @@ public void Set(string key, bool value) public void Set(string key, string value) { var v = Ensure(key); - if (!string.Equals(v.Value, value)) v.Value = value; + if (string.Equals(v.Value, value) == false) v.Value = value; } /// @@ -73,7 +162,7 @@ public void SetEnum(string key, TEnum value) where TEnum : struct { var v = Ensure(key); string s = value.ToString(); - if (!string.Equals(v.Value, s)) v.Value = s; + if (string.Equals(v.Value, s) == false) v.Value = s; } // ---------- 유틸 ---------- @@ -84,24 +173,24 @@ public void SetEnum(string key, TEnum value) where TEnum : struct /// private T Ensure(string key) where T : class, IVariable, new() { - Debug.Assert(!string.IsNullOrEmpty(key), "SmartStringVariables.Ensure: key is null or empty."); - Debug.Assert(_vars != null, "SmartStringVariables.Ensure: _vars is null (Init 순서 확인)."); - - if (_vars.TryGetValue(key, out var existing)) + if (string.IsNullOrWhiteSpace(key)) { - if (existing is T ok) return ok; - _vars.Remove(key); // 타입 다르면 제거 후 교체 + Debug.LogError("SmartStringVariables.Ensure: key is null or empty."); + return null; + } + + var smartStringVariableGroup = GameDataSo.instance.GameLocalizationData.SmartStringVariableGroup; + + if (smartStringVariableGroup.TryGetValue(key, out var existing)) + { + if (existing is T hasType) return hasType; + + smartStringVariableGroup.Remove(key); // 타입 다르면 제거 후 교체 } var created = new T(); - _vars.Add(key, created); + smartStringVariableGroup.Add(key, created); return (T)created; } - - /// 변수 존재 여부. - public bool Has(string key) => _vars != null && _vars.ContainsKey(key); - - /// 변수 제거. - public bool Remove(string key) => _vars != null && _vars.Remove(key); } }