TimerComponent.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. using System;
  2. using System.Collections.Generic;
  3. using Fort23.Core;
  4. namespace Fort23.Core
  5. {
  6. public enum TimerType
  7. {
  8. None,
  9. Wait, // 等待
  10. Count, // 次数
  11. }
  12. public class TimerEntity : Entity
  13. {
  14. public TimerType timerType;
  15. /// <summary>
  16. /// 计时时间,毫秒
  17. /// </summary>
  18. public long time;
  19. /// <summary>
  20. /// 完成回调
  21. /// </summary>
  22. public object callback1;
  23. /// <summary>
  24. /// 次数
  25. /// </summary>
  26. public int count;
  27. /// <summary>
  28. /// 针对多次的,每次Hit回调
  29. /// </summary>
  30. public object callback2;
  31. [CustomMethod(CustomMethodType.Awake)]
  32. public void Awake(TimerType timerType, long time, object callback1, int count, object callback2)
  33. {
  34. this.timerType = timerType;
  35. this.time = time;
  36. this.callback1 = callback1;
  37. this.count = count;
  38. this.callback2 = callback2;
  39. }
  40. [CustomMethod(CustomMethodType.Destroy)]
  41. public void Destroy()
  42. {
  43. this.timerType = TimerType.None;
  44. this.time = 0;
  45. this.callback1 = null;
  46. this.count = 0;
  47. this.callback2 = null;
  48. }
  49. }
  50. public class TimerComponent : Entity
  51. {
  52. public static TimerComponent Instance { get; set; }
  53. /// <summary>
  54. /// key: time, value: timer id
  55. /// </summary>
  56. private readonly MultiMap<long, long> _timeID = new MultiMap<long, long>();
  57. private readonly Queue<long> _timeOutTime = new Queue<long>();
  58. private readonly Queue<long> _timeOutTimerIds = new Queue<long>();
  59. // 记录最小时间,不用每次都去MultiMap取第一个值
  60. private long _minTime;
  61. [CustomMethod(CustomMethodType.Awake)]
  62. public void Awake()
  63. {
  64. Instance = this;
  65. }
  66. [CustomMethod(CustomMethodType.Update)]
  67. public void Update()
  68. {
  69. if (this._timeID.Count == 0)
  70. {
  71. return;
  72. }
  73. long timeNow = TimeHelper.ServerNow();
  74. if (timeNow < this._minTime)
  75. {
  76. return;
  77. }
  78. foreach (KeyValuePair<long, List<long>> kv in this._timeID)
  79. {
  80. long k = kv.Key;
  81. if (k > timeNow)
  82. {
  83. _minTime = k;
  84. break;
  85. }
  86. this._timeOutTime.Enqueue(k);
  87. }
  88. // 2.找出失效时间对应的ID
  89. while (this._timeOutTime.Count > 0)
  90. {
  91. long time = this._timeOutTime.Dequeue();
  92. // 3.取出对应的TimerEntity执行逻辑
  93. for (int i = 0; i < this._timeID[time].Count; i++)
  94. {
  95. TimerEntity timerEntity = this.GetChild<TimerEntity>(_timeID[time][i]);
  96. if (timerEntity != null)
  97. {
  98. Run(timerEntity, time);
  99. }
  100. }
  101. // foreach (long timerId in this._timeID[time])
  102. // {
  103. // TimerEntity timerEntity = this.GetChild<TimerEntity>(timerId);
  104. // if (timerEntity != null)
  105. // {
  106. // Run(timerEntity, time);
  107. // }
  108. // }
  109. this._timeID.Remove(time);
  110. }
  111. // while (this._timeOutTime.Count > 0)
  112. // {
  113. // long time = this._timeOutTime.Dequeue();
  114. // foreach (long timerId in this._timeID[time])
  115. // {
  116. // this._timeOutTimerIds.Enqueue(timerId);
  117. // }
  118. //
  119. // this._timeID.Remove(time);
  120. // }
  121. //
  122. // while (this._timeOutTimerIds.Count > 0)
  123. // {
  124. // long timerId = this._timeOutTimerIds.Dequeue();
  125. // TimerEntity timerEntity = this.GetChild<TimerEntity>(timerId);
  126. // if (timerEntity == null)
  127. // {
  128. // continue;
  129. // }
  130. //
  131. // Run(timerEntity, timerId);
  132. // }
  133. }
  134. private void Run(TimerEntity timerEntity, long timestamp)
  135. {
  136. switch (timerEntity.timerType)
  137. {
  138. case TimerType.Wait:
  139. {
  140. CTask<bool> tcs = timerEntity.callback1 as CTask<bool>;
  141. this.Remove(timerEntity.ID);
  142. tcs.SetResult(true);
  143. break;
  144. }
  145. case TimerType.Count:
  146. {
  147. if (timerEntity.count <= 1)
  148. {
  149. Action action = timerEntity.callback1 as Action;
  150. this.Remove(timerEntity.ID);
  151. action?.Invoke();
  152. break;
  153. }
  154. else
  155. {
  156. long currTime = TimeHelper.ServerNow();
  157. long tillTime = currTime - currTime % timestamp + timerEntity.time;
  158. this.AddTimer(tillTime, timerEntity);
  159. Action action = timerEntity.callback2 as Action;
  160. action?.Invoke();
  161. timerEntity.count--;
  162. break;
  163. }
  164. }
  165. }
  166. }
  167. private void AddTimer(long untillTime, TimerEntity timerEntity)
  168. {
  169. this._timeID.Add(untillTime, timerEntity.ID);
  170. if (untillTime < this._minTime)
  171. {
  172. this._minTime = untillTime;
  173. }
  174. }
  175. /// <summary>
  176. /// 等待1帧(因为实在下一次Update里面刷新,所以WaitAsync传的值小于一帧的间隔就可以)
  177. /// </summary>
  178. /// <returns></returns>
  179. public async CTask<bool> WaitFrameAsync()
  180. {
  181. return await WaitAsync(1);
  182. }
  183. /// <summary>
  184. /// 等待time毫秒
  185. /// </summary>
  186. /// <param name="time">毫秒</param>
  187. /// <returns></returns>
  188. public async CTask<bool> WaitAsync(long time)
  189. {
  190. if (time == 0)
  191. {
  192. return true;
  193. }
  194. long tillTime = TimeHelper.ServerNow() + time;
  195. CTask<bool> tcs = CTask<bool>.Create(false);
  196. TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Wait, 0, tcs, 1, null, true);
  197. this.AddTimer(tillTime, timerEntity);
  198. return await tcs;
  199. }
  200. /// <summary>
  201. /// 等待到指定毫秒的时间戳
  202. /// </summary>
  203. /// <param name="untillTime">毫秒</param>
  204. /// <returns></returns>
  205. public async CTask<bool> WaitTillAsync(long untillTime)
  206. {
  207. if (TimeHelper.ServerNow() >= untillTime)
  208. {
  209. return true;
  210. }
  211. CTask<bool> tcs = CTask<bool>.Create();
  212. TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Wait, 0, tcs, 1, null, true);
  213. this.AddTimer(untillTime, timerEntity);
  214. return await tcs;
  215. }
  216. /// <summary>
  217. ///
  218. /// </summary>
  219. /// <param name="time">计时器Hit一次的时间(毫秒)</param>
  220. /// <param name="action1">全部count完成时候回调</param>
  221. /// <param name="count">次数</param>
  222. /// <param name="action2">针对多次执行的Timer,每一次Hit时候的回调</param>
  223. /// <returns>ID, 可以通过Remove来手动中止Timer</returns>
  224. public TimerEntity AddTimer(long time, Action action1, int count = 1, Action action2 = null)
  225. {
  226. TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Count, time, action1, count, action2, true);
  227. this.AddTimer(TimeHelper.ServerNow() + time, timerEntity);
  228. return timerEntity;
  229. }
  230. public void Remove(ref long id)
  231. {
  232. this.Remove(id);
  233. id = 0;
  234. }
  235. public bool Remove(TimerEntity timerEntity)
  236. {
  237. if (timerEntity == null)
  238. {
  239. return false;
  240. }
  241. timerEntity.Dispose();
  242. return true;
  243. }
  244. public bool Remove(long id)
  245. {
  246. if (id == 0)
  247. {
  248. return false;
  249. }
  250. TimerEntity timerEntity = this.GetChild<TimerEntity>(id);
  251. return Remove(timerEntity);
  252. }
  253. }
  254. }