//Listener Process From Client Data private static async void ReadFromClient(ProtocolModel.ConnectionClient connectionClient) { try { await Task.Run(async() => { while (connectionClient.Client.Connected) { if (connectionClient.Client.GetStream().DataAvailable) { NetworkStream stream = connectionClient.Client.GetStream(); byte[] data = new byte[1024]; string json = string.Empty; var bytes = stream.Read(data, 0, data.Length); if (bytes > 0) { json = Encoding.ASCII.GetString(data, 0, bytes); } //Data Processing var token = json.Split(new[] { "\\;omansak;\\" }, StringSplitOptions.RemoveEmptyEntries); foreach (var msgToken in token) { ProtocolModel.Base baseMessage = JsonConvert.DeserializeObject <ProtocolModel.Base>(msgToken); switch (baseMessage.Type) { // Join new player and send current players case ProtocolModel.MessageType.RequestJoin: { ProtocolModel.Player player = JsonConvert.DeserializeObject <ProtocolModel.Player>(baseMessage.Data.ToString()); player.Id = connectionClient.Id; Players.Add(player); BroadcastPlayers(); RequestSendMessage($"--> {Players.First(i => i.Id == connectionClient.Id).Name} is joined."); break; } // Lobby Messages case ProtocolModel.MessageType.LobbyMessage: { BroadcastFromServer(json); break; } // Start Game case ProtocolModel.MessageType.RequestStart: { GameRunning = true; GenerateShapes(); RequestSendMessage($"--> Game started by {Players.First(i => i.Id == connectionClient.Id).Name} (host)"); break; } // Game Settings case ProtocolModel.MessageType.RequestGameSettings: { BroadcastFromServer(JsonConvert.SerializeObject(new ProtocolModel.Base { Type = ProtocolModel.MessageType.RequestGameSettings, Data = new ProtocolModel.GameSetting { GameName = GameName, Red = GameShapeRed.ToString(), Blue = GameShapeBlue.ToString(), Yellow = GameShapeYellow.ToString(), Timer = GameRefreshTime.ToString(), Win = GameWinPoint.ToString(), PanelSize = new Point(GamePanelSizeX, GamePanelSizeY) } })); break; } // Check coor inside objects case ProtocolModel.MessageType.RequestSendCoor: { ProtocolModel.ClickCoor point = JsonConvert.DeserializeObject <ProtocolModel.ClickCoor>(baseMessage.Data.ToString()); for (int j = ShapesPanel.Count - 1; j >= 0; j--) { var item = ShapesPanel[j]; if (item.Type == 0) { if (ContainsEllipse(point.Coor, item.Point)) { ShapesPanel.Remove(item); Players.First(i => i.Id == connectionClient.Id).Point += GameShapeRed; BroadcastShapes(); BroadcastPlayers(); RequestSendMessage($"--> {Players.First(i => i.Id == connectionClient.Id).Name} is gained {GameShapeRed} with Red"); break; } } if (item.Type == 1) { if (ContainsRectangle(point.Coor, item.Point)) { ShapesPanel.Remove(item); Players.First(i => i.Id == connectionClient.Id).Point += GameShapeBlue; BroadcastShapes(); BroadcastPlayers(); RequestSendMessage($"--> {Players.First(i => i.Id == connectionClient.Id).Name} is gained {GameShapeBlue} with Blue"); break; } } if (item.Type == 2) { if (ContainsTriangle(point.Coor, item.Point)) { ShapesPanel.Remove(item); Players.First(i => i.Id == connectionClient.Id).Point += GameShapeYellow; BroadcastShapes(); BroadcastPlayers(); RequestSendMessage($"--> {Players.First(i => i.Id == connectionClient.Id).Name} is gained {GameShapeYellow} with Yellow"); break; } } } break; } } } } Thread.Sleep(25); } }); } finally { Players.Remove(Players.First(i => i.Id == connectionClient.Id)); connectionClient.Client.Close(); BroadcastPlayers(); } }
// ReadFromClient: Begin interpreting packets from the specified client, performing actions based on the data received private static async void ReadFromClient(ProtocolModel.ConnectionClient connectionClient) { try { await Task.Run(() => { while (connectionClient.Client.Connected) { if (connectionClient.Client.GetStream().DataAvailable) { // Data Processing string json = DataUtils.ReadJsonFromStream(connectionClient.Client.GetStream(), SizeLimit); var token = json.Split(new[] { PacketSplitter }, StringSplitOptions.RemoveEmptyEntries); foreach (var msgToken in token) { ProtocolModel.Base baseMessage = JsonConvert.DeserializeObject <ProtocolModel.Base>(msgToken); switch (baseMessage.Type) { // RequestJoin: Add Client Data to observable Player Array (Adding the GUID from the connectionClient) then re-broadcast the new playerList case ProtocolModel.MessageType.RequestJoin: { ProtocolModel.Player player = JsonConvert.DeserializeObject <ProtocolModel.Player>(baseMessage.Data.ToString()); player.Id = connectionClient.Id; Players.Add(player); BroadcastPlayers(); RequestSendMessage($"--> {Players.First(i => i.Id == connectionClient.Id).Name} has joined."); break; } // LobbyMessage: Broadcast a General Status Message from the Server case ProtocolModel.MessageType.LobbyMessage: { SendFromServer(json); break; } // RequestStart: Sets appropriate flags for Game Running, and begins auto-populating the game panel case ProtocolModel.MessageType.RequestStart: { // Clear all Player points before starting ClearScores(); GameRunning = true; BeginShapeGen(); RequestSendMessage($"--> Game started by {Players.First(i => i.Id == connectionClient.Id).Name} (Host)"); break; } // RequestGameSettings: Requests a copy of the current public game settings available to all users case ProtocolModel.MessageType.RequestGameSettings: { SendFromServer(JsonConvert.SerializeObject(new ProtocolModel.Base { Type = ProtocolModel.MessageType.RequestGameSettings, Data = new ProtocolModel.GameSetting { GameName = GameName, CurrentPlayers = Players.Count, GameSize = GameSize + 1, GameInProgress = GameRunning, DefaultPointValues = AveragePoints, MaxShapeCount = MaxShapeCount, MaxShapeTicks = MaxShapeTicks, Timer = GameRefreshTime.ToString(), Win = GameWinPoint.ToString(), PanelSize = new Point(GamePanelSizeX, GamePanelSizeY) } })); break; } // RequestSendCoords: Queries the ClickCoords reported in order to check for Shape collission case ProtocolModel.MessageType.RequestSendCoords: { ProtocolModel.ClickCoords point = JsonConvert.DeserializeObject <ProtocolModel.ClickCoords>(baseMessage.Data.ToString()); for (int j = ShapesPanel.Count - 1; j >= 0; j--) { var item = ShapesPanel[j]; if (ShapeUtils.ContainsShape(item.Type, point.Location, item.Location)) { ShapesPanel.Remove(item); Players.First(i => i.Id == connectionClient.Id).Score += item.Value; BroadcastShapes(); BroadcastPlayers(); if (GameRunning) { int modifiedValue = item.Value >= 0 ? item.Value : Math.Abs(item.Value); RequestSendMessage($"--> {Players.First(i => i.Id == connectionClient.Id).Name} has {(item.Value >= 0 ? "gained" : "lost")} {modifiedValue} {(modifiedValue > 1 ? "points" : "point")} from clicking a {item.Color.Name} {Enum.GetName(typeof(ProtocolModel.ShapeType), item.Type)}"); } break; } } break; } } } } Thread.Sleep(25); } }); } finally { // If the task ends unexpectedly or the player disconnects at some point, // display a LEFT_GAME message in chat, and ensure their data is cleaned up // // Normally, this type of stuff would occur immediatly when the manual leave actions occur // That is still highly TODO, so this event only plays whenever the next packet tries to passthrough ProtocolModel.Player player = Players.First(i => i.Id == connectionClient.Id); Players.Remove(player); connectionClient.Client.Close(); BroadcastPlayers(); RequestSendMessage($"--> {player.Name} has left the game."); } }