diff --git a/Assets/PerfectWorld/Scripts/DebugCommandMenu/DebugCmdHistoryStore.cs b/Assets/PerfectWorld/Scripts/DebugCommandMenu/DebugCmdHistoryStore.cs index d9fae9c7df..46e4e77021 100644 --- a/Assets/PerfectWorld/Scripts/DebugCommandMenu/DebugCmdHistoryStore.cs +++ b/Assets/PerfectWorld/Scripts/DebugCommandMenu/DebugCmdHistoryStore.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using UnityEngine; namespace BrewMonster.Scripts @@ -31,7 +32,10 @@ namespace BrewMonster.Scripts public static List Load() { - // First-run: seed from Resources into PlayerPrefs so runtime can modify via PlayerPrefs. +#if UNITY_EDITOR + return LoadFromEditorJsonFile(); +#else + // Runtime: first-run seed from Resources into PlayerPrefs, then keep using PlayerPrefs. if (!IsInited()) { var seed = LoadFromResources(); @@ -41,11 +45,16 @@ namespace BrewMonster.Scripts } return LoadFromPlayerPrefs(); +#endif } public static void Save(List entries) { +#if UNITY_EDITOR + SaveToEditorJsonFile(entries); +#else SaveToPlayerPrefs(entries); +#endif } public static bool Upsert(List entries, int header, int param, bool hasParam, string describe) @@ -103,9 +112,22 @@ namespace BrewMonster.Scripts public static void Clear() { +#if UNITY_EDITOR + try + { + var path = GetEditorJsonAbsolutePath(); + if (File.Exists(path)) + File.Delete(path); + } + catch (Exception ex) + { + Debug.LogWarning($"[DebugCmdHistoryStore] Clear (editor json) failed: {ex.Message}"); + } +#else PlayerPrefs.DeleteKey(PlayerPrefsJsonKey); PlayerPrefs.DeleteKey(PlayerPrefsInitedKey); PlayerPrefs.Save(); +#endif } public static bool Remove(List entries, int header, int param, bool hasParam) @@ -121,6 +143,61 @@ namespace BrewMonster.Scripts return true; } + private static string GetEditorJsonAbsolutePath() + { + // Keep it under Assets/Resources so it can be included as a TextAsset for runtime seeding. + return Path.Combine(Application.dataPath, "Resources", $"{ResourcesJsonPathNoExt}.json"); + } + + private static List LoadFromEditorJsonFile() + { + try + { + var path = GetEditorJsonAbsolutePath(); + if (!File.Exists(path)) + return LoadFromResources(); // fallback if file not created yet + + var json = File.ReadAllText(path); + if (string.IsNullOrWhiteSpace(json)) + return new List(); + + var wrapper = JsonUtility.FromJson(json); + if (wrapper == null || wrapper.items == null) + return new List(); + + wrapper.items.RemoveAll(e => e == null); + return wrapper.items; + } + catch + { + return new List(); + } + } + + private static void SaveToEditorJsonFile(List entries) + { + try + { + var wrapper = new EntryListWrapper { items = entries ?? new List() }; + string json = JsonUtility.ToJson(wrapper, prettyPrint: true); + + var path = GetEditorJsonAbsolutePath(); + var dir = Path.GetDirectoryName(path); + if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + File.WriteAllText(path, json); + +#if UNITY_EDITOR + UnityEditor.AssetDatabase.Refresh(); +#endif + } + catch (Exception ex) + { + Debug.LogWarning($"[DebugCmdHistoryStore] Save (editor json) failed: {ex.Message}"); + } + } + private static List LoadFromResources() { try diff --git a/Assets/Scripts/EC_GameRun.cs b/Assets/Scripts/EC_GameRun.cs index 226ecd3065..aff54b0491 100644 --- a/Assets/Scripts/EC_GameRun.cs +++ b/Assets/Scripts/EC_GameRun.cs @@ -1243,6 +1243,8 @@ public partial class CECGameRun : ITickable // g_TickMemoryHistory(); // #endif + TickHealthPlaytimeChatReminder(dwDeltaTime); + return true; } diff --git a/Assets/Scripts/EC_GameRunChat.cs b/Assets/Scripts/EC_GameRunChat.cs index 562291da16..f49fe87bca 100644 --- a/Assets/Scripts/EC_GameRunChat.cs +++ b/Assets/Scripts/EC_GameRunChat.cs @@ -104,4 +104,50 @@ partial class CECGameRun } } } + + /// + /// Seconds between chat reminders (default 10). Change at runtime or in code as needed. + /// + public float healthPlaytimeChatReminderIntervalSeconds = 600f; + + private uint _healthPlaytimeChatReminderAccumMs; + private bool _healthPlaytimeChatReminderDidImmediateThisSession; + + private const string HealthPlaytimeChatReminderText = + "Chơi game quá 180 phút có hại cho sức khoẻ"; + + private static void PublishHealthPlaytimeChatReminder() + { + string redMsg = "" + HealthPlaytimeChatReminderText + ""; + EventBus.Publish(new GameSession.ChatMessageEvent(redMsg, (byte)ChatChannel.GP_CHAT_SYSTEM)); + } + + private void TickHealthPlaytimeChatReminder(uint dwDeltaMs) + { + if (GetGameState() != (int)GameState.GS_GAME) + { + _healthPlaytimeChatReminderAccumMs = 0; + _healthPlaytimeChatReminderDidImmediateThisSession = false; + return; + } + + if (!_healthPlaytimeChatReminderDidImmediateThisSession) + { + _healthPlaytimeChatReminderDidImmediateThisSession = true; + _healthPlaytimeChatReminderAccumMs = 0; + PublishHealthPlaytimeChatReminder(); + } + + float intervalSec = Mathf.Max(0.1f, healthPlaytimeChatReminderIntervalSeconds); + uint intervalMs = (uint)(intervalSec * 1000f); + if (intervalMs < 1) + intervalMs = 1; + + _healthPlaytimeChatReminderAccumMs += dwDeltaMs; + while (_healthPlaytimeChatReminderAccumMs >= intervalMs) + { + _healthPlaytimeChatReminderAccumMs -= intervalMs; + PublishHealthPlaytimeChatReminder(); + } + } }