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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. Console.WriteLine(onConnection.ActSuccess);
  27. return Task.FromResult(onConnection);
  28. }
  29. }
  30. onConnection.ActSuccess = false;
  31. return Task.FromResult(onConnection);
  32. }
  33. public override async Task AddPlayer(PlayerMsg request, IServerStreamWriter<MessageToClient> responseStream, ServerCallContext context)
  34. {
  35. lock (gameLock)
  36. {
  37. if (game.IsGaming)
  38. return;
  39. game.AddPlayer(request);
  40. var temp = (new SemaphoreSlim(0, 1), new SemaphoreSlim(0, 1));
  41. bool start = false;
  42. Console.WriteLine($"Id: {request.PlayerId} joins.");
  43. lock (semaDict)
  44. {
  45. semaDict.Add(request.PlayerId, temp);
  46. start = semaDict.Count == playerNum;
  47. }
  48. if (start)
  49. {
  50. Console.WriteLine("Game starts!");
  51. StartGame();
  52. }
  53. }
  54. do
  55. {
  56. semaDict[request.PlayerId].Item1.Wait();
  57. if (currentGameInfo != null)
  58. {
  59. await responseStream.WriteAsync(currentGameInfo);
  60. Console.WriteLine("Send!");
  61. }
  62. semaDict[request.PlayerId].Item2.Release();
  63. } while (game.IsGaming);
  64. }
  65. public void StartGame()
  66. {
  67. var waitHandle = game.StartGame();
  68. new Thread(() =>
  69. {
  70. new FrameRateTaskExecutor<int>
  71. (
  72. () => game.IsGaming,
  73. ReportGame,
  74. 1000,
  75. () =>
  76. {
  77. ReportGame(); // 最后发一次消息,唤醒发消息的线程,防止发消息的线程由于有概率处在 Wait 状态而卡住
  78. return 0;
  79. }
  80. ).Start();
  81. })
  82. { IsBackground = true }.Start();
  83. new Thread(() =>
  84. {
  85. waitHandle.Wait();
  86. this.endGameSem.Release();
  87. })
  88. { IsBackground = true }.Start();
  89. }
  90. public void WaitForEnd()
  91. {
  92. this.endGameSem.Wait();
  93. }
  94. public void ReportGame()
  95. {
  96. currentGameInfo = game.GetCopiedGameInfo();
  97. foreach (var kvp in semaDict)
  98. {
  99. kvp.Value.Item1.Release();
  100. }
  101. foreach (var kvp in semaDict)
  102. {
  103. kvp.Value.Item2.Wait();
  104. }
  105. }
  106. public GameServer()
  107. {
  108. }
  109. }
  110. }