You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

RpcServices.cs 19 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. using Grpc.Core;
  2. using Protobuf;
  3. using System.Threading;
  4. using System;
  5. using System.Net.Http.Headers;
  6. using Gaming;
  7. using GameClass.GameObj;
  8. using Preparation.Utility;
  9. using Playback;
  10. using Newtonsoft.Json;
  11. using Newtonsoft.Json.Linq;
  12. using Preparation.Interface;
  13. namespace Server
  14. {
  15. public partial class GameServer : AvailableService.AvailableServiceBase
  16. {
  17. private int playerCountNow = 0;
  18. protected object spectatorLock = new object();
  19. protected bool isSpectatorJoin = false;
  20. protected bool IsSpectatorJoin
  21. {
  22. get
  23. {
  24. lock (spectatorLock)
  25. return isSpectatorJoin;
  26. }
  27. set
  28. {
  29. lock (spectatorLock)
  30. isSpectatorJoin = value;
  31. }
  32. }
  33. public override Task<BoolRes> TryConnection(IDMsg request, ServerCallContext context)
  34. {
  35. #if DEBUG
  36. Console.WriteLine($"TryConnection ID: {request.PlayerId}");
  37. #endif
  38. var onConnection = new BoolRes();
  39. lock (gameLock)
  40. {
  41. if (0 <= request.PlayerId && request.PlayerId < playerNum) // 注意修改
  42. {
  43. onConnection.ActSuccess = true;
  44. Console.WriteLine(onConnection.ActSuccess);
  45. return Task.FromResult(onConnection);
  46. }
  47. }
  48. onConnection.ActSuccess = false;
  49. return Task.FromResult(onConnection);
  50. }
  51. protected readonly object addPlayerLock = new();
  52. public override async Task AddPlayer(PlayerMsg request, IServerStreamWriter<MessageToClient> responseStream, ServerCallContext context)
  53. {
  54. Console.WriteLine($"AddPlayer: {request.PlayerId}");
  55. if (request.PlayerId >= spectatorMinPlayerID && options.NotAllowSpectator == false)
  56. {
  57. // 观战模式
  58. lock (spetatorJoinLock) // 具体原因见另一个上锁的地方
  59. {
  60. if (semaDict.TryAdd(request.PlayerId, (new SemaphoreSlim(0, 1), new SemaphoreSlim(0, 1))))
  61. {
  62. Console.WriteLine("A new spectator comes to watch this game.");
  63. IsSpectatorJoin = true;
  64. }
  65. else
  66. {
  67. Console.WriteLine($"Duplicated Spectator ID {request.PlayerId}");
  68. return;
  69. }
  70. }
  71. do
  72. {
  73. semaDict[request.PlayerId].Item1.Wait();
  74. try
  75. {
  76. if (currentGameInfo != null)
  77. {
  78. await responseStream.WriteAsync(currentGameInfo);
  79. //Console.WriteLine("Send!");
  80. }
  81. }
  82. catch (InvalidOperationException)
  83. {
  84. if (semaDict.TryRemove(request.PlayerId, out var semas))
  85. {
  86. try
  87. {
  88. semas.Item1.Release();
  89. semas.Item2.Release();
  90. }
  91. catch { }
  92. Console.WriteLine($"The spectator {request.PlayerId} exited");
  93. }
  94. }
  95. catch (Exception)
  96. {
  97. // Console.WriteLine(ex);
  98. }
  99. finally
  100. {
  101. try
  102. {
  103. semaDict[request.PlayerId].Item2.Release();
  104. }
  105. catch { }
  106. }
  107. } while (game.GameMap.Timer.IsGaming);
  108. return;
  109. }
  110. if (game.GameMap.Timer.IsGaming)
  111. return;
  112. if (!ValidPlayerID(request.PlayerId)) //玩家id是否正确
  113. return;
  114. if (communicationToGameID[request.PlayerId] != GameObj.invalidID) //是否已经添加了该玩家
  115. return;
  116. Preparation.Utility.CharacterType characterType = Preparation.Utility.CharacterType.Null;
  117. if (request.PlayerType == PlayerType.StudentPlayer)
  118. characterType = Transformation.ToStudentType(request.StudentType);
  119. else if (request.PlayerType == PlayerType.TrickerPlayer)
  120. characterType = Transformation.ToTrickerType(request.TrickerType);
  121. lock (addPlayerLock)
  122. {
  123. Game.PlayerInitInfo playerInitInfo = new(GetBirthPointIdx(request.PlayerId), PlayerTypeToTeamID(request.PlayerType), (int)request.PlayerId, characterType);
  124. long newPlayerID = game.AddPlayer(playerInitInfo);
  125. if (newPlayerID == GameObj.invalidID)
  126. return;
  127. communicationToGameID[request.PlayerId] = newPlayerID;
  128. var temp = (new SemaphoreSlim(0, 1), new SemaphoreSlim(0, 1));
  129. bool start = false;
  130. Console.WriteLine($"Id: {request.PlayerId} joins.");
  131. lock (spetatorJoinLock) // 为了保证绝对安全,还是加上这个锁吧
  132. {
  133. if (semaDict.TryAdd(request.PlayerId, temp))
  134. {
  135. start = Interlocked.Increment(ref playerCountNow) == playerNum;
  136. }
  137. }
  138. if (start) StartGame();
  139. }
  140. do
  141. {
  142. semaDict[request.PlayerId].Item1.Wait();
  143. try
  144. {
  145. if (currentGameInfo != null)
  146. {
  147. await responseStream.WriteAsync(currentGameInfo);
  148. //Console.WriteLine("Send!");
  149. }
  150. }
  151. catch (Exception)
  152. {
  153. //Console.WriteLine(ex);
  154. }
  155. finally
  156. {
  157. semaDict[request.PlayerId].Item2.Release();
  158. }
  159. } while (game.GameMap.Timer.IsGaming);
  160. }
  161. public override Task<BoolRes> Attack(AttackMsg request, ServerCallContext context)
  162. {
  163. #if DEBUG
  164. Console.WriteLine($"Attack ID: {request.PlayerId}");
  165. #endif
  166. BoolRes boolRes = new();
  167. if (request.PlayerId >= spectatorMinPlayerID)
  168. {
  169. boolRes.ActSuccess = false;
  170. return Task.FromResult(boolRes);
  171. }
  172. if (request.Angle == double.NaN)
  173. {
  174. boolRes.ActSuccess = false;
  175. return Task.FromResult(boolRes);
  176. }
  177. var gameID = communicationToGameID[request.PlayerId];
  178. boolRes.ActSuccess = game.Attack(gameID, request.Angle);
  179. return Task.FromResult(boolRes);
  180. }
  181. public override Task<MoveRes> Move(MoveMsg request, ServerCallContext context)
  182. {
  183. #if DEBUG
  184. Console.WriteLine($"Move ID: {request.PlayerId}, TimeInMilliseconds: {request.TimeInMilliseconds}");
  185. #endif
  186. MoveRes moveRes = new();
  187. if (request.PlayerId >= spectatorMinPlayerID)
  188. {
  189. moveRes.ActSuccess = false;
  190. return Task.FromResult(moveRes);
  191. }
  192. if (request.Angle == double.NaN)
  193. {
  194. moveRes.ActSuccess = false;
  195. return Task.FromResult(moveRes);
  196. }
  197. var gameID = communicationToGameID[request.PlayerId];
  198. moveRes.ActSuccess = game.MovePlayer(gameID, (int)request.TimeInMilliseconds, request.Angle);
  199. if (!game.GameMap.Timer.IsGaming) moveRes.ActSuccess = false;
  200. return Task.FromResult(moveRes);
  201. }
  202. public override Task<BoolRes> SendMessage(SendMsg request, ServerCallContext context)
  203. {
  204. var boolRes = new BoolRes();
  205. if (request.PlayerId >= spectatorMinPlayerID || playerDeceased((int)request.PlayerId))
  206. {
  207. boolRes.ActSuccess = false;
  208. return Task.FromResult(boolRes);
  209. }
  210. if (!ValidPlayerID(request.PlayerId) || !ValidPlayerID(request.ToPlayerId)
  211. || PlayerIDToTeamID(request.PlayerId) != PlayerIDToTeamID(request.ToPlayerId) || request.PlayerId == request.ToPlayerId)
  212. {
  213. boolRes.ActSuccess = false;
  214. return Task.FromResult(boolRes);
  215. }
  216. if (request.Message.Length > 256)
  217. {
  218. #if DEBUG
  219. Console.WriteLine("Message string is too long!");
  220. #endif
  221. boolRes.ActSuccess = false;
  222. return Task.FromResult(boolRes);
  223. }
  224. else
  225. {
  226. MessageOfNews news = new();
  227. news.News = request.Message;
  228. news.FromId = request.PlayerId;
  229. news.ToId = request.ToPlayerId;
  230. lock (newsLock)
  231. {
  232. currentNews.Add(news);
  233. }
  234. #if DEBUG
  235. Console.WriteLine(news.News);
  236. #endif
  237. }
  238. boolRes.ActSuccess = true;
  239. return Task.FromResult(boolRes);
  240. }
  241. public override Task<BoolRes> PickProp(PropMsg request, ServerCallContext context)
  242. {
  243. #if DEBUG
  244. Console.WriteLine($"PickProp ID: {request.PlayerId}");
  245. #endif
  246. BoolRes boolRes = new();
  247. if (request.PlayerId >= spectatorMinPlayerID)
  248. {
  249. boolRes.ActSuccess = false;
  250. return Task.FromResult(boolRes);
  251. }
  252. var gameID = communicationToGameID[request.PlayerId];
  253. boolRes.ActSuccess = game.PickProp(gameID, Transformation.ToPropType(request.PropType));
  254. return Task.FromResult(boolRes);
  255. }
  256. public override Task<BoolRes> UseProp(PropMsg request, ServerCallContext context)
  257. {
  258. #if DEBUG
  259. Console.WriteLine($"UseProp ID: {request.PlayerId}");
  260. #endif
  261. BoolRes boolRes = new();
  262. if (request.PlayerId >= spectatorMinPlayerID)
  263. {
  264. boolRes.ActSuccess = false;
  265. return Task.FromResult(boolRes);
  266. }
  267. var gameID = communicationToGameID[request.PlayerId];
  268. game.UseProp(gameID, Transformation.ToPropType(request.PropType));
  269. boolRes.ActSuccess = true;
  270. return Task.FromResult(boolRes);
  271. }
  272. public override Task<BoolRes> ThrowProp(PropMsg request, ServerCallContext context)
  273. {
  274. #if DEBUG
  275. Console.WriteLine($"ThrowProp ID: {request.PlayerId}");
  276. #endif
  277. BoolRes boolRes = new();
  278. if (request.PlayerId >= spectatorMinPlayerID)
  279. {
  280. boolRes.ActSuccess = false;
  281. return Task.FromResult(boolRes);
  282. }
  283. var gameID = communicationToGameID[request.PlayerId];
  284. game.ThrowProp(gameID, Transformation.ToPropType(request.PropType));
  285. boolRes.ActSuccess = true;
  286. return Task.FromResult(boolRes);
  287. }
  288. public override Task<BoolRes> UseSkill(SkillMsg request, ServerCallContext context)
  289. {
  290. #if DEBUG
  291. Console.WriteLine($"UseSkill ID: {request.PlayerId}");
  292. #endif
  293. BoolRes boolRes = new();
  294. if (request.PlayerId >= spectatorMinPlayerID)
  295. {
  296. boolRes.ActSuccess = false;
  297. return Task.FromResult(boolRes);
  298. }
  299. var gameID = communicationToGameID[request.PlayerId];
  300. boolRes.ActSuccess = game.UseActiveSkill(gameID, request.SkillId);
  301. return Task.FromResult(boolRes);
  302. }
  303. public override Task<BoolRes> Graduate(IDMsg request, ServerCallContext context)
  304. {
  305. #if DEBUG
  306. Console.WriteLine($"Graduate ID: {request.PlayerId}");
  307. #endif
  308. BoolRes boolRes = new();
  309. if (request.PlayerId >= spectatorMinPlayerID)
  310. {
  311. boolRes.ActSuccess = false;
  312. return Task.FromResult(boolRes);
  313. }
  314. var gameID = communicationToGameID[request.PlayerId];
  315. boolRes.ActSuccess = game.Escape(gameID);
  316. return Task.FromResult(boolRes);
  317. }
  318. public override Task<BoolRes> StartRescueMate(TreatAndRescueMsg request, ServerCallContext context)
  319. {
  320. #if DEBUG
  321. Console.WriteLine($"StartRescueMate ID: {request.PlayerId}");
  322. #endif
  323. BoolRes boolRes = new();
  324. if (request.PlayerId >= spectatorMinPlayerID)
  325. {
  326. boolRes.ActSuccess = false;
  327. return Task.FromResult(boolRes);
  328. }
  329. var gameID = communicationToGameID[request.PlayerId];
  330. if (request.ToPlayerId >= 0 && request.ToPlayerId < options.MaxStudentCount)
  331. {
  332. var toGameID = communicationToGameID[request.ToPlayerId];
  333. boolRes.ActSuccess = game.Rescue(gameID, toGameID);
  334. }
  335. else
  336. {
  337. boolRes.ActSuccess = game.Rescue(gameID);
  338. }
  339. return Task.FromResult(boolRes);
  340. }
  341. public override Task<BoolRes> StartTreatMate(TreatAndRescueMsg request, ServerCallContext context)
  342. {
  343. #if DEBUG
  344. Console.WriteLine($"StartTreatMate ID: {request.PlayerId}");
  345. #endif
  346. BoolRes boolRes = new();
  347. if (request.PlayerId >= spectatorMinPlayerID)
  348. {
  349. boolRes.ActSuccess = false;
  350. return Task.FromResult(boolRes);
  351. }
  352. var gameID = communicationToGameID[request.PlayerId];
  353. if (request.ToPlayerId >= 0 && request.ToPlayerId < options.MaxStudentCount)
  354. {
  355. var toGameID = communicationToGameID[request.ToPlayerId];
  356. boolRes.ActSuccess = game.Treat(gameID, toGameID);
  357. }
  358. else
  359. {
  360. boolRes.ActSuccess = game.Treat(gameID);
  361. }
  362. return Task.FromResult(boolRes);
  363. }
  364. public override Task<BoolRes> StartLearning(IDMsg request, ServerCallContext context)
  365. {
  366. #if DEBUG
  367. Console.WriteLine($"StartLearning ID: {request.PlayerId}");
  368. #endif
  369. BoolRes boolRes = new();
  370. if (request.PlayerId >= spectatorMinPlayerID)
  371. {
  372. boolRes.ActSuccess = false;
  373. return Task.FromResult(boolRes);
  374. }
  375. var gameID = communicationToGameID[request.PlayerId];
  376. boolRes.ActSuccess = game.Fix(gameID);
  377. return Task.FromResult(boolRes);
  378. }
  379. public override Task<BoolRes> StartOpenChest(IDMsg request, ServerCallContext context)
  380. {
  381. #if DEBUG
  382. Console.WriteLine($"StartOpenChest ID: {request.PlayerId}");
  383. #endif
  384. BoolRes boolRes = new();
  385. if (request.PlayerId >= spectatorMinPlayerID)
  386. {
  387. boolRes.ActSuccess = false;
  388. return Task.FromResult(boolRes);
  389. }
  390. var gameID = communicationToGameID[request.PlayerId];
  391. boolRes.ActSuccess = game.OpenChest(gameID);
  392. return Task.FromResult(boolRes);
  393. }
  394. public override Task<BoolRes> StartOpenGate(IDMsg request, ServerCallContext context)
  395. {
  396. #if DEBUG
  397. Console.WriteLine($"StartOpenGate ID: {request.PlayerId}");
  398. #endif
  399. BoolRes boolRes = new();
  400. if (request.PlayerId >= spectatorMinPlayerID)
  401. {
  402. boolRes.ActSuccess = false;
  403. return Task.FromResult(boolRes);
  404. }
  405. var gameID = communicationToGameID[request.PlayerId];
  406. boolRes.ActSuccess = game.OpenDoorway(gameID);
  407. return Task.FromResult(boolRes);
  408. }
  409. public override Task<BoolRes> OpenDoor(IDMsg request, ServerCallContext context)
  410. {
  411. #if DEBUG
  412. Console.WriteLine($"OpenDoor ID: {request.PlayerId}");
  413. #endif
  414. BoolRes boolRes = new();
  415. if (request.PlayerId >= spectatorMinPlayerID)
  416. {
  417. boolRes.ActSuccess = false;
  418. return Task.FromResult(boolRes);
  419. }
  420. var gameID = communicationToGameID[request.PlayerId];
  421. boolRes.ActSuccess = game.LockOrOpenDoor(gameID);
  422. return Task.FromResult(boolRes);
  423. }
  424. public override Task<BoolRes> CloseDoor(IDMsg request, ServerCallContext context)
  425. {
  426. #if DEBUG
  427. Console.WriteLine($"CloseDoor ID: {request.PlayerId}");
  428. #endif
  429. BoolRes boolRes = new();
  430. if (request.PlayerId >= spectatorMinPlayerID)
  431. {
  432. boolRes.ActSuccess = false;
  433. return Task.FromResult(boolRes);
  434. }
  435. var gameID = communicationToGameID[request.PlayerId];
  436. boolRes.ActSuccess = game.LockOrOpenDoor(gameID);
  437. return Task.FromResult(boolRes);
  438. }
  439. public override Task<BoolRes> EndAllAction(IDMsg request, ServerCallContext context)
  440. {
  441. #if DEBUG
  442. Console.WriteLine($"EndAllAction ID: {request.PlayerId}");
  443. #endif
  444. BoolRes boolRes = new();
  445. if (request.PlayerId >= spectatorMinPlayerID)
  446. {
  447. boolRes.ActSuccess = false;
  448. return Task.FromResult(boolRes);
  449. }
  450. var gameID = communicationToGameID[request.PlayerId];
  451. boolRes.ActSuccess = game.Stop(gameID);
  452. return Task.FromResult(boolRes);
  453. }
  454. public override Task<BoolRes> SkipWindow(IDMsg request, ServerCallContext context)
  455. {
  456. #if DEBUG
  457. Console.WriteLine($"SkipWindow ID: {request.PlayerId}");
  458. #endif
  459. BoolRes boolRes = new();
  460. if (request.PlayerId >= spectatorMinPlayerID)
  461. {
  462. boolRes.ActSuccess = false;
  463. return Task.FromResult(boolRes);
  464. }
  465. var gameID = communicationToGameID[request.PlayerId];
  466. boolRes.ActSuccess = game.ClimbingThroughWindow(gameID);
  467. return Task.FromResult(boolRes);
  468. }
  469. }
  470. }