AreaModule.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. using DeepCore.IO;
  2. using DeepCrystal.ORM;
  3. using DeepCrystal.RPC;
  4. using DeepMMO.Data;
  5. using DeepMMO.Protocol;
  6. using DeepMMO.Protocol.Client;
  7. using DeepMMO.Server.Area;
  8. using DeepMMO.Server.AreaManager;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Threading.Tasks;
  12. using DeepCore;
  13. namespace DeepMMO.Server.Logic.Model
  14. {
  15. public class AreaModule : ILogicModule
  16. {
  17. public IRemoteService areaManager { get; private set; }
  18. public IRemoteService currentArea { get; protected set; }
  19. public string currentAreaName { get { return currentArea != null ? currentArea.Address.ServiceName : null; } }
  20. protected List<ZoneInfoSnap> mLastZoneInfoSnaps;
  21. protected bool mZoneInfoDirtyFlag = true;
  22. protected DateTime LastGetZoneInfoTimeStamp;
  23. public AreaModule(LogicService service) : base(service)
  24. {
  25. }
  26. protected override void Disposing()
  27. {
  28. }
  29. public override async Task OnStartAsync()
  30. {
  31. //this.areaManager = await service.Provider.GetAsync(ServerNames.AreaManager);
  32. this.areaManager = await ServerNames.GetOrCreateAreaManagerServiceAsync(this.service, this.service.serverGroupID);
  33. if (areaManager == null)
  34. {
  35. throw new Exception("Cant Find AreaManager Service");
  36. }
  37. }
  38. public override Task OnStartedAsync()
  39. {
  40. return BeginEnterZoneAsync();
  41. }
  42. public override Task OnStopAsync()
  43. {
  44. OnEnterZone = null;
  45. return this.RequestLeaveZoneAsync();
  46. }
  47. protected virtual Task BeginEnterZoneAsync()
  48. {
  49. // 寻找一个场景 //
  50. var rd = service.roleModule.GetRoleData();
  51. return this.RequestEnterZoneAsync(new RoleEnterZoneRequest()
  52. {
  53. serverID = service.serverID,
  54. servergroupID = service.serverGroupID,
  55. expectMapTemplateID = rd.last_map_template_id,
  56. expectZoneUUID = rd.last_zone_uuid,
  57. roleScenePos = rd.last_zone_pos,
  58. teamID = GetTeamID(),
  59. });
  60. }
  61. public virtual ISerializable ToRoleBattleData(RoleEnterZoneRequest req)
  62. {
  63. return null;
  64. }
  65. /// <summary>
  66. /// 请求进入场景
  67. /// </summary>
  68. public virtual async Task<RoleEnterZoneResponse> RequestEnterZoneAsync(RoleEnterZoneRequest req)
  69. {
  70. var rd = service.roleModule.GetRoleData();
  71. req.roleUUID = service.roleID;
  72. req.roleSessionName = service.sessionName;
  73. req.roleSessionNode = service.sessionNode;
  74. req.roleLogicName = service.SelfAddress.ServiceName;
  75. req.roleLogicNode = service.SelfAddress.ServiceNode;
  76. req.roleDisplayName = rd.name;
  77. req.roleUnitTemplateID = rd.unit_template_id;
  78. req.roleData = ToRoleBattleData(req);//< ---战斗相关数据
  79. req.LastZoneSaveData = rd.last_zone_saved;
  80. req.lastPublicMapID = rd.last_public_mapID;
  81. req.lastPublicMapUUID = rd.last_public_area_uuid;
  82. req.lastPublicPos = rd.last_public_map_pos;
  83. req.expectAreaNode = service.SelfAddress.ServiceNode;
  84. var result = await this.areaManager.CallAsync<RoleEnterZoneResponse>(req);
  85. if (RoleEnterZoneResponse.CheckSuccess(result))
  86. {
  87. currentArea = await service.Provider.GetAsync(new RemoteAddress(result.areaName, result.areaNode));
  88. this.service.roleModule.SaveEnterZoneInfo(result);
  89. CurZoneChange(req, result);
  90. }
  91. else
  92. {
  93. service.log.Error("Enter Zone Error : " + result);
  94. }
  95. return result;
  96. }
  97. public virtual async Task<RoleLeaveZoneResponse> RequestLeaveZoneAsync()
  98. {
  99. var rd = service.roleModule.GetRoleData();
  100. var request = new RoleLeaveZoneRequest()
  101. {
  102. zoneUUID = rd.last_zone_uuid,
  103. roleID = service.roleID,
  104. keepObject = false,
  105. };
  106. var result = await this.areaManager.CallAsync<RoleLeaveZoneResponse>(request);
  107. if (result != null && RoleLeaveZoneResponse.CheckSuccess(result))
  108. {
  109. this.service.roleModule.SaveLeaveZoneInfo(result);
  110. OnLeaveZone?.Invoke(request, result);
  111. }
  112. return result;
  113. }
  114. public virtual async Task<Response> RequestTransportAsync(RoleNeedTransportNotify tp)
  115. {
  116. var leave_result = await RequestLeaveZoneAsync();
  117. if (leave_result == null || Response.CheckSuccess(leave_result) == false)
  118. {
  119. return leave_result;
  120. }
  121. var enter_result = await this.RequestEnterZoneAsync(new RoleEnterZoneRequest()
  122. {
  123. servergroupID = service.serverGroupID,
  124. serverID = service.serverID,
  125. expectMapTemplateID = tp.nextMapID,
  126. roleScenePos = new ZonePosition() { flagName = tp.nextZoneFlagName },
  127. teamID = GetTeamID(),
  128. });
  129. return enter_result;
  130. }
  131. public virtual async Task<Response> RequestCrossMapAsync(RoleCrossMapNotify notify)
  132. {
  133. var leave_result = await RequestLeaveZoneAsync();
  134. if (leave_result == null || Response.CheckSuccess(leave_result) == false)
  135. {
  136. return leave_result;
  137. }
  138. var enter_result = await this.RequestEnterZoneAsync(new RoleEnterZoneRequest()
  139. {
  140. servergroupID = service.serverGroupID,
  141. serverID = service.serverID,
  142. expectMapTemplateID = notify.NextSceneID,
  143. roleScenePos = new ZonePosition()
  144. {
  145. x = notify.NextScenePos.x,
  146. y = notify.NextScenePos.y,
  147. z = notify.NextScenePos.z
  148. },
  149. teamID = GetTeamID(),
  150. });
  151. return enter_result;
  152. }
  153. public async Task<List<ZoneInfoSnap>> RequestGetZonesSnapInfoAsync(int mapID)
  154. {
  155. var req = new GetZonesInfoRequest();
  156. req.servergroupID = this.service.serverGroupID;
  157. req.mapID = mapID;
  158. //向AreaManager请求.
  159. var rsp = await areaManager.CallAsync<GetZonesInfoResponse>(req);
  160. return rsp.snaps;
  161. }
  162. protected virtual void CurZoneChange(RoleEnterZoneRequest req, RoleEnterZoneResponse result)
  163. {
  164. //变更过场景,场景线缓存失效.
  165. mZoneInfoDirtyFlag = true;
  166. OnEnterZone?.Invoke(req, result);
  167. }
  168. /// <summary>
  169. /// 验证出场景条件.
  170. /// </summary>
  171. /// <param name="mapID"></param>
  172. /// <returns></returns>
  173. public virtual bool ValidateLeaveZoneCondition(int mapID, out string reason)
  174. {
  175. reason = null;
  176. return true;
  177. }
  178. /// <summary>
  179. /// 验证进场景条件.
  180. /// </summary>
  181. /// <param name="mapID"></param>
  182. /// <returns></returns>
  183. public virtual bool ValidateEnterZoneCondition(int mapID, out string reason)
  184. {
  185. reason = null;
  186. return true;
  187. }
  188. public virtual bool ValidateChangeZoneCondition(int mapID, out string reason)
  189. {
  190. int curMapID = service.roleModule.LastMapID;
  191. if (ValidateLeaveZoneCondition(curMapID, out reason) == false)
  192. {
  193. return false;
  194. }
  195. return ValidateEnterZoneCondition(mapID, out reason);
  196. }
  197. public async virtual Task<ClientGetZoneInfoSnapResponse> DoClientGetZoneInfoSnapRequest(ClientGetZoneInfoSnapRequest req)
  198. {
  199. ClientGetZoneInfoSnapResponse rsp = new ClientGetZoneInfoSnapResponse();
  200. var roleData = service.roleModule.GetRoleData();
  201. rsp.s2c_curZoneUUID = roleData.last_zone_uuid;
  202. //同场景同线内使用缓存的线数据.
  203. if (mZoneInfoDirtyFlag == true || (DateTime.UtcNow - LastGetZoneInfoTimeStamp).TotalMilliseconds > 0)
  204. {
  205. var ret = await RequestGetZonesSnapInfoAsync(roleData.last_map_template_id);
  206. rsp.s2c_snaps = ret;
  207. mLastZoneInfoSnaps = ret;
  208. mZoneInfoDirtyFlag = false;
  209. LastGetZoneInfoTimeStamp = DateTime.UtcNow.AddMinutes(2);
  210. }
  211. else
  212. {
  213. rsp.s2c_snaps = mLastZoneInfoSnaps;
  214. }
  215. return rsp;
  216. }
  217. public virtual async Task<ClientChangeZoneLineResponse> DoClientChangeZoneLineRequest(ClientChangeZoneLineRequest req)
  218. {
  219. var rsp = new ClientChangeZoneLineResponse();
  220. var mapData = RPGServerTemplateManager.Instance.GetMapTemplate(service.roleModule.LastMapID);
  221. if (!RPGServerTemplateManager.Instance.AllowChangeLine(mapData) ||
  222. mLastZoneInfoSnaps == null ||
  223. service.roleModule.LastZoneUUID == req.c2s_zoneuuid)
  224. {
  225. rsp.s2c_code = ClientChangeZoneLineResponse.CODE_ERROR;
  226. return rsp;
  227. }
  228. ZoneInfoSnap snap = null;
  229. for (int i = 0; i < mLastZoneInfoSnaps.Count; i++)
  230. {
  231. snap = mLastZoneInfoSnaps[i];
  232. if (req.c2s_zoneuuid == snap.uuid)
  233. {
  234. if (snap.curPlayerCount >= snap.playerMaxCount)
  235. {
  236. rsp.s2c_code = ClientChangeZoneLineResponse.CODE_LINE_BUSY;
  237. return rsp;
  238. }
  239. else
  240. {
  241. await DoChangeZoneLineAsync(req.c2s_zoneuuid, service.roleModule.LastMapID);
  242. return rsp;
  243. }
  244. }
  245. }
  246. rsp.s2c_code = ClientChangeZoneLineResponse.CODE_NOT_EXIST;
  247. return rsp;
  248. }
  249. /// <summary>
  250. /// 请求进入指定场景.
  251. /// </summary>
  252. /// <param name="sceneUUID"></param>
  253. public virtual async Task DoEnterTargetSceneAsync(string sceneUUID, int mapID)
  254. {
  255. // var serverRoleData = service.roleModule.GetRoleData();
  256. await RequestLeaveZoneAsync();
  257. // 寻找一个场景 //
  258. await this.RequestEnterZoneAsync(new RoleEnterZoneRequest()
  259. {
  260. serverID = service.serverID,
  261. servergroupID = service.serverGroupID,
  262. expectZoneUUID = sceneUUID,
  263. expectMapTemplateID = mapID,
  264. teamID = GetTeamID(),
  265. });
  266. }
  267. public async Task DoChangeZoneLineAsync(string sceneUUID, int mapID)
  268. {
  269. // var serverRoleData = service.roleModule.GetRoleData();
  270. var rsp = await RequestLeaveZoneAsync();
  271. // 寻找一个场景 //
  272. await this.RequestEnterZoneAsync(new RoleEnterZoneRequest()
  273. {
  274. serverID = service.serverID,
  275. servergroupID = service.serverGroupID,
  276. expectZoneUUID = sceneUUID,
  277. expectMapTemplateID = mapID,
  278. roleScenePos = rsp.lastScenePos,
  279. teamID = GetTeamID(),
  280. });
  281. }
  282. public virtual void DoAreaGameOverNotify(AreaGameOverNotify notify)
  283. {
  284. }
  285. protected virtual string GetTeamID()
  286. {
  287. return null;
  288. }
  289. public delegate void PlayerEnterZoneHandler(RoleEnterZoneRequest req, RoleEnterZoneResponse result);
  290. public delegate void PlayerLeaveZoneHandler(RoleLeaveZoneRequest req, RoleLeaveZoneResponse result);
  291. public event PlayerEnterZoneHandler OnEnterZone;
  292. public event PlayerLeaveZoneHandler OnLeaveZone;
  293. }
  294. }