Ejemplo n.º 1
0
        private void OnJoin(Packet packet)
        {
            //TODO: Use all fields.

            var characterId  = packet.ReadInt32();
            var patchVersion = packet.ReadByte();
            var hdInfo       = packet.ReadString();

            Character = User.Characters.FirstOrDefault(c => c.Id == characterId);

            if (Character != null)
            {
                Console.WriteLine(Character.GetHashCode());

                InventoryItems = new ItemContainer <InventoryItem>(Character, Character.InventoryItems, (byte)Define.MAX_INVENTORY, (byte)Define.MAX_HUMAN_PARTS, Constants.InventorySlots);
                QuestItems     = new ItemContainer <QuestItem>(Character, Character.QuestItems, (byte)Define.MAX_INVENTORY, 0, Constants.QuestSlots);

                StorageItems = new ItemContainer <StorageItem>(Character, Character.StorageItems, 0, 0, new byte[] { });                //TODO: Implement storage items.

                var response = new Packet(Opcode.JOIN_RIGHT);

                response.WriteInt32(characterId);

                response.WriteInt32(Character.WorldId);
                response.WritePosition(Character.Position);

                response.WriteBoolean(false);           //Is festival
                response.WriteInt32(0);                 //Festival 'yday'

                Send(response);

                var joinSnapshot = new Snapshot();

                joinSnapshot.SetType(SnapshotType.UPDATE_SERVER_TIME);
                joinSnapshot.WriteInt32(DateTime.UtcNow.GetUnixTimestamp());

                WriteObjectData(joinSnapshot, Character, true);

                Send(joinSnapshot);

                var spawnNearPlayers = new Snapshot();
                foreach (var player in NearPlayers)
                {
                    WriteObjectData(spawnNearPlayers, player.Character);
                }

                Send(spawnNearPlayers);

                var spawnNewPlayer = new Snapshot();
                WriteObjectData(spawnNewPlayer, Character);

                SendNearPlayers(spawnNewPlayer);
            }
            else
            {
                //NOTE: In theory, it's possible to send JOIN_ERROR and an error code, but the client doesn't seem to use it.

                Disconnect();
            }
        }
Ejemplo n.º 2
0
        private void OnJoin(Packet packet)
        {
            //TODO: Use all fields.

            var characterId = packet.ReadInt32();
            var patchVersion = packet.ReadByte();
            var hdInfo = packet.ReadString();

            Character = User.Characters.FirstOrDefault(c => c.Id == characterId);

            if (Character != null)
            {
                Console.WriteLine(Character.GetHashCode());

                InventoryItems = new ItemContainer<InventoryItem>(Character, Character.InventoryItems, (byte) Define.MAX_INVENTORY, (byte) Define.MAX_HUMAN_PARTS, Constants.InventorySlots);
                QuestItems = new ItemContainer<QuestItem>(Character, Character.QuestItems, (byte) Define.MAX_INVENTORY, 0, Constants.QuestSlots);

                StorageItems = new ItemContainer<StorageItem>(Character, Character.StorageItems, 0, 0, new byte[] { }); //TODO: Implement storage items.

                var response = new Packet(Opcode.JOIN_RIGHT);

                response.WriteInt32(characterId);

                response.WriteInt32(Character.WorldId);
                response.WritePosition(Character.Position);

                response.WriteBoolean(false); //Is festival
                response.WriteInt32(0); //Festival 'yday'

                Send(response);

                var joinSnapshot = new Snapshot();

                joinSnapshot.SetType(SnapshotType.UPDATE_SERVER_TIME);
                joinSnapshot.WriteInt32(DateTime.UtcNow.GetUnixTimestamp());

                WriteObjectData(joinSnapshot, Character, true);

                Send(joinSnapshot);

                var spawnNearPlayers = new Snapshot();
                foreach (var player in NearPlayers)
                    WriteObjectData(spawnNearPlayers, player.Character);

                Send(spawnNearPlayers);

                var spawnNewPlayer = new Snapshot();
                WriteObjectData(spawnNewPlayer, Character);

                SendNearPlayers(spawnNewPlayer);
            }
            else
            {
                //NOTE: In theory, it's possible to send JOIN_ERROR and an error code, but the client doesn't seem to use it.

                Disconnect();
            }
        }
Ejemplo n.º 3
0
 public static void Serialize(this Item item, Packet packet)
 {
     packet.WriteByte(item.Slot);
     packet.WriteInt32(item.ItemId);
     packet.WriteUInt32(0x00000000); //EC D9 14 91  (Serial Number)
     packet.WriteX(item.StackSize);
     packet.WriteX(0);               //CF 46 00 00  (Hitpoints => Current Durability?)
     packet.WriteX(0);               //18 47 00 00  (Maximum Hitpoints => Maximum Durability?)
     packet.WriteUInt32(0x00000000); //00 00 00 00  (Word => ?)
     packet.WriteByte(0x00);         //00  (Ability Option => ?)
     packet.WriteByte(0x00);         //00  (Item Resistance => ?)
     packet.WriteByte(0x00);         //00  (Resistance Ability Option => ?)
     packet.WriteX(0x00000000);      //00 00 00 00  (Keep Time)
     packet.WriteByte(0x00);         //00  (Item Lock)
     packet.WriteUInt32(0x00000000); //00 00 00 00  (Bind End Time)
     packet.WriteByte(0x00);         //00  (Stability => ?)
     packet.WriteByte(0x00);         //00  (Quality => ?)
     packet.WriteByte(0x00);         //00  (Ability Rate => ?)
     packet.WriteX(0);               //00 00 00 00  (Use Time => ?)
     packet.WriteX(0);               //00 00 00 00  (Buy 'tm' => Buy Time?)
     packet.WriteX(0);               //00 00 00 00  (Price => Sell/Buy?)
     packet.WriteX(0);               //00 00 00 00  (Pay 银币 => ?)
     packet.WriteX(0);               //00 00 00 00  (Free 银币 => ?)
     packet.WriteUInt32(Constants.ServerId);
     packet.WriteByte(0);            //Attributes
 }
Ejemplo n.º 4
0
        public void WriteTaskBarItems(Packet packet, List <TaskBarItem> items)
        {
            packet.WriteInt32(items.Count);

            foreach (var taskbarItem in items)
            {
                packet.WriteInt32(taskbarItem.Line);
                packet.WriteInt32(taskbarItem.Grid);

                packet.WriteInt32(taskbarItem.Shortcut);
                packet.WriteInt32(taskbarItem.ShortcutId);
                packet.WriteInt32(taskbarItem.Type);
                packet.WriteInt32(taskbarItem.Index);
                packet.WriteInt32(taskbarItem.UserId);
                packet.WriteInt32(taskbarItem.Data);
                packet.WriteString(taskbarItem.String);
            }
        }
Ejemplo n.º 5
0
        public void WriteTaskBarItems(Packet packet, List<TaskBarItem> items)
        {
            packet.WriteInt32(items.Count);

            foreach (var taskbarItem in items)
            {
                packet.WriteInt32(taskbarItem.Line);
                packet.WriteInt32(taskbarItem.Grid);

                packet.WriteInt32(taskbarItem.Shortcut);
                packet.WriteInt32(taskbarItem.ShortcutId);
                packet.WriteInt32(taskbarItem.Type);
                packet.WriteInt32(taskbarItem.Index);
                packet.WriteInt32(taskbarItem.UserId);
                packet.WriteInt32(taskbarItem.Data);
                packet.WriteString(taskbarItem.String);
            }
        }
Ejemplo n.º 6
0
        private void OnCertify(Packet packet)
        {
            var name     = packet.ReadString();
            var password = packet.ReadString();

            //TODO: Find out what all the unused fields are and use them.

            var hdsn        = packet.ReadString();
            var ipKey       = packet.ReadBytes(21);
            var version     = packet.ReadUInt32();
            var realVersion = packet.ReadUInt32();
            var opFlag      = packet.ReadByte();
            var otpPassword = packet.ReadString();

            var user = Database.Users.FirstOrDefault(c => c.Name == name);

            //TODO: Add ECard.

            if (user != null)
            {
                if (user.Password == password)
                {
                    if (!Server.Connections.Any(c => c.User != null && c.User.Name == user.Name))
                    {
                        if (realVersion == Constants.Version)
                        {
                            User = user;

                            var result = new Packet(Opcode.CERTIFYRESULT);
                            result.WriteInt32((int)Error.CERT_OK);
                            result.WriteInt32(0);                             //Not required to fill in real name.
                            result.WriteBoolean(false);                       //Expansion
                            Send(result);

                            CharacterList();
                        }
                        else
                        {
                            var result = new Packet(Opcode.CERTIFYRESULT);
                            result.WriteInt32((int)(realVersion < Constants.Version ? Error.ERR_VERSION_TOO_LOW : Error.ERR_VERSION_MAINTAIN));
                            Send(result);

                            Disconnect();
                        }
                    }
                    else
                    {
                        var result = new Packet(Opcode.CERTIFYRESULT);
                        result.WriteInt32((int)Error.ERR_ACCOUNT_EXIST);
                        Send(result);

                        Disconnect();
                    }
                }
                else
                {
                    var result = new Packet(Opcode.CERTIFYRESULT);
                    result.WriteInt32((int)((uint)Error.CERT_CHARGE_CERTIFY_FAILED << 16));
                    Send(result);
                }
            }
            else
            {
                var result = new Packet(Opcode.CERTIFYRESULT);
                result.WriteInt32((int)((uint)Error.CERT_CHARGE_CERTIFY_FAILED << 16 | 1));
                Send(result);
            }
        }
Ejemplo n.º 7
0
        private void OnCreatePlayer(Packet packet)
        {
            var result = new Packet(Opcode.CREATEPLAYERRESULT);

            var name = packet.ReadString();
            var hdHash = packet.ReadString();
            var slot = packet.ReadInt32();
            var job = packet.ReadByte();
            var gender = packet.ReadByte();
            var hairMesh = packet.ReadByte();
            var hairColor = packet.ReadUInt32();
            var headMesh = packet.ReadByte();
            var city = packet.ReadInt32();
            var zodiacSign = packet.ReadInt32();
            var country = packet.ReadByte();
            var snCard = packet.ReadString();
            var cardType = packet.ReadInt32();
            var hdSerialNumber = packet.ReadString();
            var binAccount = packet.ReadString();
            var clothList = new int[5];
            for (var i = 0; i < 5; i++)
                clothList[i] = packet.ReadInt32();

            if (!Constants.CharacterCreationEnabled)
            {
                result.WriteInt32((int) Error.ERR_NOCREATE_ALL);
            }
            else if (Database.Characters.Any(c => c.Name == name))
            {
                result.WriteInt32((int) Error.ERR_PLAYER_EXIST);
            }
            else if (User.Characters.Count(c => !c.Deleted && !c.Blocked) > 3 || User.Characters.Count > 10 || User.Characters.Any(c => c.Slot == slot)) //TODO: Check items.
            {
                result.WriteInt32((int) Error.ERR_NOCREATE);
            }
            else
            {
                var character = new Character
                {
                    Name = name,
                    Slot = slot,
                    Job = job,
                    Gender = gender,
                    Appearance = new CharacterAppearance
                    {
                        HairMesh = hairMesh,
                        HairColor = (int) hairColor,
                        HeadMesh = headMesh
                    },
                    PersonalInformation = new PersonalInformation
                    {
                        City = city,
                        ZodiacSign = zodiacSign
                    },
                    Closet = new Closet()
                };

                for (var i = 0; i < 5; i++)
                {
                    if (clothList[i] == 0) continue;

                    character.Closet.Items.Add(new ClosetItem
                                                 {
                                                     ItemId = clothList[i],
                                                     Index = i + 1,
                                                     DateTime = DateTime.UtcNow,
                                                     Equipped = true
                                                 });
                }

                User.Characters.Add(character);

                User.AcceptedAgreement = true;

                Database.SaveChanges(); //TODO: Fix this, shouldn't do a full DB update for this...

                result.WriteInt32((int) Error.ERR_SUCCESS);

                Send(result);

                var playerSlot = new Packet(Opcode.PLAYERSLOT);

                playerSlot.WriteInt32(character.Slot);

                playerSlot.WriteString(character.Name);
                playerSlot.WriteInt32(character.Id);

                playerSlot.WriteInt32(character.WorldId);
                playerSlot.WriteByte(character.Gender);
                playerSlot.WritePosition(character.Position);

                playerSlot.WriteInt32(character.Level);
                playerSlot.WriteInt32(character.Job);

                playerSlot.WriteInt32(character.Stats.STR);
                playerSlot.WriteInt32(character.Stats.STA);
                playerSlot.WriteInt32(character.Stats.DEX);
                playerSlot.WriteInt32(character.Stats.INT);
                playerSlot.WriteInt32(character.Stats.SPI);

                playerSlot.WriteInt32(character.Appearance.HairMesh);
                playerSlot.WriteUInt32((uint) character.Appearance.HairColor);
                playerSlot.WriteInt32(character.Appearance.HeadMesh);

                playerSlot.WriteInt32(character.Blocked ? 1 : 0);
                playerSlot.WriteInt32(character.BlockTime);

                //TODO: Clean this up.

                var container = new ItemContainer<InventoryItem>(character, character.InventoryItems, (byte) Define.MAX_INVENTORY, (byte) Define.MAX_HUMAN_PARTS, Constants.InventorySlots);

                var equipmentItems = container.EquippedItems.ToList();

                playerSlot.WriteInt32(equipmentItems.Count); //TODO: Implement non-fashion items.

                //  for i = 1, count do
                //    parts = LAr:ReadByte(ar)
                //    item_id = LAr:ReadDword(ar)
                //    flag = LAr:ReadDword(ar)
                //    attr = LAr:ReadInt(ar)
                //  end

                foreach (var fashionItem in character.Closet.Items.Where(item => item.Equipped))
                    playerSlot.WriteInt32(fashionItem.ItemId);

                playerSlot.WriteInt32(User.Characters.Count(c => c.Deleted));

                Send(playerSlot);

                return;
            }

            Send(result);
        }
Ejemplo n.º 8
0
        private void CharacterList()
        {
            var packet = new Packet(Opcode.PLAYERLIST);

            packet.WriteInt32(DateTime.UtcNow.GetUnixTimestamp());
            packet.WriteByte((byte) (User.AcceptedAgreement ? 0 : 1));

            var characters = User.Characters.Where(c => !c.Deleted && !c.Blocked).ToList();
            packet.WriteByte((byte) characters.Count);
            foreach (var character in characters)
            {
                packet.WriteInt32(character.Slot);

                packet.WriteString(character.Name);
                packet.WriteInt32(character.Id);

                packet.WriteInt32(character.WorldId);
                packet.WriteByte(character.Gender);
                packet.WritePosition(character.Position);

                packet.WriteInt32(character.Level);
                packet.WriteInt32(character.Job);

                packet.WriteInt32(character.Stats.STR);
                packet.WriteInt32(character.Stats.STA);
                packet.WriteInt32(character.Stats.DEX);
                packet.WriteInt32(character.Stats.INT);
                packet.WriteInt32(character.Stats.SPI);

                packet.WriteInt32(character.Appearance.HairMesh);
                packet.WriteUInt32((uint) character.Appearance.HairColor);
                packet.WriteInt32(character.Appearance.HeadMesh);

                packet.WriteInt32(character.Blocked ? 1 : 0);
                packet.WriteInt32(character.BlockTime);

                //TODO: Clean this up.

                var container = new ItemContainer<InventoryItem>(character, character.InventoryItems, (byte) Define.MAX_INVENTORY, (byte) Define.MAX_HUMAN_PARTS, Constants.InventorySlots);

                var equipmentItems = container.EquippedItems.ToList();

                packet.WriteInt32(equipmentItems.Count); //TODO: Implement non-fashion items.

                //  for i = 1, count do
                //    parts = LAr:ReadByte(ar)
                //    item_id = LAr:ReadDword(ar)
                //    flag = LAr:ReadDword(ar)
                //    attr = LAr:ReadInt(ar)
                //  end

                for(var i = 1; i <= 5; i++)
                {
                    var item = character.Closet.Items.FirstOrDefault(c => c.Equipped && c.Index == i);

                    packet.WriteInt32(item != null ? item.ItemId : 0);
                }
            }

            packet.WriteInt32(User.Characters.Count(c => c.Deleted));

            //TODO: Implement city/province.
            packet.WriteInt32(0); //City Id
            packet.WriteInt32(0); //Province Id

            packet.WriteSByte(20); //TODO: Find out what this is.

            Send(packet);
        }
Ejemplo n.º 9
0
        private void OnCertify(Packet packet)
        {
            var name = packet.ReadString();
            var password = packet.ReadString();

            //TODO: Find out what all the unused fields are and use them.

            var hdsn = packet.ReadString();
            var ipKey = packet.ReadBytes(21);
            var version = packet.ReadUInt32();
            var realVersion = packet.ReadUInt32();
            var opFlag = packet.ReadByte();
            var otpPassword = packet.ReadString();

            var user = Database.Users.FirstOrDefault(c => c.Name == name);

            //TODO: Add ECard.

            if (user != null)
            {
                if(user.Password == password)
                {
                    if (!Server.Connections.Any(c => c.User != null && c.User.Name == user.Name))
                    {
                        if (realVersion == Constants.Version)
                        {
                            User = user;

                            var result = new Packet(Opcode.CERTIFYRESULT);
                            result.WriteInt32((int) Error.CERT_OK);
                            result.WriteInt32(0); //Not required to fill in real name.
                            result.WriteBoolean(false); //Expansion
                            Send(result);

                            CharacterList();
                        }
                        else
                        {
                            var result = new Packet(Opcode.CERTIFYRESULT);
                            result.WriteInt32((int) (realVersion < Constants.Version ? Error.ERR_VERSION_TOO_LOW : Error.ERR_VERSION_MAINTAIN));
                            Send(result);

                            Disconnect();
                        }
                    }
                    else
                    {
                        var result = new Packet(Opcode.CERTIFYRESULT);
                        result.WriteInt32((int) Error.ERR_ACCOUNT_EXIST);
                        Send(result);

                        Disconnect();
                    }
                }
                else
                {
                    var result = new Packet(Opcode.CERTIFYRESULT);
                    result.WriteInt32((int) ((uint) Error.CERT_CHARGE_CERTIFY_FAILED << 16));
                    Send(result);
                }
            }
            else
            {
                var result = new Packet(Opcode.CERTIFYRESULT);
                result.WriteInt32((int) ((uint)Error.CERT_CHARGE_CERTIFY_FAILED << 16 | 1));
                Send(result);
            }
        }
Ejemplo n.º 10
0
        private void OnCreatePlayer(Packet packet)
        {
            var result = new Packet(Opcode.CREATEPLAYERRESULT);

            var name           = packet.ReadString();
            var hdHash         = packet.ReadString();
            var slot           = packet.ReadInt32();
            var job            = packet.ReadByte();
            var gender         = packet.ReadByte();
            var hairMesh       = packet.ReadByte();
            var hairColor      = packet.ReadUInt32();
            var headMesh       = packet.ReadByte();
            var city           = packet.ReadInt32();
            var zodiacSign     = packet.ReadInt32();
            var country        = packet.ReadByte();
            var snCard         = packet.ReadString();
            var cardType       = packet.ReadInt32();
            var hdSerialNumber = packet.ReadString();
            var binAccount     = packet.ReadString();
            var clothList      = new int[5];

            for (var i = 0; i < 5; i++)
            {
                clothList[i] = packet.ReadInt32();
            }

            if (!Constants.CharacterCreationEnabled)
            {
                result.WriteInt32((int)Error.ERR_NOCREATE_ALL);
            }
            else if (Database.Characters.Any(c => c.Name == name))
            {
                result.WriteInt32((int)Error.ERR_PLAYER_EXIST);
            }
            else if (User.Characters.Count(c => !c.Deleted && !c.Blocked) > 3 || User.Characters.Count > 10 || User.Characters.Any(c => c.Slot == slot))             //TODO: Check items.
            {
                result.WriteInt32((int)Error.ERR_NOCREATE);
            }
            else
            {
                var character = new Character
                {
                    Name       = name,
                    Slot       = slot,
                    Job        = job,
                    Gender     = gender,
                    Appearance = new CharacterAppearance
                    {
                        HairMesh  = hairMesh,
                        HairColor = (int)hairColor,
                        HeadMesh  = headMesh
                    },
                    PersonalInformation = new PersonalInformation
                    {
                        City       = city,
                        ZodiacSign = zodiacSign
                    },
                    Closet = new Closet()
                };

                for (var i = 0; i < 5; i++)
                {
                    if (clothList[i] == 0)
                    {
                        continue;
                    }

                    character.Closet.Items.Add(new ClosetItem
                    {
                        ItemId   = clothList[i],
                        Index    = i + 1,
                        DateTime = DateTime.UtcNow,
                        Equipped = true
                    });
                }

                User.Characters.Add(character);

                User.AcceptedAgreement = true;

                Database.SaveChanges();                 //TODO: Fix this, shouldn't do a full DB update for this...

                result.WriteInt32((int)Error.ERR_SUCCESS);

                Send(result);

                var playerSlot = new Packet(Opcode.PLAYERSLOT);

                playerSlot.WriteInt32(character.Slot);

                playerSlot.WriteString(character.Name);
                playerSlot.WriteInt32(character.Id);

                playerSlot.WriteInt32(character.WorldId);
                playerSlot.WriteByte(character.Gender);
                playerSlot.WritePosition(character.Position);

                playerSlot.WriteInt32(character.Level);
                playerSlot.WriteInt32(character.Job);

                playerSlot.WriteInt32(character.Stats.STR);
                playerSlot.WriteInt32(character.Stats.STA);
                playerSlot.WriteInt32(character.Stats.DEX);
                playerSlot.WriteInt32(character.Stats.INT);
                playerSlot.WriteInt32(character.Stats.SPI);

                playerSlot.WriteInt32(character.Appearance.HairMesh);
                playerSlot.WriteUInt32((uint)character.Appearance.HairColor);
                playerSlot.WriteInt32(character.Appearance.HeadMesh);

                playerSlot.WriteInt32(character.Blocked ? 1 : 0);
                playerSlot.WriteInt32(character.BlockTime);

                //TODO: Clean this up.

                var container = new ItemContainer <InventoryItem>(character, character.InventoryItems, (byte)Define.MAX_INVENTORY, (byte)Define.MAX_HUMAN_PARTS, Constants.InventorySlots);

                var equipmentItems = container.EquippedItems.ToList();

                playerSlot.WriteInt32(equipmentItems.Count);                 //TODO: Implement non-fashion items.

                //  for i = 1, count do
                //    parts = LAr:ReadByte(ar)
                //    item_id = LAr:ReadDword(ar)
                //    flag = LAr:ReadDword(ar)
                //    attr = LAr:ReadInt(ar)
                //  end

                foreach (var fashionItem in character.Closet.Items.Where(item => item.Equipped))
                {
                    playerSlot.WriteInt32(fashionItem.ItemId);
                }

                playerSlot.WriteInt32(User.Characters.Count(c => c.Deleted));

                Send(playerSlot);

                return;
            }

            Send(result);
        }
Ejemplo n.º 11
0
        private void CharacterList()
        {
            var packet = new Packet(Opcode.PLAYERLIST);

            packet.WriteInt32(DateTime.UtcNow.GetUnixTimestamp());
            packet.WriteByte((byte)(User.AcceptedAgreement ? 0 : 1));

            var characters = User.Characters.Where(c => !c.Deleted && !c.Blocked).ToList();

            packet.WriteByte((byte)characters.Count);
            foreach (var character in characters)
            {
                packet.WriteInt32(character.Slot);

                packet.WriteString(character.Name);
                packet.WriteInt32(character.Id);

                packet.WriteInt32(character.WorldId);
                packet.WriteByte(character.Gender);
                packet.WritePosition(character.Position);

                packet.WriteInt32(character.Level);
                packet.WriteInt32(character.Job);

                packet.WriteInt32(character.Stats.STR);
                packet.WriteInt32(character.Stats.STA);
                packet.WriteInt32(character.Stats.DEX);
                packet.WriteInt32(character.Stats.INT);
                packet.WriteInt32(character.Stats.SPI);

                packet.WriteInt32(character.Appearance.HairMesh);
                packet.WriteUInt32((uint)character.Appearance.HairColor);
                packet.WriteInt32(character.Appearance.HeadMesh);

                packet.WriteInt32(character.Blocked ? 1 : 0);
                packet.WriteInt32(character.BlockTime);

                //TODO: Clean this up.

                var container = new ItemContainer <InventoryItem>(character, character.InventoryItems, (byte)Define.MAX_INVENTORY, (byte)Define.MAX_HUMAN_PARTS, Constants.InventorySlots);

                var equipmentItems = container.EquippedItems.ToList();

                packet.WriteInt32(equipmentItems.Count);                 //TODO: Implement non-fashion items.

                //  for i = 1, count do
                //    parts = LAr:ReadByte(ar)
                //    item_id = LAr:ReadDword(ar)
                //    flag = LAr:ReadDword(ar)
                //    attr = LAr:ReadInt(ar)
                //  end

                for (var i = 1; i <= 5; i++)
                {
                    var item = character.Closet.Items.FirstOrDefault(c => c.Equipped && c.Index == i);

                    packet.WriteInt32(item != null ? item.ItemId : 0);
                }
            }

            packet.WriteInt32(User.Characters.Count(c => c.Deleted));

            //TODO: Implement city/province.
            packet.WriteInt32(0);             //City Id
            packet.WriteInt32(0);             //Province Id

            packet.WriteSByte(20);            //TODO: Find out what this is.

            Send(packet);
        }