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.

GameServer.cs 3.7 kB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using Grpc.Core;
  2. using Protobuf;
  3. using System.Threading;
  4. using Timothy.FrameRateTask;
  5. using System;
  6. using System.Net.Http.Headers;
  7. namespace Server
  8. {
  9. public class GameServer : AvailableService.AvailableServiceBase
  10. {
  11. private Dictionary<long, (SemaphoreSlim, SemaphoreSlim)> semaDict = new();
  12. private object gameLock = new();
  13. private const int playerNum = 1;
  14. private MessageToClient currentGameInfo = new();
  15. private Game game = new();
  16. public int GameTime => game.GameTime;
  17. private SemaphoreSlim endGameSem = new(0);
  18. public override Task<BoolRes> TryConnection(IDMsg request, ServerCallContext context)
  19. {
  20. var onConnection = new BoolRes();
  21. lock (gameLock)
  22. {
  23. // if (0 <= request.PlayerId && request.PlayerId < playerNum)
  24. {
  25. onConnection.ActSuccess = true;
  26. return Task.FromResult(onConnection);
  27. }
  28. }
  29. onConnection.ActSuccess = false;
  30. return Task.FromResult(onConnection);
  31. }
  32. public override async Task AddPlayer(PlayerMsg request, IServerStreamWriter<MessageToClient> responseStream, ServerCallContext context)
  33. {
  34. lock (gameLock)
  35. {
  36. if (game.IsGaming)
  37. return;
  38. game.AddPlayer(request);
  39. var temp = (new SemaphoreSlim(0, 1), new SemaphoreSlim(0, 1));
  40. bool start = false;
  41. Console.WriteLine($"Id: {request.PlayerId} joins.");
  42. lock (semaDict)
  43. {
  44. semaDict.Add(request.PlayerId, temp);
  45. start = semaDict.Count == playerNum;
  46. }
  47. if (start)
  48. {
  49. Console.WriteLine("Game starts!");
  50. StartGame();
  51. }
  52. }
  53. do
  54. {
  55. semaDict[request.PlayerId].Item1.Wait();
  56. if (currentGameInfo != null)
  57. {
  58. await responseStream.WriteAsync(currentGameInfo);
  59. Console.WriteLine("Send!");
  60. }
  61. semaDict[request.PlayerId].Item2.Release();
  62. } while (game.IsGaming);
  63. }
  64. public void StartGame()
  65. {
  66. var waitHandle = game.StartGame();
  67. new Thread(() =>
  68. {
  69. new FrameRateTaskExecutor<int>
  70. (
  71. () => game.IsGaming,
  72. ReportGame,
  73. 1000,
  74. () =>
  75. {
  76. ReportGame(); // 最后发一次消息,唤醒发消息的线程,防止发消息的线程由于有概率处在 Wait 状态而卡住
  77. return 0;
  78. }
  79. ).Start();
  80. })
  81. { IsBackground = true }.Start();
  82. new Thread(() =>
  83. {
  84. waitHandle.Wait();
  85. this.endGameSem.Release();
  86. })
  87. { IsBackground = true }.Start();
  88. }
  89. public void WaitForEnd()
  90. {
  91. this.endGameSem.Wait();
  92. }
  93. public void ReportGame()
  94. {
  95. currentGameInfo = game.GetCopiedGameInfo();
  96. foreach (var kvp in semaDict)
  97. {
  98. kvp.Value.Item1.Release();
  99. }
  100. foreach (var kvp in semaDict)
  101. {
  102. kvp.Value.Item2.Wait();
  103. }
  104. }
  105. public GameServer()
  106. {
  107. }
  108. }
  109. }