/// ----------------------------------------------
        /// FUNCTION:		GameState
        ///
        /// DATE:			April 2 , 2019
        ///
        /// REVISIONS:
        ///
        /// DESIGNER:  Cameron Roberts, Kieran Lee
        ///
        /// PROGRAMMER: Cameron Roberts, Kieran Lee
        ///
        /// INTERFACE:      private static void GameState (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 while game is in progress
        ///                 Expect gameplay packets, discard all else.
        ///                 does initial game setup then
        ///                 receives and processes packets
        /// ----------------------------------------------
        private static void GameState(UDPSocket socket, State state, ServerStateMessageBridge bridge)
        {
            state.GameState.CollisionBuffer.requiredValidity = Math.Max((int)(state.ClientManager.CountCurrConnections * 0.8), 1);
            Console.WriteLine("set required validity to {0}", state.GameState.CollisionBuffer.requiredValidity);

            //give each player their starting ability
            for (int i = 0; i < state.GameState.CreatedPlayersCount; i++)
            {
                Player player     = (Player)state.GameState.actors [i];
                int    newSkillId = AbilityEffects.ReturnRandomAbilityId(player);
                state.GameState.OutgoingReliableElements.Enqueue(new AbilityAssignmentElement(i, newSkillId));
                player.AddAbility(1, (AbilityType)newSkillId);
            }

            //spawn test tower at 100,100
            state.GameState.AddTower(new GameUtility.Coordinate(355, 187));
            state.GameState.AddTower(new GameUtility.Coordinate(356, 302));
            state.GameState.AddTower(new GameUtility.Coordinate(150, 312));
            state.GameState.AddTower(new GameUtility.Coordinate(152, 193));

            // Fire Timer.Elapsed event every 1/30th second (sending Game State at 30 fps)
            StartGameStateTimer(socket, state);


            //Timer for keeping track of the game progress
            state.GameState.StartGamePlayTimer();

            while (state.TimesEndGameSent < 80)
            {
                if (!state.GameOver)
                {
                    try {
                        Packet packet = socket.Receive();
                        if (ReliableUDPConnection.GetPacketType(packet) != PacketType.GameplayPacket)
                        {
                            continue;
                        }
                        int actorId = ReliableUDPConnection.GetPlayerID(packet);
                        state.ClientManager.FindClientByActorId(actorId).MarkPacketReceive();

                        UnpackedPacket unpacked = state.ClientManager.FindClientByActorId(actorId).Connection.ProcessPacket(packet, unpackingArr);
                        ThreadPool.QueueUserWorkItem(ProcessIncomingPacket, unpacked);
                    } catch (Exception e) {
                        Console.WriteLine(e);
                        continue;
                    }
                }
            }
        }