Room.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. using CSharpUtil;
  2. using CSharpUtil.Net;
  3. using ProtoDataBuff;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Threading.Channels;
  8. using System.Threading.Tasks;
  9. using static System.Console;
  10. namespace BossServer.server
  11. {
  12. /// <summary>
  13. /// 房间状态
  14. /// </summary>
  15. enum RoomState
  16. {
  17. /// <summary>
  18. /// 开启状态(可以连接登入)
  19. /// </summary>
  20. Open,
  21. /// <summary>
  22. /// 已关闭(不可继续登录)
  23. /// </summary>
  24. Close,
  25. }
  26. enum TargetType
  27. {
  28. /// <summary>
  29. /// 所有
  30. /// </summary>
  31. All,
  32. /// <summary>
  33. /// 其他人
  34. /// </summary>
  35. Others,
  36. }
  37. class PropertyName
  38. {
  39. public const string Uid = nameof(Uid);
  40. public const string Name = nameof(Name);
  41. public const string Zoneid = nameof(Zoneid);
  42. public const string Hp = nameof(Hp);
  43. public const string MaxHp = nameof(MaxHp);
  44. public const string TotalDamage = nameof(TotalDamage);
  45. }
  46. /// <summary>
  47. /// 房间对象
  48. /// </summary>
  49. class Room : Singleton<Room>
  50. {
  51. /// <summary>
  52. /// 房间状态字段
  53. /// </summary>
  54. public RoomState CurrentState = RoomState.Close;
  55. /// <summary>
  56. /// 客户端
  57. /// </summary>
  58. public Dictionary<int, Peer> ClientPeers = new Dictionary<int, Peer>();
  59. /// <summary>
  60. /// 消息分发
  61. /// </summary>
  62. private Dictionary<eProtocalCommand, Action<int, sSocketData>> callbacks = new Dictionary<eProtocalCommand, Action<int, sSocketData>>();
  63. /// <summary>
  64. /// 客户端消息队列
  65. /// </summary>
  66. public Channel<KeyValuePair<int, sSocketData>> MsgChannel = Channel.CreateBounded<KeyValuePair<int, sSocketData>>(1000);
  67. public string Name => DateTime.Now.ToString("yyyyMMddHH");
  68. public int MaxHp => Config.GameOnline ? 100000 : 10000; // 初始血量10w
  69. /// <summary>
  70. /// boss集合
  71. /// </summary>
  72. private Dictionary<string, Boss> Boss_dict = new();
  73. /// <summary>
  74. /// 构造函数
  75. /// </summary>
  76. public Room()
  77. {
  78. //this.Name = DateTime.Now.ToString("yyyyMMddHH");
  79. this.callbacks.Add(eProtocalCommand.CsLogin, On_Login);
  80. this.callbacks.Add(eProtocalCommand.CsReportDamage, On_ReportDamage);
  81. this.callbacks.Add(eProtocalCommand.CsLeaveRoom, On_Leave);
  82. this.callbacks.Add(eProtocalCommand.CsReportUserHp, On_ReportUserHp);
  83. var t = Task.Run(MsgLoop);
  84. Open();
  85. }
  86. /// <summary>
  87. /// 处理客户端上报玩家剩余血量逻辑
  88. /// </summary>
  89. /// <param name="peerId"></param>
  90. /// <param name="data"></param>
  91. void On_ReportUserHp(int peerId, sSocketData data)
  92. {
  93. var msg = CSReportUserHP.Parser.ParseFrom(data._data);
  94. if (this.ClientPeers.TryGetValue(peerId, out var peer))
  95. {
  96. if (peer.Properties.ContainsKey(PropertyName.Hp))
  97. {
  98. peer.Properties[PropertyName.Hp] = msg.UserHP;
  99. }
  100. else
  101. {
  102. peer.Properties.Add(PropertyName.Hp, msg.UserHP);
  103. }
  104. }
  105. }
  106. /// <summary>
  107. /// 处理客户端登录请求
  108. /// </summary>
  109. void On_Login(int peerId, sSocketData data)
  110. {
  111. if (this.ClientPeers.TryGetValue(peerId, out var peer))
  112. {
  113. var msg = CSEnterFight.Parser.ParseFrom(data._data);
  114. peer.Properties[nameof(msg.Uid)] = msg.Uid;
  115. peer.Properties[nameof(msg.Zoneid)] = msg.Zoneid;
  116. peer.Properties[PropertyName.Name] = msg.Name;
  117. peer.bossId = msg.BossId;
  118. lock (Boss_dict)
  119. {
  120. var bossKey = $"{msg.Zoneid}-{msg.BossId}";
  121. if (Boss_dict.TryGetValue(bossKey, out var boss))
  122. {
  123. if (boss.Ended) // boss战已结束, 尚未重新开启
  124. {
  125. WriteLine("游戏结束1");
  126. peer.SendEvent(eProtocalCommand.ScGameOver, new SCGameOver() { BossHp = boss.Hp, CountDown = boss.CountDownSecs });
  127. peer.Close();
  128. }
  129. else
  130. {
  131. var peerHp = -1; // 玩家血量, -1代表未初始化
  132. var exists = boss.Peers.Where(kv => kv.Value.UID == peer.UID && kv.Value.zoneid == peer.zoneid);
  133. if (exists.Count() < 1)
  134. {
  135. boss.Peers.Add(peerId, peer);
  136. }
  137. else
  138. { // 已经进入到房间中过了
  139. var oldPeer = exists.First().Value;
  140. if (oldPeer.Properties.TryGetValue(PropertyName.Hp, out var hisHp))
  141. {
  142. peerHp = int.Parse(hisHp.ToString());
  143. peer.Properties[PropertyName.Hp] = peerHp;
  144. Console.WriteLine($" 玩家记录血量:{peerHp} ");
  145. }
  146. boss.Peers.Remove(oldPeer.Id);
  147. boss.Peers.Add(peerId, peer);
  148. }
  149. peer.SendEvent(eProtocalCommand.ScLogin, new SCEnterFight() { BossHp = boss.Hp, BossMaxHp = boss.MaxHp, UserHP = peerHp, CountDown = boss.CountDownSecs });
  150. Console.WriteLine($"boss [{boss.ZoneId}] 已经初始化完毕, " + boss.Hp);
  151. }
  152. }
  153. else // 初始化新的boss
  154. {
  155. Console.WriteLine($"初始化 boss [{msg.Zoneid}]");
  156. var b = new Boss(msg.BossId, msg.Zoneid, MaxHp, BossSettle);
  157. b.Peers.Add(peerId, peer);
  158. Boss_dict.Add(b.UID, b);
  159. peer.SendEvent(eProtocalCommand.ScLogin, new SCEnterFight() { BossHp = b.Hp, BossMaxHp = b.MaxHp, UserHP = -1, CountDown = b.CountDownSecs });
  160. }
  161. }
  162. }
  163. }
  164. void BossSettle(Boss boss)
  165. {
  166. WriteLine($"结算Boss {boss.UID}");
  167. if (Boss_dict.ContainsKey(boss.UID))
  168. {
  169. var data = $"zoneid={boss.ZoneId}&bossid={boss.Id}";
  170. HttpHelper.Instance.Post(Config.Ins.SettleUrl, data);
  171. var t = Task.Delay(TimeSpan.FromSeconds(Config.Ins.CountDownTimes)).ContinueWith(t =>
  172. {
  173. lock (Boss_dict)
  174. {
  175. Boss_dict.Remove(boss.UID);
  176. }
  177. });
  178. }
  179. }
  180. /// <summary>
  181. /// 处理客户端上报伤害请求
  182. /// </summary>
  183. void On_ReportDamage(int peerId, sSocketData data)
  184. {
  185. if (this.ClientPeers.TryGetValue(peerId, out var peer))
  186. {
  187. var msg = CSFightReportDamage.Parser.ParseFrom(data._data);
  188. if (Boss_dict.TryGetValue(peer.BossKey, out var boss))
  189. {
  190. boss.DamageQueue.Writer.WriteAsync(msg.Damage);
  191. peer.AddDamage(msg.Damage);
  192. }
  193. }
  194. }
  195. /// <summary>
  196. /// 离开房间(战斗结束)
  197. /// </summary>
  198. /// <param name="data"></param>
  199. void On_Leave(int peerId, sSocketData data)
  200. {
  201. if (this.ClientPeers.TryGetValue(peerId, out var peer))
  202. {
  203. peer.Close();
  204. }
  205. }
  206. async void MsgLoop()
  207. {
  208. while (true)
  209. {
  210. var msg = await MsgChannel.Reader.ReadAsync();
  211. if (callbacks.ContainsKey(msg.Value._protocallType))
  212. {
  213. callbacks[msg.Value._protocallType](msg.Key, msg.Value);
  214. }
  215. else
  216. {
  217. // 未找到消息处理逻辑
  218. }
  219. }
  220. }
  221. /// <summary>
  222. /// 开启
  223. /// </summary>
  224. public void Open()
  225. {
  226. Boss_dict.Clear();
  227. this.CurrentState = RoomState.Open;
  228. }
  229. public void Close()
  230. {
  231. this.CurrentState = RoomState.Close;
  232. Task.Delay(TimeSpan.FromMinutes(1)).ContinueWith(t => Open());
  233. }
  234. private object lock_peers = new object();
  235. public void AddPeer(Peer p)
  236. {
  237. if (CurrentState == RoomState.Open)
  238. {
  239. lock (lock_peers)
  240. {
  241. this.ClientPeers.Add(p.Id, p);
  242. }
  243. }
  244. else
  245. {
  246. WriteLine("游戏结束2 // 这里不应该执行到!!!");
  247. p.SendEvent(eProtocalCommand.ScGameOver, new SCGameOver() { BossHp = 0, CountDown = 9999 });
  248. p.Close();
  249. }
  250. }
  251. public void RemovePeer(Peer p)
  252. {
  253. lock (lock_peers)
  254. {
  255. if (this.ClientPeers.ContainsKey(p.Id))
  256. {
  257. this.ClientPeers.Remove(p.Id);
  258. }
  259. }
  260. }
  261. }
  262. }