Exemple #1
0
        /// <summary>
        /// Ping timer event to test the status of every client
        /// </summary>
        private void _pingTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            PacketBuilder pb        = new PacketBuilder(PacketFamily.CONNECTION, PacketAction.PING);
            DateTime      now       = DateTime.Now.ToUniversalTime();
            string        nowString = now.ToString("hh.mm.ss.ffffff");

            pb = pb.AddInt(nowString.Length).AddString(nowString);

            List <Client> disconnectedClients = new List <Client>();

            lock (Clients)
            {
                foreach (Client client in Clients)
                {
                    //if we're still waiting from 10s ago for the pong from the client
                    if (client.NeedPong)
                    {
                        //we add it to the list to be terminated
                        disconnectedClients.Add(client);
                    }
                    else
                    {
                        //if we received the last pong that we need, we're going to send another ping
                        client.Send(pb.Build());
                        client.NeedPong = true;
                    }
                }
            }

            //removing every client that failed to check in with the server
            foreach (Client client in disconnectedClients)
            {
                client.Stop();
            }
        }
Exemple #2
0
        private void _enemyUpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            foreach (Enemy enemy in Enemies)
            {
                //if the enemy moved
                if (enemy.IdleMove())
                {
                    PacketBuilder pb = new PacketBuilder(PacketFamily.ENEMY, PacketAction.MOVE);
                    pb = pb.AddInt(Enemies.IndexOf(enemy))
                         .AddInt(enemy.X)
                         .AddInt(enemy.Y)
                         .AddByte((byte)enemy.Facing);

                    //notify every client that the enemy has moved
                    lock (Clients)
                    {
                        foreach (Client client in Clients)
                        {
                            if (client.Account != null && client.Account.State == AccountState.Playing)
                            {
                                client.Send(pb.Build());
                            }
                        }
                    }
                }
            }
        }
Exemple #3
0
        public void Announce(string message)
        {
            PacketBuilder pb = new PacketBuilder(PacketFamily.SERVER, PacketAction.TALK);

            pb = pb.AddInt(message.Length)
                 .AddString(message);
            foreach (Client client in Clients)
            {
                client.Send(pb.Build());
            }
        }
Exemple #4
0
        /// <summary>
        /// Method to handle logging out of the character
        /// </summary>
        /// <param name="character">Character to be logged out</param>
        public void LogOut(PlayerCharacter character)
        {
            //saves the character state
            character.Save(_database);
            character.ServerID = 0;
            PacketBuilder pb = new PacketBuilder(PacketFamily.PLAYER, PacketAction.LOGOUT);

            pb = pb.AddInt(character.ServerID);
            foreach (Client client in _server.Clients)
            {
                if (client.Socket.Connected)
                {
                    //lets all the connected clients know that this character has logged out
                    if (client != this)
                    {
                        client.Send(pb.Build());
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// The purpose of this function is to provide one area where the packet data can be handled.
        /// I was looking to improve this approach by giving each packet its own class that handles
        /// that type of packet. That would improve the clarity of this class.
        /// </summary>
        /// <param name="pkt">The packet to be handled</param>
        private void HandlePacket(Packet pkt)
        {
            try
            {
                //packet builder for the return packet
                PacketBuilder pb;
                if (pkt.Family == PacketFamily.LOGIN)
                {
                    if (pkt.Action == PacketAction.REQUEST)
                    {
                        //login request
                        string user = pkt.ReadString(pkt.ReadByte());
                        string pass = pkt.ReadString(pkt.ReadByte());
                        pass = Utils.Security.GetHashString(pass + "PROCO304" + user);
                        CheckLogin(user, pass);
                    }
                }
                else if (pkt.Family == PacketFamily.CHARACTER)
                {
                    if (pkt.Action == PacketAction.CREATE)
                    {
                        //for character creation, the first thing we must do is get the requested name
                        string characterName = pkt.ReadString(pkt.ReadByte());
                        //and then the requested gender
                        byte gender = pkt.ReadByte();
                        //and initialise whether the name is available or not
                        bool isAvailable = true;

                        foreach (Account account in _server.Accounts)
                        {
                            foreach (Character c in account.Characters)
                            {
                                //loop through every character known to the server
                                if (c.Name == characterName)
                                {
                                    //if the name already exists, then the requested name cannot be used
                                    isAvailable = false;
                                    break;
                                }
                            }
                        }

                        if (!isAvailable)
                        {
                            //relay back to the client to tell them that the name for the character already exists
                            pb = new PacketBuilder(PacketFamily.CHARACTER, PacketAction.ALREADY_EXISTS);
                            string errMsg = "Character already exists";
                            pb = pb.AddByte((byte)errMsg.Length).AddString(errMsg);
                            Send(pb.Build());
                        }
                        else
                        {
                            //if they can have the requested character name then we add it to the collection of characters
                            PlayerCharacter character = new PlayerCharacter()
                            {
                                Name         = characterName,
                                Dexterity    = 0,
                                Strength     = 0,
                                Vitality     = 0,
                                Intelligence = 0,
                                Gender       = (Gender)gender,
                                Facing       = 0,
                                EXP          = 0,
                                Health       = 50,
                                Level        = 0,
                                X            = 0,
                                Y            = 0
                            };
                            //and let the client know that they have been accepted
                            pb = new PacketBuilder(PacketFamily.CHARACTER, PacketAction.CREATED);
                            pb = pb.AddByte((byte)characterName.Length)
                                 .AddString(characterName)
                                 .AddByte((byte)character.Gender);
                            Send(pb.Build());
                            Account.Characters.Add(character);
                            //save the new character to the database also
                            character.CreateDatabaseEntry(_database, Account.Username);
                            //and then put it out to the server console
                            Logger.Log("Character Created. Name: " + character.Name);
                        }
                    }
                    else if (pkt.Action == PacketAction.DELETE)
                    {
                        int             userid = pkt.ReadByte();
                        PlayerCharacter player = Account.GetCharacter(userid);
                        foreach (Account account in _server.Accounts)
                        {
                            PlayerCharacter toRemove = null;
                            foreach (PlayerCharacter character in account.Characters)
                            {
                                if (character.Name == player.Name)
                                {
                                    toRemove = character;
                                }
                            }
                            if (toRemove != null)
                            {
                                account.Characters.Remove(toRemove);
                            }
                        }

                        player.Delete(_database);
                        Account.Characters.Remove(player);
                        Send(pkt);
                    }
                }
                else if (pkt.Family == PacketFamily.REGISTER)
                {
                    if (pkt.Action == PacketAction.REQUEST)
                    {
                        //registering to the game
                        //getting the username
                        string username = pkt.ReadString(pkt.ReadByte());
                        //getting the password
                        string password = pkt.ReadString(pkt.ReadByte());
                        //hashing the given password using the username and "PROCO304" as the salt
                        password = Utils.Security.GetHashString(password + "PROCO304" + username);
                        //read the given email
                        string email = pkt.ReadString(pkt.ReadByte());
                        //and the given name
                        string fullname = pkt.ReadString(pkt.ReadByte());
                        //output the requested account to the server console
                        Logger.Log(String.Format("Requested username {0} password {1} email {2}", username, password, email));
                        //initiate the test to see if the account username already exists
                        bool userExists = false;
                        foreach (Account account in _server.Accounts)
                        {
                            if (account.Username == username)
                            {
                                //if the requested account name already exists in the known acccounts list then we need to reject the request
                                //and post back to the client to tell them that the username is already taken.
                                pb = new PacketBuilder(PacketFamily.REGISTER, PacketAction.REJECT);
                                string errMsg = "User already exists";
                                pb = pb.AddByte((byte)errMsg.Length).AddString(errMsg);
                                Send(pb.Build());
                                userExists = true;
                                break;
                            }
                        }

                        if (!userExists)
                        {
                            //if the account isn't already taken then we can accept the registration request,
                            //create the new entry in the database and report back to the client to tell them that
                            //their account is ready to go
                            pb = new PacketBuilder(PacketFamily.REGISTER, PacketAction.ACCEPT);
                            pb = pb.AddByte((byte)username.Length).AddString(username);
                            Send(pb.Build());
                            Account account = new Account(username, password, email, fullname);
                            _server.Accounts.Add(account);
                            account.CreateDatabaseEntry(_database, Socket.Client.RemoteEndPoint.ToString().Split(":")[0]);
                            Logger.Log("Account Created. Username: "******" has gained " + enemy.EXP + " EXP");
                                    }

                                    enemy.Contributors = new List <PlayerCharacter>();

                                    //reset position
                                    enemy.X      = enemy.SpawnX + RNG.Next(-300, 300);
                                    enemy.Y      = enemy.SpawnY + RNG.Next(-300, 300);
                                    enemy.Health = enemy.MaxHealth;
                                    //let all clients know of new poisition
                                    pb = new PacketBuilder(PacketFamily.ENEMY, PacketAction.MOVE);
                                    pb = pb.AddInt(_server.Enemies.IndexOf(enemy))
                                         .AddInt(enemy.X)
                                         .AddInt(enemy.Y)
                                         .AddByte((byte)enemy.Facing);
                                    foreach (Client client in _server.Clients)
                                    {
                                        client.Send(pb.Build());
                                    }
                                }

                                //notify all clients of new enemy hp
                                pb = new PacketBuilder(PacketFamily.ENEMY, PacketAction.TAKE_DAMAGE)
                                     .AddInt(_server.Enemies.IndexOf(enemy))
                                     .AddInt(enemy.Health);
                                foreach (Client client in _server.Clients)
                                {
                                    client.Send(pb.Build());
                                }
                            }
                        }
                    }
                }
                else if (pkt.Family == PacketFamily.CONNECTION)
                {
                    if (pkt.Action == PacketAction.PONG)
                    {
                        //Good client, responded to the PING request. We no longer need the pong.
                        NeedPong = false;
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Warn("Packet handling error. Remote endpoint: "
                            + Socket.Client.RemoteEndPoint + "\n\r StackTrace:" + e.StackTrace + "\n\r Message:" + e.Message);
            }
        }
Exemple #6
0
        public override void Update(GameTime gameTime)
        {
            _pingLabel.Update(gameTime);
            _camera.Update(gameTime);
            if (_characterSprites.Count > 0 && _camera.Focus != _characterSprites[0])
            {
                _camera.Focus = _characterSprites[0];
            }

            _thisPlayer.PlayerCharacter.IsAttacking = false;

            bool moved = false;

            if (!_txtIn.HasFocus)
            {
                //handling directional input
                if (Keyboard.GetState().IsKeyDown(Keys.A))
                {
                    _characterSprites[0].PlayerCharacter.X -= 1; _characterSprites[0].PlayerCharacter.Facing = Common.Enums.Direction.LEFT; moved = true;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.S))
                {
                    _characterSprites[0].PlayerCharacter.Y += 1; _characterSprites[0].PlayerCharacter.Facing = Common.Enums.Direction.DOWN; moved = true;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.D))
                {
                    _characterSprites[0].PlayerCharacter.X += 1; _characterSprites[0].PlayerCharacter.Facing = Common.Enums.Direction.RIGHT; moved = true;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.W))
                {
                    _characterSprites[0].PlayerCharacter.Y -= 1; _characterSprites[0].PlayerCharacter.Facing = Common.Enums.Direction.UP; moved = true;
                }
                else if (Keyboard.GetState().IsKeyUp(Keys.Enter) && _enterDown)
                {
                    _txtIn.HasFocus = true;
                }


                if (Mouse.GetState().LeftButton == ButtonState.Pressed)
                {
                    attackTimer += gameTime.ElapsedGameTime.Milliseconds;
                    if (attackTimer > 500)
                    {
                        //sending attack command to the server, every 500 ms
                        PacketBuilder pb = new PacketBuilder(PacketFamily.PLAYER, PacketAction.ATTACK);
                        pb.AddInt(_gameClient.CharacterID);
                        GameClient.NetClient.Send(pb.Build());
                        attackTimer = 0;
                        _thisPlayer.PlayerCharacter.IsAttacking = true;
                    }
                }
                else
                {
                    attackTimer = 0;
                }

                // This is in place to stop server spam, otherwise every time the sprite is updated
                // it will send the server the characters x and y (Many times a second)
                if (moved)
                {
                    PacketBuilder pb = new PacketBuilder(PacketFamily.PLAYER, PacketAction.MOVE);
                    pb = new PacketBuilder(PacketFamily.PLAYER, PacketAction.MOVE)
                         .AddInt(_characterSprites[0].PlayerCharacter.X)
                         .AddInt(_characterSprites[0].PlayerCharacter.Y)
                         .AddByte((byte)_characterSprites[0].PlayerCharacter.Facing)
                         .AddInt(_gameClient.CharacterID);
                    GameClient.NetClient.Send(pb.Build());

                    _serverNotifiedOfIdle = false;
                }
                //now we're settled and if the server doesn't know we've stopped we want to tell it that we have
                else if (!_serverNotifiedOfIdle)
                {
                    PacketBuilder pb = new PacketBuilder(PacketFamily.PLAYER, PacketAction.STOP)
                                       .AddInt(_characterSprites[0].PlayerCharacter.X)
                                       .AddInt(_characterSprites[0].PlayerCharacter.Y)
                                       .AddByte((byte)_characterSprites[0].PlayerCharacter.Facing)
                                       .AddInt(_gameClient.CharacterID);
                    GameClient.NetClient.Send(pb.Build());
                    _serverNotifiedOfIdle = true;
                }
            }
            else
            {
                if (Keyboard.GetState().IsKeyUp(Keys.Enter) && _enterDown)
                {
                    if (_txtIn.Text != "")
                    {
                        //sending a chat message to the server
                        PacketBuilder pb = new PacketBuilder(PacketFamily.PLAYER, PacketAction.TALK);
                        pb = pb.AddInt(_txtIn.Text.Length)
                             .AddString(_txtIn.Text)
                             .AddInt(_gameClient.CharacterID);
                        GameClient.NetClient.Send(pb.Build());
                        //debugging command to test health bars, will be removed if game goes live
                        if (_txtIn.Text.Split(' ')[0] == "SetHP")
                        {
                            _characterSprites[0].PlayerCharacter.Health = Convert.ToInt32(_txtIn.Text.Split(' ')[1]);
                        }
                        _txtIn.Text = "";
                    }
                    _txtIn.HasFocus = false;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                {
                    _txtIn.HasFocus = false;
                }
            }

            _characterSprites[0].PlayerCharacter.IsIdle    = !moved;
            _characterSprites[0].PlayerCharacter.IsWalking = moved;

            foreach (PlayerCharacterSprite characterSprite in _characterSprites)
            {
                characterSprite.Update(gameTime, _camera);
            }

            foreach (EnemySprite enemySprite in _enemySprites)
            {
                enemySprite.Update(gameTime, _camera);
            }

            foreach (Label lbl in _lblMessages)
            {
                lbl.Update(gameTime);
            }
            _enterDown = Keyboard.GetState().IsKeyDown(Keys.Enter);
            _txtIn.Update(gameTime);
            base.Update(gameTime);
        }
Exemple #7
0
        public void Main()
        {
            while (ShouldReceive)
            {
                try
                {
                    if (Stream == null)
                    {
                        return;
                    }

                    //the main function that receives packet data
                    byte[] buffer    = new byte[2];
                    int    readTotal = 0;
                    //reading the length of the packet
                    Stream.Read(buffer, 0, 2);
                    if (buffer[0] == 0)
                    {
                        continue;
                    }

                    byte length = buffer[0];
                    if (length < 2 && PACKET_DEBUG)
                    {
                        //we're not interested in any packets less than 2.
                        //Could happen if a client other than a DansWorld client tries to connect.
                        Logger.Error("Packet of length less than 2 received");
                        continue;
                    }

                    //initiating a new byte array of the packet length
                    byte[] data = new byte[length];

                    //while there's still data to read
                    while (readTotal < length)
                    {
                        //filling the byte array with the data read from the stream
                        int read = Stream.Read(data, 0, length);
                        if (read == 0 && PACKET_DEBUG)
                        {
                            Logger.Warn("Packet seems empty..");
                            return;
                        }
                        readTotal += read;
                    }

                    StringBuilder sb = new StringBuilder();
                    sb.Append("Packet Data: ");
                    for (int i = 0; i < data.Length; i++)
                    {
                        sb.Append("{" + data[i] + "} ");
                    }

                    if (PACKET_DEBUG)
                    {
                        Logger.Log(sb.ToString());
                    }

                    //building up the received packet data using the received byte array
                    PacketBuilder pb  = new PacketBuilder().AddBytes(data);
                    Packet        pkt = pb.Build();

                    //if we have an accepted login packet
                    if (pkt.Family == PacketFamily.LOGIN)
                    {
                        if (pkt.Action == PacketAction.ACCEPT)
                        {
                            //debug output
                            _gameClient.DisplayMessage("Login accepted");
                            //we're going to set the state of the client to logged in
                            _gameClient.SetState(GameExecution.GameState.LoggedIn);
                            //while we still have players to read the data of
                            while (pkt.ReadPosition < pkt.RawData.Length)
                            {
                                int nameLength = pkt.ReadByte();
                                if (nameLength > 0)
                                {
                                    PlayerCharacter c = new PlayerCharacter()
                                    {
                                        Name   = pkt.ReadString(nameLength),
                                        Level  = pkt.ReadByte(),
                                        Gender = (Gender)pkt.ReadByte()
                                    };
                                    _gameClient.AddPlayerCharacter(c);
                                }
                            }
                        }
                        else
                        {
                            //if the login wasn't accepted, the person should get the reason as to why
                            _gameClient.DisplayMessage(pkt.ReadString(pkt.Length - 2));
                        }
                    }
                    else if (pkt.Family == PacketFamily.REGISTER)
                    {
                        if (pkt.Action == PacketAction.ACCEPT)
                        {
                            //registration was complete, we can now go back to the main menu to log in to the created account
                            _gameClient.SetState(GameExecution.GameState.MainMenu);
                            _gameClient.DisplayMessage("Account created! Username: "******"" : p.Name));
                        }
                    }
                    //server sent an announcement
                    else if (pkt.Family == PacketFamily.SERVER)
                    {
                        if (pkt.Action == PacketAction.TALK)
                        {
                            string message = pkt.ReadString(pkt.ReadInt());
                            _gameClient.DisplayMessage(message, "SERVER");
                        }
                    }
                    //if we got a ping request, we'll send back a pong request to satisfy the server
                    else if (pkt.Family == PacketFamily.CONNECTION)
                    {
                        if (pkt.Action == PacketAction.PING)
                        {
                            PacketBuilder pBuilder   = new PacketBuilder(PacketFamily.CONNECTION, PacketAction.PONG);
                            DateTime      now        = DateTime.Now.ToUniversalTime();
                            DateTime      fromServer = DateTime.ParseExact(pkt.ReadString(pkt.ReadInt()), "hh.mm.ss.ffffff", CultureInfo.InvariantCulture);
                            TimeSpan      t          = now.Subtract(fromServer);
                            string        nowString  = now.ToShortTimeString();
                            pBuilder = pBuilder.AddInt(nowString.Length).AddString(nowString);
                            Send(pBuilder.Build());
                            _gameClient.ShowPing(t.Milliseconds);
                        }
                    }
                    else if (pkt.Family == PacketFamily.ENEMY)
                    {
                        //an enemy has been added to the game
                        if (pkt.Action == PacketAction.WELCOME)
                        {
                            Enemy enemy = new Enemy();
                            enemy.ID        = pkt.ReadInt();
                            enemy.Name      = pkt.ReadString(pkt.ReadByte());
                            enemy.Facing    = (Direction)pkt.ReadByte();
                            enemy.X         = pkt.ReadInt();
                            enemy.Y         = pkt.ReadInt();
                            enemy.Vitality  = pkt.ReadInt();
                            enemy.Level     = pkt.ReadByte();
                            enemy.MaxHealth = pkt.ReadInt();
                            enemy.Health    = pkt.ReadInt();
                            enemy.SpriteID  = pkt.ReadInt();
                            enemy.ServerID  = pkt.ReadByte();
                            _gameClient.AddEnemy(enemy);
                        }
                        //an enemy moved
                        else if (pkt.Action == PacketAction.MOVE)
                        {
                            int  id     = pkt.ReadInt();
                            int  x      = pkt.ReadInt();
                            int  y      = pkt.ReadInt();
                            byte facing = pkt.ReadByte();
                            foreach (Enemy enemy in _gameClient.GetEnemies())
                            {
                                if (enemy.ServerID == id)
                                {
                                    enemy.X      = x;
                                    enemy.Y      = y;
                                    enemy.Facing = (Direction)facing;
                                    break;
                                }
                            }
                        }
                        //an enemy took damage
                        else if (pkt.Action == PacketAction.TAKE_DAMAGE)
                        {
                            int id = pkt.ReadInt();
                            int hp = pkt.ReadInt();

                            foreach (Enemy enemy in _gameClient.GetEnemies())
                            {
                                if (enemy.ID == id)
                                {
                                    enemy.Health = hp;
                                    break;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e.Message + " Stack " + e.StackTrace);
                    continue;
                }
            }
        }