refactor(server): ♻️ make server base class to unify gameserver and playback server
tags/0.1.0
| @@ -1,22 +1,17 @@ | |||
| using Grpc.Core; | |||
| using Protobuf; | |||
| using System.Threading; | |||
| using Timothy.FrameRateTask; | |||
| using System; | |||
| using System.Net.Http.Headers; | |||
| using GameClass.GameObj; | |||
| using Gaming; | |||
| using GameClass.GameObj; | |||
| using Preparation.Utility; | |||
| using Playback; | |||
| using Newtonsoft.Json; | |||
| using Newtonsoft.Json.Linq; | |||
| using Preparation.Interface; | |||
| using Playback; | |||
| using Preparation.Utility; | |||
| using Protobuf; | |||
| using System.Collections.Concurrent; | |||
| using Timothy.FrameRateTask; | |||
| namespace Server | |||
| { | |||
| public partial class GameServer : AvailableService.AvailableServiceBase | |||
| partial class GameServer : ServerBase | |||
| { | |||
| private ConcurrentDictionary<long, (SemaphoreSlim, SemaphoreSlim)> semaDict = new(); | |||
| // private object semaDictLock = new(); | |||
| @@ -86,7 +81,7 @@ namespace Server | |||
| } | |||
| } | |||
| public void WaitForEnd() | |||
| public override void WaitForEnd() | |||
| { | |||
| this.endGameSem.Wait(); | |||
| mwr?.Dispose(); | |||
| @@ -202,7 +197,7 @@ namespace Server | |||
| return false; | |||
| } | |||
| public int[] GetScore() | |||
| public override int[] GetScore() | |||
| { | |||
| int[] score = new int[2]; // 0代表Student,1代表Tricker | |||
| game.GameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| @@ -1,26 +1,23 @@ | |||
| using Protobuf; | |||
| using Playback; | |||
| using System; | |||
| using System.Threading; | |||
| using Timothy.FrameRateTask; | |||
| using Gaming; | |||
| using Gaming; | |||
| using Grpc.Core; | |||
| using Playback; | |||
| using Protobuf; | |||
| using System.Collections.Concurrent; | |||
| using Timothy.FrameRateTask; | |||
| namespace Server | |||
| { | |||
| class PlaybackServer : AvailableService.AvailableServiceBase | |||
| class PlaybackServer : ServerBase | |||
| { | |||
| protected readonly ArgumentOptions options; | |||
| private int[,] teamScore; | |||
| private ConcurrentDictionary<long, (SemaphoreSlim, SemaphoreSlim)> semaDict = new(); | |||
| private object semaDictLock = new(); | |||
| // private object semaDictLock = new(); | |||
| private MessageToClient? currentGameInfo = new(); | |||
| private MessageOfObj currentMapMsg = new(); | |||
| private uint spectatorMinPlayerID = 2023; | |||
| private List<uint> spectatorList = new List<uint>(); | |||
| // private List<uint> spectatorList = new List<uint>(); | |||
| public int TeamCount => options.TeamCount; | |||
| private MessageWriter? mwr = null; | |||
| private object spetatorJoinLock = new(); | |||
| protected object spectatorLock = new object(); | |||
| protected bool isSpectatorJoin = false; | |||
| @@ -47,6 +44,7 @@ namespace Server | |||
| return finalScore; | |||
| } | |||
| } | |||
| public override int[] GetScore() => FinalScore; | |||
| public PlaybackServer(ArgumentOptions options) | |||
| { | |||
| this.options = options; | |||
| @@ -57,6 +55,7 @@ namespace Server | |||
| public override async Task AddPlayer(PlayerMsg request, IServerStreamWriter<MessageToClient> responseStream, ServerCallContext context) | |||
| { | |||
| Console.WriteLine($"AddPlayer: {request.PlayerId}"); | |||
| if (request.PlayerId >= spectatorMinPlayerID && options.NotAllowSpectator == false) | |||
| { | |||
| // 观战模式 | |||
| @@ -95,6 +94,7 @@ namespace Server | |||
| } | |||
| catch { } | |||
| Console.WriteLine($"The spectator {request.PlayerId} exited"); | |||
| return; | |||
| } | |||
| } | |||
| catch (Exception) | |||
| @@ -139,7 +139,7 @@ namespace Server | |||
| } | |||
| } | |||
| public void WaitForGame() | |||
| public override void WaitForEnd() | |||
| { | |||
| try | |||
| { | |||
| @@ -1,15 +1,16 @@ | |||
| using Grpc.Core; | |||
| using CommandLine; | |||
| using Grpc.Core; | |||
| using Protobuf; | |||
| using System.Threading; | |||
| using Timothy.FrameRateTask; | |||
| using System; | |||
| using System.Net.Http.Headers; | |||
| using CommandLine; | |||
| namespace Server | |||
| { | |||
| public class Program | |||
| { | |||
| static ServerBase CreateServer(ArgumentOptions options) | |||
| { | |||
| return options.Playback ? new PlaybackServer(options) : new GameServer(options); | |||
| } | |||
| static int Main(string[] args) | |||
| { | |||
| foreach (var arg in args) | |||
| @@ -28,61 +29,30 @@ namespace Server | |||
| Console.WriteLine("Server begins to run: " + options.ServerPort.ToString()); | |||
| if (options.Playback) | |||
| try | |||
| { | |||
| try | |||
| { | |||
| PlaybackServer? playbackServer = new(options); | |||
| Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) | |||
| { | |||
| Services = { AvailableService.BindService(playbackServer) }, | |||
| Ports = { new ServerPort(options.ServerIP, options.ServerPort, ServerCredentials.Insecure) } | |||
| }; | |||
| server.Start(); | |||
| Console.WriteLine("Server begins to listen!"); | |||
| playbackServer.WaitForGame(); | |||
| Console.WriteLine("Server end!"); | |||
| server.ShutdownAsync().Wait(); | |||
| Thread.Sleep(50); | |||
| Console.WriteLine(""); | |||
| Console.WriteLine("=================== Final Score ===================="); | |||
| Console.WriteLine($"Studnet: {playbackServer.FinalScore[0]}"); | |||
| Console.WriteLine($"Tricker: {playbackServer.FinalScore[1]}"); | |||
| } | |||
| catch (Exception ex) | |||
| var server = CreateServer(options); | |||
| Grpc.Core.Server rpcServer = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) | |||
| { | |||
| Console.WriteLine(ex.ToString()); | |||
| } | |||
| Services = { AvailableService.BindService(server) }, | |||
| Ports = { new ServerPort(options.ServerIP, options.ServerPort, ServerCredentials.Insecure) } | |||
| }; | |||
| rpcServer.Start(); | |||
| Console.WriteLine("Server begins to listen!"); | |||
| server.WaitForEnd(); | |||
| Console.WriteLine("Server end!"); | |||
| rpcServer.ShutdownAsync().Wait(); | |||
| Thread.Sleep(50); | |||
| Console.WriteLine(""); | |||
| Console.WriteLine("=================== Final Score ===================="); | |||
| Console.WriteLine($"Studnet: {server.GetScore()[0]}"); | |||
| Console.WriteLine($"Tricker: {server.GetScore()[1]}"); | |||
| } | |||
| else | |||
| catch (Exception ex) | |||
| { | |||
| try | |||
| { | |||
| GameServer? gameServer = new(options); | |||
| Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) | |||
| { | |||
| Services = { AvailableService.BindService(gameServer) }, | |||
| Ports = { new ServerPort(options.ServerIP, options.ServerPort, ServerCredentials.Insecure) } | |||
| }; | |||
| server.Start(); | |||
| Console.WriteLine("Server begins to listen!"); | |||
| gameServer.WaitForEnd(); | |||
| Console.WriteLine("Server end!"); | |||
| server.ShutdownAsync().Wait(); | |||
| Thread.Sleep(50); | |||
| Console.WriteLine(""); | |||
| Console.WriteLine("=================== Final Score ===================="); | |||
| Console.WriteLine($"Studnet: {gameServer.GetScore()[0]}"); | |||
| Console.WriteLine($"Tricker: {gameServer.GetScore()[1]}"); | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| Console.WriteLine(ex.ToString()); | |||
| } | |||
| Console.WriteLine(ex.ToString()); | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -1,19 +1,12 @@ | |||
| using Grpc.Core; | |||
| using Protobuf; | |||
| using System.Threading; | |||
| using System; | |||
| using System.Net.Http.Headers; | |||
| using GameClass.GameObj; | |||
| using Gaming; | |||
| using GameClass.GameObj; | |||
| using Grpc.Core; | |||
| using Preparation.Utility; | |||
| using Playback; | |||
| using Newtonsoft.Json; | |||
| using Newtonsoft.Json.Linq; | |||
| using Preparation.Interface; | |||
| using Protobuf; | |||
| namespace Server | |||
| { | |||
| public partial class GameServer : AvailableService.AvailableServiceBase | |||
| partial class GameServer : ServerBase | |||
| { | |||
| private int playerCountNow = 0; | |||
| protected object spectatorLock = new object(); | |||
| @@ -0,0 +1,14 @@ | |||
| using Grpc.Core; | |||
| using Playback; | |||
| using Protobuf; | |||
| using System.Collections.Concurrent; | |||
| using Timothy.FrameRateTask; | |||
| namespace Server | |||
| { | |||
| abstract class ServerBase : AvailableService.AvailableServiceBase | |||
| { | |||
| public abstract void WaitForEnd(); | |||
| public abstract int[] GetScore(); | |||
| } | |||
| } | |||