Example #1
0
        // This will Handle the initial connection setup and Heartbeats of a client
        private void _handleConnectionSetup(PlayerInfo player, NetworkMessage message)
        {
            // Make sure the message is from the correct client provided
            bool sentByPlayer = message.Sender.Equals(player.Endpoint);

            if (sentByPlayer)
            {
                // Record the last time we've heard from them
                player.LastPacketReceivedTime = message.ReceiveTime;

                // Do they need their Side? or a heartbeat ACK
                switch (message.Packet.Type)
                {
                case PacketType.RequestJoin:
                    Console.WriteLine("[{0:000}] Join Request from {1}", Id, player.Endpoint);
                    _sendAcceptJoin(player);
                    break;

                case PacketType.AcceptJoinAck:
                    // They acknowledged (they will send heartbeats until game start)
                    player.HavePaddle = true;
                    break;

                case PacketType.Heartbeat:
                    // They are waiting for the game start, Respond with an ACK
                    HeartbeatAckPacket hap = new HeartbeatAckPacket();
                    _sendTo(player, hap);

                    // Incase their ACK didn't reach us
                    if (!player.HavePaddle)
                    {
                        _sendAcceptJoin(player);
                    }

                    break;
                }
            }
        }
Example #2
0
        // This runs in its own Thread
        // It is the actual game
        private void _arenaRun()
        {
            Console.WriteLine("[{0:000}] Waiting for players", Id);
            GameTime gameTime = new GameTime();

            // Varibables used in the switch
            TimeSpan notifyGameStartTimeout = TimeSpan.FromSeconds(2.5);
            TimeSpan sendGameStateTimeout   = TimeSpan.FromMilliseconds(1000f / 30f); // How often to update the players

            // The loop
            bool running       = true;
            bool playerDropped = false;

            while (running)
            {
                // Pop off a message (if there is one)
                NetworkMessage message;
                bool           haveMsg = _messages.TryDequeue(out message);

                switch (State.Value)
                {
                case ArenaState.WaitingForPlayers:
                    if (haveMsg)
                    {
                        // Wait until we have two players
                        _handleConnectionSetup(LeftPlayer, message);
                        _handleConnectionSetup(RightPlayer, message);

                        // Check if we are ready or not
                        if (LeftPlayer.HavePaddle && RightPlayer.HavePaddle)
                        {
                            // Try sending the GameStart packet immediately
                            _notifyGameStart(LeftPlayer, new TimeSpan());
                            _notifyGameStart(RightPlayer, new TimeSpan());

                            // Shift the state
                            State.Value = ArenaState.NotifyingGameStart;
                        }
                    }
                    break;

                case ArenaState.NotifyingGameStart:
                    // Try sending the GameStart packet
                    _notifyGameStart(LeftPlayer, notifyGameStartTimeout);
                    _notifyGameStart(RightPlayer, notifyGameStartTimeout);

                    // Check for ACK
                    if (haveMsg && (message.Packet.Type == PacketType.GameStartAck))
                    {
                        // Mark true for those who have sent something
                        if (message.Sender.Equals(LeftPlayer.Endpoint))
                        {
                            LeftPlayer.Ready = true;
                        }
                        else if (message.Sender.Equals(RightPlayer.Endpoint))
                        {
                            RightPlayer.Ready = true;
                        }
                    }

                    // Are we ready to send/received game data?
                    if (LeftPlayer.Ready && RightPlayer.Ready)
                    {
                        // Initlize some game object positions
                        _ball.Initialize();
                        LeftPlayer.Paddle.Initialize();
                        RightPlayer.Paddle.Initialize();

                        // Send a basic game state
                        _sendGameState(LeftPlayer, new TimeSpan());
                        _sendGameState(RightPlayer, new TimeSpan());

                        // Start the game timer
                        State.Value = ArenaState.InGame;
                        Console.WriteLine("[{0:000}] Starting Game", Id);
                        _gameTimer.Start();
                    }

                    break;

                case ArenaState.InGame:
                    // Update the game timer
                    TimeSpan now = _gameTimer.Elapsed;
                    gameTime = new GameTime(now, now - gameTime.TotalGameTime);

                    // Get paddle postions from clients
                    if (haveMsg)
                    {
                        switch (message.Packet.Type)
                        {
                        case PacketType.PaddlePosition:
                            _handlePaddleUpdate(message);
                            break;

                        case PacketType.Heartbeat:
                            // Respond with an ACK
                            HeartbeatAckPacket hap    = new HeartbeatAckPacket();
                            PlayerInfo         player = message.Sender.Equals(LeftPlayer.Endpoint) ? LeftPlayer : RightPlayer;
                            _sendTo(player, hap);

                            // Record time
                            player.LastPacketReceivedTime = message.ReceiveTime;
                            break;
                        }
                    }

                    //Update the game components
                    _ball.ServerSideUpdate(gameTime);
                    _checkForBallCollisions();

                    // Send the data
                    _sendGameState(LeftPlayer, sendGameStateTimeout);
                    _sendGameState(RightPlayer, sendGameStateTimeout);
                    break;
                }

                // Check for a quit from one of the clients
                if (haveMsg && (message.Packet.Type == PacketType.Bye))
                {
                    // Well, someone dropped
                    PlayerInfo player = message.Sender.Equals(LeftPlayer.Endpoint) ? LeftPlayer : RightPlayer;
                    running = false;
                    Console.WriteLine("[{0:000}] Quit detected from {1} at {2}",
                                      Id, player.Paddle.Side, _gameTimer.Elapsed);

                    // Tell the other one
                    if (player.Paddle.Side == PaddleSide.Left)
                    {
                        // Left Quit, tell Right
                        if (RightPlayer.IsSet)
                        {
                            _server.SendBye(RightPlayer.Endpoint);
                        }
                    }
                    else
                    {
                        // Right Quit, tell Left
                        if (LeftPlayer.IsSet)
                        {
                            _server.SendBye(LeftPlayer.Endpoint);
                        }
                    }
                }

                // Check for timeouts
                playerDropped |= _timedOut(LeftPlayer);
                playerDropped |= _timedOut(RightPlayer);

                // Small nap
                Thread.Sleep(1);

                // Check quit values
                running &= !_stopRequested.Value;
                running &= !playerDropped;
            }

            // End the game
            _gameTimer.Stop();
            State.Value = ArenaState.GameOver;
            Console.WriteLine("[{0:000}] Game Over, total game time was {1}", Id, _gameTimer.Elapsed);

            // If the stop was requested, gracefully tell the players to quit
            if (_stopRequested.Value)
            {
                Console.WriteLine("[{0:000}] Notifying Players of server shutdown", Id);

                if (LeftPlayer.IsSet)
                {
                    _server.SendBye(LeftPlayer.Endpoint);
                }
                if (RightPlayer.IsSet)
                {
                    _server.SendBye(RightPlayer.Endpoint);
                }
            }

            // Tell the server that we're finished
            _server.NotifyDone(this);
        }