private void HandleHandshake(Message message) { var handshakeCommand = serializer.Deserialize <HandshakeCommand>(message.MessageString); var handshakeMessage = new HandshakeMessage { you = handshakeCommand.me }; Log($"Reply to handshake from {handshakeCommand.me}"); message.Reply(serializer.Serialize(handshakeMessage)); var id = session.Clients.Count; var connection = new PlayerConnection(tcpClient: message.TcpClient, name: handshakeCommand.me + " " + id, id: id); session.Clients.Add(connection); Log($"{session.Clients.Count}/{session.PlayersCount} players handshook"); if (session.Clients.Count == session.PlayersCount) { tcpServer.DataReceived -= TcpServer_DataReceived; Log("All players handshook. Gonna setup."); Setup(); } }
/*================================================================ * Author : Segal Au * * Date : April 9, 2019 * * Function: SendHeartBeat * * Params : * Object source * - object source * ElapsedEventArgs e * - event arguments * UDPSocket Socket * - Socket to send heart beat Packet * State state * - Game state and client manager * * Purpose : * Sends heart beat packet function (triggered by timer). * * =================================================================*/ private static void SendHeartBeat(Object source, ElapsedEventArgs e, UDPSocket socket, State state) { List <UpdateElement> unreliable = new List <UpdateElement> (); List <UpdateElement> reliable = new List <UpdateElement> (); Console.WriteLine("Count current connections {0}", state.ClientManager.CountCurrConnections); List <LobbyStatusElement.PlayerInfo> listPI = new List <LobbyStatusElement.PlayerInfo> (); try { for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } Console.WriteLine("Creating LobbyInfo packet"); PlayerConnection client = state.ClientManager.Connections [i]; listPI.Add(new LobbyStatusElement.PlayerInfo(client.ActorId, client.Name, client.Team, client.Ready)); } for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } Console.WriteLine("Sending Lobby update to client"); PlayerConnection client = state.ClientManager.Connections [i]; if (client.Disconnected()) { state.ClientManager.Connections [i] = null; } unreliable.Add(new LobbyStatusElement(listPI)); Packet startPacket = client.Connection.CreatePacket(unreliable, reliable, PacketType.HeartbeatPacket); socket.Send(startPacket, client.Destination); Console.WriteLine("Sent lobby update to client"); } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } }
/// ---------------------------------------------- /// FUNCTION: LobbyState /// /// DATE: April 2 , 2019 /// /// REVISIONS: /// /// DESIGNER: Cameron Roberts, Kieran Lee /// /// PROGRAMMER: Cameron Roberts, Kieran Lee, Segal Au /// /// INTERFACE: private static void LobbyState (UDPSocket socket, State state, ServerStateMessageBridge bridge) /// socket: socket to send and receive from /// state: gives access to client manager /// ServerStateMessageBridge: allows packets to be processed properly /// /// RETURNS: void /// /// NOTES: function that server remains in until lobyy is left and game is started. /// Expect request packets and hearbeat packets, discard all else. /// waits until all players are ready, then sends start game message. /// does not move to game state until all clients have started sending game packets /// ---------------------------------------------- private static void LobbyState(UDPSocket socket, State state, ServerStateMessageBridge bridge) { StartHeartBeat(socket, state); while (state.TimesEndGameSent < 80) { Packet packet; try { Console.WriteLine("Waiting for packet in lobby state"); packet = socket.Receive(); } catch (TimeoutException e) { Console.WriteLine("Timeout"); continue; } switch (ReliableUDPConnection.GetPacketType(packet)) { case PacketType.HeartbeatPacket: Console.WriteLine("Got heartbeat packet"); int clientId = ReliableUDPConnection.GetPlayerID(packet); state.ClientManager.Connections [clientId].MarkPacketReceive(); if (state.ClientManager.Connections [clientId] == null) { continue; } UnpackedPacket unpacked = state.ClientManager.Connections [clientId].Connection.ProcessPacket(packet, lobbyUnpackingArr); foreach (var element in unpacked.UnreliableElements) { element.UpdateState(bridge); } foreach (var element in unpacked.ReliableElements) { element.UpdateState(bridge); } break; case PacketType.RequestPacket: Console.WriteLine("Got request packet"); try { string name = ReliableUDPConnection.GetClientNameFromRequestPacket(packet); int newClient = state.ClientManager.AddConnection(socket.LastReceivedFrom, name); socket.Send(ReliableUDPConnection.CreateConfirmationPacket(newClient), state.ClientManager.Connections [newClient].Destination); Console.WriteLine("Sent confirmation packet to client " + newClient + " with name " + state.ClientManager.Connections [newClient].Name); } catch (OutOfMemoryException e) { } break; default: Log.V("Got unexpected packet type, discarding"); break; } Console.WriteLine("Checking if all players ready"); //TODO If all players ready start game send start packet and go to gamestate. Log.V("Checking if all players are ready"); bool allReady = state.ClientManager.CountCurrConnections > 0; for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } PlayerConnection client = state.ClientManager.Connections [i]; Log.V("Client " + i + ", " + client.Ready); allReady &= client.Ready; //bitwise operater to check that every connection is ready } Log.V("Current connections " + state.ClientManager.CountCurrConnections); if (allReady) { Log.D("All are ready sending startgame packet"); List <UpdateElement> unreliableElements = new List <UpdateElement> (); List <UpdateElement> reliableElements = new List <UpdateElement> (); int players = 0; for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } state.ClientManager.Connections [i].ActorId = state.GameState.AddPlayer(state.ClientManager.Connections [i].Team); players++; } reliableElements.Add(new GameStartElement(players)); var playerInfo = new List <LobbyStatusElement.PlayerInfo> (); for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } playerInfo.Add(new LobbyStatusElement.PlayerInfo(state.ClientManager.Connections [i].ClientId, state.ClientManager.Connections [i].Name, state.ClientManager.Connections [i].Team, state.ClientManager.Connections [i].Ready)); } unreliableElements.Add(new LobbyStatusElement(playerInfo)); for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } PlayerConnection client = state.ClientManager.Connections [i]; Packet startPacket = client.Connection.CreatePacket(unreliableElements, reliableElements, PacketType.HeartbeatPacket); socket.Send(startPacket, client.Destination); } //wait for each client to start sending gameplay packets, which indicates //that each client has received the gamestart Message bool allSendGame = false; int playerId; while (!allSendGame) { try{ packet = socket.Receive(); switch (ReliableUDPConnection.GetPacketType(packet)) { case PacketType.GameplayPacket: playerId = ReliableUDPConnection.GetPlayerID(packet); state.ClientManager.FindClientByActorId(playerId).startedGame = true; allSendGame = true; Console.WriteLine("Received packet from {0}", playerId); for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } PlayerConnection client = state.ClientManager.Connections [i]; Console.WriteLine("Client {0}, {1} sent a game packet while server in lobby", i, client.startedGame); allSendGame &= client.startedGame; //bitwise operater to check that every connection is ready } break; default: break; } } catch (TimeoutException e) { continue; } } sendHeartBeatPing.Enabled = false; GameState(socket, state, bridge); return; } else { Log.V("All players not ready"); } } }