AreaZonePlayer.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //#define SHOW_SEND_MESSAGE
  2. using DeepCore;
  3. using DeepCore.Concurrent;
  4. using DeepCore.GameData.Zone;
  5. using DeepCore.IO;
  6. using DeepCore.Log;
  7. using DeepCore.Protocol;
  8. using DeepCrystal.RPC;
  9. using DeepMMO.Protocol.Client;
  10. using DeepMMO.Server.AreaManager;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.IO;
  14. using System.Threading.Tasks;
  15. using DeepCore.Game3D.Host.Instance;
  16. using DeepCore.Game3D.Host.ZoneServer;
  17. using DeepCore.Game3D.Host.ZoneServer.Interface;
  18. using DeepCore.GameData;
  19. namespace DeepMMO.Server.Area
  20. {
  21. public class AreaZonePlayer : Disposable, IZoneNodePlayer
  22. {
  23. private readonly static TypeAllocRecorder Alloc = new TypeAllocRecorder(typeof(AreaZonePlayer));
  24. protected readonly Logger log;
  25. protected readonly AreaService service;
  26. protected readonly AreaZoneNode node;
  27. protected readonly int client_event_route;
  28. protected IRemoteService remote_session;
  29. protected IRemoteService remote_logic;
  30. public readonly RoleEnterZoneRequest enter;
  31. private HashMap<string, object> mAttributes = new HashMap<string, object>();
  32. private bool pause_client = false;
  33. private bool pause_logic = false;
  34. public AreaZoneNode ZoneNode { get { return node; } }
  35. public string RoleUUID { get { return enter.roleUUID; } }
  36. public string RoleSessionName { get { return enter.roleSessionName; } }
  37. public string ZoneUUID { get { return node.ZoneUUID; } }
  38. protected InstancePlayer Actor { get { return mBinding.Value.Actor; } }
  39. public AreaZonePlayer(AreaService svc, AreaZoneNode node, RoleEnterZoneRequest enter)
  40. {
  41. Alloc.RecordConstructor(this.GetType());
  42. this.log = LoggerFactory.GetLogger(GetType().Name);
  43. this.service = svc;
  44. this.node = node;
  45. this.enter = enter;
  46. this.client_event_route = TypeCodec.GetAttributeRoute(typeof(ClientBattleEvent));
  47. }
  48. #if DEBUG
  49. ~AreaZonePlayer()
  50. {
  51. Alloc.RecordDestructor(this.GetType());
  52. }
  53. #endif
  54. protected override void Disposing()
  55. {
  56. Alloc.RecordDispose(this.GetType());
  57. }
  58. internal async Task<bool> OnEnterAsync()
  59. {
  60. this.remote_session = await service.Provider.GetAsync(new RemoteAddress(enter.roleSessionName, enter.roleSessionNode));
  61. this.remote_logic = await service.Provider.GetAsync(new RemoteAddress(enter.roleLogicName, enter.roleLogicNode));
  62. return remote_session != null && remote_logic != null;
  63. }
  64. public virtual void SessionDisconnect()
  65. {
  66. this.remote_session.WormholeTransport(new ClientLeaveZoneNotify()
  67. {
  68. s2c_ZoneUUID = node.ZoneUUID,
  69. });
  70. this.remote_session.Invoke(new SessionUnbindAreaNotify()
  71. {
  72. areaName = service.SelfAddress.ServiceName,
  73. areaNode = service.SelfAddress.ServiceNode
  74. });
  75. this.pause_client = true;
  76. }
  77. public virtual void SessionBeginLeave()
  78. {
  79. this.pause_logic = true;
  80. }
  81. public virtual void SessionReconnect()
  82. {
  83. this.pause_client = false;
  84. this.pause_logic = false;
  85. this.remote_session?.WormholeTransport(new ClientEnterZoneNotify()
  86. {
  87. s2c_ZoneUUID = node.ZoneUUID,
  88. s2c_MapTemplateID = node.MapTemplateID,
  89. s2c_ZoneTemplateID = node.ZoneTemplateID,
  90. s2c_RoleDisplayName = enter.roleDisplayName,
  91. s2c_RoleUnitTemplateID = enter.roleUnitTemplateID,
  92. s2c_SceneLineIndex = enter.expectLineIndex,
  93. s2c_GuildUUID = enter.guildUUID,
  94. s2c_ZoneUpdateIntervalMS = ZoneNode.ZoneNode.ClientUpdateIntervalMS,
  95. s2c_Ext = enter.ext,
  96. });
  97. this.remote_session?.Invoke(new SessionBindAreaNotify()
  98. {
  99. areaName = service.SelfAddress.ServiceName,
  100. areaNode = service.SelfAddress.ServiceNode
  101. });
  102. }
  103. public virtual void DoGameOver(DeepCore.GameData.Zone.GameOverEvent evt)
  104. {
  105. this.remote_logic?.Invoke(new AreaGameOverNotify()
  106. {
  107. zoneUUID = node.ZoneUUID,
  108. mapTemplateID = node.MapTemplateID,
  109. zoneTemplateID = node.ZoneTemplateID,
  110. winForce = evt.WinForce,
  111. message = evt.message,
  112. });
  113. }
  114. public virtual void SendToSession(ISerializable msg)
  115. {
  116. this.remote_session?.Invoke(msg);
  117. }
  118. //---------------------------------------------------------------------------------------------
  119. #region ZoneEvents
  120. protected virtual void Actor_OnTransportScene(InstancePlayer player, InstanceFlag flag, int nextSceneID, string nextScenePosition)
  121. {
  122. this.remote_logic?.Invoke(new RoleNeedTransportNotify()
  123. {
  124. fromAreaName = service.SelfAddress.ServiceName,
  125. fromAreaNode = service.SelfAddress.ServiceNode,
  126. nextZoneID = nextSceneID,
  127. nextMapID = nextSceneID,
  128. nextZoneFlagName = nextScenePosition,
  129. });
  130. }
  131. protected virtual void Actor_OnCrossScene(InstancePlayer player,int nextSceneID)
  132. {
  133. }
  134. #endregion
  135. //---------------------------------------------------------------------------------------------
  136. #region Attributes
  137. public bool IsAttribute(string key)
  138. {
  139. return mAttributes.ContainsKey(key);
  140. }
  141. public void SetAttribute(string key, object value)
  142. {
  143. mAttributes.Put(key, value);
  144. }
  145. public object RemoveAttribute(string key)
  146. {
  147. return mAttributes.RemoveByKey(key);
  148. }
  149. public object GetAttribute(string key)
  150. {
  151. return mAttributes.Get(key);
  152. }
  153. public T GetAttributeAs<T>(string key)
  154. {
  155. object obj = mAttributes.Get(key);
  156. if (obj != null)
  157. {
  158. return (T)obj;
  159. }
  160. return default(T);
  161. }
  162. #endregion
  163. //---------------------------------------------------------------------------------------------
  164. #region RPC
  165. /// <summary>
  166. /// ClientBattleAction
  167. /// </summary>
  168. /// <param name="msg"></param>
  169. public virtual void client_rpc_Handle(Stream clientBattleAction)
  170. {
  171. try
  172. {
  173. object action;
  174. // Drop 4 for head message id //
  175. clientBattleAction.Position += 4;
  176. if (service.BattleClientCodec.doDecode(clientBattleAction, out action))
  177. {
  178. OnHandleClientMessage(action as IMessage);
  179. }
  180. }
  181. catch (Exception err)
  182. {
  183. log.Error(err.Message, err);
  184. }
  185. }
  186. public virtual void client_rpc_Handle(ArraySegment<byte> clientBattleAction)
  187. {
  188. try
  189. {
  190. object action;
  191. // Drop 4 for head message id //
  192. //clientBattleAction.Position += 4;
  193. if (service.BattleClientCodec.doDecode(new ArraySegment<byte>(clientBattleAction.Array, clientBattleAction.Offset + 4, clientBattleAction.Count - 4), out action))
  194. {
  195. OnHandleClientMessage(action as IMessage);
  196. }
  197. }
  198. catch (Exception err)
  199. {
  200. log.Error(err.Message, err);
  201. }
  202. }
  203. public virtual void client_rpc_Handle(byte[] clientBattleAction)
  204. {
  205. try
  206. {
  207. // Drop Head 4 bytes //
  208. if (service.BattleClientCodec.doDecode(new ArraySegment<byte>(clientBattleAction, 4, clientBattleAction.Length - 4), out var action))
  209. {
  210. OnHandleClientMessage(action as IMessage);
  211. }
  212. }
  213. catch (Exception err)
  214. {
  215. log.Error(err.Message, err);
  216. }
  217. }
  218. public virtual void client_rpc_Handle(ClientBattleAction msg)
  219. {
  220. try
  221. {
  222. if (service.BattleClientCodec.doDecode(new ArraySegment<byte>(msg.c2s_battleAction), out var action))
  223. {
  224. OnHandleClientMessage(action as IMessage);
  225. }
  226. }
  227. catch (Exception err)
  228. {
  229. log.Error(err.Message, err);
  230. }
  231. }
  232. public virtual void logic_rpc_Handle(ISerializable msg)
  233. {
  234. if (mRpcHandleInvoke != null)
  235. mRpcHandleInvoke(msg);
  236. }
  237. public virtual void logic_rpc_Handle(ISerializable msg, OnRpcReturn<ISerializable> cb)
  238. {
  239. if (mRpcHandleCall != null)
  240. mRpcHandleCall(msg, (rsp, err) => { cb(rsp as ISerializable, err); });
  241. }
  242. public virtual void logic_rpc_Invoke(ISerializable msg)
  243. {
  244. if (pause_logic) return;
  245. lock (mLogicSendingQueue) { mLogicSendingQueue.Add(msg); }
  246. }
  247. public virtual void logic_rpc_Call(ISerializable msg, OnRpcReturn<ISerializable> cb)
  248. {
  249. this.remote_logic?.Call<ISerializable>(msg, cb);
  250. }
  251. #endregion
  252. //---------------------------------------------------------------------------------------------
  253. #region IPlayer
  254. //---------------------------------------------------------------------------------------------
  255. private void OnHandleClientMessage(IMessage action)
  256. {
  257. if (mHandleClientMessage != null)
  258. {
  259. mHandleClientMessage.Invoke(action);
  260. }
  261. else
  262. {
  263. node.ZoneNode.QueueSceneTask((z, err) =>
  264. {
  265. if (err != null)
  266. {
  267. log.Error(err.Message, err);
  268. }
  269. else if (mHandleClientMessage != null)
  270. {
  271. mHandleClientMessage.Invoke(action);
  272. }
  273. });
  274. }
  275. }
  276. private AtomicReference<ZoneNode.PlayerClient> mBinding = new AtomicReference<ZoneNode.PlayerClient>(null);
  277. private Action<IMessage> mHandleClientMessage;
  278. private Action<object, Action<object, Exception>> mRpcHandleCall;
  279. private Action<object> mRpcHandleInvoke;
  280. private PackEvent mSendingQueue = new PackEvent();
  281. private List<ISerializable> mLogicSendingQueue = new List<ISerializable>();
  282. string IZoneNodePlayer.PlayerUUID { get { return enter.roleUUID; } }
  283. string IZoneNodePlayer.DisplayName { get { return enter.roleDisplayName; } }
  284. ZoneNode.PlayerClient IZoneNodePlayer.BindingPlayer
  285. {
  286. get { return mBinding.Value; }
  287. set { mBinding.Value = value; }
  288. }
  289. void IZoneNodePlayer.ListenClient(Action<IMessage> handler)
  290. {
  291. mHandleClientMessage = handler;
  292. }
  293. void IZoneNodePlayer.ClientSend(PlayerMessageEntry msg)
  294. {
  295. if (pause_client) return;
  296. #if SHOW_SEND_MESSAGE
  297. if (msg.message.ToString() != "DeepCore.GameData.Zone.SyncPosEvent"
  298. && msg.message.ToString() != "DeepCore.GameData.Zone.Pong"
  299. )
  300. {
  301. Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss ") + ":ZoneNode S>>>>>>>>> client: " + msg.message.ToString());
  302. }
  303. //Console.WriteLine("批量协议刷新列表添加:"+msg.message.ToString());
  304. #endif
  305. if (msg.buffer != null)
  306. {
  307. mSendingQueue.events.Add(msg.buffer);
  308. }
  309. else
  310. {
  311. mSendingQueue.events.Add(msg.message);
  312. }
  313. }
  314. void IZoneNodePlayer.ClientFlush(BattleCodec codec)
  315. {
  316. try
  317. {
  318. if (pause_logic == false)
  319. {
  320. lock (mLogicSendingQueue)
  321. {
  322. if (mLogicSendingQueue.Count > 0)
  323. {
  324. remote_logic?.BatchInvoke(mLogicSendingQueue);
  325. mLogicSendingQueue.Clear();
  326. }
  327. }
  328. }
  329. if (pause_client == false)
  330. {
  331. if (mSendingQueue.events.Count > 0)
  332. {
  333. mSendingQueue.sequenceNo = node.ZoneNode.ZoneTick;
  334. using (var buffer = MemoryStreamObjectPool.AllocAutoRelease())
  335. {
  336. try
  337. {
  338. //#if SHOW_SEND_MESSAGE
  339. // Console.WriteLine("同步客户端事件(ClientBattleEvent):"+mSendingQueue.ToString());
  340. // if (mSendingQueue.events.Count>100)
  341. // {
  342. // Console.WriteLine("XXXXXXXXXXXXXXXXX大批量客户端事件(ClientBattleEvent):" + mSendingQueue.ToString());
  343. // }
  344. //#endif
  345. if (codec.doEncodeWithHead(mSendingQueue, buffer))
  346. {
  347. var notify = BinaryMessage.FromBuffer(client_event_route, buffer);
  348. //#if SHOW_SEND_MESSAGE
  349. // if (mSendingQueue.events.Count > 100)
  350. // {
  351. // Console.WriteLine("XXXXXXXXXXXXXXXXX 字节长度:" + notify.BufferLength );
  352. // }
  353. //#endif
  354. remote_session?.WormholeTransport(notify);
  355. }
  356. }
  357. catch (Exception err)
  358. {
  359. log.Error(err.Message, err);
  360. }
  361. finally
  362. {
  363. mSendingQueue.events.Clear();
  364. }
  365. }
  366. }
  367. }
  368. }
  369. catch (Exception err)
  370. {
  371. log.Error(err.Message, err);
  372. }
  373. }
  374. void IZoneNodePlayer.OnPlayerConnected(ZoneNode.PlayerClient binding)
  375. {
  376. pause_client = false;
  377. mBinding.Value = binding;
  378. binding.Actor.OnTransportScene += Actor_OnTransportScene;
  379. binding.Actor.OnCrossScene += Actor_OnCrossScene;
  380. }
  381. void IZoneNodePlayer.OnPlayerDisconnect(ZoneNode.PlayerClient binding)
  382. {
  383. mBinding.Value = null;
  384. }
  385. void IZoneNodePlayer.OnPlayerDisposed()
  386. {
  387. this.pause_client = true;
  388. this.pause_logic = true;
  389. }
  390. void IZoneNodePlayer.GameServerRpcInvoke(object msg)
  391. {
  392. this.logic_rpc_Invoke(msg as ISerializable);
  393. }
  394. void IZoneNodePlayer.GameServerRpcCall(object msg, Action<object, Exception> callback)
  395. {
  396. this.logic_rpc_Call(msg as ISerializable, (rsp, err) => { callback(rsp, err); });
  397. }
  398. void IZoneNodePlayer.ListenGameServerRpcInvoke(Action<object> handler)
  399. {
  400. mRpcHandleInvoke = handler;
  401. }
  402. void IZoneNodePlayer.ListenGameServerRpcCall(Action<object, Action<object, Exception>> handler)
  403. {
  404. mRpcHandleCall = handler;
  405. }
  406. #endregion
  407. //---------------------------------------------------------------------------------------------
  408. //---------------------------------------------------------------------------------------------
  409. }
  410. }