| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 | using System;using System.Collections.Generic;namespace Fort23.Core{    public enum TimerType    {        None,        Wait, // 等待        Count, // 次数    }    public class TimerEntity : Entity    {        public TimerType timerType;        /// <summary>        /// 计时时间,毫秒        /// </summary>        public long time;               /// <summary>        /// 完成回调        /// </summary>        public object callback1;        /// <summary>        /// 次数        /// </summary>         public int count;        /// <summary>        /// 针对多次的,每次Hit回调        /// </summary>        public object callback2;        [CustomMethod(CustomMethodType.Awake)]        public void Awake(TimerType timerType, long time, object callback1, int count, object callback2)        {            this.timerType = timerType;            this.time = time;            this.callback1 = callback1;            this.count = count;            this.callback2 = callback2;        }        [CustomMethod(CustomMethodType.Destroy)]        public void Destroy()        {            this.timerType = TimerType.None;            this.time = 0;            this.callback1 = null;            this.count = 0;            this.callback2 = null;        }    }    public class TimerComponent : Entity    {        public static TimerComponent Instance { get; set; }        /// <summary>        /// key: time, value: timer id        /// </summary>        private readonly MultiMap<long, long> _timeID = new MultiMap<long, long>();        private readonly Queue<long> _timeOutTime = new Queue<long>();        private readonly Queue<long> _timeOutTimerIds = new Queue<long>();        // 记录最小时间,不用每次都去MultiMap取第一个值        private long _minTime;        [CustomMethod(CustomMethodType.Awake)]        public void Awake()        {            Instance = this;        }        [CustomMethod(CustomMethodType.Update)]        public void Update()        {                                   if (this._timeID.Count == 0)            {                return;            }            long timeNow = TimeHelper.ServerNow();            if (timeNow < this._minTime)            {                return;            }            foreach (KeyValuePair<long, List<long>> kv in this._timeID)            {                long k = kv.Key;                if (k > timeNow)                {                    _minTime = k;                    break;                }                this._timeOutTime.Enqueue(k);            }                        // 2.找出失效时间对应的ID            while (this._timeOutTime.Count > 0)            {                long time = this._timeOutTime.Dequeue();                // 3.取出对应的TimerEntity执行逻辑                for (int i = 0; i < this._timeID[time].Count; i++)                {                    TimerEntity timerEntity = this.GetChild<TimerEntity>(_timeID[time][i]);                    if (timerEntity != null)                    {                        Run(timerEntity, time);                    }                }                // foreach (long timerId in this._timeID[time])                // {                //     TimerEntity timerEntity = this.GetChild<TimerEntity>(timerId);                //     if (timerEntity != null)                //     {                //         Run(timerEntity, time);                //     }                // }                this._timeID.Remove(time);            }                }        private void Run(TimerEntity timerEntity, long timestamp)        {            switch (timerEntity.timerType)            {                case TimerType.Wait:                {                    CTask<bool> tcs = timerEntity.callback1 as CTask<bool>;                    this.Remove(timerEntity.ID);                    tcs.SetResult(true);                    break;                }                case TimerType.Count:                {                    if (timerEntity.count <= 1)                    {                        Action action = timerEntity.callback1 as Action;                        this.Remove(timerEntity.ID);                        action?.Invoke();                        break;                    }                    else                    {                        long currTime = TimeHelper.ServerNow();                        long tillTime = currTime - currTime % timestamp + timerEntity.time;                        this.AddTimer(tillTime, timerEntity);                        Action action = timerEntity.callback2 as Action;                        action?.Invoke();                        timerEntity.count--;                        break;                    }                }            }        }        private void AddTimer(long untillTime, TimerEntity timerEntity)        {            this._timeID.Add(untillTime, timerEntity.ID);            if (untillTime < this._minTime)            {                this._minTime = untillTime;            }        }        /// <summary>        /// 等待1帧(因为实在下一次Update里面刷新,所以WaitAsync传的值小于一帧的间隔就可以)        /// </summary>        /// <returns></returns>        public async CTask<bool> WaitFrameAsync()        {            return await WaitAsync(1);        }        /// <summary>        /// 等待time毫秒        /// </summary>        /// <param name="time">毫秒</param>        /// <returns></returns>        public async CTask<bool> WaitAsync(long time)        {            if (time == 0)            {                return true;            }            long tillTime = TimeHelper.ServerNow() + time;            CTask<bool> tcs = CTask<bool>.Create(false);            TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Wait, 0, tcs, 1, null, true);            this.AddTimer(tillTime, timerEntity);            return await tcs;        }        /// <summary>        /// 等待到指定毫秒的时间戳        /// </summary>        /// <param name="untillTime">毫秒</param>        /// <returns></returns>        public async CTask<bool> WaitTillAsync(long untillTime)        {            if (TimeHelper.ServerNow() >= untillTime)            {                return true;            }            CTask<bool> tcs = CTask<bool>.Create();            TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Wait, 0, tcs, 1, null, true);            this.AddTimer(untillTime, timerEntity);            return await tcs;        }        /// <summary>        ///         /// </summary>        /// <param name="time">计时器Hit一次的时间(毫秒)</param>        /// <param name="action1">全部count完成时候回调</param>        /// <param name="count">次数</param>        /// <param name="action2">针对多次执行的Timer,每一次Hit时候的回调</param>        /// <returns>ID, 可以通过Remove来手动中止Timer</returns>        public TimerEntity AddTimer(long time, Action action1, int count = 1, Action action2 = null)        {            TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Count, time, action1, count, action2, true);            this.AddTimer(TimeHelper.ServerNow() + time, timerEntity);            return timerEntity;        }        public void Remove(ref long id)        {            this.Remove(id);            id = 0;        }        public bool Remove(TimerEntity timerEntity)        {            if (timerEntity == null)            {                return false;            }            timerEntity.Dispose();            return true;        }        public bool Remove(long id)        {            if (id == 0)            {                return false;            }            TimerEntity timerEntity = this.GetChild<TimerEntity>(id);            return Remove(timerEntity);        }    }}
 |