ActorLocationSenderSystem.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System;
  2. using ETModel;
  3. namespace ETHotfix
  4. {
  5. [ObjectSystem]
  6. public class ActorLocationSenderAwakeSystem : AwakeSystem<ActorLocationSender, long>
  7. {
  8. public override void Awake(ActorLocationSender self, long id)
  9. {
  10. self.LastSendTime = TimeHelper.Now();
  11. self.Id = id;
  12. self.Tcs = null;
  13. self.FailTimes = 0;
  14. self.ActorId = 0;
  15. }
  16. }
  17. [ObjectSystem]
  18. public class ActorLocationSenderStartSystem : StartSystem<ActorLocationSender>
  19. {
  20. public override void Start(ActorLocationSender self)
  21. {
  22. StartAsync(self).NoAwait();
  23. }
  24. public async ETVoid StartAsync(ActorLocationSender self)
  25. {
  26. self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
  27. self.Address = StartConfigComponent.Instance
  28. .Get(IdGenerater.GetAppIdFromId(self.ActorId))
  29. .GetComponent<InnerConfig>().IPEndPoint;
  30. self.UpdateAsync().NoAwait();
  31. }
  32. }
  33. [ObjectSystem]
  34. public class ActorLocationSenderDestroySystem : DestroySystem<ActorLocationSender>
  35. {
  36. public override void Destroy(ActorLocationSender self)
  37. {
  38. self.RunError(ErrorCode.ERR_ActorRemove);
  39. self.Id = 0;
  40. self.LastSendTime = 0;
  41. self.Address = null;
  42. self.ActorId = 0;
  43. self.FailTimes = 0;
  44. self.Tcs = null;
  45. }
  46. }
  47. public static class ActorLocationSenderHelper
  48. {
  49. private static void Add(this ActorLocationSender self, ActorTask task)
  50. {
  51. if (self.IsDisposed)
  52. {
  53. throw new Exception("ActorLocationSender Disposed! dont hold ActorMessageSender");
  54. }
  55. self.WaitingTasks.Enqueue(task);
  56. // failtimes > 0表示正在重试,这时候不能加到正在发送队列
  57. if (self.FailTimes == 0)
  58. {
  59. self.AllowGet();
  60. }
  61. }
  62. public static void RunError(this ActorLocationSender self, int errorCode)
  63. {
  64. while (self.WaitingTasks.Count > 0)
  65. {
  66. ActorTask actorTask = self.WaitingTasks.Dequeue();
  67. actorTask.Tcs?.SetException(new RpcException(errorCode, ""));
  68. }
  69. self.WaitingTasks.Clear();
  70. }
  71. private static void AllowGet(this ActorLocationSender self)
  72. {
  73. if (self.Tcs == null || self.WaitingTasks.Count <= 0)
  74. {
  75. return;
  76. }
  77. ActorTask task = self.WaitingTasks.Peek();
  78. var t = self.Tcs;
  79. self.Tcs = null;
  80. t.SetResult(task);
  81. }
  82. private static ETTask<ActorTask> GetAsync(this ActorLocationSender self)
  83. {
  84. if (self.WaitingTasks.Count > 0)
  85. {
  86. ActorTask task = self.WaitingTasks.Peek();
  87. return ETTask.FromResult(task);
  88. }
  89. self.Tcs = new ETTaskCompletionSource<ActorTask>();
  90. return self.Tcs.Task;
  91. }
  92. public static async ETVoid UpdateAsync(this ActorLocationSender self)
  93. {
  94. try
  95. {
  96. long instanceId = self.InstanceId;
  97. while (true)
  98. {
  99. if (self.InstanceId != instanceId)
  100. {
  101. return;
  102. }
  103. ActorTask actorTask = await self.GetAsync();
  104. if (self.InstanceId != instanceId)
  105. {
  106. return;
  107. }
  108. if (actorTask.ActorRequest == null)
  109. {
  110. return;
  111. }
  112. await self.RunTask(actorTask);
  113. }
  114. }
  115. catch (Exception e)
  116. {
  117. Log.Error(e);
  118. }
  119. }
  120. private static async ETTask RunTask(this ActorLocationSender self, ActorTask task)
  121. {
  122. ActorMessageSender actorMessageSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(self.ActorId);
  123. IActorResponse response = await actorMessageSender.Call(task.ActorRequest);
  124. // 发送成功
  125. switch (response.Error)
  126. {
  127. case ErrorCode.ERR_NotFoundActor:
  128. // 如果没找到Actor,重试
  129. ++self.FailTimes;
  130. // 失败MaxFailTimes次则清空actor发送队列,返回失败
  131. if (self.FailTimes > ActorLocationSender.MaxFailTimes)
  132. {
  133. // 失败直接删除actorproxy
  134. Log.Info($"actor send message fail, actorid: {self.Id}");
  135. self.RunError(response.Error);
  136. self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
  137. return;
  138. }
  139. // 等待0.5s再发送
  140. await Game.Scene.GetComponent<TimerComponent>().WaitAsync(500);
  141. self.ActorId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
  142. self.Address = StartConfigComponent.Instance
  143. .Get(IdGenerater.GetAppIdFromId(self.ActorId))
  144. .GetComponent<InnerConfig>().IPEndPoint;
  145. self.AllowGet();
  146. return;
  147. case ErrorCode.ERR_ActorNoMailBoxComponent:
  148. self.RunError(response.Error);
  149. self.GetParent<ActorLocationSenderComponent>().Remove(self.Id);
  150. return;
  151. default:
  152. self.LastSendTime = TimeHelper.Now();
  153. self.FailTimes = 0;
  154. self.WaitingTasks.Dequeue();
  155. if (task.Tcs == null)
  156. {
  157. return;
  158. }
  159. IActorLocationResponse actorLocationResponse = response as IActorLocationResponse;
  160. if (actorLocationResponse == null)
  161. {
  162. task.Tcs.SetException(new Exception($"actor location respose is not IActorLocationResponse, but is: {response.GetType().Name}"));
  163. }
  164. task.Tcs.SetResult(actorLocationResponse);
  165. return;
  166. }
  167. }
  168. public static void Send(this ActorLocationSender self, IActorLocationMessage request)
  169. {
  170. if (request == null)
  171. {
  172. throw new Exception($"actor location send message is null");
  173. }
  174. ActorTask task = new ActorTask(request);
  175. self.Add(task);
  176. }
  177. public static ETTask<IActorLocationResponse> Call(this ActorLocationSender self, IActorLocationRequest request)
  178. {
  179. if (request == null)
  180. {
  181. throw new Exception($"actor location call message is null");
  182. }
  183. ETTaskCompletionSource<IActorLocationResponse> tcs = new ETTaskCompletionSource<IActorLocationResponse>();
  184. ActorTask task = new ActorTask(request, tcs);
  185. self.Add(task);
  186. return task.Tcs.Task;
  187. }
  188. }
  189. }