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);
- }
- }
- }
|