using System; using System.Collections.Generic; using SUISS.Core; using UnityEngine; namespace SUISSEngine { public sealed class TimerManager : SingletonMonobehaviour { protected override void Awake() { base.Awake(); if (!this._isValidNewInstance) { return; } base.transform.parent = null; UnityEngine.Object.DontDestroyOnLoad(this); } private void Update() { this.FireGameTimers(ref this._gameTimersDirty, this._gameTimers); this.FireClockTimers(ref this._utcClockTimersDirty, this._utcClockTimers, DateTime.UtcNow); this.FireClockTimers(ref this._localClockTimersDirty, this._localClockTimers, DateTime.Now); } protected override void OnDestroy() { base.OnDestroy(); this.CancelTimers(this._gameTimers); this.CancelTimers(this._utcClockTimers); this.CancelTimers(this._localClockTimers); } public Timer CreateGameTimer(float interval, Action action) { return this.CreateGameTimer(interval, interval, action); } [Obsolete("Use CreateGameTimer(float delay, float interval, Action action) with delay 0.0f")] public Timer CreateGameTimer(float interval, bool fireNow, Action action) { return this.CreateGameTimer(0f, interval, action); } public Timer CreateGameTimer(float delay, float interval, Action action) { TimerManager.GameTimer gameTimer = new TimerManager.GameTimer(Time.time + delay, interval, action); this._gameTimers.Add(gameTimer); this._gameTimersDirty = true; return gameTimer; } public Timer CreateOnceGameTimer(float delay, Action action) { TimerManager.GameTimer gameTimer = new TimerManager.GameTimer(Time.time + delay, action); this._gameTimers.Add(gameTimer); this._gameTimersDirty = true; return gameTimer; } public Timer CreateClockTimer(DateTimeKind kind, TimeSpan interval, Action action) { return this.CreateClockTimer(kind, TimeSpan.Zero, interval, action); } public Timer CreateClockTimer(DateTimeKind kind, TimeSpan offset, TimeSpan interval, Action action) { if (kind == DateTimeKind.Unspecified) { kind = DateTimeKind.Local; } DateTime value; if (kind != DateTimeKind.Utc) { if (kind != DateTimeKind.Local) { return null; } value = DateTime.Now; } else { value = DateTime.UtcNow; } DateTime fireTime = value.Date.Add(offset); while (fireTime.CompareTo(value) < 0) { fireTime = fireTime.Add(interval); } return this.CreateClockTimer(fireTime, interval, action); } public Timer CreateClockTimer(DateTime fireTime, TimeSpan interval, Action action) { TimerManager.ClockTimer clockTimer = new TimerManager.ClockTimer(fireTime, interval, action); this.AddClockTimerToSchedule(clockTimer); return clockTimer; } public Timer CreateClockTimer(DateTime fireTime, Action action) { TimerManager.ClockTimer clockTimer = new TimerManager.ClockTimer(fireTime, action); this.AddClockTimerToSchedule(clockTimer); return clockTimer; } private void AddClockTimerToSchedule(TimerManager.ClockTimer timer) { DateTime fireTime = timer.FireTime; if (fireTime.Kind == DateTimeKind.Unspecified) { fireTime = new DateTime(fireTime.Ticks, DateTimeKind.Local); } DateTimeKind kind = fireTime.Kind; if (kind != DateTimeKind.Utc) { if (kind == DateTimeKind.Local) { this._localClockTimers.Add(timer); this._localClockTimersDirty = true; } } else { this._utcClockTimers.Add(timer); this._utcClockTimersDirty = true; } } private void FireGameTimers(ref bool dirty, List timers) { if (timers == null) { return; } if (dirty) { timers.Sort(); dirty = false; } int num = 0; while (num < timers.Count && timers[num].FireTime <= Time.time) { TimerManager.GameTimer gameTimer = timers[num]; if (gameTimer.Action != null) { gameTimer.Action(); } if (gameTimer.Repeating) { gameTimer.FireTime += gameTimer.Interval; if (gameTimer.FireTime < Time.time) { gameTimer.FireTime = Time.time; } } else { gameTimer.Cancel(); } num++; } } private void FireClockTimers(ref bool dirty, List timers, DateTime now) { if (timers == null) { return; } if (dirty) { timers.Sort(); dirty = false; } int num = 0; while (num < timers.Count && timers[num].FireTime.CompareTo(now) <= 0) { TimerManager.ClockTimer clockTimer = timers[num]; if (clockTimer.Action != null) { clockTimer.Action(); } if (clockTimer.Repeating) { do { clockTimer.FireTime = clockTimer.FireTime.Add(clockTimer.Interval); } while (clockTimer.FireTime.CompareTo(now) <= 0); } else { clockTimer.Cancel(); } num++; } } private void CancelTimers(List timers) where T : Timer { if (timers == null) { return; } List list = new List(timers.Count); foreach (T t in timers) { list.Add(t); } foreach (Timer timer in list) { timer.Cancel(); } timers.Clear(); } private List _gameTimers = new List(); private bool _gameTimersDirty; private List _utcClockTimers = new List(); private List _localClockTimers = new List(); private bool _utcClockTimersDirty; private bool _localClockTimersDirty; private class GameTimer : Timer, IComparable { public GameTimer(float fireTime, float interval, Action action) : base(action) { this._fireTime = fireTime; this._interval = interval; this._repeating = true; } public GameTimer(float fireTime, Action action) : base(action) { this._fireTime = fireTime; this._repeating = false; } public float FireTime { get { return this._fireTime; } set { this._fireTime = value; SingletonMonobehaviour.Instance._gameTimersDirty = true; } } public float Interval { get { return this._interval; } set { this._interval = value; } } public bool Repeating { get { return this._repeating; } } public int CompareTo(TimerManager.GameTimer other) { if (this._fireTime < other._fireTime) { return -1; } if (this._fireTime > other._fireTime) { return 1; } return 0; } public override void Cancel() { if (!this._cancelled && SingletonMonobehaviour.IsAvailable && SingletonMonobehaviour.Instance._gameTimers != null) { SingletonMonobehaviour.Instance._gameTimers.Remove(this); } base.Cancel(); } private float _fireTime; private float _interval; private bool _repeating; } private class ClockTimer : Timer, IComparable { public ClockTimer(DateTime fireTime, TimeSpan interval, Action action) : base(action) { this._fireTime = fireTime; this._interval = interval; this._repeating = true; } public ClockTimer(DateTime fireTime, Action action) : base(action) { this._fireTime = fireTime; this._repeating = false; } public DateTime FireTime { get { return this._fireTime; } set { this._fireTime = value; DateTimeKind kind = this._fireTime.Kind; if (kind != DateTimeKind.Utc) { if (kind == DateTimeKind.Local) { SingletonMonobehaviour.Instance._localClockTimersDirty = true; } } else { SingletonMonobehaviour.Instance._utcClockTimersDirty = true; } } } public TimeSpan Interval { get { return this._interval; } set { this._interval = value; } } public bool Repeating { get { return this._repeating; } } public int CompareTo(TimerManager.ClockTimer other) { return this._fireTime.CompareTo(other._fireTime); } public override void Cancel() { if (!this._cancelled && SingletonMonobehaviour.IsAvailable && SingletonMonobehaviour.Instance._localClockTimers != null && SingletonMonobehaviour.Instance._utcClockTimers != null) { DateTimeKind kind = this._fireTime.Kind; if (kind != DateTimeKind.Utc) { if (kind == DateTimeKind.Local) { SingletonMonobehaviour.Instance._localClockTimers.Remove(this); } } else { SingletonMonobehaviour.Instance._utcClockTimers.Remove(this); } } base.Cancel(); } private DateTime _fireTime; private TimeSpan _interval; private bool _repeating; } } }