예제 #1
0
        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");
                }
            }
        }