using System; using System.Linq; using UnityEngine; using System.Collections.Generic; namespace BingoBrain.Core { public class UFdsa : MonoBehaviour { private class TimerTask { private UFdsa _mUFdsa; private string name; private TimerMode mode; private float startTime; private float duration; private bool isBreak = false; private float breakStart; private float breakDuration = 0; private Action timerEvent; private Action timerArgsEvent; private object[] args = null; public float TimeLeft => Mathf.Max(0f, duration - (_mUFdsa.GetTime() - startTime) + breakDuration); public TimerTask(UFdsa uFdsa, string name, TimerMode mode, float startTime, float duration, Action handler) { this._mUFdsa = uFdsa; this.name = name; this.mode = mode; this.startTime = startTime; this.duration = duration; timerEvent = handler; } public TimerTask(UFdsa uFdsa, string name, TimerMode mode, float startTime, float duration, Action handler, params object[] args) { this._mUFdsa = uFdsa; this.name = name; this.mode = mode; this.startTime = startTime; this.duration = duration; timerArgsEvent = handler; this.args = args; } public void Run() { if (isBreak) { return; } if (TimeLeft > 0f) { return; } if (mode == TimerMode.Normal) { _mUFdsa.RemoveTimer(name); } else { startTime = _mUFdsa.GetTime(); breakDuration = 0; } timerEvent?.Invoke(); timerArgsEvent?.Invoke(args); } public void Break() { if (isBreak) { return; } isBreak = true; breakStart = _mUFdsa.GetTime(); } public void Resume() { if (!isBreak) { return; } breakDuration += (_mUFdsa.GetTime() - breakStart); isBreak = false; } public static implicit operator bool(TimerTask timerTask) { return null != timerTask; } } private enum TimerMode { Normal, Repeat, } private Dictionary addTimerList = new(); private Dictionary timerList = new(); private List destroyTimerList = new(); [SerializeField] private string timerName; private TimerTimeType type = TimerTimeType.Null; public void SetTimer(string name, TimerTimeType type) { timerName = name + "_" + type; this.type = type; } private float GetTime() { return type switch { TimerTimeType.Time => Time.time, TimerTimeType.UnscaledTime => Time.unscaledTime, TimerTimeType.RealtimeSinceStartup => Time.realtimeSinceStartup, _ => 0 }; } private void Update() { if (destroyTimerList.Count > 0) { foreach (var i in destroyTimerList) { timerList.Remove(i); } destroyTimerList.Clear(); } if (addTimerList.Count > 0) { foreach (var i in addTimerList.Where(i => i.Value != null)) { timerList[i.Key] = i.Value; } addTimerList.Clear(); } if (timerList.Count > 0) { foreach (var timer in timerList.Values) { if (timer == null) { return; } timer.Run(); } } } public bool AddTimer(string key, float duration, Action handler) { return InternalAddTimer(key, TimerMode.Normal, duration, handler); } public bool AddTimer(string key, float duration, Action handler, params object[] args) { return InternalAddTimer(key, TimerMode.Normal, duration, handler, args); } public bool AddRepeatTimer(string key, float duration, Action handler) { return InternalAddTimer(key, TimerMode.Repeat, duration, handler); } public bool AddRepeatTimer(string key, float duration, Action handler, params object[] args) { return InternalAddTimer(key, TimerMode.Repeat, duration, handler, args); } private bool InternalAddTimer(string key, TimerMode mode, float duration, Action handler) { if (string.IsNullOrEmpty(key)) { return false; } if (duration <= 0.0f) { if (mode == TimerMode.Normal) { handler(); } else { Debug.LogError("[HeavyTimer]Add Repeat Timer Error: Time is Not Greater Than Zero"); } return false; } var timer = new TimerTask(this, key, mode, GetTime(), duration, handler); addTimerList[key] = timer; return true; } private bool InternalAddTimer(string key, TimerMode mode, float duration, Action handler, params object[] args) { if (string.IsNullOrEmpty(key)) { return false; } if (duration <= 0.0f) { if (mode == TimerMode.Normal) { handler(args); } else { Debug.LogError("[HeavyTimer]Add Repeat Timer Error: Time is Not Greater Than Zero"); } return false; } var timer = new TimerTask(this, key, mode, GetTime(), duration, handler, args); addTimerList[key] = timer; return true; } public void BreakTimerWithPrefix(string prefix) { if (timerList is { Count: > 0 }) { var arr = new string[timerList.Count]; timerList.Keys.CopyTo(arr, 0); foreach (var t in arr) { if (t.StartsWith(prefix)) { BreakTimer(t); } } } } public void BreakTimer(string key) { if (!timerList.ContainsKey(key)) { return; } var timer = timerList[key]; timer.Break(); } public void ResumeTimerWithPrefix(string prefix) { if (timerList is { Count: > 0 }) { var arr = new string[timerList.Count]; timerList.Keys.CopyTo(arr, 0); foreach (var t in arr) { if (t.StartsWith(prefix)) { ResumeTimer(t); } } } } public void ResumeTimer(string key) { if (!timerList.ContainsKey(key)) { return; } var timer = timerList[key]; timer.Resume(); } public void ClearTimerWithPrefix(string prefix) { if (timerList is { Count: > 0 }) { foreach (var timerKey in timerList.Keys.Where(timerKey => timerKey.StartsWith(prefix))) { RemoveTimer(timerKey); } } } public bool RemoveTimer(string key) { if (!timerList.ContainsKey(key)) { return false; } if (!destroyTimerList.Contains(key)) { destroyTimerList.Add(key); } return true; } public bool IsRunning(string key) { return timerList.ContainsKey(key); } public float GetTimerLeft(string key) { if (!timerList.ContainsKey(key)) { return 0.0f; } var timer = timerList[key]; return timer.TimeLeft; } public float GetTimerLeftWithPrefix(string prefix) { if (timerList is { Count: > 0 }) { var arr = new string[timerList.Count]; timerList.Keys.CopyTo(arr, 0); return (from t in arr where t.StartsWith(prefix) select GetTimerLeft(t)).FirstOrDefault(); } return 0.0f; } public void ClearAll() { addTimerList.Clear(); timerList.Clear(); destroyTimerList.Clear(); } public void Destroy() { Destroy(this); } private void OnDestroy() { ClearAll(); addTimerList = null; timerList = null; destroyTimerList = null; } } }